Search code examples
cwindowsmultithreadingkernel-mode

How do i properly implement threads in Windows Kernel Driver?


I am trying to learn how to code windows kernel drivers. In my driver i have 2 threads which are created at some point with PsCreateSystemThread

I have a global variable called Kill which signals the threads to terminate like this.

VOID AThread(IN PVOID Context)
{
    for (;;)
    {
        if(Kill == True)
            break;

        KmWriteProcessMemory(rProcess, &NewValue, dwAAddr, sizeof(NewValue));
    }


    PsTerminateSystemThread(STATUS_SUCCESS);
}

In my unload function i am setting Kill = TRUE

VOID f_DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    Kill = TRUE;
    IoDeleteSymbolicLink(&SymLinkName);
    IoDeleteDevice(pDeviceObject);
    DbgPrint("Driver Unloaded successfully..\r\n");
}

Most of the time there's no problem, but sometimes the machine will crash when i try to unload the driver. It happens more frequently when i have some kind of sleep function being used in the threads, so i'm assuming it's crashing because the threads have not yet terminated before the driver tries to unload.

I'm not too sure how to use synchronisation and such, and there's not a lot of clear information out there that i can find. So how do i properly implement threads and ensure they're terminated before the driver is unloaded?


Solution

  • Once the thread is created, you have HANDLE threadHandle result. Then you need to convert this handle to PETHREAD ThreadObject; :

    ObReferenceObjectByHandle(threadHandle,
                              THREAD_ALL_ACCESS,
                              NULL,
                              KernelMode,
                              &ThreadObject,
                              NULL );
    

    and close threadHandle:

    ZwClose(threadHandle);
    

    When you want to stop the thread, set the flag and wait for thread completion:

    Kill = TRUE;
    
    KeWaitForSingleObject(ThreadObject,
                        Executive,
                        KernelMode,
                        FALSE,
                        NULL );
    
    ObDereferenceObject(ThreadObject);
    

    Then f_DriverUnload function may exit.

    You can see all this stuff here: https://github.com/Microsoft/Windows-driver-samples/tree/master/general/cancel/sys

    See cancel.h and cancel.c files. Additionally, this code uses semaphore instead of global flag to stop the thread.