[driver] Introduce WV_S_DRIVER_DUMMY_IDS and related
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 31 Dec 2010 07:38:26 +0000 (02:38 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Fri, 31 Dec 2010 07:38:26 +0000 (02:38 -0500)
Introduce a structure for carrying around PnP IDs.  It uses
offsets and lengths into a referenced static WCHAR array.

Included in this commit are macros for generating an
instance of such a structure, using x-macros.

Also included is WvDriverDummyIds() which will handle a
PnP ID query IRP using a WV_S_DRIVER_DUMMY_IDS.

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

index 7d3f1dd..4c626d0 100644 (file)
@@ -60,6 +60,73 @@ typedef NTSTATUS STDCALL driver__dispatch_func(
     IN PDEVICE_OBJECT,
     IN PIRP
   );
+/* PnP IDs for a dummy device. */
+typedef struct WV_DRIVER_DUMMY_IDS {
+    winvblock__uint32 DevOffset;
+    winvblock__uint32 DevLen;
+    winvblock__uint32 InstanceOffset;
+    winvblock__uint32 InstanceLen;
+    winvblock__uint32 HardwareOffset;
+    winvblock__uint32 HardwareLen;
+    winvblock__uint32 CompatOffset;
+    winvblock__uint32 CompatLen;
+    const WCHAR * Ids;
+  } WV_S_DRIVER_DUMMY_IDS, * WV_SP_DRIVER_DUMMY_IDS;
+
+/* Macro support for dummy ID generation. */
+#define WV_M_DRIVER_DUMMY_IDS_X_ENUM(prefix_, name_, literal_)  \
+  prefix_ ## name_ ## Offset_,                                  \
+  prefix_ ## name_ ## Len_ = sizeof (literal_),                 \
+  prefix_ ## name_ ## End_ =                                    \
+    prefix_ ## name_ ## Offset_ + prefix_ ## name_ ## Len_ - 1,
+
+#define WV_M_DRIVER_DUMMY_IDS_X_LITERALS(prefix_, name_, literal_) \
+  literal_ L"\0"
+
+#define WV_M_DRIVER_DUMMY_IDS_X_FILL(prefix_, name_, literal_)  \
+  prefix_ ## name_ ## Offset_,                                  \
+  prefix_ ## name_ ## Len_,
+
+/**
+ * Generate a static const WV_S_DRIVER_DUMMY_IDS object.
+ *
+ * @v DummyIds          The name of the desired object.  Also used as prefix.
+ * @v XMacro            The x-macro with the ID text.
+ *
+ * This macro will produce the following:
+ *   enum values:
+ *     [DummyIds]DevOffset_
+ *     [DummyIds]DevLen_
+ *     [DummyIds]DevEnd_
+ *     [DummyIds]InstanceOffset_
+ *     [DummyIds]InstanceLen_
+ *     [DummyIds]InstanceEnd_
+ *     [DummyIds]HardwareOffset_
+ *     [DummyIds]HardwareLen_
+ *     [DummyIds]HardwareEnd_
+ *     [DummyIds]CompatOffset_
+ *     [DummyIds]CompatLen_
+ *     [DummyIds]CompatEnd_
+ *     [DummyIds]Len_
+ *   WCHAR[]:
+ *     [DummyIds]String_
+ *   static const WV_S_DRIVER_DUMMY_IDS:
+ *     [DummyIds]
+ */
+#define WV_M_DRIVER_DUMMY_ID_GEN(DummyIds, XMacro)    \
+                                                      \
+enum {                                                \
+    XMacro(WV_M_DRIVER_DUMMY_IDS_X_ENUM, DummyIds)    \
+    DummyIds ## Len_                                  \
+  };                                                  \
+                                                      \
+static const WCHAR DummyIds ## String_[] =            \
+  XMacro(WV_M_DRIVER_DUMMY_IDS_X_LITERALS, DummyIds); \
+                                                      \
+static const WV_S_DRIVER_DUMMY_IDS DummyIds = {       \
+    XMacro(WV_M_DRIVER_DUMMY_IDS_X_FILL, DummyIds)    \
+    DummyIds ## String_                               \
+  }
 
 extern winvblock__lib_func NTSTATUS STDCALL driver__complete_irp(
     IN PIRP,
@@ -78,5 +145,9 @@ extern winvblock__lib_func NTSTATUS STDCALL WvDriverAddDummy(
     IN DEVICE_TYPE,
     IN ULONG
   );
+extern winvblock__lib_func NTSTATUS STDCALL WvDriverDummyIds(
+    IN PIRP,
+    IN WV_SP_DRIVER_DUMMY_IDS
+  );
 
 #endif /* WV_M_DRIVER_H_ */
index fb7620a..6e41a1e 100644 (file)
@@ -965,3 +965,66 @@ winvblock__lib_func NTSTATUS STDCALL WvDriverAddDummy(
 
     return context.Status;
   }
+
+/**
+ * Handle a PnP ID query with a WV_S_DRIVER_DUMMY_IDS object.
+ *
+ * @v Irp               The PnP ID query IRP to handle.
+ * @v DummyIds          The object containing the IDs to respond with.
+ * @ret NTSTATUS        The status of the operation.
+ */
+winvblock__lib_func NTSTATUS STDCALL WvDriverDummyIds(
+    IN PIRP Irp,
+    IN WV_SP_DRIVER_DUMMY_IDS DummyIds
+  ) {
+    PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(Irp);
+    BUS_QUERY_ID_TYPE query_type = io_stack_loc->Parameters.QueryId.IdType;
+    const WCHAR * ids;
+    winvblock__uint32 len;
+    NTSTATUS status;
+
+    switch (query_type) {
+        case BusQueryDeviceID:
+          ids = DummyIds->Ids + DummyIds->DevOffset;
+          len = DummyIds->DevLen;
+          break;
+
+        case BusQueryInstanceID:
+          ids = DummyIds->Ids + DummyIds->InstanceOffset;
+          len = DummyIds->InstanceLen;
+          break;
+
+        case BusQueryHardwareIDs:
+          ids = DummyIds->Ids + DummyIds->HardwareOffset;
+          len = DummyIds->HardwareLen;
+          break;
+
+        case BusQueryCompatibleIDs:
+          ids = DummyIds->Ids + DummyIds->CompatOffset;
+          len = DummyIds->CompatLen;
+          break;
+
+        default:
+          return driver__complete_irp(Irp, 0, STATUS_NOT_SUPPORTED);
+      }
+
+    /* Allocate the return buffer. */
+    Irp->IoStatus.Information = (ULONG_PTR) wv_palloc(len * sizeof *ids);
+    if (Irp->IoStatus.Information == 0) {
+        DBG("wv_palloc failed.\n");
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        goto alloc_info;
+      }
+    /* Copy the working buffer to the return buffer. */
+    RtlCopyMemory(
+        (void *) Irp->IoStatus.Information,
+        ids,
+        len * sizeof *ids
+      );
+    status = STATUS_SUCCESS;
+
+    /* irp->IoStatus.Information not freed. */
+    alloc_info:
+
+    return driver__complete_irp(Irp, Irp->IoStatus.Information, status);
+  }