From 0edb8fe2f9fceb8452ad59a84448bdc817c1de29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 27 Dec 2007 19:02:32 +0000 Subject: [PATCH] Use UNICODE_STRING and Rtl functions instead of LPWSTR variables (can prevent some buffer overflows) Remove assumption that UNICODE_STRING buffers are always NULL terminated Remove some intermediate buffers Do not define multiple times PnP parent key svn path=/trunk/; revision=31467 --- reactos/ntoskrnl/io/pnpmgr/pnpmgr.c | 762 ++++++++++++++-------------- 1 file changed, 369 insertions(+), 393 deletions(-) diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 810d77adabd..89edacde0c5 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -19,6 +19,8 @@ /* GLOBALS *******************************************************************/ +#define ENUM_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum" + PDEVICE_NODE IopRootDeviceNode; KSPIN_LOCK IopDeviceTreeLock; ERESOURCE PpRegistryDeviceResource; @@ -403,12 +405,13 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, case DevicePropertyLocationInformation: case DevicePropertyUINumber: { - LPWSTR RegistryPropertyName, KeyNameBuffer; - UNICODE_STRING KeyName, ValueName; + LPCWSTR RegistryPropertyName; + UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); + UNICODE_STRING ValueName; OBJECT_ATTRIBUTES ObjectAttributes; KEY_VALUE_PARTIAL_INFORMATION *ValueInformation; ULONG ValueInformationLength; - HANDLE KeyHandle; + HANDLE hEnum, KeyHandle; NTSTATUS Status; switch (DeviceProperty) @@ -434,62 +437,70 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, case DevicePropertyUINumber: RegistryPropertyName = L"UINumber"; break; default: - RegistryPropertyName = NULL; break; + /* Should not happen */ + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; } - KeyNameBuffer = ExAllocatePool(PagedPool, - (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length); + DPRINT("Registry property %S\n", RegistryPropertyName); - DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer, RegistryPropertyName); + /* Open Enum key */ + InitializeObjectAttributes(&ObjectAttributes, &EnumU, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return Status; - if (KeyNameBuffer == NULL) - return STATUS_INSUFFICIENT_RESOURCES; + /* Open instance key */ + InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->InstancePath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL); + Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + ZwClose(hEnum); + if (!NT_SUCCESS(Status)) + return Status; - wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer); - RtlInitUnicodeString(&KeyName, KeyNameBuffer); - InitializeObjectAttributes(&ObjectAttributes, &KeyName, - OBJ_CASE_INSENSITIVE, NULL, NULL); + /* Allocate buffer to read as much data as required by the caller */ + ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, + Data[0]) + BufferLength; + ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength); + if (!ValueInformation) + { + ZwClose(KeyHandle); + return STATUS_INSUFFICIENT_RESOURCES; + } - Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); - ExFreePool(KeyNameBuffer); - if (!NT_SUCCESS(Status)) - return Status; + /* Read the value */ + RtlInitUnicodeString(&ValueName, RegistryPropertyName); + Status = ZwQueryValueKey(KeyHandle, &ValueName, + KeyValuePartialInformation, ValueInformation, + ValueInformationLength, + &ValueInformationLength); + ZwClose(KeyHandle); - RtlInitUnicodeString(&ValueName, RegistryPropertyName); - ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, - Data[0]) + BufferLength; - ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength); - if (ValueInformation == NULL) - { - ZwClose(KeyHandle); - return STATUS_INSUFFICIENT_RESOURCES; - } + if (!NT_SUCCESS(Status)) + { + ExFreePool(ValueInformation); + if (Status == STATUS_BUFFER_OVERFLOW) + { + *ResultLength = ValueInformation->DataLength; + return STATUS_BUFFER_TOO_SMALL; + } + else + { + *ResultLength = 0; + return Status; + } + } - Status = ZwQueryValueKey(KeyHandle, &ValueName, - KeyValuePartialInformation, ValueInformation, - ValueInformationLength, - &ValueInformationLength); - *ResultLength = ValueInformation->DataLength; - ZwClose(KeyHandle); + /* Return data */ + *ResultLength = ValueInformation->DataLength; + /* FIXME: Verify the value (NULL-terminated, correct format). */ + RtlCopyMemory(PropertyBuffer, ValueInformation->Data, + ValueInformation->DataLength); + ExFreePool(ValueInformation); - if (!NT_SUCCESS(Status)) - { - ExFreePool(ValueInformation); - if (Status == STATUS_BUFFER_OVERFLOW) - return STATUS_BUFFER_TOO_SMALL; - else - return Status; - } - - /* FIXME: Verify the value (NULL-terminated, correct format). */ - - RtlCopyMemory(PropertyBuffer, ValueInformation->Data, - ValueInformation->DataLength); - ExFreePool(ValueInformation); - - return STATUS_SUCCESS; - } + return STATUS_SUCCESS; + } case DevicePropertyBootConfiguration: Length = 0; @@ -510,43 +521,36 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, Data = &DeviceNode->BootResources; break; - case DevicePropertyEnumeratorName: - Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\'); - if (Ptr != NULL) - { - Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR); - Data = DeviceNode->InstancePath.Buffer; - } - else - { - Length = 0; - Data = NULL; - } - break; + case DevicePropertyEnumeratorName: + /* A buffer overflow can't happen here, since InstancePath + * always contains the enumerator name followed by \\ */ + Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\'); + ASSERT(Ptr); + Length = (Ptr - DeviceNode->InstancePath.Buffer + 1) * sizeof(WCHAR); + Data = DeviceNode->InstancePath.Buffer; + break; - case DevicePropertyPhysicalDeviceObjectName: - Length = DeviceNode->InstancePath.Length + sizeof(WCHAR); - Data = DeviceNode->InstancePath.Buffer; - break; + case DevicePropertyPhysicalDeviceObjectName: + /* InstancePath buffer is NULL terminated, so we can do this */ + Length = DeviceNode->InstancePath.MaximumLength; + Data = DeviceNode->InstancePath.Buffer; + break; - default: - return STATUS_INVALID_PARAMETER_2; - } + default: + return STATUS_INVALID_PARAMETER_2; + } - *ResultLength = Length; - if (BufferLength < Length) - return STATUS_BUFFER_TOO_SMALL; - RtlCopyMemory(PropertyBuffer, Data, Length); + /* Prepare returned values */ + *ResultLength = Length; + if (BufferLength < Length) + return STATUS_BUFFER_TOO_SMALL; + RtlCopyMemory(PropertyBuffer, Data, Length); - /* Terminate the string */ - if (DeviceProperty == DevicePropertyEnumeratorName - || DeviceProperty == DevicePropertyPhysicalDeviceObjectName) - { - Ptr = (PWSTR)PropertyBuffer; - Ptr[(Length / sizeof(WCHAR)) - 1] = 0; - } + /* NULL terminate the string (if required) */ + if (DeviceProperty == DevicePropertyEnumeratorName) + ((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL; - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /* @@ -1062,82 +1066,110 @@ IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context) } -static +/* + * IopCreateDeviceKeyPath + * + * Creates a registry key + * + * Parameters + * RegistryPath + * Name of the key to be created. + * Handle + * Handle to the newly created key + * + * Remarks + * This method can create nested trees, so parent of RegistryPath can + * be not existant, and will be created if needed. + */ NTSTATUS -IopCreateDeviceKeyPath(PWSTR Path, - PHANDLE Handle) +NTAPI +IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, + OUT PHANDLE Handle) { - OBJECT_ATTRIBUTES ObjectAttributes; - WCHAR KeyBuffer[MAX_PATH]; - UNICODE_STRING KeyName; - HANDLE KeyHandle; - NTSTATUS Status; - PWCHAR Current; - PWCHAR Next; + UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); + HANDLE hParent = NULL, hKey; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + LPCWSTR Current, Last; + ULONG dwLength; + NTSTATUS Status; - *Handle = NULL; + /* Assume failure */ + *Handle = NULL; - if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0) - { - return STATUS_INVALID_PARAMETER; - } + /* Open root key for device instances */ + InitializeObjectAttributes(&ObjectAttributes, + &EnumU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey(&hParent, + KEY_CREATE_SUB_KEY, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status); + return Status; + } - wcsncpy (KeyBuffer, Path, MAX_PATH-1); + Current = KeyName.Buffer = RegistryPath->Buffer; + Last = &RegistryPath->Buffer[RegistryPath->Length / sizeof(WCHAR)]; - /* Skip \\Registry\\ */ - Current = KeyBuffer; - Current = wcschr (Current, L'\\') + 1; - Current = wcschr (Current, L'\\') + 1; + /* Go up to the end of the string */ + while (Current <= Last) + { + if (Current != Last && *Current != '\\') + { + /* Not the end of the string and not a separator */ + Current++; + continue; + } - while (TRUE) - { - Next = wcschr (Current, L'\\'); - if (Next == NULL) - { - /* The end */ - } - else - { - *Next = 0; - } + /* Prepare relative key name */ + dwLength = (ULONG_PTR)Current - (ULONG_PTR)KeyName.Buffer; + KeyName.MaximumLength = KeyName.Length = dwLength; + DPRINT("Create '%wZ'\n", &KeyName); - RtlInitUnicodeString (&KeyName, KeyBuffer); - InitializeObjectAttributes (&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + /* Open key */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + hParent, + NULL); + Status = ZwCreateKey(&hKey, + Current == Last ? KEY_ALL_ACCESS : KEY_CREATE_SUB_KEY, + &ObjectAttributes, + 0, + NULL, + 0, + NULL); - DPRINT("Create '%S'\n", KeyName.Buffer); + /* Close parent key handle, we don't need it anymore */ + if (hParent) + ZwClose(hParent); - Status = ZwCreateKey (&KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes, - 0, - NULL, - 0, - NULL); - if (!NT_SUCCESS (Status)) - { - DPRINT ("ZwCreateKey() failed with status %x\n", Status); - return Status; - } + /* Key opening/creating failed? */ + if (!NT_SUCCESS(Status)) + { + DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName, Status); + return Status; + } - if (Next == NULL) - { - *Handle = KeyHandle; - return STATUS_SUCCESS; - } - else - { - ZwClose (KeyHandle); - *Next = L'\\'; - } + /* Check if it is the end of the string */ + if (Current == Last) + { + /* Yes, return success */ + *Handle = hKey; + return STATUS_SUCCESS; + } - Current = Next + 1; - } + /* Start with this new parent key */ + hParent = hKey; + Current++; + KeyName.Buffer = (LPWSTR)Current; + } - return STATUS_UNSUCCESSFUL; + return STATUS_UNSUCCESSFUL; } @@ -1225,41 +1257,6 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, sizeof(DefaultConfigFlags)); } -#if 0 - if (DeviceNode->PhysicalDeviceObject != NULL) - { - /* Create the 'Control' key */ - RtlInitUnicodeString(&KeyName, - L"Control"); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - InstanceKey, - NULL); - Status = ZwCreateKey(&LogConfKey, - KEY_ALL_ACCESS, - &ObjectAttributes, - 0, - NULL, - REG_OPTION_VOLATILE, - NULL); - if (NT_SUCCESS(Status)) - { - ULONG Reference = (ULONG)DeviceNode->PhysicalDeviceObject; - RtlInitUnicodeString(&KeyName, - L"DeviceReference"); - Status = ZwSetValueKey(LogConfKey, - &KeyName, - 0, - REG_DWORD, - &Reference, - sizeof(PVOID)); - - ZwClose(LogConfKey); - } - } -#endif - DPRINT("IopSetDeviceInstanceData() done\n"); return STATUS_SUCCESS; @@ -1606,98 +1603,96 @@ NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix) { - ULONG KeyNameBufferLength; - PWSTR KeyNameBuffer = NULL; - PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL; - UNICODE_STRING KeyName; - UNICODE_STRING KeyValue; - UNICODE_STRING ValueName; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hKey = NULL; - ULONG crc32; - NTSTATUS Status; + ULONG BufferLength; + UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); + PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation; + UNICODE_STRING KeyValue; + UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"ParentIdPrefix"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hEnum, hKey = NULL; + ULONG crc32; + NTSTATUS Status; - /* HACK: As long as some devices have a NULL device - * instance path, the following test is required :( - */ - if (DeviceNode->Parent->InstancePath.Length == 0) - { - DPRINT1("Parent of %wZ has NULL Instance path, please report!\n", - &DeviceNode->InstancePath); - return STATUS_UNSUCCESSFUL; - } + /* Allocate a buffer big enough to read a MAX_PATH prefix */ + BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR); + ParentIdPrefixInformation = ExAllocatePool(PagedPool, BufferLength + sizeof(WCHAR)); - /* 1. Try to retrieve ParentIdPrefix from registry */ - KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR); - ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR)); - if (!ParentIdPrefixInformation) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - KeyNameBuffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length); - if (!KeyNameBuffer) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - wcscat(KeyNameBuffer, DeviceNode->Parent->InstancePath.Buffer); - RtlInitUnicodeString(&KeyName, KeyNameBuffer); - InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); - Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - goto cleanup; - RtlInitUnicodeString(&ValueName, L"ParentIdPrefix"); - Status = ZwQueryValueKey( - hKey, &ValueName, - KeyValuePartialInformation, ParentIdPrefixInformation, - KeyNameBufferLength, &KeyNameBufferLength); - if (NT_SUCCESS(Status)) - { - if (ParentIdPrefixInformation->Type != REG_SZ) - Status = STATUS_UNSUCCESSFUL; - else - { - KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; - KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; - } - goto cleanup; - } - if (Status != STATUS_OBJECT_NAME_NOT_FOUND) - { - KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; - KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; - goto cleanup; - } + /* Check if allocation succeeded */ + if (!ParentIdPrefixInformation) + { + Status = STATUS_NO_MEMORY; + goto cleanup; + } - /* 2. Create the ParentIdPrefix value */ - crc32 = RtlComputeCrc32(0, - (PUCHAR)DeviceNode->Parent->InstancePath.Buffer, - DeviceNode->Parent->InstancePath.Length); + /* Open enum key */ + InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + goto cleanup; - swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32); - RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data); + /* Open instance key */ + InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->Parent->InstancePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL); + Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes); + ZwClose(hEnum); + if (!NT_SUCCESS(Status)) + goto cleanup; - /* 3. Try to write the ParentIdPrefix to registry */ - Status = ZwSetValueKey(hKey, - &ValueName, - 0, - REG_SZ, - (PVOID)KeyValue.Buffer, - (wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR)); + /* Read the prefix */ + Status = ZwQueryValueKey( + hKey, &ValueName, + KeyValuePartialInformation, ParentIdPrefixInformation, + BufferLength, &BufferLength); + if (NT_SUCCESS(Status)) + { + /* Yes, we read something */ + if (ParentIdPrefixInformation->Type != REG_SZ) + /* Hm, it was of the wrong type. Fail */ + Status = STATUS_UNSUCCESSFUL; + else + { + /* OK, value is correct ; prepare to return it */ + KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; + KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; + } + + /* We're done */ + goto cleanup; + } + + /* Check if we failed due to value not calculated */ + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + /* Another reason, fail */ + goto cleanup; + + /* Compute the prefix string of the parent */ + crc32 = RtlComputeCrc32(0, + (PUCHAR)DeviceNode->Parent->InstancePath.Buffer, + DeviceNode->Parent->InstancePath.Length); + + /* Prepare the value to return */ + /* (yes, it's safe to reuse ParentIdPrefixInformation buffer, which is at least MAX_PATH WCHARs long */ + swprintf((PWSTR)ParentIdPrefixInformation, L"%lx&%lx", DeviceNode->Parent->Level, crc32); + RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation); + + /* 3. Try to write the ParentIdPrefix to registry */ + Status = ZwSetValueKey(hKey, + &ValueName, + 0, + REG_SZ, + (PVOID)KeyValue.Buffer, + KeyValue.MaximumLength); cleanup: - if (NT_SUCCESS(Status)) - { - /* Duplicate the string to return it */ - Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix); - } - ExFreePool(ParentIdPrefixInformation); - ExFreePool(KeyNameBuffer); - if (hKey != NULL) - ZwClose(hKey); - return Status; + if (NT_SUCCESS(Status)) + { + /* Duplicate the string to return it */ + Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix); + } + /* General cleanup */ + ExFreePool(ParentIdPrefixInformation); + if (hKey != NULL) + ZwClose(hKey); + return Status; } @@ -1727,9 +1722,9 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, IO_STATUS_BLOCK IoStatusBlock; PDEVICE_NODE ParentDeviceNode; WCHAR InstancePath[MAX_PATH]; + UNICODE_STRING InstancePathU = { 0, sizeof(InstancePath), InstancePath }; IO_STACK_LOCATION Stack; NTSTATUS Status; - PWSTR KeyBuffer; PWSTR Ptr; USHORT Length; USHORT TotalLength; @@ -1791,12 +1786,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, if (NT_SUCCESS(Status)) { /* Copy the device id string */ - wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information); - - /* - * FIXME: Check for valid characters, if there is invalid characters - * then bugcheck. - */ + RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information); } else { @@ -1834,21 +1824,16 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, if (NT_SUCCESS(Status)) { /* Append the instance id string */ - wcscat(InstancePath, L"\\"); + RtlAppendUnicodeToString(&InstancePathU, L"\\"); if (ParentIdPrefix.Length > 0) { /* Add information from parent bus device to InstancePath */ - wcscat(InstancePath, ParentIdPrefix.Buffer); + RtlAppendUnicodeStringToString(&InstancePathU, &ParentIdPrefix); if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information) - wcscat(InstancePath, L"&"); + RtlAppendUnicodeToString(&InstancePathU, L"&"); } if (IoStatusBlock.Information) - wcscat(InstancePath, (PWSTR)IoStatusBlock.Information); - - /* - * FIXME: Check for valid characters, if there is invalid characters - * then bugcheck - */ + RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information); } else { @@ -1856,29 +1841,25 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, } RtlFreeUnicodeString(&ParentIdPrefix); - if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath)) - { - DPRINT("No resources\n"); - /* FIXME: Cleanup and disable device */ - } + /* + * FIXME: Check for valid characters, if there is invalid characters + * then bugcheck. + */ - DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer); + Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &InstancePathU, &DeviceNode->InstancePath); + if (!NT_SUCCESS(Status)) + { + DPRINT("No resources\n"); + /* FIXME: Cleanup and disable device */ + } - /* - * Create registry key for the instance id, if it doesn't exist yet - */ - KeyBuffer = ExAllocatePool( - PagedPool, - (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length); - wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer); - Status = IopCreateDeviceKeyPath(KeyBuffer, &InstanceKey); - ExFreePool(KeyBuffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create the instance key! (Status %lx)\n", Status); - } + DPRINT("InstancePath is %wZ\n", &DeviceNode->InstancePath); + /* Create registry key for the instance id, if it doesn't exist yet */ + Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceKey); + if (!NT_SUCCESS(Status)) + DPRINT1("IopCreateDeviceKeyPath('%wZ') failed (Status 0x%08lx)\n", &DeviceNode->InstancePath, Status); { /* Set 'Capabilities' value */ @@ -2329,102 +2310,106 @@ NTSTATUS IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, PVOID Context) { - RTL_QUERY_REGISTRY_TABLE QueryTable[3]; - PDEVICE_NODE ParentDeviceNode; - PUNICODE_STRING Service; - UNICODE_STRING ClassGUID; - NTSTATUS Status; + RTL_QUERY_REGISTRY_TABLE QueryTable[4]; + PDEVICE_NODE ParentDeviceNode; + PUNICODE_STRING Service; + UNICODE_STRING ClassGUID; + NTSTATUS Status; - DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context); + DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context); - ParentDeviceNode = (PDEVICE_NODE)Context; + ParentDeviceNode = (PDEVICE_NODE)Context; - /* - * We are called for the parent too, but we don't need to do special - * handling for this node - */ - if (DeviceNode == ParentDeviceNode) - { - DPRINT("Success\n"); - return STATUS_SUCCESS; - } + /* + * We are called for the parent too, but we don't need to do special + * handling for this node + */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } - /* - * Make sure this device node is a direct child of the parent device node - * that is given as an argument - */ - if (DeviceNode->Parent != ParentDeviceNode) - { - /* Stop the traversal immediately and indicate successful operation */ - DPRINT("Stop\n"); - return STATUS_UNSUCCESSFUL; - } + /* + * Make sure this device node is a direct child of the parent device node + * that is given as an argument + */ + ASSERT(DeviceNode->Parent == ParentDeviceNode); - if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED)) - { - WCHAR RegKeyBuffer[MAX_PATH]; - UNICODE_STRING RegKey; + if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED)) + { + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); + HANDLE hEnum; - RegKey.Length = 0; - RegKey.MaximumLength = sizeof(RegKeyBuffer); - RegKey.Buffer = RegKeyBuffer; + /* Open Enum key */ + InitializeObjectAttributes(&ObjectAttributes, &EnumU, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL) + Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + return Status; + } - /* - * Retrieve configuration from Enum key - */ + /* Prepare query table */ + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + Service = &DeviceNode->ServiceName; + RtlInitUnicodeString(Service, NULL); + RtlInitUnicodeString(&ClassGUID, NULL); - Service = &DeviceNode->ServiceName; + /* Hopefully, this string is always NULL terminated */ + QueryTable[0].Name = DeviceNode->InstancePath.Buffer; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; - RtlZeroMemory(QueryTable, sizeof(QueryTable)); - RtlInitUnicodeString(Service, NULL); - RtlInitUnicodeString(&ClassGUID, NULL); + QueryTable[1].Name = L"Service"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[1].EntryContext = Service; - QueryTable[0].Name = L"Service"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = Service; + QueryTable[2].Name = L"ClassGUID"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[2].EntryContext = &ClassGUID; + QueryTable[2].DefaultType = REG_SZ; + QueryTable[2].DefaultData = L""; + QueryTable[2].DefaultLength = 0; - QueryTable[1].Name = L"ClassGUID"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[1].EntryContext = &ClassGUID; - QueryTable[1].DefaultType = REG_SZ; - QueryTable[1].DefaultData = L""; - QueryTable[1].DefaultLength = 0; + /* Read registry */ + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PWSTR)hEnum, + QueryTable, NULL, NULL); + ZwClose(hEnum); - RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath); + /* Check for an error */ + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n", + &DeviceNode->InstancePath, Status); + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + return STATUS_SUCCESS; + } - Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, - RegKey.Buffer, QueryTable, NULL, NULL); + /* Check for a NULL service */ + if (Service->Length == 0) + { + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); - if (!NT_SUCCESS(Status)) - { - /* FIXME: Log the error */ - DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n", - &DeviceNode->InstancePath, Status); - IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); - return STATUS_SUCCESS; - } + if (ClassGUID.Length != 0) + { + /* Device has a ClassGUID value, but no Service value. + * Suppose it is using the NULL driver, so state the + * device is started */ + DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath); + IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + DeviceNode->Flags |= DN_STARTED; + } + return STATUS_SUCCESS; + } - if (Service->Buffer == NULL) - { - IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + DPRINT("Got Service %wZ\n", Service); + } - if (ClassGUID.Length != 0) - { - /* Device has a ClassGUID value, but no Service value. - * Suppose it is using the NULL driver, so state the - * device is started */ - DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath); - IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); - DeviceNode->Flags |= DN_STARTED; - } - return STATUS_SUCCESS; - } - - DPRINT("Got Service %S\n", Service->Buffer); - } - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /* @@ -2476,16 +2461,7 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, * Make sure this device node is a direct child of the parent device node * that is given as an argument */ -#if 0 - if (DeviceNode->Parent != ParentDeviceNode) - { - /* - * Stop the traversal immediately and indicate unsuccessful operation - */ - DPRINT("Stop\n"); - return STATUS_UNSUCCESSFUL; - } -#endif + ASSERT(DeviceNode->Parent == ParentDeviceNode); if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) && !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) && @@ -2563,8 +2539,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED); /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */ - CPRINT("Initialization of service %S failed (Status %x)\n", - DeviceNode->ServiceName.Buffer, Status); + DPRINT("Initialization of service %wZ failed (Status %x)\n", + &DeviceNode->ServiceName, Status); } } }