Search code examples
windowsdevice-drivercreatefile

How to open device driver for IOCTL


I am trying to open a device driver in order to send it an ioctl. There are many examples on SO and elsewhere but virtually all address opening "\\.\PhysicalDrive0" or the like. But I am trying to open a non-disk driver, compiled from Microsoft sample code at GitHub "Windows-driver-samples", namely "simgpio". It appears to have installed correctly but I don't know what "\\.\name" to use. I tried "\\.\simgpio" with no joy. Suggestions?

For reference, I've included the driver's .INF file below.

;/*++
;
;Copyright (c) Microsoft Corporation.  All rights reserved.
;
;Module Name:
;
;    SIMGPIO.INF
;
;Abstract:
;    INF file for installing Simulated GPIO Client Driver.
;
;--*/

[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%ProviderName%
DriverVer = 06/30/2020,15.29.58.35
CatalogFile=gpiosamples.cat

[SourceDisksNames]
3426=windows cd

[SourceDisksFiles]
simgpio.sys = 3426

[DestinationDirs]
DefaultDestDir = 12

[ControlFlags]
BasicDriverOk = *
ExcludeFromSelect = *

;******************************************
; SIMGPIO Client driver Install Section
;******************************************

[Manufacturer]
%ManufacturerName%=Standard,NTx86

[Standard.NTx86]
%GPIO.DeviceDesc% = GPIO_Inst,ACPI\TEST0001

[GPIO_Inst.NT]
Copyfiles = GPIOCopyFiles

[GPIOCopyFiles]
simgpio.sys,,,0x100

[GPIO_Inst.NT.Services]
AddService = simgpio,%SPSVCINST_ASSOCSERVICE%,GPIO_Service_Inst

[GPIO_Service_Inst]
DisplayName    = %GPIO.SvcDesc%
ServiceType    = %SERVICE_KERNEL_DRIVER%
StartType      = %SERVICE_DEMAND_START%
ErrorControl   = %SERVICE_ERROR_NORMAL%
ServiceBinary  = %12%\simgpio.sys

[strings]
; localizable strings
ProviderName        = "TODO-Set-Provider"
ManufacturerName    = "TODO-Set-Manufacturer"
GPIO.DeviceDesc     = "Simulated GPIO Client Driver"
GPIO.SvcDesc        = "Simulated GPIO Client Driver"

; non-localizable strings
SPSVCINST_TAGTOFRONT   = 0x00000003
SPSVCINST_ASSOCSERVICE = 0x00000002
SERVICE_KERNEL_DRIVER  = 1
SERVICE_BOOT_START     = 0
SERVICE_SYSTEM_START   = 1
SERVICE_DEMAND_START   = 3
SERVICE_ERROR_NORMAL   = 1
SERVICE_ERROR_IGNORE   = 0
SERVICE_ERROR_CRITICAL = 3
REG_EXPAND_SZ          = 0x00020000
REG_DWORD              = 0x00010001
REG_SZ                 = 0x00000000

Solution

  • Thanks to comment by @Eryk, I was able to open a driver. I include a sample program below. All error checking was omitted for clarity. I used the CDROM driver class in this example. The real challenge is finding the elusive GUID to use - you must do some deep digging in the SDK, DDK, include files or your driver.

    //  enumdevices.c - enumerate and open device(s)
    
    #pragma warning( disable : 4090 )
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    #include <setupapi.h>
    #include <cfgmgr32.h>
    
    int
    main( int argc,char** argv)
    {
        #define ALLOC(size)  GlobalAlloc( GPTR, size)
    
        SP_DEVINFO_DATA *devData;
        HANDLE devSet;
        HANDLE hDev;
        SP_DEVICE_INTERFACE_DATA *devIfData;
        SP_DEVICE_INTERFACE_DETAIL_DATA *Details;
        GUID *devGuid;
        DWORD needed;
        DWORD unused;
        int count;          // count of enumerated devices
        DWORD idev;         // device index
        DWORD iface;        // interface index
        char deviceID[200]; // device id string
        int IDSize;
        BOOL ok;
    
        devData = ALLOC(  sizeof(SP_DEVINFO_DATA) );
        devData->cbSize = sizeof(SP_DEVINFO_DATA);
    
        // GET SET OF DEVICE INTERFACES PRESENT OF SPECIFIED devGuid
        devGuid = &GUID_DEVINTERFACE_CDROM;     // set dev class guid to enumerate
        devSet = SetupDiGetClassDevs( devGuid, NULL, NULL, DIGCF_DEVICEINTERFACE|DIGCF_PRESENT );
    
        // OUTER LOOP
        idev  = 0;
        count = 0;
        while( TRUE ) {
            // GET DEVICE INFO DATA
            ok = SetupDiEnumDeviceInfo( devSet, idev, devData );
            if (!ok) break;
            
            // GET ID SIZE
            devData->cbSize = sizeof(SP_DEVINFO_DATA);
            CM_Get_Device_ID_Size( &IDSize, devData->DevInst, 0 );
    
            // GET DEVICE ID
            CM_Get_Device_ID( devData->DevInst, deviceID, 200, 0 );
            printf("Device Instance #%d: deviceId = \"%s\"\n", devData->DevInst, deviceID ); // print it
            count++;
    
            devIfData = ALLOC( sizeof(SP_DEVICE_INTERFACE_DATA) );
            devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
            iface = 0;                                  // init index
            while ( TRUE ) {                            // loop over all interfaces in set
                // GET DEVICE INTERFACE DATA index=iface
                ok = SetupDiEnumDeviceInterfaces(
                    devSet,                 // handle to interface set
                    devData,
                    devGuid, //&GUID_DEVINTERFACE_USB_DEVICE, 
                    iface,                              // interface index
                    devIfData);
                if( !ok ) break;
    
                // GET NEEDED BUFFER SIZE
                devIfData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                ok = SetupDiGetDeviceInterfaceDetail(
                    devSet,
                    devIfData,
                    NULL,
                    0,
                    &needed,
                    0 );
    
                Details = ALLOC( needed );
                Details->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);  // IMPORTANT!
    
                // GET DEVICE DETAILS
                ok = SetupDiGetDeviceInterfaceDetail(
                    devSet,                 // device set
                    devIfData,              // device info data
                    Details,                // detail data
                    needed,                 // size of Details
                    &unused,                // unused
                    NULL );                 // device info data (can be NULL)
                printf("%s\n", Details->DevicePath);        // announce
    
                // OPEN DEVICE
                hDev = CreateFile(Details->DevicePath,
                    GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                    NULL, OPEN_EXISTING, 0, NULL);
                if( hDev != INVALID_HANDLE_VALUE ) {
                  printf( "Device successfully opened\n" );
                  // DO SOMETHING WITH DEVICE HANDLE (e.g., DeviceIoControl)...
                  CloseHandle(hDev);
                }
    
                iface++;
            }
    
            idev++;     // next device
        }
        
        printf("\nenumerated %d device interfaces\n", count);
        fprintf(stderr, "Press any key to exit...\n");
        _getch();
    }
    

    Here are some other GUIDs you can use:

    static GUID GUID_DEVINTERFACE_DISK =  
    { 0x4d36e967L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
    static GUID GUID_DEVINTERFACE_USB_DEVICE =
    { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };  
    static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER =  
    { 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27} };  
    static GUID GUID_DEVINTERFACE_USB_HUB =
    { 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };