// Camel - CPU Identifying Tool
// Copyright (C) 2002, Iain Chesworth
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "common.h"
// Included class header files.
#include "cpu_info.h"
// ----------------------------------------------------------------------------
//
// Win32 Code:
// This is code to run the Windows(tm) version of Camel.
//
// ----------------------------------------------------------------------------
#ifdef _WIN32
// Global variables.
HINSTANCE g_hInstance;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Save the instance handle.
g_hInstance = hInstance;
// Initialise the common controls.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof (INITCOMMONCONTROLSEX);
InitCtrls.dwICC = ICC_TREEVIEW_CLASSES;
InitCommonControlsEx (&InitCtrls);
// Create the dialog.
DialogBox (hInstance, MAKEINTRESOURCE (IDD_CPUDIALOG), NULL, (DLGPROC) CPUDialog_DialogProc);
return 0;
}
BOOL CALLBACK CPUDialog_DialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HWND hWndOwner;
PAINTSTRUCT ps;
static CPUInfo * CPU;
RECT rc, rcOwner, rcDlg;
HICON hBigIcon, hSmallIcon;
switch (uMsg) {
case WM_INITDIALOG:
if ((hWndOwner = GetParent (hDlg)) == NULL) {
hWndOwner = GetDesktopWindow ();
}
GetWindowRect (hWndOwner, &rcOwner);
GetWindowRect (hDlg, &rcDlg);
CopyRect (&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that
// right and bottom values represent the width and
// height, and then offset the owner again to discard
// space taken up by the dialog box.
OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect (&rc, -rc.left, -rc.top);
OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining
// space and the owner's original position.
SetWindowPos (hDlg, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, SWP_NOSIZE);
// Set the CPU information inside the dialog. NB: This is for the 1st processor in a system only!
CPU = new CPUInfo ();
// Check to see if the CPU is supported.
if (CPU->DoesCPUSupportCPUID ()) {
SendDlgItemMessage (hDlg, IDC_VENDORID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetVendorID ());
SendDlgItemMessage (hDlg, IDC_TYPEID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetTypeID ());
SendDlgItemMessage (hDlg, IDC_FAMILYID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetFamilyID ());
SendDlgItemMessage (hDlg, IDC_MODELID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetModelID ());
SendDlgItemMessage (hDlg, IDC_STEPPING, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetSteppingCode ());
SendDlgItemMessage (hDlg, IDC_BRANDID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetExtendedProcessorName ());
SendDlgItemMessage (hDlg, IDC_PLATFORM, WM_SETTEXT, (WPARAM) 0, (LPARAM) OSDetection ());
} else {
SendDlgItemMessage (hDlg, IDC_BRANDID, WM_SETTEXT, (WPARAM) 0, (LPARAM) BAD_CPUID);
SendDlgItemMessage (hDlg, IDC_PLATFORM, WM_SETTEXT, (WPARAM) 0, (LPARAM) OSDetection ());
}
TVINSERTSTRUCT tvi;
TVITEM tvitem;
char szText[128];
// Configure the root of the items...
tvitem.mask = TVIF_TEXT; tvitem.cchTextMax = 128; tvitem.pszText = szText;
tvi.hParent = TVI_ROOT; tvi.hInsertAfter = TVI_SORT; tvi.item = tvitem;
// First put the processor it into the root of the tree.
sprintf (szText, TREE_LOADING);
TreeView_InsertItem (GetDlgItem (hDlg, IDC_FEATURETREE), &tvi);
// Create the threads to interrogate the processors.
CreateCPUInterrogationThreads (hDlg);
// Load the new icons for the window.
hBigIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON32), IMAGE_ICON, 32, 32, LR_COLOR);
if (hBigIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hBigIcon);
hSmallIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON16), IMAGE_ICON, 16, 16, LR_COLOR);
if (hSmallIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hSmallIcon);
// Display the dialog box.
ShowWindow (hDlg, SW_SHOW);
return true;
case WM_PAINT:
hDC = BeginPaint (hDlg, &ps);
EndPaint (hDlg, &ps);
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
EndDialog (hDlg, 0);
break;
case IDC_ABOUT:
CreateDialog (g_hInstance, MAKEINTRESOURCE (IDD_ABOUTDIALOG), hDlg, (DLGPROC) AboutDialog_DialogProc);
break;
}
break;
case WM_CLOSE:
EndDialog (hDlg, -1);
break;
case WM_DESTROY:
delete CPU;
break;
}
return false;
}
BOOL CALLBACK AboutDialog_DialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HWND hWndOwner;
PAINTSTRUCT ps;
RECT rc, rcOwner, rcDlg;
HICON hBigIcon, hSmallIcon;
switch (uMsg) {
case WM_INITDIALOG:
if ((hWndOwner = GetParent (hDlg)) == NULL) {
hWndOwner = GetDesktopWindow ();
}
GetWindowRect (hWndOwner, &rcOwner);
GetWindowRect (hDlg, &rcDlg);
CopyRect (&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that
// right and bottom values represent the width and
// height, and then offset the owner again to discard
// space taken up by the dialog box.
OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect (&rc, -rc.left, -rc.top);
OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining
// space and the owner's original position.
SetWindowPos (hDlg, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, SWP_NOSIZE);
// Load the new icons for the window.
hBigIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON32), IMAGE_ICON, 32, 32, LR_COLOR);
if (hBigIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hBigIcon);
hSmallIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON16), IMAGE_ICON, 16, 16, LR_COLOR);
if (hSmallIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hSmallIcon);
// Display the dialog box.
ShowWindow (hDlg, SW_SHOW);
return true;
case WM_PAINT:
hDC = BeginPaint (hDlg, &ps);
EndPaint (hDlg, &ps);
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
EndDialog (hDlg, 0);
break;
}
break;
case WM_CLOSE:
EndDialog (hDlg, -1);
break;
case WM_DESTROY:
break;
}
return false;
}
bool CreateCPUInterrogationThreads (HWND hDlg)
{
// Define the local variables.
HANDLE * hThread;
DWORD * dwThreadID;
SYSTEM_INFO SysInfo;
PTHREADINFO * ThreadInfo;
int nProcessors = 0;
// Get the number of processors in the system.
ZeroMemory (&SysInfo, sizeof (SYSTEM_INFO));
GetSystemInfo (&SysInfo);
// Number of physical processors in a non-Intel system
// or in a 32-bit Intel system with Hyper-Threading technology disabled
nProcessors = SysInfo.dwNumberOfProcessors;
// For each processor; spawn a CPU thread to access details.
hThread = new HANDLE [nProcessors];
dwThreadID = new DWORD [nProcessors];
ThreadInfo = new PTHREADINFO [nProcessors];
// Check to see if the memory allocation happenned.
if ((hThread == NULL) || (dwThreadID == NULL) || (ThreadInfo == NULL)) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot allocate memory for threads and CPU information structures!");
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
return false;
}
for (int nCounter = 0; nCounter < nProcessors; nCounter ++) {
ThreadInfo[nCounter] = new THREADINFO;
ThreadInfo[nCounter]->hDlg = hDlg;
ThreadInfo[nCounter]->nProcessor = nCounter + 1;
hThread[nCounter] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) DisplayCPUInformation, (LPVOID) ThreadInfo[nCounter], CREATE_SUSPENDED, &dwThreadID[nCounter]);
if (hThread[nCounter] == NULL) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot create processor interrogation thread for processor %d!", nCounter + 1);
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
}
// Set the threads affinity to the correct processor.
if (SetThreadAffinityMask (hThread[nCounter], nCounter + 1) == 0) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot set processor affinity for processor %d thread!", nCounter + 1);
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
}
ResumeThread (hThread[nCounter]);
}
// Clean up memory allocations.
delete [] ThreadInfo;
delete [] dwThreadID;
delete [] hThread;
// Return success;
return true;
}
DWORD WINAPI DisplayCPUInformation (LPVOID lpParameter)
{
PTHREADINFO ThreadInfo = (PTHREADINFO) lpParameter;
CPUInfo * CPU = new CPUInfo ();
HTREEITEM hRootNode;
HTREEITEM hParent;
TVINSERTSTRUCT tvi;
TVITEM tvitem;
char szText[128];
HWND hTreeCtrl;
// Configure the root of the items...
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = TVI_ROOT;
tvi.hInsertAfter = TVI_SORT;
tvi.item = tvitem;
// Get the handle to the tree control.
hTreeCtrl = GetDlgItem (ThreadInfo->hDlg, IDC_FEATURETREE);
// First remove the "Loading... Please Wait!".
tvitem.hItem = TreeView_GetRoot (hTreeCtrl);
TreeView_GetItem (hTreeCtrl, &tvitem);
if (strcmp (tvitem.pszText, TREE_LOADING) == 0) TreeView_DeleteItem (hTreeCtrl, tvitem.hItem);
// First put the processor it into the root of the tree.
sprintf (szText, "Processor %d", ThreadInfo->nProcessor);
// Create the new root node.
hRootNode = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the root of the items...
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
if (!CPU->DoesCPUSupportCPUID ()) {
// Inform the user that we cannot get any information.
sprintf (szText, BAD_CPUID);
TreeView_InsertItem (hTreeCtrl, &tvi);
// Cleanup memory allocations.
delete CPU;
// Terminate the thread.
return 0;
}
// Add the processor name - either extended or classical.
sprintf (szText, "Processor Name: %s", CPU->GetExtendedProcessorName ());
TreeView_InsertItem (hTreeCtrl, &tvi);
// Add the processor clock frequency.
sprintf (szText, "Clock Frequency: %d MHz", CPU->GetProcessorClockFrequency ());
TreeView_InsertItem (hTreeCtrl, &tvi);
// Display the processor serial number.
if (CPU->DoesCPUSupportFeature (SERIALNUMBER_FEATURE)) {
sprintf (szText, "Serial Number: %s", CPU->GetProcessorSerialNumber ());
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// Expand the root node.
TreeView_Expand (hTreeCtrl, hRootNode, TVE_EXPAND);
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the hardware specification node.
sprintf (szText, "On-Chip Hardware Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
// State the APIC ID if one is present.
if (CPU->DoesCPUSupportFeature (APIC_FEATURE)) {
HTREEITEM hTempParent;
// Display that the processor has an AGP Peripheral Component Interconnect [APIC].
sprintf (szText, "APIC Present");
hTempParent = TreeView_InsertItem (hTreeCtrl, &tvi);
tvi.hParent = hTempParent;
tvi.hInsertAfter = TVI_LAST;
// Attempt to display the ID of the APIC.
sprintf (szText, "APIC ID: %d", CPU->GetProcessorAPICID ());
TreeView_InsertItem (hTreeCtrl, &tvi);
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
}
// State if the processor supports the Advanced Configuration and Power Interface [ACPI].
if (CPU->DoesCPUSupportFeature (ACPI_FEATURE)) {
sprintf (szText, "ACPI Capable");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if the processor supports a thermal monitor.
if (CPU->DoesCPUSupportFeature (THERMALMONITOR_FEATURE)) {
sprintf (szText, "On-Chip Thermal Monitor");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// Check to see if L1\L2\L3 cache exists.
if (!CPU->DoesCPUSupportFeature (L1CACHE_FEATURE | L2CACHE_FEATURE | L3CACHE_FEATURE)) {
// Inform the user that on-chip cache is not supported.
sprintf (szText, "No L1\\L2\\L3 Cache Found");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State the size of the L1 cache if present.
if (CPU->DoesCPUSupportFeature (L1CACHE_FEATURE)) {
sprintf (szText, "L1 Cache: %dKB", CPU->GetProcessorCacheXSize (L1CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State the size of the L2 cache if present.
if (CPU->DoesCPUSupportFeature (L2CACHE_FEATURE)) {
sprintf (szText, "L2 Cache: %dKB", CPU->GetProcessorCacheXSize (L2CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State the size of the L3 cache if present.
if (CPU->DoesCPUSupportFeature (L3CACHE_FEATURE)) {
sprintf (szText, "L3 Cache: %dKB", CPU->GetProcessorCacheXSize (L3CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the hardware specification node.
sprintf (szText, "Power Management Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
// Check to see if power management is supported...
if (!CPU->DoesCPUSupportFeature (TEMPSENSEDIODE_FEATURE | FREQUENCYID_FEATURE | VOLTAGEID_FREQUENCY)) {
// Inform the user that power management is not supported.
sprintf (szText, "No On-Chip Support");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State if a temperature sensing diode is present.
if (CPU->DoesCPUSupportFeature (TEMPSENSEDIODE_FEATURE)) {
sprintf (szText, "Temperature Sensing Diode");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if a frequency ID control is present.
if (CPU->DoesCPUSupportFeature (FREQUENCYID_FEATURE)) {
sprintf (szText, "Frequency ID (FID) Control");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if a voltage ID control is present.
if (CPU->DoesCPUSupportFeature (VOLTAGEID_FREQUENCY)) {
sprintf (szText, "Voltage ID (VID) Control");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the features node.
sprintf (szText, "Supported Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control for images.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
if (!CPU->DoesCPUSupportFeature (CMOV_FEATURE | MTRR_FEATURE | MMX_FEATURE | MMX_PLUS_FEATURE | SSE_FEATURE |
SSE_FP_FEATURE | SSE_MMX_FEATURE | SSE2_FEATURE | AMD_3DNOW_FEATURE |
AMD_3DNOW_PLUS_FEATURE | HYPERTHREAD_FEATURE | MP_CAPABLE | IA64_FEATURE)) {
// Inform the user that no features were found.
sprintf (szText, "No Supported Features Found");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State if CMOV instructions are present.
if (CPU->DoesCPUSupportFeature (CMOV_FEATURE)) {
sprintf (szText, "CMOV Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MTRR instructions are present.
if (CPU->DoesCPUSupportFeature (MTRR_FEATURE)) {
sprintf (szText, "MTRR Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MMX instructions are present.
if (CPU->DoesCPUSupportFeature (MMX_FEATURE)) {
sprintf (szText, "MMX Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MMX+ instructions are present.
if (CPU->DoesCPUSupportFeature (MMX_PLUS_FEATURE)) {
sprintf (szText, "MMX+ Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_FEATURE)) {
sprintf (szText, "SSE Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE FP instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_FP_FEATURE)) {
sprintf (szText, "SSE FP Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE MMX instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_MMX_FEATURE)) {
sprintf (szText, "SSE MMX Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE2 instructions are present.
if (CPU->DoesCPUSupportFeature (SSE2_FEATURE)) {
sprintf (szText, "SSE2 Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if 3DNow! instructions are present.
if (CPU->DoesCPUSupportFeature (AMD_3DNOW_FEATURE)) {
sprintf (szText, "3DNow! Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if 3DNow!+ instructions are present.
if (CPU->DoesCPUSupportFeature (AMD_3DNOW_PLUS_FEATURE)) {
sprintf (szText, "3DNow!+ Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if Hyperthreading instructions are present.
if (CPU->DoesCPUSupportFeature (HYPERTHREAD_FEATURE)) {
sprintf (szText, "Hyperthreading Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
sprintf (szText, "Logical Processors Per Physical: %d", CPU->GetLogicalProcessorsPerPhysical ());
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if the processor is MP capable.
if (CPU->DoesCPUSupportFeature (MP_CAPABLE)) {
sprintf (szText, "Multi-processor Capable");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if IA64 instructions are present.
if (CPU->DoesCPUSupportFeature (IA64_FEATURE)) {
sprintf (szText, "IA64 Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Remove the CPUInfo object as we no longer need it.
delete CPU;
return 0;
}
char * OSDetection ()
{
OSVERSIONINFOEX osvi;
BOOL bIsWindows64Bit;
BOOL bOsVersionInfoEx;
char * szOperatingSystem = new char [256];
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
if (!(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))) {
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx ((OSVERSIONINFO *) &osvi)) return NULL;
}
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
// Test for the product.
if (osvi.dwMajorVersion <= 4) strcpy (szOperatingSystem, "Microsoft?Windows?NT ");
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) strcpy (szOperatingSystem, "Microsoft?Windows?2000 ");
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) strcpy (szOperatingSystem, "Microsoft?Windows?XP ");
// Test for product type.
if (bOsVersionInfoEx) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
if (osvi.wSuiteMask & VER_SUITE_PERSONAL) strcat (szOperatingSystem, "Personal ");
else strcat (szOperatingSystem, "Professional ");
} else if (osvi.wProductType == VER_NT_SERVER) {
// Check for .NET Server instead of Windows XP.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) strcpy (szOperatingSystem, "Microsoft?Windows?.NET ");
// Continue with the type detection.
if (osvi.wSuiteMask & VER_SUITE_DATACENTER) strcat (szOperatingSystem, "DataCenter Server ");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) strcat (szOperatingSystem, "Advanced Server ");
else strcat (szOperatingSystem, "Server ");
}
} else {
HKEY hKey;
char szProductType[80];
DWORD dwBufLen;
// Query the registry to retrieve information.
RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey);
RegQueryValueEx (hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
RegCloseKey (hKey);
if (lstrcmpi ("WINNT", szProductType) == 0) strcat (szOperatingSystem, "Professional ");
if (lstrcmpi ("LANMANNT", szProductType) == 0)
// Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
strcat (szOperatingSystem, "Standard Server ");
else strcat (szOperatingSystem, "Server ");
if (lstrcmpi ("SERVERNT", szProductType) == 0)
// Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
strcat (szOperatingSystem, "Enterprise Server ");
else strcat (szOperatingSystem, "Advanced Server ");
}
// Display version, service pack (if any), and build number.
if (osvi.dwMajorVersion <= 4) {
// NB: NT 4.0 and earlier.
sprintf (szOperatingSystem, "%sversion %d.%d %s (Build %d)",
szOperatingSystem,
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
// Windows XP and .NET server.
typedef BOOL (CALLBACK* LPFNPROC) (HANDLE, BOOL *);
HINSTANCE hKernelDLL;
LPFNPROC DLLProc;
// Load the Kernel32 DLL.
hKernelDLL = LoadLibrary ("kernel32");
if (hKernelDLL != NULL) {
// Only XP and .NET Server support IsWOW64Process so... Load dynamically!
DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");
// If the function address is valid, call the function.
if (DLLProc != NULL) (DLLProc) (GetCurrentProcess (), &bIsWindows64Bit);
else bIsWindows64Bit = false;
// Free the DLL module.
FreeLibrary (hKernelDLL);
}
// IsWow64Process ();
if (bIsWindows64Bit) strcat (szOperatingSystem, "64-Bit ");
else strcat (szOperatingSystem, "32-Bit ");
} else {
// Windows 2000 and everything else.
sprintf (szOperatingSystem, "%s%s(Build %d)", szOperatingSystem, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
}
break;
case VER_PLATFORM_WIN32_WINDOWS:
// Test for the product.
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
strcpy (szOperatingSystem, "Microsoft?Windows?95 ");
if (osvi.szCSDVersion[1] == 'C') strcat (szOperatingSystem, "OSR 2.5 ");
else if (osvi.szCSDVersion[1] == 'B') strcat (szOperatingSystem, "OSR 2 ");
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
strcpy (szOperatingSystem, "Microsoft?Windows?98 ");
if (osvi.szCSDVersion[1] == 'A' ) strcat (szOperatingSystem, "SE ");
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) {
strcpy (szOperatingSystem, "Microsoft?Windows?Me ");
}
break;
case VER_PLATFORM_WIN32s:
strcpy (szOperatingSystem, "Microsoft?Win32s ");
break;
default:
strcpy (szOperatingSystem, "Unknown Windows ");
break;
}
return szOperatingSystem;
}
#endif // _WIN32
// Copyright (C) 2002, Iain Chesworth
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "common.h"
// Included class header files.
#include "cpu_info.h"
// ----------------------------------------------------------------------------
//
// Win32 Code:
// This is code to run the Windows(tm) version of Camel.
//
// ----------------------------------------------------------------------------
#ifdef _WIN32
// Global variables.
HINSTANCE g_hInstance;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Save the instance handle.
g_hInstance = hInstance;
// Initialise the common controls.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof (INITCOMMONCONTROLSEX);
InitCtrls.dwICC = ICC_TREEVIEW_CLASSES;
InitCommonControlsEx (&InitCtrls);
// Create the dialog.
DialogBox (hInstance, MAKEINTRESOURCE (IDD_CPUDIALOG), NULL, (DLGPROC) CPUDialog_DialogProc);
return 0;
}
BOOL CALLBACK CPUDialog_DialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HWND hWndOwner;
PAINTSTRUCT ps;
static CPUInfo * CPU;
RECT rc, rcOwner, rcDlg;
HICON hBigIcon, hSmallIcon;
switch (uMsg) {
case WM_INITDIALOG:
if ((hWndOwner = GetParent (hDlg)) == NULL) {
hWndOwner = GetDesktopWindow ();
}
GetWindowRect (hWndOwner, &rcOwner);
GetWindowRect (hDlg, &rcDlg);
CopyRect (&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that
// right and bottom values represent the width and
// height, and then offset the owner again to discard
// space taken up by the dialog box.
OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect (&rc, -rc.left, -rc.top);
OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining
// space and the owner's original position.
SetWindowPos (hDlg, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, SWP_NOSIZE);
// Set the CPU information inside the dialog. NB: This is for the 1st processor in a system only!
CPU = new CPUInfo ();
// Check to see if the CPU is supported.
if (CPU->DoesCPUSupportCPUID ()) {
SendDlgItemMessage (hDlg, IDC_VENDORID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetVendorID ());
SendDlgItemMessage (hDlg, IDC_TYPEID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetTypeID ());
SendDlgItemMessage (hDlg, IDC_FAMILYID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetFamilyID ());
SendDlgItemMessage (hDlg, IDC_MODELID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetModelID ());
SendDlgItemMessage (hDlg, IDC_STEPPING, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetSteppingCode ());
SendDlgItemMessage (hDlg, IDC_BRANDID, WM_SETTEXT, (WPARAM) 0, (LPARAM) CPU->GetExtendedProcessorName ());
SendDlgItemMessage (hDlg, IDC_PLATFORM, WM_SETTEXT, (WPARAM) 0, (LPARAM) OSDetection ());
} else {
SendDlgItemMessage (hDlg, IDC_BRANDID, WM_SETTEXT, (WPARAM) 0, (LPARAM) BAD_CPUID);
SendDlgItemMessage (hDlg, IDC_PLATFORM, WM_SETTEXT, (WPARAM) 0, (LPARAM) OSDetection ());
}
TVINSERTSTRUCT tvi;
TVITEM tvitem;
char szText[128];
// Configure the root of the items...
tvitem.mask = TVIF_TEXT; tvitem.cchTextMax = 128; tvitem.pszText = szText;
tvi.hParent = TVI_ROOT; tvi.hInsertAfter = TVI_SORT; tvi.item = tvitem;
// First put the processor it into the root of the tree.
sprintf (szText, TREE_LOADING);
TreeView_InsertItem (GetDlgItem (hDlg, IDC_FEATURETREE), &tvi);
// Create the threads to interrogate the processors.
CreateCPUInterrogationThreads (hDlg);
// Load the new icons for the window.
hBigIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON32), IMAGE_ICON, 32, 32, LR_COLOR);
if (hBigIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hBigIcon);
hSmallIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON16), IMAGE_ICON, 16, 16, LR_COLOR);
if (hSmallIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hSmallIcon);
// Display the dialog box.
ShowWindow (hDlg, SW_SHOW);
return true;
case WM_PAINT:
hDC = BeginPaint (hDlg, &ps);
EndPaint (hDlg, &ps);
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
EndDialog (hDlg, 0);
break;
case IDC_ABOUT:
CreateDialog (g_hInstance, MAKEINTRESOURCE (IDD_ABOUTDIALOG), hDlg, (DLGPROC) AboutDialog_DialogProc);
break;
}
break;
case WM_CLOSE:
EndDialog (hDlg, -1);
break;
case WM_DESTROY:
delete CPU;
break;
}
return false;
}
BOOL CALLBACK AboutDialog_DialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HWND hWndOwner;
PAINTSTRUCT ps;
RECT rc, rcOwner, rcDlg;
HICON hBigIcon, hSmallIcon;
switch (uMsg) {
case WM_INITDIALOG:
if ((hWndOwner = GetParent (hDlg)) == NULL) {
hWndOwner = GetDesktopWindow ();
}
GetWindowRect (hWndOwner, &rcOwner);
GetWindowRect (hDlg, &rcDlg);
CopyRect (&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that
// right and bottom values represent the width and
// height, and then offset the owner again to discard
// space taken up by the dialog box.
OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect (&rc, -rc.left, -rc.top);
OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining
// space and the owner's original position.
SetWindowPos (hDlg, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, SWP_NOSIZE);
// Load the new icons for the window.
hBigIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON32), IMAGE_ICON, 32, 32, LR_COLOR);
if (hBigIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hBigIcon);
hSmallIcon = (HICON) LoadImage (g_hInstance, MAKEINTRESOURCE (IDI_APPICON16), IMAGE_ICON, 16, 16, LR_COLOR);
if (hSmallIcon != NULL) SendMessage (hDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hSmallIcon);
// Display the dialog box.
ShowWindow (hDlg, SW_SHOW);
return true;
case WM_PAINT:
hDC = BeginPaint (hDlg, &ps);
EndPaint (hDlg, &ps);
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
EndDialog (hDlg, 0);
break;
}
break;
case WM_CLOSE:
EndDialog (hDlg, -1);
break;
case WM_DESTROY:
break;
}
return false;
}
bool CreateCPUInterrogationThreads (HWND hDlg)
{
// Define the local variables.
HANDLE * hThread;
DWORD * dwThreadID;
SYSTEM_INFO SysInfo;
PTHREADINFO * ThreadInfo;
int nProcessors = 0;
// Get the number of processors in the system.
ZeroMemory (&SysInfo, sizeof (SYSTEM_INFO));
GetSystemInfo (&SysInfo);
// Number of physical processors in a non-Intel system
// or in a 32-bit Intel system with Hyper-Threading technology disabled
nProcessors = SysInfo.dwNumberOfProcessors;
// For each processor; spawn a CPU thread to access details.
hThread = new HANDLE [nProcessors];
dwThreadID = new DWORD [nProcessors];
ThreadInfo = new PTHREADINFO [nProcessors];
// Check to see if the memory allocation happenned.
if ((hThread == NULL) || (dwThreadID == NULL) || (ThreadInfo == NULL)) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot allocate memory for threads and CPU information structures!");
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
return false;
}
for (int nCounter = 0; nCounter < nProcessors; nCounter ++) {
ThreadInfo[nCounter] = new THREADINFO;
ThreadInfo[nCounter]->hDlg = hDlg;
ThreadInfo[nCounter]->nProcessor = nCounter + 1;
hThread[nCounter] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) DisplayCPUInformation, (LPVOID) ThreadInfo[nCounter], CREATE_SUSPENDED, &dwThreadID[nCounter]);
if (hThread[nCounter] == NULL) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot create processor interrogation thread for processor %d!", nCounter + 1);
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
}
// Set the threads affinity to the correct processor.
if (SetThreadAffinityMask (hThread[nCounter], nCounter + 1) == 0) {
char * szMessage = new char [128];
sprintf (szMessage, "Cannot set processor affinity for processor %d thread!", nCounter + 1);
MessageBox (hDlg, szMessage, APP_TITLE, MB_OK | MB_ICONSTOP);
delete szMessage;
}
ResumeThread (hThread[nCounter]);
}
// Clean up memory allocations.
delete [] ThreadInfo;
delete [] dwThreadID;
delete [] hThread;
// Return success;
return true;
}
DWORD WINAPI DisplayCPUInformation (LPVOID lpParameter)
{
PTHREADINFO ThreadInfo = (PTHREADINFO) lpParameter;
CPUInfo * CPU = new CPUInfo ();
HTREEITEM hRootNode;
HTREEITEM hParent;
TVINSERTSTRUCT tvi;
TVITEM tvitem;
char szText[128];
HWND hTreeCtrl;
// Configure the root of the items...
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = TVI_ROOT;
tvi.hInsertAfter = TVI_SORT;
tvi.item = tvitem;
// Get the handle to the tree control.
hTreeCtrl = GetDlgItem (ThreadInfo->hDlg, IDC_FEATURETREE);
// First remove the "Loading... Please Wait!".
tvitem.hItem = TreeView_GetRoot (hTreeCtrl);
TreeView_GetItem (hTreeCtrl, &tvitem);
if (strcmp (tvitem.pszText, TREE_LOADING) == 0) TreeView_DeleteItem (hTreeCtrl, tvitem.hItem);
// First put the processor it into the root of the tree.
sprintf (szText, "Processor %d", ThreadInfo->nProcessor);
// Create the new root node.
hRootNode = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the root of the items...
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
if (!CPU->DoesCPUSupportCPUID ()) {
// Inform the user that we cannot get any information.
sprintf (szText, BAD_CPUID);
TreeView_InsertItem (hTreeCtrl, &tvi);
// Cleanup memory allocations.
delete CPU;
// Terminate the thread.
return 0;
}
// Add the processor name - either extended or classical.
sprintf (szText, "Processor Name: %s", CPU->GetExtendedProcessorName ());
TreeView_InsertItem (hTreeCtrl, &tvi);
// Add the processor clock frequency.
sprintf (szText, "Clock Frequency: %d MHz", CPU->GetProcessorClockFrequency ());
TreeView_InsertItem (hTreeCtrl, &tvi);
// Display the processor serial number.
if (CPU->DoesCPUSupportFeature (SERIALNUMBER_FEATURE)) {
sprintf (szText, "Serial Number: %s", CPU->GetProcessorSerialNumber ());
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// Expand the root node.
TreeView_Expand (hTreeCtrl, hRootNode, TVE_EXPAND);
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the hardware specification node.
sprintf (szText, "On-Chip Hardware Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
// State the APIC ID if one is present.
if (CPU->DoesCPUSupportFeature (APIC_FEATURE)) {
HTREEITEM hTempParent;
// Display that the processor has an AGP Peripheral Component Interconnect [APIC].
sprintf (szText, "APIC Present");
hTempParent = TreeView_InsertItem (hTreeCtrl, &tvi);
tvi.hParent = hTempParent;
tvi.hInsertAfter = TVI_LAST;
// Attempt to display the ID of the APIC.
sprintf (szText, "APIC ID: %d", CPU->GetProcessorAPICID ());
TreeView_InsertItem (hTreeCtrl, &tvi);
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
}
// State if the processor supports the Advanced Configuration and Power Interface [ACPI].
if (CPU->DoesCPUSupportFeature (ACPI_FEATURE)) {
sprintf (szText, "ACPI Capable");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if the processor supports a thermal monitor.
if (CPU->DoesCPUSupportFeature (THERMALMONITOR_FEATURE)) {
sprintf (szText, "On-Chip Thermal Monitor");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// Check to see if L1\L2\L3 cache exists.
if (!CPU->DoesCPUSupportFeature (L1CACHE_FEATURE | L2CACHE_FEATURE | L3CACHE_FEATURE)) {
// Inform the user that on-chip cache is not supported.
sprintf (szText, "No L1\\L2\\L3 Cache Found");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State the size of the L1 cache if present.
if (CPU->DoesCPUSupportFeature (L1CACHE_FEATURE)) {
sprintf (szText, "L1 Cache: %dKB", CPU->GetProcessorCacheXSize (L1CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State the size of the L2 cache if present.
if (CPU->DoesCPUSupportFeature (L2CACHE_FEATURE)) {
sprintf (szText, "L2 Cache: %dKB", CPU->GetProcessorCacheXSize (L2CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State the size of the L3 cache if present.
if (CPU->DoesCPUSupportFeature (L3CACHE_FEATURE)) {
sprintf (szText, "L3 Cache: %dKB", CPU->GetProcessorCacheXSize (L3CACHE_FEATURE));
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the hardware specification node.
sprintf (szText, "Power Management Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
// Check to see if power management is supported...
if (!CPU->DoesCPUSupportFeature (TEMPSENSEDIODE_FEATURE | FREQUENCYID_FEATURE | VOLTAGEID_FREQUENCY)) {
// Inform the user that power management is not supported.
sprintf (szText, "No On-Chip Support");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State if a temperature sensing diode is present.
if (CPU->DoesCPUSupportFeature (TEMPSENSEDIODE_FEATURE)) {
sprintf (szText, "Temperature Sensing Diode");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if a frequency ID control is present.
if (CPU->DoesCPUSupportFeature (FREQUENCYID_FEATURE)) {
sprintf (szText, "Frequency ID (FID) Control");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if a voltage ID control is present.
if (CPU->DoesCPUSupportFeature (VOLTAGEID_FREQUENCY)) {
sprintf (szText, "Voltage ID (VID) Control");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Configure the tree control to not write to the root.
tvi.hParent = hRootNode;
tvi.hInsertAfter = TVI_LAST;
// Add the features node.
sprintf (szText, "Supported Features");
hParent = TreeView_InsertItem (hTreeCtrl, &tvi);
// Configure the treeview control for images.
tvitem.mask = TVIF_TEXT;
tvitem.cchTextMax = 128;
tvitem.pszText = szText;
tvi.hParent = hParent;
tvi.hInsertAfter = TVI_LAST;
if (!CPU->DoesCPUSupportFeature (CMOV_FEATURE | MTRR_FEATURE | MMX_FEATURE | MMX_PLUS_FEATURE | SSE_FEATURE |
SSE_FP_FEATURE | SSE_MMX_FEATURE | SSE2_FEATURE | AMD_3DNOW_FEATURE |
AMD_3DNOW_PLUS_FEATURE | HYPERTHREAD_FEATURE | MP_CAPABLE | IA64_FEATURE)) {
// Inform the user that no features were found.
sprintf (szText, "No Supported Features Found");
TreeView_InsertItem (hTreeCtrl, &tvi);
} else {
// State if CMOV instructions are present.
if (CPU->DoesCPUSupportFeature (CMOV_FEATURE)) {
sprintf (szText, "CMOV Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MTRR instructions are present.
if (CPU->DoesCPUSupportFeature (MTRR_FEATURE)) {
sprintf (szText, "MTRR Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MMX instructions are present.
if (CPU->DoesCPUSupportFeature (MMX_FEATURE)) {
sprintf (szText, "MMX Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if MMX+ instructions are present.
if (CPU->DoesCPUSupportFeature (MMX_PLUS_FEATURE)) {
sprintf (szText, "MMX+ Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_FEATURE)) {
sprintf (szText, "SSE Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE FP instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_FP_FEATURE)) {
sprintf (szText, "SSE FP Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE MMX instructions are present.
if (CPU->DoesCPUSupportFeature (SSE_MMX_FEATURE)) {
sprintf (szText, "SSE MMX Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if SSE2 instructions are present.
if (CPU->DoesCPUSupportFeature (SSE2_FEATURE)) {
sprintf (szText, "SSE2 Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if 3DNow! instructions are present.
if (CPU->DoesCPUSupportFeature (AMD_3DNOW_FEATURE)) {
sprintf (szText, "3DNow! Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if 3DNow!+ instructions are present.
if (CPU->DoesCPUSupportFeature (AMD_3DNOW_PLUS_FEATURE)) {
sprintf (szText, "3DNow!+ Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if Hyperthreading instructions are present.
if (CPU->DoesCPUSupportFeature (HYPERTHREAD_FEATURE)) {
sprintf (szText, "Hyperthreading Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
sprintf (szText, "Logical Processors Per Physical: %d", CPU->GetLogicalProcessorsPerPhysical ());
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if the processor is MP capable.
if (CPU->DoesCPUSupportFeature (MP_CAPABLE)) {
sprintf (szText, "Multi-processor Capable");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
// State if IA64 instructions are present.
if (CPU->DoesCPUSupportFeature (IA64_FEATURE)) {
sprintf (szText, "IA64 Instructions");
TreeView_InsertItem (hTreeCtrl, &tvi);
}
}
// Remove the CPUInfo object as we no longer need it.
delete CPU;
return 0;
}
char * OSDetection ()
{
OSVERSIONINFOEX osvi;
BOOL bIsWindows64Bit;
BOOL bOsVersionInfoEx;
char * szOperatingSystem = new char [256];
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
if (!(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))) {
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx ((OSVERSIONINFO *) &osvi)) return NULL;
}
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
// Test for the product.
if (osvi.dwMajorVersion <= 4) strcpy (szOperatingSystem, "Microsoft?Windows?NT ");
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) strcpy (szOperatingSystem, "Microsoft?Windows?2000 ");
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) strcpy (szOperatingSystem, "Microsoft?Windows?XP ");
// Test for product type.
if (bOsVersionInfoEx) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
if (osvi.wSuiteMask & VER_SUITE_PERSONAL) strcat (szOperatingSystem, "Personal ");
else strcat (szOperatingSystem, "Professional ");
} else if (osvi.wProductType == VER_NT_SERVER) {
// Check for .NET Server instead of Windows XP.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) strcpy (szOperatingSystem, "Microsoft?Windows?.NET ");
// Continue with the type detection.
if (osvi.wSuiteMask & VER_SUITE_DATACENTER) strcat (szOperatingSystem, "DataCenter Server ");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) strcat (szOperatingSystem, "Advanced Server ");
else strcat (szOperatingSystem, "Server ");
}
} else {
HKEY hKey;
char szProductType[80];
DWORD dwBufLen;
// Query the registry to retrieve information.
RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey);
RegQueryValueEx (hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
RegCloseKey (hKey);
if (lstrcmpi ("WINNT", szProductType) == 0) strcat (szOperatingSystem, "Professional ");
if (lstrcmpi ("LANMANNT", szProductType) == 0)
// Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
strcat (szOperatingSystem, "Standard Server ");
else strcat (szOperatingSystem, "Server ");
if (lstrcmpi ("SERVERNT", szProductType) == 0)
// Decide between Windows 2000 Advanced Server and Windows .NET Enterprise Server.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
strcat (szOperatingSystem, "Enterprise Server ");
else strcat (szOperatingSystem, "Advanced Server ");
}
// Display version, service pack (if any), and build number.
if (osvi.dwMajorVersion <= 4) {
// NB: NT 4.0 and earlier.
sprintf (szOperatingSystem, "%sversion %d.%d %s (Build %d)",
szOperatingSystem,
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
// Windows XP and .NET server.
typedef BOOL (CALLBACK* LPFNPROC) (HANDLE, BOOL *);
HINSTANCE hKernelDLL;
LPFNPROC DLLProc;
// Load the Kernel32 DLL.
hKernelDLL = LoadLibrary ("kernel32");
if (hKernelDLL != NULL) {
// Only XP and .NET Server support IsWOW64Process so... Load dynamically!
DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");
// If the function address is valid, call the function.
if (DLLProc != NULL) (DLLProc) (GetCurrentProcess (), &bIsWindows64Bit);
else bIsWindows64Bit = false;
// Free the DLL module.
FreeLibrary (hKernelDLL);
}
// IsWow64Process ();
if (bIsWindows64Bit) strcat (szOperatingSystem, "64-Bit ");
else strcat (szOperatingSystem, "32-Bit ");
} else {
// Windows 2000 and everything else.
sprintf (szOperatingSystem, "%s%s(Build %d)", szOperatingSystem, osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
}
break;
case VER_PLATFORM_WIN32_WINDOWS:
// Test for the product.
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) {
strcpy (szOperatingSystem, "Microsoft?Windows?95 ");
if (osvi.szCSDVersion[1] == 'C') strcat (szOperatingSystem, "OSR 2.5 ");
else if (osvi.szCSDVersion[1] == 'B') strcat (szOperatingSystem, "OSR 2 ");
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) {
strcpy (szOperatingSystem, "Microsoft?Windows?98 ");
if (osvi.szCSDVersion[1] == 'A' ) strcat (szOperatingSystem, "SE ");
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) {
strcpy (szOperatingSystem, "Microsoft?Windows?Me ");
}
break;
case VER_PLATFORM_WIN32s:
strcpy (szOperatingSystem, "Microsoft?Win32s ");
break;
default:
strcpy (szOperatingSystem, "Unknown Windows ");
break;
}
return szOperatingSystem;
}
#endif // _WIN32
'Windows > Windows API' 카테고리의 다른 글
disk free space (wince) (0) | 2013.10.01 |
---|---|
local ip address (wince) (0) | 2013.10.01 |
CenterWindow (0) | 2013.10.01 |
DrawTransparentBitmap (0) | 2013.10.01 |
system tray (0) | 2013.10.01 |