ReactOS 0.4.15-dev-7842-g558ab78
deviface.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for deviface.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define GUID_STRING_CHARS   38
 
#define GUID_STRING_BYTES   (GUID_STRING_CHARS * sizeof(WCHAR))
 

Functions

 C_ASSERT (sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}")==GUID_STRING_BYTES+sizeof(UNICODE_NULL))
 
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance (PUNICODE_STRING DeviceInstance)
 
static NTSTATUS OpenRegistryHandlesFromSymbolicLink (IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, IN OPTIONAL PHANDLE GuidKey, IN OPTIONAL PHANDLE DeviceKey, IN OPTIONAL PHANDLE InstanceKey)
 
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey (IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
 
NTSTATUS NTAPI IoGetDeviceInterfaceAlias (IN PUNICODE_STRING SymbolicLinkName, IN CONST GUID *AliasInterfaceClassGuid, OUT PUNICODE_STRING AliasSymbolicLinkName)
 
static NTSTATUS IopOpenInterfaceKey (IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
 
NTSTATUS NTAPI IoGetDeviceInterfaces (IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
 
NTSTATUS NTAPI IoRegisterDeviceInterface (IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
 
NTSTATUS NTAPI IoSetDeviceInterfaceState (IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
 

Variables

static PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\"
 

Macro Definition Documentation

◆ GUID_STRING_BYTES

#define GUID_STRING_BYTES   (GUID_STRING_CHARS * sizeof(WCHAR))

Definition at line 21 of file deviface.c.

◆ GUID_STRING_CHARS

#define GUID_STRING_CHARS   38

Definition at line 20 of file deviface.c.

◆ NDEBUG

#define NDEBUG

Definition at line 16 of file deviface.c.

Function Documentation

◆ C_ASSERT()

C_ASSERT ( sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}")  = =GUID_STRING_BYTES+sizeof(UNICODE_NULL))

◆ IoGetDeviceInterfaceAlias()

NTSTATUS NTAPI IoGetDeviceInterfaceAlias ( IN PUNICODE_STRING  SymbolicLinkName,
IN CONST GUID AliasInterfaceClassGuid,
OUT PUNICODE_STRING  AliasSymbolicLinkName 
)

Definition at line 303 of file deviface.c.

306{
308}
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239

Referenced by DeviceInterfaceTest_Func().

◆ IoGetDeviceInterfaces()

NTSTATUS NTAPI IoGetDeviceInterfaces ( IN CONST GUID InterfaceClassGuid,
IN PDEVICE_OBJECT PhysicalDeviceObject  OPTIONAL,
IN ULONG  Flags,
OUT PWSTR SymbolicLinkList 
)

Definition at line 454 of file deviface.c.

458{
461 HANDLE InterfaceKey = NULL;
462 HANDLE DeviceKey = NULL;
463 HANDLE ReferenceKey = NULL;
464 HANDLE ControlKey = NULL;
465 PKEY_BASIC_INFORMATION DeviceBi = NULL;
466 PKEY_BASIC_INFORMATION ReferenceBi = NULL;
469 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
470 PUNICODE_STRING InstanceDevicePath = NULL;
473 BOOLEAN FoundRightPDO = FALSE;
474 ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
475 UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
477
478 PAGED_CODE();
479
481 {
482 /* Parameters must pass three border of checks */
483 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
484
485 /* 1st level: Presence of a Device Node */
486 if (DeviceObjectExtension->DeviceNode == NULL)
487 {
488 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
490 }
491
492 /* 2nd level: Presence of an non-zero length InstancePath */
493 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
494 {
495 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
497 }
498
499 InstanceDevicePath = &DeviceObjectExtension->DeviceNode->InstancePath;
500 }
501
502
504 if (!NT_SUCCESS(Status))
505 {
506 DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status);
507 goto cleanup;
508 }
509
510 /* Enumerate subkeys (i.e. the different device objects) */
511 while (TRUE)
512 {
513 Status = ZwEnumerateKey(
514 InterfaceKey,
515 i,
517 NULL,
518 0,
519 &Size);
521 {
522 break;
523 }
525 {
526 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
527 goto cleanup;
528 }
529
530 DeviceBi = ExAllocatePool(PagedPool, Size);
531 if (!DeviceBi)
532 {
533 DPRINT("ExAllocatePool() failed\n");
535 goto cleanup;
536 }
537 Status = ZwEnumerateKey(
538 InterfaceKey,
539 i++,
541 DeviceBi,
542 Size,
543 &Size);
544 if (!NT_SUCCESS(Status))
545 {
546 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
547 goto cleanup;
548 }
549
550 /* Open device key */
551 KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength;
552 KeyName.Buffer = DeviceBi->Name;
555 &KeyName,
557 InterfaceKey,
558 NULL);
559 Status = ZwOpenKey(
560 &DeviceKey,
563 if (!NT_SUCCESS(Status))
564 {
565 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
566 goto cleanup;
567 }
568
570 {
571 /* Check if we are on the right physical device object,
572 * by reading the DeviceInstance string
573 */
574 RtlInitUnicodeString(&KeyName, L"DeviceInstance");
575 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength);
577 {
578 ActualLength = NeededLength;
579 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
580 if (!PartialInfo)
581 {
583 goto cleanup;
584 }
585
586 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength);
587 if (!NT_SUCCESS(Status))
588 {
589 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
590 ExFreePool(PartialInfo);
591 goto cleanup;
592 }
593 if (PartialInfo->DataLength == InstanceDevicePath->Length)
594 {
595 if (RtlCompareMemory(PartialInfo->Data, InstanceDevicePath->Buffer, InstanceDevicePath->Length) == InstanceDevicePath->Length)
596 {
597 /* found right pdo */
598 FoundRightPDO = TRUE;
599 }
600 }
601 ExFreePool(PartialInfo);
602 PartialInfo = NULL;
603 if (!FoundRightPDO)
604 {
605 /* not yet found */
606 continue;
607 }
608 }
609 else
610 {
611 /* error */
612 break;
613 }
614 }
615
616 /* Enumerate subkeys (ie the different reference strings) */
617 j = 0;
618 while (TRUE)
619 {
620 Status = ZwEnumerateKey(
621 DeviceKey,
622 j,
624 NULL,
625 0,
626 &Size);
628 {
629 break;
630 }
632 {
633 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
634 goto cleanup;
635 }
636
637 ReferenceBi = ExAllocatePool(PagedPool, Size);
638 if (!ReferenceBi)
639 {
640 DPRINT("ExAllocatePool() failed\n");
642 goto cleanup;
643 }
644 Status = ZwEnumerateKey(
645 DeviceKey,
646 j++,
648 ReferenceBi,
649 Size,
650 &Size);
651 if (!NT_SUCCESS(Status))
652 {
653 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
654 goto cleanup;
655 }
656
657 KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength;
658 KeyName.Buffer = ReferenceBi->Name;
660 {
661 /* Skip Control subkey */
662 goto NextReferenceString;
663 }
664
665 /* Open reference key */
668 &KeyName,
670 DeviceKey,
671 NULL);
672 Status = ZwOpenKey(
673 &ReferenceKey,
676 if (!NT_SUCCESS(Status))
677 {
678 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
679 goto cleanup;
680 }
681
683 {
684 /* We have to check if the interface is enabled, by
685 * reading the Linked value in the Control subkey
686 */
689 &Control,
691 ReferenceKey,
692 NULL);
693 Status = ZwOpenKey(
694 &ControlKey,
698 {
699 /* That's OK. The key doesn't exist (yet) because
700 * the interface is not activated.
701 */
702 goto NextReferenceString;
703 }
704 else if (!NT_SUCCESS(Status))
705 {
706 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
707 goto cleanup;
708 }
709
710 RtlInitUnicodeString(&KeyName, L"Linked");
711 Status = ZwQueryValueKey(ControlKey,
712 &KeyName,
714 NULL,
715 0,
716 &NeededLength);
718 {
719 ActualLength = NeededLength;
720 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
721 if (!PartialInfo)
722 {
724 goto cleanup;
725 }
726
727 Status = ZwQueryValueKey(ControlKey,
728 &KeyName,
730 PartialInfo,
731 ActualLength,
732 &NeededLength);
733 if (!NT_SUCCESS(Status))
734 {
735 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
736 ExFreePool(PartialInfo);
737 goto cleanup;
738 }
739
740 if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
741 {
742 DPRINT1("Bad registry read\n");
743 ExFreePool(PartialInfo);
744 goto cleanup;
745 }
746
747 RtlCopyMemory(&LinkedValue,
748 PartialInfo->Data,
749 PartialInfo->DataLength);
750
751 ExFreePool(PartialInfo);
752 if (LinkedValue == 0)
753 {
754 /* This interface isn't active */
755 goto NextReferenceString;
756 }
757 }
758 else
759 {
760 DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
761 goto cleanup;
762 }
763 }
764
765 /* Read the SymbolicLink string and add it into SymbolicLinkList */
766 Status = ZwQueryValueKey(
767 ReferenceKey,
770 NULL,
771 0,
772 &Size);
774 {
775 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
776 goto cleanup;
777 }
779 if (!bip)
780 {
781 DPRINT("ExAllocatePool() failed\n");
783 goto cleanup;
784 }
785 Status = ZwQueryValueKey(
786 ReferenceKey,
789 bip,
790 Size,
791 &Size);
792 if (!NT_SUCCESS(Status))
793 {
794 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
795 goto cleanup;
796 }
797 else if (bip->Type != REG_SZ)
798 {
799 DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ);
801 goto cleanup;
802 }
803 else if (bip->DataLength < 5 * sizeof(WCHAR))
804 {
805 DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR));
807 goto cleanup;
808 }
809 KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength;
810 KeyName.Buffer = (PWSTR)bip->Data;
811
812 /* Fixup the prefix (from "\\?\") */
813 RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
814
815 /* Add new symbolic link to symbolic link list */
816 if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength)
817 {
818 PWSTR NewBuffer;
819 ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength,
820 (USHORT)(ReturnBuffer.Length +
821 KeyName.Length +
822 2 * sizeof(WCHAR)));
823 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
824 if (!NewBuffer)
825 {
826 DPRINT("ExAllocatePool() failed\n");
828 goto cleanup;
829 }
830 if (ReturnBuffer.Buffer)
831 {
832 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
833 ExFreePool(ReturnBuffer.Buffer);
834 }
835 ReturnBuffer.Buffer = NewBuffer;
836 }
837 DPRINT("Adding symbolic link %wZ\n", &KeyName);
839 if (!NT_SUCCESS(Status))
840 {
841 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
842 goto cleanup;
843 }
844 /* RtlAppendUnicodeStringToString added a NULL at the end of the
845 * destination string, but didn't increase the Length field.
846 * Do it for it.
847 */
848 ReturnBuffer.Length += sizeof(WCHAR);
849
850NextReferenceString:
851 ExFreePool(ReferenceBi);
852 ReferenceBi = NULL;
853 if (bip)
854 ExFreePool(bip);
855 bip = NULL;
856 if (ReferenceKey != NULL)
857 {
858 ZwClose(ReferenceKey);
859 ReferenceKey = NULL;
860 }
861 if (ControlKey != NULL)
862 {
863 ZwClose(ControlKey);
864 ControlKey = NULL;
865 }
866 }
867 if (FoundRightPDO)
868 {
869 /* No need to go further, as we already have found what we searched */
870 break;
871 }
872
873 ExFreePool(DeviceBi);
874 DeviceBi = NULL;
875 ZwClose(DeviceKey);
876 DeviceKey = NULL;
877 }
878
879 /* Add final NULL to ReturnBuffer */
880 ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength);
881 if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength)
882 {
883 PWSTR NewBuffer;
884 ReturnBuffer.MaximumLength += sizeof(WCHAR);
885 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
886 if (!NewBuffer)
887 {
888 DPRINT("ExAllocatePool() failed\n");
890 goto cleanup;
891 }
892 if (ReturnBuffer.Buffer)
893 {
894 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
895 ExFreePool(ReturnBuffer.Buffer);
896 }
897 ReturnBuffer.Buffer = NewBuffer;
898 }
899 ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL;
900 *SymbolicLinkList = ReturnBuffer.Buffer;
902
903cleanup:
904 if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer)
905 ExFreePool(ReturnBuffer.Buffer);
906 if (InterfaceKey != NULL)
907 ZwClose(InterfaceKey);
908 if (DeviceKey != NULL)
909 ZwClose(DeviceKey);
910 if (ReferenceKey != NULL)
911 ZwClose(ReferenceKey);
912 if (ControlKey != NULL)
913 ZwClose(ControlKey);
914 if (DeviceBi)
915 ExFreePool(DeviceBi);
916 if (ReferenceBi)
917 ExFreePool(ReferenceBi);
918 if (bip)
919 ExFreePool(bip);
920 return Status;
921}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void cleanup(void)
Definition: main.c:1335
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
@ KeyBasicInformation
Definition: nt_native.h:1131
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define UNICODE_NULL
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:330
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define REG_DWORD
Definition: sdbapi.c:596
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
struct _DEVICE_NODE * DeviceNode
Definition: iotypes.h:972
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define max(a, b)
Definition: svc.c:63
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
_In_ CONST GUID * InterfaceClassGuid
Definition: iofuncs.h:1136
#define DEVICE_INTERFACE_INCLUDE_NONACTIVE
Definition: iofuncs.h:2856
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CompBattGetBatteries(), DeviceInterfaceTest_Func(), get_device_pnp_name_guid(), IopFetchConfigurationInformation(), IopGetInterfaceDeviceList(), IoRegisterPlugPlayNotification(), KsRegisterFilterWithNoKSPins(), and WdmAudOpenSysAudioDevices().

