Search code examples
c++windowsdriverwdk

driver can't start at the second time


I started to program driver. I red a lot articles and developed a test driver that's also working. At the beginnning it is just a Hello World Driver. In a Console I install the driver, start and then stoped and remove. All is working well. Just when I want to install and start it again, it returns Error no 2 at the function "StartService". Throught Debug-Message I can see that in the second time, the function DriverEntry is not called. But when I restard the PC then I can install and start the driver. Unfurtunaly I could not find any articles about this problems. Just other problem which return 2 i.e. Driver not found. But all this is working.

I install the driver with:

    SC_HANDLE hSCManager;
SC_HANDLE hService;
SERVICE_STATUS ss;

hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);

printf("Load Driver\n");

if(hSCManager)
{
    printf("Create Service\n");
    getchar();

    hService = CreateService(hSCManager, TEXT("Example"), TEXT("Example Driver"), SERVICE_START | DELETE | SERVICE_STOP, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, TEXT("C:\\Windows\\System32\\drivers\\MyFirstDriver.sys"), NULL, NULL, NULL, NULL, NULL);
    //hService = CreateService(hSCManager, TEXT("Example"), TEXT("Example Driver"), SERVICE_START | DELETE | SERVICE_STOP, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, TEXT("C:\\driver\\temp2\MyFirstDriver.sys"), NULL, NULL, NULL, NULL, NULL);

    if(!hService)
    {
        printf("OpenService Service\n");
        getchar();
        hService = OpenService(hSCManager, TEXT("Example"), SERVICE_START | DELETE | SERVICE_STOP);
    }

    if(hService)
    {
        printf("Start Service\n");
        getchar();
        if (StartService(hService, 0, NULL))
        {
            printf("Start war erfolgreich\n");
        }
        else
        {
            printf("Fehler beim starten\n");
            printf("StartService failed (%d)\n", GetLastError()); 

        }

        Sleep(5000);
        printf("Press Enter to close service\n");
        getchar();
        printf("beendet\n");
        getchar();
        ControlService(hService, SERVICE_CONTROL_STOP, &ss);



        if (DeleteService(hService)) {
            printf("Delete war erfolgreich\n");
        }
        else
        {
            printf("Fehler beim Delete\n");
            printf("Delete failed (%d)\n", GetLastError()); 
            //Error nr 6
        }

        if (CloseServiceHandle(hService)) {
            printf("Close war erfolgreich\n");
        }
        else
        {
            printf("Fehler beim Close\n");
            printf("Close failed (%d)\n", GetLastError()); 

        }
    }
    printf("Press Enter to close service\n");
        getchar();
    CloseServiceHandle(hSCManager);
}
return 0;

The Code of the driver:

    #include "stdafx.h"
#include "functions.h"

void MyFirstDriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS MyFirstDriverCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS MyFirstDriverClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS MyFirstDriverDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS MyFirstDriverAddDevice(IN PDRIVER_OBJECT  DriverObject, IN PDEVICE_OBJECT  PhysicalDeviceObject);
NTSTATUS MyFirstDriverPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS MyFirstDriverRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS MyFirstDriverUnsupportedFunc(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);


typedef struct _deviceExtension
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT TargetDeviceObject;
PDEVICE_OBJECT PhysicalDeviceObject;
UNICODE_STRING DeviceInterface;
} MyFirstDriver_DEVICE_EXTENSION, *PMyFirstDriver_DEVICE_EXTENSION;

// {282b517a-9a95-4fdc-8167-aec5f8463df3}
static const GUID GUID_MyFirstDriverInterface = {0x282B517A, 0x9a95, 0x4fdc, {0x81, 0x67, 0xae, 0xc5, 0xf8, 0x46, 0x3d, 0xf3 } };

#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{

DbgPrint("DriverEntry01 Called \r\n");
NTSTATUS NtStatus = STATUS_SUCCESS;
    INT uiIndex = 0;
DbgPrint("DriverEntry02 Called \r\n");
    PDEVICE_OBJECT pDeviceObject = NULL;
DbgPrint("DriverEntry03 Called \r\n");
    UNICODE_STRING usDriverName, usDosDeviceName;

DbgPrint("DriverEntry3 Called \r\n");
DbgPrint("DriverEntry4 Called \r\n");
DbgPrint("DriverEntry5 Called \r\n");
    DbgPrint("DriverEntry6 Called \r\n");

    RtlInitUnicodeString(&usDriverName, L"\\Device\\Example");
DbgPrint("DriverEntry7 Called \r\n");
    RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\Example"); 
DbgPrint("DriverEntry8 Called \r\n");

    NtStatus = IoCreateDevice(DriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
DbgPrint("DriverEntry9 Called \r\n");
if(NtStatus == STATUS_SUCCESS)
    {
    DbgPrint("DriverEntry10 Called \r\n");

    for(uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++)
        DriverObject->MajorFunction[uiIndex] = MyFirstDriverUnsupportedFunc;

        DriverObject->MajorFunction[IRP_MJ_CLOSE]             = MyFirstDriverClose;
        DriverObject->MajorFunction[IRP_MJ_CREATE]            = MyFirstDriverCreate;
        DriverObject->MajorFunction[IRP_MJ_PNP]    = MyFirstDriverPnP;
        DriverObject->MajorFunction[IRP_MJ_READ]              = MyFirstDriverRead;

        DriverObject->DriverUnload =  MyFirstDriverUnload; 


        DriverObject->Flags &= (~DO_DEVICE_INITIALIZING);


        IoCreateSymbolicLink(&usDosDeviceName, &usDriverName);
    }


    return NtStatus;


}



void MyFirstDriverUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Goodbye from MyFirstDriver!\n");
}


NTSTATUS MyFirstDriverUnsupportedFunc(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    DbgPrint("MyFirstDriverUnsupportedFunc \r\n");

    return NtStatus;
}

NTSTATUS MyFirstDriverRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;


    DbgPrint("Example Read Called \r\n");

    return NtStatus;
}

NTSTATUS MyFirstDriverClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
    DbgPrint("Drive Close \r\n");

    return NtStatus;
}

NTSTATUS MyFirstDriverCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

NTSTATUS MyFirstDriverDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

PMyFirstDriver_DEVICE_EXTENSION deviceExtension = NULL;

IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PMyFirstDriver_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

}

NTSTATUS MyFirstDriverAddDevice(IN PDRIVER_OBJECT  DriverObject, IN PDEVICE_OBJECT  PhysicalDeviceObject)
{
PDEVICE_OBJECT DeviceObject = NULL;
PMyFirstDriver_DEVICE_EXTENSION pExtension = NULL;
NTSTATUS status;

status = IoCreateDevice(DriverObject,
                        sizeof(MyFirstDriver_DEVICE_EXTENSION),
                        NULL,
                        FILE_DEVICE_UNKNOWN,
                        0,
                        0,
                        &DeviceObject);

if (!NT_SUCCESS(status))
    return status;

pExtension = (PMyFirstDriver_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

pExtension->DeviceObject = DeviceObject;
pExtension->PhysicalDeviceObject = PhysicalDeviceObject;
pExtension->TargetDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);

status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_MyFirstDriverInterface, NULL, &pExtension->DeviceInterface);
ASSERT(NT_SUCCESS(status));

DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}


NTSTATUS MyFirstDriverIrpCompletion(
                  IN PDEVICE_OBJECT DeviceObject,
                  IN PIRP Irp,
                  IN PVOID Context
                  )
{
PKEVENT Event = (PKEVENT) Context;

UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);

KeSetEvent(Event, IO_NO_INCREMENT, FALSE);

return(STATUS_MORE_PROCESSING_REQUIRED);
}

NTSTATUS MyFirstDriverForwardIrpSynchronous(
                          IN PDEVICE_OBJECT DeviceObject,
                          IN PIRP Irp
                          )
{
PMyFirstDriver_DEVICE_EXTENSION   deviceExtension;
KEVENT event;
NTSTATUS status;

KeInitializeEvent(&event, NotificationEvent, FALSE);
deviceExtension = (PMyFirstDriver_DEVICE_EXTENSION) DeviceObject->DeviceExtension;

IoCopyCurrentIrpStackLocationToNext(Irp);

IoSetCompletionRoutine(Irp, MyFirstDriverIrpCompletion, &event, TRUE, TRUE, TRUE);

status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

if (status == STATUS_PENDING) {
    KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
    status = Irp->IoStatus.Status;
}
return status;
}

NTSTATUS MyFirstDriverPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
PMyFirstDriver_DEVICE_EXTENSION pExt = ((PMyFirstDriver_DEVICE_EXTENSION)DeviceObject->DeviceExtension);
NTSTATUS status;

ASSERT(pExt);

switch (irpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
    IoSetDeviceInterfaceState(&pExt->DeviceInterface, TRUE);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;

case IRP_MN_QUERY_REMOVE_DEVICE:
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;

case IRP_MN_REMOVE_DEVICE:
    IoSetDeviceInterfaceState(&pExt->DeviceInterface, FALSE);
    status = MyFirstDriverForwardIrpSynchronous(DeviceObject, Irp);
    IoDetachDevice(pExt->TargetDeviceObject);
    IoDeleteDevice(pExt->DeviceObject);
    RtlFreeUnicodeString(&pExt->DeviceInterface);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;

case IRP_MN_QUERY_PNP_DEVICE_STATE:
    status = MyFirstDriverForwardIrpSynchronous(DeviceObject, Irp);
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
return MyFirstDriverDefaultHandler(DeviceObject, Irp);
}

Edit: I tried the same with sc create and sc start. In the second time, it gives the error no 2 with the additional information that he can'T find the file. But, as I said, the first time he can find the file and load. Second Time not.


Solution

  • your driver containing huge count of errors and cannot be unloaded. you create Device "\\Device\\Example"in DriverEntry but you not delete it MyFirstDriverUnload - so this Device and hold driver from unloading. you try also be WDM driver, but i sure you not registered your driver as WDM for any deviceID and your MyFirstDriverAddDevice never called. WDM drivers (after you attach self device to device stack) at all can not be unloaded by start/stop but only after stop/destroying stack.

    DriverObject->Flags &= (~DO_DEVICE_INITIALIZING);

    else one error. about IRP handling i already not say. but again - in this concrete case driver not unloaded because you not call IoDeleteDevice in MyFirstDriverUnload.