2020-09-30 17:12:29 +02:00

515 lines
14 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
All rights reserved.
Module Name:
compinfo.hxx
Abstract:
Local and remote computer information detection.
Author:
10/17/95 <adamk> created.
Steve Kiraly (SteveKi) 21-Jan-1996 used for downlevel server detection
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "compinfo.hxx"
#pragma warning ( disable : 4706 ) /* Disable assignment within conditional */
LPCTSTR CComputerInfo::GetProcessorArchitectureName() const
{
SPLASSERT(IsInfoValid());
switch (ProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
{
return PROCESSOR_ARCHITECTURE_NAME_INTEL;
}
case PROCESSOR_ARCHITECTURE_MIPS:
{
return PROCESSOR_ARCHITECTURE_NAME_MIPS;
}
case PROCESSOR_ARCHITECTURE_ALPHA:
{
return PROCESSOR_ARCHITECTURE_NAME_ALPHA;
}
case PROCESSOR_ARCHITECTURE_PPC:
{
return PROCESSOR_ARCHITECTURE_NAME_POWERPC;
}
default:
{
return PROCESSOR_ARCHITECTURE_NAME_UNKNOWN;
}
}
}
LPCTSTR CComputerInfo::GetProcessorArchitectureDirectoryName() const
{
SPLASSERT(IsInfoValid());
switch (ProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
{
return TEXT("i386");
}
case PROCESSOR_ARCHITECTURE_MIPS:
{
return TEXT("mips");
}
case PROCESSOR_ARCHITECTURE_ALPHA:
{
return TEXT("alpha");
}
case PROCESSOR_ARCHITECTURE_PPC:
{
return TEXT("ppc");
}
default:
{
return PROCESSOR_ARCHITECTURE_NAME_UNKNOWN;
}
}
}
LPCTSTR CComputerInfo::GetNativeEnvironment() const
{
SPLASSERT(IsInfoValid());
switch (ProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
{
if (IsRunningWindows95())
{
return ENVIRONMENT_WINDOWS;
}
else
{
return ENVIRONMENT_INTEL;
}
}
case PROCESSOR_ARCHITECTURE_MIPS:
{
return ENVIRONMENT_MIPS;
}
case PROCESSOR_ARCHITECTURE_ALPHA:
{
return ENVIRONMENT_ALPHA;
}
case PROCESSOR_ARCHITECTURE_PPC:
{
return ENVIRONMENT_POWERPC;
}
default:
{
SPLASSERT(FALSE);
return ENVIRONMENT_UNKNOWN;
}
}
}
BOOL CComputerInfo::GetInfo()
{
// NOTE: OSInfo.dwOSVersionInfoSize must be non-zero after the info is retrieved.
DWORD ErrorCode = ERROR_SUCCESS;
LPTSTR pCPUName = NULL;
LPTSTR pBuildNumberText = NULL;
LPTSTR pVersionText = NULL;
LPTSTR pCSDVersionText = NULL;
LPTSTR pOSTypeText = NULL;
// set size of version info structure
OSInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if( ComputerName.bEmpty() )
{
SYSTEM_INFO SystemInfo;
// get operating system info
if (!GetVersionEx(&OSInfo))
{
ErrorCode = GetLastError();
goto CleanUp;
}
// get hardware info
GetSystemInfo(&SystemInfo);
ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
ProcessorCount = SystemInfo.dwNumberOfProcessors;
}
else
{
REGISTRY_KEY_INFO RegistryKeyInfo;
// determine operating system
// if this key is found, then the OS is Windows NT
// if this key cannot be found, then the OS is Windows 95
// otherwise, it is an error
pBuildNumberText = AllocateRegistryString(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
TEXT("CurrentBuildNumber"));
if (GetLastError() == ERROR_CANTOPEN)
{
// operating system is Windows 95
OSInfo.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
// get OS version
pVersionText = AllocateRegistryString(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"),
TEXT("Version"));
if (GetLastError() != ERROR_SUCCESS)
{
ErrorCode = GetLastError();
goto CleanUp;
}
// parse OS version
OSInfo.dwMajorVersion = _tcstoul(_tcstok(pVersionText, TEXT(".")), NULL, 10);
OSInfo.dwMinorVersion = _tcstoul(_tcstok(NULL, TEXT(".")), NULL, 10);
OSInfo.dwBuildNumber = _tcstoul(_tcstok(NULL, TEXT(".")), NULL, 10);
// get CSD version
OSInfo.szCSDVersion[0] = TEXT('\0');
// processor must be Intel
ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
// processor count must be 1
ProcessorCount = 1;
}
else if (GetLastError() == ERROR_SUCCESS)
{
// operating system is Windows NT
OSInfo.dwPlatformId = VER_PLATFORM_WIN32_NT;
// parse build number (which was just retrieved)
OSInfo.dwBuildNumber = _tcstoul(pBuildNumberText, NULL, 10);
// get OS version
pVersionText = AllocateRegistryString(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
TEXT("CurrentVersion"));
if (GetLastError() != ERROR_SUCCESS)
{
ErrorCode = GetLastError();
goto CleanUp;
}
// parse OS version
OSInfo.dwMajorVersion = _tcstoul(_tcstok(pVersionText, TEXT(".")), NULL, 10);
OSInfo.dwMinorVersion = _tcstoul(_tcstok(NULL, TEXT(".")), NULL, 10);
// get CSD version
OSInfo.szCSDVersion[0] = TEXT('\0');
pCSDVersionText = AllocateRegistryString(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
TEXT("CSDVersion"));
if (GetLastError() == ERROR_SUCCESS)
{
_tcsncpy(OSInfo.szCSDVersion, pCSDVersionText, 127);
}
// get name of cpu
pCPUName = AllocateRegistryString(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
TEXT("Identifier"));
if (GetLastError() != ERROR_SUCCESS)
{
ErrorCode = GetLastError();
goto CleanUp;
}
// determine processor architecture from cpu name
if (!_tcsnicmp(pCPUName, TEXT("80386-"), 6)
|| !_tcsnicmp(pCPUName, TEXT("80486-"), 6)
|| !_tcsnicmp(pCPUName, TEXT("x86 "), 4))
{
ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
}
else if (!_tcsnicmp(pCPUName, TEXT("MIPS-"), 5)
|| !_tcsnicmp(pCPUName, TEXT("Tyne"), 4))
{
ProcessorArchitecture = PROCESSOR_ARCHITECTURE_MIPS;
}
else if (!_tcsnicmp(pCPUName, TEXT("DEC-"), 4))
{
ProcessorArchitecture = PROCESSOR_ARCHITECTURE_ALPHA;
}
else if(!_tcsnicmp(pCPUName, TEXT("PowerPC"), 7))
{
ProcessorArchitecture = PROCESSOR_ARCHITECTURE_PPC;
}
else
{
SPLASSERT(FALSE);
ProcessorArchitecture = 0;
}
// get processor count
// On Windows NT, this can be determined by the number of subkeys of the following
// registry key.
if (!GetRegistryKeyInfo(ComputerName, HKEY_LOCAL_MACHINE,
TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor"),
&RegistryKeyInfo))
{
ErrorCode = GetLastError();
goto CleanUp;
}
ProcessorCount = RegistryKeyInfo.NumSubKeys;
}
else
{
ErrorCode = GetLastError();
goto CleanUp;
}
}
// determine whether OS is retail or debug
OSIsDebugVersion = FALSE;
if (OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// get OS type
pOSTypeText = AllocateRegistryString(ComputerName,
HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
TEXT("CurrentType"));
if (GetLastError() != ERROR_SUCCESS)
{
ErrorCode = GetLastError();
goto CleanUp;
}
// if the type text contains the word "Checked",
// then it is a debug build
OSIsDebugVersion = (_tcsstr(pOSTypeText, TEXT("Checked")) != NULL);
}
CleanUp:
if (pCPUName)
{
GlobalFree(pCPUName);
}
if (pBuildNumberText)
{
GlobalFree(pBuildNumberText);
}
if (pVersionText)
{
GlobalFree(pVersionText);
}
if (pCSDVersionText)
{
GlobalFree(pCSDVersionText);
}
if (pOSTypeText)
{
GlobalFree(pOSTypeText);
}
if (ErrorCode)
{
SetLastError(ErrorCode);
return FALSE;
}
else
{
return TRUE;
}
}
BOOL CComputerInfo::IsInfoValid() const
{
// if OSInfo.dwOSVersionInfoSize is not zero, then the info has been retrieved
return (BOOL) (OSInfo.dwOSVersionInfoSize != 0);
}
////////////////////////////////////////////////////////////////////////////////
//
// AllocateRegistryString returns a copy of the string value stored at the
// specified registry key. The registry can be on either a remote machine or
// the local machine.
//
// Parameter Description
// -----------------------------------------------------------------------------
// pServerName Name of server on which registry resides.
// hRegistryRoot Registry root (i.e. HKEY_LOCAL_MACHINE). See RegConnectRegistry
// for acceptable values.
// pKeyName Name of registry key.
// pValueName Name of registry value. The value must be of type REG_SZ.
//
// Returns:
// If successful, the function returns a pointer to a copy of the string.
// If the function fails, GetLastError() will return an error code other than
// ERROR_SUCCESS, and NULL is returned from the function.
// Revision History:
// 10/17/95 <adamk> created.
//
LPTSTR AllocateRegistryString(LPCTSTR pServerName, HKEY hRegistryRoot,
LPCTSTR pKeyName, LPCTSTR pValueName)
{
DWORD ErrorCode = 0;
HKEY hRegistry = 0;
HKEY hRegistryKey = 0;
DWORD RegistryValueType;
DWORD RegistryValueSize;
LPTSTR pString = NULL;
// connect to the registry of the specified machine
if (ErrorCode = RegConnectRegistry((LPTSTR) pServerName, hRegistryRoot, &hRegistry))
{
goto CleanUp;
}
// open the registry key
if (ErrorCode = RegOpenKeyEx(hRegistry, pKeyName, 0, KEY_QUERY_VALUE, &hRegistryKey))
{
goto CleanUp;
}
// query the value's type and size
if(ErrorCode = RegQueryValueEx(hRegistryKey, pValueName, NULL, &RegistryValueType, NULL,
&RegistryValueSize))
{
goto CleanUp;
}
// make sure the value is a string
if (RegistryValueType != REG_SZ)
{
ErrorCode = ERROR_INVALID_PARAMETER;
goto CleanUp;
}
if (!(pString = (LPTSTR) GlobalAlloc(GMEM_FIXED, RegistryValueSize)))
{
ErrorCode = GetLastError();
goto CleanUp;
}
if (ErrorCode = RegQueryValueEx(hRegistryKey, pValueName, NULL, &RegistryValueType,
(LPBYTE) pString, &RegistryValueSize))
{
ErrorCode = GetLastError();
goto CleanUp;
}
CleanUp:
if (hRegistryKey)
{
RegCloseKey(hRegistryKey);
}
if (hRegistry)
{
RegCloseKey(hRegistry);
}
if (ErrorCode && pString)
{
GlobalFree(pString);
pString = NULL;
}
SetLastError (ErrorCode);
return pString;
}
////////////////////////////////////////////////////////////////////////////////
//
// GetRegistrySubKeyCount returns the number of subkeys that the specified
// registry key contains. The registry can be on either a remote machine or
// the local machine.
//
// Parameter Description
// -----------------------------------------------------------------------------
// pServerName Name of server on which registry resides.
// hRegistryRoot Registry root (i.e. HKEY_LOCAL_MACHINE). See RegConnectRegistry
// for acceptable values.
// pKeyName Name of registry key.
//
// Returns:
// If successful, the function returns the number of subkeys and GetLastError()
// will return ERROR_SUCCESS. Otherwise, GetLastError() return the error code
// indicating the reason for the failure.
// Revision History:
// 10/23/95 <adamk> created.
//
BOOL GetRegistryKeyInfo(LPCTSTR pServerName, HKEY hRegistryRoot, LPCTSTR pKeyName,
REGISTRY_KEY_INFO* pKeyInfo)
{
DWORD ErrorCode = 0;
HKEY hRegistry = 0;
HKEY hRegistryKey = 0;
// connect to the registry of the specified machine
if (ErrorCode = RegConnectRegistry((LPTSTR) pServerName, hRegistryRoot, &hRegistry))
{
goto CleanUp;
}
// open the registry key
if (ErrorCode = RegOpenKeyEx(hRegistry, pKeyName, 0, KEY_QUERY_VALUE, &hRegistryKey))
{
goto CleanUp;
}
// get the key info
if (ErrorCode = RegQueryInfoKey(hRegistryKey, NULL, 0, 0, &pKeyInfo->NumSubKeys,
&pKeyInfo->MaxSubKeyLength, &pKeyInfo->MaxClassLength, &pKeyInfo->NumValues,
&pKeyInfo->MaxValueNameLength, &pKeyInfo->MaxValueDataLength,
&pKeyInfo->SecurityDescriptorLength, &pKeyInfo->LastWriteTime))
{
goto CleanUp;
}
CleanUp:
if (hRegistryKey)
{
RegCloseKey(hRegistryKey);
}
if (hRegistry)
{
RegCloseKey(hRegistry);
}
if (ErrorCode)
{
SetLastError(ErrorCode);
return FALSE;
}
else
{
return TRUE;
}
}