Author: cgutman
Date: Mon Apr 26 06:54:25 2010
New Revision: 47029
URL:
http://svn.reactos.org/svn/reactos?rev=47029&view=rev
Log:
[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)
Modified:
trunk/reactos/ntoskrnl/io/iomgr/deviface.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/deviface.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/deviface…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/deviface.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/deviface.c [iso-8859-1] Mon Apr 26 06:54:25 2010
@@ -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 @@
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 @@
/* 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 @@
}
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;
}
-#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");
+
+ 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;
+ }
}
/* Read the SymbolicLink string and add it into SymbolicLinkList */
@@ -1118,7 +1338,10 @@
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 @@
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,