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"
40 /* memcmp() isn't exported from ntoskrnl on i386 */
41 static int kmemcmp( const void *ptr1
, const void *ptr2
, size_t n
)
43 const unsigned char *p1
, *p2
;
45 for (p1
= ptr1
, p2
= ptr2
; n
; n
--, p1
++, p2
++)
47 if (*p1
< *p2
) return -1;
48 if (*p1
> *p2
) return 1;
53 static DRIVER_OBJECT
*driver_obj
;
54 static DEVICE_OBJECT
*lower_device
, *upper_device
;
56 static POBJECT_TYPE
*pExEventObjectType
, *pIoFileObjectType
, *pPsThreadType
, *pIoDriverObjectType
;
57 static PEPROCESS
*pPsInitialSystemProcess
;
58 static void *create_caller_thread
;
60 static PETHREAD create_irp_thread
;
62 NTSTATUS WINAPI
ZwQueryInformationProcess(HANDLE
,PROCESSINFOCLASS
,void*,ULONG
,ULONG
*);
71 static void *get_proc_address(const char *name
)
73 UNICODE_STRING name_u
;
78 RtlInitAnsiString(&name_a
, name
);
79 status
= RtlAnsiStringToUnicodeString(&name_u
, &name_a
, TRUE
);
80 ok (!status
, "RtlAnsiStringToUnicodeString failed: %#x\n", status
);
81 if (status
) return NULL
;
83 ret
= MmGetSystemRoutineAddress(&name_u
);
84 RtlFreeUnicodeString(&name_u
);
88 static FILE_OBJECT
*last_created_file
;
89 static unsigned int create_count
, close_count
;
91 static NTSTATUS WINAPI
test_irp_struct_completion_routine(DEVICE_OBJECT
*reserved
, IRP
*irp
, void *context
)
93 unsigned int *result
= context
;
96 return STATUS_MORE_PROCESSING_REQUIRED
;
99 static void test_irp_struct(IRP
*irp
, DEVICE_OBJECT
*device
)
101 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
102 unsigned int irp_completion_result
;
104 ok(device
== upper_device
, "Expected device %p, got %p.\n", upper_device
, device
);
105 ok(last_created_file
!= NULL
, "last_created_file = NULL\n");
106 ok(irpsp
->FileObject
== last_created_file
, "FileObject != last_created_file\n");
107 ok(irpsp
->DeviceObject
== upper_device
, "unexpected DeviceObject\n");
108 ok(irpsp
->FileObject
->DeviceObject
== lower_device
, "unexpected FileObject->DeviceObject\n");
109 ok(!irp
->UserEvent
, "UserEvent = %p\n", irp
->UserEvent
);
110 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
111 "IRP thread is not the current thread\n");
113 ok(IoGetRequestorProcess(irp
) == IoGetCurrentProcess(), "processes didn't match\n");
115 irp
= IoAllocateIrp(1, FALSE
);
116 ok(irp
->AllocationFlags
== IRP_ALLOCATED_FIXED_SIZE
, "Got unexpected irp->AllocationFlags %#x.\n",
117 irp
->AllocationFlags
);
118 ok(irp
->CurrentLocation
== 2,
119 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
120 IoSetCompletionRoutine(irp
, test_irp_struct_completion_routine
, &irp_completion_result
,
123 irp_completion_result
= 0;
125 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
126 --irp
->CurrentLocation
;
127 --irp
->Tail
.Overlay
.CurrentStackLocation
;
128 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
129 ok(irp
->CurrentLocation
== 2,
130 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
131 ok(irp_completion_result
, "IRP completion was not called.\n");
133 --irp
->CurrentLocation
;
134 --irp
->Tail
.Overlay
.CurrentStackLocation
;
135 IoReuseIrp(irp
, STATUS_UNSUCCESSFUL
);
136 ok(irp
->CurrentLocation
== 2,
137 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
138 ok(irp
->AllocationFlags
== IRP_ALLOCATED_FIXED_SIZE
, "Got unexpected irp->AllocationFlags %#x.\n",
139 irp
->AllocationFlags
);
144 static void test_mdl_map(void)
146 char buffer
[20] = "test buffer";
150 mdl
= IoAllocateMdl(buffer
, sizeof(buffer
), FALSE
, FALSE
, NULL
);
151 ok(mdl
!= NULL
, "IoAllocateMdl failed\n");
153 MmProbeAndLockPages(mdl
, KernelMode
, IoReadAccess
);
155 addr
= MmMapLockedPagesSpecifyCache(mdl
, KernelMode
, MmCached
, NULL
, FALSE
, NormalPagePriority
);
157 ok(addr
!= NULL
, "MmMapLockedPagesSpecifyCache failed\n");
159 MmUnmapLockedPages(addr
, mdl
);
164 static void test_init_funcs(void)
166 KTIMER timer
, timer2
;
168 KeInitializeTimerEx(&timer
, NotificationTimer
);
169 ok(timer
.Header
.Type
== 8, "got: %u\n", timer
.Header
.Type
);
170 ok(timer
.Header
.Size
== 0 || timer
.Header
.Size
== 10, "got: %u\n", timer
.Header
.Size
);
171 ok(timer
.Header
.SignalState
== 0, "got: %u\n", timer
.Header
.SignalState
);
173 KeInitializeTimerEx(&timer2
, SynchronizationTimer
);
174 ok(timer2
.Header
.Type
== 9, "got: %u\n", timer2
.Header
.Type
);
175 ok(timer2
.Header
.Size
== 0 || timer2
.Header
.Size
== 10, "got: %u\n", timer2
.Header
.Size
);
176 ok(timer2
.Header
.SignalState
== 0, "got: %u\n", timer2
.Header
.SignalState
);
179 static const WCHAR driver2_path
[] =
180 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\WineTestDriver2";
182 static IMAGE_INFO test_image_info
;
183 static int test_load_image_notify_count
;
184 static WCHAR test_load_image_name
[MAX_PATH
];
186 static void WINAPI
test_load_image_notify_routine(UNICODE_STRING
*image_name
, HANDLE process_id
,
187 IMAGE_INFO
*image_info
)
189 if (test_load_image_notify_count
== -1
190 || (image_name
->Buffer
&& wcsstr(image_name
->Buffer
, L
".tmp")))
192 ++test_load_image_notify_count
;
193 test_image_info
= *image_info
;
194 wcscpy(test_load_image_name
, image_name
->Buffer
);
198 static void test_load_driver(void)
200 char full_name_buffer
[300];
201 OBJECT_NAME_INFORMATION
*full_name
= (OBJECT_NAME_INFORMATION
*)full_name_buffer
;
202 static WCHAR image_path_key_name
[] = L
"ImagePath";
203 RTL_QUERY_REGISTRY_TABLE query_table
[2];
204 UNICODE_STRING name
, image_path
;
205 OBJECT_ATTRIBUTES attr
;
210 ret
= PsSetLoadImageNotifyRoutine(test_load_image_notify_routine
);
211 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", ret
);
213 /* Routine gets registered twice on Windows. */
214 ret
= PsSetLoadImageNotifyRoutine(test_load_image_notify_routine
);
215 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", ret
);
217 RtlInitUnicodeString(&image_path
, NULL
);
218 memset(query_table
, 0, sizeof(query_table
));
219 query_table
[0].QueryRoutine
= NULL
;
220 query_table
[0].Name
= image_path_key_name
;
221 query_table
[0].EntryContext
= &image_path
;
222 query_table
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_TYPECHECK
;
223 query_table
[0].DefaultType
= REG_EXPAND_SZ
<< RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
;
225 ret
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
, driver2_path
, query_table
, NULL
, NULL
);
226 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", ret
);
227 ok(!!image_path
.Buffer
, "image_path.Buffer is NULL.\n");
229 /* The image path name in the registry may contain NT symlinks (e.g. DOS
230 * drives), which are resolved before the callback is called on Windows 10. */
231 InitializeObjectAttributes(&attr
, &image_path
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
232 ret
= ZwOpenFile(&file
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
233 todo_wine
ok(!ret
, "Got unexpected status %#x.\n", ret
);
236 ret
= ZwQueryObject(file
, ObjectNameInformation
, full_name_buffer
, sizeof(full_name_buffer
), NULL
);
237 ok(!ret
, "Got unexpected status %#x.\n", ret
);
241 RtlInitUnicodeString(&name
, driver2_path
);
243 ret
= ZwLoadDriver(&name
);
244 ok(!ret
, "got %#x\n", ret
);
246 ok(test_load_image_notify_count
== 2, "Got unexpected test_load_image_notify_count %u.\n",
247 test_load_image_notify_count
);
248 ok(test_image_info
.ImageAddressingMode
== IMAGE_ADDRESSING_MODE_32BIT
,
249 "Got unexpected ImageAddressingMode %#x.\n", test_image_info
.ImageAddressingMode
);
250 ok(test_image_info
.SystemModeImage
,
251 "Got unexpected SystemModeImage %#x.\n", test_image_info
.SystemModeImage
);
252 ok(!wcscmp(test_load_image_name
, image_path
.Buffer
) /* Win < 10 */
253 || !wcscmp(test_load_image_name
, full_name
->Name
.Buffer
),
254 "Expected image path name %ls, got %ls.\n", full_name
->Name
.Buffer
, test_load_image_name
);
256 test_load_image_notify_count
= -1;
258 ret
= ZwLoadDriver(&name
);
259 ok(ret
== STATUS_IMAGE_ALREADY_LOADED
, "got %#x\n", ret
);
261 ret
= ZwUnloadDriver(&name
);
262 ok(!ret
, "got %#x\n", ret
);
264 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
265 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", ret
);
266 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
267 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", ret
);
268 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
269 ok(ret
== STATUS_PROCEDURE_NOT_FOUND
, "Got unexpected status %#x.\n", ret
);
271 ok(test_load_image_notify_count
== -1, "Got unexpected test_load_image_notify_count %u.\n",
272 test_load_image_notify_count
);
273 RtlFreeUnicodeString(&image_path
);
276 static NTSTATUS
wait_single(void *obj
, ULONGLONG timeout
)
278 LARGE_INTEGER integer
;
280 integer
.QuadPart
= timeout
;
281 return KeWaitForSingleObject(obj
, Executive
, KernelMode
, FALSE
, &integer
);
284 static NTSTATUS
wait_multiple(ULONG count
, void *objs
[], WAIT_TYPE wait_type
, ULONGLONG timeout
)
286 LARGE_INTEGER integer
;
288 integer
.QuadPart
= timeout
;
289 return KeWaitForMultipleObjects(count
, objs
, wait_type
, Executive
, KernelMode
, FALSE
, &integer
, NULL
);
292 static NTSTATUS
wait_single_handle(HANDLE handle
, ULONGLONG timeout
)
294 LARGE_INTEGER integer
;
296 integer
.QuadPart
= timeout
;
297 return ZwWaitForSingleObject(handle
, FALSE
, &integer
);
300 static void test_current_thread(BOOL is_system
)
302 PROCESS_BASIC_INFORMATION info
;
303 DISPATCHER_HEADER
*header
;
304 HANDLE process_handle
, id
;
309 current
= IoGetCurrentProcess();
310 ok(current
!= NULL
, "Expected current process to be non-NULL\n");
312 header
= (DISPATCHER_HEADER
*)current
;
313 ok(header
->Type
== 3, "header->Type != 3, = %u\n", header
->Type
);
314 ret
= wait_single(current
, 0);
315 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
318 ok(current
== *pPsInitialSystemProcess
, "current != PsInitialSystemProcess\n");
320 ok(current
!= *pPsInitialSystemProcess
, "current == PsInitialSystemProcess\n");
322 ok(PsGetProcessId(current
) == PsGetCurrentProcessId(), "process IDs don't match\n");
323 ok(PsGetThreadProcessId((PETHREAD
)KeGetCurrentThread()) == PsGetCurrentProcessId(), "process IDs don't match\n");
325 thread
= PsGetCurrentThread();
326 ret
= wait_single( thread
, 0 );
327 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
329 ok(PsGetThreadId((PETHREAD
)KeGetCurrentThread()) == PsGetCurrentThreadId(), "thread IDs don't match\n");
330 ok(PsIsSystemThread((PETHREAD
)KeGetCurrentThread()) == is_system
, "unexpected system thread\n");
333 ok(create_caller_thread
== KeGetCurrentThread(), "thread is not create caller thread\n");
334 ok(create_irp_thread
== (PETHREAD
)KeGetCurrentThread(), "thread of create request is not current thread\n");
337 ret
= ObOpenObjectByPointer(current
, OBJ_KERNEL_HANDLE
, NULL
, PROCESS_QUERY_INFORMATION
, NULL
, KernelMode
, &process_handle
);
338 ok(!ret
, "ObOpenObjectByPointer failed: %#x\n", ret
);
340 ret
= ZwQueryInformationProcess(process_handle
, ProcessBasicInformation
, &info
, sizeof(info
), NULL
);
341 ok(!ret
, "ZwQueryInformationProcess failed: %#x\n", ret
);
343 id
= PsGetProcessInheritedFromUniqueProcessId(current
);
344 ok(id
== (HANDLE
)info
.InheritedFromUniqueProcessId
, "unexpected process id %p\n", id
);
346 ret
= ZwClose(process_handle
);
347 ok(!ret
, "ZwClose failed: %#x\n", ret
);
350 static void test_critical_region(BOOL is_dispatcher
)
354 KeEnterCriticalRegion();
355 KeEnterCriticalRegion();
357 result
= KeAreApcsDisabled();
358 ok(result
== TRUE
, "KeAreApcsDisabled returned %x\n", result
);
359 KeLeaveCriticalRegion();
361 result
= KeAreApcsDisabled();
362 ok(result
== TRUE
, "KeAreApcsDisabled returned %x\n", result
);
363 KeLeaveCriticalRegion();
365 result
= KeAreApcsDisabled();
366 ok(result
== is_dispatcher
|| broken(is_dispatcher
&& !result
),
367 "KeAreApcsDisabled returned %x\n", result
);
370 static void sleep_1ms(void)
372 LARGE_INTEGER timeout
;
374 timeout
.QuadPart
= -1 * 10000;
375 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
378 static void sleep(void)
380 LARGE_INTEGER timeout
;
381 timeout
.QuadPart
= -20 * 10000;
382 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
385 static HANDLE
create_thread(PKSTART_ROUTINE proc
, void *arg
)
387 OBJECT_ATTRIBUTES attr
= {0};
391 attr
.Length
= sizeof(attr
);
392 attr
.Attributes
= OBJ_KERNEL_HANDLE
;
393 ret
= PsCreateSystemThread(&thread
, THREAD_ALL_ACCESS
, &attr
, NULL
, NULL
, proc
, arg
);
394 ok(!ret
, "got %#x\n", ret
);
399 static void join_thread(HANDLE thread
)
403 ret
= ZwWaitForSingleObject(thread
, FALSE
, NULL
);
404 ok(!ret
, "got %#x\n", ret
);
405 ret
= ZwClose(thread
);
406 ok(!ret
, "got %#x\n", ret
);
409 static void run_thread(PKSTART_ROUTINE proc
, void *arg
)
411 HANDLE thread
= create_thread(proc
, arg
);
415 static KMUTEX test_mutex
;
417 static void WINAPI
mutex_thread(void *arg
)
419 NTSTATUS ret
, expect
= (NTSTATUS
)(DWORD_PTR
)arg
;
421 ret
= wait_single(&test_mutex
, 0);
422 ok(ret
== expect
, "expected %#x, got %#x\n", expect
, ret
);
424 if (!ret
) KeReleaseMutex(&test_mutex
, FALSE
);
425 PsTerminateSystemThread(STATUS_SUCCESS
);
428 static KEVENT remove_lock_ready
;
430 static void WINAPI
remove_lock_thread(void *arg
)
432 IO_REMOVE_LOCK
*lock
= arg
;
435 ret
= IoAcquireRemoveLockEx(lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
436 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
437 KeSetEvent(&remove_lock_ready
, 0, FALSE
);
439 IoReleaseRemoveLockAndWaitEx(lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
440 PsTerminateSystemThread(STATUS_SUCCESS
);
443 struct test_sync_dpc_context
448 static void WINAPI
test_sync_dpc(KDPC
*dpc
, void *context
, void *system_argument1
, void *system_argument2
)
450 struct test_sync_dpc_context
*c
= context
;
455 static void test_sync(void)
457 static const ULONG wine_tag
= 0x454e4957; /* WINE */
458 struct test_sync_dpc_context dpc_context
;
459 KEVENT manual_event
, auto_event
, *event
;
460 KSEMAPHORE semaphore
, semaphore2
;
461 IO_REMOVE_LOCK remove_lock
;
462 LARGE_INTEGER timeout
;
463 OBJECT_ATTRIBUTES attr
;
464 HANDLE handle
, thread
;
471 KeInitializeEvent(&manual_event
, NotificationEvent
, FALSE
);
473 ret
= wait_single(&manual_event
, 0);
474 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
476 ret
= KeReadStateEvent(&manual_event
);
477 ok(ret
== 0, "got %d\n", ret
);
479 KeSetEvent(&manual_event
, 0, FALSE
);
481 ret
= KeReadStateEvent(&manual_event
);
482 ok(ret
== 1, "got %d\n", ret
);
484 ret
= wait_single(&manual_event
, 0);
485 ok(ret
== 0, "got %#x\n", ret
);
487 ret
= wait_single(&manual_event
, 0);
488 ok(ret
== 0, "got %#x\n", ret
);
490 KeResetEvent(&manual_event
);
492 ret
= wait_single(&manual_event
, 0);
493 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
495 KeInitializeEvent(&auto_event
, SynchronizationEvent
, FALSE
);
497 ret
= wait_single(&auto_event
, 0);
498 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
500 KeSetEvent(&auto_event
, 0, FALSE
);
502 ret
= wait_single(&auto_event
, 0);
503 ok(ret
== 0, "got %#x\n", ret
);
505 ret
= wait_single(&auto_event
, 0);
506 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
508 KeInitializeEvent(&auto_event
, SynchronizationEvent
, TRUE
);
510 ret
= wait_single(&auto_event
, 0);
511 ok(ret
== 0, "got %#x\n", ret
);
513 objs
[0] = &manual_event
;
514 objs
[1] = &auto_event
;
516 ret
= wait_multiple(2, objs
, WaitAny
, 0);
517 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
519 KeSetEvent(&manual_event
, 0, FALSE
);
520 KeSetEvent(&auto_event
, 0, FALSE
);
522 ret
= wait_multiple(2, objs
, WaitAny
, 0);
523 ok(ret
== 0, "got %#x\n", ret
);
525 ret
= wait_single(&auto_event
, 0);
526 ok(ret
== 0, "got %#x\n", ret
);
528 KeResetEvent(&manual_event
);
529 KeSetEvent(&auto_event
, 0, FALSE
);
531 ret
= wait_multiple(2, objs
, WaitAny
, 0);
532 ok(ret
== 1, "got %#x\n", ret
);
534 ret
= wait_multiple(2, objs
, WaitAny
, 0);
535 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
537 KeSetEvent(&manual_event
, 0, FALSE
);
538 KeSetEvent(&auto_event
, 0, FALSE
);
540 ret
= wait_multiple(2, objs
, WaitAll
, 0);
541 ok(ret
== 0, "got %#x\n", ret
);
543 ret
= wait_multiple(2, objs
, WaitAll
, 0);
544 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
546 KeSetEvent(&auto_event
, 0, FALSE
);
547 KeResetEvent(&manual_event
);
549 ret
= wait_multiple(2, objs
, WaitAll
, 0);
550 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
552 ret
= wait_single(&auto_event
, 0);
553 ok(ret
== 0, "got %#x\n", ret
);
555 objs
[0] = &auto_event
;
556 objs
[1] = &manual_event
;
557 KeSetEvent(&manual_event
, 0, FALSE
);
558 KeSetEvent(&auto_event
, 0, FALSE
);
560 ret
= wait_multiple(2, objs
, WaitAny
, 0);
561 ok(ret
== 0, "got %#x\n", ret
);
563 ret
= wait_multiple(2, objs
, WaitAny
, 0);
564 ok(ret
== 1, "got %#x\n", ret
);
566 ret
= wait_multiple(2, objs
, WaitAny
, 0);
567 ok(ret
== 1, "got %#x\n", ret
);
569 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
570 ret
= ZwCreateEvent(&handle
, SYNCHRONIZE
, &attr
, NotificationEvent
, TRUE
);
571 ok(!ret
, "ZwCreateEvent failed: %#x\n", ret
);
573 ret
= ObReferenceObjectByHandle(handle
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, (void **)&event
, NULL
);
574 ok(!ret
, "ObReferenceObjectByHandle failed: %#x\n", ret
);
577 ret
= wait_single(event
, 0);
578 ok(ret
== 0, "got %#x\n", ret
);
579 ret
= KeReadStateEvent(event
);
580 ok(ret
== 1, "got %d\n", ret
);
582 ret
= KeReadStateEvent(event
);
583 ok(ret
== 0, "got %d\n", ret
);
584 ret
= wait_single(event
, 0);
585 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
586 ret
= wait_single_handle(handle
, 0);
587 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
589 KeSetEvent(event
, 0, FALSE
);
590 ret
= wait_single(event
, 0);
591 ok(ret
== 0, "got %#x\n", ret
);
592 ret
= wait_single_handle(handle
, 0);
593 ok(!ret
, "got %#x\n", ret
);
596 ObDereferenceObject(event
);
598 event
= IoCreateSynchronizationEvent(NULL
, &handle
);
599 ok(event
!= NULL
, "IoCreateSynchronizationEvent failed\n");
601 ret
= wait_single(event
, 0);
602 ok(ret
== 0, "got %#x\n", ret
);
604 ret
= wait_single(event
, 0);
605 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
606 ret
= wait_single_handle(handle
, 0);
607 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
609 ret
= ZwSetEvent(handle
, NULL
);
610 ok(!ret
, "NtSetEvent returned %#x\n", ret
);
611 ret
= wait_single(event
, 0);
612 ok(ret
== 0, "got %#x\n", ret
);
613 ret
= wait_single_handle(handle
, 0);
614 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
616 KeSetEvent(event
, 0, FALSE
);
617 ret
= wait_single_handle(handle
, 0);
618 ok(!ret
, "got %#x\n", ret
);
619 ret
= wait_single(event
, 0);
620 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
622 ret
= ZwClose(handle
);
623 ok(!ret
, "ZwClose returned %#x\n", ret
);
625 /* test semaphores */
626 KeInitializeSemaphore(&semaphore
, 0, 5);
628 ret
= wait_single(&semaphore
, 0);
629 ok(ret
== STATUS_TIMEOUT
, "got %u\n", ret
);
631 ret
= KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
632 ok(ret
== 0, "got prev %d\n", ret
);
634 ret
= KeReleaseSemaphore(&semaphore
, 0, 2, FALSE
);
635 ok(ret
== 1, "got prev %d\n", ret
);
637 ret
= KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
638 ok(ret
== 3, "got prev %d\n", ret
);
640 for (i
= 0; i
< 4; i
++)
642 ret
= wait_single(&semaphore
, 0);
643 ok(ret
== 0, "got %#x\n", ret
);
646 ret
= wait_single(&semaphore
, 0);
647 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
649 KeInitializeSemaphore(&semaphore2
, 3, 5);
651 ret
= KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
652 ok(ret
== 3, "got prev %d\n", ret
);
654 for (i
= 0; i
< 4; i
++)
656 ret
= wait_single(&semaphore2
, 0);
657 ok(ret
== 0, "got %#x\n", ret
);
660 objs
[0] = &semaphore
;
661 objs
[1] = &semaphore2
;
663 ret
= wait_multiple(2, objs
, WaitAny
, 0);
664 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
666 KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
667 KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
669 ret
= wait_multiple(2, objs
, WaitAny
, 0);
670 ok(ret
== 0, "got %#x\n", ret
);
672 ret
= wait_multiple(2, objs
, WaitAny
, 0);
673 ok(ret
== 1, "got %#x\n", ret
);
675 ret
= wait_multiple(2, objs
, WaitAny
, 0);
676 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
678 KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
679 KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
681 ret
= wait_multiple(2, objs
, WaitAll
, 0);
682 ok(ret
== 0, "got %#x\n", ret
);
684 ret
= wait_multiple(2, objs
, WaitAny
, 0);
685 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
688 KeInitializeMutex(&test_mutex
, 0);
690 for (i
= 0; i
< 10; i
++)
692 ret
= wait_single(&test_mutex
, 0);
693 ok(ret
== 0, "got %#x\n", ret
);
696 for (i
= 0; i
< 10; i
++)
698 ret
= KeReleaseMutex(&test_mutex
, FALSE
);
699 ok(ret
== i
- 9, "expected %d, got %d\n", i
- 9, ret
);
702 run_thread(mutex_thread
, (void *)0);
704 ret
= wait_single(&test_mutex
, 0);
705 ok(ret
== 0, "got %#x\n", ret
);
707 run_thread(mutex_thread
, (void *)STATUS_TIMEOUT
);
709 ret
= KeReleaseMutex(&test_mutex
, 0);
710 ok(ret
== 0, "got %#x\n", ret
);
712 run_thread(mutex_thread
, (void *)0);
715 KeInitializeTimerEx(&timer
, NotificationTimer
);
717 timeout
.QuadPart
= -20 * 10000;
718 KeSetTimerEx(&timer
, timeout
, 0, NULL
);
720 ret
= wait_single(&timer
, 0);
721 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
723 ret
= wait_single(&timer
, -40 * 10000);
724 ok(ret
== 0, "got %#x\n", ret
);
726 ret
= wait_single(&timer
, 0);
727 ok(ret
== 0, "got %#x\n", ret
);
729 KeCancelTimer(&timer
);
730 KeInitializeTimerEx(&timer
, SynchronizationTimer
);
732 memset(&dpc_context
, 0, sizeof(dpc_context
));
733 KeInitializeDpc(&dpc
, test_sync_dpc
, &dpc_context
);
735 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
737 ret
= wait_single(&timer
, 0);
738 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
739 ok(!dpc_context
.called
, "DPC was called unexpectedly.\n");
741 ret
= wait_single(&timer
, -40 * 10000);
742 ok(ret
== 0, "got %#x\n", ret
);
744 ok(dpc_context
.called
, "DPC was not called.\n");
746 ret
= wait_single(&timer
, -40 * 10000);
747 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
749 KeCancelTimer(&timer
);
750 KeSetTimerEx(&timer
, timeout
, 20, NULL
);
752 ret
= wait_single(&timer
, 0);
753 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
755 ret
= wait_single(&timer
, -40 * 10000);
756 ok(ret
== 0, "got %#x\n", ret
);
758 ret
= wait_single(&timer
, 0);
759 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
761 ret
= wait_single(&timer
, -40 * 10000);
762 ok(ret
== 0, "got %#x\n", ret
);
764 ret
= wait_single(&timer
, -40 * 10000);
765 ok(ret
== 0, "got %#x\n", ret
);
767 KeCancelTimer(&timer
);
769 /* Test cancelling timer. */
770 dpc_context
.called
= 0;
771 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
773 ret
= wait_single(&timer
, 0);
774 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
775 ok(!dpc_context
.called
, "DPC was called.\n");
777 KeCancelTimer(&timer
);
778 dpc_context
.called
= 0;
779 ret
= wait_single(&timer
, -40 * 10000);
780 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
781 ok(!dpc_context
.called
, "DPC was called.\n");
783 KeSetTimerEx(&timer
, timeout
, 20, &dpc
);
784 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
785 ret
= wait_single(&timer
, 0);
786 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
788 ret
= wait_single(&timer
, -40 * 10000);
789 ok(ret
== 0, "got %#x\n", ret
);
791 ret
= wait_single(&timer
, 0);
792 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
794 ret
= wait_single(&timer
, -40 * 10000);
795 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
797 ret
= wait_single(&timer
, -40 * 10000);
798 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
800 KeCancelTimer(&timer
);
801 /* Test reinitializing timer. */
802 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
803 KeInitializeTimerEx(&timer
, SynchronizationTimer
);
804 dpc_context
.called
= 0;
805 ret
= wait_single(&timer
, -40 * 10000);
806 ok(ret
== 0, "got %#x\n", ret
);
808 todo_wine
ok(dpc_context
.called
, "DPC was not called.\n");
810 ret
= wait_single(&timer
, 0);
811 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
813 todo_wine
ok(dpc_context
.called
, "DPC was not called.\n");
815 dpc_context
.called
= 0;
816 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
817 ret
= wait_single(&timer
, -40 * 10000);
818 ok(ret
== 0, "got %#x\n", ret
);
820 ok(dpc_context
.called
, "DPC was not called.\n");
822 KeCancelTimer(&timer
);
825 IoInitializeRemoveLockEx(&remove_lock
, wine_tag
, 0, 0, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
827 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
828 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
830 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
832 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
833 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
835 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
836 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
838 KeInitializeEvent(&remove_lock_ready
, SynchronizationEvent
, FALSE
);
839 thread
= create_thread(remove_lock_thread
, &remove_lock
);
840 ret
= wait_single(&remove_lock_ready
, -1000 * 10000);
841 ok(!ret
, "got %#x\n", ret
);
842 ret
= wait_single_handle(thread
, -50 * 10000);
843 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
845 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
846 ok(ret
== STATUS_DELETE_PENDING
, "got %#x\n", ret
);
848 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
849 ret
= wait_single_handle(thread
, 0);
850 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
852 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
853 ret
= wait_single_handle(thread
, -10000 * 10000);
854 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
856 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
857 ok(ret
== STATUS_DELETE_PENDING
, "got %#x\n", ret
);
860 static void test_call_driver(DEVICE_OBJECT
*device
)
862 IO_STACK_LOCATION
*irpsp
;
863 IO_STATUS_BLOCK iosb
;
868 iosb
.Status
= 0xdeadbeef;
869 iosb
.Information
= 0xdeadbeef;
870 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
871 ok(irp
->UserIosb
== &iosb
, "unexpected UserIosb\n");
872 ok(!irp
->Cancel
, "Cancel = %x\n", irp
->Cancel
);
873 ok(!irp
->CancelRoutine
, "CancelRoutine = %x\n", irp
->CancelRoutine
);
874 ok(!irp
->UserEvent
, "UserEvent = %p\n", irp
->UserEvent
);
875 ok(irp
->CurrentLocation
== 2, "CurrentLocation = %u\n", irp
->CurrentLocation
);
876 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
877 "IRP thread is not the current thread\n");
878 ok(!irp
->IoStatus
.Status
, "got status %#x\n", irp
->IoStatus
.Status
);
879 ok(!irp
->IoStatus
.Information
, "got information %#x\n", irp
->IoStatus
.Information
);
880 ok(iosb
.Status
== 0xdeadbeef, "got status %#x\n", iosb
.Status
);
881 ok(iosb
.Information
== 0xdeadbeef, "got information %#x\n", iosb
.Information
);
883 irpsp
= IoGetNextIrpStackLocation(irp
);
884 ok(irpsp
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
, "MajorFunction = %u\n", irpsp
->MajorFunction
);
885 ok(!irpsp
->DeviceObject
, "DeviceObject = %u\n", irpsp
->DeviceObject
);
886 ok(!irpsp
->FileObject
, "FileObject = %u\n", irpsp
->FileObject
);
887 ok(!irpsp
->CompletionRoutine
, "CompletionRoutine = %p\n", irpsp
->CompletionRoutine
);
889 status
= IoCallDriver(device
, irp
);
890 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
891 ok(!irp
->IoStatus
.Status
, "got status %#x\n", irp
->IoStatus
.Status
);
892 ok(!irp
->IoStatus
.Information
, "got information %#x\n", irp
->IoStatus
.Information
);
893 ok(iosb
.Status
== 0xdeadbeef, "got status %#x\n", iosb
.Status
);
894 ok(iosb
.Information
== 0xdeadbeef, "got information %#x\n", iosb
.Information
);
896 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
897 irp
->IoStatus
.Information
= 123;
898 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
899 ok(iosb
.Status
== STATUS_SUCCESS
, "got status %#x\n", iosb
.Status
);
900 ok(iosb
.Information
== 123, "got information %#x\n", iosb
.Information
);
902 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
904 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &event
, &iosb
);
905 ok(irp
->UserIosb
== &iosb
, "unexpected UserIosb\n");
906 ok(!irp
->Cancel
, "Cancel = %x\n", irp
->Cancel
);
907 ok(!irp
->CancelRoutine
, "CancelRoutine = %x\n", irp
->CancelRoutine
);
908 ok(irp
->UserEvent
== &event
, "UserEvent = %p\n", irp
->UserEvent
);
909 ok(irp
->CurrentLocation
== 2, "CurrentLocation = %u\n", irp
->CurrentLocation
);
910 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
911 "IRP thread is not the current thread\n");
913 irpsp
= IoGetNextIrpStackLocation(irp
);
914 ok(irpsp
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
, "MajorFunction = %u\n", irpsp
->MajorFunction
);
915 ok(!irpsp
->DeviceObject
, "DeviceObject = %u\n", irpsp
->DeviceObject
);
916 ok(!irpsp
->FileObject
, "FileObject = %u\n", irpsp
->FileObject
);
917 ok(!irpsp
->CompletionRoutine
, "CompletionRoutine = %p\n", irpsp
->CompletionRoutine
);
919 status
= wait_single(&event
, 0);
920 ok(status
== STATUS_TIMEOUT
, "got %#x\n", status
);
922 status
= IoCallDriver(device
, irp
);
923 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
925 status
= wait_single(&event
, 0);
926 ok(status
== STATUS_TIMEOUT
, "got %#x\n", status
);
928 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
929 irp
->IoStatus
.Information
= 0;
930 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
932 status
= wait_single(&event
, 0);
933 ok(status
== STATUS_SUCCESS
, "got %#x\n", status
);
936 static int cancel_cnt
;
938 static void WINAPI
cancel_irp(DEVICE_OBJECT
*device
, IRP
*irp
)
940 IoReleaseCancelSpinLock(irp
->CancelIrql
);
941 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
942 ok(!irp
->CancelRoutine
, "CancelRoutine = %p\n", irp
->CancelRoutine
);
943 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
944 irp
->IoStatus
.Information
= 0;
948 static void WINAPI
cancel_ioctl_irp(DEVICE_OBJECT
*device
, IRP
*irp
)
950 IoReleaseCancelSpinLock(irp
->CancelIrql
);
951 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
952 irp
->IoStatus
.Information
= 0;
954 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
957 static NTSTATUS WINAPI
cancel_test_completion(DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
959 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
960 *(BOOL
*)context
= TRUE
;
961 return STATUS_SUCCESS
;
964 static void test_cancel_irp(DEVICE_OBJECT
*device
)
966 IO_STACK_LOCATION
*irpsp
;
967 IO_STATUS_BLOCK iosb
;
969 BOOL completion_called
;
973 /* cancel IRP with no cancel routine */
974 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
976 r
= IoCancelIrp(irp
);
977 ok(!r
, "IoCancelIrp returned %x\n", r
);
978 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
980 r
= IoCancelIrp(irp
);
981 ok(!r
, "IoCancelIrp returned %x\n", r
);
984 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
986 /* cancel IRP with cancel routine */
987 status
= IoCallDriver(device
, irp
);
988 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
990 ok(irp
->CurrentLocation
== 1, "CurrentLocation = %u\n", irp
->CurrentLocation
);
991 irpsp
= IoGetCurrentIrpStackLocation(irp
);
992 ok(irpsp
->DeviceObject
== device
, "DeviceObject = %u\n", irpsp
->DeviceObject
);
994 IoSetCancelRoutine(irp
, cancel_irp
);
996 r
= IoCancelIrp(irp
);
997 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
998 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
999 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1002 r
= IoCancelIrp(irp
);
1003 ok(!r
, "IoCancelIrp returned %x\n", r
);
1004 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1005 ok(!cancel_cnt
, "cancel_cnt = %d\n", cancel_cnt
);
1007 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1009 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_ERROR */
1010 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1011 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, FALSE
, TRUE
);
1013 status
= IoCallDriver(device
, irp
);
1014 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
1016 IoSetCancelRoutine(irp
, cancel_irp
);
1018 r
= IoCancelIrp(irp
);
1019 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1020 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1021 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1023 completion_called
= FALSE
;
1024 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1025 ok(completion_called
, "completion not called\n");
1027 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_CANCEL flag */
1028 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1029 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, TRUE
, FALSE
);
1031 status
= IoCallDriver(device
, irp
);
1032 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
1034 IoSetCancelRoutine(irp
, cancel_irp
);
1036 r
= IoCancelIrp(irp
);
1037 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1038 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1039 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1041 completion_called
= FALSE
;
1042 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1043 ok(completion_called
, "completion not called\n");
1045 /* cancel IRP with cancel and completion routines, but no SL_INVOKE_ON_ERROR nor SL_INVOKE_ON_CANCEL flag */
1046 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1047 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, FALSE
, FALSE
);
1049 status
= IoCallDriver(device
, irp
);
1050 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#x\n", status
);
1052 IoSetCancelRoutine(irp
, cancel_irp
);
1054 r
= IoCancelIrp(irp
);
1055 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1056 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1057 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1059 completion_called
= FALSE
;
1060 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1061 ok(!completion_called
, "completion not called\n");
1064 static int callout_cnt
;
1066 static void WINAPI
callout(void *parameter
)
1068 ok(parameter
== (void*)0xdeadbeef, "parameter = %p\n", parameter
);
1072 static void test_stack_callout(void)
1074 NTSTATUS (WINAPI
*pKeExpandKernelStackAndCallout
)(PEXPAND_STACK_CALLOUT
,void*,SIZE_T
);
1075 NTSTATUS (WINAPI
*pKeExpandKernelStackAndCalloutEx
)(PEXPAND_STACK_CALLOUT
,void*,SIZE_T
,BOOLEAN
,void*);
1078 pKeExpandKernelStackAndCallout
= get_proc_address("KeExpandKernelStackAndCallout");
1079 if (pKeExpandKernelStackAndCallout
)
1082 ret
= pKeExpandKernelStackAndCallout(callout
, (void*)0xdeadbeef, 4096);
1083 ok(ret
== STATUS_SUCCESS
, "KeExpandKernelStackAndCallout failed: %#x\n", ret
);
1084 ok(callout_cnt
== 1, "callout_cnt = %u\n", callout_cnt
);
1086 else win_skip("KeExpandKernelStackAndCallout is not available\n");
1088 pKeExpandKernelStackAndCalloutEx
= get_proc_address("KeExpandKernelStackAndCalloutEx");
1089 if (pKeExpandKernelStackAndCalloutEx
)
1092 ret
= pKeExpandKernelStackAndCalloutEx(callout
, (void*)0xdeadbeef, 4096, FALSE
, NULL
);
1093 ok(ret
== STATUS_SUCCESS
, "KeExpandKernelStackAndCalloutEx failed: %#x\n", ret
);
1094 ok(callout_cnt
== 1, "callout_cnt = %u\n", callout_cnt
);
1096 else win_skip("KeExpandKernelStackAndCalloutEx is not available\n");
1099 static void test_lookaside_list(void)
1101 NPAGED_LOOKASIDE_LIST list
;
1102 PAGED_LOOKASIDE_LIST paged_list
;
1103 ULONG tag
= 0x454e4957; /* WINE */
1105 ExInitializeNPagedLookasideList(&list
, NULL
, NULL
, POOL_NX_ALLOCATION
, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 0);
1106 ok(list
.L
.Depth
== 4, "Expected 4 got %u\n", list
.L
.Depth
);
1107 ok(list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", list
.L
.MaximumDepth
);
1108 ok(list
.L
.TotalAllocates
== 0, "Expected 0 got %u\n", list
.L
.TotalAllocates
);
1109 ok(list
.L
.AllocateMisses
== 0, "Expected 0 got %u\n", list
.L
.AllocateMisses
);
1110 ok(list
.L
.TotalFrees
== 0, "Expected 0 got %u\n", list
.L
.TotalFrees
);
1111 ok(list
.L
.FreeMisses
== 0, "Expected 0 got %u\n", list
.L
.FreeMisses
);
1112 ok(list
.L
.Type
== (NonPagedPool
|POOL_NX_ALLOCATION
),
1113 "Expected NonPagedPool|POOL_NX_ALLOCATION got %u\n", list
.L
.Type
);
1114 ok(list
.L
.Tag
== tag
, "Expected %x got %x\n", tag
, list
.L
.Tag
);
1115 ok(list
.L
.Size
== LOOKASIDE_MINIMUM_BLOCK_SIZE
,
1116 "Expected %u got %u\n", LOOKASIDE_MINIMUM_BLOCK_SIZE
, list
.L
.Size
);
1117 ok(list
.L
.LastTotalAllocates
== 0,"Expected 0 got %u\n", list
.L
.LastTotalAllocates
);
1118 ok(list
.L
.LastAllocateMisses
== 0,"Expected 0 got %u\n", list
.L
.LastAllocateMisses
);
1119 ExDeleteNPagedLookasideList(&list
);
1122 ExInitializeNPagedLookasideList(&list
, NULL
, NULL
, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 20);
1123 ok(list
.L
.Depth
== 4, "Expected 4 got %u\n", list
.L
.Depth
);
1124 ok(list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", list
.L
.MaximumDepth
);
1125 ok(list
.L
.Type
== NonPagedPool
, "Expected NonPagedPool got %u\n", list
.L
.Type
);
1126 ExDeleteNPagedLookasideList(&list
);
1128 ExInitializePagedLookasideList(&paged_list
, NULL
, NULL
, POOL_NX_ALLOCATION
, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 0);
1129 ok(paged_list
.L
.Depth
== 4, "Expected 4 got %u\n", paged_list
.L
.Depth
);
1130 ok(paged_list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", paged_list
.L
.MaximumDepth
);
1131 ok(paged_list
.L
.TotalAllocates
== 0, "Expected 0 got %u\n", paged_list
.L
.TotalAllocates
);
1132 ok(paged_list
.L
.AllocateMisses
== 0, "Expected 0 got %u\n", paged_list
.L
.AllocateMisses
);
1133 ok(paged_list
.L
.TotalFrees
== 0, "Expected 0 got %u\n", paged_list
.L
.TotalFrees
);
1134 ok(paged_list
.L
.FreeMisses
== 0, "Expected 0 got %u\n", paged_list
.L
.FreeMisses
);
1135 ok(paged_list
.L
.Type
== (PagedPool
|POOL_NX_ALLOCATION
),
1136 "Expected PagedPool|POOL_NX_ALLOCATION got %u\n", paged_list
.L
.Type
);
1137 ok(paged_list
.L
.Tag
== tag
, "Expected %x got %x\n", tag
, paged_list
.L
.Tag
);
1138 ok(paged_list
.L
.Size
== LOOKASIDE_MINIMUM_BLOCK_SIZE
,
1139 "Expected %u got %u\n", LOOKASIDE_MINIMUM_BLOCK_SIZE
, paged_list
.L
.Size
);
1140 ok(paged_list
.L
.LastTotalAllocates
== 0,"Expected 0 got %u\n", paged_list
.L
.LastTotalAllocates
);
1141 ok(paged_list
.L
.LastAllocateMisses
== 0,"Expected 0 got %u\n", paged_list
.L
.LastAllocateMisses
);
1142 ExDeletePagedLookasideList(&paged_list
);
1144 paged_list
.L
.Depth
= 0;
1145 ExInitializePagedLookasideList(&paged_list
, NULL
, NULL
, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 20);
1146 ok(paged_list
.L
.Depth
== 4, "Expected 4 got %u\n", paged_list
.L
.Depth
);
1147 ok(paged_list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", paged_list
.L
.MaximumDepth
);
1148 ok(paged_list
.L
.Type
== PagedPool
, "Expected PagedPool got %u\n", paged_list
.L
.Type
);
1149 ExDeletePagedLookasideList(&paged_list
);
1152 static void test_version(void)
1154 USHORT
*pNtBuildNumber
;
1157 pNtBuildNumber
= get_proc_address("NtBuildNumber");
1158 ok(!!pNtBuildNumber
, "Could not get pointer to NtBuildNumber\n");
1160 PsGetVersion(NULL
, NULL
, &build
, NULL
);
1161 ok(*pNtBuildNumber
== build
, "Expected build number %u, got %u\n", build
, *pNtBuildNumber
);
1164 static void WINAPI
thread_proc(void *arg
)
1166 PsTerminateSystemThread(STATUS_SUCCESS
);
1169 static void test_ob_reference(void)
1171 POBJECT_TYPE (WINAPI
*pObGetObjectType
)(void*);
1172 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
1173 HANDLE event_handle
, file_handle
, file_handle2
, thread_handle
, handle
;
1174 DISPATCHER_HEADER
*header
;
1177 POBJECT_TYPE obj1_type
;
1178 UNICODE_STRING pathU
;
1182 pObGetObjectType
= get_proc_address("ObGetObjectType");
1183 if (!pObGetObjectType
)
1184 win_skip("ObGetObjectType not found\n");
1186 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1187 status
= ZwCreateEvent(&event_handle
, SYNCHRONIZE
, &attr
, NotificationEvent
, TRUE
);
1188 ok(!status
, "ZwCreateEvent failed: %#x\n", status
);
1190 RtlInitUnicodeString(&pathU
, L
"\\??\\C:\\windows\\winetest_ntoskrnl_file.tmp");
1191 attr
.ObjectName
= &pathU
;
1192 attr
.Attributes
= OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
;
1193 status
= ZwCreateFile(&file_handle
, DELETE
| FILE_WRITE_DATA
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0, 0, FILE_CREATE
,
1194 FILE_DELETE_ON_CLOSE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
1195 ok(!status
, "ZwCreateFile failed: %#x\n", status
);
1197 status
= ZwDuplicateObject(NtCurrentProcess(), file_handle
, NtCurrentProcess(), &file_handle2
,
1198 0, OBJ_KERNEL_HANDLE
, DUPLICATE_SAME_ACCESS
);
1199 ok(!status
, "ZwDuplicateObject failed: %#x\n", status
);
1201 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1202 status
= PsCreateSystemThread(&thread_handle
, SYNCHRONIZE
, &attr
, NULL
, NULL
, thread_proc
, NULL
);
1203 ok(!status
, "PsCreateSystemThread returned: %#x\n", status
);
1205 status
= ObReferenceObjectByHandle(NULL
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, &obj1
, NULL
);
1206 ok(status
== STATUS_INVALID_HANDLE
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1208 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj1
, NULL
);
1209 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObReferenceObjectByHandle returned: %#x\n", status
);
1211 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, NULL
, KernelMode
, &obj1
, NULL
);
1212 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1214 if (pObGetObjectType
)
1216 obj1_type
= pObGetObjectType(obj1
);
1217 ok(obj1_type
== *pExEventObjectType
, "ObGetObjectType returned %p\n", obj1_type
);
1220 if (sizeof(void *) != 4) /* avoid dealing with fastcall */
1222 ObfReferenceObject(obj1
);
1223 ObDereferenceObject(obj1
);
1226 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj2
, NULL
);
1227 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObReferenceObjectByHandle returned: %#x\n", status
);
1229 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, &obj2
, NULL
);
1230 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1231 ok(obj1
== obj2
, "obj1 != obj2\n");
1233 ObDereferenceObject(obj2
);
1235 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, NULL
, KernelMode
, &obj2
, NULL
);
1236 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1237 ok(obj1
== obj2
, "obj1 != obj2\n");
1239 ObDereferenceObject(obj2
);
1240 ObDereferenceObject(obj1
);
1242 status
= ObReferenceObjectByHandle(file_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj1
, NULL
);
1243 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1245 status
= ObReferenceObjectByHandle(file_handle2
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj2
, NULL
);
1246 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1247 ok(obj1
== obj2
, "obj1 != obj2\n");
1250 ok(file
->Type
== 5, "Type = %u\n", file
->Type
);
1252 ObDereferenceObject(obj1
);
1253 ObDereferenceObject(obj2
);
1255 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj1
, NULL
);
1256 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1258 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj2
, NULL
);
1259 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1260 ok(obj1
== obj2
, "obj1 != obj2\n");
1263 ok(header
->Type
== 6, "Type = %u\n", header
->Type
);
1265 status
= wait_single(header
, 0);
1266 ok(status
== 0 || status
== STATUS_TIMEOUT
, "got %#x\n", status
);
1268 ObDereferenceObject(obj2
);
1270 status
= ObOpenObjectByPointer(obj1
, OBJ_KERNEL_HANDLE
, NULL
, 0, NULL
, KernelMode
, &handle
);
1271 ok(status
== STATUS_SUCCESS
, "ObOpenObjectByPointer failed: %#x\n", status
);
1273 status
= ZwClose(handle
);
1274 ok(!status
, "ZwClose failed: %#x\n", status
);
1276 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj2
, NULL
);
1277 ok(!status
, "ObReferenceObjectByHandle failed: %#x\n", status
);
1278 ok(obj1
== obj2
, "obj1 != obj2\n");
1279 ObDereferenceObject(obj2
);
1281 status
= ObOpenObjectByPointer(obj1
, OBJ_KERNEL_HANDLE
, NULL
, 0, *pIoFileObjectType
, KernelMode
, &handle
);
1282 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObOpenObjectByPointer returned: %#x\n", status
);
1284 ObDereferenceObject(obj1
);
1286 status
= ZwClose(thread_handle
);
1287 ok(!status
, "ZwClose failed: %#x\n", status
);
1289 status
= ZwClose(event_handle
);
1290 ok(!status
, "ZwClose failed: %#x\n", status
);
1292 status
= ZwClose(file_handle
);
1293 ok(!status
, "ZwClose failed: %#x\n", status
);
1295 status
= ZwClose(file_handle2
);
1296 ok(!status
, "ZwClose failed: %#x\n", status
);
1299 static void check_resource_(int line
, ERESOURCE
*resource
, ULONG exclusive_waiters
,
1300 ULONG shared_waiters
, BOOLEAN exclusive
, ULONG shared_count
)
1305 count
= ExGetExclusiveWaiterCount(resource
);
1306 ok_(__FILE__
, line
, count
== exclusive_waiters
,
1307 "expected %u exclusive waiters, got %u\n", exclusive_waiters
, count
);
1308 count
= ExGetSharedWaiterCount(resource
);
1309 ok_(__FILE__
, line
, count
== shared_waiters
,
1310 "expected %u shared waiters, got %u\n", shared_waiters
, count
);
1311 ret
= ExIsResourceAcquiredExclusiveLite(resource
);
1312 ok_(__FILE__
, line
, ret
== exclusive
,
1313 "expected exclusive %u, got %u\n", exclusive
, ret
);
1314 count
= ExIsResourceAcquiredSharedLite(resource
);
1315 ok_(__FILE__
, line
, count
== shared_count
,
1316 "expected shared %u, got %u\n", shared_count
, count
);
1318 #define check_resource(a,b,c,d,e) check_resource_(__LINE__,a,b,c,d,e)
1320 static KEVENT resource_shared_ready
, resource_shared_done
, resource_exclusive_ready
, resource_exclusive_done
;
1322 static void WINAPI
resource_shared_thread(void *arg
)
1324 ERESOURCE
*resource
= arg
;
1327 check_resource(resource
, 0, 0, FALSE
, 0);
1329 ret
= ExAcquireResourceSharedLite(resource
, TRUE
);
1330 ok(ret
== TRUE
, "got ret %u\n", ret
);
1332 check_resource(resource
, 0, 0, FALSE
, 1);
1334 KeSetEvent(&resource_shared_ready
, IO_NO_INCREMENT
, FALSE
);
1335 KeWaitForSingleObject(&resource_shared_done
, Executive
, KernelMode
, FALSE
, NULL
);
1337 ExReleaseResourceForThreadLite(resource
, (ULONG_PTR
)PsGetCurrentThread());
1339 PsTerminateSystemThread(STATUS_SUCCESS
);
1342 static void WINAPI
resource_exclusive_thread(void *arg
)
1344 ERESOURCE
*resource
= arg
;
1347 check_resource(resource
, 0, 0, FALSE
, 0);
1349 ret
= ExAcquireResourceExclusiveLite(resource
, TRUE
);
1350 ok(ret
== TRUE
, "got ret %u\n", ret
);
1352 check_resource(resource
, 0, 0, TRUE
, 1);
1354 KeSetEvent(&resource_exclusive_ready
, IO_NO_INCREMENT
, FALSE
);
1355 KeWaitForSingleObject(&resource_exclusive_done
, Executive
, KernelMode
, FALSE
, NULL
);
1357 ExReleaseResourceForThreadLite(resource
, (ULONG_PTR
)PsGetCurrentThread());
1359 PsTerminateSystemThread(STATUS_SUCCESS
);
1362 static void test_resource(void)
1367 HANDLE thread
, thread2
;
1369 memset(&resource
, 0xcc, sizeof(resource
));
1371 status
= ExInitializeResourceLite(&resource
);
1372 ok(status
== STATUS_SUCCESS
, "got status %#x\n", status
);
1373 check_resource(&resource
, 0, 0, FALSE
, 0);
1375 KeEnterCriticalRegion();
1377 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1378 ok(ret
== TRUE
, "got ret %u\n", ret
);
1379 check_resource(&resource
, 0, 0, TRUE
, 1);
1381 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1382 ok(ret
== TRUE
, "got ret %u\n", ret
);
1383 check_resource(&resource
, 0, 0, TRUE
, 2);
1385 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1386 ok(ret
== TRUE
, "got ret %u\n", ret
);
1387 check_resource(&resource
, 0, 0, TRUE
, 3);
1389 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1390 check_resource(&resource
, 0, 0, TRUE
, 2);
1392 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1393 check_resource(&resource
, 0, 0, TRUE
, 1);
1395 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1396 check_resource(&resource
, 0, 0, FALSE
, 0);
1398 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1399 ok(ret
== TRUE
, "got ret %u\n", ret
);
1400 check_resource(&resource
, 0, 0, FALSE
, 1);
1402 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1403 ok(ret
== TRUE
, "got ret %u\n", ret
);
1404 check_resource(&resource
, 0, 0, FALSE
, 2);
1406 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1407 ok(ret
== FALSE
, "got ret %u\n", ret
);
1408 check_resource(&resource
, 0, 0, FALSE
, 2);
1410 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1411 check_resource(&resource
, 0, 0, FALSE
, 1);
1413 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1414 check_resource(&resource
, 0, 0, FALSE
, 0);
1416 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1417 ok(ret
== TRUE
, "got ret %u\n", ret
);
1418 check_resource(&resource
, 0, 0, FALSE
, 1);
1420 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1421 check_resource(&resource
, 0, 0, FALSE
, 0);
1423 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1424 ok(ret
== TRUE
, "got ret %u\n", ret
);
1425 check_resource(&resource
, 0, 0, FALSE
, 1);
1427 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1428 check_resource(&resource
, 0, 0, FALSE
, 0);
1430 /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */
1432 KeInitializeEvent(&resource_shared_ready
, SynchronizationEvent
, FALSE
);
1433 KeInitializeEvent(&resource_shared_done
, SynchronizationEvent
, FALSE
);
1434 thread
= create_thread(resource_shared_thread
, &resource
);
1435 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1436 check_resource(&resource
, 0, 0, FALSE
, 0);
1438 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1439 ok(ret
== FALSE
, "got ret %u\n", ret
);
1441 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1442 ok(ret
== TRUE
, "got ret %u\n", ret
);
1443 check_resource(&resource
, 0, 0, FALSE
, 1);
1445 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1446 check_resource(&resource
, 0, 0, FALSE
, 0);
1448 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1449 ok(ret
== TRUE
, "got ret %u\n", ret
);
1450 check_resource(&resource
, 0, 0, FALSE
, 1);
1452 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1453 check_resource(&resource
, 0, 0, FALSE
, 0);
1455 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1456 ok(ret
== TRUE
, "got ret %u\n", ret
);
1457 check_resource(&resource
, 0, 0, FALSE
, 1);
1459 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1460 check_resource(&resource
, 0, 0, FALSE
, 0);
1462 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1463 join_thread(thread
);
1464 check_resource(&resource
, 0, 0, FALSE
, 0);
1466 /* Acquire the resource as exclusive, and then spawn a shared thread. */
1468 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1469 ok(ret
== TRUE
, "got ret %u\n", ret
);
1470 check_resource(&resource
, 0, 0, TRUE
, 1);
1472 thread
= create_thread(resource_shared_thread
, &resource
);
1474 check_resource(&resource
, 0, 1, TRUE
, 1);
1476 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1477 ok(ret
== TRUE
, "got ret %u\n", ret
);
1478 check_resource(&resource
, 0, 1, TRUE
, 2);
1480 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1481 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1482 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1483 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1484 join_thread(thread
);
1485 check_resource(&resource
, 0, 0, FALSE
, 0);
1487 /* Do not acquire the resource ourselves, but spawn an exclusive thread holding it. */
1489 KeInitializeEvent(&resource_exclusive_ready
, SynchronizationEvent
, FALSE
);
1490 KeInitializeEvent(&resource_exclusive_done
, SynchronizationEvent
, FALSE
);
1491 thread
= create_thread(resource_exclusive_thread
, &resource
);
1492 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1493 check_resource(&resource
, 0, 0, FALSE
, 0);
1495 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1496 ok(ret
== FALSE
, "got ret %u\n", ret
);
1497 check_resource(&resource
, 0, 0, FALSE
, 0);
1499 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1500 ok(ret
== FALSE
, "got ret %u\n", ret
);
1501 check_resource(&resource
, 0, 0, FALSE
, 0);
1503 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1504 ok(ret
== FALSE
, "got ret %u\n", ret
);
1505 check_resource(&resource
, 0, 0, FALSE
, 0);
1507 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1508 ok(ret
== FALSE
, "got ret %u\n", ret
);
1509 check_resource(&resource
, 0, 0, FALSE
, 0);
1511 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1512 join_thread(thread
);
1513 check_resource(&resource
, 0, 0, FALSE
, 0);
1515 /* Acquire the resource as shared, and then spawn an exclusive waiter. */
1517 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1518 ok(ret
== TRUE
, "got ret %u\n", ret
);
1519 check_resource(&resource
, 0, 0, FALSE
, 1);
1521 thread
= create_thread(resource_exclusive_thread
, &resource
);
1523 check_resource(&resource
, 1, 0, FALSE
, 1);
1525 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1526 ok(ret
== TRUE
, "got ret %u\n", ret
);
1527 check_resource(&resource
, 1, 0, FALSE
, 2);
1528 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1530 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1531 ok(ret
== TRUE
, "got ret %u\n", ret
);
1532 check_resource(&resource
, 1, 0, FALSE
, 2);
1533 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1535 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1536 ok(ret
== FALSE
, "got ret %u\n", ret
);
1537 check_resource(&resource
, 1, 0, FALSE
, 1);
1539 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1540 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1541 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1542 join_thread(thread
);
1543 check_resource(&resource
, 0, 0, FALSE
, 0);
1545 /* Spawn a shared and then exclusive waiter. */
1547 KeInitializeEvent(&resource_shared_ready
, SynchronizationEvent
, FALSE
);
1548 KeInitializeEvent(&resource_shared_done
, SynchronizationEvent
, FALSE
);
1549 thread
= create_thread(resource_shared_thread
, &resource
);
1550 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1551 check_resource(&resource
, 0, 0, FALSE
, 0);
1553 thread2
= create_thread(resource_exclusive_thread
, &resource
);
1555 check_resource(&resource
, 1, 0, FALSE
, 0);
1557 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1558 ok(ret
== FALSE
, "got ret %u\n", ret
);
1559 check_resource(&resource
, 1, 0, FALSE
, 0);
1561 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1562 ok(ret
== FALSE
, "got ret %u\n", ret
);
1563 check_resource(&resource
, 1, 0, FALSE
, 0);
1565 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1566 ok(ret
== TRUE
, "got ret %u\n", ret
);
1567 check_resource(&resource
, 1, 0, FALSE
, 1);
1568 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1570 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1571 ok(ret
== FALSE
, "got ret %u\n", ret
);
1572 check_resource(&resource
, 1, 0, FALSE
, 0);
1574 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1575 join_thread(thread
);
1576 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1577 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1578 join_thread(thread2
);
1579 check_resource(&resource
, 0, 0, FALSE
, 0);
1581 KeLeaveCriticalRegion();
1583 status
= ExDeleteResourceLite(&resource
);
1584 ok(status
== STATUS_SUCCESS
, "got status %#x\n", status
);
1587 static void test_lookup_thread(void)
1590 PETHREAD thread
= NULL
;
1592 status
= PsLookupThreadByThreadId(PsGetCurrentThreadId(), &thread
);
1593 ok(!status
, "PsLookupThreadByThreadId failed: %#x\n", status
);
1594 ok((PKTHREAD
)thread
== KeGetCurrentThread(), "thread != KeGetCurrentThread\n");
1595 if (thread
) ObDereferenceObject(thread
);
1597 status
= PsLookupThreadByThreadId(NULL
, &thread
);
1598 ok(status
== STATUS_INVALID_CID
|| broken(status
== STATUS_INVALID_PARAMETER
) /* winxp */,
1599 "PsLookupThreadByThreadId returned %#x\n", status
);
1602 static void test_stack_limits(void)
1604 ULONG_PTR low
= 0, high
= 0;
1606 IoGetStackLimits(&low
, &high
);
1607 ok(low
, "low = 0\n");
1608 ok(low
< high
, "low >= high\n");
1609 ok(low
< (ULONG_PTR
)&low
&& (ULONG_PTR
)&low
< high
, "stack variable is not in stack limits\n");
1612 static unsigned int got_completion
;
1614 static NTSTATUS WINAPI
completion_cb(DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
1616 ok(device
== context
, "Got device %p; expected %p.\n", device
, context
);
1618 return STATUS_SUCCESS
;
1621 static void test_completion(void)
1628 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
1630 irp
= IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION
, upper_device
,
1631 NULL
, 0, NULL
, 0, FALSE
, &event
, &io
);
1633 IoSetCompletionRoutine(irp
, completion_cb
, NULL
, TRUE
, TRUE
, TRUE
);
1634 ret
= IoCallDriver(upper_device
, irp
);
1635 ok(ret
== STATUS_SUCCESS
, "IoCallDriver returned %#x\n", ret
);
1636 ok(got_completion
== 2, "got %u calls to completion routine\n", got_completion
);
1639 static void test_IoAttachDeviceToDeviceStack(void)
1641 DEVICE_OBJECT
*dev1
, *dev2
, *dev3
, *ret
;
1644 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1645 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev1
);
1646 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1647 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1648 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev2
);
1649 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1650 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1651 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev3
);
1652 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1654 /* TODO: initialize devices properly */
1655 dev1
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1656 dev2
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1658 ret
= IoAttachDeviceToDeviceStack(dev2
, dev1
);
1659 ok(ret
== dev1
, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret
, dev1
);
1660 ok(dev1
->AttachedDevice
== dev2
, "dev1->AttachedDevice = %p, expected %p\n",
1661 dev1
->AttachedDevice
, dev2
);
1662 ok(!dev2
->AttachedDevice
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1663 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1664 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1666 ret
= IoAttachDeviceToDeviceStack(dev3
, dev1
);
1667 ok(ret
== dev2
, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret
, dev2
);
1668 ok(dev1
->AttachedDevice
== dev2
, "dev1->AttachedDevice = %p, expected %p\n",
1669 dev1
->AttachedDevice
, dev2
);
1670 ok(dev2
->AttachedDevice
== dev3
, "dev2->AttachedDevice = %p, expected %p\n",
1671 dev2
->AttachedDevice
, dev3
);
1672 ok(!dev3
->AttachedDevice
, "dev3->AttachedDevice = %p\n", dev3
->AttachedDevice
);
1673 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1674 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1675 ok(dev3
->StackSize
== 3, "dev3->StackSize = %d\n", dev3
->StackSize
);
1677 IoDetachDevice(dev1
);
1678 ok(!dev1
->AttachedDevice
, "dev1->AttachedDevice = %p\n", dev1
->AttachedDevice
);
1679 ok(dev2
->AttachedDevice
== dev3
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1681 IoDetachDevice(dev2
);
1682 ok(!dev2
->AttachedDevice
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1683 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1684 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1685 ok(dev3
->StackSize
== 3, "dev3->StackSize = %d\n", dev3
->StackSize
);
1687 IoDeleteDevice(dev1
);
1688 IoDeleteDevice(dev2
);
1689 IoDeleteDevice(dev3
);
1692 static void test_object_name(void)
1694 static const WCHAR event_nameW
[] = L
"\\wine_test_event";
1695 static const WCHAR device_nameW
[] = L
"\\Device\\WineTestDriver";
1697 OBJECT_NAME_INFORMATION
*name
= (OBJECT_NAME_INFORMATION
*)buffer
;
1698 OBJECT_ATTRIBUTES attr
;
1699 UNICODE_STRING string
;
1706 ret
= ObQueryNameString(lower_device
, name
, 0, &ret_size
);
1707 ok(ret
== STATUS_INFO_LENGTH_MISMATCH
, "got status %#x\n", ret
);
1708 ok(ret_size
== sizeof(*name
) + sizeof(device_nameW
), "got size %u\n", ret_size
);
1711 ret
= ObQueryNameString(lower_device
, name
, sizeof(buffer
), &ret_size
);
1712 ok(!ret
, "got status %#x\n", ret
);
1713 ok(!wcscmp(name
->Name
.Buffer
, device_nameW
), "got name %ls\n", name
->Name
.Buffer
);
1714 ok(ret_size
== sizeof(*name
) + sizeof(device_nameW
), "got size %u\n", ret_size
);
1715 ok(name
->Name
.Length
== wcslen(device_nameW
) * sizeof(WCHAR
), "got length %u\n", name
->Name
.Length
);
1716 ok(name
->Name
.MaximumLength
== sizeof(device_nameW
), "got maximum length %u\n", name
->Name
.MaximumLength
);
1718 event
= IoCreateSynchronizationEvent(NULL
, &handle
);
1719 ok(!!event
, "failed to create event\n");
1722 ret
= ObQueryNameString(event
, name
, sizeof(buffer
), &ret_size
);
1723 ok(!ret
, "got status %#x\n", ret
);
1724 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1725 ok(ret_size
== sizeof(*name
), "got size %u\n", ret_size
);
1726 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1727 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1729 ret
= ZwClose(handle
);
1730 ok(!ret
, "got status %#x\n", ret
);
1732 RtlInitUnicodeString(&string
, event_nameW
);
1733 InitializeObjectAttributes(&attr
, &string
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1734 ret
= ZwCreateEvent(&handle
, 0, &attr
, NotificationEvent
, TRUE
);
1735 ok(!ret
, "got status %#x\n", ret
);
1736 ret
= ObReferenceObjectByHandle(handle
, 0, *pExEventObjectType
, KernelMode
, (void **)&event
, NULL
);
1737 ok(!ret
, "got status %#x\n", ret
);
1740 ret
= ObQueryNameString(event
, name
, sizeof(buffer
), &ret_size
);
1741 ok(!ret
, "got status %#x\n", ret
);
1742 ok(!wcscmp(name
->Name
.Buffer
, event_nameW
), "got name %ls\n", name
->Name
.Buffer
);
1743 ok(ret_size
== sizeof(*name
) + sizeof(event_nameW
), "got size %u\n", ret_size
);
1744 ok(name
->Name
.Length
== wcslen(event_nameW
) * sizeof(WCHAR
), "got length %u\n", name
->Name
.Length
);
1745 ok(name
->Name
.MaximumLength
== sizeof(event_nameW
), "got maximum length %u\n", name
->Name
.MaximumLength
);
1747 ObDereferenceObject(event
);
1748 ret
= ZwClose(handle
);
1749 ok(!ret
, "got status %#x\n", ret
);
1752 ret
= ObQueryNameString(KeGetCurrentThread(), name
, sizeof(buffer
), &ret_size
);
1753 ok(!ret
, "got status %#x\n", ret
);
1754 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1755 ok(ret_size
== sizeof(*name
), "got size %u\n", ret_size
);
1756 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1757 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1760 ret
= ObQueryNameString(IoGetCurrentProcess(), name
, sizeof(buffer
), &ret_size
);
1761 ok(!ret
, "got status %#x\n", ret
);
1762 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1763 ok(ret_size
== sizeof(*name
), "got size %u\n", ret_size
);
1764 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1765 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1768 static PIO_WORKITEM main_test_work_item
;
1770 static void WINAPI
main_test_task(DEVICE_OBJECT
*device
, void *context
)
1773 void *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
1775 IoFreeWorkItem(main_test_work_item
);
1776 main_test_work_item
= NULL
;
1778 test_current_thread(TRUE
);
1779 test_critical_region(FALSE
);
1780 test_call_driver(device
);
1781 test_cancel_irp(device
);
1782 test_stack_limits();
1785 /* print process report */
1788 kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
1789 PsGetCurrentProcessId(), successes
+ failures
+ todo_successes
+ todo_failures
,
1790 todo_successes
, failures
+ todo_failures
,
1791 (failures
+ todo_failures
!= 1) ? "failures" : "failure", skipped
);
1795 *((LONG
*)buffer
) = failures
;
1796 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1797 irp
->IoStatus
.Information
= sizeof(failures
);
1798 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1801 #if defined(__i386__) || defined(__x86_64__)
1802 static void test_executable_pool(void)
1804 static const unsigned char bytes
[] =
1805 { 0xb8, 0xef, 0xbe, 0xad, 0xde, 0xc3 }; /* mov $0xdeadbeef,%eax ; ret */
1806 static const ULONG tag
= 0x74736574; /* test */
1810 func
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(bytes
), tag
);
1811 ok(!!func
, "Got NULL memory.\n");
1813 memcpy(func
, bytes
, sizeof(bytes
));
1815 ok(ret
== 0xdeadbeef, "Got %#x.\n", ret
);
1817 ExFreePoolWithTag(func
, tag
);
1821 static void test_affinity(void)
1823 KAFFINITY (WINAPI
*pKeSetSystemAffinityThreadEx
)(KAFFINITY affinity
);
1824 void (WINAPI
*pKeRevertToUserAffinityThreadEx
)(KAFFINITY affinity
);
1825 ULONG (WINAPI
*pKeQueryActiveProcessorCountEx
)(USHORT
);
1826 KAFFINITY (WINAPI
*pKeQueryActiveProcessors
)(void);
1827 KAFFINITY mask
, mask_all_cpus
;
1828 ULONG cpu_count
, count
;
1830 pKeQueryActiveProcessorCountEx
= get_proc_address("KeQueryActiveProcessorCountEx");
1831 if (!pKeQueryActiveProcessorCountEx
)
1833 win_skip("KeQueryActiveProcessorCountEx is not available.\n");
1837 pKeQueryActiveProcessors
= get_proc_address("KeQueryActiveProcessors");
1838 ok(!!pKeQueryActiveProcessors
, "KeQueryActiveProcessors is not available.\n");
1840 pKeSetSystemAffinityThreadEx
= get_proc_address("KeSetSystemAffinityThreadEx");
1841 ok(!!pKeSetSystemAffinityThreadEx
, "KeSetSystemAffinityThreadEx is not available.\n");
1843 pKeRevertToUserAffinityThreadEx
= get_proc_address("KeRevertToUserAffinityThreadEx");
1844 ok(!!pKeRevertToUserAffinityThreadEx
, "KeRevertToUserAffinityThreadEx is not available.\n");
1846 count
= pKeQueryActiveProcessorCountEx(1);
1847 todo_wine
ok(!count
, "Got unexpected count %u.\n", count
);
1849 cpu_count
= pKeQueryActiveProcessorCountEx(0);
1850 ok(cpu_count
, "Got unexpected cpu_count %u.\n", cpu_count
);
1852 count
= pKeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
1853 ok(count
== cpu_count
, "Got unexpected count %u.\n", count
);
1855 mask_all_cpus
= ~((~0u) << cpu_count
);
1857 mask
= pKeQueryActiveProcessors();
1858 ok(mask
== mask_all_cpus
, "Got unexpected mask %#lx.\n", mask
);
1860 pKeRevertToUserAffinityThreadEx(0x2);
1862 mask
= pKeSetSystemAffinityThreadEx(0);
1863 ok(!mask
, "Got unexpected mask %#lx.\n", mask
);
1865 pKeRevertToUserAffinityThreadEx(0x2);
1867 mask
= pKeSetSystemAffinityThreadEx(0x1);
1868 ok(mask
== 0x2, "Got unexpected mask %#lx.\n", mask
);
1870 mask
= pKeSetSystemAffinityThreadEx(~(KAFFINITY
)0);
1871 ok(mask
== 0x1, "Got unexpected mask %#lx.\n", mask
);
1873 pKeRevertToUserAffinityThreadEx(~(KAFFINITY
)0);
1874 mask
= pKeSetSystemAffinityThreadEx(0x1);
1875 ok(mask
== mask_all_cpus
, "Got unexpected mask %#lx.\n", mask
);
1877 pKeRevertToUserAffinityThreadEx(0);
1879 mask
= pKeSetSystemAffinityThreadEx(0x1);
1880 ok(!mask
, "Got unexpected mask %#lx.\n", mask
);
1882 KeRevertToUserAffinityThread();
1884 mask
= pKeSetSystemAffinityThreadEx(0x1);
1885 ok(!mask
, "Got unexpected mask %#lx.\n", mask
);
1887 KeRevertToUserAffinityThread();
1890 struct test_dpc_func_context
1892 volatile LONG call_count
;
1893 volatile LONG selected_count
;
1894 volatile DEFERRED_REVERSE_BARRIER sync_barrier_start_value
, sync_barrier_mid_value
, sync_barrier_end_value
;
1895 volatile LONG done_barrier_start_value
;
1898 static BOOLEAN (WINAPI
*pKeSignalCallDpcSynchronize
)(void *barrier
);
1899 static void (WINAPI
*pKeSignalCallDpcDone
)(void *barrier
);
1901 static void WINAPI
test_dpc_func(PKDPC Dpc
, void *context
, void *cpu_count
,
1902 void *reverse_barrier
)
1904 DEFERRED_REVERSE_BARRIER
*barrier
= reverse_barrier
;
1905 struct test_dpc_func_context
*data
= context
;
1907 InterlockedIncrement(&data
->call_count
);
1909 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_start_value
.Barrier
,
1910 *(volatile LONG
*)&barrier
->Barrier
, 0);
1911 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_start_value
.TotalProcessors
,
1912 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
1914 if (pKeSignalCallDpcSynchronize(reverse_barrier
))
1915 InterlockedIncrement(&data
->selected_count
);
1917 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_mid_value
.Barrier
,
1918 *(volatile LONG
*)&barrier
->Barrier
, 0);
1919 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_mid_value
.TotalProcessors
,
1920 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
1922 data
->done_barrier_start_value
= *(volatile LONG
*)cpu_count
;
1924 if (pKeSignalCallDpcSynchronize(reverse_barrier
))
1925 InterlockedIncrement(&data
->selected_count
);
1927 pKeSignalCallDpcSynchronize(reverse_barrier
);
1928 pKeSignalCallDpcSynchronize(reverse_barrier
);
1930 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_end_value
.Barrier
,
1931 *(volatile LONG
*)&barrier
->Barrier
, 0);
1932 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_end_value
.TotalProcessors
,
1933 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
1935 pKeSignalCallDpcDone(cpu_count
);
1938 static void test_dpc(void)
1940 void (WINAPI
*pKeGenericCallDpc
)(PKDEFERRED_ROUTINE routine
, void *context
);
1941 struct test_dpc_func_context data
;
1945 pKeGenericCallDpc
= get_proc_address("KeGenericCallDpc");
1946 if (!pKeGenericCallDpc
)
1948 win_skip("KeGenericCallDpc is not available.\n");
1952 pKeSignalCallDpcDone
= get_proc_address("KeSignalCallDpcDone");
1953 ok(!!pKeSignalCallDpcDone
, "KeSignalCallDpcDone is not available.\n");
1954 pKeSignalCallDpcSynchronize
= get_proc_address("KeSignalCallDpcSynchronize");
1955 ok(!!pKeSignalCallDpcSynchronize
, "KeSignalCallDpcSynchronize is not available.\n");
1958 cpu_mask
= KeQueryActiveProcessors();
1968 memset(&data
, 0, sizeof(data
));
1970 KeSetSystemAffinityThread(0x1);
1972 pKeGenericCallDpc(test_dpc_func
, &data
);
1973 ok(data
.call_count
== cpu_count
, "Got unexpected call_count %u.\n", data
.call_count
);
1974 ok(data
.selected_count
== 2, "Got unexpected selected_count %u.\n", data
.selected_count
);
1975 ok(data
.sync_barrier_start_value
.Barrier
== cpu_count
,
1976 "Got unexpected sync_barrier_start_value.Barrier %d.\n",
1977 data
.sync_barrier_start_value
.Barrier
);
1978 ok(data
.sync_barrier_start_value
.TotalProcessors
== cpu_count
,
1979 "Got unexpected sync_barrier_start_value.TotalProcessors %d.\n",
1980 data
.sync_barrier_start_value
.TotalProcessors
);
1982 ok(data
.sync_barrier_mid_value
.Barrier
== (0x80000000 | cpu_count
),
1983 "Got unexpected sync_barrier_mid_value.Barrier %d.\n",
1984 data
.sync_barrier_mid_value
.Barrier
);
1985 ok(data
.sync_barrier_mid_value
.TotalProcessors
== cpu_count
,
1986 "Got unexpected sync_barrier_mid_value.TotalProcessors %d.\n",
1987 data
.sync_barrier_mid_value
.TotalProcessors
);
1989 ok(data
.sync_barrier_end_value
.Barrier
== cpu_count
,
1990 "Got unexpected sync_barrier_end_value.Barrier %d.\n",
1991 data
.sync_barrier_end_value
.Barrier
);
1992 ok(data
.sync_barrier_end_value
.TotalProcessors
== cpu_count
,
1993 "Got unexpected sync_barrier_end_value.TotalProcessors %d.\n",
1994 data
.sync_barrier_end_value
.TotalProcessors
);
1996 ok(data
.done_barrier_start_value
== cpu_count
, "Got unexpected done_barrier_start_value %d.\n", data
.done_barrier_start_value
);
1998 KeRevertToUserAffinityThread();
2001 static void test_process_memory(const struct test_input
*test_input
)
2003 NTSTATUS (WINAPI
*pMmCopyVirtualMemory
)(PEPROCESS fromprocess
, void *fromaddress
, PEPROCESS toprocess
,
2004 void *toaddress
, SIZE_T bufsize
, KPROCESSOR_MODE mode
, SIZE_T
*copied
);
2005 char buffer
[sizeof(teststr
)];
2006 ULONG64 modified_value
;
2013 pMmCopyVirtualMemory
= get_proc_address("MmCopyVirtualMemory");
2015 status
= PsLookupProcessByProcessId((HANDLE
)(ULONG_PTR
)test_input
->process_id
, &process
);
2016 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
2021 if (0) /* Crashes on Windows. */
2022 PsGetProcessSectionBaseAddress(NULL
);
2024 base
= PsGetProcessSectionBaseAddress(process
);
2025 ok(!!base
, "Got NULL base address.\n");
2027 ok(process
== PsGetCurrentProcess(), "Got unexpected process %p, PsGetCurrentProcess() %p.\n",
2028 process
, PsGetCurrentProcess());
2030 modified_value
= 0xdeadbeeffeedcafe;
2031 if (pMmCopyVirtualMemory
)
2034 status
= pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2035 buffer
, sizeof(buffer
), UserMode
, &size
);
2036 todo_wine
ok(status
== STATUS_ACCESS_VIOLATION
, "Got unexpected status %#x.\n", status
);
2037 ok(!size
, "Got unexpected size %#lx.\n", size
);
2039 memset(buffer
, 0, sizeof(buffer
));
2041 if (0) /* Passing NULL for the copied size address hangs Windows. */
2042 pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2043 buffer
, sizeof(buffer
), KernelMode
, NULL
);
2044 status
= pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2045 buffer
, sizeof(buffer
), KernelMode
, &size
);
2046 todo_wine
ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
2047 todo_wine
ok(size
== sizeof(buffer
), "Got unexpected size %lu.\n", size
);
2048 todo_wine
ok(!strcmp(buffer
, teststr
), "Got unexpected test string.\n");
2052 win_skip("MmCopyVirtualMemory is not available.\n");
2055 if (!test_input
->running_under_wine
)
2057 KeStackAttachProcess((PKPROCESS
)process
, &state
);
2058 todo_wine
ok(!strcmp(teststr
, (char *)(base
+ test_input
->teststr_offset
)),
2059 "Strings do not match.\n");
2060 *test_input
->modified_value
= modified_value
;
2061 KeUnstackDetachProcess(&state
);
2063 ObDereferenceObject(process
);
2066 static void test_permanence(void)
2068 OBJECT_ATTRIBUTES attr
;
2069 HANDLE handle
, handle2
;
2073 RtlInitUnicodeString(&str
, L
"\\BaseNamedObjects\\wine_test_dir");
2074 InitializeObjectAttributes(&attr
, &str
, 0, 0, NULL
);
2075 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2076 ok(!status
, "got %#x\n", status
);
2077 status
= ZwClose( handle
);
2078 ok(!status
, "got %#x\n", status
);
2079 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2080 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#x\n", status
);
2082 attr
.Attributes
= OBJ_PERMANENT
;
2083 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2084 ok(!status
, "got %#x\n", status
);
2085 status
= ZwClose( handle
);
2086 ok(!status
, "got %#x\n", status
);
2088 attr
.Attributes
= 0;
2089 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2090 ok(!status
, "got %#x\n", status
);
2091 status
= ZwMakeTemporaryObject( handle
);
2092 ok(!status
, "got %#x\n", status
);
2093 status
= ZwMakeTemporaryObject( handle
);
2094 ok(!status
, "got %#x\n", status
);
2095 status
= ZwClose( handle
);
2096 ok(!status
, "got %#x\n", status
);
2097 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2098 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#x\n", status
);
2100 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2101 ok(!status
, "got %#x\n", status
);
2102 attr
.Attributes
= OBJ_PERMANENT
;
2103 status
= ZwOpenDirectoryObject( &handle2
, 0, &attr
);
2104 ok(status
== STATUS_SUCCESS
, "got %#x\n", status
);
2105 status
= ZwClose( handle2
);
2106 ok(!status
, "got %#x\n", status
);
2107 status
= ZwClose( handle
);
2108 ok(!status
, "got %#x\n", status
);
2109 attr
.Attributes
= 0;
2110 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2111 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#x\n", status
);
2114 static NTSTATUS
main_test(DEVICE_OBJECT
*device
, IRP
*irp
, IO_STACK_LOCATION
*stack
)
2116 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2117 void *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2118 struct test_input
*test_input
= (struct test_input
*)buffer
;
2119 OBJECT_ATTRIBUTES attr
= {0};
2120 UNICODE_STRING pathU
;
2124 return STATUS_ACCESS_VIOLATION
;
2125 if (length
< sizeof(failures
))
2126 return STATUS_BUFFER_TOO_SMALL
;
2128 attr
.Length
= sizeof(attr
);
2129 RtlInitUnicodeString(&pathU
, L
"\\??\\C:\\windows\\winetest_ntoskrnl_okfile");
2130 running_under_wine
= test_input
->running_under_wine
;
2131 winetest_debug
= test_input
->winetest_debug
;
2132 winetest_report_success
= test_input
->winetest_report_success
;
2133 attr
.ObjectName
= &pathU
;
2134 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
; /* needed to be accessible from system threads */
2135 ZwOpenFile(&okfile
, FILE_APPEND_DATA
| SYNCHRONIZE
, &attr
, &io
,
2136 FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
2138 pExEventObjectType
= get_proc_address("ExEventObjectType");
2139 ok(!!pExEventObjectType
, "ExEventObjectType not found\n");
2141 pIoFileObjectType
= get_proc_address("IoFileObjectType");
2142 ok(!!pIoFileObjectType
, "IofileObjectType not found\n");
2144 pPsThreadType
= get_proc_address("PsThreadType");
2145 ok(!!pPsThreadType
, "IofileObjectType not found\n");
2147 pPsInitialSystemProcess
= get_proc_address("PsInitialSystemProcess");
2148 ok(!!pPsInitialSystemProcess
, "PsInitialSystemProcess not found\n");
2150 test_irp_struct(irp
, device
);
2151 test_current_thread(FALSE
);
2152 test_critical_region(TRUE
);
2158 test_stack_callout();
2159 test_lookaside_list();
2160 test_ob_reference();
2162 test_lookup_thread();
2163 test_IoAttachDeviceToDeviceStack();
2165 #if defined(__i386__) || defined(__x86_64__)
2166 test_executable_pool();
2170 test_process_memory(test_input
);
2173 if (main_test_work_item
) return STATUS_UNEXPECTED_IO_ERROR
;
2175 main_test_work_item
= IoAllocateWorkItem(lower_device
);
2176 ok(main_test_work_item
!= NULL
, "main_test_work_item = NULL\n");
2178 IoMarkIrpPending(irp
);
2179 IoQueueWorkItem(main_test_work_item
, main_test_task
, DelayedWorkQueue
, irp
);
2181 return STATUS_PENDING
;
2184 static NTSTATUS
test_basic_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2186 ULONG length
= min(stack
->Parameters
.DeviceIoControl
.OutputBufferLength
, sizeof(teststr
));
2187 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2190 return STATUS_ACCESS_VIOLATION
;
2192 memcpy(buffer
, teststr
, length
);
2195 return STATUS_SUCCESS
;
2198 static NTSTATUS
get_dword(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
, DWORD value
)
2200 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2201 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2204 return STATUS_ACCESS_VIOLATION
;
2206 if (length
< sizeof(DWORD
))
2207 return STATUS_BUFFER_TOO_SMALL
;
2209 *(DWORD
*)buffer
= value
;
2210 *info
= sizeof(DWORD
);
2211 return STATUS_SUCCESS
;
2214 static NTSTATUS
get_fscontext(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2216 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2217 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2218 struct file_context
*context
= stack
->FileObject
->FsContext
;
2221 return STATUS_ACCESS_VIOLATION
;
2223 if (length
< sizeof(DWORD
))
2224 return STATUS_BUFFER_TOO_SMALL
;
2226 *(DWORD
*)buffer
= context
->id
;
2227 *info
= sizeof(DWORD
);
2228 return STATUS_SUCCESS
;
2231 static NTSTATUS
return_status(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2233 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2237 return STATUS_ACCESS_VIOLATION
;
2239 if (stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(DWORD
)
2240 || stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< 3)
2241 return STATUS_BUFFER_TOO_SMALL
;
2243 ret
= *(DWORD
*)irp
->AssociatedIrp
.SystemBuffer
;
2244 memcpy(buffer
, "ghi", 3);
2249 static NTSTATUS
test_load_driver_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2251 BOOL
*load
= irp
->AssociatedIrp
.SystemBuffer
;
2252 UNICODE_STRING name
;
2255 return STATUS_ACCESS_VIOLATION
;
2259 RtlInitUnicodeString(&name
, driver2_path
);
2261 return ZwLoadDriver(&name
);
2263 return ZwUnloadDriver(&name
);
2266 static NTSTATUS
test_mismatched_status_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2268 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2269 char *buffer
= irp
->UserBuffer
;
2273 irp
->IoStatus
.Status
= STATUS_ACCESS_VIOLATION
;
2274 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2275 return STATUS_ACCESS_VIOLATION
;
2278 if (length
< sizeof(teststr
))
2280 irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
2281 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2282 return STATUS_BUFFER_TOO_SMALL
;
2285 memcpy(buffer
, teststr
, sizeof(teststr
));
2287 /* This is deliberate; some broken drivers do this */
2289 irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
2290 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2291 return STATUS_SUCCESS
;
2294 static NTSTATUS
test_completion_ioctl(DEVICE_OBJECT
*device
, IRP
*irp
)
2296 if (device
== upper_device
)
2298 IoCopyCurrentIrpStackLocationToNext(irp
);
2299 IoSetCompletionRoutine(irp
, completion_cb
, upper_device
, TRUE
, TRUE
, TRUE
);
2300 return IoCallDriver(lower_device
, irp
);
2304 ok(device
== lower_device
, "Got wrong device.\n");
2305 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2306 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2307 return STATUS_SUCCESS
;
2311 static NTSTATUS WINAPI
driver_Create(DEVICE_OBJECT
*device
, IRP
*irp
)
2313 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
2314 struct file_context
*context
= ExAllocatePool(PagedPool
, sizeof(*context
));
2318 irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
2319 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2320 return STATUS_NO_MEMORY
;
2323 context
->id
= ++create_count
;
2324 context
->namelen
= min(irpsp
->FileObject
->FileName
.Length
, sizeof(context
->name
));
2325 memcpy(context
->name
, irpsp
->FileObject
->FileName
.Buffer
, context
->namelen
);
2326 irpsp
->FileObject
->FsContext
= context
;
2328 last_created_file
= irpsp
->FileObject
;
2329 create_caller_thread
= KeGetCurrentThread();
2330 create_irp_thread
= irp
->Tail
.Overlay
.Thread
;
2332 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2333 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2334 return STATUS_SUCCESS
;
2337 static NTSTATUS WINAPI
driver_IoControl(DEVICE_OBJECT
*device
, IRP
*irp
)
2339 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2340 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
2342 switch (stack
->Parameters
.DeviceIoControl
.IoControlCode
)
2344 case IOCTL_WINETEST_BASIC_IOCTL
:
2345 status
= test_basic_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
2347 case IOCTL_WINETEST_MAIN_TEST
:
2348 status
= main_test(device
, irp
, stack
);
2350 case IOCTL_WINETEST_LOAD_DRIVER
:
2351 status
= test_load_driver_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
2353 case IOCTL_WINETEST_RESET_CANCEL
:
2355 status
= STATUS_SUCCESS
;
2357 case IOCTL_WINETEST_TEST_CANCEL
:
2358 IoSetCancelRoutine(irp
, cancel_ioctl_irp
);
2359 IoMarkIrpPending(irp
);
2360 return STATUS_PENDING
;
2361 case IOCTL_WINETEST_GET_CANCEL_COUNT
:
2362 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, cancel_cnt
);
2364 case IOCTL_WINETEST_GET_CREATE_COUNT
:
2365 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, create_count
);
2367 case IOCTL_WINETEST_GET_CLOSE_COUNT
:
2368 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, close_count
);
2370 case IOCTL_WINETEST_GET_FSCONTEXT
:
2371 status
= get_fscontext(irp
, stack
, &irp
->IoStatus
.Information
);
2373 case IOCTL_WINETEST_RETURN_STATUS
:
2374 status
= return_status(irp
, stack
, &irp
->IoStatus
.Information
);
2376 case IOCTL_WINETEST_DETACH
:
2377 IoDetachDevice(lower_device
);
2378 status
= STATUS_SUCCESS
;
2380 case IOCTL_WINETEST_MISMATCHED_STATUS
:
2381 return test_mismatched_status_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
2382 case IOCTL_WINETEST_COMPLETION
:
2383 return test_completion_ioctl(device
, irp
);
2388 if (status
!= STATUS_PENDING
)
2390 irp
->IoStatus
.Status
= status
;
2391 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2396 static NTSTATUS WINAPI
driver_FlushBuffers(DEVICE_OBJECT
*device
, IRP
*irp
)
2398 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation(irp
);
2399 ok(device
== lower_device
, "Expected device %p, got %p.\n", lower_device
, device
);
2400 ok(irpsp
->DeviceObject
== device
, "device != DeviceObject\n");
2401 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
2402 "IRP thread is not the current thread\n");
2403 IoMarkIrpPending(irp
);
2404 return STATUS_PENDING
;
2407 static BOOL
compare_file_name(const struct file_context
*context
, const WCHAR
*expect
)
2409 return context
->namelen
== wcslen(expect
) * sizeof(WCHAR
)
2410 && !kmemcmp(context
->name
, expect
, context
->namelen
);
2413 static NTSTATUS WINAPI
driver_QueryInformation(DEVICE_OBJECT
*device
, IRP
*irp
)
2415 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2418 switch (stack
->Parameters
.QueryFile
.FileInformationClass
)
2420 case FileNameInformation
:
2422 const struct file_context
*context
= stack
->FileObject
->FsContext
;
2423 FILE_NAME_INFORMATION
*info
= irp
->AssociatedIrp
.SystemBuffer
;
2426 if (stack
->Parameters
.QueryFile
.Length
< sizeof(*info
))
2428 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2432 if (compare_file_name(context
, L
"\\notimpl"))
2434 ret
= STATUS_NOT_IMPLEMENTED
;
2437 else if (compare_file_name(context
, L
""))
2439 ret
= STATUS_INVALID_DEVICE_REQUEST
;
2442 else if (compare_file_name(context
, L
"\\badparam"))
2444 ret
= STATUS_INVALID_PARAMETER
;
2447 else if (compare_file_name(context
, L
"\\genfail"))
2449 ret
= STATUS_UNSUCCESSFUL
;
2452 else if (compare_file_name(context
, L
"\\badtype"))
2454 ret
= STATUS_OBJECT_TYPE_MISMATCH
;
2458 len
= stack
->Parameters
.QueryFile
.Length
- FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
2459 if (len
< context
->namelen
)
2460 ret
= STATUS_BUFFER_OVERFLOW
;
2463 len
= context
->namelen
;
2464 ret
= STATUS_SUCCESS
;
2466 irp
->IoStatus
.Information
= FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + len
;
2467 info
->FileNameLength
= context
->namelen
;
2468 memcpy(info
->FileName
, context
->name
, len
);
2473 ret
= STATUS_NOT_IMPLEMENTED
;
2477 irp
->IoStatus
.Status
= ret
;
2478 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2482 static NTSTATUS WINAPI
driver_QueryVolumeInformation(DEVICE_OBJECT
*device
, IRP
*irp
)
2484 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2485 ULONG length
= stack
->Parameters
.QueryVolume
.Length
;
2488 switch (stack
->Parameters
.QueryVolume
.FsInformationClass
)
2490 case FileFsVolumeInformation
:
2492 FILE_FS_VOLUME_INFORMATION
*info
= irp
->AssociatedIrp
.SystemBuffer
;
2493 static const WCHAR label
[] = L
"WineTestDriver";
2494 ULONG serial
= 0xdeadbeef;
2496 if (length
< sizeof(FILE_FS_VOLUME_INFORMATION
))
2498 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2502 info
->VolumeCreationTime
.QuadPart
= 0;
2503 info
->VolumeSerialNumber
= serial
;
2504 info
->VolumeLabelLength
= min( lstrlenW(label
) * sizeof(WCHAR
),
2505 length
- offsetof( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) );
2506 info
->SupportsObjects
= TRUE
;
2507 memcpy( info
->VolumeLabel
, label
, info
->VolumeLabelLength
);
2509 irp
->IoStatus
.Information
= offsetof( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + info
->VolumeLabelLength
;
2510 ret
= STATUS_SUCCESS
;
2514 ret
= STATUS_NOT_IMPLEMENTED
;
2518 irp
->IoStatus
.Status
= ret
;
2519 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2523 static NTSTATUS WINAPI
driver_Close(DEVICE_OBJECT
*device
, IRP
*irp
)
2525 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2527 if (stack
->FileObject
->FsContext
)
2528 ExFreePool(stack
->FileObject
->FsContext
);
2529 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2530 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2531 return STATUS_SUCCESS
;
2534 static VOID WINAPI
driver_Unload(DRIVER_OBJECT
*driver
)
2536 UNICODE_STRING linkW
;
2538 DbgPrint("unloading driver\n");
2540 RtlInitUnicodeString(&linkW
, L
"\\DosDevices\\WineTestDriver");
2541 IoDeleteSymbolicLink(&linkW
);
2543 IoDeleteDevice(upper_device
);
2544 IoDeleteDevice(lower_device
);
2547 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, PUNICODE_STRING registry
)
2549 UNICODE_STRING nameW
, linkW
;
2553 DbgPrint("loading driver\n");
2555 driver_obj
= driver
;
2557 /* Allow unloading of the driver */
2558 driver
->DriverUnload
= driver_Unload
;
2560 /* Set driver functions */
2561 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_Create
;
2562 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_IoControl
;
2563 driver
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = driver_FlushBuffers
;
2564 driver
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] = driver_QueryInformation
;
2565 driver
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = driver_QueryVolumeInformation
;
2566 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_Close
;
2568 RtlInitUnicodeString(&nameW
, L
"IoDriverObjectType");
2569 pIoDriverObjectType
= MmGetSystemRoutineAddress(&nameW
);
2571 RtlInitUnicodeString(&nameW
, L
"\\Driver\\WineTestDriver");
2572 if ((status
= ObReferenceObjectByName(&nameW
, 0, NULL
, 0, *pIoDriverObjectType
, KernelMode
, NULL
, &obj
)))
2576 ObDereferenceObject(obj
);
2577 return STATUS_UNSUCCESSFUL
;
2579 ObDereferenceObject(obj
);
2581 RtlInitUnicodeString(&nameW
, L
"\\Device\\WineTestDriver");
2582 RtlInitUnicodeString(&linkW
, L
"\\DosDevices\\WineTestDriver");
2584 if (!(status
= IoCreateDevice(driver
, 0, &nameW
, FILE_DEVICE_UNKNOWN
,
2585 FILE_DEVICE_SECURE_OPEN
, FALSE
, &lower_device
)))
2587 status
= IoCreateSymbolicLink(&linkW
, &nameW
);
2588 lower_device
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2593 RtlInitUnicodeString(&nameW
, L
"\\Device\\WineTestUpper");
2595 status
= IoCreateDevice(driver
, 0, &nameW
, FILE_DEVICE_UNKNOWN
,
2596 FILE_DEVICE_SECURE_OPEN
, FALSE
, &upper_device
);
2601 IoAttachDeviceToDeviceStack(upper_device
, lower_device
);
2602 upper_device
->Flags
&= ~DO_DEVICE_INITIALIZING
;