msxml3/tests: Add missing return value test (Coverity).
[wine.git] / tools / winedump / minidump.c
blobda1369cbf840dbae51d727bfb2a89331061d64a4
1 /*
2 * MiniDump dumping utility
4 * Copyright 2005 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdarg.h>
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winver.h"
29 #include "dbghelp.h"
30 #include "winedump.h"
32 static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
34 if (md->DataSize)
35 dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
38 static void dump_mdmp_string(DWORD rva)
40 const MINIDUMP_STRING* ms = PRD(rva, sizeof(MINIDUMP_STRING));
41 if (ms)
42 dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
43 else
44 printf("<<?>>");
47 static const MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, unsigned int str_idx)
49 const MINIDUMP_DIRECTORY* dir;
50 unsigned int i;
52 for (i = 0; i < hdr->NumberOfStreams; i++)
54 dir = PRD(hdr->StreamDirectoryRva + i * sizeof(MINIDUMP_DIRECTORY),
55 sizeof(MINIDUMP_DIRECTORY));
56 if (!dir) continue;
57 if (dir->StreamType == str_idx) return dir;
59 return NULL;
62 enum FileSig get_kind_mdmp(void)
64 const DWORD* pdw;
66 pdw = PRD(0, sizeof(DWORD));
67 if (!pdw) {printf("Can't get main signature, aborting\n"); return SIG_UNKNOWN;}
69 if (*pdw == 0x504D444D /* "MDMP" */) return SIG_MDMP;
70 return SIG_UNKNOWN;
73 void mdmp_dump(void)
75 const MINIDUMP_HEADER* hdr = PRD(0, sizeof(MINIDUMP_HEADER));
76 ULONG idx, ndir = 0;
77 const MINIDUMP_DIRECTORY* dir;
78 const void* stream;
80 if (!hdr)
82 printf("Cannot get Minidump header\n");
83 return;
86 printf("Signature: %u (%.4s)\n", hdr->Signature, (const char*)&hdr->Signature);
87 printf("Version: %x\n", hdr->Version);
88 printf("NumberOfStreams: %u\n", hdr->NumberOfStreams);
89 printf("StreamDirectoryRva: %u\n", hdr->StreamDirectoryRva);
90 printf("CheckSum: %u\n", hdr->CheckSum);
91 printf("TimeDateStamp: %s\n", get_time_str(hdr->u.TimeDateStamp));
92 printf("Flags: %x%08x\n", (DWORD)(hdr->Flags >> 32), (DWORD)hdr->Flags);
94 for (idx = 0; idx <= LastReservedStream; idx++)
96 if (!(dir = get_mdmp_dir(hdr, idx))) continue;
98 stream = PRD(dir->Location.Rva, dir->Location.DataSize);
99 printf("Directory [%u]: ", ndir++);
100 switch (dir->StreamType)
102 case ThreadListStream:
104 const MINIDUMP_THREAD_LIST* mtl = (const MINIDUMP_THREAD_LIST*)stream;
105 const MINIDUMP_THREAD* mt = mtl->Threads;
106 unsigned int i;
108 printf("Threads: %u\n", mtl->NumberOfThreads);
109 for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
111 printf(" Thread: #%d\n", i);
112 printf(" ThreadId: %u\n", mt->ThreadId);
113 printf(" SuspendCount: %u\n", mt->SuspendCount);
114 printf(" PriorityClass: %u\n", mt->PriorityClass);
115 printf(" Priority: %u\n", mt->Priority);
116 printf(" Teb: 0x%x%08x\n", (DWORD)(mt->Teb >> 32), (DWORD)mt->Teb);
117 printf(" Stack: 0x%x%08x-0x%x%08x\n",
118 (DWORD)(mt->Stack.StartOfMemoryRange >> 32),
119 (DWORD)mt->Stack.StartOfMemoryRange,
120 (DWORD)((mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize) >> 32),
121 (DWORD)(mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize));
122 dump_mdmp_data(&mt->Stack.Memory, " ");
123 printf(" ThreadContext:\n");
124 dump_mdmp_data(&mt->ThreadContext, " ");
127 break;
128 case ModuleListStream:
129 case 0xFFF0:
131 const MINIDUMP_MODULE_LIST* mml = (const MINIDUMP_MODULE_LIST*)stream;
132 const MINIDUMP_MODULE* mm = mml->Modules;
133 unsigned int i;
134 const char* p1;
135 const char* p2;
137 printf("Modules (%s): %u\n",
138 dir->StreamType == ModuleListStream ? "PE" : "ELF",
139 mml->NumberOfModules);
140 for (i = 0; i < mml->NumberOfModules; i++, mm++)
142 printf(" Module #%d:\n", i);
143 printf(" BaseOfImage: 0x%x%08x\n",
144 (DWORD)(mm->BaseOfImage >> 32), (DWORD) mm->BaseOfImage);
145 printf(" SizeOfImage: %u\n", mm->SizeOfImage);
146 printf(" CheckSum: %u\n", mm->CheckSum);
147 printf(" TimeDateStamp: %s\n", get_time_str(mm->TimeDateStamp));
148 printf(" ModuleName: ");
149 dump_mdmp_string(mm->ModuleNameRva);
150 printf("\n");
151 printf(" VersionInfo:\n");
152 printf(" dwSignature: %x\n", mm->VersionInfo.dwSignature);
153 printf(" dwStrucVersion: %x\n",
154 mm->VersionInfo.dwStrucVersion);
155 printf(" dwFileVersion: %d,%d,%d,%d\n",
156 HIWORD(mm->VersionInfo.dwFileVersionMS),
157 LOWORD(mm->VersionInfo.dwFileVersionMS),
158 HIWORD(mm->VersionInfo.dwFileVersionLS),
159 LOWORD(mm->VersionInfo.dwFileVersionLS));
160 printf(" dwProductVersion %d,%d,%d,%d\n",
161 HIWORD(mm->VersionInfo.dwProductVersionMS),
162 LOWORD(mm->VersionInfo.dwProductVersionMS),
163 HIWORD(mm->VersionInfo.dwProductVersionLS),
164 LOWORD(mm->VersionInfo.dwProductVersionLS));
165 printf(" dwFileFlagsMask: %u\n",
166 mm->VersionInfo.dwFileFlagsMask);
167 printf(" dwFileFlags: %s%s%s%s%s%s\n",
168 mm->VersionInfo.dwFileFlags & VS_FF_DEBUG ? "Debug " : "",
169 mm->VersionInfo.dwFileFlags & VS_FF_INFOINFERRED ? "Inferred " : "",
170 mm->VersionInfo.dwFileFlags & VS_FF_PATCHED ? "Patched " : "",
171 mm->VersionInfo.dwFileFlags & VS_FF_PRERELEASE ? "PreRelease " : "",
172 mm->VersionInfo.dwFileFlags & VS_FF_PRIVATEBUILD ? "PrivateBuild " : "",
173 mm->VersionInfo.dwFileFlags & VS_FF_SPECIALBUILD ? "SpecialBuild " : "");
174 if (mm->VersionInfo.dwFileOS)
176 switch (mm->VersionInfo.dwFileOS & 0x000F)
178 case VOS__BASE: p1 = "_base"; break;
179 case VOS__WINDOWS16:p1 = "16 bit Windows"; break;
180 case VOS__PM16: p1 = "16 bit Presentation Manager"; break;
181 case VOS__PM32: p1 = "32 bit Presentation Manager"; break;
182 case VOS__WINDOWS32:p1 = "32 bit Windows"; break;
183 default: p1 = "---"; break;
185 switch (mm->VersionInfo.dwFileOS & 0xF0000)
187 case VOS_UNKNOWN: p2 = "unknown"; break;
188 case VOS_DOS: p2 = "DOS"; break;
189 case VOS_OS216: p2 = "16 bit OS/2"; break;
190 case VOS_OS232: p2 = "32 bit OS/2"; break;
191 case VOS_NT: p2 = "Windows NT"; break;
192 default: p2 = "---"; break;
194 printf(" dwFileOS: %s running on %s\n", p1, p2);
196 else printf(" dwFileOS: 0\n");
197 switch (mm->VersionInfo.dwFileType)
199 case VFT_UNKNOWN: p1 = "Unknown"; break;
200 case VFT_APP: p1 = "Application"; break;
201 case VFT_DLL: p1 = "DLL"; break;
202 case VFT_DRV: p1 = "Driver"; break;
203 case VFT_FONT: p1 = "Font"; break;
204 case VFT_VXD: p1 = "VxD"; break;
205 case VFT_STATIC_LIB: p1 = "Static Library"; break;
206 default: p1 = "---"; break;
208 printf(" dwFileType: %s\n", p1);
209 printf(" dwFileSubtype: %u\n",
210 mm->VersionInfo.dwFileSubtype);
211 printf(" dwFileDate: %x%08x\n",
212 mm->VersionInfo.dwFileDateMS, mm->VersionInfo.dwFileDateLS);
213 printf(" CvRecord: <%u>\n", mm->CvRecord.DataSize);
214 dump_mdmp_data(&mm->CvRecord, " ");
215 printf(" MiscRecord: <%u>\n", mm->MiscRecord.DataSize);
216 dump_mdmp_data(&mm->MiscRecord, " ");
217 printf(" Reserved0: 0x%x%08x\n",
218 (DWORD)(mm->Reserved0 >> 32), (DWORD)mm->Reserved0);
219 printf(" Reserved1: 0x%x%08x\n",
220 (DWORD)(mm->Reserved1 >> 32), (DWORD)mm->Reserved1);
223 break;
224 case MemoryListStream:
226 const MINIDUMP_MEMORY_LIST* mml = (const MINIDUMP_MEMORY_LIST*)stream;
227 const MINIDUMP_MEMORY_DESCRIPTOR* mmd = mml->MemoryRanges;
228 unsigned int i;
230 printf("Memory Ranges: %u\n", mml->NumberOfMemoryRanges);
231 for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
233 printf(" Memory Range #%d:\n", i);
234 printf(" Range: 0x%x%08x-0x%x%08x\n",
235 (DWORD)(mmd->StartOfMemoryRange >> 32),
236 (DWORD)mmd->StartOfMemoryRange,
237 (DWORD)((mmd->StartOfMemoryRange + mmd->Memory.DataSize) >> 32),
238 (DWORD)(mmd->StartOfMemoryRange + mmd->Memory.DataSize));
239 dump_mdmp_data(&mmd->Memory, " ");
242 break;
243 case SystemInfoStream:
245 const MINIDUMP_SYSTEM_INFO* msi = (const MINIDUMP_SYSTEM_INFO*)stream;
246 const char* str;
247 char tmp[128];
249 printf("System Information:\n");
250 switch (msi->ProcessorArchitecture)
252 case PROCESSOR_ARCHITECTURE_UNKNOWN:
253 str = "Unknown";
254 break;
255 case PROCESSOR_ARCHITECTURE_INTEL:
256 strcpy(tmp, "Intel ");
257 switch (msi->ProcessorLevel)
259 case 3: str = "80386"; break;
260 case 4: str = "80486"; break;
261 case 5: str = "Pentium"; break;
262 case 6: str = "Pentium Pro/II or AMD Athlon"; break;
263 case 15: str = "Pentium 4 or AMD Athlon64"; break;
264 default: str = "???"; break;
266 strcat(tmp, str);
267 strcat(tmp, " (");
268 if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
270 if (HIBYTE(msi->ProcessorRevision) == 0xFF)
271 sprintf(tmp + strlen(tmp), "%c%d", 'A' + ((msi->ProcessorRevision>>4)&0xf)-0x0a, msi->ProcessorRevision&0xf);
272 else
273 sprintf(tmp + strlen(tmp), "%c%d", 'A' + HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
275 else sprintf(tmp + strlen(tmp), "%d.%d", HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
276 str = tmp;
277 break;
278 case PROCESSOR_ARCHITECTURE_MIPS:
279 str = "Mips";
280 break;
281 case PROCESSOR_ARCHITECTURE_ALPHA:
282 str = "Alpha";
283 break;
284 case PROCESSOR_ARCHITECTURE_PPC:
285 str = "PowerPC";
286 break;
287 case PROCESSOR_ARCHITECTURE_ARM:
288 str = "ARM";
289 break;
290 case PROCESSOR_ARCHITECTURE_ARM64:
291 str = "ARM64";
292 break;
293 case PROCESSOR_ARCHITECTURE_AMD64:
294 str = "X86_64";
295 break;
296 case PROCESSOR_ARCHITECTURE_MSIL:
297 str = "MSIL";
298 break;
299 case PROCESSOR_ARCHITECTURE_NEUTRAL:
300 str = "Neutral";
301 break;
302 default:
303 str = "???";
304 break;
306 printf(" Processor: %s (#%d CPUs)\n", str, msi->u.s.NumberOfProcessors);
307 switch (msi->MajorVersion)
309 case 3:
310 switch (msi->MinorVersion)
312 case 51: str = "NT 3.51"; break;
313 default: str = "3-????"; break;
315 break;
316 case 4:
317 switch (msi->MinorVersion)
319 case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
320 case 10: str = "98"; break;
321 case 90: str = "ME"; break;
322 default: str = "4-????"; break;
324 break;
325 case 5:
326 switch (msi->MinorVersion)
328 case 0: str = "2000"; break;
329 case 1: str = "XP"; break;
330 case 2:
331 if (msi->u.s.ProductType == 1) str = "XP";
332 else if (msi->u.s.ProductType == 3) str = "Server 2003";
333 else str = "5-????";
334 break;
335 default: str = "5-????"; break;
337 break;
338 case 6:
339 switch (msi->MinorVersion)
341 case 0:
342 if (msi->u.s.ProductType == 1) str = "Vista";
343 else if (msi->u.s.ProductType == 3) str = "Server 2008";
344 else str = "6-????";
345 break;
346 case 1:
347 if (msi->u.s.ProductType == 1) str = "Win7";
348 else if (msi->u.s.ProductType == 3) str = "Server 2008 R2";
349 else str = "6-????";
350 break;
351 case 2:
352 if (msi->u.s.ProductType == 1) str = "Win8";
353 else if (msi->u.s.ProductType == 3) str = "Server 2012";
354 else str = "6-????";
355 break;
356 case 3:
357 if (msi->u.s.ProductType == 1) str = "Win8.1";
358 else if (msi->u.s.ProductType == 3) str = "Server 2012 R2";
359 else str = "6-????";
360 break;
361 default: str = "6-????"; break;
363 break;
364 case 10:
365 switch (msi->MinorVersion)
367 case 0:
368 if (msi->u.s.ProductType == 1) str = "Win10";
369 else str = "10-????";
370 break;
371 default: str = "10-????"; break;
373 break;
374 default: str = "???"; break;
376 printf(" Version: Windows %s (%u)\n", str, msi->BuildNumber);
377 printf(" PlatformId: %u\n", msi->PlatformId);
378 printf(" CSD: ");
379 dump_mdmp_string(msi->CSDVersionRva);
380 printf("\n");
381 printf(" Reserved1: %u\n", msi->u1.Reserved1);
382 if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
384 printf(" x86.VendorId: %.12s\n",
385 (const char*)msi->Cpu.X86CpuInfo.VendorId);
386 printf(" x86.VersionInformation: %x\n",
387 msi->Cpu.X86CpuInfo.VersionInformation);
388 printf(" x86.FeatureInformation: %x\n",
389 msi->Cpu.X86CpuInfo.FeatureInformation);
390 printf(" x86.AMDExtendedCpuFeatures: %x\n",
391 msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
393 if (sizeof(MINIDUMP_SYSTEM_INFO) + 4 > dir->Location.DataSize &&
394 msi->CSDVersionRva >= dir->Location.Rva + 4)
396 const char* code = PRD(dir->Location.Rva + sizeof(MINIDUMP_SYSTEM_INFO), 4);
397 const DWORD* wes;
398 if (code && code[0] == 'W' && code[1] == 'I' && code[2] == 'N' && code[3] == 'E' &&
399 *(wes = (const DWORD*)(code += 4)) >= 3)
401 /* assume we have wine extensions */
402 printf(" Wine details:\n");
403 printf(" build-id: %s\n", code + wes[1]);
404 printf(" system: %s\n", code + wes[2]);
405 printf(" release: %s\n", code + wes[3]);
409 break;
410 case MiscInfoStream:
412 const MINIDUMP_MISC_INFO* mmi = (const MINIDUMP_MISC_INFO*)stream;
414 printf("Misc Information\n");
415 printf(" Size: %u\n", mmi->SizeOfInfo);
416 printf(" Flags: %s%s\n",
417 mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID ? "ProcessId " : "",
418 mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES ? "ProcessTimes " : "");
419 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
420 printf(" ProcessId: %u\n", mmi->ProcessId);
421 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
423 printf(" ProcessCreateTime: %u\n", mmi->ProcessCreateTime);
424 printf(" ProcessUserTime: %u\n", mmi->ProcessUserTime);
425 printf(" ProcessKernelTime: %u\n", mmi->ProcessKernelTime);
428 break;
429 case ExceptionStream:
431 const MINIDUMP_EXCEPTION_STREAM* mes = (const MINIDUMP_EXCEPTION_STREAM*)stream;
432 unsigned int i;
434 printf("Exception:\n");
435 printf(" ThreadId: %08x\n", mes->ThreadId);
436 printf(" ExceptionRecord:\n");
437 printf(" ExceptionCode: %u\n", mes->ExceptionRecord.ExceptionCode);
438 printf(" ExceptionFlags: %u\n", mes->ExceptionRecord.ExceptionFlags);
439 printf(" ExceptionRecord: 0x%x%08x\n",
440 (DWORD)(mes->ExceptionRecord.ExceptionRecord >> 32),
441 (DWORD)mes->ExceptionRecord.ExceptionRecord);
442 printf(" ExceptionAddress: 0x%x%08x\n",
443 (DWORD)(mes->ExceptionRecord.ExceptionAddress >> 32),
444 (DWORD)(mes->ExceptionRecord.ExceptionAddress));
445 printf(" ExceptionNumberParameters: %u\n",
446 mes->ExceptionRecord.NumberParameters);
447 for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
449 printf(" [%d]: 0x%x%08x\n", i,
450 (DWORD)(mes->ExceptionRecord.ExceptionInformation[i] >> 32),
451 (DWORD)mes->ExceptionRecord.ExceptionInformation[i]);
453 printf(" ThreadContext:\n");
454 dump_mdmp_data(&mes->ThreadContext, " ");
456 break;
458 default:
459 printf("NIY %d\n", dir->StreamType);
460 printf(" RVA: %u\n", dir->Location.Rva);
461 printf(" Size: %u\n", dir->Location.DataSize);
462 dump_mdmp_data(&dir->Location, " ");
463 break;