ReactOS  0.4.15-dev-3294-ge98684e
devaction.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: PnP manager device manipulation functions
5  * COPYRIGHT: Casper S. Hornstrup (chorns@users.sourceforge.net)
6  * 2007 HervĂ© Poussineau (hpoussin@reactos.org)
7  * 2014-2017 Thomas Faber (thomas.faber@reactos.org)
8  * 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
9  */
10 
11 /* Device tree is a resource shared among all system services: hal, kernel, drivers etc.
12  * Thus all code which interacts with the tree needs to be synchronized.
13  * Here it's done via a list of DEVICE_ACTION_REQUEST structures, which represents
14  * the device action queue. It is being processed exclusively by the PipDeviceActionWorker.
15  *
16  * Operation queuing can be done with the PiQueueDeviceAction function or with
17  * the PiPerfomSyncDeviceAction for synchronous operations.
18  * All device manipulation like starting, removing, enumeration (see DEVICE_ACTION enum)
19  * have to be done with the PiQueueDeviceAction in order to avoid race conditions.
20  *
21  * Note: there is one special operation here - PiActionEnumRootDevices. It is meant to be done
22  * during initialization process (and be the first device tree operation executed) and
23  * is always executed synchronously.
24  */
25 
26 /* INCLUDES ******************************************************************/
27 
28 #include <ntoskrnl.h>
29 #define NDEBUG
30 #include <debug.h>
31 
32 /* GLOBALS *******************************************************************/
33 
35 extern BOOLEAN PnpSystemInit;
39 
40 #define MAX_DEVICE_ID_LEN 200
41 #define MAX_SEPARATORS_INSTANCEID 0
42 #define MAX_SEPARATORS_DEVICEID 1
43 
44 /* DATA **********************************************************************/
45 
51 static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
52 
53 #define TAG_PNP_DEVACTION 'aDpP'
54 
55 /* TYPES *********************************************************************/
56 
57 typedef struct _DEVICE_ACTION_REQUEST
58 {
65 
67 {
74 
75 typedef struct _ADD_DEV_DRIVERS_LIST
76 {
81 
83 {
88 
89 /* FUNCTIONS *****************************************************************/
90 
93 
96 
97 USHORT
98 NTAPI
99 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid);
100 
101 NTSTATUS
103 
104 VOID
105 NTAPI
107 
108 static
109 VOID
111 
112 static
113 NTSTATUS
115 
116 static
117 NTSTATUS
120  _In_ HANDLE InstanceHandle);
121 
122 static
123 BOOLEAN
125  _In_ PWCHAR Id,
127 {
128  PWCHAR PtrChar;
129  PWCHAR StringEnd;
130  WCHAR Char;
131  ULONG SeparatorsCount = 0;
132  PWCHAR PtrPrevChar = NULL;
133  ULONG MaxSeparators;
134  BOOLEAN IsMultiSz;
135 
136  PAGED_CODE();
137 
138  switch (QueryType)
139  {
140  case BusQueryDeviceID:
141  MaxSeparators = MAX_SEPARATORS_DEVICEID;
142  IsMultiSz = FALSE;
143  break;
144  case BusQueryInstanceID:
145  MaxSeparators = MAX_SEPARATORS_INSTANCEID;
146  IsMultiSz = FALSE;
147  break;
148 
149  case BusQueryHardwareIDs:
151  MaxSeparators = MAX_SEPARATORS_DEVICEID;
152  IsMultiSz = TRUE;
153  break;
154 
155  default:
156  DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
157  return FALSE;
158  }
159 
160  StringEnd = Id + MAX_DEVICE_ID_LEN;
161 
162  for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
163  {
164  Char = *PtrChar;
165 
166  if (Char == UNICODE_NULL)
167  {
168  if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
169  {
170  if (MaxSeparators == SeparatorsCount || IsMultiSz)
171  {
172  return TRUE;
173  }
174 
175  DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
176  SeparatorsCount, MaxSeparators);
177  goto ErrorExit;
178  }
179 
180  StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
181  PtrPrevChar = PtrChar;
182  SeparatorsCount = 0;
183  }
184  else if (Char < ' ' || Char > 0x7F || Char == ',')
185  {
186  DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
187  goto ErrorExit;
188  }
189  else if (Char == ' ')
190  {
191  *PtrChar = '_';
192  }
193  else if (Char == '\\')
194  {
195  SeparatorsCount++;
196 
197  if (SeparatorsCount > MaxSeparators)
198  {
199  DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
200  SeparatorsCount, MaxSeparators);
201  goto ErrorExit;
202  }
203  }
204  }
205 
206  DPRINT1("IopValidateID: Not terminated ID\n");
207 
208 ErrorExit:
209  // FIXME logging
210  return FALSE;
211 }
212 
213 static
214 NTSTATUS
217  _Out_ PUNICODE_STRING InstancePath)
218 {
220  UNICODE_STRING DeviceId;
224  UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
226  BOOLEAN IsValidID;
227 
228  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
229 
230  Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
231  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
232  &IoStatusBlock,
234  &Stack);
235  if (!NT_SUCCESS(Status))
236  {
237  DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
238  return Status;
239  }
240 
242 
243  if (!IsValidID)
244  {
245  DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
246  }
247 
248  /* Save the device id string */
250 
251  DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
252 
254  if (!NT_SUCCESS(Status))
255  {
256  DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
257  RtlFreeUnicodeString(&DeviceId);
258  return Status;
259  }
260 
261  /* This bit is only check after enumeration */
262  if (DeviceCapabilities.HardwareDisabled)
263  {
264  /* FIXME: Cleanup device */
265  RtlFreeUnicodeString(&DeviceId);
267  }
268 
269  if (!DeviceCapabilities.UniqueID)
270  {
271  /* Device has not a unique ID. We need to prepend parent bus unique identifier */
272  DPRINT("Instance ID is not unique\n");
273  Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
274  if (!NT_SUCCESS(Status))
275  {
276  DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
277  RtlFreeUnicodeString(&DeviceId);
278  return Status;
279  }
280  }
281 
282  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
283 
284  Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
285  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
286  &IoStatusBlock,
288  &Stack);
289  if (!NT_SUCCESS(Status))
290  {
291  DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status);
293  }
294 
296  {
298 
299  if (!IsValidID)
300  {
301  DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
302  }
303  }
304 
307 
308  InstancePath->Length = 0;
309  InstancePath->MaximumLength = DeviceId.Length + sizeof(WCHAR) +
310  ParentIdPrefix.Length +
311  InstanceId.Length +
312  sizeof(UNICODE_NULL);
313  if (ParentIdPrefix.Length && InstanceId.Length)
314  {
315  InstancePath->MaximumLength += sizeof(WCHAR);
316  }
317 
318  InstancePath->Buffer = ExAllocatePoolWithTag(PagedPool,
319  InstancePath->MaximumLength,
320  TAG_IO);
321  if (!InstancePath->Buffer)
322  {
324  RtlFreeUnicodeString(&ParentIdPrefix);
325  RtlFreeUnicodeString(&DeviceId);
327  }
328 
329  /* Start with the device id */
330  RtlCopyUnicodeString(InstancePath, &DeviceId);
331  RtlAppendUnicodeToString(InstancePath, L"\\");
332 
333  /* Add information from parent bus device to InstancePath */
334  RtlAppendUnicodeStringToString(InstancePath, &ParentIdPrefix);
335  if (ParentIdPrefix.Length && InstanceId.Length)
336  {
337  RtlAppendUnicodeToString(InstancePath, L"&");
338  }
339 
340  /* Finally, add the id returned by the driver stack */
342 
343  /*
344  * FIXME: Check for valid characters, if there is invalid characters
345  * then bugcheck
346  */
347 
349  RtlFreeUnicodeString(&DeviceId);
350  RtlFreeUnicodeString(&ParentIdPrefix);
351 
352  return STATUS_SUCCESS;
353 }
354 
359 static
360 NTSTATUS
361 NTAPI
367  PVOID Ctx,
369 {
373  BOOLEAN loadDrivers = (BOOLEAN)(ULONG_PTR)EntryContext;
374 
375  PAGED_CODE();
376 
377  // No filter value present
378  if (ValueType != REG_SZ)
379  return STATUS_SUCCESS;
380 
381  if (ValueLength <= sizeof(WCHAR))
383 
384  // open the service registry key
385  UNICODE_STRING serviceName = { .Length = 0 }, servicesKeyName;
387  RtlInitUnicodeString(&servicesKeyName, ServicesKeyName);
388 
389  HANDLE ccsServicesHandle, serviceHandle = NULL;
390 
391  Status = IopOpenRegistryKeyEx(&ccsServicesHandle, NULL, &servicesKeyName, KEY_READ);
392  if (!NT_SUCCESS(Status))
393  {
394  DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
395  return Status;
396  }
397 
398  Status = IopOpenRegistryKeyEx(&serviceHandle, ccsServicesHandle, &serviceName, KEY_READ);
399  ZwClose(ccsServicesHandle);
400  if (!NT_SUCCESS(Status))
401  {
402  DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
403  return Status;
404  }
405 
407  sizeof(*driverEntry),
409 
410  if (!driverEntry)
411  {
412  DPRINT1("Failed to allocate driverEntry for \"%wZ\"\n", &serviceName);
413  ZwClose(serviceHandle);
415  }
416 
417  // check if the driver is disabled
419  SERVICE_LOAD_TYPE startType = DisableLoad;
420 
421  Status = IopGetRegistryValue(serviceHandle, L"Start", &kvInfo);
422  if (NT_SUCCESS(Status))
423  {
424  if (kvInfo->Type == REG_DWORD)
425  {
426  RtlMoveMemory(&startType,
427  (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
428  sizeof(startType));
429  }
430 
431  ExFreePool(kvInfo);
432  }
433 
434  // TODO: take into account other start types (like SERVICE_DEMAND_START)
435  if (startType >= DisableLoad)
436  {
437  if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
438  {
440  }
441 
442  DPRINT("Service \"%wZ\" is disabled (start type %u)\n", &serviceName, startType);
444  goto Cleanup;
445  }
446 
447  // check if the driver is already loaded
448  UNICODE_STRING driverName;
449  Status = IopGetDriverNames(serviceHandle, &driverName, NULL);
450  if (!NT_SUCCESS(Status))
451  {
452  DPRINT1("Unable to obtain the driver name for \"%wZ\"\n", &serviceName);
453  goto Cleanup;
454  }
455 
456  // try to open it
457  Status = ObReferenceObjectByName(&driverName,
459  NULL, /* PassedAccessState */
460  0, /* DesiredAccess */
462  KernelMode,
463  NULL, /* ParseContext */
464  (PVOID*)&DriverObject);
465  RtlFreeUnicodeString(&driverName);
466 
467  // the driver was not probably loaded, try to load
468  if (!NT_SUCCESS(Status))
469  {
470  if (loadDrivers)
471  {
472  Status = IopLoadDriver(serviceHandle, &DriverObject);
473  }
474  else
475  {
476  DPRINT("Service \"%wZ\" will not be loaded now\n", &serviceName);
477  // return failure, the driver will be loaded later (in a subsequent call)
479  goto Cleanup;
480  }
481  }
482 
483  if (NT_SUCCESS(Status))
484  {
485  driverEntry->DriverObject = DriverObject;
486  driverEntry->DriverType = context->DriverType;
487  InsertTailList(context->DriversListHead, &driverEntry->ListEntry);
488  ZwClose(serviceHandle);
489  return STATUS_SUCCESS;
490  }
491  else
492  {
493  if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
494  {
495  switch (Status)
496  {
499  break;
502  break;
505  break;
506  default:
508  break;
509  }
510  }
511 
512  DPRINT1("Failed to load driver \"%wZ\" for %wZ (status %x)\n",
513  &serviceName, &context->DeviceNode->InstancePath, Status);
514  }
515 
516 Cleanup:
517  ExFreePoolWithTag(driverEntry, TAG_PNP_DEVACTION);
518  if (serviceHandle)
519  {
520  ZwClose(serviceHandle);
521  }
522  return Status;
523 }
524 
525 
529 static
530 NTSTATUS
532  PLIST_ENTRY DriversListHead,
534  HANDLE EnumSubKey,
535  HANDLE ClassKey,
536  BOOLEAN Lower,
537  BOOLEAN LoadDrivers)
538 {
539  RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, };
540  ATTACH_FILTER_DRIVERS_CONTEXT routineContext;
542 
543  PAGED_CODE();
544 
545  routineContext.DriversListHead = DriversListHead;
546  routineContext.DeviceNode = DeviceNode;
547 
548  // First add device filters
549  routineContext.DriverType = Lower ? LowerFilter : UpperFilter;
552  .Name = Lower ? L"LowerFilters" : L"UpperFilters",
553  .DefaultType = REG_NONE,
554  .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
555  };
556 
558  (PWSTR)EnumSubKey,
559  QueryTable,
560  &routineContext,
561  NULL);
562  if (ClassKey == NULL)
563  {
564  return Status;
565  }
566 
567  // Then add device class filters
568  routineContext.DriverType = Lower ? LowerClassFilter : UpperClassFilter;
571  .Name = Lower ? L"LowerFilters" : L"UpperFilters",
572  .DefaultType = REG_NONE,
573  .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
574  };
575 
577  (PWSTR)ClassKey,
578  QueryTable,
579  &routineContext,
580  NULL);
581  return Status;
582 }
583 
592 static
593 NTSTATUS
596  _In_ BOOLEAN LoadDrivers)
597 {
599  HANDLE EnumRootKey, SubKey;
600  HANDLE ClassKey = NULL;
602  static UNICODE_STRING ccsControlClass =
603  RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
605 
606  PAGED_CODE();
607 
608  // open the enumeration root key
609  Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ);
610  if (!NT_SUCCESS(Status))
611  {
612  DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &EnumRoot, Status);
613  return Status;
614  }
615 
616  // open an instance subkey
617  Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ);
618  ZwClose(EnumRootKey);
619  if (!NT_SUCCESS(Status))
620  {
621  DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
622  &DeviceNode->InstancePath, Status);
623  return Status;
624  }
625 
626  // try to get the class GUID of an instance and its registry key
627  Status = IopGetRegistryValue(SubKey, REGSTR_VAL_CLASSGUID, &kvInfo);
628  if (NT_SUCCESS(Status))
629  {
630  if (kvInfo->Type == REG_SZ && kvInfo->DataLength > sizeof(WCHAR))
631  {
632  UNICODE_STRING classGUID = {
633  .MaximumLength = kvInfo->DataLength,
634  .Length = kvInfo->DataLength - sizeof(UNICODE_NULL),
635  .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset)
636  };
637  HANDLE ccsControlHandle;
638 
639  Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ);
640  if (!NT_SUCCESS(Status))
641  {
642  DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n",
643  &ccsControlClass, Status);
644  }
645  else
646  {
647  // open the CCS\Control\Class<ClassGUID> key
648  Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ);
649  ZwClose(ccsControlHandle);
650  if (!NT_SUCCESS(Status))
651  {
652  DPRINT1("Failed to open class key \"%wZ\" (status %x)\n", &classGUID, Status);
653  }
654  }
655 
656  if (ClassKey)
657  {
658  // Check the Properties key of a class too
659  // Windows fills some device properties from this key (which is protected)
660  // TODO: add the device properties from this key
661 
663  HANDLE propertiesHandle;
664 
665  Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ);
666  if (!NT_SUCCESS(Status))
667  {
668  DPRINT("Properties key failed to open for \"%wZ\" (status %x)\n",
669  &classGUID, Status);
670  }
671  else
672  {
673  ZwClose(propertiesHandle);
674  }
675  }
676  }
677 
678  ExFreePool(kvInfo);
679  }
680 
681  // the driver loading order:
682  // 1. LowerFilters
683  // 2. LowerClassFilters
684  // 3. Device driver (only one service!)
685  // 4. UpperFilters
686  // 5. UpperClassFilters
687 
688  LIST_ENTRY drvListHead;
689  InitializeListHead(&drvListHead);
690 
691  // lower (class) filters
692  Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers);
693  if (!NT_SUCCESS(Status))
694  {
695  goto Cleanup;
696  }
697 
698  ATTACH_FILTER_DRIVERS_CONTEXT routineContext = {
699  .DriversListHead = &drvListHead,
700  .DriverType = DeviceDriver,
701  .DeviceNode = DeviceNode
702  };
703 
704  RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{
706  .Name = L"Service",
708  .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here
709  .DefaultData = L"",
710  .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
711  },};
712 
713  // device driver
715  (PWSTR)SubKey,
716  queryTable,
717  &routineContext,
718  NULL);
719  if (NT_SUCCESS(Status))
720  {
721  // do nothing
722  }
723  // if a driver is not found, but a device allows raw access -> proceed
724  else if (Status == STATUS_OBJECT_NAME_NOT_FOUND &&
725  (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK
726  {
727  // add a dummy entry to the drivers list (need for later processing)
728  PADD_DEV_DRIVERS_LIST driverEntry = ExAllocatePoolZero(PagedPool,
729  sizeof(*driverEntry),
731  driverEntry->DriverType = DeviceDriver;
732  InsertTailList(&drvListHead, &driverEntry->ListEntry);
733  DPRINT("No service for \"%wZ\" (RawDeviceOK)\n", &DeviceNode->InstancePath);
734  }
735  else
736  {
738  {
740  }
741  DPRINT("No service for \"%wZ\" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers);
742  goto Cleanup;
743  }
744 
745  // upper (class) filters
746  Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers);
747  if (!NT_SUCCESS(Status))
748  {
749  goto Cleanup;
750  }
751 
752  // finally loop through the stack and call AddDevice for every driver
753  for (PLIST_ENTRY listEntry = drvListHead.Flink;
754  listEntry != &drvListHead;
755  listEntry = listEntry->Flink)
756  {
757  PADD_DEV_DRIVERS_LIST driverEntry;
758  driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
759  PDRIVER_OBJECT driverObject = driverEntry->DriverObject;
760 
761  // FIXME: ReactOS is not quite ready for this assert
762  // (legacy drivers should not have AddDevice routine)
763  // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER));
764 
765  if (driverObject && driverObject->DriverExtension->AddDevice)
766  {
767  Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject,
768  DeviceNode->PhysicalDeviceObject);
769  }
770  else if (driverObject == NULL)
771  {
772  // valid only for DeviceDriver
773  ASSERT(driverEntry->DriverType == DeviceDriver);
774  ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK
776  }
777  else
778  {
779  // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here,
780  // but ReactOS' PnP stack is not that correct yet
781  DeviceNode->Flags |= DNF_LEGACY_DRIVER;
783  }
784 
785  // for filter drivers we don't care about the AddDevice result
786  if (driverEntry->DriverType == DeviceDriver)
787  {
788  if (NT_SUCCESS(Status))
789  {
790  PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
791 
792  // HACK: Check if we have a ACPI device (needed for power management)
793  if (fdo->DeviceType == FILE_DEVICE_ACPI)
794  {
795  static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
796 
797  // There can be only one system power device
798  if (!SystemPowerDeviceNodeCreated)
799  {
802  SystemPowerDeviceNodeCreated = TRUE;
803  }
804  }
805 
806  ObDereferenceObject(fdo);
808  }
809  else
810  {
811  // lower filters (if already started) will be removed upon this request
814  break;
815  }
816  }
817 
818 #if DBG
819  PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject);
820  if (attachedDO->Flags & DO_DEVICE_INITIALIZING)
821  {
822  DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO);
823  }
824 #endif
825  }
826 
827 Cleanup:
828  while (!IsListEmpty(&drvListHead))
829  {
830  PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead);
831  PADD_DEV_DRIVERS_LIST driverEntry;
832  driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
833 
834  // drivers which don't have any devices (in case of failure) will be cleaned up
835  if (driverEntry->DriverObject)
836  {
837  ObDereferenceObject(driverEntry->DriverObject);
838  }
839  ExFreePoolWithTag(driverEntry, TAG_PNP_DEVACTION);
840  }
841 
842  ZwClose(SubKey);
843  if (ClassKey != NULL)
844  {
845  ZwClose(ClassKey);
846  }
847 
848  return Status;
849 }
850 
851 NTSTATUS
852 NTAPI
854  PDEVICE_CAPABILITIES DeviceCaps)
855 {
856  IO_STATUS_BLOCK StatusBlock;
859  HANDLE InstanceKey;
861 
862  /* Set up the Header */
863  RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
864  DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
865  DeviceCaps->Version = 1;
866  DeviceCaps->Address = -1;
867  DeviceCaps->UINumber = -1;
868 
869  /* Set up the Stack */
871  Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
872 
873  /* Send the IRP */
874  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
875  &StatusBlock,
877  &Stack);
878  if (!NT_SUCCESS(Status))
879  {
881  {
882  DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
883  }
884  return Status;
885  }
886 
887  /* Map device capabilities to capability flags */
888  DeviceNode->CapabilityFlags = 0;
889  if (DeviceCaps->LockSupported)
890  DeviceNode->CapabilityFlags |= 0x00000001; // CM_DEVCAP_LOCKSUPPORTED
891 
892  if (DeviceCaps->EjectSupported)
893  DeviceNode->CapabilityFlags |= 0x00000002; // CM_DEVCAP_EJECTSUPPORTED
894 
895  if (DeviceCaps->Removable)
896  DeviceNode->CapabilityFlags |= 0x00000004; // CM_DEVCAP_REMOVABLE
897 
898  if (DeviceCaps->DockDevice)
899  DeviceNode->CapabilityFlags |= 0x00000008; // CM_DEVCAP_DOCKDEVICE
900 
901  if (DeviceCaps->UniqueID)
902  DeviceNode->CapabilityFlags |= 0x00000010; // CM_DEVCAP_UNIQUEID
903 
904  if (DeviceCaps->SilentInstall)
905  DeviceNode->CapabilityFlags |= 0x00000020; // CM_DEVCAP_SILENTINSTALL
906 
907  if (DeviceCaps->RawDeviceOK)
908  DeviceNode->CapabilityFlags |= 0x00000040; // CM_DEVCAP_RAWDEVICEOK
909 
910  if (DeviceCaps->SurpriseRemovalOK)
911  DeviceNode->CapabilityFlags |= 0x00000080; // CM_DEVCAP_SURPRISEREMOVALOK
912 
913  if (DeviceCaps->HardwareDisabled)
914  DeviceNode->CapabilityFlags |= 0x00000100; // CM_DEVCAP_HARDWAREDISABLED
915 
916  if (DeviceCaps->NonDynamic)
917  DeviceNode->CapabilityFlags |= 0x00000200; // CM_DEVCAP_NONDYNAMIC
918 
919  if (DeviceCaps->NoDisplayInUI)
920  DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
921  else
922  DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
923 
924  Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
925  if (NT_SUCCESS(Status))
926  {
927  /* Set 'Capabilities' value */
928  RtlInitUnicodeString(&ValueName, L"Capabilities");
929  Status = ZwSetValueKey(InstanceKey,
930  &ValueName,
931  0,
932  REG_DWORD,
933  &DeviceNode->CapabilityFlags,
934  sizeof(ULONG));
935 
936  /* Set 'UINumber' value */
937  if (DeviceCaps->UINumber != MAXULONG)
938  {
939  RtlInitUnicodeString(&ValueName, L"UINumber");
940  Status = ZwSetValueKey(InstanceKey,
941  &ValueName,
942  0,
943  REG_DWORD,
944  &DeviceCaps->UINumber,
945  sizeof(ULONG));
946  }
947 
948  ZwClose(InstanceKey);
949  }
950 
951  return Status;
952 }
953 
954 static
955 NTSTATUS
957  HANDLE InstanceKey)
958 {
961  PWSTR Ptr;
965  BOOLEAN IsValidID;
966 
967  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
968 
969  RtlZeroMemory(&Stack, sizeof(Stack));
970  Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
971  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
972  &IoStatusBlock,
974  &Stack);
975  if (NT_SUCCESS(Status))
976  {
978 
979  if (!IsValidID)
980  {
981  DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
982  }
983 
984  TotalLength = 0;
985 
987  DPRINT("Hardware IDs:\n");
988  while (*Ptr)
989  {
990  DPRINT(" %S\n", Ptr);
991  Length = (ULONG)wcslen(Ptr) + 1;
992 
993  Ptr += Length;
994  TotalLength += Length;
995  }
996  DPRINT("TotalLength: %hu\n", TotalLength);
997  DPRINT("\n");
998 
999  RtlInitUnicodeString(&ValueName, L"HardwareID");
1000  Status = ZwSetValueKey(InstanceKey,
1001  &ValueName,
1002  0,
1003  REG_MULTI_SZ,
1005  (TotalLength + 1) * sizeof(WCHAR));
1006  if (!NT_SUCCESS(Status))
1007  {
1008  DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1009  }
1010  }
1011  else
1012  {
1013  DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1014  }
1015 
1016  return Status;
1017 }
1018 
1019 static
1020 NTSTATUS
1022  HANDLE InstanceKey)
1023 {
1026  PWSTR Ptr;
1028  NTSTATUS Status;
1030  BOOLEAN IsValidID;
1031 
1032  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1033 
1034  RtlZeroMemory(&Stack, sizeof(Stack));
1035  Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1036  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1037  &IoStatusBlock,
1039  &Stack);
1041  {
1043 
1044  if (!IsValidID)
1045  {
1046  DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
1047  }
1048 
1049  TotalLength = 0;
1050 
1052  DPRINT("Compatible IDs:\n");
1053  while (*Ptr)
1054  {
1055  DPRINT(" %S\n", Ptr);
1056  Length = (ULONG)wcslen(Ptr) + 1;
1057 
1058  Ptr += Length;
1059  TotalLength += Length;
1060  }
1061  DPRINT("TotalLength: %hu\n", TotalLength);
1062  DPRINT("\n");
1063 
1064  RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
1065  Status = ZwSetValueKey(InstanceKey,
1066  &ValueName,
1067  0,
1068  REG_MULTI_SZ,
1070  (TotalLength + 1) * sizeof(WCHAR));
1071  if (!NT_SUCCESS(Status))
1072  {
1073  DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
1074  }
1075  }
1076  else
1077  {
1078  DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1079  }
1080 
1081  return Status;
1082 }
1083 
1087 VOID
1090  _In_ HANDLE InstanceKey)
1091 {
1092  PAGED_CODE();
1093 
1094  LCID localeId;
1095 
1096  // Get the Locale ID
1097  NTSTATUS status = ZwQueryDefaultLocale(FALSE, &localeId);
1098  if (!NT_SUCCESS(status))
1099  {
1100  DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
1101  return;
1102  }
1103 
1104  // Step 1: Write the DeviceDesc value if does not exist
1105 
1106  UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
1107  ULONG len;
1108 
1109  status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, KeyValueBasicInformation, NULL, 0, &len);
1111  {
1112  PWSTR deviceDesc = NULL;
1113  status = PiIrpQueryDeviceText(DeviceNode, localeId, DeviceTextDescription, &deviceDesc);
1114 
1115  if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
1116  {
1117  status = ZwSetValueKey(InstanceKey,
1118  &valDeviceDesc,
1119  0,
1120  REG_SZ,
1121  deviceDesc,
1122  ((ULONG)wcslen(deviceDesc) + 1) * sizeof(WCHAR));
1123 
1124  if (!NT_SUCCESS(status))
1125  {
1126  DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1127  }
1128  }
1129  else
1130  {
1131  // This key is mandatory, so even if the Irp fails, we still write it
1132  UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
1133  DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
1134 
1135  status = ZwSetValueKey(InstanceKey,
1136  &valDeviceDesc,
1137  0,
1138  REG_SZ,
1139  unknownDeviceDesc.Buffer,
1140  unknownDeviceDesc.MaximumLength);
1141  if (!NT_SUCCESS(status))
1142  {
1143  DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1144  }
1145  }
1146 
1147  if (deviceDesc)
1148  {
1149  ExFreePoolWithTag(deviceDesc, 0);
1150  }
1151  }
1152 
1153  // Step 2: LocaltionInformation is overwritten unconditionally
1154 
1155  PWSTR deviceLocationInfo = NULL;
1157  localeId,
1159  &deviceLocationInfo);
1160 
1161  if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
1162  {
1163  UNICODE_STRING valLocationInfo = RTL_CONSTANT_STRING(L"LocationInformation");
1164 
1165  status = ZwSetValueKey(InstanceKey,
1166  &valLocationInfo,
1167  0,
1168  REG_SZ,
1169  deviceLocationInfo,
1170  ((ULONG)wcslen(deviceLocationInfo) + 1) * sizeof(WCHAR));
1171  if (!NT_SUCCESS(status))
1172  {
1173  DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1174  }
1175  }
1176 
1177  if (deviceLocationInfo)
1178  {
1179  ExFreePoolWithTag(deviceLocationInfo, 0);
1180  }
1181  else
1182  {
1183  DPRINT("Driver didn't return LocationInformation (status %x)\n", status);
1184  }
1185 }
1186 
1187 static
1188 NTSTATUS
1191 {
1193  NTSTATUS Status;
1194  HANDLE InstanceKey = NULL;
1195  UNICODE_STRING InstancePathU;
1196  PDEVICE_OBJECT OldDeviceObject;
1197 
1198  DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
1199  DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
1200 
1201  /*
1202  * FIXME: For critical errors, cleanup and disable device, but always
1203  * return STATUS_SUCCESS.
1204  */
1205 
1206  Status = IopCreateDeviceInstancePath(DeviceNode, &InstancePathU);
1207  if (!NT_SUCCESS(Status))
1208  {
1210  {
1211  DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
1212  }
1213  return Status;
1214  }
1215 
1216  /* Verify that this is not a duplicate */
1217  OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
1218  if (OldDeviceObject != NULL)
1219  {
1220  PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
1221 
1222  DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
1223  DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
1224  DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
1225 
1226  KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1227  0x01,
1228  (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
1229  (ULONG_PTR)OldDeviceObject,
1230  0);
1231  }
1232 
1233  DeviceNode->InstancePath = InstancePathU;
1234 
1235  DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1236 
1237  /*
1238  * Create registry key for the instance id, if it doesn't exist yet
1239  */
1240  Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
1241  if (!NT_SUCCESS(Status))
1242  {
1243  DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1244 
1245  /* We have to return success otherwise we abort the traverse operation */
1246  return STATUS_SUCCESS;
1247  }
1248 
1249  IopQueryHardwareIds(DeviceNode, InstanceKey);
1250 
1251  IopQueryCompatibleIds(DeviceNode, InstanceKey);
1252 
1253  DeviceNode->Flags |= DNF_IDS_QUERIED;
1254 
1255  // Set the device's DeviceDesc and LocationInformation fields
1256  PiSetDevNodeText(DeviceNode, InstanceKey);
1257 
1258  DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1259 
1260  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1261  &IoStatusBlock,
1263  NULL);
1265  {
1267 
1268  DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1269  DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1270  DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
1272  }
1273  else
1274  {
1275  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1276 
1277  DeviceNode->ChildBusNumber = 0xFFFFFFF0;
1278  DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
1279  DeviceNode->ChildBusTypeIndex = -1;
1280  }
1281 
1282  DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1283 
1284  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1285  &IoStatusBlock,
1287  NULL);
1289  {
1292  }
1293  else
1294  {
1295  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1296  DeviceNode->BootResources = NULL;
1297  }
1298 
1299  DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1300 
1301  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1302  &IoStatusBlock,
1304  NULL);
1305  if (NT_SUCCESS(Status))
1306  {
1308  }
1309  else
1310  {
1311  DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
1312  DeviceNode->ResourceRequirements = NULL;
1313  }
1314 
1315  if (InstanceKey != NULL)
1316  {
1317  IopSetDeviceInstanceData(InstanceKey, DeviceNode);
1318  }
1319 
1320  // Try installing a critical device, so its Service key is populated
1321  // then call IopSetServiceEnumData to populate service's Enum key.
1322  // That allows us to start devices during an early boot
1324  IopSetServiceEnumData(DeviceNode, InstanceKey);
1325 
1326  ZwClose(InstanceKey);
1327 
1329 
1331  {
1332  /* Report the device to the user-mode pnp manager */
1333  IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
1334  &DeviceNode->InstancePath);
1335  }
1336 
1337  return STATUS_SUCCESS;
1338 }
1339 
1340 static
1341 NTSTATUS
1344  _In_ HANDLE InstanceHandle)
1345 {
1346  UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1347  UNICODE_STRING ServiceKeyName;
1348  UNICODE_STRING EnumKeyName;
1351  PKEY_VALUE_FULL_INFORMATION KeyValueInformation, kvInfo2;
1352  HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1354  ULONG Count = 0, NextInstance = 0;
1355  WCHAR ValueBuffer[6];
1357 
1358  // obtain the device node's ServiceName
1359  Status = IopGetRegistryValue(InstanceHandle, L"Service", &kvInfo2);
1360  if (!NT_SUCCESS(Status))
1361  {
1362  return Status;
1363  }
1364 
1365  if (kvInfo2->Type != REG_SZ || kvInfo2->DataLength <= sizeof(WCHAR))
1366  {
1367  ExFreePool(kvInfo2);
1368  return STATUS_UNSUCCESSFUL;
1369  }
1370 
1371  ServiceName.MaximumLength = kvInfo2->DataLength;
1372  ServiceName.Length = kvInfo2->DataLength - sizeof(UNICODE_NULL);
1373  ServiceName.Buffer = (PVOID)((ULONG_PTR)kvInfo2 + kvInfo2->DataOffset);
1374 
1375  DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1376  DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1377  DPRINT("Service: %wZ\n", &ServiceName);
1378 
1379  ServiceKeyName.MaximumLength = ServicesKeyPath.Length + ServiceName.Length + sizeof(UNICODE_NULL);
1380  ServiceKeyName.Length = 0;
1381  ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1382  if (ServiceKeyName.Buffer == NULL)
1383  {
1384  DPRINT1("No ServiceKeyName.Buffer!\n");
1386  }
1387 
1388  RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1389  RtlAppendUnicodeStringToString(&ServiceKeyName, &ServiceName);
1390 
1391  DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1392 
1393  Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1394  if (!NT_SUCCESS(Status))
1395  {
1396  goto done;
1397  }
1398 
1400  &ServiceName,
1401  &DeviceNode->ServiceName);
1402  if (!NT_SUCCESS(Status))
1403  {
1404  goto done;
1405  }
1406 
1407  RtlInitUnicodeString(&EnumKeyName, L"Enum");
1408  Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1409  ServiceKey,
1410  &EnumKeyName,
1411  KEY_SET_VALUE,
1413  &Disposition);
1414  if (NT_SUCCESS(Status))
1415  {
1417  {
1418  /* Read the NextInstance value */
1419  Status = IopGetRegistryValue(ServiceEnumKey,
1420  L"Count",
1421  &KeyValueInformation);
1422  if (!NT_SUCCESS(Status))
1423  goto done;
1424 
1425  if ((KeyValueInformation->Type == REG_DWORD) &&
1426  (KeyValueInformation->DataLength))
1427  {
1428  /* Read it */
1429  Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1430  KeyValueInformation->DataOffset);
1431  }
1432 
1433  ExFreePool(KeyValueInformation);
1434  KeyValueInformation = NULL;
1435 
1436  /* Read the NextInstance value */
1437  Status = IopGetRegistryValue(ServiceEnumKey,
1438  L"NextInstance",
1439  &KeyValueInformation);
1440  if (!NT_SUCCESS(Status))
1441  goto done;
1442 
1443  if ((KeyValueInformation->Type == REG_DWORD) &&
1444  (KeyValueInformation->DataLength))
1445  {
1446  NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1447  KeyValueInformation->DataOffset);
1448  }
1449 
1450  ExFreePool(KeyValueInformation);
1451  KeyValueInformation = NULL;
1452  }
1453 
1454  /* Set the instance path */
1455  swprintf(ValueBuffer, L"%lu", NextInstance);
1456  RtlInitUnicodeString(&ValueName, ValueBuffer);
1457  Status = ZwSetValueKey(ServiceEnumKey,
1458  &ValueName,
1459  0,
1460  REG_SZ,
1461  DeviceNode->InstancePath.Buffer,
1462  DeviceNode->InstancePath.MaximumLength);
1463  if (!NT_SUCCESS(Status))
1464  goto done;
1465 
1466  /* Increment Count and NextInstance */
1467  Count++;
1468  NextInstance++;
1469 
1470  /* Set the new Count value */
1471  RtlInitUnicodeString(&ValueName, L"Count");
1472  Status = ZwSetValueKey(ServiceEnumKey,
1473  &ValueName,
1474  0,
1475  REG_DWORD,
1476  &Count,
1477  sizeof(Count));
1478  if (!NT_SUCCESS(Status))
1479  goto done;
1480 
1481  /* Set the new NextInstance value */
1482  RtlInitUnicodeString(&ValueName, L"NextInstance");
1483  Status = ZwSetValueKey(ServiceEnumKey,
1484  &ValueName,
1485  0,
1486  REG_DWORD,
1487  &NextInstance,
1488  sizeof(NextInstance));
1489  }
1490 
1491 done:
1492  if (ServiceEnumKey != NULL)
1493  ZwClose(ServiceEnumKey);
1494 
1495  if (ServiceKey != NULL)
1496  ZwClose(ServiceKey);
1497 
1498  ExFreePool(ServiceKeyName.Buffer);
1499  ExFreePool(kvInfo2);
1500 
1501  return Status;
1502 }
1503 
1504 static
1505 NTSTATUS
1508 {
1510  NTSTATUS Status;
1511 
1512  if (!(DeviceNode->Flags & DNF_IDS_QUERIED))
1513  {
1514  // query ids (for reported devices)
1516  HANDLE enumRootHandle, instanceHandle;
1517 
1518  // open the enumeration root key
1519  Status = IopOpenRegistryKeyEx(&enumRootHandle, NULL, &enumRoot, KEY_READ);
1520  if (!NT_SUCCESS(Status))
1521  {
1522  DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &enumRoot, Status);
1523  return Status;
1524  }
1525 
1526  // open an instance subkey
1527  Status = IopOpenRegistryKeyEx(&instanceHandle, enumRootHandle, &DeviceNode->InstancePath, KEY_READ);
1528  ZwClose(enumRootHandle);
1529  if (!NT_SUCCESS(Status))
1530  {
1531  DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
1532  &DeviceNode->InstancePath, Status);
1533  return Status;
1534  }
1535 
1536  IopQueryHardwareIds(DeviceNode, instanceHandle);
1537  IopQueryCompatibleIds(DeviceNode, instanceHandle);
1538 
1539  DeviceNode->Flags |= DNF_IDS_QUERIED;
1540  ZwClose(instanceHandle);
1541  }
1542 
1543  // we're about to start - needs enumeration
1544  DeviceNode->Flags |= DNF_REENUMERATE;
1545 
1546  DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
1547 
1549  if (!NT_SUCCESS(Status))
1550  {
1551  DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
1552  }
1553 
1554  /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
1555  IoInvalidateDeviceState(DeviceNode->PhysicalDeviceObject);
1556 
1557  DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
1558  IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
1559 
1561 
1562  return STATUS_SUCCESS;
1563 }
1564 
1565 /* PUBLIC FUNCTIONS **********************************************************/
1566 
1576 static
1577 NTSTATUS
1581 {
1582  KIRQL oldIrql;
1583 
1588 
1589  PDEVICE_OBJECT vpbDevObj = DeviceObject, targetDevice = DeviceObject;
1590 
1591  // walk the device stack down, stop on a first mounted device
1592  do
1593  {
1594  if (vpbDevObj->Vpb)
1595  {
1596  // two locks are needed here
1597  KeWaitForSingleObject(&vpbDevObj->DeviceLock, Executive, KernelMode, FALSE, NULL);
1598  IoAcquireVpbSpinLock(&oldIrql);
1599 
1601  {
1602  vpbDevObj->Vpb->Flags &= ~VPB_REMOVE_PENDING;
1603  }
1604  else
1605  {
1606  vpbDevObj->Vpb->Flags |= VPB_REMOVE_PENDING;
1607  }
1608 
1609  BOOLEAN isMounted = (_Bool)(vpbDevObj->Vpb->Flags & VPB_MOUNTED);
1610 
1611  if (isMounted)
1612  {
1613  targetDevice = vpbDevObj->Vpb->DeviceObject;
1614  }
1615 
1616  IoReleaseVpbSpinLock(oldIrql);
1617  KeSetEvent(&vpbDevObj->DeviceLock, IO_NO_INCREMENT, FALSE);
1618 
1619  if (isMounted)
1620  {
1621  break;
1622  }
1623  }
1624 
1626  vpbDevObj = vpbDevObj->AttachedDevice;
1628  } while (vpbDevObj);
1629 
1630  ASSERT(targetDevice);
1631 
1632  PVOID info;
1633  IO_STACK_LOCATION stack = {.MajorFunction = IRP_MJ_PNP, .MinorFunction = MinorFunction};
1634 
1635  return IopSynchronousCall(targetDevice, &stack, &info);
1636 }
1637 
1638 NTSTATUS
1641 
1642 static
1643 VOID
1644 NTAPI
1646 {
1648 
1650 
1651  /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1653 
1654  /* Start of HACK: update resources stored in registry, so IopDetectResourceConflict works */
1655  DeviceNode->ResourceList->Count = 0;
1656  DeviceNode->ResourceListTranslated->Count = 0;
1658  /* End of HACK */
1659 
1661  PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
1663  if (refCount != 0)
1664  {
1665  DPRINT1("Leaking device %wZ, refCount = %d\n", &DeviceNode->InstancePath, (INT32)refCount);
1666  }
1667 }
1668 
1669 static
1670 VOID
1672 {
1673  /* This function DOES dereference the device objects in all cases */
1674 
1675  ULONG i;
1676 
1677  for (i = 0; i < DeviceRelations->Count; i++)
1678  {
1679  IopSendRemoveDevice(DeviceRelations->Objects[i]);
1680  DeviceRelations->Objects[i] = NULL;
1681  }
1682 
1683  ExFreePool(DeviceRelations);
1684 }
1685 
1686 static
1687 VOID
1689 {
1690  PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1691  KIRQL OldIrql;
1692 
1694  ChildDeviceNode = ParentDeviceNode->Child;
1695  while (ChildDeviceNode != NULL)
1696  {
1697  NextDeviceNode = ChildDeviceNode->Sibling;
1699 
1700  IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1701 
1702  ChildDeviceNode = NextDeviceNode;
1703 
1705  }
1707 }
1708 
1709 static
1710 VOID
1711 NTAPI
1713 {
1715  /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1717 }
1718 
1719 static
1720 VOID
1721 NTAPI
1723 {
1724  /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1726 
1727  PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
1728 }
1729 
1730 static
1731 VOID
1733 {
1734  PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1735  KIRQL OldIrql;
1736 
1738  ChildDeviceNode = ParentDeviceNode->Child;
1739  while (ChildDeviceNode != NULL)
1740  {
1741  NextDeviceNode = ChildDeviceNode->Sibling;
1743 
1745 
1746  ChildDeviceNode = NextDeviceNode;
1747 
1749  }
1751 }
1752 
1753 static
1754 VOID
1756 {
1757  /* This function DOES dereference the device objects in all cases */
1758 
1759  ULONG i;
1760 
1761  for (i = 0; i < DeviceRelations->Count; i++)
1762  {
1763  IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1764  ObDereferenceObject(DeviceRelations->Objects[i]);
1765  DeviceRelations->Objects[i] = NULL;
1766  }
1767 
1768  ExFreePool(DeviceRelations);
1769 }
1770 
1771 static
1772 VOID
1774 {
1777  PDEVICE_RELATIONS DeviceRelations;
1778  NTSTATUS Status;
1779 
1781 
1782  Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1783 
1785  &IoStatusBlock,
1787  &Stack);
1788  if (!NT_SUCCESS(Status))
1789  {
1790  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1791  DeviceRelations = NULL;
1792  }
1793  else
1794  {
1795  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1796  }
1797 
1798  if (DeviceRelations)
1799  IopCancelRemoveDeviceRelations(DeviceRelations);
1800 }
1801 
1802 static
1803 NTSTATUS
1804 NTAPI
1806 {
1808  NTSTATUS Status;
1809 
1810  ASSERT(DeviceNode);
1811 
1812  IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1813  &DeviceNode->InstancePath);
1814 
1816 
1817  PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
1818 
1819  if (!NT_SUCCESS(Status))
1820  {
1821  DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1822  IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1823  &DeviceNode->InstancePath);
1824  }
1825 
1826  return Status;
1827 }
1828 
1829 static
1830 NTSTATUS
1832 {
1833  PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1834  NTSTATUS Status;
1835  KIRQL OldIrql;
1836 
1838  ChildDeviceNode = ParentDeviceNode->Child;
1839  while (ChildDeviceNode != NULL)
1840  {
1841  NextDeviceNode = ChildDeviceNode->Sibling;
1844 
1846  if (!NT_SUCCESS(Status))
1847  {
1848  FailedRemoveDevice = ChildDeviceNode;
1849  goto cleanup;
1850  }
1851 
1853  ChildDeviceNode = NextDeviceNode;
1854  }
1856 
1857  return STATUS_SUCCESS;
1858 
1859 cleanup:
1861  ChildDeviceNode = ParentDeviceNode->Child;
1862  while (ChildDeviceNode != NULL)
1863  {
1864  NextDeviceNode = ChildDeviceNode->Sibling;
1866 
1868 
1869  /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1870  * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1871  if (ChildDeviceNode == FailedRemoveDevice)
1872  return Status;
1873 
1874  ChildDeviceNode = NextDeviceNode;
1875 
1877  }
1879 
1880  return Status;
1881 }
1882 
1883 static
1884 NTSTATUS
1886 {
1887  /* This function DOES NOT dereference the device objects on SUCCESS
1888  * but it DOES dereference device objects on FAILURE */
1889 
1890  ULONG i, j;
1891  NTSTATUS Status;
1892 
1893  for (i = 0; i < DeviceRelations->Count; i++)
1894  {
1895  Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1896  if (!NT_SUCCESS(Status))
1897  {
1898  j = i;
1899  goto cleanup;
1900  }
1901  }
1902 
1903  return STATUS_SUCCESS;
1904 
1905 cleanup:
1906  /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1907  * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1908  for (i = 0; i <= j; i++)
1909  {
1910  IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1911  ObDereferenceObject(DeviceRelations->Objects[i]);
1912  DeviceRelations->Objects[i] = NULL;
1913  }
1914  for (; i < DeviceRelations->Count; i++)
1915  {
1916  ObDereferenceObject(DeviceRelations->Objects[i]);
1917  DeviceRelations->Objects[i] = NULL;
1918  }
1919  ExFreePool(DeviceRelations);
1920 
1921  return Status;
1922 }
1923 
1924 static
1925 NTSTATUS
1927 {
1931  PDEVICE_RELATIONS DeviceRelations;
1932  NTSTATUS Status;
1933 
1934  if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
1935  {
1936  DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
1937  return STATUS_UNSUCCESSFUL;
1938  }
1939 
1941  {
1942  DPRINT1("Removal vetoed by failing the query remove request\n");
1943 
1945 
1946  return STATUS_UNSUCCESSFUL;
1947  }
1948 
1949  Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1950 
1952  &IoStatusBlock,
1954  &Stack);
1955  if (!NT_SUCCESS(Status))
1956  {
1957  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1958  DeviceRelations = NULL;
1959  }
1960  else
1961  {
1962  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1963  }
1964 
1965  if (DeviceRelations)
1966  {
1967  Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
1968  if (!NT_SUCCESS(Status))
1969  return Status;
1970  }
1971 
1973  if (!NT_SUCCESS(Status))
1974  {
1975  if (DeviceRelations)
1976  IopCancelRemoveDeviceRelations(DeviceRelations);
1977  return Status;
1978  }
1979 
1980  if (DeviceRelations)
1981  IopSendRemoveDeviceRelations(DeviceRelations);
1983 
1984  return STATUS_SUCCESS;
1985 }
1986 
1987 static
1988 NTSTATUS
1990 {
1991  NTSTATUS Status;
1992 
1993  // This function removes the device subtree, with the root in DeviceNode
1994  // atm everyting is in fact done inside this function, which is completely wrong.
1995  // The right implementation should have a separate removal worker thread and
1996  // properly do device node state transitions
1997 
1998  DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
1999 
2000  BOOLEAN surpriseRemoval = (_Bool)(DeviceNode->Flags & DNF_DEVICE_GONE);
2001 
2002  Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, surpriseRemoval);
2003 
2004  if (surpriseRemoval)
2005  {
2006  IopSendSurpriseRemoval(DeviceNode->PhysicalDeviceObject);
2007  IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL, &DeviceNode->InstancePath);
2008  }
2009 
2010  if (NT_SUCCESS(Status))
2011  {
2012  IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
2013  if (surpriseRemoval)
2014  {
2015  IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL, &DeviceNode->InstancePath);
2016  }
2017  return STATUS_SUCCESS;
2018  }
2019 
2020  return Status;
2021 }
2022 
2023 /*
2024  * @implemented
2025  */
2026 VOID
2027 NTAPI
2029 {
2031  PNP_DEVICE_STATE PnPFlags;
2032  NTSTATUS Status;
2033 
2035  if (!NT_SUCCESS(Status))
2036  {
2038  {
2039  DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status);
2040  }
2041  return;
2042  }
2043 
2044  if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
2045  DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
2046  else
2047  DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
2048 
2049  if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
2050  DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
2051  else
2052  DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
2053 
2054  if ((PnPFlags & PNP_DEVICE_REMOVED) ||
2055  ((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
2056  {
2057  /* Flag it if it's failed */
2058  if (PnPFlags & PNP_DEVICE_FAILED)
2059  {
2061  }
2062 
2063  DeviceNode->Flags |= DNF_DEVICE_GONE;
2065  }
2066  // it doesn't work anyway. A real resource rebalancing should be implemented
2067 #if 0
2068  else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
2069  {
2070  /* Stop for resource rebalance */
2071  Status = IopStopDevice(DeviceNode);
2072  if (!NT_SUCCESS(Status))
2073  {
2074  DPRINT1("Failed to stop device for rebalancing\n");
2075 
2076  /* Stop failed so don't rebalance */
2078  }
2079  }
2080 
2081  /* Resource rebalance */
2083  {
2084  DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2085 
2087  &IoStatusBlock,
2089  NULL);
2091  {
2092  DeviceNode->BootResources =
2095  }
2096  else
2097  {
2098  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
2099  DeviceNode->BootResources = NULL;
2100  }
2101 
2102  DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2103 
2105  &IoStatusBlock,
2107  NULL);
2108  if (NT_SUCCESS(Status))
2109  {
2110  DeviceNode->ResourceRequirements =
2112  }
2113  else
2114  {
2115  DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
2116  DeviceNode->ResourceRequirements = NULL;
2117  }
2118 
2119  /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
2120  if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
2121  {
2122  DPRINT1("Restart after resource rebalance failed\n");
2123 
2124  DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
2125  DeviceNode->Flags |= DNF_START_FAILED;
2126 
2128  }
2129  }
2130 #endif
2131 }
2132 
2133 static
2134 NTSTATUS
2137 {
2138  PDEVICE_OBJECT ChildDeviceObject;
2139  PDEVICE_NODE ChildDeviceNode;
2140  ULONG i;
2141 
2142  // bus relations are already obtained for this device node
2143 
2144  if (!NT_SUCCESS(DeviceNode->CompletionStatus))
2145  {
2146  DPRINT("QDR request failed for %wZ, status %x\n",
2147  &DeviceNode->InstancePath, DeviceNode->CompletionStatus);
2148  // treat as if there are no child objects
2149  }
2150 
2151  PDEVICE_RELATIONS DeviceRelations = DeviceNode->OverUsed1.PendingDeviceRelations;
2152  DeviceNode->OverUsed1.PendingDeviceRelations = NULL;
2153 
2154  // it's acceptable not to have PDOs
2155  if (!DeviceRelations)
2156  {
2158  DPRINT("No PDOs\n");
2159  return STATUS_SUCCESS;
2160  }
2161 
2162  // mark children nodes as non-present (those not returned in DR request will be removed)
2163  for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2164  {
2165  child->Flags &= ~DNF_ENUMERATED;
2166  }
2167 
2168  DPRINT("PiEnumerateDevice: enumerating %u children\n", DeviceRelations->Count);
2169 
2170  // create device nodes for all new children and set DNF_ENUMERATED back for old ones
2171  for (i = 0; i < DeviceRelations->Count; i++)
2172  {
2173  ChildDeviceObject = DeviceRelations->Objects[i];
2174  ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);
2175 
2176  ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
2177  if (!ChildDeviceNode)
2178  {
2179  /* One doesn't exist, create it */
2180  ChildDeviceNode = PipAllocateDeviceNode(ChildDeviceObject);
2181  if (ChildDeviceNode)
2182  {
2183  PiInsertDevNode(ChildDeviceNode, DeviceNode);
2184 
2185  /* Mark the node as enumerated */
2186  ChildDeviceNode->Flags |= DNF_ENUMERATED;
2187 
2188  /* Mark the DO as bus enumerated */
2189  ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2190  }
2191  else
2192  {
2193  /* Ignore this DO */
2194  DPRINT1("PipAllocateDeviceNode() failed. Skipping PDO %u\n", i);
2195  ObDereferenceObject(ChildDeviceObject);
2196  }
2197  }
2198  else
2199  {
2200  /* Mark it as enumerated */
2201  ChildDeviceNode->Flags |= DNF_ENUMERATED;
2202  ObDereferenceObject(ChildDeviceObject);
2203  }
2204  }
2205  ExFreePool(DeviceRelations);
2206 
2207  // time to remove non-reported devices
2208  for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2209  {
2210  if (!(child->Flags & (DNF_ENUMERATED|DNF_DEVICE_GONE)))
2211  {
2212  // this flag indicates that this is a surprise removal
2213  child->Flags |= DNF_DEVICE_GONE;
2215  }
2216  }
2217 
2219  return STATUS_SUCCESS;
2220 }
2221 
2222 static
2223 NTSTATUS
2224 NTAPI
2226 {
2228  PVOID Dummy;
2229 
2231  Stack.MajorFunction = IRP_MJ_PNP;
2232  Stack.MinorFunction = IRP_MN_EJECT;
2233 
2234  return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2235 }
2236 
2237 /*
2238  * @implemented
2239  */
2240 VOID
2241 NTAPI
2243 {
2245  PDEVICE_RELATIONS DeviceRelations;
2249  NTSTATUS Status;
2250 
2251  IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2252  &DeviceNode->InstancePath);
2253 
2255  {
2256  goto cleanup;
2257  }
2258 
2259  Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2260 
2262  &IoStatusBlock,
2264  &Stack);
2265  if (!NT_SUCCESS(Status))
2266  {
2267  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2268  DeviceRelations = NULL;
2269  }
2270  else
2271  {
2272  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2273  }
2274 
2275  if (DeviceRelations)
2276  {
2277  Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2278  if (!NT_SUCCESS(Status))
2279  goto cleanup;
2280  }
2281 
2283  if (!NT_SUCCESS(Status))
2284  {
2285  if (DeviceRelations)
2286  IopCancelRemoveDeviceRelations(DeviceRelations);
2287  goto cleanup;
2288  }
2289 
2291  {
2292  if (DeviceRelations)
2293  IopCancelRemoveDeviceRelations(DeviceRelations);
2295  goto cleanup;
2296  }
2297 
2298  if (DeviceRelations)
2299  IopSendRemoveDeviceRelations(DeviceRelations);
2301 
2303  if (Capabilities.EjectSupported)
2304  {
2306  {
2307  goto cleanup;
2308  }
2309  }
2310  else
2311  {
2312  // DeviceNode->Flags |= DNF_DISABLED;
2313  }
2314 
2315  IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2316  &DeviceNode->InstancePath);
2317 
2318  return;
2319 
2320 cleanup:
2321  IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2322  &DeviceNode->InstancePath);
2323 }
2324 
2325 static
2326 VOID
2329 {
2330  NTSTATUS status;
2331  BOOLEAN doProcessAgain;
2332  PDEVICE_NODE currentNode = RootNode;
2333  PDEVICE_OBJECT referencedObject;
2334 
2335  do
2336  {
2337  doProcessAgain = FALSE;
2338 
2339  // The device can be removed during processing, but we still need its Parent and Sibling
2340  // links to continue the tree traversal. So keep the link till the and of a cycle
2341  referencedObject = currentNode->PhysicalDeviceObject;
2342  ObReferenceObject(referencedObject);
2343 
2344  // Devices with problems are skipped (unless they are not being removed)
2345  if (currentNode->Flags & DNF_HAS_PROBLEM &&
2346  currentNode->State != DeviceNodeAwaitingQueuedRemoval)
2347  {
2348  goto skipEnum;
2349  }
2350 
2351  switch (currentNode->State)
2352  {
2353  case DeviceNodeUnspecified: // this state is not used
2354  break;
2356  DPRINT("DeviceNodeUninitialized %wZ\n", &currentNode->InstancePath);
2357  status = PiInitializeDevNode(currentNode);
2358  doProcessAgain = NT_SUCCESS(status);
2359  break;
2360  case DeviceNodeInitialized:
2361  DPRINT("DeviceNodeInitialized %wZ\n", &currentNode->InstancePath);
2363  doProcessAgain = NT_SUCCESS(status);
2364  break;
2366  DPRINT("DeviceNodeDriversAdded %wZ\n", &currentNode->InstancePath);
2367  status = IopAssignDeviceResources(currentNode);
2368  doProcessAgain = NT_SUCCESS(status);
2369  break;
2371  DPRINT("DeviceNodeResourcesAssigned %wZ\n", &currentNode->InstancePath);
2372  // send IRP_MN_START_DEVICE
2373  PiIrpStartDevice(currentNode);
2374 
2375  // skip DeviceNodeStartPending, it is probably used for an async IRP_MN_START_DEVICE
2377  doProcessAgain = TRUE;
2378  break;
2379  case DeviceNodeStartPending: // skipped on XP/2003
2380  break;
2382  DPRINT("DeviceNodeStartCompletion %wZ\n", &currentNode->InstancePath);
2383  status = currentNode->CompletionStatus;
2384  doProcessAgain = TRUE;
2385  if (!NT_SUCCESS(status))
2386  {
2390 
2391  PiSetDevNodeProblem(currentNode, problem);
2393  }
2394  else
2395  {
2396  // TODO: IopDoDeferredSetInterfaceState and IopAllocateLegacyBootResources
2397  // are called here too
2398 
2400  }
2401  break;
2403  DPRINT("DeviceNodeStartPostWork %wZ\n", &currentNode->InstancePath);
2404  status = PiStartDeviceFinal(currentNode);
2405  doProcessAgain = TRUE;
2406  break;
2407  case DeviceNodeStarted:
2408  if (currentNode->Flags & DNF_REENUMERATE)
2409  {
2410  DPRINT("DeviceNodeStarted REENUMERATE %wZ\n", &currentNode->InstancePath);
2411  currentNode->Flags &= ~DNF_REENUMERATE;
2413 
2414  // again, skip DeviceNodeEnumeratePending as with the starting sequence
2416  doProcessAgain = TRUE;
2417  }
2418  break;
2420  // we're here after sending IRP_MN_QUERY_STOP_DEVICE
2421  status = currentNode->CompletionStatus;
2422  if (NT_SUCCESS(status))
2423  {
2424  PiSetDevNodeState(currentNode, DeviceNodeStopped);
2425  }
2426  else
2427  {
2428  PiIrpCancelStopDevice(currentNode);
2429  PiSetDevNodeState(currentNode, DeviceNodeStarted);
2430  }
2431  break;
2432  case DeviceNodeStopped:
2433  // TODO: do resource rebalance (not implemented)
2434  ASSERT(FALSE);
2435  break;
2437  break;
2438  case DeviceNodeEnumeratePending: // skipped on XP/2003
2439  break;
2441  DPRINT("DeviceNodeEnumerateCompletion %wZ\n", &currentNode->InstancePath);
2442  status = PiEnumerateDevice(currentNode);
2443  doProcessAgain = TRUE;
2444  break;
2446  break;
2448  DPRINT("DeviceNodeAwaitingQueuedRemoval %wZ\n", &currentNode->InstancePath);
2449  status = IopRemoveDevice(currentNode);
2450  break;
2452  break;
2454  break;
2455  case DeviceNodeRemoved:
2456  break;
2458  break;
2459  case DeviceNodeDeleted:
2460  break;
2461  default:
2462  break;
2463  }
2464 
2465 skipEnum:
2466  if (!doProcessAgain)
2467  {
2468  KIRQL OldIrql;
2470  /* If we have a child, simply go down the tree */
2471  if (currentNode->State != DeviceNodeRemoved && currentNode->Child != NULL)
2472  {
2473  ASSERT(currentNode->Child->Parent == currentNode);
2474  currentNode = currentNode->Child;
2475  }
2476  else
2477  {
2478  while (currentNode != RootNode)
2479  {
2480  /* All children processed -- go sideways */
2481  if (currentNode->Sibling != NULL)
2482  {
2483  ASSERT(currentNode->Sibling->Parent == currentNode->Parent);
2484  currentNode = currentNode->Sibling;
2485  break;
2486  }
2487  else
2488  {
2489  /* We're the last sibling -- go back up */
2490  ASSERT(currentNode->Parent->LastChild == currentNode);
2491  currentNode = currentNode->Parent;
2492  }
2493  /* We already visited the parent and all its children, so keep looking */
2494  }
2495  }
2497  }
2498  ObDereferenceObject(referencedObject);
2499  } while (doProcessAgain || currentNode != RootNode);
2500 }
2501 
2502 #ifdef DBG
2503 static
2504 PCSTR
2505 ActionToStr(
2507 {
2508  switch (Action)
2509  {
2511  return "PiActionEnumDeviceTree";
2513  return "PiActionEnumRootDevices";
2514  case PiActionResetDevice:
2515  return "PiActionResetDevice";
2517  return "PiActionAddBootDevices";
2518  case PiActionStartDevice:
2519  return "PiActionStartDevice";
2520  default:
2521  return "(request unknown)";
2522  }
2523 }
2524 #endif
2525 
2526 static
2527 VOID
2528 NTAPI
2531 {
2532  PLIST_ENTRY ListEntry;
2534  KIRQL OldIrql;
2535  PDEVICE_NODE deviceNode;
2536  NTSTATUS status;
2537 
2540  {
2543  Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2544 
2545  ASSERT(Request->DeviceObject);
2546 
2547  deviceNode = IopGetDeviceNode(Request->DeviceObject);
2548  ASSERT(deviceNode);
2549 
2551 
2552  DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2553  Request, Request->DeviceObject, ActionToStr(Request->Action));
2554 
2555  switch (Request->Action)
2556  {
2558  {
2559  if (deviceNode->State == DeviceNodeInitialized &&
2560  !(deviceNode->Flags & DNF_HAS_PROBLEM))
2561  {
2563  }
2564  break;
2565  }
2568  deviceNode->Flags |= DNF_REENUMERATE;
2569  PiDevNodeStateMachine(deviceNode);
2570  break;
2571 
2572  case PiActionResetDevice:
2573  // TODO: the operation is a no-op for everything except removed nodes
2574  // for removed nodes, it returns them back to DeviceNodeUninitialized
2576  break;
2577 
2578  case PiActionStartDevice:
2579  // This action is triggered from usermode, when a driver is installed
2580  // for a non-critical PDO
2581  if (deviceNode->State == DeviceNodeInitialized &&
2582  !(deviceNode->Flags & DNF_HAS_PROBLEM))
2583  {
2584  PiDevNodeStateMachine(deviceNode);
2585  }
2586  else
2587  {
2588  DPRINT1("NOTE: attempt to start an already started/uninitialized device %wZ\n",
2589  &deviceNode->InstancePath);
2591  }
2592  break;
2593 
2594  default:
2595  DPRINT1("Unimplemented device action %u\n", Request->Action);
2597  break;
2598  }
2599 
2600  if (Request->CompletionStatus)
2601  {
2602  *Request->CompletionStatus = status;
2603  }
2604 
2605  if (Request->CompletionEvent)
2606  {
2607  KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2608  }
2609 
2610  DPRINT("Finished processing PnP request %p\n", Request);
2611  ObDereferenceObject(Request->DeviceObject);
2614  }
2618 }
2619 
2629 VOID
2633  _In_opt_ PKEVENT CompletionEvent,
2634  _Out_opt_ NTSTATUS *CompletionStatus)
2635 {
2637  KIRQL OldIrql;
2638 
2640 
2641  DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2642  DeviceObject, Request, ActionToStr(Action));
2643 
2645 
2646  Request->DeviceObject = DeviceObject;
2647  Request->Action = Action;
2648  Request->CompletionEvent = CompletionEvent;
2649  Request->CompletionStatus = CompletionStatus;
2650 
2652  InsertTailList(&IopDeviceActionRequestList, &Request->RequestListEntry);
2653 
2655  {
2657 
2661 
2663  return;
2664  }
2665 
2667  {
2669  return;
2670  }
2674 
2677 }
2678 
2688 NTSTATUS
2692 {
2693  KEVENT opFinished;
2694  NTSTATUS status;
2695 
2697  PiQueueDeviceAction(DeviceObject, Action, &opFinished, &status);
2699 
2700  return status;
2701 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:26
#define IRP_MN_CANCEL_REMOVE_DEVICE
struct _CM_RESOURCE_LIST * PCM_RESOURCE_LIST
struct _ADD_DEV_DRIVERS_LIST ADD_DEV_DRIVERS_LIST
LIST_ENTRY IopDeviceActionRequestList
Definition: devaction.c:46
struct _ATTACH_FILTER_DRIVERS_CONTEXT * PATTACH_FILTER_DRIVERS_CONTEXT
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4155
#define IN
Definition: typedefs.h:39
return STATUS_NOT_SUPPORTED
NTSTATUS IopGetDriverNames(_In_ HANDLE ServiceHandle, _Out_ PUNICODE_STRING DriverName, _Out_opt_ PUNICODE_STRING ServiceName)
Definition: driver.c:125
ULONG Flags
Definition: iotypes.h:847
static NTSTATUS PiInitializeDevNode(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1189
#define STATUS_PLUGPLAY_NO_DEVICE
Definition: ntstatus.h:731
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:850
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1831
#define IRP_MN_QUERY_RESOURCES
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
static VOID IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1732
static NTSTATUS PiEnumerateDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2135
#define IRP_MN_REMOVE_DEVICE
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IRP_MN_QUERY_ID
struct _ATTACH_FILTER_DRIVERS_CONTEXT ATTACH_FILTER_DRIVERS_CONTEXT
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static VOID PiDevNodeStateMachine(_In_ PDEVICE_NODE RootNode)
Definition: devaction.c:2327
#define DNF_HAS_PROBLEM
Definition: iotypes.h:183
#define TAG_IO
Definition: tag.h:69
#define _In_opt_
Definition: ms_sal.h:309
#define PNP_DEVICE_REMOVED
Definition: iotypes.h:1004
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1805
PNP_DEVNODE_STATE PiSetDevNodeState(_In_ PDEVICE_NODE DeviceNode, _In_ PNP_DEVNODE_STATE NewState)
Definition: devnode.c:108
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS PiIrpCancelStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:154
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define _Out_
Definition: ms_sal.h:345
#define DNUF_NOT_DISABLEABLE
Definition: iotypes.h:211
Definition: http.c:7251
NTSTATUS PiIrpQueryDeviceText(_In_ PDEVICE_NODE DeviceNode, _In_ LCID LocaleId, _In_ DEVICE_TEXT_TYPE Type, _Out_ PWSTR *DeviceText)
Definition: pnpirp.c:201
#define CM_PROB_HELD_FOR_EJECT
Definition: cfg.h:77
#define KEY_READ
Definition: nt_native.h:1023
struct _DEVICE_ACTION_REQUEST DEVICE_ACTION_REQUEST
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
#define RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
Definition: green.h:16
#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
#define CM_PROB_OUT_OF_MEMORY
Definition: cfg.h:33
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:522
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
enum _CM_SERVICE_LOAD_TYPE SERVICE_LOAD_TYPE
LONG NTSTATUS
Definition: precomp.h:26
ULONG PNP_DEVICE_STATE
Definition: iotypes.h:997
DEVICE_ACTION Action
Definition: devaction.c:63
#define STATUS_FAILED_DRIVER_ENTRY
Definition: ntstatus.h:911
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1722
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
NTSYSAPI NTSTATUS NTAPI ZwQueryDefaultLocale(_In_ BOOLEAN UserProfile, _Out_ PLCID DefaultLocaleId)
#define DNF_HAS_BOOT_CONFIG
Definition: iotypes.h:176
struct _IO_RESOURCE_REQUIREMENTS_LIST * PIO_RESOURCE_REQUIREMENTS_LIST
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define CM_PROB_FAILED_START
Definition: cfg.h:40
DEVICE_CAPABILITIES
Definition: iotypes.h:965
#define CM_PROB_FAILED_POST_START
Definition: cfg.h:73
DWORD LCID
Definition: nls.h:13
static NTSTATUS PiIrpSendRemoveCheckVpb(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction)
Sends one of the remove IRPs to the device stack.
Definition: devaction.c:1578
POBJECT_TYPE IoDriverObjectType
Definition: driver.c:33
#define IRP_MN_EJECT
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define CM_PROB_FAILED_DRIVER_ENTRY
Definition: cfg.h:67
uint16_t * PWCHAR
Definition: typedefs.h:56
#define swprintf
Definition: precomp.h:40
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1155
#define InsertTailList(ListHead, Entry)
_In_ ULONG TotalLength
Definition: usbdlib.h:158
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:279
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
NTSTATUS PiIrpStartDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:87
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
struct _DEVICE_NODE * Parent
Definition: iotypes.h:836
static HWND child
Definition: cursoricon.c:298
#define PNP_DEVICE_DONT_DISPLAY_IN_UI
Definition: iotypes.h:1002
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define OBJ_OPENIF
Definition: winternl.h:229
static NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:1989
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
static NTSTATUS IopQueryHardwareIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:956
DWORD Id
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1911
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:1021
return STATUS_NOT_IMPLEMENTED
NTSTATUS NTAPI IopCreateRegistryKeyEx(OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
struct _DEVICE_NODE * Child
Definition: iotypes.h:835
KSPIN_LOCK IopDeviceActionLock
Definition: devaction.c:49
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int UINT32
#define IRP_MN_QUERY_REMOVE_DEVICE
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
#define DNUF_DONT_SHOW_IN_UI
Definition: iotypes.h:209
NTSTATUS IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:961
PDEVICE_NODE PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject)
VOID NTAPI IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:2028
LIST_ENTRY ListEntry
Definition: devaction.c:77
#define REG_MULTI_SZ
Definition: nt_native.h:1501
NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
Definition: devaction.c:853
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2282
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1697
LIST_ENTRY RequestListEntry
Definition: devaction.c:59
NTSTATUS PiPerformSyncDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
Perfom a device operation synchronously via PiQueueDeviceAction.
Definition: devaction.c:2689
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:907
PDEVICE_OBJECT DeviceObject
Definition: devaction.c:60
static NTSTATUS IopCreateDeviceInstancePath(_In_ PDEVICE_NODE DeviceNode, _Out_ PUNICODE_STRING InstancePath)
Definition: devaction.c:215
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define IopDeviceNodeSetFlag(DeviceNode, Flag)
Definition: io.h:146
VOID NTAPI IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:45
unsigned char BOOLEAN
#define TAG_PNP_DEVACTION
Definition: devaction.c:53
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4155
#define DO_BUS_ENUMERATED_DEVICE
struct _PNP_BUS_INFORMATION * PPNP_BUS_INFORMATION
PNP_DEVNODE_STATE State
Definition: iotypes.h:841
#define _In_
Definition: ms_sal.h:308
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
KEVENT PiEnumerationFinished
Definition: devaction.c:50
#define DeviceCapabilities
Definition: wingdi.h:4449
Definition: bufpool.h:45
_ADD_DEV_DRIVER_TYPE
Definition: devaction.c:66
void * PVOID
Definition: retypes.h:9
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:79
static int isMounted
Definition: fatten.c:16
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
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
enum _DEVICE_ACTION DEVICE_ACTION
KIRQL OldIrql
Definition: mm.h:1502
Definition: _stack.h:47
#define STATUS_ILL_FORMED_SERVICE_ENTRY
Definition: ntstatus.h:588
static VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1645
BOOLEAN PnpSystemInit
Definition: iomgr.c:17
Status
Definition: gdiplustypes.h:24
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
enum _ADD_DEV_DRIVER_TYPE ADD_DEV_DRIVER_TYPE
char serviceName[]
Definition: tftpd.cpp:34
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
VOID PiSetDevNodeProblem(_In_ PDEVICE_NODE DeviceNode, _In_ UINT32 Problem)
Definition: devnode.c:132
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
int Count
Definition: noreturn.cpp:7
NTSTATUS IopQueueTargetDeviceEvent(const GUID *Guid, PUNICODE_STRING DeviceIds)
Definition: plugplay.c:43
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
static BOOLEAN IopValidateID(_In_ PWCHAR Id, _In_ BUS_QUERY_ID_TYPE QueryType)
Definition: devaction.c:124
PDRIVER_OBJECT DriverObject
Definition: devaction.c:78
LPTSTR ServiceName
Definition: ServiceMain.c:15
#define PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:1005
NTSTATUS IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION IoStackLocation, OUT PVOID *Information)
#define ASSERT(a)
Definition: mode.c:44
USHORT NTAPI IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
Definition: pnpmgr.c:411
NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
Definition: pnpmgr.c:760
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSTATUS CompletionStatus
Definition: iotypes.h:845
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DNF_REENUMERATE
Definition: iotypes.h:173
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:122
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
#define CM_PROB_DISABLED_SERVICE
Definition: cfg.h:62
#define ENUM_ROOT
Definition: io.h:53
static NTSTATUS PiCallDriverAddDevice(_In_ PDEVICE_NODE DeviceNode, _In_ BOOLEAN LoadDrivers)
Loads all drivers for a device node (actual service and filters) and calls their AddDevice routine.
Definition: devaction.c:594
#define ObDereferenceObject
Definition: obfuncs.h:203
static NTSTATUS PiAttachFilterDrivers(PLIST_ENTRY DriversListHead, PDEVICE_NODE DeviceNode, HANDLE EnumSubKey, HANDLE ClassKey, BOOLEAN Lower, BOOLEAN LoadDrivers)
Calls PiAttachFilterDriversCallback for filter drivers (if any)
Definition: devaction.c:531
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
#define PNP_DEVICE_NOT_DISABLEABLE
Definition: iotypes.h:1006
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define REGSTR_VAL_CLASSGUID
Definition: regstr.h:422
static VOID IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1688
_Must_inspect_result_ _In_ KTMOBJECT_TYPE QueryType
Definition: nttmapi.h:404
static NTSTATUS NTAPI PiAttachFilterDriversCallback(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Ctx, PVOID EntryContext)
Loads and/or returns the driver associated with the registry entry if the driver is enabled....
Definition: devaction.c:362
struct _RTL_QUERY_REGISTRY_TABLE RTL_QUERY_REGISTRY_TABLE
PDEVICE_NODE PopSystemPowerDeviceNode
Definition: power.c:25
Definition: Node.h:9
static VOID NTAPI IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1712
struct _test_info info[]
Definition: SetCursorPos.c:19
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
WORK_QUEUE_ITEM IopDeviceActionWorkItem
Definition: devaction.c:47
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2529
#define IRP_MN_QUERY_BUS_INFORMATION
#define MAX_DEVICE_ID_LEN
Definition: devaction.c:40
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:240
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN PnPBootDriversInitialized
Definition: pnpinit.c:27
static const WCHAR L[]
Definition: oid.c:1250
#define DNF_DEVICE_GONE
Definition: iotypes.h:186
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define CM_PROB_DRIVER_FAILED_LOAD
Definition: cfg.h:69
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define DNF_LEGACY_DRIVER
Definition: iotypes.h:182
static NTSTATUS IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
_In_ PNDIS_STRING DeviceInstance
Definition: ndis.h:5202
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
#define PNP_DEVICE_FAILED
Definition: iotypes.h:1003
static const WCHAR Cleanup[]
Definition: register.c:80
VOID NTAPI IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:2242
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define IopDeviceNodeHasFlag(DeviceNode, Flag)
Definition: io.h:164
#define REGSTR_KEY_DEVICE_PROPERTIES
Definition: regstr.h:752
#define MAX_SEPARATORS_INSTANCEID
Definition: devaction.c:41
#define CM_PROB_NEED_RESTART
Definition: cfg.h:44
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965
UNICODE_STRING InstancePath
Definition: iotypes.h:853
#define MAXULONG
Definition: typedefs.h:251
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1671
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
PDRIVER_ADD_DEVICE AddDevice
Definition: iotypes.h:2220
static NTSTATUS NTAPI IopSendEject(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:2225
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1606
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:1455
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1773
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1885
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
NTSTATUS PiIrpQueryPnPDeviceState(_In_ PDEVICE_NODE DeviceNode, _Out_ PPNP_DEVICE_STATE DeviceState)
Definition: pnpirp.c:232
unsigned short USHORT
Definition: pedump.c:61
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
static VOID ErrorExit(LPTSTR lpszMessage)
Definition: telnetd.c:647
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PDEVICE_OBJECT NTAPI IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1385
#define STATUS_PNP_REBOOT_REQUIRED
Definition: ntstatus.h:830
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define _Out_opt_
Definition: ms_sal.h:346
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MN_QUERY_DEVICE_RELATIONS
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:834
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1755
#define DPRINT1
Definition: precomp.h:8
VOID PiNotifyTargetDeviceChange(_In_ LPCGUID Event, _In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PTARGET_DEVICE_CUSTOM_NOTIFICATION CustomNotification)
Delivers the event to all drivers subscribed to EventCategoryTargetDeviceChange PnP event.
Definition: pnpnotify.c:258
ERESOURCE IopDriverLoadResource
Definition: driver.c:19
VOID PiInsertDevNode(_In_ PDEVICE_NODE DeviceNode, _In_ PDEVICE_NODE ParentNode)
Definition: devnode.c:80
#define BOOLEAN
Definition: pedump.c:73
#define ObReferenceObject
Definition: obfuncs.h:204
static NTSTATUS PiStartDeviceFinal(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1506
static NTSTATUS IopSetServiceEnumData(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
Definition: devaction.c:1342
#define DNF_IDS_QUERIED
Definition: iotypes.h:175
#define FILE_DEVICE_ACPI
Definition: winioctl.h:156
NTSTATUS NTAPI IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:1116
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:48
#define CM_PROB_DRIVER_SERVICE_KEY_INVALID
Definition: cfg.h:70
ULONG ERESOURCE
Definition: env_spec_w32.h:594
static const WCHAR ServicesKeyName[]
Definition: devaction.c:51
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
signed int INT32
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
char * cleanup(char *str)
Definition: wpickclick.c:99
NTSTATUS * CompletionStatus
Definition: devaction.c:62
#define DNF_ENUMERATED
Definition: iotypes.h:174
VOID PiQueueDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action, _In_opt_ PKEVENT CompletionEvent, _Out_opt_ NTSTATUS *CompletionStatus)
Queue a device operation to a worker thread.
Definition: devaction.c:2630
const char * PCSTR
Definition: typedefs.h:52
#define STATUS_SUCCESS
Definition: shellext.h:65
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define CM_PROB_FAILED_ADD
Definition: cfg.h:61
#define REG_NONE
Definition: nt_native.h:1492
#define DPRINT
Definition: sndvol32.h:71
_In_ WDFDEVICE _In_ PPNP_BUS_INFORMATION BusInformation
Definition: wdfdevice.h:3912
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define REG_DWORD
Definition: sdbapi.c:596
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define VPB_MOUNTED
Definition: iotypes.h:1807
NTSTATUS PiIrpQueryDeviceRelations(_In_ PDEVICE_NODE DeviceNode, _In_ DEVICE_RELATION_TYPE Type)
Definition: pnpirp.c:176
NTSTATUS NTAPI ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, IN ULONG Attributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext, OUT PVOID *ObjectPtr)
Definition: obref.c:409
static SERVICE_STATUS status
Definition: service.c:31
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
NTSTATUS NTAPI IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIO_STATUS_BLOCK IoStatusBlock, IN UCHAR MinorFunction, IN PIO_STACK_LOCATION Stack)
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
#define MAX_SEPARATORS_DEVICEID
Definition: devaction.c:42
struct _ADD_DEV_DRIVERS_LIST * PADD_DEV_DRIVERS_LIST
#define CM_PROB_REGISTRY
Definition: cfg.h:49
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
struct _DEVICE_ACTION_REQUEST * PDEVICE_ACTION_REQUEST
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:84
VOID PiSetDevNodeText(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceKey)
Sets the DeviceNode's DeviceDesc and LocationInformation registry values.
Definition: devaction.c:1088
PDEVICE_NODE FASTCALL IopGetDeviceNode(IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:606
#define IRP_MN_QUERY_CAPABILITIES
PCONFIGURATION_COMPONENT_DATA RootNode
Definition: macharm.c:19
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1415
#define PAGED_CODE()
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define REG_SZ
Definition: layer.c:22
Definition: ps.c:97
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:271