Доброго времени суток. Недавно у меня была задача программно без использования WMI получить сериальный номер винчестера, не тома! На старых осях: Windows XP, 2003, всё работало нормально, но вот на Windows Vista/Seven - проблемы.
Прошу помочь данную проблему, пнуть в нужную сторону, или помочь ссылкой, кодом и т.д.
# THID.cpp:
| Код | #include "THID.h" //---------------------------------------------------------------------------
// Valid values for the bCommandReg member of IDEREGS; #define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI. #define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA. //---------------------------------------------------------------------------
PCHAR THID::GetHDDSerial() { PrepareClass(); // ---- int iTheHDDNumber = 0; // номер диска; // ---- // создаем хэндл диска PHYSICALDRIVEX - номер диска; HANDLE hDisk = CreateFile(L"\\\\.\\PHYSICALDRIVE0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // ---- if ( hDisk == INVALID_HANDLE_VALUE ) { return m_szHardDriveSerialNumber; } // ---- DWORD dwBytesRet = 0; // ---- GETVERSIONINPARAMS VIP; memset( & VIP, 0, sizeof(VIP)); // ---- if ( DeviceIoControl(hDisk, SMART_GET_VERSION, NULL, 0, & VIP, sizeof(VIP), & dwBytesRet, NULL) == NULL ) { CloseHandle(hDisk); return m_szHardDriveSerialNumber; } // ---- if ( VIP.bIDEDeviceMap <= 0 ) { CloseHandle(hDisk); return m_szHardDriveSerialNumber; } // ---- BYTE bIDCmd = (((VIP.bIDEDeviceMap >> iTheHDDNumber) & 0x10) != 0) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; // ---- if ( bIDCmd != IDE_ATA_IDENTIFY ) { CloseHandle(hDisk); return m_szHardDriveSerialNumber; } // ---- SENDCMDINPARAMS scip; memset( & scip, 0, sizeof(scip)); // ---- scip.irDriveRegs.bFeaturesReg = 0; scip.irDriveRegs.bSectorCountReg = 1; scip.irDriveRegs.bSectorNumberReg = 1; scip.irDriveRegs.bCylLowReg = 0; scip.irDriveRegs.bCylHighReg = 0; scip.irDriveRegs.bDriveHeadReg = 0xA0 | ((iTheHDDNumber & 1) << 4); scip.irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; scip.bDriveNumber = iTheHDDNumber; scip.cBufferSize = 512; // ---- int iBufSize = sizeof(SENDCMDOUTPARAMS) + 512 - 1; // ---- BYTE * IdOutCmd = new BYTE[iBufSize]; memset(IdOutCmd, 0, iBufSize); // ---- if ( DeviceIoControl(hDisk, SMART_RCV_DRIVE_DATA, (LPVOID) & scip, sizeof(SENDCMDINPARAMS) - 1, (LPVOID)IdOutCmd, iBufSize, & dwBytesRet, NULL) != NULL ) { // Указатель на адрес сектора HDD, в котором хранится разная полезная инфа; USHORT * pIdSector = (USHORT*)((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer; // ---- if ( pIdSector != NULL ) { WORD wDiskData[256]; memset(wDiskData, 0, sizeof(wDiskData)); // ---- // Заполняем наши данные; //for (int ijk = 0; ijk < 256; ijk++) wDiskData[ijk] = pIdSector[ijk]; memcpy(wDiskData, pIdSector, sizeof(WORD) * 256); // ---- // Конвертируем в строку SN; ConvertToString(wDiskData, 10, 19, m_szHardDriveSerialNumber); } } // ---- CloseHandle(hDisk); // ---- delete IdOutCmd; // ---- return m_szHardDriveSerialNumber; } //---------------------------------------------------------------------------
void THID::ConvertToString(WORD wDiskData[256], int firstIndex, int lastIndex, PCHAR szOutString) { char string[1024]; memset(string, 0, sizeof(string)); // ---- int i = 0; int j = 0; int position = 0; // ---- // each integer has two characters stored in it backwards; for (i = firstIndex; i <= lastIndex; i++) { // get high byte for 1st character; string[position] = (char)(wDiskData[i] / 256); position++; // ---- // get low byte for 2nd character; string[position] = (char)(wDiskData[i] % 256); position++; } // ---- // cut off the trailing blanks; // ---- for (i = 0, j = 0; i <= position; i++) { if ( string[i] != ' ' ) { szOutString[j] = string[i]; j++; } } }
|
# THID.h:
| Код | #ifndef THID_H #define THID_H //---------------------------------------------------------------------------
#include <stdlib.h> #include <stdio.h> #include <stddef.h> #include <string.h> #include <windows.h> #include <winioctl.h> //--------------------------------------------------------------------------- class THID { private: char m_szHardDriveSerialNumber[1024]; // ---- void PrepareClass() { memset(m_szHardDriveSerialNumber, 0, sizeof(m_szHardDriveSerialNumber)); } // ---- void ConvertToString(WORD wDiskData[256], int firstIndex, int lastIndex, PCHAR szOutString); public: THID() {}; ~THID() {}; // ---- PCHAR GetHDDSerial(); }; //--------------------------------------------------------------------------- #endif //---------------------------------------------------------------------------
|
# Добавлено: При попытки запустить данный код на Windows Vista/Seven, то hDisk == INVALID_HANDLE_VALUE. - То есть тупо даже не получается получить дескриптор на объект.
P.S. -> Надеюсь на помощь.
# Добавлено: - Разобрался в чём проблема, оказывается что в Windows Vista/Seven программу нужно запускать от имени администратора, чтобы данный код работал =( - А вот это уже проблема =( - Кто-что может порекомендовать?
# Добавлено: - Ещё один интересный факт. У меня ноут и персоналка, одна и таже ось, разные винты. - Под персоналкой от администратора показывает HID, на ноуте даже из под админа не показывает HID. - Такс, для ноута я вижу нужно писать отдельную функцию получения HID, так как VIP.bIDEDeviceMap == 0.
|