[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnproot.c
index 6f1834e..cbe802a 100644 (file)
@@ -126,10 +126,66 @@ LocateChildDevice(
     return STATUS_NO_SUCH_DEVICE;
 }
 
+NTSTATUS
+PnpRootRegisterDevice(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension = PnpRootDeviceObject->DeviceExtension;
+    PPNPROOT_DEVICE Device;
+    PDEVICE_NODE DeviceNode;
+    PWSTR InstancePath;
+    UNICODE_STRING InstancePathCopy;
+
+    Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
+    if (!Device) return STATUS_NO_MEMORY;
+
+    DeviceNode = IopGetDeviceNode(DeviceObject);
+    if (!RtlCreateUnicodeString(&InstancePathCopy, DeviceNode->InstancePath.Buffer))
+    {
+        ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+        return STATUS_NO_MEMORY;
+    }
+
+    InstancePath = wcsrchr(InstancePathCopy.Buffer, L'\\');
+    ASSERT(InstancePath);
+
+    if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath + 1))
+    {
+        RtlFreeUnicodeString(&InstancePathCopy);
+        ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+        return STATUS_NO_MEMORY;
+    }
+
+    InstancePath[0] = UNICODE_NULL;
+
+    if (!RtlCreateUnicodeString(&Device->DeviceID, InstancePathCopy.Buffer))
+    {
+        RtlFreeUnicodeString(&InstancePathCopy);
+        RtlFreeUnicodeString(&Device->InstanceID);
+        ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+        return STATUS_NO_MEMORY;
+    }
+
+    InstancePath[0] = L'\\';
+
+    Device->Pdo = DeviceObject;
+
+    KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+    InsertTailList(&DeviceExtension->DeviceListHead,
+                   &Device->ListEntry);
+    DeviceExtension->DeviceListCount++;
+    KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+
+    RtlFreeUnicodeString(&InstancePathCopy);
+
+    return STATUS_SUCCESS;
+}
+
 /* Creates a new PnP device for a legacy driver */
 NTSTATUS
 PnpRootCreateDevice(
     IN PUNICODE_STRING ServiceName,
+    IN OPTIONAL PDRIVER_OBJECT DriverObject,
     OUT PDEVICE_OBJECT *PhysicalDeviceObject,
     OUT OPTIONAL PUNICODE_STRING FullInstancePath)
 {
@@ -142,7 +198,7 @@ PnpRootCreateDevice(
     UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
     ULONG NextInstance;
     UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM);
-    HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE;
+    HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE, InstanceKeyHandle;
     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
     OBJECT_ATTRIBUTES ObjectAttributes;
 
@@ -241,6 +297,18 @@ tryagain:
         goto cleanup;
     }
 
