3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/deviface.c
6 * PURPOSE: Device interface functions
8 * PROGRAMMERS: Filip Navara (xnavara@volny.cz)
9 * Matthew Brace (ismarc@austin.rr.com)
10 * Hervé Poussineau (hpoussin@reactos.com)
13 /* INCLUDES ******************************************************************/
18 #include <internal/debug.h>
20 /* FUNCTIONS *****************************************************************/
22 static PWCHAR BaseKeyString
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
29 IoOpenDeviceInterfaceRegistryKey(
30 IN PUNICODE_STRING SymbolicLinkName
,
31 IN ACCESS_MASK DesiredAccess
,
32 OUT PHANDLE DeviceInterfaceKey
)
34 return STATUS_NOT_IMPLEMENTED
;
42 IoGetDeviceInterfaceAlias(
43 IN PUNICODE_STRING SymbolicLinkName
,
44 IN CONST GUID
*AliasInterfaceClassGuid
,
45 OUT PUNICODE_STRING AliasSymbolicLinkName
)
47 return STATUS_NOT_IMPLEMENTED
;
51 * IoGetDeviceInterfaces
53 * Returns a list of device interfaces of a particular device interface class.
57 * Points to a class GUID specifying the device interface class.
59 * PhysicalDeviceObject
60 * Points to an optional PDO that narrows the search to only the
61 * device interfaces of the device represented by the PDO.
64 * Specifies flags that modify the search for device interfaces. The
65 * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
66 * returned symbolic links should contain also disabled device
67 * interfaces in addition to the enabled ones.
70 * Points to a character pointer that is filled in on successful return
71 * with a list of unicode strings identifying the device interfaces
72 * that match the search criteria. The newly allocated buffer contains
73 * a list of symbolic link names. Each unicode string in the list is
74 * null-terminated; the end of the whole list is marked by an additional
75 * NULL. The caller is responsible for freeing the buffer (ExFreePool)
76 * when it is no longer needed.
77 * If no device interfaces match the search criteria, this routine
78 * returns STATUS_SUCCESS and the string contains a single NULL
84 * The parameters PhysicalDeviceObject and Flags aren't correctly
85 * processed. Rest of the cases was tested under Windows(R) XP and
86 * the function worked correctly.
90 IoGetDeviceInterfaces(
91 IN CONST GUID
*InterfaceClassGuid
,
92 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
94 OUT PWSTR
*SymbolicLinkList
)
96 PWCHAR BaseInterfaceString
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
97 UNICODE_STRING GuidString
;
98 UNICODE_STRING BaseKeyName
;
99 UNICODE_STRING AliasKeyName
;
100 UNICODE_STRING SymbolicLink
;
101 UNICODE_STRING Control
;
102 UNICODE_STRING SubKeyName
;
103 UNICODE_STRING SymbolicLinkKeyName
;
104 UNICODE_STRING ControlKeyName
;
105 UNICODE_STRING TempString
;
108 HANDLE SymbolicLinkKey
;
109 PKEY_FULL_INFORMATION fip
;
110 PKEY_FULL_INFORMATION bfip
= NULL
;
111 PKEY_BASIC_INFORMATION bip
;
112 PKEY_VALUE_PARTIAL_INFORMATION vpip
= NULL
;
113 PWCHAR SymLinkList
= NULL
;
114 ULONG SymLinkListSize
= 0;
119 OBJECT_ATTRIBUTES ObjectAttributes
;
121 Status
= RtlStringFromGUID(InterfaceClassGuid
, &GuidString
);
122 if (!NT_SUCCESS(Status
))
124 DPRINT("RtlStringFromGUID() Failed.\n");
125 return STATUS_INVALID_HANDLE
;
128 RtlInitUnicodeString(&AliasKeyName
, BaseInterfaceString
);
129 RtlInitUnicodeString(&SymbolicLink
, L
"SymbolicLink");
130 RtlInitUnicodeString(&Control
, L
"\\Control");
131 BaseKeyName
.Length
= wcslen(BaseKeyString
) * sizeof(WCHAR
);
132 BaseKeyName
.MaximumLength
= BaseKeyName
.Length
+ (38 * sizeof(WCHAR
));
133 BaseKeyName
.Buffer
= ExAllocatePool(
135 BaseKeyName
.MaximumLength
);
136 ASSERT(BaseKeyName
.Buffer
!= NULL
);
137 wcscpy(BaseKeyName
.Buffer
, BaseKeyString
);
138 RtlAppendUnicodeStringToString(&BaseKeyName
, &GuidString
);
140 if (PhysicalDeviceObject
)
142 WCHAR GuidBuffer
[40];
143 UNICODE_STRING PdoGuidString
;
145 RtlFreeUnicodeString(&BaseKeyName
);
148 PhysicalDeviceObject
,
149 DevicePropertyClassGuid
,
154 RtlInitUnicodeString(&PdoGuidString
, GuidBuffer
);
155 if (RtlCompareUnicodeString(&GuidString
, &PdoGuidString
, TRUE
))
157 DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n");
158 return STATUS_INVALID_HANDLE
;
161 DPRINT("IoGetDeviceInterfaces() called with PDO, not implemented.\n");
162 return STATUS_NOT_IMPLEMENTED
;
166 InitializeObjectAttributes(
169 OBJ_CASE_INSENSITIVE
,
178 if (!NT_SUCCESS(Status
))
180 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
181 RtlFreeUnicodeString(&BaseKeyName
);
192 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
194 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
195 RtlFreeUnicodeString(&BaseKeyName
);
196 ZwClose(InterfaceKey
);
200 fip
= (PKEY_FULL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
210 if (!NT_SUCCESS(Status
))
212 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
214 RtlFreeUnicodeString(&BaseKeyName
);
215 ZwClose(InterfaceKey
);
219 for (; i
< fip
->SubKeys
; i
++)
221 Status
= ZwEnumerateKey(
229 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
231 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
233 if (SymLinkList
!= NULL
)
234 ExFreePool(SymLinkList
);
235 RtlFreeUnicodeString(&BaseKeyName
);
236 ZwClose(InterfaceKey
);
240 bip
= (PKEY_BASIC_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
243 Status
= ZwEnumerateKey(
251 if (!NT_SUCCESS(Status
))
253 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
256 if (SymLinkList
!= NULL
)
257 ExFreePool(SymLinkList
);
258 RtlFreeUnicodeString(&BaseKeyName
);
259 ZwClose(InterfaceKey
);
263 SubKeyName
.Length
= 0;
264 SubKeyName
.MaximumLength
= BaseKeyName
.Length
+ bip
->NameLength
+ sizeof(WCHAR
);
265 SubKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, SubKeyName
.MaximumLength
);
266 ASSERT(SubKeyName
.Buffer
!= NULL
);
267 TempString
.Length
= TempString
.MaximumLength
= bip
->NameLength
;
268 TempString
.Buffer
= bip
->Name
;
269 RtlCopyUnicodeString(&SubKeyName
, &BaseKeyName
);
270 RtlAppendUnicodeToString(&SubKeyName
, L
"\\");
271 RtlAppendUnicodeStringToString(&SubKeyName
, &TempString
);
275 InitializeObjectAttributes(
278 OBJ_CASE_INSENSITIVE
,
287 if (!NT_SUCCESS(Status
))
289 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
291 if (SymLinkList
!= NULL
)
292 ExFreePool(SymLinkList
);
293 RtlFreeUnicodeString(&SubKeyName
);
294 RtlFreeUnicodeString(&BaseKeyName
);
295 ZwClose(InterfaceKey
);
306 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
308 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
310 RtlFreeUnicodeString(&BaseKeyName
);
311 RtlFreeUnicodeString(&SubKeyName
);
313 ZwClose(InterfaceKey
);
317 bfip
= (PKEY_FULL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
318 ASSERT(bfip
!= NULL
);
327 if (!NT_SUCCESS(Status
))
329 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
331 RtlFreeUnicodeString(&SubKeyName
);
332 RtlFreeUnicodeString(&BaseKeyName
);
334 ZwClose(InterfaceKey
);
338 for(j
= 0; j
< bfip
->SubKeys
; j
++)
340 Status
= ZwEnumerateKey(
348 if (Status
== STATUS_NO_MORE_ENTRIES
)
351 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
353 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
356 if (SymLinkList
!= NULL
)
357 ExFreePool(SymLinkList
);
358 RtlFreeUnicodeString(&SubKeyName
);
359 RtlFreeUnicodeString(&BaseKeyName
);
361 ZwClose(InterfaceKey
);
365 bip
= (PKEY_BASIC_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
368 Status
= ZwEnumerateKey(
376 if (!NT_SUCCESS(Status
))
378 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
382 if (SymLinkList
!= NULL
)
383 ExFreePool(SymLinkList
);
384 RtlFreeUnicodeString(&SubKeyName
);
385 RtlFreeUnicodeString(&BaseKeyName
);
387 ZwClose(InterfaceKey
);
391 if (!wcsncmp(bip
->Name
, L
"Control", bip
->NameLength
))
396 SymbolicLinkKeyName
.Length
= 0;
397 SymbolicLinkKeyName
.MaximumLength
= SubKeyName
.Length
+ bip
->NameLength
+ sizeof(WCHAR
);
398 SymbolicLinkKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, SymbolicLinkKeyName
.MaximumLength
);
399 ASSERT(SymbolicLinkKeyName
.Buffer
!= NULL
);
400 TempString
.Length
= TempString
.MaximumLength
= bip
->NameLength
;
401 TempString
.Buffer
= bip
->Name
;
402 RtlCopyUnicodeString(&SymbolicLinkKeyName
, &SubKeyName
);
403 RtlAppendUnicodeToString(&SymbolicLinkKeyName
, L
"\\");
404 RtlAppendUnicodeStringToString(&SymbolicLinkKeyName
, &TempString
);
406 ControlKeyName
.Length
= 0;
407 ControlKeyName
.MaximumLength
= SymbolicLinkKeyName
.Length
+ Control
.Length
+ sizeof(WCHAR
);
408 ControlKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, ControlKeyName
.MaximumLength
);
409 ASSERT(ControlKeyName
.Buffer
!= NULL
);
410 RtlCopyUnicodeString(&ControlKeyName
, &SymbolicLinkKeyName
);
411 RtlAppendUnicodeStringToString(&ControlKeyName
, &Control
);
415 InitializeObjectAttributes(
417 &SymbolicLinkKeyName
,
418 OBJ_CASE_INSENSITIVE
,
427 if (!NT_SUCCESS(Status
))
429 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
432 if (SymLinkList
!= NULL
)
433 ExFreePool(SymLinkList
);
434 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
435 RtlFreeUnicodeString(&SubKeyName
);
436 RtlFreeUnicodeString(&BaseKeyName
);
438 ZwClose(InterfaceKey
);
442 Status
= ZwQueryValueKey(
445 KeyValuePartialInformation
,
450 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
453 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
455 DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status
);
458 if (SymLinkList
!= NULL
)
459 ExFreePool(SymLinkList
);
460 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
461 RtlFreeUnicodeString(&SubKeyName
);
462 RtlFreeUnicodeString(&BaseKeyName
);
463 ZwClose(SymbolicLinkKey
);
465 ZwClose(InterfaceKey
);
469 vpip
= (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
470 ASSERT(vpip
!= NULL
);
472 Status
= ZwQueryValueKey(
475 KeyValuePartialInformation
,
480 if (!NT_SUCCESS(Status
))
482 DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status
);
486 if (SymLinkList
!= NULL
)
487 ExFreePool(SymLinkList
);
488 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
489 RtlFreeUnicodeString(&SubKeyName
);
490 RtlFreeUnicodeString(&BaseKeyName
);
491 ZwClose(SymbolicLinkKey
);
493 ZwClose(InterfaceKey
);
497 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, ControlKeyName
.Buffer
);
499 if (NT_SUCCESS(Status
))
501 /* Put the name in the string here */
502 if (SymLinkList
== NULL
)
504 SymLinkListSize
= vpip
->DataLength
;
505 SymLinkList
= ExAllocatePool(NonPagedPool
, SymLinkListSize
+ sizeof(WCHAR
));
506 ASSERT(SymLinkList
!= NULL
);
507 RtlCopyMemory(SymLinkList
, vpip
->Data
, vpip
->DataLength
);
508 SymLinkList
[vpip
->DataLength
/ sizeof(WCHAR
)] = 0;
509 SymLinkList
[1] = '?';
513 PWCHAR OldSymLinkList
;
514 ULONG OldSymLinkListSize
;
515 PWCHAR SymLinkListPtr
;
517 OldSymLinkList
= SymLinkList
;
518 OldSymLinkListSize
= SymLinkListSize
;
519 SymLinkListSize
+= vpip
->DataLength
;
520 SymLinkList
= ExAllocatePool(NonPagedPool
, SymLinkListSize
+ sizeof(WCHAR
));
521 ASSERT(SymLinkList
!= NULL
);
522 RtlCopyMemory(SymLinkList
, OldSymLinkList
, OldSymLinkListSize
);
523 ExFreePool(OldSymLinkList
);
524 SymLinkListPtr
= SymLinkList
+ (OldSymLinkListSize
/ sizeof(WCHAR
));
525 RtlCopyMemory(SymLinkListPtr
, vpip
->Data
, vpip
->DataLength
);
526 SymLinkListPtr
[vpip
->DataLength
/ sizeof(WCHAR
)] = 0;
527 SymLinkListPtr
[1] = '?';
531 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
532 RtlFreeUnicodeString(&ControlKeyName
);
533 ZwClose(SymbolicLinkKey
);
537 RtlFreeUnicodeString(&SubKeyName
);
541 if (SymLinkList
!= NULL
)
543 SymLinkList
[SymLinkListSize
/ sizeof(WCHAR
)] = 0;
547 SymLinkList
= ExAllocatePool(NonPagedPool
, 2 * sizeof(WCHAR
));
551 *SymbolicLinkList
= SymLinkList
;
553 RtlFreeUnicodeString(&BaseKeyName
);
554 ZwClose(InterfaceKey
);
559 return STATUS_SUCCESS
;
567 IoRegisterDeviceInterface(
568 IN PDEVICE_OBJECT PhysicalDeviceObject
,
569 IN CONST GUID
*InterfaceClassGuid
,
570 IN PUNICODE_STRING ReferenceString OPTIONAL
,
571 OUT PUNICODE_STRING SymbolicLinkName
)
573 PUNICODE_STRING InstancePath
;
574 UNICODE_STRING GuidString
;
575 UNICODE_STRING SubKeyName
;
576 UNICODE_STRING InterfaceKeyName
;
577 UNICODE_STRING BaseKeyName
;
578 UCHAR PdoNameInfoBuffer
[sizeof(OBJECT_NAME_INFORMATION
) + (256 * sizeof(WCHAR
))];
579 POBJECT_NAME_INFORMATION PdoNameInfo
= (POBJECT_NAME_INFORMATION
)PdoNameInfoBuffer
;
580 UNICODE_STRING DeviceInstance
= RTL_CONSTANT_STRING(L
"DeviceInstance");
581 UNICODE_STRING SymbolicLink
= RTL_CONSTANT_STRING(L
"SymbolicLink");
586 OBJECT_ATTRIBUTES ObjectAttributes
;
590 if (!(PhysicalDeviceObject
->Flags
& DO_BUS_ENUMERATED_DEVICE
))
592 DPRINT("PhysicalDeviceObject 0x%p is not a valid Pdo\n", PhysicalDeviceObject
);
593 return STATUS_INVALID_PARAMETER_1
;
596 Status
= RtlStringFromGUID(InterfaceClassGuid
, &GuidString
);
597 if (!NT_SUCCESS(Status
))
599 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status
);
603 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
604 Status
= ObQueryNameString(
605 PhysicalDeviceObject
,
607 sizeof(PdoNameInfoBuffer
),
609 if (!NT_SUCCESS(Status
))
611 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status
);
614 ASSERT(PdoNameInfo
->Name
.Length
);
616 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
617 ASSERT(PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
);
618 InstancePath
= &PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
->InstancePath
;
619 BaseKeyName
.Length
= wcslen(BaseKeyString
) * sizeof(WCHAR
);
620 BaseKeyName
.MaximumLength
= BaseKeyName
.Length
622 BaseKeyName
.Buffer
= ExAllocatePool(
624 BaseKeyName
.MaximumLength
);
625 if (!BaseKeyName
.Buffer
)
627 DPRINT("ExAllocatePool() failed\n");
628 return STATUS_INSUFFICIENT_RESOURCES
;
630 wcscpy(BaseKeyName
.Buffer
, BaseKeyString
);
631 RtlAppendUnicodeStringToString(&BaseKeyName
, &GuidString
);
633 /* Create BaseKeyName key in registry */
634 InitializeObjectAttributes(
637 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
| OBJ_OPENIF
,
638 NULL
, /* RootDirectory */
639 NULL
); /* SecurityDescriptor */
641 Status
= ZwCreateKey(
648 NULL
); /* Disposition */
650 if (!NT_SUCCESS(Status
))
652 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
653 ExFreePool(BaseKeyName
.Buffer
);
657 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
658 InterfaceKeyName
.Length
= 0;
659 InterfaceKeyName
.MaximumLength
=
660 4 * sizeof(WCHAR
) + /* 4 = size of ##?# */
661 InstancePath
->Length
+
662 sizeof(WCHAR
) + /* 1 = size of # */
664 InterfaceKeyName
.Buffer
= ExAllocatePool(
666 InterfaceKeyName
.MaximumLength
);
667 if (!InterfaceKeyName
.Buffer
)
669 DPRINT("ExAllocatePool() failed\n");
670 return STATUS_INSUFFICIENT_RESOURCES
;
673 RtlAppendUnicodeToString(&InterfaceKeyName
, L
"##?#");
674 StartIndex
= InterfaceKeyName
.Length
/ sizeof(WCHAR
);
675 RtlAppendUnicodeStringToString(&InterfaceKeyName
, InstancePath
);
676 for (i
= 0; i
< InstancePath
->Length
/ sizeof(WCHAR
); i
++)
678 if (InterfaceKeyName
.Buffer
[StartIndex
+ i
] == '\\')
679 InterfaceKeyName
.Buffer
[StartIndex
+ i
] = '#';
681 RtlAppendUnicodeToString(&InterfaceKeyName
, L
"#");
682 RtlAppendUnicodeStringToString(&InterfaceKeyName
, &GuidString
);
684 /* Create the interface key in registry */
685 InitializeObjectAttributes(
688 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
| OBJ_OPENIF
,
690 NULL
); /* SecurityDescriptor */
692 Status
= ZwCreateKey(
699 NULL
); /* Disposition */
701 if (!NT_SUCCESS(Status
))
703 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
705 ExFreePool(BaseKeyName
.Buffer
);
709 /* Write DeviceInstance entry. Value is InstancePath */
710 Status
= ZwSetValueKey(
715 InstancePath
->Buffer
,
716 InstancePath
->Length
);
717 if (!NT_SUCCESS(Status
))
719 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
720 ZwClose(InterfaceKey
);
722 ExFreePool(InterfaceKeyName
.Buffer
);
723 ExFreePool(BaseKeyName
.Buffer
);
727 /* Create subkey. Name is #ReferenceString */
728 SubKeyName
.Length
= 0;
729 SubKeyName
.MaximumLength
= sizeof(WCHAR
);
730 if (ReferenceString
&& ReferenceString
->Length
)
731 SubKeyName
.MaximumLength
+= ReferenceString
->Length
;
732 SubKeyName
.Buffer
= ExAllocatePool(
734 SubKeyName
.MaximumLength
);
735 if (!SubKeyName
.Buffer
)
737 DPRINT("ExAllocatePool() failed\n");
738 ZwClose(InterfaceKey
);
740 ExFreePool(InterfaceKeyName
.Buffer
);
741 ExFreePool(BaseKeyName
.Buffer
);
742 return STATUS_INSUFFICIENT_RESOURCES
;
744 RtlAppendUnicodeToString(&SubKeyName
, L
"#");
745 if (ReferenceString
&& ReferenceString
->Length
)
746 RtlAppendUnicodeStringToString(&SubKeyName
, ReferenceString
);
748 /* Create SubKeyName key in registry */
749 InitializeObjectAttributes(
752 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
753 InterfaceKey
, /* RootDirectory */
754 NULL
); /* SecurityDescriptor */
756 Status
= ZwCreateKey(
763 NULL
); /* Disposition */
765 if (!NT_SUCCESS(Status
))
767 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
768 ZwClose(InterfaceKey
);
770 ExFreePool(InterfaceKeyName
.Buffer
);
771 ExFreePool(BaseKeyName
.Buffer
);
775 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
776 SymbolicLinkName
->Length
= 0;
777 SymbolicLinkName
->MaximumLength
= SymbolicLinkName
->Length
778 + 4 * sizeof(WCHAR
) /* 4 = size of \??\ */
779 + InstancePath
->Length
780 + sizeof(WCHAR
) /* 1 = size of # */
782 + sizeof(WCHAR
); /* final NULL */
783 if (ReferenceString
&& ReferenceString
->Length
)
784 SymbolicLinkName
->MaximumLength
+= sizeof(WCHAR
) + ReferenceString
->Length
;
785 SymbolicLinkName
->Buffer
= ExAllocatePool(
787 SymbolicLinkName
->MaximumLength
);
788 if (!SymbolicLinkName
->Buffer
)
790 DPRINT("ExAllocatePool() failed\n");
792 ZwClose(InterfaceKey
);
794 ExFreePool(InterfaceKeyName
.Buffer
);
795 ExFreePool(SubKeyName
.Buffer
);
796 ExFreePool(BaseKeyName
.Buffer
);
797 return STATUS_INSUFFICIENT_RESOURCES
;
799 RtlAppendUnicodeToString(SymbolicLinkName
, L
"\\??\\");
800 StartIndex
= SymbolicLinkName
->Length
/ sizeof(WCHAR
);
801 RtlAppendUnicodeStringToString(SymbolicLinkName
, InstancePath
);
802 for (i
= 0; i
< InstancePath
->Length
/ sizeof(WCHAR
); i
++)
804 if (SymbolicLinkName
->Buffer
[StartIndex
+ i
] == '\\')
805 SymbolicLinkName
->Buffer
[StartIndex
+ i
] = '#';
807 RtlAppendUnicodeToString(SymbolicLinkName
, L
"#");
808 RtlAppendUnicodeStringToString(SymbolicLinkName
, &GuidString
);
809 if (ReferenceString
&& ReferenceString
->Length
)
811 RtlAppendUnicodeToString(SymbolicLinkName
, L
"\\");
812 RtlAppendUnicodeStringToString(SymbolicLinkName
, ReferenceString
);
814 SymbolicLinkName
->Buffer
[SymbolicLinkName
->Length
] = '\0';
816 /* Create symbolic link */
817 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName
, &PdoNameInfo
->Name
);
818 Status
= IoCreateSymbolicLink(SymbolicLinkName
, &PdoNameInfo
->Name
);
819 if (!NT_SUCCESS(Status
))
821 DPRINT("IoCreateSymbolicLink() failed with status 0x%08lx\n", Status
);
823 ZwClose(InterfaceKey
);
825 ExFreePool(SubKeyName
.Buffer
);
826 ExFreePool(InterfaceKeyName
.Buffer
);
827 ExFreePool(BaseKeyName
.Buffer
);
828 ExFreePool(SymbolicLinkName
->Buffer
);
832 /* Write symbolic link name in registry */
833 Status
= ZwSetValueKey(
838 SymbolicLinkName
->Buffer
,
839 SymbolicLinkName
->Length
);
840 if (!NT_SUCCESS(Status
))
842 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
843 ExFreePool(SymbolicLinkName
->Buffer
);
847 ZwClose(InterfaceKey
);
849 ExFreePool(SubKeyName
.Buffer
);
850 ExFreePool(InterfaceKeyName
.Buffer
);
851 ExFreePool(BaseKeyName
.Buffer
);
861 IoSetDeviceInterfaceState(
862 IN PUNICODE_STRING SymbolicLinkName
,
865 PDEVICE_OBJECT PhysicalDeviceObject
;
866 PFILE_OBJECT FileObject
;
867 UNICODE_STRING GuidString
;
868 PWCHAR StartPosition
;
872 if (SymbolicLinkName
== NULL
)
873 return STATUS_INVALID_PARAMETER_1
;
875 DPRINT("IoSetDeviceInterfaceState('%wZ', %d)\n", SymbolicLinkName
, Enable
);
876 Status
= IoGetDeviceObjectPointer(SymbolicLinkName
,
877 0, /* DesiredAccess */
879 &PhysicalDeviceObject
);
880 if (!NT_SUCCESS(Status
))
883 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
884 /* Get GUID from SymbolicLinkName */
885 StartPosition
= wcschr(SymbolicLinkName
->Buffer
, L
'{');
886 EndPosition
= wcschr(SymbolicLinkName
->Buffer
, L
'}');
887 if (!StartPosition
||!EndPosition
|| StartPosition
> EndPosition
)
888 return STATUS_INVALID_PARAMETER_1
;
889 GuidString
.Buffer
= StartPosition
;
890 GuidString
.MaximumLength
= GuidString
.Length
= (ULONG_PTR
)(EndPosition
+ 1) - (ULONG_PTR
)StartPosition
;
892 IopNotifyPlugPlayNotification(
893 PhysicalDeviceObject
,
894 EventCategoryDeviceInterfaceChange
,
895 Enable
? (LPGUID
)&GUID_DEVICE_INTERFACE_ARRIVAL
: (LPGUID
)&GUID_DEVICE_INTERFACE_REMOVAL
,
897 (PVOID
)SymbolicLinkName
);
899 ObDereferenceObject(FileObject
);
901 return STATUS_SUCCESS
;