在软件进行加密运算时,读取硬盘ID,CPU ID,网卡ID成为加密计算的输入参数之一,本篇将讲述如何使用API来读取硬盘的ID,具体过程如下:
---------------------------------------------------------------------------------------------------------------------
其中hDisk为CreateFile打开磁盘的句柄;
LONG get_harddisk_id(HANDLE hDisk, TCHAR *pszDiskId)
{
char diskid[MAX_DISKID], *pcharId;
UCHAR WWID[WWID_LENGTH_16];
PUCHAR InquiryBuffer = NULL;
LONG status;
ULONG Signature;
UCHAR i, idlen = 0;
BOOL bSupportPage83 = FALSE, bWWIDGot = FALSE;
STORAGE_PROPERTY_QUERY *PropQuery;
STORAGE_DEVICE_DESCRIPTOR *DevDesc;
memset(diskid, 0, MAX_DISKID);
pcharId = diskid; //we need to use ANSI to get disk ID and convert it finally
memset(WWID, 0, WWID_LENGTH_16);
if ((InquiryBuffer = (PUCHAR)malloc(INQDATA_SIZE)) == NULL)
{
status = ERROR_INSUFFICIENT_BUFFER;
goto cleanup;
}
// First query its ACSL address ID
status = GetInquiryDataByHandle(hDisk, FALSE, 0, InquiryBuffer, INQDATA_SIZE);
if (status != ERROR_SUCCESS){
PropQuery = (STORAGE_PROPERTY_QUERY*) InquiryBuffer;
PropQuery->PropertyId = StorageDeviceProperty;
PropQuery->QueryType = PropertyStandardQuery;
DevDesc = (STORAGE_DEVICE_DESCRIPTOR *) PropQuery;
status = __QueryProperty(hDisk, PropQuery, sizeof(STORAGE_PROPERTY_QUERY), INQDATA_SIZE);
if (DevDesc->VendorIdOffset > 0){
sprintf(pcharId, "%s", InquiryBuffer + DevDesc->VendorIdOffset);
}
if (DevDesc->ProductIdOffset > 0){
sprintf(pcharId + strlen(pcharId), "%s", InquiryBuffer + DevDesc->ProductIdOffset);
}
if (DevDesc->ProductRevisionOffset > 0){
sprintf(pcharId + strlen(pcharId), "%s", InquiryBuffer + DevDesc->ProductRevisionOffset);
}
if (DevDesc->SerialNumberOffset > 0)
{
if ((strlen((const char*)pcharId) + strlen((const char*)InquiryBuffer + DevDesc->SerialNumberOffset) ) < (MAX_DISKID - 24)){
sprintf(pcharId + strlen(pcharId), "%s", InquiryBuffer + DevDesc->SerialNumberOffset);
}
else
{
_vsnprintf(pcharId + strlen(pcharId), MAX_DISKID - 24 - strlen(pcharId), "%s", (char*)InquiryBuffer + DevDesc->SerialNumberOffset);
}
}
if ( (status = GetSignatureByHandle(hDisk, &Signature)) == ERROR_SUCCESS ){
sprintf(pcharId + strlen(pcharId), "%x", Signature);
}
__MakeReadable((PUCHAR)pcharId, (ULONG)strlen(pcharId));
goto cleanup; //we have gotten its disk ID information
}
// Get ID by supported pages such as 0x80, 0x83
memcpy(pcharId, InquiryBuffer+8, 24);
__MakeReadable((PUCHAR)pcharId, 24);
//get supported pages
status = GetInquiryDataByHandle(hDisk, TRUE, 0, InquiryBuffer, INQDATA_SIZE);
if ( status == ERROR_SUCCESS)
{
PINQUIRYPAGEHEADER_SP pSPPageHdr = (PINQUIRYPAGEHEADER_SP)InquiryBuffer;
UCHAR nMaxPagesLength = (UCHAR)INQDATA_SIZE - (UCHAR)FIELD_OFFSET(INQUIRYPAGEHEADER_SP, SupportPages);
for( i = 0; i < nMaxPagesLength && i < pSPPageHdr->PageLength; i ++){
if(pSPPageHdr->SupportPages[i] == (UCHAR)0x83){
bSupportPage83 = TRUE;
break;
}
}
}
// get scsi_lun_wwid
if(bSupportPage83 && GetInquiryDataByHandle(hDisk, TRUE, 0x83, InquiryBuffer, INQDATA_SIZE) == DSTATUS_SUCCESS){
PINQUIRYPAGEHEADER pPageHdr = (PINQUIRYPAGEHEADER) InquiryBuffer;
UCHAR nLen = (pPageHdr->PageLength > (UCHAR)(INQDATA_SIZE - FIELD_OFFSET(INQUIRYPAGEHEADER, IdDesc))) ? /
(UCHAR)(INQDATA_SIZE - FIELD_OFFSET(INQUIRYPAGEHEADER, IdDesc)) : /
pPageHdr->PageLength;
PINQUIRY_ID_HEADER pIdTemp, pId = (PINQUIRY_ID_HEADER)pPageHdr->IdDesc;
for (i = 0; (nLen > 0) && (nLen >= (pId->IdLength + (UCHAR)FIELD_OFFSET(INQUIRY_ID_HEADER,Id))); i++){
if (pId->IdType == 0){
/* ID Type: Vendor-Specific (no guarantee globally unique) */
}
else if (pId->IdType == 1){
/* ID Type: Vendor-Specific (over 8 bytes) (not globally unique) */
}
else if ((pId->IdType == 2) && (pId->IdLength == WWID_LENGTH_8)){
/* ID Type: IEEE Extended Unique ID (64-bit), this is world wide id, get it */
bWWIDGot = TRUE;
memcpy(WWID, pId->Id, WWID_LENGTH_8);
idlen = WWID_LENGTH_8;
break;
}
else if ((pId->IdType == 3) && (pId->IdLength == WWID_LENGTH_16)){
/* ID Type: FC-PH 64-bit Name ID (X3.230-1994)
in the absence of IEEE Extended Unique ID (we going to use this one) */
bWWIDGot = TRUE;
memcpy(WWID, pId->Id, WWID_LENGTH_16);
idlen = WWID_LENGTH_16;
break;
}
pIdTemp = (PINQUIRY_ID_HEADER)(pId->Id + pId->IdLength); //move to next Id
nLen -= pId->IdLength + (UCHAR)FIELD_OFFSET(INQUIRY_ID_HEADER,Id);
pId = (PINQUIRY_ID_HEADER)pIdTemp;
}
}
if(bWWIDGot){
char *p = pcharId + 24;
for( i = 0; i < idlen; i ++){
sprintf(p, "%02x", WWID[i]);
p ++; p ++;
}
}
else if( (GetInquiryDataByHandle(hDisk, TRUE, 0x80, InquiryBuffer, INQDATA_SIZE) == ERROR_SUCCESS)
&& InquiryBuffer[1] == 0x80 && InquiryBuffer[3] >= 4 && InquiryBuffer[3] <= 100) {
memcpy(pcharId+24, InquiryBuffer+4, InquiryBuffer[3]);
__MakeReadable((PUCHAR)pcharId+24, InquiryBuffer[3]);
pcharId[24+InquiryBuffer[3]] = '/0';
}
else{
if ( (status = GetSignatureByHandle(hDisk, &Signature)) == ERROR_SUCCESS ){
sprintf(pcharId + strlen(pcharId), "%x", Signature);
}
}
cleanup:
if(InquiryBuffer != NULL){
free (InquiryBuffer);
}
// convert ANSI disk ID to wide string disk ID string
AnsiToUnicode(diskid, MAX_DISKID, pszDiskId, MAX_DISKID);
return status;
}
-----------------------------------------------------------------------------------------------------------------------------
LONG GetInquiryDataByHandle(HANDLE hDisk, IN UCHAR VPD, IN UCHAR PageCode, IN PVOID Buffer, IN ULONG BufferSize)
{
LONG Status = 0;
PSCSI_PASS_THROUGH_DIRECT passThrough;
ULONG i;
assert(Buffer != NULL);
memset(Buffer, 0, BufferSize);
passThrough = (PSCSI_PASS_THROUGH_DIRECT)malloc(sizeof(SCSI_PASS_THROUGH_DIRECT));
if (passThrough == NULL){
return ERROR_INSUFFICIENT_BUFFER;
}
memset(passThrough, 0, sizeof(SCSI_PASS_THROUGH_DIRECT));
/* make buffer size fit inside of a byte for inquiry command */
if (BufferSize > 252){
BufferSize = 252;
}
passThrough->Length = sizeof (SCSI_PASS_THROUGH_DIRECT);
passThrough->ScsiStatus = 0;
passThrough->PathId = 0;
passThrough->TargetId = 0;
passThrough->Lun = 0;
passThrough->CdbLength = 6;
passThrough->SenseInfoLength = 0;
passThrough->DataIn = SCSI_IOCTL_DATA_IN;
passThrough->DataTransferLength = BufferSize;
passThrough->TimeOutValue = 3;
passThrough->DataBuffer = Buffer;
passThrough->SenseInfoOffset = 0;
passThrough->Cdb[0] = SCSIOP_INQUIRY;
passThrough->Cdb[1] = VPD;
passThrough->Cdb[2] = VPD ? PageCode : 0;
passThrough->Cdb[3] = 0x00;
passThrough->Cdb[4] = (UCHAR)BufferSize;
passThrough->Cdb[5] = 0x00;
Status = __ExecuteDiskIoctlByHandle(hDisk, IOCTL_SCSI_PASS_THROUGH_DIRECT,
passThrough, sizeof (SCSI_PASS_THROUGH_DIRECT), Buffer, BufferSize,
NULL);
if ( Status != 0){
goto cleanup;
}
if (passThrough->ScsiStatus != 0){
Status = -1;
goto cleanup;
}
for (i = 0; i < BufferSize; i++){
if (*((char *)Buffer+i) != 0)
break;
}
/* No data is read */
if (i == BufferSize){
Status = -1;
}
cleanup:
free (passThrough);
return Status;
}
-----------------------------------------------------------------------------------------------------------------------------
__inline LONG __ExecuteDiskIoctlByHandle(
IN HANDLE hDisk,
IN ULONG IoControlCode,
IN PVOID InBuf,
IN ULONG InBufLen,
IN PVOID OutBuf,
IN ULONG OutBufLen,
OUT DWORD *pRet)
{
LONG status;
DWORD dwRet;
if(pRet == NULL){
pRet = &dwRet;
}
if(!DeviceIoControl(hDisk, IoControlCode, InBuf, InBufLen, OutBuf, OutBufLen, pRet, NULL)){
status = GetLastError();
}
else{
status = 0;
}
return status;
}
-----------------------------------------------------------------------------------------------------------------------------
__inline LONG __QueryProperty(IN HANDLE hDisk, IN STORAGE_PROPERTY_QUERY *PropQuery, ULONG InBufLen, ULONG OutBufLen)
{
return __ExecuteDiskIoctlByHandle(hDisk, IOCTL_STORAGE_QUERY_PROPERTY,
PropQuery, InBufLen, PropQuery, OutBufLen, NULL);
}
-----------------------------------------------------------------------------------------------------------------------------
__inline LONG __GetScsiAddress(HANDLE handle, SCSI_ADDRESS *addr)
{
memset(addr, 0, sizeof(SCSI_ADDRESS));
return __ExecuteDiskIoctlByHandle(handle, IOCTL_SCSI_GET_ADDRESS,
NULL, 0, addr, sizeof(SCSI_ADDRESS), NULL);
}
-----------------------------------------------------------------------------------------------------------------------------
__inline ULONG __MakeReadable(PUCHAR data, ULONG len)
{
ULONG Count = 0;
while(len--)
{
if (*data <= 32 || *data >= 127)
{
*data = '_';
Count++;
}
data++;
}
return Count;
}