2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Example Test Driver
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
16 static KMT_MESSAGE_HANDLER TestMessageHandler
;
17 static KMT_IRP_HANDLER TestIrpHandler
;
20 static PDRIVER_OBJECT TestDriverObject
;
26 * This is called by DriverEntry as early as possible, but with ResultBuffer
27 * initialized, so that test macros work correctly
31 * This is guaranteed not to have been touched by DriverEntry before
32 * the call to TestEntry
34 * Driver Registry Path
35 * This is guaranteed not to have been touched by DriverEntry before
36 * the call to TestEntry
38 * Pointer to receive a test-specific name for the device to create
40 * Pointer to a flags variable instructing DriverEntry how to proceed.
41 * See the KMT_TESTENTRY_FLAGS enumeration for possible values
42 * Initialized to zero on entry
45 * DriverEntry will fail if this is a failure status
49 IN PDRIVER_OBJECT DriverObject
,
50 IN PCUNICODE_STRING RegistryPath
,
51 OUT PCWSTR
*DeviceName
,
54 NTSTATUS Status
= STATUS_SUCCESS
;
58 UNREFERENCED_PARAMETER(RegistryPath
);
59 UNREFERENCED_PARAMETER(Flags
);
63 ok_irql(PASSIVE_LEVEL
);
64 TestDriverObject
= DriverObject
;
66 *DeviceName
= L
"Example";
68 trace("Hi, this is the example driver\n");
70 KmtRegisterIrpHandler(IRP_MJ_CREATE
, NULL
, TestIrpHandler
);
71 KmtRegisterIrpHandler(IRP_MJ_CLOSE
, NULL
, TestIrpHandler
);
72 KmtRegisterMessageHandler(0, NULL
, TestMessageHandler
);
80 * Test unload routine.
81 * This is called by the driver's Unload routine as early as possible, with
82 * ResultBuffer and the test device object still valid, so that test macros
87 * This is guaranteed not to have been touched by Unload before the call
94 IN PDRIVER_OBJECT DriverObject
)
100 ok_irql(PASSIVE_LEVEL
);
101 ok_eq_pointer(DriverObject
, TestDriverObject
);
103 trace("Unloading example driver\n");
107 * @name TestMessageHandler
109 * Test message handler routine
111 * @param DeviceObject
113 * This is guaranteed not to have been touched by the dispatch function
114 * before the call to the IRP handler
117 * This is guaranteed not to have been touched by the dispatch function
118 * before the call to the IRP handler, except for passing it to
119 * IoGetCurrentStackLocation
120 * @param IoStackLocation
122 * This is guaranteed not to have been touched by the dispatch function
123 * before the call to the IRP handler
130 IN PDEVICE_OBJECT DeviceObject
,
131 IN ULONG ControlCode
,
132 IN PVOID Buffer OPTIONAL
,
134 IN OUT PSIZE_T OutLength
)
136 NTSTATUS Status
= STATUS_SUCCESS
;
142 static int TimesReceived
= 0;
145 ok(TimesReceived
== 1, "Received control code 1 %d times\n", TimesReceived
);
146 ok_eq_pointer(Buffer
, NULL
);
147 ok_eq_ulong((ULONG
)InLength
, 0LU);
148 ok_eq_ulong((ULONG
)*OutLength
, 0LU);
151 case IOCTL_SEND_STRING
:
153 static int TimesReceived
= 0;
154 ANSI_STRING ExpectedString
= RTL_CONSTANT_STRING("yay");
155 ANSI_STRING ReceivedString
;
158 ok(TimesReceived
== 1, "Received control code 2 %d times\n", TimesReceived
);
159 ok(Buffer
!= NULL
, "Buffer is NULL\n");
160 ok_eq_ulong((ULONG
)InLength
, (ULONG
)ExpectedString
.Length
);
161 ok_eq_ulong((ULONG
)*OutLength
, 0LU);
162 ReceivedString
.MaximumLength
= ReceivedString
.Length
= (USHORT
)InLength
;
163 ReceivedString
.Buffer
= Buffer
;
164 ok(RtlCompareString(&ExpectedString
, &ReceivedString
, FALSE
) == 0, "Received string: %Z\n", &ReceivedString
);
167 case IOCTL_SEND_MYSTRUCT
:
169 static int TimesReceived
= 0;
170 MY_STRUCT ExpectedStruct
= { 123, ":D" };
171 MY_STRUCT ResultStruct
= { 456, "!!!" };
174 ok(TimesReceived
== 1, "Received control code 3 %d times\n", TimesReceived
);
175 ok(Buffer
!= NULL
, "Buffer is NULL\n");
176 ok_eq_ulong((ULONG
)InLength
, (ULONG
)sizeof ExpectedStruct
);
177 ok_eq_ulong((ULONG
)*OutLength
, 2LU * sizeof ExpectedStruct
);
178 if (!skip(Buffer
&& InLength
>= sizeof ExpectedStruct
, "Cannot read from buffer!\n"))
179 ok(RtlCompareMemory(&ExpectedStruct
, Buffer
, sizeof ExpectedStruct
) == sizeof ExpectedStruct
, "Buffer does not contain expected values\n");
181 if (!skip(Buffer
&& *OutLength
>= 2 * sizeof ExpectedStruct
, "Cannot write to buffer!\n"))
183 RtlCopyMemory((PCHAR
)Buffer
+ sizeof ExpectedStruct
, &ResultStruct
, sizeof ResultStruct
);
184 *OutLength
= 2 * sizeof ExpectedStruct
;
189 ok(0, "Got an unknown message! DeviceObject=%p, ControlCode=%lu, Buffer=%p, In=%lu, Out=%lu bytes\n",
190 DeviceObject
, ControlCode
, Buffer
, InLength
, *OutLength
);
198 * @name TestIrpHandler
200 * Test IRP handler routine
202 * @param DeviceObject
204 * This is guaranteed not to have been touched by the dispatch function
205 * before the call to the IRP handler
208 * This is guaranteed not to have been touched by the dispatch function
209 * before the call to the IRP handler, except for passing it to
210 * IoGetCurrentStackLocation
211 * @param IoStackLocation
213 * This is guaranteed not to have been touched by the dispatch function
214 * before the call to the IRP handler
221 IN PDEVICE_OBJECT DeviceObject
,
223 IN PIO_STACK_LOCATION IoStackLocation
)
225 NTSTATUS Status
= STATUS_SUCCESS
;
229 ok_irql(PASSIVE_LEVEL
);
230 ok_eq_pointer(DeviceObject
->DriverObject
, TestDriverObject
);
232 if (IoStackLocation
->MajorFunction
== IRP_MJ_CREATE
)
233 trace("Got IRP_MJ_CREATE!\n");
234 else if (IoStackLocation
->MajorFunction
== IRP_MJ_CLOSE
)
235 trace("Got IRP_MJ_CLOSE!\n");
237 trace("Got an IRP!\n");
239 Irp
->IoStatus
.Status
= Status
;
240 Irp
->IoStatus
.Information
= 0;
242 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);