/* Starshatter: The Open Source Project Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors Copyright (c) 1997-2006, Destroyer Studios LLC. AUTHOR: John DiCamillo OVERVIEW ======== Collect and Display Machine, OS, and Driver Information */ #include #include "MachineInfo.h" #include "Utils.h" #define DIRECTINPUT_VERSION 0x0700 #include #include #include #include #include // +--------------------------------------------------------------------+ static int cpu_class=-1; static int cpu_speed=-1; static int platform=-1; static int dx_version=-1; static int total_ram=-1; static OSVERSIONINFO os_ver = { sizeof(OSVERSIONINFO) }; static SYSTEM_INFO cpu_info; static MEMORYSTATUS mem_info = { sizeof(MEMORYSTATUS) }; // +--------------------------------------------------------------------+ const char* MachineInfo::GetShortDescription() { static char desc[256]; static const char* cpu_names[] = { "8088", "8086", "80286", "80386", "80486", "Pentium", "Pentium II", "Pentium 3", "Pentium 4" }; static const char* os_names[] = { "DOS", "Windows 95", "Windows 98", "Windows NT", "Windows 2000", "Windows XP", "Windows XP x64", "Windows Vista", "Windows Seven", "Future Windows" }; int cpu_index = GetCpuClass(); if (cpu_index < 0) cpu_index = 0; else if (cpu_index > 8) cpu_index = 8; int os_index = GetPlatform(); if (os_index < 0) os_index = 0; sprintf_s(desc, "%s %d MHz %d MB RAM %s", cpu_names[cpu_index], GetCpuSpeed(), GetTotalRam(), os_names[os_index]); return desc; } // +--------------------------------------------------------------------+ static void DescribeCpuMake(); static void DescribeOwner95(); static void DescribeOwnerNT(); static void DescribeDrivers95(const char* sType); static void DescribeDriversNT(const char* sType); static void DescribeDriverVersion(const char* file); static void DescribeDXVersion(const char* component); // wait for at least target_time, // return the exact amount of time actually waited: static double SpinWait(double target_time) { double actual_time = 0; LARGE_INTEGER ifreq; LARGE_INTEGER cnt1; LARGE_INTEGER cnt2; QueryPerformanceFrequency(&ifreq); double freq = (double) ifreq.QuadPart; QueryPerformanceCounter(&cnt1); do { QueryPerformanceCounter(&cnt2); double delta = (double) (cnt2.QuadPart - cnt1.QuadPart); actual_time = delta / freq; } while (actual_time < target_time); return actual_time; } static double CalcCpuSpeed() { const auto before = std::chrono::high_resolution_clock::now(); double seconds = SpinWait(0.1); const auto after = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = after - before; double clocks = diff.count(); return (clocks/seconds); } /**************************************************************************** * * GetDXVersion * * This function returns * 0 Insufficient DirectX installed * 9 At least DirectX 9 installed. * ****************************************************************************/ DWORD GetDXVersion() { HRESULT hr = 0; HINSTANCE DDHinst = 0; LPDIRECT3D9 d3d9 = 0; OSVERSIONINFO osVer = { sizeof(OSVERSIONINFO) }; // First get the windows platform if (!GetVersionEx(&osVer)) return 0; // NT versions do not support DirectX 9 if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) { if (osVer.dwMajorVersion <= 4) return 0; } DDHinst = LoadLibrary("D3D9.DLL"); if (DDHinst == 0) { return 0; } FreeLibrary(DDHinst); return 9; } // +--------------------------------------------------------------------+ int MachineInfo::GetCpuClass() { if (cpu_class < 0) { GetSystemInfo(&cpu_info); if (cpu_info.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL || cpu_info.dwProcessorType < PROCESSOR_INTEL_PENTIUM) Print("INCOMPATIBLE CPU TYPE!\n"); if (GetPlatform() < OS_WINNT) cpu_class = CPU_P5; else cpu_class = cpu_info.wProcessorLevel; } return cpu_class; } // +--------------------------------------------------------------------+ int MachineInfo::GetCpuSpeed() { if (cpu_speed < 0) { cpu_speed = (int) (CalcCpuSpeed() / 1e6); } return cpu_speed; } // +--------------------------------------------------------------------+ int MachineInfo::GetTotalRam() { if (total_ram < 0) { GlobalMemoryStatus(&mem_info); total_ram = (int) (mem_info.dwTotalPhys/(1024*1024)) + 1; } return total_ram; } // +--------------------------------------------------------------------+ int MachineInfo::GetPlatform() { if (platform < 0) { GetVersionEx(&os_ver); switch (os_ver.dwPlatformId) { default: case VER_PLATFORM_WIN32s: case VER_PLATFORM_WIN32_WINDOWS: { char msg[256]; sprintf_s(msg, "Invalid Operating System Platform: %d\n", os_ver.dwPlatformId); //-V576 Print(msg); } break; case VER_PLATFORM_WIN32_NT: if (os_ver.dwMajorVersion == 4) platform = OS_WINNT; else if (os_ver.dwMajorVersion == 5 && os_ver.dwMinorVersion == 0) platform = OS_WIN2K; else if (os_ver.dwMajorVersion == 5 && os_ver.dwMinorVersion == 1) platform = OS_WINXP; else if (os_ver.dwMajorVersion == 5 && os_ver.dwMinorVersion == 2) platform = OS_WINXP64; else if (os_ver.dwMajorVersion == 6 && os_ver.dwMinorVersion == 0) platform = OS_WINVISTA; else if (os_ver.dwMajorVersion == 6 && os_ver.dwMinorVersion == 1) platform = OS_WINSEVEN; else if (os_ver.dwMajorVersion >= 6) platform = OS_WINFUTURE; else { platform = OS_INVALID; Print("Invalid Operating System Platform (NT-series): %d.%d\n", os_ver.dwMajorVersion, os_ver.dwMinorVersion); } break; } } return platform; } // +--------------------------------------------------------------------+ int MachineInfo::GetDirectXVersion() { if (dx_version < 0) { dx_version = GetDXVersion(); } return dx_version; } // +--------------------------------------------------------------------+ void MachineInfo::DescribeMachine() { GetPlatform(); GetCpuClass(); Print("+====================================================================+\n"); Print("| |\n"); char txt[256]; switch (platform) { case OS_WIN95: sprintf_s(txt, "Windows 95 version %d.%d.%d %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, LOWORD(os_ver.dwBuildNumber), os_ver.szCSDVersion); break; case OS_WIN98: sprintf_s(txt, "Windows 98 version %d.%d.%d %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, LOWORD(os_ver.dwBuildNumber), os_ver.szCSDVersion); break; case OS_WINNT: sprintf_s(txt, "Windows NT %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; case OS_WIN2K: sprintf_s(txt, "Windows 2000 %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); case OS_WINXP: sprintf_s(txt, "Windows XP %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; case OS_WINXP64: sprintf_s(txt, "Windows XP x64 %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; case OS_WINVISTA: sprintf_s(txt, "Windows Vista %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; case OS_WINSEVEN: sprintf_s(txt, "Windows 7 %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; case OS_WINFUTURE: sprintf_s(txt, "Windows from the future %d.%d (Build %d) %s", //-V576 os_ver.dwMajorVersion, os_ver.dwMinorVersion, os_ver.dwBuildNumber, os_ver.szCSDVersion); break; default: sprintf_s(txt, "Unknown Operating System Platform"); break; } Print("| %-66s |\n", txt); Print("| |\n"); if (platform == OS_WIN95 || platform == OS_WIN98) DescribeOwner95(); else DescribeOwnerNT(); sprintf_s(txt, "CPUs Detected: %d CPU Level: %d.%d.%d CPU Speed: %d", //-V576 cpu_info.dwNumberOfProcessors, cpu_info.wProcessorLevel, cpu_info.wProcessorRevision >> 8, cpu_info.wProcessorRevision & 0xff, GetCpuSpeed() + 1); Print("| %-66s |\n", txt); DescribeCpuMake(); GlobalMemoryStatus(&mem_info); total_ram = (int) (mem_info.dwTotalPhys/(1024*1024)) + 1; int swap_max = (int) (mem_info.dwTotalPageFile/(1024*1024)); int swap_avail = (int) (mem_info.dwAvailPageFile/(1024*1024)); sprintf_s(txt, "%d MB RAM %d MB Max Swap %d MB Avail Swap", total_ram, swap_max, swap_avail); Print("| %-66s |\n", txt); Print("| |\n"); Print("| DirectX %d installed. |\n", GetDirectXVersion()); DescribeDXVersion("DDRAW"); DescribeDXVersion("D3DIM"); DescribeDXVersion("DINPUT"); DescribeDXVersion("DPLAY"); DescribeDXVersion("DSOUND"); DescribeDXVersion("DMUSIC"); DescribeDXVersion("DSHOW"); Print("| |\n"); if (platform == OS_WIN95 || platform == OS_WIN98) { DescribeDrivers95("Display"); DescribeDrivers95("Media"); DescribeDrivers95("Monitor"); DescribeDrivers95("Multimedia"); } else { DescribeDriversNT(""); } Print("+====================================================================+\n"); Print("\n"); } // +--------------------------------------------------------------------+ static void DescribeCpuMake() { HKEY hkWin; char sProcessor[256] = ""; char sMMXInfo[256] = ""; char sVendor[256] = ""; DWORD dwSize; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "Identifier", NULL, NULL, (LPBYTE) sProcessor, &dwSize); dwSize = 256; RegQueryValueEx(hkWin, "MMXIdentifier", NULL, NULL, (LPBYTE) sMMXInfo, &dwSize); dwSize = 256; RegQueryValueEx(hkWin, "VendorIdentifier", NULL, NULL, (LPBYTE) sVendor, &dwSize); RegCloseKey(hkWin); } if (sProcessor[0]) Print("| %-66s |\n", sProcessor); if (sMMXInfo[0]) Print("| %-66s |\n", sMMXInfo); if (sVendor[0]) Print("| %-66s |\n", sVendor); if (sProcessor[0] || sMMXInfo[0] || sVendor[0]) Print("| |\n"); } // +--------------------------------------------------------------------+ static void DescribeOwner95() { HKEY hkWin; char sRegisteredOwner[256] = ""; char sRegisteredOrganization[256] = ""; DWORD dwSize; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "RegisteredOwner", NULL, NULL, (LPBYTE) sRegisteredOwner, &dwSize); dwSize = 256; RegQueryValueEx(hkWin, "RegisteredOrganization", NULL, NULL, (LPBYTE) sRegisteredOrganization, &dwSize); RegCloseKey(hkWin); } else { Print("Could not access registered owner\n"); } if (sRegisteredOwner[0]) { char txt[256]; sprintf_s(txt, "Registered Owner: %s, %s", sRegisteredOwner, sRegisteredOrganization); Print("| %-66s |\n", txt); Print("| |\n"); } } static void DescribeOwnerNT() { HKEY hkWin; char sRegisteredOwner[256] = ""; char sRegisteredOrganization[256] = ""; DWORD dwSize; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "RegisteredOwner", NULL, NULL, (LPBYTE) sRegisteredOwner, &dwSize); dwSize = 256; RegQueryValueEx(hkWin, "RegisteredOrganization", NULL, NULL, (LPBYTE) sRegisteredOrganization, &dwSize); RegCloseKey(hkWin); } else { Print("Could not access registered owner\n"); } if (sRegisteredOwner[0]) { char txt[256]; sprintf_s(txt, "Registered Owner: %s, %s", sRegisteredOwner, sRegisteredOrganization); Print("| %-66s |\n", txt); Print("| |\n"); } } // +--------------------------------------------------------------------+ static void DescribeDrivers95(const char* sType) { HKEY hkWin, hkSub; int nKey = 0; char sKey[256]; char sSub[256]; char sDriver[256]; char txt[256]; DWORD dwSize; int worked; // describe the video driver(s): do { worked = 0; sprintf_s(sKey, "System\\CurrentControlSet\\Services\\Class\\%s\\%04X", sType, nKey); sprintf_s(sSub, "System\\CurrentControlSet\\Services\\Class\\%s\\%04X\\DEFAULT", sType, nKey); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sKey, 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "DriverDesc", NULL, NULL, (LPBYTE) sDriver, &dwSize); if (sDriver[0]) { sprintf_s(txt, "* %s", sDriver); Print("| %-66s |\n", txt); worked = 1; } // try to find the driver file name: if (worked) { ZeroMemory(sDriver, sizeof(sDriver)); dwSize = 256; DWORD err = RegQueryValueEx(hkWin, "Driver", NULL, NULL, (LPBYTE) sDriver, &dwSize); if (err != ERROR_SUCCESS) { dwSize = 256; err = RegQueryValueEx(hkWin, "DeviceDriver", NULL, NULL, (LPBYTE) sDriver, &dwSize); } if (err != ERROR_SUCCESS) { dwSize = 256; err = RegQueryValueEx(hkWin, "drv", NULL, NULL, (LPBYTE) sDriver, &dwSize); } if (err != ERROR_SUCCESS) { if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSub, 0, KEY_READ, &hkSub) == ERROR_SUCCESS) { dwSize = 256; err = RegQueryValueEx(hkSub, "drv", NULL, NULL, (LPBYTE) sDriver, &dwSize); RegCloseKey(hkSub); } } // if we found it, try to display version info: if (err == ERROR_SUCCESS) { DescribeDriverVersion(sDriver); } Print("| |\n"); } RegCloseKey(hkWin); } nKey++; } while (worked); } static void DescribeDriversNT(const char* sType) { Print("| |\n"); HKEY hkWin; char sVideo[256] = ""; char sDriver[256] = ""; DWORD dwSize = 0; // find the pointer to the video driver: if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "\\Device\\Video0", NULL, NULL, (LPBYTE) sVideo, &dwSize); RegCloseKey(hkWin); } // follow the pointer and get the driver description: if (dwSize && sVideo[0]) { const char* sLeader = "\\REGISTRY\\Machine\\"; int nLeader = strlen(sLeader); if (_strnicmp(sVideo, sLeader, nLeader) == 0) { if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sVideo + nLeader, 0, KEY_READ, &hkWin) == ERROR_SUCCESS) { dwSize = 256; RegQueryValueEx(hkWin, "Device Description", NULL, NULL, (LPBYTE) sDriver, &dwSize); RegCloseKey(hkWin); } } } if (sDriver[0]) { Print("| %-66s |\n", sDriver); Print("| |\n"); } } // +--------------------------------------------------------------------+ static char sTranslation[16]; static void GetTranslation(const LPBYTE pBlock) { LPBYTE sData = NULL; UINT lenData = 0; if (VerQueryValue(pBlock, "\\VarFileInfo\\Translation", (LPVOID*) &sData, &lenData)) { if (lenData && sData) { sprintf_s(sTranslation, "%02X%02X%02X%02X", sData[1], sData[0], sData[3], sData[2]); } } } void DisplayVersionString(const LPBYTE pBlock, LPTSTR sSection) { char txt[256]; char sFullSection[256]; sprintf_s(sFullSection, "\\StringFileInfo\\%s\\%s", sTranslation, sSection); LPBYTE sData = NULL; UINT lenData = 0; DWORD dwErr = 0; if (VerQueryValue(pBlock, sFullSection, (LPVOID*) &sData, &lenData)) { if (lenData && sData) { sprintf_s(txt, "%-16s %s", sSection, sData); Print("| %-60s |\n", txt); } } } static void DescribeDriverVersion(const char* file) { DWORD dwHandle = 0; TCHAR szFile[512]; strcpy_s(szFile, file); int nBytes = GetFileVersionInfoSize(szFile, &dwHandle); if (nBytes <= 0) { char szWinDir[256]; GetSystemDirectory(szWinDir, 256); sprintf_s(szFile, "%s\\%s", szWinDir, file); nBytes = GetFileVersionInfoSize(szFile, &dwHandle); if (nBytes <= 0) return; } LPBYTE pBlock = new BYTE[nBytes]; if (pBlock && GetFileVersionInfo(szFile, dwHandle, nBytes, (LPVOID) pBlock)) { GetTranslation(pBlock); DisplayVersionString(pBlock, "CompanyName"); // DisplayVersionString(pBlock, "FileDescription"); DisplayVersionString(pBlock, "FileVersion"); // DisplayVersionString(pBlock, "InternalName"); // DisplayVersionString(pBlock, "LegalCopyright"); // DisplayVersionString(pBlock, "OriginalFilename"); // DisplayVersionString(pBlock, "ProductName"); // DisplayVersionString(pBlock, "ProductVersion"); // DisplayVersionString(pBlock, "Comments"); // DisplayVersionString(pBlock, "LegalTrademarks"); // DisplayVersionString(pBlock, "PrivateBuild"); // DisplayVersionString(pBlock, "SpecialBuild"); } delete [] pBlock; } static void DescribeDXVersion(const char* component) { DWORD dwHandle = 0; char szFile[512]; char szWinDir[512]; GetSystemDirectory(szWinDir, 512); sprintf_s(szFile, "%s\\%s.dll", szWinDir, component); int nBytes = GetFileVersionInfoSize(szFile, &dwHandle); if (nBytes <= 0) { return; } LPBYTE pBlock = new BYTE[nBytes]; if (pBlock && GetFileVersionInfo(szFile, dwHandle, nBytes, (LPVOID) pBlock)) { GetTranslation(pBlock); char txt[256]; char sFullSection[256]; LPBYTE sData = NULL; UINT lenData = 0; DWORD dwErr = 0; sprintf_s(sFullSection, "\\StringFileInfo\\%s\\FileVersion", sTranslation); if (VerQueryValue(pBlock, sFullSection, (LPVOID*) &sData, &lenData)) { if (lenData && sData) { sprintf_s(txt, "%-8s%s", component, sData); Print("| %-64s |\n", txt); } } } delete [] pBlock; }