ntoskrnl: Make the standard C functions available for importing.
[wine.git] / dlls / ntoskrnl.exe / tests / driver.c
blobdbe189da8129acfe75e3b51e4a28345d3fa09419
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>
24 #include <stdio.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winternl.h"
31 #include "winioctl.h"
32 #include "ddk/ntddk.h"
33 #include "ddk/ntifs.h"
34 #include "ddk/wdm.h"
36 #include "driver.h"
38 static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
39 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
40 static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
41 '\\','W','i','n','e','T','e','s','t','U','p','p','e','r',0};
42 static const WCHAR driver_link[] = {'\\','D','o','s','D','e','v','i','c','e','s',
43 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
45 static DRIVER_OBJECT *driver_obj;
46 static DEVICE_OBJECT *lower_device, *upper_device;
48 static HANDLE okfile;
49 static LONG successes;
50 static LONG failures;
51 static LONG skipped;
52 static LONG todo_successes;
53 static LONG todo_failures;
54 static int todo_level, todo_do_loop;
55 static int running_under_wine;
56 static int winetest_debug;
57 static int winetest_report_success;
59 static POBJECT_TYPE *pExEventObjectType, *pIoFileObjectType, *pPsThreadType;
60 static PEPROCESS *pPsInitialSystemProcess;
61 static void *create_caller_thread;
63 void WINAPI ObfReferenceObject( void *obj );
65 NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
67 static void kvprintf(const char *format, __ms_va_list ap)
69 static char buffer[512];
70 IO_STATUS_BLOCK io;
71 int len = vsnprintf(buffer, sizeof(buffer), format, ap);
72 ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL);
75 static void WINAPIV kprintf(const char *format, ...)
77 __ms_va_list valist;
79 __ms_va_start(valist, format);
80 kvprintf(format, valist);
81 __ms_va_end(valist);
84 static void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args)
86 const char *current_file;
88 if (!(current_file = drv_strrchr(file, '/')) &&
89 !(current_file = drv_strrchr(file, '\\')))
90 current_file = file;
91 else
92 current_file++;
94 if (todo_level)
96 if (condition)
98 kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line);
99 kvprintf(msg, args);
100 InterlockedIncrement(&todo_failures);
102 else
104 if (winetest_debug > 0)
106 kprintf("%s:%d: Test marked todo: ", current_file, line);
107 kvprintf(msg, args);
109 InterlockedIncrement(&todo_successes);
112 else
114 if (!condition)
116 kprintf("%s:%d: Test failed: ", current_file, line);
117 kvprintf(msg, args);
118 InterlockedIncrement(&failures);
120 else
122 if (winetest_report_success)
123 kprintf("%s:%d: Test succeeded\n", current_file, line);
124 InterlockedIncrement(&successes);
129 static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...)
131 __ms_va_list args;
132 __ms_va_start(args, msg);
133 vok_(file, line, condition, msg, args);
134 __ms_va_end(args);
137 static void vskip_(const char *file, int line, const char *msg, __ms_va_list args)
139 const char *current_file;
141 if (!(current_file = drv_strrchr(file, '/')) &&
142 !(current_file = drv_strrchr(file, '\\')))
143 current_file = file;
144 else
145 current_file++;
147 kprintf("%s:%d: Tests skipped: ", current_file, line);
148 kvprintf(msg, args);
149 skipped++;
152 static void WINAPIV win_skip_(const char *file, int line, const char *msg, ...)
154 __ms_va_list args;
155 __ms_va_start(args, msg);
156 if (running_under_wine)
157 vok_(file, line, 0, msg, args);
158 else
159 vskip_(file, line, msg, args);
160 __ms_va_end(args);
163 static void winetest_start_todo( int is_todo )
165 todo_level = (todo_level << 1) | (is_todo != 0);
166 todo_do_loop=1;
169 static int winetest_loop_todo(void)
171 int do_loop=todo_do_loop;
172 todo_do_loop=0;
173 return do_loop;
176 static void winetest_end_todo(void)
178 todo_level >>= 1;
181 static int broken(int condition)
183 return !running_under_wine && condition;
186 #define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__)
187 #define todo_if(is_todo) for (winetest_start_todo(is_todo); \
188 winetest_loop_todo(); \
189 winetest_end_todo())
190 #define todo_wine todo_if(running_under_wine)
191 #define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine)
192 #define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__)
194 static void *get_proc_address(const char *name)
196 UNICODE_STRING name_u;
197 ANSI_STRING name_a;
198 NTSTATUS status;
199 void *ret;
201 RtlInitAnsiString(&name_a, name);
202 status = RtlAnsiStringToUnicodeString(&name_u, &name_a, TRUE);
203 ok (!status, "RtlAnsiStringToUnicodeString failed: %#x\n", status);
204 if (status) return NULL;
206 ret = MmGetSystemRoutineAddress(&name_u);
207 RtlFreeUnicodeString(&name_u);
208 return ret;
211 static FILE_OBJECT *last_created_file;
213 static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device)
215 IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
217 ok(device == upper_device, "Expected device %p, got %p.\n", upper_device, device);
218 ok(last_created_file != NULL, "last_created_file = NULL\n");
219 ok(irpsp->FileObject == last_created_file, "FileObject != last_created_file\n");
220 ok(irpsp->DeviceObject == upper_device, "unexpected DeviceObject\n");
221 ok(irpsp->FileObject->DeviceObject == lower_device, "unexpected FileObject->DeviceObject\n");
222 ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
223 ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
224 "IRP thread is not the current thread\n");
227 static void test_mdl_map(void)
229 char buffer[20] = "test buffer";
230 void *addr;
231 MDL *mdl;
233 mdl = IoAllocateMdl(buffer, sizeof(buffer), FALSE, FALSE, NULL);
234 ok(mdl != NULL, "IoAllocateMdl failed\n");
236 MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
238 addr = MmMapLockedPagesSpecifyCache(mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
239 todo_wine
240 ok(addr != NULL, "MmMapLockedPagesSpecifyCache failed\n");
242 MmUnmapLockedPages(addr, mdl);
244 IoFreeMdl(mdl);
247 static void test_init_funcs(void)
249 KTIMER timer, timer2;
251 KeInitializeTimerEx(&timer, NotificationTimer);
252 ok(timer.Header.Type == 8, "got: %u\n", timer.Header.Type);
253 ok(timer.Header.Size == 0 || timer.Header.Size == 10, "got: %u\n", timer.Header.Size);
254 ok(timer.Header.SignalState == 0, "got: %u\n", timer.Header.SignalState);
256 KeInitializeTimerEx(&timer2, SynchronizationTimer);
257 ok(timer2.Header.Type == 9, "got: %u\n", timer2.Header.Type);
258 ok(timer2.Header.Size == 0 || timer2.Header.Size == 10, "got: %u\n", timer2.Header.Size);
259 ok(timer2.Header.SignalState == 0, "got: %u\n", timer2.Header.SignalState);
262 static const WCHAR driver2_path[] = {
263 '\\','R','e','g','i','s','t','r','y',
264 '\\','M','a','c','h','i','n','e',
265 '\\','S','y','s','t','e','m',
266 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
267 '\\','S','e','r','v','i','c','e','s',
268 '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r','2',0
271 static void test_load_driver(void)
273 UNICODE_STRING name;
274 NTSTATUS ret;
276 RtlInitUnicodeString(&name, driver2_path);
278 ret = ZwLoadDriver(&name);
279 ok(!ret, "got %#x\n", ret);
281 ret = ZwLoadDriver(&name);
282 ok(ret == STATUS_IMAGE_ALREADY_LOADED, "got %#x\n", ret);
284 ret = ZwUnloadDriver(&name);
285 ok(!ret, "got %#x\n", ret);
288 static NTSTATUS wait_single(void *obj, ULONGLONG timeout)
290 LARGE_INTEGER integer;
292 integer.QuadPart = timeout;
293 return KeWaitForSingleObject(obj, Executive, KernelMode, FALSE, &integer);
296 static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, ULONGLONG timeout)
298 LARGE_INTEGER integer;
300 integer.QuadPart = timeout;
301 return KeWaitForMultipleObjects(count, objs, wait_type, Executive, KernelMode, FALSE, &integer, NULL);
304 static NTSTATUS wait_single_handle(HANDLE handle, ULONGLONG timeout)
306 LARGE_INTEGER integer;
308 integer.QuadPart = timeout;
309 return ZwWaitForSingleObject(handle, FALSE, &integer);
312 static void test_current_thread(BOOL is_system)
314 PROCESS_BASIC_INFORMATION info;
315 DISPATCHER_HEADER *header;
316 HANDLE process_handle, id;
317 PEPROCESS current;
318 PETHREAD thread;
319 NTSTATUS ret;
321 current = IoGetCurrentProcess();
322 ok(current != NULL, "Expected current process to be non-NULL\n");
324 header = (DISPATCHER_HEADER*)current;
325 ok(header->Type == 3, "header->Type != 3, = %u\n", header->Type);
326 ret = wait_single(current, 0);
327 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
329 if (is_system)
330 ok(current == *pPsInitialSystemProcess, "current != PsInitialSystemProcess\n");
331 else
332 ok(current != *pPsInitialSystemProcess, "current == PsInitialSystemProcess\n");
334 ok(PsGetProcessId(current) == PsGetCurrentProcessId(), "process IDs don't match\n");
335 ok(PsGetThreadProcessId((PETHREAD)KeGetCurrentThread()) == PsGetCurrentProcessId(), "process IDs don't match\n");
337 thread = PsGetCurrentThread();
338 ret = wait_single( thread, 0 );
339 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
341 ok(PsGetThreadId((PETHREAD)KeGetCurrentThread()) == PsGetCurrentThreadId(), "thread IDs don't match\n");
342 ok(PsIsSystemThread((PETHREAD)KeGetCurrentThread()) == is_system, "unexpected system thread\n");
343 if (!is_system)
344 ok(create_caller_thread == KeGetCurrentThread(), "thread is not create caller thread\n");
346 ret = ObOpenObjectByPointer(current, OBJ_KERNEL_HANDLE, NULL, PROCESS_QUERY_INFORMATION, NULL, KernelMode, &process_handle);
347 ok(!ret, "ObOpenObjectByPointer failed: %#x\n", ret);
349 ret = ZwQueryInformationProcess(process_handle, ProcessBasicInformation, &info, sizeof(info), NULL);
350 ok(!ret, "ZwQueryInformationProcess failed: %#x\n", ret);
352 id = PsGetProcessInheritedFromUniqueProcessId(current);
353 ok(id == (HANDLE)info.InheritedFromUniqueProcessId, "unexpected process id %p\n", id);
355 ret = ZwClose(process_handle);
356 ok(!ret, "ZwClose failed: %#x\n", ret);
359 static void test_critical_region(BOOL is_dispatcher)
361 BOOLEAN result;
363 KeEnterCriticalRegion();
364 KeEnterCriticalRegion();
366 result = KeAreApcsDisabled();
367 ok(result == TRUE, "KeAreApcsDisabled returned %x\n", result);
368 KeLeaveCriticalRegion();
370 result = KeAreApcsDisabled();
371 ok(result == TRUE, "KeAreApcsDisabled returned %x\n", result);
372 KeLeaveCriticalRegion();
374 result = KeAreApcsDisabled();
375 ok(result == is_dispatcher || broken(is_dispatcher && !result),
376 "KeAreApcsDisabled returned %x\n", result);
379 static void sleep(void)
381 LARGE_INTEGER timeout;
382 timeout.QuadPart = -20 * 10000;
383 KeDelayExecutionThread( KernelMode, FALSE, &timeout );
386 static HANDLE create_thread(PKSTART_ROUTINE proc, void *arg)
388 OBJECT_ATTRIBUTES attr = {0};
389 HANDLE thread;
390 NTSTATUS ret;
392 attr.Length = sizeof(attr);
393 attr.Attributes = OBJ_KERNEL_HANDLE;
394 ret = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, &attr, NULL, NULL, proc, arg);
395 ok(!ret, "got %#x\n", ret);
397 return thread;
400 static void join_thread(HANDLE thread)
402 NTSTATUS ret;
404 ret = ZwWaitForSingleObject(thread, FALSE, NULL);
405 ok(!ret, "got %#x\n", ret);
406 ret = ZwClose(thread);
407 ok(!ret, "got %#x\n", ret);
410 static void run_thread(PKSTART_ROUTINE proc, void *arg)
412 HANDLE thread = create_thread(proc, arg);
413 join_thread(thread);
416 static KMUTEX test_mutex;
418 static void WINAPI mutex_thread(void *arg)
420 NTSTATUS ret, expect = (NTSTATUS)(DWORD_PTR)arg;
422 ret = wait_single(&test_mutex, 0);
423 ok(ret == expect, "expected %#x, got %#x\n", expect, ret);
425 if (!ret) KeReleaseMutex(&test_mutex, FALSE);
426 PsTerminateSystemThread(STATUS_SUCCESS);
429 static void test_sync(void)
431 KSEMAPHORE semaphore, semaphore2;
432 KEVENT manual_event, auto_event, *event;
433 KTIMER timer;
434 LARGE_INTEGER timeout;
435 OBJECT_ATTRIBUTES attr;
436 void *objs[2];
437 NTSTATUS ret;
438 HANDLE handle;
439 int i;
441 KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
443 ret = wait_single(&manual_event, 0);
444 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
446 KeSetEvent(&manual_event, 0, FALSE);
448 ret = wait_single(&manual_event, 0);
449 ok(ret == 0, "got %#x\n", ret);
451 ret = wait_single(&manual_event, 0);
452 ok(ret == 0, "got %#x\n", ret);
454 KeResetEvent(&manual_event);
456 ret = wait_single(&manual_event, 0);
457 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
459 KeInitializeEvent(&auto_event, SynchronizationEvent, FALSE);
461 ret = wait_single(&auto_event, 0);
462 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
464 KeSetEvent(&auto_event, 0, FALSE);
466 ret = wait_single(&auto_event, 0);
467 ok(ret == 0, "got %#x\n", ret);
469 ret = wait_single(&auto_event, 0);
470 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
472 KeInitializeEvent(&auto_event, SynchronizationEvent, TRUE);
474 ret = wait_single(&auto_event, 0);
475 ok(ret == 0, "got %#x\n", ret);
477 objs[0] = &manual_event;
478 objs[1] = &auto_event;
480 ret = wait_multiple(2, objs, WaitAny, 0);
481 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
483 KeSetEvent(&manual_event, 0, FALSE);
484 KeSetEvent(&auto_event, 0, FALSE);
486 ret = wait_multiple(2, objs, WaitAny, 0);
487 ok(ret == 0, "got %#x\n", ret);
489 ret = wait_single(&auto_event, 0);
490 ok(ret == 0, "got %#x\n", ret);
492 KeResetEvent(&manual_event);
493 KeSetEvent(&auto_event, 0, FALSE);
495 ret = wait_multiple(2, objs, WaitAny, 0);
496 ok(ret == 1, "got %#x\n", ret);
498 ret = wait_multiple(2, objs, WaitAny, 0);
499 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
501 KeSetEvent(&manual_event, 0, FALSE);
502 KeSetEvent(&auto_event, 0, FALSE);
504 ret = wait_multiple(2, objs, WaitAll, 0);
505 ok(ret == 0, "got %#x\n", ret);
507 ret = wait_multiple(2, objs, WaitAll, 0);
508 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
510 KeSetEvent(&auto_event, 0, FALSE);
511 KeResetEvent(&manual_event);
513 ret = wait_multiple(2, objs, WaitAll, 0);
514 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
516 ret = wait_single(&auto_event, 0);
517 ok(ret == 0, "got %#x\n", ret);
519 objs[0] = &auto_event;
520 objs[1] = &manual_event;
521 KeSetEvent(&manual_event, 0, FALSE);
522 KeSetEvent(&auto_event, 0, FALSE);
524 ret = wait_multiple(2, objs, WaitAny, 0);
525 ok(ret == 0, "got %#x\n", ret);
527 ret = wait_multiple(2, objs, WaitAny, 0);
528 ok(ret == 1, "got %#x\n", ret);
530 ret = wait_multiple(2, objs, WaitAny, 0);
531 ok(ret == 1, "got %#x\n", ret);
533 InitializeObjectAttributes(&attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
534 ret = ZwCreateEvent(&handle, SYNCHRONIZE, &attr, NotificationEvent, TRUE);
535 ok(!ret, "ZwCreateEvent failed: %#x\n", ret);
537 ret = ObReferenceObjectByHandle(handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, (void **)&event, NULL);
538 ok(!ret, "ObReferenceObjectByHandle failed: %#x\n", ret);
540 ret = wait_single(event, 0);
541 ok(ret == 0, "got %#x\n", ret);
542 KeResetEvent(event);
543 ret = wait_single(event, 0);
544 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
545 ret = wait_single_handle(handle, 0);
546 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
548 KeSetEvent(event, 0, FALSE);
549 ret = wait_single(event, 0);
550 ok(ret == 0, "got %#x\n", ret);
551 ret = wait_single_handle(handle, 0);
552 ok(!ret, "got %#x\n", ret);
554 ZwClose(handle);
555 ObDereferenceObject(event);
557 event = IoCreateSynchronizationEvent(NULL, &handle);
558 ok(event != NULL, "IoCreateSynchronizationEvent failed\n");
560 ret = wait_single(event, 0);
561 ok(ret == 0, "got %#x\n", ret);
562 KeResetEvent(event);
563 ret = wait_single(event, 0);
564 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
565 ret = wait_single_handle(handle, 0);
566 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
568 ret = ZwSetEvent(handle, NULL);
569 ok(!ret, "NtSetEvent returned %#x\n", ret);
570 ret = wait_single(event, 0);
571 ok(ret == 0, "got %#x\n", ret);
572 ret = wait_single_handle(handle, 0);
573 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
575 KeSetEvent(event, 0, FALSE);
576 ret = wait_single_handle(handle, 0);
577 ok(!ret, "got %#x\n", ret);
578 ret = wait_single(event, 0);
579 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
581 ret = ZwClose(handle);
582 ok(!ret, "ZwClose returned %#x\n", ret);
584 /* test semaphores */
585 KeInitializeSemaphore(&semaphore, 0, 5);
587 ret = wait_single(&semaphore, 0);
588 ok(ret == STATUS_TIMEOUT, "got %u\n", ret);
590 ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
591 ok(ret == 0, "got prev %d\n", ret);
593 ret = KeReleaseSemaphore(&semaphore, 0, 2, FALSE);
594 ok(ret == 1, "got prev %d\n", ret);
596 ret = KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
597 ok(ret == 3, "got prev %d\n", ret);
599 for (i = 0; i < 4; i++)
601 ret = wait_single(&semaphore, 0);
602 ok(ret == 0, "got %#x\n", ret);
605 ret = wait_single(&semaphore, 0);
606 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
608 KeInitializeSemaphore(&semaphore2, 3, 5);
610 ret = KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
611 ok(ret == 3, "got prev %d\n", ret);
613 for (i = 0; i < 4; i++)
615 ret = wait_single(&semaphore2, 0);
616 ok(ret == 0, "got %#x\n", ret);
619 objs[0] = &semaphore;
620 objs[1] = &semaphore2;
622 ret = wait_multiple(2, objs, WaitAny, 0);
623 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
625 KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
626 KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
628 ret = wait_multiple(2, objs, WaitAny, 0);
629 ok(ret == 0, "got %#x\n", ret);
631 ret = wait_multiple(2, objs, WaitAny, 0);
632 ok(ret == 1, "got %#x\n", ret);
634 ret = wait_multiple(2, objs, WaitAny, 0);
635 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
637 KeReleaseSemaphore(&semaphore, 0, 1, FALSE);
638 KeReleaseSemaphore(&semaphore2, 0, 1, FALSE);
640 ret = wait_multiple(2, objs, WaitAll, 0);
641 ok(ret == 0, "got %#x\n", ret);
643 ret = wait_multiple(2, objs, WaitAny, 0);
644 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
646 /* test mutexes */
647 KeInitializeMutex(&test_mutex, 0);
649 for (i = 0; i < 10; i++)
651 ret = wait_single(&test_mutex, 0);
652 ok(ret == 0, "got %#x\n", ret);
655 for (i = 0; i < 10; i++)
657 ret = KeReleaseMutex(&test_mutex, FALSE);
658 ok(ret == i - 9, "expected %d, got %d\n", i - 9, ret);
661 run_thread(mutex_thread, (void *)0);
663 ret = wait_single(&test_mutex, 0);
664 ok(ret == 0, "got %#x\n", ret);
666 run_thread(mutex_thread, (void *)STATUS_TIMEOUT);
668 ret = KeReleaseMutex(&test_mutex, 0);
669 ok(ret == 0, "got %#x\n", ret);
671 run_thread(mutex_thread, (void *)0);
673 /* test timers */
674 KeInitializeTimerEx(&timer, NotificationTimer);
676 timeout.QuadPart = -20 * 10000;
677 KeSetTimerEx(&timer, timeout, 0, NULL);
679 ret = wait_single(&timer, 0);
680 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
682 ret = wait_single(&timer, -40 * 10000);
683 ok(ret == 0, "got %#x\n", ret);
685 ret = wait_single(&timer, 0);
686 ok(ret == 0, "got %#x\n", ret);
688 KeCancelTimer(&timer);
689 KeInitializeTimerEx(&timer, SynchronizationTimer);
691 KeSetTimerEx(&timer, timeout, 0, NULL);
693 ret = wait_single(&timer, 0);
694 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
696 ret = wait_single(&timer, -40 * 10000);
697 ok(ret == 0, "got %#x\n", ret);
699 ret = wait_single(&timer, -40 * 10000);
700 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
702 KeCancelTimer(&timer);
703 KeSetTimerEx(&timer, timeout, 20, NULL);
705 ret = wait_single(&timer, 0);
706 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
708 ret = wait_single(&timer, -40 * 10000);
709 ok(ret == 0, "got %#x\n", ret);
711 ret = wait_single(&timer, 0);
712 ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
714 ret = wait_single(&timer, -40 * 10000);
715 ok(ret == 0, "got %#x\n", ret);
717 ret = wait_single(&timer, -40 * 10000);
718 ok(ret == 0, "got %#x\n", ret);
720 KeCancelTimer(&timer);
723 static void test_call_driver(DEVICE_OBJECT *device)
725 IO_STACK_LOCATION *irpsp;
726 IO_STATUS_BLOCK iosb;
727 IRP *irp = NULL;
728 KEVENT event;
729 NTSTATUS status;
731 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
732 ok(irp->UserIosb == &iosb, "unexpected UserIosb\n");
733 ok(!irp->Cancel, "Cancel = %x\n", irp->Cancel);
734 ok(!irp->CancelRoutine, "CancelRoutine = %x\n", irp->CancelRoutine);
735 ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
736 ok(irp->CurrentLocation == 2, "CurrentLocation = %u\n", irp->CurrentLocation);
737 ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
738 "IRP thread is not the current thread\n");
740 irpsp = IoGetNextIrpStackLocation(irp);
741 ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
742 ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
743 ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
744 ok(!irpsp->CompletionRoutine, "CompletionRouptine = %p\n", irpsp->CompletionRoutine);
746 status = IoCallDriver(device, irp);
747 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
749 irp->IoStatus.Status = STATUS_SUCCESS;
750 irp->IoStatus.Information = 0;
751 IoCompleteRequest(irp, IO_NO_INCREMENT);
753 KeInitializeEvent(&event, NotificationEvent, FALSE);
755 irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &event, &iosb);
756 ok(irp->UserIosb == &iosb, "unexpected UserIosb\n");
757 ok(!irp->Cancel, "Cancel = %x\n", irp->Cancel);
758 ok(!irp->CancelRoutine, "CancelRoutine = %x\n", irp->CancelRoutine);
759 ok(irp->UserEvent == &event, "UserEvent = %p\n", irp->UserEvent);
760 ok(irp->CurrentLocation == 2, "CurrentLocation = %u\n", irp->CurrentLocation);
761 ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
762 "IRP thread is not the current thread\n");
764 irpsp = IoGetNextIrpStackLocation(irp);
765 ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
766 ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
767 ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
768 ok(!irpsp->CompletionRoutine, "CompletionRouptine = %p\n", irpsp->CompletionRoutine);
770 status = wait_single(&event, 0);
771 ok(status == STATUS_TIMEOUT, "got %#x\n", status);
773 status = IoCallDriver(device, irp);
774 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
776 status = wait_single(&event, 0);
777 ok(status == STATUS_TIMEOUT, "got %#x\n", status);
779 irp->IoStatus.Status = STATUS_SUCCESS;
780 irp->IoStatus.Information = 0;
781 IoCompleteRequest(irp, IO_NO_INCREMENT);
783 status = wait_single(&event, 0);
784 ok(status == STATUS_SUCCESS, "got %#x\n", status);
787 static int cancel_cnt;
789 static void WINAPI cancel_irp(DEVICE_OBJECT *device, IRP *irp)
791 IoReleaseCancelSpinLock(irp->CancelIrql);
792 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
793 ok(!irp->CancelRoutine, "CancelRoutine = %p\n", irp->CancelRoutine);
794 irp->IoStatus.Status = STATUS_CANCELLED;
795 irp->IoStatus.Information = 0;
796 cancel_cnt++;
799 static void WINAPI cancel_ioctl_irp(DEVICE_OBJECT *device, IRP *irp)
801 IoReleaseCancelSpinLock(irp->CancelIrql);
802 irp->IoStatus.Status = STATUS_CANCELLED;
803 irp->IoStatus.Information = 0;
804 cancel_cnt++;
805 IoCompleteRequest(irp, IO_NO_INCREMENT);
808 static NTSTATUS WINAPI cancel_test_completion(DEVICE_OBJECT *device, IRP *irp, void *context)
810 ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
811 *(BOOL*)context = TRUE;
812 return STATUS_SUCCESS;
815 static void test_cancel_irp(DEVICE_OBJECT *device)
817 IO_STACK_LOCATION *irpsp;
818 IO_STATUS_BLOCK iosb;
819 IRP *irp = NULL;
820 BOOL completion_called;
821 BOOLEAN r;
822 NTSTATUS status;
824 /* cancel IRP with no cancel routine */
825 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
827 r = IoCancelIrp(irp);
828 ok(!r, "IoCancelIrp returned %x\n", r);
829 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
831 r = IoCancelIrp(irp);
832 ok(!r, "IoCancelIrp returned %x\n", r);
833 IoFreeIrp(irp);
835 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
837 /* cancel IRP with cancel routine */
838 status = IoCallDriver(device, irp);
839 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
841 ok(irp->CurrentLocation == 1, "CurrentLocation = %u\n", irp->CurrentLocation);
842 irpsp = IoGetCurrentIrpStackLocation(irp);
843 ok(irpsp->DeviceObject == device, "DeviceObject = %u\n", irpsp->DeviceObject);
845 IoSetCancelRoutine(irp, cancel_irp);
846 cancel_cnt = 0;
847 r = IoCancelIrp(irp);
848 ok(r == TRUE, "IoCancelIrp returned %x\n", r);
849 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
850 ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
852 cancel_cnt = 0;
853 r = IoCancelIrp(irp);
854 ok(!r, "IoCancelIrp returned %x\n", r);
855 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
856 ok(!cancel_cnt, "cancel_cnt = %d\n", cancel_cnt);
858 IoCompleteRequest(irp, IO_NO_INCREMENT);
860 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_ERROR */
861 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
862 IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, FALSE, TRUE);
864 status = IoCallDriver(device, irp);
865 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
867 IoSetCancelRoutine(irp, cancel_irp);
868 cancel_cnt = 0;
869 r = IoCancelIrp(irp);
870 ok(r == TRUE, "IoCancelIrp returned %x\n", r);
871 ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
872 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
874 completion_called = FALSE;
875 IoCompleteRequest(irp, IO_NO_INCREMENT);
876 ok(completion_called, "completion not called\n");
878 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_CANCEL flag */
879 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
880 IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, TRUE, FALSE);
882 status = IoCallDriver(device, irp);
883 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
885 IoSetCancelRoutine(irp, cancel_irp);
886 cancel_cnt = 0;
887 r = IoCancelIrp(irp);
888 ok(r == TRUE, "IoCancelIrp returned %x\n", r);
889 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
890 ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
892 completion_called = FALSE;
893 IoCompleteRequest(irp, IO_NO_INCREMENT);
894 ok(completion_called, "completion not called\n");
896 /* cancel IRP with cancel and completion routines, but no SL_INVOKE_ON_ERROR nor SL_INVOKE_ON_CANCEL flag */
897 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
898 IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, FALSE, FALSE);
900 status = IoCallDriver(device, irp);
901 ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
903 IoSetCancelRoutine(irp, cancel_irp);
904 cancel_cnt = 0;
905 r = IoCancelIrp(irp);
906 ok(r == TRUE, "IoCancelIrp returned %x\n", r);
907 ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
908 ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
910 completion_called = FALSE;
911 IoCompleteRequest(irp, IO_NO_INCREMENT);
912 ok(!completion_called, "completion not called\n");
915 static int callout_cnt;
917 static void WINAPI callout(void *parameter)
919 ok(parameter == (void*)0xdeadbeef, "parameter = %p\n", parameter);
920 callout_cnt++;
923 static void test_stack_callout(void)
925 NTSTATUS (WINAPI *pKeExpandKernelStackAndCallout)(PEXPAND_STACK_CALLOUT,void*,SIZE_T);
926 NTSTATUS (WINAPI *pKeExpandKernelStackAndCalloutEx)(PEXPAND_STACK_CALLOUT,void*,SIZE_T,BOOLEAN,void*);
927 NTSTATUS ret;
929 pKeExpandKernelStackAndCallout = get_proc_address("KeExpandKernelStackAndCallout");
930 if (pKeExpandKernelStackAndCallout)
932 callout_cnt = 0;
933 ret = pKeExpandKernelStackAndCallout(callout, (void*)0xdeadbeef, 4096);
934 ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCallout failed: %#x\n", ret);
935 ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt);
937 else win_skip("KeExpandKernelStackAndCallout is not available\n");
939 pKeExpandKernelStackAndCalloutEx = get_proc_address("KeExpandKernelStackAndCalloutEx");
940 if (pKeExpandKernelStackAndCalloutEx)
942 callout_cnt = 0;
943 ret = pKeExpandKernelStackAndCalloutEx(callout, (void*)0xdeadbeef, 4096, FALSE, NULL);
944 ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCalloutEx failed: %#x\n", ret);
945 ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt);
947 else win_skip("KeExpandKernelStackAndCalloutEx is not available\n");
950 static void test_lookaside_list(void)
952 NPAGED_LOOKASIDE_LIST list;
953 ULONG tag = 0x454e4957; /* WINE */
955 ExInitializeNPagedLookasideList(&list, NULL, NULL, POOL_NX_ALLOCATION, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 0);
956 ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth);
957 ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth);
958 ok(list.L.TotalAllocates == 0, "Expected 0 got %u\n", list.L.TotalAllocates);
959 ok(list.L.AllocateMisses == 0, "Expected 0 got %u\n", list.L.AllocateMisses);
960 ok(list.L.TotalFrees == 0, "Expected 0 got %u\n", list.L.TotalFrees);
961 ok(list.L.FreeMisses == 0, "Expected 0 got %u\n", list.L.FreeMisses);
962 ok(list.L.Type == (NonPagedPool|POOL_NX_ALLOCATION),
963 "Expected NonPagedPool|POOL_NX_ALLOCATION got %u\n", list.L.Type);
964 ok(list.L.Tag == tag, "Expected %x got %x\n", tag, list.L.Tag);
965 ok(list.L.Size == LOOKASIDE_MINIMUM_BLOCK_SIZE,
966 "Expected %u got %u\n", LOOKASIDE_MINIMUM_BLOCK_SIZE, list.L.Size);
967 ok(list.L.LastTotalAllocates == 0,"Expected 0 got %u\n", list.L.LastTotalAllocates);
968 ok(list.L.LastAllocateMisses == 0,"Expected 0 got %u\n", list.L.LastAllocateMisses);
969 ExDeleteNPagedLookasideList(&list);
971 list.L.Depth = 0;
972 ExInitializeNPagedLookasideList(&list, NULL, NULL, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE, tag, 20);
973 ok(list.L.Depth == 4, "Expected 4 got %u\n", list.L.Depth);
974 ok(list.L.MaximumDepth == 256, "Expected 256 got %u\n", list.L.MaximumDepth);
975 ok(list.L.Type == NonPagedPool, "Expected NonPagedPool got %u\n", list.L.Type);
976 ExDeleteNPagedLookasideList(&list);
979 static void test_version(void)
981 USHORT *pNtBuildNumber;
982 ULONG build;
984 pNtBuildNumber = get_proc_address("NtBuildNumber");
985 ok(!!pNtBuildNumber, "Could not get pointer to NtBuildNumber\n");
987 PsGetVersion(NULL, NULL, &build, NULL);
988 ok(*pNtBuildNumber == build, "Expected build number %u, got %u\n", build, *pNtBuildNumber);
991 static void WINAPI thread_proc(void *arg)
993 PsTerminateSystemThread(STATUS_SUCCESS);
996 static void test_ob_reference(const WCHAR *test_path)
998 POBJECT_TYPE (WINAPI *pObGetObjectType)(void*);
999 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
1000 HANDLE event_handle, file_handle, file_handle2, thread_handle, handle;
1001 DISPATCHER_HEADER *header;
1002 FILE_OBJECT *file;
1003 void *obj1, *obj2;
1004 POBJECT_TYPE obj1_type;
1005 UNICODE_STRING pathU;
1006 IO_STATUS_BLOCK io;
1007 WCHAR *tmp_path;
1008 SIZE_T len;
1009 NTSTATUS status;
1011 static const WCHAR tmpW[] = {'.','t','m','p',0};
1013 pObGetObjectType = get_proc_address("ObGetObjectType");
1014 if (!pObGetObjectType)
1015 win_skip("ObGetObjectType not found\n");
1017 InitializeObjectAttributes(&attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
1018 status = ZwCreateEvent(&event_handle, SYNCHRONIZE, &attr, NotificationEvent, TRUE);
1019 ok(!status, "ZwCreateEvent failed: %#x\n", status);
1021 len = wcslen(test_path);
1022 tmp_path = ExAllocatePool(PagedPool, len * sizeof(WCHAR) + sizeof(tmpW));
1023 memcpy(tmp_path, test_path, len * sizeof(WCHAR));
1024 memcpy(tmp_path + len, tmpW, sizeof(tmpW));
1026 RtlInitUnicodeString(&pathU, tmp_path);
1027 attr.ObjectName = &pathU;
1028 attr.Attributes = OBJ_KERNEL_HANDLE;
1029 status = ZwCreateFile(&file_handle, DELETE | FILE_WRITE_DATA | SYNCHRONIZE, &attr, &io, NULL, 0, 0, FILE_CREATE,
1030 FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
1031 ok(!status, "ZwCreateFile failed: %#x\n", status);
1032 ExFreePool(tmp_path);
1034 status = ZwDuplicateObject(NtCurrentProcess(), file_handle, NtCurrentProcess(), &file_handle2,
1035 0, OBJ_KERNEL_HANDLE, DUPLICATE_SAME_ACCESS);
1036 ok(!status, "ZwDuplicateObject failed: %#x\n", status);
1038 InitializeObjectAttributes(&attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
1039 status = PsCreateSystemThread(&thread_handle, SYNCHRONIZE, &attr, NULL, NULL, thread_proc, NULL);
1040 ok(!status, "PsCreateSystemThread returned: %#x\n", status);
1042 status = ObReferenceObjectByHandle(NULL, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj1, NULL);
1043 ok(status == STATUS_INVALID_HANDLE, "ObReferenceObjectByHandle failed: %#x\n", status);
1045 status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj1, NULL);
1046 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "ObReferenceObjectByHandle returned: %#x\n", status);
1048 status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj1, NULL);
1049 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1051 if (pObGetObjectType)
1053 obj1_type = pObGetObjectType(obj1);
1054 ok(obj1_type == *pExEventObjectType, "ObGetObjectType returned %p\n", obj1_type);
1057 if (sizeof(void *) != 4) /* avoid dealing with fastcall */
1059 ObfReferenceObject(obj1);
1060 ObDereferenceObject(obj1);
1063 status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj2, NULL);
1064 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "ObReferenceObjectByHandle returned: %#x\n", status);
1066 status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj2, NULL);
1067 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1068 ok(obj1 == obj2, "obj1 != obj2\n");
1070 ObDereferenceObject(obj2);
1072 status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj2, NULL);
1073 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1074 ok(obj1 == obj2, "obj1 != obj2\n");
1076 ObDereferenceObject(obj2);
1077 ObDereferenceObject(obj1);
1079 status = ObReferenceObjectByHandle(file_handle, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj1, NULL);
1080 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1082 status = ObReferenceObjectByHandle(file_handle2, SYNCHRONIZE, *pIoFileObjectType, KernelMode, &obj2, NULL);
1083 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1084 ok(obj1 == obj2, "obj1 != obj2\n");
1086 file = obj1;
1087 ok(file->Type == 5, "Type = %u\n", file->Type);
1089 ObDereferenceObject(obj1);
1090 ObDereferenceObject(obj2);
1092 status = ObReferenceObjectByHandle(thread_handle, SYNCHRONIZE, *pPsThreadType, KernelMode, &obj1, NULL);
1093 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1095 status = ObReferenceObjectByHandle(thread_handle, SYNCHRONIZE, *pPsThreadType, KernelMode, &obj2, NULL);
1096 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1097 ok(obj1 == obj2, "obj1 != obj2\n");
1099 header = obj1;
1100 ok(header->Type == 6, "Type = %u\n", header->Type);
1102 status = wait_single(header, 0);
1103 ok(status == 0 || status == STATUS_TIMEOUT, "got %#x\n", status);
1105 ObDereferenceObject(obj2);
1107 status = ObOpenObjectByPointer(obj1, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &handle);
1108 ok(status == STATUS_SUCCESS, "ObOpenObjectByPointer failed: %#x\n", status);
1110 status = ZwClose(handle);
1111 ok(!status, "ZwClose failed: %#x\n", status);
1113 status = ObReferenceObjectByHandle(thread_handle, SYNCHRONIZE, *pPsThreadType, KernelMode, &obj2, NULL);
1114 ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
1115 ok(obj1 == obj2, "obj1 != obj2\n");
1116 ObDereferenceObject(obj2);
1118 status = ObOpenObjectByPointer(obj1, OBJ_KERNEL_HANDLE, NULL, 0, *pIoFileObjectType, KernelMode, &handle);
1119 ok(status == STATUS_OBJECT_TYPE_MISMATCH, "ObOpenObjectByPointer returned: %#x\n", status);
1121 ObDereferenceObject(obj1);
1123 status = ZwClose(thread_handle);
1124 ok(!status, "ZwClose failed: %#x\n", status);
1126 status = ZwClose(event_handle);
1127 ok(!status, "ZwClose failed: %#x\n", status);
1129 status = ZwClose(file_handle);
1130 ok(!status, "ZwClose failed: %#x\n", status);
1132 status = ZwClose(file_handle2);
1133 ok(!status, "ZwClose failed: %#x\n", status);
1136 static void check_resource_(int line, ERESOURCE *resource, ULONG exclusive_waiters,
1137 ULONG shared_waiters, BOOLEAN exclusive, ULONG shared_count)
1139 BOOLEAN ret;
1140 ULONG count;
1142 count = ExGetExclusiveWaiterCount(resource);
1143 ok_(__FILE__, line, count == exclusive_waiters,
1144 "expected %u exclusive waiters, got %u\n", exclusive_waiters, count);
1145 count = ExGetSharedWaiterCount(resource);
1146 ok_(__FILE__, line, count == shared_waiters,
1147 "expected %u shared waiters, got %u\n", shared_waiters, count);
1148 ret = ExIsResourceAcquiredExclusiveLite(resource);
1149 ok_(__FILE__, line, ret == exclusive,
1150 "expected exclusive %u, got %u\n", exclusive, ret);
1151 count = ExIsResourceAcquiredSharedLite(resource);
1152 ok_(__FILE__, line, count == shared_count,
1153 "expected shared %u, got %u\n", shared_count, count);
1155 #define check_resource(a,b,c,d,e) check_resource_(__LINE__,a,b,c,d,e)
1157 static KEVENT resource_shared_ready, resource_shared_done, resource_exclusive_ready, resource_exclusive_done;
1159 static void WINAPI resource_shared_thread(void *arg)
1161 ERESOURCE *resource = arg;
1162 BOOLEAN ret;
1164 check_resource(resource, 0, 0, FALSE, 0);
1166 ret = ExAcquireResourceSharedLite(resource, TRUE);
1167 ok(ret == TRUE, "got ret %u\n", ret);
1169 check_resource(resource, 0, 0, FALSE, 1);
1171 KeSetEvent(&resource_shared_ready, IO_NO_INCREMENT, FALSE);
1172 KeWaitForSingleObject(&resource_shared_done, Executive, KernelMode, FALSE, NULL);
1174 ExReleaseResourceForThreadLite(resource, (ULONG_PTR)PsGetCurrentThread());
1176 PsTerminateSystemThread(STATUS_SUCCESS);
1179 static void WINAPI resource_exclusive_thread(void *arg)
1181 ERESOURCE *resource = arg;
1182 BOOLEAN ret;
1184 check_resource(resource, 0, 0, FALSE, 0);
1186 ret = ExAcquireResourceExclusiveLite(resource, TRUE);
1187 ok(ret == TRUE, "got ret %u\n", ret);
1189 check_resource(resource, 0, 0, TRUE, 1);
1191 KeSetEvent(&resource_exclusive_ready, IO_NO_INCREMENT, FALSE);
1192 KeWaitForSingleObject(&resource_exclusive_done, Executive, KernelMode, FALSE, NULL);
1194 ExReleaseResourceForThreadLite(resource, (ULONG_PTR)PsGetCurrentThread());
1196 PsTerminateSystemThread(STATUS_SUCCESS);
1199 static void test_resource(void)
1201 ERESOURCE resource;
1202 NTSTATUS status;
1203 BOOLEAN ret;
1204 HANDLE thread, thread2;
1206 memset(&resource, 0xcc, sizeof(resource));
1208 status = ExInitializeResourceLite(&resource);
1209 ok(status == STATUS_SUCCESS, "got status %#x\n", status);
1210 check_resource(&resource, 0, 0, FALSE, 0);
1212 KeEnterCriticalRegion();
1214 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1215 ok(ret == TRUE, "got ret %u\n", ret);
1216 check_resource(&resource, 0, 0, TRUE, 1);
1218 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1219 ok(ret == TRUE, "got ret %u\n", ret);
1220 check_resource(&resource, 0, 0, TRUE, 2);
1222 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1223 ok(ret == TRUE, "got ret %u\n", ret);
1224 check_resource(&resource, 0, 0, TRUE, 3);
1226 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1227 check_resource(&resource, 0, 0, TRUE, 2);
1229 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1230 check_resource(&resource, 0, 0, TRUE, 1);
1232 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1233 check_resource(&resource, 0, 0, FALSE, 0);
1235 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1236 ok(ret == TRUE, "got ret %u\n", ret);
1237 check_resource(&resource, 0, 0, FALSE, 1);
1239 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1240 ok(ret == TRUE, "got ret %u\n", ret);
1241 check_resource(&resource, 0, 0, FALSE, 2);
1243 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1244 ok(ret == FALSE, "got ret %u\n", ret);
1245 check_resource(&resource, 0, 0, FALSE, 2);
1247 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1248 check_resource(&resource, 0, 0, FALSE, 1);
1250 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1251 check_resource(&resource, 0, 0, FALSE, 0);
1253 ret = ExAcquireSharedStarveExclusive(&resource, FALSE);
1254 ok(ret == TRUE, "got ret %u\n", ret);
1255 check_resource(&resource, 0, 0, FALSE, 1);
1257 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1258 check_resource(&resource, 0, 0, FALSE, 0);
1260 ret = ExAcquireSharedWaitForExclusive(&resource, FALSE);
1261 ok(ret == TRUE, "got ret %u\n", ret);
1262 check_resource(&resource, 0, 0, FALSE, 1);
1264 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1265 check_resource(&resource, 0, 0, FALSE, 0);
1267 /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */
1269 KeInitializeEvent(&resource_shared_ready, SynchronizationEvent, FALSE);
1270 KeInitializeEvent(&resource_shared_done, SynchronizationEvent, FALSE);
1271 thread = create_thread(resource_shared_thread, &resource);
1272 KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL);
1273 check_resource(&resource, 0, 0, FALSE, 0);
1275 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1276 ok(ret == FALSE, "got ret %u\n", ret);
1278 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1279 ok(ret == TRUE, "got ret %u\n", ret);
1280 check_resource(&resource, 0, 0, FALSE, 1);
1282 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1283 check_resource(&resource, 0, 0, FALSE, 0);
1285 ret = ExAcquireSharedStarveExclusive(&resource, FALSE);
1286 ok(ret == TRUE, "got ret %u\n", ret);
1287 check_resource(&resource, 0, 0, FALSE, 1);
1289 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1290 check_resource(&resource, 0, 0, FALSE, 0);
1292 ret = ExAcquireSharedWaitForExclusive(&resource, FALSE);
1293 ok(ret == TRUE, "got ret %u\n", ret);
1294 check_resource(&resource, 0, 0, FALSE, 1);
1296 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1297 check_resource(&resource, 0, 0, FALSE, 0);
1299 KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE);
1300 join_thread(thread);
1301 check_resource(&resource, 0, 0, FALSE, 0);
1303 /* Acquire the resource as exclusive, and then spawn a shared thread. */
1305 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1306 ok(ret == TRUE, "got ret %u\n", ret);
1307 check_resource(&resource, 0, 0, TRUE, 1);
1309 thread = create_thread(resource_shared_thread, &resource);
1310 sleep();
1311 check_resource(&resource, 0, 1, TRUE, 1);
1313 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1314 ok(ret == TRUE, "got ret %u\n", ret);
1315 check_resource(&resource, 0, 1, TRUE, 2);
1317 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1318 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1319 KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL);
1320 KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE);
1321 join_thread(thread);
1322 check_resource(&resource, 0, 0, FALSE, 0);
1324 /* Do not acquire the resource ourselves, but spawn an exclusive thread holding it. */
1326 KeInitializeEvent(&resource_exclusive_ready, SynchronizationEvent, FALSE);
1327 KeInitializeEvent(&resource_exclusive_done, SynchronizationEvent, FALSE);
1328 thread = create_thread(resource_exclusive_thread, &resource);
1329 KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL);
1330 check_resource(&resource, 0, 0, FALSE, 0);
1332 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1333 ok(ret == FALSE, "got ret %u\n", ret);
1334 check_resource(&resource, 0, 0, FALSE, 0);
1336 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1337 ok(ret == FALSE, "got ret %u\n", ret);
1338 check_resource(&resource, 0, 0, FALSE, 0);
1340 ret = ExAcquireSharedStarveExclusive(&resource, FALSE);
1341 ok(ret == FALSE, "got ret %u\n", ret);
1342 check_resource(&resource, 0, 0, FALSE, 0);
1344 ret = ExAcquireSharedWaitForExclusive(&resource, FALSE);
1345 ok(ret == FALSE, "got ret %u\n", ret);
1346 check_resource(&resource, 0, 0, FALSE, 0);
1348 KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE);
1349 join_thread(thread);
1350 check_resource(&resource, 0, 0, FALSE, 0);
1352 /* Acquire the resource as shared, and then spawn an exclusive waiter. */
1354 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1355 ok(ret == TRUE, "got ret %u\n", ret);
1356 check_resource(&resource, 0, 0, FALSE, 1);
1358 thread = create_thread(resource_exclusive_thread, &resource);
1359 sleep();
1360 check_resource(&resource, 1, 0, FALSE, 1);
1362 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1363 ok(ret == TRUE, "got ret %u\n", ret);
1364 check_resource(&resource, 1, 0, FALSE, 2);
1365 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1367 ret = ExAcquireSharedStarveExclusive(&resource, FALSE);
1368 ok(ret == TRUE, "got ret %u\n", ret);
1369 check_resource(&resource, 1, 0, FALSE, 2);
1370 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1372 ret = ExAcquireSharedWaitForExclusive(&resource, FALSE);
1373 ok(ret == FALSE, "got ret %u\n", ret);
1374 check_resource(&resource, 1, 0, FALSE, 1);
1376 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1377 KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL);
1378 KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE);
1379 join_thread(thread);
1380 check_resource(&resource, 0, 0, FALSE, 0);
1382 /* Spawn a shared and then exclusive waiter. */
1384 KeInitializeEvent(&resource_shared_ready, SynchronizationEvent, FALSE);
1385 KeInitializeEvent(&resource_shared_done, SynchronizationEvent, FALSE);
1386 thread = create_thread(resource_shared_thread, &resource);
1387 KeWaitForSingleObject(&resource_shared_ready, Executive, KernelMode, FALSE, NULL);
1388 check_resource(&resource, 0, 0, FALSE, 0);
1390 thread2 = create_thread(resource_exclusive_thread, &resource);
1391 sleep();
1392 check_resource(&resource, 1, 0, FALSE, 0);
1394 ret = ExAcquireResourceExclusiveLite(&resource, FALSE);
1395 ok(ret == FALSE, "got ret %u\n", ret);
1396 check_resource(&resource, 1, 0, FALSE, 0);
1398 ret = ExAcquireResourceSharedLite(&resource, FALSE);
1399 ok(ret == FALSE, "got ret %u\n", ret);
1400 check_resource(&resource, 1, 0, FALSE, 0);
1402 ret = ExAcquireSharedStarveExclusive(&resource, FALSE);
1403 ok(ret == TRUE, "got ret %u\n", ret);
1404 check_resource(&resource, 1, 0, FALSE, 1);
1405 ExReleaseResourceForThreadLite(&resource, (ULONG_PTR)PsGetCurrentThread());
1407 ret = ExAcquireSharedWaitForExclusive(&resource, FALSE);
1408 ok(ret == FALSE, "got ret %u\n", ret);
1409 check_resource(&resource, 1, 0, FALSE, 0);
1411 KeSetEvent(&resource_shared_done, IO_NO_INCREMENT, FALSE);
1412 join_thread(thread);
1413 KeWaitForSingleObject(&resource_exclusive_ready, Executive, KernelMode, FALSE, NULL);
1414 KeSetEvent(&resource_exclusive_done, IO_NO_INCREMENT, FALSE);
1415 join_thread(thread2);
1416 check_resource(&resource, 0, 0, FALSE, 0);
1418 KeLeaveCriticalRegion();
1420 status = ExDeleteResourceLite(&resource);
1421 ok(status == STATUS_SUCCESS, "got status %#x\n", status);
1424 static void test_lookup_thread(void)
1426 NTSTATUS status;
1427 PETHREAD thread = NULL;
1429 status = PsLookupThreadByThreadId(PsGetCurrentThreadId(), &thread);
1430 ok(!status, "PsLookupThreadByThreadId failed: %#x\n", status);
1431 ok((PKTHREAD)thread == KeGetCurrentThread(), "thread != KeGetCurrentThread\n");
1432 if (thread) ObDereferenceObject(thread);
1434 status = PsLookupThreadByThreadId(NULL, &thread);
1435 ok(status == STATUS_INVALID_CID || broken(status == STATUS_INVALID_PARAMETER) /* winxp */,
1436 "PsLookupThreadByThreadId returned %#x\n", status);
1439 static void test_IoAttachDeviceToDeviceStack(void)
1441 DEVICE_OBJECT *dev1, *dev2, *dev3, *ret;
1442 NTSTATUS status;
1444 status = IoCreateDevice(driver_obj, 0, NULL, FILE_DEVICE_UNKNOWN,
1445 FILE_DEVICE_SECURE_OPEN, FALSE, &dev1);
1446 ok(status == STATUS_SUCCESS, "IoCreateDevice failed\n");
1447 status = IoCreateDevice(driver_obj, 0, NULL, FILE_DEVICE_UNKNOWN,
1448 FILE_DEVICE_SECURE_OPEN, FALSE, &dev2);
1449 ok(status == STATUS_SUCCESS, "IoCreateDevice failed\n");
1450 status = IoCreateDevice(driver_obj, 0, NULL, FILE_DEVICE_UNKNOWN,
1451 FILE_DEVICE_SECURE_OPEN, FALSE, &dev3);
1452 ok(status == STATUS_SUCCESS, "IoCreateDevice failed\n");
1454 /* TODO: initialize devices properly */
1455 dev1->Flags &= ~DO_DEVICE_INITIALIZING;
1456 dev2->Flags &= ~DO_DEVICE_INITIALIZING;
1458 ret = IoAttachDeviceToDeviceStack(dev2, dev1);
1459 ok(ret == dev1, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret, dev1);
1460 ok(dev1->AttachedDevice == dev2, "dev1->AttachedDevice = %p, expected %p\n",
1461 dev1->AttachedDevice, dev2);
1462 ok(!dev2->AttachedDevice, "dev2->AttachedDevice = %p\n", dev2->AttachedDevice);
1463 ok(dev1->StackSize == 1, "dev1->StackSize = %d\n", dev1->StackSize);
1464 ok(dev2->StackSize == 2, "dev2->StackSize = %d\n", dev2->StackSize);
1466 ret = IoAttachDeviceToDeviceStack(dev3, dev1);
1467 ok(ret == dev2, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret, dev2);
1468 ok(dev1->AttachedDevice == dev2, "dev1->AttachedDevice = %p, expected %p\n",
1469 dev1->AttachedDevice, dev2);
1470 ok(dev2->AttachedDevice == dev3, "dev2->AttachedDevice = %p, expected %p\n",
1471 dev2->AttachedDevice, dev3);
1472 ok(!dev3->AttachedDevice, "dev3->AttachedDevice = %p\n", dev3->AttachedDevice);
1473 ok(dev1->StackSize == 1, "dev1->StackSize = %d\n", dev1->StackSize);
1474 ok(dev2->StackSize == 2, "dev2->StackSize = %d\n", dev2->StackSize);
1475 ok(dev3->StackSize == 3, "dev3->StackSize = %d\n", dev3->StackSize);
1477 IoDetachDevice(dev1);
1478 ok(!dev1->AttachedDevice, "dev1->AttachedDevice = %p\n", dev1->AttachedDevice);
1479 ok(dev2->AttachedDevice == dev3, "dev2->AttachedDevice = %p\n", dev2->AttachedDevice);
1481 IoDetachDevice(dev2);
1482 ok(!dev2->AttachedDevice, "dev2->AttachedDevice = %p\n", dev2->AttachedDevice);
1483 ok(dev1->StackSize == 1, "dev1->StackSize = %d\n", dev1->StackSize);
1484 ok(dev2->StackSize == 2, "dev2->StackSize = %d\n", dev2->StackSize);
1485 ok(dev3->StackSize == 3, "dev3->StackSize = %d\n", dev3->StackSize);
1487 IoDeleteDevice(dev1);
1488 IoDeleteDevice(dev2);
1489 IoDeleteDevice(dev3);
1492 static PIO_WORKITEM main_test_work_item;
1494 static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context)
1496 IRP *irp = context;
1497 void *buffer = irp->AssociatedIrp.SystemBuffer;
1499 IoFreeWorkItem(main_test_work_item);
1500 main_test_work_item = NULL;
1502 test_current_thread(TRUE);
1503 test_critical_region(FALSE);
1504 test_call_driver(device);
1505 test_cancel_irp(device);
1507 /* print process report */
1508 if (winetest_debug)
1510 kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
1511 PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures,
1512 todo_successes, failures + todo_failures,
1513 (failures + todo_failures != 1) ? "failures" : "failure", skipped );
1515 ZwClose(okfile);
1517 *((LONG *)buffer) = failures;
1518 irp->IoStatus.Status = STATUS_SUCCESS;
1519 irp->IoStatus.Information = sizeof(failures);
1520 IoCompleteRequest(irp, IO_NO_INCREMENT);
1523 static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack)
1525 ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
1526 void *buffer = irp->AssociatedIrp.SystemBuffer;
1527 struct test_input *test_input = (struct test_input *)buffer;
1528 OBJECT_ATTRIBUTES attr = {0};
1529 UNICODE_STRING pathU;
1530 IO_STATUS_BLOCK io;
1532 if (!buffer)
1533 return STATUS_ACCESS_VIOLATION;
1534 if (length < sizeof(failures))
1535 return STATUS_BUFFER_TOO_SMALL;
1537 attr.Length = sizeof(attr);
1538 RtlInitUnicodeString(&pathU, test_input->path);
1539 running_under_wine = test_input->running_under_wine;
1540 winetest_debug = test_input->winetest_debug;
1541 winetest_report_success = test_input->winetest_report_success;
1542 attr.ObjectName = &pathU;
1543 attr.Attributes = OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */
1544 ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT);
1546 pExEventObjectType = get_proc_address("ExEventObjectType");
1547 ok(!!pExEventObjectType, "ExEventObjectType not found\n");
1549 pIoFileObjectType = get_proc_address("IoFileObjectType");
1550 ok(!!pIoFileObjectType, "IofileObjectType not found\n");
1552 pPsThreadType = get_proc_address("PsThreadType");
1553 ok(!!pPsThreadType, "IofileObjectType not found\n");
1555 pPsInitialSystemProcess = get_proc_address("PsInitialSystemProcess");
1556 ok(!!pPsInitialSystemProcess, "PsInitialSystemProcess not found\n");
1558 test_irp_struct(irp, device);
1559 test_current_thread(FALSE);
1560 test_critical_region(TRUE);
1561 test_mdl_map();
1562 test_init_funcs();
1563 test_load_driver();
1564 test_sync();
1565 test_version();
1566 test_stack_callout();
1567 test_lookaside_list();
1568 test_ob_reference(test_input->path);
1569 test_resource();
1570 test_lookup_thread();
1571 test_IoAttachDeviceToDeviceStack();
1573 if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
1575 main_test_work_item = IoAllocateWorkItem(lower_device);
1576 ok(main_test_work_item != NULL, "main_test_work_item = NULL\n");
1578 IoQueueWorkItem(main_test_work_item, main_test_task, DelayedWorkQueue, irp);
1579 return STATUS_PENDING;
1582 static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
1584 ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
1585 char *buffer = irp->AssociatedIrp.SystemBuffer;
1587 if (!buffer)
1588 return STATUS_ACCESS_VIOLATION;
1590 if (length < sizeof(teststr))
1591 return STATUS_BUFFER_TOO_SMALL;
1593 memcpy(buffer, teststr, sizeof(teststr));
1594 *info = sizeof(teststr);
1596 return STATUS_SUCCESS;
1599 static NTSTATUS get_cancel_count(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
1601 ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
1602 char *buffer = irp->AssociatedIrp.SystemBuffer;
1604 if (!buffer)
1605 return STATUS_ACCESS_VIOLATION;
1607 if (length < sizeof(DWORD))
1608 return STATUS_BUFFER_TOO_SMALL;
1610 *(DWORD*)buffer = cancel_cnt;
1611 *info = sizeof(DWORD);
1612 return STATUS_SUCCESS;
1615 static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
1617 BOOL *load = irp->AssociatedIrp.SystemBuffer;
1618 UNICODE_STRING name;
1620 if (!load)
1621 return STATUS_ACCESS_VIOLATION;
1623 *info = 0;
1625 RtlInitUnicodeString(&name, driver2_path);
1626 if (*load)
1627 return ZwLoadDriver(&name);
1628 else
1629 return ZwUnloadDriver(&name);
1632 static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
1634 IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
1636 last_created_file = irpsp->FileObject;
1637 create_caller_thread = KeGetCurrentThread();
1639 irp->IoStatus.Status = STATUS_SUCCESS;
1640 IoCompleteRequest(irp, IO_NO_INCREMENT);
1641 return STATUS_SUCCESS;
1644 static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
1646 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
1647 NTSTATUS status = STATUS_NOT_SUPPORTED;
1649 switch (stack->Parameters.DeviceIoControl.IoControlCode)
1651 case IOCTL_WINETEST_BASIC_IOCTL:
1652 status = test_basic_ioctl(irp, stack, &irp->IoStatus.Information);
1653 break;
1654 case IOCTL_WINETEST_MAIN_TEST:
1655 status = main_test(device, irp, stack);
1656 break;
1657 case IOCTL_WINETEST_LOAD_DRIVER:
1658 status = test_load_driver_ioctl(irp, stack, &irp->IoStatus.Information);
1659 break;
1660 case IOCTL_WINETEST_RESET_CANCEL:
1661 cancel_cnt = 0;
1662 status = STATUS_SUCCESS;
1663 break;
1664 case IOCTL_WINETEST_TEST_CANCEL:
1665 IoSetCancelRoutine(irp, cancel_ioctl_irp);
1666 IoMarkIrpPending(irp);
1667 return STATUS_PENDING;
1668 case IOCTL_WINETEST_GET_CANCEL_COUNT:
1669 status = get_cancel_count(irp, stack, &irp->IoStatus.Information);
1670 break;
1671 case IOCTL_WINETEST_DETACH:
1672 IoDetachDevice(lower_device);
1673 status = STATUS_SUCCESS;
1674 break;
1675 default:
1676 break;
1679 if (status != STATUS_PENDING)
1681 irp->IoStatus.Status = status;
1682 IoCompleteRequest(irp, IO_NO_INCREMENT);
1684 else IoMarkIrpPending(irp);
1685 return status;
1688 static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
1690 IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
1691 ok(device == lower_device, "Expected device %p, got %p.\n", lower_device, device);
1692 ok(irpsp->DeviceObject == device, "device != DeviceObject\n");
1693 ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
1694 "IRP thread is not the current thread\n");
1695 IoMarkIrpPending(irp);
1696 return STATUS_PENDING;
1699 static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
1701 irp->IoStatus.Status = STATUS_SUCCESS;
1702 IoCompleteRequest(irp, IO_NO_INCREMENT);
1703 return STATUS_SUCCESS;
1706 static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
1708 UNICODE_STRING linkW;
1710 DbgPrint("unloading driver\n");
1712 RtlInitUnicodeString(&linkW, driver_link);
1713 IoDeleteSymbolicLink(&linkW);
1715 IoDeleteDevice(upper_device);
1716 IoDeleteDevice(lower_device);
1719 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
1721 UNICODE_STRING nameW, linkW;
1722 NTSTATUS status;
1724 DbgPrint("loading driver\n");
1726 driver_obj = driver;
1728 /* Allow unloading of the driver */
1729 driver->DriverUnload = driver_Unload;
1731 /* Set driver functions */
1732 driver->MajorFunction[IRP_MJ_CREATE] = driver_Create;
1733 driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl;
1734 driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
1735 driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
1737 RtlInitUnicodeString(&nameW, device_name);
1738 RtlInitUnicodeString(&linkW, driver_link);
1740 if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
1741 FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device)))
1743 status = IoCreateSymbolicLink(&linkW, &nameW);
1744 lower_device->Flags &= ~DO_DEVICE_INITIALIZING;
1747 if (!status)
1749 RtlInitUnicodeString(&nameW, upper_name);
1751 status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
1752 FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device);
1755 if (!status)
1757 IoAttachDeviceToDeviceStack(upper_device, lower_device);
1758 upper_device->Flags &= ~DO_DEVICE_INITIALIZING;
1761 return status;