获取硬盘序列号以及mac地址

  1. //  diskid32.cpp
  2. //  for displaying the details of hard drives in a command window
  3. //  06/11/00  Lynn McGuire  written with many contributions from others,
  4. //                            IDE drives only under Windows NT/2K and 9X,
  5. //                            maybe SCSI drives later
  6. //  11/20/03  Lynn McGuire  added ReadPhysicalDriveInNTWithZeroRights
  7. //  10/26/05  Lynn McGuire  fix the flipAndCodeBytes function
  8. //  01/22/08  Lynn McGuire  incorporate changes from Gonzalo Diethelm,
  9. //                             remove media serial number code since does 
  10. //                             not work on USB hard drives or thumb drives
  11. //  01/29/08  Lynn McGuire  add ReadPhysicalDriveInNTUsingSmart
  12. #define PRINTING_TO_CONSOLE_ALLOWED
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <stddef.h>
  16. #include <string.h>
  17. #include <windows.h>
  18. #include <winioctl.h>
  19.     //  special include from the MS DDK
  20. //#include "c:/win2kddk/inc/ddk/ntddk.h"
  21. //#include "c:/win2kddk/inc/ntddstor.h"
  22. #define  TITLE   "DiskId32"
  23. char HardDriveSerialNumber [1024];
  24. char HardDriveModelNumber [1024];
  25. int PRINT_DEBUG = false;
  26. static void dump_buffer (const char* title,
  27.             const unsigned char* buffer,
  28.             int len);
  29. void WriteConstantString (char *entry, char *string)
  30. {
  31. }
  32.    //  Required to ensure correct PhysicalDrive IOCTL structure setup
  33. #pragma pack(1)
  34. #define  IDENTIFY_BUFFER_SIZE  512
  35.    //  IOCTL commands
  36. #define  DFP_GET_VERSION          0x00074080
  37. #define  DFP_SEND_DRIVE_COMMAND   0x0007c084
  38. #define  DFP_RECEIVE_DRIVE_DATA   0x0007c088
  39. #define  FILE_DEVICE_SCSI              0x0000001b
  40. #define  IOCTL_SCSI_MINIPORT_IDENTIFY  ((FILE_DEVICE_SCSI << 16) + 0x0501)
  41. #define  IOCTL_SCSI_MINIPORT 0x0004D008  //  see NTDDSCSI.H for definition
  42. #define SMART_GET_VERSION               CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
  43. #define SMART_SEND_DRIVE_COMMAND        CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  44. #define SMART_RCV_DRIVE_DATA            CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  45. typedef struct _GETVERSIONINPARAMS {
  46.         UCHAR    bVersion;               // Binary driver version.
  47.         UCHAR    bRevision;              // Binary driver revision.
  48.         UCHAR    bReserved;              // Not used.
  49.         UCHAR    bIDEDeviceMap;          // Bit map of IDE devices.
  50.         ULONG   fCapabilities;          // Bit mask of driver capabilities.
  51.         ULONG   dwReserved[4];          // For future use.
  52. } GETVERSIONINPARAMS, *PGETVERSIONINPARAMS, *LPGETVERSIONINPARAMS;
  53.    //  GETVERSIONOUTPARAMS contains the data returned from the 
  54.    //  Get Driver Version function.
  55. typedef struct _GETVERSIONOUTPARAMS
  56. {
  57.    BYTE bVersion;      // Binary driver version.
  58.    BYTE bRevision;     // Binary driver revision.
  59.    BYTE bReserved;     // Not used.
  60.    BYTE bIDEDeviceMap; // Bit map of IDE devices.
  61.    DWORD fCapabilities; // Bit mask of driver capabilities.
  62.    DWORD dwReserved[4]; // For future use.
  63. } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
  64.    //  Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS 
  65. #define  CAP_IDE_ID_FUNCTION             1  // ATA ID command supported
  66. #define  CAP_IDE_ATAPI_ID                2  // ATAPI ID command supported
  67. #define  CAP_IDE_EXECUTE_SMART_FUNCTION  4  // SMART commannds supported
  68.    //  IDE registers
  69. typedef struct _IDEREGS
  70. {
  71.    BYTE bFeaturesReg;       // Used for specifying SMART "commands".
  72.    BYTE bSectorCountReg;    // IDE sector count register
  73.    BYTE bSectorNumberReg;   // IDE sector number register
  74.    BYTE bCylLowReg;         // IDE low order cylinder value
  75.    BYTE bCylHighReg;        // IDE high order cylinder value
  76.    BYTE bDriveHeadReg;      // IDE drive/head register
  77.    BYTE bCommandReg;        // Actual IDE command.
  78.    BYTE bReserved;          // reserved for future use.  Must be zero.
  79. } IDEREGS, *PIDEREGS, *LPIDEREGS;
  80.    //  SENDCMDINPARAMS contains the input parameters for the 
  81.    //  Send Command to Drive function.
  82. typedef struct _SENDCMDINPARAMS
  83. {
  84.    DWORD     cBufferSize;   //  Buffer size in bytes
  85.    IDEREGS   irDriveRegs;   //  Structure with drive register values.
  86.    BYTE bDriveNumber;       //  Physical drive number to send 
  87.                             //  command to (0,1,2,3).
  88.    BYTE bReserved[3];       //  Reserved for future expansion.
  89.    DWORD     dwReserved[4]; //  For future use.
  90.    BYTE      bBuffer[1];    //  Input buffer.
  91. } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
  92.    //  Valid values for the bCommandReg member of IDEREGS.
  93. #define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI.
  94. #define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA.
  95.    // Status returned from driver
  96. typedef struct _DRIVERSTATUS
  97. {
  98.    BYTE  bDriverError;  //  Error code from driver, or 0 if no error.
  99.    BYTE  bIDEStatus;    //  Contents of IDE Error register.
  100.                         //  Only valid when bDriverError is SMART_IDE_ERROR.
  101.    BYTE  bReserved[2];  //  Reserved for future expansion.
  102.    DWORD  dwReserved[2];  //  Reserved for future expansion.
  103. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
  104.    // Structure returned by PhysicalDrive IOCTL for several commands
  105. typedef struct _SENDCMDOUTPARAMS
  106. {
  107.    DWORD         cBufferSize;   //  Size of bBuffer in bytes
  108.    DRIVERSTATUS  DriverStatus;  //  Driver status structure.
  109.    BYTE          bBuffer[1];    //  Buffer of arbitrary length in which to store the data read from the                                                       // drive.
  110. } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
  111.    // The following struct defines the interesting part of the IDENTIFY
  112.    // buffer:
  113. typedef struct _IDSECTOR
  114. {
  115.    USHORT  wGenConfig;
  116.    USHORT  wNumCyls;
  117.    USHORT  wReserved;
  118.    USHORT  wNumHeads;
  119.    USHORT  wBytesPerTrack;
  120.    USHORT  wBytesPerSector;
  121.    USHORT  wSectorsPerTrack;
  122.    USHORT  wVendorUnique[3];
  123.    CHAR    sSerialNumber[20];
  124.    USHORT  wBufferType;
  125.    USHORT  wBufferSize;
  126.    USHORT  wECCSize;
  127.    CHAR    sFirmwareRev[8];
  128.    CHAR    sModelNumber[40];
  129.    USHORT  wMoreVendorUnique;
  130.    USHORT  wDoubleWordIO;
  131.    USHORT  wCapabilities;
  132.    USHORT  wReserved1;
  133.    USHORT  wPIOTiming;
  134.    USHORT  wDMATiming;
  135.    USHORT  wBS;
  136.    USHORT  wNumCurrentCyls;
  137.    USHORT  wNumCurrentHeads;
  138.    USHORT  wNumCurrentSectorsPerTrack;
  139.    ULONG   ulCurrentSectorCapacity;
  140.    USHORT  wMultSectorStuff;
  141.    ULONG   ulTotalAddressableSectors;
  142.    USHORT  wSingleWordDMA;
  143.    USHORT  wMultiWordDMA;
  144.    BYTE    bReserved[128];
  145. } IDSECTOR, *PIDSECTOR;
  146. typedef struct _SRB_IO_CONTROL
  147. {
  148.    ULONG HeaderLength;
  149.    UCHAR Signature[8];
  150.    ULONG Timeout;
  151.    ULONG ControlCode;
  152.    ULONG ReturnCode;
  153.    ULONG Length;
  154. } SRB_IO_CONTROL, *PSRB_IO_CONTROL;
  155.    // Define global buffers.
  156. BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
  157. char *ConvertToString (DWORD diskdata [256],
  158.                int firstIndex,
  159.                int lastIndex,
  160.                char* buf);
  161. void PrintIdeInfo (int drive, DWORD diskdata [256]);
  162. BOOL DoIDENTIFY (HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS, BYTE, BYTE,
  163.                  PDWORD);
  164.    //  Max number of drives assuming primary/secondary, master/slave topology
  165. #define  MAX_IDE_DRIVES  16
  166. int ReadPhysicalDriveInNTWithAdminRights (void)
  167. {
  168.    int done = FALSE;
  169.    int drive = 0;
  170.    for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
  171.    {
  172.       HANDLE hPhysicalDriveIOCTL = 0;
  173.          //  Try to get a handle to PhysicalDrive IOCTL, report failure
  174.          //  and exit if can't.
  175.       char driveName [256];
  176.       sprintf (driveName, ".//PhysicalDrive%d", drive);
  177.          //  Windows NT, Windows 2000, must have admin rights
  178.       hPhysicalDriveIOCTL = CreateFile (driveName,
  179.                                GENERIC_READ | GENERIC_WRITE, 
  180.                                FILE_SHARE_READ | FILE_SHARE_WRITE , NULL,
  181.                                OPEN_EXISTING, 0, NULL);
  182.       // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
  183.       //    printf ("Unable to open physical drive %d, error code: 0x%lX/n",
  184.       //            drive, GetLastError ());
  185.       if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
  186.       {
  187. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  188.          if (PRINT_DEBUG) 
  189.              printf ("/n%d ReadPhysicalDriveInNTWithAdminRights ERROR"
  190.                      "/nCreateFile(%s) returned INVALID_HANDLE_VALUE/n",
  191.                      __LINE__, driveName);
  192. #endif
  193.       }
  194.       else
  195.       {
  196.          GETVERSIONOUTPARAMS VersionParams;
  197.          DWORD               cbBytesReturned = 0;
  198.             // Get the version, etc of PhysicalDrive IOCTL
  199.          memset ((void*) &VersionParams, 0, sizeof(VersionParams));
  200.          if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
  201.                    NULL, 
  202.                    0,
  203.                    &VersionParams,
  204.                    sizeof(VersionParams),
  205.                    &cbBytesReturned, NULL) )
  206.          {         
  207. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  208.             if (PRINT_DEBUG)
  209.             {
  210.                DWORD err = GetLastError ();
  211.                printf ("/n%d ReadPhysicalDriveInNTWithAdminRights ERROR"
  212.                        "/nDeviceIoControl(%d, DFP_GET_VERSION) returned 0, error is %d/n",
  213.                        __LINE__, (int) hPhysicalDriveIOCTL, (int) err);
  214.             }
  215. #endif
  216.          }
  217.             // If there is a IDE device at number "i" issue commands
  218.             // to the device
  219.          if (VersionParams.bIDEDeviceMap <= 0)
  220.          {
  221. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  222.             if (PRINT_DEBUG)
  223.                 printf ("/n%d ReadPhysicalDriveInNTWithAdminRights ERROR"
  224.                         "/nNo device found at position %d (%d)/n",
  225.                         __LINE__, (int) drive, (int) VersionParams.bIDEDeviceMap);
  226. #endif
  227.          }
  228.          else
  229.          {
  230.             BYTE             bIDCmd = 0;   // IDE or ATAPI IDENTIFY cmd
  231.             SENDCMDINPARAMS  scip;
  232.             //SENDCMDOUTPARAMS OutCmd;
  233.                // Now, get the ID sector for all IDE devices in the system.
  234.                // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
  235.                // otherwise use the IDE_ATA_IDENTIFY command
  236.             bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? /
  237.                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
  238.             memset (&scip, 0, sizeof(scip));
  239.             memset (IdOutCmd, 0, sizeof(IdOutCmd));
  240.             if ( DoIDENTIFY (hPhysicalDriveIOCTL, 
  241.                        &scip, 
  242.                        (PSENDCMDOUTPARAMS)&IdOutCmd, 
  243.                        (BYTE) bIDCmd,
  244.                        (BYTE) drive,
  245.                        &cbBytesReturned))
  246.             {
  247.                DWORD diskdata [256];
  248.                int ijk = 0;
  249.                USHORT *pIdSector = (USHORT *)
  250.                              ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
  251.                for (ijk = 0; ijk < 256; ijk++)
  252.                   diskdata [ijk] = pIdSector [ijk];
  253.                PrintIdeInfo (drive, diskdata);
  254.                done = TRUE;
  255.             }
  256.         }
  257.          CloseHandle (hPhysicalDriveIOCTL);
  258.       }
  259.    }
  260.    return done;
  261. }
  262. //
  263. // IDENTIFY data (from ATAPI driver source)
  264. //
  265. #pragma pack(1)
  266. typedef struct _IDENTIFY_DATA {
  267.     USHORT GeneralConfiguration;            // 00 00
  268.     USHORT NumberOfCylinders;               // 02  1
  269.     USHORT Reserved1;                       // 04  2
  270.     USHORT NumberOfHeads;                   // 06  3
  271.     USHORT UnformattedBytesPerTrack;        // 08  4
  272.     USHORT UnformattedBytesPerSector;       // 0A  5
  273.     USHORT SectorsPerTrack;                 // 0C  6
  274.     USHORT VendorUnique1[3];                // 0E  7-9
  275.     USHORT SerialNumber[10];                // 14  10-19
  276.     USHORT BufferType;                      // 28  20
  277.     USHORT BufferSectorSize;                // 2A  21
  278.     USHORT NumberOfEccBytes;                // 2C  22
  279.     USHORT FirmwareRevision[4];             // 2E  23-26
  280.     USHORT ModelNumber[20];                 // 36  27-46
  281.     UCHAR  MaximumBlockTransfer;            // 5E  47
  282.     UCHAR  VendorUnique2;                   // 5F
  283.     USHORT DoubleWordIo;                    // 60  48
  284.     USHORT Capabilities;                    // 62  49
  285.     USHORT Reserved2;                       // 64  50
  286.     UCHAR  VendorUnique3;                   // 66  51
  287.     UCHAR  PioCycleTimingMode;              // 67
  288.     UCHAR  VendorUnique4;                   // 68  52
  289.     UCHAR  DmaCycleTimingMode;              // 69
  290.     USHORT TranslationFieldsValid:1;        // 6A  53
  291.     USHORT Reserved3:15;
  292.     USHORT NumberOfCurrentCylinders;        // 6C  54
  293.     USHORT NumberOfCurrentHeads;            // 6E  55
  294.     USHORT CurrentSectorsPerTrack;          // 70  56
  295.     ULONG  CurrentSectorCapacity;           // 72  57-58
  296.     USHORT CurrentMultiSectorSetting;       //     59
  297.     ULONG  UserAddressableSectors;          //     60-61
  298.     USHORT SingleWordDMASupport : 8;        //     62
  299.     USHORT SingleWordDMAActive : 8;
  300.     USHORT MultiWordDMASupport : 8;         //     63
  301.     USHORT MultiWordDMAActive : 8;
  302.     USHORT AdvancedPIOModes : 8;            //     64
  303.     USHORT Reserved4 : 8;
  304.     USHORT MinimumMWXferCycleTime;          //     65
  305.     USHORT RecommendedMWXferCycleTime;      //     66
  306.     USHORT MinimumPIOCycleTime;             //     67
  307.     USHORT MinimumPIOCycleTimeIORDY;        //     68
  308.     USHORT Reserved5[2];                    //     69-70
  309.     USHORT ReleaseTimeOverlapped;           //     71
  310.     USHORT ReleaseTimeServiceCommand;       //     72
  311.     USHORT MajorRevision;                   //     73
  312.     USHORT MinorRevision;                   //     74
  313.     USHORT Reserved6[50];                   //     75-126
  314.     USHORT SpecialFunctionsEnabled;         //     127
  315.     USHORT Reserved7[128];                  //     128-255
  316. } IDENTIFY_DATA, *PIDENTIFY_DATA;
  317. #pragma pack()
  318. int ReadPhysicalDriveInNTUsingSmart (void)
  319. {
  320.    int done = FALSE;
  321.    int drive = 0;
  322.    for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
  323.    {
  324.       HANDLE hPhysicalDriveIOCTL = 0;
  325.          //  Try to get a handle to PhysicalDrive IOCTL, report failure
  326.          //  and exit if can't.
  327.       char driveName [256];
  328.       sprintf (driveName, ".//PhysicalDrive%d", drive);
  329.          //  Windows NT, Windows 2000, Windows Server 2003, Vista
  330.       hPhysicalDriveIOCTL = CreateFile (driveName,
  331.                                GENERIC_READ | GENERIC_WRITE, 
  332.                                FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
  333.                                NULL, OPEN_EXISTING, 0, NULL);
  334.       // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
  335.       //    printf ("Unable to open physical drive %d, error code: 0x%lX/n",
  336.       //            drive, GetLastError ());
  337.       if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
  338.       {
  339. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  340.          if (PRINT_DEBUG) 
  341.              printf ("/n%d ReadPhysicalDriveInNTUsingSmart ERROR"
  342.                      "/nCreateFile(%s) returned INVALID_HANDLE_VALUE/n"
  343.                      "Error Code %d/n",
  344.                      __LINE__, driveName, GetLastError ());
  345. #endif
  346.       }
  347.       else
  348.       {
  349.          GETVERSIONINPARAMS GetVersionParams;
  350.          DWORD cbBytesReturned = 0;
  351.             // Get the version, etc of PhysicalDrive IOCTL
  352.          memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));
  353.          if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION,
  354.                    NULL, 
  355.                    0,
  356.                    &GetVersionParams, sizeof (GETVERSIONINPARAMS),
  357.                    &cbBytesReturned, NULL) )
  358.          {         
  359. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  360.             if (PRINT_DEBUG)
  361.             {
  362.                DWORD err = GetLastError ();
  363.                printf ("/n%d ReadPhysicalDriveInNTUsingSmart ERROR"
  364.                        "/nDeviceIoControl(%d, SMART_GET_VERSION) returned 0, error is %d/n",
  365.                        __LINE__, (int) hPhysicalDriveIOCTL, (int) err);
  366.             }
  367. #endif
  368.          }
  369.          else
  370.          {
  371.                 // Print the SMART version
  372.             // PrintVersion (& GetVersionParams);
  373.                // Allocate the command buffer
  374.             ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
  375.             PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);
  376.                // Retrieve the IDENTIFY data
  377.                // Prepare the command
  378. #define ID_CMD          0xEC            // Returns ID sector for ATA
  379.             Command -> irDriveRegs.bCommandReg = ID_CMD;
  380.             DWORD BytesReturned = 0;
  381.             if ( ! DeviceIoControl (hPhysicalDriveIOCTL, 
  382.                                     SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),
  383.                                     Command, CommandSize,
  384.                                     &BytesReturned, NULL) )
  385.             {
  386.                    // Print the error
  387.                 //PrintError ("SMART_RCV_DRIVE_DATA IOCTL", GetLastError());
  388.             } 
  389.             else
  390.             {
  391.                    // Print the IDENTIFY data
  392.                 DWORD diskdata [256];
  393.                 USHORT *pIdSector = (USHORT *)
  394.                              (PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) Command) -> bBuffer;
  395.                 for (int ijk = 0; ijk < 256; ijk++)
  396.                    diskdata [ijk] = pIdSector [ijk];
  397.                 PrintIdeInfo (drive, diskdata);
  398.                 done = TRUE;
  399.             }
  400.                // Done
  401.             CloseHandle (hPhysicalDriveIOCTL);
  402.             free (Command);
  403.          }
  404.       }
  405.    }
  406.    return done;
  407. }
  408. //  Required to ensure correct PhysicalDrive IOCTL structure setup
  409. #pragma pack(4)
  410. //
  411. // IOCTL_STORAGE_QUERY_PROPERTY
  412. //
  413. // Input Buffer:
  414. //      a STORAGE_PROPERTY_QUERY structure which describes what type of query
  415. //      is being done, what property is being queried for, and any additional
  416. //      parameters which a particular property query requires.
  417. //
  418. //  Output Buffer:
  419. //      Contains a buffer to place the results of the query into.  Since all
  420. //      property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER,
  421. //      the IOCTL can be called once with a small buffer then again using
  422. //      a buffer as large as the header reports is necessary.
  423. //
  424. //
  425. // Types of queries
  426. //
  427. typedef enum _STORAGE_QUERY_TYPE {
  428.     PropertyStandardQuery = 0,          // Retrieves the descriptor
  429.     PropertyExistsQuery,                // Used to test whether the descriptor is supported
  430.     PropertyMaskQuery,                  // Used to retrieve a mask of writeable fields in the descriptor
  431.     PropertyQueryMaxDefined     // use to validate the value
  432. } STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
  433. //
  434. // define some initial property id's
  435. //
  436. typedef enum _STORAGE_PROPERTY_ID {
  437.     StorageDeviceProperty = 0,
  438.     StorageAdapterProperty
  439. } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
  440. //
  441. // Query structure - additional parameters for specific queries can follow
  442. // the header
  443. //
  444. typedef struct _STORAGE_PROPERTY_QUERY {
  445.     //
  446.     // ID of the property being retrieved
  447.     //
  448.     STORAGE_PROPERTY_ID PropertyId;
  449.     //
  450.     // Flags indicating the type of query being performed
  451.     //
  452.     STORAGE_QUERY_TYPE QueryType;
  453.     //
  454.     // Space for additional parameters if necessary
  455.     //
  456.     UCHAR AdditionalParameters[1];
  457. } STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
  458. #define IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
  459. //
  460. // Device property descriptor - this is really just a rehash of the inquiry
  461. // data retrieved from a scsi device
  462. //
  463. // This may only be retrieved from a target device.  Sending this to the bus
  464. // will result in an error
  465. //
  466. #pragma pack(4)
  467. typedef struct _STORAGE_DEVICE_DESCRIPTOR {
  468.     //
  469.     // Sizeof(STORAGE_DEVICE_DESCRIPTOR)
  470.     //
  471.     ULONG Version;
  472.     //
  473.     // Total size of the descriptor, including the space for additional
  474.     // data and id strings
  475.     //
  476.     ULONG Size;
  477.     //
  478.     // The SCSI-2 device type
  479.     //
  480.     UCHAR DeviceType;
  481.     //
  482.     // The SCSI-2 device type modifier (if any) - this may be zero
  483.     //
  484.     UCHAR DeviceTypeModifier;
  485.     //
  486.     // Flag indicating whether the device's media (if any) is removable.  This
  487.     // field should be ignored for media-less devices
  488.     //
  489.     BOOLEAN RemovableMedia;
  490.     //
  491.     // Flag indicating whether the device can support mulitple outstanding
  492.     // commands.  The actual synchronization in this case is the responsibility
  493.     // of the port driver.
  494.     //
  495.     BOOLEAN CommandQueueing;
  496.     //
  497.     // Byte offset to the zero-terminated ascii string containing the device's
  498.     // vendor id string.  For devices with no such ID this will be zero
  499.     //
  500.     ULONG VendorIdOffset;
  501.     //
  502.     // Byte offset to the zero-terminated ascii string containing the device's
  503.     // product id string.  For devices with no such ID this will be zero
  504.     //
  505.     ULONG ProductIdOffset;
  506.     //
  507.     // Byte offset to the zero-terminated ascii string containing the device's
  508.     // product revision string.  For devices with no such string this will be
  509.     // zero
  510.     //
  511.     ULONG ProductRevisionOffset;
  512.     //
  513.     // Byte offset to the zero-terminated ascii string containing the device's
  514.     // serial number.  For devices with no serial number this will be zero
  515.     //
  516.     ULONG SerialNumberOffset;
  517.     //
  518.     // Contains the bus type (as defined above) of the device.  It should be
  519.     // used to interpret the raw device properties at the end of this structure
  520.     // (if any)
  521.     //
  522.     STORAGE_BUS_TYPE BusType;
  523.     //
  524.     // The number of bytes of bus-specific data which have been appended to
  525.     // this descriptor
  526.     //
  527.     ULONG RawPropertiesLength;
  528.     //
  529.     // Place holder for the first byte of the bus specific property data
  530.     //
  531.     UCHAR RawDeviceProperties[1];
  532. } STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
  533.     //  function to decode the serial numbers of IDE hard drives
  534.     //  using the IOCTL_STORAGE_QUERY_PROPERTY command 
  535. char * flipAndCodeBytes (const char * str,
  536.              int pos,
  537.              int flip,
  538.              char * buf)
  539. {
  540.    int i;
  541.    int j = 0;
  542.    int k = 0;
  543.    buf [0] = '/0';
  544.    if (pos <= 0)
  545.       return buf;
  546.    if ( ! j)
  547.    {
  548.       char p = 0;
  549.       // First try to gather all characters representing hex digits only.
  550.       j = 1;
  551.       k = 0;
  552.       buf[k] = 0;
  553.       for (i = pos; j && str[i] != '/0'; ++i)
  554.       {
  555.      char c = tolower(str[i]);
  556.      if (isspace(c))
  557.         c = '0';
  558.      ++p;
  559.      buf[k] <<= 4;
  560.      if (c >= '0' && c <= '9')
  561.         buf[k] |= (unsigned char) (c - '0');
  562.      else if (c >= 'a' && c <= 'f')
  563.         buf[k] |= (unsigned char) (c - 'a' + 10);
  564.      else
  565.      {
  566.         j = 0;
  567.         break;
  568.      }
  569.      if (p == 2)
  570.      {
  571.         if (buf[k] != '/0' && ! isprint(buf[k]))
  572.         {
  573.            j = 0;
  574.            break;
  575.         }
  576.         ++k;
  577.         p = 0;
  578.         buf[k] = 0;
  579.      }
  580.       }
  581.    }
  582.    if ( ! j)
  583.    {
  584.       // There are non-digit characters, gather them as is.
  585.       j = 1;
  586.       k = 0;
  587.       for (i = pos; j && str[i] != '/0'; ++i)
  588.       {
  589.          char c = str[i];
  590.          if ( ! isprint(c))
  591.          {
  592.             j = 0;
  593.             break;
  594.          }
  595.          buf[k++] = c;
  596.       }
  597.    }
  598.    if ( ! j)
  599.    {
  600.       // The characters are not there or are not printable.
  601.       k = 0;
  602.    }
  603.    buf[k] = '/0';
  604.    if (flip)
  605.       // Flip adjacent characters
  606.       for (j = 0; j < k; j += 2)
  607.       {
  608.          char t = buf[j];
  609.          buf[j] = buf[j + 1];
  610.          buf[j + 1] = t;
  611.       }
  612.    // Trim any beginning and end space
  613.    i = j = -1;
  614.    for (k = 0; buf[k] != '/0'; ++k)
  615.    {
  616.       if (! isspace(buf[k]))
  617.       {
  618.          if (i < 0)
  619.             i = k;
  620.          j = k;
  621.       }
  622.    }
  623.    if ((i >= 0) && (j >= 0))
  624.    {
  625.       for (k = i; (k <= j) && (buf[k] != '/0'); ++k)
  626.          buf[k - i] = buf[k];
  627.       buf[k - i] = '/0';
  628.    }
  629.    return buf;
  630. }
  631. #define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)
  632. typedef struct _DISK_GEOMETRY_EX {
  633.   DISK_GEOMETRY  Geometry;
  634.   LARGE_INTEGER  DiskSize;
  635.   UCHAR  Data[1];
  636. } DISK_GEOMETRY_EX, *PDISK_GEOMETRY_EX;
  637. int ReadPhysicalDriveInNTWithZeroRights (void)
  638. {
  639.    int done = FALSE;
  640.    int drive = 0;
  641.    for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
  642.    {
  643.       HANDLE hPhysicalDriveIOCTL = 0;
  644.          //  Try to get a handle to PhysicalDrive IOCTL, report failure
  645.          //  and exit if can't.
  646.       char driveName [256];
  647.       sprintf (driveName, ".//PhysicalDrive%d", drive);
  648.          //  Windows NT, Windows 2000, Windows XP - admin rights not required
  649.       hPhysicalDriveIOCTL = CreateFile (driveName, 0,
  650.                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  651.                                OPEN_EXISTING, 0, NULL);
  652.       if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
  653.       {
  654. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  655.          if (PRINT_DEBUG)
  656.              printf ("/n%d ReadPhysicalDriveInNTWithZeroRights ERROR"
  657.                      "/nCreateFile(%s) returned INVALID_HANDLE_VALUE/n",
  658.                      __LINE__, driveName);
  659. #endif
  660.       }
  661.       else
  662.       {
  663.          STORAGE_PROPERTY_QUERY query;
  664.          DWORD cbBytesReturned = 0;
  665.          char buffer [10000];
  666.          memset ((void *) & query, 0, sizeof (query));
  667.          query.PropertyId = StorageDeviceProperty;
  668.          query.QueryType = PropertyStandardQuery;
  669.          memset (buffer, 0, sizeof (buffer));
  670.          if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
  671.                    & query,
  672.                    sizeof (query),
  673.                    & buffer,
  674.                    sizeof (buffer),
  675.                    & cbBytesReturned, NULL) )
  676.          {         
  677.              STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer;
  678.              char serialNumber [1000];
  679.              char modelNumber [1000];
  680.              char vendorId [1000];
  681.              char productRevision [1000];
  682. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  683.              if (PRINT_DEBUG)
  684.              {
  685.                  printf ("/n%d STORAGE_DEVICE_DESCRIPTOR contents for drive %d/n"
  686.                          "                Version: %ld/n"
  687.                          "                   Size: %ld/n"
  688.                          "             DeviceType: %02x/n"
  689.                          "     DeviceTypeModifier: %02x/n"
  690.                          "         RemovableMedia: %d/n"
  691.                          "        CommandQueueing: %d/n"
  692.                          "         VendorIdOffset: %4ld (0x%02lx)/n"
  693.                          "        ProductIdOffset: %4ld (0x%02lx)/n"
  694.                          "  ProductRevisionOffset: %4ld (0x%02lx)/n"
  695.                          "     SerialNumberOffset: %4ld (0x%02lx)/n"
  696.                          "                BusType: %d/n"
  697.                          "    RawPropertiesLength: %ld/n",
  698.                          __LINE__, drive,
  699.                          (unsigned long) descrip->Version,
  700.                          (unsigned long) descrip->Size,
  701.                          (int) descrip->DeviceType,
  702.                          (int) descrip->DeviceTypeModifier,
  703.                          (int) descrip->RemovableMedia,
  704.                          (int) descrip->CommandQueueing,
  705.                          (unsigned long) descrip->VendorIdOffset,
  706.                          (unsigned long) descrip->VendorIdOffset,
  707.                          (unsigned long) descrip->ProductIdOffset,
  708.                          (unsigned long) descrip->ProductIdOffset,
  709.                          (unsigned long) descrip->ProductRevisionOffset,
  710.                          (unsigned long) descrip->ProductRevisionOffset,
  711.                          (unsigned long) descrip->SerialNumberOffset,
  712.                          (unsigned long) descrip->SerialNumberOffset,
  713.                          (int) descrip->BusType,
  714.                          (unsigned long) descrip->RawPropertiesLength);
  715.                 dump_buffer ("Contents of RawDeviceProperties",
  716.                              (unsigned char*) descrip->RawDeviceProperties,
  717.                              descrip->RawPropertiesLength);
  718.                 dump_buffer ("Contents of first 256 bytes in buffer",
  719.                              (unsigned char*) buffer, 256);
  720.              }
  721. #endif
  722.              flipAndCodeBytes (buffer,
  723.                                descrip -> VendorIdOffset,
  724.                                0, vendorId );
  725.              flipAndCodeBytes (buffer,
  726.                                descrip -> ProductIdOffset,
  727.                                0, modelNumber );
  728.              flipAndCodeBytes (buffer,
  729.                                descrip -> ProductRevisionOffset,
  730.                                0, productRevision );
  731.              flipAndCodeBytes (buffer,
  732.                                descrip -> SerialNumberOffset,
  733.                                1, serialNumber );
  734.              if (0 == HardDriveSerialNumber [0] &
  735.                         //  serial number must be alphanumeric
  736.                         //  (but there can be leading spaces on IBM drives)
  737.                    (isalnum (serialNumber [0]) || isalnum (serialNumber [19])))
  738.              {
  739.                 strcpy (HardDriveSerialNumber, serialNumber);
  740.                 strcpy (HardDriveModelNumber, modelNumber);
  741.                 done = TRUE;
  742.              }
  743. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  744.              printf ("/n**** STORAGE_DEVICE_DESCRIPTOR for drive %d ****/n"
  745.                      "Vendor Id = [%s]/n"
  746.                      "Product Id = [%s]/n"
  747.                      "Product Revision = [%s]/n"
  748.                      "Serial Number = [%s]/n",
  749.                      drive,
  750.                      vendorId,
  751.                      modelNumber,
  752.                      productRevision,
  753.                      serialNumber);
  754. #endif
  755.                // Get the disk drive geometry.
  756.              memset (buffer, 0, sizeof(buffer));
  757.              if ( ! DeviceIoControl (hPhysicalDriveIOCTL,
  758.                       IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
  759.                       NULL,
  760.                       0,
  761.                       &buffer,
  762.                       sizeof(buffer),
  763.                       &cbBytesReturned,
  764.                       NULL))
  765.              {
  766. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  767.                 if (PRINT_DEBUG)
  768.                    printf ("/n%d ReadPhysicalDriveInNTWithZeroRights ERROR"
  769.                            "|nDeviceIoControl(%s, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) returned 0",
  770.                            driveName);
  771. #endif
  772.              }
  773.              else
  774.              {         
  775.                 DISK_GEOMETRY_EX* geom = (DISK_GEOMETRY_EX*) &buffer;
  776.                 int fixed = (geom->Geometry.MediaType == FixedMedia);
  777.                 __int64 size = geom->DiskSize.QuadPart;
  778.                      
  779. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  780.                 printf ("/n**** DISK_GEOMETRY_EX for drive %d ****/n"
  781.                         "Disk is%s fixed/n"
  782.                         "DiskSize = %I64d/n",
  783.                         drive,
  784.                         fixed ? "" : " NOT",
  785.                         size);
  786. #endif
  787.             }
  788.          }
  789.          else
  790.          {
  791.              DWORD err = GetLastError ();
  792. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  793.              printf ("/nDeviceIOControl IOCTL_STORAGE_QUERY_PROPERTY error = %d/n", err);
  794. #endif
  795.          }
  796.          CloseHandle (hPhysicalDriveIOCTL);
  797.       }
  798.    }
  799.    return done;
  800. }
  801.    // DoIDENTIFY
  802.    // FUNCTION: Send an IDENTIFY command to the drive
  803.    // bDriveNum = 0-3
  804.    // bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY
  805. BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
  806.                  PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
  807.                  PDWORD lpcbBytesReturned)
  808. {
  809.       // Set up data structures for IDENTIFY command.
  810.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  811.    pSCIP -> irDriveRegs.bFeaturesReg = 0;
  812.    pSCIP -> irDriveRegs.bSectorCountReg = 1;
  813.    //pSCIP -> irDriveRegs.bSectorNumberReg = 1;
  814.    pSCIP -> irDriveRegs.bCylLowReg = 0;
  815.    pSCIP -> irDriveRegs.bCylHighReg = 0;
  816.       // Compute the drive number.
  817.    pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
  818.       // The command can either be IDE identify or ATAPI identify.
  819.    pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
  820.    pSCIP -> bDriveNumber = bDriveNum;
  821.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  822.    return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,
  823.                (LPVOID) pSCIP,
  824.                sizeof(SENDCMDINPARAMS) - 1,
  825.                (LPVOID) pSCOP,
  826.                sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
  827.                lpcbBytesReturned, NULL) );
  828. }
  829. //  ---------------------------------------------------
  830.    // (* Output Bbuffer for the VxD (rt_IdeDinfo record) *)
  831. typedef struct _rt_IdeDInfo_
  832. {
  833.     BYTE IDEExists[4];
  834.     BYTE DiskExists[8];
  835.     WORD DisksRawInfo[8*256];
  836. } rt_IdeDInfo, *pt_IdeDInfo;
  837.    // (* IdeDinfo "data fields" *)
  838. typedef struct _rt_DiskInfo_
  839. {
  840.    BOOL DiskExists;
  841.    BOOL ATAdevice;
  842.    BOOL RemovableDevice;
  843.    WORD TotLogCyl;
  844.    WORD TotLogHeads;
  845.    WORD TotLogSPT;
  846.    char SerialNumber[20];
  847.    char FirmwareRevision[8];
  848.    char ModelNumber[40];
  849.    WORD CurLogCyl;
  850.    WORD CurLogHeads;
  851.    WORD CurLogSPT;
  852. } rt_DiskInfo;
  853. #define  m_cVxDFunctionIdesDInfo  1
  854. //  ---------------------------------------------------
  855. int ReadDrivePortsInWin9X (void)
  856. {
  857.    int done = FALSE;
  858.    unsigned long int i = 0;
  859.    HANDLE VxDHandle = 0;
  860.    pt_IdeDInfo pOutBufVxD = 0;
  861.    DWORD lpBytesReturned = 0;
  862.         //  set the thread priority high so that we get exclusive access to the disk
  863.    BOOL status =
  864.         // SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  865.         SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS);
  866.         // SetPriorityClass (GetCurrentProcess (), HIGH_PRIORITY_CLASS);
  867. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  868.    if (0 == status) 
  869.        // printf ("/nERROR: Could not SetThreadPriority, LastError: %d/n", GetLastError ());
  870.        printf ("/nERROR: Could not SetPriorityClass, LastError: %d/n", GetLastError ());
  871. #endif
  872.       // 1. Make an output buffer for the VxD
  873.    rt_IdeDInfo info;
  874.    pOutBufVxD = &info;
  875.       // *****************
  876.       // KLUDGE WARNING!!!
  877.       // HAVE to zero out the buffer space for the IDE information!
  878.       // If this is NOT done then garbage could be in the memory
  879.       // locations indicating if a disk exists or not.
  880.    ZeroMemory (&info, sizeof(info));
  881.       // 1. Try to load the VxD
  882.        //  must use the short file name path to open a VXD file
  883.    //char StartupDirectory [2048];
  884.    //char shortFileNamePath [2048];
  885.    //char *p = NULL;
  886.    //char vxd [2048];
  887.       //  get the directory that the exe was started from
  888.    //GetModuleFileName (hInst, (LPSTR) StartupDirectory, sizeof (StartupDirectory));
  889.       //  cut the exe name from string
  890.    //p = &(StartupDirectory [strlen (StartupDirectory) - 1]);
  891.    //while (p >= StartupDirectory && *p && '//' != *p) p--;
  892.    //*p = '/0';   
  893.    //GetShortPathName (StartupDirectory, shortFileNamePath, 2048);
  894.    //sprintf (vxd, ".//%s//IDE21201.VXD", shortFileNamePath);
  895.    //VxDHandle = CreateFile (vxd, 0, 0, 0,
  896.    //               0, FILE_FLAG_DELETE_ON_CLOSE, 0);   
  897.    VxDHandle = CreateFile (".//IDE21201.VXD", 0, 0, 0,
  898.                             0, FILE_FLAG_DELETE_ON_CLOSE, 0);
  899.    if (VxDHandle != INVALID_HANDLE_VALUE)
  900.    {
  901.          // 2. Run VxD function
  902.       DeviceIoControl (VxDHandle, m_cVxDFunctionIdesDInfo,
  903.                     0, 0, pOutBufVxD, sizeof(pt_IdeDInfo), &lpBytesReturned, 0);
  904.          // 3. Unload VxD
  905.       CloseHandle (VxDHandle);
  906.    }
  907.    else
  908.         MessageBox (NULL, "ERROR: Could not open IDE21201.VXD file"
  909.                     TITLE, MB_ICONSTOP);
  910.       // 4. Translate and store data
  911.    for (i=0; i<8; i++)
  912.    {
  913.       if((pOutBufVxD->DiskExists[i]) && (pOutBufVxD->IDEExists[i/2]))
  914.       {
  915.             DWORD diskinfo [256];
  916.             for (int j = 0; j < 256; j++) 
  917.                 diskinfo [j] = pOutBufVxD -> DisksRawInfo [i * 256 + j];
  918.             // process the information for this buffer
  919.            PrintIdeInfo (i, diskinfo);
  920.             done = TRUE;
  921.       }
  922.    }
  923.         //  reset the thread priority back to normal
  924.    // SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  925.    SetPriorityClass (GetCurrentProcess (), NORMAL_PRIORITY_CLASS);
  926.    return done;
  927. }
  928. #define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
  929. int ReadIdeDriveAsScsiDriveInNT (void)
  930. {
  931.    int done = FALSE;
  932.    int controller = 0;
  933.    for (controller = 0; controller < 16; controller++)
  934.    {
  935.       HANDLE hScsiDriveIOCTL = 0;
  936.       char   driveName [256];
  937.          //  Try to get a handle to PhysicalDrive IOCTL, report failure
  938.          //  and exit if can't.
  939.       sprintf (driveName, ".//Scsi%d:", controller);
  940.          //  Windows NT, Windows 2000, any rights should do
  941.       hScsiDriveIOCTL = CreateFile (driveName,
  942.                                GENERIC_READ | GENERIC_WRITE, 
  943.                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  944.                                OPEN_EXISTING, 0, NULL);
  945.       // if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE)
  946.       //    printf ("Unable to open SCSI controller %d, error code: 0x%lX/n",
  947.       //            controller, GetLastError ());
  948.       if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
  949.       {
  950.          int drive = 0;
  951.          for (drive = 0; drive < 2; drive++)
  952.          {
  953.             char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
  954.             SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
  955.             SENDCMDINPARAMS *pin =
  956.                    (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
  957.             DWORD dummy;
  958.    
  959.             memset (buffer, 0, sizeof (buffer));
  960.             p -> HeaderLength = sizeof (SRB_IO_CONTROL);
  961.             p -> Timeout = 10000;
  962.             p -> Length = SENDIDLENGTH;
  963.             p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
  964.             strncpy ((char *) p -> Signature, "SCSIDISK", 8);
  965.   
  966.             pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
  967.             pin -> bDriveNumber = drive;
  968.             if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, 
  969.                                  buffer,
  970.                                  sizeof (SRB_IO_CONTROL) +
  971.                                          sizeof (SENDCMDINPARAMS) - 1,
  972.                                  buffer,
  973.                                  sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
  974.                                  &dummy, NULL))
  975.             {
  976.                SENDCMDOUTPARAMS *pOut =
  977.                     (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
  978.                IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
  979.                if (pId -> sModelNumber [0])
  980.                {
  981.                   DWORD diskdata [256];
  982.                   int ijk = 0;
  983.                   USHORT *pIdSector = (USHORT *) pId;
  984.           
  985.                   for (ijk = 0; ijk < 256; ijk++)
  986.                      diskdata [ijk] = pIdSector [ijk];
  987.                   PrintIdeInfo (controller * 2 + drive, diskdata);
  988.                   done = TRUE;
  989.                }
  990.             }
  991.          }
  992.          CloseHandle (hScsiDriveIOCTL);
  993.       }
  994.    }
  995.    return done;
  996. }
  997. void PrintIdeInfo (int drive, DWORD diskdata [256])
  998. {
  999.    char serialNumber [1024];
  1000.    char modelNumber [1024];
  1001.    char revisionNumber [1024];
  1002.    char bufferSize [32];
  1003.    __int64 sectors = 0;
  1004.    __int64 bytes = 0;
  1005.       //  copy the hard drive serial number to the buffer
  1006.    ConvertToString (diskdata, 10, 19, serialNumber);
  1007.    ConvertToString (diskdata, 27, 46, modelNumber);
  1008.    ConvertToString (diskdata, 23, 26, revisionNumber);
  1009.    sprintf (bufferSize, "%u", diskdata [21] * 512);
  1010.    if (0 == HardDriveSerialNumber [0] &
  1011.        //  serial number must be alphanumeric
  1012.        //  (but there can be leading spaces on IBM drives)
  1013.        (isalnum (serialNumber [0]) || isalnum (serialNumber [19])))
  1014.    {
  1015.       strcpy (HardDriveSerialNumber, serialNumber);
  1016.       strcpy (HardDriveModelNumber, modelNumber);
  1017.    }
  1018. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1019.    printf ("/nDrive %d - ", drive);
  1020.    switch (drive / 2)
  1021.    {
  1022.       case 0: printf ("Primary Controller - ");
  1023.               break;
  1024.       case 1: printf ("Secondary Controller - ");
  1025.               break;
  1026.       case 2: printf ("Tertiary Controller - ");
  1027.               break;
  1028.       case 3: printf ("Quaternary Controller - ");
  1029.               break;
  1030.    }
  1031.    switch (drive % 2)
  1032.    {
  1033.       case 0: printf (" - Master drive/n/n");
  1034.               break;
  1035.       case 1: printf (" - Slave drive/n/n");
  1036.               break;
  1037.    }
  1038.    printf ("Drive Model Number________________: [%s]/n",
  1039.            modelNumber);
  1040.    printf ("Drive Serial Number_______________: [%s]/n",
  1041.            serialNumber);
  1042.    printf ("Drive Controller Revision Number__: [%s]/n",
  1043.            revisionNumber);
  1044.    printf ("Controller Buffer Size on Drive___: %s bytes/n",
  1045.            bufferSize);
  1046.    printf ("Drive Type________________________: ");
  1047.    if (diskdata [0] & 0x0080)
  1048.       printf ("Removable/n");
  1049.    else if (diskdata [0] & 0x0040)
  1050.       printf ("Fixed/n");
  1051.    else printf ("Unknown/n");
  1052.            
  1053.         //  calculate size based on 28 bit or 48 bit addressing
  1054.         //  48 bit addressing is reflected by bit 10 of word 83
  1055.     if (diskdata [83] & 0x400) 
  1056.         sectors = diskdata [103] * 65536I64 * 65536I64 * 65536I64 + 
  1057.                     diskdata [102] * 65536I64 * 65536I64 + 
  1058.                     diskdata [101] * 65536I64 + 
  1059.                     diskdata [100];
  1060.     else
  1061.         sectors = diskdata [61] * 65536 + diskdata [60];
  1062.         //  there are 512 bytes in a sector
  1063.     bytes = sectors * 512;
  1064.     printf ("Drive Size________________________: %I64d bytes/n",
  1065.             bytes);
  1066. #endif  // PRINTING_TO_CONSOLE_ALLOWED
  1067.    char string1 [1000];
  1068.    sprintf (string1, "Drive%dModelNumber", drive);
  1069.    WriteConstantString (string1, modelNumber);
  1070.    sprintf (string1, "Drive%dSerialNumber", drive);
  1071.    WriteConstantString (string1, serialNumber);
  1072.    sprintf (string1, "Drive%dControllerRevisionNumber", drive);
  1073.    WriteConstantString (string1, revisionNumber);
  1074.    sprintf (string1, "Drive%dControllerBufferSize", drive);
  1075.    WriteConstantString (string1, bufferSize);
  1076.    sprintf (string1, "Drive%dType", drive);
  1077.    if (diskdata [0] & 0x0080)
  1078.       WriteConstantString (string1, "Removable");
  1079.    else if (diskdata [0] & 0x0040)
  1080.       WriteConstantString (string1, "Fixed");
  1081.    else
  1082.       WriteConstantString (string1, "Unknown");
  1083. }
  1084. char *ConvertToString (DWORD diskdata [256],
  1085.                int firstIndex,
  1086.                int lastIndex,
  1087.                char* buf)
  1088. {
  1089.    int index = 0;
  1090.    int position = 0;
  1091.       //  each integer has two characters stored in it backwards
  1092.    for (index = firstIndex; index <= lastIndex; index++)
  1093.    {
  1094.          //  get high byte for 1st character
  1095.       buf [position++] = (char) (diskdata [index] / 256);
  1096.          //  get low byte for 2nd character
  1097.       buf [position++] = (char) (diskdata [index] % 256);
  1098.    }
  1099.       //  end the string 
  1100.    buf[position] = '/0';
  1101.       //  cut off the trailing blanks
  1102.    for (index = position - 1; index > 0 && isspace(buf [index]); index--)
  1103.       buf [index] = '/0';
  1104.    return buf;
  1105. }
  1106. long getHardDriveComputerID ()
  1107. {
  1108.    int done = FALSE;
  1109.    // char string [1024];
  1110.    __int64 id = 0;
  1111.    OSVERSIONINFO version;
  1112.    strcpy (HardDriveSerialNumber, "");
  1113.    memset (&version, 0, sizeof (version));
  1114.    version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  1115.    GetVersionEx (&version);
  1116.    if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1117.     {
  1118.           //  this works under WinNT4 or Win2K if you have admin rights
  1119. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1120.         printf ("/nTrying to read the drive IDs using physical access with admin rights/n");
  1121. #endif
  1122.         done = ReadPhysicalDriveInNTWithAdminRights ();
  1123.             //  this should work in WinNT or Win2K if previous did not work
  1124.             //  this is kind of a backdoor via the SCSI mini port driver into
  1125.             //     the IDE drives
  1126. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1127.         printf ("/nTrying to read the drive IDs using the SCSI back door/n");
  1128. #endif
  1129.         // if ( ! done) 
  1130.             done = ReadIdeDriveAsScsiDriveInNT ();
  1131.           //  this works under WinNT4 or Win2K or WinXP if you have any rights
  1132. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1133.         printf ("/nTrying to read the drive IDs using physical access with zero rights/n");
  1134. #endif
  1135.         //if ( ! done)
  1136.             done = ReadPhysicalDriveInNTWithZeroRights ();
  1137.           //  this works under WinNT4 or Win2K or WinXP or Windows Server 2003 or Vista if you have any rights
  1138. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1139.         printf ("/nTrying to read the drive IDs using Smart/n");
  1140. #endif
  1141.         //if ( ! done)
  1142.             done = ReadPhysicalDriveInNTUsingSmart ();
  1143.    }
  1144.    else
  1145.    {
  1146.          //  this works under Win9X and calls a VXD
  1147.       int attempt = 0;
  1148.          //  try this up to 10 times to get a hard drive serial number
  1149.       for (attempt = 0;
  1150.            attempt < 10 && ! done && 0 == HardDriveSerialNumber [0];
  1151.            attempt++)
  1152.          done = ReadDrivePortsInWin9X ();
  1153.    }
  1154.    if (HardDriveSerialNumber [0] > 0)
  1155.    {
  1156.       char *p = HardDriveSerialNumber;
  1157.       WriteConstantString ("HardDriveSerialNumber", HardDriveSerialNumber);
  1158.          //  ignore first 5 characters from western digital hard drives if
  1159.          //  the first four characters are WD-W
  1160.       if ( ! strncmp (HardDriveSerialNumber, "WD-W", 4)) 
  1161.          p += 5;
  1162.       for ( ; p && *p; p++)
  1163.       {
  1164.          if ('-' == *p) 
  1165.             continue;
  1166.          id *= 10;
  1167.          switch (*p)
  1168.          {
  1169.             case '0': id += 0; break;
  1170.             case '1': id += 1; break;
  1171.             case '2': id += 2; break;
  1172.             case '3': id += 3; break;
  1173.             case '4': id += 4; break;
  1174.             case '5': id += 5; break;
  1175.             case '6': id += 6; break;
  1176.             case '7': id += 7; break;
  1177.             case '8': id += 8; break;
  1178.             case '9': id += 9; break;
  1179.             case 'a'case 'A': id += 10; break;
  1180.             case 'b'case 'B': id += 11; break;
  1181.             case 'c'case 'C': id += 12; break;
  1182.             case 'd'case 'D': id += 13; break;
  1183.             case 'e'case 'E': id += 14; break;
  1184.             case 'f'case 'F': id += 15; break;
  1185.             case 'g'case 'G': id += 16; break;
  1186.             case 'h'case 'H': id += 17; break;
  1187.             case 'i'case 'I': id += 18; break;
  1188.             case 'j'case 'J': id += 19; break;
  1189.             case 'k'case 'K': id += 20; break;
  1190.             case 'l'case 'L': id += 21; break;
  1191.             case 'm'case 'M': id += 22; break;
  1192.             case 'n'case 'N': id += 23; break;
  1193.             case 'o'case 'O': id += 24; break;
  1194.             case 'p'case 'P': id += 25; break;
  1195.             case 'q'case 'Q': id += 26; break;
  1196.             case 'r'case 'R': id += 27; break;
  1197.             case 's'case 'S': id += 28; break;
  1198.             case 't'case 'T': id += 29; break;
  1199.             case 'u'case 'U': id += 30; break;
  1200.             case 'v'case 'V': id += 31; break;
  1201.             case 'w'case 'W': id += 32; break;
  1202.             case 'x'case 'X': id += 33; break;
  1203.             case 'y'case 'Y': id += 34; break;
  1204.             case 'z'case 'Z': id += 35; break;
  1205.          }                            
  1206.       }
  1207.    }
  1208.    id %= 100000000;
  1209.    if (strstr (HardDriveModelNumber, "IBM-"))
  1210.       id += 300000000;
  1211.    else if (strstr (HardDriveModelNumber, "MAXTOR") ||
  1212.             strstr (HardDriveModelNumber, "Maxtor"))
  1213.       id += 400000000;
  1214.    else if (strstr (HardDriveModelNumber, "WDC "))
  1215.       id += 500000000;
  1216.    else
  1217.       id += 600000000;
  1218. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1219.    printf ("/nHard Drive Serial Number__________: %s/n"
  1220.            HardDriveSerialNumber);
  1221.    printf ("/nHard Drive Model Number___________: %s/n"
  1222.            HardDriveModelNumber);
  1223.    printf ("/nComputer ID_______________________: %I64d/n", id);
  1224. #endif
  1225.    return (long) id;
  1226. }
  1227. // GetMACAdapters.cpp : Defines the entry point for the console application.
  1228. //
  1229. // Author:  Khalid Shaikh [Shake@ShakeNet.com]
  1230. // Date:    April 5th, 2002
  1231. //
  1232. // This program fetches the MAC address of the localhost by fetching the 
  1233. // information through GetAdapatersInfo.  It does not rely on the NETBIOS
  1234. // protocol and the ethernet adapter need not be connect to a network.
  1235. //
  1236. // Supported in Windows NT/2000/XP
  1237. // Supported in Windows 95/98/Me
  1238. //
  1239. // Supports multiple NIC cards on a PC.
  1240. #include <Iphlpapi.h>
  1241. #include <Assert.h>
  1242. #pragma comment(lib, "iphlpapi.lib")
  1243. // Prints the MAC address stored in a 6 byte array to stdout
  1244. static void PrintMACaddress(unsigned char MACData[])
  1245. {
  1246. #ifdef PRINTING_TO_CONSOLE_ALLOWED
  1247.     printf("/nMAC Address: %02X-%02X-%02X-%02X-%02X-%02X/n"
  1248.         MACData[0], MACData[1], MACData[2], MACData[3], MACData[4], MACData[5]);
  1249. #endif
  1250.    char string [256];
  1251.    sprintf (string"%02X-%02X-%02X-%02X-%02X-%02X", MACData[0], MACData[1], 
  1252.                MACData[2], MACData[3], MACData[4], MACData[5]);
  1253.    WriteConstantString ("MACaddress"string);
  1254. }
  1255. // Fetches the MAC address and prints it
  1256. DWORD GetMACaddress(void)
  1257. {
  1258.   DWORD MACaddress = 0;
  1259.   IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information
  1260.                                          // for up to 16 NICs
  1261.   DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer
  1262.   DWORD dwStatus = GetAdaptersInfo(      // Call GetAdapterInfo
  1263.             AdapterInfo,                 // [out] buffer to receive data
  1264.             &dwBufLen);                  // [in] size of receive data buffer
  1265.   assert(dwStatus == ERROR_SUCCESS);  // Verify return value is
  1266.                                       // valid, no buffer overflow
  1267.   PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; // Contains pointer to
  1268.                                                // current adapter info
  1269.   do {
  1270.     if (MACaddress == 0)
  1271.         MACaddress = pAdapterInfo->Address [5] + pAdapterInfo->Address [4] * 256 + 
  1272.                     pAdapterInfo->Address [3] * 256 * 256 + 
  1273.                     pAdapterInfo->Address [2] * 256 * 256 * 256;
  1274.     PrintMACaddress(pAdapterInfo->Address); // Print MAC address
  1275.     pAdapterInfo = pAdapterInfo->Next;    // Progress through linked list
  1276.   }
  1277.   while(pAdapterInfo);                    // Terminate if last adapter
  1278.   
  1279.   return MACaddress;
  1280. }
  1281. static void dump_buffer (const char* title,
  1282.             const unsigned char* buffer,
  1283.             int len)
  1284. {
  1285.    int i = 0;
  1286.    int j;
  1287.    printf ("/n-- %s --/n", title);
  1288.    if (len > 0)
  1289.    {
  1290.       printf ("%8.8s "" ");
  1291.       for (j = 0; j < 16; ++j)
  1292.       {
  1293.         printf (" %2X", j);
  1294.       }
  1295.       printf ("  ");
  1296.       for (j = 0; j < 16; ++j)
  1297.       {
  1298.         printf ("%1X", j);
  1299.       }
  1300.       printf ("/n");
  1301.    }
  1302.    while (i < len)
  1303.    {
  1304.       printf("%08x ", i);
  1305.       for (j = 0; j < 16; ++j)
  1306.       {
  1307.      if ((i + j) < len)
  1308.         printf (" %02x", (int) buffer[i +j]);
  1309.      else
  1310.         printf ("   ");
  1311.       }
  1312.       printf ("  ");
  1313.       for (j = 0; j < 16; ++j)
  1314.       {
  1315.      if ((i + j) < len)
  1316.         printf ("%c", isprint (buffer[i + j]) ? buffer [i + j] : '.');
  1317.      else
  1318.         printf (" ");
  1319.       }
  1320.       printf ("/n");
  1321.       i += 16;
  1322.    }
  1323.    printf ("-- DONE --/n");
  1324. }
  1325. int main (int argc, char * argv [])
  1326. {
  1327.    printf ("To get all details use /"diskid32 /d/"/n");
  1328.    if (argc > 1 && strstr (argv [1], "/d"))
  1329.       PRINT_DEBUG = true;
  1330.    else
  1331.       PRINT_DEBUG = false;
  1332.       
  1333.    long id = getHardDriveComputerID ();
  1334.    GetMACaddress ();
  1335.    return 0;
  1336. }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值