zoukankan      html  css  js  c++  java
  • 读取计算机 CPU 硬盘 主板号的源程序

    http://www.codeguru.com/forum/showthread.php?t=123783

    //Unique PCID.h
    #include "smart.h"
    struct SPentiumIIISerialNumber
    {
    DWORD high;
    DWORD middle;
    DWORD low;
    };

    class CUniquePCID
    {
    public:

    //returns the MAC address of the FIRST network card in the PC
    bool GetMACAddress(__int64 & iMACAddress);

    //returns 0 if disabled
    bool CPUID(SPentiumIIISerialNumber & serialnumber) const;

    //returns serial # of drive C - 0 indicates no drive C
    //this function returns the number, as C: should always be there!
    DWORD HardDiskVolume() const {return m_dwHD;}

    bool GetIDESerialNo(CString & csSerialNumber,CString & csError);



    CUniquePCID();
    virtual ~CUniquePCID();

    private:
    DWORD m_dwHD;

    //returns 0, and gives error message if fails
    HANDLE OpenSMART(CString & csError,bool bWindows9X = true);//not entirerly sure that it works under NT - but worth a try!

    bool DoEnableSMART(HANDLE hSMARTIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, BYTE bDriveNum, PDWORD lpcbBytesReturned);
    bool DoIDENTIFY(HANDLE hSMARTIOCTL, PSENDCMDINPARAMS pSCIP,PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, PDWORD lpcbBytesReturned);
    void ChangeByteOrder(PCHAR szString, USHORT uscStrSize);



    };


    //smart.h
    /****************************************************************************
    * *
    * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
    * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
    * PURPOSE. *
    * *
    * Copyright 1993-98 Microsoft Corporation. All Rights Reserved. *
    * *
    ****************************************************************************/

    /****************************************************************************
    *
    * PROGRAM: SMART.H
    *
    * PURPOSE: Structure definitions for an application that calls SMART Ioctls
    *
    ****************************************************************************/

    #ifndef SMARTIOCTL_INCLUDED
    #define SMARTIOCTL_INCLUDED

    // Miscellaneous

    #define MAX_IDE_DRIVES 4 // Max number of drives assuming primary/secondary, master/slave topology
    #define READ_ATTRIBUTE_BUFFER_SIZE 512
    #define IDENTIFY_BUFFER_SIZE 512
    #define READ_THRESHOLD_BUFFER_SIZE 512

    //
    // IOCTL commands
    //
    #define DFP_GET_VERSION 0x00074080
    #define DFP_SEND_DRIVE_COMMAND 0x0007c084
    #define DFP_RECEIVE_DRIVE_DATA 0x0007c088

    //---------------------------------------------------------------------
    // 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_ID 0xA1 // Returns ID sector for ATAPI.
    #define IDE_ID_FUNCTION 0xEC // Returns ID sector for ATA.
    #define IDE_EXECUTE_SMART_FUNCTION 0xB0 // Performs SMART cmd.
    // Requires valid bFeaturesReg,
    // bCylLowReg, and bCylHighReg
    //
    // Cylinder register values required when issuing SMART command
    //
    #define SMART_CYL_LOW 0x4F
    #define SMART_CYL_HI 0xC2

    //---------------------------------------------------------------------
    // 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;

    //
    // bDriverError values
    //
    #define SMART_NO_ERROR 0 // No error
    #define SMART_IDE_ERROR 1 // Error from IDE controller
    #define SMART_INVALID_FLAG 2 // Invalid command flag
    #define SMART_INVALID_COMMAND 3 // Invalid command byte
    #define SMART_INVALID_BUFFER 4 // Bad buffer (null, invalid addr..)
    #define SMART_INVALID_DRIVE 5 // Drive number not valid
    #define SMART_INVALID_IOCTL 6 // Invalid IOCTL
    #define SMART_ERROR_NO_MEM 7 // Could not lock user's buffer
    #define SMART_INVALID_REGISTER 8 // Some IDE Register not valid
    #define SMART_NOT_SUPPORTED 9 // Invalid cmd flag set
    #define SMART_NO_IDE_DEVICE 10 // Cmd issued to device not present
    // although drive number is valid
    // 11-255 reserved

    //---------------------------------------------------------------------
    // Structure returned by SMART IOCTL for several commands
    //---------------------------------------------------------------------
    typedef struct _SENDCMDOUTPARAMS {
    DWORD cBufferSize; // Size of bBuffer in bytes
    DRIVERSTATUS DriverStatus; // Driver status structure.
    char bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive.
    } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;


    //---------------------------------------------------------------------
    // Feature register defines for SMART "sub commands"
    //---------------------------------------------------------------------
    #define SMART_READ_ATTRIBUTE_VALUES 0xD0 // ATA4: Renamed
    // SMART READ DATA
    #define SMART_READ_ATTRIBUTE_THRESHOLDS 0xD1 // Obsoleted in ATA4!
    #define SMART_ENABLE_DISABLE_ATTRIBUTE_AUTOSAVE 0xD2
    #define SMART_SAVE_ATTRIBUTE_VALUES 0xD3
    #define SMART_EXECUTE_OFFLINE_IMMEDIATE 0xD4 // ATA4
    // Vendor specific commands:
    #define SMART_ENABLE_SMART_OPERATIONS 0xD8
    #define SMART_DISABLE_SMART_OPERATIONS 0xD9
    #define SMART_RETURN_SMART_STATUS 0xDA

    #endif

    //---------------------------------------------------------------------
    // The following structure defines the structure of a Drive Attribute
    //---------------------------------------------------------------------
    typedef struct _DRIVEATTRIBUTE {
    BYTE bAttrID; // Identifies which attribute
    WORD wStatusFlags; // see bit definitions below
    BYTE bAttrValue; // Current normalized value
    BYTE bWorstValue; // How bad has it ever been?
    BYTE bRawValue[6]; // Un-normalized value
    BYTE bReserved; // ...
    } DRIVEATTRIBUTE, *PDRIVEATTRIBUTE, *LPDRIVEATTRIBUTE;

    //---------------------------------------------------------------------
    // The following structure defines the structure of a Warranty Threshold
    // Obsoleted in ATA4!
    //---------------------------------------------------------------------
    typedef struct _ATTRTHRESHOLD {
    BYTE bAttrID; // Identifies which attribute
    BYTE bWarrantyThreshold; // Triggering value
    BYTE bReserved[10]; // ...
    } ATTRTHRESHOLD, *PATTRTHRESHOLD, *LPATTRTHRESHOLD;

    //---------------------------------------------------------------------
    // 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 szSerialNumber[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;

    //---------------------------------------------------------------------
    // Valid Attribute IDs
    //---------------------------------------------------------------------
    #define ATTR_INVALID 0
    #define ATTR_READ_ERROR_RATE 1
    #define ATTR_THROUGHPUT_PERF 2
    #define ATTR_SPIN_UP_TIME 3
    #define ATTR_START_STOP_COUNT 4
    #define ATTR_REALLOC_SECTOR_COUNT 5
    #define ATTR_READ_CHANNEL_MARGIN 6
    #define ATTR_SEEK_ERROR_RATE 7
    #define ATTR_SEEK_TIME_PERF 8
    #define ATTR_POWER_ON_HRS_COUNT 9
    #define ATTR_SPIN_RETRY_COUNT 10
    #define ATTR_CALIBRATION_RETRY_COUNT 11
    #define ATTR_POWER_CYCLE_COUNT 12

    //---------------------------------------------------------------------
    // Status Flags Values
    //---------------------------------------------------------------------
    #define PRE_FAILURE_WARRANTY 0x1
    #define ON_LINE_COLLECTION 0x2
    #define PERFORMANCE_ATTRIBUTE 0x4
    #define ERROR_RATE_ATTRIBUTE 0x8
    #define EVENT_COUNT_ATTRIBUTE 0x10
    #define SELF_PRESERVING_ATTRIBUTE 0x20

    #define NUM_ATTRIBUTE_STRUCTS 30



    //uniquepcid.cpp
    #pragma pack(1) // Required to ensure correct SMART IOCTL structure setup
    #include "UniquePCID.h"
    #include "nb30.h"
    #include "winosver.h"

    #ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif





    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////
    // http://support.microsoft.com/support.../Q208/0/48.ASP
    CUniquePCID::CUniquePCID()
    {

    UINT uiOldMode = SetErrorMode(SEM_FAILCRITICALERRORS);

    //collect the drive volume info on construction, as it doesn't take long.
    //the other calls are more likely to fail and/or take longer to calculate

    if (!GetVolumeInformation("C:\\",0,0,&m_dwHD,0,0,0,0))
    {
    m_dwHD = 0;
    }

    SetErrorMode(uiOldMode);


    }

    CUniquePCID::~CUniquePCID()
    {

    }

    bool CUniquePCID::CPUID(SPentiumIIISerialNumber & serialnumber) const
    {


    SPentiumIIISerialNumber * pSerialNumber = &serialnumber;

    serialnumber.high = 0;
    serialnumber.middle = 0;
    serialnumber.low = 0;




    BOOL bGotSerialNumber = FALSE;
    BOOL bSupportsCpuID = FALSE;



    __asm
    {
    //
    // The CPUID instruction is supported only if bit 21 of
    // EFLAGS can be changed.
    //
    pushfd
    pop eax // get current EFLAGS

    mov ecx, eax
    xor eax, 200000h // toggle bit 21

    push eax
    popfd // set new EFLAGS

    pushfd
    pop eax // retrieve EFLAGS again

    xor eax, ecx // did bit 21 change?
    jz restore_eflags // no, CPUID not supported
    mov dword ptr [bSupportsCpuID], TRUE

    restore_eflags:
    push ecx
    popfd // restore original EFLAGS

    cmp dword ptr [bSupportsCpuID], FALSE
    jz exit_function

    //
    // CPUID uses the value in EAX to determine what info to
    // return. When EAX is 0 on input, CPUID returns the
    // highest value allowed for EAX. The return value _must_
    // be >= 3, or the serial number is not supported.
    //
    mov eax, 0
    cpuid
    cmp eax, 3 // function "3" supported?
    jl exit_function // no, there's no serial #

    //
    // Check bit 18 of the processor "feature flags" to
    // determine if the processor serial number is available
    // and enabled. The "feature flags" are returned in EDX
    // after executing CPUID with EAX=1.
    //
    mov eax, 1
    cpuid
    test edx, 40000h // is bit 18 set?
    jz exit_function // no, serial # disabled
    // or not available
    //
    // 96-bit processor serial number is available:
    // high 32 bits are in EAX after CPUID with EAX=1
    // middle 32 bits are in EDX after CPUID with EAX=3
    // low 32 bits are in ECX after CPUID with EAX=3
    //
    mov edi, dword ptr [pSerialNumber]
    mov dword ptr [edi.high], eax

    mov eax, 3
    cpuid
    mov dword ptr [edi.middle], edx
    mov dword ptr [edi.low], ecx
    mov dword ptr [bGotSerialNumber], TRUE
    }
    exit_function:




    return bGotSerialNumber;
    }


    bool CUniquePCID::GetMACAddress(__int64 & iMACAddress)
    {
    bool bResult = false;

    struct ASTAT
    {

    ADAPTER_STATUS adapt;
    NAME_BUFFER NameBuff [30];
    };

    ASTAT Adapter;


    //firstly enumerate all the network cards
    //not good to just assume that one is there
    NCB Ncb;
    UCHAR uRetCode;

    LANA_ENUM lenum;

    memset( &Ncb, 0, sizeof(Ncb) );
    Ncb.ncb_command = NCBENUM;
    Ncb.ncb_buffer = (UCHAR *)&lenum;
    Ncb.ncb_length = sizeof(lenum);
    uRetCode = Netbios( &Ncb );


    if (uRetCode == 0)
    {

    //reset the card - don't fret you won't lose network traffic!
    memset( &Ncb, 0, sizeof(Ncb) );
    Ncb.ncb_command = NCBRESET;
    Ncb.ncb_lana_num = lenum.lana[0];

    uRetCode = Netbios( &Ncb );


    //getnet card status

    memset( &Ncb, 0, sizeof (Ncb) );
    Ncb.ncb_command = NCBASTAT;
    Ncb.ncb_lana_num = lenum.lana[0];

    strcpy( (char*)Ncb.ncb_callname, "* " );
    (Ncb.ncb_buffer) = (PUCHAR)&Adapter;
    Ncb.ncb_length = sizeof(Adapter);

    uRetCode = Netbios( &Ncb );

    if ( uRetCode == 0 )
    {

    for (int i = 0;i<6; i++)
    {
    __int64 iCurVal = Adapter.adapt.adapter_address[i];

    iCurVal = iCurVal * pow(0x100 , 5-i);
    iMACAddress += iCurVal;
    }

    bResult = true;

    }

    }

    return bResult;

    }







    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    bool CUniquePCID::GetIDESerialNo(CString & csSerialNumber,CString & csError)
    {
    bool bResult = false;
    SENDCMDINPARAMS scip;
    SENDCMDOUTPARAMS OutCmd;
    BYTE byDfpDriveMap = 0;
    BYTE byIDCmd;
    DWORD cbBytesReturned;
    BYTE IdOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

    CWinOSVer osversion;

    bool bWindows9x = !osversion.WinNT();
    HANDLE hSMARTIOCtrl = OpenSMART(csError,bWindows9x);

    #ifdef _DEBUG
    if (!hSMARTIOCtrl)
    {
    AfxMessageBox(csError,MB_OK);
    }
    #endif


    if (hSMARTIOCtrl)
    {
    GETVERSIONOUTPARAMS VersionParams;
    memset(&VersionParams, 0, sizeof(VersionParams));

    if ( DeviceIoControl(hSMARTIOCtrl, DFP_GET_VERSION,
    NULL,
    0,
    &VersionParams,
    sizeof(VersionParams),
    &cbBytesReturned, NULL) )
    {

    for (BYTE i = 0; i < MAX_IDE_DRIVES; i++)
    {
    //
    // If there is a IDE device at number "i" issue commands
    // to the device.
    if (VersionParams.bIDEDeviceMap >> i & 1)
    {
    // Try to enable SMART so we can tell if a drive supports it.
    // Ignore ATAPI devices.
    //

    if (!(VersionParams.bIDEDeviceMap >> i & 0x10))
    {
    memset(&scip, 0, sizeof(scip));
    memset(&OutCmd, 0, sizeof(OutCmd));

    if (DoEnableSMART(hSMARTIOCtrl, &scip, &OutCmd, i, &cbBytesReturned))
    {

    // Mark the drive as SMART enabled
    byDfpDriveMap |= (1 << i);
    //Not needed in this app - but may be usefull to have a list of drives later on...
    }
    }

    }

    // Now, get the ID sector for all IDE devices in the system.
    // If the device is ATAPI use the IDE_ATAPI_ID command,
    // otherwise use the IDE_ID_FUNCTION command.
    byIDCmd = (VersionParams.bIDEDeviceMap >> i & 0x10) ? IDE_ATAPI_ID : IDE_ID_FUNCTION;


    memset(&scip, 0, sizeof(scip));
    memset(IdOutCmd, 0,sizeof(IdOutCmd) );


    if ( DoIDENTIFY(hSMARTIOCtrl, &scip, (PSENDCMDOUTPARAMS)&IdOutCmd, byIDCmd, i, &cbBytesReturned))
    {

    PIDSECTOR pIDS = (PIDSECTOR) ((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer;

    //change word array to byte array
    ChangeByteOrder(pIDS->szSerialNumber,sizeof pIDS->szSerialNumber);

    char szTempSerialNo[41];

    memset(szTempSerialNo,0, sizeof(szTempSerialNo));

    strncpy(szTempSerialNo,pIDS->szSerialNumber,sizeof(pIDS->szSerialNumber));
    csSerialNumber = szTempSerialNo;

    bResult = true;
    }


    }



    }
    else
    {
    csError = "DFP_GET_VERSION failed";
    }


    }


    if (hSMARTIOCtrl)
    {
    CloseHandle(hSMARTIOCtrl);
    hSMARTIOCtrl = 0;
    }


    return bResult;
    }




    void CUniquePCID::ChangeByteOrder(PCHAR szString, USHORT uscStrSize)
    {
    USHORT i;
    CHAR temp;

    for (i = 0; i < uscStrSize; i+=2)
    {
    temp = szString[i];
    szString[i] = szString[i+1];
    szString[i+1] = temp;
    }
    }

    HANDLE CUniquePCID::OpenSMART(CString & csError,bool bWindows9X)
    {
    HANDLE hSMARTIOCTL = 0;

    if (bWindows9X)
    {
    hSMARTIOCTL = CreateFile("\\\\.\\SMARTVSD", 0,0,0,CREATE_NEW, 0, 0);
    // Version Windows 95 OSR2, Windows 98
    if (hSMARTIOCTL == INVALID_HANDLE_VALUE)
    {
    csError.Format("Unable to open SMARTVSD, error code: 0x%lX\n", GetLastError());
    hSMARTIOCTL = 0;
    }
    }
    else
    {
    // Windows NT, Windows 2000
    hSMARTIOCTL = CreateFile("\\\\.\\PhysicalDrive0",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
    OPEN_EXISTING,0,NULL);
    if ( hSMARTIOCTL == INVALID_HANDLE_VALUE)
    {
    csError.Format("Unable to open physical drive, error code: 0x%lX\n", GetLastError());
    hSMARTIOCTL = 0;
    }

    }

    return hSMARTIOCTL;

    }
    /****************************************************************************
    *
    * DoEnableSMART
    *
    * FUNCTION: Send a SMART_ENABLE_SMART_OPERATIONS command to the drive
    * bDriveNum = 0-3
    *
    ****************************************************************************/
    bool CUniquePCID:oEnableSMART(HANDLE hSMARTIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, BYTE bDriveNum, PDWORD lpcbBytesReturned)
    {
    //
    // Set up data structures for Enable SMART Command.
    //
    pSCIP->cBufferSize = 0;

    pSCIP->irDriveRegs.bFeaturesReg = SMART_ENABLE_SMART_OPERATIONS;
    pSCIP->irDriveRegs.bSectorCountReg = 1;
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    pSCIP->irDriveRegs.bCylLowReg = SMART_CYL_LOW;
    pSCIP->irDriveRegs.bCylHighReg = SMART_CYL_HI;

    //
    // Compute the drive number.
    //
    pSCIP->irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
    pSCIP->irDriveRegs.bCommandReg = IDE_EXECUTE_SMART_FUNCTION;
    pSCIP->bDriveNumber = bDriveNum;


    bool bResult = ( DeviceIoControl(hSMARTIOCTL, DFP_SEND_DRIVE_COMMAND,
    (LPVOID)pSCIP, sizeof(SENDCMDINPARAMS) - 1,
    (LPVOID)pSCOP, sizeof(SENDCMDOUTPARAMS) - 1,
    lpcbBytesReturned, NULL) !=0 );



    return bResult;
    }
    /****************************************************************************
    *
    * DoIDENTIFY
    *
    * FUNCTION: Send an IDENTIFY command to the drive
    * bDriveNum = 0-3
    * bIDCmd = IDE_ID_FUNCTION or IDE_ATAPI_ID
    *
    ****************************************************************************/
    bool CUniquePCID:oIDENTIFY(HANDLE hSMARTIOCTL, 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;


    bool bResult = ( DeviceIoControl(hSMARTIOCTL, DFP_RECEIVE_DRIVE_DATA,
    (LPVOID)pSCIP, sizeof(SENDCMDINPARAMS) - 1,
    (LPVOID)pSCOP, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
    lpcbBytesReturned, NULL) !=0);


    return bResult;
    }





    "Take a chance while you still got a choice"

  • 相关阅读:
    浅谈MSSQL2012中的列存储索引(columnstore indexes)
    《高性能SQL调优精要与案例解析》新书样章
    关系库执行计划中三种最常用连接方式的伪码实现
    python基础-字符串
    python基础-文件和目录
    python基础-列表
    python基础-对象
    python基础-入门
    python算法-二叉树广度优先遍历
    Python算法-二叉树深度优先遍历
  • 原文地址:https://www.cnblogs.com/cy163/p/1858723.html
Copyright © 2011-2022 走看看