www.pudn.com > ComputerInformation.zip > CPUInformation.cpp


// Disclaimer and Copyright Information 
// CPUInformation.cpp : Implementation of CCPUInformation 
// 
// All rights reserved. 
// 
// Written by Naveen K Kohli (naveenkohli@att.net) 
// Version 1.0 
// 
// Distribute freely, except: don't remove my name from the source or 
// documentation (don't take credit for my work), mark your changes (don't 
// get me blamed for your possible bugs), don't alter or remove this 
// notice. 
// No warrantee of any kind, express or implied, is included with this 
// software; use at your own risk, responsibility for damages (if any) to 
// anyone resulting from the use of this software rests entirely with the 
// user. 
// 
// Send bug reports, bug fixes, enhancements, requests, flames, etc. to 
// naveenkohli@att.net 
/////////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "SystemCPU.h" 
#include "CPUInformation.h" 
#include  
 
///////////////////////////////////////////////////////////////////////////// 
// CCPUInformation 
 
HRESULT CCPUInformation::FinalConstruct () 
{ 
	HRESULT hr; 
 
	hr = CoCreateInstance (CLSID_OSInformation, 0, CLSCTX_INPROC_SERVER, IID_IOSInformation, 
		(void **) &m_pOSInfo); 
	if (FAILED (hr)) 
	{ 
		return E_NOINTERFACE; 
	} 
 
	return S_OK; 
} 
 
void CCPUInformation::FinalRelease () 
{ 
	if (m_pOSInfo != NULL) 
	{ 
		m_pOSInfo->Release (); 
	} 
} 
 
STDMETHODIMP CCPUInformation::InterfaceSupportsErrorInfo(REFIID riid) 
{ 
	static const IID* arr[] =  
	{ 
		&IID_ICPUInformation 
	}; 
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++) 
	{ 
		if (::InlineIsEqualGUID(*arr[i],riid)) 
			return S_OK; 
	} 
	return S_FALSE; 
} 
 
