最近学习scsi和DeviceIoControl,下载了微软WDK一些例子,以下代码精简自Windows-driver-samples-masterstorage oolssptisrcspti.c ,略有修改。
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#include <winioctl.h>
void QueryPropertyForDevice(HANDLE);
void PrintDeviceDescriptor(PSTORAGE_DEVICE_DESCRIPTOR);
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Usage: %s
", argv[0] );
printf("Examples:
");
printf(" %s g: (PrintDeviceDescriptor)
", argv[0]);
}
char filepath[7];
StringCbPrintf(filepath, sizeof(filepath), "\\.\%s", argv[1]);
HANDLE hDevice = CreateFile(filepath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
unsigned long errorCode = GetLastError();
printf("Error opening %s. Error: %d
",
filepath, errorCode);
return errorCode;
}
QueryPropertyForDevice(hDevice);
CloseHandle(hDevice);
return 0;
}
#define BOOLEAN_TO_STRING(_b_)
( (_b_) ? "True" : "False" )
LPCSTR BusTypeStrings[] = {
"Unknown",
"Scsi",
"Atapi",
"Ata",
"1394",
"Ssa",
"Fibre",
"Usb",
"RAID",
"Not Defined",
};
#define NUMBER_OF_BUS_TYPE_STRINGS (sizeof(BusTypeStrings)/sizeof(BusTypeStrings[0]))
void QueryPropertyForDevice(HANDLE hDevice)
{
bool result;
DWORD readed;
STORAGE_DESCRIPTOR_HEADER *DeviceDescriptorHeader;
STORAGE_DEVICE_DESCRIPTOR *DeviceDescriptor;
DWORD devDescLength;
STORAGE_PROPERTY_QUERY query;
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
DeviceDescriptorHeader = (STORAGE_DESCRIPTOR_HEADER *) malloc( sizeof(STORAGE_DESCRIPTOR_HEADER) );
result = DeviceIoControl( hDevice, // device to be queried
IOCTL_STORAGE_QUERY_PROPERTY, // operation to perform
&query, sizeof(query), // no input buffer
DeviceDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), // output buffer
&readed, // # bytes returned
NULL ); // synchronous I/O
devDescLength = DeviceDescriptorHeader->Size;
DeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR *) malloc( devDescLength );
result = DeviceIoControl( hDevice, // device to be queried
IOCTL_STORAGE_QUERY_PROPERTY, // operation to perform
&query, sizeof(query), // no input buffer
DeviceDescriptor, devDescLength, // output buffer
&readed, // # bytes returned
NULL ); // synchronous I/O
PrintDeviceDescriptor(DeviceDescriptor);
free(DeviceDescriptorHeader);
free(DeviceDescriptor);
}
void PrintDeviceDescriptor(PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor)
{
LPCSTR vendorId = "";
LPCSTR productId = "";
LPCSTR productRevision = "";
LPCSTR serialNumber = "";
LPCSTR busType;
if ((ULONG)DeviceDescriptor->BusType < NUMBER_OF_BUS_TYPE_STRINGS) {
busType = BusTypeStrings[DeviceDescriptor->BusType];
} else {
busType = BusTypeStrings[NUMBER_OF_BUS_TYPE_STRINGS-1];
}
if ((DeviceDescriptor->ProductIdOffset != 0) &&
(DeviceDescriptor->ProductIdOffset != -1)) {
productId = (LPCSTR)(DeviceDescriptor);
productId += (ULONG_PTR)DeviceDescriptor->ProductIdOffset;
}
if ((DeviceDescriptor->VendorIdOffset != 0) &&
(DeviceDescriptor->VendorIdOffset != -1)) {
vendorId = (LPCSTR)(DeviceDescriptor);
vendorId += (ULONG_PTR)DeviceDescriptor->VendorIdOffset;
}
if ((DeviceDescriptor->ProductRevisionOffset != 0) &&
(DeviceDescriptor->ProductRevisionOffset != -1)) {
productRevision = (LPCSTR)(DeviceDescriptor);
productRevision += (ULONG_PTR)DeviceDescriptor->ProductRevisionOffset;
}
if ((DeviceDescriptor->SerialNumberOffset != 0) &&
(DeviceDescriptor->SerialNumberOffset != -1)) {
serialNumber = (LPCSTR)(DeviceDescriptor);
serialNumber += (ULONG_PTR)DeviceDescriptor->SerialNumberOffset;
}
puts("
***** STORAGE DEVICE DESCRIPTOR DATA *****");
printf(" Version: %08x
"
" TotalSize: %08x
"
" DeviceType: %08x
"
" DeviceTypeModifier: %08x
"
" RemovableMedia: %s
"
" CommandQueueing: %s
"
" Vendor Id: %s
"
" Product Id: %s
"
" Product Revision: %s
"
" Serial Number: %s
"
" Bus Type: %s
",
DeviceDescriptor->Version,
DeviceDescriptor->Size,
DeviceDescriptor->DeviceType,
DeviceDescriptor->DeviceTypeModifier,
BOOLEAN_TO_STRING(DeviceDescriptor->RemovableMedia),
BOOLEAN_TO_STRING(DeviceDescriptor->CommandQueueing),
vendorId,
productId,
productRevision,
serialNumber,
busType);
printf("
");
}
参考链接:
https://www.cnblogs.com/shangdawei/p/3164005.html
c#参考
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace ConsoleApplication2
{
class Program
{
const uint GENERIC_READ = 0x80000000;
const uint GENERIC_WRITE = 0x40000000;
const uint FILE_SHARE_READ = 1;
const uint FILE_SHARE_WRITE = 2;
const uint OPEN_EXISTING = 3;
const int IOCTL_STORAGE_QUERY_PROPERTY = 2954240;
public enum STORAGE_PROPERTY_ID
{
StorageDeviceProperty = 0,
StorageAdapterProperty = 1,
StorageDeviceIdProperty = 2,
StorageDeviceUniqueIdProperty = 3,
StorageDeviceWriteCacheProperty = 4,
StorageMiniportProperty = 5,
StorageAccessAlignmentProperty = 6,
StorageDeviceSeekPenaltyProperty = 7,
StorageDeviceTrimProperty = 8,
StorageDeviceWriteAggregationProperty = 9,
StorageDeviceDeviceTelemetryProperty = 10, // 0xA
StorageDeviceLBProvisioningProperty = 11, // 0xB
StorageDevicePowerProperty = 12, // 0xC
StorageDeviceCopyOffloadProperty = 13, // 0xD
StorageDeviceResiliencyProperty = 14 // 0xE
}
public enum STORAGE_QUERY_TYPE
{
PropertyStandardQuery = 0,
PropertyExistsQuery = 1,
PropertyMaskQuery = 2,
PropertyQueryMaxDefined = 3
}
[StructLayout(LayoutKind.Sequential)]
public struct STORAGE_PROPERTY_QUERY
{
public STORAGE_PROPERTY_ID PropertyId;
public STORAGE_QUERY_TYPE QueryType;
public byte[] AdditionalParameters;
}
public enum STORAGE_BUS_TYPE
{
BusTypeUnknown = 0x00,
BusTypeScsi = 0x1,
BusTypeAtapi = 0x2,
BusTypeAta = 0x3,
BusType1394 = 0x4,
BusTypeSsa = 0x5,
BusTypeFibre = 0x6,
BusTypeUsb = 0x7,
BusTypeRAID = 0x8,
BusTypeiScsi = 0x9,
BusTypeSas = 0xA,
BusTypeSata = 0xB,
BusTypeSd = 0xC,
BusTypeMmc = 0xD,
BusTypeVirtual = 0xE,
BusTypeFileBackedVirtual = 0xF,
BusTypeMax = 0x10,
BusTypeMaxReserved = 0x7F
}
public struct STORAGE_DESCRIPTOR_HEADER
{
public int Version;
public int Size;
}
public struct STORAGE_DEVICE_DESCRIPTOR
{
public uint Version;
public uint Size;
public byte DeviceType;
public byte DeviceTypeModifier;
[MarshalAs(UnmanagedType.U1)]
public bool RemovableMedia;
[MarshalAs(UnmanagedType.U1)]
public bool CommandQueueing;
public uint VendorIdOffset;
public uint ProductIdOffset;
public uint ProductRevisionOffset;
public uint SerialNumberOffset;
public STORAGE_BUS_TYPE BusType;
public uint RawPropertiesLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
public byte[] RawDeviceProperties;
}
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
int IoControlCode,
byte[] InBuffer,
int nInBufferSize,
byte[] OutBuffer,
int nOutBufferSize,
out int pBytesReturned,
IntPtr Overlapped
);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(
int hDevice,
int IoControlCode,
ref STORAGE_PROPERTY_QUERY InBuffer,
int nInBufferSize,
out STORAGE_DESCRIPTOR_HEADER OutBuffer,
int nOutBufferSize,
out int pBytesReturned,
IntPtr Overlapped
);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(
int hDevice,
int IoControlCode,
ref STORAGE_PROPERTY_QUERY InBuffer,
int nInBufferSize,
out STORAGE_DEVICE_DESCRIPTOR OutBuffer,
int nOutBufferSize,
out int pBytesReturned,
IntPtr Overlapped
);
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
static extern unsafe int CreateFile
(
string FileName, // file name
uint DesiredAccess, // access mode
uint ShareMode, // share mode
uint SecurityAttributes, // Security Attributes
uint CreationDisposition, // how to create
uint FlagsAndAttributes, // file attributes
int hTemplateFile // handle to template file
);
static void Main(string[] args)
{
var query = new STORAGE_PROPERTY_QUERY {};
var qsize = Marshal.SizeOf(query);
var header = new STORAGE_DESCRIPTOR_HEADER { };
var hsize = Marshal.SizeOf(header);
var descriptor = new STORAGE_DEVICE_DESCRIPTOR { };
var rsize = Marshal.SizeOf(descriptor);
int written;
var hDev = CreateFile("\\.\H:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
DeviceIoControl(hDev, IOCTL_STORAGE_QUERY_PROPERTY, ref query, qsize, out header, hsize, out written, IntPtr.Zero);
DeviceIoControl(hDev, IOCTL_STORAGE_QUERY_PROPERTY, ref query, qsize, out descriptor, header.Size, out written, IntPtr.Zero);
IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(descriptor));
Marshal.StructureToPtr(descriptor, intptr, true);
var productId = Marshal.PtrToStringAnsi(new IntPtr((long)intptr + descriptor.ProductIdOffset));
var vendorId = Marshal.PtrToStringAnsi(new IntPtr((long)intptr + descriptor.VendorIdOffset));
var productRevision = Marshal.PtrToStringAnsi(new IntPtr((long)intptr + descriptor.ProductRevisionOffset));
var serialnumver = Marshal.PtrToStringAnsi(new IntPtr((long)intptr + descriptor.SerialNumberOffset));
//Console.WriteLine(Convert.ToUInt32(EIOControlCode.StorageQueryProperty));
Console.WriteLine();
Console.WriteLine(" Version: " + descriptor.Version);
Console.WriteLine(" Size: " + descriptor.Size);
Console.WriteLine(" DeviceType: " + descriptor.DeviceType);
Console.WriteLine(" DeviceTypeModifier: " + descriptor.DeviceTypeModifier);
Console.WriteLine(" RemovableMedia: " + descriptor.RemovableMedia);
Console.WriteLine(" CommandQueueing: " + descriptor.CommandQueueing);
Console.WriteLine(" Vendor Id: " + vendorId);
Console.WriteLine(" productId: " + productId);
Console.WriteLine(" productRevision: " + productRevision);
Console.WriteLine(" SerialNumber: " + serialnumver);
Console.WriteLine(" BusType: " + descriptor.BusType);
Console.ReadLine();
}
}
}
参考链接
http://www.pinvoke.net/default.aspx/Structures/STORAGE_DEVICE_DESCRIPTOR.html
https://stackoverflow.com/questions/17268889/pinvoke-deviceiocontrol-parameters