ReactOS  0.4.15-dev-1207-g698a8e6
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;
38 
39 #define MAX_DEVICE_ID_LEN 200
40 #define MAX_SEPARATORS_INSTANCEID 0
41 #define MAX_SEPARATORS_DEVICEID 1
42 
43 /* DATA **********************************************************************/
44 
50 
51 /* TYPES *********************************************************************/
52 
53 typedef struct _DEVICE_ACTION_REQUEST
54 {
61 
62 /* FUNCTIONS *****************************************************************/
63 
66 
69 
70 USHORT
71 NTAPI
72 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid);
73 
76 
77 VOID
78 NTAPI
80 
81 static
82 VOID
84 
85 static
88 
89 static
90 BOOLEAN
92  _In_ PWCHAR Id,
94 {
95  PWCHAR PtrChar;
96  PWCHAR StringEnd;
97  WCHAR Char;
98  ULONG SeparatorsCount = 0;
99  PWCHAR PtrPrevChar = NULL;
100  ULONG MaxSeparators;
101  BOOLEAN IsMultiSz;
102 
103  PAGED_CODE();
104 
105  switch (QueryType)
106  {
107  case BusQueryDeviceID:
108  MaxSeparators = MAX_SEPARATORS_DEVICEID;
109  IsMultiSz = FALSE;
110  break;
111  case BusQueryInstanceID:
112  MaxSeparators = MAX_SEPARATORS_INSTANCEID;
113  IsMultiSz = FALSE;
114  break;
115 
116  case BusQueryHardwareIDs:
118  MaxSeparators = MAX_SEPARATORS_DEVICEID;
119  IsMultiSz = TRUE;
120  break;
121 
122  default:
123  DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
124  return FALSE;
125  }
126 
127  StringEnd = Id + MAX_DEVICE_ID_LEN;
128 
129  for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
130  {
131  Char = *PtrChar;
132 
133  if (Char == UNICODE_NULL)
134  {
135  if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
136  {
137  if (MaxSeparators == SeparatorsCount || IsMultiSz)
138  {
139  return TRUE;
140  }
141 
142  DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
143  SeparatorsCount, MaxSeparators);
144  goto ErrorExit;
145  }
146 
147  StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
148  PtrPrevChar = PtrChar;
149  SeparatorsCount = 0;
150  }
151  else if (Char < ' ' || Char > 0x7F || Char == ',')
152  {
153  DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
154  goto ErrorExit;
155  }
156  else if (Char == ' ')
157  {
158  *PtrChar = '_';
159  }
160  else if (Char == '\\')
161  {
162  SeparatorsCount++;
163 
164  if (SeparatorsCount > MaxSeparators)
165  {
166  DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
167  SeparatorsCount, MaxSeparators);
168  goto ErrorExit;
169  }
170  }
171  }
172 
173  DPRINT1("IopValidateID: Not terminated ID\n");
174 
175 ErrorExit:
176  // FIXME logging
177  return FALSE;
178 }
179 
180 static
181 NTSTATUS
184  _Out_ PUNICODE_STRING InstancePath)
185 {
187  UNICODE_STRING DeviceId;
189  IO_STACK_LOCATION Stack;
191  UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
193  BOOLEAN IsValidID;
194 
195  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
196 
197  Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
198  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
199  &IoStatusBlock,
201  &Stack);
202  if (!NT_SUCCESS(Status))
203  {
204  DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
205  return Status;
206  }
207 
209 
210  if (!IsValidID)
211  {
212  DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
213  }
214 
215  /* Save the device id string */
217 
218  DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
219 
221  if (!NT_SUCCESS(Status))
222  {
223  DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
224  RtlFreeUnicodeString(&DeviceId);
225  return Status;
226  }
227 
228  /* This bit is only check after enumeration */
229  if (DeviceCapabilities.HardwareDisabled)
230  {
231  /* FIXME: Cleanup device */
232  DeviceNode->Flags |= DNF_DISABLED;
233  RtlFreeUnicodeString(&DeviceId);
235  }
236  else
237  {
238  DeviceNode->Flags &= ~DNF_DISABLED;
239  }
240 
241  if (!DeviceCapabilities.UniqueID)
242  {
243  /* Device has not a unique ID. We need to prepend parent bus unique identifier */
244  DPRINT("Instance ID is not unique\n");
245  Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
246  if (!NT_SUCCESS(Status))
247  {
248  DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
249  RtlFreeUnicodeString(&DeviceId);
250  return Status;
251  }
252  }
253 
254  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
255 
256  Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
257  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
258  &IoStatusBlock,
260  &Stack);
261  if (!NT_SUCCESS(Status))
262  {
263  DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status);
265  }
266 
268  {
270 
271  if (!IsValidID)
272  {
273  DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
274  }
275  }
276 
279 
280  InstancePath->Length = 0;
281  InstancePath->MaximumLength = DeviceId.Length + sizeof(WCHAR) +
282  ParentIdPrefix.Length +
283  InstanceId.Length +
284  sizeof(UNICODE_NULL);
285  if (ParentIdPrefix.Length && InstanceId.Length)
286  {
287  InstancePath->MaximumLength += sizeof(WCHAR);
288  }
289 
290  InstancePath->Buffer = ExAllocatePoolWithTag(PagedPool,
291  InstancePath->MaximumLength,
292  TAG_IO);
293  if (!InstancePath->Buffer)
294  {
296  RtlFreeUnicodeString(&ParentIdPrefix);
297  RtlFreeUnicodeString(&DeviceId);
299  }
300 
301  /* Start with the device id */
302  RtlCopyUnicodeString(InstancePath, &DeviceId);
303  RtlAppendUnicodeToString(InstancePath, L"\\");
304 
305  /* Add information from parent bus device to InstancePath */
306  RtlAppendUnicodeStringToString(InstancePath, &ParentIdPrefix);
307  if (ParentIdPrefix.Length && InstanceId.Length)
308  {
309  RtlAppendUnicodeToString(InstancePath, L"&");
310  }
311 
312  /* Finally, add the id returned by the driver stack */
314 
315  /*
316  * FIXME: Check for valid characters, if there is invalid characters
317  * then bugcheck
318  */
319 
321  RtlFreeUnicodeString(&DeviceId);
322  RtlFreeUnicodeString(&ParentIdPrefix);
323 
324  return STATUS_SUCCESS;
325 }
326 
327 NTSTATUS
328 NTAPI
330  PDEVICE_CAPABILITIES DeviceCaps)
331 {
332  IO_STATUS_BLOCK StatusBlock;
333  IO_STACK_LOCATION Stack;
335  HANDLE InstanceKey;
337 
338  /* Set up the Header */
339  RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
340  DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
341  DeviceCaps->Version = 1;
342  DeviceCaps->Address = -1;
343  DeviceCaps->UINumber = -1;
344 
345  /* Set up the Stack */
346  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
347  Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
348 
349  /* Send the IRP */
350  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
351  &StatusBlock,
353  &Stack);
354  if (!NT_SUCCESS(Status))
355  {
357  {
358  DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
359  }
360  return Status;
361  }
362 
363  /* Map device capabilities to capability flags */
364  DeviceNode->CapabilityFlags = 0;
365  if (DeviceCaps->LockSupported)
366  DeviceNode->CapabilityFlags |= 0x00000001; // CM_DEVCAP_LOCKSUPPORTED
367 
368  if (DeviceCaps->EjectSupported)
369  DeviceNode->CapabilityFlags |= 0x00000002; // CM_DEVCAP_EJECTSUPPORTED
370 
371  if (DeviceCaps->Removable)
372  DeviceNode->CapabilityFlags |= 0x00000004; // CM_DEVCAP_REMOVABLE
373 
374  if (DeviceCaps->DockDevice)
375  DeviceNode->CapabilityFlags |= 0x00000008; // CM_DEVCAP_DOCKDEVICE
376 
377  if (DeviceCaps->UniqueID)
378  DeviceNode->CapabilityFlags |= 0x00000010; // CM_DEVCAP_UNIQUEID
379 
380  if (DeviceCaps->SilentInstall)
381  DeviceNode->CapabilityFlags |= 0x00000020; // CM_DEVCAP_SILENTINSTALL
382 
383  if (DeviceCaps->RawDeviceOK)
384  DeviceNode->CapabilityFlags |= 0x00000040; // CM_DEVCAP_RAWDEVICEOK
385 
386  if (DeviceCaps->SurpriseRemovalOK)
387  DeviceNode->CapabilityFlags |= 0x00000080; // CM_DEVCAP_SURPRISEREMOVALOK
388 
389  if (DeviceCaps->HardwareDisabled)
390  DeviceNode->CapabilityFlags |= 0x00000100; // CM_DEVCAP_HARDWAREDISABLED
391 
392  if (DeviceCaps->NonDynamic)
393  DeviceNode->CapabilityFlags |= 0x00000200; // CM_DEVCAP_NONDYNAMIC
394 
395  if (DeviceCaps->NoDisplayInUI)
396  DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
397  else
398  DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
399 
400  Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
401  if (NT_SUCCESS(Status))
402  {
403  /* Set 'Capabilities' value */
404  RtlInitUnicodeString(&ValueName, L"Capabilities");
405  Status = ZwSetValueKey(InstanceKey,
406  &ValueName,
407  0,
408  REG_DWORD,
409  &DeviceNode->CapabilityFlags,
410  sizeof(ULONG));
411 
412  /* Set 'UINumber' value */
413  if (DeviceCaps->UINumber != MAXULONG)
414  {
415  RtlInitUnicodeString(&ValueName, L"UINumber");
416  Status = ZwSetValueKey(InstanceKey,
417  &ValueName,
418  0,
419  REG_DWORD,
420  &DeviceCaps->UINumber,
421  sizeof(ULONG));
422  }
423 
424  ZwClose(InstanceKey);
425  }
426 
427  return Status;
428 }
429 
430 static
431 NTSTATUS
433  HANDLE InstanceKey)
434 {
435  IO_STACK_LOCATION Stack;
437  PWSTR Ptr;
441  BOOLEAN IsValidID;
442 
443  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
444 
445  RtlZeroMemory(&Stack, sizeof(Stack));
446  Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
447  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
448  &IoStatusBlock,
450  &Stack);
451  if (NT_SUCCESS(Status))
452  {
454 
455  if (!IsValidID)
456  {
457  DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
458  }
459 
460  TotalLength = 0;
461 
463  DPRINT("Hardware IDs:\n");
464  while (*Ptr)
465  {
466  DPRINT(" %S\n", Ptr);
467  Length = (ULONG)wcslen(Ptr) + 1;
468 
469  Ptr += Length;
470  TotalLength += Length;
471  }
472  DPRINT("TotalLength: %hu\n", TotalLength);
473  DPRINT("\n");
474 
475  RtlInitUnicodeString(&ValueName, L"HardwareID");
476  Status = ZwSetValueKey(InstanceKey,
477  &ValueName,
478  0,
479  REG_MULTI_SZ,
481  (TotalLength + 1) * sizeof(WCHAR));
482  if (!NT_SUCCESS(Status))
483  {
484  DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
485  }
486  }
487  else
488  {
489  DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
490  }
491 
492  return Status;
493 }
494 
495 static
496 NTSTATUS
498  HANDLE InstanceKey)
499 {
500  IO_STACK_LOCATION Stack;
502  PWSTR Ptr;
506  BOOLEAN IsValidID;
507 
508  DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
509 
510  RtlZeroMemory(&Stack, sizeof(Stack));
511  Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
512  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
513  &IoStatusBlock,
515  &Stack);
517  {
519 
520  if (!IsValidID)
521  {
522  DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
523  }
524 
525  TotalLength = 0;
526 
528  DPRINT("Compatible IDs:\n");
529  while (*Ptr)
530  {
531  DPRINT(" %S\n", Ptr);
532  Length = (ULONG)wcslen(Ptr) + 1;
533 
534  Ptr += Length;
535  TotalLength += Length;
536  }
537  DPRINT("TotalLength: %hu\n", TotalLength);
538  DPRINT("\n");
539 
540  RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
541  Status = ZwSetValueKey(InstanceKey,
542  &ValueName,
543  0,
544  REG_MULTI_SZ,
546  (TotalLength + 1) * sizeof(WCHAR));
547  if (!NT_SUCCESS(Status))
548  {
549  DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
550  }
551  }
552  else
553  {
554  DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
555  }
556 
557  return Status;
558 }
559 
560 /*
561  * IopActionInterrogateDeviceStack
562  *
563  * Retrieve information for all (direct) child nodes of a parent node.
564  *
565  * Parameters
566  * DeviceNode
567  * Pointer to device node.
568  * Context
569  * Pointer to parent node to retrieve child node information for.
570  *
571  * Remarks
572  * Any errors that occur are logged instead so that all child services have a chance
573  * of being interrogated.
574  */
575 
576 NTSTATUS
578  PVOID Context)
579 {
582  PWSTR LocationInformation;
583  PDEVICE_NODE ParentDeviceNode;
584  IO_STACK_LOCATION Stack;
587  LCID LocaleId;
588  HANDLE InstanceKey = NULL;
590  UNICODE_STRING InstancePathU;
591  PDEVICE_OBJECT OldDeviceObject;
592 
593  DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
594  DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
595 
596  ParentDeviceNode = (PDEVICE_NODE)Context;
597 
598  /*
599  * We are called for the parent too, but we don't need to do special
600  * handling for this node
601  */
602  if (DeviceNode == ParentDeviceNode)
603  {
604  DPRINT("Success\n");
605  return STATUS_SUCCESS;
606  }
607 
608  /*
609  * Make sure this device node is a direct child of the parent device node
610  * that is given as an argument
611  */
612  if (DeviceNode->Parent != ParentDeviceNode)
613  {
614  DPRINT("Skipping 2+ level child\n");
615  return STATUS_SUCCESS;
616  }
617 
618  /* Skip processing if it was already completed before */
619  if (DeviceNode->Flags & DNF_PROCESSED)
620  {
621  /* Nothing to do */
622  return STATUS_SUCCESS;
623  }
624 
625  /* Get Locale ID */
626  Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
627  if (!NT_SUCCESS(Status))
628  {
629  DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status);
630  return Status;
631  }
632 
633  /*
634  * FIXME: For critical errors, cleanup and disable device, but always
635  * return STATUS_SUCCESS.
636  */
637 
638  Status = IopCreateDeviceInstancePath(DeviceNode, &InstancePathU);
639  if (!NT_SUCCESS(Status))
640  {
642  {
643  DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
644  }
645 
646  /* We have to return success otherwise we abort the traverse operation */
647  return STATUS_SUCCESS;
648  }
649 
650  /* Verify that this is not a duplicate */
651  OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
652  if (OldDeviceObject != NULL)
653  {
654  PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
655 
656  DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
657  DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
658  DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
659 
660  KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
661  0x01,
662  (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
663  (ULONG_PTR)OldDeviceObject,
664  0);
665  }
666 
667  DeviceNode->InstancePath = InstancePathU;
668 
669  DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
670 
671  /*
672  * Create registry key for the instance id, if it doesn't exist yet
673  */
674  Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
675  if (!NT_SUCCESS(Status))
676  {
677  DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
678 
679  /* We have to return success otherwise we abort the traverse operation */
680  return STATUS_SUCCESS;
681  }
682 
683  IopQueryHardwareIds(DeviceNode, InstanceKey);
684 
685  IopQueryCompatibleIds(DeviceNode, InstanceKey);
686 
687  DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
688 
689  Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
690  Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
691  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
692  &IoStatusBlock,
694  &Stack);
696  : NULL;
697  /* This key is mandatory, so even if the Irp fails, we still write it */
698  RtlInitUnicodeString(&ValueName, L"DeviceDesc");
699  if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
700  {
701  if (DeviceDescription &&
703  {
704  /* This key is overriden when a driver is installed. Don't write the
705  * new description if another one already exists */
706  Status = ZwSetValueKey(InstanceKey,
707  &ValueName,
708  0,
709  REG_SZ,
711  ((ULONG)wcslen(DeviceDescription) + 1) * sizeof(WCHAR));
712  }
713  else
714  {
715  UNICODE_STRING DeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
716  DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status);
717 
718  Status = ZwSetValueKey(InstanceKey,
719  &ValueName,
720  0,
721  REG_SZ,
722  DeviceDesc.Buffer,
723  DeviceDesc.MaximumLength);
724  if (!NT_SUCCESS(Status))
725  {
726  DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status);
727  }
728 
729  }
730  }
731 
732  if (DeviceDescription)
733  {
735  }
736 
737  DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
738 
739  Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
740  Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
741  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
742  &IoStatusBlock,
744  &Stack);
746  {
747  LocationInformation = (PWSTR)IoStatusBlock.Information;
748  DPRINT("LocationInformation: %S\n", LocationInformation);
749  RtlInitUnicodeString(&ValueName, L"LocationInformation");
750  Status = ZwSetValueKey(InstanceKey,
751  &ValueName,
752  0,
753  REG_SZ,
754  LocationInformation,
755  ((ULONG)wcslen(LocationInformation) + 1) * sizeof(WCHAR));
756  if (!NT_SUCCESS(Status))
757  {
758  DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
759  }
760 
761  ExFreePoolWithTag(LocationInformation, 0);
762  }
763  else
764  {
765  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
766  }
767 
768  DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
769 
770  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
771  &IoStatusBlock,
773  NULL);
775  {
777 
778  DeviceNode->ChildBusNumber = BusInformation->BusNumber;
779  DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
780  DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
781  ExFreePoolWithTag(BusInformation, 0);
782  }
783  else
784  {
785  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
786 
787  DeviceNode->ChildBusNumber = 0xFFFFFFF0;
788  DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
789  DeviceNode->ChildBusTypeIndex = -1;
790  }
791 
792  DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
793 
794  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
795  &IoStatusBlock,
797  NULL);
799  {
802  }
803  else
804  {
805  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
806  DeviceNode->BootResources = NULL;
807  }
808 
809  DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
810 
811  Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
812  &IoStatusBlock,
814  NULL);
815  if (NT_SUCCESS(Status))
816  {
818  }
819  else
820  {
821  DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
822  DeviceNode->ResourceRequirements = NULL;
823  }
824 
825  if (InstanceKey != NULL)
826  {
827  IopSetDeviceInstanceData(InstanceKey, DeviceNode);
828  }
829 
830  ZwClose(InstanceKey);
831 
833 
835  {
836  /* Report the device to the user-mode pnp manager */
837  IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
838  &DeviceNode->InstancePath);
839  }
840 
841  return STATUS_SUCCESS;
842 }
843 
844 /*
845  * IopActionConfigureChildServices
846  *
847  * Retrieve configuration for all (direct) child nodes of a parent node.
848  *
849  * Parameters
850  * DeviceNode
851  * Pointer to device node.
852  * Context
853  * Pointer to parent node to retrieve child node configuration for.
854  *
855  * Remarks
856  * Any errors that occur are logged instead so that all child services have a chance of beeing
857  * configured.
858  */
859 
860 NTSTATUS
862  PVOID Context)
863 {
865  PDEVICE_NODE ParentDeviceNode;
869  DEVICE_CAPABILITIES DeviceCaps;
870 
871  DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
872 
873  ParentDeviceNode = (PDEVICE_NODE)Context;
874 
875  /*
876  * We are called for the parent too, but we don't need to do special
877  * handling for this node
878  */
879  if (DeviceNode == ParentDeviceNode)
880  {
881  DPRINT("Success\n");
882  return STATUS_SUCCESS;
883  }
884 
885  /*
886  * Make sure this device node is a direct child of the parent device node
887  * that is given as an argument
888  */
889 
890  if (DeviceNode->Parent != ParentDeviceNode)
891  {
892  DPRINT("Skipping 2+ level child\n");
893  return STATUS_SUCCESS;
894  }
895 
896  if (!(DeviceNode->Flags & DNF_PROCESSED))
897  {
898  DPRINT1("Child not ready to be configured\n");
899  return STATUS_SUCCESS;
900  }
901 
902  if (!(DeviceNode->Flags & (DNF_DISABLED | DNF_STARTED | DNF_ADDED)))
903  {
904  UNICODE_STRING RegKey;
905 
906  /* Install the service for this if it's in the CDDB */
908 
909  /*
910  * Retrieve configuration from Enum key
911  */
912 
913  Service = &DeviceNode->ServiceName;
914 
918 
919  QueryTable[0].Name = L"Service";
922 
923  QueryTable[1].Name = L"ClassGUID";
927  QueryTable[1].DefaultData = L"";
928  QueryTable[1].DefaultLength = 0;
929 
930  RegKey.Length = 0;
931  RegKey.MaximumLength = sizeof(ENUM_ROOT) + sizeof(WCHAR) + DeviceNode->InstancePath.Length;
933  RegKey.MaximumLength,
934  TAG_IO);
935  if (RegKey.Buffer == NULL)
936  {
939  }
940 
942  RtlAppendUnicodeToString(&RegKey, L"\\");
943  RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
944 
946  RegKey.Buffer, QueryTable, NULL, NULL);
948 
949  if (!NT_SUCCESS(Status))
950  {
951  /* FIXME: Log the error */
952  DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
953  &DeviceNode->InstancePath, Status);
955  return STATUS_SUCCESS;
956  }
957 
958  if (Service->Buffer == NULL)
959  {
960  if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps)) &&
961  DeviceCaps.RawDeviceOK)
962  {
963  DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
964  RtlInitEmptyUnicodeString(&DeviceNode->ServiceName, NULL, 0);
965  }
966  else if (ClassGUID.Length != 0)
967  {
968  /* Device has a ClassGUID value, but no Service value.
969  * Suppose it is using the NULL driver, so state the
970  * device is started */
971  DPRINT("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
973  }
974  else
975  {
978  }
979  return STATUS_SUCCESS;
980  }
981 
982  DPRINT("Got Service %S\n", Service->Buffer);
983  }
984 
985  return STATUS_SUCCESS;
986 }
987 
988 /*
989  * IopActionInitChildServices
990  *
991  * Initialize the service for all (direct) child nodes of a parent node
992  *
993  * Parameters
994  * DeviceNode
995  * Pointer to device node.
996  * Context
997  * Pointer to parent node to initialize child node services for.
998  *
999  * Remarks
1000  * If the driver image for a service is not loaded and initialized
1001  * it is done here too. Any errors that occur are logged instead so
1002  * that all child services have a chance of being initialized.
1003  */
1004 
1005 NTSTATUS
1007  PVOID Context)
1008 {
1009  PDEVICE_NODE ParentDeviceNode;
1010  NTSTATUS Status;
1011  BOOLEAN BootDrivers = !PnpSystemInit;
1012 
1013  DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode, Context);
1014 
1015  ParentDeviceNode = Context;
1016 
1017  /*
1018  * We are called for the parent too, but we don't need to do special
1019  * handling for this node
1020  */
1021  if (DeviceNode == ParentDeviceNode)
1022  {
1023  DPRINT("Success\n");
1024  return STATUS_SUCCESS;
1025  }
1026 
1027  /*
1028  * We don't want to check for a direct child because
1029  * this function is called during boot to reinitialize
1030  * devices with drivers that couldn't load yet due to
1031  * stage 0 limitations (ie can't load from disk yet).
1032  */
1033 
1034  if (!(DeviceNode->Flags & DNF_PROCESSED))
1035  {
1036  DPRINT1("Child not ready to be added\n");
1037  return STATUS_SUCCESS;
1038  }
1039 
1043  return STATUS_SUCCESS;
1044 
1045  if (DeviceNode->ServiceName.Buffer == NULL)
1046  {
1047  /* We don't need to worry about loading the driver because we're
1048  * being driven in raw mode so our parent must be loaded to get here */
1050  if (NT_SUCCESS(Status))
1051  {
1053  if (!NT_SUCCESS(Status))
1054  {
1055  DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
1056  &DeviceNode->InstancePath, Status);
1057  }
1058  }
1059  }
1060  else
1061  {
1062  PLDR_DATA_TABLE_ENTRY ModuleObject;
1064 
1067  /* Get existing DriverObject pointer (in case the driver has
1068  already been loaded and initialized) */
1070  &DriverObject,
1071  &DeviceNode->ServiceName,
1072  FALSE);
1073 
1074  if (!NT_SUCCESS(Status))
1075  {
1076  /* Driver is not initialized, try to load it */
1077  Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
1078 
1080  {
1081  /* Initialize the driver */
1083  &DeviceNode->ServiceName, FALSE, &DriverObject);
1084  if (!NT_SUCCESS(Status))
1086  }
1088  {
1089  DPRINT1("Service '%wZ' is disabled\n", &DeviceNode->ServiceName);
1091  }
1092  else
1093  {
1094  DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
1095  &DeviceNode->ServiceName, Status);
1096  if (!BootDrivers)
1098  }
1099  }
1102 
1103  /* Driver is loaded and initialized at this point */
1104  if (NT_SUCCESS(Status))
1105  {
1106  /* Initialize the device, including all filters */
1108 
1109  /* Remove the extra reference */
1111  }
1112  else
1113  {
1114  /*
1115  * Don't disable when trying to load only boot drivers
1116  */
1117  if (!BootDrivers)
1118  {
1120  }
1121  }
1122  }
1123 
1124  return STATUS_SUCCESS;
1125 }
1126 
1127 static
1128 NTSTATUS
1130 {
1131  UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1132  UNICODE_STRING ServiceKeyName;
1133  UNICODE_STRING EnumKeyName;
1135  PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
1136  HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1138  ULONG Count = 0, NextInstance = 0;
1139  WCHAR ValueBuffer[6];
1141 
1142  DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1143  DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1144  DPRINT("Service: %wZ\n", &DeviceNode->ServiceName);
1145 
1146  if (DeviceNode->ServiceName.Buffer == NULL)
1147  {
1148  DPRINT1("No service!\n");
1149  return STATUS_SUCCESS;
1150  }
1151 
1152  ServiceKeyName.MaximumLength = ServicesKeyPath.Length + DeviceNode->ServiceName.Length + sizeof(UNICODE_NULL);
1153  ServiceKeyName.Length = 0;
1154  ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1155  if (ServiceKeyName.Buffer == NULL)
1156  {
1157  DPRINT1("No ServiceKeyName.Buffer!\n");
1159  }
1160 
1161  RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1162  RtlAppendUnicodeStringToString(&ServiceKeyName, &DeviceNode->ServiceName);
1163 
1164  DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1165 
1166  Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1167  if (!NT_SUCCESS(Status))
1168  {
1169  goto done;
1170  }
1171 
1172  RtlInitUnicodeString(&EnumKeyName, L"Enum");
1173  Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1174  ServiceKey,
1175  &EnumKeyName,
1176  KEY_SET_VALUE,
1178  &Disposition);
1179  if (NT_SUCCESS(Status))
1180  {
1182  {
1183  /* Read the NextInstance value */
1184  Status = IopGetRegistryValue(ServiceEnumKey,
1185  L"Count",
1186  &KeyValueInformation);
1187  if (!NT_SUCCESS(Status))
1188  goto done;
1189 
1190  if ((KeyValueInformation->Type == REG_DWORD) &&
1191  (KeyValueInformation->DataLength))
1192  {
1193  /* Read it */
1194  Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1195  KeyValueInformation->DataOffset);
1196  }
1197 
1198  ExFreePool(KeyValueInformation);
1199  KeyValueInformation = NULL;
1200 
1201  /* Read the NextInstance value */
1202  Status = IopGetRegistryValue(ServiceEnumKey,
1203  L"NextInstance",
1204  &KeyValueInformation);
1205  if (!NT_SUCCESS(Status))
1206  goto done;
1207 
1208  if ((KeyValueInformation->Type == REG_DWORD) &&
1209  (KeyValueInformation->DataLength))
1210  {
1211  NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1212  KeyValueInformation->DataOffset);
1213  }
1214 
1215  ExFreePool(KeyValueInformation);
1216  KeyValueInformation = NULL;
1217  }
1218 
1219  /* Set the instance path */
1220  swprintf(ValueBuffer, L"%lu", NextInstance);
1221  RtlInitUnicodeString(&ValueName, ValueBuffer);
1222  Status = ZwSetValueKey(ServiceEnumKey,
1223  &ValueName,
1224  0,
1225  REG_SZ,
1226  DeviceNode->InstancePath.Buffer,
1227  DeviceNode->InstancePath.MaximumLength);
1228  if (!NT_SUCCESS(Status))
1229  goto done;
1230 
1231  /* Increment Count and NextInstance */
1232  Count++;
1233  NextInstance++;
1234 
1235  /* Set the new Count value */
1236  RtlInitUnicodeString(&ValueName, L"Count");
1237  Status = ZwSetValueKey(ServiceEnumKey,
1238  &ValueName,
1239  0,
1240  REG_DWORD,
1241  &Count,
1242  sizeof(Count));
1243  if (!NT_SUCCESS(Status))
1244  goto done;
1245 
1246  /* Set the new NextInstance value */
1247  RtlInitUnicodeString(&ValueName, L"NextInstance");
1248  Status = ZwSetValueKey(ServiceEnumKey,
1249  &ValueName,
1250  0,
1251  REG_DWORD,
1252  &NextInstance,
1253  sizeof(NextInstance));
1254  }
1255 
1256 done:
1257  if (ServiceEnumKey != NULL)
1258  ZwClose(ServiceEnumKey);
1259 
1260  if (ServiceKey != NULL)
1261  ZwClose(ServiceKey);
1262 
1263  ExFreePool(ServiceKeyName.Buffer);
1264 
1265  return Status;
1266 }
1267 
1268 static
1269 VOID
1270 NTAPI
1272 {
1273  IO_STACK_LOCATION Stack;
1275  NTSTATUS Status;
1276  PVOID Dummy;
1278 
1279  /* Get the device node */
1281 
1282  ASSERT(!(DeviceNode->Flags & DNF_DISABLED));
1283 
1284  /* Build the I/O stack location */
1285  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1286  Stack.MajorFunction = IRP_MJ_PNP;
1288 
1289  Stack.Parameters.StartDevice.AllocatedResources =
1290  DeviceNode->ResourceList;
1291  Stack.Parameters.StartDevice.AllocatedResourcesTranslated =
1292  DeviceNode->ResourceListTranslated;
1293 
1294  /* Do the call */
1295  Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1296  if (!NT_SUCCESS(Status))
1297  {
1298  /* Send an IRP_MN_REMOVE_DEVICE request */
1300 
1301  /* Set the appropriate flag */
1302  DeviceNode->Flags |= DNF_START_FAILED;
1303  DeviceNode->Problem = CM_PROB_FAILED_START;
1304 
1305  DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode->InstancePath, Status);
1306  return;
1307  }
1308 
1309  DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
1310 
1312  if (!NT_SUCCESS(Status))
1313  {
1314  DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
1315  }
1316 
1317  /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
1319 
1320  /* Otherwise, mark us as started */
1321  DeviceNode->Flags |= DNF_STARTED;
1322  DeviceNode->Flags &= ~DNF_STOPPED;
1323 
1324  /* We now need enumeration */
1326 }
1327 
1328 static
1329 NTSTATUS
1330 NTAPI
1332 {
1334  NTSTATUS Status;
1335  PAGED_CODE();
1336 
1337  /* Sanity check */
1338  ASSERT((DeviceNode->Flags & DNF_ADDED));
1342 
1343  /* Get the device object */
1344  DeviceObject = DeviceNode->PhysicalDeviceObject;
1345 
1346  /* Check if we're not started yet */
1347  if (!(DeviceNode->Flags & DNF_STARTED))
1348  {
1349  /* Start us */
1351  }
1352 
1353  /* Do we need to query IDs? This happens in the case of manual reporting */
1354 #if 0
1355  if (DeviceNode->Flags & DNF_NEED_QUERY_IDS)
1356  {
1357  DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
1358  /* And that case shouldn't happen yet */
1359  ASSERT(FALSE);
1360  }
1361 #endif
1362 
1364 
1365  /* Make sure we're started, and check if we need enumeration */
1366  if ((DeviceNode->Flags & DNF_STARTED) &&
1368  {
1369  /* Enumerate us */
1372  }
1373  else
1374  {
1375  /* Nothing to do */
1377  }
1378 
1379  /* Return */
1380  return Status;
1381 }
1382 
1383 NTSTATUS
1386 {
1387  NTSTATUS Status;
1388  HANDLE InstanceHandle = NULL, ControlHandle = NULL;
1389  UNICODE_STRING KeyName, ValueString;
1391 
1392  if (DeviceNode->Flags & DNF_DISABLED)
1393  return STATUS_SUCCESS;
1394 
1396  if (!NT_SUCCESS(Status))
1397  goto ByeBye;
1398 
1399  /* New PnP ABI */
1401 
1402  /* FIX: Should be done in new device instance code */
1403  Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceHandle);
1404  if (!NT_SUCCESS(Status))
1405  goto ByeBye;
1406 
1407  /* FIX: Should be done in IoXxxPrepareDriverLoading */
1408  // {
1409  RtlInitUnicodeString(&KeyName, L"Control");
1411  &KeyName,
1413  InstanceHandle,
1414  NULL);
1415  Status = ZwCreateKey(&ControlHandle,
1416  KEY_SET_VALUE,
1418  0,
1419  NULL,
1421  NULL);
1422  if (!NT_SUCCESS(Status))
1423  goto ByeBye;
1424 
1425  RtlInitUnicodeString(&KeyName, L"ActiveService");
1426  ValueString = DeviceNode->ServiceName;
1427  if (!ValueString.Buffer)
1428  RtlInitUnicodeString(&ValueString, L"");
1429  Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, ValueString.Buffer, ValueString.Length + sizeof(UNICODE_NULL));
1430  // }
1431 
1432 ByeBye:
1433  if (ControlHandle != NULL)
1434  ZwClose(ControlHandle);
1435 
1436  if (InstanceHandle != NULL)
1437  ZwClose(InstanceHandle);
1438 
1439  return Status;
1440 }
1441 
1442 static
1443 NTSTATUS
1444 NTAPI
1446 {
1447  IO_STACK_LOCATION Stack;
1448  PVOID Dummy;
1449 
1450  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1451  Stack.MajorFunction = IRP_MJ_PNP;
1453 
1454  return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1455 }
1456 
1457 static
1458 VOID
1459 NTAPI
1461 {
1462  IO_STACK_LOCATION Stack;
1463  PVOID Dummy;
1464 
1465  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1466  Stack.MajorFunction = IRP_MJ_PNP;
1468 
1469  /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
1470  IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1471 }
1472 
1473 NTSTATUS
1476 {
1477  NTSTATUS Status;
1478 
1479  DPRINT("Stopping device: %wZ\n", &DeviceNode->InstancePath);
1480 
1481  Status = IopQueryStopDevice(DeviceNode->PhysicalDeviceObject);
1482  if (NT_SUCCESS(Status))
1483  {
1484  IopSendStopDevice(DeviceNode->PhysicalDeviceObject);
1485 
1487  DeviceNode->Flags |= DNF_STOPPED;
1488 
1489  return STATUS_SUCCESS;
1490  }
1491 
1492  return Status;
1493 }
1494 
1495 /* PUBLIC FUNCTIONS **********************************************************/
1496 
1497 static
1498 VOID
1499 NTAPI
1501 {
1502  IO_STACK_LOCATION Stack;
1503  PVOID Dummy;
1505 
1506  /* Drop all our state for this device in case it isn't really going away */
1508 
1509  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1510  Stack.MajorFunction = IRP_MJ_PNP;
1512 
1513  /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1514  IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1515 
1518  &GUID_TARGET_DEVICE_REMOVE_COMPLETE,
1519  NULL,
1520  NULL);
1522 }
1523 
1524 static
1525 VOID
1527 {
1528  /* This function DOES dereference the device objects in all cases */
1529 
1530  ULONG i;
1531 
1532  for (i = 0; i < DeviceRelations->Count; i++)
1533  {
1534  IopSendRemoveDevice(DeviceRelations->Objects[i]);
1535  DeviceRelations->Objects[i] = NULL;
1536  }
1537 
1538  ExFreePool(DeviceRelations);
1539 }
1540 
1541 static
1542 VOID
1544 {
1545  PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1546  KIRQL OldIrql;
1547 
1549  ChildDeviceNode = ParentDeviceNode->Child;
1550  while (ChildDeviceNode != NULL)
1551  {
1552  NextDeviceNode = ChildDeviceNode->Sibling;
1554 
1555  IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1556 
1557  ChildDeviceNode = NextDeviceNode;
1558 
1560  }
1562 }
1563 
1564 static
1565 VOID
1566 NTAPI
1568 {
1569  IO_STACK_LOCATION Stack;
1570  PVOID Dummy;
1571 
1572  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1573  Stack.MajorFunction = IRP_MJ_PNP;
1575 
1576  /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1577  IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1578 }
1579 
1580 static
1581 VOID
1582 NTAPI
1584 {
1585  IO_STACK_LOCATION Stack;
1586  PVOID Dummy;
1587 
1588  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1589  Stack.MajorFunction = IRP_MJ_PNP;
1591 
1592  /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1593  IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1594 
1597  &GUID_TARGET_DEVICE_REMOVE_CANCELLED,
1598  NULL,
1599  NULL);
1600 }
1601 
1602 static
1603 VOID
1605 {
1606  PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1607  KIRQL OldIrql;
1608 
1610  ChildDeviceNode = ParentDeviceNode->Child;
1611  while (ChildDeviceNode != NULL)
1612  {
1613  NextDeviceNode = ChildDeviceNode->Sibling;
1615 
1617 
1618  ChildDeviceNode = NextDeviceNode;
1619 
1621  }
1623 }
1624 
1625 static
1626 VOID
1628 {
1629  /* This function DOES dereference the device objects in all cases */
1630 
1631  ULONG i;
1632 
1633  for (i = 0; i < DeviceRelations->Count; i++)
1634  {
1635  IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1636  ObDereferenceObject(DeviceRelations->Objects[i]);
1637  DeviceRelations->Objects[i] = NULL;
1638  }
1639 
1640  ExFreePool(DeviceRelations);
1641 }
1642 
1643 static
1644 VOID
1646 {
1647  IO_STACK_LOCATION Stack;
1649  PDEVICE_RELATIONS DeviceRelations;
1650  NTSTATUS Status;
1651 
1653 
1654  Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1655 
1657  &IoStatusBlock,
1659  &Stack);
1660  if (!NT_SUCCESS(Status))
1661  {
1662  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1663  DeviceRelations = NULL;
1664  }
1665  else
1666  {
1667  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1668  }
1669 
1670  if (DeviceRelations)
1671  IopCancelRemoveDeviceRelations(DeviceRelations);
1672 }
1673 
1674 static
1675 NTSTATUS
1676 NTAPI
1678 {
1680  IO_STACK_LOCATION Stack;
1681  PVOID Dummy;
1682  NTSTATUS Status;
1683 
1684  ASSERT(DeviceNode);
1685 
1686  IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1687  &DeviceNode->InstancePath);
1688 
1689  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1690  Stack.MajorFunction = IRP_MJ_PNP;
1692 
1693  Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy);
1694 
1697  &GUID_TARGET_DEVICE_QUERY_REMOVE,
1698  NULL,
1699  NULL);
1700 
1701  if (!NT_SUCCESS(Status))
1702  {
1703  DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1704  IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1705  &DeviceNode->InstancePath);
1706  }
1707 
1708  return Status;
1709 }
1710 
1711 static
1712 NTSTATUS
1714 {
1715  PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1716  NTSTATUS Status;
1717  KIRQL OldIrql;
1718 
1720  ChildDeviceNode = ParentDeviceNode->Child;
1721  while (ChildDeviceNode != NULL)
1722  {
1723  NextDeviceNode = ChildDeviceNode->Sibling;
1725 
1727  if (!NT_SUCCESS(Status))
1728  {
1729  FailedRemoveDevice = ChildDeviceNode;
1730  goto cleanup;
1731  }
1732 
1734  ChildDeviceNode = NextDeviceNode;
1735  }
1737 
1738  return STATUS_SUCCESS;
1739 
1740 cleanup:
1742  ChildDeviceNode = ParentDeviceNode->Child;
1743  while (ChildDeviceNode != NULL)
1744  {
1745  NextDeviceNode = ChildDeviceNode->Sibling;
1747 
1749 
1750  /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1751  * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1752  if (ChildDeviceNode == FailedRemoveDevice)
1753  return Status;
1754 
1755  ChildDeviceNode = NextDeviceNode;
1756 
1758  }
1760 
1761  return Status;
1762 }
1763 
1764 static
1765 NTSTATUS
1767 {
1768  /* This function DOES NOT dereference the device objects on SUCCESS
1769  * but it DOES dereference device objects on FAILURE */
1770 
1771  ULONG i, j;
1772  NTSTATUS Status;
1773 
1774  for (i = 0; i < DeviceRelations->Count; i++)
1775  {
1776  Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1777  if (!NT_SUCCESS(Status))
1778  {
1779  j = i;
1780  goto cleanup;
1781  }
1782  }
1783 
1784  return STATUS_SUCCESS;
1785 
1786 cleanup:
1787  /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1788  * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1789  for (i = 0; i <= j; i++)
1790  {
1791  IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1792  ObDereferenceObject(DeviceRelations->Objects[i]);
1793  DeviceRelations->Objects[i] = NULL;
1794  }
1795  for (; i < DeviceRelations->Count; i++)
1796  {
1797  ObDereferenceObject(DeviceRelations->Objects[i]);
1798  DeviceRelations->Objects[i] = NULL;
1799  }
1800  ExFreePool(DeviceRelations);
1801 
1802  return Status;
1803 }
1804 
1805 static
1806 NTSTATUS
1808 {
1810  IO_STACK_LOCATION Stack;
1812  PDEVICE_RELATIONS DeviceRelations;
1813  NTSTATUS Status;
1814 
1815  if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
1816  {
1817  DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
1818  return STATUS_UNSUCCESSFUL;
1819  }
1820 
1822  {
1823  DPRINT1("Removal vetoed by failing the query remove request\n");
1824 
1826 
1827  return STATUS_UNSUCCESSFUL;
1828  }
1829 
1830  Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1831 
1833  &IoStatusBlock,
1835  &Stack);
1836  if (!NT_SUCCESS(Status))
1837  {
1838  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1839  DeviceRelations = NULL;
1840  }
1841  else
1842  {
1843  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1844  }
1845 
1846  if (DeviceRelations)
1847  {
1848  Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
1849  if (!NT_SUCCESS(Status))
1850  return Status;
1851  }
1852 
1854  if (!NT_SUCCESS(Status))
1855  {
1856  if (DeviceRelations)
1857  IopCancelRemoveDeviceRelations(DeviceRelations);
1858  return Status;
1859  }
1860 
1861  if (DeviceRelations)
1862  IopSendRemoveDeviceRelations(DeviceRelations);
1864 
1865  return STATUS_SUCCESS;
1866 }
1867 
1868 static
1869 VOID
1872  IN PDEVICE_RELATIONS DeviceRelations)
1873 {
1874  PDEVICE_NODE Child = DeviceNode->Child, NextChild;
1875  ULONG i;
1876  BOOLEAN Found;
1877 
1879  return;
1880 
1881  while (Child != NULL)
1882  {
1883  NextChild = Child->Sibling;
1884  Found = FALSE;
1885 
1886  for (i = 0; DeviceRelations && i < DeviceRelations->Count; i++)
1887  {
1888  if (IopGetDeviceNode(DeviceRelations->Objects[i]) == Child)
1889  {
1890  Found = TRUE;
1891  break;
1892  }
1893  }
1894 
1895  if (!Found && !(Child->Flags & DNF_WILL_BE_REMOVED))
1896  {
1897  /* Send removal IRPs to all of its children */
1898  IopPrepareDeviceForRemoval(Child->PhysicalDeviceObject, TRUE);
1899 
1900  /* Send the surprise removal IRP */
1901  IopSendSurpriseRemoval(Child->PhysicalDeviceObject);
1902 
1903  /* Tell the user-mode PnP manager that a device was removed */
1904  IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
1905  &Child->InstancePath);
1906 
1907  /* Send the remove device IRP */
1908  IopSendRemoveDevice(Child->PhysicalDeviceObject);
1909  }
1910 
1911  Child = NextChild;
1912  }
1913 }
1914 
1915 NTSTATUS
1917 {
1918  NTSTATUS Status;
1919 
1920  DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
1921 
1922  Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, FALSE);
1923  if (NT_SUCCESS(Status))
1924  {
1925  IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
1926  IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
1927  &DeviceNode->InstancePath);
1928  return STATUS_SUCCESS;
1929  }
1930 
1931  return Status;
1932 }
1933 
1934 /*
1935  * @implemented
1936  */
1937 VOID
1938 NTAPI
1940 {
1942  IO_STACK_LOCATION Stack;
1943  ULONG_PTR PnPFlags;
1944  NTSTATUS Status;
1946 
1947  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
1948  Stack.MajorFunction = IRP_MJ_PNP;
1950 
1951  Status = IopSynchronousCall(PhysicalDeviceObject, &Stack, (PVOID*)&PnPFlags);
1952  if (!NT_SUCCESS(Status))
1953  {
1955  {
1956  DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status);
1957  }
1958  return;
1959  }
1960 
1961  if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
1962  DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
1963  else
1964  DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
1965 
1966  if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
1967  DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
1968  else
1969  DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
1970 
1971  if ((PnPFlags & PNP_DEVICE_REMOVED) ||
1972  ((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
1973  {
1974  /* Flag it if it's failed */
1975  if (PnPFlags & PNP_DEVICE_FAILED) DeviceNode->Problem = CM_PROB_FAILED_POST_START;
1976 
1977  /* Send removal IRPs to all of its children */
1979 
1980  /* Send surprise removal */
1982 
1983  /* Tell the user-mode PnP manager that a device was removed */
1984  IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
1985  &DeviceNode->InstancePath);
1986 
1988  }
1989  else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
1990  {
1991  /* Stop for resource rebalance */
1993  if (!NT_SUCCESS(Status))
1994  {
1995  DPRINT1("Failed to stop device for rebalancing\n");
1996 
1997  /* Stop failed so don't rebalance */
1999  }
2000  }
2001 
2002  /* Resource rebalance */
2004  {
2005  DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2006 
2008  &IoStatusBlock,
2010  NULL);
2012  {
2013  DeviceNode->BootResources =
2016  }
2017  else
2018  {
2019  DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
2020  DeviceNode->BootResources = NULL;
2021  }
2022 
2023  DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2024 
2026  &IoStatusBlock,
2028  NULL);
2029  if (NT_SUCCESS(Status))
2030  {
2031  DeviceNode->ResourceRequirements =
2033  }
2034  else
2035  {
2036  DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
2037  DeviceNode->ResourceRequirements = NULL;
2038  }
2039 
2040  /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
2042  {
2043  DPRINT1("Restart after resource rebalance failed\n");
2044 
2046  DeviceNode->Flags |= DNF_START_FAILED;
2047 
2049  }
2050  }
2051 }
2052 
2053 /*
2054  * IopInitializePnpServices
2055  *
2056  * Initialize services for discovered children
2057  *
2058  * Parameters
2059  * DeviceNode
2060  * Top device node to start initializing services.
2061  *
2062  * Return Value
2063  * Status
2064  */
2065 NTSTATUS
2067 {
2069 
2070  DPRINT("IopInitializePnpServices(%p)\n", DeviceNode);
2071 
2073  &Context,
2074  DeviceNode,
2076  DeviceNode);
2077 
2078  return IopTraverseDeviceTree(&Context);
2079 }
2080 
2081 static
2082 NTSTATUS
2085 {
2087  PDEVICE_RELATIONS DeviceRelations;
2088  PDEVICE_OBJECT ChildDeviceObject;
2090  PDEVICE_NODE ChildDeviceNode;
2091  IO_STACK_LOCATION Stack;
2092  NTSTATUS Status;
2093  ULONG i;
2094 
2096  {
2098 
2099  DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
2100  IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
2101  &DeviceNode->InstancePath);
2102  }
2103 
2104  DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2105 
2106  Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
2107 
2109  DeviceNode->PhysicalDeviceObject,
2110  &IoStatusBlock,
2112  &Stack);
2113  if (!NT_SUCCESS(Status))
2114  {
2115  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2116  return Status;
2117  }
2118 
2119  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2120 
2121  /*
2122  * Send removal IRPs for devices that have disappeared
2123  * NOTE: This code handles the case where no relations are specified
2124  */
2125  IopHandleDeviceRemoval(DeviceNode, DeviceRelations);
2126 
2127  /* Now we bail if nothing was returned */
2128  if (!DeviceRelations)
2129  {
2130  /* We're all done */
2131  DPRINT("No PDOs\n");
2132  return STATUS_SUCCESS;
2133  }
2134 
2135  DPRINT("Got %u PDOs\n", DeviceRelations->Count);
2136 
2137  /*
2138  * Create device nodes for all discovered devices
2139  */
2140  for (i = 0; i < DeviceRelations->Count; i++)
2141  {
2142  ChildDeviceObject = DeviceRelations->Objects[i];
2143  ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);
2144 
2145  ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
2146  if (!ChildDeviceNode)
2147  {
2148  /* One doesn't exist, create it */
2150  DeviceNode,
2151  ChildDeviceObject,
2152  NULL,
2153  &ChildDeviceNode);
2154  if (NT_SUCCESS(Status))
2155  {
2156  /* Mark the node as enumerated */
2157  ChildDeviceNode->Flags |= DNF_ENUMERATED;
2158 
2159  /* Mark the DO as bus enumerated */
2160  ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2161  }
2162  else
2163  {
2164  /* Ignore this DO */
2165  DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status, i);
2166  ObDereferenceObject(ChildDeviceObject);
2167  }
2168  }
2169  else
2170  {
2171  /* Mark it as enumerated */
2172  ChildDeviceNode->Flags |= DNF_ENUMERATED;
2173  ObDereferenceObject(ChildDeviceObject);
2174  }
2175  }
2176  ExFreePool(DeviceRelations);
2177 
2178  /*
2179  * Retrieve information about all discovered children from the bus driver
2180  */
2182  &Context,
2183  DeviceNode,
2185  DeviceNode);
2186 
2188  if (!NT_SUCCESS(Status))
2189  {
2190  DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
2191  return Status;
2192  }
2193 
2194  /*
2195  * Retrieve configuration from the registry for discovered children
2196  */
2198  &Context,
2199  DeviceNode,
2201  DeviceNode);
2202 
2204  if (!NT_SUCCESS(Status))
2205  {
2206  DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
2207  return Status;
2208  }
2209 
2210  /*
2211  * Initialize services for discovered children.
2212  */
2214  if (!NT_SUCCESS(Status))
2215  {
2216  DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status);
2217  return Status;
2218  }
2219 
2220  DPRINT("IopEnumerateDevice() finished\n");
2221  return STATUS_SUCCESS;
2222 }
2223 
2224 static
2225 NTSTATUS
2226 NTAPI
2228 {
2229  IO_STACK_LOCATION Stack;
2230  PVOID Dummy;
2231 
2232  RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
2233  Stack.MajorFunction = IRP_MJ_PNP;
2234  Stack.MinorFunction = IRP_MN_EJECT;
2235 
2236  return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2237 }
2238 
2239 /*
2240  * @implemented
2241  */
2242 VOID
2243 NTAPI
2245 {
2247  PDEVICE_RELATIONS DeviceRelations;
2249  IO_STACK_LOCATION Stack;
2251  NTSTATUS Status;
2252 
2253  IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2254  &DeviceNode->InstancePath);
2255 
2257  {
2258  goto cleanup;
2259  }
2260 
2261  Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2262 
2264  &IoStatusBlock,
2266  &Stack);
2267  if (!NT_SUCCESS(Status))
2268  {
2269  DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2270  DeviceRelations = NULL;
2271  }
2272  else
2273  {
2274  DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2275  }
2276 
2277  if (DeviceRelations)
2278  {
2279  Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2280  if (!NT_SUCCESS(Status))
2281  goto cleanup;
2282  }
2283 
2285  if (!NT_SUCCESS(Status))
2286  {
2287  if (DeviceRelations)
2288  IopCancelRemoveDeviceRelations(DeviceRelations);
2289  goto cleanup;
2290  }
2291 
2293  {
2294  if (DeviceRelations)
2295  IopCancelRemoveDeviceRelations(DeviceRelations);
2297  goto cleanup;
2298  }
2299 
2300  if (DeviceRelations)
2301  IopSendRemoveDeviceRelations(DeviceRelations);
2303 
2305  if (Capabilities.EjectSupported)
2306  {
2308  {
2309  goto cleanup;
2310  }
2311  }
2312  else
2313  {
2314  DeviceNode->Flags |= DNF_DISABLED;
2315  }
2316 
2317  IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2318  &DeviceNode->InstancePath);
2319 
2320  return;
2321 
2322 cleanup:
2323  IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2324  &DeviceNode->InstancePath);
2325 }
2326 
2327 static
2328 NTSTATUS
2331 {
2333 
2334  ASSERT(DeviceNode->Flags & DNF_ENUMERATED);
2335  ASSERT(DeviceNode->Flags & DNF_PROCESSED);
2336 
2337  /* Check if there's already a driver loaded for this device */
2338  if (DeviceNode->Flags & DNF_ADDED)
2339  {
2340  /* FIXME: our drivers do not handle device removal well enough */
2341 #if 0
2342  /* Remove the device node */
2344  if (NT_SUCCESS(Status))
2345  {
2346  /* Invalidate device relations for the parent to reenumerate the device */
2347  DPRINT1("A new driver will be loaded for '%wZ' (FDO above removed)\n", &DeviceNode->InstancePath);
2348  Status = IoInvalidateDeviceRelations(DeviceNode->Parent->PhysicalDeviceObject, BusRelations);
2349  }
2350  else
2351 #endif
2352  {
2353  /* A driver has already been loaded for this device */
2354  DPRINT("A reboot is required for the current driver for '%wZ' to be replaced\n", &DeviceNode->InstancePath);
2355  DeviceNode->Problem = CM_PROB_NEED_RESTART;
2356  }
2357  }
2358  else
2359  {
2360  /* FIXME: What if the device really is disabled? */
2361  DeviceNode->Flags &= ~DNF_DISABLED;
2362  DeviceNode->Problem = 0;
2363 
2364  /* Load service data from the registry */
2366 
2367  if (NT_SUCCESS(Status))
2368  {
2369  /* Start the service and begin PnP initialization of the device again */
2370  DPRINT("A new driver will be loaded for '%wZ' (no FDO above)\n", &DeviceNode->InstancePath);
2372  }
2373  }
2374 
2375  return Status;
2376 }
2377 
2378 #ifdef DBG
2379 static
2380 PCSTR
2381 ActionToStr(
2383 {
2384  switch (Action)
2385  {
2387  return "PiActionEnumDeviceTree";
2389  return "PiActionEnumRootDevices";
2390  case PiActionResetDevice:
2391  return "PiActionResetDevice";
2392  default:
2393  return "(request unknown)";
2394  }
2395 }
2396 #endif
2397 
2398 static
2399 VOID
2400 NTAPI
2403 {
2404  PLIST_ENTRY ListEntry;
2406  KIRQL OldIrql;
2407 
2410  {
2413  Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2414 
2415  ASSERT(Request->DeviceObject);
2416 
2417  PDEVICE_NODE deviceNode = IopGetDeviceNode(Request->DeviceObject);
2418  ASSERT(deviceNode);
2419 
2421 
2422  DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2423  Request, Request->DeviceObject, ActionToStr(Request->Action));
2424 
2425  switch (Request->Action)
2426  {
2429  status = PipEnumerateDevice(deviceNode);
2430  break;
2431 
2432  case PiActionResetDevice:
2433  status = PipResetDevice(deviceNode);
2434  break;
2435 
2436  default:
2437  DPRINT1("Unimplemented device action %u\n", Request->Action);
2439  break;
2440  }
2441 
2442  if (Request->CompletionStatus)
2443  {
2444  *Request->CompletionStatus = status;
2445  }
2446 
2447  if (Request->CompletionEvent)
2448  {
2449  KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2450  }
2451 
2452  DPRINT("Finished processing PnP request %p\n", Request);
2453  ObDereferenceObject(Request->DeviceObject);
2456  }
2460 }
2461 
2471 VOID
2475  _In_opt_ PKEVENT CompletionEvent,
2476  _Out_opt_ NTSTATUS *CompletionStatus)
2477 {
2479  KIRQL OldIrql;
2480 
2482 
2483  DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2484  DeviceObject, Request, ActionToStr(Action));
2485 
2487 
2488  Request->DeviceObject = DeviceObject;
2489  Request->Action = Action;
2490  Request->CompletionEvent = CompletionEvent;
2491  Request->CompletionStatus = CompletionStatus;
2492 
2494  InsertTailList(&IopDeviceActionRequestList, &Request->RequestListEntry);
2495 
2497  {
2499 
2503 
2505  return;
2506  }
2507 
2509  {
2511  return;
2512  }
2516 
2519 }
2520 
2530 NTSTATUS
2534 {
2535  KEVENT opFinished;
2536  NTSTATUS status;
2537 
2539  PiQueueDeviceAction(DeviceObject, Action, &opFinished, &status);
2541 
2542  return status;
2543 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:26
NTSTATUS NTAPI PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, IN BOOLEAN LoadDriver, IN PDRIVER_OBJECT DriverObject)
Definition: pnpinit.c:291
#define IRP_MN_CANCEL_REMOVE_DEVICE
struct _CM_RESOURCE_LIST * PCM_RESOURCE_LIST
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
LIST_ENTRY IopDeviceActionRequestList
Definition: devaction.c:45
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4142
#define IN
Definition: typedefs.h:39
ULONG Flags
Definition: iotypes.h:836
#define STATUS_PLUGPLAY_NO_DEVICE
Definition: ntstatus.h:731
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:839
NTSTATUS NTAPI IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION IoStackLocation, OUT PVOID *Information)
Definition: pnpmgr.c:549
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1713
#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:717
_In_ WDFREQUEST Request
Definition: cdrom.h:1234
static VOID IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1604
#define DNF_PROCESSED
Definition: iotypes.h:167
#define IRP_MN_REMOVE_DEVICE
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IRP_MN_QUERY_ID
#define TAG_IO
Definition: tag.h:69
#define PNP_DEVICE_REMOVED
Definition: iotypes.h:987
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1677
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
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
#define DNUF_NOT_DISABLEABLE
Definition: iotypes.h:204
#define CM_PROB_HELD_FOR_EJECT
Definition: cfg.h:77
NTSTATUS IopInitializePnpServices(IN PDEVICE_NODE DeviceNode)
Definition: devaction.c:2066
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 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2143
NTSTATUS IopActionInitChildServices(PDEVICE_NODE DeviceNode, PVOID Context)
Definition: devaction.c:1006
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:666
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
LONG NTSTATUS
Definition: precomp.h:26
DEVICE_ACTION Action
Definition: devaction.c:59
NTSTATUS IopCreateDeviceNode(IN PDEVICE_NODE ParentNode, IN PDEVICE_OBJECT PhysicalDeviceObject, IN PUNICODE_STRING ServiceName, OUT PDEVICE_NODE *DeviceNode)
#define DNF_STOPPED
Definition: iotypes.h:182
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1583
#define DNF_NO_RESOURCE_REQUIRED
Definition: iotypes.h:174
NTSYSAPI NTSTATUS NTAPI ZwQueryDefaultLocale(_In_ BOOLEAN UserProfile, _Out_ PLCID DefaultLocaleId)
NTSTATUS FASTCALL IopLoadServiceModule(IN PUNICODE_STRING ServiceName, OUT PLDR_DATA_TABLE_ENTRY *ModuleObject)
Definition: driver.c:316
#define DNF_HAS_BOOT_CONFIG
Definition: iotypes.h:196
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
struct _IO_RESOURCE_REQUIREMENTS_LIST * PIO_RESOURCE_REQUIREMENTS_LIST
#define CM_PROB_FAILED_START
Definition: cfg.h:40
DEVICE_CAPABILITIES
Definition: iotypes.h:948
#define CM_PROB_FAILED_POST_START
Definition: cfg.h:73
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
DWORD LCID
Definition: nls.h:13
#define IRP_MN_EJECT
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
static NTSTATUS IopSetServiceEnumData(PDEVICE_NODE DeviceNode)
Definition: devaction.c:1129
#define CM_PROB_FAILED_DRIVER_ENTRY
Definition: cfg.h:67
uint16_t * PWCHAR
Definition: typedefs.h:56
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
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
#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:825
NTSTATUS IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, PVOID Context)
Definition: devaction.c:577
#define PNP_DEVICE_DONT_DISPLAY_IN_UI
Definition: iotypes.h:985
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define DNF_RESOURCE_ASSIGNED
Definition: iotypes.h:176
#define _In_opt_
Definition: no_sal2.h:212
static NTSTATUS PipEnumerateDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2083
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
static NTSTATUS IopQueryHardwareIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:432
DWORD Id
uint32_t ULONG_PTR
Definition: typedefs.h:65
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define DNF_START_FAILED
Definition: iotypes.h:169
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:497
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)
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(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define STATUS_DRIVER_UNABLE_TO_LOAD
Definition: ntstatus.h:745
struct _DEVICE_NODE * PDEVICE_NODE
struct _DEVICE_NODE * Child
Definition: iotypes.h:824
KSPIN_LOCK IopDeviceActionLock
Definition: devaction.c:48
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#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:203
VOID NTAPI IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:1939
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define DNF_WILL_BE_REMOVED
Definition: iotypes.h:183
NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
Definition: devaction.c:329
LIST_ENTRY RequestListEntry
Definition: devaction.c:55
NTSTATUS PiPerformSyncDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
Perfom a device operation synchronously via PiQueueDeviceAction.
Definition: devaction.c:2531
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:907
PDEVICE_OBJECT DeviceObject
Definition: devaction.c:56
static NTSTATUS IopCreateDeviceInstancePath(_In_ PDEVICE_NODE DeviceNode, _Out_ PUNICODE_STRING InstancePath)
Definition: devaction.c:182
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define IopDeviceNodeSetFlag(DeviceNode, Flag)
Definition: io.h:142
VOID NTAPI IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:46
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define DO_BUS_ENUMERATED_DEVICE
static NTSTATUS NTAPI IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1445
struct _PNP_BUS_INFORMATION * PPNP_BUS_INFORMATION
#define _Out_
Definition: no_sal2.h:160
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
KEVENT PiEnumerationFinished
Definition: devaction.c:49
#define DeviceCapabilities
Definition: wingdi.h:4448
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS FASTCALL IopInitializeDevice(IN PDEVICE_NODE DeviceNode, IN PDRIVER_OBJECT DriverObject)
return Found
Definition: dirsup.c:1270
static const WCHAR ClassGUID[]
Definition: devclass.c:30
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
#define DNF_STARTED
Definition: iotypes.h:168
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
#define IRP_MN_QUERY_STOP_DEVICE
static VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1500
BOOLEAN PnpSystemInit
Definition: iomgr.c:17
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
#define _Out_opt_
Definition: no_sal2.h:214
NTSTATUS IopQueueTargetDeviceEvent(const GUID *Guid, PUNICODE_STRING DeviceIds)
Definition: plugplay.c:46
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
static NTSTATUS PipResetDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2329
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
static BOOLEAN IopValidateID(_In_ PWCHAR Id, _In_ BUS_QUERY_ID_TYPE QueryType)
Definition: devaction.c:91
#define PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:988
#define IRP_MN_STOP_DEVICE
USHORT NTAPI IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
Definition: pnpmgr.c:481
NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
Definition: pnpmgr.c:904
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:125
#define CM_PROB_DISABLED_SERVICE
Definition: cfg.h:62
static VOID NTAPI IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1460
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG Action
Definition: fsrtlfuncs.h:738
#define ENUM_ROOT
Definition: io.h:53
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define IRP_MN_START_DEVICE
#define PNP_DEVICE_NOT_DISABLEABLE
Definition: iotypes.h:989
#define DNF_NEED_ENUMERATION_ONLY
Definition: iotypes.h:194
NTSTATUS FASTCALL IopGetDriverObject(OUT PDRIVER_OBJECT *DriverObject, IN PUNICODE_STRING ServiceName, IN BOOLEAN FileSystem)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define IRP_MN_QUERY_DEVICE_TEXT
static VOID IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1543
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
_Must_inspect_result_ _In_ KTMOBJECT_TYPE QueryType
Definition: nttmapi.h:404
Definition: Node.h:9
static VOID NTAPI IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1271
static VOID NTAPI IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1567
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
WORK_QUEUE_ITEM IopDeviceActionWorkItem
Definition: devaction.c:46
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2401
#define IRP_MN_QUERY_BUS_INFORMATION
#define MAX_DEVICE_ID_LEN
Definition: devaction.c:39
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
Status
Definition: gdiplustypes.h:24
static const WCHAR L[]
Definition: oid.c:1250
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define CM_PROB_DRIVER_FAILED_LOAD
Definition: cfg.h:69
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
#define DNF_LEGACY_DRIVER
Definition: iotypes.h:181
Definition: btrfs_drv.h:1922
static NTSTATUS IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
_In_ PNDIS_STRING DeviceInstance
Definition: ndis.h:5202
#define DNF_DISABLED
Definition: iotypes.h:188
Definition: typedefs.h:119
#define PNP_DEVICE_FAILED
Definition: iotypes.h:986
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
VOID NTAPI IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:2244
#define IopDeviceNodeHasFlag(DeviceNode, Flag)
Definition: io.h:160
#define MAX_SEPARATORS_INSTANCEID
Definition: devaction.c:40
#define CM_PROB_NEED_RESTART
Definition: cfg.h:44
* PDEVICE_CAPABILITIES
Definition: iotypes.h:948
#define MAXULONG
Definition: typedefs.h:251
static NTSTATUS NTAPI IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode)
Definition: devaction.c:1331
#define _In_
Definition: no_sal2.h:158
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1526
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
static NTSTATUS NTAPI IopSendEject(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:2227
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1750
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:2486
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#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:1599
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1645
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1766
unsigned short USHORT
Definition: pedump.c:61
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
static VOID ErrorExit(LPTSTR lpszMessage)
Definition: telnetd.c:647
NTSTATUS FASTCALL IopInitializeDriverModule(IN PDEVICE_NODE DeviceNode, IN PLDR_DATA_TABLE_ENTRY ModuleObject, IN PUNICODE_STRING ServiceName, IN BOOLEAN FileSystemDriver, OUT PDRIVER_OBJECT *DriverObject)
Definition: driver.c:469
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
UNICODE_STRING ServiceName
Definition: iotypes.h:843
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
unsigned int * PULONG
Definition: retypes.h:1
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_MN_QUERY_DEVICE_RELATIONS
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:823
NTSTATUS IopStartDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:1384
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1627
NTSTATUS IopStopDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:1474
#define CM_PROB_FAILED_INSTALL
Definition: cfg.h:58
#define DPRINT1
Definition: precomp.h:8
NTSTATUS IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, PVOID Context)
Definition: devaction.c:861
NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:1916
ERESOURCE IopDriverLoadResource
Definition: driver.c:19
#define ObReferenceObject
Definition: obfuncs.h:204
NTSTATUS NTAPI IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:1105
#define IopInitDeviceTreeTraverseContext( _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context)
Definition: io.h:225
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:47
struct tagContext Context
Definition: acpixf.h:1034
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE Child
Definition: acpixf.h:728
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
char * cleanup(char *str)
Definition: wpickclick.c:99
NTSTATUS * CompletionStatus
Definition: devaction.c:58
#define DNF_ENUMERATED
Definition: iotypes.h:170
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:2472
const char * PCSTR
Definition: typedefs.h:52
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
static VOID IopHandleDeviceRemoval(IN PDEVICE_NODE DeviceNode, IN PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1870
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define DNF_ADDED
Definition: iotypes.h:179
#define DNF_RESOURCE_REPORTED
Definition: iotypes.h:177
#define REG_DWORD
Definition: sdbapi.c:596
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)
#define MAX_SEPARATORS_DEVICEID
Definition: devaction.c:41
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
INTERFACE_TYPE LegacyBusType
Definition: cmtypes.h:365
#define IRP_MN_QUERY_PNP_DEVICE_STATE
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
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define DNF_START_REQUEST_PENDING
Definition: iotypes.h:173
PDEVICE_NODE FASTCALL IopGetDeviceNode(IN PDEVICE_OBJECT DeviceObject)
NTSTATUS IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:750
#define IRP_MN_QUERY_CAPABILITIES
#define STATUS_IMAGE_ALREADY_LOADED
Definition: ntstatus.h:506
_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