HDDのシリアル番号や型番などを取得する

test102.gif
HDDのシリアルナンバーを取得するにはDeviceIoControlを利用して、HDDへ直接ATA/ATAPIのコマンドを送る。

シリアル番号以外にも取得できる情報はたくさんある。詳しくはATA/ATAPIの仕様書を参照するといいだろう。
http://www.t13.org/内で「ATAPI」と検索すれば見つかり、PDF形式やWORD形式で無料ダウンロードできる。

依存環境:ATL
#include "winioctl.h"
#include "atlstr.h"

//
//	ATA/ATAPIデバイス情報取得用クラス
//
//以下の情報を参照しています。
//
//・ATA/ATAPI-8コマンドセット(ドラフト案)
//	http://www.t13.org/
//	上のHPのトップページから「ATAPI」で検索。検索結果の「ATA8-ACS」から「1699Dr0-ATA8-ACS.pdf」
//
//・Microsoftの用意しているサンプルアプリケーション(ソースコード)
//	http://download.microsoft.com/download/winddk/sample3/9x/W9X/EN-US/SmartApp.exe
//
class	CDnpATAPI
{
protected:

	enum	IO_CONTROL_CODE
	{
		DFP_RECEIVE_DRIVE_DATA = 0x0007c088,
	};

	enum	ATAPI_COMMAND_CODE
	{
		ATAPI_IDENTIFY_DEVICE	= 0xEC,
	};


#pragma pack(push,1)

	struct	IDENTIFY_DEVICE_OUTDATA
	{
		SENDCMDOUTPARAMS	sSendCmdOutParam;
		BYTE	pData[IDENTIFY_BUFFER_SIZE - 1];
	};

public:
	//
	//	IDENTIFY_DEVICEの取得結果構造体
	//
	struct IDENTIFY_DEVICE
	{
		USHORT	wGeneralConfiguration;		//0			//15bit:0=ATAデバイス、7bit:1=リムーバブルメディア・デバイス
		USHORT	wObsolute1;					//1
		USHORT	wSpecificConfiguration;		//2
		USHORT	wObsolute2;					//3
		USHORT	wRetired1[2];				//4-5
		USHORT	wObsolute3;					//6
		ULONG	ulReservedForCompactFlash;	//7-8
		USHORT	wRetired2;					//9
		CHAR	pszSerialNumber[20];		//10-19		//シリアルナンバー
		ULONG	ulRetired3;					//20-21
		USHORT	wObsolute4;					//22
		CHAR	pszFirmwareRev[8];			//23-26		//ファームウエア・バージョン
		CHAR	pszModelNumber[40];			//27-46		//モデル名
		USHORT	wMaxNumPerInterupt;			//47
		USHORT	wReserved1;					//48
		USHORT	wCapabilities1;				//49		//8bit:1=DMA対応 9bit:1=LBA対応 10bit:1=IORDY無効 11bit:1=IORDY対応/0=不明
		USHORT	wCapabilities2;				//50
		ULONG	ulObsolute5;				//51-52
		USHORT	wField88and7063;			//53		//2bit:1=88ワード目情報利用可能 1bit:1=70:64ワード目情報利用可能
		USHORT	wObsolute6[5];				//54-58
		USHORT	wMultSectorStuff;			//59
		ULONG	ulTotalAddressableSectors;	//60-61
		USHORT	wObsolute7;					//62
		USHORT	wMultiWordDMA;				//63		//0bit:1=mode0対応 1bit:1=mode1対応 2bit:1=mode2対応 8bit:1=mode0選択 9bit:mode1選択 10bit:mode2選択
		USHORT	wPIOMode;					//64
		USHORT	wMinMultiwordDMACycleTime;	//65
		USHORT	wRecommendedMultiwordDMACycleTime;	//66
		USHORT	wMinPIOCycleTimewoFlowCtrl;	//67
		USHORT	wMinPIOCycleTimeWithFlowCtrl;	//68
		USHORT	wReserved2[6];				//69-74
		USHORT	wQueueDepth;				//75
		USHORT	wReserved3[4];				//76-79
		USHORT	wMajorVersion;				//80		//4bit:1=ATA/ATAPI-4対応 5bit:1=ATA/ATAPI-5対応 6bit:1=ATA/ATAPI-6対応 7bit:1=ATA/ATAPI-7対応
		USHORT	wMinorVersion;				//81
		USHORT	wCommandSetSupported1;		//82		//0bit:1=SMART対応 1bit:SecurityMode対応 ....
		USHORT	wCommandSetSupported2;		//83		//0bit:1=DOWNLOAD Microcode対応 ....
		USHORT	wCommandSetSupported3;		//84		//0bit:1=SMART error logging対応 1bit:1=SMART self-test対応 ....
		USHORT	wCommandSetEnable1;			//85		//0bit:1=SMART利用可能 ....
		USHORT	wCommandSetEnable2;			//86		//0bit:1=DOWNLOAD Microcode利用可能 ....
		USHORT	wCommandSetDefault;			//87
		USHORT	wUltraDMAMode;				//88		//0bit:1=UltraDMAmode0対応 1bit:1=UltraDMAmode1対応 ....
		USHORT	wTimeReqForSecurityErase;	//89
		USHORT	wTimeReqForEnhancedSecure;	//90
		USHORT	wCurrentPowerManagement;	//91
		USHORT	wMasterPasswordRevision;	//92
		USHORT	wHardwareResetResult;		//93
		USHORT	wAcoustricmanagement;		//94
		USHORT	wStreamMinRequestSize;		//95
		USHORT	wStreamingTimeDMA;			//96
		USHORT	wStreamingAccessLatency;	//97
		ULONG	ulStreamingPerformance;		//98-99
		USHORT	pwMaxUserLBA[4];			//100-103
		USHORT	wStremingTimePIO;			//104
		USHORT	wReserved4;					//105
		USHORT	wSectorSize;				//106
		USHORT	wInterSeekDelay;			//107
		USHORT	wIEEEOUI;					//108
		USHORT	wUniqueID3;					//109
		USHORT	wUniqueID2;					//110
		USHORT	wUniqueID1;					//111
		USHORT	wReserved5[4];				//112-115
		USHORT	wReserved6;					//116
		ULONG	ulWordsPerLogicalSector;	//117-118
		USHORT	wReserved7[8];				//119-126
		USHORT	wRemovableMediaStatus;		//127
		USHORT	wSecurityStatus;			//128
		USHORT	pwVendorSpecific[31];		//129-159
		USHORT	wCFAPowerMode1;				//160
		USHORT	wReserved8[15];				//161-175
		CHAR	pszCurrentMediaSerialNo[60];//176-205
		USHORT	wReserved9[49];				//206-254
		USHORT	wIntegrityWord;				//255		//0-7bit:Signature 8-15bit:Checksum
	};
#pragma	pack(pop)


protected:

