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


// Disclaimer and Copyright Information 
// HDiskInformation.cpp : Implementation of CHDiskInformation 
// 
// All rights reserved. 
// 
// Written by Naveen K Kohli (naveenkohli@netzero.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@netzero.net 
/////////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include  
#include "SystemHDisk.h" 
#include "HDiskInformation.h" 
 
///////////////////////////////////////////////////////////////////////////// 
// CHDiskInformation 
 
STDMETHODIMP CHDiskInformation::InterfaceSupportsErrorInfo(REFIID riid) 
{ 
	static const IID* arr[] =  
	{ 
		&IID_IHDiskInformation 
	}; 
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++) 
	{ 
		if (::InlineIsEqualGUID(*arr[i],riid)) 
			return S_OK; 
	} 
	return S_FALSE; 
} 
 
STDMETHODIMP CHDiskInformation::get_NumberOfPartitions(long *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	*pVal = m_NumberOfPartitions; 
 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_Bootable(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_BOOL; 
	V_ARRAY (pVal) = m_pBootable; 
 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_Letter(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	::VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_BSTR; 
	V_ARRAY (pVal) = m_pPartitionLetter; 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_PartitionType(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	::VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_BSTR; 
	V_ARRAY (pVal) = m_pPartitionType; 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_PartitionNumber(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_I4; 
	V_ARRAY (pVal) = m_pPartitionNumber; 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_PartitionLength(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	::VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_I4; 
	V_ARRAY (pVal) = m_pPartitionLength; 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::get_HiddenSectors(VARIANT *pVal) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) 
	{ 
		return hRes; 
	} 
 
	::VariantInit (pVal); 
 
	V_VT (pVal) = VT_ARRAY | VT_I4; 
	V_ARRAY (pVal) = m_pHiddenSectors; 
	return hRes; 
} 
 
STDMETHODIMP CHDiskInformation::GetHDiskInformation(long *plNumberOfPartitions, 
													VARIANT *pbstrDriveLetterArr, 
													VARIANT *pbBootableArr, 
													VARIANT *pbstrTypeArr, 
													VARIANT *plPartitionNumberArr, 
													VARIANT *plLengthArr, 
													VARIANT *plHiddenSectorsArr) 
{ 
	HRESULT hRes = E_FAIL; 
 
	if ((hRes = GetInformation ()) != S_OK) { 
		return hRes; 
	} 
 
	*plNumberOfPartitions = m_NumberOfPartitions; 
 
	::VariantInit (pbstrDriveLetterArr); 
	::VariantInit (pbBootableArr); 
	::VariantInit (pbstrTypeArr); 
	::VariantInit (plPartitionNumberArr); 
	::VariantInit (plLengthArr); 
	::VariantInit (plHiddenSectorsArr); 
 
	V_VT (pbstrDriveLetterArr) = VT_ARRAY | VT_BSTR; 
	V_ARRAY (pbstrDriveLetterArr) = m_pPartitionLetter; 
 
	V_VT (pbBootableArr) = VT_ARRAY | VT_BOOL; 
	V_ARRAY (pbBootableArr) = m_pBootable; 
 
	V_VT (pbstrTypeArr) = VT_ARRAY | VT_BSTR; 
	V_ARRAY (pbstrTypeArr) = m_pPartitionType; 
 
	V_VT (plPartitionNumberArr) = VT_ARRAY | VT_I4; 
	V_ARRAY (plPartitionNumberArr) = m_pPartitionNumber; 
 
	V_VT (plLengthArr) = VT_ARRAY | VT_R8; 
	V_ARRAY (plLengthArr) = m_pPartitionLength; 
 
	V_VT (plHiddenSectorsArr) = VT_ARRAY | VT_I4; 
	V_ARRAY (plHiddenSectorsArr) = m_pHiddenSectors; 
	return S_OK; 
} 
 
HRESULT CHDiskInformation::GetInformation () 
{ 
	UINT i, nIndex; 
	UINT nDrives, nDriveType; 
	HRESULT hRes = S_OK; 
	HANDLE hDevice = NULL; 
	BOOL fResult; 
	DWORD dwBytes, dwError; 
	double tmpNum = 0.; 
	char szCurrentDrive[MAX_PATH]; 
	char szName[80]; 
	char lpMultiByteStr[128]; 
	DWORD dwLogicalDrives; 
	PARTITION_INFORMATION  *pPartitionInfo = NULL; 
 
	if (m_bInformationObtained) 
	{ 
		return S_OK; 
	} 
 
	CComBSTR bstrDriveLetter; 
	SAFEARRAY *pSafeArray = NULL; 
	SAFEARRAYBOUND arrayBound[1]; 
 
	arrayBound[0].lLbound = 0; 
	arrayBound[0].cElements = 32; 
 
	pSafeArray = ::SafeArrayCreate (VT_BSTR, 1, arrayBound); 
 
	// Get the all the logical drives. Function will return a bit mask of the logical 
	// drives. Bits are set if the corresponding drives are available. Bit 0 represents 
	// drive A, bit 2 is drive B and so on. 
	dwLogicalDrives = ::GetLogicalDrives (); 
 
	m_NumberOfPartitions = nIndex = 0; 
 
	for (nDrives = 0; nDrives < 32; nDrives ++) 
	{ 
		if (dwLogicalDrives && (1 << nDrives)) 
		{ 
			wsprintf (szCurrentDrive, "%c", nDrives + 'A'); 
			strcpy (szName, szCurrentDrive); 
			strcat (szCurrentDrive, _T (":\\")); 
			 
			// Get the drive type. 
			nDriveType = ::GetDriveType (szCurrentDrive); 
 
			// If its a hard drive type of drive, then get the partition information. 
			if (nDriveType == DRIVE_FIXED) 
			{ 
				bstrDriveLetter = szName; 
				::SafeArrayPutElement (pSafeArray, (long *) &nIndex, bstrDriveLetter.Copy ()); 
				m_NumberOfPartitions++; 
				nIndex++; 
			} 
		} 
	} 
 
	// Create the SafeArrays. 
 
	if (FAILED (this->InitializeSafeArrays ())) 
	{ 
		return E_FAIL; 
	} 
 
	// Get information for each drive and stuff into arrays. 
	for (i = 0; i < nIndex; i++) 
	{ 
		::SafeArrayGetElement (pSafeArray, (long *) &i, &bstrDriveLetter); 
 
		::WideCharToMultiByte (CP_ACP, 0, bstrDriveLetter, -1, lpMultiByteStr, 
							   sizeof (lpMultiByteStr), NULL, NULL); 
 
		strcat (lpMultiByteStr, _T (":")); 
		sprintf(szName,"\\\\.\\%s", lpMultiByteStr); 
 
		hDevice = CreateFile (szName, GENERIC_READ | GENERIC_WRITE, 
							  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 
							  OPEN_EXISTING, 0, NULL); 
		if (hDevice == INVALID_HANDLE_VALUE) 
		{ 
			dwError = ::GetLastError (); 
			continue; 
		} 
 
		// Get the partition information. 
		pPartitionInfo = new PARTITION_INFORMATION ; 
		fResult = ::DeviceIoControl (hDevice, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, 
									 pPartitionInfo, sizeof (*pPartitionInfo), 
									 &dwBytes, (LPOVERLAPPED) NULL); 
		 
		if (!fResult) { 
			dwError = GetLastError (); 
			continue; 
		} 
 
		::SafeArrayPutElement (m_pPartitionLetter, (long *) &i, bstrDriveLetter.Copy ()); 
		::SafeArrayPutElement (m_pBootable, (long *) &i, &pPartitionInfo->BootIndicator); 
		tmpNum = (double)pPartitionInfo->PartitionLength.QuadPart; 
		::SafeArrayPutElement (m_pPartitionLength, (long *) &i, &tmpNum); 
		::SafeArrayPutElement (m_pHiddenSectors, (long *) &i, &pPartitionInfo->HiddenSectors); 
		::SafeArrayPutElement (m_pPartitionNumber, (long *) &i, &pPartitionInfo->PartitionNumber); 
		::SafeArrayPutElement (m_pPartitionType, (long *) &i, 
							   GetPartitionType ((DWORD)pPartitionInfo->PartitionType).Copy ()); 
 
		::CloseHandle (hDevice); 
 
		if (pPartitionInfo != NULL) 
		{ 
			delete pPartitionInfo; 
			pPartitionInfo = NULL; 
		} 
	} 
 
	m_bInformationObtained = true; 
	return S_OK; 
} 
 
HRESULT CHDiskInformation::InitializeSafeArrays () 
{ 
	SAFEARRAYBOUND arrayBound[1]; 
 
	if (m_NumberOfPartitions <= 0) 
	{ 
		return E_FAIL; 
	} 
 
	arrayBound[0].lLbound = 0; 
	arrayBound[0].cElements = m_NumberOfPartitions; 
 
	m_pBootable = ::SafeArrayCreate (VT_BOOL, 1, arrayBound); 
	m_pPartitionLetter = ::SafeArrayCreate (VT_BSTR, 1, arrayBound); 
	m_pPartitionType = ::SafeArrayCreate (VT_BSTR, 1, arrayBound); 
	m_pPartitionNumber = ::SafeArrayCreate (VT_I4, 1, arrayBound); 
	m_pPartitionLength = ::SafeArrayCreate (VT_R8, 1, arrayBound); 
	m_pHiddenSectors = ::SafeArrayCreate (VT_I4, 1, arrayBound); 
 
	return S_OK; 
} 
 
CComBSTR CHDiskInformation::GetPartitionType (DWORD dwType) const 
{ 
	CComBSTR bstrType; 
 
	switch (dwType) 
	{ 
		case PARTITION_ENTRY_UNUSED: 
			bstrType = _T ("Unknown"); 
			break; 
		case PARTITION_FAT_12: 
			bstrType = _T ("12-bit FAT"); 
			break; 
		case PARTITION_XENIX_1: 
			bstrType = _T ("Xenix type 1"); 
			break; 
		case PARTITION_XENIX_2: 
			bstrType = _T ("Xenix type 2"); 
			break; 
		case PARTITION_FAT_16: 
			bstrType = _T ("FAT16"); 
			break; 
		case PARTITION_EXTENDED: 
			bstrType = _T ("Extended");  
			break; 
		case PARTITION_FAT32: 
			bstrType = _T ("FAT32"); 
			break; 
		case PARTITION_HUGE: 
			bstrType = _T ("MS-DOS V4 Huge"); 
			break; 
		case PARTITION_IFS: 
			bstrType = _T ("IFS"); 
			break; 
		case PARTITION_PREP: 
			bstrType = _T ("PowerPC Reference Platform"); 
			break; 
		case PARTITION_UNIX: 
			bstrType = _T ("UNIX"); 
			break; 
		case VALID_NTFT: 
			bstrType = _T ("NTFT"); 
			break; 
		case PARTITION_LDM: 
			bstrType = _T ("Logical Disk Manager"); 
			break; 
		case PARTITION_XINT13: 
			bstrType = _T ("Partition with Extened int13 Services"); 
			break; 
		case PARTITION_XINT13_EXTENDED: 
			bstrType = _T ("Exteneded Partition with Extended int13 Services"); 
			break; 
		case PARTITION_FAT32_XINT13 : 
			bstrType = _T ("FAT32 with Extended int13 Services"); 
			break; 
	} 
 
	return bstrType; 
}