ntoskrnl.exe: Implement NtBuildNumber.
[wine.git] / dlls / ntoskrnl.exe / tests / driver.c
blob3984240e86d28a981ebdd96631a01a633e88879f
1 /*
2 * ntoskrnl.exe testing framework
4 * Copyright 2015 Sebastian Lackner
5 * Copyright 2015 Michael Müller
6 * Copyright 2015 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winternl.h"
30 #include "winioctl.h"
31 #include "ddk/ntddk.h"
32 #include "ddk/wdm.h"
34 #include "driver.h"
36 static const WCHAR driver_device[] = {'\\','D','e','v','i','c','e',
37 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
38 static const WCHAR driver_link[] = {'\\','D','o','s','D','e','v','i','c','e','s',
39 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
41 static HANDLE okfile;
42 static LONG successes;
43 static LONG failures;
44 static LONG skipped;
45 static LONG todo_successes;
46 static LONG todo_failures;
47 static int todo_level, todo_do_loop;
48 static int running_under_wine;
49 static int winetest_debug;
50 static int winetest_report_success;
52 extern int CDECL _vsnprintf(char *str, size_t len, const char *format, __ms_va_list argptr);
54 static void kvprintf(const char *format, __ms_va_list ap)
56 static char buffer[512];
57 IO_STATUS_BLOCK io;
59 _vsnprintf(buffer, sizeof(buffer), format, ap);
60 ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, strlen(buffer), NULL, NULL);
63 static void WINAPIV kprintf(const char *format, ...)
65 __ms_va_list valist;
67 __ms_va_start(valist, format);
68 kvprintf(format, valist);
69 __ms_va_end(valist);
72 static void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args)
74 const char *current_file;
76 if (!(current_file = drv_strrchr(file, '/')) &&
77 !(current_file = drv_strrchr(file, '\\')))
78 current_file = file;
79 else
80 current_file++;
82 if (todo_level)
84 if (condition)
86 kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line);
87 kvprintf(msg, args);
88 InterlockedIncrement(&todo_failures);
90 else
92 if (winetest_debug > 0)
94 kprintf("%s:%d: Test marked todo: ", current_file, line);
95 kvprintf(msg, args);
97 InterlockedIncrement(&todo_successes);
100 else
102 if (!condition)
104 kprintf("%s:%d: Test failed: ", current_file, line);
105 kvprintf(msg, args);
106 InterlockedIncrement(&failures);
108 else
110 if (winetest_report_success)
111 kprintf("%s:%d: Test succeeded\n", current_file, line);
112 InterlockedIncrement(&successes);
117 static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...)
119 __ms_va_list args;
120 __ms_va_start(args, msg);
121 vok_(file, line, condition, msg, args);
122 __ms_va_end(args);
125 void vskip_(const char *file, int line, const char *msg, __ms_va_list args)
127 const char *current_file;
129 if (!(current_file = drv_strrchr(file, '/')) &&
130 !(current_file = drv_strrchr(file, '\\')))
131 current_file = file;
132 else
133 current_file++;
135 kprintf("%s:%d: Tests skipped: ", current_file, line);
136 kvprintf(msg, args);
137 skipped++;
140 void WINAPIV win_skip_(const char *file, int line, const char *msg, ...)
142 __ms_va_list args;
143 __ms_va_start(args, msg);
144 if (running_under_wine)
145 vok_(file, line, 0, msg, args);
146 else
147 vskip_(file, line, msg, args);
148 __ms_va_end(args);
151 static void winetest_start_todo( int is_todo )
153 todo_level = (todo_level << 1) | (is_todo != 0);
154 todo_do_loop=1;
157 static int winetest_loop_todo(void)
159 int do_loop=todo_do_loop;
160 todo_do_loop=0;
161 return do_loop;
164 static void winetest_end_todo(void)
166 todo_level >>= 1;
169 #define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__)
170 #define todo_if(is_todo) for (winetest_start_todo(is_todo); \
171 winetest_loop_todo(); \
172 winetest_end_todo())
173 #define todo_wine todo_if(running_under_wine)
174 #define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine)
175 #define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__)
177 static void *get_proc_address(const char *name)
179 UNICODE_STRING name_u;
180 ANSI_STRING name_a;
181 NTSTATUS status;
182 void *ret;
184 RtlInitAnsiString(&name_a, name);
185 status = RtlAnsiStringToUnicodeString(&name_u, &name_a, TRUE);
186 ok (!status, "RtlAnsiStringToUnicodeString failed: %#x\n", status);
187 if (status) return NULL;
189 ret = MmGetSystemRoutineAddress(&name_u);
190 RtlFreeUnicodeString(&name_u);
191 return ret;
194 static void test_currentprocess(void)
196 PEPROCESS current;
198 current = IoGetCurrentProcess();
199 todo_wine
200 ok(current != NULL, "Expected current process to be non-NULL\n");
203 static FILE_OBJECT *last_created_file;
205 static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device)
207 IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
209 ok(last_created_file != NULL, "last_created_file = NULL\n");
210 ok(irpsp->FileObject == last_created_file, "FileObject != last_created_file\n");
211 ok(irpsp->DeviceObject == device, "unexpected DeviceObject\n");
212 ok(irpsp->FileObject->DeviceObject == device, "unexpected FileObject->DeviceObject\n");
215 static void test_mdl_map(void)
217 char buffer[20] = "test buffer";
218 void *addr;
219 MDL *mdl;
221 mdl = IoAllocateMdl(buffer, sizeof(buffer), FALSE, FALSE, NULL);
222 ok(mdl != NULL, "IoAllocateMdl failed\n");
224 MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
226 addr = MmMapLockedPagesSpecifyCache(mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
227 todo_wine
228 ok(addr != NULL, "MmMapLockedPagesSpecifyCache failed\n");
230 /* MmUnmapLockedPages(addr, mdl); */
232 IoFreeMdl(mdl);
235 static void test_init_funcs(void)
237 KTIMER timer, timer2;
239 KeInitializeTimerEx(&timer, NotificationTimer);
240 ok(timer.Header.Type == 8, "got: %u\n", timer.Header.Type);
241 ok(timer.Header.Size == 0 || timer.Header.Size == 10, "got: %u\n", timer.Header.Size);
242 ok(timer.Header.SignalState == 0, "got: %u\n", timer.Header.SignalState);
244 KeInitializeTimerEx(&timer2, SynchronizationTimer);
245 ok(timer2.Header.Type == 9, "got: %u\n", timer2.Header.Type);
246 ok(timer2.Header.Size == 0 || timer2.Header.Size == 10, "got: %u\n", timer2.Header.Size);
247 ok(timer2.Header.SignalState == 0, "got: %u\n", timer2.Header.SignalState);
250 static const WCHAR driver2_path[] = {
251 '\\','R','e','g','i','s','t','r','y',
252 '\\','M','a','c','h','i','n','e',
253 '\\','S','y','s','t','e','m',
254 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
255 '\\','S','e','r','v','i','c','e','s',
256 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r','2',0
259 static void test_load_driver(void)
261 UNICODE_STRING name;
262 NTSTATUS ret;
264 RtlInitUnicodeString(&name, driver2_path);
266 ret = ZwLoadDriver(&name);
267 ok(!ret, "got %#x\n", ret);
269 ret = ZwLoadDriver(&name);
270 ok(ret == STATUS_IMAGE_ALREADY_LOADED, "got %#x\n", ret);
272 ret = ZwUnloadDriver(&name);
273 ok(!ret, "got %#x\n", ret);
276 static NTSTATUS wait_single(void *obj, ULONGLONG timeout)
278 LARGE_INTEGER integer;
280 integer.QuadPart = timeout;
281 return KeWaitForSingleObject(obj, Executive, KernelMode, FALSE, &integer);
284 static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, ULONGLONG timeout)
286 LARGE_INTEGER integer;
288 integer.QuadPart = timeout;
289 return KeWaitForMultipleObjects(count, objs, wait_type, Executive, KernelMode, FALSE, &integer, NULL);
292 static void run_thread(PKSTART_ROUTINE proc, void *arg)
294 OBJECT_ATTRIBUTES attr = {0};
295 HANDLE thread;
296 NTSTATUS ret;
298 attr.Length = sizeof(attr);
299 attr.Attributes = OBJ_KERNEL_HANDLE;
300 ret = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, &attr, NULL, NULL, proc, arg);
301 ok(!ret, "got %#x\n", ret);
303 ret = ZwWaitForSingleObject(thread, FALSE, NULL);
304 ok(!ret, "got %#x\n", ret);
305 ret = ZwClose(thread);
306 ok(!ret, "got %#x\n", ret);
309 static KMUTEX test_mutex;
311 static void WINAPI mutex_thread(void *arg)
313 NTSTATUS ret, expect = (NTSTATUS)(DWORD_PTR)arg;
315 ret = wait_single(&test_mutex, 0);
316 ok(ret == expect, "expected %#x, got %#x\n", expect, ret);
318 if (!ret) KeReleaseMutex(&test_mutex, FALSE);
319 PsTerminateSystemThread(STATUS_SUCCESS);
322 static void test_sync(void)
324 KSEMAPHORE semaphore, semaphore2;
325 KEVENT manual_event, auto_event;
326 KTIMER timer;
327 LARGE_INTEGER timeout;
328 void *objs[2];
329 NTSTATUS ret;
330 int i;
332 KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
334 ret = wait_single(&manual_event, 0);
335 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
337 KeSetEvent(&manual_event, 0, FALSE);
339 ret = wait_single(&manual_event, 0);
340 ok(ret == 0, "got %#x\n", ret);
342 ret = wait_single(&manual_event, 0);
343 ok(ret == 0, "got %#x\n", ret);
345 KeResetEvent(&manual_event);
347 ret = wait_single(&manual_event, 0);
348 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
350 KeInitializeEvent(&auto_event, SynchronizationEvent, FALSE);
352 ret = wait_single(&auto_event, 0);
353 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
355 KeSetEvent(&auto_event, 0, FALSE);
357 ret = wait_single(&auto_event, 0);
358 ok(ret == 0, "got %#x\n", ret);
360 ret = wait_single(&auto_event, 0);
361 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
363 KeInitializeEvent(&auto_event, SynchronizationEvent, TRUE);
365 ret = wait_single(&auto_event, 0);
366 ok(ret == 0, "got %#x\n", ret);
368 objs[0] = &manual_event;
369 objs[1] = &auto_event;
371 ret = wait_multiple(2, objs, WaitAny, 0);
372 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
374 KeSetEvent(&manual_event, 0, FALSE);
375 KeSetEvent(&auto_event, 0, FALSE);
377 ret = wait_multiple(2, objs, WaitAny, 0);
378 ok(ret == 0, "got %#x\n", ret);
380 ret = wait_single(&auto_event, 0);
381 ok(ret == 0, "got %#x\n", ret);
383 KeResetEvent(&manual_event);
384 KeSetEvent(&auto_event, 0, FALSE);
386 ret = wait_multiple(2, objs, WaitAny, 0);
387 ok(ret == 1, "got %#x\n", ret);
389 ret = wait_multiple(2, objs, WaitAny, 0);
390 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
392 KeSetEvent(&manual_event, 0, FALSE);
393 KeSetEvent(&auto_event, 0, FALSE);
395 ret = wait_multiple(2, objs, WaitAll, 0);
396 ok(ret == 0, "got %#x\n", ret);
398 ret = wait_multiple(2, objs, WaitAll, 0);
399 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
401 KeSetEvent(&auto_event, 0, FALSE);
402 KeResetEvent(&manual_event);
404 ret = wait_multiple(2, objs, WaitAll, 0);
405 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
407 ret = wait_single(&auto_event, 0);
408 ok(ret == 0, "got %#x\n", ret);
410 objs[0] = &auto_event;
411 objs[1] = &manual_event;
412 KeSetEvent(&manual_event, 0, FALSE);
413 KeSetEvent(&auto_event, 0, FALSE);
415 ret = wait_multiple(2, objs, WaitAny, 0);
416 ok(ret == 0, "got %#x\n", ret);
418 ret = wait_multiple(2, objs, WaitAny, 0);
419 ok(ret == 1, "got %#x\n", ret);
421 ret = wait_multiple(2, objs, WaitAny, 0);
422 ok(ret == 1, "got %#x\n", ret);
424 /* test semaphores */
425 KeInitializeSemaphore(&semaphore, 0, 5);
427 ret = wait_single(&semaphore, 0);
428 ok(ret == STATUS_TIMEOUT, "got %u\n", ret);
430 ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
431 ok(ret == 0, "got prev %d\n", ret);
433 ret = KeReleaseSemaphore(&semaphore, 0, 2, FALSE);
434 ok(ret == 1, "got prev %d\n", ret);
436 ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
437 ok(ret == 3, "got prev %d\n", ret);
439 for (i = 0; i < 4; i++)
441 ret = wait_single(&semaphore, 0);
442 ok(ret == 0, "got %#x\n", ret);
445 ret = wait_single(&semaphore, 0);
446 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
448 KeInitializeSemaphore(&semaphore2, 3, 5);
450 ret = KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
451 ok(ret == 3, "got prev %d\n", ret);
453 for (i = 0; i < 4; i++)
455 ret = wait_single(&semaphore2, 0);
456 ok(ret == 0, "got %#x\n", ret);
459 objs[0] = &semaphore;
460 objs[1] = &semaphore2;
462 ret = wait_multiple(2, objs, WaitAny, 0);
463 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
465 KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
466 KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
468 ret = wait_multiple(2, objs, WaitAny, 0);
469 ok(ret == 0, "got %#x\n", ret);
471 ret = wait_multiple(2, objs, WaitAny, 0);
472 ok(ret == 1, "got %#x\n", ret);
474 ret = wait_multiple(2, objs, WaitAny, 0);
475 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
477 KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
478 KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
480 ret = wait_multiple(2, objs, WaitAll, 0);
481 ok(ret == 0, "got %#x\n", ret);
483 ret = wait_multiple(2, objs, WaitAny, 0);
484 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
486 /* test mutexes */
487 KeInitializeMutex(&test_mutex, 0);
489 for (i = 0; i < 10; i++)
491 ret = wait_single(&test_mutex, 0);
492 ok(ret == 0, "got %#x\n", ret);
495 for (i = 0; i < 10; i++)
497 ret = KeReleaseMutex(&test_mutex, FALSE);
498 ok(ret == i - 9, "expected %d, got %d\n", i - 9, ret);
501 run_thread(mutex_thread, (void *)0);
503 ret = wait_single(&test_mutex, 0);
504 ok(ret == 0, "got %#x\n", ret);
506 run_thread(mutex_thread, (void *)STATUS_TIMEOUT);
508 ret = KeReleaseMutex(&test_mutex, 0);
509 ok(ret == 0, "got %#x\n", ret);
511 run_thread(mutex_thread, (void *)0);
513 /* test timers */
514 KeInitializeTimerEx(&timer, NotificationTimer);
516 timeout.QuadPart = -100;
517 KeSetTimerEx(&timer, timeout, 0, NULL);
519 ret = wait_single(&timer, 0);
520 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
522 ret = wait_single(&timer, -200);
523 ok(ret == 0, "got %#x\n", ret);
525 ret = wait_single(&timer, 0);
526 ok(ret == 0, "got %#x\n", ret);
528 KeCancelTimer(&timer);
529 KeInitializeTimerEx(&timer, SynchronizationTimer);
531 KeSetTimerEx(&timer, timeout, 0, NULL);
533 ret = wait_single(&timer, 0);
534 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
536 ret = wait_single(&timer, -200);
537 ok(ret == 0, "got %#x\n", ret);
539 ret = wait_single(&timer, 0);
540 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
542 KeCancelTimer(&timer);
543 KeSetTimerEx(&timer, timeout, 10, NULL);
545 ret = wait_single(&timer, 0);
546 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
548 ret = wait_single(&timer, -200);
549 ok(ret == 0, "got %#x\n", ret);
551 ret = wait_single(&timer, 0);
552 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
554 ret = wait_single(&timer, -20 * 10000);
555 ok(ret == 0, "got %#x\n", ret);
557 ret = wait_single(&timer, -20 * 10000);
558 ok(ret == 0, "got %#x\n", ret);
560 KeCancelTimer(&timer);
563 static int callout_cnt;
565 static void WINAPI callout(void *parameter)
567 ok(parameter == (void*)0xdeadbeef, "parameter = %p\n", parameter);
568 callout_cnt++;
571 static void test_stack_callout(void)
573 NTSTATUS (WINAPI *pKeExpandKernelStackAndCallout)(PEXPAND_STACK_CALLOUT,void*,SIZE_T);
574 NTSTATUS (WINAPI *pKeExpandKernelStackAndCalloutEx)(PEXPAND_STACK_CALLOUT,void*,SIZE_T,BOOLEAN,void*);
575 NTSTATUS ret;
577 pKeExpandKernelStackAndCallout = get_proc_address("KeExpandKernelStackAndCallout");
578 if (pKeExpandKernelStackAndCallout)
580 callout_cnt = 0;
581 ret = pKeExpandKernelStackAndCallout(callout, (void*)0xdeadbeef, 4096);
582 ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCallout failed: %#x\n", ret);
583 ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt);
585 else win_skip("KeExpandKernelStackAndCallout is not available\n");
587 pKeExpandKernelStackAndCalloutEx = get_proc_address("KeExpandKernelStackAndCalloutEx");
588 if (pKeExpandKernelStackAndCalloutEx)
590 callout_cnt = 0;
591 ret = pKeExpandKernelStackAndCalloutEx(callout, (void*)0xdeadbeef, 4096, FALSE, NULL);
592 ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCalloutEx failed: %#x\n", ret);
593 ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt);
595 else win_skip("KeExpandKernelStackAndCalloutEx is not available\n");
598 static void test_lookaside_list(void)
600 NPAGED_LOOKASIDE_LIST list;
601 ULONG tag = 0x454e4957; /* WINE */
603 ExInitializeNPagedLookasideList(&list, NULL, NULL, POOL_NX_ALLOCATION, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 0);
604 ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth);
605 ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth);
606 ok(list.L.TotalAllocates == 0, "Expected 0 got %u\n", list.L.TotalAllocates);
607 ok(list.L.AllocateMisses == 0, "Expected 0 got %u\n", list.L.AllocateMisses);
608 ok(list.L.TotalFrees == 0, "Expected 0 got %u\n", list.L.TotalFrees);
609 ok(list.L.FreeMisses == 0, "Expected 0 got %u\n", list.L.FreeMisses);
610 ok(list.L.Type == (NonPagedPool|POOL_NX_ALLOCATION),
611 "Expected NonPagedPool|POOL_NX_ALLOCATION got %u\n", list.L.Type);
612 ok(list.L.Tag == tag, "Expected %x got %x\n", tag, list.L.Tag);
613 ok(list.L.Size == LOOKASIDE_MINIMUM_BLOCK_SIZE,
614 "Expected %u got %u\n", LOOKASIDE_MINIMUM_BLOCK_SIZE, list.L.Size);
615 ok(list.L.LastTotalAllocates == 0,"Expected 0 got %u\n", list.L.LastTotalAllocates);
616 ok(list.L.LastAllocateMisses == 0,"Expected 0 got %u\n", list.L.LastAllocateMisses);
617 ExDeleteNPagedLookasideList(&list);
619 list.L.Depth = 0;
620 ExInitializeNPagedLookasideList(&list, NULL, NULL, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 20);
621 ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth);
622 ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth);
623 ok(list.L.Type == NonPagedPool, "Expected NonPagedPool got %u\n", list.L.Type);
624 ExDeleteNPagedLookasideList(&list);
627 static void test_version(void)
629 USHORT *pNtBuildNumber;
630 ULONG build;
632 pNtBuildNumber = get_proc_address("NtBuildNumber");
633 ok(!!pNtBuildNumber, "Could not get pointer to NtBuildNumber\n");
635 PsGetVersion(NULL, NULL, &build, NULL);
636 ok(*pNtBuildNumber == build, "Expected build number %u, got %u\n", build, *pNtBuildNumber);
639 static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
641 ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
642 void *buffer = irp->AssociatedIrp.SystemBuffer;
643 struct test_input *test_input = (struct test_input *)buffer;
644 OBJECT_ATTRIBUTES attr = {0};
645 UNICODE_STRING pathU;
646 IO_STATUS_BLOCK io;
648 if (!buffer)
649 return STATUS_ACCESS_VIOLATION;
651 if (length < sizeof(failures))
652 return STATUS_BUFFER_TOO_SMALL;
654 attr.Length = sizeof(attr);
655 RtlInitUnicodeString(&pathU, test_input->path);
656 running_under_wine = test_input->running_under_wine;
657 winetest_debug = test_input->winetest_debug;
658 winetest_report_success = test_input->winetest_report_success;
659 attr.ObjectName = &pathU;
660 attr.Attributes = OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */
661 ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT);
663 test_irp_struct(irp, device);
664 test_currentprocess();
665 test_mdl_map();
666 test_init_funcs();
667 test_load_driver();
668 test_sync();
669 test_version();
670 test_stack_callout();
671 test_lookaside_list();
673 /* print process report */
674 if (test_input->winetest_debug)
676 kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
677 PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures,
678 todo_successes, failures + todo_failures,
679 (failures + todo_failures != 1) ? "failures" : "failure", skipped );
681 ZwClose(okfile);
682 *((LONG *)buffer) = failures;
683 *info = sizeof(failures);
684 return STATUS_SUCCESS;
687 static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
689 ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
690 char *buffer = irp->AssociatedIrp.SystemBuffer;
692 if (!buffer)
693 return STATUS_ACCESS_VIOLATION;
695 if (length < sizeof(teststr))
696 return STATUS_BUFFER_TOO_SMALL;
698 strcpy(buffer, teststr);
699 *info = sizeof(teststr);
701 return STATUS_SUCCESS;
704 static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
706 BOOL *load = irp->AssociatedIrp.SystemBuffer;
707 UNICODE_STRING name;
709 if (!load)
710 return STATUS_ACCESS_VIOLATION;
712 *info = 0;
714 RtlInitUnicodeString(&name, driver2_path);
715 if (*load)
716 return ZwLoadDriver(&name);
717 else
718 return ZwUnloadDriver(&name);
721 static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
723 IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
725 last_created_file = irpsp->FileObject;
727 irp->IoStatus.Status = STATUS_SUCCESS;
728 IoCompleteRequest(irp, IO_NO_INCREMENT);
729 return STATUS_SUCCESS;
732 static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
734 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
735 NTSTATUS status = STATUS_NOT_SUPPORTED;
737 switch (stack->Parameters.DeviceIoControl.IoControlCode)
739 case IOCTL_WINETEST_BASIC_IOCTL:
740 status = test_basic_ioctl(irp, stack, &irp->IoStatus.Information);
741 break;
742 case IOCTL_WINETEST_MAIN_TEST:
743 status = main_test(device, irp, stack, &irp->IoStatus.Information);
744 break;
745 case IOCTL_WINETEST_LOAD_DRIVER:
746 status = test_load_driver_ioctl(irp, stack, &irp->IoStatus.Information);
747 break;
748 default:
749 break;
752 irp->IoStatus.Status = status;
753 IoCompleteRequest(irp, IO_NO_INCREMENT);
754 return status;
757 static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
759 irp->IoStatus.Status = STATUS_SUCCESS;
760 IoCompleteRequest(irp, IO_NO_INCREMENT);
761 return STATUS_SUCCESS;
764 static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
766 UNICODE_STRING linkW;
768 DbgPrint("unloading driver\n");
770 RtlInitUnicodeString(&linkW, driver_link);
771 IoDeleteSymbolicLink(&linkW);
773 IoDeleteDevice(driver->DeviceObject);
776 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
778 UNICODE_STRING nameW, linkW;
779 DEVICE_OBJECT *device;
780 NTSTATUS status;
782 DbgPrint("loading driver\n");
784 /* Allow unloading of the driver */
785 driver->DriverUnload = driver_Unload;
787 /* Set driver functions */
788 driver->MajorFunction[IRP_MJ_CREATE] = driver_Create;
789 driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl;
790 driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
792 RtlInitUnicodeString(&nameW, driver_device);
793 RtlInitUnicodeString(&linkW, driver_link);
795 if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
796 FILE_DEVICE_SECURE_OPEN, FALSE, &device)))
797 status = IoCreateSymbolicLink(&linkW, &nameW);
799 return status;