VC6 하드 드라이브 일련 번호, 모델, 개정 번호 가져오기

하드디스크 파라미터 정보를 읽는 컨트롤을 해야 하기 때문에 인터넷에서 많은 코드를 찾았지만 초보자로서 다른 사람의 코드를 사용할 때 여러 가지 문제점을 발견할 수 있다.
1. 필요한 헤더 파일이 명시되지 않음
2. 일부 정의는 제시되지 않았다
3. 코드의 개발 환경이 명확하지 않아 컴파일할 때'XXX'가 정의되지 않았습니다.
3. 추가된 코드가 어디에 쓰여 있는지 명확하지 않다
위와 같은 상황은 초보자에게는 쉽게 만날 수 있기 때문에 정리해 봤습니다.
다음은'하드디스크 일련 번호, 모델, 수정 버전 번호 읽기'의 전체 코드(win32 C++ 콘솔 프로그램), 개발 환경: win XP SP2 + VC6.0
헤더 파일:StructDef.h
//                VC(     VS2010)    :C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\WinIoCtl.h

typedef struct _DRIVERSTATUS {
	BYTE     bDriverError;           // Error code from driver,
	// or 0 if no error.
	BYTE     bIDEError;                      // Contents of IDE Error register.
	// Only valid when bDriverError
	// is SMART_IDE_ERROR.
	BYTE     bReserved[2];           // Reserved for future expansion.
	DWORD   dwReserved[2];          // Reserved for future expansion.
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;

typedef struct _IDEREGS {
	BYTE     bFeaturesReg;           // Used for specifying SMART "commands".
	BYTE     bSectorCountReg;        // IDE sector count register
	BYTE     bSectorNumberReg;       // IDE sector number register
	BYTE     bCylLowReg;             // IDE low order cylinder value
	BYTE     bCylHighReg;            // IDE high order cylinder value
	BYTE     bDriveHeadReg;          // IDE drive/head register
	BYTE     bCommandReg;            // Actual IDE command.
	BYTE     bReserved;              // reserved for future use.  Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;

typedef struct _SENDCMDOUTPARAMS {
	DWORD                   cBufferSize;            // Size of bBuffer in bytes
	DRIVERSTATUS            DriverStatus;           // Driver status structure.
	BYTE                    bBuffer[1];             // Buffer of arbitrary length in which to store the data read from the                                                                                  // drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;

typedef struct _SENDCMDINPARAMS {
	DWORD   cBufferSize;            // Buffer size in bytes
	IDEREGS irDriveRegs;            // Structure with drive register values.
	BYTE     bDriveNumber;           // Physical drive number to send
	// command to (0,1,2,3).
	BYTE     bReserved[3];           // Reserved for future expansion.
	DWORD   dwReserved[4];          // For future use.
	BYTE     bBuffer[1];                     // Input buffer.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;

typedef struct _GETVERSIONINPARAMS {
	BYTE     bVersion;               // Binary driver version.
	BYTE     bRevision;              // Binary driver revision.
	BYTE     bReserved;              // Not used.
	BYTE     bIDEDeviceMap;          // Bit map of IDE devices.
	DWORD   fCapabilities;          // Bit mask of driver capabilities.
	DWORD   dwReserved[4];          // For future use.
} GETVERSIONINPARAMS, *PGETVERSIONINPARAMS, *LPGETVERSIONINPARAMS;

#define SMART_GET_VERSION               CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
#define SMART_RCV_DRIVE_DATA            CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define DFP_SEND_DRIVE_COMMAND SMART_SEND_DRIVE_COMMAND
#define GETVERSIONOUTPARAMS GETVERSIONINPARAMS
#define DFP_RCV_DRIVE_DATA SMART_RCV_DRIVE_DATA
#define DFP_GET_VERSION SMART_GET_VERSION
#define IDENTIFY_BUFFER_SIZE        512

마스터: m.cpp
/*
	  :VC6       、  、     
*/

#include <iostream>
#include <windows.h>
#include <winioctl.h>
#include "Struct_Def.h"

using namespace std;

const WORD IDE_ATAPI_IDENTIFY = 0xA1;		//  ATAPI     
const WORD IDE_ATA_IDENTIFY = 0xEC;			//  ATA     
const int MAX_IDE_DRIVES = 1;				//  IDE   

string Trim(string str)				// cut off leading and tailing blanks
{
	string::size_type pos = str.find_last_not_of(' ');
	if(pos != string::npos)
	{
		str.erase(pos + 1);
		pos = str.find_first_not_of(' ');
		if(pos != string::npos) 
			str.erase(0, pos);
	}
	else 
		str.erase(str.begin(), str.end());
	
	return str;
}

// fetch characters what we need from DiskData[FirstIndex ... LastIndex]
string __fastcall ConvertToString(DWORD DiskData[256], int FirstIndex, int LastIndex)
{
	int i = 0;
	char ResBuf[1024] = {0};
	
	for(char *p = (char*)(DiskData + FirstIndex); p <= (char*)(DiskData + LastIndex); p += sizeof(DiskData))
	{
		ResBuf[i++] = *(p+1);
		ResBuf[i++] = *p;
	}
	
	return Trim(ResBuf);			// cut off leading and tailing blanks
}

BOOL __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, byte bIDCmd, byte bDriveNum, PDWORD lpcbBytesReturned)
{
	// Set up data structures for IDENTIFY command.
	pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
	pSCIP->irDriveRegs.bFeaturesReg = 0;
	pSCIP->irDriveRegs.bSectorCountReg = 1;
	pSCIP->irDriveRegs.bSectorNumberReg = 1;
	pSCIP->irDriveRegs.bCylLowReg = 0;
	pSCIP->irDriveRegs.bCylHighReg = 0;
	
	//Compute the drive number.(               )
	pSCIP->irDriveRegs.bDriveHeadReg = (bDriveNum & 1) ? 0xB0 : 0xA0;
	
	// The command can either be IDE identify or ATAPI identify.
	pSCIP->irDriveRegs.bCommandReg = bIDCmd;
	pSCIP->bDriveNumber = bDriveNum;
	pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
	
	return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA, (LPVOID)pSCIP, sizeof(SENDCMDINPARAMS) - 1, 
		(LPVOID)pSCOP, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL);
}

//       、   、     
void __fastcall ReadPhysicalDriveOnNT()
{
	//IDENTIFY_BUFFER_SIZE = 512
	byte IdOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
	char serialNo[21], modelNo[21], revisionNo[21];
	
	for(int Drive=0; Drive < 4; Drive++)
	{
		HANDLE hPhysicalDriveIOCTL;
		char DriveName[32];
		sprintf(DriveName, "\\\\.\\PhysicalDrive%d", Drive);
		hPhysicalDriveIOCTL = CreateFile(DriveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
		
		if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
		{
			DWORD cbBytesReturned = 0;
			GETVERSIONOUTPARAMS VersionParams;
			
			// Get the version, etc of PhysicalDrive IOCTL
			ZeroMemory(&VersionParams, sizeof(GETVERSIONOUTPARAMS));
			
			if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof(VersionParams), &cbBytesReturned, NULL))
			{
				continue;
			}
			
			if(VersionParams.bIDEDeviceMap > 0)
			{
				// IDE or ATAPI IDENTIFY cmd
				byte bIDCmd = 0;
				SENDCMDINPARAMS InParams;
				
				// Now, get the ID sector for all IDE devices in the system.
				// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
				// otherwise use the IDE_ATA_IDENTIFY command
				//               
				bIDCmd = (VersionParams.bIDEDeviceMap >> Drive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
				
				ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
				ZeroMemory(IdOutCmd, sizeof(IdOutCmd));
				
				if(DoIdentify(hPhysicalDriveIOCTL, &InParams, (PSENDCMDOUTPARAMS)IdOutCmd, (BYTE)bIDCmd,(BYTE)Drive, &cbBytesReturned))
				{
					DWORD DiskData[256];
					USHORT *pIDSector;												//     IDSECTOR,    
					pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)IdOutCmd)->bBuffer;
					
					for(int i=0; i < 256; i++)
						DiskData[i] = pIDSector[i];

					FILE *fp = NULL;
					if(NULL != (fp = fopen("a.log", "w")))
					{
						fwrite(DiskData, sizeof(DiskData), 1, fp);
						fclose(fp);
						cout<<"Write file successful"<<endl;
					}
					
					strcpy(serialNo, ConvertToString(DiskData, 10, 19).c_str());	// get serial number
					strcpy(modelNo, ConvertToString(DiskData, 27, 46).c_str());		// get model type
					strcpy(revisionNo, ConvertToString (DiskData, 23, 26).c_str());	//        

					printf("SerialNo=%s
ModelNo=%s
RevisionNo=%s
", serialNo, modelNo, revisionNo); } } CloseHandle(hPhysicalDriveIOCTL); } } } int main() { ReadPhysicalDriveOnNT(); return 0; }

실행 결과:
Write file successful
SerialNo=6VMSHFW9
ModelNo=ST3500418AS
RevisionNo=CC68
Press any key to continue

좋은 웹페이지 즐겨찾기