windowsdriverkmdfplug-and-playwindows-application-driver

How to write an application to control a driver which is pnp and in kmdf?


so I will detail so that we can easily understand

I have to make a driver for a pcie card, I already have the driver that I wrote in kmdf, now I am using this driver, unfortunately I find myself stuck, I have to write an application (which for example would call the METHOD_IN_DIRECT function that I defined in a switch case in my IoDeviceControl)

I therefore tried to start from an example on github and modified it so that it works ... but obviously as this example is for a NONpnp driver it is not usable for my driver which is pnp.

So I looked for examples of applications that worked with a pnp driver to see the model / shape, but I can't find a tutorial / sites / example on the realization of this famous application, one of the only sites that spoke about it was saying:

"Set an interface guide so the application can find the device and talk to it."

now my question is:

"how to write an aplication to control a PNP driver"

the main in "test.c":

int __cdecl
main(
    _In_              ULONG argc,
    _In_reads_(argc) PCHAR argv[]
    )
{
    HANDLE   hDevice;
    DWORD    errNum = 0;
    CHAR     driverLocation[MAX_PATH];
    BOOL     ok;
    LONG     error;
//    ULONG bytesReturned;

    printf("main start. \n");


    // 
    //open the device
    printf("createFile. \n");
    
    hDevice = CreateFileA(DRIVER_NAME,
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        NULL,
                        CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);


    if (hDevice == INVALID_HANDLE_VALUE){...}
    
    printf("press enter \n");

    int c = getchar();

    printf("reception d'un charactere . \n");

    if (c) {
        
        printf("ioctl go \n");

        DoIoctls(hDevice);

        printf("ioctl end \n");

        //
        // Close the handle to the device before unloading the driver.
        //
        CloseHandle(hDevice);

        //
        // Unload the driver.  Ignore any errors.
        //
        ManageDriver(DRIVER_NAME, driverLocation, DRIVER_FUNC_REMOVE);
    }
    c = getchar();

    return;


}

here is the main of "test.c" which is at the base for nonpnp but that I modified that said I do not know how to embed the use of the GUID in my application (I imagine that it is because of that that it does not work).

the function DoIoctl :

VOID
DoIoctls(
    HANDLE hDevice
)
{
    char OutputBuffer[100];
    char InputBuffer[200];
    BOOL bRc;
    ULONG bytesReturned;


    //
    // Printing Input & Output buffer pointers and size
    //

    printf("\nInputBuffer Pointer = %p, BufLength = %Id\n", InputBuffer,sizeof(InputBuffer));
        
    printf("OutputBuffer Pointer = %p BufLength = %Id\n", OutputBuffer,sizeof(OutputBuffer));
        

    //
    // Performing METHOD_IN_DIRECT
    //

    printf("\nCalling DeviceIoControl METHOD_IN_DIRECT\n");

    if (FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer),"this String is from User Application; using METHOD_IN_DIRECT"))) 
    {
        return;
    }

    if (FAILED(StringCchCopy(OutputBuffer, sizeof(OutputBuffer),"This String is from User Application in OutBuffer; using METHOD_IN_DIRECT"))) 
    {
        return;
    }

    bRc = DeviceIoControl(hDevice,
                        (DWORD)Spw_PCIe_IOCTL_IN_BUFFERED,
                        InputBuffer,
                        (DWORD)strlen(InputBuffer) + 1,
                        OutputBuffer,
                        sizeof(OutputBuffer),
                        &bytesReturned,
                        NULL
                        );

    if (!bRc)
    {
        printf("Error in DeviceIoControl : %d \n", GetLastError());
        return;
    }

    printf("    Number of bytes transfered from OutBuffer: %d\n",bytesReturned);    


    //
    // Performing METHOD_OUT_DIRECT
    //

    printf("\nCalling DeviceIoControl METHOD_OUT_DIRECT\n");
    if (FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), "this String is from User Application; using METHOD_OUT_DIRECT"))) {
        return;
    }

    memset(OutputBuffer, 0, sizeof(OutputBuffer));

    bRc = DeviceIoControl(hDevice,
                        (DWORD)Spw_PCIe_IOCTL_OUT_BUFFERED,
                        InputBuffer,
                        (DWORD)strlen(InputBuffer) + 1,
                        OutputBuffer,
                        sizeof(OutputBuffer),
                        &bytesReturned,
                        NULL
                        );

    if (!bRc)
    {
        printf("Error in DeviceIoControl : : %d", GetLastError());
        return;
    }

    printf("    OutBuffer (%d): %s\n", bytesReturned, OutputBuffer);

    return;
}

