1 /*
2  * PROJECT:     Dr. Watson crash reporter
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Output system info
5  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include <udmihelp.h>
10 #include <winreg.h>
11 #include <reactos/buildno.h>
12 
13 static const char* Exception2Str(DWORD code)
14 {
15     switch (code)
16     {
17     case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
18     case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT";
19     case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
20     case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
21     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
22     case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
23     case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
24     case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
25     case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION";
26     case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
27     case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
28     case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
29     case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
30     case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
31     case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
32     case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
33     case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
34     case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
35     case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
36     case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
37     case EXCEPTION_GUARD_PAGE: return "EXCEPTION_GUARD_PAGE";
38     case EXCEPTION_INVALID_HANDLE: return "EXCEPTION_INVALID_HANDLE";
39     }
40 
41     return "--";
42 }
43 
44 static void ReadKey(HKEY hKey, const char* ValueName, char* Buffer, DWORD size)
45 {
46     DWORD dwType;
47     LSTATUS ret = RegQueryValueExA(hKey, ValueName, NULL, &dwType, (LPBYTE)Buffer, &size);
48     if (ret != ERROR_SUCCESS || dwType != REG_SZ)
49         Buffer[0] = '\0';
50 }
51 
52 void PrintSystemInfo(FILE* output, DumpData& data)
53 {
54     SYSTEMTIME LocalTime;
55     GetLocalTime(&LocalTime);
56     xfprintf(output, NEWLINE "ReactOS " KERNEL_VERSION_STR " DrWtsn32" NEWLINE NEWLINE);
57     xfprintf(output, "Application exception occurred:" NEWLINE);
58     xfprintf(output, "    App: %ls (pid=%d, tid=0x%x)" NEWLINE, data.ProcessName.c_str(), data.ProcessID, data.ThreadID);
59     xfprintf(output, "    When: %d/%d/%d @ %02d:%02d:%02d.%d" NEWLINE,
60              LocalTime.wDay, LocalTime.wMonth, LocalTime.wYear,
61              LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds);
62 
63     xfprintf(output, "    First chance: %u" NEWLINE, data.ExceptionInfo.dwFirstChance);
64     EXCEPTION_RECORD& Record = data.ExceptionInfo.ExceptionRecord;
65     xfprintf(output, "    Exception number: 0x%08x (%s)" NEWLINE, Record.ExceptionCode, Exception2Str(Record.ExceptionCode));
66     xfprintf(output, "    Exception flags: 0x%08x" NEWLINE, Record.ExceptionFlags);
67     xfprintf(output, "    Exception address: %p" NEWLINE, Record.ExceptionAddress);
68     if (Record.NumberParameters)
69     {
70         xfprintf(output, "    Exception parameters: %u" NEWLINE, Record.NumberParameters);
71         for (DWORD n = 0; n < std::min<DWORD>(EXCEPTION_MAXIMUM_PARAMETERS, Record.NumberParameters); ++n)
72         {
73             xfprintf(output, "      Parameter %u: 0x%p" NEWLINE, n, Record.ExceptionInformation[n]);
74         }
75     }
76 
77     char Buffer[MAX_PATH];
78     DWORD count = sizeof(Buffer);
79     xfprintf(output, NEWLINE "*----> System Information <----*" NEWLINE NEWLINE);
80     if (GetComputerNameA(Buffer, &count))
81         xfprintf(output, "    Computer Name: %s" NEWLINE, Buffer);
82     count = sizeof(Buffer);
83     if (GetUserNameA(Buffer, &count))
84         xfprintf(output, "    User Name: %s" NEWLINE, Buffer);
85 
86 
87     PVOID SMBiosBuf;
88     PCHAR DmiStrings[ID_STRINGS_MAX] = { 0 };
89     SMBiosBuf = LoadSMBiosData(DmiStrings);
90     if (SMBiosBuf)
91     {
92         if (DmiStrings[BIOS_VENDOR])
93             xfprintf(output, "    BIOS Vendor: %s" NEWLINE, DmiStrings[BIOS_VENDOR]);
94         if (DmiStrings[BIOS_VERSION])
95             xfprintf(output, "    BIOS Version: %s" NEWLINE, DmiStrings[BIOS_VERSION]);
96         if (DmiStrings[BIOS_DATE])
97             xfprintf(output, "    BIOS Date: %s" NEWLINE, DmiStrings[BIOS_DATE]);
98         if (DmiStrings[SYS_VENDOR])
99             xfprintf(output, "    System Manufacturer: %s" NEWLINE, DmiStrings[SYS_VENDOR]);
100         if (DmiStrings[SYS_FAMILY])
101             xfprintf(output, "    System Family: %s" NEWLINE, DmiStrings[SYS_FAMILY]);
102         if (DmiStrings[SYS_PRODUCT])
103             xfprintf(output, "    System Model: %s" NEWLINE, DmiStrings[SYS_PRODUCT]);
104         if (DmiStrings[SYS_VERSION])
105             xfprintf(output, "    System Version: %s" NEWLINE, DmiStrings[SYS_VERSION]);
106         if (DmiStrings[SYS_SKU])
107             xfprintf(output, "    System SKU: %s" NEWLINE, DmiStrings[SYS_SKU]);
108         if (DmiStrings[BOARD_VENDOR])
109             xfprintf(output, "    Baseboard Manufacturer: %s" NEWLINE, DmiStrings[BOARD_VENDOR]);
110         if (DmiStrings[BOARD_NAME])
111             xfprintf(output, "    Baseboard Model: %s" NEWLINE, DmiStrings[BOARD_NAME]);
112         if (DmiStrings[BOARD_VERSION])
113             xfprintf(output, "    Baseboard Version: %s" NEWLINE, DmiStrings[BOARD_VERSION]);
114         FreeSMBiosData(SMBiosBuf);
115     }
116 
117     SYSTEM_INFO info;
118     GetSystemInfo(&info);
119     xfprintf(output, "    Number of Processors: %d" NEWLINE, info.dwNumberOfProcessors);
120 
121     HKEY hKey;
122     LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
123                              0, KEY_READ, &hKey);
124     if (ret == ERROR_SUCCESS)
125     {
126         DWORD dwType;
127         count = sizeof(Buffer);
128         ret = RegQueryValueExA(hKey, "Identifier", NULL, &dwType, (LPBYTE)Buffer, &count);
129         if (ret == ERROR_SUCCESS && dwType == REG_SZ)
130         {
131             Buffer[count] = '\0';
132             xfprintf(output, "    Processor Type: %s" NEWLINE, Buffer);
133         }
134         RegCloseKey(hKey);
135     }
136 
137     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
138     if (ret == ERROR_SUCCESS)
139     {
140         char Version[50];
141         ReadKey(hKey, "ProductName", Buffer, sizeof(Buffer));
142         ReadKey(hKey, "CurrentVersion", Version, sizeof(Version));
143         xfprintf(output, "    %s Version: %s" NEWLINE, Buffer, Version);
144         ReadKey(hKey, "BuildLab", Buffer, sizeof(Buffer));
145         xfprintf(output, "    BuildLab: %s" NEWLINE, Buffer);
146         ReadKey(hKey, "CSDVersion", Buffer, sizeof(Buffer));
147         if (Buffer[0])
148             xfprintf(output, "    Service Pack: %s" NEWLINE, Buffer);
149         ReadKey(hKey, "CurrentType", Buffer, sizeof(Buffer));
150         xfprintf(output, "    Current Type: %s" NEWLINE, Buffer);
151         ReadKey(hKey, "RegisteredOrganization", Buffer, sizeof(Buffer));
152         xfprintf(output, "    Registered Organization: %s" NEWLINE, Buffer);
153         ReadKey(hKey, "RegisteredOwner", Buffer, sizeof(Buffer));
154         xfprintf(output, "    Registered Owner: %s" NEWLINE, Buffer);
155 
156         RegCloseKey(hKey);
157     }
158 }
159