◆ IoOpenDeviceInterfaceRegistryKey()

NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey ( IN PUNICODE_STRING  SymbolicLinkName,
IN ACCESS_MASK  DesiredAccess,
OUT PHANDLE  DeviceInterfaceKey 
)

Definition at line 241 of file deviface.c.

244{
245 HANDLE InstanceKey, DeviceParametersKey;
248 UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
249
252 NULL,
253 NULL,
254 &InstanceKey);
255 if (!NT_SUCCESS(Status))
256 return Status;
257
259 &DeviceParametersU,
261 InstanceKey,
262 NULL);
263 Status = ZwCreateKey(&DeviceParametersKey,
266 0,
267 NULL,
269 NULL);
270 ZwClose(InstanceKey);
271
272 if (NT_SUCCESS(Status))
273 *DeviceInterfaceKey = DeviceParametersKey;
274
275 return Status;
276}
#define OBJ_OPENIF
Definition: winternl.h:229
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
static NTSTATUS OpenRegistryHandlesFromSymbolicLink(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, IN OPTIONAL PHANDLE GuidKey, IN OPTIONAL PHANDLE DeviceKey, IN OPTIONAL PHANDLE InstanceKey)
Definition: deviface.c:33
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING SymbolicLinkName
Definition: wdfdevice.h:3739
_In_ ACCESS_MASK _Out_ PHANDLE DeviceInterfaceKey
Definition: iofuncs.h:1116

