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