X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fio%2Fiomgr%2Fdeviface.c;h=8a8db7a843f498b356726d831d438b89f12af908;hp=59eddeb898cbaca0891984880288c45afb01ddc6;hb=540e5b6f31a5d212bbb9396de997d260931c88b5;hpb=770cc844b035d859ca1a6e85b3fb649c7439183a diff --git a/reactos/ntoskrnl/io/iomgr/deviface.c b/reactos/ntoskrnl/io/iomgr/deviface.c index 59eddeb898c..8a8db7a843f 100644 --- a/reactos/ntoskrnl/io/iomgr/deviface.c +++ b/reactos/ntoskrnl/io/iomgr/deviface.c @@ -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,