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 } 273