+    /* Finish creating the instance path in the registry */
+    InitializeObjectAttributes(&ObjectAttributes, &Device->InstanceID, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL);
+    Status = ZwCreateKey(&InstanceKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+    if (NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create instance path (0x%x)\n", Status);
+        goto cleanup;
+    }
+
+    /* Just close the handle */
+    ZwClose(InstanceKeyHandle);
+
     if (FullInstancePath)
     {
         FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length;
@@ -259,7 +327,7 @@ tryagain:
 
     /* Initialize a device object */
     Status = IoCreateDevice(
-        PnpRootDeviceObject->DriverObject,
+        DriverObject ? DriverObject : PnpRootDeviceObject->DriverObject,
         sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
         NULL,
         FILE_DEVICE_CONTROLLER,
@@ -319,12 +387,16 @@ QueryStringCallback(
     UNICODE_STRING Source;
 
     if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0)
+    {
+        Destination->Length = 0;
+        Destination->MaximumLength = 0;
+        Destination->Buffer = NULL;
         return STATUS_SUCCESS;
+    }
 
-    Source.MaximumLength = Source.Length = ValueLength;
+    Source.MaximumLength = Source.Length = (USHORT)ValueLength;
     Source.Buffer = ValueData;
-    if (Source.Length > 0 && Source.Buffer[Source.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
-        Source.Length -= sizeof(WCHAR);
+
     return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &Source, Destination);
 }
 
@@ -365,7 +437,7 @@ EnumerateDevices(
     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM);
     UNICODE_STRING SubKeyName;
     WCHAR DevicePath[MAX_PATH + 1];
-    RTL_QUERY_REGISTRY_TABLE QueryTable[5];
+    RTL_QUERY_REGISTRY_TABLE QueryTable[4];
     PPNPROOT_DEVICE Device = NULL;
     HANDLE KeyHandle = INVALID_HANDLE_VALUE;
     HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
@@ -471,10 +543,8 @@ EnumerateDevices(
             /* Terminate the string */
             SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
 
-            _snwprintf(
-                DevicePath,
-                sizeof(DevicePath) / sizeof(WCHAR),
-                L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
+            _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR),
+                       L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
             DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name);
             if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE)
             {
@@ -491,14 +561,14 @@ EnumerateDevices(
                 /* Fill device ID and instance ID */
                 if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
                 {
-                    DPRINT("RtlCreateUnicodeString() failed\n");
+                    DPRINT1("RtlCreateUnicodeString() failed\n");
                     Status = STATUS_NO_MEMORY;
                     goto cleanup;
                 }
 
                 if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name))
                 {
-                    DPRINT("RtlCreateUnicodeString() failed\n");
+                    DPRINT1("RtlCreateUnicodeString() failed\n");
                     Status = STATUS_NO_MEMORY;
                     goto cleanup;
                 }
@@ -507,38 +577,45 @@ EnumerateDevices(
                 Status = IopOpenRegistryKeyEx(&DeviceKeyHandle, SubKeyHandle, &Device->InstanceID, KEY_READ);
                 if (!NT_SUCCESS(Status))
                 {
-                    DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
+                    DPRINT1("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
                     break;
                 }
 
-                /* Fill other informations */
+                /* Fill information from the device instance key */
+                RtlZeroMemory(QueryTable, sizeof(QueryTable));
+                QueryTable[0].QueryRoutine = QueryStringCallback;
+                QueryTable[0].Name = L"DeviceDesc";
+                QueryTable[0].EntryContext = &Device->DeviceDescription;
+
+                RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+                                       (PCWSTR)DeviceKeyHandle,
+                                       QueryTable,
+                                       NULL,
+                                       NULL);
+
+                /* Fill information from the LogConf subkey */
                 Buffer1.Data = (PVOID *)&Device->ResourceRequirementsList;
                 Buffer1.Length = NULL;
                 Buffer2.Data = (PVOID *)&Device->ResourceList;
                 Buffer2.Length = &Device->ResourceListSize;
                 RtlZeroMemory(QueryTable, sizeof(QueryTable));
-                QueryTable[0].QueryRoutine = QueryStringCallback;
-                QueryTable[0].Name = L"DeviceDesc";
-                QueryTable[0].EntryContext = &Device->DeviceDescription;
-                QueryTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY;
-                QueryTable[1].Name = L"LogConf";
+                QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+                QueryTable[0].Name = L"LogConf";
+                QueryTable[1].QueryRoutine = QueryBinaryValueCallback;
+                QueryTable[1].Name = L"BasicConfigVector";
+                QueryTable[1].EntryContext = &Buffer1;
                 QueryTable[2].QueryRoutine = QueryBinaryValueCallback;
-                QueryTable[2].Name = L"BasicConfigVector";
-                QueryTable[2].EntryContext = &Buffer1;
-                QueryTable[3].QueryRoutine = QueryBinaryValueCallback;
-                QueryTable[3].Name = L"BootConfig";
-                QueryTable[3].EntryContext = &Buffer2;
-
-                Status = RtlQueryRegistryValues(
-                    RTL_REGISTRY_HANDLE,
-                    (PCWSTR)DeviceKeyHandle,
-                    QueryTable,
-                    NULL,
-                    NULL);
-                if (!NT_SUCCESS(Status))
+                QueryTable[2].Name = L"BootConfig";
+                QueryTable[2].EntryContext = &Buffer2;
+
+                if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+                                                       (PCWSTR)DeviceKeyHandle,
+                                                       QueryTable,
+                                                       NULL,
+                                                       NULL)))
                 {
-                    DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status);
-                    break;
+                    /* Non-fatal error */
+                    DPRINT1("Failed to read the LogConf key for %S\\%S\n", DevicePath, SubKeyInfo->Name);
                 }
 
                 ZwClose(DeviceKeyHandle);
