ReactOS  0.4.13-dev-249-gcba1a2f
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))
22 C_ASSERT(sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}") == GUID_STRING_BYTES + sizeof(UNICODE_NULL));
23 
24 /* FUNCTIONS *****************************************************************/
25 
28 
29 static PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
30 
31 static
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 
86  StartPosition = wcschr(SymbolicLinkName->Buffer, L'{');
87  EndPosition = wcschr(SymbolicLinkName->Buffer, L'}');
88  if (!StartPosition || !EndPosition || StartPosition > EndPosition)
89  {
90  DPRINT1("Bad symbolic link: %wZ\n", SymbolicLinkName);
92  }
93  GuidString.Buffer = StartPosition;
94  GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition);
95 
97  &GuidString,
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 
125  SymbolicLinkName);
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 
185 cleanup:
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  *--*/
239 NTSTATUS
240 NTAPI
244 {
245  HANDLE InstanceKey, DeviceParametersKey;
248  UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
249 
250  Status = OpenRegistryHandlesFromSymbolicLink(SymbolicLinkName,
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  *--*/
301 NTSTATUS
302 NTAPI
305  OUT PUNICODE_STRING AliasSymbolicLinkName)
306 {
307  return STATUS_NOT_IMPLEMENTED;
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  *--*/
329 static 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 
360  Status = RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
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 
404 cleanup:
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  *--*/
452 NTSTATUS
453 NTAPI
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;
468  PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
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 
480  if (PhysicalDeviceObject != NULL)
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,
768  &SymbolicLink,
770  NULL,
771  0,
772  &Size);
774  {
775  DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
776  goto cleanup;
777  }
778  bip = ExAllocatePool(PagedPool, Size);
779  if (!bip)
780  {
781  DPRINT("ExAllocatePool() failed\n");
783  goto cleanup;
784  }
785  Status = ZwQueryValueKey(
786  ReferenceKey,
787  &SymbolicLink,
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);
838  Status = RtlAppendUnicodeStringToString(&ReturnBuffer, &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 
850 NextReferenceString:
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 
903 cleanup:
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  *--*/
953 NTSTATUS
954 NTAPI
958  OUT PUNICODE_STRING SymbolicLinkName)
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,
1128  &DeviceInstance,
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;
1201  SymbolicLinkName->Buffer = ExAllocatePool(
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  }
1215  RtlAppendUnicodeToString(SymbolicLinkName, L"\\??\\");
1216  StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1217  RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath);
1218  for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1219  {
1220  if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1221  SymbolicLinkName->Buffer[StartIndex + i] = '#';
1222  }
1223  RtlAppendUnicodeToString(SymbolicLinkName, L"#");
1224  RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString);
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 */
1235  IoDeleteSymbolicLink(SymbolicLinkName);
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);
1249  ExFreePool(SymbolicLinkName->Buffer);
1250  return SymLinkStatus;
1251  }
1252 
1253  if (ReferenceString && ReferenceString->Length)
1254  {
1255  RtlAppendUnicodeToString(SymbolicLinkName, L"\\");
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);
1272  ExFreePool(SymbolicLinkName->Buffer);
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  *--*/
1309 NTSTATUS
1310 NTAPI
1312  IN BOOLEAN Enable)
1313 {
1316  NTSTATUS Status;
1317  LPCGUID EventGuid;
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  {
1331  return STATUS_INVALID_PARAMETER;
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);
1342  return STATUS_INVALID_PARAMETER;
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);
1367  return STATUS_INVALID_PARAMETER;
1368  }
1369 
1370  GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1371  GuidString.Length = GUID_STRING_BYTES;
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 */
1381  Status = OpenRegistryHandlesFromSymbolicLink(SymbolicLinkName,
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,
1396  KEY_SET_VALUE,
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  }
1435  TAG_IO);
1436  if (DeviceInstance.Buffer == NULL)
1437  {
1438  /* no memory */
1440  }
1441 
1443  LinkNameNoPrefix.Buffer,
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 
1456  if (!PhysicalDeviceObject)
1457  {
1458  DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1461  }
1462 
1464 
1469  EventGuid,
1470  &DeviceGuid,
1471  (PVOID)SymbolicLinkName);
1472 
1474  DPRINT("Status %x\n", Status);
1475  return STATUS_SUCCESS;
1476 }
1477 
1478 /* EOF */
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 STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
_In_ CONST GUID * AliasInterfaceClassGuid
Definition: iofuncs.h:960
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4711
static PWSTR GuidString
Definition: apphelp.c:91
#define IN
Definition: typedefs.h:38
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
Definition: deviface.c:241
#define TAG_IO
Definition: tag.h:69
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:193
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4723
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1156
NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
Definition: deviface.c:454
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
uint16_t * PWCHAR
Definition: typedefs.h:54
_In_ ACCESS_MASK _Out_ PHANDLE DeviceInterfaceKey
Definition: iofuncs.h:1113
#define PAGED_CODE()
Definition: video.h:57
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define OBJ_OPENIF
Definition: winternl.h:229
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
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
#define REGSTR_PATH_DEVICE_CLASSES
Definition: regstr.h:481
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
NTSTATUS NTAPI IoGetDeviceInterfaceAlias(IN PUNICODE_STRING SymbolicLinkName, IN CONST GUID *AliasInterfaceClassGuid, OUT PUNICODE_STRING AliasSymbolicLinkName)
Definition: deviface.c:303
_In_ CONST GUID _In_opt_ PUNICODE_STRING ReferenceString
Definition: iofuncs.h:1134
unsigned char BOOLEAN
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
#define GUID_STRING_BYTES
Definition: deviface.c:21
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
struct _DEVICE_NODE * DeviceNode
Definition: iotypes.h:919
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define DEVICE_INTERFACE_INCLUDE_NONACTIVE
Definition: iofuncs.h:2808
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_WRITE
Definition: nt_native.h:1031
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const UCHAR Index[8]
Definition: usbohci.c:18
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID IopNotifyPlugPlayNotification(IN PDEVICE_OBJECT DeviceObject, IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, IN LPCGUID Event, IN PVOID EventCategoryData1, IN PVOID EventCategoryData2)
Definition: pnpnotify.c:36
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static PWCHAR BaseKeyString
Definition: deviface.c:29
static const WCHAR L[]
Definition: oid.c:1250
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:461
_In_ PNDIS_STRING DeviceInstance
Definition: ndis.h:5202
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
static const WCHAR Control[]
Definition: interface.c:27
Status
Definition: gdiplustypes.h:24
_In_ ULONG _In_ PVOID StartPosition
Definition: usbdlib.h:145
C_ASSERT(sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}")==GUID_STRING_BYTES+sizeof(UNICODE_NULL))
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:330
unsigned short USHORT
Definition: pedump.c:61
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
const GUID GUID_DEVICE_INTERFACE_REMOVAL
Definition: deviface.c:15
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
_In_ CONST GUID * InterfaceClassGuid
Definition: iofuncs.h:1134
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:148
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
char * cleanup(char *str)
Definition: wpickclick.c:99
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define REG_DWORD
Definition: sdbapi.c:596
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define CONST
Definition: pedump.c:81
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
struct _OBJECT_NAME_INFORMATION * POBJECT_NAME_INFORMATION
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define REG_SZ
Definition: layer.c:22
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68