指定盘符获取u盘PID、VID、序列号等信息

最近学习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

原文地址:https://www.cnblogs.com/sherlock-merlin/p/11074666.html