mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[NTOSKRNL]
- Create a helper function named OpenRegistryHandlesFromSymbolicLink which opens handles to various paths associated with a symbolic link - Store the Linked value in IoSetDeviceInterfaceState - Implement checking if an interface is enabled by reading the Linked value - Interfaces reported from IoGetDeviceInterfaces are only active ones now (unless the caller explicitly says that they want disabled ones too) svn path=/trunk/; revision=47029
This commit is contained in:
parent
770cc844b0
commit
540e5b6f31
1 changed files with 280 additions and 12 deletions
|
@ -20,6 +20,180 @@
|
||||||
|
|
||||||
static PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
|
static PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
OpenRegistryHandlesFromSymbolicLink(IN PUNICODE_STRING SymbolicLinkName,
|
||||||
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN OPTIONAL PHANDLE GuidKey,
|
||||||
|
IN OPTIONAL PHANDLE DeviceKey,
|
||||||
|
IN OPTIONAL PHANDLE InstanceKey)
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
WCHAR PathBuffer[MAX_PATH];
|
||||||
|
UNICODE_STRING BaseKeyU;
|
||||||
|
UNICODE_STRING GuidString, SubKeyName, ReferenceString;
|
||||||
|
PWCHAR StartPosition, EndPosition;
|
||||||
|
HANDLE ClassesKey;
|
||||||
|
PHANDLE GuidKeyRealP, DeviceKeyRealP, InstanceKeyRealP;
|
||||||
|
HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
SubKeyName.Buffer = NULL;
|
||||||
|
|
||||||
|
if (GuidKey != NULL)
|
||||||
|
GuidKeyRealP = GuidKey;
|
||||||
|
else
|
||||||
|
GuidKeyRealP = &GuidKeyReal;
|
||||||
|
|
||||||
|
if (DeviceKey != NULL)
|
||||||
|
DeviceKeyRealP = DeviceKey;
|
||||||
|
else
|
||||||
|
DeviceKeyRealP = &DeviceKeyReal;
|
||||||
|
|
||||||
|
if (InstanceKey != NULL)
|
||||||
|
InstanceKeyRealP = InstanceKey;
|
||||||
|
else
|
||||||
|
InstanceKeyRealP = &InstanceKeyReal;
|
||||||
|
|
||||||
|
*GuidKeyRealP = INVALID_HANDLE_VALUE;
|
||||||
|
*DeviceKeyRealP = INVALID_HANDLE_VALUE;
|
||||||
|
*InstanceKeyRealP = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
BaseKeyU.Buffer = PathBuffer;
|
||||||
|
BaseKeyU.Length = 0;
|
||||||
|
BaseKeyU.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||||||
|
|
||||||
|
RtlAppendUnicodeToString(&BaseKeyU, BaseKeyString);
|
||||||
|
|
||||||
|
/* Open the DeviceClasses key */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&BaseKeyU,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
Status = ZwOpenKey(&ClassesKey,
|
||||||
|
DesiredAccess | KEY_ENUMERATE_SUB_KEYS,
|
||||||
|
&ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open %wZ\n", &BaseKeyU);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartPosition = wcschr(SymbolicLinkName->Buffer, L'{');
|
||||||
|
EndPosition = wcschr(SymbolicLinkName->Buffer, L'}');
|
||||||
|
if (!StartPosition || !EndPosition || StartPosition > EndPosition)
|
||||||
|
{
|
||||||
|
DPRINT1("Bad symbolic link: %wZ\n", SymbolicLinkName);
|
||||||
|
return STATUS_INVALID_PARAMETER_1;
|
||||||
|
}
|
||||||
|
GuidString.Buffer = StartPosition;
|
||||||
|
GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition);
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&GuidString,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
ClassesKey,
|
||||||
|
NULL);
|
||||||
|
Status = ZwOpenKey(GuidKeyRealP,
|
||||||
|
DesiredAccess | KEY_ENUMERATE_SUB_KEYS,
|
||||||
|
&ObjectAttributes);
|
||||||
|
ZwClose(ClassesKey);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open %wZ%wZ (%x)\n", &BaseKeyU, &GuidString, Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubKeyName.Buffer = ExAllocatePool(PagedPool, SymbolicLinkName->Length);
|
||||||
|
if (!SubKeyName.Buffer)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
SubKeyName.MaximumLength = SymbolicLinkName->Length;
|
||||||
|
SubKeyName.Length = 0;
|
||||||
|
|
||||||
|
RtlAppendUnicodeStringToString(&SubKeyName,
|
||||||
|
SymbolicLinkName);
|
||||||
|
|
||||||
|
SubKeyName.Buffer[0] = L'#';
|
||||||
|
SubKeyName.Buffer[1] = L'#';
|
||||||
|
SubKeyName.Buffer[2] = L'?';
|
||||||
|
SubKeyName.Buffer[3] = L'#';
|
||||||
|
|
||||||
|
ReferenceString.Buffer = wcsrchr(SubKeyName.Buffer, '\\');
|
||||||
|
if (ReferenceString.Buffer != NULL)
|
||||||
|
{
|
||||||
|
ReferenceString.Buffer[0] = L'#';
|
||||||
|
|
||||||
|
SubKeyName.Length = ReferenceString.Buffer - SubKeyName.Buffer;
|
||||||
|
ReferenceString.Length = SymbolicLinkName->Length - SubKeyName.Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&ReferenceString, L"#");
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&SubKeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
*GuidKeyRealP,
|
||||||
|
NULL);
|
||||||
|
Status = ZwOpenKey(DeviceKeyRealP,
|
||||||
|
DesiredAccess | KEY_ENUMERATE_SUB_KEYS,
|
||||||
|
&ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open %wZ%wZ\\%wZ\n", &BaseKeyU, &GuidString, &SubKeyName);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ReferenceString,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
*DeviceKeyRealP,
|
||||||
|
NULL);
|
||||||
|
Status = ZwOpenKey(InstanceKeyRealP,
|
||||||
|
DesiredAccess,
|
||||||
|
&ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open %wZ%wZ\\%wZ%\\%wZ (%x)\n", &BaseKeyU, &GuidString, &SubKeyName, &ReferenceString, Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (SubKeyName.Buffer != NULL)
|
||||||
|
ExFreePool(SubKeyName.Buffer);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
if (!GuidKey)
|
||||||
|
ZwClose(*GuidKeyRealP);
|
||||||
|
|
||||||
|
if (!DeviceKey)
|
||||||
|
ZwClose(*DeviceKeyRealP);
|
||||||
|
|
||||||
|
if (!InstanceKey)
|
||||||
|
ZwClose(*InstanceKeyRealP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*GuidKeyRealP != INVALID_HANDLE_VALUE)
|
||||||
|
ZwClose(*GuidKeyRealP);
|
||||||
|
|
||||||
|
if (*DeviceKeyRealP != INVALID_HANDLE_VALUE)
|
||||||
|
ZwClose(*DeviceKeyRealP);
|
||||||
|
|
||||||
|
if (*InstanceKeyRealP != INVALID_HANDLE_VALUE)
|
||||||
|
ZwClose(*InstanceKeyRealP);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/*++
|
/*++
|
||||||
* @name IoOpenDeviceInterfaceRegistryKey
|
* @name IoOpenDeviceInterfaceRegistryKey
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
|
@ -395,10 +569,11 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
||||||
PKEY_BASIC_INFORMATION DeviceBi = NULL;
|
PKEY_BASIC_INFORMATION DeviceBi = NULL;
|
||||||
PKEY_BASIC_INFORMATION ReferenceBi = NULL;
|
PKEY_BASIC_INFORMATION ReferenceBi = NULL;
|
||||||
PKEY_VALUE_PARTIAL_INFORMATION bip = NULL;
|
PKEY_VALUE_PARTIAL_INFORMATION bip = NULL;
|
||||||
|
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyName;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
BOOLEAN FoundRightPDO = FALSE;
|
BOOLEAN FoundRightPDO = FALSE;
|
||||||
ULONG i = 0, j, Size;
|
ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
|
||||||
UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
|
UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
@ -552,7 +727,6 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
||||||
/* We have to check if the interface is enabled, by
|
/* We have to check if the interface is enabled, by
|
||||||
* reading the Linked value in the Control subkey
|
* reading the Linked value in the Control subkey
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
InitializeObjectAttributes(
|
InitializeObjectAttributes(
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
&Control,
|
&Control,
|
||||||
|
@ -572,17 +746,63 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
||||||
}
|
}
|
||||||
else if (!NT_SUCCESS(Status))
|
else if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"Linked");
|
||||||
|
Status = ZwQueryValueKey(ControlKey,
|
||||||
|
&KeyName,
|
||||||
|
KeyValuePartialInformation,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&NeededLength);
|
||||||
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
ActualLength = NeededLength;
|
||||||
|
PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
|
||||||
|
if (!PartialInfo)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ZwQueryValueKey(ControlKey,
|
||||||
|
&KeyName,
|
||||||
|
KeyValuePartialInformation,
|
||||||
|
PartialInfo,
|
||||||
|
ActualLength,
|
||||||
|
&NeededLength);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
|
||||||
|
ExFreePool(PartialInfo);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
|
||||||
|
{
|
||||||
|
DPRINT1("Bad registry read\n");
|
||||||
|
ExFreePool(PartialInfo);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(&LinkedValue,
|
||||||
|
PartialInfo->Data,
|
||||||
|
PartialInfo->DataLength);
|
||||||
|
|
||||||
|
ExFreePool(PartialInfo);
|
||||||
|
if (LinkedValue == 0)
|
||||||
|
{
|
||||||
|
/* This interface isn't active */
|
||||||
|
goto NextReferenceString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/* FIXME: Read the Linked value
|
|
||||||
* If it doesn't exist => ERROR
|
|
||||||
* If it is not a REG_DWORD or Size != sizeof(ULONG) => ERROR
|
|
||||||
* If its value is 0, go to NextReferenceString
|
|
||||||
* At the moment, do as if it is active...
|
|
||||||
*/
|
|
||||||
DPRINT1("Checking if device is enabled is not implemented yet!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the SymbolicLink string and add it into SymbolicLinkList */
|
/* Read the SymbolicLink string and add it into SymbolicLinkList */
|
||||||
|
@ -1118,7 +1338,10 @@ IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName,
|
||||||
PWCHAR EndPosition;
|
PWCHAR EndPosition;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
LPCGUID EventGuid;
|
LPCGUID EventGuid;
|
||||||
|
HANDLE InstanceHandle, ControlHandle;
|
||||||
|
UNICODE_STRING KeyName;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
ULONG LinkedValue;
|
||||||
|
|
||||||
if (SymbolicLinkName == NULL)
|
if (SymbolicLinkName == NULL)
|
||||||
return STATUS_INVALID_PARAMETER_1;
|
return STATUS_INVALID_PARAMETER_1;
|
||||||
|
@ -1140,6 +1363,51 @@ IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName,
|
||||||
SymLink.Buffer = SymbolicLinkName->Buffer;
|
SymLink.Buffer = SymbolicLinkName->Buffer;
|
||||||
SymLink.MaximumLength = SymLink.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)SymLink.Buffer);
|
SymLink.MaximumLength = SymLink.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)SymLink.Buffer);
|
||||||
DPRINT("IoSetDeviceInterfaceState('%wZ', %d)\n", SymbolicLinkName, Enable);
|
DPRINT("IoSetDeviceInterfaceState('%wZ', %d)\n", SymbolicLinkName, Enable);
|
||||||
|
|
||||||
|
Status = OpenRegistryHandlesFromSymbolicLink(SymbolicLinkName,
|
||||||
|
KEY_CREATE_SUB_KEY,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&InstanceHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"Control");
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&KeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
InstanceHandle,
|
||||||
|
NULL);
|
||||||
|
Status = ZwCreateKey(&ControlHandle,
|
||||||
|
KEY_SET_VALUE,
|
||||||
|
&ObjectAttributes,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
REG_OPTION_VOLATILE,
|
||||||
|
NULL);
|
||||||
|
ZwClose(InstanceHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create the Control subkey\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedValue = (Enable ? 1 : 0);
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&KeyName, L"Linked");
|
||||||
|
Status = ZwSetValueKey(ControlHandle,
|
||||||
|
&KeyName,
|
||||||
|
0,
|
||||||
|
REG_DWORD,
|
||||||
|
&LinkedValue,
|
||||||
|
sizeof(ULONG));
|
||||||
|
ZwClose(ControlHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to write the Linked value\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get pointer to the PDO */
|
/* Get pointer to the PDO */
|
||||||
Status = IoGetDeviceObjectPointer(
|
Status = IoGetDeviceObjectPointer(
|
||||||
&SymLink,
|
&SymLink,
|
||||||
|
|
Loading…
Reference in a new issue