線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4814
推到 Plurk!
推到 Facebook!

BIOS 讀取 硬碟型號的問題

尚未結案
xiaolaba
一般會員


發表:10
回覆:17
積分:5
註冊:2010-05-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2013-02-26 11:04:44 IP:42.2.xxx.xxx 訂閱
其實這個疑問並不知道是否合適在這版發文.

俺的需求是這樣的, 每次 PC 開機, BIOS 都會顯示 硬碟的大小序號等資料, 如果俺要在 WINDOWS 裡面, 用甚麼 API 達到同樣的目標呢

或,

怎樣直接讀寫硬碟控制器達到目的呢.

謝謝
------
http://xiaolaba.wordpress.com
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2013-02-27 12:51:23 IP:114.42.xxx.xxx 訂閱
自己研究一下程式碼吧,以下是在cb 6下可正常運行,而裡面的hugh(本人)有加入一點點程式碼。


[code cpp]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "iphlpapi.lib") // must add path lib psdk
#pragma hdrstop


//---------------------------------------------------------------------------
#pragma package(smart_init)
char HardDriveSerialNumber[1024];
char HardDriveModelNumber[1024];
int PRINT_DEBUG = false;

static void dump_buffer(const char* title, const unsigned char* buffer,
int len);

void WriteConstantString(char *entry, char *string) {
}

// Required to ensure correct PhysicalDrive IOCTL structure setup
#pragma pack(1)

#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

