ReactOS 0.4.17-dev-1190-g4c812f4
deviface.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/deviface.c
5 * PURPOSE: Device interface functions
6 *
7 * PROGRAMMERS: Filip Navara (xnavara@volny.cz)
8 * Matthew Brace (ismarc@austin.rr.com)
9 * Hervé Poussineau (hpoussin@reactos.org)
10 * Oleg Dubinskiy (oleg.dubinskiy@reactos.org)
11 */
12
13/* INCLUDES ******************************************************************/
14
15#include <ntoskrnl.h>
16
17#define NDEBUG
18#include <debug.h>
19
20/* FIXME: This should be somewhere global instead of having 20 different versions */
21#define GUID_STRING_CHARS 38
22#define GUID_STRING_BYTES (GUID_STRING_CHARS * sizeof(WCHAR))
23C_ASSERT(sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}") == GUID_STRING_BYTES + sizeof(UNICODE_NULL));
24
25/* FUNCTIONS *****************************************************************/
26
29
30static PCWSTR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
31
59static
62 _In_ PCUNICODE_STRING DeviceString,
65 _In_ BOOLEAN UserModePrefixFormat,
67{
68 static const UNICODE_STRING KernelModePrefix = RTL_CONSTANT_STRING(L"\\??\\");
69 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
70 static const UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
71 UNICODE_STRING MungedDeviceString, SymbolicLink;
74 USHORT i;
75
76 /* Use a backslash if reference string is not specified */
77 if (!ReferenceString)
78 ReferenceString = &PathSep;
79
80 /* Duplicate the device string (to "munge" it) */
81 Status = RtlDuplicateUnicodeString(0, DeviceString, &MungedDeviceString);
82 if (!NT_SUCCESS(Status))
83 {
84 DPRINT1("RtlDuplicateUnicodeString() failed, Status 0x%08lx\n", Status);
85 return Status;
86 }
87
88 /* Replace all '\' by '#' in device string */
89 for (i = 0; i < MungedDeviceString.Length / sizeof(WCHAR); i++)
90 {
91 if (MungedDeviceString.Buffer[i] == L'\\')
92 MungedDeviceString.Buffer[i] = L'#';
93 }
94
95 /* Calculate total length */
96 Length = KernelModePrefix.Length // Same as UserModePrefix.Length
97 + MungedDeviceString.Length
98 + sizeof(L"#") + GuidString->Length
99 + ReferenceString->Length;
101
102 /* Build up new symbolic link */
103 SymbolicLink.Length = 0;
104 SymbolicLink.MaximumLength = Length;
106 if (!SymbolicLink.Buffer)
107 {
108 DPRINT1("ExAllocatePoolWithTag() failed\n");
110 }
111
113 L"%wZ%wZ#%wZ%wZ",
114 UserModePrefixFormat ?
115 &UserModePrefix : &KernelModePrefix,
116 &MungedDeviceString,
120
121 DPRINT("New symbolic link is %wZ\n", &SymbolicLink);
122
124 return STATUS_SUCCESS;
125}
126
159static
163 _Out_opt_ PUNICODE_STRING PrefixString,
164 _Out_opt_ PUNICODE_STRING MungedString,
167 _Out_opt_ PBOOLEAN ReferenceStringPresent,
169{
170 static const UNICODE_STRING KernelModePrefix = RTL_CONSTANT_STRING(L"\\??\\");
171 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
172 UNICODE_STRING MungedStringReal, GuidStringReal, ReferenceStringReal;
173 UNICODE_STRING LinkNameNoPrefix;
174 USHORT i, ReferenceStringOffset;
176
177 DPRINT("Symbolic link is %wZ\n", SymbolicLinkName);
178
179 /* The symbolic link name looks like \??\ACPI#PNP0501#1#{GUID}\ReferenceString
180 * Make sure it starts with the expected prefix. */
181 if (!RtlPrefixUnicodeString(&KernelModePrefix, SymbolicLinkName, FALSE) &&
183 {
184 DPRINT1("Invalid link name %wZ\n", SymbolicLinkName);
186 }
187
188 /* Sanity checks */
189 ASSERT(KernelModePrefix.Length == UserModePrefix.Length);
190 ASSERT(SymbolicLinkName->Length >= KernelModePrefix.Length);
191
192 /* Make a version without the prefix for further processing */
193 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + KernelModePrefix.Length / sizeof(WCHAR);
194 LinkNameNoPrefix.Length = SymbolicLinkName->Length - KernelModePrefix.Length;
195 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
196
197 DPRINT("Symbolic link without prefix is %wZ\n", &LinkNameNoPrefix);
198
199 /* Find the reference string, if any */
200 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
201 {
202 if (LinkNameNoPrefix.Buffer[i] == L'\\')
203 break;
204 }
205 ReferenceStringOffset = i * sizeof(WCHAR);
206
207 /* The GUID is before the reference string or at the end */
208 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
209 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
210 {
211 DPRINT1("Invalid link name %wZ\n", SymbolicLinkName);
213 }
214
215 /* Get reference string (starts with \ after {GUID}) from link without prefix */
216 ReferenceStringReal.Buffer = LinkNameNoPrefix.Buffer + ReferenceStringOffset / sizeof(WCHAR);
217 ReferenceStringReal.Length = LinkNameNoPrefix.Length - ReferenceStringOffset;
218 ReferenceStringReal.MaximumLength = ReferenceStringReal.Length;
219
220 DPRINT("Reference string is %wZ\n", &ReferenceStringReal);
221
222 /* Get GUID string (device class GUID in {} brackets) */
223 GuidStringReal.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
224 GuidStringReal.Length = GUID_STRING_BYTES;
225 GuidStringReal.MaximumLength = GuidStringReal.Length;
226
227 DPRINT("GUID string is %wZ\n", &GuidStringReal);
228
229 /* Validate GUID string for:
230 * 1) {} brackets at the start and the end;
231 * 2) - separators in the appropriate places. */
232 ASSERT(GuidStringReal.Buffer[0] == L'{');
233 ASSERT(GuidStringReal.Buffer[GUID_STRING_CHARS - 1] == L'}');
234 ASSERT(GuidStringReal.Buffer[9] == L'-');
235 ASSERT(GuidStringReal.Buffer[14] == L'-');
236 ASSERT(GuidStringReal.Buffer[19] == L'-');
237 ASSERT(GuidStringReal.Buffer[24] == L'-');
238
239 if (MungedString)
240 {
241 /* Create a munged path string (looks like ACPI#PNP0501#1#) */
242 MungedStringReal.Buffer = LinkNameNoPrefix.Buffer;
243 MungedStringReal.Length = LinkNameNoPrefix.Length - ReferenceStringReal.Length - GUID_STRING_BYTES - sizeof(WCHAR);
244 MungedStringReal.MaximumLength = MungedStringReal.Length;
245
246 DPRINT("Munged string is %wZ\n", &MungedStringReal);
247 }
248
249 /* Store received parts if the parameters are not null */
250 if (PrefixString)
251 {
252 PrefixString->Buffer = SymbolicLinkName->Buffer;
253 PrefixString->Length = KernelModePrefix.Length; // Same as UserModePrefix.Length
254 PrefixString->MaximumLength = PrefixString->Length;
255
256 DPRINT("Prefix string is %wZ\n", PrefixString);
257 }
258
259 if (MungedString)
260 *MungedString = MungedStringReal;
261
262 if (GuidString)
263 *GuidString = GuidStringReal;
264
265 if (ReferenceString)
266 {
267 if (ReferenceStringReal.Length > sizeof(WCHAR))
268 *ReferenceString = ReferenceStringReal;
269 else
270 RtlInitEmptyUnicodeString(ReferenceString, NULL, 0);
271 }
272
273 if (ReferenceStringPresent)
274 *ReferenceStringPresent = ReferenceStringReal.Length > sizeof(WCHAR);
275
277 {
278 /* Convert GUID string into a GUID and store it also */
279 Status = RtlGUIDFromString(&GuidStringReal, InterfaceClassGuid);
280 if (!NT_SUCCESS(Status))
281 {
282 DPRINT1("RtlGUIDFromString() failed, Status 0x%08lx\n", Status);
283 }
284 }
285
286 /* We're done */
287 return Status;
288}
289
295static
299 _Out_opt_ PULONG DeviceDisposition,
300 _Out_opt_ PHANDLE InstanceHandle,
301 _Out_opt_ PULONG InstanceDisposition,
302 _In_ HANDLE ClassHandle,
306{
309 HANDLE DeviceKeyHandle, InstanceKeyHandle;
310 ULONG DeviceKeyDisposition, InstanceKeyDisposition;
311 BOOLEAN ReferenceStringPresent = FALSE; /* Assuming no ref string by default */
313 USHORT i;
314
315 DeviceKeyHandle = InstanceKeyHandle = NULL;
316
317 /* Duplicate the symbolic link (we'll modify it later) */
319 if (!NT_SUCCESS(Status))
320 {
321 DPRINT1("RtlDuplicateUnicodeString() failed, Status 0x%08lx\n", Status);
322 goto Quit;
323 }
324
325 /* Separate it into its constituents */
327 NULL,
328 NULL,
329 NULL,
331 &ReferenceStringPresent,
332 NULL);
333 if (!NT_SUCCESS(Status))
334 {
335 DPRINT1("Failed to separate symbolic link %wZ, Status 0x%08lx\n", &SymbolicLink, Status);
336 goto Quit;
337 }
338
339 /* Did we got a ref string? */
340 if (ReferenceStringPresent)
341 {
342 /* Remove it from our symbolic link */
343 SymbolicLink.MaximumLength = SymbolicLink.Length -= ReferenceString.Length;
344
345 /* Replace the 1st backslash `\` character by '#' pound */
346 ReferenceString.Buffer[0] = L'#';
347 }
348 else
349 {
350 /* No ref string, initialize it with a single pound character '#' */
352 }
353
354 /* Replace all '\' by '#' in symbolic link */
355 for (i = 0; i < SymbolicLink.Length / sizeof(WCHAR); i++)
356 {
357 if (SymbolicLink.Buffer[i] == L'\\')
358 SymbolicLink.Buffer[i] = L'#';
359 }
360
361 /* Fix prefix: '#??#' -> '##?#' */
362 SymbolicLink.Buffer[1] = L'#';
363
364 DPRINT("Munged symbolic link is %wZ\n", &SymbolicLink);
365
366 /* Try to open or create device interface keys */
367 if (Create)
368 {
369 Status = IopCreateRegistryKeyEx(&DeviceKeyHandle,
370 ClassHandle,
374 &DeviceKeyDisposition);
375 }
376 else
377 {
378 Status = IopOpenRegistryKeyEx(&DeviceKeyHandle,
379 ClassHandle,
382 }
383
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT1("Failed to create or open %wZ, Status 0x%08lx\n", &SymbolicLink, Status);
387 goto Quit;
388 }
389
390 DPRINT("Munged reference string is %wZ\n", &ReferenceString);
391
392 /* Try to open or create instance subkeys */
393 if (Create)
394 {
395 Status = IopCreateRegistryKeyEx(&InstanceKeyHandle,
396 DeviceKeyHandle,
400 &InstanceKeyDisposition);
401 }
402 else
403 {
404 Status = IopOpenRegistryKeyEx(&InstanceKeyHandle,
405 DeviceKeyHandle,
408 }
409
410 if (!NT_SUCCESS(Status))
411 {
412 DPRINT1("Failed to create or open %wZ, Status 0x%08lx\n", &ReferenceString, Status);
413 goto Quit;
414 }
415
417
418Quit:
419 if (NT_SUCCESS(Status))
420 {
421 if (DeviceHandle)
422 *DeviceHandle = DeviceKeyHandle;
423 else
424 ZwClose(DeviceKeyHandle);
425
426 if (DeviceDisposition)
427 *DeviceDisposition = DeviceKeyDisposition;
428
429 if (InstanceHandle)
430 *InstanceHandle = InstanceKeyHandle;
431 else
432 ZwClose(InstanceKeyHandle);
433
434 if (InstanceDisposition)
435 *InstanceDisposition = InstanceKeyDisposition;
436 }
437 else
438 {
439 if (InstanceKeyHandle)
440 ZwClose(InstanceKeyHandle);
441
442 if (Create)
443 ZwDeleteKey(DeviceKeyHandle);
444
445 if (DeviceKeyHandle)
446 ZwClose(DeviceKeyHandle);
447 }
448
449 if (SymbolicLink.Buffer)
451
452 return Status;
453}
454
460static
465 _Out_opt_ PHANDLE GuidKey,
466 _Out_opt_ PHANDLE DeviceKey,
467 _Out_opt_ PHANDLE InstanceKey)
468{
469 UNICODE_STRING BaseKeyU;
471 HANDLE ClassesKey;
472 HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal;
474
475 ClassesKey = GuidKeyReal = DeviceKeyReal = InstanceKeyReal = NULL;
476
478
479 /* Separate symbolic link onto the parts */
481 NULL,
482 NULL,
483 &GuidString,
484 NULL,
485 NULL,
486 NULL);
487 if (!NT_SUCCESS(Status))
488 {
489 DPRINT1("Failed to parse symbolic link %wZ, Status 0x%08lx\n",
491 goto Quit;
492 }
493
494 /* Open the DeviceClasses key */
495 Status = IopOpenRegistryKeyEx(&ClassesKey,
496 NULL,
497 &BaseKeyU,
499 if (!NT_SUCCESS(Status))
500 {
501 DPRINT1("Failed to open %wZ, Status 0x%08lx\n", &BaseKeyU, Status);
502 goto Quit;
503 }
504
505 /* Open the GUID subkey */
506 Status = IopOpenRegistryKeyEx(&GuidKeyReal,
507 ClassesKey,
508 &GuidString,
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT1("Failed to open %wZ%wZ, Status 0x%08lx\n", &BaseKeyU, &GuidString, Status);
513 goto Quit;
514 }
515
516 /* Open the device and instance subkeys */
518 NULL,
519 &InstanceKeyReal,
520 NULL,
521 GuidKeyReal,
524 FALSE);
525 if (!NT_SUCCESS(Status))
526 {
527 DPRINT1("Failed to open %wZ%wZ, Status 0x%08lx\n", &BaseKeyU, &GuidString, Status);
528 goto Quit;
529 }
530
532
533Quit:
534 if (NT_SUCCESS(Status))
535 {
536 if (GuidKey)
537 *GuidKey = GuidKeyReal;
538 else
539 ZwClose(GuidKeyReal);
540
541 if (DeviceKey)
542 *DeviceKey = DeviceKeyReal;
543 else
544 ZwClose(DeviceKeyReal);
545
546 if (InstanceKey)
547 *InstanceKey = InstanceKeyReal;
548 else
549 ZwClose(InstanceKeyReal);
550 }
551 else
552 {
553 if (GuidKeyReal)
554 ZwClose(GuidKeyReal);
555
556 if (DeviceKeyReal)
557 ZwClose(DeviceKeyReal);
558
559 if (InstanceKeyReal)
560 ZwClose(InstanceKeyReal);
561 }
562
563 if (ClassesKey)
564 ZwClose(ClassesKey);
565
566 return Status;
567}
568
573 _Out_opt_ PHANDLE DeviceKey,
574 _Out_opt_ PHANDLE InstanceKey)
575{
578 NULL,
579 DeviceKey,
580 InstanceKey);
581}
582
583/*++
584 * @name IoOpenDeviceInterfaceRegistryKey
585 * @unimplemented
586 *
587 * Provides a handle to the device's interface instance registry key.
588 * Documented in WDK.
589 *
590 * @param SymbolicLinkName
591 * Pointer to a string which identifies the device interface instance
592 *
593 * @param DesiredAccess
594 * Desired ACCESS_MASK used to access the key (like KEY_READ,
595 * KEY_WRITE, etc)
596 *
597 * @param DeviceInterfaceKey
598 * If a call has been succesfull, a handle to the registry key
599 * will be stored there
600 *
601 * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS
602 * otherwise (see WDK for details)
603 *
604 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread
605 *
606 *--*/
608NTAPI
612{
613 HANDLE InstanceKey, DeviceParametersKey;
616 UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
617
620 NULL,
621 NULL,
622 &InstanceKey);
623 if (!NT_SUCCESS(Status))
624 return Status;
625
627 &DeviceParametersU,
629 InstanceKey,
630 NULL);
631 Status = ZwCreateKey(&DeviceParametersKey,
634 0,
635 NULL,
637 NULL);
638 ZwClose(InstanceKey);
639
640 if (NT_SUCCESS(Status))
641 *DeviceInterfaceKey = DeviceParametersKey;
642
643 return Status;
644}
645
646/*++
647 * @name IopOpenInterfaceKey
648 *
649 * Returns the alias device interface of the specified device interface
650 *
651 * @param InterfaceClassGuid
652 * FILLME
653 *
654 * @param DesiredAccess
655 * FILLME
656 *
657 * @param pInterfaceKey
658 * FILLME
659 *
660 * @return Usual NTSTATUS
661 *
662 * @remarks None
663 *
664 *--*/
665static NTSTATUS
668 OUT HANDLE *pInterfaceKey)
669{
670 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\");
674 HANDLE InterfaceKey = NULL;
676
677 GuidString.Buffer = KeyName.Buffer = NULL;
678
680 if (!NT_SUCCESS(Status))
681 {
682 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
683 goto cleanup;
684 }
685
686 KeyName.Length = 0;
687 KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length;
688 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
689 if (!KeyName.Buffer)
690 {
691 DPRINT("ExAllocatePool() failed\n");
693 goto cleanup;
694 }
695
697 if (!NT_SUCCESS(Status))
698 {
699 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
700 goto cleanup;
701 }
703 if (!NT_SUCCESS(Status))
704 {
705 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
706 goto cleanup;
707 }
709 if (!NT_SUCCESS(Status))
710 {
711 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
712 goto cleanup;
713 }
715 if (!NT_SUCCESS(Status))
716 {
717 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
718 goto cleanup;
719 }
720
723 &KeyName,
725 NULL,
726 NULL);
727 Status = ZwOpenKey(
728 &InterfaceKey,
731 if (!NT_SUCCESS(Status))
732 {
733 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
734 goto cleanup;
735 }
736
737 *pInterfaceKey = InterfaceKey;
739
740cleanup:
741 if (!NT_SUCCESS(Status))
742 {
743 if (InterfaceKey != NULL)
744 ZwClose(InterfaceKey);
745 }
748 return Status;
749}
750
771NTAPI
775 _Out_ PUNICODE_STRING AliasSymbolicLinkName)
776{
777 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
778 UNICODE_STRING AliasSymbolicLink = {0};
779 UNICODE_STRING AliasGuidString = {0};
780 UNICODE_STRING DeviceString = {0};
783 HANDLE DeviceKey, AliasInstanceKey;
784 BOOLEAN UserModePrefixFormat;
785 BOOLEAN ReferenceStringPresent = FALSE; /* Assuming no ref string by default */
788
789 DPRINT("IoGetDeviceInterfaceAlias(%wZ, 0x%p)\n", SymbolicLinkName, AliasInterfaceClassGuid);
790
791 /* Sanity check */
793 {
794 DPRINT1("IoGetDeviceInterfaceAlias() invalid symbolic link or alias class GUID\n");
796 }
797
798 /* Convert alias GUID to a string */
800 if (!NT_SUCCESS(Status))
801 {
802 DPRINT1("RtlStringFromGUID() failed, Status 0x%08lx\n", Status);
803 goto Quit;
804 }
805
806 DPRINT("Alias GUID is %wZ\n", &AliasGuidString);
807
808 /* Get the device instance string of existing symbolic link */
811 NULL,
812 &DeviceKey,
813 NULL);
814 if (!NT_SUCCESS(Status))
815 {
816 DPRINT1("Failed to open device instance key for %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
817 goto Quit;
818 }
819
820 Status = IopGetRegistryValue(DeviceKey, L"DeviceInstance", &kvInfo);
821 ZwClose(DeviceKey);
822 if (!NT_SUCCESS(Status))
823 {
824 DPRINT1("Failed get device instance value, Status 0x%08lx\n", Status);
825 goto Quit;
826 }
827
828 if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0 || kvInfo->DataLength > MAXUSHORT)
829 {
830 DPRINT1("Wrong or empty instance value\n");
832 goto Quit;
833 }
834
835 /* Convert received data to unicode string */
836 Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset);
837 PnpRegSzToString(Buffer, kvInfo->DataLength, &DeviceString.Length);
838 DeviceString.MaximumLength = DeviceString.Length;
839 DeviceString.Buffer = Buffer;
840
841 /*
842 * Separate symbolic link into 4 parts:
843 * 1) prefix string (\??\ for kernel mode or \\?\ for user mode),
844 * 2) munged path string (like ##?#ACPI#PNP0501#1#{GUID}),
845 * 3) GUID string (the current GUID),
846 * 4) reference string (goes after GUID, starts with '\').
847 *
848 * We need only reference string.
849 */
851 NULL,
852 NULL,
853 NULL,
855 &ReferenceStringPresent,
856 NULL);
857 if (!NT_SUCCESS(Status))
858 {
859 DPRINT1("Failed to separate symbolic link %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
860 goto Quit;
861 }
862
863 DPRINT("Device string is '%wZ'\n", &DeviceString);
864
865 /* Does symbolic link have kernel mode "\??\" or user mode "\\?\" prefix format? */
866 UserModePrefixFormat = RtlPrefixUnicodeString(&UserModePrefix, SymbolicLinkName, FALSE);
867
868 /* Build up new symbolic link with alias GUID */
869 Status = IopBuildSymbolicLink(&DeviceString,
870 &AliasGuidString,
871 ReferenceStringPresent ? &ReferenceString : NULL,
872 UserModePrefixFormat,
873 &AliasSymbolicLink);
874 if (!NT_SUCCESS(Status))
875 {
876 DPRINT1("Failed to build alias symbolic link, Status 0x%08lx\n", Status);
877 goto Quit;
878 }
879
880 /* Make sure that alias symbolic link key exists in registry */
881 Status = OpenRegistryHandlesFromSymbolicLink(&AliasSymbolicLink,
882 KEY_READ,
883 NULL,
884 NULL,
885 &AliasInstanceKey);
886 if (!NT_SUCCESS(Status))
887 {
888 DPRINT1("Failed to open alias symbolic link key, Status 0x%08lx\n", Status);
889 goto Quit;
890 }
891 ZwClose(AliasInstanceKey);
892
893 /* We're done */
894 DPRINT("IoGetDeviceInterfaceAlias(): alias symbolic link %wZ\n", &AliasSymbolicLink);
895 *AliasSymbolicLinkName = AliasSymbolicLink;
897
898Quit:
899 if (!NT_SUCCESS(Status))
900 {
901 if (AliasSymbolicLink.Buffer)
902 RtlFreeUnicodeString(&AliasSymbolicLink);
903 }
904
905 if (AliasGuidString.Buffer)
906 RtlFreeUnicodeString(&AliasGuidString);
907
908 return Status;
909}
910
911/*++
912 * @name IoGetDeviceInterfaces
913 * @implemented
914 *
915 * Returns a list of device interfaces of a particular device interface class.
916 * Documented in WDK
917 *
918 * @param InterfaceClassGuid
919 * Points to a class GUID specifying the device interface class
920 *
921 * @param PhysicalDeviceObject
922 * Points to an optional PDO that narrows the search to only the
923 * device interfaces of the device represented by the PDO
924 *
925 * @param Flags
926 * Specifies flags that modify the search for device interfaces. The
927 * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
928 * returned symbolic links should contain also disabled device
929 * interfaces in addition to the enabled ones.
930 *
931 * @param SymbolicLinkList
932 * Points to a character pointer that is filled in on successful return
933 * with a list of unicode strings identifying the device interfaces
934 * that match the search criteria. The newly allocated buffer contains
935 * a list of symbolic link names. Each unicode string in the list is
936 * null-terminated; the end of the whole list is marked by an additional
937 * NULL. The caller is responsible for freeing the buffer (ExFreePool)
938 * when it is no longer needed.
939 * If no device interfaces match the search criteria, this routine
940 * returns STATUS_SUCCESS and the string contains a single NULL
941 * character.
942 *
943 * @return Usual NTSTATUS
944 *
945 * @remarks None
946 *
947 *--*/
949NTAPI
952 IN ULONG Flags,
954{
957 HANDLE InterfaceKey = NULL;
958 HANDLE DeviceKey = NULL;
959 HANDLE ReferenceKey = NULL;
960 HANDLE ControlKey = NULL;
961 PKEY_BASIC_INFORMATION DeviceBi = NULL;
962 PKEY_BASIC_INFORMATION ReferenceBi = NULL;
965 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
966 PUNICODE_STRING InstanceDevicePath = NULL;
969 BOOLEAN FoundRightPDO = FALSE;
970 ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
971 UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
973
974 PAGED_CODE();
975
977 {
978 /* Parameters must pass three border of checks */
979 DeviceObjectExtension = IoGetDevObjExtension(PhysicalDeviceObject);
980
981 /* 1st level: Presence of a Device Node */
982 if (DeviceObjectExtension->DeviceNode == NULL)
983 {
984 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
986 }
987
988 /* 2nd level: Presence of an non-zero length InstancePath */
989 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
990 {
991 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
993 }
994
995 InstanceDevicePath = &DeviceObjectExtension->DeviceNode->InstancePath;
996 }
997
998
1000 if (!NT_SUCCESS(Status))
1001 {
1002 DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status);
1003 goto cleanup;
1004 }
1005
1006 /* Enumerate subkeys (i.e. the different device objects) */
1007 while (TRUE)
1008 {
1009 Status = ZwEnumerateKey(
1010 InterfaceKey,
1011 i,
1013 NULL,
1014 0,
1015 &Size);
1017 {
1018 break;
1019 }
1021 {
1022 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1023 goto cleanup;
1024 }
1025
1026 DeviceBi = ExAllocatePool(PagedPool, Size);
1027 if (!DeviceBi)
1028 {
1029 DPRINT("ExAllocatePool() failed\n");
1031 goto cleanup;
1032 }
1033 Status = ZwEnumerateKey(
1034 InterfaceKey,
1035 i++,
1037 DeviceBi,
1038 Size,
1039 &Size);
1040 if (!NT_SUCCESS(Status))
1041 {
1042 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1043 goto cleanup;
1044 }
1045
1046 /* Open device key */
1047 KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength;
1048 KeyName.Buffer = DeviceBi->Name;
1051 &KeyName,
1053 InterfaceKey,
1054 NULL);
1055 Status = ZwOpenKey(
1056 &DeviceKey,
1059 if (!NT_SUCCESS(Status))
1060 {
1061 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1062 goto cleanup;
1063 }
1064
1066 {
1067 /* Check if we are on the right physical device object,
1068 * by reading the DeviceInstance string
1069 */
1070 RtlInitUnicodeString(&KeyName, L"DeviceInstance");
1071 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength);
1073 {
1074 ActualLength = NeededLength;
1075 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1076 if (!PartialInfo)
1077 {
1079 goto cleanup;
1080 }
1081
1082 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength);
1083 if (!NT_SUCCESS(Status))
1084 {
1085 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1086 ExFreePool(PartialInfo);
1087 goto cleanup;
1088 }
1089 if (PartialInfo->DataLength == InstanceDevicePath->Length)
1090 {
1091 if (RtlCompareMemory(PartialInfo->Data, InstanceDevicePath->Buffer, InstanceDevicePath->Length) == InstanceDevicePath->Length)
1092 {
1093 /* found right pdo */
1094 FoundRightPDO = TRUE;
1095 }
1096 }
1097 ExFreePool(PartialInfo);
1098 PartialInfo = NULL;
1099 if (!FoundRightPDO)
1100 {
1101 /* not yet found */
1102 continue;
1103 }
1104 }
1105 else
1106 {
1107 /* error */
1108 break;
1109 }
1110 }
1111
1112 /* Enumerate subkeys (ie the different reference strings) */
1113 j = 0;
1114 while (TRUE)
1115 {
1116 Status = ZwEnumerateKey(
1117 DeviceKey,
1118 j,
1120 NULL,
1121 0,
1122 &Size);
1124 {
1125 break;
1126 }
1128 {
1129 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1130 goto cleanup;
1131 }
1132
1133 ReferenceBi = ExAllocatePool(PagedPool, Size);
1134 if (!ReferenceBi)
1135 {
1136 DPRINT("ExAllocatePool() failed\n");
1138 goto cleanup;
1139 }
1140 Status = ZwEnumerateKey(
1141 DeviceKey,
1142 j++,
1144 ReferenceBi,
1145 Size,
1146 &Size);
1147 if (!NT_SUCCESS(Status))
1148 {
1149 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1150 goto cleanup;
1151 }
1152
1153 KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength;
1154 KeyName.Buffer = ReferenceBi->Name;
1156 {
1157 /* Skip Control subkey */
1158 goto NextReferenceString;
1159 }
1160
1161 /* Open reference key */
1164 &KeyName,
1166 DeviceKey,
1167 NULL);
1168 Status = ZwOpenKey(
1169 &ReferenceKey,
1172 if (!NT_SUCCESS(Status))
1173 {
1174 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1175 goto cleanup;
1176 }
1177
1179 {
1180 /* We have to check if the interface is enabled, by
1181 * reading the Linked value in the Control subkey
1182 */
1185 &Control,
1187 ReferenceKey,
1188 NULL);
1189 Status = ZwOpenKey(
1190 &ControlKey,
1194 {
1195 /* That's OK. The key doesn't exist (yet) because
1196 * the interface is not activated.
1197 */
1198 goto NextReferenceString;
1199 }
1200 else if (!NT_SUCCESS(Status))
1201 {
1202 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
1203 goto cleanup;
1204 }
1205
1206 RtlInitUnicodeString(&KeyName, L"Linked");
1207 Status = ZwQueryValueKey(ControlKey,
1208 &KeyName,
1210 NULL,
1211 0,
1212 &NeededLength);
1214 {
1215 ActualLength = NeededLength;
1216 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1217 if (!PartialInfo)
1218 {
1220 goto cleanup;
1221 }
1222
1223 Status = ZwQueryValueKey(ControlKey,
1224 &KeyName,
1226 PartialInfo,
1227 ActualLength,
1228 &NeededLength);
1229 if (!NT_SUCCESS(Status))
1230 {
1231 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1232 ExFreePool(PartialInfo);
1233 goto cleanup;
1234 }
1235
1236 if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
1237 {
1238 DPRINT1("Bad registry read\n");
1239 ExFreePool(PartialInfo);
1240 goto cleanup;
1241 }
1242
1243 RtlCopyMemory(&LinkedValue,
1244 PartialInfo->Data,
1245 PartialInfo->DataLength);
1246
1247 ExFreePool(PartialInfo);
1248 if (LinkedValue == 0)
1249 {
1250 /* This interface isn't active */
1251 goto NextReferenceString;
1252 }
1253 }
1254 else
1255 {
1256 DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
1257 goto cleanup;
1258 }
1259 }
1260
1261 /* Read the SymbolicLink string and add it into SymbolicLinkList */
1262 Status = ZwQueryValueKey(
1263 ReferenceKey,
1264 &SymbolicLink,
1266 NULL,
1267 0,
1268 &Size);
1270 {
1271 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1272 goto cleanup;
1273 }
1275 if (!bip)
1276 {
1277 DPRINT("ExAllocatePool() failed\n");
1279 goto cleanup;
1280 }
1281 Status = ZwQueryValueKey(
1282 ReferenceKey,
1283 &SymbolicLink,
1285 bip,
1286 Size,
1287 &Size);
1288 if (!NT_SUCCESS(Status))
1289 {
1290 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1291 goto cleanup;
1292 }
1293 else if (bip->Type != REG_SZ)
1294 {
1295 DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ);
1297 goto cleanup;
1298 }
1299 else if (bip->DataLength < 5 * sizeof(WCHAR))
1300 {
1301 DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR));
1303 goto cleanup;
1304 }
1305 KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength;
1306 KeyName.Buffer = (PWSTR)bip->Data;
1307
1308 /* Fixup the prefix (from "\\?\") */
1309 RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
1310
1311 /* Add new symbolic link to symbolic link list */
1312 if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength)
1313 {
1314 PWSTR NewBuffer;
1315 ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength,
1316 (USHORT)(ReturnBuffer.Length +
1317 KeyName.Length +
1318 2 * sizeof(WCHAR)));
1319 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1320 if (!NewBuffer)
1321 {
1322 DPRINT("ExAllocatePool() failed\n");
1324 goto cleanup;
1325 }
1326 if (ReturnBuffer.Buffer)
1327 {
1328 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1329 ExFreePool(ReturnBuffer.Buffer);
1330 }
1331 ReturnBuffer.Buffer = NewBuffer;
1332 }
1333 DPRINT("Adding symbolic link %wZ\n", &KeyName);
1335 if (!NT_SUCCESS(Status))
1336 {
1337 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
1338 goto cleanup;
1339 }
1340 /* RtlAppendUnicodeStringToString added a NULL at the end of the
1341 * destination string, but didn't increase the Length field.
1342 * Do it for it.
1343 */
1344 ReturnBuffer.Length += sizeof(WCHAR);
1345
1346NextReferenceString:
1347 ExFreePool(ReferenceBi);
1348 ReferenceBi = NULL;
1349 if (bip)
1350 ExFreePool(bip);
1351 bip = NULL;
1352 if (ReferenceKey != NULL)
1353 {
1354 ZwClose(ReferenceKey);
1355 ReferenceKey = NULL;
1356 }
1357 if (ControlKey != NULL)
1358 {
1359 ZwClose(ControlKey);
1360 ControlKey = NULL;
1361 }
1362 }
1363 if (FoundRightPDO)
1364 {
1365 /* No need to go further, as we already have found what we searched */
1366 break;
1367 }
1368
1369 ExFreePool(DeviceBi);
1370 DeviceBi = NULL;
1371 ZwClose(DeviceKey);
1372 DeviceKey = NULL;
1373 }
1374
1375 /* Add final NULL to ReturnBuffer */
1376 ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength);
1377 if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength)
1378 {
1379 PWSTR NewBuffer;
1380 ReturnBuffer.MaximumLength += sizeof(WCHAR);
1381 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1382 if (!NewBuffer)
1383 {
1384 DPRINT("ExAllocatePool() failed\n");
1386 goto cleanup;
1387 }
1388 if (ReturnBuffer.Buffer)
1389 {
1390 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1391 ExFreePool(ReturnBuffer.Buffer);
1392 }
1393 ReturnBuffer.Buffer = NewBuffer;
1394 }
1395 ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1396 *SymbolicLinkList = ReturnBuffer.Buffer;
1398
1399cleanup:
1400 if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer)
1401 ExFreePool(ReturnBuffer.Buffer);
1402 if (InterfaceKey != NULL)
1403 ZwClose(InterfaceKey);
1404 if (DeviceKey != NULL)
1405 ZwClose(DeviceKey);
1406 if (ReferenceKey != NULL)
1407 ZwClose(ReferenceKey);
1408 if (ControlKey != NULL)
1409 ZwClose(ControlKey);
1410 if (DeviceBi)
1411 ExFreePool(DeviceBi);
1412 if (ReferenceBi)
1413 ExFreePool(ReferenceBi);
1414 if (bip)
1415 ExFreePool(bip);
1416 return Status;
1417}
1418
1419/*++
1420 * @name IoRegisterDeviceInterface
1421 * @implemented
1422 *
1423 * Registers a device interface class, if it has not been previously registered,
1424 * and creates a new instance of the interface class, which a driver can
1425 * subsequently enable for use by applications or other system components.
1426 * Documented in WDK.
1427 *
1428 * @param PhysicalDeviceObject
1429 * Points to an optional PDO that narrows the search to only the
1430 * device interfaces of the device represented by the PDO
1431 *
1432 * @param InterfaceClassGuid
1433 * Points to a class GUID specifying the device interface class
1434 *
1435 * @param ReferenceString
1436 * Optional parameter, pointing to a unicode string. For a full
1437 * description of this rather rarely used param (usually drivers
1438 * pass NULL here) see WDK
1439 *
1440 * @param SymbolicLinkName
1441 * Pointer to the resulting unicode string
1442 *
1443 * @return Usual NTSTATUS
1444 *
1445 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
1446 * system thread
1447 *
1448 *--*/
1450NTAPI
1455{
1456 PUNICODE_STRING InstancePath;
1459 UNICODE_STRING InterfaceKeyName;
1460 UNICODE_STRING BaseKeyName;
1461 UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))];
1462 POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer;
1465 HANDLE ClassKey;
1466 HANDLE InterfaceKey;
1467 HANDLE SubKey;
1468 ULONG StartIndex;
1470 ULONG i;
1471 NTSTATUS Status, SymLinkStatus;
1472 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
1473
1475
1476 DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n",
1478
1479 /* Parameters must pass three border of checks */
1480 DeviceObjectExtension = IoGetDevObjExtension(PhysicalDeviceObject);
1481
1482 /* 1st level: Presence of a Device Node */
1483 if (DeviceObjectExtension->DeviceNode == NULL)
1484 {
1485 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
1487 }
1488
1489 /* 2nd level: Presence of an non-zero length InstancePath */
1490 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
1491 {
1492 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
1494 }
1495
1496 /* 3rd level: Optional, based on WDK documentation */
1497 if (ReferenceString != NULL)
1498 {
1499 /* Reference string must not contain path-separator symbols */
1500 for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++)
1501 {
1502 if ((ReferenceString->Buffer[i] == '\\') ||
1503 (ReferenceString->Buffer[i] == '/'))
1505 }
1506 }
1507
1509 if (!NT_SUCCESS(Status))
1510 {
1511 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
1512 return Status;
1513 }
1514
1515 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
1518 PdoNameInfo,
1519 sizeof(PdoNameInfoBuffer),
1520 &i);
1521 if (!NT_SUCCESS(Status))
1522 {
1523 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status);
1524 return Status;
1525 }
1526 ASSERT(PdoNameInfo->Name.Length);
1527
1528 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1530 InstancePath = &(IoGetDevObjExtension(PhysicalDeviceObject)->DeviceNode->InstancePath);
1531 BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR);
1532 BaseKeyName.MaximumLength = BaseKeyName.Length
1533 + GuidString.Length;
1534 BaseKeyName.Buffer = ExAllocatePool(
1535 PagedPool,
1536 BaseKeyName.MaximumLength);
1537 if (!BaseKeyName.Buffer)
1538 {
1539 DPRINT("ExAllocatePool() failed\n");
1541 }
1542 wcscpy(BaseKeyName.Buffer, BaseKeyString);
1544
1545 /* Create BaseKeyName key in registry */
1548 &BaseKeyName,
1550 NULL, /* RootDirectory */
1551 NULL); /* SecurityDescriptor */
1552
1553 Status = ZwCreateKey(
1554 &ClassKey,
1555 KEY_WRITE,
1557 0, /* TileIndex */
1558 NULL, /* Class */
1560 NULL); /* Disposition */
1561
1562 if (!NT_SUCCESS(Status))
1563 {
1564 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1565 ExFreePool(BaseKeyName.Buffer);
1566 return Status;
1567 }
1568
1569 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
1570 InterfaceKeyName.Length = 0;
1571 InterfaceKeyName.MaximumLength =
1572 4 * sizeof(WCHAR) + /* 4 = size of ##?# */
1573 InstancePath->Length +
1574 sizeof(WCHAR) + /* 1 = size of # */
1575 GuidString.Length;
1576 InterfaceKeyName.Buffer = ExAllocatePool(
1577 PagedPool,
1578 InterfaceKeyName.MaximumLength);
1579 if (!InterfaceKeyName.Buffer)
1580 {
1581 DPRINT("ExAllocatePool() failed\n");
1583 }
1584
1585 RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#");
1586 StartIndex = InterfaceKeyName.Length / sizeof(WCHAR);
1587 RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath);
1588 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1589 {
1590 if (InterfaceKeyName.Buffer[StartIndex + i] == '\\')
1591 InterfaceKeyName.Buffer[StartIndex + i] = '#';
1592 }
1593 RtlAppendUnicodeToString(&InterfaceKeyName, L"#");
1594 RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString);
1595
1596 /* Create the interface key in registry */
1599 &InterfaceKeyName,
1601 ClassKey,
1602 NULL); /* SecurityDescriptor */
1603
1604 Status = ZwCreateKey(
1605 &InterfaceKey,
1606 KEY_WRITE,
1608 0, /* TileIndex */
1609 NULL, /* Class */
1611 NULL); /* Disposition */
1612
1613 if (!NT_SUCCESS(Status))
1614 {
1615 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1616 ZwClose(ClassKey);
1617 ExFreePool(BaseKeyName.Buffer);
1618 return Status;
1619 }
1620
1621 /* Write DeviceInstance entry. Value is InstancePath */
1622 Status = ZwSetValueKey(
1623 InterfaceKey,
1625 0, /* TileIndex */
1626 REG_SZ,
1627 InstancePath->Buffer,
1628 InstancePath->Length);
1629 if (!NT_SUCCESS(Status))
1630 {
1631 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1632 ZwClose(InterfaceKey);
1633 ZwClose(ClassKey);
1634 ExFreePool(InterfaceKeyName.Buffer);
1635 ExFreePool(BaseKeyName.Buffer);
1636 return Status;
1637 }
1638
1639 /* Create subkey. Name is #ReferenceString */
1640 SubKeyName.Length = 0;
1641 SubKeyName.MaximumLength = sizeof(WCHAR);
1642 if (ReferenceString && ReferenceString->Length)
1643 SubKeyName.MaximumLength += ReferenceString->Length;
1644 SubKeyName.Buffer = ExAllocatePool(
1645 PagedPool,
1646 SubKeyName.MaximumLength);
1647 if (!SubKeyName.Buffer)
1648 {
1649 DPRINT("ExAllocatePool() failed\n");
1650 ZwClose(InterfaceKey);
1651 ZwClose(ClassKey);
1652 ExFreePool(InterfaceKeyName.Buffer);
1653 ExFreePool(BaseKeyName.Buffer);
1655 }
1657 if (ReferenceString && ReferenceString->Length)
1659
1660 /* Create SubKeyName key in registry */
1663 &SubKeyName,
1665 InterfaceKey, /* RootDirectory */
1666 NULL); /* SecurityDescriptor */
1667
1668 Status = ZwCreateKey(
1669 &SubKey,
1670 KEY_WRITE,
1672 0, /* TileIndex */
1673 NULL, /* Class */
1675 NULL); /* Disposition */
1676
1677 if (!NT_SUCCESS(Status))
1678 {
1679 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1680 ZwClose(InterfaceKey);
1681 ZwClose(ClassKey);
1682 ExFreePool(InterfaceKeyName.Buffer);
1683 ExFreePool(BaseKeyName.Buffer);
1684 return Status;
1685 }
1686
1687 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1688 SymbolicLinkName->Length = 0;
1689 SymbolicLinkName->MaximumLength = SymbolicLinkName->Length
1690 + 4 * sizeof(WCHAR) /* 4 = size of \??\ */
1691 + InstancePath->Length
1692 + sizeof(WCHAR) /* 1 = size of # */
1693 + GuidString.Length
1694 + sizeof(WCHAR); /* final NULL */
1695 if (ReferenceString && ReferenceString->Length)
1696 SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length;
1698 PagedPool,
1699 SymbolicLinkName->MaximumLength);
1700 if (!SymbolicLinkName->Buffer)
1701 {
1702 DPRINT("ExAllocatePool() failed\n");
1703 ZwClose(SubKey);
1704 ZwClose(InterfaceKey);
1705 ZwClose(ClassKey);
1706 ExFreePool(InterfaceKeyName.Buffer);
1707 ExFreePool(SubKeyName.Buffer);
1708 ExFreePool(BaseKeyName.Buffer);
1710 }
1712 StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1714 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1715 {
1716 if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1717 SymbolicLinkName->Buffer[StartIndex + i] = '#';
1718 }
1721 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1722
1723 /* Create symbolic link */
1724 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name);
1725 SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1726
1727 /* If the symbolic link already exists, return an informational success status */
1728 if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION)
1729 {
1730 /* HACK: Delete the existing symbolic link and update it to the new PDO name */
1732 IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1733 SymLinkStatus = STATUS_OBJECT_NAME_EXISTS;
1734 }
1735
1736 if (!NT_SUCCESS(SymLinkStatus))
1737 {
1738 DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus);
1739 ZwClose(SubKey);
1740 ZwClose(InterfaceKey);
1741 ZwClose(ClassKey);
1742 ExFreePool(SubKeyName.Buffer);
1743 ExFreePool(InterfaceKeyName.Buffer);
1744 ExFreePool(BaseKeyName.Buffer);
1746 return SymLinkStatus;
1747 }
1748
1749 if (ReferenceString && ReferenceString->Length)
1750 {
1753 }
1754 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1755
1756 /* Write symbolic link name in registry */
1757 SymbolicLinkName->Buffer[1] = '\\';
1758 Status = ZwSetValueKey(
1759 SubKey,
1760 &SymbolicLink,
1761 0, /* TileIndex */
1762 REG_SZ,
1763 SymbolicLinkName->Buffer,
1764 SymbolicLinkName->Length);
1765 if (!NT_SUCCESS(Status))
1766 {
1767 DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1769 }
1770 else
1771 {
1772 SymbolicLinkName->Buffer[1] = '?';
1773 }
1774
1775 ZwClose(SubKey);
1776 ZwClose(InterfaceKey);
1777 ZwClose(ClassKey);
1778 ExFreePool(SubKeyName.Buffer);
1779 ExFreePool(InterfaceKeyName.Buffer);
1780 ExFreePool(BaseKeyName.Buffer);
1781
1782 return NT_SUCCESS(Status) ? SymLinkStatus : Status;
1783}
1784
1785/*++
1786 * @name IoSetDeviceInterfaceState
1787 * @implemented
1788 *
1789 * Enables or disables an instance of a previously registered device
1790 * interface class.
1791 * Documented in WDK.
1792 *
1793 * @param SymbolicLinkName
1794 * Pointer to the string identifying instance to enable or disable
1795 *
1796 * @param Enable
1797 * TRUE = enable, FALSE = disable
1798 *
1799 * @return Usual NTSTATUS
1800 *
1801 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
1802 * system thread
1803 *
1804 *--*/
1806NTAPI
1809{
1814 HANDLE InstanceHandle, ControlHandle;
1817 ULONG LinkedValue, Index;
1818 GUID DeviceGuid;
1819 UNICODE_STRING DosDevicesPrefix1 = RTL_CONSTANT_STRING(L"\\??\\");
1820 UNICODE_STRING DosDevicesPrefix2 = RTL_CONSTANT_STRING(L"\\\\?\\");
1821 UNICODE_STRING LinkNameNoPrefix;
1822 USHORT i;
1823 USHORT ReferenceStringOffset;
1824
1825 if (SymbolicLinkName == NULL)
1826 {
1828 }
1829
1830 DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable);
1831
1832 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1833 /* Make sure it starts with the expected prefix */
1834 if (!RtlPrefixUnicodeString(&DosDevicesPrefix1, SymbolicLinkName, FALSE) &&
1835 !RtlPrefixUnicodeString(&DosDevicesPrefix2, SymbolicLinkName, FALSE))
1836 {
1837 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1839 }
1840
1841 /* Make a version without the prefix for further processing */
1842 ASSERT(DosDevicesPrefix1.Length == DosDevicesPrefix2.Length);
1843 ASSERT(SymbolicLinkName->Length >= DosDevicesPrefix1.Length);
1844 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + DosDevicesPrefix1.Length / sizeof(WCHAR);
1845 LinkNameNoPrefix.Length = SymbolicLinkName->Length - DosDevicesPrefix1.Length;
1846 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
1847
1848 /* Find the reference string, if any */
1849 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
1850 {
1851 if (LinkNameNoPrefix.Buffer[i] == L'\\')
1852 {
1853 break;
1854 }
1855 }
1856 ReferenceStringOffset = i * sizeof(WCHAR);
1857
1858 /* The GUID is before the reference string or at the end */
1859 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
1860 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
1861 {
1862 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1864 }
1865
1866 GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1868 GuidString.MaximumLength = GuidString.Length;
1869 Status = RtlGUIDFromString(&GuidString, &DeviceGuid);
1870 if (!NT_SUCCESS(Status))
1871 {
1872 DPRINT1("RtlGUIDFromString() invalid GUID '%wZ' in link name '%wZ'\n", &GuidString, SymbolicLinkName);
1873 return Status;
1874 }
1875
1876 /* Open registry keys */
1879 NULL,
1880 NULL,
1881 &InstanceHandle);
1882 if (!NT_SUCCESS(Status))
1883 return Status;
1884
1885 RtlInitUnicodeString(&KeyName, L"Control");
1887 &KeyName,
1889 InstanceHandle,
1890 NULL);
1891 Status = ZwCreateKey(&ControlHandle,
1894 0,
1895 NULL,
1897 NULL);
1898 ZwClose(InstanceHandle);
1899 if (!NT_SUCCESS(Status))
1900 {
1901 DPRINT1("Failed to create the Control subkey\n");
1902 return Status;
1903 }
1904
1905 LinkedValue = (Enable ? 1 : 0);
1906
1907 RtlInitUnicodeString(&KeyName, L"Linked");
1908 Status = ZwSetValueKey(ControlHandle,
1909 &KeyName,
1910 0,
1911 REG_DWORD,
1912 &LinkedValue,
1913 sizeof(ULONG));
1914 ZwClose(ControlHandle);
1915 if (!NT_SUCCESS(Status))
1916 {
1917 DPRINT1("Failed to write the Linked value\n");
1918 return Status;
1919 }
1920
1921 ASSERT(GuidString.Buffer >= LinkNameNoPrefix.Buffer + 1);
1922 DeviceInstance.Length = (USHORT)((GuidString.Buffer - LinkNameNoPrefix.Buffer - 1) * sizeof(WCHAR));
1923 if (DeviceInstance.Length == 0)
1924 {
1925 DPRINT1("No device instance in link name '%wZ'\n", SymbolicLinkName);
1927 }
1928 DeviceInstance.MaximumLength = DeviceInstance.Length;
1930 DeviceInstance.MaximumLength,
1931 TAG_IO);
1932 if (DeviceInstance.Buffer == NULL)
1933 {
1934 /* no memory */
1936 }
1937
1939 LinkNameNoPrefix.Buffer,
1940 DeviceInstance.Length);
1941
1942 for (Index = 0; Index < DeviceInstance.Length / sizeof(WCHAR); Index++)
1943 {
1944 if (DeviceInstance.Buffer[Index] == L'#')
1945 {
1946 DeviceInstance.Buffer[Index] = L'\\';
1947 }
1948 }
1949
1951
1953 {
1954 DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1957 }
1958
1960
1962
1965
1967 DPRINT("Status %x\n", Status);
1968 return STATUS_SUCCESS;
1969}
1970
1971/* EOF */
#define PAGED_CODE()
@ DeviceNode
Definition: Node.h:9
unsigned char BOOLEAN
Definition: actypes.h:127
#define REG_SZ
Definition: layer.c:22
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
@ Create
Definition: registry.c:563
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#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:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
static const WCHAR SymbolicLink[]
Definition: interface.c:31
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#define L(x)
Definition: resources.c:13
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
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
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#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
_Must_inspect_result_ _In_ WDFDEVICE _In_ REFGUID EventGuid
Status
Definition: gdiplustypes.h:24
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
_In_ PUNICODE_STRING SymbolicLinkName
Definition: hubucx.h:491
#define C_ASSERT(e)
Definition: intsafe.h:73
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PWSTR GuidString
Definition: apphelp.c:93
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
_In_ PIOMMU_DEVICE_PATH _In_ PIOMMU_SVM_CAPABILITIES _Out_ PVOID * DeviceHandle
Definition: haltypes.h:1894
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
@ KeyBasicInformation
Definition: nt_native.h:1134
@ KeyValuePartialInformation
Definition: nt_native.h:1185
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define KEY_READ
Definition: nt_native.h:1026
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1021
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1060
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
struct _OBJECT_NAME_INFORMATION * POBJECT_NAME_INFORMATION
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1022
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1034
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1063
#define KEY_SET_VALUE
Definition: nt_native.h:1020
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
BOOLEAN NTAPI PnpRegSzToString(IN PWCHAR RegSzData, IN ULONG RegSzLength, OUT PUSHORT StringLength OPTIONAL)
Definition: pnputil.c:171
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1036
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
NTSTATUS NTAPI IopCreateRegistryKeyEx(OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
#define IoGetDevObjExtension(DeviceObject)
Definition: io.h:128
static NTSTATUS IopSeparateSymbolicLink(_In_ PCUNICODE_STRING SymbolicLinkName, _Out_opt_ PUNICODE_STRING PrefixString, _Out_opt_ PUNICODE_STRING MungedString, _Out_opt_ PUNICODE_STRING GuidString, _Out_opt_ PUNICODE_STRING ReferenceString, _Out_opt_ PBOOLEAN ReferenceStringPresent, _Out_opt_ LPGUID InterfaceClassGuid)
Parses the specified symbolic link onto the 4 parts: prefix, device string, class GUID and reference ...
Definition: deviface.c:161
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:234
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:666
#define GUID_STRING_CHARS
Definition: deviface.c:21
static NTSTATUS IopOpenOrCreateSymbolicLinkSubKeys(_Out_opt_ PHANDLE DeviceHandle, _Out_opt_ PULONG DeviceDisposition, _Out_opt_ PHANDLE InstanceHandle, _Out_opt_ PULONG InstanceDisposition, _In_ HANDLE ClassHandle, _In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN Create)
Retrieves a handles to the device and instance registry keys for the previously opened registry key h...
Definition: deviface.c:297
NTSTATUS IopOpenDeviceInterfaceKeys(_In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _Out_opt_ PHANDLE DeviceKey, _Out_opt_ PHANDLE InstanceKey)
Definition: deviface.c:570
static PCWSTR BaseKeyString
Definition: deviface.c:30
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
Definition: deviface.c:609
static NTSTATUS IopBuildSymbolicLink(_In_ PCUNICODE_STRING DeviceString, _In_ PCUNICODE_STRING GuidString, _In_opt_ PCUNICODE_STRING ReferenceString, _In_ BOOLEAN UserModePrefixFormat, _Out_ PUNICODE_STRING SymbolicLinkName)
Creates a new symbolic link from the specified format of the prefix, device string,...
Definition: deviface.c:61
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:950
static NTSTATUS OpenRegistryHandlesFromSymbolicLink(_In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _Out_opt_ PHANDLE GuidKey, _Out_opt_ PHANDLE DeviceKey, _Out_opt_ PHANDLE InstanceKey)
Retrieves a handles to the GUID, device and instance registry keys for the specified symbolic link.
Definition: deviface.c:462
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:1451
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1807
NTSTATUS NTAPI 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.
Definition: deviface.c:772
#define GUID_STRING_BYTES
Definition: deviface.c:22
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:189
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:285
NTSTRSAFEVAPI RtlUnicodeStringPrintf(_In_ PUNICODE_STRING DestinationString, _In_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:3241
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
#define CONST
Definition: pedump.c:81
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define REGSTR_PATH_DEVICE_CLASSES
Definition: regstr.h:481
#define REG_DWORD
Definition: sdbapi.c:615
wcscpy
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct _DEVICE_NODE * DeviceNode
Definition: iotypes.h:1095
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define max(a, b)
Definition: svc.c:63
#define TAG_IO
Definition: tag.h:79
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ CONST GUID _In_opt_ PCUNICODE_STRING ReferenceString
Definition: wdfdevice.h:3636
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
_In_ CONST GUID * AliasInterfaceClassGuid
Definition: iofuncs.h:962
_In_ ACCESS_MASK _Out_ PHANDLE DeviceInterfaceKey
Definition: iofuncs.h:1116
_In_ CONST GUID * InterfaceClassGuid
Definition: iofuncs.h:1136
#define DEVICE_INTERFACE_INCLUDE_NONACTIVE
Definition: iofuncs.h:2863
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3311