[USP10_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / kmtests / ntos_io / IoReadWrite_user.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for Read/Write operations
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9 #include "IoReadWrite.h"
10
11 static
12 VOID
13 TestRead(
14 _In_ HANDLE FileHandle,
15 _In_ BOOLEAN Cached,
16 _In_ BOOLEAN UseFastIo,
17 _In_ BOOLEAN ReturnPending)
18 {
19 NTSTATUS Status;
20 IO_STATUS_BLOCK IoStatus;
21 HANDLE EventHandle;
22 UCHAR Buffer[32];
23 LARGE_INTEGER Offset;
24 ULONG BaseKey, StatusKey, Key;
25 DWORD WaitStatus;
26
27 BaseKey = (UseFastIo ? KEY_USE_FASTIO : 0) |
28 (ReturnPending ? KEY_RETURN_PENDING : 0);
29
30 EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
31 ok(EventHandle != NULL, "CreateEvent failed with %lu\n", GetLastError());
32
33 for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
34 {
35 //trace("\tSTATUS KEY: %lx\n", StatusKey);
36 ResetEvent(EventHandle);
37 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
38 Key = BaseKey | StatusKey | KEY_DATA(0x11);
39 Offset.QuadPart = 0;
40 Status = NtReadFile(FileHandle,
41 EventHandle,
42 NULL,
43 NULL,
44 &IoStatus,
45 NULL,
46 0,
47 &Offset,
48 &Key);
49 WaitStatus = WaitForSingleObject(EventHandle, 0);
50 if (ReturnPending)
51 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
52 else
53 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
54 if (Cached && UseFastIo && !ReturnPending)
55 {
56 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
57 ok_eq_hex(IoStatus.Status, STATUS_BUFFER_OVERFLOW);
58 ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
59 }
60 else
61 {
62 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
63 ok_eq_hex(IoStatus.Status, 0x55555555);
64 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
65 }
66
67 KmtStartSeh()
68 ResetEvent(EventHandle);
69 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
70 Key = BaseKey | StatusKey | KEY_DATA(0x22);
71 Offset.QuadPart = 0;
72 Status = NtReadFile(FileHandle,
73 EventHandle,
74 NULL,
75 NULL,
76 &IoStatus,
77 NULL,
78 sizeof(Buffer),
79 &Offset,
80 &Key);
81 WaitStatus = WaitForSingleObject(EventHandle, 0);
82 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
83 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
84 ok_eq_hex(IoStatus.Status, 0x55555555);
85 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
86 KmtEndSeh(STATUS_SUCCESS);
87
88 ResetEvent(EventHandle);
89 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
90 RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
91 Key = BaseKey | StatusKey | KEY_DATA(0x33);
92 Offset.QuadPart = 0;
93 Status = NtReadFile(FileHandle,
94 EventHandle,
95 NULL,
96 NULL,
97 &IoStatus,
98 Buffer,
99 0,
100 &Offset,
101 &Key);
102 WaitStatus = WaitForSingleObject(EventHandle, 0);
103 if (ReturnPending)
104 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
105 else
106 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
107 if (Cached && UseFastIo && !ReturnPending)
108 {
109 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
110 ok_eq_hex(IoStatus.Status, STATUS_BUFFER_OVERFLOW);
111 ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
112 }
113 else
114 {
115 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
116 ok_eq_hex(IoStatus.Status, 0x55555555);
117 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
118 }
119 ok_eq_uint(Buffer[0], 0x55);
120
121 ResetEvent(EventHandle);
122 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
123 RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
124 Key = BaseKey | StatusKey | KEY_DATA(0x44);
125 Offset.QuadPart = 0;
126 Status = NtReadFile(FileHandle,
127 EventHandle,
128 NULL,
129 NULL,
130 &IoStatus,
131 Buffer,
132 sizeof(Buffer),
133 &Offset,
134 &Key);
135 WaitStatus = WaitForSingleObject(EventHandle, 0);
136 ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
137 if ((Cached && UseFastIo && !ReturnPending &&
138 (StatusKey == KEY_SUCCEED || StatusKey == KEY_FAIL_OVERFLOW || StatusKey == KEY_FAIL_EOF)) ||
139 !KEY_ERROR(StatusKey))
140 {
141 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
142 ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
143 ok_eq_ulongptr(IoStatus.Information, TEST_FILE_SIZE);
144 }
145 else
146 {
147 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
148 ok_eq_hex(IoStatus.Status, 0x55555555);
149 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
150 }
151 if ((StatusKey != KEY_FAIL_VERIFY_REQUIRED && !KEY_ERROR(StatusKey)) ||
152 Cached)
153 {
154 ok_eq_uint(Buffer[0], 0x44);
155 ok_eq_uint(Buffer[TEST_FILE_SIZE - 1], 0x44);
156 ok_eq_uint(Buffer[TEST_FILE_SIZE], 0x55);
157 }
158 else
159 {
160 ok_eq_uint(Buffer[0], 0x55);
161 }
162 }
163 }
164
165 static
166 VOID
167 TestWrite(
168 _In_ HANDLE FileHandle,
169 _In_ BOOLEAN Cached,
170 _In_ BOOLEAN UseFastIo,
171 _In_ BOOLEAN ReturnPending)
172 {
173 NTSTATUS Status;
174 IO_STATUS_BLOCK IoStatus;
175 HANDLE EventHandle;
176 UCHAR Buffer[32];
177 LARGE_INTEGER Offset;
178 ULONG BaseKey, StatusKey, Key;
179 DWORD WaitStatus;
180
181 BaseKey = (UseFastIo ? KEY_USE_FASTIO : 0) |
182 (ReturnPending ? KEY_RETURN_PENDING : 0);
183
184 EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
185 ok(EventHandle != NULL, "CreateEvent failed with %lu\n", GetLastError());
186
187 for (StatusKey = KEY_SUCCEED ; StatusKey != 0xff; StatusKey = KEY_NEXT(StatusKey))
188 {
189 //trace("\tSTATUS KEY: %lx\n", StatusKey);
190 ResetEvent(EventHandle);
191 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
192 Key = BaseKey | StatusKey | KEY_DATA(0x11);
193 Offset.QuadPart = 0;
194 Status = NtWriteFile(FileHandle,
195 EventHandle,
196 NULL,
197 NULL,
198 &IoStatus,
199 NULL,
200 0,
201 &Offset,
202 &Key);
203 WaitStatus = WaitForSingleObject(EventHandle, 0);
204 ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
205 if (!KEY_ERROR(StatusKey))
206 {
207 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
208 ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
209 ok_eq_ulongptr(IoStatus.Information, 0);
210 }
211 else
212 {
213 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
214 ok_eq_hex(IoStatus.Status, 0x55555555);
215 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
216 }
217
218 KmtStartSeh()
219 ResetEvent(EventHandle);
220 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
221 Key = BaseKey | StatusKey | KEY_DATA(0x22);
222 Offset.QuadPart = 0;
223 Status = NtWriteFile(FileHandle,
224 EventHandle,
225 NULL,
226 NULL,
227 &IoStatus,
228 NULL,
229 sizeof(Buffer),
230 &Offset,
231 &Key);
232 WaitStatus = WaitForSingleObject(EventHandle, 0);
233 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
234 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
235 ok_eq_hex(IoStatus.Status, 0x55555555);
236 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
237 KmtEndSeh(STATUS_SUCCESS);
238
239 ResetEvent(EventHandle);
240 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
241 RtlFillMemory(Buffer, sizeof(Buffer), 0x55);
242 Key = BaseKey | StatusKey | KEY_DATA(0x33);
243 Offset.QuadPart = 0;
244 Status = NtWriteFile(FileHandle,
245 EventHandle,
246 NULL,
247 NULL,
248 &IoStatus,
249 Buffer,
250 0,
251 &Offset,
252 &Key);
253 WaitStatus = WaitForSingleObject(EventHandle, 0);
254 ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
255 if (!KEY_ERROR(StatusKey))
256 {
257 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
258 ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
259 ok_eq_ulongptr(IoStatus.Information, 0);
260 }
261 else
262 {
263 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
264 ok_eq_hex(IoStatus.Status, 0x55555555);
265 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
266 }
267
268 ResetEvent(EventHandle);
269 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
270 RtlFillMemory(Buffer, sizeof(Buffer), 0x44);
271 Key = BaseKey | StatusKey | KEY_DATA(0x44);
272 Offset.QuadPart = 0;
273 Status = NtWriteFile(FileHandle,
274 EventHandle,
275 NULL,
276 NULL,
277 &IoStatus,
278 Buffer,
279 sizeof(Buffer),
280 &Offset,
281 &Key);
282 WaitStatus = WaitForSingleObject(EventHandle, 0);
283 ok_eq_hex(Status, TestGetReturnStatus(StatusKey));
284 if (!KEY_ERROR(StatusKey))
285 {
286 ok_eq_ulong(WaitStatus, WAIT_OBJECT_0);
287 ok_eq_hex(IoStatus.Status, TestGetReturnStatus(StatusKey));
288 ok_eq_ulongptr(IoStatus.Information, sizeof(Buffer));
289 }
290 else
291 {
292 ok_eq_ulong(WaitStatus, WAIT_TIMEOUT);
293 ok_eq_hex(IoStatus.Status, 0x55555555);
294 ok_eq_ulongptr(IoStatus.Information, (ULONG_PTR)0x5555555555555555);
295 }
296 }
297 }
298
299 START_TEST(IoReadWrite)
300 {
301 HANDLE FileHandle;
302 UNICODE_STRING CachedFileName = RTL_CONSTANT_STRING(L"\\Device\\Kmtest-IoReadWrite\\Cached");
303 UNICODE_STRING NonCachedFileName = RTL_CONSTANT_STRING(L"\\Device\\Kmtest-IoReadWrite\\NonCached");
304 OBJECT_ATTRIBUTES ObjectAttributes;
305 IO_STATUS_BLOCK IoStatus;
306 NTSTATUS Status;
307
308 KmtLoadDriver(L"IoReadWrite", FALSE);
309 KmtOpenDriver();
310
311 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
312 InitializeObjectAttributes(&ObjectAttributes,
313 &NonCachedFileName,
314 OBJ_CASE_INSENSITIVE,
315 NULL,
316 NULL);
317 Status = NtOpenFile(&FileHandle,
318 FILE_ALL_ACCESS,
319 &ObjectAttributes,
320 &IoStatus,
321 0,
322 FILE_NON_DIRECTORY_FILE |
323 FILE_SYNCHRONOUS_IO_NONALERT);
324 ok_eq_hex(Status, STATUS_SUCCESS);
325 if (!skip(NT_SUCCESS(Status), "No file\n"))
326 {
327 ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
328 ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
329 trace("Non-Cached read, no FastIo, direct return\n");
330 TestRead(FileHandle, FALSE, FALSE, FALSE);
331 trace("Non-Cached read, allow FastIo, direct return\n");
332 TestRead(FileHandle, FALSE, TRUE, FALSE);
333 trace("Non-Cached read, no FastIo, pending return\n");
334 TestRead(FileHandle, FALSE, FALSE, TRUE);
335 trace("Non-Cached read, allow FastIo, pending return\n");
336 TestRead(FileHandle, FALSE, TRUE, TRUE);
337
338 trace("Non-Cached write, no FastIo, direct return\n");
339 TestWrite(FileHandle, FALSE, FALSE, FALSE);
340 trace("Non-Cached write, allow FastIo, direct return\n");
341 TestWrite(FileHandle, FALSE, TRUE, FALSE);
342 trace("Non-Cached write, no FastIo, pending return\n");
343 TestWrite(FileHandle, FALSE, FALSE, TRUE);
344 trace("Non-Cached write, allow FastIo, pending return\n");
345 TestWrite(FileHandle, FALSE, TRUE, TRUE);
346 NtClose(FileHandle);
347 }
348
349 RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
350 InitializeObjectAttributes(&ObjectAttributes,
351 &CachedFileName,
352 OBJ_CASE_INSENSITIVE,
353 NULL,
354 NULL);
355 Status = NtOpenFile(&FileHandle,
356 FILE_ALL_ACCESS,
357 &ObjectAttributes,
358 &IoStatus,
359 0,
360 FILE_NON_DIRECTORY_FILE |
361 FILE_SYNCHRONOUS_IO_NONALERT);
362 ok_eq_hex(Status, STATUS_SUCCESS);
363 if (!skip(NT_SUCCESS(Status), "No file\n"))
364 {
365 ok_eq_hex(IoStatus.Status, STATUS_SUCCESS);
366 ok_eq_ulongptr(IoStatus.Information, FILE_OPENED);
367 trace("Cached read, no FastIo, direct return\n");
368 TestRead(FileHandle, TRUE, FALSE, FALSE);
369 trace("Cached read, allow FastIo, direct return\n");
370 TestRead(FileHandle, TRUE, TRUE, FALSE);
371 trace("Cached read, no FastIo, pending return\n");
372 TestRead(FileHandle, TRUE, FALSE, TRUE);
373 trace("Cached read, allow FastIo, pending return\n");
374 TestRead(FileHandle, TRUE, TRUE, TRUE);
375
376 trace("Cached write, no FastIo, direct return\n");
377 TestWrite(FileHandle, TRUE, FALSE, FALSE);
378 trace("Cached write, allow FastIo, direct return\n");
379 TestWrite(FileHandle, TRUE, TRUE, FALSE);
380 trace("Cached write, no FastIo, pending return\n");
381 TestWrite(FileHandle, TRUE, FALSE, TRUE);
382 trace("Cached write, allow FastIo, pending return\n");
383 TestWrite(FileHandle, TRUE, TRUE, TRUE);
384 NtClose(FileHandle);
385 }
386
387 KmtCloseDriver();
388 KmtUnloadDriver();
389 }