/* Starshatter OpenSource Distribution Copyright (c) 1997-2004, Destroyer Studios LLC. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name "Destroyer Studios" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SUBSYSTEM: nGenEx.lib FILE: MachineInfo.cpp AUTHOR: John DiCamillo OVERVIEW ======== Collect and Display Machine, OS, and Driver Information */ #include #include "MemDebug.h" #include "MachineInfo.h" #define DIRECTINPUT_VERSION 0x0700 #include #include #include #include #include // +--------------------------------------------------------------------+ void Print(const char* fmt, ...); 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(__FILE__,__LINE__) 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(__FILE__,__LINE__) 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; }