ReactOS 0.4.16-dev-91-g764881a
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 && kvInfo->DataLength > sizeof(WCHAR))
632 {
633 UNICODE_STRING classGUID = {
634 .MaximumLength = kvInfo->DataLength,
635 .Length = kvInfo->DataLength - sizeof(UNICODE_NULL),
636 .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset)
637 };
638 HANDLE ccsControlHandle;
639
640 Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ);
641 if (!NT_SUCCESS(Status))
642 {
643 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n",
644 &ccsControlClass, Status);
645 }
646 else
647 {
648 // open the CCS\Control\Class<ClassGUID> key
649 Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ);
650 ZwClose(ccsControlHandle);
651 if (!NT_SUCCESS(Status))
652 {
653 DPRINT1("Failed to open class key \"%wZ\" (status %x)\n", &classGUID, Status);
654 }
655 }
656
657 if (ClassKey)
658 {
659 // Check the Properties key of a class too
660 // Windows fills some device properties from this key (which is protected)
661 // TODO: add the device properties from this key
662
664 HANDLE propertiesHandle;
665
666 Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ);
667 if (!NT_SUCCESS(Status))
668 {
669 DPRINT("Properties key failed to open for \"%wZ\" (status %x)\n",
670 &classGUID, Status);
671 }
672 else
673 {
674 ZwClose(propertiesHandle);
675 }
676 }
677 }
678
679 ExFreePool(kvInfo);
680 }
681
682 // the driver loading order:
683 // 1. LowerFilters
684 // 2. LowerClassFilters
685 // 3. Device driver (only one service!)
686 // 4. UpperFilters
687 // 5. UpperClassFilters
688
689 LIST_ENTRY drvListHead;
690 InitializeListHead(&drvListHead);
691
692 // lower (class) filters
693 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers);
694 if (!NT_SUCCESS(Status))
695 {
696 goto Cleanup;
697 }
698
699 ATTACH_FILTER_DRIVERS_CONTEXT routineContext = {
700 .DriversListHead = &drvListHead,
701 .DriverType = DeviceDriver,
702 .DeviceNode = DeviceNode
703 };
704
705 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{
707 .Name = L"Service",
709 .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here
710 .DefaultData = L"",
711 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
712 },};
713
714 // device driver
716 (PWSTR)SubKey,
717 queryTable,
718 &routineContext,
719 NULL);
720 if (NT_SUCCESS(Status))
721 {
722 // do nothing
723 }
724 // if a driver is not found, but a device allows raw access -> proceed
726 (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK
727 {
728 // add a dummy entry to the drivers list (need for later processing)
730 sizeof(*driverEntry),
732 driverEntry->DriverType = DeviceDriver;
733 InsertTailList(&drvListHead, &driverEntry->ListEntry);
734 DPRINT("No service for \"%wZ\" (RawDeviceOK)\n", &DeviceNode->InstancePath);
735 }
736 else
737 {
739 {
741 }
742 DPRINT("No service for \"%wZ\" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers);
743 goto Cleanup;
744 }
745
746 // upper (class) filters
747 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers);
748 if (!NT_SUCCESS(Status))
749 {
750 goto Cleanup;
751 }
752
753 // finally loop through the stack and call AddDevice for every driver
754 for (PLIST_ENTRY listEntry = drvListHead.Flink;
755 listEntry != &drvListHead;
756 listEntry = listEntry->Flink)
757 {
758 PADD_DEV_DRIVERS_LIST driverEntry;
759 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
760 PDRIVER_OBJECT driverObject = driverEntry->DriverObject;
761
762 // FIXME: ReactOS is not quite ready for this assert
763 // (legacy drivers should not have AddDevice routine)
764 // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER));
765
766 if (driverObject && driverObject->DriverExtension->AddDevice)
767 {
768 Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject,
769 DeviceNode->PhysicalDeviceObject);
770 }
771 else if (driverObject == NULL)
772 {
773 // valid only for DeviceDriver
774 ASSERT(driverEntry->DriverType == DeviceDriver);
775 ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK
777 }
778 else
779 {
780 // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here,
781 // but ReactOS' PnP stack is not that correct yet
784 }
785
786 // for filter drivers we don't care about the AddDevice result
787 if (driverEntry->DriverType == DeviceDriver)
788 {
789 if (NT_SUCCESS(Status))
790 {
791 PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
792
793 // HACK: Check if we have a ACPI device (needed for power management)
794 if (fdo->DeviceType == FILE_DEVICE_ACPI)
795 {
796 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
797
798 // There can be only one system power device
799 if (!SystemPowerDeviceNodeCreated)
800 {
803 SystemPowerDeviceNodeCreated = TRUE;
804 }
805 }
806
809 }
810 else
811 {
812 // lower filters (if already started) will be removed upon this request
815 break;
816 }
817 }
818
819#if DBG
820 PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject);
821 if (attachedDO->Flags & DO_DEVICE_INITIALIZING)
822 {
823 DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO);
824 }
825#endif
826 }
827
828Cleanup:
829 while (!IsListEmpty(&drvListHead))
830 {
831 PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead);
832 PADD_DEV_DRIVERS_LIST driverEntry;
833 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
834
835 // drivers which don't have any devices (in case of failure) will be cleaned up
836 if (driverEntry->DriverObject)
837 {
838 ObDereferenceObject(driverEntry->DriverObject);
839 }
841 }
842
843 ZwClose(SubKey);
844 if (ClassKey != NULL)
845 {
846 ZwClose(ClassKey);
847 }
848
849 return Status;
850}
851
853NTAPI
855 PDEVICE_CAPABILITIES DeviceCaps)
856{
857 IO_STATUS_BLOCK StatusBlock;
860 HANDLE InstanceKey;
862
863 /* Set up the Header */
864 RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
865 DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
866 DeviceCaps->Version = 1;
867 DeviceCaps->Address = -1;
868 DeviceCaps->UINumber = -1;
869
870 /* Set up the Stack */
872 Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
873
874 /* Send the IRP */
875 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
876 &StatusBlock,
878 &Stack);
879 if (!NT_SUCCESS(Status))
880 {
882 {
883 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
884 }
885 return Status;
886 }
887
888 /* Map device capabilities to capability flags */
889 DeviceNode->CapabilityFlags = 0;
890 if (DeviceCaps->LockSupported)
891 DeviceNode->CapabilityFlags |= 0x00000001; // CM_DEVCAP_LOCKSUPPORTED
892
893 if (DeviceCaps->EjectSupported)
894 DeviceNode->CapabilityFlags |= 0x00000002; // CM_DEVCAP_EJECTSUPPORTED
895
896 if (DeviceCaps->Removable)
897 DeviceNode->CapabilityFlags |= 0x00000004; // CM_DEVCAP_REMOVABLE
898
899 if (DeviceCaps->DockDevice)
900 DeviceNode->CapabilityFlags |= 0x00000008; // CM_DEVCAP_DOCKDEVICE
901
902 if (DeviceCaps->UniqueID)
903 DeviceNode->CapabilityFlags |= 0x00000010; // CM_DEVCAP_UNIQUEID
904
905 if (DeviceCaps->SilentInstall)
906 DeviceNode->CapabilityFlags |= 0x00000020; // CM_DEVCAP_SILENTINSTALL
907
908 if (DeviceCaps->RawDeviceOK)
909 DeviceNode->CapabilityFlags |= 0x00000040; // CM_DEVCAP_RAWDEVICEOK
910
911 if (DeviceCaps->SurpriseRemovalOK)
912 DeviceNode->CapabilityFlags |= 0x00000080; // CM_DEVCAP_SURPRISEREMOVALOK
913
914 if (DeviceCaps->HardwareDisabled)
915 DeviceNode->CapabilityFlags |= 0x00000100; // CM_DEVCAP_HARDWAREDISABLED
916
917 if (DeviceCaps->NonDynamic)
918 DeviceNode->CapabilityFlags |= 0x00000200; // CM_DEVCAP_NONDYNAMIC
919
920 if (DeviceCaps->NoDisplayInUI)
921 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
922 else
923 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
924
925 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
926 if (NT_SUCCESS(Status))
927 {
928 /* Set 'Capabilities' value */
929 RtlInitUnicodeString(&ValueName, L"Capabilities");
930 Status = ZwSetValueKey(InstanceKey,
931 &ValueName,
932 0,
933 REG_DWORD,
934 &DeviceNode->CapabilityFlags,
935 sizeof(ULONG));
936
937 /* Set 'UINumber' value */
938 if (DeviceCaps->UINumber != MAXULONG)
939 {
940 RtlInitUnicodeString(&ValueName, L"UINumber");
941 Status = ZwSetValueKey(InstanceKey,
942 &ValueName,
943 0,
944 REG_DWORD,
945 &DeviceCaps->UINumber,
946 sizeof(ULONG));
947 }
948
949 ZwClose(InstanceKey);
950 }
951
952 return Status;
953}
954
955static
958 HANDLE InstanceKey)
959{
962 PWSTR Ptr;
966 BOOLEAN IsValidID;
967
968 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
969
970 RtlZeroMemory(&Stack, sizeof(Stack));
971 Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
972 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
975 &Stack);
976 if (NT_SUCCESS(Status))
977 {
979
980 if (!IsValidID)
981 {
982 DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
983 }
984
985 TotalLength = 0;
986
988 DPRINT("Hardware IDs:\n");
989 while (*Ptr)
990 {
991 DPRINT(" %S\n", Ptr);
992 Length = (ULONG)wcslen(Ptr) + 1;
993
994 Ptr += Length;
996 }
997 DPRINT("TotalLength: %hu\n", TotalLength);
998 DPRINT("\n");
999
1000 RtlInitUnicodeString(&ValueName, L"HardwareID");
1001 Status = ZwSetValueKey(InstanceKey,
1002 &ValueName,
1003 0,
1006 (TotalLength + 1) * sizeof(WCHAR));
1007 if (!NT_SUCCESS(Status))
1008 {
1009 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1010 }
1011 }
1012 else
1013 {
1014 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1015 }
1016
1017 return Status;
1018}
1019
1020static
1023 HANDLE InstanceKey)
1024{
1027 PWSTR Ptr;
1031 BOOLEAN IsValidID;
1032
1033 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1034
1035 RtlZeroMemory(&Stack, sizeof(Stack));
1036 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1037 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1040 &Stack);
1042 {
1044
1045 if (!IsValidID)
1046 {
1047 DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
1048 }
1049
1050 TotalLength = 0;
1051
1053 DPRINT("Compatible IDs:\n");
1054 while (*Ptr)
1055 {
1056 DPRINT(" %S\n", Ptr);
1057 Length = (ULONG)wcslen(Ptr) + 1;
1058
1059 Ptr += Length;
1061 }
1062 DPRINT("TotalLength: %hu\n", TotalLength);
1063 DPRINT("\n");
1064
1065 RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
1066 Status = ZwSetValueKey(InstanceKey,
1067 &ValueName,
1068 0,
1071 (TotalLength + 1) * sizeof(WCHAR));
1072 if (!NT_SUCCESS(Status))
1073 {
1074 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
1075 }
1076 }
1077 else
1078 {
1079 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1080 }
1081
1082 return Status;
1083}
1084
1088VOID
1091 _In_ HANDLE InstanceKey)
1092{
1093 PAGED_CODE();
1094
1095 LCID localeId;
1096
1097 // Get the Locale ID
1099 if (!NT_SUCCESS(status))
1100 {
1101 DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
1102 return;
1103 }
1104
1105 // Step 1: Write the DeviceDesc value if does not exist
1106
1107 UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
1108 ULONG len;
1109
1110 status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, KeyValueBasicInformation, NULL, 0, &len);
1112 {
1113 PWSTR deviceDesc = NULL;
1115
1116 if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
1117 {
1118 status = ZwSetValueKey(InstanceKey,
1119 &valDeviceDesc,
1120 0,
1121 REG_SZ,
1122 deviceDesc,
1123 ((ULONG)wcslen(deviceDesc) + 1) * sizeof(WCHAR));
1124
1125 if (!NT_SUCCESS(status))
1126 {
1127 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1128 }
1129 }
1130 else
1131 {
1132 // This key is mandatory, so even if the Irp fails, we still write it
1133 UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
1134 DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
1135
1136 status = ZwSetValueKey(InstanceKey,
1137 &valDeviceDesc,
1138 0,
1139 REG_SZ,
1140 unknownDeviceDesc.Buffer,
1141 unknownDeviceDesc.MaximumLength);
1142 if (!NT_SUCCESS(status))
1143 {
1144 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1145 }
1146 }
1147
1148 if (deviceDesc)
1149 {
1150 ExFreePoolWithTag(deviceDesc, 0);
1151 }
1152 }
1153
1154 // Step 2: LocaltionInformation is overwritten unconditionally
1155
1156 PWSTR deviceLocationInfo = NULL;
1158 localeId,
1160 &deviceLocationInfo);
1161
1162 if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
1163 {
1164 UNICODE_STRING valLocationInfo = RTL_CONSTANT_STRING(L"LocationInformation");
1165
1166 status = ZwSetValueKey(InstanceKey,
1167 &valLocationInfo,
1168 0,
1169 REG_SZ,
1170 deviceLocationInfo,
1171 ((ULONG)wcslen(deviceLocationInfo) + 1) * sizeof(WCHAR));
1172 if (!NT_SUCCESS(status))
1173 {
1174 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1175 }
1176 }
1177
1178 if (deviceLocationInfo)
1179 {
1180 ExFreePoolWithTag(deviceLocationInfo, 0);
1181 }
1182 else
1183 {
1184 DPRINT("Driver didn't return LocationInformation (status %x)\n", status);
1185 }
1186}
1187
1188static
1192{
1195 HANDLE InstanceKey = NULL;
1196 UNICODE_STRING InstancePathU;
1197 PDEVICE_OBJECT OldDeviceObject;
1198
1199 DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
1200 DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
1201
1202 /*
1203 * FIXME: For critical errors, cleanup and disable device, but always
1204 * return STATUS_SUCCESS.
1205 */
1206
1208 if (!NT_SUCCESS(Status))
1209 {
1211 {
1212 DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
1213 }
1214 return Status;
1215 }
1216
1217 /* Verify that this is not a duplicate */
1218 OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
1219 if (OldDeviceObject != NULL)
1220 {
1221 PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
1222
1223 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
1224 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
1225 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
1226
1227 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1228 0x01,
1229 (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
1230 (ULONG_PTR)OldDeviceObject,
1231 0);
1232 }
1233
1234 DeviceNode->InstancePath = InstancePathU;
1235
1236 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1237
1238 /*
1239 * Create registry key for the instance id, if it doesn't exist yet
1240 */
1241 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
1242 if (!NT_SUCCESS(Status))
1243 {
1244 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1245
1246 /* We have to return success otherwise we abort the traverse operation */
1247 return STATUS_SUCCESS;
1248 }
1249
1250 IopQueryHardwareIds(DeviceNode, InstanceKey);
1251
1252 IopQueryCompatibleIds(DeviceNode, InstanceKey);
1253
1254 DeviceNode->Flags |= DNF_IDS_QUERIED;
1255
1256 // Set the device's DeviceDesc and LocationInformation fields
1257 PiSetDevNodeText(DeviceNode, InstanceKey);
1258
1259 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1260
1261 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1264 NULL);
1266 {
1268
1269 DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1270 DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1271 DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
1273 }
1274 else
1275 {
1276 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1277
1278 DeviceNode->ChildBusNumber = 0xFFFFFFF0;
1279 DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
1280 DeviceNode->ChildBusTypeIndex = -1;
1281 }
1282
1283 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1284
1285 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1288 NULL);
1290 {
1293 }
1294 else
1295 {
1296 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1297 DeviceNode->BootResources = NULL;
1298 }
1299
1300 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1301
1302 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1305 NULL);
1306 if (NT_SUCCESS(Status))
1307 {
1309 }
1310 else
1311 {
1312 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
1313 DeviceNode->ResourceRequirements = NULL;
1314 }
1315
1316 if (InstanceKey != NULL)
1317 {
1319 }
1320
1321 // Try installing a critical device, so its Service key is populated
1322 // then call IopSetServiceEnumData to populate service's Enum key.
1323 // That allows us to start devices during an early boot
1325 IopSetServiceEnumData(DeviceNode, InstanceKey);
1326
1327 ZwClose(InstanceKey);
1328
1330
1332 {
1333 /* Report the device to the user-mode pnp manager */
1334 IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED,
1335 &DeviceNode->InstancePath);
1336 }
1337
1338 return STATUS_SUCCESS;
1339}
1340
1341static
1345 _In_ HANDLE InstanceHandle)
1346{
1347 UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1348 UNICODE_STRING ServiceKeyName;
1349 UNICODE_STRING EnumKeyName;
1352 PKEY_VALUE_FULL_INFORMATION KeyValueInformation, kvInfo2;
1353 HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1355 ULONG Count = 0, NextInstance = 0;
1356 WCHAR ValueBuffer[6];
1358
1359 // obtain the device node's ServiceName
1360 Status = IopGetRegistryValue(InstanceHandle, L"Service", &kvInfo2);
1361 if (!NT_SUCCESS(Status))
1362 {
1363 return Status;
1364 }
1365
1366 if (kvInfo2->Type != REG_SZ || kvInfo2->DataLength <= sizeof(WCHAR))
1367 {
1368 ExFreePool(kvInfo2);
1369 return STATUS_UNSUCCESSFUL;
1370 }
1371
1372 ServiceName.MaximumLength = kvInfo2->DataLength;
1373 ServiceName.Length = kvInfo2->DataLength - sizeof(UNICODE_NULL);
1374 ServiceName.Buffer = (PVOID)((ULONG_PTR)kvInfo2 + kvInfo2->DataOffset);
1375
1376 DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1377 DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1378 DPRINT("Service: %wZ\n", &ServiceName);
1379
1380 ServiceKeyName.MaximumLength = ServicesKeyPath.Length + ServiceName.Length + sizeof(UNICODE_NULL);
1381 ServiceKeyName.Length = 0;
1382 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1383 if (ServiceKeyName.Buffer == NULL)
1384 {
1385 DPRINT1("No ServiceKeyName.Buffer!\n");
1387 }
1388
1389 RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1391
1392 DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1393
1394 Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1395 if (!NT_SUCCESS(Status))
1396 {
1397 goto done;
1398 }
1399
1401 &ServiceName,
1402 &DeviceNode->ServiceName);
1403 if (!NT_SUCCESS(Status))
1404 {
1405 goto done;
1406 }
1407
1408 RtlInitUnicodeString(&EnumKeyName, L"Enum");
1409 Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1410 ServiceKey,
1411 &EnumKeyName,
1414 &Disposition);
1415 if (NT_SUCCESS(Status))
1416 {
1418 {
1419 /* Read the NextInstance value */
1420 Status = IopGetRegistryValue(ServiceEnumKey,
1421 L"Count",
1422 &KeyValueInformation);
1423 if (!NT_SUCCESS(Status))
1424 goto done;
1425
1426 if ((KeyValueInformation->Type == REG_DWORD) &&
1427 (KeyValueInformation->DataLength))
1428 {
1429 /* Read it */
1430 Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1431 KeyValueInformation->DataOffset);
1432 }
1433
1434 ExFreePool(KeyValueInformation);
1435 KeyValueInformation = NULL;
1436
1437 /* Read the NextInstance value */
1438 Status = IopGetRegistryValue(ServiceEnumKey,
1439 L"NextInstance",
1440 &KeyValueInformation);
1441 if (!NT_SUCCESS(Status))
1442 goto done;
1443
1444 if ((KeyValueInformation->Type == REG_DWORD) &&
1445 (KeyValueInformation->DataLength))
1446 {
1447 NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1448 KeyValueInformation->DataOffset);
1449 }
1450
1451 ExFreePool(KeyValueInformation);
1452 KeyValueInformation = NULL;
1453 }
1454
1455 /* Set the instance path */
1456 swprintf(ValueBuffer, L"%lu", NextInstance);
1457 RtlInitUnicodeString(&ValueName, ValueBuffer);
1458 Status = ZwSetValueKey(ServiceEnumKey,
1459 &ValueName,
1460 0,
1461 REG_SZ,
1462 DeviceNode->InstancePath.Buffer,
1463 DeviceNode->InstancePath.MaximumLength);
1464 if (!NT_SUCCESS(Status))
1465 goto done;
1466
1467 /* Increment Count and NextInstance */
1468 Count++;
1469 NextInstance++;
1470
1471 /* Set the new Count value */
1473 Status = ZwSetValueKey(ServiceEnumKey,
1474 &ValueName,
1475 0,
1476 REG_DWORD,
1477 &Count,
1478 sizeof(Count));
1479 if (!NT_SUCCESS(Status))
1480 goto done;
1481
1482 /* Set the new NextInstance value */
1483 RtlInitUnicodeString(&ValueName, L"NextInstance");
1484 Status = ZwSetValueKey(ServiceEnumKey,
1485 &ValueName,
1486 0,
1487 REG_DWORD,
1488 &NextInstance,
1489 sizeof(NextInstance));
1490 }
1491
1492done:
1493 if (ServiceEnumKey != NULL)
1494 ZwClose(ServiceEnumKey);
1495
1496 if (ServiceKey != NULL)
1497 ZwClose(ServiceKey);
1498
1499 ExFreePool(ServiceKeyName.Buffer);
1500 ExFreePool(kvInfo2);
1501
1502 return Status;
1503}
1504
1514static
1518{
1519 PNP_DEVICE_STATE PnPFlags;
1521
1523 if (!NT_SUCCESS(Status))
1524 {
1525 return Status;
1526 }
1527
1528 if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
1529 DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
1530 else
1531 DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
1532
1533 if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
1534 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
1535 else
1536 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
1537
1538 if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
1539 {
1541 PnPFlags & PNP_DEVICE_DISABLED
1544
1546 }
1547 else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
1548 {
1549 // Query resource rebalance
1550
1551 if (PnPFlags & PNP_DEVICE_FAILED)
1553 else
1555
1556 // Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
1557 DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
1558
1559 // This will be caught up later by enumeration
1561 }
1562 else if (PnPFlags & PNP_DEVICE_FAILED)
1563 {
1566 }
1567
1568 return STATUS_SUCCESS;
1569}
1570
1571static
1575{
1578
1579 if (!(DeviceNode->Flags & DNF_IDS_QUERIED))
1580 {
1581 // query ids (for reported devices)
1583 HANDLE enumRootHandle, instanceHandle;
1584
1585 // open the enumeration root key
1586 Status = IopOpenRegistryKeyEx(&enumRootHandle, NULL, &enumRoot, KEY_READ);
1587 if (!NT_SUCCESS(Status))
1588 {
1589 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &enumRoot, Status);
1590 return Status;
1591 }
1592
1593 // open an instance subkey
1594 Status = IopOpenRegistryKeyEx(&instanceHandle, enumRootHandle, &DeviceNode->InstancePath, KEY_READ);
1595 ZwClose(enumRootHandle);
1596 if (!NT_SUCCESS(Status))
1597 {
1598 DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
1599 &DeviceNode->InstancePath, Status);
1600 return Status;
1601 }
1602
1603 IopQueryHardwareIds(DeviceNode, instanceHandle);
1604 IopQueryCompatibleIds(DeviceNode, instanceHandle);
1605
1606 DeviceNode->Flags |= DNF_IDS_QUERIED;
1607 ZwClose(instanceHandle);
1608 }
1609
1610 // we're about to start - needs enumeration
1611 DeviceNode->Flags |= DNF_REENUMERATE;
1612
1613 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
1614
1616 if (!NT_SUCCESS(Status))
1617 {
1618 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
1619 }
1620
1621 // Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
1623
1624 DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
1625 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
1626
1628
1629 return STATUS_SUCCESS;
1630}
1631
1632/* PUBLIC FUNCTIONS **********************************************************/
1633
1643static
1648{
1649 KIRQL oldIrql;
1650
1655
1656 PDEVICE_OBJECT vpbDevObj = DeviceObject, targetDevice = DeviceObject;
1657
1658 // walk the device stack down, stop on a first mounted device
1659 do
1660 {
1661 if (vpbDevObj->Vpb)
1662 {
1663 // two locks are needed here
1664 KeWaitForSingleObject(&vpbDevObj->DeviceLock, Executive, KernelMode, FALSE, NULL);
1665 IoAcquireVpbSpinLock(&oldIrql);
1666
1668 {
1669 vpbDevObj->Vpb->Flags &= ~VPB_REMOVE_PENDING;
1670 }
1671 else
1672 {
1673 vpbDevObj->Vpb->Flags |= VPB_REMOVE_PENDING;
1674 }
1675
1676 BOOLEAN isMounted = (_Bool)(vpbDevObj->Vpb->Flags & VPB_MOUNTED);
1677
1678 if (isMounted)
1679 {
1680 targetDevice = vpbDevObj->Vpb->DeviceObject;
1681 }
1682
1683 IoReleaseVpbSpinLock(oldIrql);
1684 KeSetEvent(&vpbDevObj->DeviceLock, IO_NO_INCREMENT, FALSE);
1685
1686 if (isMounted)
1687 {
1688 break;
1689 }
1690 }
1691
1693 vpbDevObj = vpbDevObj->AttachedDevice;
1695 } while (vpbDevObj);
1696
1697 ASSERT(targetDevice);
1698
1699 PVOID info;
1700 IO_STACK_LOCATION stack = {.MajorFunction = IRP_MJ_PNP, .MinorFunction = MinorFunction};
1701
1702 return IopSynchronousCall(targetDevice, &stack, &info);
1703}
1704
1708
1709static
1710VOID
1711NTAPI
1713{
1715
1717
1718 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1720
1721 /* Start of HACK: update resources stored in registry, so IopDetectResourceConflict works */
1722 if (DeviceNode->ResourceList)
1723 {
1724 ASSERT(DeviceNode->ResourceListTranslated);
1725 DeviceNode->ResourceList->Count = 0;
1726 DeviceNode->ResourceListTranslated->Count = 0;
1728 }
1729 /* End of HACK */
1730
1732 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
1734 if (refCount != 0)
1735 {
1736 DPRINT1("Leaking device %wZ, refCount = %d\n", &DeviceNode->InstancePath, (INT32)refCount);
1737 }
1738}
1739
1740static
1741VOID
1743{
1744 /* This function DOES dereference the device objects in all cases */
1745
1746 ULONG i;
1747
1748 for (i = 0; i < DeviceRelations->Count; i++)
1749 {
1750 IopSendRemoveDevice(DeviceRelations->Objects[i]);
1751 DeviceRelations->Objects[i] = NULL;
1752 }
1753
1754 ExFreePool(DeviceRelations);
1755}
1756
1757static
1758VOID
1760{
1761 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1762 KIRQL OldIrql;
1763
1765 ChildDeviceNode = ParentDeviceNode->Child;
1766 while (ChildDeviceNode != NULL)
1767 {
1768 NextDeviceNode = ChildDeviceNode->Sibling;
1770
1771 IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1772
1773 ChildDeviceNode = NextDeviceNode;
1774
1776 }
1778}
1779
1780static
1781VOID
1782NTAPI
1784{
1786 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1788}
1789
1790static
1791VOID
1792NTAPI
1794{
1795 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1797
1798 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
1799}
1800
1801static
1802VOID
1804{
1805 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1806 KIRQL OldIrql;
1807
1809 ChildDeviceNode = ParentDeviceNode->Child;
1810 while (ChildDeviceNode != NULL)
1811 {
1812 NextDeviceNode = ChildDeviceNode->Sibling;
1814
1816
1817 ChildDeviceNode = NextDeviceNode;
1818
1820 }
1822}
1823
1824static
1825VOID
1827{
1828 /* This function DOES dereference the device objects in all cases */
1829
1830 ULONG i;
1831
1832 for (i = 0; i < DeviceRelations->Count; i++)
1833 {
1834 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1835 ObDereferenceObject(DeviceRelations->Objects[i]);
1836 DeviceRelations->Objects[i] = NULL;
1837 }
1838
1839 ExFreePool(DeviceRelations);
1840}
1841
1842static
1843VOID
1845{
1848 PDEVICE_RELATIONS DeviceRelations;
1850
1852
1853 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1854
1858 &Stack);
1859 if (!NT_SUCCESS(Status))
1860 {
1861 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1862 DeviceRelations = NULL;
1863 }
1864 else
1865 {
1866 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1867 }
1868
1869 if (DeviceRelations)
1870 IopCancelRemoveDeviceRelations(DeviceRelations);
1871}
1872
1873static
1875NTAPI
1877{
1880
1882
1883 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1884 &DeviceNode->InstancePath);
1885
1887
1888 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
1889
1890 if (!NT_SUCCESS(Status))
1891 {
1892 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1893 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1894 &DeviceNode->InstancePath);
1895 }
1896
1897 return Status;
1898}
1899
1900static
1903{
1904 PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1906 KIRQL OldIrql;
1907
1909 ChildDeviceNode = ParentDeviceNode->Child;
1910 while (ChildDeviceNode != NULL)
1911 {
1912 NextDeviceNode = ChildDeviceNode->Sibling;
1915
1917 if (!NT_SUCCESS(Status))
1918 {
1919 FailedRemoveDevice = ChildDeviceNode;
1920 goto cleanup;
1921 }
1922
1924 ChildDeviceNode = NextDeviceNode;
1925 }
1927
1928 return STATUS_SUCCESS;
1929
1930cleanup:
1932 ChildDeviceNode = ParentDeviceNode->Child;
1933 while (ChildDeviceNode != NULL)
1934 {
1935 NextDeviceNode = ChildDeviceNode->Sibling;
1937
1939
1940 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1941 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1942 if (ChildDeviceNode == FailedRemoveDevice)
1943 return Status;
1944
1945 ChildDeviceNode = NextDeviceNode;
1946
1948 }
1950
1951 return Status;
1952}
1953
1954static
1957{
1958 /* This function DOES NOT dereference the device objects on SUCCESS
1959 * but it DOES dereference device objects on FAILURE */
1960
1961 ULONG i, j;
1963
1964 for (i = 0; i < DeviceRelations->Count; i++)
1965 {
1966 Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1967 if (!NT_SUCCESS(Status))
1968 {
1969 j = i;
1970 goto cleanup;
1971 }
1972 }
1973
1974 return STATUS_SUCCESS;
1975
1976cleanup:
1977 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1978 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1979 for (i = 0; i <= j; i++)
1980 {
1981 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1982 ObDereferenceObject(DeviceRelations->Objects[i]);
1983 DeviceRelations->Objects[i] = NULL;
1984 }
1985 for (; i < DeviceRelations->Count; i++)
1986 {
1987 ObDereferenceObject(DeviceRelations->Objects[i]);
1988 DeviceRelations->Objects[i] = NULL;
1989 }
1990 ExFreePool(DeviceRelations);
1991
1992 return Status;
1993}
1994
1995static
1998{
2002 PDEVICE_RELATIONS DeviceRelations;
2004
2005 if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
2006 {
2007 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
2008 return STATUS_UNSUCCESSFUL;
2009 }
2010
2012 {
2013 DPRINT1("Removal vetoed by failing the query remove request\n");
2014
2016
2017 return STATUS_UNSUCCESSFUL;
2018 }
2019
2020 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
2021
2025 &Stack);
2026 if (!NT_SUCCESS(Status))
2027 {
2028 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2029 DeviceRelations = NULL;
2030 }
2031 else
2032 {
2033 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2034 }
2035
2036 if (DeviceRelations)
2037 {
2038 Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
2039 if (!NT_SUCCESS(Status))
2040 return Status;
2041 }
2042
2044 if (!NT_SUCCESS(Status))
2045 {
2046 if (DeviceRelations)
2047 IopCancelRemoveDeviceRelations(DeviceRelations);
2048 return Status;
2049 }
2050
2051 if (DeviceRelations)
2052 IopSendRemoveDeviceRelations(DeviceRelations);
2054
2055 return STATUS_SUCCESS;
2056}
2057
2058static
2061{
2063
2064 // This function removes the device subtree, with the root in DeviceNode
2065 // atm everyting is in fact done inside this function, which is completely wrong.
2066 // The right implementation should have a separate removal worker thread and
2067 // properly do device node state transitions
2068
2069 DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
2070
2071 BOOLEAN surpriseRemoval = (_Bool)(DeviceNode->Flags & DNF_DEVICE_GONE);
2072
2073 Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, surpriseRemoval);
2074
2075 if (surpriseRemoval)
2076 {
2077 IopSendSurpriseRemoval(DeviceNode->PhysicalDeviceObject);
2078 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL, &DeviceNode->InstancePath);
2079 }
2080
2081 if (NT_SUCCESS(Status))
2082 {
2083 IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
2084 if (surpriseRemoval)
2085 {
2086 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL, &DeviceNode->InstancePath);
2087 }
2088 return STATUS_SUCCESS;
2089 }
2090
2091 return Status;
2092}
2093
2094static
2098{
2099 PDEVICE_OBJECT ChildDeviceObject;
2100 PDEVICE_NODE ChildDeviceNode;
2101 ULONG i;
2102
2103 // bus relations are already obtained for this device node
2104
2105 if (!NT_SUCCESS(DeviceNode->CompletionStatus))
2106 {
2107 DPRINT("QDR request failed for %wZ, status %x\n",
2108 &DeviceNode->InstancePath, DeviceNode->CompletionStatus);
2109 // treat as if there are no child objects
2110 }
2111
2112 PDEVICE_RELATIONS DeviceRelations = DeviceNode->OverUsed1.PendingDeviceRelations;
2113 DeviceNode->OverUsed1.PendingDeviceRelations = NULL;
2114
2115 // it's acceptable not to have PDOs
2116 if (!DeviceRelations)
2117 {
2119 DPRINT("No PDOs\n");
2120 return STATUS_SUCCESS;
2121 }
2122
2123 // mark children nodes as non-present (those not returned in DR request will be removed)
2124 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2125 {
2126 child->Flags &= ~DNF_ENUMERATED;
2127 }
2128
2129 DPRINT("PiEnumerateDevice: enumerating %u children\n", DeviceRelations->Count);
2130
2131 // create device nodes for all new children and set DNF_ENUMERATED back for old ones
2132 for (i = 0; i < DeviceRelations->Count; i++)
2133 {
2134 ChildDeviceObject = DeviceRelations->Objects[i];
2135 ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);
2136
2137 ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
2138 if (!ChildDeviceNode)
2139 {
2140 /* One doesn't exist, create it */
2141 ChildDeviceNode = PipAllocateDeviceNode(ChildDeviceObject);
2142 if (ChildDeviceNode)
2143 {
2144 PiInsertDevNode(ChildDeviceNode, DeviceNode);
2145
2146 /* Mark the node as enumerated */
2147 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2148
2149 /* Mark the DO as bus enumerated */
2150 ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2151 }
2152 else
2153 {
2154 /* Ignore this DO */
2155 DPRINT1("PipAllocateDeviceNode() failed. Skipping PDO %u\n", i);
2156 ObDereferenceObject(ChildDeviceObject);
2157 }
2158 }
2159 else
2160 {
2161 /* Mark it as enumerated */
2162 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2163 ObDereferenceObject(ChildDeviceObject);
2164 }
2165 }
2166 ExFreePool(DeviceRelations);
2167
2168 // time to remove non-reported devices
2169 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2170 {
2171 if (!(child->Flags & (DNF_ENUMERATED|DNF_DEVICE_GONE)))
2172 {
2173 // this flag indicates that this is a surprise removal
2174 child->Flags |= DNF_DEVICE_GONE;
2176 }
2177 }
2178
2180 return STATUS_SUCCESS;
2181}
2182
2183static
2185NTAPI
2187{
2189 PVOID Dummy;
2190
2192 Stack.MajorFunction = IRP_MJ_PNP;
2193 Stack.MinorFunction = IRP_MN_EJECT;
2194
2195 return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2196}
2197
2198/*
2199 * @implemented
2200 */
2201VOID
2202NTAPI
2204{
2206 PDEVICE_RELATIONS DeviceRelations;
2211
2212 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2213 &DeviceNode->InstancePath);
2214
2216 {
2217 goto cleanup;
2218 }
2219
2220 Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2221
2225 &Stack);
2226 if (!NT_SUCCESS(Status))
2227 {
2228 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2229 DeviceRelations = NULL;
2230 }
2231 else
2232 {
2233 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2234 }
2235
2236 if (DeviceRelations)
2237 {
2238 Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2239 if (!NT_SUCCESS(Status))
2240 goto cleanup;
2241 }
2242
2244 if (!NT_SUCCESS(Status))
2245 {
2246 if (DeviceRelations)
2247 IopCancelRemoveDeviceRelations(DeviceRelations);
2248 goto cleanup;
2249 }
2250
2252 {
2253 if (DeviceRelations)
2254 IopCancelRemoveDeviceRelations(DeviceRelations);
2256 goto cleanup;
2257 }
2258
2259 if (DeviceRelations)
2260 IopSendRemoveDeviceRelations(DeviceRelations);
2262
2264 if (Capabilities.EjectSupported)
2265 {
2267 {
2268 goto cleanup;
2269 }
2270 }
2271 else
2272 {
2273 // DeviceNode->Flags |= DNF_DISABLED;
2274 }
2275
2276 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2277 &DeviceNode->InstancePath);
2278
2279 return;
2280
2281cleanup:
2282 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2283 &DeviceNode->InstancePath);
2284}
2285
2286static
2287VOID
2290{
2292
2293 PCM_RESOURCE_LIST bootConfig = NULL;
2294 PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
2295
2296 PiIrpQueryResources(DeviceNode, &bootConfig);
2297 PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
2298
2299 DeviceNode->BootResources = bootConfig;
2300 DeviceNode->ResourceRequirements = resourceRequirements;
2301
2302 if (bootConfig)
2303 {
2305 }
2306
2307 DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
2308}
2309
2310static
2311VOID
2314{
2316 BOOLEAN doProcessAgain;
2317 PDEVICE_NODE currentNode = RootNode;
2318 PDEVICE_OBJECT referencedObject;
2319
2320 do
2321 {
2322 doProcessAgain = FALSE;
2323
2324 // The device can be removed during processing, but we still need its Parent and Sibling
2325 // links to continue the tree traversal. So keep the link till the and of a cycle
2326 referencedObject = currentNode->PhysicalDeviceObject;
2327 ObReferenceObject(referencedObject);
2328
2329 // Devices with problems are skipped (unless they are not being removed)
2330 if (currentNode->Flags & DNF_HAS_PROBLEM &&
2331 currentNode->State != DeviceNodeAwaitingQueuedRemoval)
2332 {
2333 goto skipEnum;
2334 }
2335
2336 switch (currentNode->State)
2337 {
2338 case DeviceNodeUnspecified: // this state is not used
2339 break;
2341 DPRINT("DeviceNodeUninitialized %wZ\n", &currentNode->InstancePath);
2342 status = PiInitializeDevNode(currentNode);
2343 doProcessAgain = NT_SUCCESS(status);
2344 break;
2346 DPRINT("DeviceNodeInitialized %wZ\n", &currentNode->InstancePath);
2348 doProcessAgain = NT_SUCCESS(status);
2349 break;
2351 DPRINT("DeviceNodeDriversAdded %wZ\n", &currentNode->InstancePath);
2352 status = IopAssignDeviceResources(currentNode);
2353 doProcessAgain = NT_SUCCESS(status);
2354 break;
2356 DPRINT("DeviceNodeResourcesAssigned %wZ\n", &currentNode->InstancePath);
2357 // send IRP_MN_START_DEVICE
2358 PiIrpStartDevice(currentNode);
2359
2360 // skip DeviceNodeStartPending, it is probably used for an async IRP_MN_START_DEVICE
2362 doProcessAgain = TRUE;
2363 break;
2364 case DeviceNodeStartPending: // skipped on XP/2003
2365 break;
2367 DPRINT("DeviceNodeStartCompletion %wZ\n", &currentNode->InstancePath);
2368 status = currentNode->CompletionStatus;
2369 doProcessAgain = TRUE;
2370 if (!NT_SUCCESS(status))
2371 {
2375
2376 PiSetDevNodeProblem(currentNode, problem);
2378 }
2379 else
2380 {
2381 // TODO: IopDoDeferredSetInterfaceState and IopAllocateLegacyBootResources
2382 // are called here too
2383
2385 }
2386 break;
2388 DPRINT("DeviceNodeStartPostWork %wZ\n", &currentNode->InstancePath);
2389 // TODO: inspect the status
2390 status = PiStartDeviceFinal(currentNode);
2391 doProcessAgain = TRUE;
2392 break;
2393 case DeviceNodeStarted:
2394 if (currentNode->Flags & DNF_REENUMERATE)
2395 {
2396 DPRINT("DeviceNodeStarted REENUMERATE %wZ\n", &currentNode->InstancePath);
2397 currentNode->Flags &= ~DNF_REENUMERATE;
2399
2400 // again, skip DeviceNodeEnumeratePending as with the starting sequence
2402 doProcessAgain = TRUE;
2403 }
2404 else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
2405 {
2406 if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
2407 {
2408 PiFakeResourceRebalance(currentNode);
2409 currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
2410 }
2411 else
2412 {
2413 PiIrpQueryStopDevice(currentNode);
2415 }
2416
2417 doProcessAgain = TRUE;
2418 }
2419 break;
2421 // we're here after sending IRP_MN_QUERY_STOP_DEVICE
2422 status = currentNode->CompletionStatus;
2423 if (NT_SUCCESS(status))
2424 {
2425 PiIrpStopDevice(currentNode);
2427 }
2428 else
2429 {
2430 PiIrpCancelStopDevice(currentNode);
2432 }
2433 doProcessAgain = TRUE;
2434 break;
2435 case DeviceNodeStopped:
2436 // TODO: do resource rebalance (not implemented)
2437 PiFakeResourceRebalance(currentNode);
2438
2440 doProcessAgain = TRUE;
2441 break;
2443 break;
2444 case DeviceNodeEnumeratePending: // skipped on XP/2003
2445 break;
2447 DPRINT("DeviceNodeEnumerateCompletion %wZ\n", &currentNode->InstancePath);
2448 status = PiEnumerateDevice(currentNode);
2449 doProcessAgain = TRUE;
2450 break;
2452 break;
2454 DPRINT("DeviceNodeAwaitingQueuedRemoval %wZ\n", &currentNode->InstancePath);
2455 status = IopRemoveDevice(currentNode);
2456 break;
2458 break;
2460 break;
2461 case DeviceNodeRemoved:
2462 break;
2464 break;
2465 case DeviceNodeDeleted:
2466 break;
2467 default:
2468 break;
2469 }
2470
2471skipEnum:
2472 if (!doProcessAgain)
2473 {
2474 KIRQL OldIrql;
2476 /* If we have a child, simply go down the tree */
2477 if (currentNode->State != DeviceNodeRemoved && currentNode->Child != NULL)
2478 {
2479 ASSERT(currentNode->Child->Parent == currentNode);
2480 currentNode = currentNode->Child;
2481 }
2482 else
2483 {
2484 while (currentNode != RootNode)
2485 {
2486 /* All children processed -- go sideways */
2487 if (currentNode->Sibling != NULL)
2488 {
2489 ASSERT(currentNode->Sibling->Parent == currentNode->Parent);
2490 currentNode = currentNode->Sibling;
2491 break;
2492 }
2493 else
2494 {
2495 /* We're the last sibling -- go back up */
2496 ASSERT(currentNode->Parent->LastChild == currentNode);
2497 currentNode = currentNode->Parent;
2498 }
2499 /* We already visited the parent and all its children, so keep looking */
2500 }
2501 }
2503 }
2504 ObDereferenceObject(referencedObject);
2505 } while (doProcessAgain || currentNode != RootNode);
2506}
2507
2508#ifdef DBG
2509static
2510PCSTR
2511ActionToStr(
2513{
2514 switch (Action)
2515 {
2517 return "PiActionEnumDeviceTree";
2519 return "PiActionEnumRootDevices";
2521 return "PiActionResetDevice";
2523 return "PiActionAddBootDevices";
2525 return "PiActionStartDevice";
2526 case PiActionQueryState:
2527 return "PiActionQueryState";
2528 default:
2529 return "(request unknown)";
2530 }
2531}
2532#endif
2533
2534static
2535VOID
2536NTAPI
2539{
2540 PLIST_ENTRY ListEntry;
2542 KIRQL OldIrql;
2543 PDEVICE_NODE deviceNode;
2545
2548 {
2551 Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2552
2553 ASSERT(Request->DeviceObject);
2554
2555 deviceNode = IopGetDeviceNode(Request->DeviceObject);
2556 ASSERT(deviceNode);
2557
2559
2560 DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2561 Request, Request->DeviceObject, ActionToStr(Request->Action));
2562
2563 switch (Request->Action)
2564 {
2566 {
2567 if (deviceNode->State == DeviceNodeInitialized &&
2568 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2569 {
2571 }
2572 break;
2573 }
2576 deviceNode->Flags |= DNF_REENUMERATE;
2577 PiDevNodeStateMachine(deviceNode);
2578 break;
2579
2581 // TODO: the operation is a no-op for everything except removed nodes
2582 // for removed nodes, it returns them back to DeviceNodeUninitialized
2583 if (deviceNode->State == DeviceNodeRemoved)
2584 {
2585 deviceNode->State = DeviceNodeUninitialized;
2586 }
2588 break;
2589
2591 // This action is triggered from usermode, when a driver is installed
2592 // for a non-critical PDO
2593 if (deviceNode->State == DeviceNodeInitialized &&
2594 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2595 {
2596 PiDevNodeStateMachine(deviceNode);
2597 }
2598 else
2599 {
2600 DPRINT1("NOTE: attempt to start an already started/uninitialized device %wZ\n",
2601 &deviceNode->InstancePath);
2603 }
2604 break;
2605
2606 case PiActionQueryState:
2607 // This action is only valid for started devices. If the device is not yet
2608 // started, the PnP manager issues IRP_MN_QUERY_PNP_DEVICE_STATE by itself.
2609 if (deviceNode->State == DeviceNodeStarted)
2610 {
2611 // Issue a IRP_MN_QUERY_PNP_DEVICE_STATE request: it will update node's flags
2612 // and then do enumeration if something has changed
2613 status = PiUpdateDeviceState(deviceNode);
2614 if (NT_SUCCESS(status))
2615 {
2616 PiDevNodeStateMachine(deviceNode);
2617 }
2618 }
2619 // TODO: Windows may return STATUS_DELETE_PENDING here
2621 break;
2622
2623 default:
2624 DPRINT1("Unimplemented device action %u\n", Request->Action);
2626 break;
2627 }
2628
2629 if (Request->CompletionStatus)
2630 {
2631 *Request->CompletionStatus = status;
2632 }
2633
2634 if (Request->CompletionEvent)
2635 {
2636 KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2637 }
2638
2639 DPRINT("Finished processing PnP request %p\n", Request);
2640 ObDereferenceObject(Request->DeviceObject);
2643 }
2647}
2648
2658VOID
2662 _In_opt_ PKEVENT CompletionEvent,
2663 _Out_opt_ NTSTATUS *CompletionStatus)
2664{
2666 KIRQL OldIrql;
2667
2669
2670 DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2671 DeviceObject, Request, ActionToStr(Action));
2672
2674
2675 Request->DeviceObject = DeviceObject;
2676 Request->Action = Action;
2677 Request->CompletionEvent = CompletionEvent;
2678 Request->CompletionStatus = CompletionStatus;
2679
2682
2684 {
2686
2690
2692 return;
2693 }
2694
2696 {
2698 return;
2699 }
2703
2706}
2707
2721{
2722 KEVENT opFinished;
2724
2728
2729 return status;
2730}
#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
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:1022
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:1783
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:1645
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:854
BOOLEAN PnpSystemInit
Definition: iomgr.c:17
static NTSTATUS PiEnumerateDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2096
struct _ADD_DEV_DRIVERS_LIST * PADD_DEV_DRIVERS_LIST
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2537
struct _ADD_DEV_DRIVERS_LIST ADD_DEV_DRIVERS_LIST
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1844
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1956
_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:1759
static NTSTATUS IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
static NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:2060
static VOID PiDevNodeStateMachine(_In_ PDEVICE_NODE RootNode)
Definition: devaction.c:2312
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:1089
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1826
static NTSTATUS NTAPI IopSendEject(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:2186
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1793
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1742
static NTSTATUS IopSetServiceEnumData(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
Definition: devaction.c:1343
#define MAX_SEPARATORS_DEVICEID
Definition: devaction.c:42
static NTSTATUS PiStartDeviceFinal(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1573
static VOID PiFakeResourceRebalance(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2288
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1876
static NTSTATUS PiInitializeDevNode(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1190
#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:957
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:1803
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:48
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1902
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:2659
static NTSTATUS PiUpdateDeviceState(_In_ PDEVICE_NODE DeviceNode)
Processes the IoInvalidateDeviceState request.
Definition: devaction.c:1516
VOID NTAPI IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: devaction.c:2203
static VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1712
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:2718
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
#define _Out_opt_
Definition: ms_sal.h:346
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define KernelMode
Definition: asm.h:34
_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 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:4219
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
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
_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:1938
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_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_PLUGPLAY_NO_DEVICE
Definition: ntstatus.h:731
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
_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:1000
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:989
PNP_DEVNODE_STATE State
Definition: iotypes.h:996
struct _DEVICE_NODE * Child
Definition: iotypes.h:990
ULONG Flags
Definition: iotypes.h:1002
struct _DEVICE_NODE * Parent
Definition: iotypes.h:991
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1005
UNICODE_STRING InstancePath
Definition: iotypes.h:1008
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:98
#define TAG_IO
Definition: tag.h:80
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