Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

The Ultimate Toolbox - Updates and User Contributions

, 12 Feb 2013 CPOL
Updates and User Contributions for the Ultimate Toolbox Libraries
OutlookDemoUpdate.zip
Ultimate Grid
Demos
OutlookStyle
OutlookStyle.aps
OutlookStyle.dsp
OutlookStyle.dsw
OutlookStyle.suo
res
bitmap1.bmp
bmattach.bmp
bmp00001.bmp
bmp00002.bmp
bmp00003.bmp
Flags.bmp
OutlookStyle.ico
OutlookStyleDoc.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
toolbarf.bmp
UltimateGrid72_Src_Update01.zip
CellTypes
Include
Source
UltimateGrid72_Src_Update02.zip
DataSources
ODBC
OleDB
EditControls
UltimateGrid72_Src_Update03.zip
UltimateGrid72_Src_Update04.zip
UltimateGrid73_src.zip
BuildDLL
Build DLL.dsp
Build DLL.dsw
res
BuildLib
ugmfclib.dsp
ugmfclib.dsw
Lib
Skel
UltimateTCP-IP42_Src_Update01.zip
Ultimate TCP-IP
Include
Security
Include
Source
source
UltimateTCP-IP42_Src_Update02.zip
Examples
Client
Mail
icon1.ico
icon2.ico
MailClientS.suo
test.dsp
test.dsw
UltimateTCP-IP42_Src_Update03.zip
ultimatetoolbox93_src_update01.zip
Ultimate Toolbox
include
source
UltimateToolbox93_Src_Update02.zip
lib
Build DLLs
Build Libs
UltimateToolbox93_Src_Update03.zip
UltimateToolbox93_Src_Update04.zip
UltimateToolbox93_Src_Update05.zip
// ==========================================================================
// 					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"

#ifdef _WIN64
#pragma message ("Ultimate Toolbox: COXSysInfo - cpuinf library unavailable for 64 bit - bypassing compilation.")
// v9.3 - update 03 - 64-bit - The intel cpuinf32 library relies on inline assembly
// for compilation, which is not implemeted in the MS 64-bit compilers. Update needed. - TD
#else
#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);
}

  
#endif // _WIN64

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

The Ultimate Toolbox
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.
 
Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
Group type: Organisation

392 members


| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 13 Feb 2013
Article Copyright 2008 by The Ultimate Toolbox
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid