1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS kernel-mode tests
3*c2c66affSColin Finck * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4*c2c66affSColin Finck * PURPOSE: Kernel-Mode Test Suite Power IRP management test
5*c2c66affSColin Finck * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6*c2c66affSColin Finck */
7*c2c66affSColin Finck
8*c2c66affSColin Finck #include <kmt_test.h>
9*c2c66affSColin Finck #include "PoIrp.h"
10*c2c66affSColin Finck
11*c2c66affSColin Finck static PDRIVER_OBJECT TestDriverObject;
12*c2c66affSColin Finck static KMT_MESSAGE_HANDLER TestMessageHandler;
13*c2c66affSColin Finck
14*c2c66affSColin Finck static PDEVICE_OBJECT DeviceObject1;
15*c2c66affSColin Finck static PDEVICE_OBJECT DeviceObject2;
16*c2c66affSColin Finck static PDEVICE_OBJECT DeviceObject3;
17*c2c66affSColin Finck
18*c2c66affSColin Finck static
19*c2c66affSColin Finck NTSTATUS
CreateTestDevices(_In_ PDRIVER_OBJECT DriverObject)20*c2c66affSColin Finck CreateTestDevices(
21*c2c66affSColin Finck _In_ PDRIVER_OBJECT DriverObject)
22*c2c66affSColin Finck {
23*c2c66affSColin Finck NTSTATUS Status;
24*c2c66affSColin Finck PDEVICE_OBJECT AttachedDevice;
25*c2c66affSColin Finck
26*c2c66affSColin Finck Status = IoCreateDevice(DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject1);
27*c2c66affSColin Finck if (!NT_SUCCESS(Status))
28*c2c66affSColin Finck return Status;
29*c2c66affSColin Finck
30*c2c66affSColin Finck DeviceObject1->Flags &= ~DO_DEVICE_INITIALIZING;
31*c2c66affSColin Finck
32*c2c66affSColin Finck Status = IoCreateDevice(DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject2);
33*c2c66affSColin Finck if (!NT_SUCCESS(Status))
34*c2c66affSColin Finck {
35*c2c66affSColin Finck IoDeleteDevice(DeviceObject1);
36*c2c66affSColin Finck return Status;
37*c2c66affSColin Finck }
38*c2c66affSColin Finck
39*c2c66affSColin Finck AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject2, DeviceObject1);
40*c2c66affSColin Finck ok(AttachedDevice == DeviceObject1, "Device attached to %p is %p, expected %p\n", DeviceObject2, AttachedDevice, DeviceObject1);
41*c2c66affSColin Finck if (AttachedDevice == NULL)
42*c2c66affSColin Finck {
43*c2c66affSColin Finck IoDeleteDevice(DeviceObject2);
44*c2c66affSColin Finck IoDeleteDevice(DeviceObject1);
45*c2c66affSColin Finck return STATUS_UNSUCCESSFUL;
46*c2c66affSColin Finck }
47*c2c66affSColin Finck
48*c2c66affSColin Finck DeviceObject2->Flags &= ~DO_DEVICE_INITIALIZING;
49*c2c66affSColin Finck
50*c2c66affSColin Finck Status = IoCreateDevice(DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject3);
51*c2c66affSColin Finck if (!NT_SUCCESS(Status))
52*c2c66affSColin Finck {
53*c2c66affSColin Finck IoDetachDevice(DeviceObject1);
54*c2c66affSColin Finck IoDeleteDevice(DeviceObject2);
55*c2c66affSColin Finck IoDeleteDevice(DeviceObject1);
56*c2c66affSColin Finck return Status;
57*c2c66affSColin Finck }
58*c2c66affSColin Finck
59*c2c66affSColin Finck AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject3, DeviceObject1);
60*c2c66affSColin Finck ok(AttachedDevice == DeviceObject2, "Device attached to %p is %p, expected %p\n", DeviceObject2, AttachedDevice, DeviceObject2);
61*c2c66affSColin Finck if (AttachedDevice == NULL)
62*c2c66affSColin Finck {
63*c2c66affSColin Finck IoDeleteDevice(DeviceObject3);
64*c2c66affSColin Finck IoDetachDevice(DeviceObject1);
65*c2c66affSColin Finck IoDeleteDevice(DeviceObject2);
66*c2c66affSColin Finck IoDeleteDevice(DeviceObject1);
67*c2c66affSColin Finck return STATUS_UNSUCCESSFUL;
68*c2c66affSColin Finck }
69*c2c66affSColin Finck
70*c2c66affSColin Finck DeviceObject3->Flags &= ~DO_DEVICE_INITIALIZING;
71*c2c66affSColin Finck
72*c2c66affSColin Finck return Status;
73*c2c66affSColin Finck }
74*c2c66affSColin Finck
75*c2c66affSColin Finck NTSTATUS
TestEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PCUNICODE_STRING RegistryPath,_Out_ PCWSTR * DeviceName,_Inout_ INT * Flags)76*c2c66affSColin Finck TestEntry(
77*c2c66affSColin Finck _In_ PDRIVER_OBJECT DriverObject,
78*c2c66affSColin Finck _In_ PCUNICODE_STRING RegistryPath,
79*c2c66affSColin Finck _Out_ PCWSTR *DeviceName,
80*c2c66affSColin Finck _Inout_ INT *Flags)
81*c2c66affSColin Finck {
82*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
83*c2c66affSColin Finck
84*c2c66affSColin Finck PAGED_CODE();
85*c2c66affSColin Finck
86*c2c66affSColin Finck UNREFERENCED_PARAMETER(RegistryPath);
87*c2c66affSColin Finck
88*c2c66affSColin Finck TestDriverObject = DriverObject;
89*c2c66affSColin Finck
90*c2c66affSColin Finck *DeviceName = L"PoIrp";
91*c2c66affSColin Finck *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE;
92*c2c66affSColin Finck
93*c2c66affSColin Finck KmtRegisterMessageHandler(0, NULL, TestMessageHandler);
94*c2c66affSColin Finck
95*c2c66affSColin Finck return Status;
96*c2c66affSColin Finck }
97*c2c66affSColin Finck
98*c2c66affSColin Finck VOID
TestUnload(IN PDRIVER_OBJECT DriverObject)99*c2c66affSColin Finck TestUnload(
100*c2c66affSColin Finck IN PDRIVER_OBJECT DriverObject)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck UNREFERENCED_PARAMETER(DriverObject);
103*c2c66affSColin Finck
104*c2c66affSColin Finck PAGED_CODE();
105*c2c66affSColin Finck }
106*c2c66affSColin Finck
107*c2c66affSColin Finck //
108*c2c66affSColin Finck // PoRequestPowerIrp test
109*c2c66affSColin Finck //
110*c2c66affSColin Finck static KEVENT TestDoneEvent;
111*c2c66affSColin Finck static PIRP RequestedPowerIrp;
112*c2c66affSColin Finck static PIRP RequestedPowerIrpReturned;
113*c2c66affSColin Finck
114*c2c66affSColin Finck static
115*c2c66affSColin Finck VOID
116*c2c66affSColin Finck NTAPI
RequestedPowerCompletion(_In_ PDEVICE_OBJECT DeviceObject,_In_ UCHAR MinorFunction,_In_ POWER_STATE PowerState,_In_opt_ PVOID Context,_In_ PIO_STATUS_BLOCK IoStatus)117*c2c66affSColin Finck RequestedPowerCompletion(
118*c2c66affSColin Finck _In_ PDEVICE_OBJECT DeviceObject,
119*c2c66affSColin Finck _In_ UCHAR MinorFunction,
120*c2c66affSColin Finck _In_ POWER_STATE PowerState,
121*c2c66affSColin Finck _In_opt_ PVOID Context,
122*c2c66affSColin Finck _In_ PIO_STATUS_BLOCK IoStatus)
123*c2c66affSColin Finck {
124*c2c66affSColin Finck PIRP Irp;
125*c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
126*c2c66affSColin Finck
127*c2c66affSColin Finck ok_eq_pointer(DeviceObject, DeviceObject2);
128*c2c66affSColin Finck ok_eq_uint(MinorFunction, IRP_MN_SET_POWER);
129*c2c66affSColin Finck ok_eq_uint(PowerState.DeviceState, PowerDeviceD0);
130*c2c66affSColin Finck ok_eq_pointer(Context, &RequestedPowerIrp);
131*c2c66affSColin Finck Irp = CONTAINING_RECORD(IoStatus, IRP, IoStatus);
132*c2c66affSColin Finck ok_eq_pointer(Irp, RequestedPowerIrp);
133*c2c66affSColin Finck ok_eq_ulongptr(IoStatus->Information, 7);
134*c2c66affSColin Finck ok_eq_hex(IoStatus->Status, STATUS_WAIT_3);
135*c2c66affSColin Finck KeSetEvent(&TestDoneEvent, IO_NO_INCREMENT, FALSE);
136*c2c66affSColin Finck
137*c2c66affSColin Finck ok_eq_uint(Irp->StackCount, 5);
138*c2c66affSColin Finck ok_eq_uint(Irp->CurrentLocation, 4);
139*c2c66affSColin Finck ok_eq_pointer(Irp->Tail.Overlay.Thread, NULL);
140*c2c66affSColin Finck IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
141*c2c66affSColin Finck ok_eq_uint(IoStackLocation->MajorFunction, 0);
142*c2c66affSColin Finck ok_eq_uint(IoStackLocation->MinorFunction, 0);
143*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->CompletionRoutine, NULL);
144*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Context, NULL);
145*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Parameters.Others.Argument1, DeviceObject);
146*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Parameters.Others.Argument2, (PVOID)(ULONG_PTR)MinorFunction);
147*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Parameters.Others.Argument3, (PVOID)(ULONG_PTR)PowerState.SystemState);
148*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Parameters.Others.Argument4, Context);
149*c2c66affSColin Finck }
150*c2c66affSColin Finck
151*c2c66affSColin Finck static
152*c2c66affSColin Finck NTSTATUS
RequestedPowerIrpHandler(_In_ PDEVICE_OBJECT DeviceObject,_In_ PIRP Irp,_In_ PIO_STACK_LOCATION IoStackLocation)153*c2c66affSColin Finck RequestedPowerIrpHandler(
154*c2c66affSColin Finck _In_ PDEVICE_OBJECT DeviceObject,
155*c2c66affSColin Finck _In_ PIRP Irp,
156*c2c66affSColin Finck _In_ PIO_STACK_LOCATION IoStackLocation)
157*c2c66affSColin Finck {
158*c2c66affSColin Finck if (RequestedPowerIrp == NULL)
159*c2c66affSColin Finck RequestedPowerIrp = Irp;
160*c2c66affSColin Finck else
161*c2c66affSColin Finck ok_eq_pointer(Irp, RequestedPowerIrp);
162*c2c66affSColin Finck
163*c2c66affSColin Finck ok_eq_uint(Irp->StackCount, 5);
164*c2c66affSColin Finck ok_eq_ulongptr(Irp->IoStatus.Information, 0);
165*c2c66affSColin Finck ok_eq_hex(Irp->IoStatus.Status, STATUS_NOT_SUPPORTED);
166*c2c66affSColin Finck ok_eq_pointer(Irp->Tail.Overlay.Thread, NULL);
167*c2c66affSColin Finck ok_eq_uint(IoStackLocation->MajorFunction, IRP_MJ_POWER);
168*c2c66affSColin Finck ok_eq_uint(IoStackLocation->MinorFunction, IRP_MN_SET_POWER);
169*c2c66affSColin Finck ok_eq_pointer(IoStackLocation->Context, RequestedPowerCompletion);
170*c2c66affSColin Finck ok_eq_uint(IoStackLocation->Parameters.Power.Type, DevicePowerState);
171*c2c66affSColin Finck ok_eq_uint(IoStackLocation->Parameters.Power.State.DeviceState, PowerDeviceD0);
172*c2c66affSColin Finck
173*c2c66affSColin Finck if (DeviceObject == DeviceObject1)
174*c2c66affSColin Finck {
175*c2c66affSColin Finck ok_eq_uint(Irp->CurrentLocation, 3);
176*c2c66affSColin Finck Irp->IoStatus.Information = 7;
177*c2c66affSColin Finck Irp->IoStatus.Status = STATUS_WAIT_3;
178*c2c66affSColin Finck PoStartNextPowerIrp(Irp);
179*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
180*c2c66affSColin Finck return STATUS_SUCCESS;
181*c2c66affSColin Finck }
182*c2c66affSColin Finck else if (DeviceObject == DeviceObject2)
183*c2c66affSColin Finck {
184*c2c66affSColin Finck ok_eq_uint(Irp->CurrentLocation, 3);
185*c2c66affSColin Finck PoStartNextPowerIrp(Irp);
186*c2c66affSColin Finck IoSkipCurrentIrpStackLocation(Irp);
187*c2c66affSColin Finck return PoCallDriver(DeviceObject1, Irp);
188*c2c66affSColin Finck }
189*c2c66affSColin Finck else if (DeviceObject == DeviceObject3)
190*c2c66affSColin Finck {
191*c2c66affSColin Finck ok_eq_uint(Irp->CurrentLocation, 3);
192*c2c66affSColin Finck PoStartNextPowerIrp(Irp);
193*c2c66affSColin Finck IoSkipCurrentIrpStackLocation(Irp);
194*c2c66affSColin Finck return PoCallDriver(DeviceObject2, Irp);
195*c2c66affSColin Finck }
196*c2c66affSColin Finck else
197*c2c66affSColin Finck {
198*c2c66affSColin Finck ok(0, "\n");
199*c2c66affSColin Finck PoStartNextPowerIrp(Irp);
200*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
201*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
202*c2c66affSColin Finck }
203*c2c66affSColin Finck }
204*c2c66affSColin Finck
205*c2c66affSColin Finck static
206*c2c66affSColin Finck VOID
TestPoRequestPowerIrp(VOID)207*c2c66affSColin Finck TestPoRequestPowerIrp(VOID)
208*c2c66affSColin Finck {
209*c2c66affSColin Finck NTSTATUS Status;
210*c2c66affSColin Finck POWER_STATE PowerState;
211*c2c66affSColin Finck
212*c2c66affSColin Finck KmtRegisterIrpHandler(IRP_MJ_POWER, NULL, RequestedPowerIrpHandler);
213*c2c66affSColin Finck
214*c2c66affSColin Finck KeInitializeEvent(&TestDoneEvent, NotificationEvent, FALSE);
215*c2c66affSColin Finck
216*c2c66affSColin Finck PowerState.DeviceState = PowerDeviceD0;
217*c2c66affSColin Finck Status = PoRequestPowerIrp(DeviceObject2,
218*c2c66affSColin Finck IRP_MN_SET_POWER,
219*c2c66affSColin Finck PowerState,
220*c2c66affSColin Finck RequestedPowerCompletion,
221*c2c66affSColin Finck &RequestedPowerIrp,
222*c2c66affSColin Finck &RequestedPowerIrpReturned);
223*c2c66affSColin Finck ok(Status == STATUS_PENDING, "PoRequestPowerIrp returned %lx\n", Status);
224*c2c66affSColin Finck ok_eq_pointer(RequestedPowerIrpReturned, RequestedPowerIrp);
225*c2c66affSColin Finck
226*c2c66affSColin Finck Status = KeWaitForSingleObject(&TestDoneEvent, Executive, KernelMode, FALSE, NULL);
227*c2c66affSColin Finck ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
228*c2c66affSColin Finck KmtUnregisterIrpHandler(IRP_MJ_POWER, NULL, RequestedPowerIrpHandler);
229*c2c66affSColin Finck }
230*c2c66affSColin Finck
231*c2c66affSColin Finck
232*c2c66affSColin Finck //
233*c2c66affSColin Finck // Message handler
234*c2c66affSColin Finck //
235*c2c66affSColin Finck static
236*c2c66affSColin Finck NTSTATUS
TestMessageHandler(_In_ PDEVICE_OBJECT DeviceObject,_In_ ULONG ControlCode,_In_ PVOID Buffer OPTIONAL,_In_ SIZE_T InLength,_Inout_ PSIZE_T OutLength)237*c2c66affSColin Finck TestMessageHandler(
238*c2c66affSColin Finck _In_ PDEVICE_OBJECT DeviceObject,
239*c2c66affSColin Finck _In_ ULONG ControlCode,
240*c2c66affSColin Finck _In_ PVOID Buffer OPTIONAL,
241*c2c66affSColin Finck _In_ SIZE_T InLength,
242*c2c66affSColin Finck _Inout_ PSIZE_T OutLength)
243*c2c66affSColin Finck {
244*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
245*c2c66affSColin Finck
246*c2c66affSColin Finck PAGED_CODE();
247*c2c66affSColin Finck
248*c2c66affSColin Finck switch (ControlCode)
249*c2c66affSColin Finck {
250*c2c66affSColin Finck case IOCTL_RUN_TEST:
251*c2c66affSColin Finck {
252*c2c66affSColin Finck Status = CreateTestDevices(TestDriverObject);
253*c2c66affSColin Finck ok_eq_hex(Status, STATUS_SUCCESS);
254*c2c66affSColin Finck if (!NT_SUCCESS(Status))
255*c2c66affSColin Finck return Status;
256*c2c66affSColin Finck
257*c2c66affSColin Finck TestPoRequestPowerIrp();
258*c2c66affSColin Finck
259*c2c66affSColin Finck IoDetachDevice(DeviceObject2);
260*c2c66affSColin Finck IoDeleteDevice(DeviceObject3);
261*c2c66affSColin Finck IoDetachDevice(DeviceObject1);
262*c2c66affSColin Finck IoDeleteDevice(DeviceObject2);
263*c2c66affSColin Finck IoDeleteDevice(DeviceObject1);
264*c2c66affSColin Finck
265*c2c66affSColin Finck break;
266*c2c66affSColin Finck }
267*c2c66affSColin Finck default:
268*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
269*c2c66affSColin Finck }
270*c2c66affSColin Finck
271*c2c66affSColin Finck return Status;
272*c2c66affSColin Finck }
273