最近学习scsi和DeviceIoControl,下载了微软WDK一些例子,以下代码精简自Windows-driver-samples-master\storage\tools\spti\src\spti.c ,略有修改。

#include <windows.h>
#include <stdio.h>
#include <strsafe.h> void QueryPropertyForDevice(HANDLE);
void PrintDeviceDescriptor(PSTORAGE_DEVICE_DESCRIPTOR); int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Usage: %s \n", argv[0] );
printf("Examples:\n");
printf(" %s g: (PrintDeviceDescriptor)\n", 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\n",
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("\n ***** STORAGE DEVICE DESCRIPTOR DATA *****");
printf(" Version: %08x\n"
" TotalSize: %08x\n"
" DeviceType: %08x\n"
" DeviceTypeModifier: %08x\n"
" RemovableMedia: %s\n"
" CommandQueueing: %s\n"
" Vendor Id: %s\n"
" Product Id: %s\n"
" Product Revision: %s\n"
" Serial Number: %s\n"
" Bus Type: %s\n",
DeviceDescriptor->Version,
DeviceDescriptor->Size,
DeviceDescriptor->DeviceType,
DeviceDescriptor->DeviceTypeModifier,
BOOLEAN_TO_STRING(DeviceDescriptor->RemovableMedia),
BOOLEAN_TO_STRING(DeviceDescriptor->CommandQueueing),
vendorId,
productId,
productRevision,
serialNumber,
busType); printf("\n");
}

参考链接:

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

指定盘符获取u盘PID、VID、序列号等信息的更多相关文章

  1. C#通过盘符获取剩余空间

    public static long GetHardDiskSpace(string str_HardDiskName) { ; str_HardDiskName = str_HardDiskName ...

  2. 学习1__STM32--FatFS之逻辑盘符与物理盘符

    FatFS源代码中的函数逻辑关系 第一 调用函数 f_mount() result = f_mount(&fs, FS_VOLUME_NAND, ); /* Mount a logical d ...

  3. 外网远程顶级域名连接群晖的WebDAV文件服务映射盘符

       外网远程顶级域名连接群晖的WebDAV文件服务映射盘符 https://www.cnblogs.com/delphixx/p/11846546.html 电子文件管理规范   1.手机拍照截屏 ...

  4. Win10 隐藏盘符

    1.隐藏盘符 打开磁盘管理 -> 对要隐藏的盘符单击右键 -> 更改驱动器号和路径 -> 删除. 打开资源管理,已经看不到该盘符,该盘符已被隐藏.只是隐藏,该盘符上的数据仍然还在. ...

  5. REM 根据卷标搜索随身固态U盘的盘符.BAT

    REM 根据卷标搜索随身固态U盘的盘符.BAT@echo offfor /f "tokens=2 delims==" %%a in ('wmic logicaldisk where ...

  6. 打开随身U盘_办公专用盘 2019年11月29日

    ;;; ; 打开随身U盘_办公专用盘 2019年11月29日 ; https://www.autoahk.com/?p=16553; https://www.cnblogs.com/delphixx/ ...

  7. 批处理bat命令--获取当前盘符和当前目录和上级目录

    批处理bat命令--获取当前盘符和当前目录和上级目录 批处理命令获取当前盘符和当前目录%~d0 是当前盘符%cd% 是当前目录可以用echo %cd%进行打印测试 以下例子是命令行编译Visual S ...

  8. java web实现读取指定盘符下的图像(二)

    之前写了一篇文章是关于如何读取指定盘符下的图片,虽然功能可以实现,但是使用的是I/O流的方式,效率不高.现在发现还有一个更好的办法,使用也更加的方便. 我们知道,当我们的图片是放在tomcat下web ...

  9. NSIS:获取硬盘中容量最大的分区盘符

    原文 NSIS:获取硬盘中容量最大的分区盘符 我们在安装一些在线视频软件比如迅雷看看时,会发现他们的安装程序会自动判断当前系统中容量最大的分区,以便在其中创建数据缓冲下载的文件夹,这种功能如果实现呢, ...

随机推荐

  1. 嵌入式编程中使用 do{...} while(0) 的解释

    最近在看esp32的idf,有一些宏定义使用了do while(0)这种看起来好像没啥用的代码.然后我查了一下资料,发现在linux内核代码中经常用到这个东西! 现在就将这个东西整理一下. 为什么在内 ...

  2. SpringMVC 注解配置

    使用注解配置spring  mvc (1)spring mvc的配置文件 <?xml version="1.0" encoding="UTF-8"?> ...

  3. Spring之IOC、AOP和事务

    IOC 什么是IOC?如果你回答:Spring是个IOC容器,实现原理是反射,没了.这样证明你没有真正理解IOC. IOC的意思是控制反转,还有个外号叫依赖注入(DI).为什么起这么晦涩难懂的名字呢? ...

  4. 面试题之第一部分(Python基础篇) 80题

    第一部分(python基础篇)80题 为什么学习Python?==*== # 1. python应用于很多领域,比如后端,前端,爬虫,机器学习(人工智能)等方面,几乎能涵盖各个开发语言的领域,同时它相 ...

  5. Jquery - ajax url路径问题

    Jquery - ajax url路径问题 2016年04月26日 09:59:27 yuxuac 阅读数 32308    版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...

  6. 神机iPhone6停产,苹果产业链应该感谢它还是痛恨它?

    据国内媒体报道,一些苹果上游供应商已经接到通知,iPhone6系列将会在5月底彻底停产,一时间,竟在网络上引发汹涌的怀念之情.iPhone6的特别之处在于它是苹果第一款大屏幕的智能手机,标志着库克彻底 ...

  7. Vue - 路由守卫使用

    import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.us ...

  8. 「AT1983 BBQ Hard」

    呦,来一次久违的BBQ吧! AT题...日本的题库质量一向很高 这题是有关组合数的DP... 前置芝士 快速计算组合数,具体还是自行百度. 膜域下的除法. 具体做法 题目中的问题: \(\sum_{i ...

  9. linux环境下安装solr

    1.上传并解压solr文件 2.将solr解压缩包的dist/solr-4.10.3.war包部署到tomcat下.并改名为solr.war 3.解压war包(启动tomcat后会自动解压war包) ...

  10. 6、mysql事务

    1.mysql事务 —mysql中,事务其实是一个最小的不可分割的工作单元.事务能够保证一个业务的完整性,例如:银行存款: a  - >    -100 >update user set ...