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