Referenced by Enum(), KsFilterFactoryUpdateCacheData(), KsRegisterFilterWithNoKSPins(), and PcNewRegistryKey().

◆ IopGetDeviceObjectFromDeviceInstance()

PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance ( PUNICODE_STRING  DeviceInstance)

Definition at line 206 of file plugplay.c.

207{
209 IOP_FIND_DEVICE_INSTANCE_TRAVERSE_CONTEXT DeviceInstanceContext;
210
211 if (IopRootDeviceNode == NULL)
212 return NULL;
213
214 if (DeviceInstance == NULL ||
215 DeviceInstance->Length == 0)
216 {
218 {
221 }
222 else
223 return NULL;
224 }
225
226 /* Traverse the device tree to find the matching device node */
227 DeviceInstanceContext.InstancePath = DeviceInstance;
228 DeviceInstanceContext.DeviceObject = NULL;
232 &DeviceInstanceContext);
234
235 /* In case of error or instance not found, this will still be NULL from above. */
236 return DeviceInstanceContext.DeviceObject;
237}
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#define IopInitDeviceTreeTraverseContext( _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context)
Definition: io.h:229
NTSTATUS IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
NTSTATUS IopFindDeviceInstanceTraverse(_In_ PDEVICE_NODE DeviceNode, _Inout_ PVOID Context)
Definition: plugplay.c:186
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:892
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by IoSetDeviceInterfaceState().

