读取光驱driver信息 的方法
来源:互联网 发布:dlp数据防泄密软件 编辑:程序博客网 时间:2024/04/30 05:32
使用 SCSI cmd获得driver信息
主要有下面2个文件:scsi_struct.h
2: main.cpp
以上只是简单的获得了driver的vendorID, productID,productversion 信息,至于其他信息可以通过同样的方法 获得,不过命令有所区别,具体请参阅MSDN DeviceIoControl 章节
主要有下面2个文件:scsi_struct.h
//------------------------scsi_struct.h--------------------------------------
#include <windows.h>
// If this was not defined we should also assume that some structs are not defined as well
#ifndef IOCTL_SCSI_PASS_THROUGH_DIRECT
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
// Reference [2]
typedef struct _SCSI_PASS_THROUGH_DIRECT
{
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
#endif
#pragma pack(1)
/*!
Reference [1] page 528
*/
enum MMC_KEY_FORMAT_CODE_CLASS0
{
KEY_FORMAT_AGID_CSS = 0,
KEY_FORMAT_CHAL_KEY = 1,
KEY_FORMAT_KEY1 = 2,
KEY_FORMAT_TITLE_KEY = 4,
KEY_FORMAT_ASF = 5,
KEY_FORMAT_RPC_STATE = 8,
KEY_FORMAT_AGID_CPRM = 0x11,
KEY_FORMAT_NONE = 0x3F
};
/*!
The type code field specifies the current state of regionalization process
Reference [1] Table 524, page 533
*/
enum RPC_STATE_TYPE_CODES
{
//! No drive region
RPC_STATE_TYPECODE_NONE = 0,
//! Drive region is set
RPC_STATE_TYPECODE_SET = 1,
//! Drive region is set. Additional restrictions required to make changes
RPC_STATE_TYPECODE_LAST_CHANCE = 2,
//! Drive region has been set permamently, but may be reset by vendor
RPC_STATE_TYPECODE_PERM = 3
};
/*!
RPC Scheme specifies the type of Region Playback Controls being used by the Drive
*/
enum RPC_STATE_SCHEMES
{
//!Drive does not enforce Region Playback Controls (RPC)
RPC_STATE_SCHEMES_UNK = 0,
/*!
Drive region shall adhere to this standard and all requirements of the CSS
license agreement concerning RPC.
*/
RPC_STATE_SCHEMES_RPC2 = 1
};
/*!
This structure is returned when a REPORT_KEY is executed with key type = 8
Reference [1]p.533
*/
typedef struct _REPORT_KEY_DATA_RPC_STATE
{
char rsvrd1[4];
//
// RPC state
//
/*!
# of User Controlled Changes Available is a count down counter that indicates the number of times that the user
may set the region. This value is initially 5.
*/
unsigned char nb_user_changes: 3;
/*!
# of Vendor Resets Available is a count down counter that indicates the number of times that the vendor may
reset the region. The manufacturer of the Drive sets this value to 4 and the value is decremented each time the
vendor clears the Drives region. When this value is zero, the vendor may no longer clear the Drives region.
*/
unsigned char nb_vendor_resets: 3;
unsigned char type_code: 2;
/*!
The Region Mask returns a value that specifies the Drive Region in which the Drive is located. Once the Drive
Region has been set, the Drive shall be located in only one region. Each bit represents one of eight regions. If a
bit is cleared in this field, the disc may be played in the corresponding region. If a bit is set in this field, the disc
may not be played in the corresponding region.
*/
unsigned char region_mask;
/*
RPC Scheme specifies the type of Region Playback Controls being used by the Drive
*/
unsigned char rpc_scheme;
char rsvrd2;
} REPORT_KEY_DATA_RPC_STATE;
typedef struct _SCSI_INQUIRY_STD_DATA
{
UCHAR preipheral_device_type : 5;
UCHAR peripheral_qualifier: 3;
UCHAR rsvrd : 7;
UCHAR rmb: 1;
UCHAR version;
UCHAR RESPONSE_DATA_FORMAT; // 7 = AERC, 6 = Obsolete, 5 = NormACA, 4 = HiSup 3-0 = Response data format.
// If ANSI Version = 0, this is ATAPI and bits 7-4 = ATAPI version.
UCHAR ADDITIONAL_LENGTH; // Number of additional bytes available in inquiry data
UCHAR SCCSReserved; // SCC-2 device flag and reserved fields
UCHAR flags1; // First byte of support flags
UCHAR flags2; // Second byte of support flags (Byte 7)
char vendor_id[8];
char product_id[16];
char product_revision_level[4];
} SCSI_INQUIRY_STD_DATA;
#ifndef SCSIOP_INQUIRY
// Reference [2]
#define SCSIOP_INQUIRY 0x12
#define SCSIOP_REPORT_KEY 0xA4
// Reference [2]
typedef struct _CDB_INQUIRY
{
UCHAR OperationCode6; // 0x12 - SCSIOP_INQUIRY
UCHAR Reserved1 : 5;
UCHAR LogicalUnitNumber : 3;
UCHAR PageCode;
UCHAR IReserved;
UCHAR AllocationLength;
UCHAR Control;
} CDB_INQUIRY6;
// Reference [2]
typedef struct _CDB_REPORT_KEY
{
UCHAR OperationCode; // 0xA4 - SCSIOP_REPORT_KEY
UCHAR Reserved1 : 5;
UCHAR Lun : 3;
UCHAR LogicalBlockAddress[4]; // for title key
UCHAR Reserved2[2];
USHORT AllocationLength;
UCHAR KeyFormat : 6;
UCHAR AGID : 2;
UCHAR Control;
} CDB_REPORT_KEY;
#endif
#pragma pack()
#include <windows.h>
// If this was not defined we should also assume that some structs are not defined as well
#ifndef IOCTL_SCSI_PASS_THROUGH_DIRECT
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
// Reference [2]
typedef struct _SCSI_PASS_THROUGH_DIRECT
{
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
#endif
#pragma pack(1)
/*!
Reference [1] page 528
*/
enum MMC_KEY_FORMAT_CODE_CLASS0
{
KEY_FORMAT_AGID_CSS = 0,
KEY_FORMAT_CHAL_KEY = 1,
KEY_FORMAT_KEY1 = 2,
KEY_FORMAT_TITLE_KEY = 4,
KEY_FORMAT_ASF = 5,
KEY_FORMAT_RPC_STATE = 8,
KEY_FORMAT_AGID_CPRM = 0x11,
KEY_FORMAT_NONE = 0x3F
};
/*!
The type code field specifies the current state of regionalization process
Reference [1] Table 524, page 533
*/
enum RPC_STATE_TYPE_CODES
{
//! No drive region
RPC_STATE_TYPECODE_NONE = 0,
//! Drive region is set
RPC_STATE_TYPECODE_SET = 1,
//! Drive region is set. Additional restrictions required to make changes
RPC_STATE_TYPECODE_LAST_CHANCE = 2,
//! Drive region has been set permamently, but may be reset by vendor
RPC_STATE_TYPECODE_PERM = 3
};
/*!
RPC Scheme specifies the type of Region Playback Controls being used by the Drive
*/
enum RPC_STATE_SCHEMES
{
//!Drive does not enforce Region Playback Controls (RPC)
RPC_STATE_SCHEMES_UNK = 0,
/*!
Drive region shall adhere to this standard and all requirements of the CSS
license agreement concerning RPC.
*/
RPC_STATE_SCHEMES_RPC2 = 1
};
/*!
This structure is returned when a REPORT_KEY is executed with key type = 8
Reference [1]p.533
*/
typedef struct _REPORT_KEY_DATA_RPC_STATE
{
char rsvrd1[4];
//
// RPC state
//
/*!
# of User Controlled Changes Available is a count down counter that indicates the number of times that the user
may set the region. This value is initially 5.
*/
unsigned char nb_user_changes: 3;
/*!
# of Vendor Resets Available is a count down counter that indicates the number of times that the vendor may
reset the region. The manufacturer of the Drive sets this value to 4 and the value is decremented each time the
vendor clears the Drives region. When this value is zero, the vendor may no longer clear the Drives region.
*/
unsigned char nb_vendor_resets: 3;
unsigned char type_code: 2;
/*!
The Region Mask returns a value that specifies the Drive Region in which the Drive is located. Once the Drive
Region has been set, the Drive shall be located in only one region. Each bit represents one of eight regions. If a
bit is cleared in this field, the disc may be played in the corresponding region. If a bit is set in this field, the disc
may not be played in the corresponding region.
*/
unsigned char region_mask;
/*
RPC Scheme specifies the type of Region Playback Controls being used by the Drive
*/
unsigned char rpc_scheme;
char rsvrd2;
} REPORT_KEY_DATA_RPC_STATE;
typedef struct _SCSI_INQUIRY_STD_DATA
{
UCHAR preipheral_device_type : 5;
UCHAR peripheral_qualifier: 3;
UCHAR rsvrd : 7;
UCHAR rmb: 1;
UCHAR version;
UCHAR RESPONSE_DATA_FORMAT; // 7 = AERC, 6 = Obsolete, 5 = NormACA, 4 = HiSup 3-0 = Response data format.
// If ANSI Version = 0, this is ATAPI and bits 7-4 = ATAPI version.
UCHAR ADDITIONAL_LENGTH; // Number of additional bytes available in inquiry data
UCHAR SCCSReserved; // SCC-2 device flag and reserved fields
UCHAR flags1; // First byte of support flags
UCHAR flags2; // Second byte of support flags (Byte 7)
char vendor_id[8];
char product_id[16];
char product_revision_level[4];
} SCSI_INQUIRY_STD_DATA;
#ifndef SCSIOP_INQUIRY
// Reference [2]
#define SCSIOP_INQUIRY 0x12
#define SCSIOP_REPORT_KEY 0xA4
// Reference [2]
typedef struct _CDB_INQUIRY
{
UCHAR OperationCode6; // 0x12 - SCSIOP_INQUIRY
UCHAR Reserved1 : 5;
UCHAR LogicalUnitNumber : 3;
UCHAR PageCode;
UCHAR IReserved;
UCHAR AllocationLength;
UCHAR Control;
} CDB_INQUIRY6;
// Reference [2]
typedef struct _CDB_REPORT_KEY
{
UCHAR OperationCode; // 0xA4 - SCSIOP_REPORT_KEY
UCHAR Reserved1 : 5;
UCHAR Lun : 3;
UCHAR LogicalBlockAddress[4]; // for title key
UCHAR Reserved2[2];
USHORT AllocationLength;
UCHAR KeyFormat : 6;
UCHAR AGID : 2;
UCHAR Control;
} CDB_REPORT_KEY;
#endif
#pragma pack()
2: main.cpp
#include <stdio.h>
#include <memory.h>
#include "scsi_struct.h"
#include <conio.h>
bool carry_cdb(HANDLE device, void *cdb, UCHAR cdb_length, void *buffer, DWORD buffer_length, int data_in = SCSI_IOCTL_DATA_IN)
{
DWORD returned;
// size of SCSI_PASS_THROUGH + 96 bytes for sense data
unsigned char cmd[sizeof(SCSI_PASS_THROUGH_DIRECT) + 96] = {0};
// shortcut to the buffer
SCSI_PASS_THROUGH_DIRECT *pcmd = (SCSI_PASS_THROUGH_DIRECT *) cmd;
// Copy the CDB to the SCSI_PASS_THROUGH structure
memcpy(pcmd->Cdb, cdb, cdb_length);
pcmd->DataBuffer = buffer;
pcmd->DataTransferLength = buffer_length;
pcmd->DataIn = data_in;
pcmd->CdbLength = cdb_length;
pcmd->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->SenseInfoLength = sizeof(cmd) - sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->TimeOutValue = 6000;
BOOL bRet = DeviceIoControl(
device,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
(LPVOID)&cmd,
sizeof(cmd),
(LPVOID)&cmd,
sizeof(cmd),
&returned,
NULL);
#ifdef _DEBUG
DWORD err = ::GetLastError();
if (err != ERROR_SUCCESS)
{
printf("carry_cdb(): last error = %08X ", err);
}
#endif
return bRet ? true : false;
}
void print_inquiry_info(HANDLE device)
{
CDB_INQUIRY6 inquiry = {0};
SCSI_INQUIRY_STD_DATA data = {0};
inquiry.AllocationLength = sizeof(data);
inquiry.OperationCode6 = SCSIOP_INQUIRY;
if (!carry_cdb(device, &inquiry, sizeof(inquiry), &data, sizeof(data)))
{
printf("could not inquire!");
return;
}
printf(
"Drive info: "
"----------- ");
char snip[100] = {0};
int i;
strncpy(snip, data.vendor_id, i = sizeof(data.vendor_id));
snip[i] = 0;
printf("vendor id: %s ", snip);
strncpy(snip, data.product_id , i = sizeof(data.product_id));
snip[i] = 0;
printf("product id: %s ", snip);
strncpy(snip, data.product_revision_level , i = sizeof(data.product_revision_level));
snip[i] = 0;
printf("product rev level: %s ", snip);
}
void print_region_info(HANDLE device)
{
static char *region_names[] =
{
"United States of America, Canada", // Region 1
"Europe, including France, Greece, Turkey, Egypt, Arabia, Japan and South Africa", // 2
"Korea, Thailand, Vietnam, Borneo and Indonesia", // 3
"Australia and New Zealand, Mexico, the Caribbean, and South America", // 4
"India, Africa, Russia and former USSR countries", // 5
"Peoples Republic of China", // 6
"Unused",
"Airlines/Cruise Ships",
"Expansion (often used as region free)"
};
static char *region_set[] =
{
"No region set", // 0
"Region set", // 1
"Drive region is set. Additional restrictions required to make changes", // 2
"Region set permanently, but may be reset by vendor", // 3
};
REPORT_KEY_DATA_RPC_STATE region = {0};
CDB_REPORT_KEY report = {0};
report.OperationCode = SCSIOP_REPORT_KEY;
report.AllocationLength = sizeof(REPORT_KEY_DATA_RPC_STATE);
report.AGID = 0;
report.KeyFormat = KEY_FORMAT_RPC_STATE;
if (!carry_cdb(device, &report, sizeof(report), ®ion, sizeof(region)))
{
printf("Could not get region info! ");
return;
}
unsigned char region_code = ~region.region_mask;
int i;
char *region_name = "No Region Coding";
for (i=7;i>=0;i--)
{
if ( (1 << i) & region_code)
{
region_name = region_names[i];
break;
}
}
printf(
"Region Information: "
"------------------- "
"Vendor changes: %d "
"User changes: %d "
"Region name: %s "
"Type code: %s ",
region.nb_vendor_resets,
region.nb_user_changes,
region_name,
region_set[region.type_code]
);
}
int main(int argc, char *argv[])
{
HANDLE device;
char devname[20];
if (argc < 2)
{
printf("usage %s drive", argv[0]);
return -1;
}
sprintf(devname, "//./%c:", argv[1][0]);
device = ::CreateFile(devname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if (device == (HANDLE)-1)
{
printf("Cannot open device! ");
return -1;
}
print_inquiry_info(device);
printf(" ");
print_region_info(device);
::CloseHandle(device);
printf("press any key to quit ");
getch();
return 0;
}
#include <memory.h>
#include "scsi_struct.h"
#include <conio.h>
bool carry_cdb(HANDLE device, void *cdb, UCHAR cdb_length, void *buffer, DWORD buffer_length, int data_in = SCSI_IOCTL_DATA_IN)
{
DWORD returned;
// size of SCSI_PASS_THROUGH + 96 bytes for sense data
unsigned char cmd[sizeof(SCSI_PASS_THROUGH_DIRECT) + 96] = {0};
// shortcut to the buffer
SCSI_PASS_THROUGH_DIRECT *pcmd = (SCSI_PASS_THROUGH_DIRECT *) cmd;
// Copy the CDB to the SCSI_PASS_THROUGH structure
memcpy(pcmd->Cdb, cdb, cdb_length);
pcmd->DataBuffer = buffer;
pcmd->DataTransferLength = buffer_length;
pcmd->DataIn = data_in;
pcmd->CdbLength = cdb_length;
pcmd->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->SenseInfoLength = sizeof(cmd) - sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
pcmd->TimeOutValue = 6000;
BOOL bRet = DeviceIoControl(
device,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
(LPVOID)&cmd,
sizeof(cmd),
(LPVOID)&cmd,
sizeof(cmd),
&returned,
NULL);
#ifdef _DEBUG
DWORD err = ::GetLastError();
if (err != ERROR_SUCCESS)
{
printf("carry_cdb(): last error = %08X ", err);
}
#endif
return bRet ? true : false;
}
void print_inquiry_info(HANDLE device)
{
CDB_INQUIRY6 inquiry = {0};
SCSI_INQUIRY_STD_DATA data = {0};
inquiry.AllocationLength = sizeof(data);
inquiry.OperationCode6 = SCSIOP_INQUIRY;
if (!carry_cdb(device, &inquiry, sizeof(inquiry), &data, sizeof(data)))
{
printf("could not inquire!");
return;
}
printf(
"Drive info: "
"----------- ");
char snip[100] = {0};
int i;
strncpy(snip, data.vendor_id, i = sizeof(data.vendor_id));
snip[i] = 0;
printf("vendor id: %s ", snip);
strncpy(snip, data.product_id , i = sizeof(data.product_id));
snip[i] = 0;
printf("product id: %s ", snip);
strncpy(snip, data.product_revision_level , i = sizeof(data.product_revision_level));
snip[i] = 0;
printf("product rev level: %s ", snip);
}
void print_region_info(HANDLE device)
{
static char *region_names[] =
{
"United States of America, Canada", // Region 1
"Europe, including France, Greece, Turkey, Egypt, Arabia, Japan and South Africa", // 2
"Korea, Thailand, Vietnam, Borneo and Indonesia", // 3
"Australia and New Zealand, Mexico, the Caribbean, and South America", // 4
"India, Africa, Russia and former USSR countries", // 5
"Peoples Republic of China", // 6
"Unused",
"Airlines/Cruise Ships",
"Expansion (often used as region free)"
};
static char *region_set[] =
{
"No region set", // 0
"Region set", // 1
"Drive region is set. Additional restrictions required to make changes", // 2
"Region set permanently, but may be reset by vendor", // 3
};
REPORT_KEY_DATA_RPC_STATE region = {0};
CDB_REPORT_KEY report = {0};
report.OperationCode = SCSIOP_REPORT_KEY;
report.AllocationLength = sizeof(REPORT_KEY_DATA_RPC_STATE);
report.AGID = 0;
report.KeyFormat = KEY_FORMAT_RPC_STATE;
if (!carry_cdb(device, &report, sizeof(report), ®ion, sizeof(region)))
{
printf("Could not get region info! ");
return;
}
unsigned char region_code = ~region.region_mask;
int i;
char *region_name = "No Region Coding";
for (i=7;i>=0;i--)
{
if ( (1 << i) & region_code)
{
region_name = region_names[i];
break;
}
}
printf(
"Region Information: "
"------------------- "
"Vendor changes: %d "
"User changes: %d "
"Region name: %s "
"Type code: %s ",
region.nb_vendor_resets,
region.nb_user_changes,
region_name,
region_set[region.type_code]
);
}
int main(int argc, char *argv[])
{
HANDLE device;
char devname[20];
if (argc < 2)
{
printf("usage %s drive", argv[0]);
return -1;
}
sprintf(devname, "//./%c:", argv[1][0]);
device = ::CreateFile(devname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if (device == (HANDLE)-1)
{
printf("Cannot open device! ");
return -1;
}
print_inquiry_info(device);
printf(" ");
print_region_info(device);
::CloseHandle(device);
printf("press any key to quit ");
getch();
return 0;
}
以上只是简单的获得了driver的vendorID, productID,productversion 信息,至于其他信息可以通过同样的方法 获得,不过命令有所区别,具体请参阅MSDN DeviceIoControl 章节
- 读取光驱driver信息 的方法
- linux读取ISO文件或是光驱的方法--挂载
- linux读取ISO文件或是光驱的方法--挂载
- 打开、关闭光驱的方法
- 设置光驱启动的方法
- 读取光驱上的指定扇区
- 读取,写入properties信息的方法
- Windows 下读取DMI信息的方法
- linux下读取dmi信息的方法
- Windows 下读取DMI信息的方法
- DOS下使用光驱的方法
- 笔记本光驱不读盘的应急处理方法
- 鲜为人知的光驱拆卸方法介绍
- 找了些如何获取光驱信息的帖子
- 光驱无法识别,提示注册表信息不完整的解决办法
- 用C#读取图片的EXIF信息的方法
- 用C#读取图片的EXIF信息的方法(一)
- 用C#读取图片的EXIF信息的方法(一)
- 昨日京城随想
- 打雷了,下雨收衣服了-网络视频即将被管制
- 开始新的旅程!
- test
- 开贴
- 读取光驱driver信息 的方法
- 只有550行的TCL解释器--C语言源程序
- 用OpenSSL编写SSL,TLS程序 - Win32版
- 今天心情
- 听来的故事
- 把程序输出信息加到系统日志里去
- 昨天的面试
- VC中打印程序的分析
- 最近的读书计划-思考中医