@@ -643,7 +720,7 @@ PnpRootQueryDeviceRelations(
     {
         /* Get the entry */
         Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
-    
+
         if (!Device->Pdo)
         {
             /* Create a physical device object for the
@@ -799,10 +876,8 @@ PdoQueryCapabilities(
     IN PIRP Irp,
     IN PIO_STACK_LOCATION IrpSp)
 {
-    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
     PDEVICE_CAPABILITIES DeviceCapabilities;
 
-    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
     DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
 
     if (DeviceCapabilities->Version != 1)
@@ -904,18 +979,19 @@ PdoQueryDeviceText(
             UNICODE_STRING String;
             DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
 
-            Status = RtlDuplicateUnicodeString(
-                RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-                &DeviceExtension->DeviceInfo->DeviceDescription,
-                &String);
-            Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+            if (DeviceExtension->DeviceInfo->DeviceDescription.Buffer != NULL)
+            {
+                Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                                   &DeviceExtension->DeviceInfo->DeviceDescription,
+                                                   &String);
+                Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+            }
             break;
         }
 
         case DeviceTextLocationInformation:
         {
             DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
-            Status = STATUS_NOT_SUPPORTED;
             break;
         }
 
@@ -1027,10 +1103,12 @@ PnpRootPdoPnpControl(
   IN PIRP Irp)
 {
   PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+  PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
 
   DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+  FdoDeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
   Status = Irp->IoStatus.Status;
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
@@ -1070,7 +1148,32 @@ PnpRootPdoPnpControl(
         break;
 
     case IRP_MN_REMOVE_DEVICE:
-        DPRINT1("IRP_MN_REMOVE_DEVICE is UNIMPLEMENTED!\n");
+        /* Remove the device from the device list and decrement the device count*/
+        KeAcquireGuardedMutex(&FdoDeviceExtension->DeviceListLock);
+        RemoveEntryList(&DeviceExtension->DeviceInfo->ListEntry);
+        FdoDeviceExtension->DeviceListCount--;
+        KeReleaseGuardedMutex(&FdoDeviceExtension->DeviceListLock);
+
+        /* Free some strings we created */
+        RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceDescription);
+        RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceID);
+        RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->InstanceID);
+
+        /* Free the resource requirements list */
+        if (DeviceExtension->DeviceInfo->ResourceRequirementsList != NULL)
+            ExFreePool(DeviceExtension->DeviceInfo->ResourceRequirementsList);
+
+        /* Free the boot resources list */
+        if (DeviceExtension->DeviceInfo->ResourceList != NULL)
+            ExFreePool(DeviceExtension->DeviceInfo->ResourceList);
+
+        /* Free the device info */
+        ExFreePool(DeviceExtension->DeviceInfo);
+
+        /* Finally, delete the device object */
+        IoDeleteDevice(DeviceObject);
+
+        /* Return success */
         Status = STATUS_SUCCESS;
         break;
 
@@ -1085,7 +1188,6 @@ PnpRootPdoPnpControl(
 
         default:
             DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
-            Status = STATUS_NOT_IMPLEMENTED;
             break;
     }
 
@@ -1191,7 +1293,7 @@ PnpRootDriverEntry(
     DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
 
     IopRootDriverObject = DriverObject;
-    
+
     DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
 
     DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;