磁盘ID的读取方法

在软件进行加密运算时,读取硬盘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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值