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
27 #define WIN32_NO_STATUS
32 #include "ddk/ntddk.h"
33 #include "ddk/ntifs.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
;
49 static LONG successes
;
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];
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
, ...)
79 __ms_va_start(valist
, format
);
80 kvprintf(format
, 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
, '\\')))
98 kprintf("%s:%d: Test succeeded inside todo block: ", current_file
, line
);
100 InterlockedIncrement(&todo_failures
);
104 if (winetest_debug
> 0)
106 kprintf("%s:%d: Test marked todo: ", current_file
, line
);
109 InterlockedIncrement(&todo_successes
);
116 kprintf("%s:%d: Test failed: ", current_file
, line
);
118 InterlockedIncrement(&failures
);
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
, ...)
132 __ms_va_start(args
, msg
);
133 vok_(file
, line
, condition
, msg
, 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
, '\\')))
147 kprintf("%s:%d: Tests skipped: ", current_file
, line
);
152 static void WINAPIV
win_skip_(const char *file
, int line
, const char *msg
, ...)
155 __ms_va_start(args
, msg
);
156 if (running_under_wine
)
157 vok_(file
, line
, 0, msg
, args
);
159 vskip_(file
, line
, msg
, args
);
163 static void winetest_start_todo( int is_todo
)
165 todo_level
= (todo_level
<< 1) | (is_todo
!= 0);
169 static int winetest_loop_todo(void)
171 int do_loop
=todo_do_loop
;
176 static void winetest_end_todo(void)
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(); \
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
;
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
);
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";
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
);
240 ok(addr
!= NULL
, "MmMapLockedPagesSpecifyCache failed\n");
242 MmUnmapLockedPages(addr
, 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)
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
;
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
);
330 ok(current
== *pPsInitialSystemProcess
, "current != PsInitialSystemProcess\n");
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");
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
)
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};
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
);
400 static void join_thread(HANDLE thread
)
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
);
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
;
434 LARGE_INTEGER timeout
;
435 OBJECT_ATTRIBUTES attr
;
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
);
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
);
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
);
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
);
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);
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
;
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;
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;
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
;
820 BOOL completion_called
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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*);
929 pKeExpandKernelStackAndCallout
= get_proc_address("KeExpandKernelStackAndCallout");
930 if (pKeExpandKernelStackAndCallout
)
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
)
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
);
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
;
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
;
1004 POBJECT_TYPE obj1_type
;
1005 UNICODE_STRING pathU
;
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");
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");
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
)
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
;
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
;
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)
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
);
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
);
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
);
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)
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
;
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
)
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 */
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
);
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
;
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
);
1566 test_stack_callout();
1567 test_lookaside_list();
1568 test_ob_reference(test_input
->path
);
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
;
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
;
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
;
1621 return STATUS_ACCESS_VIOLATION
;
1625 RtlInitUnicodeString(&name
, driver2_path
);
1627 return ZwLoadDriver(&name
);
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
);
1654 case IOCTL_WINETEST_MAIN_TEST
:
1655 status
= main_test(device
, irp
, stack
);
1657 case IOCTL_WINETEST_LOAD_DRIVER
:
1658 status
= test_load_driver_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
1660 case IOCTL_WINETEST_RESET_CANCEL
:
1662 status
= STATUS_SUCCESS
;
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
);
1671 case IOCTL_WINETEST_DETACH
:
1672 IoDetachDevice(lower_device
);
1673 status
= STATUS_SUCCESS
;
1679 if (status
!= STATUS_PENDING
)
1681 irp
->IoStatus
.Status
= status
;
1682 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1684 else IoMarkIrpPending(irp
);
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
;
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
;
1749 RtlInitUnicodeString(&nameW
, upper_name
);
1751 status
= IoCreateDevice(driver
, 0, &nameW
, FILE_DEVICE_UNKNOWN
,
1752 FILE_DEVICE_SECURE_OPEN
, FALSE
, &upper_device
);
1757 IoAttachDeviceToDeviceStack(upper_device
, lower_device
);
1758 upper_device
->Flags
&= ~DO_DEVICE_INITIALIZING
;