양병규님(www.delmadang.com)의 팁과
Alex Konshin(
http://home.earthlink.net/~akonshin)의 자료를
참고하여 C++ Builder로 포팅하였습니다.
이 함수는 제조번호만 씁니다만, 구조체를 보시면 다른 정보도 얻을 수 있습니다.
포팅에만 신경을 써서, 군더더기가 있을 수 있아오니,
발견하시는 분은 리플바랍니다.
Functin Body..
TfrmSplash::GetIDESerial(String *sr, bool bNT)
{
const IDE_ID_FUNCTION = 0xEC;
const IDENTIFY_BUFFER_SIZE = 512;
const DFP_RECEIVE_DRIVE_DATA = 0x0007c088;
const DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
const IOCTL_SCSI_MINIPORT = 0x0004d008;
const IOCTL_SCSI_MINIPORT_IDENTIFY = 0x001b0501;
const BufferSize = sizeof(TSrbIoControl) + DataSize;
const W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;
HANDLE hDevice;
unsigned long cbBytesReturned = 0;
TSendCmdInParams *pInData;
void *pOutData;
unsigned char Buffer[BufferSize];
memset(Buffer,0x00,sizeof(Buffer));
TSrbIoControl *srbControl;
srbControl = (TSrbIoControl *)Buffer;
if(bNT){
hDevice = CreateFile( "\\\\.\\Scsi0:", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
if (hDevice==INVALID_HANDLE_VALUE) return;
srbControl->HeaderLength = sizeof(TSrbIoControl);
strncpy(srbControl->Signature,"SCSIDISK",8);
srbControl->Timeout = 2;
srbControl->Length = DataSize;
srbControl->ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
pInData = (TSendCmdInParams*)(Buffer + sizeof(TSrbIoControl));
pOutData = pInData;
pInData->cBufferSize = IDENTIFY_BUFFER_SIZE;
pInData->bDriveNumber = 0;
pInData->irDriveRegs.bFeaturesReg = 0;
pInData->irDriveRegs.bSectorCountReg = 1;
pInData->irDriveRegs.bSectorNumberReg = 1;
pInData->irDriveRegs.bCylLowReg = 0;
pInData->irDriveRegs.bCylHighReg = 0;
pInData->irDriveRegs.bDriveHeadReg = 0xA0;
pInData->irDriveRegs.bCommandReg = IDE_ID_FUNCTION;
DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT, &Buffer, BufferSize, &Buffer, BufferSize, &cbBytesReturned, NULL );
}
else{
hDevice = CreateFile( "\\\\.\\SMARTVSD", 0, 0, NULL, CREATE_NEW, 0, 0 );
if (hDevice==INVALID_HANDLE_VALUE) return;
pInData = (TSendCmdInParams*)(&Buffer);
pOutData = pInData->bBuffer;
pInData->cBufferSize = IDENTIFY_BUFFER_SIZE;
pInData->bDriveNumber = 0;
pInData->irDriveRegs.bFeaturesReg = 0;
pInData->irDriveRegs.bSectorCountReg = 1;
pInData->irDriveRegs.bSectorNumberReg = 1;
pInData->irDriveRegs.bCylLowReg = 0;
pInData->irDriveRegs.bCylHighReg = 0;
pInData->irDriveRegs.bDriveHeadReg = 0xA0;
pInData->irDriveRegs.bCommandReg = IDE_ID_FUNCTION;
DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA,pInData, sizeof(TSendCmdInParams)-1,
pOutData, W9xBufferSize, &cbBytesReturned, NULL );
}
TIdSector *IS = (TIdSector *)((char *)pOutData+16);
ChangeByteOrder(&IS->sSerialNumber, sizeof(IS->sSerialNumber));
*sr = IS->sSerialNumber;
*sr = sr->SubString(1,20);
CloseHandle(hDevice);
}
Header....
struct TIdSector{
unsigned short wGenConfig;
unsigned short wNumCyls;
unsigned short wReserved;
unsigned short wNumHeads;
unsigned short wBytesPerTrack;
unsigned short wBytesPerSector;
unsigned short wSectorsPerTrack;
unsigned short wVendorUnique[3];
char sSerialNumber[20];
unsigned short wBufferType;
unsigned short wBufferSize;
unsigned short wECCSize;
char sFirmwareRev[8];
char sModelNumber[40];
unsigned short wMoreVendorUnique;
unsigned short wDoubleWordIO;
unsigned short wCapabilities;
unsigned short wReserved1;
unsigned short wPIOTiming;
unsigned short wDMATiming;
unsigned short wBS;
unsigned short wNumCurrentCyls;
unsigned short wNumCurrentHeads;
unsigned short wNumCurrentSectorsPerTrack;
unsigned long ulCurrentSectorCapacity;
unsigned short wMultSectorStuff;
unsigned long ulTotalAddressableSectors;
unsigned short wSingleWordDMA;
unsigned short wMultiWordDMA;
unsigned char bReserved[128];
};
struct TSrbIoControl{
unsigned long HeaderLength;
char Signature[8];
unsigned long Timeout;
unsigned long ControlCode;
unsigned long ReturnCode;
unsigned long Length;
};
struct TIDERegs{
unsigned char bFeaturesReg; // Used for specifying SMART "commands".
unsigned char bSectorCountReg; // IDE sector count register
unsigned char bSectorNumberReg;// IDE sector number register
unsigned char bCylLowReg; // IDE low order cylinder value
unsigned char bCylHighReg; // IDE high order cylinder value
unsigned char bDriveHeadReg; // IDE drive/head register
unsigned char bCommandReg; // Actual IDE command.
unsigned char bReserved; // reserved for future use. Must be zero.
};
struct TSendCmdInParams{
unsigned long cBufferSize; // Buffer size in bytes
TIDERegs irDriveRegs; // Structure with drive register values.
unsigned char bDriveNumber; // Physical drive number to send command to (0,1,2,3).
unsigned char bReserved[3]; // Reserved for future expansion.
unsigned long dwReserved[4];// For future use.
unsigned char bBuffer[1]; // Input buffer.
};
관련함수
void ChangeByteOrder(void *Data, int Size)
{
char *ptr = (char *)Data;
for (int i = 0;i < Size-1;i++){
char c = *ptr;
*ptr = *(ptr+1);
*(ptr+1) = c;
ptr+=2;
}
}
**** 9x 계열이면 System 폴더의 smartvsd.vxd를 System\IOSubSys에 카피하고 재부팅하여야 합니다.