#define SMART_GET_VERSION CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
#define SMART_SEND_DRIVE_COMMAND CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)


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

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

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;
typedef struct _SRB_IO_CONTROL {
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;
// Define global buffers.
BYTE IdOutCmd[sizeof(SENDCMDOUTPARAMS) IDENTIFY_BUFFER_SIZE - 1];
char *ConvertToString(DWORD diskdata[256], int firstIndex, int lastIndex,
char* buf);
void PrintIdeInfo(int drive, DWORD diskdata[256]);
BOOL DoIDENTIFY(HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS, BYTE, BYTE,
PDWORD);
// Max number of drives assuming primary/secondary, master/slave topology
#define MAX_IDE_DRIVES 16
// Required to ensure correct PhysicalDrive IOCTL structure setup
#pragma pack(4)
//
// IOCTL_STORAGE_QUERY_PROPERTY
//
// Input Buffer:
// a STORAGE_PROPERTY_QUERY structure which describes what type of query
// is being done, what property is being queried for, and any additional
// parameters which a particular property query requires.
//
// Output Buffer:
// Contains a buffer to place the results of the query into. Since all
// property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER,
// the IOCTL can be called once with a small buffer then again using
// a buffer as large as the header reports is necessary.
//
//
// Types of queries
//
typedef enum _STORAGE_QUERY_TYPE {
PropertyStandardQuery = 0, // Retrieves the descriptor
PropertyExistsQuery, // Used to test whether the descriptor is supported
PropertyMaskQuery,
// Used to retrieve a mask of writeable fields in the descriptor
PropertyQueryMaxDefined // use to validate the value
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;
//
// define some initial property id's
//
typedef enum _STORAGE_PROPERTY_ID {
StorageDeviceProperty = 0, StorageAdapterProperty
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;
//
// Query structure - additional parameters for specific queries can follow
// the header
//
typedef struct _STORAGE_PROPERTY_QUERY {
//
// ID of the property being retrieved
//
STORAGE_PROPERTY_ID PropertyId;
//
// Flags indicating the type of query being performed
//
STORAGE_QUERY_TYPE QueryType;
//
// Space for additional parameters if necessary
//
UCHAR AdditionalParameters[1];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;
#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
//
// Device property descriptor - this is really just a rehash of the inquiry
// data retrieved from a scsi device
//
// This may only be retrieved from a target device. Sending this to the bus
// will result in an error
//
#pragma pack(4)
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
//
// Sizeof(STORAGE_DEVICE_DESCRIPTOR)
//
ULONG Version;
//
// Total size of the descriptor, including the space for additional
// data and id strings
//
ULONG Size;
//
// The SCSI-2 device type
//
UCHAR DeviceType;
//
// The SCSI-2 device type modifier (if any) - this may be zero
//
UCHAR DeviceTypeModifier;
//
// Flag indicating whether the device's media (if any) is removable. This
// field should be ignored for media-less devices
//
BOOLEAN RemovableMedia;
//
// Flag indicating whether the device can support mulitple outstanding
// commands. The actual synchronization in this case is the responsibility
// of the port driver.
//
BOOLEAN CommandQueueing;
//
// Byte offset to the zero-terminated ascii string containing the device's
// vendor id string. For devices with no such ID this will be zero
//
ULONG VendorIdOffset;
//
// Byte offset to the zero-terminated ascii string containing the device's
// product id string. For devices with no such ID this will be zero
//
ULONG ProductIdOffset;
//
// Byte offset to the zero-terminated ascii string containing the device's
// product revision string. For devices with no such string this will be
// zero
//
ULONG ProductRevisionOffset;
//
// Byte offset to the zero-terminated ascii string containing the device's
// serial number. For devices with no serial number this will be zero
//
ULONG SerialNumberOffset;
//
// Contains the bus type (as defined above) of the device. It should be
// used to interpret the raw device properties at the end of this structure
// (if any)
//
STORAGE_BUS_TYPE BusType;
//
// The number of bytes of bus-specific data which have been appended to
// this descriptor
//
ULONG RawPropertiesLength;
//
// Place holder for the first byte of the bus specific property data
//
UCHAR RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
// function to decode the serial numbers of IDE hard drives
// using the IOCTL_STORAGE_QUERY_PROPERTY command
char * flipAndCodeBytes(const char * str, int pos, int flip, char * buf) {
int i;
int j = 0;
int k = 0;
buf[0] = '\0';
if (pos <= 0)
return buf;
if (!j) {
char p = 0;
// First try to gather all characters representing hex digits only.
j = 1;
k = 0;
buf[k] = 0;
for (i = pos; j && str[i] != '\0'; i) {
char c = tolower(str[i]);
if (isspace(c))
c = '0';
p;
buf[k] <<= 4;
if (c >= '0' && c <= '9')
buf[k] |= (unsigned char)(c - '0');
else if (c >= 'a' && c <= 'f')
buf[k] |= (unsigned char)(c - 'a' 10);
else {
j = 0;
break;
}
if (p == 2) {
if (buf[k] != '\0' && !isprint(buf[k])) {
j = 0;
break;
}
k;
p = 0;
buf[k] = 0;
}
}
}
if (!j) {
// There are non-digit characters, gather them as is.
j = 1;
k = 0;
for (i = pos; j && str[i] != '\0'; i) {
char c = str[i];
if (!isprint(c)) {
j = 0;
break;
}
buf[k ] = c;
}
}
if (!j) {
// The characters are not there or are not printable.
k = 0;
}
buf[k] = '\0';
if (flip)
// Flip adjacent characters
for (j = 0; j < k; j = 2) {
char t = buf[j];
buf[j] = buf[j 1];
buf[j 1] = t;
}
// Trim any beginning and end space
i = j = -1;
for (k = 0; buf[k] != '\0'; k) {
if (!isspace(buf[k])) {
if (i < 0)
i = k;
j = k;
}
}
if ((i >= 0) && (j >= 0)) {
for (k = i; (k <= j) && (buf[k] != '\0'); k)
buf[k - i] = buf[k];
buf[k - i] = '\0';
}
return buf;
}
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)
// typedef struct _DISK_GEOMETRY_EX {
// DISK_GEOMETRY Geometry;
// LARGE_INTEGER DiskSize;
// UCHAR Data[1];
// } DISK_GEOMETRY_EX, *PDISK_GEOMETRY_EX;

//int ReadPhysicalDriveInNTWithZeroRights(void) {
int ReadPhysicalDriveInNTWithZeroRights(TStringList *ls) {
int done = FALSE;
int drive = 0;
for (drive = 0; drive < MAX_IDE_DRIVES; drive ) {
HANDLE hPhysicalDriveIOCTL = 0;
// Try to get a handle to PhysicalDrive IOCTL, report failure
// and exit if can't.
char driveName[256];
sprintf(driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT, Windows 2000, Windows XP - admin rights not required
hPhysicalDriveIOCTL = CreateFile(driveName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) {
#ifdef PRINTING_TO_CONSOLE_ALLOWED
if (PRINT_DEBUG)
printf("\n%d ReadPhysicalDriveInNTWithZeroRights ERROR"
"\nCreateFile(%s) returned INVALID_HANDLE_VALUE\n", __LINE__,
driveName);
#endif
}
else {
STORAGE_PROPERTY_QUERY query;
DWORD cbBytesReturned = 0;
char buffer[10000];
memset((void *) & query, 0, sizeof(query));
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
memset(buffer, 0, sizeof(buffer));
if (DeviceIoControl(hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(query), &buffer, sizeof(buffer), &cbBytesReturned,
NULL)) {
STORAGE_DEVICE_DESCRIPTOR * descrip =
(STORAGE_DEVICE_DESCRIPTOR*)&buffer;
char serialNumber[1000];
char modelNumber[1000];
char vendorId[1000];
char productRevision[1000];
#ifdef PRINTING_TO_CONSOLE_ALLOWED
if (PRINT_DEBUG) {
printf("\n%d STORAGE_DEVICE_DESCRIPTOR contents for drive %d\n"
" Version: %ld\n" " Size: %ld\n"
" DeviceType: x\n" " DeviceTypeModifier: x\n"
" RemovableMedia: %d\n" " CommandQueueing: %d\n"
" VendorIdOffset: %4ld (0xlx)\n" " ProductIdOffset: %4ld (0xlx)\n"
" ProductRevisionOffset: %4ld (0xlx)\n" " SerialNumberOffset: %4ld (0xlx)\n"
" BusType: %d\n" " RawPropertiesLength: %ld\n",
__LINE__, drive, (unsigned long) descrip->Version,
(unsigned long) descrip->Size, (int) descrip->DeviceType,
(int) descrip->DeviceTypeModifier, (int) descrip->RemovableMedia,
(int) descrip->CommandQueueing,
(unsigned long) descrip->VendorIdOffset,
(unsigned long) descrip->VendorIdOffset,
(unsigned long) descrip->ProductIdOffset,
(unsigned long) descrip->ProductIdOffset,
(unsigned long) descrip->ProductRevisionOffset,
(unsigned long) descrip->ProductRevisionOffset,
(unsigned long) descrip->SerialNumberOffset,
(unsigned long) descrip->SerialNumberOffset,
(int) descrip->BusType,
(unsigned long) descrip->RawPropertiesLength);
dump_buffer("Contents of RawDeviceProperties",
(unsigned char*) descrip->RawDeviceProperties,
descrip->RawPropertiesLength);
dump_buffer("Contents of first 256 bytes in buffer",
(unsigned char*) buffer, 256);
}
#endif
flipAndCodeBytes(buffer, descrip->VendorIdOffset, 0, vendorId);
flipAndCodeBytes(buffer, descrip->ProductIdOffset, 0, modelNumber);
flipAndCodeBytes(buffer, descrip->ProductRevisionOffset, 0,
productRevision);
flipAndCodeBytes(buffer, descrip->SerialNumberOffset, 1, serialNumber);
if (0 == HardDriveSerialNumber[0] &&
// serial number must be alphanumeric
// (but there can be leading spaces on IBM drives)
(isalnum(serialNumber[0]) || isalnum(serialNumber[19]))) {
strcpy(HardDriveSerialNumber, serialNumber);
strcpy(HardDriveModelNumber, modelNumber);
done = TRUE;
}
#ifdef PRINTING_TO_CONSOLE_ALLOWED
printf("\n**** STORAGE_DEVICE_DESCRIPTOR for drive %d ****\n"
"Vendor Id = [%s]\n" "Product Id = [%s]\n"
"Product Revision = [%s]\n" "Serial Number = [%s]\n", drive,
vendorId, modelNumber, productRevision, serialNumber);
#endif
// below add by Hugh 20120326
if (drive==0)
{
ls->Add(AnsiString(vendorId));
ls->Add(AnsiString(modelNumber));
ls->Add(AnsiString(productRevision));
ls->Add(AnsiString(serialNumber));
}

// End by Hugh

// Get the disk drive geometry.
memset(buffer, 0, sizeof(buffer));
if (!DeviceIoControl(hPhysicalDriveIOCTL,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &buffer, sizeof(buffer),
&cbBytesReturned, NULL)) {
#ifdef PRINTING_TO_CONSOLE_ALLOWED
if (PRINT_DEBUG)
printf("\n%d ReadPhysicalDriveInNTWithZeroRights ERROR"
"|nDeviceIoControl(%s, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) returned 0",
driveName);
#endif
}
else {
DISK_GEOMETRY_EX* geom = (DISK_GEOMETRY_EX*)&buffer;
int fixed = (geom->Geometry.MediaType == FixedMedia);
__int64 size = geom->DiskSize.QuadPart;
#ifdef PRINTING_TO_CONSOLE_ALLOWED
printf("\n**** DISK_GEOMETRY_EX for drive %d ****\n"
"Disk is%s fixed\n" "DiskSize = %I64d\n", drive, fixed ? "" :
" NOT", size);
#endif
}
}
else {
DWORD err = GetLastError();
#ifdef PRINTING_TO_CONSOLE_ALLOWED
printf("\nDeviceIOControl IOCTL_STORAGE_QUERY_PROPERTY error = %d\n",
err);
#endif
}
CloseHandle(hPhysicalDriveIOCTL);
}
}
return done;
}

void __fastcall TForm1::_btn1Click(TObject *Sender)
{
// please search "hugh" to see what i added,and you can modify for fitting yours
TStringList *info = new TStringList;
ReadPhysicalDriveInNTWithZeroRights(info);
delete info;
}

[/code]


------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2013-02-26 21:53:09, 註解 無‧
xiaolaba
一般會員


發表:10
回覆:17
積分:5
註冊:2010-05-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2013-02-27 22:41:43 IP:42.2.xxx.xxx 訂閱
實在謝謝你 蕭沖大大

記得不久前也是你給俺的另外一個答案

俺有電腦時安裝的 Visual studio 2012 的, 但是 CB6就不明白是什麼軟件

這麼長, 俺可以研究好一陣子了
------
http://xiaolaba.wordpress.com
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2013-02-28 18:16:16 IP:114.42.xxx.xxx 訂閱
別客氣,

若你是vs2012,那麼應該把 TStringList的參數與相關內容刪除即可以跑。

TStringList是 delphi/cb 才有的東西,其它的部份應該可以在vc上跑。

===================引 用 xiaolaba 文 章===================
實在謝謝你 蕭沖大大

記得不久前也是你給俺的另外一個答案

俺有電腦時安裝的 Visual studio 2012 的, 但是 CB6就不明白是什麼軟件

這麼長, 俺可以研究好一陣子了
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
Ktop_Robot
站務副站長


發表:0
回覆:3511
積分:0
註冊:2007-04-17

發送簡訊給我
#5 引用回覆 回覆 發表時間:2013-03-11 19:44:47 IP:000.000.xxx.xxx 未訂閱
提問者您好:


以上回應是否已得到滿意的答覆?


若已得到滿意的答覆,請在一週內結案,否則請在一週內回覆還有什麼未盡事宜,不然,
將由版主(尚無版主之區域將由副站長或站長)自由心證,選擇較合適之解答予以結案處理,
被選上之答題者同樣會有加分獎勵同時發問者將受到扣 1 分的處分。不便之處,請見諒。


有問有答有結案,才能有良性的互動,良好的討論環境需要大家共同維護,感謝您的配合。

------
我是機器人,我不接受簡訊.
系統時間:2024-04-23 17:39:25
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!