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 <winreg.h>
10 #include <reactos/buildno.h>
11 
12 static const char* Exception2Str(DWORD code)
13 {
14     switch (code)
15     {
16     case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
17     case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT";
18     case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
19     case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
20     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
21     case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
22     case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
23     case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
24     case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION";
25     case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
26     case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
27     case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
28     case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
29     case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
30     case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
31     case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
32     case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
33     case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
34     case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
35     case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
36     case EXCEPTION_GUARD_PAGE: return "EXCEPTION_GUARD_PAGE";
37     case EXCEPTION_INVALID_HANDLE: return "EXCEPTION_INVALID_HANDLE";
38     }
39 
40     return "--";
41 }
42 
43 static void ReadKey(HKEY hKey, const char* ValueName, char* Buffer, DWORD size)
44 {
45     DWORD dwType;
46     LSTATUS ret = RegQueryValueExA(hKey, ValueName, NULL, &dwType, (LPBYTE)Buffer, &size);
47     if (ret != ERROR_SUCCESS || dwType != REG_SZ)
48         Buffer[0] = '\0';
49 }
50 
51 void PrintSystemInfo(FILE* output, DumpData& data)
52 {
53     SYSTEMTIME LocalTime;
54     GetLocalTime(&LocalTime);
55     xfprintf(output, NEWLINE "ReactOS " KERNEL_VERSION_STR " DrWtsn32" NEWLINE NEWLINE);
56     xfprintf(output, "Application exception occurred:" NEWLINE);
57     xfprintf(output, "    App: %ls (pid=%d, tid=0x%x)" NEWLINE, data.ProcessName.c_str(), data.ProcessID, data.ThreadID);
58     xfprintf(output, "    When: %d/%d/%d @ %02d:%02d:%02d.%d" NEWLINE,
59              LocalTime.wDay, LocalTime.wMonth, LocalTime.wYear,
60              LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds);
61     DWORD ExceptionCode = data.ExceptionInfo.ExceptionRecord.ExceptionCode;
62     xfprintf(output, "    Exception number: 0x%8x (%s)" NEWLINE, ExceptionCode, Exception2Str(ExceptionCode));
63 
64     char Buffer[MAX_PATH];
65     DWORD count = sizeof(Buffer);
66     xfprintf(output, NEWLINE "*----> System Information <----*" NEWLINE NEWLINE);
67     if (GetComputerNameA(Buffer, &count))
68         xfprintf(output, "    Computer Name: %s" NEWLINE, Buffer);
69     count = sizeof(Buffer);
70     if (GetUserNameA(Buffer, &count))
71         xfprintf(output, "    User Name: %s" NEWLINE, Buffer);
72 
73 
74     SYSTEM_INFO info;
75     GetSystemInfo(&info);
76     xfprintf(output, "    Number of Processors: %d" NEWLINE, info.dwNumberOfProcessors);
77 
78     HKEY hKey;
79     LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
80                              0, KEY_READ, &hKey);
81     if (ret == ERROR_SUCCESS)
82     {
83         DWORD dwType;
84         count = sizeof(Buffer);
85         ret = RegQueryValueExA(hKey, "Identifier", NULL, &dwType, (LPBYTE)Buffer, &count);
86         if (ret == ERROR_SUCCESS && dwType == REG_SZ)
87         {
88             Buffer[count] = '\0';
89             xfprintf(output, "    Processor Type: %s" NEWLINE, Buffer);
90         }
91         RegCloseKey(hKey);
92     }
93 
94     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
95     if (ret == ERROR_SUCCESS)
96     {
97         char Version[50];
98         ReadKey(hKey, "ProductName", Buffer, sizeof(Buffer));
99         ReadKey(hKey, "CurrentVersion", Version, sizeof(Version));
100         xfprintf(output, "    %s Version: %s" NEWLINE, Buffer, Version);
101         ReadKey(hKey, "BuildLab", Buffer, sizeof(Buffer));
102         xfprintf(output, "    BuildLab: %s" NEWLINE, Buffer);
103         ReadKey(hKey, "CSDVersion", Buffer, sizeof(Buffer));
104         if (Buffer[0])
105             xfprintf(output, "    Service Pack: %s" NEWLINE, Buffer);
106         ReadKey(hKey, "CurrentType", Buffer, sizeof(Buffer));
107         xfprintf(output, "    Current Type: %s" NEWLINE, Buffer);
108         ReadKey(hKey, "RegisteredOrganization", Buffer, sizeof(Buffer));
109         xfprintf(output, "    Registered Organization: %s" NEWLINE, Buffer);
110         ReadKey(hKey, "RegisteredOwner", Buffer, sizeof(Buffer));
111         xfprintf(output, "    Registered Owner: %s" NEWLINE, Buffer);
112 
113         RegCloseKey(hKey);
114     }
115 }
116