2 * File minidump.c - management of dumps (read & write)
4 * Copyright (C) 2004, Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
26 #include "dbghelp_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
32 /* hard to see how we can generate this very easily (how to grab latest exception
35 static void DumpException(struct process* pcs, HANDLE hFile, RVA* rva)
37 MINIDUMP_EXCEPTION_STREAM mdExcpt;
39 mdExcpt.ThreadId = DEBUG_CurrThread->tid;
40 mdExcpt.__alignment = 0;
41 mdExcpt.ExceptionRecord.
45 ULONGLONG ExceptionRecord;
46 ULONGLONG ExceptionAddress;
47 ULONG NumberParameters;
48 ULONG __unusedAlignment;
49 ULONGLONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
53 /******************************************************************
56 * Write in File the modules from pcs
58 static void dump_modules(struct process* pcs, HANDLE hFile, RVA* rva)
60 MINIDUMP_MODULE mdModule;
61 MINIDUMP_MODULE_LIST mdModuleList;
63 struct module* module = NULL;
65 mdModuleList.NumberOfModules = 0;
66 for (module = pcs->lmodules; module; module = module->next)
67 mdModuleList.NumberOfModules++;
68 WriteFile(hFile, &mdModuleList.NumberOfModules,
69 sizeof(mdModuleList.NumberOfModules), &written, NULL);
70 *rva += sizeof(mdModuleList.NumberOfModules) +
71 sizeof(mdModule) * mdModuleList.NumberOfModules;
72 for (module = pcs->lmodules; module; module = module->next)
74 mdModule.BaseOfImage = (DWORD)module->module.BaseOfImage;
75 mdModule.SizeOfImage = module->module.ImageSize;
76 mdModule.CheckSum = module->module.CheckSum;
77 mdModule.TimeDateStamp = module->module.TimeDateStamp;
78 mdModule.ModuleNameRva = *rva;
79 *rva += strlen(module->module.ModuleName) + 1;
80 memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */
81 mdModule.CvRecord.DataSize = 0; /* FIXME */
82 mdModule.CvRecord.Rva = 0; /* FIXME */
83 mdModule.MiscRecord.DataSize = 0; /* FIXME */
84 mdModule.MiscRecord.Rva = 0; /* FIXME */
85 mdModule.Reserved0 = 0;
86 mdModule.Reserved1 = 0;
87 WriteFile(hFile, &mdModule, sizeof(mdModule), &written, NULL);
89 for (module = pcs->lmodules; module; module = module->next)
91 WriteFile(hFile, module->module.ModuleName,
92 strlen(module->module.ModuleName) + 1, &written, NULL);
93 FIXME("CV and misc records not written\n");
97 /******************************************************************
100 * Dumps into File the information about the system
102 static void dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva)
104 MINIDUMP_SYSTEM_INFO mdSysInfo;
106 OSVERSIONINFOA osInfo;
109 GetSystemInfo(&sysInfo);
110 GetVersionExA(&osInfo);
112 mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
113 mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
114 mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
115 mdSysInfo.Reserved0 = 0;
117 mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
118 mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
119 mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
120 mdSysInfo.PlatformId = osInfo.dwPlatformId;
122 mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo);
123 mdSysInfo.Reserved1 = 0;
125 WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL);
126 *rva += sizeof(mdSysInfo);
127 WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1,
129 *rva += strlen(osInfo.szCSDVersion) + 1;
132 /******************************************************************
135 * Dumps into File the information about running threads
137 static void dump_threads(struct process* pcs, HANDLE hFile, RVA* rva)
140 MINIDUMP_THREAD mdThd;
141 MINIDUMP_THREAD_LIST mdThdList;
145 mdThdList.NumberOfThreads = pcs->num_threads;
146 WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads),
148 *rva += sizeof(mdThdList.NumberOfThreads) +
149 mdThdList.NumberOfThreads * sizeof(mdThd);
150 for (thd = pcs->threads; thd; thd = thd->next)
152 mdThd.ThreadId = thd->tid;
153 mdThd.SuspendCount = 0; /* FIXME */
154 mdThd.PriorityClass = 0; /* FIXME */
155 mdThd.Priority = 0; /* FIXME */
156 mdThd.Teb = 0; /* FIXME */
157 mdThd.Stack.StartOfMemoryRange = 0; /* FIXME */
158 mdThd.Stack.Memory.DataSize = 0; /* FIXME */
159 mdThd.Stack.Memory.Rva = 0; /* FIXME */
160 mdThd.ThreadContext.DataSize = 0;/* FIXME */
161 mdThd.ThreadContext.Rva = 0; /* FIXME */
163 WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL);
164 FIXME("Stack & thread context not written\n");
169 /******************************************************************
170 * MiniDumpWriteDump (DEBUGHLP.@)
174 BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
175 MINIDUMP_TYPE DumpType,
176 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
177 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
178 PMINIDUMP_CALLBACK_INFORMATION CallbackParam)
181 MINIDUMP_HEADER mdHead;
182 MINIDUMP_DIRECTORY mdDir;
183 DWORD currRva, written;
184 DWORD i, nStream, addStream;
187 pcs = process_find_by_handle(hProcess);
188 if (!pcs) return FALSE; /* FIXME: should try to load it ??? */
192 nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0;
194 if (DumpType & MiniDumpNormal)
195 addStream += 3; /* sure ? thread stack back trace */
197 if (DumpType & MiniDumpWithDataSegs)
198 FIXME("NIY MiniDumpWithDataSegs\n");
199 if (DumpType & MiniDumpWithFullMemory)
200 FIXME("NIY MiniDumpWithFullMemory\n");
201 if (DumpType & MiniDumpWithHandleData)
202 FIXME("NIY MiniDumpWithHandleData\n");
203 if (DumpType & MiniDumpFilterMemory)
204 FIXME("NIY MiniDumpFilterMemory\n");
205 if (DumpType & MiniDumpScanMemory)
206 FIXME("NIY MiniDumpScanMemory\n");
208 /* 2) write header */
209 rva = sizeof(mdHead);
210 mdHead.Signature = MINIDUMP_SIGNATURE;
211 mdHead.Version = MINIDUMP_VERSION;
212 mdHead.NumberOfStreams = nStream + addStream;
213 mdHead.StreamDirectoryRva = rva;
214 mdHead.u.TimeDateStamp = time(NULL);
215 mdHead.Flags = DumpType;
216 WriteFile(hFile, &mdHead, sizeof(mdHead), &written, NULL);
218 /* 3) write stream directories */
219 rva += (nStream + addStream) * sizeof(mdDir);
220 /* 3.1) write data stream directories */
221 currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
222 SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
223 mdDir.StreamType = ModuleListStream;
224 mdDir.Location.Rva = rva;
225 dump_modules(pcs, hFile, &rva);
226 mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
227 SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
228 WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
230 currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
231 SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
232 mdDir.StreamType = ThreadListStream;
233 mdDir.Location.Rva = rva;
234 dump_threads(pcs, hFile, &rva);
235 mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
236 SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
237 WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
239 currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
240 SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
241 mdDir.StreamType = SystemInfoStream;
242 mdDir.Location.Rva = rva;
243 dump_system_info(pcs, hFile, &rva);
244 mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
245 SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
246 WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
248 /* 3.2) write user define stream */
249 for (i = 0; i < nStream; i++)
251 mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
252 mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
253 mdDir.Location.Rva = rva;
254 WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
255 currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
256 SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
258 UserStreamParam->UserStreamArray[i].Buffer,
259 UserStreamParam->UserStreamArray[i].BufferSize,
261 rva += UserStreamParam->UserStreamArray[i].BufferSize;
262 SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);