Author: cgutman Date: Fri Apr 2 05:47:14 2010 New Revision: 46659
URL: http://svn.reactos.org/svn/reactos?rev=46659&view=rev Log: [NTOSKRNL] - Fix certain scenarios in which a device node can have a NULL instance path which causes registry corruption when we try to write registry keys for that device node - Create the 'Control' subkey and add the ActiveService value inside it - Fix a memory leak - TODO: Fill AllocConfig and FilteredConfigVector
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c... ============================================================================== --- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] Fri Apr 2 05:47:14 2010 @@ -60,6 +60,11 @@ IopUpdateResourceMapForPnPDevice( IN PDEVICE_NODE DeviceNode);
+NTSTATUS +NTAPI +IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, + OUT PHANDLE Handle); + PDEVICE_NODE FASTCALL IopGetDeviceNode(PDEVICE_OBJECT DeviceObject) @@ -141,6 +146,9 @@ IO_STACK_LOCATION Stack; ULONG RequiredLength; NTSTATUS Status; + HANDLE InstanceHandle, ControlHandle; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes;
IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n"); @@ -215,8 +223,31 @@ } }
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceHandle); + if (!NT_SUCCESS(Status)) + return Status; + + RtlInitUnicodeString(&KeyName, L"Control"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + InstanceHandle, + NULL); + Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); + if (!NT_SUCCESS(Status)) + { + ZwClose(InstanceHandle); + return Status; + } + + RtlInitUnicodeString(&KeyName, L"ActiveService"); + Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length); + if (NT_SUCCESS(Status)) IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + + ZwClose(ControlHandle); + ZwClose(InstanceHandle);
return Status; } @@ -372,6 +403,8 @@ KIRQL OldIrql; UNICODE_STRING FullServiceName; UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_"); + UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN"); + HANDLE TempHandle;
DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n", ParentNode, PhysicalDeviceObject, ServiceName); @@ -384,30 +417,37 @@
RtlZeroMemory(Node, sizeof(DEVICE_NODE));
+ if (!ServiceName) + ServiceName = &UnknownDeviceName; + if (!PhysicalDeviceObject) { - if (ServiceName) - { - FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName->Length; - FullServiceName.Length = 0; - FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength); - if (!FullServiceName.Buffer) - { - ExFreePool(Node); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix); - RtlAppendUnicodeStringToString(&FullServiceName, ServiceName); - } - - Status = PnpRootCreateDevice(ServiceName ? &FullServiceName : NULL, &PhysicalDeviceObject); + FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName->Length; + FullServiceName.Length = 0; + FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength); + if (!FullServiceName.Buffer) + { + ExFreePool(Node); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix); + RtlAppendUnicodeStringToString(&FullServiceName, ServiceName); + + Status = PnpRootCreateDevice(&FullServiceName, &PhysicalDeviceObject, &Node->InstancePath); if (!NT_SUCCESS(Status)) { DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status); ExFreePool(Node); return Status; } + + /* Create the device key for legacy drivers */ + Status = IopCreateDeviceKeyPath(&Node->InstancePath, &TempHandle); + if (NT_SUCCESS(Status)) + ZwClose(TempHandle); + + ExFreePool(FullServiceName.Buffer);
/* This is for drivers passed on the command line to ntoskrnl.exe */ IopDeviceNodeSetFlag(Node, DNF_STARTED); @@ -873,6 +913,7 @@ ULONG ResCount; ULONG ListSize, ResultLength; NTSTATUS Status; + HANDLE ControlHandle;
DPRINT("IopSetDeviceInstanceData() called\n");
@@ -946,9 +987,21 @@ sizeof(DefaultConfigFlags)); }
+ /* Create the 'Control' key */ + RtlInitUnicodeString(&KeyName, L"Control"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + InstanceKey, + NULL); + Status = ZwCreateKey(&ControlHandle, 0, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); + + if (NT_SUCCESS(Status)) + ZwClose(ControlHandle); + DPRINT("IopSetDeviceInstanceData() done\n");
- return STATUS_SUCCESS; + return Status; }
BOOLEAN
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnprepor... ============================================================================== --- trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] Fri Apr 2 05:47:14 2010 @@ -161,7 +161,8 @@ { /* Create the PDO */ Status = PnpRootCreateDevice(&ServiceName, - &Pdo); + &Pdo, + NULL); if (!NT_SUCCESS(Status)) { DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.... ============================================================================== --- trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] Fri Apr 2 05:47:14 2010 @@ -131,30 +131,25 @@ NTSTATUS PnpRootCreateDevice( IN PUNICODE_STRING ServiceName, - IN PDEVICE_OBJECT *PhysicalDeviceObject) + OUT PDEVICE_OBJECT *PhysicalDeviceObject, + OUT OPTIONAL PUNICODE_STRING FullInstancePath) { PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; - UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"LEGACY_UNKNOWN"); - PUNICODE_STRING LocalServiceName; PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; WCHAR DevicePath[MAX_PATH + 1]; WCHAR InstancePath[5]; PPNPROOT_DEVICE Device = NULL; NTSTATUS Status; ULONG i; + UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\");
DeviceExtension = PnpRootDeviceObject->DeviceExtension; KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
- if (ServiceName) - LocalServiceName = ServiceName; - else - LocalServiceName = &UnknownServiceName; - - DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName); + DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName);
/* Search for a free instance ID */ - _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\%wZ", REGSTR_KEY_ROOTENUM, LocalServiceName); + _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\%wZ", REGSTR_KEY_ROOTENUM, ServiceName); for (i = 0; i < 9999; i++) { _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", i); @@ -164,7 +159,7 @@ } if (i == 9999) { - DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName); + DPRINT1("Too much legacy devices reported for service '%wZ'\n", ServiceName); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } @@ -187,6 +182,22 @@ { Status = STATUS_NO_MEMORY; goto cleanup; + } + + if (FullInstancePath) + { + FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length; + FullInstancePath->Length = 0; + FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength); + if (!FullInstancePath->Buffer) + { + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID); + RtlAppendUnicodeStringToString(FullInstancePath, &PathSep); + RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID); }
/* Initialize a device object */