ReactOS 0.4.16-dev-981-g80eb313
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
569/*++
570 * @name IoOpenDeviceInterfaceRegistryKey
571 * @unimplemented
572 *
573 * Provides a handle to the device's interface instance registry key.
574 * Documented in WDK.
575 *
576 * @param SymbolicLinkName
577 * Pointer to a string which identifies the device interface instance
578 *
579 * @param DesiredAccess
580 * Desired ACCESS_MASK used to access the key (like KEY_READ,
581 * KEY_WRITE, etc)
582 *
583 * @param DeviceInterfaceKey
584 * If a call has been succesfull, a handle to the registry key
585 * will be stored there
586 *
587 * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS
588 * otherwise (see WDK for details)
589 *
590 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread
591 *
592 *--*/
594NTAPI
598{
599 HANDLE InstanceKey, DeviceParametersKey;
602 UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
603
606 NULL,
607 NULL,
608 &InstanceKey);
609 if (!NT_SUCCESS(Status))
610 return Status;
611
613 &DeviceParametersU,
615 InstanceKey,
616 NULL);
617 Status = ZwCreateKey(&DeviceParametersKey,
620 0,
621 NULL,
623 NULL);
624 ZwClose(InstanceKey);
625
626 if (NT_SUCCESS(Status))
627 *DeviceInterfaceKey = DeviceParametersKey;
628
629 return Status;
630}
631
632/*++
633 * @name IopOpenInterfaceKey
634 *
635 * Returns the alias device interface of the specified device interface
636 *
637 * @param InterfaceClassGuid
638 * FILLME
639 *
640 * @param DesiredAccess
641 * FILLME
642 *
643 * @param pInterfaceKey
644 * FILLME
645 *
646 * @return Usual NTSTATUS
647 *
648 * @remarks None
649 *
650 *--*/
651static NTSTATUS
654 OUT HANDLE *pInterfaceKey)
655{
656 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\");
660 HANDLE InterfaceKey = NULL;
662
663 GuidString.Buffer = KeyName.Buffer = NULL;
664
666 if (!NT_SUCCESS(Status))
667 {
668 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
669 goto cleanup;
670 }
671
672 KeyName.Length = 0;
673 KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length;
674 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
675 if (!KeyName.Buffer)
676 {
677 DPRINT("ExAllocatePool() failed\n");
679 goto cleanup;
680 }
681
683 if (!NT_SUCCESS(Status))
684 {
685 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
686 goto cleanup;
687 }
689 if (!NT_SUCCESS(Status))
690 {
691 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
692 goto cleanup;
693 }
695 if (!NT_SUCCESS(Status))
696 {
697 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
698 goto cleanup;
699 }
701 if (!NT_SUCCESS(Status))
702 {
703 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
704 goto cleanup;
705 }
706
709 &KeyName,
711 NULL,
712 NULL);
713 Status = ZwOpenKey(
714 &InterfaceKey,
717 if (!NT_SUCCESS(Status))
718 {
719 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
720 goto cleanup;
721 }
722
723 *pInterfaceKey = InterfaceKey;
725
726cleanup:
727 if (!NT_SUCCESS(Status))
728 {
729 if (InterfaceKey != NULL)
730 ZwClose(InterfaceKey);
731 }
734 return Status;
735}
736
757NTAPI
761 _Out_ PUNICODE_STRING AliasSymbolicLinkName)
762{
763 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
764 UNICODE_STRING AliasSymbolicLink = {0};
765 UNICODE_STRING AliasGuidString = {0};
766 UNICODE_STRING DeviceString = {0};
769 HANDLE DeviceKey, AliasInstanceKey;
770 BOOLEAN UserModePrefixFormat;
771 BOOLEAN ReferenceStringPresent = FALSE; /* Assuming no ref string by default */
774
775 DPRINT("IoGetDeviceInterfaceAlias(%wZ, 0x%p)\n", SymbolicLinkName, AliasInterfaceClassGuid);
776
777 /* Sanity check */
779 {
780 DPRINT1("IoGetDeviceInterfaceAlias() invalid symbolic link or alias class GUID\n");
782 }
783
784 /* Convert alias GUID to a string */
786 if (!NT_SUCCESS(Status))
787 {
788 DPRINT1("RtlStringFromGUID() failed, Status 0x%08lx\n", Status);
789 goto Quit;
790 }
791
792 DPRINT("Alias GUID is %wZ\n", &AliasGuidString);
793
794 /* Get the device instance string of existing symbolic link */
797 NULL,
798 &DeviceKey,
799 NULL);
800 if (!NT_SUCCESS(Status))
801 {
802 DPRINT1("Failed to open device instance key for %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
803 goto Quit;
804 }
805
806 Status = IopGetRegistryValue(DeviceKey, L"DeviceInstance", &kvInfo);
807 ZwClose(DeviceKey);
808 if (!NT_SUCCESS(Status))
809 {
810 DPRINT1("Failed get device instance value, Status 0x%08lx\n", Status);
811 goto Quit;
812 }
813
814 if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0 || kvInfo->DataLength > MAXUSHORT)
815 {
816 DPRINT1("Wrong or empty instance value\n");
818 goto Quit;
819 }
820
821 /* Convert received data to unicode string */
822 Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset);
823 PnpRegSzToString(Buffer, kvInfo->DataLength, &DeviceString.Length);
824 DeviceString.MaximumLength = DeviceString.Length;
825 DeviceString.Buffer = Buffer;
826
827 /*
828 * Separate symbolic link into 4 parts:
829 * 1) prefix string (\??\ for kernel mode or \\?\ for user mode),
830 * 2) munged path string (like ##?#ACPI#PNP0501#1#{GUID}),
831 * 3) GUID string (the current GUID),
832 * 4) reference string (goes after GUID, starts with '\').
833 *
834 * We need only reference string.
835 */
837 NULL,
838 NULL,
839 NULL,
841 &ReferenceStringPresent,
842 NULL);
843 if (!NT_SUCCESS(Status))
844 {
845 DPRINT1("Failed to separate symbolic link %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
846 goto Quit;
847 }
848
849 DPRINT("Device string is '%wZ'\n", &DeviceString);
850
851 /* Does symbolic link have kernel mode "\??\" or user mode "\\?\" prefix format? */
852 UserModePrefixFormat = RtlPrefixUnicodeString(&UserModePrefix, SymbolicLinkName, FALSE);
853
854 /* Build up new symbolic link with alias GUID */
855 Status = IopBuildSymbolicLink(&DeviceString,
856 &AliasGuidString,
857 ReferenceStringPresent ? &ReferenceString : NULL,
858 UserModePrefixFormat,
859 &AliasSymbolicLink);
860 if (!NT_SUCCESS(Status))
861 {
862 DPRINT1("Failed to build alias symbolic link, Status 0x%08lx\n", Status);
863 goto Quit;
864 }
865
866 /* Make sure that alias symbolic link key exists in registry */
867 Status = OpenRegistryHandlesFromSymbolicLink(&AliasSymbolicLink,
868 KEY_READ,
869 NULL,
870 NULL,
871 &AliasInstanceKey);
872 if (!NT_SUCCESS(Status))
873 {
874 DPRINT1("Failed to open alias symbolic link key, Status 0x%08lx\n", Status);
875 goto Quit;
876 }
877 ZwClose(AliasInstanceKey);
878
879 /* We're done */
880 DPRINT("IoGetDeviceInterfaceAlias(): alias symbolic link %wZ\n", &AliasSymbolicLink);
881 *AliasSymbolicLinkName = AliasSymbolicLink;
883
884Quit:
885 if (!NT_SUCCESS(Status))
886 {
887 if (AliasSymbolicLink.Buffer)
888 RtlFreeUnicodeString(&AliasSymbolicLink);
889 }
890
891 if (AliasGuidString.Buffer)
892 RtlFreeUnicodeString(&AliasGuidString);
893
894 return Status;
895}
896
897/*++
898 * @name IoGetDeviceInterfaces
899 * @implemented
900 *
901 * Returns a list of device interfaces of a particular device interface class.
902 * Documented in WDK
903 *
904 * @param InterfaceClassGuid
905 * Points to a class GUID specifying the device interface class
906 *
907 * @param PhysicalDeviceObject
908 * Points to an optional PDO that narrows the search to only the
909 * device interfaces of the device represented by the PDO
910 *
911 * @param Flags
912 * Specifies flags that modify the search for device interfaces. The
913 * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
914 * returned symbolic links should contain also disabled device
915 * interfaces in addition to the enabled ones.
916 *
917 * @param SymbolicLinkList
918 * Points to a character pointer that is filled in on successful return
919 * with a list of unicode strings identifying the device interfaces
920 * that match the search criteria. The newly allocated buffer contains
921 * a list of symbolic link names. Each unicode string in the list is
922 * null-terminated; the end of the whole list is marked by an additional
923 * NULL. The caller is responsible for freeing the buffer (ExFreePool)
924 * when it is no longer needed.
925 * If no device interfaces match the search criteria, this routine
926 * returns STATUS_SUCCESS and the string contains a single NULL
927 * character.
928 *
929 * @return Usual NTSTATUS
930 *
931 * @remarks None
932 *
933 *--*/
935NTAPI
938 IN ULONG Flags,
940{
943 HANDLE InterfaceKey = NULL;
944 HANDLE DeviceKey = NULL;
945 HANDLE ReferenceKey = NULL;
946 HANDLE ControlKey = NULL;
947 PKEY_BASIC_INFORMATION DeviceBi = NULL;
948 PKEY_BASIC_INFORMATION ReferenceBi = NULL;
951 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
952 PUNICODE_STRING InstanceDevicePath = NULL;
955 BOOLEAN FoundRightPDO = FALSE;
956 ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
957 UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
959
960 PAGED_CODE();
961
963 {
964 /* Parameters must pass three border of checks */
965 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
966
967 /* 1st level: Presence of a Device Node */
968 if (DeviceObjectExtension->DeviceNode == NULL)
969 {
970 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
972 }
973
974 /* 2nd level: Presence of an non-zero length InstancePath */
975 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
976 {
977 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
979 }
980
981 InstanceDevicePath = &DeviceObjectExtension->DeviceNode->InstancePath;
982 }
983
984
986 if (!NT_SUCCESS(Status))
987 {
988 DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status);
989 goto cleanup;
990 }
991
992 /* Enumerate subkeys (i.e. the different device objects) */
993 while (TRUE)
994 {
995 Status = ZwEnumerateKey(
996 InterfaceKey,
997 i,
999 NULL,
1000 0,
1001 &Size);
1003 {
1004 break;
1005 }
1007 {
1008 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1009 goto cleanup;
1010 }
1011
1012 DeviceBi = ExAllocatePool(PagedPool, Size);
1013 if (!DeviceBi)
1014 {
1015 DPRINT("ExAllocatePool() failed\n");
1017 goto cleanup;
1018 }
1019 Status = ZwEnumerateKey(
1020 InterfaceKey,
1021 i++,
1023 DeviceBi,
1024 Size,
1025 &Size);
1026 if (!NT_SUCCESS(Status))
1027 {
1028 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1029 goto cleanup;
1030 }
1031
1032 /* Open device key */
1033 KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength;
1034 KeyName.Buffer = DeviceBi->Name;
1037 &KeyName,
1039 InterfaceKey,
1040 NULL);
1041 Status = ZwOpenKey(
1042 &DeviceKey,
1045 if (!NT_SUCCESS(Status))
1046 {
1047 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1048 goto cleanup;
1049 }
1050
1052 {
1053 /* Check if we are on the right physical device object,
1054 * by reading the DeviceInstance string
1055 */
1056 RtlInitUnicodeString(&KeyName, L"DeviceInstance");
1057 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength);
1059 {
1060 ActualLength = NeededLength;
1061 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1062 if (!PartialInfo)
1063 {
1065 goto cleanup;
1066 }
1067
1068 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength);
1069 if (!NT_SUCCESS(Status))
1070 {
1071 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1072 ExFreePool(PartialInfo);
1073 goto cleanup;
1074 }
1075 if (PartialInfo->DataLength == InstanceDevicePath->Length)
1076 {
1077 if (RtlCompareMemory(PartialInfo->Data, InstanceDevicePath->Buffer, InstanceDevicePath->Length) == InstanceDevicePath->Length)
1078 {
1079 /* found right pdo */
1080 FoundRightPDO = TRUE;
1081 }
1082 }
1083 ExFreePool(PartialInfo);
1084 PartialInfo = NULL;
1085 if (!FoundRightPDO)
1086 {
1087 /* not yet found */
1088 continue;
1089 }
1090 }
1091 else
1092 {
1093 /* error */
1094 break;
1095 }
1096 }
1097
1098 /* Enumerate subkeys (ie the different reference strings) */
1099 j = 0;
1100 while (TRUE)
1101 {
1102 Status = ZwEnumerateKey(
1103 DeviceKey,
1104 j,
1106 NULL,
1107 0,
1108 &Size);
1110 {
1111 break;
1112 }
1114 {
1115 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1116 goto cleanup;
1117 }
1118
1119 ReferenceBi = ExAllocatePool(PagedPool, Size);
1120 if (!ReferenceBi)
1121 {
1122 DPRINT("ExAllocatePool() failed\n");
1124 goto cleanup;
1125 }
1126 Status = ZwEnumerateKey(
1127 DeviceKey,
1128 j++,
1130 ReferenceBi,
1131 Size,
1132 &Size);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1136 goto cleanup;
1137 }
1138
1139 KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength;
1140 KeyName.Buffer = ReferenceBi->Name;
1142 {
1143 /* Skip Control subkey */
1144 goto NextReferenceString;
1145 }
1146
1147 /* Open reference key */
1150 &KeyName,
1152 DeviceKey,
1153 NULL);
1154 Status = ZwOpenKey(
1155 &ReferenceKey,
1158 if (!NT_SUCCESS(Status))
1159 {
1160 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1161 goto cleanup;
1162 }
1163
1165 {
1166 /* We have to check if the interface is enabled, by
1167 * reading the Linked value in the Control subkey
1168 */
1171 &Control,
1173 ReferenceKey,
1174 NULL);
1175 Status = ZwOpenKey(
1176 &ControlKey,
1180 {
1181 /* That's OK. The key doesn't exist (yet) because
1182 * the interface is not activated.
1183 */
1184 goto NextReferenceString;
1185 }
1186 else if (!NT_SUCCESS(Status))
1187 {
1188 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
1189 goto cleanup;
1190 }
1191
1192 RtlInitUnicodeString(&KeyName, L"Linked");
1193 Status = ZwQueryValueKey(ControlKey,
1194 &KeyName,
1196 NULL,
1197 0,
1198 &NeededLength);
1200 {
1201 ActualLength = NeededLength;
1202 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1203 if (!PartialInfo)
1204 {
1206 goto cleanup;
1207 }
1208
1209 Status = ZwQueryValueKey(ControlKey,
1210 &KeyName,
1212 PartialInfo,
1213 ActualLength,
1214 &NeededLength);
1215 if (!NT_SUCCESS(Status))
1216 {
1217 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1218 ExFreePool(PartialInfo);
1219 goto cleanup;
1220 }
1221
1222 if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
1223 {
1224 DPRINT1("Bad registry read\n");
1225 ExFreePool(PartialInfo);
1226 goto cleanup;
1227 }
1228
1229 RtlCopyMemory(&LinkedValue,
1230 PartialInfo->Data,
1231 PartialInfo->DataLength);
1232
1233 ExFreePool(PartialInfo);
1234 if (LinkedValue == 0)
1235 {
1236 /* This interface isn't active */
1237 goto NextReferenceString;
1238 }
1239 }
1240 else
1241 {
1242 DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
1243 goto cleanup;
1244 }
1245 }
1246
1247 /* Read the SymbolicLink string and add it into SymbolicLinkList */
1248 Status = ZwQueryValueKey(
1249 ReferenceKey,
1250 &SymbolicLink,
1252 NULL,
1253 0,
1254 &Size);
1256 {
1257 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1258 goto cleanup;
1259 }
1261 if (!bip)
1262 {
1263 DPRINT("ExAllocatePool() failed\n");
1265 goto cleanup;
1266 }
1267 Status = ZwQueryValueKey(
1268 ReferenceKey,
1269 &SymbolicLink,
1271 bip,
1272 Size,
1273 &Size);
1274 if (!NT_SUCCESS(Status))
1275 {
1276 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1277 goto cleanup;
1278 }
1279 else if (bip->Type != REG_SZ)
1280 {
1281 DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ);
1283 goto cleanup;
1284 }
1285 else if (bip->DataLength < 5 * sizeof(WCHAR))
1286 {
1287 DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR));
1289 goto cleanup;
1290 }
1291 KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength;
1292 KeyName.Buffer = (PWSTR)bip->Data;
1293
1294 /* Fixup the prefix (from "\\?\") */
1295 RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
1296
1297 /* Add new symbolic link to symbolic link list */
1298 if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength)
1299 {
1300 PWSTR NewBuffer;
1301 ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength,
1302 (USHORT)(ReturnBuffer.Length +
1303 KeyName.Length +
1304 2 * sizeof(WCHAR)));
1305 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1306 if (!NewBuffer)
1307 {
1308 DPRINT("ExAllocatePool() failed\n");
1310 goto cleanup;
1311 }
1312 if (ReturnBuffer.Buffer)
1313 {
1314 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1315 ExFreePool(ReturnBuffer.Buffer);
1316 }
1317 ReturnBuffer.Buffer = NewBuffer;
1318 }
1319 DPRINT("Adding symbolic link %wZ\n", &KeyName);
1321 if (!NT_SUCCESS(Status))
1322 {
1323 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
1324 goto cleanup;
1325 }
1326 /* RtlAppendUnicodeStringToString added a NULL at the end of the
1327 * destination string, but didn't increase the Length field.
1328 * Do it for it.
1329 */
1330 ReturnBuffer.Length += sizeof(WCHAR);
1331
1332NextReferenceString:
1333 ExFreePool(ReferenceBi);
1334 ReferenceBi = NULL;
1335 if (bip)
1336 ExFreePool(bip);
1337 bip = NULL;
1338 if (ReferenceKey != NULL)
1339 {
1340 ZwClose(ReferenceKey);
1341 ReferenceKey = NULL;
1342 }
1343 if (ControlKey != NULL)
1344 {
1345 ZwClose(ControlKey);
1346 ControlKey = NULL;
1347 }
1348 }
1349 if (FoundRightPDO)
1350 {
1351 /* No need to go further, as we already have found what we searched */
1352 break;
1353 }
1354
1355 ExFreePool(DeviceBi);
1356 DeviceBi = NULL;
1357 ZwClose(DeviceKey);
1358 DeviceKey = NULL;
1359 }
1360
1361 /* Add final NULL to ReturnBuffer */
1362 ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength);
1363 if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength)
1364 {
1365 PWSTR NewBuffer;
1366 ReturnBuffer.MaximumLength += sizeof(WCHAR);
1367 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1368 if (!NewBuffer)
1369 {
1370 DPRINT("ExAllocatePool() failed\n");
1372 goto cleanup;
1373 }
1374 if (ReturnBuffer.Buffer)
1375 {
1376 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1377 ExFreePool(ReturnBuffer.Buffer);
1378 }
1379 ReturnBuffer.Buffer = NewBuffer;
1380 }
1381 ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1382 *SymbolicLinkList = ReturnBuffer.Buffer;
1384
1385cleanup:
1386 if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer)
1387 ExFreePool(ReturnBuffer.Buffer);
1388 if (InterfaceKey != NULL)
1389 ZwClose(InterfaceKey);
1390 if (DeviceKey != NULL)
1391 ZwClose(DeviceKey);
1392 if (ReferenceKey != NULL)
1393 ZwClose(ReferenceKey);
1394 if (ControlKey != NULL)
1395 ZwClose(ControlKey);
1396 if (DeviceBi)
1397 ExFreePool(DeviceBi);
1398 if (ReferenceBi)
1399 ExFreePool(ReferenceBi);
1400 if (bip)
1401 ExFreePool(bip);
1402 return Status;
1403}
1404
1405/*++
1406 * @name IoRegisterDeviceInterface
1407 * @implemented
1408 *
1409 * Registers a device interface class, if it has not been previously registered,
1410 * and creates a new instance of the interface class, which a driver can
1411 * subsequently enable for use by applications or other system components.
1412 * Documented in WDK.
1413 *
1414 * @param PhysicalDeviceObject
1415 * Points to an optional PDO that narrows the search to only the
1416 * device interfaces of the device represented by the PDO
1417 *
1418 * @param InterfaceClassGuid
1419 * Points to a class GUID specifying the device interface class
1420 *
1421 * @param ReferenceString
1422 * Optional parameter, pointing to a unicode string. For a full
1423 * description of this rather rarely used param (usually drivers
1424 * pass NULL here) see WDK
1425 *
1426 * @param SymbolicLinkName
1427 * Pointer to the resulting unicode string
1428 *
1429 * @return Usual NTSTATUS
1430 *
1431 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
1432 * system thread
1433 *
1434 *--*/
1436NTAPI
1441{
1442 PUNICODE_STRING InstancePath;
1445 UNICODE_STRING InterfaceKeyName;
1446 UNICODE_STRING BaseKeyName;
1447 UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))];
1448 POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer;
1451 HANDLE ClassKey;
1452 HANDLE InterfaceKey;
1453 HANDLE SubKey;
1454 ULONG StartIndex;
1456 ULONG i;
1457 NTSTATUS Status, SymLinkStatus;
1458 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
1459
1461
1462 DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n",
1464
1465 /* Parameters must pass three border of checks */
1466 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
1467
1468 /* 1st level: Presence of a Device Node */
1469 if (DeviceObjectExtension->DeviceNode == NULL)
1470 {
1471 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
1473 }
1474
1475 /* 2nd level: Presence of an non-zero length InstancePath */
1476 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
1477 {
1478 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
1480 }
1481
1482 /* 3rd level: Optional, based on WDK documentation */
1483 if (ReferenceString != NULL)
1484 {
1485 /* Reference string must not contain path-separator symbols */
1486 for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++)
1487 {
1488 if ((ReferenceString->Buffer[i] == '\\') ||
1489 (ReferenceString->Buffer[i] == '/'))
1491 }
1492 }
1493
1495 if (!NT_SUCCESS(Status))
1496 {
1497 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
1498 return Status;
1499 }
1500
1501 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
1504 PdoNameInfo,
1505 sizeof(PdoNameInfoBuffer),
1506 &i);
1507 if (!NT_SUCCESS(Status))
1508 {
1509 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status);
1510 return Status;
1511 }
1512 ASSERT(PdoNameInfo->Name.Length);
1513
1514 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1515 ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode);
1516 InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath;
1517 BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR);
1518 BaseKeyName.MaximumLength = BaseKeyName.Length
1519 + GuidString.Length;
1520 BaseKeyName.Buffer = ExAllocatePool(
1521 PagedPool,
1522 BaseKeyName.MaximumLength);
1523 if (!BaseKeyName.Buffer)
1524 {
1525 DPRINT("ExAllocatePool() failed\n");
1527 }
1528 wcscpy(BaseKeyName.Buffer, BaseKeyString);
1530
1531 /* Create BaseKeyName key in registry */
1534 &BaseKeyName,
1536 NULL, /* RootDirectory */
1537 NULL); /* SecurityDescriptor */
1538
1539 Status = ZwCreateKey(
1540 &ClassKey,
1541 KEY_WRITE,
1543 0, /* TileIndex */
1544 NULL, /* Class */
1546 NULL); /* Disposition */
1547
1548 if (!NT_SUCCESS(Status))
1549 {
1550 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1551 ExFreePool(BaseKeyName.Buffer);
1552 return Status;
1553 }
1554
1555 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
1556 InterfaceKeyName.Length = 0;
1557 InterfaceKeyName.MaximumLength =
1558 4 * sizeof(WCHAR) + /* 4 = size of ##?# */
1559 InstancePath->Length +
1560 sizeof(WCHAR) + /* 1 = size of # */
1561 GuidString.Length;
1562 InterfaceKeyName.Buffer = ExAllocatePool(
1563 PagedPool,
1564 InterfaceKeyName.MaximumLength);
1565 if (!InterfaceKeyName.Buffer)
1566 {
1567 DPRINT("ExAllocatePool() failed\n");
1569 }
1570
1571 RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#");
1572 StartIndex = InterfaceKeyName.Length / sizeof(WCHAR);
1573 RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath);
1574 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1575 {
1576 if (InterfaceKeyName.Buffer[StartIndex + i] == '\\')
1577 InterfaceKeyName.Buffer[StartIndex + i] = '#';
1578 }
1579 RtlAppendUnicodeToString(&InterfaceKeyName, L"#");
1580 RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString);
1581
1582 /* Create the interface key in registry */
1585 &InterfaceKeyName,
1587 ClassKey,
1588 NULL); /* SecurityDescriptor */
1589
1590 Status = ZwCreateKey(
1591 &InterfaceKey,
1592 KEY_WRITE,
1594 0, /* TileIndex */
1595 NULL, /* Class */
1597 NULL); /* Disposition */
1598
1599 if (!NT_SUCCESS(Status))
1600 {
1601 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1602 ZwClose(ClassKey);
1603 ExFreePool(BaseKeyName.Buffer);
1604 return Status;
1605 }
1606
1607 /* Write DeviceInstance entry. Value is InstancePath */
1608 Status = ZwSetValueKey(
1609 InterfaceKey,
1611 0, /* TileIndex */
1612 REG_SZ,
1613 InstancePath->Buffer,
1614 InstancePath->Length);
1615 if (!NT_SUCCESS(Status))
1616 {
1617 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1618 ZwClose(InterfaceKey);
1619 ZwClose(ClassKey);
1620 ExFreePool(InterfaceKeyName.Buffer);
1621 ExFreePool(BaseKeyName.Buffer);
1622 return Status;
1623 }
1624
1625 /* Create subkey. Name is #ReferenceString */
1626 SubKeyName.Length = 0;
1627 SubKeyName.MaximumLength = sizeof(WCHAR);
1628 if (ReferenceString && ReferenceString->Length)
1629 SubKeyName.MaximumLength += ReferenceString->Length;
1630 SubKeyName.Buffer = ExAllocatePool(
1631 PagedPool,
1632 SubKeyName.MaximumLength);
1633 if (!SubKeyName.Buffer)
1634 {
1635 DPRINT("ExAllocatePool() failed\n");
1636 ZwClose(InterfaceKey);
1637 ZwClose(ClassKey);
1638 ExFreePool(InterfaceKeyName.Buffer);
1639 ExFreePool(BaseKeyName.Buffer);
1641 }
1643 if (ReferenceString && ReferenceString->Length)
1645
1646 /* Create SubKeyName key in registry */
1649 &SubKeyName,
1651 InterfaceKey, /* RootDirectory */
1652 NULL); /* SecurityDescriptor */
1653
1654 Status = ZwCreateKey(
1655 &SubKey,
1656 KEY_WRITE,
1658 0, /* TileIndex */
1659 NULL, /* Class */
1661 NULL); /* Disposition */
1662
1663 if (!NT_SUCCESS(Status))
1664 {
1665 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1666 ZwClose(InterfaceKey);
1667 ZwClose(ClassKey);
1668 ExFreePool(InterfaceKeyName.Buffer);
1669 ExFreePool(BaseKeyName.Buffer);
1670 return Status;
1671 }
1672
1673 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1674 SymbolicLinkName->Length = 0;
1675 SymbolicLinkName->MaximumLength = SymbolicLinkName->Length
1676 + 4 * sizeof(WCHAR) /* 4 = size of \??\ */
1677 + InstancePath->Length
1678 + sizeof(WCHAR) /* 1 = size of # */
1679 + GuidString.Length
1680 + sizeof(WCHAR); /* final NULL */
1681 if (ReferenceString && ReferenceString->Length)
1682 SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length;
1684 PagedPool,
1685 SymbolicLinkName->MaximumLength);
1686 if (!SymbolicLinkName->Buffer)
1687 {
1688 DPRINT("ExAllocatePool() failed\n");
1689 ZwClose(SubKey);
1690 ZwClose(InterfaceKey);
1691 ZwClose(ClassKey);
1692 ExFreePool(InterfaceKeyName.Buffer);
1693 ExFreePool(SubKeyName.Buffer);
1694 ExFreePool(BaseKeyName.Buffer);
1696 }
1698 StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1700 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1701 {
1702 if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1703 SymbolicLinkName->Buffer[StartIndex + i] = '#';
1704 }
1707 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1708
1709 /* Create symbolic link */
1710 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name);
1711 SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1712
1713 /* If the symbolic link already exists, return an informational success status */
1714 if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION)
1715 {
1716 /* HACK: Delete the existing symbolic link and update it to the new PDO name */
1718 IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1719 SymLinkStatus = STATUS_OBJECT_NAME_EXISTS;
1720 }
1721
1722 if (!NT_SUCCESS(SymLinkStatus))
1723 {
1724 DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus);
1725 ZwClose(SubKey);
1726 ZwClose(InterfaceKey);
1727 ZwClose(ClassKey);
1728 ExFreePool(SubKeyName.Buffer);
1729 ExFreePool(InterfaceKeyName.Buffer);
1730 ExFreePool(BaseKeyName.Buffer);
1732 return SymLinkStatus;
1733 }
1734
1735 if (ReferenceString && ReferenceString->Length)
1736 {
1739 }
1740 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1741
1742 /* Write symbolic link name in registry */
1743 SymbolicLinkName->Buffer[1] = '\\';
1744 Status = ZwSetValueKey(
1745 SubKey,
1746 &SymbolicLink,
1747 0, /* TileIndex */
1748 REG_SZ,
1749 SymbolicLinkName->Buffer,
1750 SymbolicLinkName->Length);
1751 if (!NT_SUCCESS(Status))
1752 {
1753 DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1755 }
1756 else
1757 {
1758 SymbolicLinkName->Buffer[1] = '?';
1759 }
1760
1761 ZwClose(SubKey);
1762 ZwClose(InterfaceKey);
1763 ZwClose(ClassKey);
1764 ExFreePool(SubKeyName.Buffer);
1765 ExFreePool(InterfaceKeyName.Buffer);
1766 ExFreePool(BaseKeyName.Buffer);
1767
1768 return NT_SUCCESS(Status) ? SymLinkStatus : Status;
1769}
1770
1771/*++
1772 * @name IoSetDeviceInterfaceState
1773 * @implemented
1774 *
1775 * Enables or disables an instance of a previously registered device
1776 * interface class.
1777 * Documented in WDK.
1778 *
1779 * @param SymbolicLinkName
1780 * Pointer to the string identifying instance to enable or disable
1781 *
1782 * @param Enable
1783 * TRUE = enable, FALSE = disable
1784 *
1785 * @return Usual NTSTATUS
1786 *
1787 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
1788 * system thread
1789 *
1790 *--*/
1792NTAPI
1795{
1800 HANDLE InstanceHandle, ControlHandle;
1803 ULONG LinkedValue, Index;
1804 GUID DeviceGuid;
1805 UNICODE_STRING DosDevicesPrefix1 = RTL_CONSTANT_STRING(L"\\??\\");
1806 UNICODE_STRING DosDevicesPrefix2 = RTL_CONSTANT_STRING(L"\\\\?\\");
1807 UNICODE_STRING LinkNameNoPrefix;
1808 USHORT i;
1809 USHORT ReferenceStringOffset;
1810
1811 if (SymbolicLinkName == NULL)
1812 {
1814 }
1815
1816 DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable);
1817
1818 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1819 /* Make sure it starts with the expected prefix */
1820 if (!RtlPrefixUnicodeString(&DosDevicesPrefix1, SymbolicLinkName, FALSE) &&
1821 !RtlPrefixUnicodeString(&DosDevicesPrefix2, SymbolicLinkName, FALSE))
1822 {
1823 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1825 }
1826
1827 /* Make a version without the prefix for further processing */
1828 ASSERT(DosDevicesPrefix1.Length == DosDevicesPrefix2.Length);
1829 ASSERT(SymbolicLinkName->Length >= DosDevicesPrefix1.Length);
1830 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + DosDevicesPrefix1.Length / sizeof(WCHAR);
1831 LinkNameNoPrefix.Length = SymbolicLinkName->Length - DosDevicesPrefix1.Length;
1832 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
1833
1834 /* Find the reference string, if any */
1835 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
1836 {
1837 if (LinkNameNoPrefix.Buffer[i] == L'\\')
1838 {
1839 break;
1840 }
1841 }
1842 ReferenceStringOffset = i * sizeof(WCHAR);
1843
1844 /* The GUID is before the reference string or at the end */
1845 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
1846 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
1847 {
1848 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1850 }
1851
1852 GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1854 GuidString.MaximumLength = GuidString.Length;
1855 Status = RtlGUIDFromString(&GuidString, &DeviceGuid);
1856 if (!NT_SUCCESS(Status))
1857 {
1858 DPRINT1("RtlGUIDFromString() invalid GUID '%wZ' in link name '%wZ'\n", &GuidString, SymbolicLinkName);
1859 return Status;
1860 }
1861
1862 /* Open registry keys */
1865 NULL,
1866 NULL,
1867 &InstanceHandle);
1868 if (!NT_SUCCESS(Status))
1869 return Status;
1870
1871 RtlInitUnicodeString(&KeyName, L"Control");
1873 &KeyName,
1875 InstanceHandle,
1876 NULL);
1877 Status = ZwCreateKey(&ControlHandle,
1880 0,
1881 NULL,
1883 NULL);
1884 ZwClose(InstanceHandle);
1885 if (!NT_SUCCESS(Status))
1886 {
1887 DPRINT1("Failed to create the Control subkey\n");
1888 return Status;
1889 }
1890
1891 LinkedValue = (Enable ? 1 : 0);
1892
1893 RtlInitUnicodeString(&KeyName, L"Linked");
1894 Status = ZwSetValueKey(ControlHandle,
1895 &KeyName,
1896 0,
1897 REG_DWORD,
1898 &LinkedValue,
1899 sizeof(ULONG));
1900 ZwClose(ControlHandle);
1901 if (!NT_SUCCESS(Status))
1902 {
1903 DPRINT1("Failed to write the Linked value\n");
1904 return Status;
1905 }
1906
1907 ASSERT(GuidString.Buffer >= LinkNameNoPrefix.Buffer + 1);
1908 DeviceInstance.Length = (GuidString.Buffer - LinkNameNoPrefix.Buffer - 1) * sizeof(WCHAR);
1909 if (DeviceInstance.Length == 0)
1910 {
1911 DPRINT1("No device instance in link name '%wZ'\n", SymbolicLinkName);
1913 }
1914 DeviceInstance.MaximumLength = DeviceInstance.Length;
1916 DeviceInstance.MaximumLength,
1917 TAG_IO);
1918 if (DeviceInstance.Buffer == NULL)
1919 {
1920 /* no memory */
1922 }
1923
1925 LinkNameNoPrefix.Buffer,
1926 DeviceInstance.Length);
1927
1928 for (Index = 0; Index < DeviceInstance.Length / sizeof(WCHAR); Index++)
1929 {
1930 if (DeviceInstance.Buffer[Index] == L'#')
1931 {
1932 DeviceInstance.Buffer[Index] = L'\\';
1933 }
1934 }
1935
1937
1939 {
1940 DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1943 }
1944
1946
1948
1951
1953 DPRINT("Status %x\n", Status);
1954 return STATUS_SUCCESS;
1955}
1956
1957/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
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
wcscpy
#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
static void cleanup(void)
Definition: main.c:1335
static const WCHAR SymbolicLink[]
Definition: interface.c:31
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#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: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
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
#define C_ASSERT(e)
Definition: intsafe.h:73
#define REG_SZ
Definition: layer.c:22
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:106
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
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:1131
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
struct _OBJECT_NAME_INFORMATION * POBJECT_NAME_INFORMATION
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
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
#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)
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:206
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:652
#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
static PCWSTR BaseKeyString
Definition: deviface.c:30
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
Definition: deviface.c:595
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:936
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:1437
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1793
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:758
#define GUID_STRING_BYTES
Definition: deviface.c:22
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
NTSTRSAFEVAPI RtlUnicodeStringPrintf(_In_ PUNICODE_STRING DestinationString, _In_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:3241
#define L(x)
Definition: ntvdm.h:50
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
unsigned short USHORT
Definition: pedump.c:61
#define REGSTR_PATH_DEVICE_CLASSES
Definition: regstr.h:481
#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:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct _DEVICE_NODE * DeviceNode
Definition: iotypes.h:1090
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define max(a, b)
Definition: svc.c:63
#define TAG_IO
Definition: tag.h:79
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
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:3630
_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
_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 * 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:2856
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180