www.pudn.com > disk_primary.rar > disk.h
//&/#define PRINTING_TO_CONSOLE_ALLOWED //#include#include // Required to ensure correct PhysicalDrive IOCTL structure setup //&/#pragma pack(1) // Max number of drives assuming primary/secondary, master/slave topology #define MAX_IDE_DRIVES 4 #define IDENTIFY_BUFFER_SIZE 512 // IOCTL commands #define DFP_GET_VERSION 0x00074080 #define DFP_SEND_DRIVE_COMMAND 0x0007c084 #define DFP_RECEIVE_DRIVE_DATA 0x0007c088 #define FILE_DEVICE_SCSI 0x0000001b #define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501) #define IOCTL_SCSI_MINIPORT 0x0004D008 // see NTDDSCSI.H for definition // GETVERSIONOUTPARAMS contains the data returned from the // Get Driver Version function. typedef struct _GETVERSIONOUTPARAMS { BYTE bVersion; // Binary driver version. BYTE bRevision; // Binary driver revision. BYTE bReserved; // Not used. BYTE bIDEDeviceMap; // Bit map of IDE devices. DWORD fCapabilities; // Bit mask of driver capabilities. DWORD dwReserved[4]; // For future use. } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS; // Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS #define CAP_IDE_ID_FUNCTION 1 // ATA ID command supported #define CAP_IDE_ATAPI_ID 2 // ATAPI ID command supported #define CAP_IDE_EXECUTE_SMART_FUNCTION 4 // SMART commannds supported // IDE registers typedef struct _IDEREGS { BYTE bFeaturesReg; // Used for specifying SMART "commands". BYTE bSectorCountReg; // IDE sector count register BYTE bSectorNumberReg; // IDE sector number register BYTE bCylLowReg; // IDE low order cylinder value BYTE bCylHighReg; // IDE high order cylinder value BYTE bDriveHeadReg; // IDE drive/head register BYTE bCommandReg; // Actual IDE command. BYTE bReserved; // reserved for future use. Must be zero. } IDEREGS, *PIDEREGS, *LPIDEREGS; // SENDCMDINPARAMS contains the input parameters for the // Send Command to Drive function. typedef struct _SENDCMDINPARAMS { DWORD cBufferSize; // Buffer size in bytes IDEREGS irDriveRegs; // Structure with drive register values. BYTE bDriveNumber; // Physical drive number to send // command to (0,1,2,3). BYTE bReserved[3]; // Reserved for future expansion. DWORD dwReserved[4]; // For future use. BYTE bBuffer[1]; // Input buffer. } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; // 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. // Status returned from driver typedef struct _DRIVERSTATUS { BYTE bDriverError; // Error code from driver, or 0 if no error. BYTE bIDEStatus; // Contents of IDE Error register. // Only valid when bDriverError is SMART_IDE_ERROR. BYTE bReserved[2]; // Reserved for future expansion. DWORD dwReserved[2]; // Reserved for future expansion. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; // Structure returned by PhysicalDrive IOCTL for several commands typedef struct _SENDCMDOUTPARAMS { DWORD cBufferSize; // Size of bBuffer in bytes DRIVERSTATUS DriverStatus; // Driver status structure. BYTE bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive. } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; // Define global buffers. BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1]; // DoIDENTIFY // FUNCTION: Send an IDENTIFY command to the drive // bDriveNum = 0-3 // bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, PDWORD lpcbBytesReturned) { // Set up data structures for IDENTIFY command. pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; pSCIP -> irDriveRegs.bFeaturesReg = 0; pSCIP -> irDriveRegs.bSectorCountReg = 1; pSCIP -> irDriveRegs.bSectorNumberReg = 1; pSCIP -> irDriveRegs.bCylLowReg = 0; pSCIP -> irDriveRegs.bCylHighReg = 0; // Compute the drive number. pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4); // The command can either be IDE identify or ATAPI identify. pSCIP -> irDriveRegs.bCommandReg = bIDCmd; pSCIP -> bDriveNumber = bDriveNum; pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA, (LPVOID) pSCIP, sizeof(SENDCMDINPARAMS) - 1, (LPVOID) pSCOP, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL) ); } int ReadPhysicalDriveInNT(int drive,DWORD diskdata[256]) //drive从0开始; { int done = FALSE; char driveName [256]; memset(driveName,0,256); driveName[ 0] = '\\'; driveName[ 1] = '\\'; driveName[ 2] = '.'; driveName[ 3] = '\\'; driveName[ 4] = 'P'; driveName[ 5] = 'h'; driveName[ 6] = 'y'; driveName[ 7] = 's'; driveName[ 8] = 'i'; driveName[ 9] = 'c'; driveName[10] = 'a'; driveName[11] = 'l'; driveName[12] = 'D'; driveName[13] = 'r'; driveName[14] = 'i'; driveName[15] = 'v'; driveName[16] = 'e'; driveName[17] = 0x30+drive; //&for (drive = 0; drive < MAX_IDE_DRIVES; drive++) //&{ //处理driveName; HANDLE hPhysicalDriveIOCTL = 0; // Try to get a handle to PhysicalDrive IOCTL, report failure // and exit if can't. //&controller for循环两次起点: //sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive); // Windows NT, Windows 2000, must have admin rights hPhysicalDriveIOCTL = CreateFile (driveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) // printf ("Unable to open physical drive %d, error code: 0x%lX\n", // drive, GetLastError ()); if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) { GETVERSIONOUTPARAMS VersionParams; DWORD cbBytesReturned = 0; // Get the version, etc of PhysicalDrive IOCTL memset ((void*) &VersionParams, 0, sizeof(VersionParams)); if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof(VersionParams), &cbBytesReturned, NULL) ) { // printf ("DFP_GET_VERSION failed for drive %d\n", i); // continue; } // If there is a IDE device at number "i" issue commands // to the device if (VersionParams.bIDEDeviceMap > 0) { BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd SENDCMDINPARAMS scip; //SENDCMDOUTPARAMS OutCmd; // Now, get the ID sector for all IDE devices in the system. // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command, // otherwise use the IDE_ATA_IDENTIFY command bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? \ IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; memset (&scip, 0, sizeof(scip)); memset (IdOutCmd, 0, sizeof(IdOutCmd)); if ( DoIDENTIFY (hPhysicalDriveIOCTL, &scip, (PSENDCMDOUTPARAMS)&IdOutCmd, (BYTE) bIDCmd, (BYTE) drive, &cbBytesReturned)) { int ijk = 0; USHORT *pIdSector = (USHORT *)((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer; for (ijk = 0; ijk < 256; ijk++) diskdata[ijk] = pIdSector [ijk]; //PrintIdeInfo (drive, diskdata); done = TRUE; } } CloseHandle (hPhysicalDriveIOCTL); } return done; } char* ConvertToString(DWORD diskdata[256], int firstIndex, int len) { static char sc[512+1]; int index = 0; int nScore = 0; int end = firstIndex + len; // each integer has two characters stored in it backwards for (index = firstIndex; index < end; index++) { // get high byte for 1st character sc[nScore] = (char) (diskdata[index] / 256); nScore++; // get low byte for 2nd character sc[nScore] = (char) (diskdata[index] % 256); nScore++; } // end the sc sc [nScore] = '\0'; // cut off the trailing blanks---从右边开始截去空格,遇到非空格返回! for (index=nScore-1; index>0 && sc[index]==0x20; index--) sc[index] = '\0'; //&/sc[index]==0x20 --- 不能放到for循环的{}内,否则逻辑错误! return sc; } /////////////////////////////////////////////////////////////////////////////// //将一个无符号型数转换成16进制字符串: static char* UINTtosHex(unsigned int uN,bool bLmt8=true) { static char s[16+1]; int bit = 4; unsigned int nA[16]; int i; unsigned int Ib = uN; int len=0; while(Ib>0) { Ib = Ib>>bit; len++; } for(i=0;i >((len-1-i)*bit)); uN -= (((unsigned int)nA[i])<<((len-1-i)*bit)); } for(int k=0;k<17;k++) s[k] = 0; int odd=0; i = 0; if(bLmt8) { for(i=0;i<8-len;i++) s[i] = 48; odd = 8-len; i = (len>8)? (len-8):0; //长度超过8取后8位;//长度小于8前面补0;否则用实际的16进制字串! } for( ;i 9) //0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F; s[odd+i] = 55+nA[i]; else s[odd+i] = 48+nA[i]; } return s; } //将一个16进制字符串转换成无符号型数: static void sHextoUINT(unsigned int& uN,bool bLmt8=true,char* sH=0,int len=8) { int bit = 4; unsigned int nA[16]; int i; for(i=0;i 64)? (sH[i]-55):(sH[i]-48); } //如果需要限长:对于长度小于等于8,取前n位;长度>8,取后8位;或者补限制的也直接转换;不限长的也从0开始累加; i = 0; if(bLmt8) { i = (len>8) ? (len-8) : 0; } uN = 0; for( ;i 268435455) id %= 268435456; return (long) id; } /////////////////////////////////////////////////////////////////////////////// */ /* /////////////////////////////////////////////////////////////////////////////// typedef struct _SRB_IO_CONTROL { ULONG HeaderLength; UCHAR Signature[8]; ULONG Timeout; ULONG ControlCode; ULONG ReturnCode; ULONG Length; } SRB_IO_CONTROL, *PSRB_IO_CONTROL; // The following struct defines the interesting part of the IDENTIFY // buffer: typedef struct _IDSECTOR { USHORT wGenConfig; USHORT wNumCyls; USHORT wReserved; USHORT wNumHeads; USHORT wBytesPerTrack; USHORT wBytesPerSector; USHORT wSectorsPerTrack; USHORT wVendorUnique[3]; CHAR sSerialNumber[20]; USHORT wBufferType; USHORT wBufferSize; USHORT wECCSize; CHAR sFirmwareRev[8]; CHAR sModelNumber[40]; USHORT wMoreVendorUnique; USHORT wDoubleWordIO; USHORT wCapabilities; USHORT wReserved1; USHORT wPIOTiming; USHORT wDMATiming; USHORT wBS; USHORT wNumCurrentCyls; USHORT wNumCurrentHeads; USHORT wNumCurrentSectorsPerTrack; ULONG ulCurrentSectorCapacity; USHORT wMultSectorStuff; ULONG ulTotalAddressableSectors; USHORT wSingleWordDMA; USHORT wMultiWordDMA; BYTE bReserved[128]; } IDSECTOR, *PIDSECTOR; //#define SENDIDLENGTH sizeof(SENDCMDOUTPARAMS)+IDENTIFY_BUFFER_SIZE int ReadIdeDriveAsScsiDriveInNT (int controller,int driver,DWORD diskdata[256]) { const int SENDIDLENGTH = sizeof(SENDCMDOUTPARAMS)+IDENTIFY_BUFFER_SIZE; int done = FALSE; char driveName [256]; memset(driveName,0,256); driveName[ 0] = '\\'; driveName[ 1] = '\\'; driveName[ 2] = '.'; driveName[ 3] = '\\'; driveName[ 4] = 'S'; driveName[ 5] = 'c'; driveName[ 6] = 's'; driveName[ 7] = 'i'; driveName[ 8] = 0x30 + controller; HANDLE hScsiDriveIOCTL = 0; // Try to get a handle to PhysicalDrive IOCTL, report failure // and exit if can't. //sprintf (driveName, "\\\\.\\Scsi%d:", controller); // Windows NT, Windows 2000, any rights should do //&controller for循环两次起点: //for (controller = 0; controller < 2; controller++) //{ //处理driveName; hScsiDriveIOCTL = CreateFile (driveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE) // printf ("Unable to open SCSI controller %d, error code: 0x%lX\n", // controller, GetLastError ()); if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE) { int drive = 0; //&driver for循环两次起点: //for (drive = 0; drive < 2; drive++) //{ //处理drive循环; char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH]; SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer; SENDCMDINPARAMS *pin = (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); DWORD dummy; memset (buffer, 0, sizeof (buffer)); p -> HeaderLength = sizeof (SRB_IO_CONTROL); p -> Timeout = 10000; p -> Length = SENDIDLENGTH; p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; strncpy ((char *) p -> Signature, "SCSIDISK", 8); pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; pin -> bDriveNumber = drive; if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, buffer, sizeof (SRB_IO_CONTROL) + sizeof (SENDCMDINPARAMS) - 1, buffer, sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, &dummy, NULL)) { SENDCMDOUTPARAMS *pOut = (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer); if (pId -> sModelNumber [0]) { //DWORD diskdata [256]; int ijk = 0; USHORT *pIdSector = (USHORT *) pId; for (ijk = 0; ijk < 256; ijk++) diskdata [ijk] = pIdSector [ijk]; //PrintIdeInfo (controller * 2 + drive, diskdata); done = TRUE; } } //} CloseHandle (hScsiDriveIOCTL); } //} return done; } /////////////////////////////////////////////////////////////////////////////// */