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
26 #define WIN32_NO_STATUS
31 #include "ddk/ntddk.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};
42 static LONG successes
;
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];
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
, ...)
67 __ms_va_start(valist
, format
);
68 kvprintf(format
, 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
, '\\')))
86 kprintf("%s:%d: Test succeeded inside todo block: ", current_file
, line
);
88 InterlockedIncrement(&todo_failures
);
92 if (winetest_debug
> 0)
94 kprintf("%s:%d: Test marked todo: ", current_file
, line
);
97 InterlockedIncrement(&todo_successes
);
104 kprintf("%s:%d: Test failed: ", current_file
, line
);
106 InterlockedIncrement(&failures
);
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
, ...)
120 __ms_va_start(args
, msg
);
121 vok_(file
, line
, condition
, msg
, 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
, '\\')))
135 kprintf("%s:%d: Tests skipped: ", current_file
, line
);
140 void WINAPIV
win_skip_(const char *file
, int line
, const char *msg
, ...)
143 __ms_va_start(args
, msg
);
144 if (running_under_wine
)
145 vok_(file
, line
, 0, msg
, args
);
147 vskip_(file
, line
, msg
, args
);
151 static void winetest_start_todo( int is_todo
)
153 todo_level
= (todo_level
<< 1) | (is_todo
!= 0);
157 static int winetest_loop_todo(void)
159 int do_loop
=todo_do_loop
;
164 static void winetest_end_todo(void)
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(); \
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
;
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
);
194 static void test_currentprocess(void)
198 current
= IoGetCurrentProcess();
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";
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
);
228 ok(addr
!= NULL
, "MmMapLockedPagesSpecifyCache failed\n");
230 /* MmUnmapLockedPages(addr, 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)
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};
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
;
327 LARGE_INTEGER timeout
;
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
);
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);
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
);
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*);
577 pKeExpandKernelStackAndCallout
= get_proc_address("KeExpandKernelStackAndCallout");
578 if (pKeExpandKernelStackAndCallout
)
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
)
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
);
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
;
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
;
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();
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
);
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
;
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
;
710 return STATUS_ACCESS_VIOLATION
;
714 RtlInitUnicodeString(&name
, driver2_path
);
716 return ZwLoadDriver(&name
);
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
);
742 case IOCTL_WINETEST_MAIN_TEST
:
743 status
= main_test(device
, irp
, stack
, &irp
->IoStatus
.Information
);
745 case IOCTL_WINETEST_LOAD_DRIVER
:
746 status
= test_load_driver_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
752 irp
->IoStatus
.Status
= status
;
753 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
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
;
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
);