ReactOS 0.4.16-dev-329-g9223134
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 */
11
12/* INCLUDES ******************************************************************/
13
14#include <ntoskrnl.h>
15
16#define NDEBUG
17#include <debug.h>
18
19/* FIXME: This should be somewhere global instead of having 20 different versions */
20#define GUID_STRING_CHARS 38
21#define GUID_STRING_BYTES (GUID_STRING_CHARS * sizeof(WCHAR))
22C_ASSERT(sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}") == GUID_STRING_BYTES + sizeof(UNICODE_NULL));
23
24/* FUNCTIONS *****************************************************************/
25
28
29static PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
30
31static
35 IN OPTIONAL PHANDLE GuidKey,
36 IN OPTIONAL PHANDLE DeviceKey,
37 IN OPTIONAL PHANDLE InstanceKey)
38{
40 UNICODE_STRING BaseKeyU;
42 PWCHAR StartPosition, EndPosition;
43 HANDLE ClassesKey;
44 PHANDLE GuidKeyRealP, DeviceKeyRealP, InstanceKeyRealP;
45 HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal;
47
48 SubKeyName.Buffer = NULL;
49
50 if (GuidKey != NULL)
51 GuidKeyRealP = GuidKey;
52 else
53 GuidKeyRealP = &GuidKeyReal;
54
55 if (DeviceKey != NULL)
56 DeviceKeyRealP = DeviceKey;
57 else
58 DeviceKeyRealP = &DeviceKeyReal;
59
60 if (InstanceKey != NULL)
61 InstanceKeyRealP = InstanceKey;
62 else
63 InstanceKeyRealP = &InstanceKeyReal;
64
65 *GuidKeyRealP = NULL;
66 *DeviceKeyRealP = NULL;
67 *InstanceKeyRealP = NULL;
68
70
71 /* Open the DeviceClasses key */
73 &BaseKeyU,
75 NULL,
76 NULL);
77 Status = ZwOpenKey(&ClassesKey,
80 if (!NT_SUCCESS(Status))
81 {
82 DPRINT1("Failed to open %wZ\n", &BaseKeyU);
83 goto cleanup;
84 }
85
87 EndPosition = wcschr(SymbolicLinkName->Buffer, L'}');
88 if (!StartPosition || !EndPosition || StartPosition > EndPosition)
89 {
90 DPRINT1("Bad symbolic link: %wZ\n", SymbolicLinkName);
92 }
94 GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition);
95
99 ClassesKey,
100 NULL);
101 Status = ZwCreateKey(GuidKeyRealP,
104 0,
105 NULL,
107 NULL);
108 ZwClose(ClassesKey);
109 if (!NT_SUCCESS(Status))
110 {
111 DPRINT1("Failed to open %wZ%wZ (%x)\n", &BaseKeyU, &GuidString, Status);
112 goto cleanup;
113 }
114
115 SubKeyName.MaximumLength = SymbolicLinkName->Length + sizeof(WCHAR);
116 SubKeyName.Length = 0;
117 SubKeyName.Buffer = ExAllocatePool(PagedPool, SubKeyName.MaximumLength);
118 if (!SubKeyName.Buffer)
119 {
121 goto cleanup;
122 }
123
126
127 SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
128
129 SubKeyName.Buffer[0] = L'#';
130 SubKeyName.Buffer[1] = L'#';
131 SubKeyName.Buffer[2] = L'?';
132 SubKeyName.Buffer[3] = L'#';
133
134 ReferenceString.Buffer = wcsrchr(SubKeyName.Buffer, '\\');
135 if (ReferenceString.Buffer != NULL)
136 {
137 ReferenceString.Buffer[0] = L'#';
138
139 SubKeyName.Length = (USHORT)((ULONG_PTR)(ReferenceString.Buffer) - (ULONG_PTR)SubKeyName.Buffer);
140 ReferenceString.Length = SymbolicLinkName->Length - SubKeyName.Length;
141 }
142 else
143 {
145 }
146
148 &SubKeyName,
150 *GuidKeyRealP,
151 NULL);
152 Status = ZwCreateKey(DeviceKeyRealP,
155 0,
156 NULL,
158 NULL);
159 if (!NT_SUCCESS(Status))
160 {
161 DPRINT1("Failed to open %wZ%wZ\\%wZ Status %x\n", &BaseKeyU, &GuidString, &SubKeyName, Status);
162 goto cleanup;
163 }
164
168 *DeviceKeyRealP,
169 NULL);
170 Status = ZwCreateKey(InstanceKeyRealP,
173 0,
174 NULL,
176 NULL);
177 if (!NT_SUCCESS(Status))
178 {
179 DPRINT1("Failed to open %wZ%wZ\\%wZ%\\%wZ (%x)\n", &BaseKeyU, &GuidString, &SubKeyName, &ReferenceString, Status);
180 goto cleanup;
181 }
182
184
185cleanup:
186 if (SubKeyName.Buffer != NULL)
187 ExFreePool(SubKeyName.Buffer);
188
189 if (NT_SUCCESS(Status))
190 {
191 if (!GuidKey)
192 ZwClose(*GuidKeyRealP);
193
194 if (!DeviceKey)
195 ZwClose(*DeviceKeyRealP);
196
197 if (!InstanceKey)
198 ZwClose(*InstanceKeyRealP);
199 }
200 else
201 {
202 if (*GuidKeyRealP != NULL)
203 ZwClose(*GuidKeyRealP);
204
205 if (*DeviceKeyRealP != NULL)
206 ZwClose(*DeviceKeyRealP);
207
208 if (*InstanceKeyRealP != NULL)
209 ZwClose(*InstanceKeyRealP);
210 }
211
212 return Status;
213}
214
215/*++
216 * @name IoOpenDeviceInterfaceRegistryKey
217 * @unimplemented
218 *
219 * Provides a handle to the device's interface instance registry key.
220 * Documented in WDK.
221 *
222 * @param SymbolicLinkName
223 * Pointer to a string which identifies the device interface instance
224 *
225 * @param DesiredAccess
226 * Desired ACCESS_MASK used to access the key (like KEY_READ,
227 * KEY_WRITE, etc)
228 *
229 * @param DeviceInterfaceKey
230 * If a call has been succesfull, a handle to the registry key
231 * will be stored there
232 *
233 * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS
234 * otherwise (see WDK for details)
235 *
236 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread
237 *
238 *--*/
240NTAPI
244{
245 HANDLE InstanceKey, DeviceParametersKey;
248 UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
249
252 NULL,
253 NULL,
254 &InstanceKey);
255 if (!NT_SUCCESS(Status))
256 return Status;
257
259 &DeviceParametersU,
261 InstanceKey,
262 NULL);
263 Status = ZwCreateKey(&DeviceParametersKey,
266 0,
267 NULL,
269 NULL);
270 ZwClose(InstanceKey);
271
272 if (NT_SUCCESS(Status))
273 *DeviceInterfaceKey = DeviceParametersKey;
274
275 return Status;
276}
277
278/*++
279 * @name IoGetDeviceInterfaceAlias
280 * @unimplemented
281 *
282 * Returns the alias device interface of the specified device interface
283 * instance, if the alias exists.
284 * Documented in WDK.
285 *
286 * @param SymbolicLinkName
287 * Pointer to a string which identifies the device interface instance
288 *
289 * @param AliasInterfaceClassGuid
290 * See WDK
291 *
292 * @param AliasSymbolicLinkName
293 * See WDK
294 *
295 * @return Three different NTSTATUS values in case of errors, and STATUS_SUCCESS
296 * otherwise (see WDK for details)
297 *
298 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread
299 *
300 *--*/
302NTAPI
305 OUT PUNICODE_STRING AliasSymbolicLinkName)
306{
308}
309
310/*++
311 * @name IopOpenInterfaceKey
312 *
313 * Returns the alias device interface of the specified device interface
314 *
315 * @param InterfaceClassGuid
316 * FILLME
317 *
318 * @param DesiredAccess
319 * FILLME
320 *
321 * @param pInterfaceKey
322 * FILLME
323 *
324 * @return Usual NTSTATUS
325 *
326 * @remarks None
327 *
328 *--*/
329static NTSTATUS
332 OUT HANDLE *pInterfaceKey)
333{
334 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\");
338 HANDLE InterfaceKey = NULL;
340
341 GuidString.Buffer = KeyName.Buffer = NULL;
342
344 if (!NT_SUCCESS(Status))
345 {
346 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
347 goto cleanup;
348 }
349
350 KeyName.Length = 0;
351 KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length;
352 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
353 if (!KeyName.Buffer)
354 {
355 DPRINT("ExAllocatePool() failed\n");
357 goto cleanup;
358 }
359
361 if (!NT_SUCCESS(Status))
362 {
363 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
364 goto cleanup;
365 }
367 if (!NT_SUCCESS(Status))
368 {
369 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
370 goto cleanup;
371 }
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
376 goto cleanup;
377 }
379 if (!NT_SUCCESS(Status))
380 {
381 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
382 goto cleanup;
383 }
384
387 &KeyName,
389 NULL,
390 NULL);
391 Status = ZwOpenKey(
392 &InterfaceKey,
395 if (!NT_SUCCESS(Status))
396 {
397 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
398 goto cleanup;
399 }
400
401 *pInterfaceKey = InterfaceKey;
403
404cleanup:
405 if (!NT_SUCCESS(Status))
406 {
407 if (InterfaceKey != NULL)
408 ZwClose(InterfaceKey);
409 }
412 return Status;
413}
414
415/*++
416 * @name IoGetDeviceInterfaces
417 * @implemented
418 *
419 * Returns a list of device interfaces of a particular device interface class.
420 * Documented in WDK
421 *
422 * @param InterfaceClassGuid
423 * Points to a class GUID specifying the device interface class
424 *
425 * @param PhysicalDeviceObject
426 * Points to an optional PDO that narrows the search to only the
427 * device interfaces of the device represented by the PDO
428 *
429 * @param Flags
430 * Specifies flags that modify the search for device interfaces. The
431 * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
432 * returned symbolic links should contain also disabled device
433 * interfaces in addition to the enabled ones.
434 *
435 * @param SymbolicLinkList
436 * Points to a character pointer that is filled in on successful return
437 * with a list of unicode strings identifying the device interfaces
438 * that match the search criteria. The newly allocated buffer contains
439 * a list of symbolic link names. Each unicode string in the list is
440 * null-terminated; the end of the whole list is marked by an additional
441 * NULL. The caller is responsible for freeing the buffer (ExFreePool)
442 * when it is no longer needed.
443 * If no device interfaces match the search criteria, this routine
444 * returns STATUS_SUCCESS and the string contains a single NULL
445 * character.
446 *
447 * @return Usual NTSTATUS
448 *
449 * @remarks None
450 *
451 *--*/
453NTAPI
456 IN ULONG Flags,
458{
461 HANDLE InterfaceKey = NULL;
462 HANDLE DeviceKey = NULL;
463 HANDLE ReferenceKey = NULL;
464 HANDLE ControlKey = NULL;
465 PKEY_BASIC_INFORMATION DeviceBi = NULL;
466 PKEY_BASIC_INFORMATION ReferenceBi = NULL;
469 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
470 PUNICODE_STRING InstanceDevicePath = NULL;
473 BOOLEAN FoundRightPDO = FALSE;
474 ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
475 UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
477
478 PAGED_CODE();
479
481 {
482 /* Parameters must pass three border of checks */
483 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
484
485 /* 1st level: Presence of a Device Node */
486 if (DeviceObjectExtension->DeviceNode == NULL)
487 {
488 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
490 }
491
492 /* 2nd level: Presence of an non-zero length InstancePath */
493 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
494 {
495 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
497 }
498
499 InstanceDevicePath = &DeviceObjectExtension->DeviceNode->InstancePath;
500 }
501
502
504 if (!NT_SUCCESS(Status))
505 {
506 DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status);
507 goto cleanup;
508 }
509
510 /* Enumerate subkeys (i.e. the different device objects) */
511 while (TRUE)
512 {
513 Status = ZwEnumerateKey(
514 InterfaceKey,
515 i,
517 NULL,
518 0,
519 &Size);
521 {
522 break;
523 }
525 {
526 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
527 goto cleanup;
528 }
529
530 DeviceBi = ExAllocatePool(PagedPool, Size);
531 if (!DeviceBi)
532 {
533 DPRINT("ExAllocatePool() failed\n");
535 goto cleanup;
536 }
537 Status = ZwEnumerateKey(
538 InterfaceKey,
539 i++,
541 DeviceBi,
542 Size,
543 &Size);
544 if (!NT_SUCCESS(Status))
545 {
546 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
547 goto cleanup;
548 }
549
550 /* Open device key */
551 KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength;
552 KeyName.Buffer = DeviceBi->Name;
555 &KeyName,
557 InterfaceKey,
558 NULL);
559 Status = ZwOpenKey(
560 &DeviceKey,
563 if (!NT_SUCCESS(Status))
564 {
565 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
566 goto cleanup;
567 }
568
570 {
571 /* Check if we are on the right physical device object,
572 * by reading the DeviceInstance string
573 */
574 RtlInitUnicodeString(&KeyName, L"DeviceInstance");
575 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength);
577 {
578 ActualLength = NeededLength;
579 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
580 if (!PartialInfo)
581 {
583 goto cleanup;
584 }
585
586 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength);
587 if (!NT_SUCCESS(Status))
588 {
589 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
590 ExFreePool(PartialInfo);
591 goto cleanup;
592 }
593 if (PartialInfo->DataLength == InstanceDevicePath->Length)
594 {
595 if (RtlCompareMemory(PartialInfo->Data, InstanceDevicePath->Buffer, InstanceDevicePath->Length) == InstanceDevicePath->Length)
596 {
597 /* found right pdo */
598 FoundRightPDO = TRUE;
599 }
600 }
601 ExFreePool(PartialInfo);
602 PartialInfo = NULL;
603 if (!FoundRightPDO)
604 {
605 /* not yet found */
606 continue;
607 }
608 }
609 else
610 {
611 /* error */
612 break;
613 }
614 }
615
616 /* Enumerate subkeys (ie the different reference strings) */
617 j = 0;
618 while (TRUE)
619 {
620 Status = ZwEnumerateKey(
621 DeviceKey,
622 j,
624 NULL,
625 0,
626 &Size);
628 {
629 break;
630 }
632 {
633 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
634 goto cleanup;
635 }
636
637 ReferenceBi = ExAllocatePool(PagedPool, Size);
638 if (!ReferenceBi)
639 {
640 DPRINT("ExAllocatePool() failed\n");
642 goto cleanup;
643 }
644 Status = ZwEnumerateKey(
645 DeviceKey,
646 j++,
648 ReferenceBi,
649 Size,
650 &Size);
651 if (!NT_SUCCESS(Status))
652 {
653 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
654 goto cleanup;
655 }
656
657 KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength;
658 KeyName.Buffer = ReferenceBi->Name;
660 {
661 /* Skip Control subkey */
662 goto NextReferenceString;
663 }
664
665 /* Open reference key */
668 &KeyName,
670 DeviceKey,
671 NULL);
672 Status = ZwOpenKey(
673 &ReferenceKey,
676 if (!NT_SUCCESS(Status))
677 {
678 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
679 goto cleanup;
680 }
681
683 {
684 /* We have to check if the interface is enabled, by
685 * reading the Linked value in the Control subkey
686 */
689 &Control,
691 ReferenceKey,
692 NULL);
693 Status = ZwOpenKey(
694 &ControlKey,
698 {
699 /* That's OK. The key doesn't exist (yet) because
700 * the interface is not activated.
701 */
702 goto NextReferenceString;
703 }
704 else if (!NT_SUCCESS(Status))
705 {
706 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
707 goto cleanup;
708 }
709
710 RtlInitUnicodeString(&KeyName, L"Linked");
711 Status = ZwQueryValueKey(ControlKey,
712 &KeyName,
714 NULL,
715 0,
716 &NeededLength);
718 {
719 ActualLength = NeededLength;
720 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
721 if (!PartialInfo)
722 {
724 goto cleanup;
725 }
726
727 Status = ZwQueryValueKey(ControlKey,
728 &KeyName,
730 PartialInfo,
731 ActualLength,
732 &NeededLength);
733 if (!NT_SUCCESS(Status))
734 {
735 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
736 ExFreePool(PartialInfo);
737 goto cleanup;
738 }
739
740 if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
741 {
742 DPRINT1("Bad registry read\n");
743 ExFreePool(PartialInfo);
744 goto cleanup;
745 }
746
747 RtlCopyMemory(&LinkedValue,
748 PartialInfo->Data,
749 PartialInfo->DataLength);
750
751 ExFreePool(PartialInfo);
752 if (LinkedValue == 0)
753 {
754 /* This interface isn't active */
755 goto NextReferenceString;
756 }
757 }
758 else
759 {
760 DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
761 goto cleanup;
762 }
763 }
764
765 /* Read the SymbolicLink string and add it into SymbolicLinkList */
766 Status = ZwQueryValueKey(
767 ReferenceKey,
770 NULL,
771 0,
772 &Size);
774 {
775 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
776 goto cleanup;
777 }
779 if (!bip)
780 {
781 DPRINT("ExAllocatePool() failed\n");
783 goto cleanup;
784 }
785 Status = ZwQueryValueKey(
786 ReferenceKey,
789 bip,
790 Size,
791 &Size);
792 if (!NT_SUCCESS(Status))
793 {
794 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
795 goto cleanup;
796 }
797 else if (bip->Type != REG_SZ)
798 {
799 DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ);
801 goto cleanup;
802 }
803 else if (bip->DataLength < 5 * sizeof(WCHAR))
804 {
805 DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR));
807 goto cleanup;
808 }
809 KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength;
810 KeyName.Buffer = (PWSTR)bip->Data;
811
812 /* Fixup the prefix (from "\\?\") */
813 RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
814
815 /* Add new symbolic link to symbolic link list */
816 if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength)
817 {
818 PWSTR NewBuffer;
819 ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength,
820 (USHORT)(ReturnBuffer.Length +
821 KeyName.Length +
822 2 * sizeof(WCHAR)));
823 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
824 if (!NewBuffer)
825 {
826 DPRINT("ExAllocatePool() failed\n");
828 goto cleanup;
829 }
830 if (ReturnBuffer.Buffer)
831 {
832 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
833 ExFreePool(ReturnBuffer.Buffer);
834 }
835 ReturnBuffer.Buffer = NewBuffer;
836 }
837 DPRINT("Adding symbolic link %wZ\n", &KeyName);
839 if (!NT_SUCCESS(Status))
840 {
841 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
842 goto cleanup;
843 }
844 /* RtlAppendUnicodeStringToString added a NULL at the end of the
845 * destination string, but didn't increase the Length field.
846 * Do it for it.
847 */
848 ReturnBuffer.Length += sizeof(WCHAR);
849
850NextReferenceString:
851 ExFreePool(ReferenceBi);
852 ReferenceBi = NULL;
853 if (bip)
854 ExFreePool(bip);
855 bip = NULL;
856 if (ReferenceKey != NULL)
857 {
858 ZwClose(ReferenceKey);
859 ReferenceKey = NULL;
860 }
861 if (ControlKey != NULL)
862 {
863 ZwClose(ControlKey);
864 ControlKey = NULL;
865 }
866 }
867 if (FoundRightPDO)
868 {
869 /* No need to go further, as we already have found what we searched */
870 break;
871 }
872
873 ExFreePool(DeviceBi);
874 DeviceBi = NULL;
875 ZwClose(DeviceKey);
876 DeviceKey = NULL;
877 }
878
879 /* Add final NULL to ReturnBuffer */
880 ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength);
881 if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength)
882 {
883 PWSTR NewBuffer;
884 ReturnBuffer.MaximumLength += sizeof(WCHAR);
885 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
886 if (!NewBuffer)
887 {
888 DPRINT("ExAllocatePool() failed\n");
890 goto cleanup;
891 }
892 if (ReturnBuffer.Buffer)
893 {
894 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
895 ExFreePool(ReturnBuffer.Buffer);
896 }
897 ReturnBuffer.Buffer = NewBuffer;
898 }
899 ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL;
900 *SymbolicLinkList = ReturnBuffer.Buffer;
902
903cleanup:
904 if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer)
905 ExFreePool(ReturnBuffer.Buffer);
906 if (InterfaceKey != NULL)
907 ZwClose(InterfaceKey);
908 if (DeviceKey != NULL)
909 ZwClose(DeviceKey);
910 if (ReferenceKey != NULL)
911 ZwClose(ReferenceKey);
912 if (ControlKey != NULL)
913 ZwClose(ControlKey);
914 if (DeviceBi)
915 ExFreePool(DeviceBi);
916 if (ReferenceBi)
917 ExFreePool(ReferenceBi);
918 if (bip)
919 ExFreePool(bip);
920 return Status;
921}
922
923/*++
924 * @name IoRegisterDeviceInterface
925 * @implemented
926 *
927 * Registers a device interface class, if it has not been previously registered,
928 * and creates a new instance of the interface class, which a driver can
929 * subsequently enable for use by applications or other system components.
930 * Documented in WDK.
931 *
932 * @param PhysicalDeviceObject
933 * Points to an optional PDO that narrows the search to only the
934 * device interfaces of the device represented by the PDO
935 *
936 * @param InterfaceClassGuid
937 * Points to a class GUID specifying the device interface class
938 *
939 * @param ReferenceString
940 * Optional parameter, pointing to a unicode string. For a full
941 * description of this rather rarely used param (usually drivers
942 * pass NULL here) see WDK
943 *
944 * @param SymbolicLinkName
945 * Pointer to the resulting unicode string
946 *
947 * @return Usual NTSTATUS
948 *
949 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
950 * system thread
951 *
952 *--*/
954NTAPI
959{
960 PUNICODE_STRING InstancePath;
963 UNICODE_STRING InterfaceKeyName;
964 UNICODE_STRING BaseKeyName;
965 UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))];
966 POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer;
969 HANDLE ClassKey;
970 HANDLE InterfaceKey;
971 HANDLE SubKey;
972 ULONG StartIndex;
974 ULONG i;
975 NTSTATUS Status, SymLinkStatus;
976 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
977
979
980 DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n",
982
983 /* Parameters must pass three border of checks */
984 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
985
986 /* 1st level: Presence of a Device Node */
987 if (DeviceObjectExtension->DeviceNode == NULL)
988 {
989 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
991 }
992
993 /* 2nd level: Presence of an non-zero length InstancePath */
994 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
995 {
996 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
998 }
999
1000 /* 3rd level: Optional, based on WDK documentation */
1001 if (ReferenceString != NULL)
1002 {
1003 /* Reference string must not contain path-separator symbols */
1004 for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++)
1005 {
1006 if ((ReferenceString->Buffer[i] == '\\') ||
1007 (ReferenceString->Buffer[i] == '/'))
1009 }
1010 }
1011
1013 if (!NT_SUCCESS(Status))
1014 {
1015 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
1016 return Status;
1017 }
1018
1019 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
1022 PdoNameInfo,
1023 sizeof(PdoNameInfoBuffer),
1024 &i);
1025 if (!NT_SUCCESS(Status))
1026 {
1027 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status);
1028 return Status;
1029 }
1030 ASSERT(PdoNameInfo->Name.Length);
1031
1032 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1033 ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode);
1034 InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath;
1035 BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR);
1036 BaseKeyName.MaximumLength = BaseKeyName.Length
1037 + GuidString.Length;
1038 BaseKeyName.Buffer = ExAllocatePool(
1039 PagedPool,
1040 BaseKeyName.MaximumLength);
1041 if (!BaseKeyName.Buffer)
1042 {
1043 DPRINT("ExAllocatePool() failed\n");
1045 }
1046 wcscpy(BaseKeyName.Buffer, BaseKeyString);
1048
1049 /* Create BaseKeyName key in registry */
1052 &BaseKeyName,
1054 NULL, /* RootDirectory */
1055 NULL); /* SecurityDescriptor */
1056
1057 Status = ZwCreateKey(
1058 &ClassKey,
1059 KEY_WRITE,
1061 0, /* TileIndex */
1062 NULL, /* Class */
1064 NULL); /* Disposition */
1065
1066 if (!NT_SUCCESS(Status))
1067 {
1068 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1069 ExFreePool(BaseKeyName.Buffer);
1070 return Status;
1071 }
1072
1073 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
1074 InterfaceKeyName.Length = 0;
1075 InterfaceKeyName.MaximumLength =
1076 4 * sizeof(WCHAR) + /* 4 = size of ##?# */
1077 InstancePath->Length +
1078 sizeof(WCHAR) + /* 1 = size of # */
1079 GuidString.Length;
1080 InterfaceKeyName.Buffer = ExAllocatePool(
1081 PagedPool,
1082 InterfaceKeyName.MaximumLength);
1083 if (!InterfaceKeyName.Buffer)
1084 {
1085 DPRINT("ExAllocatePool() failed\n");
1087 }
1088
1089 RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#");
1090 StartIndex = InterfaceKeyName.Length / sizeof(WCHAR);
1091 RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath);
1092 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1093 {
1094 if (InterfaceKeyName.Buffer[StartIndex + i] == '\\')
1095 InterfaceKeyName.Buffer[StartIndex + i] = '#';
1096 }
1097 RtlAppendUnicodeToString(&InterfaceKeyName, L"#");
1098 RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString);
1099
1100 /* Create the interface key in registry */
1103 &InterfaceKeyName,
1105 ClassKey,
1106 NULL); /* SecurityDescriptor */
1107
1108 Status = ZwCreateKey(
1109 &InterfaceKey,
1110 KEY_WRITE,
1112 0, /* TileIndex */
1113 NULL, /* Class */
1115 NULL); /* Disposition */
1116
1117 if (!NT_SUCCESS(Status))
1118 {
1119 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1120 ZwClose(ClassKey);
1121 ExFreePool(BaseKeyName.Buffer);
1122 return Status;
1123 }
1124
1125 /* Write DeviceInstance entry. Value is InstancePath */
1126 Status = ZwSetValueKey(
1127 InterfaceKey,
1129 0, /* TileIndex */
1130 REG_SZ,
1131 InstancePath->Buffer,
1132 InstancePath->Length);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1136 ZwClose(InterfaceKey);
1137 ZwClose(ClassKey);
1138 ExFreePool(InterfaceKeyName.Buffer);
1139 ExFreePool(BaseKeyName.Buffer);
1140 return Status;
1141 }
1142
1143 /* Create subkey. Name is #ReferenceString */
1144 SubKeyName.Length = 0;
1145 SubKeyName.MaximumLength = sizeof(WCHAR);
1146 if (ReferenceString && ReferenceString->Length)
1147 SubKeyName.MaximumLength += ReferenceString->Length;
1148 SubKeyName.Buffer = ExAllocatePool(
1149 PagedPool,
1150 SubKeyName.MaximumLength);
1151 if (!SubKeyName.Buffer)
1152 {
1153 DPRINT("ExAllocatePool() failed\n");
1154 ZwClose(InterfaceKey);
1155 ZwClose(ClassKey);
1156 ExFreePool(InterfaceKeyName.Buffer);
1157 ExFreePool(BaseKeyName.Buffer);
1159 }
1161 if (ReferenceString && ReferenceString->Length)
1163
1164 /* Create SubKeyName key in registry */
1167 &SubKeyName,
1169 InterfaceKey, /* RootDirectory */
1170 NULL); /* SecurityDescriptor */
1171
1172 Status = ZwCreateKey(
1173 &SubKey,
1174 KEY_WRITE,
1176 0, /* TileIndex */
1177 NULL, /* Class */
1179 NULL); /* Disposition */
1180
1181 if (!NT_SUCCESS(Status))
1182 {
1183 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1184 ZwClose(InterfaceKey);
1185 ZwClose(ClassKey);
1186 ExFreePool(InterfaceKeyName.Buffer);
1187 ExFreePool(BaseKeyName.Buffer);
1188 return Status;
1189 }
1190
1191 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1192 SymbolicLinkName->Length = 0;
1193 SymbolicLinkName->MaximumLength = SymbolicLinkName->Length
1194 + 4 * sizeof(WCHAR) /* 4 = size of \??\ */
1195 + InstancePath->Length
1196 + sizeof(WCHAR) /* 1 = size of # */
1197 + GuidString.Length
1198 + sizeof(WCHAR); /* final NULL */
1199 if (ReferenceString && ReferenceString->Length)
1200 SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length;
1202 PagedPool,
1203 SymbolicLinkName->MaximumLength);
1204 if (!SymbolicLinkName->Buffer)
1205 {
1206 DPRINT("ExAllocatePool() failed\n");
1207 ZwClose(SubKey);
1208 ZwClose(InterfaceKey);
1209 ZwClose(ClassKey);
1210 ExFreePool(InterfaceKeyName.Buffer);
1211 ExFreePool(SubKeyName.Buffer);
1212 ExFreePool(BaseKeyName.Buffer);
1214 }
1216 StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1218 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1219 {
1220 if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1221 SymbolicLinkName->Buffer[StartIndex + i] = '#';
1222 }
1225 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1226
1227 /* Create symbolic link */
1228 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name);
1229 SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1230
1231 /* If the symbolic link already exists, return an informational success status */
1232 if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION)
1233 {
1234 /* HACK: Delete the existing symbolic link and update it to the new PDO name */
1236 IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1237 SymLinkStatus = STATUS_OBJECT_NAME_EXISTS;
1238 }
1239
1240 if (!NT_SUCCESS(SymLinkStatus))
1241 {
1242 DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus);
1243 ZwClose(SubKey);
1244 ZwClose(InterfaceKey);
1245 ZwClose(ClassKey);
1246 ExFreePool(SubKeyName.Buffer);
1247 ExFreePool(InterfaceKeyName.Buffer);
1248 ExFreePool(BaseKeyName.Buffer);
1250 return SymLinkStatus;
1251 }
1252
1253 if (ReferenceString && ReferenceString->Length)
1254 {
1257 }
1258 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1259
1260 /* Write symbolic link name in registry */
1261 SymbolicLinkName->Buffer[1] = '\\';
1262 Status = ZwSetValueKey(
1263 SubKey,
1264 &SymbolicLink,
1265 0, /* TileIndex */
1266 REG_SZ,
1267 SymbolicLinkName->Buffer,
1268 SymbolicLinkName->Length);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1273 }
1274 else
1275 {
1276 SymbolicLinkName->Buffer[1] = '?';
1277 }
1278
1279 ZwClose(SubKey);
1280 ZwClose(InterfaceKey);
1281 ZwClose(ClassKey);
1282 ExFreePool(SubKeyName.Buffer);
1283 ExFreePool(InterfaceKeyName.Buffer);
1284 ExFreePool(BaseKeyName.Buffer);
1285
1286 return NT_SUCCESS(Status) ? SymLinkStatus : Status;
1287}
1288
1289/*++
1290 * @name IoSetDeviceInterfaceState
1291 * @implemented
1292 *
1293 * Enables or disables an instance of a previously registered device
1294 * interface class.
1295 * Documented in WDK.
1296 *
1297 * @param SymbolicLinkName
1298 * Pointer to the string identifying instance to enable or disable
1299 *
1300 * @param Enable
1301 * TRUE = enable, FALSE = disable
1302 *
1303 * @return Usual NTSTATUS
1304 *
1305 * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a
1306 * system thread
1307 *
1308 *--*/
1310NTAPI
1313{
1318 HANDLE InstanceHandle, ControlHandle;
1321 ULONG LinkedValue, Index;
1322 GUID DeviceGuid;
1323 UNICODE_STRING DosDevicesPrefix1 = RTL_CONSTANT_STRING(L"\\??\\");
1324 UNICODE_STRING DosDevicesPrefix2 = RTL_CONSTANT_STRING(L"\\\\?\\");
1325 UNICODE_STRING LinkNameNoPrefix;
1326 USHORT i;
1327 USHORT ReferenceStringOffset;
1328
1329 if (SymbolicLinkName == NULL)
1330 {
1332 }
1333
1334 DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable);
1335
1336 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1337 /* Make sure it starts with the expected prefix */
1338 if (!RtlPrefixUnicodeString(&DosDevicesPrefix1, SymbolicLinkName, FALSE) &&
1339 !RtlPrefixUnicodeString(&DosDevicesPrefix2, SymbolicLinkName, FALSE))
1340 {
1341 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1343 }
1344
1345 /* Make a version without the prefix for further processing */
1346 ASSERT(DosDevicesPrefix1.Length == DosDevicesPrefix2.Length);
1347 ASSERT(SymbolicLinkName->Length >= DosDevicesPrefix1.Length);
1348 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + DosDevicesPrefix1.Length / sizeof(WCHAR);
1349 LinkNameNoPrefix.Length = SymbolicLinkName->Length - DosDevicesPrefix1.Length;
1350 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
1351
1352 /* Find the reference string, if any */
1353 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
1354 {
1355 if (LinkNameNoPrefix.Buffer[i] == L'\\')
1356 {
1357 break;
1358 }
1359 }
1360 ReferenceStringOffset = i * sizeof(WCHAR);
1361
1362 /* The GUID is before the reference string or at the end */
1363 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
1364 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
1365 {
1366 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1368 }
1369
1370 GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1372 GuidString.MaximumLength = GuidString.Length;
1373 Status = RtlGUIDFromString(&GuidString, &DeviceGuid);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 DPRINT1("RtlGUIDFromString() invalid GUID '%wZ' in link name '%wZ'\n", &GuidString, SymbolicLinkName);
1377 return Status;
1378 }
1379
1380 /* Open registry keys */
1383 NULL,
1384 NULL,
1385 &InstanceHandle);
1386 if (!NT_SUCCESS(Status))
1387 return Status;
1388
1389 RtlInitUnicodeString(&KeyName, L"Control");
1391 &KeyName,
1393 InstanceHandle,
1394 NULL);
1395 Status = ZwCreateKey(&ControlHandle,
1398 0,
1399 NULL,
1401 NULL);
1402 ZwClose(InstanceHandle);
1403 if (!NT_SUCCESS(Status))
1404 {
1405 DPRINT1("Failed to create the Control subkey\n");
1406 return Status;
1407 }
1408
1409 LinkedValue = (Enable ? 1 : 0);
1410
1411 RtlInitUnicodeString(&KeyName, L"Linked");
1412 Status = ZwSetValueKey(ControlHandle,
1413 &KeyName,
1414 0,
1415 REG_DWORD,
1416 &LinkedValue,
1417 sizeof(ULONG));
1418 ZwClose(ControlHandle);
1419 if (!NT_SUCCESS(Status))
1420 {
1421 DPRINT1("Failed to write the Linked value\n");
1422 return Status;
1423 }
1424
1425 ASSERT(GuidString.Buffer >= LinkNameNoPrefix.Buffer + 1);
1426 DeviceInstance.Length = (GuidString.Buffer - LinkNameNoPrefix.Buffer - 1) * sizeof(WCHAR);
1427 if (DeviceInstance.Length == 0)
1428 {
1429 DPRINT1("No device instance in link name '%wZ'\n", SymbolicLinkName);
1431 }
1432 DeviceInstance.MaximumLength = DeviceInstance.Length;
1434 DeviceInstance.MaximumLength,
1435 TAG_IO);
1436 if (DeviceInstance.Buffer == NULL)
1437 {
1438 /* no memory */
1440 }
1441
1443 LinkNameNoPrefix.Buffer,
1444 DeviceInstance.Length);
1445
1446 for (Index = 0; Index < DeviceInstance.Length / sizeof(WCHAR); Index++)
1447 {
1448 if (DeviceInstance.Buffer[Index] == L'#')
1449 {
1450 DeviceInstance.Buffer[Index] = L'\\';
1451 }
1452 }
1453
1455
1457 {
1458 DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1461 }
1462
1464
1466
1469
1471 DPRINT("Status %x\n", Status);
1472 return STATUS_SUCCESS;
1473}
1474
1475/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#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 wcschr
Definition: compat.h:17
#define wcsrchr
Definition: compat.h:16
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
_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)
#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)
@ 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
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_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
NTSTATUS IopQueueDeviceChangeEvent(_In_ const GUID *EventGuid, _In_ const GUID *InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Definition: plugplay.c:52
VOID PiNotifyDeviceInterfaceChange(_In_ LPCGUID Event, _In_ LPCGUID InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Delivers the event to all drivers subscribed to EventCategoryDeviceInterfaceChange.
Definition: pnpnotify.c:161
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:330
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
Definition: deviface.c:241
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:454
static PWCHAR BaseKeyString
Definition: deviface.c:29
NTSTATUS NTAPI IoGetDeviceInterfaceAlias(IN PUNICODE_STRING SymbolicLinkName, IN CONST GUID *AliasInterfaceClassGuid, OUT PUNICODE_STRING AliasSymbolicLinkName)
Definition: deviface.c:303
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
static NTSTATUS OpenRegistryHandlesFromSymbolicLink(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, IN OPTIONAL PHANDLE GuidKey, IN OPTIONAL PHANDLE DeviceKey, IN OPTIONAL PHANDLE InstanceKey)
Definition: deviface.c:33
#define GUID_STRING_BYTES
Definition: deviface.c:21
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
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#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
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#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:1085
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define max(a, b)
Definition: svc.c:63
#define TAG_IO
Definition: tag.h:80
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
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_ ULONG _In_ PVOID StartPosition
Definition: usbdlib.h:159
_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
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180