MSDN Documentation

Windows Kernel Development

Creating Threads

This document provides a comprehensive guide to creating threads within the Windows kernel. Understanding thread creation is fundamental for building efficient and responsive operating system components.

Kernel-Mode Thread Creation

In kernel mode, threads are created using the PsCreateSystemThread function. This function allows the creation of threads that execute with system privileges, often used for background tasks, device drivers, and system services.

PsCreateSystemThread Function

The PsCreateSystemThread function signature is as follows:

NTSTATUS PsCreateSystemThread(
  OUT PHANDLE             ThreadHandle,
  IN  ACCESS_MASK         DesiredAccess,
  IN  POBJECT_ATTRIBUTES  ObjectAttributes,
  IN  HANDLE              ProcessHandle,
  OUT PCLIENT_ID          ClientId,
  IN  PKSTART_ROUTINE     StartRoutine,
  IN  PVOID               Context
);
                
  • ThreadHandle: A pointer to a variable that receives the thread object's handle.
  • DesiredAccess: The desired access mask for the thread object.
  • ObjectAttributes: A pointer to an object attribute structure that specifies the object's attributes, such as its name and security descriptor.
  • ProcessHandle: A handle to the process object in which the thread is to be created. For system threads, this is typically NULL.
  • ClientId: A pointer to a CLIENT_ID structure that receives the thread's unique identifier.
  • StartRoutine: A pointer to the thread's entry point function.
  • Context: A pointer to the context passed to the thread's entry point function.

Example: Creating a System Thread

// Define the thread start routine
VOID MyThreadRoutine(PVOID StartContext) {
    DbgPrint("Hello from kernel thread!\n");
    // Perform thread-specific tasks
    PsTerminateSystemThread(STATUS_SUCCESS);
}

// In your driver's AddDevice routine or initialization routine:
HANDLE hThread;
PVOID threadId; // Not strictly needed for PsCreateSystemThread

NTSTATUS status = PsCreateSystemThread(
    &hThread,
    THREAD_ALL_ACCESS,
    NULL, // ObjectAttributes
    NULL, // ProcessHandle for system thread
    &threadId,
    MyThreadRoutine,
    NULL  // Context
);

if (NT_SUCCESS(status)) {
    DbgPrint("System thread created successfully.\n");
    // You might want to close the handle if not needed further
    // ObCloseHandle(hThread, KernelMode);
} else {
    DbgPrint("Failed to create system thread. Status: 0x%X\n", status);
}
                
Note: When creating system threads, ensure that the thread routine is designed to be robust and handles potential errors gracefully. Threads created with PsCreateSystemThread run in the context of the system process (PID 4) and have significant privileges.

User-Mode Thread Creation

While this documentation focuses on kernel-mode, it's important to note that user-mode applications typically create threads using CreateThread or _beginthreadex from the Win32 API.

CreateThread Function (Win32 API)

The CreateThread function is used to create a thread in the calling process's address space.

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T                dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID                lpParameter,
  DWORD                 dwCreationFlags,
  LPDWORD               lpThreadId
);
                

Thread Object Management

Kernel threads are represented by EPROCESS and ETHREAD structures. The system automatically manages their lifecycle. However, developers must be mindful of resources, synchronization, and termination.

Key Structures

  • ETHREAD: Represents a thread in the kernel.
  • EPROCESS: Represents a process, which contains one or more threads.

Thread Termination

Threads should be terminated gracefully using functions like PsTerminateSystemThread in kernel mode or ExitThread in user mode. Forceful termination can lead to resource leaks and system instability.

Best Practices

  • Minimize the number of threads to reduce overhead.
  • Use synchronization primitives correctly to avoid race conditions.
  • Ensure threads terminate properly when they are no longer needed.
  • Design thread routines to be modular and testable.
  • Handle exceptions and errors robustly within thread execution.
Caution: Improper thread management, especially in kernel mode, can lead to severe system issues, including deadlocks, crashes, and security vulnerabilities. Always refer to official Microsoft documentation for the latest guidelines and best practices.