原谅转自:
#define DFP_GET_VERSION 0x00074080
#define FILE_DEVICE_SCSI 0x0000001b#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16 ) + 0x0501)#define IOCTL_SCSI_MINIPORT 0x0004D008#define IDENTIFY_BUFFER_SIZE 512#define SENDIDLENGTH (sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE)#define IDE_ATAPI_IDENTIFY 0xA1#define IDE_ATA_IDENTIFY 0xEC#define DFP_RECEIVE_DRIVE_DATA 0x0007c088typedef struct _IDSECTOR{ USHORT wGenConfig; USHORT wNumCyls; USHORT wReserved; USHORT wNumHeads; USHORT wBytesPerTrack; USHORT wBytesPerSector; USHORT wSectorsPerTrack; USHORT wVendorUnique[3]; CHAR sSerialNumber[20]; USHORT wBufferType; USHORT wBufferSize; USHORT wECCSize; CHAR sFirmwareRev[8]; CHAR sModelNumber[40]; USHORT wMoreVendorUnique; USHORT wDoubleWordIO; USHORT wCapabilities; USHORT wReserved1; USHORT wPIOTiming; USHORT wDMATiming; USHORT wBS; USHORT wNumCurrentCyls; USHORT wNumCurrentHeads; USHORT wNumCurrentSectorsPerTrack; ULONG ulCurrentSectorCapacity; USHORT wMultSectorStuff; ULONG ulTotalAddressableSectors; USHORT wSingleWordDMA; USHORT wMultiWordDMA; BYTE bReserved[128];}IDSECTOR, *PIDSECTOR;//typedef struct _DRIVERSTATUS//{ // BYTE bDriverError;// BYTE bIDEStatus;// BYTE bReserved[2];// DWORD dwReserved[2];////}DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;//typedef struct _SENDCMDOUTPARAMS//{ // DWORD cBufferSize;// DRIVERSTATUS DriverStatus;// BYTE bBuffer[1];//}SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;typedef struct _SRB_IO_CONTROL{ ULONG HeaderLength; UCHAR Signature[8]; ULONG Timeout; ULONG ControlCode; ULONG ReturnCode; ULONG Length;}SRB_IO_CONTROL, *PSRB_IO_CONTROL;//typedef struct _IDEREGS//{//// BYTE bFeaturesReg;// BYTE bSectorCountReg;// BYTE bSectorNumberReg;// BYTE bCylLowReg;// BYTE bCylHighReg;// BYTE bDriveHeadReg;// BYTE bCommandReg;// BYTE bReserved;////}IDEREGS, *PIDEREGS, *LPIDEREGS;//typedef struct _SENDCMDINPARAMS//{ // DWORD cBufferSize;// IDEREGS irDriveRegs;// BYTE bDriveNumber;// BYTE bReserved[3];// DWORD dwReserved[4];// BYTE bBuffer[1];//}SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;typedef struct _GETVERSIONOUTPARAMS{ BYTE bVersion; BYTE bRevision; BYTE bReserved; BYTE bIDEDeviceMap; DWORD fCapabilities; DWORD dwReserved[4];}GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;typedef struct _UNICODE_STRING{ USHORT Length; USHORT MaximumLength; PWSTR Buffer;}UNICODE_STRING,*PUNICODE_STRING;typedef struct _OBJECT_ATTRIBUTES{ ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService;}OBJECT_ATTRIBUTES;typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;// 函数指针typedef DWORD (__stdcall *ZWOS )( PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);typedef DWORD (__stdcall *ZWMV )( HANDLE,HANDLE,PVOID,ULONG,ULONG,PLARGE_INTEGER,PSIZE_T,DWORD,ULONG,ULONG);typedef DWORD (__stdcall *ZWUMV )( HANDLE,PVOID);BOOL WinNTHDSerialNumAsScsiRead(BYTE* dwSerial, UINT* puSerialLen, UINT uMaxSerialLen){ BOOL bInfoLoaded = FALSE; for (int iController = 0; iController < 2; ++iController) { HANDLE hScsiDriveIOCTL = 0; char szDriveName[256]; sprintf( szDriveName, "\\\\.\\Scsi%d:", iController ); // Windows NT, Windows 2000, any rights should do hScsiDriveIOCTL = CreateFile(szDriveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE) // printf ("Unable to open SCSI controller %d, error code: 0x%lX\n", // controller, GetLastError ()); if( hScsiDriveIOCTL != INVALID_HANDLE_VALUE ) { int iDrive = 0; for (iDrive = 0; iDrive < 2; ++ iDrive) { char szBuffer[sizeof (SRB_IO_CONTROL) + SENDIDLENGTH] = { 0 }; SRB_IO_CONTROL* p = ( SRB_IO_CONTROL* )szBuffer; SENDCMDINPARAMS* pin = ( SENDCMDINPARAMS* )( szBuffer + sizeof (SRB_IO_CONTROL)); DWORD dwResult; p->HeaderLength = sizeof (SRB_IO_CONTROL); p->Timeout = 10000; p->Length = SENDIDLENGTH; p->ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; strncpy((char*) p->Signature, "SCSIDISK", 8 ); pin->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; pin->bDriveNumber = iDrive; if (DeviceIoControl(hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, szBuffer, sizeof (SRB_IO_CONTROL) + sizeof (SENDCMDINPARAMS) - 1, szBuffer, sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, &dwResult, NULL)) { SENDCMDOUTPARAMS* pOut = (SENDCMDOUTPARAMS*) (szBuffer + sizeof( SRB_IO_CONTROL)); IDSECTOR* pId = (IDSECTOR*) (pOut->bBuffer); if (pId->sModelNumber[0]) { if (* puSerialLen + 20U <= uMaxSerialLen) { CopyMemory(dwSerial + * puSerialLen, ((USHORT*) pId) + 10, 20); // Cut off the trailing blanks for (UINT i = 20; i != 0U && ' ' == dwSerial[* puSerialLen + i - 1]; --i); * puSerialLen += i; CopyMemory( dwSerial + * puSerialLen, ( ( USHORT* )pId ) + 27, 40 ); // Cut off the trailing blanks for( i = 40; i != 0U && ' ' == dwSerial[* puSerialLen + i - 1]; -- i ); * puSerialLen += i; bInfoLoaded = TRUE; } else { ::CloseHandle( hScsiDriveIOCTL ); return bInfoLoaded; } } } } ::CloseHandle( hScsiDriveIOCTL ); } } return bInfoLoaded;}BOOL 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; // calc the drive number. pSCIP->irDriveRegs.bDriveHeadReg = 0xA0 | ( ( bDriveNum & 1 ) << 4 ); // 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_RECEIVE_DRIVE_DATA, (LPVOID) pSCIP, sizeof (SENDCMDINPARAMS) - 1, (LPVOID) pSCOP, sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL);}BOOL WinNTHDSerialNumAsPhysicalRead( BYTE* dwSerial, UINT* puSerialLen, UINT uMaxSerialLen ){ BOOL bInfoLoaded = FALSE; for (UINT uDrive = 0; uDrive < 4; ++ uDrive) { HANDLE hPhysicalDriveIOCTL = 0; // Try to get a handle to PhysicalDrive IOCTL, report failure // and exit if can't. char szDriveName [256]; sprintf( szDriveName, "\\\\.\\PhysicalDrive%d", uDrive ); // Windows NT, Windows 2000, must have admin rights hPhysicalDriveIOCTL = CreateFile(szDriveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) { GETVERSIONOUTPARAMS VersionParams = { 0 }; DWORD cbBytesReturned = 0; // Get the version, etc of PhysicalDrive IOCTL if( DeviceIoControl( hPhysicalDriveIOCTL, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof (GETVERSIONOUTPARAMS), &cbBytesReturned, NULL)) { // If there is a IDE device at number "i" issue commands // to the device if (VersionParams.bIDEDeviceMap != 0) { BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd SENDCMDINPARAMS scip = { 0 }; // 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 >> uDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; BYTE IdOutCmd[sizeof( SENDCMDOUTPARAMS ) + IDENTIFY_BUFFER_SIZE - 1] = { 0 }; if (DoIdentify( hPhysicalDriveIOCTL, &scip, (PSENDCMDOUTPARAMS)&IdOutCmd, (BYTE)bIDCmd, (BYTE)uDrive, &cbBytesReturned)) { if (* puSerialLen + 20U <= uMaxSerialLen) { CopyMemory(dwSerial + * puSerialLen, ((USHORT*)(((PSENDCMDOUTPARAMS )IdOutCmd )->bBuffer)) + 10, 20); // 序列号 // Cut off the trailing blanks for (UINT i = 20; i != 0U && ' ' == dwSerial[* puSerialLen + i - 1]; --i); * puSerialLen += i; CopyMemory(dwSerial + * puSerialLen, ((USHORT*)(((PSENDCMDOUTPARAMS)IdOutCmd )->bBuffer)) + 27, 40); // 型号 // Cut off the trailing blanks for (i = 40; i != 0U && ' ' == dwSerial[* puSerialLen + i - 1]; -- i); * puSerialLen += i; bInfoLoaded = TRUE; } else { ::CloseHandle( hPhysicalDriveIOCTL ); return bInfoLoaded; } } } } CloseHandle( hPhysicalDriveIOCTL ); } } return bInfoLoaded;}// 如何获取硬盘序列好// 结果存放在 disk_info.txt 文件中void GetDiskSuquenceID(){ UINT uSystemInfoLen; BYTE szSystemInfo[1024] = { 0 }; OSVERSIONINFO ovi = { 0 }; ovi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); GetVersionEx( &ovi ); if( ovi.dwPlatformId != VER_PLATFORM_WIN32_NT ) // 获取不到硬盘序列号信息,返回 return; if( !WinNTHDSerialNumAsPhysicalRead(szSystemInfo, &uSystemInfoLen, 1024)) WinNTHDSerialNumAsScsiRead(szSystemInfo, &uSystemInfoLen, 1024); // 以写追加的方式打开保存结果的文件 FILE *pf = fopen("./disk_info.txt", "a+"); // 检测文件指针的有效性 assert(NULL != pf); if (NULL == pf) return; // 把硬盘序列号写入文件 fprintf(pf, "\ndisk sequence info is %s\n",szSystemInfo ); // 关闭文件 fclose(pf);}