mirror of
https://github.com/reactos/reactos.git
synced 2025-05-21 10:05:35 +00:00
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
This commit is contained in:
parent
fe052d8d46
commit
0edb8fe2f9
1 changed files with 369 additions and 393 deletions
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
#define ENUM_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum"
|
||||||
|
|
||||||
PDEVICE_NODE IopRootDeviceNode;
|
PDEVICE_NODE IopRootDeviceNode;
|
||||||
KSPIN_LOCK IopDeviceTreeLock;
|
KSPIN_LOCK IopDeviceTreeLock;
|
||||||
ERESOURCE PpRegistryDeviceResource;
|
ERESOURCE PpRegistryDeviceResource;
|
||||||
|
@ -403,12 +405,13 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
|
||||||
case DevicePropertyLocationInformation:
|
case DevicePropertyLocationInformation:
|
||||||
case DevicePropertyUINumber:
|
case DevicePropertyUINumber:
|
||||||
{
|
{
|
||||||
LPWSTR RegistryPropertyName, KeyNameBuffer;
|
LPCWSTR RegistryPropertyName;
|
||||||
UNICODE_STRING KeyName, ValueName;
|
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
|
||||||
|
UNICODE_STRING ValueName;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
|
KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
|
||||||
ULONG ValueInformationLength;
|
ULONG ValueInformationLength;
|
||||||
HANDLE KeyHandle;
|
HANDLE hEnum, KeyHandle;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
switch (DeviceProperty)
|
switch (DeviceProperty)
|
||||||
|
@ -434,62 +437,70 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
|
||||||
case DevicePropertyUINumber:
|
case DevicePropertyUINumber:
|
||||||
RegistryPropertyName = L"UINumber"; break;
|
RegistryPropertyName = L"UINumber"; break;
|
||||||
default:
|
default:
|
||||||
RegistryPropertyName = NULL; break;
|
/* Should not happen */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyNameBuffer = ExAllocatePool(PagedPool,
|
DPRINT("Registry property %S\n", RegistryPropertyName);
|
||||||
(49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
|
|
||||||
|
|
||||||
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)
|
/* Open instance key */
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
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\\");
|
/* Allocate buffer to read as much data as required by the caller */
|
||||||
wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer);
|
ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
|
||||||
RtlInitUnicodeString(&KeyName, KeyNameBuffer);
|
Data[0]) + BufferLength;
|
||||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName,
|
ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
|
||||||
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
if (!ValueInformation)
|
||||||
|
{
|
||||||
|
ZwClose(KeyHandle);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
|
/* Read the value */
|
||||||
ExFreePool(KeyNameBuffer);
|
RtlInitUnicodeString(&ValueName, RegistryPropertyName);
|
||||||
if (!NT_SUCCESS(Status))
|
Status = ZwQueryValueKey(KeyHandle, &ValueName,
|
||||||
return Status;
|
KeyValuePartialInformation, ValueInformation,
|
||||||
|
ValueInformationLength,
|
||||||
|
&ValueInformationLength);
|
||||||
|
ZwClose(KeyHandle);
|
||||||
|
|
||||||
RtlInitUnicodeString(&ValueName, RegistryPropertyName);
|
if (!NT_SUCCESS(Status))
|
||||||
ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
|
{
|
||||||
Data[0]) + BufferLength;
|
ExFreePool(ValueInformation);
|
||||||
ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
|
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||||
if (ValueInformation == NULL)
|
{
|
||||||
{
|
*ResultLength = ValueInformation->DataLength;
|
||||||
ZwClose(KeyHandle);
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
*ResultLength = 0;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Status = ZwQueryValueKey(KeyHandle, &ValueName,
|
/* Return data */
|
||||||
KeyValuePartialInformation, ValueInformation,
|
*ResultLength = ValueInformation->DataLength;
|
||||||
ValueInformationLength,
|
/* FIXME: Verify the value (NULL-terminated, correct format). */
|
||||||
&ValueInformationLength);
|
RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
|
||||||
*ResultLength = ValueInformation->DataLength;
|
ValueInformation->DataLength);
|
||||||
ZwClose(KeyHandle);
|
ExFreePool(ValueInformation);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
return STATUS_SUCCESS;
|
||||||
{
|
}
|
||||||
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;
|
||||||
|
@ -510,43 +521,36 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
|
||||||
Data = &DeviceNode->BootResources;
|
Data = &DeviceNode->BootResources;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DevicePropertyEnumeratorName:
|
case DevicePropertyEnumeratorName:
|
||||||
Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
|
/* A buffer overflow can't happen here, since InstancePath
|
||||||
if (Ptr != NULL)
|
* always contains the enumerator name followed by \\ */
|
||||||
{
|
Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
|
||||||
Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR);
|
ASSERT(Ptr);
|
||||||
Data = DeviceNode->InstancePath.Buffer;
|
Length = (Ptr - DeviceNode->InstancePath.Buffer + 1) * sizeof(WCHAR);
|
||||||
}
|
Data = DeviceNode->InstancePath.Buffer;
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
Length = 0;
|
|
||||||
Data = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DevicePropertyPhysicalDeviceObjectName:
|
case DevicePropertyPhysicalDeviceObjectName:
|
||||||
Length = DeviceNode->InstancePath.Length + sizeof(WCHAR);
|
/* InstancePath buffer is NULL terminated, so we can do this */
|
||||||
Data = DeviceNode->InstancePath.Buffer;
|
Length = DeviceNode->InstancePath.MaximumLength;
|
||||||
break;
|
Data = DeviceNode->InstancePath.Buffer;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return STATUS_INVALID_PARAMETER_2;
|
return STATUS_INVALID_PARAMETER_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ResultLength = Length;
|
/* Prepare returned values */
|
||||||
if (BufferLength < Length)
|
*ResultLength = Length;
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
if (BufferLength < Length)
|
||||||
RtlCopyMemory(PropertyBuffer, Data, Length);
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
RtlCopyMemory(PropertyBuffer, Data, Length);
|
||||||
|
|
||||||
/* Terminate the string */
|
/* NULL terminate the string (if required) */
|
||||||
if (DeviceProperty == DevicePropertyEnumeratorName
|
if (DeviceProperty == DevicePropertyEnumeratorName)
|
||||||
|| DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
|
((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
{
|
|
||||||
Ptr = (PWSTR)PropertyBuffer;
|
|
||||||
Ptr[(Length / sizeof(WCHAR)) - 1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
NTSTATUS
|
||||||
IopCreateDeviceKeyPath(PWSTR Path,
|
NTAPI
|
||||||
PHANDLE Handle)
|
IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
|
||||||
|
OUT PHANDLE Handle)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
|
||||||
WCHAR KeyBuffer[MAX_PATH];
|
HANDLE hParent = NULL, hKey;
|
||||||
UNICODE_STRING KeyName;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
HANDLE KeyHandle;
|
UNICODE_STRING KeyName;
|
||||||
NTSTATUS Status;
|
LPCWSTR Current, Last;
|
||||||
PWCHAR Current;
|
ULONG dwLength;
|
||||||
PWCHAR Next;
|
NTSTATUS Status;
|
||||||
|
|
||||||
*Handle = NULL;
|
/* Assume failure */
|
||||||
|
*Handle = NULL;
|
||||||
|
|
||||||
if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
|
/* Open root key for device instances */
|
||||||
{
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
return STATUS_INVALID_PARAMETER;
|
&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\\ */
|
/* Go up to the end of the string */
|
||||||
Current = KeyBuffer;
|
while (Current <= Last)
|
||||||
Current = wcschr (Current, L'\\') + 1;
|
{
|
||||||
Current = wcschr (Current, L'\\') + 1;
|
if (Current != Last && *Current != '\\')
|
||||||
|
{
|
||||||
|
/* Not the end of the string and not a separator */
|
||||||
|
Current++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while (TRUE)
|
/* Prepare relative key name */
|
||||||
{
|
dwLength = (ULONG_PTR)Current - (ULONG_PTR)KeyName.Buffer;
|
||||||
Next = wcschr (Current, L'\\');
|
KeyName.MaximumLength = KeyName.Length = dwLength;
|
||||||
if (Next == NULL)
|
DPRINT("Create '%wZ'\n", &KeyName);
|
||||||
{
|
|
||||||
/* The end */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*Next = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&KeyName, KeyBuffer);
|
/* Open key */
|
||||||
InitializeObjectAttributes (&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&KeyName,
|
&KeyName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE,
|
||||||
NULL,
|
hParent,
|
||||||
NULL);
|
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 opening/creating failed? */
|
||||||
KEY_ALL_ACCESS,
|
if (!NT_SUCCESS(Status))
|
||||||
&ObjectAttributes,
|
{
|
||||||
0,
|
DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName, Status);
|
||||||
NULL,
|
return Status;
|
||||||
0,
|
}
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS (Status))
|
|
||||||
{
|
|
||||||
DPRINT ("ZwCreateKey() failed with status %x\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Next == NULL)
|
/* Check if it is the end of the string */
|
||||||
{
|
if (Current == Last)
|
||||||
*Handle = KeyHandle;
|
{
|
||||||
return STATUS_SUCCESS;
|
/* Yes, return success */
|
||||||
}
|
*Handle = hKey;
|
||||||
else
|
return STATUS_SUCCESS;
|
||||||
{
|
}
|
||||||
ZwClose (KeyHandle);
|
|
||||||
*Next = L'\\';
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
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");
|
DPRINT("IopSetDeviceInstanceData() done\n");
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -1606,98 +1603,96 @@ NTSTATUS
|
||||||
IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
|
IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
|
||||||
PUNICODE_STRING ParentIdPrefix)
|
PUNICODE_STRING ParentIdPrefix)
|
||||||
{
|
{
|
||||||
ULONG KeyNameBufferLength;
|
ULONG BufferLength;
|
||||||
PWSTR KeyNameBuffer = NULL;
|
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
|
PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation;
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyValue;
|
||||||
UNICODE_STRING KeyValue;
|
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"ParentIdPrefix");
|
||||||
UNICODE_STRING ValueName;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
HANDLE hEnum, hKey = NULL;
|
||||||
HANDLE hKey = NULL;
|
ULONG crc32;
|
||||||
ULONG crc32;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* HACK: As long as some devices have a NULL device
|
/* Allocate a buffer big enough to read a MAX_PATH prefix */
|
||||||
* instance path, the following test is required :(
|
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
|
||||||
*/
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1. Try to retrieve ParentIdPrefix from registry */
|
/* Check if allocation succeeded */
|
||||||
KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
|
if (!ParentIdPrefixInformation)
|
||||||
ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR));
|
{
|
||||||
if (!ParentIdPrefixInformation)
|
Status = STATUS_NO_MEMORY;
|
||||||
{
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Create the ParentIdPrefix value */
|
/* Open enum key */
|
||||||
crc32 = RtlComputeCrc32(0,
|
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||||
(PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
|
Status = ZwOpenKey(&hEnum, 0, &ObjectAttributes);
|
||||||
DeviceNode->Parent->InstancePath.Length);
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
|
/* Open instance key */
|
||||||
RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data);
|
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 */
|
/* Read the prefix */
|
||||||
Status = ZwSetValueKey(hKey,
|
Status = ZwQueryValueKey(
|
||||||
&ValueName,
|
hKey, &ValueName,
|
||||||
0,
|
KeyValuePartialInformation, ParentIdPrefixInformation,
|
||||||
REG_SZ,
|
BufferLength, &BufferLength);
|
||||||
(PVOID)KeyValue.Buffer,
|
if (NT_SUCCESS(Status))
|
||||||
(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
ExFreePool(ParentIdPrefixInformation);
|
/* General cleanup */
|
||||||
ExFreePool(KeyNameBuffer);
|
ExFreePool(ParentIdPrefixInformation);
|
||||||
if (hKey != NULL)
|
if (hKey != NULL)
|
||||||
ZwClose(hKey);
|
ZwClose(hKey);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1727,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;
|
||||||
|
@ -1791,12 +1786,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Copy the device id string */
|
/* Copy the device id string */
|
||||||
wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
|
RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information);
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Check for valid characters, if there is invalid characters
|
|
||||||
* then bugcheck.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1834,21 +1824,16 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Append the instance id string */
|
/* Append the instance id string */
|
||||||
wcscat(InstancePath, L"\\");
|
RtlAppendUnicodeToString(&InstancePathU, 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 */
|
||||||
wcscat(InstancePath, ParentIdPrefix.Buffer);
|
RtlAppendUnicodeStringToString(&InstancePathU, &ParentIdPrefix);
|
||||||
if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information)
|
if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information)
|
||||||
wcscat(InstancePath, L"&");
|
RtlAppendUnicodeToString(&InstancePathU, L"&");
|
||||||
}
|
}
|
||||||
if (IoStatusBlock.Information)
|
if (IoStatusBlock.Information)
|
||||||
wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
|
RtlAppendUnicodeToString(&InstancePathU, (PWSTR)IoStatusBlock.Information);
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Check for valid characters, if there is invalid characters
|
|
||||||
* then bugcheck
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1856,29 +1841,25 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString(&ParentIdPrefix);
|
RtlFreeUnicodeString(&ParentIdPrefix);
|
||||||
|
|
||||||
if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath))
|
/*
|
||||||
{
|
* FIXME: Check for valid characters, if there is invalid characters
|
||||||
DPRINT("No resources\n");
|
* then bugcheck.
|
||||||
/* FIXME: Cleanup and disable device */
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
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, &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 */
|
||||||
|
@ -2329,102 +2310,106 @@ NTSTATUS
|
||||||
IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
|
IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
|
||||||
PVOID Context)
|
PVOID Context)
|
||||||
{
|
{
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
RTL_QUERY_REGISTRY_TABLE QueryTable[4];
|
||||||
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
|
||||||
*/
|
*/
|
||||||
if (DeviceNode->Parent != ParentDeviceNode)
|
ASSERT(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))
|
||||||
{
|
{
|
||||||
WCHAR RegKeyBuffer[MAX_PATH];
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
UNICODE_STRING RegKey;
|
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT);
|
||||||
|
HANDLE hEnum;
|
||||||
|
|
||||||
RegKey.Length = 0;
|
/* Open Enum key */
|
||||||
RegKey.MaximumLength = sizeof(RegKeyBuffer);
|
InitializeObjectAttributes(&ObjectAttributes, &EnumU,
|
||||||
RegKey.Buffer = RegKeyBuffer;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* Prepare query table */
|
||||||
* Retrieve configuration from Enum key
|
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));
|
QueryTable[1].Name = L"Service";
|
||||||
RtlInitUnicodeString(Service, NULL);
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||||
RtlInitUnicodeString(&ClassGUID, NULL);
|
QueryTable[1].EntryContext = Service;
|
||||||
|
|
||||||
QueryTable[0].Name = L"Service";
|
QueryTable[2].Name = L"ClassGUID";
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||||
QueryTable[0].EntryContext = Service;
|
QueryTable[2].EntryContext = &ClassGUID;
|
||||||
|
QueryTable[2].DefaultType = REG_SZ;
|
||||||
|
QueryTable[2].DefaultData = L"";
|
||||||
|
QueryTable[2].DefaultLength = 0;
|
||||||
|
|
||||||
QueryTable[1].Name = L"ClassGUID";
|
/* Read registry */
|
||||||
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PWSTR)hEnum,
|
||||||
QueryTable[1].EntryContext = &ClassGUID;
|
QueryTable, NULL, NULL);
|
||||||
QueryTable[1].DefaultType = REG_SZ;
|
ZwClose(hEnum);
|
||||||
QueryTable[1].DefaultData = L"";
|
|
||||||
QueryTable[1].DefaultLength = 0;
|
|
||||||
|
|
||||||
RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
|
/* Check for an error */
|
||||||
RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
|
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,
|
/* Check for a NULL service */
|
||||||
RegKey.Buffer, QueryTable, NULL, NULL);
|
if (Service->Length == 0)
|
||||||
|
{
|
||||||
|
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (ClassGUID.Length != 0)
|
||||||
{
|
{
|
||||||
/* FIXME: Log the error */
|
/* Device has a ClassGUID value, but no Service value.
|
||||||
DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
|
* Suppose it is using the NULL driver, so state the
|
||||||
&DeviceNode->InstancePath, Status);
|
* device is started */
|
||||||
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
|
DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
|
||||||
return STATUS_SUCCESS;
|
IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
|
||||||
}
|
DeviceNode->Flags |= DN_STARTED;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (Service->Buffer == NULL)
|
DPRINT("Got Service %wZ\n", Service);
|
||||||
{
|
}
|
||||||
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
|
|
||||||
|
|
||||||
if (ClassGUID.Length != 0)
|
return STATUS_SUCCESS;
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2476,16 +2461,7 @@ 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
|
ASSERT(DeviceNode->Parent == ParentDeviceNode);
|
||||||
if (DeviceNode->Parent != ParentDeviceNode)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 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) &&
|
||||||
|
@ -2563,8 +2539,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) */
|
||||||
CPRINT("Initialization of service %S failed (Status %x)\n",
|
DPRINT("Initialization of service %wZ failed (Status %x)\n",
|
||||||
DeviceNode->ServiceName.Buffer, Status);
|
&DeviceNode->ServiceName, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue