mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +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
|
||||
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
|
||||
* @unimplemented
|
||||
|
@ -395,10 +569,11 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
|||
PKEY_BASIC_INFORMATION DeviceBi = NULL;
|
||||
PKEY_BASIC_INFORMATION ReferenceBi = NULL;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION bip = NULL;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
|
||||
UNICODE_STRING KeyName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
BOOLEAN FoundRightPDO = FALSE;
|
||||
ULONG i = 0, j, Size;
|
||||
ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
|
||||
UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -552,7 +727,6 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
|||
/* We have to check if the interface is enabled, by
|
||||
* reading the Linked value in the Control subkey
|
||||
*/
|
||||
#if 0
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&Control,
|
||||
|
@ -572,17 +746,63 @@ IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid,
|
|||
}
|
||||
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;
|
||||
}
|
||||
#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 */
|
||||
|
@ -1118,7 +1338,10 @@ IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName,
|
|||
PWCHAR EndPosition;
|
||||
NTSTATUS Status;
|
||||
LPCGUID EventGuid;
|
||||
|
||||
HANDLE InstanceHandle, ControlHandle;
|
||||
UNICODE_STRING KeyName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
ULONG LinkedValue;
|
||||
|
||||
if (SymbolicLinkName == NULL)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
@ -1140,6 +1363,51 @@ IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName,
|
|||
SymLink.Buffer = SymbolicLinkName->Buffer;
|
||||
SymLink.MaximumLength = SymLink.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)SymLink.Buffer);
|
||||
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 */
|
||||
Status = IoGetDeviceObjectPointer(
|
||||
&SymLink,
|
||||
|
|
Loading…
Reference in a new issue