- Partially revert 31467 to unbreak devices installation.

svn path=/trunk/; revision=31495
This commit is contained in:
Aleksey Bragin 2007-12-29 21:39:15 +00:00
parent a701dd6a99
commit 6cda2ec675

View file

@ -405,13 +405,12 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
case DevicePropertyLocationInformation: case DevicePropertyLocationInformation:
case DevicePropertyUINumber: case DevicePropertyUINumber:
{ {
LPCWSTR RegistryPropertyName; LPWSTR RegistryPropertyName, KeyNameBuffer;
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); UNICODE_STRING KeyName, ValueName;
UNICODE_STRING ValueName;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
KEY_VALUE_PARTIAL_INFORMATION *ValueInformation; KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
ULONG ValueInformationLength; ULONG ValueInformationLength;
HANDLE hEnum, KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
switch (DeviceProperty) switch (DeviceProperty)
@ -437,70 +436,62 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
case DevicePropertyUINumber: case DevicePropertyUINumber:
RegistryPropertyName = L"UINumber"; break; RegistryPropertyName = L"UINumber"; break;
default: default:
/* Should not happen */ RegistryPropertyName = NULL; break;
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
} }
DPRINT("Registry property %S\n", RegistryPropertyName); KeyNameBuffer = ExAllocatePool(PagedPool,
(49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
/* Open Enum key */ DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer, RegistryPropertyName);
InitializeObjectAttributes(&ObjectAttributes, &EnumU,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
if (!NT_SUCCESS(Status))
return Status;
/* Open instance key */ if (KeyNameBuffer == NULL)
InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->InstancePath, return STATUS_INSUFFICIENT_RESOURCES;
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
ZwClose(hEnum);
if (!NT_SUCCESS(Status))
return Status;
/* Allocate buffer to read as much data as required by the caller */ wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer);
Data[0]) + BufferLength; RtlInitUnicodeString(&KeyName, KeyNameBuffer);
ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength); InitializeObjectAttributes(&ObjectAttributes, &KeyName,
if (!ValueInformation) OBJ_CASE_INSENSITIVE, NULL, NULL);
{
ZwClose(KeyHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Read the value */ Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
RtlInitUnicodeString(&ValueName, RegistryPropertyName); ExFreePool(KeyNameBuffer);
Status = ZwQueryValueKey(KeyHandle, &ValueName, if (!NT_SUCCESS(Status))
KeyValuePartialInformation, ValueInformation, return Status;
ValueInformationLength,
&ValueInformationLength);
ZwClose(KeyHandle);
if (!NT_SUCCESS(Status)) RtlInitUnicodeString(&ValueName, RegistryPropertyName);
{ ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
ExFreePool(ValueInformation); Data[0]) + BufferLength;
if (Status == STATUS_BUFFER_OVERFLOW) ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
{ if (ValueInformation == NULL)
*ResultLength = ValueInformation->DataLength; {
return STATUS_BUFFER_TOO_SMALL; ZwClose(KeyHandle);
} return STATUS_INSUFFICIENT_RESOURCES;
else }
{
*ResultLength = 0;
return Status;
}
}
/* Return data */ Status = ZwQueryValueKey(KeyHandle, &ValueName,
*ResultLength = ValueInformation->DataLength; KeyValuePartialInformation, ValueInformation,
/* FIXME: Verify the value (NULL-terminated, correct format). */ ValueInformationLength,
RtlCopyMemory(PropertyBuffer, ValueInformation->Data, &ValueInformationLength);
ValueInformation->DataLength); *ResultLength = ValueInformation->DataLength;
ExFreePool(ValueInformation); ZwClose(KeyHandle);
return STATUS_SUCCESS; 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;
}
case DevicePropertyBootConfiguration: case DevicePropertyBootConfiguration:
Length = 0; Length = 0;
@ -521,36 +512,43 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
Data = &DeviceNode->BootResources; Data = &DeviceNode->BootResources;
break; break;
case DevicePropertyEnumeratorName: case DevicePropertyEnumeratorName:
/* A buffer overflow can't happen here, since InstancePath Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
* always contains the enumerator name followed by \\ */ if (Ptr != NULL)
Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\'); {
ASSERT(Ptr); Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR);
Length = (Ptr - DeviceNode->InstancePath.Buffer + 1) * sizeof(WCHAR); Data = DeviceNode->InstancePath.Buffer;
Data = DeviceNode->InstancePath.Buffer; }
break; else
{
Length = 0;
Data = NULL;
}
break;
case DevicePropertyPhysicalDeviceObjectName: case DevicePropertyPhysicalDeviceObjectName:
/* InstancePath buffer is NULL terminated, so we can do this */ Length = DeviceNode->InstancePath.Length + sizeof(WCHAR);
Length = DeviceNode->InstancePath.MaximumLength; Data = DeviceNode->InstancePath.Buffer;
Data = DeviceNode->InstancePath.Buffer; break;
break;
default: default:
return STATUS_INVALID_PARAMETER_2; return STATUS_INVALID_PARAMETER_2;
} }
/* Prepare returned values */ *ResultLength = Length;
*ResultLength = Length; if (BufferLength < Length)
if (BufferLength < Length) return STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL; RtlCopyMemory(PropertyBuffer, Data, Length);
RtlCopyMemory(PropertyBuffer, Data, Length);
/* NULL terminate the string (if required) */ /* Terminate the string */
if (DeviceProperty == DevicePropertyEnumeratorName) if (DeviceProperty == DevicePropertyEnumeratorName
((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL; || DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
{
Ptr = (PWSTR)PropertyBuffer;
Ptr[(Length / sizeof(WCHAR)) - 1] = 0;
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* /*
@ -1603,98 +1601,98 @@ NTSTATUS
IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
PUNICODE_STRING ParentIdPrefix) PUNICODE_STRING ParentIdPrefix)
{ {
ULONG BufferLength; ULONG KeyNameBufferLength;
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); PWSTR KeyNameBuffer = NULL;
PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation; PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
UNICODE_STRING KeyValue; UNICODE_STRING KeyName;
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"ParentIdPrefix"); UNICODE_STRING KeyValue;
OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING ValueName;
HANDLE hEnum, hKey = NULL; OBJECT_ATTRIBUTES ObjectAttributes;
ULONG crc32; HANDLE hKey = NULL;
NTSTATUS Status; ULONG crc32;
NTSTATUS Status;
/* Allocate a buffer big enough to read a MAX_PATH prefix */ /* HACK: As long as some devices have a NULL device
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR); * instance path, the following test is required :(
ParentIdPrefixInformation = ExAllocatePool(PagedPool, BufferLength + sizeof(WCHAR)); */
if (DeviceNode->Parent->InstancePath.Length == 0)
{
DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
&DeviceNode->InstancePath);
return STATUS_UNSUCCESSFUL;
}
/* Check if allocation succeeded */ /* 1. Try to retrieve ParentIdPrefix from registry */
if (!ParentIdPrefixInformation) KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
{ ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR));
Status = STATUS_NO_MEMORY; if (!ParentIdPrefixInformation)
goto cleanup; {
} 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;
}
/* Open enum key */ /* 2. Create the ParentIdPrefix value */
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); crc32 = RtlComputeCrc32(0,
Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes); (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
if (!NT_SUCCESS(Status)) DeviceNode->Parent->InstancePath.Length);
goto cleanup;
/* Open instance key */ swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
InitializeObjectAttributes(&ObjectAttributes, &DeviceNode->Parent->InstancePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hEnum, NULL); RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data);
Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes);
ZwClose(hEnum);
if (!NT_SUCCESS(Status))
goto cleanup;
/* Read the prefix */ /* 3. Try to write the ParentIdPrefix to registry */
Status = ZwQueryValueKey( Status = ZwSetValueKey(hKey,
hKey, &ValueName, &ValueName,
KeyValuePartialInformation, ParentIdPrefixInformation, 0,
BufferLength, &BufferLength); REG_SZ,
if (NT_SUCCESS(Status)) (PVOID)KeyValue.Buffer,
{ (wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
/* 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;
if (KeyValue.Length && KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR) - 1] == UNICODE_NULL);
KeyValue.Length -= sizeof(WCHAR);
}
/* 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: cleanup:
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Duplicate the string to return it */ /* Duplicate the string to return it */
Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix); Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix);
} }
/* General cleanup */ ExFreePool(ParentIdPrefixInformation);
ExFreePool(ParentIdPrefixInformation); ExFreePool(KeyNameBuffer);
if (hKey != NULL) if (hKey != NULL)
ZwClose(hKey); ZwClose(hKey);
return Status; return Status;
} }
@ -1724,9 +1722,9 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_NODE ParentDeviceNode; PDEVICE_NODE ParentDeviceNode;
WCHAR InstancePath[MAX_PATH]; WCHAR InstancePath[MAX_PATH];
UNICODE_STRING InstancePathU = { 0, sizeof(InstancePath), InstancePath };
IO_STACK_LOCATION Stack; IO_STACK_LOCATION Stack;
NTSTATUS Status; NTSTATUS Status;
PWSTR KeyBuffer;
PWSTR Ptr; PWSTR Ptr;
USHORT Length; USHORT Length;
USHORT TotalLength; USHORT TotalLength;
@ -1788,7 +1786,12 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Copy the device id string */ /* Copy the device id string */
RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information); wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
/*
* FIXME: Check for valid characters, if there is invalid characters
* then bugcheck.
*/
} }
else else
{ {
@ -1826,16 +1829,21 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Append the instance id string */ /* Append the instance id string */
RtlAppendUnicodeToString(&InstancePathU, L"\\"); wcscat(InstancePath, L"\\");
if (ParentIdPrefix.Length > 0) if (ParentIdPrefix.Length > 0)
{ {
/* Add information from parent bus device to InstancePath */ /* Add information from parent bus device to InstancePath */
RtlAppendUnicodeStringToString(&InstancePathU, &ParentIdPrefix); wcscat(InstancePath, ParentIdPrefix.Buffer);
if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information) if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information)
RtlAppendUnicodeToString(&InstancePathU, L"&"); wcscat(InstancePath, L"&");
} }
if (IoStatusBlock.Information) if (IoStatusBlock.Information)
RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information); wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
/*
* FIXME: Check for valid characters, if there is invalid characters
* then bugcheck
*/
} }
else else
{ {
@ -1843,25 +1851,29 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
} }
RtlFreeUnicodeString(&ParentIdPrefix); RtlFreeUnicodeString(&ParentIdPrefix);
/* if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath))
* FIXME: Check for valid characters, if there is invalid characters {
* then bugcheck. DPRINT("No resources\n");
*/ /* FIXME: Cleanup and disable device */
}
Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
&InstancePathU, &DeviceNode->InstancePath);
if (!NT_SUCCESS(Status))
{
DPRINT("No resources\n");
/* FIXME: Cleanup and disable device */
}
DPRINT("InstancePath is %wZ\n", &DeviceNode->InstancePath); /*
* 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*/&DeviceNode->InstancePath, &InstanceKey);
ExFreePool(KeyBuffer);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
}
/* 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 */ /* Set 'Capabilities' value */
@ -2312,106 +2324,102 @@ NTSTATUS
IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
PVOID Context) PVOID Context)
{ {
RTL_QUERY_REGISTRY_TABLE QueryTable[4]; RTL_QUERY_REGISTRY_TABLE QueryTable[3];
PDEVICE_NODE ParentDeviceNode; PDEVICE_NODE ParentDeviceNode;
PUNICODE_STRING Service; PUNICODE_STRING Service;
UNICODE_STRING ClassGUID; UNICODE_STRING ClassGUID;
NTSTATUS Status; 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 * We are called for the parent too, but we don't need to do special
* handling for this node * handling for this node
*/ */
if (DeviceNode == ParentDeviceNode) if (DeviceNode == ParentDeviceNode)
{ {
DPRINT("Success\n"); DPRINT("Success\n");
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* /*
* Make sure this device node is a direct child of the parent device node * Make sure this device node is a direct child of the parent device node
* that is given as an argument * that is given as an argument
*/ */
ASSERT(DeviceNode->Parent == ParentDeviceNode); if (DeviceNode->Parent != ParentDeviceNode)
{
/* Stop the traversal immediately and indicate successful operation */
DPRINT("Stop\n");
return STATUS_UNSUCCESSFUL;
}
if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED)) if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
{ {
OBJECT_ATTRIBUTES ObjectAttributes; WCHAR RegKeyBuffer[MAX_PATH];
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); UNICODE_STRING RegKey;
HANDLE hEnum;
/* Open Enum key */ RegKey.Length = 0;
InitializeObjectAttributes(&ObjectAttributes, &EnumU, RegKey.MaximumLength = sizeof(RegKeyBuffer);
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL) RegKey.Buffer = RegKeyBuffer;
Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
/* FIXME: Log the error */
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
return Status;
}
/* Prepare query table */ /*
RtlZeroMemory(QueryTable, sizeof(QueryTable)); * Retrieve configuration from Enum key
Service = &DeviceNode->ServiceName; */
RtlInitUnicodeString(Service, NULL);
RtlInitUnicodeString(&ClassGUID, NULL);
/* Hopefully, this string is always NULL terminated */ Service = &DeviceNode->ServiceName;
QueryTable[0].Name = DeviceNode->InstancePath.Buffer;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
QueryTable[1].Name = L"Service"; RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; RtlInitUnicodeString(Service, NULL);
QueryTable[1].EntryContext = Service; RtlInitUnicodeString(&ClassGUID, NULL);
QueryTable[2].Name = L"ClassGUID"; QueryTable[0].Name = L"Service";
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[2].EntryContext = &ClassGUID; QueryTable[0].EntryContext = Service;
QueryTable[2].DefaultType = REG_SZ;
QueryTable[2].DefaultData = L"";
QueryTable[2].DefaultLength = 0;
/* Read registry */ QueryTable[1].Name = L"ClassGUID";
Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PWSTR)hEnum, QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable, NULL, NULL); QueryTable[1].EntryContext = &ClassGUID;
ZwClose(hEnum); QueryTable[1].DefaultType = REG_SZ;
QueryTable[1].DefaultData = L"";
QueryTable[1].DefaultLength = 0;
/* Check for an error */ RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
if (!NT_SUCCESS(Status)) RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
{
/* 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;
}
/* Check for a NULL service */ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
if (Service->Length == 0) RegKey.Buffer, QueryTable, NULL, NULL);
{
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
if (ClassGUID.Length != 0) if (!NT_SUCCESS(Status))
{ {
/* Device has a ClassGUID value, but no Service value. /* FIXME: Log the error */
* Suppose it is using the NULL driver, so state the DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
* device is started */ &DeviceNode->InstancePath, Status);
DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath); IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); return STATUS_SUCCESS;
DeviceNode->Flags |= DN_STARTED; }
}
return STATUS_SUCCESS;
}
DPRINT("Got Service %wZ\n", Service); if (Service->Buffer == NULL)
} {
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;
}
DPRINT("Got Service %S\n", Service->Buffer);
}
return STATUS_SUCCESS;
} }
/* /*
@ -2463,11 +2471,16 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
* Make sure this device node is a direct child of the parent device node * Make sure this device node is a direct child of the parent device node
* that is given as an argument * that is given as an argument
*/ */
#if 0
if (DeviceNode->Parent != ParentDeviceNode) if (DeviceNode->Parent != ParentDeviceNode)
{ {
DPRINT("Not a direct child\n"); /*
return STATUS_UNSUCCESSFUL; * Stop the traversal immediately and indicate unsuccessful operation
*/
DPRINT("Stop\n");
return STATUS_UNSUCCESSFUL;
} }
#endif
if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) && if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
!IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) && !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
@ -2545,8 +2558,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED); IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
/* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */ /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
DPRINT("Initialization of service %wZ failed (Status %x)\n", CPRINT("Initialization of service %S failed (Status %x)\n",
&DeviceNode->ServiceName, Status); DeviceNode->ServiceName.Buffer, Status);
} }
} }
} }