function ManageDriver :

BOOLEAN
ManageDriver(                                //   <- ManageDriver 
    IN LPCTSTR  DriverName,
    IN LPCTSTR  ServiceName,
    IN USHORT   Function
)
{

    SC_HANDLE   schSCManager;
    BOOLEAN rCode = TRUE;

    schSCManager = OpenSCManager(NULL,                   // local machine
                                 NULL,                   // local database
                                 SC_MANAGER_ALL_ACCESS   // access required
                                 )   

    // Do the requested function.
    switch (Function) {;

    case DRIVER_FUNC_REMOVE:       //  REMOVE

        printf("remove case. \n");
        // Stop the driver.

        StopDriver(schSCManager,DriverName);
            
        // Remove the driver service.

        RemoveDriver(schSCManager,DriverName);

        // Ignore all errors.

        rCode = TRUE;

        break;

    default:
        printf("Unknown ManageDriver() function. \n");
        rCode = FALSE;

        break;

     }


    // Close handle to service control manager.
    if (schSCManager) {

        CloseServiceHandle(schSCManager);
    }


    return rCode;
}   // ManageDriver  fin 

function remove :

BOOLEAN
RemoveDriver(                                 //   <- RemoveDriver
    _In_ SC_HANDLE    SchSCManager,
    _In_ LPCTSTR      DriverName
)
{
    SC_HANDLE   schService;
    BOOLEAN     rCode;


    // Open the handle to the existing service.

    schService = OpenService(SchSCManager,DriverName,SERVICE_ALL_ACCESS);

    // Mark the service for deletion from the service control manager database.

    DeleteService(schService)

if (schService) {

        CloseServiceHandle(schService);
    }

    return rCode;

}   // RemoveDriver  fin 

function StartDriver :

BOOLEAN
StartDriver(
    _In_ SC_HANDLE    SchSCManager,
    _In_ LPCTSTR      DriverName
)
{
    SC_HANDLE   schService;
    DWORD       err;


    // Open the handle to the existing service.

    schService = OpenService(SchSCManager, DriverName,SERVICE_ALL_ACCESS );
       
    // Start the execution of the service (i.e. start the driver).

    StartService(schService,     // service identifier
                      0,              // number of arguments
                      NULL            // pointer to arguments
                      )


    // Close the service object.

    if (schService) {

        CloseServiceHandle(schService);
    }

    return TRUE;

}   // StartDriver   fin

function StopDriver :

BOOLEAN
StopDriver(
    _In_ SC_HANDLE    SchSCManager,
    _In_ LPCTSTR      DriverName
)
{
    BOOLEAN         rCode = TRUE;
    SC_HANDLE       schService;
    SERVICE_STATUS  serviceStatus;

    //
    // Open the handle to the existing service.
    //

    schService = OpenService(SchSCManager,
                 DriverName,
                 SERVICE_ALL_ACCESS
                 );

    //
    // Request that the service stop.
    //

    ControlService(schService,
                   SERVICE_CONTROL_STOP,
                   &serviceStatus
                   )

    //
    // Close the service object.
    //

    if (schService) {

        CloseServiceHandle(schService);
    }

    return rCode;

}   //  StopDriver   fin


I deleted everything that is debugger otherwise there is sure that it would not be clear

if you had any indication maybe I'm wrong about the nature of applications maybe the solution is very dumb but if you know anything about writing application for pnp driver I'm a taker

to shorten it :

i would need an application skeleton, but not just any, i need one that works for a pnp driver.

(it doesn't matter which driver as long as it's a pnp) this is to be able to compare with my application and see what is missing from my aplication to support plug and play

cordially thank you all


Solution

  • You need to obtain the device path using the SetupDi functions as shown in this answer.