	//
	//	文字列並びの整形
	//
	VOID ChangeByteOrder(PCHAR szString, USHORT uscStrSize)
	{
		USHORT	i;
		CHAR	temp;

		for(i = 0; i < uscStrSize; i+=2)
		{
			temp = szString[i];
			szString[i] = szString[i+1];
			szString[i+1] = temp;
		}
	}


	//
	//	DeviceIoControlへ渡すハンドルの取得
	//
	bool	GetIoCtrlHandle(HANDLE* phIoCtrl,int nDeviceNo)
	{
		BOOL	ret;
		HANDLE	hIoCtrl;
		OSVERSIONINFO	sVerInfo;

		if(phIoCtrl == NULL)
			return	false;
		*phIoCtrl = INVALID_HANDLE_VALUE;

		::ZeroMemory(&sVerInfo,sizeof(OSVERSIONINFO));
		sVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		ret = ::GetVersionEx(&sVerInfo);
		if(ret == FALSE)
			return	false;

		//OSによってCreateFile処理を変える
		if(sVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
			hIoCtrl = ::CreateFile(_T("\\\\.\\SMARTVSD"), 0,0,0,CREATE_NEW, 0, 0);		//Windows 9x
		else
		{
			CAtlString	strDevice;
			strDevice.Format(_T("\\\\.\\PhysicalDrive%d"),nDeviceNo);
			hIoCtrl = ::CreateFile(strDevice,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
		}
		if(hIoCtrl == INVALID_HANDLE_VALUE)
			return	false;

		*phIoCtrl = hIoCtrl;

		return	true;
	}


public:

	class	CModelInfo
	{
	public:
		CAtlString	_strModel;
		CAtlString	_strFirmware;
		CAtlString	_strSerialNo;
	};



	//
	//	デバイス情報取得
	//
	bool	GetIdentifyDevice(int nDeviceNo,IDENTIFY_DEVICE* pData,CModelInfo* pInfo=NULL)
	{
		bool	ret;
		BOOL	bRet;
		HANDLE	hIoCtrl;
		DWORD	dwReturned;
		IDENTIFY_DEVICE_OUTDATA	sSendCmdOutParam;
		SENDCMDINPARAMS	sSendCmd;

		if(pData == NULL)
			return	false;
		::ZeroMemory(pData,sizeof(IDENTIFY_DEVICE));
		if(pInfo)
			*pInfo = CModelInfo();

		//ハンドル取得
		ret = GetIoCtrlHandle(&hIoCtrl,nDeviceNo);
		if(ret == false)
			return	false;

		::ZeroMemory(&sSendCmdOutParam,sizeof(IDENTIFY_DEVICE_OUTDATA));
		::ZeroMemory(&sSendCmd,sizeof(SENDCMDINPARAMS));
		sSendCmd.irDriveRegs.bCommandReg		= ATAPI_IDENTIFY_DEVICE;			//IDENTIFY DEVICEコマンド番号
		sSendCmd.irDriveRegs.bDriveHeadReg		= 0xA0 | ((nDeviceNo & 1) << 4);	//ドライブ番号
		sSendCmd.cBufferSize	= IDENTIFY_BUFFER_SIZE;
		sSendCmd.bDriveNumber	= nDeviceNo;			//ドライブ番号

		//IDENTIFY DEVICEコマンドの実行
		bRet = ::DeviceIoControl(hIoCtrl,DFP_RECEIVE_DRIVE_DATA,&sSendCmd,sizeof(SENDCMDINPARAMS),&sSendCmdOutParam,sizeof(IDENTIFY_DEVICE_OUTDATA),&dwReturned,NULL);
		::CloseHandle(hIoCtrl);
		if(ret == FALSE || dwReturned != sizeof(IDENTIFY_DEVICE_OUTDATA))
			return	false;

		memcpy_s(pData,sizeof(IDENTIFY_DEVICE),sSendCmdOutParam.sSendCmdOutParam.bBuffer,sizeof(IDENTIFY_DEVICE));

		if(pInfo)
		{
			char	pszBuff[256];
			IDENTIFY_DEVICE*	pData;

			pData = (IDENTIFY_DEVICE*)sSendCmdOutParam.sSendCmdOutParam.bBuffer;
			ChangeByteOrder(pData->pszModelNumber,sizeof(pData->pszModelNumber));
			ChangeByteOrder(pData->pszFirmwareRev,sizeof(pData->pszFirmwareRev));
			ChangeByteOrder(pData->pszSerialNumber,sizeof(pData->pszSerialNumber));

			strncpy_s(pszBuff,256 * sizeof(char),pData->pszModelNumber,sizeof(pData->pszModelNumber));
			pInfo->_strModel = pszBuff;
			strncpy_s(pszBuff,256 * sizeof(char),pData->pszFirmwareRev,sizeof(pData->pszFirmwareRev));
			pInfo->_strFirmware = pszBuff;
			strncpy_s(pszBuff,256 * sizeof(char),pData->pszSerialNumber,sizeof(pData->pszSerialNumber));
			pInfo->_strSerialNo = pszBuff;
		}

		return	true;
	}






};






bool	Test()
{
	int		i;

	//PCに接続されているHDDドライブのうち最初の4つの情報を取得&表示する
	for(i = 0; i < 4; i++)
	{
		bool		ret;
		CDnpATAPI	cIDE;
		CDnpATAPI::CModelInfo		cInfo;
		CDnpATAPI::IDENTIFY_DEVICE	sInfo;

		ret = cIDE.GetIdentifyDevice(i,&sInfo,&cInfo);
		if(ret == false)
			continue;

		CAtlString	strMessage;

		strMessage = _T("型番:");
		strMessage += cInfo._strModel;
		strMessage += _T("\n");

		strMessage += _T("シリアル番号:");
		strMessage += cInfo._strSerialNo;
		strMessage += _T("\n");

		strMessage += _T("ファームウエア:");
		strMessage += cInfo._strFirmware;
		strMessage += _T("\n");
		strMessage += _T("\n");

		if(sInfo.wGeneralConfiguration & 0x8000)
			strMessage += _T("NOT ATA Device\n");
		else
			strMessage += _T("ATA Device\n");

		if(sInfo.wGeneralConfiguration & 0x0008)
			strMessage += _T("Removable Media Device\n");

		if(sInfo.wCapabilities1 & 0x0100)
			strMessage += _T("DMA対応\n");
		if(sInfo.wCapabilities1 & 0x0200)
			strMessage += _T("LBA対応\n");
		if(sInfo.wCapabilities1 & 0x0800)
			strMessage += _T("IORDY対応\n");

		if(sInfo.wMultiWordDMA & 0x0400)
			strMessage += _T("Multiword DMA mode 2利用中\n");
		else if(sInfo.wMultiWordDMA & 0x0200)
			strMessage += _T("Multiword DMA mode 1利用中\n");
		else if(sInfo.wMultiWordDMA & 0x0100)
			strMessage += _T("Multiword DMA mode 0利用中\n");
		if(sInfo.wMultiWordDMA & 0x0004)
			strMessage += _T("Multiword DMA mode 2対応\n");
		else if(sInfo.wMultiWordDMA & 0x0002)
			strMessage += _T("Multiword DMA mode 1対応\n");
		else if(sInfo.wMultiWordDMA & 0x0001)
			strMessage += _T("Multiword DMA mode 0対応\n");

		if(sInfo.wMajorVersion & 0x0080)
			strMessage += _T("ATA/ATAPI-7対応\n");
		else if(sInfo.wMajorVersion & 0x0040)
			strMessage += _T("ATA/ATAPI-6対応\n");
		else if(sInfo.wMajorVersion & 0x0020)
			strMessage += _T("ATA/ATAPI-5対応\n");
		else if(sInfo.wMajorVersion & 0x0010)
			strMessage += _T("ATA/ATAPI-4対応\n");

		if(sInfo.wCommandSetEnable1 & 0x0001)
			strMessage += _T("S.M.A.R.T.利用可能\n");
		if(sInfo.wCommandSetEnable1 & 0x0004)
			strMessage += _T("Removable Media機能利用可能\n");
		if(sInfo.wCommandSetEnable1 & 0x0020)
			strMessage += _T("ライトキャッシュ利用可能\n");

		if(sInfo.wUltraDMAMode & 0x4000)
			strMessage += _T("Ultra DMA mode 6利用中\n");
		else if(sInfo.wUltraDMAMode & 0x2000)
			strMessage += _T("Ultra DMA mode 5利用中\n");
		else if(sInfo.wUltraDMAMode & 0x1000)
			strMessage += _T("Ultra DMA mode 4利用中\n");
		else if(sInfo.wUltraDMAMode & 0x0800)
			strMessage += _T("Ultra DMA mode 3利用中\n");
		else if(sInfo.wUltraDMAMode & 0x0400)
			strMessage += _T("Ultra DMA mode 2利用中\n");
		else if(sInfo.wUltraDMAMode & 0x0200)
			strMessage += _T("Ultra DMA mode 1利用中\n");
		else if(sInfo.wUltraDMAMode & 0x0100)
			strMessage += _T("Ultra DMA mode 0利用中\n");
		if(sInfo.wUltraDMAMode & 0x0040)
			strMessage += _T("Ultra DMA mode 6対応\n");
		else if(sInfo.wUltraDMAMode & 0x0020)
			strMessage += _T("Ultra DMA mode 5対応\n");
		else if(sInfo.wUltraDMAMode & 0x0010)
			strMessage += _T("Ultra DMA mode 4対応\n");
		else if(sInfo.wUltraDMAMode & 0x0008)
			strMessage += _T("Ultra DMA mode 3対応\n");
		else if(sInfo.wUltraDMAMode & 0x0004)
			strMessage += _T("Ultra DMA mode 2対応\n");
		else if(sInfo.wUltraDMAMode & 0x0002)
			strMessage += _T("Ultra DMA mode 1対応\n");
		else if(sInfo.wUltraDMAMode & 0x0001)
			strMessage += _T("Ultra DMA mode 0対応\n");

		::MessageBox(NULL,strMessage,_T(""),MB_OK);
	}

	return	true;
}

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


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