[bus,driver] Revisit driver unload and thread exit
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 31 Dec 2010 20:05:10 +0000 (15:05 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 31 Dec 2010 20:05:10 +0000 (15:05 -0500)
These changes allow for some really nice test successes
for starting the service, updating the driver, uninstalling,
using the Add Hardware Wizard, etc.

src/include/bus.h
src/winvblock/bus/bus.c
src/winvblock/bus/pnp.c
src/winvblock/driver.c

index 1e3d956..cac907f 100644 (file)
@@ -69,7 +69,6 @@ typedef struct WV_BUS_T {
     WV_FP_BUS_THREAD Thread;
     KEVENT ThreadSignal;
     winvblock__bool Stop;
-    KEVENT ThreadStopped;
     WV_E_BUS_STATE OldState;
     WV_E_BUS_STATE State;
     WV_FP_BUS_PNP QueryDevText;
@@ -114,7 +113,10 @@ extern winvblock__lib_func void WvBusInit(WV_SP_BUS_T);
 extern winvblock__lib_func WV_SP_BUS_T WvBusCreate(void);
 extern winvblock__lib_func void WvBusProcessWorkItems(WV_SP_BUS_T);
 extern winvblock__lib_func void WvBusCancelWorkItems(WV_SP_BUS_T);
-extern winvblock__lib_func NTSTATUS WvBusStartThread(WV_SP_BUS_T);
+extern winvblock__lib_func NTSTATUS WvBusStartThread(
+    IN WV_SP_BUS_T,
+    OUT PETHREAD *
+  );
 extern winvblock__lib_func winvblock__bool STDCALL WvBusInitNode(
     OUT WV_SP_BUS_NODE,
     IN PDEVICE_OBJECT
index 9e73cf7..bd7b49f 100644 (file)
@@ -104,7 +104,6 @@ winvblock__lib_func void WvBusInit(WV_SP_BUS_T Bus) {
     KeInitializeSpinLock(&Bus->BusPrivate_.WorkItemsLock);
     InitializeListHead(&Bus->BusPrivate_.WorkItems);
     KeInitializeEvent(&Bus->ThreadSignal, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&Bus->ThreadStopped, SynchronizationEvent, FALSE);
   }
 
 /**
@@ -341,7 +340,8 @@ static void STDCALL WvBusThread_(IN void * context) {
       }
 
     bus->Thread(bus);
-    KeSetEvent(&bus->ThreadStopped, 0, FALSE);
+    DBG("Exiting.\n");
+    PsTerminateSystemThread(STATUS_SUCCESS);
     return;
   }
 
@@ -389,17 +389,21 @@ static void STDCALL WvBusDefaultThread_(IN WV_SP_BUS_T bus) {
  * Start a bus thread.
  *
  * @v Bus               The bus to start a thread for.
+ * @v Thread            A PETHREAD to be filled to reference the thread.
  * @ret NTSTATUS        The status of the thread creation operation.
  *
  * Also see WV_F_BUS_THREAD in the header for details about the prototype
  * for implementing your own bus thread routine.  You set WV_S_BUS_T::Thread
  * to specify your own thread routine, then call this function to start it.
+ * When stopping the thread, you can wait on the thread handle.
  */
 winvblock__lib_func NTSTATUS WvBusStartThread(
-    WV_SP_BUS_T Bus
+    IN WV_SP_BUS_T Bus,
+    OUT PETHREAD * Thread
   ) {
     OBJECT_ATTRIBUTES obj_attrs;
     HANDLE thread_handle;
+    NTSTATUS status;
 
     if (!Bus) {
         DBG("No bus specified!\n");
@@ -413,7 +417,7 @@ winvblock__lib_func NTSTATUS WvBusStartThread(
         NULL,
         NULL
       );
-    return PsCreateSystemThread(
+    status = PsCreateSystemThread(
         &thread_handle,
         THREAD_ALL_ACCESS,
         &obj_attrs,
@@ -422,6 +426,16 @@ winvblock__lib_func NTSTATUS WvBusStartThread(
         WvBusThread_,
         Bus
       );
+    if (!NT_SUCCESS(status))
+      return status;
+    return ObReferenceObjectByHandle(
+        thread_handle,
+        THREAD_ALL_ACCESS,
+        *PsThreadType,
+        KernelMode,
+        Thread,
+        NULL
+      );
   }
 
 /**
index 38bfd92..a46f2ec 100644 (file)
@@ -125,6 +125,8 @@ static NTSTATUS STDCALL WvBusPnpRemoveDev_(IN WV_SP_BUS_T bus, IN PIRP irp) {
       IoDetachDevice(lower);
     /* Delete. */
     IoDeleteDevice(bus->Fdo);
+    /* Stop the thread. */
+    bus->Stop = TRUE;
     return status;
   }
 
index 38adca8..81bbf54 100644 (file)
@@ -68,6 +68,7 @@ static UNICODE_STRING WvDriverBusDosname_ = {
 /* The main bus. */
 static WV_S_BUS_T WvDriverBus_ = {0};
 static WV_S_DEV_T WvDriverBusDev_ = {0};
+static PETHREAD WvDriverBusThread_ = NULL;
 /* Contains TXTSETUP.SIF/BOOT.INI-style OsLoadOptions parameters. */
 static LPWSTR WvDriverOsLoadOpts_ = NULL;
 
@@ -209,7 +210,7 @@ static NTSTATUS STDCALL driver__attach_fdo_(
         DBG("IoAttachDeviceToDeviceStack() failed!\n");
         goto err_attach;
       }
-    status = WvBusStartThread(&WvDriverBus_);
+    status = WvBusStartThread(&WvDriverBus_, &WvDriverBusThread_);
     if (!NT_SUCCESS(status)) {
         DBG("Couldn't start bus thread!\n");
         goto err_thread;
@@ -564,13 +565,17 @@ static NTSTATUS driver__dispatch_pnp_(
 static void STDCALL driver__unload_(IN PDRIVER_OBJECT DriverObject) {
     DBG("Unloading...\n");
     WvDriverBus_.Stop = TRUE;
-    KeWaitForSingleObject(
-        &WvDriverBus_.ThreadStopped,
-        Executive,
-        KernelMode,
-        FALSE,
-        NULL
-      );
+    KeSetEvent(&WvDriverBus_.ThreadSignal, 0, FALSE);
+    if (WvDriverBusThread_) {
+        KeWaitForSingleObject(
+            WvDriverBusThread_,
+            Executive,
+            KernelMode,
+            FALSE,
+            NULL
+          );
+        ObDereferenceObject(WvDriverBusThread_);
+      }
     if (WvDriverStateHandle_ != NULL)
       PoUnregisterSystemState(WvDriverStateHandle_);
     IoDeleteSymbolicLink(&WvDriverBusDosname_);