Author: fireball Date: Sun Jul 9 01:33:25 2006 New Revision: 22948
URL: http://svn.reactos.org/svn/reactos?rev=22948&view=rev Log: [AUDIT] + [FORMATTING] - Coding style applied (make file's header proper, add headers for every function) - All functions except one are documented in MSDN - One undocumented function will undergo further examination and documentation
Modified: trunk/reactos/ntoskrnl/io/iomgr/deviface.c (contents, props changed)
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 (original) +++ trunk/reactos/ntoskrnl/io/iomgr/deviface.c Sun Jul 9 01:33:25 2006 @@ -1,7 +1,7 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/deviface.c + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/io/iomgr/deviface.c * PURPOSE: Device interface functions * * PROGRAMMERS: Filip Navara (xnavara@volny.cz) @@ -20,868 +20,974 @@
static PWCHAR BaseKeyString = L"\Registry\Machine\System\CurrentControlSet\Control\DeviceClasses\";
-/* +/*++ + * @name IoOpenDeviceInterfaceRegistryKey * @unimplemented - */ - -NTSTATUS STDCALL -IoOpenDeviceInterfaceRegistryKey( - IN PUNICODE_STRING SymbolicLinkName, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE DeviceInterfaceKey) + * + * Provides a handle to the device's interface instance registry key. + * Documented in WDK. + * + * @param SymbolicLinkName + * Pointer to a string which identifies the device interface instance + * + * @param DesiredAccess + * Desired ACCESS_MASK used to access the key (like KEY_READ, + * KEY_WRITE, etc) + * + * @param DeviceInterfaceKey + * If a call has been succesfull, a handle to the registry key + * will be stored there + * + * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS + * otherwise (see WDK for details) + * + * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread + * + *--*/ +NTSTATUS +NTAPI +IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DeviceInterfaceKey) { - return STATUS_NOT_IMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; }
-/* +/*++ + * @name IoGetDeviceInterfaceAlias * @unimplemented - */ - -NTSTATUS STDCALL -IoGetDeviceInterfaceAlias( - IN PUNICODE_STRING SymbolicLinkName, - IN CONST GUID *AliasInterfaceClassGuid, - OUT PUNICODE_STRING AliasSymbolicLinkName) + * + * Returns the alias device interface of the specified device interface + * instance, if the alias exists. + * Documented in WDK. + * + * @param SymbolicLinkName + * Pointer to a string which identifies the device interface instance + * + * @param AliasInterfaceClassGuid + * See WDK + * + * @param AliasSymbolicLinkName + * See WDK + * + * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS + * otherwise (see WDK for details) + * + * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread + * + *--*/ +NTSTATUS +NTAPI +IoGetDeviceInterfaceAlias(IN PUNICODE_STRING SymbolicLinkName, + IN CONST GUID *AliasInterfaceClassGuid, + OUT PUNICODE_STRING AliasSymbolicLinkName) { - return STATUS_NOT_IMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; }
+/*++ + * @name IopOpenInterfaceKey + * + * Returns the alias device interface of the specified device interface + * + * @param InterfaceClassGuid + * FILLME + * + * @param DesiredAccess + * FILLME + * + * @param pInterfaceKey + * FILLME + * + * @return Usual NTSTATUS + * + * @remarks None + * + *--*/ static NTSTATUS -IopOpenInterfaceKey( - IN CONST GUID *InterfaceClassGuid, - IN ACCESS_MASK DesiredAccess, - OUT HANDLE *pInterfaceKey) +IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, + IN ACCESS_MASK DesiredAccess, + OUT HANDLE *pInterfaceKey) { - UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\Registry\Machine\"); - UNICODE_STRING GuidString; - UNICODE_STRING KeyName; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE InterfaceKey = INVALID_HANDLE_VALUE; - NTSTATUS Status; - - GuidString.Buffer = KeyName.Buffer = NULL; - - Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - KeyName.Length = 0; - KeyName.MaximumLength = LocalMachine.Length + (wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length; - KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength); - if (!KeyName.Buffer) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - - Status = RtlAppendUnicodeStringToString(&KeyName, &LocalMachine); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); - goto cleanup; - } - Status = RtlAppendUnicodeToString(&KeyName, REGSTR_PATH_DEVICE_CLASSES); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); - goto cleanup; - } - Status = RtlAppendUnicodeToString(&KeyName, L"\"); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); - goto cleanup; - } - Status = RtlAppendUnicodeStringToString(&KeyName, &GuidString); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - InitializeObjectAttributes( - &ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = ZwOpenKey( - &InterfaceKey, - DesiredAccess, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - *pInterfaceKey = InterfaceKey; - Status = STATUS_SUCCESS; + UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\Registry\Machine\"); + UNICODE_STRING GuidString; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE InterfaceKey = INVALID_HANDLE_VALUE; + NTSTATUS Status; + + GuidString.Buffer = KeyName.Buffer = NULL; + + Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + KeyName.Length = 0; + KeyName.MaximumLength = LocalMachine.Length + (wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length; + KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength); + if (!KeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = RtlAppendUnicodeStringToString(&KeyName, &LocalMachine); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeToString(&KeyName, REGSTR_PATH_DEVICE_CLASSES); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeToString(&KeyName, L"\"); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeStringToString(&KeyName, &GuidString); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey( + &InterfaceKey, + DesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + *pInterfaceKey = InterfaceKey; + Status = STATUS_SUCCESS;
cleanup: - if (!NT_SUCCESS(Status)) - { - if (InterfaceKey != INVALID_HANDLE_VALUE) - ZwClose(InterfaceKey); - } - RtlFreeUnicodeString(&GuidString); - RtlFreeUnicodeString(&KeyName); - return Status; + if (!NT_SUCCESS(Status)) + { + if (InterfaceKey != INVALID_HANDLE_VALUE) + ZwClose(InterfaceKey); + } + RtlFreeUnicodeString(&GuidString); + RtlFreeUnicodeString(&KeyName); + return Status; }
-/* - * IoGetDeviceInterfaces +/*++ + * @name IoGetDeviceInterfaces + * @implemented * * Returns a list of device interfaces of a particular device interface class. - * - * Parameters - * InterfaceClassGuid - * Points to a class GUID specifying the device interface class. - * - * PhysicalDeviceObject - * Points to an optional PDO that narrows the search to only the - * device interfaces of the device represented by the PDO. - * - * Flags - * Specifies flags that modify the search for device interfaces. The - * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of - * returned symbolic links should contain also disabled device - * interfaces in addition to the enabled ones. - * - * SymbolicLinkList - * Points to a character pointer that is filled in on successful return - * with a list of unicode strings identifying the device interfaces - * that match the search criteria. The newly allocated buffer contains - * a list of symbolic link names. Each unicode string in the list is - * null-terminated; the end of the whole list is marked by an additional - * NULL. The caller is responsible for freeing the buffer (ExFreePool) - * when it is no longer needed. - * If no device interfaces match the search criteria, this routine - * returns STATUS_SUCCESS and the string contains a single NULL - * character. - * - * Status - * @implemented - * - */ - -NTSTATUS STDCALL -IoGetDeviceInterfaces( - IN CONST GUID *InterfaceClassGuid, - IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, - IN ULONG Flags, - OUT PWSTR *SymbolicLinkList) + * Documented in WDK + * + * @param InterfaceClassGuid + * Points to a class GUID specifying the device interface class + * + * @param PhysicalDeviceObject + * Points to an optional PDO that narrows the search to only the + * device interfaces of the device represented by the PDO + * + * @param Flags + * Specifies flags that modify the search for device interfaces. The + * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of + * returned symbolic links should contain also disabled device + * interfaces in addition to the enabled ones. + * + * @param SymbolicLinkList + * Points to a character pointer that is filled in on successful return + * with a list of unicode strings identifying the device interfaces + * that match the search criteria. The newly allocated buffer contains + * a list of symbolic link names. Each unicode string in the list is + * null-terminated; the end of the whole list is marked by an additional + * NULL. The caller is responsible for freeing the buffer (ExFreePool) + * when it is no longer needed. + * If no device interfaces match the search criteria, this routine + * returns STATUS_SUCCESS and the string contains a single NULL + * character. + * + * @return Usual NTSTATUS + * + * @remarks None + * + *--*/ +NTSTATUS +NTAPI +IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + IN ULONG Flags, + OUT PWSTR *SymbolicLinkList) { - UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); - UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); - HANDLE InterfaceKey = INVALID_HANDLE_VALUE; - HANDLE DeviceKey = INVALID_HANDLE_VALUE; - HANDLE ReferenceKey = INVALID_HANDLE_VALUE; - HANDLE ControlKey = INVALID_HANDLE_VALUE; - PKEY_BASIC_INFORMATION DeviceBi = NULL; - PKEY_BASIC_INFORMATION ReferenceBi = NULL; - PKEY_VALUE_PARTIAL_INFORMATION bip = NULL; - UNICODE_STRING KeyName; - OBJECT_ATTRIBUTES ObjectAttributes; - BOOLEAN FoundRightPDO = FALSE; - ULONG i = 0, j, Size; - UNICODE_STRING ReturnBuffer = {0,}; - NTSTATUS Status; - - PAGED_CODE(); - - Status = IopOpenInterfaceKey(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, &InterfaceKey); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - /* Enumerate subkeys (ie the different device objets) */ - while (TRUE) - { - Status = ZwEnumerateKey( - InterfaceKey, - i, - KeyBasicInformation, - NULL, - 0, - &Size); - if (Status == STATUS_NO_MORE_ENTRIES) - break; - else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - DeviceBi = ExAllocatePool(PagedPool, Size); - if (!DeviceBi) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - Status = ZwEnumerateKey( - InterfaceKey, - i++, - KeyBasicInformation, - DeviceBi, - Size, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - /* Open device key */ - KeyName.Length = KeyName.MaximumLength = DeviceBi->NameLength; - KeyName.Buffer = DeviceBi->Name; - InitializeObjectAttributes( - &ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - InterfaceKey, - NULL); - Status = ZwOpenKey( - &DeviceKey, - KEY_ENUMERATE_SUB_KEYS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - if (PhysicalDeviceObject) - { - /* Check if we are on the right physical device object, - * by reading the DeviceInstance string - */ - DPRINT1("PhysicalDeviceObject != NULL. Case not implemented.\n"); - //FoundRightPDO = TRUE; - Status = STATUS_NOT_IMPLEMENTED; - goto cleanup; - } - - /* Enumerate subkeys (ie the different reference strings) */ - j = 0; - while (TRUE) - { - Status = ZwEnumerateKey( - DeviceKey, - j, + UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); + UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); + HANDLE InterfaceKey = INVALID_HANDLE_VALUE; + HANDLE DeviceKey = INVALID_HANDLE_VALUE; + HANDLE ReferenceKey = INVALID_HANDLE_VALUE; + HANDLE ControlKey = INVALID_HANDLE_VALUE; + PKEY_BASIC_INFORMATION DeviceBi = NULL; + PKEY_BASIC_INFORMATION ReferenceBi = NULL; + PKEY_VALUE_PARTIAL_INFORMATION bip = NULL; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + BOOLEAN FoundRightPDO = FALSE; + ULONG i = 0, j, Size; + UNICODE_STRING ReturnBuffer = {0,}; + NTSTATUS Status; + + PAGED_CODE(); + + Status = IopOpenInterfaceKey(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, &InterfaceKey); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* Enumerate subkeys (ie the different device objets) */ + while (TRUE) + { + Status = ZwEnumerateKey( + InterfaceKey, + i, KeyBasicInformation, NULL, 0, &Size); - if (Status == STATUS_NO_MORE_ENTRIES) + if (Status == STATUS_NO_MORE_ENTRIES) + { break; - else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { + } + else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; - } - - ReferenceBi = ExAllocatePool(PagedPool, Size); - if (!ReferenceBi) - { + } + + DeviceBi = ExAllocatePool(PagedPool, Size); + if (!DeviceBi) + { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; - } - Status = ZwEnumerateKey( - DeviceKey, - j++, + } + Status = ZwEnumerateKey( + InterfaceKey, + i++, KeyBasicInformation, - ReferenceBi, + DeviceBi, Size, &Size); - if (!NT_SUCCESS(Status)) - { + if (!NT_SUCCESS(Status)) + { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; - } - - KeyName.Length = KeyName.MaximumLength = ReferenceBi->NameLength; - KeyName.Buffer = ReferenceBi->Name; - if (RtlEqualUnicodeString(&KeyName, &Control, TRUE)) - { - /* Skip Control subkey */ - goto NextReferenceString; - } - - /* Open reference key */ - InitializeObjectAttributes( + } + + /* Open device key */ + KeyName.Length = KeyName.MaximumLength = DeviceBi->NameLength; + KeyName.Buffer = DeviceBi->Name; + InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, - DeviceKey, + InterfaceKey, NULL); - Status = ZwOpenKey( - &ReferenceKey, - KEY_QUERY_VALUE, + Status = ZwOpenKey( + &DeviceKey, + KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { + if (!NT_SUCCESS(Status)) + { DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); goto cleanup; - } - - if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) - { - /* We have to check if the interface is enabled, by - * reading the Linked value in the Control subkey - */ + } + + if (PhysicalDeviceObject) + { + /* Check if we are on the right physical device object, + * by reading the DeviceInstance string + */ + DPRINT1("PhysicalDeviceObject != NULL. Case not implemented.\n"); + //FoundRightPDO = TRUE; + Status = STATUS_NOT_IMPLEMENTED; + goto cleanup; + } + + /* Enumerate subkeys (ie the different reference strings) */ + j = 0; + while (TRUE) + { + Status = ZwEnumerateKey( + DeviceKey, + j, + KeyBasicInformation, + NULL, + 0, + &Size); + if (Status == STATUS_NO_MORE_ENTRIES) + { + break; + } + else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + ReferenceBi = ExAllocatePool(PagedPool, Size); + if (!ReferenceBi) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + Status = ZwEnumerateKey( + DeviceKey, + j++, + KeyBasicInformation, + ReferenceBi, + Size, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + KeyName.Length = KeyName.MaximumLength = ReferenceBi->NameLength; + KeyName.Buffer = ReferenceBi->Name; + if (RtlEqualUnicodeString(&KeyName, &Control, TRUE)) + { + /* Skip Control subkey */ + goto NextReferenceString; + } + + /* Open reference key */ InitializeObjectAttributes( - &ObjectAttributes, - &Control, - OBJ_CASE_INSENSITIVE, - ReferenceKey, - NULL); + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + DeviceKey, + NULL); Status = ZwOpenKey( - &ControlKey, - KEY_QUERY_VALUE, - &ObjectAttributes); - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - /* That's OK. The key doesn't exist (yet) because - * the interface is not activated. - */ - goto NextReferenceString; - } - else if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - /* 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 */ - Status = ZwQueryValueKey( - ReferenceKey, - &SymbolicLink, - KeyValuePartialInformation, - NULL, - 0, - &Size); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - bip = ExAllocatePool(PagedPool, Size); - if (!bip) - { + &ReferenceKey, + KEY_QUERY_VALUE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) + { + /* We have to check if the interface is enabled, by + * reading the Linked value in the Control subkey + */ + InitializeObjectAttributes( + &ObjectAttributes, + &Control, + OBJ_CASE_INSENSITIVE, + ReferenceKey, + NULL); + Status = ZwOpenKey( + &ControlKey, + KEY_QUERY_VALUE, + &ObjectAttributes); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* That's OK. The key doesn't exist (yet) because + * the interface is not activated. + */ + goto NextReferenceString; + } + else if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + /* 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 */ + Status = ZwQueryValueKey( + ReferenceKey, + &SymbolicLink, + KeyValuePartialInformation, + NULL, + 0, + &Size); + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + bip = ExAllocatePool(PagedPool, Size); + if (!bip) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + Status = ZwQueryValueKey( + ReferenceKey, + &SymbolicLink, + KeyValuePartialInformation, + bip, + Size, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + else if (bip->Type != REG_SZ) + { + DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ); + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + else if (bip->DataLength < 5 * sizeof(WCHAR)) + { + DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength < 5 * sizeof(WCHAR)); + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + KeyName.Length = KeyName.MaximumLength = bip->DataLength - 4 * sizeof(WCHAR); + KeyName.Buffer = &((PWSTR)bip->Data)[4]; + if (KeyName.Length && KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] == UNICODE_NULL) + { + /* Remove trailing NULL */ + KeyName.Length -= sizeof(WCHAR); + } + + /* Add new symbolic link to symbolic link list */ + if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength) + { + PWSTR NewBuffer; + ReturnBuffer.MaximumLength = max(ReturnBuffer.MaximumLength * 2, ReturnBuffer.Length + KeyName.Length + 2 * sizeof(WCHAR)); + NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); + if (!NewBuffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); + ExFreePool(ReturnBuffer.Buffer); + ReturnBuffer.Buffer = NewBuffer; + } + DPRINT("Adding symbolic link %wZ\n", &KeyName); + Status = RtlAppendUnicodeStringToString(&ReturnBuffer, &KeyName); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + /* RtlAppendUnicodeStringToString added a NULL at the end of the + * destination string, but didn't increase the Length field. + * Do it for it. + */ + ReturnBuffer.Length += sizeof(WCHAR); + +NextReferenceString: + ExFreePool(ReferenceBi); + ReferenceBi = NULL; + ExFreePool(bip); + bip = NULL; + if (ReferenceKey != INVALID_HANDLE_VALUE) + { + ZwClose(ReferenceKey); + ReferenceKey = INVALID_HANDLE_VALUE; + } + if (ControlKey != INVALID_HANDLE_VALUE) + { + ZwClose(ControlKey); + ControlKey = INVALID_HANDLE_VALUE; + } + } + if (FoundRightPDO) + { + /* No need to go further, as we already have found what we searched */ + break; + } + + ExFreePool(DeviceBi); + DeviceBi = NULL; + ZwClose(DeviceKey); + DeviceKey = INVALID_HANDLE_VALUE; + } + + /* Add final NULL to ReturnBuffer */ + if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength) + { + PWSTR NewBuffer; + ReturnBuffer.MaximumLength += sizeof(WCHAR); + NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); + if (!NewBuffer) + { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; - } - Status = ZwQueryValueKey( - ReferenceKey, - &SymbolicLink, - KeyValuePartialInformation, - bip, - Size, - &Size); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - else if (bip->Type != REG_SZ) - { - DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - else if (bip->DataLength < 5 * sizeof(WCHAR)) - { - DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength < 5 * sizeof(WCHAR)); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - KeyName.Length = KeyName.MaximumLength = bip->DataLength - 4 * sizeof(WCHAR); - KeyName.Buffer = &((PWSTR)bip->Data)[4]; - if (KeyName.Length && KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] == UNICODE_NULL) - /* Remove trailing NULL */ - KeyName.Length -= sizeof(WCHAR); - - /* Add new symbolic link to symbolic link list */ - if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength) - { - PWSTR NewBuffer; - ReturnBuffer.MaximumLength = max(ReturnBuffer.MaximumLength * 2, ReturnBuffer.Length + KeyName.Length + 2 * sizeof(WCHAR)); - NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); - if (!NewBuffer) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); - ExFreePool(ReturnBuffer.Buffer); - ReturnBuffer.Buffer = NewBuffer; - } - DPRINT("Adding symbolic link %wZ\n", &KeyName); - Status = RtlAppendUnicodeStringToString(&ReturnBuffer, &KeyName); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); - goto cleanup; - } - /* RtlAppendUnicodeStringToString added a NULL at the end of the - * destination string, but didn't increase the Length field. - * Do it for it. - */ - ReturnBuffer.Length += sizeof(WCHAR); - -NextReferenceString: - ExFreePool(ReferenceBi); - ReferenceBi = NULL; - ExFreePool(bip); - bip = NULL; - if (ReferenceKey != INVALID_HANDLE_VALUE) - { - ZwClose(ReferenceKey); - ReferenceKey = INVALID_HANDLE_VALUE; - } - if (ControlKey != INVALID_HANDLE_VALUE) - { - ZwClose(ControlKey); - ControlKey = INVALID_HANDLE_VALUE; - } - } - if (FoundRightPDO) - { - /* No need to go further, as we already have found what we searched */ - break; - } - - ExFreePool(DeviceBi); - DeviceBi = NULL; - ZwClose(DeviceKey); - DeviceKey = INVALID_HANDLE_VALUE; - } - - /* Add final NULL to ReturnBuffer */ - if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength) - { - PWSTR NewBuffer; - ReturnBuffer.MaximumLength += sizeof(WCHAR); - NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); - if (!NewBuffer) - { - DPRINT("ExAllocatePool() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); - ExFreePool(ReturnBuffer.Buffer); - ReturnBuffer.Buffer = NewBuffer; - } - ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL; - *SymbolicLinkList = ReturnBuffer.Buffer; - Status = STATUS_SUCCESS; + } + RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); + ExFreePool(ReturnBuffer.Buffer); + ReturnBuffer.Buffer = NewBuffer; + } + ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL; + *SymbolicLinkList = ReturnBuffer.Buffer; + Status = STATUS_SUCCESS;
cleanup: - if (!NT_SUCCESS(Status)) - ExFreePool(ReturnBuffer.Buffer); - if (InterfaceKey != INVALID_HANDLE_VALUE) - ZwClose(InterfaceKey); - if (DeviceKey != INVALID_HANDLE_VALUE) - ZwClose(DeviceKey); - if (ReferenceKey != INVALID_HANDLE_VALUE) - ZwClose(ReferenceKey); - if (ControlKey != INVALID_HANDLE_VALUE) - ZwClose(ControlKey); - ExFreePool(DeviceBi); - ExFreePool(ReferenceBi); - ExFreePool(bip); - return Status; + if (!NT_SUCCESS(Status)) + ExFreePool(ReturnBuffer.Buffer); + if (InterfaceKey != INVALID_HANDLE_VALUE) + ZwClose(InterfaceKey); + if (DeviceKey != INVALID_HANDLE_VALUE) + ZwClose(DeviceKey); + if (ReferenceKey != INVALID_HANDLE_VALUE) + ZwClose(ReferenceKey); + if (ControlKey != INVALID_HANDLE_VALUE) + ZwClose(ControlKey); + ExFreePool(DeviceBi); + ExFreePool(ReferenceBi); + ExFreePool(bip); + return Status; }
-/* +/*++ + * @name IoRegisterDeviceInterface * @implemented - */ - -NTSTATUS STDCALL -IoRegisterDeviceInterface( - IN PDEVICE_OBJECT PhysicalDeviceObject, - IN CONST GUID *InterfaceClassGuid, - IN PUNICODE_STRING ReferenceString OPTIONAL, - OUT PUNICODE_STRING SymbolicLinkName) + * + * Registers a device interface class, if it has not been previously registered, + * and creates a new instance of the interface class, which a driver can + * subsequently enable for use by applications or other system components. + * Documented in WDK. + * + * @param PhysicalDeviceObject + * Points to an optional PDO that narrows the search to only the + * device interfaces of the device represented by the PDO + * + * @param InterfaceClassGuid + * Points to a class GUID specifying the device interface class + * + * @param ReferenceString + * Optional parameter, pointing to a unicode string. For a full + * description of this rather rarely used param (usually drivers + * pass NULL here) see WDK + * + * @param SymbolicLinkName + * Pointer to the resulting unicode string + * + * @return Usual NTSTATUS + * + * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a + * system thread + * + *--*/ +NTSTATUS +NTAPI +IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, + IN CONST GUID *InterfaceClassGuid, + IN PUNICODE_STRING ReferenceString OPTIONAL, + OUT PUNICODE_STRING SymbolicLinkName) { - PUNICODE_STRING InstancePath; - UNICODE_STRING GuidString; - UNICODE_STRING SubKeyName; - UNICODE_STRING InterfaceKeyName; - UNICODE_STRING BaseKeyName; - UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))]; - POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer; - UNICODE_STRING DeviceInstance = RTL_CONSTANT_STRING(L"DeviceInstance"); - UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); - HANDLE ClassKey; - HANDLE InterfaceKey; - HANDLE SubKey; - ULONG StartIndex; - OBJECT_ATTRIBUTES ObjectAttributes; - ULONG i; - NTSTATUS Status; - - ASSERT_IRQL(PASSIVE_LEVEL); - - if (!(PhysicalDeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE)) - { - DPRINT("PhysicalDeviceObject 0x%p is not a valid Pdo\n", PhysicalDeviceObject); - return STATUS_INVALID_PARAMETER_1; - } - - Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); - return Status; - } - - /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */ - Status = ObQueryNameString( - PhysicalDeviceObject, - PdoNameInfo, - sizeof(PdoNameInfoBuffer), - &i); - if (!NT_SUCCESS(Status)) - { - DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status); - return Status; - } - ASSERT(PdoNameInfo->Name.Length); - - /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses{GUID} */ - ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode); - InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath; - BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); - BaseKeyName.MaximumLength = BaseKeyName.Length - + GuidString.Length; - BaseKeyName.Buffer = ExAllocatePool( - PagedPool, - BaseKeyName.MaximumLength); - if (!BaseKeyName.Buffer) - { - DPRINT("ExAllocatePool() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - wcscpy(BaseKeyName.Buffer, BaseKeyString); - RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); - - /* Create BaseKeyName key in registry */ - InitializeObjectAttributes( - &ObjectAttributes, - &BaseKeyName, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, - NULL, /* RootDirectory */ - NULL); /* SecurityDescriptor */ - - Status = ZwCreateKey( - &ClassKey, - KEY_WRITE, - &ObjectAttributes, - 0, /* TileIndex */ - NULL, /* Class */ - REG_OPTION_VOLATILE, - NULL); /* Disposition */ - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - ExFreePool(BaseKeyName.Buffer); - return Status; - } - - /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */ - InterfaceKeyName.Length = 0; - InterfaceKeyName.MaximumLength = - 4 * sizeof(WCHAR) + /* 4 = size of ##?# */ - InstancePath->Length + - sizeof(WCHAR) + /* 1 = size of # */ - GuidString.Length; - InterfaceKeyName.Buffer = ExAllocatePool( - PagedPool, - InterfaceKeyName.MaximumLength); - if (!InterfaceKeyName.Buffer) - { - DPRINT("ExAllocatePool() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#"); - StartIndex = InterfaceKeyName.Length / sizeof(WCHAR); - RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath); - for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) - { - if (InterfaceKeyName.Buffer[StartIndex + i] == '\') - InterfaceKeyName.Buffer[StartIndex + i] = '#'; - } - RtlAppendUnicodeToString(&InterfaceKeyName, L"#"); - RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString); - - /* Create the interface key in registry */ - InitializeObjectAttributes( - &ObjectAttributes, - &InterfaceKeyName, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, - ClassKey, - NULL); /* SecurityDescriptor */ - - Status = ZwCreateKey( - &InterfaceKey, - KEY_WRITE, - &ObjectAttributes, - 0, /* TileIndex */ - NULL, /* Class */ - REG_OPTION_VOLATILE, - NULL); /* Disposition */ - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - ZwClose(ClassKey); - ExFreePool(BaseKeyName.Buffer); - return Status; - } - - /* Write DeviceInstance entry. Value is InstancePath */ - Status = ZwSetValueKey( - InterfaceKey, - &DeviceInstance, - 0, /* TileIndex */ - REG_SZ, - InstancePath->Buffer, - InstancePath->Length); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - return Status; - } - - /* Create subkey. Name is #ReferenceString */ - SubKeyName.Length = 0; - SubKeyName.MaximumLength = sizeof(WCHAR); - if (ReferenceString && ReferenceString->Length) - SubKeyName.MaximumLength += ReferenceString->Length; - SubKeyName.Buffer = ExAllocatePool( - PagedPool, - SubKeyName.MaximumLength); - if (!SubKeyName.Buffer) - { - DPRINT("ExAllocatePool() failed\n"); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlAppendUnicodeToString(&SubKeyName, L"#"); - if (ReferenceString && ReferenceString->Length) - RtlAppendUnicodeStringToString(&SubKeyName, ReferenceString); - - /* Create SubKeyName key in registry */ - InitializeObjectAttributes( - &ObjectAttributes, - &SubKeyName, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - InterfaceKey, /* RootDirectory */ - NULL); /* SecurityDescriptor */ - - Status = ZwCreateKey( - &SubKey, - KEY_WRITE, - &ObjectAttributes, - 0, /* TileIndex */ - NULL, /* Class */ - REG_OPTION_VOLATILE, - NULL); /* Disposition */ - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - return Status; - } - - /* Create symbolic link name: ??\ACPI#PNP0501#1#{GUID}\ReferenceString */ - SymbolicLinkName->Length = 0; - SymbolicLinkName->MaximumLength = SymbolicLinkName->Length - + 4 * sizeof(WCHAR) /* 4 = size of ??\ */ - + InstancePath->Length - + sizeof(WCHAR) /* 1 = size of # */ - + GuidString.Length - + sizeof(WCHAR); /* final NULL */ - if (ReferenceString && ReferenceString->Length) - SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length; - SymbolicLinkName->Buffer = ExAllocatePool( - PagedPool, - SymbolicLinkName->MaximumLength); - if (!SymbolicLinkName->Buffer) - { - DPRINT("ExAllocatePool() failed\n"); - ZwClose(SubKey); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(SubKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlAppendUnicodeToString(SymbolicLinkName, L"\??\"); - StartIndex = SymbolicLinkName->Length / sizeof(WCHAR); - RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath); - for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) - { - if (SymbolicLinkName->Buffer[StartIndex + i] == '\') - SymbolicLinkName->Buffer[StartIndex + i] = '#'; - } - RtlAppendUnicodeToString(SymbolicLinkName, L"#"); - RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString); - if (ReferenceString && ReferenceString->Length) - { - RtlAppendUnicodeToString(SymbolicLinkName, L"\"); - RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); - } - SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; - - /* Create symbolic link */ - DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name); - Status = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoCreateSymbolicLink() failed with status 0x%08lx\n", Status); - ZwClose(SubKey); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(SubKeyName.Buffer); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - ExFreePool(SymbolicLinkName->Buffer); - return Status; - } - - /* Write symbolic link name in registry */ - SymbolicLinkName->Buffer[1] = '\'; - Status = ZwSetValueKey( - SubKey, - &SymbolicLink, - 0, /* TileIndex */ - REG_SZ, - SymbolicLinkName->Buffer, - SymbolicLinkName->Length); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ExFreePool(SymbolicLinkName->Buffer); - } - - /* Remove \?\ at the start of symbolic link name */ - SymbolicLinkName->Length -= 4 * sizeof(WCHAR); - SymbolicLinkName->MaximumLength -= 4 * sizeof(WCHAR); - RtlMoveMemory( - SymbolicLinkName->Buffer, - &SymbolicLinkName->Buffer[4], - SymbolicLinkName->Length); - - ZwClose(SubKey); - ZwClose(InterfaceKey); - ZwClose(ClassKey); - ExFreePool(SubKeyName.Buffer); - ExFreePool(InterfaceKeyName.Buffer); - ExFreePool(BaseKeyName.Buffer); - - return Status; + PUNICODE_STRING InstancePath; + UNICODE_STRING GuidString; + UNICODE_STRING SubKeyName; + UNICODE_STRING InterfaceKeyName; + UNICODE_STRING BaseKeyName; + UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))]; + POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer; + UNICODE_STRING DeviceInstance = RTL_CONSTANT_STRING(L"DeviceInstance"); + UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); + HANDLE ClassKey; + HANDLE InterfaceKey; + HANDLE SubKey; + ULONG StartIndex; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG i; + NTSTATUS Status; + + ASSERT_IRQL(PASSIVE_LEVEL); + + if (!(PhysicalDeviceObject->Flags & DO_BUS_ENUMERATED_DEVICE)) + { + DPRINT("PhysicalDeviceObject 0x%p is not a valid Pdo\n", PhysicalDeviceObject); + return STATUS_INVALID_PARAMETER_1; + } + + Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); + return Status; + } + + /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */ + Status = ObQueryNameString( + PhysicalDeviceObject, + PdoNameInfo, + sizeof(PdoNameInfoBuffer), + &i); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status); + return Status; + } + ASSERT(PdoNameInfo->Name.Length); + + /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses{GUID} */ + ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode); + InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath; + BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); + BaseKeyName.MaximumLength = BaseKeyName.Length + + GuidString.Length; + BaseKeyName.Buffer = ExAllocatePool( + PagedPool, + BaseKeyName.MaximumLength); + if (!BaseKeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy(BaseKeyName.Buffer, BaseKeyString); + RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); + + /* Create BaseKeyName key in registry */ + InitializeObjectAttributes( + &ObjectAttributes, + &BaseKeyName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, + NULL, /* RootDirectory */ + NULL); /* SecurityDescriptor */ + + Status = ZwCreateKey( + &ClassKey, + KEY_WRITE, + &ObjectAttributes, + 0, /* TileIndex */ + NULL, /* Class */ + REG_OPTION_VOLATILE, + NULL); /* Disposition */ + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */ + InterfaceKeyName.Length = 0; + InterfaceKeyName.MaximumLength = + 4 * sizeof(WCHAR) + /* 4 = size of ##?# */ + InstancePath->Length + + sizeof(WCHAR) + /* 1 = size of # */ + GuidString.Length; + InterfaceKeyName.Buffer = ExAllocatePool( + PagedPool, + InterfaceKeyName.MaximumLength); + if (!InterfaceKeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#"); + StartIndex = InterfaceKeyName.Length / sizeof(WCHAR); + RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath); + for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) + { + if (InterfaceKeyName.Buffer[StartIndex + i] == '\') + InterfaceKeyName.Buffer[StartIndex + i] = '#'; + } + RtlAppendUnicodeToString(&InterfaceKeyName, L"#"); + RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString); + + /* Create the interface key in registry */ + InitializeObjectAttributes( + &ObjectAttributes, + &InterfaceKeyName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, + ClassKey, + NULL); /* SecurityDescriptor */ + + Status = ZwCreateKey( + &InterfaceKey, + KEY_WRITE, + &ObjectAttributes, + 0, /* TileIndex */ + NULL, /* Class */ + REG_OPTION_VOLATILE, + NULL); /* Disposition */ + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ZwClose(ClassKey); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Write DeviceInstance entry. Value is InstancePath */ + Status = ZwSetValueKey( + InterfaceKey, + &DeviceInstance, + 0, /* TileIndex */ + REG_SZ, + InstancePath->Buffer, + InstancePath->Length); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Create subkey. Name is #ReferenceString */ + SubKeyName.Length = 0; + SubKeyName.MaximumLength = sizeof(WCHAR); + if (ReferenceString && ReferenceString->Length) + SubKeyName.MaximumLength += ReferenceString->Length; + SubKeyName.Buffer = ExAllocatePool( + PagedPool, + SubKeyName.MaximumLength); + if (!SubKeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlAppendUnicodeToString(&SubKeyName, L"#"); + if (ReferenceString && ReferenceString->Length) + RtlAppendUnicodeStringToString(&SubKeyName, ReferenceString); + + /* Create SubKeyName key in registry */ + InitializeObjectAttributes( + &ObjectAttributes, + &SubKeyName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + InterfaceKey, /* RootDirectory */ + NULL); /* SecurityDescriptor */ + + Status = ZwCreateKey( + &SubKey, + KEY_WRITE, + &ObjectAttributes, + 0, /* TileIndex */ + NULL, /* Class */ + REG_OPTION_VOLATILE, + NULL); /* Disposition */ + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Create symbolic link name: ??\ACPI#PNP0501#1#{GUID}\ReferenceString */ + SymbolicLinkName->Length = 0; + SymbolicLinkName->MaximumLength = SymbolicLinkName->Length + + 4 * sizeof(WCHAR) /* 4 = size of ??\ */ + + InstancePath->Length + + sizeof(WCHAR) /* 1 = size of # */ + + GuidString.Length + + sizeof(WCHAR); /* final NULL */ + if (ReferenceString && ReferenceString->Length) + SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length; + SymbolicLinkName->Buffer = ExAllocatePool( + PagedPool, + SymbolicLinkName->MaximumLength); + if (!SymbolicLinkName->Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + ZwClose(SubKey); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(SubKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlAppendUnicodeToString(SymbolicLinkName, L"\??\"); + StartIndex = SymbolicLinkName->Length / sizeof(WCHAR); + RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath); + for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) + { + if (SymbolicLinkName->Buffer[StartIndex + i] == '\') + SymbolicLinkName->Buffer[StartIndex + i] = '#'; + } + RtlAppendUnicodeToString(SymbolicLinkName, L"#"); + RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString); + if (ReferenceString && ReferenceString->Length) + { + RtlAppendUnicodeToString(SymbolicLinkName, L"\"); + RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); + } + SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; + + /* Create symbolic link */ + DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name); + Status = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateSymbolicLink() failed with status 0x%08lx\n", Status); + ZwClose(SubKey); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(SubKeyName.Buffer); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + ExFreePool(SymbolicLinkName->Buffer); + return Status; + } + + /* Write symbolic link name in registry */ + SymbolicLinkName->Buffer[1] = '\'; + Status = ZwSetValueKey( + SubKey, + &SymbolicLink, + 0, /* TileIndex */ + REG_SZ, + SymbolicLinkName->Buffer, + SymbolicLinkName->Length); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ExFreePool(SymbolicLinkName->Buffer); + } + + /* Remove \?\ at the start of symbolic link name */ + SymbolicLinkName->Length -= 4 * sizeof(WCHAR); + SymbolicLinkName->MaximumLength -= 4 * sizeof(WCHAR); + RtlMoveMemory( + SymbolicLinkName->Buffer, + &SymbolicLinkName->Buffer[4], + SymbolicLinkName->Length); + + ZwClose(SubKey); + ZwClose(InterfaceKey); + ZwClose(ClassKey); + ExFreePool(SubKeyName.Buffer); + ExFreePool(InterfaceKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + + return Status; }
-/* +/*++ + * @name IoSetDeviceInterfaceState * @implemented - */ - -NTSTATUS STDCALL -IoSetDeviceInterfaceState( - IN PUNICODE_STRING SymbolicLinkName, - IN BOOLEAN Enable) + * + * Enables or disables an instance of a previously registered device + * interface class. + * Documented in WDK. + * + * @param SymbolicLinkName + * Pointer to the string identifying instance to enable or disable + * + * @param Enable + * TRUE = enable, FALSE = disable + * + * @return Usual NTSTATUS + * + * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a + * system thread + * + *--*/ +NTSTATUS +NTAPI +IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, + IN BOOLEAN Enable) { - PDEVICE_OBJECT PhysicalDeviceObject; - PFILE_OBJECT FileObject; - UNICODE_STRING ObjectName; - UNICODE_STRING GuidString; - PWCHAR StartPosition; - PWCHAR EndPosition; - NTSTATUS Status; - LPCGUID EventGuid; - - if (SymbolicLinkName == NULL) - return STATUS_INVALID_PARAMETER_1; - - DPRINT("IoSetDeviceInterfaceState('%wZ', %d)\n", SymbolicLinkName, Enable); - - /* Symbolic link name is ACPI#PNP0501#1#{GUID}\ReferenceString */ - /* Get GUID from SymbolicLinkName */ - StartPosition = wcschr(SymbolicLinkName->Buffer, L'{'); - EndPosition = wcschr(SymbolicLinkName->Buffer, L'}'); - if (!StartPosition ||!EndPosition || StartPosition > EndPosition) - return STATUS_INVALID_PARAMETER_1; - GuidString.Buffer = StartPosition; - GuidString.MaximumLength = GuidString.Length = (ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition; - - /* Create ??\SymbolicLinkName string */ - ObjectName.Length = 0; - ObjectName.MaximumLength = SymbolicLinkName->Length + 4 * sizeof(WCHAR); - ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength); - if (!ObjectName.Buffer) - return STATUS_INSUFFICIENT_RESOURCES; - RtlAppendUnicodeToString(&ObjectName, L"\??\"); - RtlAppendUnicodeStringToString(&ObjectName, SymbolicLinkName); - - /* Get pointer to the PDO */ - Status = IoGetDeviceObjectPointer(&ObjectName, - 0, /* DesiredAccess */ - &FileObject, - &PhysicalDeviceObject); - if (!NT_SUCCESS(Status)) - { - ExFreePool(ObjectName.Buffer); - return Status; - } - - EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL; - IopNotifyPlugPlayNotification( - PhysicalDeviceObject, - EventCategoryDeviceInterfaceChange, - EventGuid, - &GuidString, - (PVOID)SymbolicLinkName); - - ObDereferenceObject(FileObject); - ExFreePool(ObjectName.Buffer); - - return STATUS_SUCCESS; + PDEVICE_OBJECT PhysicalDeviceObject; + PFILE_OBJECT FileObject; + UNICODE_STRING ObjectName; + UNICODE_STRING GuidString; + PWCHAR StartPosition; + PWCHAR EndPosition; + NTSTATUS Status; + LPCGUID EventGuid; + + if (SymbolicLinkName == NULL) + return STATUS_INVALID_PARAMETER_1; + + DPRINT("IoSetDeviceInterfaceState('%wZ', %d)\n", SymbolicLinkName, Enable); + + /* Symbolic link name is ACPI#PNP0501#1#{GUID}\ReferenceString */ + /* Get GUID from SymbolicLinkName */ + StartPosition = wcschr(SymbolicLinkName->Buffer, L'{'); + EndPosition = wcschr(SymbolicLinkName->Buffer, L'}'); + if (!StartPosition ||!EndPosition || StartPosition > EndPosition) + return STATUS_INVALID_PARAMETER_1; + GuidString.Buffer = StartPosition; + GuidString.MaximumLength = GuidString.Length = (ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition; + + /* Create ??\SymbolicLinkName string */ + ObjectName.Length = 0; + ObjectName.MaximumLength = SymbolicLinkName->Length + 4 * sizeof(WCHAR); + ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength); + if (!ObjectName.Buffer) + return STATUS_INSUFFICIENT_RESOURCES; + RtlAppendUnicodeToString(&ObjectName, L"\??\"); + RtlAppendUnicodeStringToString(&ObjectName, SymbolicLinkName); + + /* Get pointer to the PDO */ + Status = IoGetDeviceObjectPointer(&ObjectName, + 0, /* DesiredAccess */ + &FileObject, + &PhysicalDeviceObject); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ObjectName.Buffer); + return Status; + } + + EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL; + IopNotifyPlugPlayNotification( + PhysicalDeviceObject, + EventCategoryDeviceInterfaceChange, + EventGuid, + &GuidString, + (PVOID)SymbolicLinkName); + + ObDereferenceObject(FileObject); + ExFreePool(ObjectName.Buffer); + + return STATUS_SUCCESS; }
/* EOF */
Propchange: trunk/reactos/ntoskrnl/io/iomgr/deviface.c ------------------------------------------------------------------------------ --- svn:needs-lock (original) +++ svn:needs-lock (removed) @@ -1,1 +1,0 @@ -*