2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Shortcuts for sending different IRP_MJ_PNP requests
5 * COPYRIGHT: Copyright 2010 Sir Richard <sir_richard@svn.reactos.org>
6 * Copyright 2020 Victor Perevertkin <victor.perevertkin@reactos.org>
15 _In_ PDEVICE_OBJECT DeviceObject
,
16 _In_ PIO_STACK_LOCATION IoStackLocation
,
17 _Out_ PVOID
*Information
)
20 PIO_STACK_LOCATION IrpStack
;
21 IO_STATUS_BLOCK IoStatusBlock
;
24 PDEVICE_OBJECT TopDeviceObject
;
27 /* Call the top of the device stack */
28 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
31 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
34 ObDereferenceObject(TopDeviceObject
);
35 return STATUS_INSUFFICIENT_RESOURCES
;
38 /* Initialize to failure */
39 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
40 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
42 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
43 if ((IoStackLocation
->MajorFunction
== IRP_MJ_PNP
) &&
44 (IoStackLocation
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
))
46 /* Copy the resource requirements list into the IOSB */
47 Irp
->IoStatus
.Information
=
48 IoStatusBlock
.Information
= (ULONG_PTR
)IoStackLocation
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
51 /* Initialize the event */
52 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
55 Irp
->UserIosb
= &IoStatusBlock
;
56 Irp
->UserEvent
= &Event
;
59 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
60 IoQueueThreadIrp(Irp
);
62 /* Copy-in the stack */
63 IrpStack
= IoGetNextIrpStackLocation(Irp
);
64 *IrpStack
= *IoStackLocation
;
67 Status
= IoCallDriver(TopDeviceObject
, Irp
);
68 /* Otherwise we may get stuck here or have IoStatusBlock not populated */
69 ASSERT(!KeAreAllApcsDisabled());
70 if (Status
== STATUS_PENDING
)
73 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
74 Status
= IoStatusBlock
.Status
;
77 /* Remove the reference */
78 ObDereferenceObject(TopDeviceObject
);
80 /* Return the information */
81 *Information
= (PVOID
)IoStatusBlock
.Information
;
85 // IRP_MN_START_DEVICE (0x00)
88 _In_ PDEVICE_NODE DeviceNode
)
93 ASSERT(DeviceNode
->State
== DeviceNodeResourcesAssigned
);
96 IO_STACK_LOCATION stack
= {
97 .MajorFunction
= IRP_MJ_PNP
,
98 .MinorFunction
= IRP_MN_START_DEVICE
,
99 .Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
,
100 .Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
103 // Vista+ does an asynchronous call
104 NTSTATUS status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
, &stack
, &info
);
105 DeviceNode
->CompletionStatus
= status
;
109 // IRP_MN_STOP_DEVICE (0x04)
112 _In_ PDEVICE_NODE DeviceNode
)
117 ASSERT(DeviceNode
->State
== DeviceNodeQueryStopped
);
120 IO_STACK_LOCATION stack
= {
121 .MajorFunction
= IRP_MJ_PNP
,
122 .MinorFunction
= IRP_MN_STOP_DEVICE
125 // Drivers should never fail a IRP_MN_STOP_DEVICE request
126 NTSTATUS status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
, &stack
, &info
);
127 ASSERT(NT_SUCCESS(status
));
131 // IRP_MN_QUERY_STOP_DEVICE (0x05)
133 PiIrpQueryStopDevice(
134 _In_ PDEVICE_NODE DeviceNode
)
139 ASSERT(DeviceNode
->State
== DeviceNodeStarted
);
142 IO_STACK_LOCATION stack
= {
143 .MajorFunction
= IRP_MJ_PNP
,
144 .MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
147 NTSTATUS status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
, &stack
, &info
);
148 DeviceNode
->CompletionStatus
= status
;
152 // IRP_MN_CANCEL_STOP_DEVICE (0x06)
154 PiIrpCancelStopDevice(
155 _In_ PDEVICE_NODE DeviceNode
)
160 ASSERT(DeviceNode
->State
== DeviceNodeQueryStopped
);
163 IO_STACK_LOCATION stack
= {
164 .MajorFunction
= IRP_MJ_PNP
,
165 .MinorFunction
= IRP_MN_CANCEL_STOP_DEVICE
168 // in fact we don't care which status is returned here
169 NTSTATUS status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
, &stack
, &info
);
170 ASSERT(NT_SUCCESS(status
));
174 // IRP_MN_QUERY_DEVICE_RELATIONS (0x07)
176 PiIrpQueryDeviceRelations(
177 _In_ PDEVICE_NODE DeviceNode
,
178 _In_ DEVICE_RELATION_TYPE Type
)
183 ASSERT(DeviceNode
->State
== DeviceNodeStarted
);
185 IO_STACK_LOCATION stack
= {
186 .MajorFunction
= IRP_MJ_PNP
,
187 .MinorFunction
= IRP_MN_QUERY_DEVICE_RELATIONS
,
188 .Parameters
.QueryDeviceRelations
.Type
= Type
191 // Vista+ does an asynchronous call
192 NTSTATUS status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
,
194 (PVOID
)&DeviceNode
->OverUsed1
.PendingDeviceRelations
);
195 DeviceNode
->CompletionStatus
= status
;
199 // IRP_MN_QUERY_PNP_DEVICE_STATE (0x14)
201 PiIrpQueryPnPDeviceState(
202 _In_ PDEVICE_NODE DeviceNode
,
203 _Out_ PPNP_DEVICE_STATE DeviceState
)
208 ASSERT(DeviceNode
->State
== DeviceNodeStartPostWork
||
209 DeviceNode
->State
== DeviceNodeStarted
);
212 IO_STACK_LOCATION stack
= {
213 .MajorFunction
= IRP_MJ_PNP
,
214 .MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
218 status
= IopSynchronousCall(DeviceNode
->PhysicalDeviceObject
, &stack
, (PVOID
)&longState
);
219 if (NT_SUCCESS(status
))
221 *DeviceState
= longState
;