◆ IopOpenInterfaceKey()

static NTSTATUS IopOpenInterfaceKey ( IN CONST GUID InterfaceClassGuid,
IN ACCESS_MASK  DesiredAccess,
OUT HANDLE pInterfaceKey 
)
static

Definition at line 330 of file deviface.c.

333{
334 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\");
338 HANDLE InterfaceKey = NULL;
340
341 GuidString.Buffer = KeyName.Buffer = NULL;
342
344 if (!NT_SUCCESS(Status))
345 {
346 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
347 goto cleanup;
348 }
349
350 KeyName.Length = 0;
351 KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length;
352 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
353 if (!KeyName.Buffer)
354 {
355 DPRINT("ExAllocatePool() failed\n");
357 goto cleanup;
358 }
359
361 if (!NT_SUCCESS(Status))
362 {
363 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
364 goto cleanup;
365 }
367 if (!NT_SUCCESS(Status))
368 {
369 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
370 goto cleanup;
371 }
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
376 goto cleanup;
377 }
379 if (!NT_SUCCESS(Status))
380 {
381 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
382 goto cleanup;
383 }
384
387 &KeyName,
389 NULL,
390 NULL);
391 Status = ZwOpenKey(
392 &InterfaceKey,
395 if (!NT_SUCCESS(Status))
396 {
397 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
398 goto cleanup;
399 }
400
401 *pInterfaceKey = InterfaceKey;
403
404cleanup:
405 if (!NT_SUCCESS(Status))
406 {
407 if (InterfaceKey != NULL)
408 ZwClose(InterfaceKey);
409 }
412 return Status;
413}
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
static PWSTR GuidString
Definition: apphelp.c:93
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define REGSTR_PATH_DEVICE_CLASSES
Definition: regstr.h:481

Referenced by IoGetDeviceInterfaces().

◆ IoRegisterDeviceInterface()

NTSTATUS NTAPI IoRegisterDeviceInterface ( IN PDEVICE_OBJECT  PhysicalDeviceObject,
IN CONST GUID InterfaceClassGuid,
IN PUNICODE_STRING ReferenceString  OPTIONAL,
OUT PUNICODE_STRING  SymbolicLinkName 
)

Definition at line 955 of file deviface.c.

