[dummy] Handle PnP device removal
[people/sha0/winvblock.git] / src / winvblock / dummy.c
index 4f4aa57..caa694a 100644 (file)
@@ -49,11 +49,20 @@ static NTSTATUS STDCALL WvDummyPnp(
     IN PIRP irp,
     IN UCHAR code
   ) {
-    if (code != IRP_MN_QUERY_ID)
-      return WvlIrpComplete(irp, 0, STATUS_NOT_SUPPORTED);
+    switch (code) {
+        case IRP_MN_QUERY_ID:
+          /* The WV_S_DEV_T extension points to the dummy IDs. */
+          return WvDummyIds(irp, dev->ext);
 
-    /* The WV_S_DEV_T extension points to the dummy IDs. */
-    return WvDummyIds(irp, dev->ext);
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+          return WvlIrpComplete(irp, 0, STATUS_SUCCESS);
+
+        case IRP_MN_REMOVE_DEVICE:
+          return WvlIrpComplete(irp, 0, WvlBusRemoveNode(&dev->BusNode));
+
+        default:
+          return WvlIrpComplete(irp, 0, STATUS_NOT_SUPPORTED);
+      }
   }
 
 typedef struct WV_ADD_DUMMY {
@@ -62,6 +71,7 @@ typedef struct WV_ADD_DUMMY {
     ULONG DevCharacteristics;
     PKEVENT Event;
     NTSTATUS Status;
+    PDEVICE_OBJECT Pdo;
   } WV_S_ADD_DUMMY, * WV_SP_ADD_DUMMY;
 
 /**
@@ -142,6 +152,7 @@ static VOID STDCALL WvDummyAdd_(PVOID context) {
     pdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
     dummy_context->Status = STATUS_SUCCESS;
+    dummy_context->Pdo = pdo;
     KeSetEvent(dummy_context->Event, 0, FALSE);
     return;
 
@@ -164,12 +175,14 @@ static VOID STDCALL WvDummyAdd_(PVOID context) {
  * @v DummyIds                  The PnP IDs for the dummy.
  * @v DevType                   The type for the dummy device.
  * @v DevCharacteristics        The dummy device characteristics.
+ * @v Pdo                       Filled with a pointer to the created PDO.
  * @ret NTSTATUS                The status of the operation.
  */
 WVL_M_LIB NTSTATUS STDCALL WvDummyAdd(
     IN const WV_S_DUMMY_IDS * DummyIds,
     IN DEVICE_TYPE DevType,
-    IN ULONG DevCharacteristics
+    IN ULONG DevCharacteristics,
+    OUT PDEVICE_OBJECT * Pdo
   ) {
     KEVENT event;
     WV_S_ADD_DUMMY context = {
@@ -177,7 +190,8 @@ WVL_M_LIB NTSTATUS STDCALL WvDummyAdd(
         DevType,
         DevCharacteristics,
         &event,
-        STATUS_UNSUCCESSFUL
+        STATUS_UNSUCCESSFUL,
+        NULL
       };
     WVL_S_BUS_CUSTOM_WORK_ITEM work_item = {
         WvDummyAdd_,
@@ -206,9 +220,23 @@ WVL_M_LIB NTSTATUS STDCALL WvDummyAdd(
         NULL
       );
 
+    if (context.Pdo)
+      *Pdo = context.Pdo;
     return context.Status;
   }
 
+/**
+ * Remove a dummy PDO node on the WinVBlock bus.
+ *
+ * @v Pdo               The PDO to remove.
+ * @ret NTSTATUS        The status of the operation.
+ *
+ * It might actually be better to handle a PnP remove IOCTL.
+ */
+WVL_M_LIB NTSTATUS STDCALL WvDummyRemove(IN PDEVICE_OBJECT Pdo) {
+    return WvlBusRemoveNode(&WvDevFromDevObj(Pdo)->BusNode);
+  }
+
 /**
  * Handle a PnP ID query with a WV_S_DUMMY_IDS object.
  *