2204 lines
55 KiB
C++
2204 lines
55 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXSysInfo
|
|
// ==========================================================================
|
|
//
|
|
// Version: 9.3
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "OXSysInfo.h"
|
|
#include "OXMainRes.h"
|
|
|
|
#include <winsock.h>
|
|
#include <afxdisp.h> // MFC OLE automation classes
|
|
#include <math.h>
|
|
|
|
#include <lm.h>
|
|
#include <lmerr.h>
|
|
#include <lmaccess.h>
|
|
|
|
#include "UTBStrOp.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
// Constants used to set unitialized values
|
|
#define UNINIT_BYTE 0x17
|
|
#define UNINIT_DWORD 0x17171717
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(COXSysInfo, CObject)
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// None
|
|
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
COXSysInfo::COXSysInfo()
|
|
{
|
|
// constructor
|
|
}
|
|
|
|
COXSysInfo::~COXSysInfo()
|
|
{
|
|
// destructor
|
|
}
|
|
|
|
BOOL COXSysInfo::GetComputerName(CString *psComputerName) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psComputerName: Name of local computer
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the name of the local computer
|
|
|
|
ASSERT(psComputerName != NULL);
|
|
|
|
BOOL bReturn;
|
|
DWORD dwBufSize;
|
|
TCHAR buffer[MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
dwBufSize = sizeof(buffer)/sizeof(buffer[0]);
|
|
|
|
bReturn = ::GetComputerName(buffer, &dwBufSize);
|
|
|
|
if (bReturn)
|
|
*psComputerName = buffer;
|
|
else
|
|
{
|
|
TRACE(_T("COXSysInfo::GetComputerName - ::GetComputerName() failed\n"));
|
|
}
|
|
|
|
return (bReturn);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetUserName(CString *psUserName) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psUserName: Name of current user
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the name of the current user
|
|
|
|
ASSERT(psUserName != NULL);
|
|
|
|
BOOL bReturn;
|
|
DWORD dwBufSize;
|
|
TCHAR buffer[UNLEN+1];
|
|
|
|
dwBufSize = sizeof(buffer)/sizeof(buffer[0]);
|
|
|
|
bReturn = ::GetUserName(buffer, &dwBufSize);
|
|
|
|
if (bReturn)
|
|
*psUserName = buffer;
|
|
else
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserName - ::GetUserName() failed\n"));
|
|
}
|
|
|
|
return (bReturn);
|
|
}
|
|
|
|
|
|
BOOL COXSysInfo::GetUserAndDomainName(CString *psUserName, CString *psDomainName) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psUserName: Name of current user
|
|
// CString *psDomainName: Name of current domain logged on to
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the name of the current user and the domain. Works only
|
|
// on Win NT.
|
|
|
|
ASSERT(psUserName != NULL);
|
|
ASSERT(psDomainName != NULL);
|
|
|
|
BOOL bSuccess = FALSE;
|
|
#define BUF_SIZE 512
|
|
DWORD dwBufSize = BUF_SIZE;
|
|
TCHAR buffer[BUF_SIZE];
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
if (bIsNT)
|
|
// We're running on NT.
|
|
{
|
|
HANDLE hToken(0);
|
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
|
|
{
|
|
if (GetLastError() == ERROR_NO_TOKEN)
|
|
// We'll try to open the process token since no thread token exists
|
|
{
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserAndDomainName - ::OpenProcessToken() failed\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
// Failed to get the thread token
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserAndDomainName - ::OpenThreadToken() failed\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
ASSERT(hToken != NULL);
|
|
bSuccess = GetTokenInformation(hToken, TokenUser, buffer, dwBufSize, &dwBufSize);
|
|
|
|
if (!bSuccess)
|
|
{
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
// Allocate a bigger bufer and try again
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserAndDomainName - Insuffient buffer() trying again ...\n"));
|
|
CloseHandle(hToken);
|
|
return FALSE;
|
|
}
|
|
else
|
|
// We have an error while getting the token info
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserAndDomainName - ::GetTokenInformation() failed\n"));
|
|
CloseHandle(hToken);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
CloseHandle(hToken);
|
|
|
|
SID_NAME_USE Snu;
|
|
DWORD dwUserName = BUF_SIZE;
|
|
DWORD dwDomainName = BUF_SIZE;
|
|
TCHAR userName[BUF_SIZE];
|
|
TCHAR domainName[BUF_SIZE];
|
|
|
|
bSuccess = LookupAccountSid(NULL, ((PTOKEN_USER)buffer)->User.Sid, userName, &dwUserName, domainName, &dwDomainName, &Snu);
|
|
if (bSuccess)
|
|
{
|
|
*psUserName = userName;
|
|
*psDomainName = domainName;
|
|
}
|
|
}
|
|
else
|
|
// Not Win NT
|
|
{
|
|
TRACE(_T("COXSysInfo::GetUserAndDomainName : NON WIN NT NOT SUPPORTED\n"));
|
|
VERIFY(psUserName->LoadString(IDS_OX_SYSINFOUNKNOWNUSER)); //"<UNKNOWN>"
|
|
VERIFY(psDomainName->LoadString(IDS_OX_SYSINFOUNKNOWNDOMAIN)); //"<UNKNOWN>"
|
|
}
|
|
|
|
return (bSuccess);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetPrimaryIPAddress(CString *psIPAddress,
|
|
LPCSTR pszHostName/*=NULL*/) const
|
|
{
|
|
// --- In: LPCSTR pszHostName: Host name for which primary
|
|
// IP address will be retrieved
|
|
// --- Out: CString *psIPAddress: Current IP address (0.0.0.0
|
|
// if undefined)
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the current network IP address
|
|
|
|
ASSERT(psIPAddress != NULL);
|
|
|
|
CStringArray IPArray;
|
|
if(!GetListIPAddresses(&IPArray,TRUE,pszHostName))
|
|
return FALSE;
|
|
|
|
*psIPAddress=IPArray[0];
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetListIPAddresses(CStringArray* psIPAddressList,
|
|
BOOL bPrimary /* = FALSE */,
|
|
LPCSTR pszHostName/*=NULL*/) const
|
|
{
|
|
// --- In: BOOL bPrimary : TRUE if only primary IP must be
|
|
// retrieved
|
|
// LPCSTR pszHostName: Host name for which IP address
|
|
// will be retrieved
|
|
// --- Out: CStringArray* psIPAddressList: List of IP addresses
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the list of network IP address of a
|
|
// multi-homed computer
|
|
|
|
ASSERT(psIPAddressList!=NULL);
|
|
|
|
CHAR buffer[255];
|
|
WORD wVersionRequested;
|
|
WSADATA wsaData;
|
|
int err;
|
|
|
|
HINSTANCE hLib = LoadLibrary(_T("WS2_32.DLL"));
|
|
if (hLib != NULL)
|
|
{
|
|
// Loaded WS2_32.DLL...
|
|
typedef int (WINAPI* WSASTARTUP) (WORD wVersionRequested, LPWSADATA lpWSAData);
|
|
WSASTARTUP dWSAStartup = (WSASTARTUP) GetProcAddress(hLib, "WSAStartup");
|
|
|
|
typedef int (WINAPI* GETHOSTNAME) (char FAR* name, int namelen);
|
|
GETHOSTNAME dgethostname = (GETHOSTNAME) GetProcAddress(hLib, "gethostname");
|
|
|
|
typedef struct hostent FAR* (WINAPI* GETHOSTBYNAME) (const char FAR* name);
|
|
GETHOSTBYNAME dgethostbyname = (GETHOSTBYNAME) GetProcAddress(hLib, "gethostbyname");
|
|
|
|
typedef int (WINAPI* WSACLEANUP) ();
|
|
WSACLEANUP dWSACleanup = (WSACLEANUP) GetProcAddress(hLib, "WSACleanup");
|
|
|
|
typedef char FAR* (WINAPI* INET_NTOA) (struct in_addr in);
|
|
INET_NTOA dinet_ntoa = (INET_NTOA) GetProcAddress(hLib, "inet_ntoa");
|
|
|
|
// Verify all dll entries
|
|
if (dWSAStartup == NULL || dgethostname == NULL ||
|
|
dgethostbyname == NULL || dWSACleanup == NULL || dinet_ntoa == NULL)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetListIPAddresses - GetProcAddress() failed\n"));
|
|
// Free the DLL
|
|
FreeLibrary(hLib);
|
|
return (FALSE);
|
|
}
|
|
|
|
wVersionRequested = MAKEWORD(1, 1);
|
|
err = dWSAStartup(wVersionRequested, &wsaData);
|
|
if (err != 0)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetListIPAddresses - WSAStartup() failed\n"));
|
|
// Free the DLL
|
|
FreeLibrary(hLib);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL bSuccess=TRUE;
|
|
if(pszHostName==NULL)
|
|
{
|
|
bSuccess=(dgethostname(buffer, sizeof(buffer))==0);
|
|
pszHostName=(LPCSTR)buffer;
|
|
}
|
|
if (bSuccess)
|
|
{
|
|
hostent* pHostInfo = dgethostbyname(pszHostName);
|
|
if (pHostInfo != NULL)
|
|
{
|
|
ASSERT(pHostInfo->h_addrtype == PF_INET);
|
|
ASSERT(pHostInfo->h_length == 4);
|
|
|
|
// Iterate all the address of this host
|
|
// and put them in stringarray
|
|
int i = 0;
|
|
in_addr address;
|
|
while (pHostInfo->h_addr_list[i] != NULL)
|
|
{
|
|
PBYTE pAddress = (PBYTE)pHostInfo->h_addr_list[i];
|
|
|
|
// ... Put the seperate bytes in a single long
|
|
address.S_un.S_addr = (u_long)pAddress[0];
|
|
address.S_un.S_addr += ((u_long)pAddress[1]) << 8;
|
|
address.S_un.S_addr += ((u_long)pAddress[2]) << 16;
|
|
address.S_un.S_addr += ((u_long)pAddress[3]) << 24;
|
|
|
|
// ... Convert long to string (4 numbers seperated by dots)
|
|
psIPAddressList->Add(CString(dinet_ntoa(address)));
|
|
|
|
if (bPrimary)
|
|
break;
|
|
|
|
i++;
|
|
}
|
|
|
|
// Free the Winsock resources
|
|
dWSACleanup();
|
|
// Free the DLL
|
|
FreeLibrary(hLib);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
TRACE(_T("COXSysInfo::GetListIPAddresses - gethostname() or gethostbyname() failed\n"));
|
|
// Free the Winsock resources
|
|
dWSACleanup();
|
|
// Free the DLL
|
|
FreeLibrary(hLib);
|
|
return FALSE;
|
|
}
|
|
|
|
TRACE(_T("COXSysInfo::GetListIPAddresses - LoadLibrary of WS2_32.DLL failed\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL COXSysInfo::GetWindowsVersion(DWORD *pdwPlatform, DWORD *pdwMajor,
|
|
DWORD *pdwMinor) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwPlatform: Current Windows platform
|
|
// DWORD *pdwMajor: Major OS version
|
|
// DWORD *pdwMinor: Minor OS version
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the current Windows OS version
|
|
|
|
ASSERT(pdwPlatform!=NULL && pdwMajor!=NULL && pdwMinor!=NULL);
|
|
|
|
OSVERSIONINFO osvi;
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
BOOL bReturn = GetVersionEx(&osvi);
|
|
|
|
if (!bReturn)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetWindowsVersion - ::GetVersionEx() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// Possible platform IDs:
|
|
// VER_PLATFORM_WIN32s Win32s on Windows 3.1.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 0) Windows 95.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 1) Windows 98.
|
|
// VER_PLATFORM_WIN32_NT Windows NT/XP/Vista.
|
|
|
|
*pdwPlatform = osvi.dwPlatformId;
|
|
*pdwMajor = osvi.dwMajorVersion;
|
|
*pdwMinor = osvi.dwMinorVersion;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetWindowsBuildNumber(DWORD *pdwBuildNumber) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwBuildNumber: Windows platform build number
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the current Windows OS version build number
|
|
|
|
ASSERT(pdwBuildNumber!=NULL);
|
|
|
|
OSVERSIONINFO osvi;
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
BOOL bReturn = GetVersionEx(&osvi);
|
|
|
|
if (!bReturn)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetWindowsBuildNumber - ::GetVersionEx() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// Possible platform IDs:
|
|
// VER_PLATFORM_WIN32s Win32s on Windows 3.1.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 0) Windows 95.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 1) Windows 98.
|
|
// VER_PLATFORM_WIN32_NT Windows NT.
|
|
|
|
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
|
|
*pdwBuildNumber = osvi.dwBuildNumber;
|
|
else
|
|
*pdwBuildNumber = LOWORD(osvi.dwBuildNumber);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetWindowsPlatformInfo(CString& sPlatformInfo) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString& sPlatformInfo: additional information about
|
|
// the operating system
|
|
// --- Effect: Retrieves additional information for current
|
|
// Windows OS version
|
|
|
|
OSVERSIONINFO osvi;
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
BOOL bReturn = GetVersionEx(&osvi);
|
|
|
|
if (!bReturn)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetWindowsBuildNumber - ::GetVersionEx() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// Possible platform IDs:
|
|
// VER_PLATFORM_WIN32s Win32s on Windows 3.1.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 0) Windows 95.
|
|
// VER_PLATFORM_WIN32_WINDOWS (dwMinorVersion is 1) Windows 98.
|
|
// VER_PLATFORM_WIN32_NT Windows NT.
|
|
|
|
sPlatformInfo=osvi.szCSDVersion;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsNT(BOOL *pbResult) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pbResult: TRUE if Windows NT running
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Determines if the current Windows OS
|
|
// version is NT
|
|
|
|
ASSERT(pbResult!=NULL);
|
|
|
|
OSVERSIONINFO osvi;
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if (!GetVersionEx(&osvi))
|
|
{
|
|
TRACE(_T("COXSysInf::IsNT: GetVersionEx() has failed\n"));
|
|
return (FALSE);
|
|
}
|
|
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
// We're running on NT.
|
|
*pbResult=TRUE;
|
|
else
|
|
*pbResult=FALSE;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsNTServer(BOOL *pbResult) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pbResult: TRUE if Windows NT Server
|
|
// installed
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Determines if the current Windows OS
|
|
// version is NT Server or not
|
|
|
|
ASSERT(pbResult!=NULL);
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
if (bIsNT)
|
|
{
|
|
HKEY hKey;
|
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
_T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
|
|
0, KEY_EXECUTE, &hKey) != ERROR_SUCCESS)
|
|
return (FALSE);
|
|
|
|
DWORD dwType, dwSize;
|
|
CString sProductType;
|
|
LPTSTR lpProductType=sProductType.GetBuffer(MAX_PATH+1);
|
|
if(RegQueryValueEx(hKey,_T("ProductType"),NULL,&dwType,
|
|
(LPBYTE)lpProductType,&dwSize)!=ERROR_SUCCESS)
|
|
{
|
|
sProductType.ReleaseBuffer();
|
|
return (FALSE);
|
|
}
|
|
sProductType.ReleaseBuffer();
|
|
ASSERT(dwType==REG_SZ);
|
|
RegCloseKey(hKey);
|
|
|
|
if (sProductType==_T("WinNT"))
|
|
*pbResult=FALSE;
|
|
else if (sProductType==_T("LanmanNT"))
|
|
*pbResult=TRUE;
|
|
else if (sProductType==_T("ServerNT"))
|
|
*pbResult=TRUE;
|
|
else
|
|
return (FALSE);
|
|
}
|
|
else
|
|
*pbResult=FALSE;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsOSR2(BOOL *pbResult) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pbResult: TRUE if Windows 95 OSR 2
|
|
// installed
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Determines if the current Windows OS
|
|
// version is Windows 95 OSR 2 or not
|
|
|
|
ASSERT(pbResult!=NULL);
|
|
|
|
OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };
|
|
BOOL bReturn = GetVersionEx(&osvi);
|
|
if (!bReturn)
|
|
{
|
|
TRACE(_T("COXSysInfo::IsOSR2 - ::GetVersionEx() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
WORD wVersion = LOWORD(osvi.dwBuildNumber);
|
|
*pbResult=FALSE;
|
|
if ((osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (wVersion > 1000))
|
|
// OSR2 (or greater) of Windows 95...
|
|
*pbResult=TRUE;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetWindowsDir(CString *psWinDir) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psWinDir: Windows directory
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the Windows directory
|
|
|
|
ASSERT(psWinDir != NULL);
|
|
|
|
TCHAR buffer[_MAX_PATH+1];
|
|
BOOL bReturn;
|
|
|
|
bReturn = GetWindowsDirectory(buffer, sizeof(buffer)/sizeof(buffer[0]));
|
|
|
|
if (bReturn)
|
|
*psWinDir = buffer;
|
|
else
|
|
{
|
|
TRACE(_T("COXSysInfo::GetWindowsDir - ::GetWindowsDirectory() failed\n"));
|
|
}
|
|
|
|
return (bReturn);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetSystemDir(CString *psSysDir) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psSysDir: System directory
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the System directory
|
|
|
|
ASSERT(psSysDir != NULL);
|
|
|
|
TCHAR buffer[MAX_PATH+1];
|
|
BOOL bReturn;
|
|
|
|
bReturn = ::GetSystemDirectory(buffer, sizeof(buffer)/sizeof(buffer[0]));
|
|
|
|
if (bReturn)
|
|
*psSysDir = buffer;
|
|
else
|
|
TRACE(_T("COXSysInfo::GetSystemDir - ::GetSystemDirectory() failed\n"));
|
|
|
|
return (bReturn);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetTempDir(CString *psTempDir) const
|
|
{
|
|
// --- In:
|
|
// --- Out: CString *psTempDir: Temp directory
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the temp directory
|
|
|
|
ASSERT(psTempDir != NULL);
|
|
|
|
TCHAR buffer[_MAX_PATH+1];
|
|
BOOL bReturn;
|
|
|
|
bReturn = ::GetTempPath(sizeof(buffer)/sizeof(buffer[0]), buffer);
|
|
|
|
if (bReturn)
|
|
*psTempDir = buffer;
|
|
else
|
|
TRACE(_T("COXSysInfo::GetTempDir - ::GetTempPath() failed\n"));
|
|
|
|
return (bReturn);
|
|
}
|
|
|
|
|
|
HICON COXSysInfo::GetFileIcon(LPCTSTR pszFileName, BOOL bSmall,
|
|
BOOL bSelected, BOOL bFileMustExist) const
|
|
{
|
|
SHFILEINFO shfi;
|
|
|
|
// FILE_ATTRIBUTE_NORMAL and SHGFI_USEFILEATTRIBUTES allow to retrieve data
|
|
// without checking if file exists
|
|
if(!::SHGetFileInfo(pszFileName,
|
|
(bFileMustExist ? 0 : FILE_ATTRIBUTE_NORMAL),&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_SHELLICONSIZE|SHGFI_ICON|
|
|
(bFileMustExist ? 0 : SHGFI_USEFILEATTRIBUTES)|
|
|
(bSmall ? SHGFI_SMALLICON : SHGFI_LARGEICON)|
|
|
(bSelected ? SHGFI_SELECTED : 0)))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return shfi.hIcon;
|
|
}
|
|
|
|
|
|
HICON COXSysInfo::GetFileExtIcon(LPCTSTR pszFileExt, BOOL bSmall, BOOL bSelected) const
|
|
{
|
|
CString sFileName;
|
|
sFileName.Format(_T(".%s"),pszFileExt);
|
|
return GetFileIcon(sFileName,bSmall,bSelected,FALSE);
|
|
}
|
|
|
|
|
|
BOOL COXSysInfo::GetDriveTypeInfo(int nDrive, CString *psFileSysType,
|
|
int *pnDiskType) const
|
|
{
|
|
// --- In: int nDrive: drive 0-25 (A-Z)
|
|
// --- Out: CString *psFileSysType: File system type
|
|
// int *pnDiskType: Disk type
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves disk drive information
|
|
|
|
ASSERT(psFileSysType != NULL);
|
|
ASSERT(pnDiskType != NULL);
|
|
|
|
// Looking for drives 0-25 (A-Z)
|
|
if ((nDrive < 0) || (nDrive >= 26))
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDriveTypeInfo - invalid drive number\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
TCHAR szRoot[8];
|
|
TCHAR szVolName[_MAX_PATH+1];
|
|
DWORD dwVolSer, dwMaxLen, dwFileSysFlags;
|
|
TCHAR szFileSysName[_MAX_PATH+1];
|
|
|
|
UTBStr::stprintf(szRoot, 8, _T("%c:\\"), 65 + nDrive);
|
|
UINT uiDriveType = ::GetDriveType(szRoot);
|
|
|
|
if ((uiDriveType == DRIVE_UNKNOWN) || (uiDriveType == DRIVE_NO_ROOT_DIR))
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDriveTypeInfo - ::GetDriveType() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
*pnDiskType = (int) uiDriveType;
|
|
|
|
if (GetVolumeInformation(szRoot, szVolName,
|
|
sizeof(szVolName)/sizeof(szVolName[0]), &dwVolSer, &dwMaxLen,
|
|
&dwFileSysFlags, szFileSysName,
|
|
sizeof(szFileSysName)/sizeof(szFileSysName[0])) == FALSE)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDriveTypeInfo - ::GetVolumeInformation() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
*psFileSysType = szFileSysName;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetDriveVolumeInfo(int nDrive, CString *psVolumeName,
|
|
DWORD *pdwVolSer, DWORDLONG *pdwTotalSpace,
|
|
DWORDLONG *pdwFreeSpace) const
|
|
{
|
|
// --- In: int nDrive: drive 0-25 (A-Z)
|
|
// --- Out: CString *psVolumeName: Disk volume name
|
|
// DWORD *pdwVolSer: Disk serial number
|
|
// DWORDLONG *pdwTotalSpace: Total space bytes
|
|
// DWORDLONG *pdwFreeSpace: Total free space bytes
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves disk drive volume information
|
|
|
|
ASSERT(psVolumeName != NULL);
|
|
ASSERT(pdwVolSer != NULL);
|
|
ASSERT(pdwTotalSpace != NULL);
|
|
ASSERT(pdwFreeSpace != NULL);
|
|
|
|
TCHAR szRoot[8];
|
|
TCHAR szVolName[_MAX_PATH+1];
|
|
DWORD dwVolSer, dwMaxLen, dwFileSysFlags;
|
|
TCHAR szFileSysName[_MAX_PATH+1];
|
|
BOOL bRet = TRUE;
|
|
|
|
// Looking for drives 0-25 (A-Z)
|
|
if ((nDrive < 0) || (nDrive >= 26))
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDriveVolumeInfo - invalid drive number\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
UTBStr::stprintf(szRoot, 8, _T("%c:\\"), 65 + nDrive);
|
|
|
|
dwMaxLen = MAX_PATH;
|
|
|
|
if (GetVolumeInformation(szRoot, szVolName,
|
|
sizeof(szVolName)/sizeof(szVolName[0]), &dwVolSer, &dwMaxLen,
|
|
&dwFileSysFlags, szFileSysName,
|
|
sizeof(szFileSysName)/sizeof(szFileSysName[0])) == FALSE)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDriveVolumeInfo - ::GetVolumeInformation() failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
*psVolumeName = szVolName;
|
|
*pdwVolSer = dwVolSer;
|
|
|
|
DWORD dwSectorsPerCluster, dwBytesPerSector;
|
|
DWORD dwNumberOfFreeClusters, dwTotalNumberOfClusters;
|
|
|
|
BOOL bIsOSR2;
|
|
if(IsOSR2(&bIsOSR2) && bIsOSR2)
|
|
{
|
|
// OSR2 (or greater) of Windows 95...
|
|
|
|
HINSTANCE hLib = LoadLibrary(_T("KERNEL32.DLL"));
|
|
|
|
if (hLib != NULL)
|
|
{
|
|
// Loaded KERNEL32.DLL...
|
|
typedef BOOL (WINAPI *GETDISKFREESPACEEX) (LPCTSTR lpDirectoryName,
|
|
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
|
|
PULARGE_INTEGER lpTotalNumberOfBytes,
|
|
PULARGE_INTEGER lpTotalNumberOfFreeBytes);
|
|
|
|
GETDISKFREESPACEEX dGetDiskFreeSpaceEx =
|
|
(GETDISKFREESPACEEX) GetProcAddress(hLib, "GetDiskFreeSpaceExA");
|
|
|
|
ULARGE_INTEGER ulFreeBytesAvailable;
|
|
ULARGE_INTEGER ulTotalBytes;
|
|
ULARGE_INTEGER ulTotalFree;
|
|
|
|
if (dGetDiskFreeSpaceEx != NULL)
|
|
{
|
|
if (dGetDiskFreeSpaceEx(szRoot, &ulFreeBytesAvailable, &ulTotalBytes,
|
|
&ulTotalFree) > 0)
|
|
{
|
|
// Get total disk space...
|
|
*pdwTotalSpace = (DWORDLONG) ulTotalBytes.QuadPart;
|
|
|
|
// Get free disk space...
|
|
*pdwFreeSpace = (DWORDLONG) ulTotalFree.QuadPart;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetDiskFreeSpace(szRoot, &dwSectorsPerCluster, &dwBytesPerSector,
|
|
&dwNumberOfFreeClusters, &dwTotalNumberOfClusters) == 0)
|
|
return (FALSE);
|
|
|
|
// Get total disk space...
|
|
*pdwTotalSpace = (DWORDLONG)dwSectorsPerCluster *
|
|
(DWORDLONG)dwBytesPerSector * (DWORDLONG)dwTotalNumberOfClusters;
|
|
|
|
// Get free disk space...
|
|
*pdwFreeSpace = (DWORDLONG)dwSectorsPerCluster *
|
|
(DWORDLONG)dwBytesPerSector * (DWORDLONG)dwNumberOfFreeClusters;
|
|
}
|
|
|
|
// Free the DLL
|
|
FreeLibrary(hLib);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetDiskFreeSpace(szRoot, &dwSectorsPerCluster, &dwBytesPerSector,
|
|
&dwNumberOfFreeClusters, &dwTotalNumberOfClusters) == 0)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
// Get total disk space...
|
|
*pdwTotalSpace = (DWORDLONG)dwSectorsPerCluster *
|
|
(DWORDLONG)dwBytesPerSector * (DWORDLONG)dwTotalNumberOfClusters;
|
|
|
|
// Get free disk space...
|
|
*pdwFreeSpace = (DWORDLONG)dwSectorsPerCluster *
|
|
(DWORDLONG)dwBytesPerSector * (DWORDLONG)dwNumberOfFreeClusters;
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetDisplayResolution(int *pnxRes, int *pnyRes) const
|
|
{
|
|
// --- In:
|
|
// --- Out: int *xRes: horizontal screen resolution (pixels)
|
|
// int *yRes: vertical screen resolution (pixels)
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the display resolution size
|
|
|
|
ASSERT(pnxRes != NULL);
|
|
ASSERT(pnyRes != NULL);
|
|
|
|
int iXRes = DeviceCaps(HORZRES);
|
|
if (iXRes == -1)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDisplayResolution - invalid X resolution\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
int iYRes = DeviceCaps(VERTRES);
|
|
if (iYRes == -1)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetDisplayResolution - invalid Y resolution\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
*pnxRes = iXRes;
|
|
*pnyRes = iYRes;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetDisplayNumColors(DWORDLONG *pdwNumColors, int *pnNumBits) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORDLONG *pdwNumColors: Number of colors used by current display
|
|
// int *pnNumBits: Number of bits for color depth
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the display color usage
|
|
|
|
ASSERT(pdwNumColors != NULL);
|
|
ASSERT(pnNumBits != NULL);
|
|
|
|
int iBitsPixel = DeviceCaps(PLANES) * DeviceCaps(BITSPIXEL);
|
|
int i;
|
|
*pdwNumColors = 1;
|
|
|
|
for(i=0;i<iBitsPixel;i++)
|
|
*pdwNumColors = *pdwNumColors * 2;
|
|
|
|
*pnNumBits = iBitsPixel;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetAllDisplayModes(CArrayDisplayMode* parrDisplayMode) const
|
|
{
|
|
ASSERT(parrDisplayMode!=NULL);
|
|
|
|
parrDisplayMode->RemoveAll();
|
|
|
|
// # of DEVMODEs
|
|
int nModeNum=-1;
|
|
// Information about supported display resolutions, 200 should be enough
|
|
DEVMODE dvmd[1024];
|
|
|
|
// Get all of the possible display modes
|
|
::ZeroMemory((void*)&dvmd, sizeof(dvmd));
|
|
do
|
|
{
|
|
nModeNum++;
|
|
dvmd[nModeNum].dmSize = sizeof(DEVMODE);
|
|
dvmd[nModeNum].dmDriverExtra = 0;
|
|
} while(::EnumDisplaySettings(NULL, nModeNum, &dvmd[nModeNum]));
|
|
|
|
ASSERT(nModeNum>0);
|
|
|
|
// Sort all of the display modes:
|
|
// 1: Resolution (width), 2: color depth, 3: frequency.
|
|
::qsort(&dvmd[0],nModeNum,sizeof(DEVMODE),DevModeCompare);
|
|
|
|
for(int nIndex=0; nIndex<nModeNum; nIndex++)
|
|
{
|
|
if(nIndex>0)
|
|
{
|
|
// If this is not the first DEVMODE entry, possibly add a seperator bar
|
|
if((dvmd[nIndex].dmPelsWidth==dvmd[nIndex-1].dmPelsWidth) &&
|
|
(dvmd[nIndex].dmPelsHeight==dvmd[nIndex-1].dmPelsHeight) &&
|
|
(dvmd[nIndex].dmBitsPerPel==dvmd[nIndex-1].dmBitsPerPel))
|
|
{
|
|
// This entry is identical to the previous entry except for refrash rate
|
|
// Let's not add this entry to the menu
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// We started a new resolution, add it to our array
|
|
DISPLAYMODE displayMode;
|
|
|
|
displayMode.dwBitsPerPixel=dvmd[nIndex].dmBitsPerPel;
|
|
displayMode.dwHorzResolution=dvmd[nIndex].dmPelsWidth;
|
|
displayMode.dwVertResolution=dvmd[nIndex].dmPelsHeight;
|
|
|
|
displayMode.dwNumColors=1;
|
|
for(DWORD nIndex=0; nIndex<displayMode.dwBitsPerPixel; nIndex++)
|
|
displayMode.dwNumColors*=2;
|
|
|
|
parrDisplayMode->Add(displayMode);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXSysInfo::GetDisplayMaxResolution(int *pnxRes, int *pnyRes) const
|
|
{
|
|
// --- In:
|
|
// --- Out: int *xRes: max horizontal screen resolution (pixels)
|
|
// int *yRes: max vertical screen resolution (pixels)
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the display resolution size
|
|
|
|
ASSERT(pnxRes != NULL);
|
|
ASSERT(pnyRes != NULL);
|
|
|
|
CArrayDisplayMode arrDisplayMode;
|
|
if(!GetAllDisplayModes(&arrDisplayMode) || arrDisplayMode.GetSize()==0)
|
|
return (FALSE);
|
|
|
|
DWORD dwMaxXRes=0;
|
|
DWORD dwMaxYRes=0;
|
|
for(int nIndex=0; nIndex<arrDisplayMode.GetSize(); nIndex++)
|
|
{
|
|
DISPLAYMODE displayMode=arrDisplayMode.GetAt(nIndex);
|
|
if(dwMaxXRes*dwMaxYRes<
|
|
displayMode.dwHorzResolution*displayMode.dwVertResolution)
|
|
{
|
|
dwMaxXRes=displayMode.dwHorzResolution;
|
|
dwMaxYRes=displayMode.dwVertResolution;
|
|
}
|
|
}
|
|
|
|
ASSERT(dwMaxXRes*dwMaxYRes>0);
|
|
|
|
*pnxRes=dwMaxXRes;
|
|
*pnyRes=dwMaxYRes;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetDisplayMaxNumColors(DWORDLONG *pdwNumColors, int *pnNumBits) const
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORDLONG *pdwNumColors: Max number of colors used
|
|
// by current display
|
|
// int *pnNumBits: Max number of bits for color depth
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the display color usage
|
|
|
|
ASSERT(pdwNumColors != NULL);
|
|
ASSERT(pnNumBits != NULL);
|
|
|
|
CArrayDisplayMode arrDisplayMode;
|
|
if(!GetAllDisplayModes(&arrDisplayMode) || arrDisplayMode.GetSize()==0)
|
|
return (FALSE);
|
|
|
|
DWORD dwMaxNumBits=0;
|
|
int nIndex=0;
|
|
for(nIndex=0; nIndex<arrDisplayMode.GetSize(); nIndex++)
|
|
{
|
|
DISPLAYMODE displayMode=arrDisplayMode.GetAt(nIndex);
|
|
if(dwMaxNumBits<displayMode.dwBitsPerPixel)
|
|
dwMaxNumBits=displayMode.dwBitsPerPixel;
|
|
}
|
|
|
|
ASSERT(dwMaxNumBits>0);
|
|
|
|
*pnNumBits=dwMaxNumBits;
|
|
|
|
*pdwNumColors = 1;
|
|
for(nIndex=0;nIndex<(int)dwMaxNumBits;nIndex++)
|
|
*pdwNumColors = *pdwNumColors * 2;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsSmallFont(BOOL* pbIsSmall) const
|
|
{
|
|
// --- In:
|
|
// --- Out: BOOL *pbIsSmall: if TRUE then small fonts are used,
|
|
// otherwise the large ones
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the flag that specifies whether small or
|
|
// large fonts are used in the system
|
|
|
|
ASSERT(pbIsSmall!=NULL);
|
|
|
|
CWnd* pWnd=CWnd::GetDesktopWindow();
|
|
if(pWnd!=NULL)
|
|
{
|
|
CDC* pDC=pWnd->GetWindowDC();
|
|
if(pDC!=NULL)
|
|
{
|
|
TEXTMETRIC tm;
|
|
if(pDC->GetTextMetrics(&tm))
|
|
{
|
|
if(tm.tmHeight>16)
|
|
*pbIsSmall=FALSE;
|
|
else
|
|
*pbIsSmall=TRUE;
|
|
pWnd->ReleaseDC(pDC);
|
|
return TRUE;
|
|
}
|
|
pWnd->ReleaseDC(pDC);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL COXSysInfo::GetTotalPhysicalMemory(DWORD_PTR *pdwPhysMem)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwPhysMem: Total physical RAM
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the amount of physical memory
|
|
|
|
ASSERT(pdwPhysMem != NULL);
|
|
|
|
GetMemStatus() ;
|
|
|
|
*pdwPhysMem = m_memStatus.dwTotalPhys;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetFreePhysicalMemory(DWORD_PTR *pdwFreeMem)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwFreeMem: Total free physical RAM
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the amount of free physical memory
|
|
|
|
ASSERT(pdwFreeMem != NULL);
|
|
|
|
GetMemStatus();
|
|
|
|
*pdwFreeMem = m_memStatus.dwAvailPhys;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetTotalPageFile(DWORD_PTR *pdwTotalPageFile)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwTotalPageFile: Total page file size
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the size of the page file
|
|
|
|
ASSERT(pdwTotalPageFile != NULL);
|
|
|
|
GetMemStatus();
|
|
|
|
*pdwTotalPageFile = m_memStatus.dwTotalPageFile;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetFreePageFile(DWORD_PTR *pdwFreePageFile)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwFreePageFile: Total free page file size
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the free space of the page file
|
|
|
|
ASSERT(pdwFreePageFile != NULL);
|
|
|
|
GetMemStatus();
|
|
|
|
*pdwFreePageFile = m_memStatus.dwAvailPageFile;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetTotalVirtual(DWORD_PTR *pdwTotalVirtual)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwTotalVirtual: Total virtual memory
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the size of virtual memory
|
|
|
|
ASSERT(pdwTotalVirtual != NULL);
|
|
|
|
GetMemStatus();
|
|
|
|
*pdwTotalVirtual = m_memStatus.dwTotalVirtual;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetFreeVirtual(DWORD_PTR *pdwFreeVirtual)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwFreeVirtual: Total free virtual memory
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the size of the free virtual memory
|
|
|
|
ASSERT(pdwFreeVirtual != NULL);
|
|
|
|
GetMemStatus();
|
|
|
|
*pdwFreeVirtual = m_memStatus.dwAvailVirtual;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetNumProcessors(int *pnNumProcessors)
|
|
{
|
|
// --- In:
|
|
// --- Out: int *pnNumProcessors: Total number of processors in machine
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the number of CPUs
|
|
|
|
ASSERT(pnNumProcessors != NULL);
|
|
|
|
GetSysInfo();
|
|
|
|
*pnNumProcessors = (int) m_sysInfo.dwNumberOfProcessors;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetProcessorType(DWORD *pdwProcessorType)
|
|
{
|
|
// --- In:
|
|
// --- Out: DWORD *pdwProcessorType: Processor type
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the processor type (primary processor)
|
|
|
|
ASSERT(pdwProcessorType != NULL);
|
|
|
|
GetSysInfo();
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
|
|
*pdwProcessorType = (DWORD)PROCESSOR_UNKNOWN;
|
|
|
|
// VER_PLATFORM_WIN32s Win32s on Windows 3.1.
|
|
// VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95.
|
|
// VER_PLATFORM_WIN32_NT Win32 on Windows NT.
|
|
|
|
if (bIsNT)
|
|
{
|
|
// Running NT - so step through processor
|
|
// architecture and type to determine
|
|
// the actual CPU
|
|
|
|
// Now determine processor architecture
|
|
switch(m_sysInfo.wProcessorArchitecture)
|
|
{
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
|
switch(m_sysInfo.wProcessorLevel)
|
|
{
|
|
case 3:
|
|
*pdwProcessorType = PROCESSOR_INTEL_386;
|
|
break;
|
|
|
|
case 4:
|
|
*pdwProcessorType = PROCESSOR_INTEL_486;
|
|
break;
|
|
|
|
case 5:
|
|
*pdwProcessorType = PROCESSOR_INTEL_PENTIUM;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_MIPS:
|
|
*pdwProcessorType = PROCESSOR_MIPSR4000;
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_ALPHA:
|
|
*pdwProcessorType = m_sysInfo.wProcessorLevel;
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_PPC:
|
|
switch(m_sysInfo.wProcessorLevel)
|
|
{
|
|
case 1:
|
|
*pdwProcessorType = PROCESSOR_PPC601;
|
|
break;
|
|
|
|
case 3:
|
|
*pdwProcessorType = PROCESSOR_PPC603;
|
|
break;
|
|
|
|
case 4:
|
|
*pdwProcessorType = PROCESSOR_PPC604;
|
|
break;
|
|
|
|
case 6:
|
|
*pdwProcessorType = PROCESSOR_PPC603PLUS;
|
|
break;
|
|
|
|
case 9:
|
|
*pdwProcessorType = PROCESSOR_PPC604PLUS;
|
|
break;
|
|
|
|
case 20:
|
|
*pdwProcessorType = PROCESSOR_PPC620;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Running Win95
|
|
|
|
// PROCESSOR_INTEL_386
|
|
// PROCESSOR_INTEL_486
|
|
// PROCESSOR_INTEL_PENTIUM
|
|
|
|
*pdwProcessorType = m_sysInfo.dwProcessorType;
|
|
}
|
|
|
|
if(*pdwProcessorType==PROCESSOR_INTEL_PENTIUM ||
|
|
*pdwProcessorType == (DWORD)PROCESSOR_UNKNOWN)
|
|
{
|
|
WORD nCPUType=wincpuid();
|
|
ASSERT(nCPUType>=5);
|
|
switch(nCPUType)
|
|
{
|
|
// Pentium
|
|
case 5:
|
|
{
|
|
break;
|
|
}
|
|
// Pentium Pro, Pentium II, Pentium Celeron, Pentium III
|
|
case 6:
|
|
{
|
|
// retrieve CPUID
|
|
WORD nCPUidEx=wincpuidext();
|
|
// analyze the model number
|
|
int nModel=(nCPUidEx&0x00f0)>>4;
|
|
switch(nModel)
|
|
{
|
|
case 1:
|
|
*pdwProcessorType=(DWORD)PROCESSOR_INTEL_PENTIUMPRO;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 5:
|
|
*pdwProcessorType=(DWORD)PROCESSOR_INTEL_PENTIUM2;
|
|
break;
|
|
case 6:
|
|
*pdwProcessorType=(DWORD)PROCESSOR_INTEL_PENTIUMCELERON;
|
|
break;
|
|
case 7:
|
|
case 8:
|
|
*pdwProcessorType=(DWORD)PROCESSOR_INTEL_PENTIUM3;
|
|
break;
|
|
default:
|
|
*pdwProcessorType=(DWORD)PROCESSOR_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
*pdwProcessorType=(DWORD)PROCESSOR_UNKNOWN;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsCoProcessorPresent(BOOL* pbResult)
|
|
{
|
|
ASSERT(pbResult!=NULL);
|
|
|
|
BOOL bIsNT;
|
|
if(!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
|
|
DWORD dwProcessorType;
|
|
GetProcessorType(&dwProcessorType);
|
|
|
|
// we return TRUE if we're not running on x86
|
|
// other CPUs have built in floating-point, with no registry entry
|
|
|
|
if((dwProcessorType != PROCESSOR_INTEL_386) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_486) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM))
|
|
{
|
|
*pbResult=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(!bIsNT)
|
|
{
|
|
DWORD dwFeatures=wincpufeatures();
|
|
|
|
if(dwFeatures & 0x00000001) //then CPU contains a floating-point unit (FPU)
|
|
*pbResult=TRUE;
|
|
else
|
|
*pbResult=FALSE;
|
|
}
|
|
else
|
|
{
|
|
HKEY hKey;
|
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
_T("HARDWARE\\DESCRIPTION\\System\\FloatingPointProcessor"),
|
|
0, KEY_EXECUTE, &hKey) != ERROR_SUCCESS)
|
|
{
|
|
// GetLastError() will indicate ERROR_RESOURCE_DATA_NOT_FOUND
|
|
// if we can't find the key. This indicates no coprocessor present
|
|
*pbResult=FALSE;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXSysInfo::GetProcessorSpeed(DWORD* pdwProcessorSpeed, int nIndex/*=0*/) const
|
|
{
|
|
ASSERT(pdwProcessorSpeed!=NULL);
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
if (!bIsNT && nIndex>0)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetProcessorSpeed: Windows 95 doesn't support multiprocessor systems\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
DWORD dwSpeed=0;
|
|
if(nIndex>0 || bIsNT)
|
|
{
|
|
ASSERT(bIsNT);
|
|
// Running NT
|
|
|
|
CString sRegistryPath;
|
|
sRegistryPath.Format(_T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d"),nIndex);
|
|
|
|
HKEY hKey;
|
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,sRegistryPath,0,KEY_READ,&hKey)!=ERROR_SUCCESS)
|
|
return (FALSE);
|
|
|
|
DWORD dwType, dwValue, dwSize;
|
|
if(RegQueryValueEx(hKey,_T("~MHz"),NULL,&dwType,(LPBYTE)&dwValue,&dwSize)!=
|
|
ERROR_SUCCESS)
|
|
return (FALSE);
|
|
|
|
ASSERT(dwType==REG_DWORD && dwSize==sizeof(DWORD));
|
|
|
|
dwSpeed=dwValue;
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
struct FREQ_INFO CPUSpeed=cpuspeed(0);
|
|
if(CPUSpeed.in_cycles==0 && CPUSpeed.ex_ticks==0)
|
|
{
|
|
TRACE(_T("This processor cannot be accurately timed with this function.\n The processor is either an Intel Clone or is below 80386 level."));
|
|
return (FALSE);
|
|
}
|
|
|
|
dwSpeed=CPUSpeed.norm_freq;
|
|
}
|
|
|
|
enum CPUSpeed arrCPUSpeed[35];
|
|
arrCPUSpeed[0]=CPUSPEED_16;
|
|
arrCPUSpeed[1]=CPUSPEED_20;
|
|
arrCPUSpeed[2]=CPUSPEED_25;
|
|
arrCPUSpeed[3]=CPUSPEED_33;
|
|
arrCPUSpeed[4]=CPUSPEED_40;
|
|
arrCPUSpeed[5]=CPUSPEED_50;
|
|
arrCPUSpeed[6]=CPUSPEED_60;
|
|
arrCPUSpeed[7]=CPUSPEED_66;
|
|
arrCPUSpeed[8]=CPUSPEED_75;
|
|
arrCPUSpeed[9]=CPUSPEED_80;
|
|
arrCPUSpeed[10]=CPUSPEED_90;
|
|
arrCPUSpeed[11]=CPUSPEED_100;
|
|
arrCPUSpeed[12]=CPUSPEED_120;
|
|
arrCPUSpeed[13]=CPUSPEED_133;
|
|
arrCPUSpeed[14]=CPUSPEED_150;
|
|
arrCPUSpeed[15]=CPUSPEED_166;
|
|
arrCPUSpeed[16]=CPUSPEED_180;
|
|
arrCPUSpeed[17]=CPUSPEED_200;
|
|
arrCPUSpeed[18]=CPUSPEED_233;
|
|
arrCPUSpeed[19]=CPUSPEED_266;
|
|
arrCPUSpeed[20]=CPUSPEED_300;
|
|
arrCPUSpeed[21]=CPUSPEED_333;
|
|
arrCPUSpeed[22]=CPUSPEED_350;
|
|
arrCPUSpeed[23]=CPUSPEED_400;
|
|
arrCPUSpeed[24]=CPUSPEED_450;
|
|
arrCPUSpeed[25]=CPUSPEED_500;
|
|
arrCPUSpeed[26]=CPUSPEED_533;
|
|
arrCPUSpeed[27]=CPUSPEED_550;
|
|
arrCPUSpeed[28]=CPUSPEED_600;
|
|
arrCPUSpeed[29]=CPUSPEED_650;
|
|
arrCPUSpeed[30]=CPUSPEED_667;
|
|
arrCPUSpeed[31]=CPUSPEED_700;
|
|
arrCPUSpeed[32]=CPUSPEED_733;
|
|
arrCPUSpeed[33]=CPUSPEED_750;
|
|
arrCPUSpeed[34]=CPUSPEED_800;
|
|
|
|
*pdwProcessorSpeed=0;
|
|
UINT nMargin=0xffff;
|
|
UINT nNewMargin;
|
|
for(int nIterator=0; nIterator<countof(arrCPUSpeed); nIterator++)
|
|
{
|
|
nNewMargin=abs((int) (dwSpeed-arrCPUSpeed[nIterator]));
|
|
if(nNewMargin<nMargin)
|
|
{
|
|
nMargin=nNewMargin;
|
|
*pdwProcessorSpeed=arrCPUSpeed[nIterator];
|
|
}
|
|
}
|
|
|
|
if(*pdwProcessorSpeed==0)
|
|
return (FALSE);
|
|
else
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetTimeStamp(DWORD *pdwHigh, DWORD *pdwLow) const
|
|
{
|
|
ASSERT(pdwHigh!=NULL);
|
|
ASSERT(pdwLow!=NULL);
|
|
|
|
TIME_STAMP stamp=winrdtsc();
|
|
|
|
if(stamp.High!=0 || stamp.Low!=0)
|
|
{
|
|
*pdwHigh=stamp.High;
|
|
*pdwLow=stamp.Low;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
TRACE(_T("The primary processor doesn't support time stamp functionality"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL COXSysInfo::IsMMXProcessor(BOOL* pbMMX)
|
|
{
|
|
ASSERT(pbMMX!=NULL);
|
|
|
|
DWORD dwProcessorType;
|
|
GetProcessorType(&dwProcessorType);
|
|
|
|
// relevant only to x86 processors
|
|
|
|
if((dwProcessorType != PROCESSOR_INTEL_386) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_486) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM2) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUMPRO) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUMCELERON) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM3))
|
|
{
|
|
*pbMMX=FALSE;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwFeatures=wincpufeatures();
|
|
|
|
if(dwFeatures & 0x00800000) //then MMX(TM) technology
|
|
*pbMMX=TRUE;
|
|
else
|
|
*pbMMX=FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXSysInfo::IsOverdriveProcessor(BOOL* pbOverdrive)
|
|
{
|
|
ASSERT(pbOverdrive!=NULL);
|
|
|
|
DWORD dwProcessorType;
|
|
GetProcessorType(&dwProcessorType);
|
|
|
|
// relevant only to x86 processors
|
|
|
|
if((dwProcessorType != PROCESSOR_INTEL_386) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_486) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM2) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUMPRO) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUMCELERON) &&
|
|
(dwProcessorType != PROCESSOR_INTEL_PENTIUM3))
|
|
{
|
|
*pbOverdrive=FALSE;
|
|
}
|
|
else
|
|
{
|
|
// retrieve CPUID
|
|
WORD nCPUidEx=wincpuidext();
|
|
|
|
// get processor type
|
|
if(((nCPUidEx&0x3000)>>12)==1) // if it equals 1 then it is Overdrive processor
|
|
*pbOverdrive=TRUE;
|
|
else
|
|
*pbOverdrive=FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL COXSysInfo::GetModemInfo(CArrayModemInfo* parrModemInfo) const
|
|
{
|
|
ASSERT(parrModemInfo!=NULL);
|
|
|
|
parrModemInfo->RemoveAll();
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
|
|
CString sRegistryPath;
|
|
HKEY hKey=NULL;
|
|
HKEY hSubKey=NULL;
|
|
BOOL bSuccess=FALSE;
|
|
|
|
if(bIsNT)
|
|
{
|
|
// Running NT
|
|
|
|
sRegistryPath.Format(_T("System\\CurrentControlSet\\Control\\Class"));
|
|
|
|
if(::RegOpenKeyEx(HKEY_LOCAL_MACHINE,sRegistryPath,0,KEY_READ,&hKey)!=
|
|
ERROR_SUCCESS)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetNumModems: failed to open registry key where modem information should be located"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// enumerate all subkeys
|
|
|
|
DWORD dwIndex=0;
|
|
CString sSubKeyPath;
|
|
LPTSTR lpName=sSubKeyPath.GetBuffer(MAX_PATH+1);
|
|
while(::RegEnumKey(hKey,dwIndex,lpName,MAX_PATH+1)==ERROR_SUCCESS)
|
|
{
|
|
if(::RegOpenKeyEx(hKey,sSubKeyPath,0,KEY_READ,&hSubKey)==ERROR_SUCCESS)
|
|
{
|
|
DWORD dwType, dwSize;
|
|
LPTSTR lpszValue=NULL;
|
|
if(::RegQueryValueEx(hSubKey,_T("Class"),NULL,&dwType,(LPBYTE)lpszValue,
|
|
&dwSize)==ERROR_SUCCESS)
|
|
{
|
|
ASSERT(dwType==REG_SZ);
|
|
|
|
CString sClassName;
|
|
lpszValue=sClassName.GetBuffer(dwSize/sizeof(TCHAR));
|
|
VERIFY(::RegQueryValueEx(hSubKey,_T("Class"),NULL,&dwType,
|
|
(LPBYTE)lpszValue,&dwSize)==ERROR_SUCCESS);
|
|
sClassName.ReleaseBuffer();
|
|
if(sClassName==_T("Modem"))
|
|
bSuccess=TRUE;
|
|
}
|
|
|
|
if(bSuccess)
|
|
break;
|
|
else
|
|
{
|
|
RegCloseKey(hSubKey);
|
|
hSubKey=NULL;
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
sSubKeyPath.ReleaseBuffer();
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
// Running Windows 95/98
|
|
|
|
sRegistryPath.Format(_T("System\\CurrentControlSet\\Services\\Class\\Modem"));
|
|
|
|
if(::RegOpenKeyEx(HKEY_LOCAL_MACHINE,sRegistryPath,0,KEY_READ,&hSubKey)!=
|
|
ERROR_SUCCESS)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetNumModems: failed to open registry key where modem information should be located"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// enumerate all subkeys
|
|
|
|
bSuccess=TRUE;
|
|
}
|
|
|
|
if(bSuccess)
|
|
{
|
|
ASSERT(hSubKey!=NULL);
|
|
|
|
DWORD dwModemIndex=0;
|
|
CString sModemSubKeyPath;
|
|
LPTSTR lpModemName=sModemSubKeyPath.GetBuffer(_MAX_PATH+1);
|
|
|
|
while(::RegEnumKey(hSubKey,dwModemIndex,lpModemName,
|
|
(_MAX_PATH+1)*sizeof(TCHAR))==ERROR_SUCCESS)
|
|
{
|
|
HKEY hModemSubKey=NULL;
|
|
if(::RegOpenKeyEx(hSubKey,sModemSubKeyPath,0,
|
|
KEY_QUERY_VALUE,&hModemSubKey)==ERROR_SUCCESS)
|
|
{
|
|
// enumerate all values
|
|
|
|
DWORD dwIndex=0;
|
|
DWORD dwType, dwSize;
|
|
CString sValueName;
|
|
LPTSTR lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
DWORD dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
LPBYTE lpData=NULL;
|
|
|
|
MODEMINFO modemInfo;
|
|
BOOL bModemFound=FALSE;
|
|
|
|
while(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,&dwValueNameLength,
|
|
NULL,&dwType,lpData,&dwSize)==ERROR_SUCCESS)
|
|
{
|
|
sValueName.ReleaseBuffer();
|
|
|
|
if(sValueName==_T("DeviceType"))
|
|
{
|
|
ASSERT(dwType==REG_BINARY && dwSize==1);
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
BYTE deviceType;
|
|
VERIFY(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,
|
|
&dwValueNameLength,NULL,&dwType,&deviceType,&dwSize)==
|
|
ERROR_SUCCESS);
|
|
|
|
if(deviceType==2)
|
|
bModemFound=TRUE;
|
|
}
|
|
else if(sValueName==_T("DriverDesc"))
|
|
{
|
|
ASSERT(dwType==REG_SZ);
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
LPTSTR lpszDriverDesc=modemInfo.sDriverDesc.
|
|
GetBuffer(dwSize/sizeof(TCHAR));
|
|
VERIFY(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,
|
|
&dwValueNameLength,NULL,&dwType,(LPBYTE)lpszDriverDesc,
|
|
&dwSize)==ERROR_SUCCESS);
|
|
modemInfo.sDriverDesc.ReleaseBuffer();
|
|
}
|
|
else if(sValueName==_T("Manufacturer"))
|
|
{
|
|
ASSERT(dwType==REG_SZ);
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
LPTSTR lpszManufacturer=modemInfo.sManufacturer.
|
|
GetBuffer(dwSize/sizeof(TCHAR));
|
|
VERIFY(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,
|
|
&dwValueNameLength,NULL,&dwType,(LPBYTE)lpszManufacturer,
|
|
&dwSize)==ERROR_SUCCESS);
|
|
modemInfo.sManufacturer.ReleaseBuffer();
|
|
}
|
|
else if(sValueName==_T("Model"))
|
|
{
|
|
ASSERT(dwType==REG_SZ);
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
LPTSTR lpszModel=modemInfo.sModel.
|
|
GetBuffer(dwSize/sizeof(TCHAR));
|
|
VERIFY(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,
|
|
&dwValueNameLength,NULL,&dwType,(LPBYTE)lpszModel,
|
|
&dwSize)==ERROR_SUCCESS);
|
|
modemInfo.sModel.ReleaseBuffer();
|
|
}
|
|
else if(sValueName==_T("PortSubClass"))
|
|
{
|
|
ASSERT(dwType==REG_BINARY && dwSize==1);
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
BYTE port;
|
|
VERIFY(::RegEnumValue(hModemSubKey,dwIndex,lpValueName,
|
|
&dwValueNameLength,NULL,&dwType,&port,&dwSize)==
|
|
ERROR_SUCCESS);
|
|
|
|
modemInfo.nPort=port;
|
|
}
|
|
|
|
lpValueName=sValueName.GetBuffer(_MAX_PATH+1);
|
|
dwValueNameLength=(_MAX_PATH+1)*sizeof(TCHAR);
|
|
|
|
dwIndex++;
|
|
}
|
|
sValueName.ReleaseBuffer();
|
|
RegCloseKey(hModemSubKey);
|
|
|
|
if(bModemFound)
|
|
parrModemInfo->Add(modemInfo);
|
|
}
|
|
dwModemIndex++;
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXSysInfo::GetNumModems(int *pnNumModems) const
|
|
{
|
|
ASSERT(pnNumModems!=NULL);
|
|
|
|
CArrayModemInfo arrModemInfo;
|
|
|
|
if(!GetModemInfo(&arrModemInfo))
|
|
return FALSE;
|
|
else
|
|
{
|
|
*pnNumModems= PtrToInt(arrModemInfo.GetSize());
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL COXSysInfo::GetNICAddress(LPNICADDRESS pNICAddress) const
|
|
{
|
|
// --- In:
|
|
// --- Out: LPNICADDRESS pNICAddress: valid pointer to Network
|
|
// Interface Card (NIC) address
|
|
// structure
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the NIC address
|
|
// --- Comment: This function bases its functionality on the fact that
|
|
// the MAC address is part of the GUID generated on given
|
|
// machine. It also recognises the fact that on Windows 2000
|
|
// and later CoCreateGuid will return GUID, which contains
|
|
// encrypted MAC address and therefore cannot be traced back.
|
|
// On these platforms UuidCreateSequential has to be used
|
|
// to obtain the version of GUID that we expect..
|
|
|
|
ASSERT(pNICAddress!=NULL);
|
|
|
|
int nIndex;
|
|
GUID guid;
|
|
// create signature for the UuidCreateSequential function
|
|
typedef int (WINAPI* UuidCreateSequential) (UUID *Uuid);
|
|
UuidCreateSequential dUuidCreateSequential = NULL;
|
|
// attempt to open the rpcrt4.DLL
|
|
HINSTANCE hLib = NULL;
|
|
hLib = LoadLibrary(_T("rpcrt4.DLL"));
|
|
|
|
if (hLib != NULL)
|
|
{ // Loaded rpcrt4.DLL, if possible get pointer to the UuidCreateSequential method
|
|
dUuidCreateSequential = (UuidCreateSequential) GetProcAddress(hLib, "UuidCreateSequential");
|
|
|
|
if ( dUuidCreateSequential == NULL )
|
|
{ // if the UuidCreateSequential method in the rpcrt4.DLL is not found then use
|
|
// the traditional way to retrieve the GUID
|
|
if( ::CoCreateGuid( &guid ) != S_OK )
|
|
return FALSE;
|
|
}
|
|
else if( dUuidCreateSequential( &guid ) != RPC_S_OK )
|
|
return FALSE;
|
|
}
|
|
else if(::CoCreateGuid(&guid)!=S_OK)
|
|
return FALSE;
|
|
|
|
for(nIndex=0; nIndex<countof(pNICAddress->data); nIndex++)
|
|
pNICAddress->data[nIndex]=guid.Data4[nIndex+2];
|
|
|
|
for(nIndex=0; nIndex<countof(pNICAddress->data); nIndex++)
|
|
if(pNICAddress->data[nIndex]!=0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL COXSysInfo::GetFreeSystemResources(int* pnFreeResources,
|
|
enum RESOURCETYPE resourceType) const
|
|
{
|
|
ASSERT(pnFreeResources!=NULL);
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
if (bIsNT)
|
|
// We're running on NT.
|
|
return (FALSE);
|
|
|
|
HINSTANCE hLib = LoadLibrary(_T("RSRC32.dll"));
|
|
if (hLib != NULL)
|
|
{
|
|
typedef LONG (WINAPI* GETFREESYSTEMRESOURCES) (int);
|
|
GETFREESYSTEMRESOURCES pfnGetFreeSystemResources =
|
|
(GETFREESYSTEMRESOURCES) GetProcAddress(hLib, "_MyGetFreeSystemResources32@4");
|
|
ASSERT(pfnGetFreeSystemResources!=NULL);
|
|
|
|
*pnFreeResources=pfnGetFreeSystemResources((int)resourceType);
|
|
|
|
FreeLibrary(hLib);
|
|
|
|
return (TRUE);
|
|
}
|
|
else
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
// printers info
|
|
//
|
|
|
|
BOOL COXSysInfo::GetDefaultPrinterName(CString& sPrinterName) const
|
|
{
|
|
// --- In:
|
|
// --- Out: sPrinterName: reference to string to which the
|
|
// name of the default printer will be
|
|
// copied. If it is empty then there is
|
|
// default printers in the system
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the name of the default printer
|
|
|
|
// Local variables
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
|
|
sPrinterName.Empty();
|
|
|
|
if (!bIsNT)
|
|
{
|
|
LPTSTR lpszPrinterName=GetRegistryString(HKEY_CURRENT_CONFIG,
|
|
_T("SYSTEM\\CurrentControlSet\\Control\\Print\\Printers"),
|
|
_T("Default"));
|
|
if(lpszPrinterName!=NULL)
|
|
{
|
|
sPrinterName=lpszPrinterName;
|
|
::GlobalFree(lpszPrinterName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
LPTSTR lpszTemp; // Get Default printer name.
|
|
GetProfileString(_T("windows"),_T("device"),_T(""),
|
|
szTemp, sizeof(szTemp));
|
|
if(lstrlen(szTemp)!=0)
|
|
{
|
|
// Terminate at first comma, just want printer name.
|
|
lpszTemp=_tcschr(szTemp,',');
|
|
if(lpszTemp!=NULL)
|
|
*lpszTemp = '\x0';
|
|
sPrinterName=(LPTSTR)szTemp;
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::GetAllPrintersName(CStringArray& arrPrinterName) const
|
|
{
|
|
// --- In:
|
|
// --- Out: sPrinterName: reference to string array to which the
|
|
// name of found printers will be copied.
|
|
// If it is empty then there is no
|
|
// printers found
|
|
//
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the name of all printers in the system.
|
|
|
|
BOOL bIsNT;
|
|
if (!IsNT(&bIsNT))
|
|
return (FALSE);
|
|
|
|
arrPrinterName.RemoveAll();
|
|
|
|
BOOL bReturnCode;
|
|
DWORD dwSize, dwPrinters, dwNeeded;
|
|
DWORD dwType=PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS;
|
|
DWORD dwLevel=(bIsNT) ? 4 : 5;
|
|
bReturnCode=::EnumPrinters(dwType,NULL,dwLevel,NULL,0,&dwSize,&dwPrinters);
|
|
|
|
// If Return Code is TRUE, there is nothing to enumerate.
|
|
if (bReturnCode)
|
|
return (TRUE);
|
|
|
|
// If LastError is any thing other than allocate size error, flag and exit.
|
|
DWORD dwErrorCode=::GetLastError();
|
|
if (dwErrorCode!=ERROR_INSUFFICIENT_BUFFER)
|
|
return (FALSE);
|
|
|
|
// Loop until we have size right.
|
|
BOOL bRightSize=FALSE;
|
|
LPBYTE lpInfo=NULL;
|
|
while(!bRightSize)
|
|
{
|
|
if(NULL!=(lpInfo=(LPBYTE)GlobalAlloc(GPTR,dwSize)))
|
|
{
|
|
#ifdef _DEBUG
|
|
::memset(lpInfo,UNINIT_BYTE,dwSize);
|
|
#endif
|
|
// Enumerate
|
|
bRightSize=EnumPrinters(dwType,NULL,dwLevel,lpInfo,dwSize,&dwNeeded,&dwPrinters);
|
|
if(!bRightSize)
|
|
{
|
|
dwErrorCode=GetLastError();
|
|
// If anything other than allocate size error, flag and exit.
|
|
if (dwErrorCode != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
::GlobalFree(lpInfo);
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
::GlobalFree(lpInfo);
|
|
lpInfo=NULL;
|
|
dwSize=dwNeeded;
|
|
}
|
|
}
|
|
else // EnumPrinters returned success
|
|
{
|
|
if(bIsNT)
|
|
{
|
|
// Save pointer to PRINTER_INFO structure
|
|
LPPRINTER_INFO_4 lpPrinterInfo=(LPPRINTER_INFO_4)lpInfo;
|
|
for(DWORD dwIndex=0; dwIndex<dwPrinters; dwIndex++)
|
|
arrPrinterName.
|
|
Add((LPTSTR)lpPrinterInfo[dwIndex].pPrinterName);
|
|
}
|
|
else
|
|
{
|
|
// Save pointer to PRINTER_INFO structure
|
|
LPPRINTER_INFO_5 lpPrinterInfo=(LPPRINTER_INFO_5)lpInfo;
|
|
for(DWORD dwIndex=0; dwIndex<dwPrinters; dwIndex++)
|
|
arrPrinterName.
|
|
Add((LPTSTR)lpPrinterInfo[dwIndex].pPrinterName);
|
|
}
|
|
::GlobalFree(lpInfo);
|
|
}
|
|
}
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL COXSysInfo::GetPrinterInfo(const CString& sPrinterName,
|
|
LPPRINTER_INFO_2& lpPrinterInfo) const
|
|
{
|
|
// --- In: sPrinterName: reference to string which is the
|
|
// name of installed printer.
|
|
// --- Out: lpPrinterInfo: reference to the pointer to
|
|
// PRINTER_INFO_2 structure
|
|
// that will be populated with data as
|
|
// result of execution of this function.
|
|
// You shouldn't allocate any memory.
|
|
// This function will allocate all
|
|
// necessary memory. The caller will
|
|
// be responsible for freeing that memory.
|
|
// Use GlobalFree() function in order to
|
|
// do that
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the printer info for specified printer
|
|
// installed inthe system
|
|
|
|
ASSERT(!sPrinterName.IsEmpty());
|
|
|
|
HANDLE hPrinter=NULL;
|
|
if(!::OpenPrinter((LPTSTR)(LPCTSTR)sPrinterName,&hPrinter,NULL) ||
|
|
hPrinter==NULL)
|
|
{
|
|
TRACE(_T("COXSysInfo::GetPrinterInfo: OpenPrinter() has failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
DWORD dwSize, dwNeeded;
|
|
if(::GetPrinter(hPrinter,2,NULL,0,&dwSize))
|
|
{
|
|
TRACE(_T("COXSysInfo::GetPrinterInfo: GetPrinter() has failed\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
// If LastError is any thing other than allocate size error, flag and exit.
|
|
DWORD dwErrorCode=::GetLastError();
|
|
if(dwErrorCode!=ERROR_INSUFFICIENT_BUFFER)
|
|
return (FALSE);
|
|
|
|
// Loop until we have size right.
|
|
BOOL bRightSize=FALSE;
|
|
LPBYTE lpInfo=NULL;
|
|
while(!bRightSize)
|
|
{
|
|
if(NULL!=(lpInfo=(LPBYTE)GlobalAlloc(GPTR,dwSize)))
|
|
{
|
|
#ifdef _DEBUG
|
|
::memset(lpInfo,UNINIT_BYTE,dwSize);
|
|
#endif
|
|
// Get Printer Info
|
|
bRightSize=::GetPrinter(hPrinter,2,lpInfo,dwSize,&dwNeeded);
|
|
if(!bRightSize)
|
|
{
|
|
dwErrorCode=GetLastError();
|
|
// If anything other than allocate size error, flag and exit.
|
|
if(dwErrorCode!=ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
::GlobalFree(lpInfo);
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
::GlobalFree(lpInfo);
|
|
lpInfo=NULL;
|
|
dwSize=dwNeeded;
|
|
}
|
|
}
|
|
else // GetPrinter returned success
|
|
{
|
|
// Save pointer to PRINTER_INFO structure
|
|
lpPrinterInfo=(LPPRINTER_INFO_2)lpInfo;
|
|
}
|
|
}
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsLocalPrinter(const CString& sPrinterName,
|
|
BOOL* pbLocalPrinter) const
|
|
{
|
|
// --- In: sPrinterName: reference to string which is the
|
|
// name of installed printer.
|
|
// --- Out: pbLocalPrinter: TRUE if specified printer is local,
|
|
// or FALSE otherwise
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the flag that specify whether the printer
|
|
// is local or not
|
|
|
|
ASSERT(pbLocalPrinter!=NULL);
|
|
|
|
LPPRINTER_INFO_2 lpPrinterInfo=NULL;
|
|
if(GetPrinterInfo(sPrinterName,lpPrinterInfo) && lpPrinterInfo!=NULL)
|
|
{
|
|
*pbLocalPrinter=(lpPrinterInfo->pServerName!=NULL &&
|
|
lstrlen(lpPrinterInfo->pServerName)>0) ? FALSE : TRUE;
|
|
::GlobalFree(lpPrinterInfo);
|
|
return (TRUE);
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL COXSysInfo::IsSharedPrinter(const CString& sPrinterName,
|
|
BOOL* pbSharedPrinter) const
|
|
{
|
|
// --- In: sPrinterName: reference to string which is the
|
|
// name of installed printer.
|
|
// --- Out: pbSharedPrinter:TRUE if specified printer is shared,
|
|
// or FALSE otherwise
|
|
// --- Returns: BOOL - TRUE if success
|
|
// --- Effect: Retrieves the flag that specify whether the printer
|
|
// is shared or not
|
|
|
|
ASSERT(pbSharedPrinter!=NULL);
|
|
|
|
LPPRINTER_INFO_2 lpPrinterInfo=NULL;
|
|
if(GetPrinterInfo(sPrinterName,lpPrinterInfo) && lpPrinterInfo!=NULL)
|
|
{
|
|
*pbSharedPrinter=((lpPrinterInfo->
|
|
Attributes&PRINTER_ATTRIBUTE_SHARED)!=0 &&
|
|
lpPrinterInfo->pShareName!=NULL &&
|
|
lstrlen(lpPrinterInfo->pShareName)>0) ? TRUE : FALSE;
|
|
::GlobalFree(lpPrinterInfo);
|
|
return (TRUE);
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
// protected
|
|
|
|
int COXSysInfo::DeviceCaps(int iIndex) const
|
|
{
|
|
int iValue;
|
|
|
|
HDC hDC = CreateIC(_T("DISPLAY"), NULL, NULL, NULL);
|
|
ASSERT(hDC != NULL);
|
|
iValue = GetDeviceCaps(hDC, iIndex);
|
|
DeleteDC(hDC);
|
|
|
|
return (iValue);
|
|
}
|
|
|
|
void COXSysInfo::GetMemStatus()
|
|
{
|
|
m_memStatus.dwLength = sizeof(m_memStatus);
|
|
GlobalMemoryStatus(&m_memStatus);
|
|
}
|
|
|
|
void COXSysInfo::GetSysInfo()
|
|
{
|
|
::GetSystemInfo(&m_sysInfo);
|
|
}
|
|
|
|
LPTSTR COXSysInfo::GetRegistryString(HKEY hKeyClass, LPTSTR lpszSubKey,
|
|
LPTSTR lpszValueName) const
|
|
{
|
|
// Local variables
|
|
HKEY hKey=NULL; // Registry key
|
|
LPTSTR lpszKeyValue; // Buffer for key name
|
|
DWORD dwKeySize=0; // Size of key value
|
|
DWORD dwKeyDataType=0; // Type of data stored in key
|
|
|
|
if(ERROR_SUCCESS!=RegOpenKey(hKeyClass, lpszSubKey, &hKey))
|
|
return NULL;
|
|
|
|
// Got key, get value. First, get the size of the key.
|
|
if(ERROR_SUCCESS!=RegQueryValueEx(hKey,lpszValueName,
|
|
NULL,NULL,NULL,&dwKeySize))
|
|
return NULL;
|
|
if(dwKeySize <= 1)
|
|
return NULL;
|
|
|
|
lpszKeyValue=(LPTSTR)GlobalAlloc(GPTR,(++dwKeySize));
|
|
if(lpszKeyValue==NULL)
|
|
return NULL;
|
|
|
|
RegQueryValueEx(hKey,lpszValueName,NULL,&dwKeyDataType,
|
|
(LPBYTE)lpszKeyValue,&dwKeySize);
|
|
|
|
// it's caller responsibility to free the memory allocated for lpszKeyValue
|
|
return lpszKeyValue;
|
|
}
|
|
|
|
|
|
// static
|
|
|
|
// Sort all of the display modes:
|
|
// 1: Resolution (width), 2: color depth, 3: frequency.
|
|
int _cdecl DevModeCompare(const void *elem1, const void *elem2)
|
|
{
|
|
ASSERT(elem1!=NULL);
|
|
ASSERT(elem2!=NULL);
|
|
|
|
PDEVMODE pdvmd1=(PDEVMODE)elem1;
|
|
PDEVMODE pdvmd2=(PDEVMODE)elem2;
|
|
|
|
int nResult=pdvmd1->dmPelsWidth-pdvmd2->dmPelsWidth;
|
|
if(nResult!=0)
|
|
return (nResult);
|
|
|
|
nResult=pdvmd1->dmBitsPerPel-pdvmd2->dmBitsPerPel;
|
|
if(nResult!=0)
|
|
return (nResult);
|
|
|
|
nResult=pdvmd1->dmDisplayFrequency-pdvmd2->dmDisplayFrequency;
|
|
return(nResult);
|
|
}
|
|
|
|
|