959{
960 PUNICODE_STRING InstancePath;
963 UNICODE_STRING InterfaceKeyName;
964 UNICODE_STRING BaseKeyName;
965 UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))];
966 POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer;
969 HANDLE ClassKey;
970 HANDLE InterfaceKey;
971 HANDLE SubKey;
972 ULONG StartIndex;
974 ULONG i;
975 NTSTATUS Status, SymLinkStatus;
976 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
977
979
980 DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n",
982
983 /* Parameters must pass three border of checks */
984 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
985
986 /* 1st level: Presence of a Device Node */
987 if (DeviceObjectExtension->DeviceNode == NULL)
988 {
989 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
991 }
992
993 /* 2nd level: Presence of an non-zero length InstancePath */
994 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
995 {
996 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
998 }
999
1000 /* 3rd level: Optional, based on WDK documentation */
1001 if (ReferenceString != NULL)
1002 {
1003 /* Reference string must not contain path-separator symbols */
1004 for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++)
1005 {
1006 if ((ReferenceString->Buffer[i] == '\\') ||
1007 (ReferenceString->Buffer[i] == '/'))
1009 }
1010 }
1011
1013 if (!NT_SUCCESS(Status))
1014 {
1015 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
1016 return Status;
1017 }
1018
1019 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
1022 PdoNameInfo,
1023 sizeof(PdoNameInfoBuffer),
1024 &i);
1025 if (!NT_SUCCESS(Status))
1026 {
1027 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status);
1028 return Status;
1029 }
1030 ASSERT(PdoNameInfo->Name.Length);
1031
1032 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1033 ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode);
1034 InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath;
1035 BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR);
1036 BaseKeyName.MaximumLength = BaseKeyName.Length
1037 + GuidString.Length;
1038 BaseKeyName.Buffer = ExAllocatePool(
1039 PagedPool,
1040 BaseKeyName.MaximumLength);
1041 if (!BaseKeyName.Buffer)
1042 {
1043 DPRINT("ExAllocatePool() failed\n");
1045 }
1046 wcscpy(BaseKeyName.Buffer, BaseKeyString);
1048
1049 /* Create BaseKeyName key in registry */
1052 &BaseKeyName,
1054 NULL, /* RootDirectory */
1055 NULL); /* SecurityDescriptor */
1056
1057 Status = ZwCreateKey(
1058 &ClassKey,
1059 KEY_WRITE,
1061 0, /* TileIndex */
1062 NULL, /* Class */
1064 NULL); /* Disposition */
1065
1066 if (!NT_SUCCESS(Status))
1067 {
1068 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1069 ExFreePool(BaseKeyName.Buffer);
1070 return Status;
1071 }
1072
1073 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
1074 InterfaceKeyName.Length = 0;
1075 InterfaceKeyName.MaximumLength =
1076 4 * sizeof(WCHAR) + /* 4 = size of ##?# */
1077 InstancePath->Length +
1078 sizeof(WCHAR) + /* 1 = size of # */
1079 GuidString.Length;
1080 InterfaceKeyName.Buffer = ExAllocatePool(
1081 PagedPool,
1082 InterfaceKeyName.MaximumLength);
1083 if (!InterfaceKeyName.Buffer)
1084 {
1085 DPRINT("ExAllocatePool() failed\n");
1087 }
1088
1089 RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#");
1090 StartIndex = InterfaceKeyName.Length / sizeof(WCHAR);
1091 RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath);
1092 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1093 {
1094 if (InterfaceKeyName.Buffer[StartIndex + i] == '\\')
1095 InterfaceKeyName.Buffer[StartIndex + i] = '#';
1096 }
1097 RtlAppendUnicodeToString(&InterfaceKeyName, L"#");
1098 RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString);
1099
1100 /* Create the interface key in registry */
1103 &InterfaceKeyName,
1105 ClassKey,
1106 NULL); /* SecurityDescriptor */
1107
1108 Status = ZwCreateKey(
1109 &InterfaceKey,
1110 KEY_WRITE,
1112 0, /* TileIndex */
1113 NULL, /* Class */
1115 NULL); /* Disposition */
1116
1117 if (!NT_SUCCESS(Status))
1118 {
1119 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1120 ZwClose(ClassKey);
1121 ExFreePool(BaseKeyName.Buffer);
1122 return Status;
1123 }
1124
1125 /* Write DeviceInstance entry. Value is InstancePath */
1126 Status = ZwSetValueKey(
1127 InterfaceKey,
1129 0, /* TileIndex */
1130 REG_SZ,
1131 InstancePath->Buffer,
1132 InstancePath->Length);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1136 ZwClose(InterfaceKey);
1137 ZwClose(ClassKey);
1138 ExFreePool(InterfaceKeyName.Buffer);
1139 ExFreePool(BaseKeyName.Buffer);
1140 return Status;
1141 }
1142
1143 /* Create subkey. Name is #ReferenceString */
1144 SubKeyName.Length = 0;
1145 SubKeyName.MaximumLength = sizeof(WCHAR);
1146 if (ReferenceString && ReferenceString->Length)
1147 SubKeyName.MaximumLength += ReferenceString->Length;
1148 SubKeyName.Buffer = ExAllocatePool(
1149 PagedPool,
1150 SubKeyName.MaximumLength);
1151 if (!SubKeyName.Buffer)
1152 {
1153 DPRINT("ExAllocatePool() failed\n");
1154 ZwClose(InterfaceKey);
1155 ZwClose(ClassKey);
1156 ExFreePool(InterfaceKeyName.Buffer);
1157 ExFreePool(BaseKeyName.Buffer);
1159 }
1161 if (ReferenceString && ReferenceString->Length)
1163
1164 /* Create SubKeyName key in registry */
1167 &SubKeyName,
1169 InterfaceKey, /* RootDirectory */
1170 NULL); /* SecurityDescriptor */
1171
1172 Status = ZwCreateKey(
1173 &SubKey,
1174 KEY_WRITE,
1176 0, /* TileIndex */
1177 NULL, /* Class */
1179 NULL); /* Disposition */
1180
1181 if (!NT_SUCCESS(Status))
1182 {
1183 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1184 ZwClose(InterfaceKey);
1185 ZwClose(ClassKey);
1186 ExFreePool(InterfaceKeyName.Buffer);
1187 ExFreePool(BaseKeyName.Buffer);
1188 return Status;
1189 }
1190
1191 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1192 SymbolicLinkName->Length = 0;
1193 SymbolicLinkName->MaximumLength = SymbolicLinkName->Length
1194 + 4 * sizeof(WCHAR) /* 4 = size of \??\ */
1195 + InstancePath->Length
1196 + sizeof(WCHAR) /* 1 = size of # */
1197 + GuidString.Length
1198 + sizeof(WCHAR); /* final NULL */
1199 if (ReferenceString && ReferenceString->Length)
1200 SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length;
1202 PagedPool,
1203 SymbolicLinkName->MaximumLength);
1204 if (!SymbolicLinkName->Buffer)
1205 {
1206 DPRINT("ExAllocatePool() failed\n");
1207 ZwClose(SubKey);
1208 ZwClose(InterfaceKey);
1209 ZwClose(ClassKey);
1210 ExFreePool(InterfaceKeyName.Buffer);
1211 ExFreePool(SubKeyName.Buffer);
1212 ExFreePool(BaseKeyName.Buffer);
1214 }
1216 StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1218 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1219 {
1220 if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1221 SymbolicLinkName->Buffer[StartIndex + i] = '#';
1222 }
1225 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1226
1227 /* Create symbolic link */
1228 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name);
1229 SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1230
1231 /* If the symbolic link already exists, return an informational success status */
1232 if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION)
1233 {
1234 /* HACK: Delete the existing symbolic link and update it to the new PDO name */
1236 IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1237 SymLinkStatus = STATUS_OBJECT_NAME_EXISTS;
1238 }
1239
1240 if (!NT_SUCCESS(SymLinkStatus))
1241 {
1242 DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus);
1243 ZwClose(SubKey);
1244 ZwClose(InterfaceKey);
1245 ZwClose(ClassKey);
1246 ExFreePool(SubKeyName.Buffer);
1247 ExFreePool(InterfaceKeyName.Buffer);
1248 ExFreePool(BaseKeyName.Buffer);
1250 return SymLinkStatus;
1251 }
1252
1253 if (ReferenceString && ReferenceString->Length)
1254 {
1257 }
1258 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1259
1260 /* Write symbolic link name in registry */
1261 SymbolicLinkName->Buffer[1] = '\\';
1262 Status = ZwSetValueKey(
1263 SubKey,
1264 &SymbolicLink,
1265 0, /* TileIndex */
1266 REG_SZ,
1267 SymbolicLinkName->Buffer,
1268 SymbolicLinkName->Length);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1273 }
1274 else
1275 {
1276 SymbolicLinkName->Buffer[1] = '?';
1277 }
1278
1279 ZwClose(SubKey);
1280 ZwClose(InterfaceKey);
1281 ZwClose(ClassKey);
1282 ExFreePool(SubKeyName.Buffer);
1283 ExFreePool(InterfaceKeyName.Buffer);
1284 ExFreePool(BaseKeyName.Buffer);
1285
1286 return NT_SUCCESS(Status) ? SymLinkStatus : Status;
1287}
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
struct _OBJECT_NAME_INFORMATION * POBJECT_NAME_INFORMATION
#define KEY_WRITE
Definition: nt_native.h:1031
static PWCHAR BaseKeyString
Definition: deviface.c:29
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
_Must_inspect_result_ _In_ WDFDEVICE _In_ CONST GUID _In_opt_ PCUNICODE_STRING ReferenceString
Definition: wdfdevice.h:3630
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by _Function_class_(), BatteryClassInitializeDevice(), Bus_PDO_PnP(), ClassAddDevice(), ClasspRegisterMountedDeviceInterface(), FdoHandleStartDevice(), FdoStartAdapter(), FreeBT_AddDevice(), HidClassPDO_PnP(), i8042PowerWorkItem(), KsCreateBusEnumObject(), KspRegisterDeviceAssociation(), KspRegisterDeviceInterfaces(), Mx::MxRegisterDeviceInterface(), NdisIAddDevice(), PartitionHandleStartDevice(), PcRegisterSubdevice(), RamdiskAddDevice(), RamdiskPnp(), RegisterDeviceInterfaces(), ScsiFlopInitDevice(), SerenumAddDevice(), SerialAddDeviceInternal(), SysAudioRegisterDeviceInterfaces(), Test_IoRegisterDeviceInterface(), USBH_SymbolicLink(), USBPORT_RegisterDeviceInterface(), and WdmAudRegisterDeviceInterface().

