ドライブのモデル名や接続I/F情報などを取得する

test104.gif
情報を取得したドライブに対してDeviceIoControlによりIOCTL_STORAGE_QUERY_PROPERTYコマンドを実行すると、そのドライブの情報を取得できる。

とは言うものの実際に利用してみると、情報を取得できないドライブが少なからずある。また取得できても例えばシリアル番号などは値の格納され方がドライブによって異なっている。図でCとDドライブのシリアル番号は本来0x20 0x20 ... 0x45 0x32というバイト配列(文字列)のシリアル番号だが、二重にアスキーエンコードされている。逆にFドライブの場合はシリアル番号がアスキー文字列になっていない。情報がきちんと取得できない原因はドライブ側のためどうしようもないのだが...

結局、信頼できる情報はリムーバブルメディアかどうかと接続インターフェースぐらいだろうか?

#include "winioctl.h"
#include "atlstr.h"


class	CDnpStorageProperty
{
public:

	//
	//	使用中のドライブレター取得
	//
	//ドライブ名が文字列として列挙されて返る。例:AとC、Dドライブが使われているなら"ACD"
	//
	bool	GetUsedDriveLetter(TCHAR* pszLetter,int nSize)
	{
		int		i;
		int		nIndex;
		TCHAR	cbDrive;
		DWORD	dwDrives;

		if(pszLetter == NULL || nSize <= 0)
			return	false;

		dwDrives = ::GetLogicalDrives();

		ZeroMemory(pszLetter,sizeof(TCHAR) * nSize);
		nIndex = 0;
		cbDrive = _T('A');
		for(i = 0; i <= 'Z' - 'A'; i++)
		{
			if(! ((1 << i) & dwDrives))
				continue;

			pszLetter[nIndex++] = cbDrive + i;
			if(nIndex < nSize)
				continue;

			return	(dwDrives << (i+1)) ? false : true;
		}

		return	true;
	}



	class	CInfo
	{
	public:
		CAtlString	_strSerialNo;
		CAtlString	_strProductID;
		CAtlString	_strVendorID;
		CAtlString	_strRevision;
		bool		_bRemovableMedia;
		STORAGE_BUS_TYPE	_enumBusType;

		CInfo()
		{
			_bRemovableMedia = false;
			_enumBusType = BusTypeUnknown;
		}
	};






	//
	//	ドライブのプロパティ情報を取得する
	//
	bool	GetStorageProperty(TCHAR cbDrive,CInfo* pInfo)
	{
		BOOL	ret;
		HANDLE	hDrive;
		DWORD	dwRet;
		DWORD	dwLen;
		BYTE*	pcbData;
		CAtlString	strDrive;
		STORAGE_DEVICE_DESCRIPTOR*	pDescriptor;
		STORAGE_PROPERTY_QUERY		sQuery;

		if(pInfo == NULL)
			return	false;
		*pInfo = CInfo();

		strDrive.Format(_T("\\\\.\\%c:"),cbDrive);
		hDrive = CreateFile(strDrive,GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if(hDrive == INVALID_HANDLE_VALUE)
			return	false;

		dwLen = 4096;		//十分なバッファー領域を確保
		pcbData = new BYTE[dwLen];
		if(pcbData == NULL)
		{
			::CloseHandle(hDrive);
			return	false;
		}
		ZeroMemory(pcbData,dwLen);

		sQuery.PropertyId	= StorageDeviceProperty;
		sQuery.QueryType	= PropertyStandardQuery;
		sQuery.AdditionalParameters[0] = NULL;
		ret = ::DeviceIoControl(hDrive,IOCTL_STORAGE_QUERY_PROPERTY,&sQuery,sizeof(STORAGE_PROPERTY_QUERY),pcbData,dwLen,&dwRet,NULL);
		::CloseHandle(hDrive);
		if(ret == FALSE)
		{
			delete	pcbData;
			return	false;
		}

		pDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pcbData;

		if(pDescriptor->SerialNumberOffset)
			pInfo->_strSerialNo		= (char*)pDescriptor + pDescriptor->SerialNumberOffset;
		if(pDescriptor->ProductIdOffset)
			pInfo->_strProductID	= (char*)pDescriptor + pDescriptor->ProductIdOffset;
		if(pDescriptor->ProductRevisionOffset)
			pInfo->_strRevision		= (char*)pDescriptor + pDescriptor->ProductRevisionOffset;
		if(pDescriptor->VendorIdOffset)
			pInfo->_strVendorID		= (char*)pDescriptor + pDescriptor->VendorIdOffset;
		pInfo->_enumBusType		= pDescriptor->BusType;
		pInfo->_bRemovableMedia	= pDescriptor->RemovableMedia ? true : false;

		delete	pcbData;

		return	true;
	}




};






bool	Test()
{
	bool	ret;
	size_t	i;
	size_t	nSize;
	TCHAR	pszDrives[256];

	CAtlString	strBuff;
	CAtlString	strMessage;
	CDnpStorageProperty			cStorage;
	CDnpStorageProperty::CInfo	cInfo;

	ret = cStorage.GetUsedDriveLetter(pszDrives,256);
	if(ret == false)
		return	false;


	nSize = ::_tcslen(pszDrives);
	for(i = 0; i < nSize; i++)
	{
		ret = cStorage.GetStorageProperty(pszDrives[i],&cInfo);
		if(ret == false)
			continue;

		strBuff.Format(_T("\nドライブ:%c"),pszDrives[i]);
		strMessage += strBuff;
		strMessage += _T("\nベンダーID:");
		strMessage += cInfo._strVendorID;
		strMessage += _T("\nプロダクトID:");
		strMessage += cInfo._strProductID;
		strMessage += _T("\nシリアル番号:");
		strMessage += cInfo._strSerialNo;
		strMessage += _T("\nリビジョン番号:");
		strMessage += cInfo._strRevision;

		strMessage += _T("\nメディアタイプ:");
		strMessage += (cInfo._bRemovableMedia) ? _T("リムーバブルメディア") : _T("固定メディア");

		strMessage += _T("\n接続インターフェース:");
		switch(cInfo._enumBusType)
		{
		case	BusTypeScsi:
			strMessage += _T("SCSI");
			break;

		case	BusTypeAtapi:
			strMessage += _T("ATAPI");
			break;

		case	BusTypeAta:
			strMessage += _T("ATA");
			break;

		case	BusType1394:
			strMessage += _T("IEEE1394");
			break;

		case	BusTypeSsa:
			strMessage += _T("BusTypeSsa");
			break;

		case	BusTypeFibre:
			strMessage += _T("BusTypeFibre");
			break;

		case	BusTypeUsb:
			strMessage += _T("USB");
			break;

		case	BusTypeRAID:
			strMessage += _T("RAID");
			break;

		case	BusTypeiScsi:
			strMessage += _T("iSCSI");
			break;

		case	BusTypeSas:
			strMessage += _T("SAS");
			break;

		case	BusTypeSata:
			strMessage += _T("SerialATA");
			break;

		case	BusTypeSd:
			strMessage += _T("SD");
			break;

		case	BusTypeMmc:
			strMessage += _T("MMC");
			break;

		default:
		case	BusTypeUnknown:
			strMessage += _T("不明");
			break;
		}
		strMessage += _T("\n");
	}
	::MessageBox(NULL,strMessage,_T(""),MB_OK);

	return	true;
}

プロジェクトファイルをダウンロード


カテゴリー「システム情報」 のエントリー