ReactOS 0.4.16-dev-1170-ge326b06
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
39
40#define MAX_DEVICE_ID_LEN 200
41#define MAX_SEPARATORS_INSTANCEID 0
42#define MAX_SEPARATORS_DEVICEID 1
43
44/* DATA **********************************************************************/
45
51static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
52
53/* TYPES *********************************************************************/
54
56{
63
65{
72
74{
79
81{
86
87/* FUNCTIONS *****************************************************************/
88
91
94
98
101
102VOID
103NTAPI
105
106static
107VOID
109
110static
113
114static
118 _In_ HANDLE InstanceHandle);
119
120static
123 _In_ PWCHAR Id,
125{
126 PWCHAR PtrChar;
127 PWCHAR StringEnd;
128 WCHAR Char;
129 ULONG SeparatorsCount = 0;
130 PWCHAR PtrPrevChar = NULL;
131 ULONG MaxSeparators;
132 BOOLEAN IsMultiSz;
133
134 PAGED_CODE();
135
136 switch (QueryType)
137 {
138 case BusQueryDeviceID:
139 MaxSeparators = MAX_SEPARATORS_DEVICEID;
140 IsMultiSz = FALSE;
141 break;
143 MaxSeparators = MAX_SEPARATORS_INSTANCEID;
144 IsMultiSz = FALSE;
145 break;
146
149 MaxSeparators = MAX_SEPARATORS_DEVICEID;
150 IsMultiSz = TRUE;
151 break;
152
153 default:
154 DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
155 return FALSE;
156 }
157
158 StringEnd = Id + MAX_DEVICE_ID_LEN;
159
160 for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
161 {
162 Char = *PtrChar;
163
164 if (Char == UNICODE_NULL)
165 {
166 if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
167 {
168 if (MaxSeparators == SeparatorsCount || IsMultiSz)
169 {
170 return TRUE;
171 }
172
173 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
174 SeparatorsCount, MaxSeparators);
175 goto ErrorExit;
176 }
177
178 StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
179 PtrPrevChar = PtrChar;
180 SeparatorsCount = 0;
181 }
182 else if (Char < ' ' || Char > 0x7F || Char == ',')
183 {
184 DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
185 goto ErrorExit;
186 }
187 else if (Char == ' ')
188 {
189 *PtrChar = '_';
190 }
191 else if (Char == '\\')
192 {
193 SeparatorsCount++;
194
195 if (SeparatorsCount > MaxSeparators)
196 {
197 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
198 SeparatorsCount, MaxSeparators);
199 goto ErrorExit;
200 }
201 }
202 }
203
204 DPRINT1("IopValidateID: Not terminated ID\n");
205
207 // FIXME logging
208 return FALSE;
209}
210
211static
215 _Out_ PUNICODE_STRING InstancePath)
216{
218 UNICODE_STRING DeviceId;
222 UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
224 BOOLEAN IsValidID;
225
226 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
227
228 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
229 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
232 &Stack);
233 if (!NT_SUCCESS(Status))
234 {
235 DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
236 return Status;
237 }
238
240
241 if (!IsValidID)
242 {
243 DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
244 }
245
246 /* Save the device id string */
248
249 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
250
252 if (!NT_SUCCESS(Status))
253 {
255 {
256 DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
257 }
258 RtlFreeUnicodeString(&DeviceId);
259 return Status;
260 }
261
262 /* This bit is only check after enumeration */
263 if (DeviceCapabilities.HardwareDisabled)
264 {
265 /* FIXME: Cleanup device */
266 RtlFreeUnicodeString(&DeviceId);
268 }
269
270 if (!DeviceCapabilities.UniqueID)
271 {
272 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
273 DPRINT("Instance ID is not unique\n");
274 Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
278 RtlFreeUnicodeString(&DeviceId);
279 return Status;
280 }
281 }
282
283 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
284
285 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
286 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
289 &Stack);
290 if (!NT_SUCCESS(Status))
291 {
292 DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status);
294 }
295
297 {
299
300 if (!IsValidID)
301 {
302 DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
303 }
304 }
305
308
309 InstancePath->Length = 0;
310 InstancePath->MaximumLength = DeviceId.Length + sizeof(WCHAR) +
311 ParentIdPrefix.Length +
312 InstanceId.Length +
313 sizeof(UNICODE_NULL);
314 if (ParentIdPrefix.Length && InstanceId.Length)
315 {
316 InstancePath->MaximumLength += sizeof(WCHAR);
317 }
318
319 InstancePath->Buffer = ExAllocatePoolWithTag(PagedPool,
320 InstancePath->MaximumLength,
321 TAG_IO);
322 if (!InstancePath->Buffer)
323 {
325 RtlFreeUnicodeString(&ParentIdPrefix);
326 RtlFreeUnicodeString(&DeviceId);
328 }
329
330 /* Start with the device id */
331 RtlCopyUnicodeString(InstancePath, &DeviceId);
332 RtlAppendUnicodeToString(InstancePath, L"\\");
333
334 /* Add information from parent bus device to InstancePath */
335 RtlAppendUnicodeStringToString(InstancePath, &ParentIdPrefix);
336 if (ParentIdPrefix.Length && InstanceId.Length)
337 {
338 RtlAppendUnicodeToString(InstancePath, L"&");
339 }
340
341 /* Finally, add the id returned by the driver stack */
343
344 /*
345 * FIXME: Check for valid characters, if there is invalid characters
346 * then bugcheck
347 */
348
350 RtlFreeUnicodeString(&DeviceId);
351 RtlFreeUnicodeString(&ParentIdPrefix);
352
353 return STATUS_SUCCESS;
354}
355
360static
362NTAPI
368 PVOID Ctx,
370{
374 BOOLEAN loadDrivers = (BOOLEAN)(ULONG_PTR)EntryContext;
375
376 PAGED_CODE();
377
378 // No filter value present
379 if (ValueType != REG_SZ)
380 return STATUS_SUCCESS;
381
382 if (ValueLength <= sizeof(WCHAR))
384
385 // open the service registry key
386 UNICODE_STRING serviceName = { .Length = 0 }, servicesKeyName;
388 RtlInitUnicodeString(&servicesKeyName, ServicesKeyName);
389
390 HANDLE ccsServicesHandle, serviceHandle = NULL;
391
392 Status = IopOpenRegistryKeyEx(&ccsServicesHandle, NULL, &servicesKeyName, KEY_READ);
393 if (!NT_SUCCESS(Status))
394 {
395 DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
396 return Status;
397 }
398
399 Status = IopOpenRegistryKeyEx(&serviceHandle, ccsServicesHandle, &serviceName, KEY_READ);
400 ZwClose(ccsServicesHandle);
401 if (!NT_SUCCESS(Status))
402 {
403 DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
404 return Status;
405 }
406
408 sizeof(*driverEntry),
410
411 if (!driverEntry)
412 {
413 DPRINT1("Failed to allocate driverEntry for \"%wZ\"\n", &serviceName);
414 ZwClose(serviceHandle);
416 }
417
418 // check if the driver is disabled
420 SERVICE_LOAD_TYPE startType = DisableLoad;
421
422 Status = IopGetRegistryValue(serviceHandle, L"Start", &kvInfo);
423 if (NT_SUCCESS(Status))
424 {
425 if (kvInfo->Type == REG_DWORD)
426 {
427 RtlMoveMemory(&startType,
428 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
429 sizeof(startType));
430 }
431
432 ExFreePool(kvInfo);
433 }
434
435 // TODO: take into account other start types (like SERVICE_DEMAND_START)
436 if (startType >= DisableLoad)
437 {
438 if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
439 {
441 }
442
443 DPRINT("Service \"%wZ\" is disabled (start type %u)\n", &serviceName, startType);
445 goto Cleanup;
446 }
447
448 // check if the driver is already loaded
449 UNICODE_STRING driverName;
450 Status = IopGetDriverNames(serviceHandle, &driverName, NULL);
451 if (!NT_SUCCESS(Status))
452 {
453 DPRINT1("Unable to obtain the driver name for \"%wZ\"\n", &serviceName);
454 goto Cleanup;
455 }
456
457 // try to open it
458 Status = ObReferenceObjectByName(&driverName,
460 NULL, /* PassedAccessState */
461 0, /* DesiredAccess */
464 NULL, /* ParseContext */
466 RtlFreeUnicodeString(&driverName);
467
468 // the driver was not probably loaded, try to load
469 if (!NT_SUCCESS(Status))
470 {
471 if (loadDrivers)
472 {
473 Status = IopLoadDriver(serviceHandle, &DriverObject);
474 }
475 else
476 {
477 DPRINT("Service \"%wZ\" will not be loaded now\n", &serviceName);
478 // return failure, the driver will be loaded later (in a subsequent call)
480 goto Cleanup;
481 }
482 }
483
484 if (NT_SUCCESS(Status))
485 {
486 driverEntry->DriverObject = DriverObject;
487 driverEntry->DriverType = context->DriverType;
488 InsertTailList(context->DriversListHead, &driverEntry->ListEntry);
489 ZwClose(serviceHandle);
490 return STATUS_SUCCESS;
491 }
492 else
493 {
494 if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
495 {
496 switch (Status)
497 {
500 break;
503 break;
506 break;
507 default:
509 break;
510 }
511 }
512
513 DPRINT1("Failed to load driver \"%wZ\" for %wZ (status %x)\n",
514 &serviceName, &context->DeviceNode->InstancePath, Status);
515 }
516
517Cleanup:
519 if (serviceHandle)
520 {
521 ZwClose(serviceHandle);
522 }
523 return Status;
524}
525
526
530static
533 PLIST_ENTRY DriversListHead,
535 HANDLE EnumSubKey,
536 HANDLE ClassKey,
537 BOOLEAN Lower,
538 BOOLEAN LoadDrivers)
539{
540 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, };
541 ATTACH_FILTER_DRIVERS_CONTEXT routineContext;
543
544 PAGED_CODE();
545
546 routineContext.DriversListHead = DriversListHead;
547 routineContext.DeviceNode = DeviceNode;
548
549 // First add device filters
550 routineContext.DriverType = Lower ? LowerFilter : UpperFilter;
553 .Name = Lower ? L"LowerFilters" : L"UpperFilters",
554 .DefaultType = REG_NONE,
555 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
556 };
557
559 (PWSTR)EnumSubKey,
561 &routineContext,
562 NULL);
563 if (ClassKey == NULL)
564 {
565 return Status;
566 }
567
568 // Then add device class filters
569 routineContext.DriverType = Lower ? LowerClassFilter : UpperClassFilter;
572 .Name = Lower ? L"LowerFilters" : L"UpperFilters",
573 .DefaultType = REG_NONE,
574 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
575 };
576
578 (PWSTR)ClassKey,
580 &routineContext,
581 NULL);
582 return Status;
583}
584
593static
597 _In_ BOOLEAN LoadDrivers)
598{
600 HANDLE EnumRootKey, SubKey;
601 HANDLE ClassKey = NULL;
603 static UNICODE_STRING ccsControlClass =
604 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
606
607 PAGED_CODE();
608
609 // open the enumeration root key
610 Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ);
611 if (!NT_SUCCESS(Status))
612 {
613 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &EnumRoot, Status);
614 return Status;
615 }
616
617 // open an instance subkey
618 Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ);
619 ZwClose(EnumRootKey);
620 if (!NT_SUCCESS(Status))
621 {
622 DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
623 &DeviceNode->InstancePath, Status);
624 return Status;
625 }
626
627 // try to get the class GUID of an instance and its registry key
629 if (NT_SUCCESS(Status))
630 {
631 if ((kvInfo->Type == REG_SZ) &&
632 (kvInfo->DataLength > sizeof(UNICODE_NULL)) &&
634 ((kvInfo->DataLength % sizeof(WCHAR)) == 0))
635 {
636 UNICODE_STRING classGUID = {
637 .MaximumLength = kvInfo->DataLength,
638 .Length = (USHORT)(kvInfo->DataLength - sizeof(UNICODE_NULL)),
639 .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset)
640 };
641 HANDLE ccsControlHandle;
642
643 Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ);
644 if (!NT_SUCCESS(Status))
645 {
646 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n",
647 &ccsControlClass, Status);
648 }
649 else
650 {
651 // open the CCS\Control\Class<ClassGUID> key
652 Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ);
653 ZwClose(ccsControlHandle);
654 if (!NT_SUCCESS(Status))
655 {
656 DPRINT1("Failed to open class key \"%wZ\" (status %x)\n", &classGUID, Status);
657 }
658 }
659
660 if (ClassKey)
661 {
662 // Check the Properties key of a class too
663 // Windows fills some device properties from this key (which is protected)
664 // TODO: add the device properties from this key
665
667 HANDLE propertiesHandle;
668
669 Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ);
670 if (!NT_SUCCESS(Status))
671 {
672 DPRINT("Properties key failed to open for \"%wZ\" (status %x)\n",
673 &classGUID, Status);
674 }
675 else
676 {
677 ZwClose(propertiesHandle);
678 }
679 }
680 }
681
682 ExFreePool(kvInfo);
683 }
684
685 // the driver loading order:
686 // 1. LowerFilters
687 // 2. LowerClassFilters
688 // 3. Device driver (only one service!)
689 // 4. UpperFilters
690 // 5. UpperClassFilters
691
692 LIST_ENTRY drvListHead;
693 InitializeListHead(&drvListHead);
694
695 // lower (class) filters
696 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers);
697 if (!NT_SUCCESS(Status))
698 {
699 goto Cleanup;
700 }
701
702 ATTACH_FILTER_DRIVERS_CONTEXT routineContext = {
703 .DriversListHead = &drvListHead,
704 .DriverType = DeviceDriver,
705 .DeviceNode = DeviceNode
706 };
707
708 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{
710 .Name = L"Service",
712 .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here
713 .DefaultData = L"",
714 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
715 },};
716
717 // device driver
719 (PWSTR)SubKey,
720 queryTable,
721 &routineContext,
722 NULL);
723 if (NT_SUCCESS(Status))
724 {
725 // do nothing
726 }
727 // if a driver is not found, but a device allows raw access -> proceed
729 (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK
730 {
731 // add a dummy entry to the drivers list (need for later processing)
733 sizeof(*driverEntry),
735 driverEntry->DriverType = DeviceDriver;
736 InsertTailList(&drvListHead, &driverEntry->ListEntry);
737 DPRINT("No service for \"%wZ\" (RawDeviceOK)\n", &DeviceNode->InstancePath);
738 }
739 else
740 {
742 {
744 }
745 DPRINT("No service for \"%wZ\" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers);
746 goto Cleanup;
747 }
748
749 // upper (class) filters
750 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers);
751 if (!NT_SUCCESS(Status))
752 {
753 goto Cleanup;
754 }
755
756 // finally loop through the stack and call AddDevice for every driver
757 for (PLIST_ENTRY listEntry = drvListHead.Flink;
758 listEntry != &drvListHead;
759 listEntry = listEntry->Flink)
760 {
761 PADD_DEV_DRIVERS_LIST driverEntry;
762 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
763 PDRIVER_OBJECT driverObject = driverEntry->DriverObject;
764
765 // FIXME: ReactOS is not quite ready for this assert
766 // (legacy drivers should not have AddDevice routine)
767 // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER));
768
769 if (driverObject && driverObject->DriverExtension->AddDevice)
770 {
771 Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject,
772 DeviceNode->PhysicalDeviceObject);
773 }
774 else if (driverObject == NULL)
775 {
776 // valid only for DeviceDriver
777 ASSERT(driverEntry->DriverType == DeviceDriver);
778 ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK
780 }
781 else
782 {
783 // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here,
784 // but ReactOS' PnP stack is not that correct yet
787 }
788
789 // for filter drivers we don't care about the AddDevice result
790 if (driverEntry->DriverType == DeviceDriver)
791 {
792 if (NT_SUCCESS(Status))
793 {
794 PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
795
796 // HACK: Check if we have a ACPI device (needed for power management)
797 if (fdo->DeviceType == FILE_DEVICE_ACPI)
798 {
799 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
800
801 // There can be only one system power device
802 if (!SystemPowerDeviceNodeCreated)
803 {
806 SystemPowerDeviceNodeCreated = TRUE;
807 }
808 }
809
812 }
813 else
814 {
815 // lower filters (if already started) will be removed upon this request
818 break;
819 }
820 }
821
822#if DBG
823 PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject);
824 if (attachedDO->Flags & DO_DEVICE_INITIALIZING)
825 {
826 DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO);
827 }
828#endif
829 }
830
831Cleanup:
832 while (!IsListEmpty(&drvListHead))
833 {
834 PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead);
835 PADD_DEV_DRIVERS_LIST driverEntry;
836 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
837
838 // drivers which don't have any devices (in case of failure) will be cleaned up
839 if (driverEntry->DriverObject)
840 {
841 ObDereferenceObject(driverEntry->DriverObject);
842 }
844 }
845
846 ZwClose(SubKey);
847 if (ClassKey != NULL)
848 {
849 ZwClose(ClassKey);
850 }
851
852 return Status;
853}
854
856NTAPI
858 PDEVICE_CAPABILITIES DeviceCaps)
859{
860 IO_STATUS_BLOCK StatusBlock;
863 HANDLE InstanceKey;
865
866 /* Set up the Header */
867 RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
868 DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
869 DeviceCaps->Version = 1;
870 DeviceCaps->Address = -1;
871 DeviceCaps->UINumber = -1;
872
873 /* Set up the Stack */
875 Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
876
877 /* Send the IRP */
878 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
879 &StatusBlock,
881 &Stack);
882 if (!NT_SUCCESS(Status))
883 {
885 {
886 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
887 }
888 return Status;
889 }
890
891 /* Map device capabilities to capability flags */
892 DeviceNode->CapabilityFlags = 0;
893 if (DeviceCaps->LockSupported)
894 DeviceNode->CapabilityFlags |= 0x00000001; // CM_DEVCAP_LOCKSUPPORTED
895
896 if (DeviceCaps->EjectSupported)
897 DeviceNode->CapabilityFlags |= 0x00000002; // CM_DEVCAP_EJECTSUPPORTED
898
899 if (DeviceCaps->Removable)
900 DeviceNode->CapabilityFlags |= 0x00000004; // CM_DEVCAP_REMOVABLE
901
902 if (DeviceCaps->DockDevice)
903 DeviceNode->CapabilityFlags |= 0x00000008; // CM_DEVCAP_DOCKDEVICE
904
905 if (DeviceCaps->UniqueID)
906 DeviceNode->CapabilityFlags |= 0x00000010; // CM_DEVCAP_UNIQUEID
907
908 if (DeviceCaps->SilentInstall)
909 DeviceNode->CapabilityFlags |= 0x00000020; // CM_DEVCAP_SILENTINSTALL
910
911 if (DeviceCaps->RawDeviceOK)
912 DeviceNode->CapabilityFlags |= 0x00000040; // CM_DEVCAP_RAWDEVICEOK
913
914 if (DeviceCaps->SurpriseRemovalOK)
915 DeviceNode->CapabilityFlags |= 0x00000080; // CM_DEVCAP_SURPRISEREMOVALOK
916
917 if (DeviceCaps->HardwareDisabled)
918 DeviceNode->CapabilityFlags |= 0x00000100; // CM_DEVCAP_HARDWAREDISABLED
919
920 if (DeviceCaps->NonDynamic)
921 DeviceNode->CapabilityFlags |= 0x00000200; // CM_DEVCAP_NONDYNAMIC
922
923 if (DeviceCaps->NoDisplayInUI)
924 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
925 else
926 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
927
928 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
929 if (NT_SUCCESS(Status))
930 {
931 /* Set 'Capabilities' value */
932 RtlInitUnicodeString(&ValueName, L"Capabilities");
933 Status = ZwSetValueKey(InstanceKey,
934 &ValueName,
935 0,
936 REG_DWORD,
937 &DeviceNode->CapabilityFlags,
938 sizeof(ULONG));
939
940 /* Set 'UINumber' value */
941 if (DeviceCaps->UINumber != MAXULONG)
942 {
943 RtlInitUnicodeString(&ValueName, L"UINumber");
944 Status = ZwSetValueKey(InstanceKey,
945 &ValueName,
946 0,
947 REG_DWORD,
948 &DeviceCaps->UINumber,
949 sizeof(ULONG));
950 }
951
952 ZwClose(InstanceKey);
953 }
954
955 return Status;
956}
957
958static
961 HANDLE InstanceKey)
962{
965 PWSTR Ptr;
969 BOOLEAN IsValidID;
970
971 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
972
973 RtlZeroMemory(&Stack, sizeof(Stack));
974 Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
975 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
978 &Stack);
979 if (NT_SUCCESS(Status))
980 {
982
983 if (!IsValidID)
984 {
985 DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
986 }
987
988 TotalLength = 0;
989
991 DPRINT("Hardware IDs:\n");
992 while (*Ptr)
993 {
994 DPRINT(" %S\n", Ptr);
995 Length = (ULONG)wcslen(Ptr) + 1;
996
997 Ptr += Length;
999 }
1000 DPRINT("TotalLength: %hu\n", TotalLength);
1001 DPRINT("\n");
1002
1003 RtlInitUnicodeString(&ValueName, L"HardwareID");
1004 Status = ZwSetValueKey(InstanceKey,
1005 &ValueName,
1006 0,
1009 (TotalLength + 1) * sizeof(WCHAR));
1010 if (!NT_SUCCESS(Status))
1011 {
1012 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1013 }
1014 }
1015 else
1016 {
1017 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1018 }
1019
1020 return Status;
1021}
1022
1023static
1026 HANDLE InstanceKey)
1027{
1030 PWSTR Ptr;
1034 BOOLEAN IsValidID;
1035
1036 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1037
1038 RtlZeroMemory(&Stack, sizeof(Stack));
1039 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1040 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1043 &Stack);
1045 {
1047
1048 if (!IsValidID)
1049 {
1050 DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
1051 }
1052
1053 TotalLength = 0;
1054
1056 DPRINT("Compatible IDs:\n");
1057 while (*Ptr)
1058 {
1059 DPRINT(" %S\n", Ptr);
1060 Length = (ULONG)wcslen(Ptr) + 1;
1061
1062 Ptr += Length;
1064 }
1065 DPRINT("TotalLength: %hu\n", TotalLength);
1066 DPRINT("\n");
1067
1068 RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
1069 Status = ZwSetValueKey(InstanceKey,
1070 &ValueName,
1071 0,
1074 (TotalLength + 1) * sizeof(WCHAR));
1075 if (!NT_SUCCESS(Status))
1076 {
1077 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
1078 }
1079 }
1080 else
1081 {
1082 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1083 }
1084
1085 return Status;
1086}
1087
1091VOID
1094 _In_ HANDLE InstanceKey)
1095{
1096 PAGED_CODE();
1097
1098 LCID localeId;
1099
1100 // Get the Locale ID
1102 if (!NT_SUCCESS(status))
1103 {
1104 DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
1105 return;
1106 }
1107
1108 // Step 1: Write the DeviceDesc value if does not exist
1109
1110 UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
1111 ULONG len;
1112
1113 status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, KeyValueBasicInformation, NULL, 0, &len);
1115 {
1116 PWSTR deviceDesc = NULL;
1118
1119 if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
1120 {
1121 status = ZwSetValueKey(InstanceKey,
1122 &valDeviceDesc,
1123 0,
1124 REG_SZ,
1125 deviceDesc,
1126 ((ULONG)wcslen(deviceDesc) + 1) * sizeof(WCHAR));
1127
1128 if (!NT_SUCCESS(status))
1129 {
1130 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1131 }
1132 }
1133 else
1134 {
1135 // This key is mandatory, so even if the Irp fails, we still write it
1136 UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
1137 DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
1138
1139 status = ZwSetValueKey(InstanceKey,
1140 &valDeviceDesc,
1141 0,
1142 REG_SZ,
1143 unknownDeviceDesc.Buffer,
1144 unknownDeviceDesc.MaximumLength);
1145 if (!NT_SUCCESS(status))
1146 {
1147 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1148 }
1149 }
1150
1151 if (deviceDesc)
1152 {
1153 ExFreePoolWithTag(deviceDesc, 0);
1154 }
1155 }
1156
1157 // Step 2: LocaltionInformation is overwritten unconditionally
1158
1159 PWSTR deviceLocationInfo = NULL;
1161 localeId,
1163 &deviceLocationInfo);
1164
1165 if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
1166 {
1167 UNICODE_STRING valLocationInfo = RTL_CONSTANT_STRING(L"LocationInformation");
1168
1169 status = ZwSetValueKey(InstanceKey,
1170 &valLocationInfo,
1171 0,
1172 REG_SZ,
1173 deviceLocationInfo,
1174 ((ULONG)wcslen(deviceLocationInfo) + 1) * sizeof(WCHAR));
1175 if (!NT_SUCCESS(status))
1176 {
1177 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1178 }
1179 }
1180
1181 if (deviceLocationInfo)
1182 {
1183 ExFreePoolWithTag(deviceLocationInfo, 0);
1184 }
1185 else
1186 {
1187 DPRINT("Driver didn't return LocationInformation (status %x)\n", status);
1188 }
1189}
1190
1191static
1195{
1198 HANDLE InstanceKey = NULL;
1199 UNICODE_STRING InstancePathU;
1200 PDEVICE_OBJECT OldDeviceObject;
1201
1202 DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
1203 DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
1204
1205 /*
1206 * FIXME: For critical errors, cleanup and disable device, but always
1207 * return STATUS_SUCCESS.
1208 */
1209
1211 if (!NT_SUCCESS(Status))
1212 {
1214 {
1215 DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
1216 }
1217 return Status;
1218 }
1219
1220 /* Verify that this is not a duplicate */
1221 OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
1222 if (OldDeviceObject != NULL)
1223 {
1224 PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
1225
1226 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
1227 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
1228 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
1229
1230 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1231 0x01,
1232 (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
1233 (ULONG_PTR)OldDeviceObject,
1234 0);
1235 }
1236
1237 DeviceNode->InstancePath = InstancePathU;
1238
1239 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1240
1241 /*
1242 * Create registry key for the instance id, if it doesn't exist yet
1243 */
1244 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
1245 if (!NT_SUCCESS(Status))
1246 {
1247 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1248
1249 /* We have to return success otherwise we abort the traverse operation */
1250 return STATUS_SUCCESS;
1251 }
1252
1253 IopQueryHardwareIds(DeviceNode, InstanceKey);
1254
1255 IopQueryCompatibleIds(DeviceNode, InstanceKey);
1256
1257 DeviceNode->Flags |= DNF_IDS_QUERIED;
1258
1259 // Set the device's DeviceDesc and LocationInformation fields
1260 PiSetDevNodeText(DeviceNode, InstanceKey);
1261
1262 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1263
1264 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1267 NULL);
1269 {
1271
1272 DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1273 DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1274 DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
1276 }
1277 else
1278 {
1279 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1280
1281 DeviceNode->ChildBusNumber = 0xFFFFFFF0;
1282 DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
1283 DeviceNode->ChildBusTypeIndex = -1;
1284 }
1285
1286 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1287
1288 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1291 NULL);
1293 {
1296 }
1297 else
1298 {
1299 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1300 DeviceNode->BootResources = NULL;
1301 }
1302
1303 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1304
1305 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1308 NULL);
1309 if (NT_SUCCESS(Status))
1310 {
1312 }
1313 else
1314 {
1315 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
1316 DeviceNode->ResourceRequirements = NULL;
1317 }
1318
1319 if (InstanceKey != NULL)
1320 {
1322 }
1323
1324 // Try installing a critical device, so its Service key is populated
1325 // then call IopSetServiceEnumData to populate service's Enum key.
1326 // That allows us to start devices during an early boot
1328 IopSetServiceEnumData(DeviceNode, InstanceKey);
1329
1330 ZwClose(InstanceKey);
1331
1333
1335 {
1336 /* Report the device to the user-mode pnp manager */
1337 IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED,
1338 &DeviceNode->InstancePath);
1339 }
1340
1341 return STATUS_SUCCESS;
1342}
1343
1344static
1348 _In_ HANDLE InstanceHandle)
1349{
1350 UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1351 UNICODE_STRING ServiceKeyName;
1352 UNICODE_STRING EnumKeyName;
1355 PKEY_VALUE_FULL_INFORMATION KeyValueInformation, kvInfo2;
1356 HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1358 ULONG Count = 0, NextInstance = 0;
1359 WCHAR ValueBuffer[6];
1361
1362 // obtain the device node's ServiceName
1363 Status = IopGetRegistryValue(InstanceHandle, L"Service", &kvInfo2);
1364 if (!NT_SUCCESS(Status))
1365 {
1366 return Status;
1367 }
1368
1369 if ((kvInfo2->Type != REG_SZ) ||
1370 (kvInfo2->DataLength <= sizeof(UNICODE_NULL)) ||
1371 (kvInfo2->DataLength > UNICODE_STRING_MAX_BYTES) ||
1372 ((kvInfo2->DataLength % sizeof(WCHAR)) != 0))
1373 {
1374 DPRINT1("ObjectName invalid (Type = %lu, DataLength = %lu)\n",
1375 kvInfo2->Type,
1376 kvInfo2->DataLength);
1377 ExFreePool(kvInfo2);
1378 return STATUS_UNSUCCESSFUL;
1379 }
1380
1381 ServiceName.MaximumLength = kvInfo2->DataLength;
1382 ServiceName.Length = (USHORT)(kvInfo2->DataLength - sizeof(UNICODE_NULL));
1383 ServiceName.Buffer = (PVOID)((ULONG_PTR)kvInfo2 + kvInfo2->DataOffset);
1384
1385 DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1386 DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1387 DPRINT("Service: %wZ\n", &ServiceName);
1388
1389 ServiceKeyName.MaximumLength = ServicesKeyPath.Length + ServiceName.Length + sizeof(UNICODE_NULL);
1390 ServiceKeyName.Length = 0;
1391 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1392 if (ServiceKeyName.Buffer == NULL)
1393 {
1394 DPRINT1("No ServiceKeyName.Buffer!\n");
1396 }
1397
1398 RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1400
1401 DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1402
1403 Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1404 if (!NT_SUCCESS(Status))
1405 {
1406 goto done;
1407 }
1408
1410 &ServiceName,
1411 &DeviceNode->ServiceName);
1412 if (!NT_SUCCESS(Status))
1413 {
1414 goto done;
1415 }
1416
1417 RtlInitUnicodeString(&EnumKeyName, L"Enum");
1418 Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1419 ServiceKey,
1420 &EnumKeyName,
1423 &Disposition);
1424 if (NT_SUCCESS(Status))
1425 {
1427 {
1428 /* Read the NextInstance value */
1429 Status = IopGetRegistryValue(ServiceEnumKey,
1430 L"Count",
1431 &KeyValueInformation);
1432 if (!NT_SUCCESS(Status))
1433 goto done;
1434
1435 if ((KeyValueInformation->Type == REG_DWORD) &&
1436 (KeyValueInformation->DataLength))
1437 {
1438 /* Read it */
1439 Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1440 KeyValueInformation->DataOffset);
1441 }
1442
1443 ExFreePool(KeyValueInformation);
1444 KeyValueInformation = NULL;
1445
1446 /* Read the NextInstance value */
1447 Status = IopGetRegistryValue(ServiceEnumKey,
1448 L"NextInstance",
1449 &KeyValueInformation);
1450 if (!NT_SUCCESS(Status))
1451 goto done;
1452
1453 if ((KeyValueInformation->Type == REG_DWORD) &&
1454 (KeyValueInformation->DataLength))
1455 {
1456 NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1457 KeyValueInformation->DataOffset);
1458 }
1459
1460 ExFreePool(KeyValueInformation);
1461 KeyValueInformation = NULL;
1462 }
1463
1464 /* Set the instance path */
1465 swprintf(ValueBuffer, L"%lu", NextInstance);
1466 RtlInitUnicodeString(&ValueName, ValueBuffer);
1467 Status = ZwSetValueKey(ServiceEnumKey,
1468 &ValueName,
1469 0,
1470 REG_SZ,
1471 DeviceNode->InstancePath.Buffer,
1472 DeviceNode->InstancePath.MaximumLength);
1473 if (!NT_SUCCESS(Status))
1474 goto done;
1475
1476 /* Increment Count and NextInstance */
1477 Count++;
1478 NextInstance++;
1479
1480 /* Set the new Count value */
1482 Status = ZwSetValueKey(ServiceEnumKey,
1483 &ValueName,
1484 0,
1485 REG_DWORD,
1486 &Count,
1487 sizeof(Count));
1488 if (!NT_SUCCESS(Status))
1489 goto done;
1490
1491 /* Set the new NextInstance value */
1492 RtlInitUnicodeString(&ValueName, L"NextInstance");
1493 Status = ZwSetValueKey(ServiceEnumKey,
1494 &ValueName,
1495 0,
1496 REG_DWORD,
1497 &NextInstance,
1498 sizeof(NextInstance));
1499 }
1500
1501done:
1502 if (ServiceEnumKey != NULL)
1503 ZwClose(ServiceEnumKey);
1504
1505 if (ServiceKey != NULL)
1506 ZwClose(ServiceKey);
1507
1508 ExFreePool(ServiceKeyName.Buffer);
1509 ExFreePool(kvInfo2);
1510
1511 return Status;
1512}
1513
1523static
1527{
1528 PNP_DEVICE_STATE PnPFlags;
1530
1532 if (!NT_SUCCESS(Status))
1533 {
1534 return Status;
1535 }
1536
1537 if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
1538 DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
1539 else
1540 DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
1541
1542 if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
1543 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
1544 else
1545 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
1546
1547 if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
1548 {
1550 PnPFlags & PNP_DEVICE_DISABLED
1553
1555 }
1556 else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
1557 {
1558 // Query resource rebalance
1559
1560 if (PnPFlags & PNP_DEVICE_FAILED)
1562 else
1564
1565 // Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
1566 DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
1567
1568 // This will be caught up later by enumeration
1570 }
1571 else if (PnPFlags & PNP_DEVICE_FAILED)
1572 {
1575 }
1576
1577 return STATUS_SUCCESS;
1578}
1579
1580static
1584{
1587
1588 if (!(DeviceNode->Flags & DNF_IDS_QUERIED))
1589 {
1590 // query ids (for reported devices)
1592 HANDLE enumRootHandle, instanceHandle;
1593
1594 // open the enumeration root key
1595 Status = IopOpenRegistryKeyEx(&enumRootHandle, NULL, &enumRoot, KEY_READ);
1596 if (!NT_SUCCESS(Status))
1597 {
1598 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &enumRoot, Status);
1599 return Status;
1600 }
1601
1602 // open an instance subkey
1603 Status = IopOpenRegistryKeyEx(&instanceHandle, enumRootHandle, &DeviceNode->InstancePath, KEY_READ);
1604 ZwClose(enumRootHandle);
1605 if (!NT_SUCCESS(Status))
1606 {
1607 DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
1608 &DeviceNode->InstancePath, Status);
1609 return Status;
1610 }
1611
1612 IopQueryHardwareIds(DeviceNode, instanceHandle);
1613 IopQueryCompatibleIds(DeviceNode, instanceHandle);
1614
1615 DeviceNode->Flags |= DNF_IDS_QUERIED;
1616 ZwClose(instanceHandle);
1617 }
1618
1619 // we're about to start - needs enumeration
1620 DeviceNode->Flags |= DNF_REENUMERATE;
1621
1622 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
1623
1625 if (!NT_SUCCESS(Status))
1626 {
1627 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
1628 }
1629
1630 // Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
1632
1633 DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
1634 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
1635
1637
1638 return STATUS_SUCCESS;
1639}
1640
1641/* PUBLIC FUNCTIONS **********************************************************/
1642
1652static
1657{
1658 KIRQL oldIrql;
1659
1664
1665 PDEVICE_OBJECT vpbDevObj = DeviceObject, targetDevice = DeviceObject;
1666
1667 // walk the device stack down, stop on a first mounted device
1668 do
1669 {
1670 if (vpbDevObj->Vpb)
1671 {
1672 // two locks are needed here
1673 KeWaitForSingleObject(&vpbDevObj->DeviceLock, Executive, KernelMode, FALSE, NULL);
1674 IoAcquireVpbSpinLock(&oldIrql);
1675
1677 {
1678 vpbDevObj->Vpb->Flags &= ~VPB_REMOVE_PENDING;
1679 }
1680 else
1681 {
1682 vpbDevObj->Vpb->Flags |= VPB_REMOVE_PENDING;
1683 }
1684
1685 BOOLEAN isMounted = (_Bool)(vpbDevObj->Vpb->Flags & VPB_MOUNTED);
1686
1687 if (isMounted)
1688 {
1689 targetDevice = vpbDevObj->Vpb->DeviceObject;
1690 }
1691
1692 IoReleaseVpbSpinLock(oldIrql);
1693 KeSetEvent(&vpbDevObj->DeviceLock, IO_NO_INCREMENT, FALSE);
1694
1695 if (isMounted)
1696 {
1697 break;
1698 }
1699 }
1700
1702 vpbDevObj = vpbDevObj->AttachedDevice;
1704 } while (vpbDevObj);
1705
1706 ASSERT(targetDevice);
1707
1708 PVOID info;
1709 IO_STACK_LOCATION stack = {.MajorFunction = IRP_MJ_PNP, .MinorFunction = MinorFunction};
1710
1711 return IopSynchronousCall(targetDevice, &stack, &info);
1712}
1713
1717
1718static
1719VOID
1720NTAPI
1722{
1724
1726
1727 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1729
1730 /* Start of HACK: update resources stored in registry, so IopDetectResourceConflict works */
1731 if (DeviceNode->ResourceList)
1732 {
1733 ASSERT(DeviceNode->ResourceListTranslated);
1734 DeviceNode->ResourceList->Count = 0;
1735 DeviceNode->ResourceListTranslated->Count = 0;
1737 }
1738 /* End of HACK */
1739
1741 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
1743 if (refCount != 0)
1744 {
1745 DPRINT1("Leaking device %wZ, refCount = %d\n", &DeviceNode->InstancePath, (INT32)refCount);
1746 }
1747}
1748
1749static
1750VOID
1752{
1753 /* This function DOES dereference the device objects in all cases */
1754
1755 ULONG i;
1756
1757 for (i = 0; i < DeviceRelations->Count; i++)
1758 {
1759 IopSendRemoveDevice(DeviceRelations->Objects[i]);
1760 DeviceRelations->Objects[i] = NULL;
1761 }
1762
1763 ExFreePool(DeviceRelations);
1764}
1765
1766static
1767VOID
1769{
1770 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1771 KIRQL OldIrql;
1772
1774 ChildDeviceNode = ParentDeviceNode->Child;
1775 while (ChildDeviceNode != NULL)
1776 {
1777 NextDeviceNode = ChildDeviceNode->Sibling;
1779
1780 IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1781
1782 ChildDeviceNode = NextDeviceNode;
1783
1785 }
1787}
1788
1789static
1790VOID
1791NTAPI
1793{
1795 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1797}
1798
1799static
1800VOID
1801NTAPI
1803{
1804 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1806
1807 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
1808}
1809
1810static
1811VOID
1813{
1814 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1815 KIRQL OldIrql;
1816
1818 ChildDeviceNode = ParentDeviceNode->Child;
1819 while (ChildDeviceNode != NULL)
1820 {
1821 NextDeviceNode = ChildDeviceNode->Sibling;
1823
1825
1826 ChildDeviceNode = NextDeviceNode;
1827
1829 }
1831}
1832
1833static
1834VOID
1836{
1837 /* This function DOES dereference the device objects in all cases */
1838
1839 ULONG i;
1840
1841 for (i = 0; i < DeviceRelations->Count; i++)
1842 {
1843 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1844 ObDereferenceObject(DeviceRelations->Objects[i]);
1845 DeviceRelations->Objects[i] = NULL;
1846 }
1847
1848 ExFreePool(DeviceRelations);
1849}
1850
1851static
1852VOID
1854{
1857 PDEVICE_RELATIONS DeviceRelations;
1859
1861
1862 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1863
1867 &Stack);
1868 if (!NT_SUCCESS(Status))
1869 {
1870 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1871 DeviceRelations = NULL;
1872 }
1873 else
1874 {
1875 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1876 }
1877
1878 if (DeviceRelations)
1879 IopCancelRemoveDeviceRelations(DeviceRelations);
1880}
1881
1882static
1884NTAPI
1886{
1889
1891
1892 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1893 &DeviceNode->InstancePath);
1894
1896
1897 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
1898
1899 if (!NT_SUCCESS(Status))
1900 {
1901 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1902 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1903 &DeviceNode->InstancePath);
1904 }
1905
1906 return Status;
1907}
1908
1909static
1912{
1913 PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1915 KIRQL OldIrql;
1916
1918 ChildDeviceNode = ParentDeviceNode->Child;
1919 while (ChildDeviceNode != NULL)
1920 {
1921 NextDeviceNode = ChildDeviceNode->Sibling;
1924
1926 if (!NT_SUCCESS(Status))
1927 {
1928 FailedRemoveDevice = ChildDeviceNode;
1929 goto cleanup;
1930 }
1931
1933 ChildDeviceNode = NextDeviceNode;
1934 }
1936
1937 return STATUS_SUCCESS;
1938
1939cleanup:
1941 ChildDeviceNode = ParentDeviceNode->Child;
1942 while (ChildDeviceNode != NULL)
1943 {
1944 NextDeviceNode = ChildDeviceNode->Sibling;
1946
1948
1949 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1950 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1951 if (ChildDeviceNode == FailedRemoveDevice)
1952 return Status;
1953
1954 ChildDeviceNode = NextDeviceNode;
1955
1957 }
1959
1960 return Status;
1961}
1962
1963static
1966{
1967 /* This function DOES NOT dereference the device objects on SUCCESS
1968 * but it DOES dereference device objects on FAILURE */
1969
1970 ULONG i, j;
1972
1973 for (i = 0; i < DeviceRelations->Count; i++)
1974 {
1975 Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 j = i;
1979 goto cleanup;
1980 }
1981 }
1982
1983 return STATUS_SUCCESS;
1984
1985cleanup:
1986 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1987 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1988 for (i = 0; i <= j; i++)
1989 {
1990 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1991 ObDereferenceObject(DeviceRelations->Objects[i]);
1992 DeviceRelations->Objects[i] = NULL;
1993 }
1994 for (; i < DeviceRelations->Count; i++)
1995 {
1996 ObDereferenceObject(DeviceRelations->Objects[i]);
1997 DeviceRelations->Objects[i] = NULL;
1998 }
1999 ExFreePool(DeviceRelations);
2000
2001 return Status;
2002}
2003
2004static
2007{
2011 PDEVICE_RELATIONS DeviceRelations;
2013
2014 if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
2015 {
2016 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
2017 return STATUS_UNSUCCESSFUL;
2018 }
2019
2021 {
2022 DPRINT1("Removal vetoed by failing the query remove request\n");
2023
2025
2026 return STATUS_UNSUCCESSFUL;
2027 }
2028
2029 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
2030
2034 &Stack);
2035 if (!NT_SUCCESS(Status))
2036 {
2037 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2038 DeviceRelations = NULL;
2039 }
2040 else
2041 {
2042 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2043 }
2044
2045 if (DeviceRelations)
2046 {
2047 Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
2048 if (!NT_SUCCESS(Status))
2049 return Status;
2050 }
2051
2053 if (!NT_SUCCESS(Status))
2054 {
2055 if (DeviceRelations)
2056 IopCancelRemoveDeviceRelations(DeviceRelations);
2057 return Status;
2058 }
2059
2060 if (DeviceRelations)
2061 IopSendRemoveDeviceRelations(DeviceRelations);
2063
2064 return STATUS_SUCCESS;
2065}
2066
2067static
2070{
2072
2073 // This function removes the device subtree, with the root in DeviceNode
2074 // atm everyting is in fact done inside this function, which is completely wrong.
2075 // The right implementation should have a separate removal worker thread and
2076 // properly do device node state transitions
2077
2078 DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
2079
2080 BOOLEAN surpriseRemoval = (_Bool)(DeviceNode->Flags & DNF_DEVICE_GONE);
2081
2082 Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, surpriseRemoval);
2083
2084 if (surpriseRemoval)
2085 {
2086 IopSendSurpriseRemoval(DeviceNode->PhysicalDeviceObject);
2087 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL, &DeviceNode->InstancePath);
2088 }
2089
2090 if (NT_SUCCESS(Status))
2091 {
2092 IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
2093 if (surpriseRemoval)
2094 {
2095 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL, &DeviceNode->InstancePath);
2096 }
2097 return STATUS_SUCCESS;
2098 }
2099
2100 return Status;
2101}
2102
2103static
2107{
2108 PDEVICE_OBJECT ChildDeviceObject;
2109 PDEVICE_NODE ChildDeviceNode;
2110 ULONG i;
2111
2112 // bus relations are already obtained for this device node
2113
2114 if (!NT_SUCCESS(DeviceNode->CompletionStatus))
2115 {
2116 DPRINT("QDR request failed for %wZ, status %x\n",
2117 &DeviceNode->InstancePath, DeviceNode->CompletionStatus);
2118 // treat as if there are no child objects
2119 }
2120
2121 PDEVICE_RELATIONS DeviceRelations = DeviceNode->OverUsed1.PendingDeviceRelations;
2122 DeviceNode->OverUsed1.PendingDeviceRelations = NULL;
2123
2124 // it's acceptable not to have PDOs
2125 if (!DeviceRelations)
2126 {
2128 DPRINT("No PDOs\n");
2129 return STATUS_SUCCESS;
2130 }
2131
2132 // mark children nodes as non-present (those not returned in DR request will be removed)
2133 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2134 {
2135 child->Flags &= ~DNF_ENUMERATED;
2136 }
2137
2138 DPRINT("PiEnumerateDevice: enumerating %u children\n", DeviceRelations->Count);
2139
2140 // create device nodes for all new children and set DNF_ENUMERATED back for old ones
2141 for (i = 0; i < DeviceRelations->Count; i++)
2142 {
2143 ChildDeviceObject = DeviceRelations->Objects[i];
2144 ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);
2145
2146 ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
2147 if (!ChildDeviceNode)
2148 {
2149 /* One doesn't exist, create it */
2150 ChildDeviceNode = PipAllocateDeviceNode(ChildDeviceObject);
2151 if (ChildDeviceNode)
2152 {
2153 PiInsertDevNode(ChildDeviceNode, DeviceNode);
2154
2155 /* Mark the node as enumerated */
2156 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2157
2158 /* Mark the DO as bus enumerated */
2159 ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2160 }
2161 else
2162 {
2163 /* Ignore this DO */
2164 DPRINT1("PipAllocateDeviceNode() failed. Skipping PDO %u\n", i);
2165 ObDereferenceObject(ChildDeviceObject);
2166 }
2167 }
2168 else
2169 {
2170 /* Mark it as enumerated */
2171 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2172 ObDereferenceObject(ChildDeviceObject);
2173 }
2174 }
2175 ExFreePool(DeviceRelations);
2176
2177 // time to remove non-reported devices
2178 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2179 {
2180 if (!(child->Flags & (DNF_ENUMERATED|DNF_DEVICE_GONE)))
2181 {
2182 // this flag indicates that this is a surprise removal
2183 child->Flags |= DNF_DEVICE_GONE;
2185 }
2186 }
2187
2189 return STATUS_SUCCESS;
2190}
2191
2192static
2194NTAPI
2196{
2198 PVOID Dummy;
2199
2201 Stack.MajorFunction = IRP_MJ_PNP;
2202 Stack.MinorFunction = IRP_MN_EJECT;
2203
2204 return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2205}
2206
2207/*
2208 * @implemented
2209 */
2210VOID
2211NTAPI
2213{
2215 PDEVICE_RELATIONS DeviceRelations;
2220
2221 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2222 &DeviceNode->InstancePath);
2223
2225 {
2226 goto cleanup;
2227 }
2228
2229 Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2230
2234 &Stack);
2235 if (!NT_SUCCESS(Status))
2236 {
2237 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2238 DeviceRelations = NULL;
2239 }
2240 else
2241 {
2242 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2243 }
2244
2245 if (DeviceRelations)
2246 {
2247 Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2248 if (!NT_SUCCESS(Status))
2249 goto cleanup;
2250 }
2251
2253 if (!NT_SUCCESS(Status))
2254 {
2255 if (DeviceRelations)
2256 IopCancelRemoveDeviceRelations(DeviceRelations);
2257 goto cleanup;
2258 }
2259
2261 {
2262 if (DeviceRelations)
2263 IopCancelRemoveDeviceRelations(DeviceRelations);
2265 goto cleanup;
2266 }
2267
2268 if (DeviceRelations)
2269 IopSendRemoveDeviceRelations(DeviceRelations);
2271
2273 if (Capabilities.EjectSupported)
2274 {
2276 {
2277 goto cleanup;
2278 }
2279 }
2280 else
2281 {
2282 // DeviceNode->Flags |= DNF_DISABLED;
2283 }
2284
2285 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2286 &DeviceNode->InstancePath);
2287
2288 return;
2289
2290cleanup:
2291 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2292 &DeviceNode->InstancePath);
2293}
2294
2295static
2296VOID
2299{
2301
2302 PCM_RESOURCE_LIST bootConfig = NULL;
2303 PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
2304
2305 PiIrpQueryResources(DeviceNode, &bootConfig);
2306 PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
2307
2308 DeviceNode->BootResources = bootConfig;
2309 DeviceNode->ResourceRequirements = resourceRequirements;
2310
2311 if (bootConfig)
2312 {
2314 }
2315
2316 DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
2317}
2318
2319static
2320VOID
2323{
2325 BOOLEAN doProcessAgain;
2326 PDEVICE_NODE currentNode = RootNode;
2327 PDEVICE_OBJECT referencedObject;
2328
2329 do
2330 {
2331 doProcessAgain = FALSE;
2332
2333 // The device can be removed during processing, but we still need its Parent and Sibling
2334 // links to continue the tree traversal. So keep the link till the and of a cycle
2335 referencedObject = currentNode->PhysicalDeviceObject;
2336 ObReferenceObject(referencedObject);
2337
2338 // Devices with problems are skipped (unless they are not being removed)
2339 if (currentNode->Flags & DNF_HAS_PROBLEM &&
2340 currentNode->State != DeviceNodeAwaitingQueuedRemoval)
2341 {
2342 goto skipEnum;
2343 }
2344
2345 switch (currentNode->State)
2346 {
2347 case DeviceNodeUnspecified: // this state is not used
2348 break;
2350 DPRINT("DeviceNodeUninitialized %wZ\n", &currentNode->InstancePath);
2351 status = PiInitializeDevNode(currentNode);
2352 doProcessAgain = NT_SUCCESS(status);
2353 break;
2355 DPRINT("DeviceNodeInitialized %wZ\n", &currentNode->InstancePath);
2357 doProcessAgain = NT_SUCCESS(status);
2358 break;
2360 DPRINT("DeviceNodeDriversAdded %wZ\n", &currentNode->InstancePath);
2361 status = IopAssignDeviceResources(currentNode);
2362 doProcessAgain = NT_SUCCESS(status);
2363 break;
2365 DPRINT("DeviceNodeResourcesAssigned %wZ\n", &currentNode->InstancePath);
2366 // send IRP_MN_START_DEVICE
2367 PiIrpStartDevice(currentNode);
2368
2369 // skip DeviceNodeStartPending, it is probably used for an async IRP_MN_START_DEVICE
2371 doProcessAgain = TRUE;
2372 break;
2373 case DeviceNodeStartPending: // skipped on XP/2003
2374 break;
2376 DPRINT("DeviceNodeStartCompletion %wZ\n", &currentNode->InstancePath);
2377 status = currentNode->CompletionStatus;
2378 doProcessAgain = TRUE;
2379 if (!NT_SUCCESS(status))
2380 {
2384
2385 PiSetDevNodeProblem(currentNode, problem);
2387 }
2388 else
2389 {
2390 // TODO: IopDoDeferredSetInterfaceState and IopAllocateLegacyBootResources
2391 // are called here too
2392
2394 }
2395 break;
2397 DPRINT("DeviceNodeStartPostWork %wZ\n", &currentNode->InstancePath);
2398 // TODO: inspect the status
2399 status = PiStartDeviceFinal(currentNode);
2400 doProcessAgain = TRUE;
2401 break;
2402 case DeviceNodeStarted:
2403 if (currentNode->Flags & DNF_REENUMERATE)
2404 {
2405 DPRINT("DeviceNodeStarted REENUMERATE %wZ\n", &currentNode->InstancePath);
2406 currentNode->Flags &= ~DNF_REENUMERATE;
2408
2409 // again, skip DeviceNodeEnumeratePending as with the starting sequence
2411 doProcessAgain = TRUE;
2412 }
2413 else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
2414 {
2415 if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
2416 {
2417 PiFakeResourceRebalance(currentNode);
2418 currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
2419 }
2420 else
2421 {
2422 PiIrpQueryStopDevice(currentNode);
2424 }
2425
2426 doProcessAgain = TRUE;
2427 }
2428 break;
2430 // we're here after sending IRP_MN_QUERY_STOP_DEVICE
2431 status = currentNode->CompletionStatus;
2432 if (NT_SUCCESS(status))
2433 {
2434 PiIrpStopDevice(currentNode);
2436 }
2437 else
2438 {
2439 PiIrpCancelStopDevice(currentNode);
2441 }
2442 doProcessAgain = TRUE;
2443 break;
2444 case DeviceNodeStopped:
2445 // TODO: do resource rebalance (not implemented)
2446 PiFakeResourceRebalance(currentNode);
2447
2449 doProcessAgain = TRUE;
2450 break;
2452 break;
2453 case DeviceNodeEnumeratePending: // skipped on XP/2003
2454 break;
2456 DPRINT("DeviceNodeEnumerateCompletion %wZ\n", &currentNode->InstancePath);
2457 status = PiEnumerateDevice(currentNode);
2458 doProcessAgain = TRUE;
2459 break;
2461 break;
2463 DPRINT("DeviceNodeAwaitingQueuedRemoval %wZ\n", &currentNode->InstancePath);
2464 status = IopRemoveDevice(currentNode);
2465 break;
2467 break;
2469 break;
2470 case DeviceNodeRemoved:
2471 break;
2473 break;
2474 case DeviceNodeDeleted:
2475 break;
2476 default:
2477 break;
2478 }
2479
2480skipEnum:
2481 if (!doProcessAgain)
2482 {
2483 KIRQL OldIrql;
2485 /* If we have a child, simply go down the tree */
2486 if (currentNode->State != DeviceNodeRemoved && currentNode->Child != NULL)
2487 {
2488 ASSERT(currentNode->Child->Parent == currentNode);
2489 currentNode = currentNode->Child;
2490 }
2491 else
2492 {
2493 while (currentNode != RootNode)
2494 {
2495 /* All children processed -- go sideways */
2496 if (currentNode->Sibling != NULL)
2497 {
2498 ASSERT(currentNode->Sibling->Parent == currentNode->Parent);
2499 currentNode = currentNode->Sibling;
2500 break;
2501 }
2502 else
2503 {
2504 /* We're the last sibling -- go back up */
2505 ASSERT(currentNode->Parent->LastChild == currentNode);
2506 currentNode = currentNode->Parent;
2507 }
2508 /* We already visited the parent and all its children, so keep looking */
2509 }
2510 }
2512 }
2513 ObDereferenceObject(referencedObject);
2514 } while (doProcessAgain || currentNode != RootNode);
2515}
2516
2517#ifdef DBG
2518static
2519PCSTR
2520ActionToStr(
2522{
2523 switch (Action)
2524 {
2526 return "PiActionEnumDeviceTree";
2528 return "PiActionEnumRootDevices";
2530 return "PiActionResetDevice";
2532 return "PiActionAddBootDevices";
2534 return "PiActionStartDevice";
2535 case PiActionQueryState:
2536 return "PiActionQueryState";
2537 default:
2538 return "(request unknown)";
2539 }
2540}
2541#endif
2542
2543static
2544VOID
2545NTAPI
2548{
2549 PLIST_ENTRY ListEntry;
2551 KIRQL OldIrql;
2552 PDEVICE_NODE deviceNode;
2554
2557 {
2560 Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2561
2562 ASSERT(Request->DeviceObject);
2563
2564 deviceNode = IopGetDeviceNode(Request->DeviceObject);
2565 ASSERT(deviceNode);
2566
2568
2569 DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2570 Request, Request->DeviceObject, ActionToStr(Request->Action));
2571
2572 switch (Request->Action)
2573 {
2575 {
2576 if (deviceNode->State == DeviceNodeInitialized &&
2577 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2578 {
2580 }
2581 break;
2582 }
2585 deviceNode->Flags |= DNF_REENUMERATE;
2586 PiDevNodeStateMachine(deviceNode);
2587 break;
2588
2590 // TODO: the operation is a no-op for everything except removed nodes
2591 // for removed nodes, it returns them back to DeviceNodeUninitialized
2592 if (deviceNode->State == DeviceNodeRemoved)
2593 {
2594 deviceNode->State = DeviceNodeUninitialized;
2595 }
2597 break;
2598
2600 // This action is triggered from usermode, when a driver is installed
2601 // for a non-critical PDO
2602 if (deviceNode->State == DeviceNodeInitialized &&
2603 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2604 {
2605 PiDevNodeStateMachine(deviceNode);
2606 }
2607 else
2608 {
2609 DPRINT1("NOTE: attempt to start an already started/uninitialized device %wZ\n",
2610 &deviceNode->InstancePath);
2612 }
2613 break;
2614
2615 case PiActionQueryState:
2616 // This action is only valid for started devices. If the device is not yet
2617 // started, the PnP manager issues IRP_MN_QUERY_PNP_DEVICE_STATE by itself.
2618 if (deviceNode->State == DeviceNodeStarted)
2619 {
2620 // Issue a IRP_MN_QUERY_PNP_DEVICE_STATE request: it will update node's flags
2621 // and then do enumeration if something has changed
2622 status = PiUpdateDeviceState(deviceNode);
2623 if (NT_SUCCESS(status))
2624 {
2625 PiDevNodeStateMachine(deviceNode);
2626 }
2627 }
2628 // TODO: Windows may return STATUS_DELETE_PENDING here
2630 break;
2631
2632 default:
2633 DPRINT1("Unimplemented device action %u\n", Request->Action);
2635 break;
2636 }
2637
2638 if (Request->CompletionStatus)
2639 {
2640 *Request->CompletionStatus = status;
2641 }
2642
2643 if (Request->CompletionEvent)
2644 {
2645 KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2646 }
2647
2648 DPRINT("Finished processing PnP request %p\n", Request);
2649 ObDereferenceObject(Request->DeviceObject);
2652 }
2656}
2657
2667VOID
2671 _In_opt_ PKEVENT CompletionEvent,
2672 _Out_opt_ NTSTATUS *CompletionStatus)
2673{
2675 KIRQL OldIrql;
2676
2678
2679 DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2680 DeviceObject, Request, ActionToStr(Action));
2681
2683
2684 Request->DeviceObject = DeviceObject;
2685 Request->Action = Action;
2686 Request->CompletionEvent = CompletionEvent;
2687 Request->CompletionStatus = CompletionStatus;
2688
2691
2693 {
2695
2699
2701 return;
2702 }
2703
2705 {
2707 return;
2708 }
2712
2715}
2716
2730{
2731 KEVENT opFinished;
2733
2737
2738 return status;
2739}
#define PAGED_CODE()
DWORD Id
@ DeviceNode
Definition: Node.h:9
signed int INT32
unsigned char BOOLEAN
unsigned int UINT32
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static WCHAR ServiceName[]
Definition: browser.c:19
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define CM_PROB_REGISTRY
Definition: cfg.h:49
#define CM_PROB_FAILED_ADD
Definition: cfg.h:61
#define CM_PROB_HELD_FOR_EJECT
Definition: cfg.h:77
#define CM_PROB_HARDWARE_DISABLED
Definition: cfg.h:59
#define CM_PROB_NEED_RESTART
Definition: cfg.h:44
#define CM_PROB_DEVICE_NOT_THERE
Definition: cfg.h:54
#define CM_PROB_DRIVER_SERVICE_KEY_INVALID
Definition: cfg.h:70
#define CM_PROB_FAILED_START
Definition: cfg.h:40
#define CM_PROB_DRIVER_FAILED_LOAD
Definition: cfg.h:69
#define CM_PROB_OUT_OF_MEMORY
Definition: cfg.h:33
#define CM_PROB_FAILED_POST_START
Definition: cfg.h:73
#define CM_PROB_FAILED_DRIVER_ENTRY
Definition: cfg.h:67
#define CM_PROB_DISABLED_SERVICE
Definition: cfg.h:62
Definition: bufpool.h:45
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: d3dkmdt.h:46
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:1025
LIST_ENTRY IopDeviceActionRequestList
Definition: devaction.c:46
KSPIN_LOCK IopDeviceActionLock
Definition: devaction.c:49
#define MAX_DEVICE_ID_LEN
Definition: devaction.c:40
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
static VOID NTAPI IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1792
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:532
KEVENT PiEnumerationFinished
Definition: devaction.c:50
NTSTATUS IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:606
static NTSTATUS PiIrpSendRemoveCheckVpb(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction)
Sends one of the remove IRPs to the device stack.
Definition: devaction.c:1654
NTSTATUS IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:961
ERESOURCE IopDriverLoadResource
Definition: driver.c:20
struct _ATTACH_FILTER_DRIVERS_CONTEXT * PATTACH_FILTER_DRIVERS_CONTEXT
static NTSTATUS IopCreateDeviceInstancePath(_In_ PDEVICE_NODE DeviceNode, _Out_ PUNICODE_STRING InstancePath)
Definition: devaction.c:213
static const WCHAR ServicesKeyName[]
Definition: devaction.c:51
BOOLEAN PnPBootDriversInitialized
Definition: pnpinit.c:21
NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
Definition: pnpmgr.c:760
NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
Definition: devaction.c:857
BOOLEAN PnpSystemInit
Definition: iomgr.c:17
static NTSTATUS PiEnumerateDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2105
struct _ADD_DEV_DRIVERS_LIST * PADD_DEV_DRIVERS_LIST
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2546
struct _ADD_DEV_DRIVERS_LIST ADD_DEV_DRIVERS_LIST
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1853
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1965
_ADD_DEV_DRIVER_TYPE
Definition: devaction.c:65
@ UpperFilter
Definition: devaction.c:69
@ LowerFilter
Definition: devaction.c:66
@ LowerClassFilter
Definition: devaction.c:67
@ DeviceDriver
Definition: devaction.c:68
@ UpperClassFilter
Definition: devaction.c:70
USHORT NTAPI IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
Definition: pnpmgr.c:411
struct _DEVICE_ACTION_REQUEST DEVICE_ACTION_REQUEST
static VOID IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1768
static NTSTATUS IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
static NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:2069
static VOID PiDevNodeStateMachine(_In_ PDEVICE_NODE RootNode)
Definition: devaction.c:2321
WORK_QUEUE_ITEM IopDeviceActionWorkItem
Definition: devaction.c:47
VOID PiSetDevNodeText(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceKey)
Sets the DeviceNode's DeviceDesc and LocationInformation registry values.
Definition: devaction.c:1092
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1835
static NTSTATUS NTAPI IopSendEject(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:2195
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1802
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1751
static NTSTATUS IopSetServiceEnumData(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
Definition: devaction.c:1346
#define MAX_SEPARATORS_DEVICEID
Definition: devaction.c:42
static NTSTATUS PiStartDeviceFinal(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1582
static VOID PiFakeResourceRebalance(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2297
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1885
static NTSTATUS PiInitializeDevNode(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1193
#define MAX_SEPARATORS_INSTANCEID
Definition: devaction.c:41
struct _DEVICE_ACTION_REQUEST * PDEVICE_ACTION_REQUEST
static BOOLEAN IopValidateID(_In_ PWCHAR Id, _In_ BUS_QUERY_ID_TYPE QueryType)
Definition: devaction.c:122
static NTSTATUS IopQueryHardwareIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:960
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:363
static VOID IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1812
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:48
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1911
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:2668
static NTSTATUS PiUpdateDeviceState(_In_ PDEVICE_NODE DeviceNode)
Processes the IoInvalidateDeviceState request.
Definition: devaction.c:1525
VOID NTAPI IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:2212
static VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1721
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
NTSTATUS PiPerformSyncDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
Perfom a device operation synchronously via PiQueueDeviceAction.
Definition: devaction.c:2727
VOID NTAPI IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:45
enum _ADD_DEV_DRIVER_TYPE ADD_DEV_DRIVER_TYPE
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:20
struct _ATTACH_FILTER_DRIVERS_CONTEXT ATTACH_FILTER_DRIVERS_CONTEXT
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:595
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static void cleanup(void)
Definition: main.c:1335
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#define swprintf
Definition: precomp.h:40
static const WCHAR Cleanup[]
Definition: register.c:80
#define ULONG_PTR
Definition: config.h:101
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
static int isMounted
Definition: fatten.c:16
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:908
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
Definition: green.h:16
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
struct _CM_RESOURCE_LIST * PCM_RESOURCE_LIST
@ InterfaceTypeUndefined
Definition: hwresource.cpp:136
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
#define REG_SZ
Definition: layer.c:22
PCONFIGURATION_COMPONENT_DATA RootNode
Definition: macharm.c:19
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static HWND child
Definition: cursoricon.c:298
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
NTSYSAPI NTSTATUS NTAPI ZwQueryDefaultLocale(_In_ BOOLEAN UserProfile, _Out_ PLCID DefaultLocaleId)
#define KernelMode
Definition: asm.h:38
#define DNF_REENUMERATE
Definition: iotypes.h:173
#define DNF_LEGACY_DRIVER
Definition: iotypes.h:182
#define DNF_ENUMERATED
Definition: iotypes.h:174
#define DNF_DEVICE_GONE
Definition: iotypes.h:186
@ DeviceNodeDriversAdded
Definition: iotypes.h:537
@ DeviceNodeRemovePendingCloses
Definition: iotypes.h:551
@ DeviceNodeStopped
Definition: iotypes.h:544
@ DeviceNodeRestartCompletion
Definition: iotypes.h:545
@ DeviceNodeAwaitingQueuedRemoval
Definition: iotypes.h:549
@ DeviceNodeRemoved
Definition: iotypes.h:552
@ DeviceNodeInitialized
Definition: iotypes.h:536
@ DeviceNodeQueryRemoved
Definition: iotypes.h:550
@ DeviceNodeStartPostWork
Definition: iotypes.h:541
@ DeviceNodeStarted
Definition: iotypes.h:542
@ DeviceNodeStartCompletion
Definition: iotypes.h:540
@ DeviceNodeDeleted
Definition: iotypes.h:554
@ DeviceNodeEnumerateCompletion
Definition: iotypes.h:547
@ DeviceNodeAwaitingQueuedDeletion
Definition: iotypes.h:548
@ DeviceNodeEnumeratePending
Definition: iotypes.h:546
@ DeviceNodeResourcesAssigned
Definition: iotypes.h:538
@ DeviceNodeUninitialized
Definition: iotypes.h:535
@ DeviceNodeQueryStopped
Definition: iotypes.h:543
@ DeviceNodeStartPending
Definition: iotypes.h:539
@ DeviceNodeUnspecified
Definition: iotypes.h:534
@ DeviceNodeDeletePendingCloses
Definition: iotypes.h:553
#define DNUF_NOT_DISABLEABLE
Definition: iotypes.h:211
#define DNUF_DONT_SHOW_IN_UI
Definition: iotypes.h:209
#define DNF_HAS_BOOT_CONFIG
Definition: iotypes.h:176
#define DNF_HAS_PROBLEM
Definition: iotypes.h:183
#define DNF_NON_STOPPED_REBALANCE
Definition: iotypes.h:181
#define DNF_IDS_QUERIED
Definition: iotypes.h:175
#define DNF_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:180
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4202
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4203
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
int Count
Definition: noreturn.cpp:7
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
@ KeyValueBasicInformation
Definition: nt_native.h:1180
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define REG_MULTI_SZ
Definition: nt_native.h:1501
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
struct _RTL_QUERY_REGISTRY_TABLE RTL_QUERY_REGISTRY_TABLE
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_NONE
Definition: nt_native.h:1492
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define UNICODE_NULL
#define UNICODE_STRING_MAX_BYTES
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ SynchronizationEvent
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
NTSTATUS PiIrpQueryResources(_In_ PDEVICE_NODE DeviceNode, _Out_ PCM_RESOURCE_LIST *Resources)
Definition: pnpirp.c:201
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
NTSTATUS PiIrpStartDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:87
PDEVICE_NODE FASTCALL IopGetDeviceNode(IN PDEVICE_OBJECT DeviceObject)
NTSTATUS PiIrpQueryPnPDeviceState(_In_ PDEVICE_NODE DeviceNode, _Out_ PPNP_DEVICE_STATE DeviceState)
Definition: pnpirp.c:284
NTSTATUS PiIrpCancelStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:154
@ PiActionResetDevice
Definition: io.h:528
@ PiActionQueryState
Definition: io.h:531
@ PiActionAddBootDevices
Definition: io.h:529
@ PiActionStartDevice
Definition: io.h:530
@ PiActionEnumRootDevices
Definition: io.h:527
@ PiActionEnumDeviceTree
Definition: io.h:526
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1950
VOID PiInsertDevNode(_In_ PDEVICE_NODE DeviceNode, _In_ PDEVICE_NODE ParentNode)
Definition: devnode.c:80
NTSTATUS NTAPI IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:1116
PDEVICE_NODE PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject)
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:522
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
#define IopDeviceNodeHasFlag(DeviceNode, Flag)
Definition: io.h:164
NTSTATUS IopQueueDeviceInstallEvent(_In_ const GUID *Guid, _In_ PUNICODE_STRING DeviceId)
Definition: plugplay.c:97
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1036
#define IopDeviceNodeSetFlag(DeviceNode, Flag)
Definition: io.h:146
NTSTATUS IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION IoStackLocation, OUT PVOID *Information)
NTSTATUS NTAPI IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIO_STATUS_BLOCK IoStatusBlock, IN UCHAR MinorFunction, IN PIO_STACK_LOCATION Stack)
NTSTATUS IopGetDriverNames(_In_ HANDLE ServiceHandle, _Out_ PUNICODE_STRING DriverName, _Out_opt_ PUNICODE_STRING ServiceName)
Definition: driver.c:123
NTSTATUS PiIrpQueryResourceRequirements(_In_ PDEVICE_NODE DeviceNode, _Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources)
Definition: pnpirp.c:227
VOID PiSetDevNodeProblem(_In_ PDEVICE_NODE DeviceNode, _In_ UINT32 Problem)
Definition: devnode.c:132
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)
PNP_DEVNODE_STATE PiSetDevNodeState(_In_ PDEVICE_NODE DeviceNode, _In_ PNP_DEVNODE_STATE NewState)
Definition: devnode.c:108
enum _DEVICE_ACTION DEVICE_ACTION
NTSTATUS PiIrpQueryStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:133
NTSTATUS PiIrpStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:111
NTSTATUS IopQueueTargetDeviceEvent(_In_ const GUID *Guid, _In_ PUNICODE_STRING DeviceIds)
#define ENUM_ROOT
Definition: io.h:53
NTSTATUS PiIrpQueryDeviceText(_In_ PDEVICE_NODE DeviceNode, _In_ LCID LocaleId, _In_ DEVICE_TEXT_TYPE Type, _Out_ PWSTR *DeviceText)
Definition: pnpirp.c:253
NTSTATUS PiIrpQueryDeviceRelations(_In_ PDEVICE_NODE DeviceNode, _In_ DEVICE_RELATION_TYPE Type)
Definition: pnpirp.c:176
PDEVICE_OBJECT NTAPI IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1385
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
POBJECT_TYPE IoDriverObjectType
Definition: driver.c:34
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
#define STATUS_FAILED_DRIVER_ENTRY
Definition: ntstatus.h:911
#define STATUS_ILL_FORMED_SERVICE_ENTRY
Definition: ntstatus.h:588
#define STATUS_PNP_REBOOT_REQUIRED
Definition: ntstatus.h:830
#define STATUS_PLUGPLAY_NO_DEVICE
Definition: ntstatus.h:731
_Must_inspect_result_ _In_ KTMOBJECT_TYPE QueryType
Definition: nttmapi.h:404
#define L(x)
Definition: ntvdm.h:50
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
#define BOOLEAN
Definition: pedump.c:73
unsigned short USHORT
Definition: pedump.c:61
PDEVICE_NODE PopSystemPowerDeviceNode
Definition: power.c:25
#define FILE_DEVICE_ACPI
Definition: winioctl.h:95
#define REGSTR_KEY_DEVICE_PROPERTIES
Definition: regstr.h:752
#define REGSTR_VAL_CLASSGUID
Definition: regstr.h:422
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
#define REG_DWORD
Definition: sdbapi.c:596
DWORD LCID
Definition: nls.h:13
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PDRIVER_OBJECT DriverObject
Definition: devaction.c:76
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:77
LIST_ENTRY ListEntry
Definition: devaction.c:75
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:82
DEVICE_ACTION Action
Definition: devaction.c:61
LIST_ENTRY RequestListEntry
Definition: devaction.c:57
PDEVICE_OBJECT DeviceObject
Definition: devaction.c:58
NTSTATUS * CompletionStatus
Definition: devaction.c:60
NTSTATUS CompletionStatus
Definition: iotypes.h:1005
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:994
PNP_DEVNODE_STATE State
Definition: iotypes.h:1001
struct _DEVICE_NODE * Child
Definition: iotypes.h:995
ULONG Flags
Definition: iotypes.h:1007
struct _DEVICE_NODE * Parent
Definition: iotypes.h:996
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1010
UNICODE_STRING InstancePath
Definition: iotypes.h:1013
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
PDRIVER_ADD_DEVICE AddDevice
Definition: iotypes.h:2220
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2282
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: http.c:7252
Definition: format.c:80
Definition: ps.c:97
#define TAG_PNP_DEVACTION
Definition: tag.h:96
#define TAG_IO
Definition: tag.h:79
static VOID ErrorExit(LPTSTR lpszMessage)
Definition: telnetd.c:647
char serviceName[]
Definition: tftpd.cpp:34
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_In_ ULONG TotalLength
Definition: usbdlib.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFDEVICE _In_ PPNP_BUS_INFORMATION BusInformation
Definition: wdfdevice.h:3915
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1699
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define DeviceCapabilities
Definition: wingdi.h:4449
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
struct _PNP_BUS_INFORMATION * PPNP_BUS_INFORMATION
enum _CM_SERVICE_LOAD_TYPE SERVICE_LOAD_TYPE
@ DisableLoad
Definition: cmtypes.h:1000
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
DEVICE_CAPABILITIES
Definition: iotypes.h:965
@ EjectionRelations
Definition: iotypes.h:2153
@ RemovalRelations
Definition: iotypes.h:2155
@ BusRelations
Definition: iotypes.h:2152
#define IRP_MN_EJECT
#define PNP_DEVICE_NOT_DISABLEABLE
Definition: iotypes.h:1006
#define VPB_MOUNTED
Definition: iotypes.h:1807
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:1005
#define DO_BUS_ENUMERATED_DEVICE
#define PNP_DEVICE_FAILED
Definition: iotypes.h:1003
ULONG PNP_DEVICE_STATE
Definition: iotypes.h:997
#define PNP_DEVICE_DONT_DISPLAY_IN_UI
Definition: iotypes.h:1002
#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS
#define IRP_MN_QUERY_ID
#define IRP_MN_REMOVE_DEVICE
#define PNP_DEVICE_DISABLED
Definition: iotypes.h:1001
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define IRP_MN_QUERY_CAPABILITIES
#define IRP_MN_QUERY_RESOURCES
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965
#define IRP_MN_CANCEL_REMOVE_DEVICE
@ DeviceTextLocationInformation
Definition: iotypes.h:2946
@ DeviceTextDescription
Definition: iotypes.h:2945
@ BusQueryCompatibleIDs
Definition: iotypes.h:2938
@ BusQueryInstanceID
Definition: iotypes.h:2939
@ BusQueryDeviceID
Definition: iotypes.h:2936
@ BusQueryHardwareIDs
Definition: iotypes.h:2937
#define PNP_DEVICE_REMOVED
Definition: iotypes.h:1004
struct _IO_RESOURCE_REQUIREMENTS_LIST * PIO_RESOURCE_REQUIREMENTS_LIST
#define IRP_MN_QUERY_BUS_INFORMATION
#define IRP_MN_QUERY_REMOVE_DEVICE
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ NonPagedPoolMustSucceed
Definition: ketypes.h:880
@ Executive
Definition: ketypes.h:415
@ LockQueueIoDatabaseLock
Definition: ketypes.h:668
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180