◆ IoSetDeviceInterfaceState()

NTSTATUS NTAPI IoSetDeviceInterfaceState ( IN PUNICODE_STRING  SymbolicLinkName,
IN BOOLEAN  Enable 
)

Definition at line 1311 of file deviface.c.

1313{
1318 HANDLE InstanceHandle, ControlHandle;
1321 ULONG LinkedValue, Index;
1322 GUID DeviceGuid;
1323 UNICODE_STRING DosDevicesPrefix1 = RTL_CONSTANT_STRING(L"\\??\\");
1324 UNICODE_STRING DosDevicesPrefix2 = RTL_CONSTANT_STRING(L"\\\\?\\");
1325 UNICODE_STRING LinkNameNoPrefix;
1326 USHORT i;
1327 USHORT ReferenceStringOffset;
1328
1329 if (SymbolicLinkName == NULL)
1330 {
1332 }
1333
1334 DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable);
1335
1336 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1337 /* Make sure it starts with the expected prefix */
1338 if (!RtlPrefixUnicodeString(&DosDevicesPrefix1, SymbolicLinkName, FALSE) &&
1339 !RtlPrefixUnicodeString(&DosDevicesPrefix2, SymbolicLinkName, FALSE))
1340 {
1341 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1343 }
1344
1345 /* Make a version without the prefix for further processing */
1346 ASSERT(DosDevicesPrefix1.Length == DosDevicesPrefix2.Length);
1347 ASSERT(SymbolicLinkName->Length >= DosDevicesPrefix1.Length);
1348 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + DosDevicesPrefix1.Length / sizeof(WCHAR);
1349 LinkNameNoPrefix.Length = SymbolicLinkName->Length - DosDevicesPrefix1.Length;
1350 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
1351
1352 /* Find the reference string, if any */
1353 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
1354 {
1355 if (LinkNameNoPrefix.Buffer[i] == L'\\')
1356 {
1357 break;
1358 }
1359 }
1360 ReferenceStringOffset = i * sizeof(WCHAR);
1361
1362 /* The GUID is before the reference string or at the end */
1363 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
1364 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
1365 {
1366 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1368 }
1369
1370 GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1372 GuidString.MaximumLength = GuidString.Length;
1373 Status = RtlGUIDFromString(&GuidString, &DeviceGuid);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 DPRINT1("RtlGUIDFromString() invalid GUID '%wZ' in link name '%wZ'\n", &GuidString, SymbolicLinkName);
1377 return Status;
1378 }
1379
1380 /* Open registry keys */
1383 NULL,
1384 NULL,
1385 &InstanceHandle);
1386 if (!NT_SUCCESS(Status))
1387 return Status;
1388
1389 RtlInitUnicodeString(&KeyName, L"Control");
1391 &KeyName,
1393 InstanceHandle,
1394 NULL);
1395 Status = ZwCreateKey(&ControlHandle,
1398 0,
1399 NULL,
1401 NULL);
1402 ZwClose(InstanceHandle);
1403 if (!NT_SUCCESS(Status))
1404 {
1405 DPRINT1("Failed to create the Control subkey\n");
1406 return Status;
1407 }
1408
1409 LinkedValue = (Enable ? 1 : 0);
1410
1411 RtlInitUnicodeString(&KeyName, L"Linked");
1412 Status = ZwSetValueKey(ControlHandle,
1413 &KeyName,
1414 0,
1415 REG_DWORD,
1416 &LinkedValue,
1417 sizeof(ULONG));
1418 ZwClose(ControlHandle);
1419 if (!NT_SUCCESS(Status))
1420 {
1421 DPRINT1("Failed to write the Linked value\n");
1422 return Status;
1423 }
1424
1425 ASSERT(GuidString.Buffer >= LinkNameNoPrefix.Buffer + 1);
1426 DeviceInstance.Length = (GuidString.Buffer - LinkNameNoPrefix.Buffer - 1) * sizeof(WCHAR);
1427 if (DeviceInstance.Length == 0)
1428 {
1429 DPRINT1("No device instance in link name '%wZ'\n", SymbolicLinkName);
1431 }
1432 DeviceInstance.MaximumLength = DeviceInstance.Length;
1434 DeviceInstance.MaximumLength,
1435 TAG_IO);
1436 if (DeviceInstance.Buffer == NULL)
1437 {
1438 /* no memory */
1440 }
1441
1443 LinkNameNoPrefix.Buffer,
1444 DeviceInstance.Length);
1445
1446 for (Index = 0; Index < DeviceInstance.Length / sizeof(WCHAR); Index++)
1447 {
1448 if (DeviceInstance.Buffer[Index] == L'#')
1449 {
1450 DeviceInstance.Buffer[Index] = L'\\';
1451 }
1452 }
1453
1455
1457 {
1458 DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1461 }
1462
1464
1466
1469
1471 DPRINT("Status %x\n", Status);
1472 return STATUS_SUCCESS;
1473}
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
const GUID GUID_DEVICE_INTERFACE_REMOVAL
Definition: deviface.c:15
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_Must_inspect_result_ _In_ WDFDEVICE _In_ REFGUID EventGuid
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
NTSTATUS IopQueueDeviceChangeEvent(_In_ const GUID *EventGuid, _In_ const GUID *InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Definition: plugplay.c:52
VOID PiNotifyDeviceInterfaceChange(_In_ LPCGUID Event, _In_ LPCGUID InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Delivers the event to all drivers subscribed to EventCategoryDeviceInterfaceChange.
Definition: pnpnotify.c:161
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
#define GUID_STRING_BYTES
Definition: deviface.c:21
#define TAG_IO
Definition: tag.h:80
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ WDFCOLLECTION _In_ ULONG Index
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by _Function_class_(), add_volume_device(), BatteryClassInitializeDevice(), BatteryClassUnload(), Bus_PDO_PnP(), check_system_root(), ClasspRegisterMountedDeviceInterface(), FdoHandleRemoveDevice(), FdoHandleStartDevice(), FdoRemoveAdapter(), FdoStartAdapter(), HandleRemoveDevice(), HandleStartDevice(), HandleSurpriseRemoval(), HidClassPDO_PnP(), i8042PowerWorkItem(), KsCreateBusEnumObject(), KspEnableBusDeviceInterface(), KspRegisterDeviceAssociation(), KspRemoveDeviceAssociations(), KspSetDeviceInterfacesState(), Mx::MxSetDeviceInterfaceState(), NdisIPnPStartDevice(), NdisIPnPStopDevice(), PartitionHandleRemove(), PartitionHandleStartDevice(), PcRegisterSubdevice(), RamdiskAddDevice(), RamdiskPnp(), RamdiskRemoveBusDevice(), RegisterDeviceInterfaces(), remove_volume_child(), ScsiFlopRemoveDevice(), ScsiFlopStartDevice(), SerenumFdoStartDevice(), SerialPnpStartDevice(), SysAudioRegisterDeviceInterfaces(), Test_IoSetDeviceInterface(), USBH_SymbolicLink(), USBPORT_RegisterDeviceInterface(), and WdmAudRegisterDeviceInterface().

◆ OpenRegistryHandlesFromSymbolicLink()

static NTSTATUS OpenRegistryHandlesFromSymbolicLink ( IN PUNICODE_STRING  SymbolicLinkName,
IN ACCESS_MASK  DesiredAccess,
IN OPTIONAL PHANDLE  GuidKey,
IN OPTIONAL PHANDLE  DeviceKey,
IN OPTIONAL PHANDLE  InstanceKey 
)
static

Definition at line 33 of file deviface.c.

38{
40 UNICODE_STRING BaseKeyU;
42 PWCHAR StartPosition, EndPosition;
43 HANDLE ClassesKey;
44 PHANDLE GuidKeyRealP, DeviceKeyRealP, InstanceKeyRealP;
45 HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal;
47
48 SubKeyName.Buffer = NULL;
49
50 if (GuidKey != NULL)
51 GuidKeyRealP = GuidKey;
52 else
53 GuidKeyRealP = &GuidKeyReal;
54
55 if (DeviceKey != NULL)
56 DeviceKeyRealP = DeviceKey;
57 else
58 DeviceKeyRealP = &DeviceKeyReal;
59
60 if (InstanceKey != NULL)
61 InstanceKeyRealP = InstanceKey;
62 else
63 InstanceKeyRealP = &InstanceKeyReal;
64
65 *GuidKeyRealP = NULL;
66 *DeviceKeyRealP = NULL;
67 *InstanceKeyRealP = NULL;
68
70
71 /* Open the DeviceClasses key */
73 &BaseKeyU,
75 NULL,
76 NULL);
77 Status = ZwOpenKey(&ClassesKey,
80 if (!NT_SUCCESS(Status))
81 {
82 DPRINT1("Failed to open %wZ\n", &BaseKeyU);
83 goto cleanup;
84 }
85
87 EndPosition = wcschr(SymbolicLinkName->Buffer, L'}');
88 if (!StartPosition || !EndPosition || StartPosition > EndPosition)
89 {
90 DPRINT1("Bad symbolic link: %wZ\n", SymbolicLinkName);
92 }
94 GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition);
95
99 ClassesKey,
100 NULL);
101 Status = ZwCreateKey(GuidKeyRealP,
104 0,
105 NULL,
107 NULL);
108 ZwClose(ClassesKey);
109 if (!NT_SUCCESS(Status))
110 {
111 DPRINT1("Failed to open %wZ%wZ (%x)\n", &BaseKeyU, &GuidString, Status);
112 goto cleanup;
113 }
114
115 SubKeyName.MaximumLength = SymbolicLinkName->Length + sizeof(WCHAR);
116 SubKeyName.Length = 0;
117 SubKeyName.Buffer = ExAllocatePool(PagedPool, SubKeyName.MaximumLength);
118 if (!SubKeyName.Buffer)
119 {
121 goto cleanup;
122 }
123
126
127 SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
128
129 SubKeyName.Buffer[0] = L'#';
130 SubKeyName.Buffer[1] = L'#';
131 SubKeyName.Buffer[2] = L'?';
132 SubKeyName.Buffer[3] = L'#';
133
134 ReferenceString.Buffer = wcsrchr(SubKeyName.Buffer, '\\');
135 if (ReferenceString.Buffer != NULL)
136 {
137 ReferenceString.Buffer[0] = L'#';
138
139 SubKeyName.Length = (USHORT)((ULONG_PTR)(ReferenceString.Buffer) - (ULONG_PTR)SubKeyName.Buffer);
140 ReferenceString.Length = SymbolicLinkName->Length - SubKeyName.Length;
141 }
142 else
143 {
145 }
146
148 &SubKeyName,
150 *GuidKeyRealP,
151 NULL);
152 Status = ZwCreateKey(DeviceKeyRealP,
155 0,
156 NULL,
158 NULL);
159 if (!NT_SUCCESS(Status))
160 {
161 DPRINT1("Failed to open %wZ%wZ\\%wZ Status %x\n", &BaseKeyU, &GuidString, &SubKeyName, Status);
162 goto cleanup;
163 }
164
168 *DeviceKeyRealP,
169 NULL);
170 Status = ZwCreateKey(InstanceKeyRealP,
173 0,
174 NULL,
176 NULL);
177 if (!NT_SUCCESS(Status))
178 {
179 DPRINT1("Failed to open %wZ%wZ\\%wZ%\\%wZ (%x)\n", &BaseKeyU, &GuidString, &SubKeyName, &ReferenceString, Status);
180 goto cleanup;
181 }
182
184
185cleanup:
186 if (SubKeyName.Buffer != NULL)
187 ExFreePool(SubKeyName.Buffer);
188
189 if (NT_SUCCESS(Status))
190 {
191 if (!GuidKey)
192 ZwClose(*GuidKeyRealP);
193
194 if (!DeviceKey)
195 ZwClose(*DeviceKeyRealP);
196
197 if (!InstanceKey)
198 ZwClose(*InstanceKeyRealP);
199 }
200 else
201 {
202 if (*GuidKeyRealP != NULL)
203 ZwClose(*GuidKeyRealP);
204
205 if (*DeviceKeyRealP != NULL)
206 ZwClose(*DeviceKeyRealP);
207
208 if (*InstanceKeyRealP != NULL)
209 ZwClose(*InstanceKeyRealP);
210 }
211
212 return Status;
213}
#define wcschr
Definition: compat.h:17
#define wcsrchr
Definition: compat.h:16
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
_In_ ULONG _In_ PVOID StartPosition
Definition: usbdlib.h:159

Referenced by IoOpenDeviceInterfaceRegistryKey(), and IoSetDeviceInterfaceState().

Variable Documentation

◆ BaseKeyString

PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\"
static

Definition at line 29 of file deviface.c.

Referenced by IoRegisterDeviceInterface(), and OpenRegistryHandlesFromSymbolicLink().