STDMETHODIMP CCPUInformation::get_NumberOfProcessors(long *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_lNumberOfProcessors; 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_CPUSpeed(long *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_lCPUSpeed; 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_PageSize(long *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_lPageSize; 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_ActiveProcessorMask(long *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_lActiveMask; 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_Vendor(BSTR *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_bstrVendor.Copy (); 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_ProcessorType(BSTR *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_bstrCPUType.Copy (); 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_Architecture(BSTR *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_bstrArchitecture.Copy (); 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_CPULevel(BSTR *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_CPULevel.Copy (); 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::get_CPURevision(BSTR *pVal) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_CPURevision.Copy (); 
	return S_OK; 
} 
 
STDMETHODIMP CCPUInformation::GetCPUInformation(BSTR *pbstrVendor, 
												BSTR *pbstrType, 
												BSTR *pbstrArchitecture, 
												BSTR *pbstrLevel, 
												BSTR *pbstrRevision, 
												long *plNumberOfProcessors, 
												long *plSpeed, 
												long *plPageSize, 
												long *plMask) 
{ 
	HRESULT hRes = S_OK; 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pbstrVendor = m_bstrVendor.Copy (); 
	*pbstrType = m_bstrCPUType.Copy (); 
	*pbstrLevel = m_CPULevel.Copy (); 
	*pbstrArchitecture = m_bstrArchitecture.Copy (); 
	*pbstrRevision = m_CPURevision.Copy (); 
	*plMask = m_lActiveMask; 
	*plPageSize = m_lPageSize; 
	*plSpeed = m_lCPUSpeed; 
	*plNumberOfProcessors = m_lNumberOfProcessors; 
 
	return S_OK; 
} 
 
HRESULT CCPUInformation::GetInformation () 
{ 
	HRESULT hRes = S_OK; 
	long bIsWin95 = FALSE; 
	SYSTEM_INFO sysInfo; 
	char str [MAX_PATH]; 
	CComBSTR tmpStr; 
	LONG result; 
	HKEY hKey; 
	TCHAR vendorData [64]; 
	DWORD data, dataSize; 
	LPTSTR lpErrDesc = NULL; 
 
	// Get the processor speed info. 
	result = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
		"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey); 
 
	// Check if the function has succeeded. 
	if (result == ERROR_SUCCESS) 
	{ 
		dataSize = MAX_PATH; 
		result = ::RegQueryValueEx (hKey, _T("~MHz"), NULL, NULL, 
			(LPBYTE)&data, &dataSize); 
 
		if (result != ERROR_SUCCESS) 
		{ 
			ATLTRACE (_T ("Failed to get CPU Speed information!\n")); 
			return MakeAPIErrorDesc (); 
		} 
		 
		m_lCPUSpeed = data; 
 
		dataSize = sizeof (vendorData); 
 
		result = ::RegQueryValueEx (hKey, _T("VendorIdentifier"), NULL, NULL, 
			(LPBYTE)vendorData, &dataSize); 
 
		if (result != ERROR_SUCCESS) 
		{ 
			ATLTRACE (_T ("Failed to get vendor information!\n")); 
			return MakeAPIErrorDesc (); 
		} 
 
		m_bstrVendor = vendorData; 
	} 
	else 
	{ 
		return MakeAPIErrorDesc (); 
	} 
 
	// Make sure to close the reg key 
 
	RegCloseKey (hKey); 
 
	// Get the hardware information 
 
	::GetSystemInfo (&sysInfo); 
 
	// Lets check the processor type first 
 
	if (sysInfo.dwProcessorType  == PROCESSOR_INTEL_386) 
	{ 
		m_bstrCPUType = _T ("Intel 386"); 
	} 
	else if (sysInfo.dwProcessorType  == PROCESSOR_INTEL_486) 
	{ 
		m_bstrCPUType = _T ("Intel 486"); 
	} 
	else if (sysInfo.dwProcessorType  == PROCESSOR_INTEL_PENTIUM) 
	{ 
		m_bstrCPUType = _T ("Intel Pentium"); 
	} 
	else if (sysInfo.dwProcessorType  == PROCESSOR_MIPS_R4000) 
	{ 
		// only for NT 
		m_bstrCPUType = _T ("MIPS"); 
	} 
	else if (sysInfo.dwProcessorType  == PROCESSOR_ALPHA_21064) 
	{ 
		// only for NT 
		m_bstrCPUType = _T ("Alpha"); 
	} 
	else 
	{ 
		m_bstrCPUType = _T ("Unknown"); 
	} 
 
	// check number of processors 
 
	m_lNumberOfProcessors = sysInfo.dwNumberOfProcessors; 
 
	// Get the information if we have Win95 OS. 
 
	hRes = m_pOSInfo->get_IsWin95 (&bIsWin95); 
	if (FAILED (hRes)) { 
		ATLTRACE (_T ("Failed to OS information!\n")); 
		return hRes; 
	} 
 
	// Check the architecture type and processor level 
 
	// Windows 95 doesn't use processor level 
	m_CPURevision = _T ("Unknown"); 
 
	if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 
	{ 
		m_bstrArchitecture = _T ("Pentium"); 
		switch (sysInfo.wProcessorLevel) 
		{ 
			case 3: 
				m_CPULevel = _T ("Intel 80386"); 
				if (!bIsWin95) 
				{ 
					m_CPURevision = HIBYTE (sysInfo.wProcessorRevision); 
					m_CPURevision += _T ("A"); 
					tmpStr = LOBYTE (sysInfo.wProcessorRevision); 
					m_CPURevision += tmpStr; 
				} 
				break; 
			case 4: 
				m_CPULevel = _T ("Intel 80486"); 
				if (!bIsWin95) 
				{ 
					m_CPURevision = HIBYTE (sysInfo.wProcessorRevision); 
					m_CPURevision += _T ("A"); 
					tmpStr = LOBYTE (sysInfo.wProcessorRevision); 
					m_CPURevision += tmpStr; 
				} 
				break; 
			case 5: 
				m_CPULevel = _T ("Pentium"); 
				// Check if the MMX instruction set is availbale or not. 
 
				if (IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE)) 
				{ 
					m_CPULevel += _T (" MMX"); 
				} 
 
				if (!bIsWin95) 
				{ 
					m_CPURevision = _T ("Model "); 
					sprintf (str, "%d", HIBYTE (sysInfo.wProcessorRevision)); 
					tmpStr = str; 
					m_CPURevision.Append (tmpStr); 
					m_CPURevision.Append (_T (", Stepping ")); 
					sprintf (str, "%d", LOBYTE (sysInfo.wProcessorRevision)); 
					tmpStr = str; 
					m_CPURevision += tmpStr; 
				} 
				break; 
			case 6: 
				m_CPULevel = _T ("Pentium (II/Pro)"); 
				break; 
		} 
	} 
	else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_MIPS) 
	{ 
		m_bstrArchitecture = _T ("MIPS"); 
		if (sysInfo.wProcessorLevel == 0004) { 
			m_CPULevel = _T ("MIPS R4000"); 
		} 
		else { 
			m_CPULevel = _T ("Unknown"); 
		} 
	} 
	else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA) 
	{ 
		m_bstrArchitecture = _T ("Alpha"); 
 
		itoa (sysInfo.wProcessorLevel , str, 10); 
 
		tmpStr = m_bstrArchitecture; 
		tmpStr.Append (str); 
		m_CPULevel.Append (tmpStr); 
	} 
	else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_PPC) 
	{ 
		m_bstrArchitecture = _T ("PPC"); 
 
		switch (sysInfo.wProcessorLevel) 
		{ 
			case 1: 
				m_CPULevel = _T ("PPC 601"); 
				break; 
			case 3: 
				m_CPULevel = _T ("PPC 603"); 
				break; 
			case 4: 
				m_CPULevel = _T ("PPC 604"); 
				break; 
			case 6: 
				m_CPULevel = _T ("PPC 603+"); 
				break; 
			case 9: 
				m_CPULevel = _T ("PPC 604+"); 
				break; 
			case 20: 
				m_CPULevel = _T ("PPC 620"); 
				break; 
		} 
	} 
	else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_UNKNOWN) 
	{ 
		m_bstrArchitecture = _T ("Unknown"); 
	} 
 
	::SysFreeString (tmpStr); 
 
	// Check page size 
	m_lPageSize = sysInfo.dwPageSize; 
 
	// Get active processor mask 
	// It represent how many processors are active (?? I am not sure) 
	m_lActiveMask = sysInfo.dwActiveProcessorMask; 
	return hRes; 
} 
 
HRESULT 
CCPUInformation::MakeAPIErrorDesc () 
{ 
	LPTSTR lpErrDesc = NULL; 
	DWORD dwError = ::GetLastError (); 
 
	FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |  
		FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, 
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpErrDesc, 0, NULL); 
 
	if (NULL != lpErrDesc) 
	{ 
		return Error (lpErrDesc, IID_IOSInformation, E_FAIL); 
	} 
	else 
	{ 
		return Error (_T ("Unknown Error"), IID_IOSInformation, E_FAIL); 
	} 
}