[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

svn path=/trunk/; revision=46659
This commit is contained in:
Cameron Gutman 2010-04-02 03:47:14 +00:00
parent 623bc96350
commit b121447744
3 changed files with 91 additions and 26 deletions

View file

@ -60,6 +60,11 @@ NTSTATUS
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 @@ IopStartDevice(
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,9 +223,32 @@ IopStartDevice(
}
}
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 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
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,24 +417,24 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
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)
{
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);
ExFreePool(Node);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = PnpRootCreateDevice(ServiceName ? &FullServiceName : NULL, &PhysicalDeviceObject);
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);
@ -409,6 +442,13 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
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);
IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
@ -873,6 +913,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
ULONG ResCount;
ULONG ListSize, ResultLength;
NTSTATUS Status;
HANDLE ControlHandle;
DPRINT("IopSetDeviceInstanceData() called\n");
@ -946,9 +987,21 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
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

View file

@ -161,7 +161,8 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
{
/* Create the PDO */
Status = PnpRootCreateDevice(&ServiceName,
&Pdo);
&Pdo,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);

View file

@ -131,30 +131,25 @@ LocateChildDevice(
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 @@ PnpRootCreateDevice(
}
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;
}
@ -189,6 +184,22 @@ PnpRootCreateDevice(
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 */
Status = IoCreateDevice(
PnpRootDeviceObject->DriverObject,