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
24 #pragma makedep testdll
31 #define WIN32_NO_STATUS
36 #include "ddk/ntddk.h"
37 #include "ddk/ntifs.h"
39 #include "ddk/fltkernel.h"
45 /* memcmp() isn't exported from ntoskrnl on i386 */
46 static int kmemcmp( const void *ptr1
, const void *ptr2
, size_t n
)
48 const unsigned char *p1
, *p2
;
50 for (p1
= ptr1
, p2
= ptr2
; n
; n
--, p1
++, p2
++)
52 if (*p1
< *p2
) return -1;
53 if (*p1
> *p2
) return 1;
58 static DRIVER_OBJECT
*driver_obj
;
59 static DEVICE_OBJECT
*lower_device
, *upper_device
;
61 static POBJECT_TYPE
*pExEventObjectType
, *pIoFileObjectType
, *pPsThreadType
, *pIoDriverObjectType
;
62 static PEPROCESS
*pPsInitialSystemProcess
;
63 static void *create_caller_thread
;
65 static PETHREAD create_irp_thread
;
67 NTSTATUS WINAPI
ZwQueryInformationProcess(HANDLE
,PROCESSINFOCLASS
,void*,ULONG
,ULONG
*);
76 static void *get_proc_address(const char *name
)
78 UNICODE_STRING name_u
;
83 RtlInitAnsiString(&name_a
, name
);
84 status
= RtlAnsiStringToUnicodeString(&name_u
, &name_a
, TRUE
);
85 ok (!status
, "RtlAnsiStringToUnicodeString failed: %#lx\n", status
);
86 if (status
) return NULL
;
88 ret
= MmGetSystemRoutineAddress(&name_u
);
89 RtlFreeUnicodeString(&name_u
);
93 static FILE_OBJECT
*last_created_file
;
94 static unsigned int create_count
, close_count
;
96 static NTSTATUS WINAPI
test_irp_struct_completion_routine(DEVICE_OBJECT
*reserved
, IRP
*irp
, void *context
)
98 unsigned int *result
= context
;
101 return STATUS_MORE_PROCESSING_REQUIRED
;
104 static void test_irp_struct(IRP
*irp
, DEVICE_OBJECT
*device
)
106 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
107 unsigned int irp_completion_result
;
109 ok(device
== upper_device
, "Expected device %p, got %p.\n", upper_device
, device
);
110 ok(last_created_file
!= NULL
, "last_created_file = NULL\n");
111 ok(irpsp
->FileObject
== last_created_file
, "FileObject != last_created_file\n");
112 ok(irpsp
->DeviceObject
== upper_device
, "unexpected DeviceObject\n");
113 ok(irpsp
->FileObject
->DeviceObject
== lower_device
, "unexpected FileObject->DeviceObject\n");
114 ok(!irp
->UserEvent
, "UserEvent = %p\n", irp
->UserEvent
);
115 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
116 "IRP thread is not the current thread\n");
118 ok(IoGetRequestorProcess(irp
) == IoGetCurrentProcess(), "processes didn't match\n");
120 irp
= IoAllocateIrp(1, FALSE
);
121 ok(irp
->AllocationFlags
== IRP_ALLOCATED_FIXED_SIZE
, "Got unexpected irp->AllocationFlags %#x.\n",
122 irp
->AllocationFlags
);
123 ok(irp
->CurrentLocation
== 2,
124 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
125 IoSetCompletionRoutine(irp
, test_irp_struct_completion_routine
, &irp_completion_result
,
128 irp_completion_result
= 0;
130 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
131 --irp
->CurrentLocation
;
132 --irp
->Tail
.Overlay
.CurrentStackLocation
;
133 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
134 ok(irp
->CurrentLocation
== 2,
135 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
136 ok(irp_completion_result
, "IRP completion was not called.\n");
138 --irp
->CurrentLocation
;
139 --irp
->Tail
.Overlay
.CurrentStackLocation
;
140 IoReuseIrp(irp
, STATUS_UNSUCCESSFUL
);
141 ok(irp
->CurrentLocation
== 2,
142 "Got unexpected irp->CurrentLocation %u.\n", irp
->CurrentLocation
);
143 ok(irp
->AllocationFlags
== IRP_ALLOCATED_FIXED_SIZE
, "Got unexpected irp->AllocationFlags %#x.\n",
144 irp
->AllocationFlags
);
149 static int cancel_queue_cnt
;
151 static void WINAPI
cancel_queued_irp(DEVICE_OBJECT
*device
, IRP
*irp
)
153 IoReleaseCancelSpinLock(irp
->CancelIrql
);
154 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
155 ok(!irp
->CancelRoutine
, "CancelRoutine = %p\n", irp
->CancelRoutine
);
156 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
157 irp
->IoStatus
.Information
= 0;
161 static void test_queue(void)
163 KDEVICE_QUEUE_ENTRY
*entry
;
169 irp
= IoAllocateIrp(1, FALSE
);
171 memset(&queue
, 0xcd, sizeof(queue
));
172 KeInitializeDeviceQueue(&queue
);
173 ok(!queue
.Busy
, "unexpected Busy state\n");
174 ok(queue
.Size
== sizeof(queue
), "unexpected Size %x\n", queue
.Size
);
175 ok(queue
.Type
== IO_TYPE_DEVICE_QUEUE
, "unexpected Type %x\n", queue
.Type
);
176 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
178 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
179 ok(!ret
, "expected KeInsertDeviceQueue to not insert IRP\n");
180 ok(queue
.Busy
, "expected Busy state\n");
181 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
182 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected not inserted\n");
184 entry
= KeRemoveDeviceQueue(&queue
);
185 ok(!entry
, "expected KeRemoveDeviceQueue to return NULL\n");
186 ok(!queue
.Busy
, "unexpected Busy state\n");
187 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
188 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected not inserted\n");
190 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
191 ok(!ret
, "expected KeInsertDeviceQueue to not insert IRP\n");
192 ok(queue
.Busy
, "expected Busy state\n");
193 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
194 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected not inserted\n");
196 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
197 ok(ret
, "expected KeInsertDeviceQueue to insert IRP\n");
198 ok(queue
.Busy
, "expected Busy state\n");
199 ok(!IsListEmpty(&queue
.DeviceListHead
), "unexpected empty queue list\n");
200 ok(irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
201 ok(queue
.DeviceListHead
.Flink
== &irp
->Tail
.Overlay
.DeviceQueueEntry
.DeviceListEntry
,
202 "unexpected queue list head\n");
204 entry
= KeRemoveDeviceQueue(&queue
);
205 ok(entry
!= NULL
, "expected KeRemoveDeviceQueue to return non-NULL\n");
206 ok(CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DeviceQueueEntry
) == irp
,
207 "unexpected IRP returned\n");
208 ok(queue
.Busy
, "expected Busy state\n");
209 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
210 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected not inserted\n");
212 entry
= KeRemoveDeviceQueue(&queue
);
213 ok(entry
== NULL
, "expected KeRemoveDeviceQueue to return NULL\n");
214 ok(!queue
.Busy
, "unexpected Busy state\n");
215 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
216 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected not inserted\n");
219 ok(irp
->Cancel
, "unexpected non-cancelled state\n");
221 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
222 ok(!ret
, "expected KeInsertDeviceQueue to not insert IRP\n");
223 ok(queue
.Busy
, "expected Busy state\n");
224 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
225 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
226 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
227 ok(ret
, "expected KeInsertDeviceQueue to insert IRP\n");
228 ok(queue
.Busy
, "expected Busy state\n");
229 ok(!IsListEmpty(&queue
.DeviceListHead
), "unexpected empty queue list\n");
230 ok(irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
231 ok(queue
.DeviceListHead
.Flink
== &irp
->Tail
.Overlay
.DeviceQueueEntry
.DeviceListEntry
,
232 "unexpected queue list head\n");
234 entry
= KeRemoveDeviceQueue(&queue
);
235 ok(entry
!= NULL
, "expected KeRemoveDeviceQueue to return non-NULL\n");
236 ok(CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DeviceQueueEntry
) == irp
,
237 "unexpected IRP returned\n");
238 ok(queue
.Busy
, "expected Busy state\n");
239 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
240 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
241 ok(irp
->Cancel
, "unexpected non-cancelled state\n");
245 irp
= IoAllocateIrp(1, FALSE
);
247 IoAcquireCancelSpinLock(&irql
);
248 IoSetCancelRoutine(irp
, cancel_queued_irp
);
249 IoReleaseCancelSpinLock(irql
);
251 ret
= KeInsertDeviceQueue(&queue
, &irp
->Tail
.Overlay
.DeviceQueueEntry
);
252 ok(ret
, "expected KeInsertDeviceQueue to insert IRP\n");
253 ok(queue
.Busy
, "expected Busy state\n");
254 ok(!IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
255 ok(irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
256 ok(queue
.DeviceListHead
.Flink
== &irp
->Tail
.Overlay
.DeviceQueueEntry
.DeviceListEntry
,
257 "unexpected queue list head\n");
260 ok(irp
->Cancel
, "unexpected non-cancelled state\n");
261 ok(cancel_queue_cnt
, "expected cancel routine to be called\n");
263 entry
= KeRemoveDeviceQueue(&queue
);
264 ok(entry
!= NULL
, "expected KeRemoveDeviceQueue to return non-NULL\n");
265 ok(CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.DeviceQueueEntry
) == irp
,
266 "unexpected IRP returned\n");
267 ok(irp
->Cancel
, "unexpected non-cancelled state\n");
268 ok(cancel_queue_cnt
, "expected cancel routine to be called\n");
269 ok(queue
.Busy
, "expected Busy state\n");
270 ok(IsListEmpty(&queue
.DeviceListHead
), "expected empty queue list\n");
271 ok(!irp
->Tail
.Overlay
.DeviceQueueEntry
.Inserted
, "expected inserted\n");
276 static void test_mdl_map(void)
278 char buffer
[20] = "test buffer";
282 mdl
= IoAllocateMdl(buffer
, sizeof(buffer
), FALSE
, FALSE
, NULL
);
283 ok(mdl
!= NULL
, "IoAllocateMdl failed\n");
285 MmProbeAndLockPages(mdl
, KernelMode
, IoReadAccess
);
287 addr
= MmMapLockedPagesSpecifyCache(mdl
, KernelMode
, MmCached
, NULL
, FALSE
, NormalPagePriority
);
289 ok(addr
!= NULL
, "MmMapLockedPagesSpecifyCache failed\n");
291 MmUnmapLockedPages(addr
, mdl
);
296 static void test_init_funcs(void)
298 KTIMER timer
, timer2
;
300 KeInitializeTimerEx(&timer
, NotificationTimer
);
301 ok(timer
.Header
.Type
== 8, "got: %u\n", timer
.Header
.Type
);
302 ok(timer
.Header
.Size
== 0 || timer
.Header
.Size
== 10, "got: %u\n", timer
.Header
.Size
);
303 ok(timer
.Header
.SignalState
== 0, "got: %lu\n", timer
.Header
.SignalState
);
305 KeInitializeTimerEx(&timer2
, SynchronizationTimer
);
306 ok(timer2
.Header
.Type
== 9, "got: %u\n", timer2
.Header
.Type
);
307 ok(timer2
.Header
.Size
== 0 || timer2
.Header
.Size
== 10, "got: %u\n", timer2
.Header
.Size
);
308 ok(timer2
.Header
.SignalState
== 0, "got: %lu\n", timer2
.Header
.SignalState
);
311 static const WCHAR driver2_path
[] =
312 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\WineTestDriver2";
314 static IMAGE_INFO test_image_info
;
315 static int test_load_image_notify_count
;
316 static WCHAR test_load_image_name
[MAX_PATH
];
318 static void WINAPI
test_load_image_notify_routine(UNICODE_STRING
*image_name
, HANDLE process_id
,
319 IMAGE_INFO
*image_info
)
321 if (image_name
->Buffer
&& wcsstr(image_name
->Buffer
, L
".tmp"))
323 ++test_load_image_notify_count
;
324 test_image_info
= *image_info
;
325 wcscpy(test_load_image_name
, image_name
->Buffer
);
329 static void test_load_driver(void)
331 char full_name_buffer
[300];
332 OBJECT_NAME_INFORMATION
*full_name
= (OBJECT_NAME_INFORMATION
*)full_name_buffer
;
333 static WCHAR image_path_key_name
[] = L
"ImagePath";
334 RTL_QUERY_REGISTRY_TABLE query_table
[2];
335 UNICODE_STRING name
, image_path
;
336 OBJECT_ATTRIBUTES attr
;
341 ret
= PsSetLoadImageNotifyRoutine(test_load_image_notify_routine
);
342 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", ret
);
344 /* Routine gets registered twice on Windows. */
345 ret
= PsSetLoadImageNotifyRoutine(test_load_image_notify_routine
);
346 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", ret
);
348 RtlInitUnicodeString(&image_path
, NULL
);
349 memset(query_table
, 0, sizeof(query_table
));
350 query_table
[0].QueryRoutine
= NULL
;
351 query_table
[0].Name
= image_path_key_name
;
352 query_table
[0].EntryContext
= &image_path
;
353 query_table
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_TYPECHECK
;
354 query_table
[0].DefaultType
= REG_EXPAND_SZ
<< RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
;
356 ret
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
, driver2_path
, query_table
, NULL
, NULL
);
357 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", ret
);
358 ok(!!image_path
.Buffer
, "image_path.Buffer is NULL.\n");
360 /* The image path name in the registry may contain NT symlinks (e.g. DOS
361 * drives), which are resolved before the callback is called on Windows 10. */
362 InitializeObjectAttributes(&attr
, &image_path
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
363 ret
= ZwOpenFile(&file
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
364 todo_wine
ok(!ret
, "Got unexpected status %#lx.\n", ret
);
367 ret
= ZwQueryObject(file
, ObjectNameInformation
, full_name_buffer
, sizeof(full_name_buffer
), NULL
);
368 ok(!ret
, "Got unexpected status %#lx.\n", ret
);
372 RtlInitUnicodeString(&name
, driver2_path
);
374 ret
= ZwLoadDriver(&name
);
375 ok(!ret
, "got %#lx\n", ret
);
377 ok(test_load_image_notify_count
== 2, "Got unexpected test_load_image_notify_count %u.\n",
378 test_load_image_notify_count
);
379 ok(test_image_info
.ImageAddressingMode
== IMAGE_ADDRESSING_MODE_32BIT
,
380 "Got unexpected ImageAddressingMode %#x.\n", test_image_info
.ImageAddressingMode
);
381 ok(test_image_info
.SystemModeImage
,
382 "Got unexpected SystemModeImage %#x.\n", test_image_info
.SystemModeImage
);
383 ok(!wcscmp(test_load_image_name
, image_path
.Buffer
) /* Win < 10 */
384 || !wcscmp(test_load_image_name
, full_name
->Name
.Buffer
),
385 "Expected image path name %ls, got %ls.\n", full_name
->Name
.Buffer
, test_load_image_name
);
387 test_load_image_notify_count
= 0;
389 ret
= ZwLoadDriver(&name
);
390 ok(ret
== STATUS_IMAGE_ALREADY_LOADED
, "got %#lx\n", ret
);
392 ret
= ZwUnloadDriver(&name
);
393 ok(!ret
, "got %#lx\n", ret
);
395 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
396 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", ret
);
397 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
398 ok(ret
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", ret
);
399 ret
= PsRemoveLoadImageNotifyRoutine(test_load_image_notify_routine
);
400 ok(ret
== STATUS_PROCEDURE_NOT_FOUND
, "Got unexpected status %#lx.\n", ret
);
402 ok(test_load_image_notify_count
== 0, "Got unexpected test_load_image_notify_count %u.\n",
403 test_load_image_notify_count
);
404 RtlFreeUnicodeString(&image_path
);
407 static NTSTATUS
wait_single(void *obj
, ULONGLONG timeout
)
409 LARGE_INTEGER integer
;
411 integer
.QuadPart
= timeout
;
412 return KeWaitForSingleObject(obj
, Executive
, KernelMode
, FALSE
, &integer
);
415 static NTSTATUS
wait_multiple(ULONG count
, void *objs
[], WAIT_TYPE wait_type
, ULONGLONG timeout
)
417 LARGE_INTEGER integer
;
419 integer
.QuadPart
= timeout
;
420 return KeWaitForMultipleObjects(count
, objs
, wait_type
, Executive
, KernelMode
, FALSE
, &integer
, NULL
);
423 static NTSTATUS
wait_single_handle(HANDLE handle
, ULONGLONG timeout
)
425 LARGE_INTEGER integer
;
427 integer
.QuadPart
= timeout
;
428 return ZwWaitForSingleObject(handle
, FALSE
, &integer
);
431 static void test_current_thread(BOOL is_system
)
433 PROCESS_BASIC_INFORMATION info
;
434 DISPATCHER_HEADER
*header
;
435 HANDLE process_handle
, id
;
440 current
= IoGetCurrentProcess();
441 ok(current
!= NULL
, "Expected current process to be non-NULL\n");
443 header
= (DISPATCHER_HEADER
*)current
;
444 ok(header
->Type
== 3, "header->Type != 3, = %u\n", header
->Type
);
445 ret
= wait_single(current
, 0);
446 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
449 ok(current
== *pPsInitialSystemProcess
, "current != PsInitialSystemProcess\n");
451 ok(current
!= *pPsInitialSystemProcess
, "current == PsInitialSystemProcess\n");
453 ok(PsGetProcessId(current
) == PsGetCurrentProcessId(), "process IDs don't match\n");
454 ok(PsGetThreadProcessId((PETHREAD
)KeGetCurrentThread()) == PsGetCurrentProcessId(), "process IDs don't match\n");
456 thread
= PsGetCurrentThread();
457 ret
= wait_single( thread
, 0 );
458 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
460 ok(PsGetThreadId((PETHREAD
)KeGetCurrentThread()) == PsGetCurrentThreadId(), "thread IDs don't match\n");
461 ok(PsIsSystemThread((PETHREAD
)KeGetCurrentThread()) == is_system
, "unexpected system thread\n");
462 ok(ExGetPreviousMode() == is_system
? KernelMode
: UserMode
, "previous mode is not correct\n");
465 ok(create_caller_thread
== KeGetCurrentThread(), "thread is not create caller thread\n");
466 ok(create_irp_thread
== (PETHREAD
)KeGetCurrentThread(), "thread of create request is not current thread\n");
469 ret
= ObOpenObjectByPointer(current
, OBJ_KERNEL_HANDLE
, NULL
, PROCESS_QUERY_INFORMATION
, NULL
, KernelMode
, &process_handle
);
470 ok(!ret
, "ObOpenObjectByPointer failed: %#lx\n", ret
);
472 ret
= ZwQueryInformationProcess(process_handle
, ProcessBasicInformation
, &info
, sizeof(info
), NULL
);
473 ok(!ret
, "ZwQueryInformationProcess failed: %#lx\n", ret
);
475 id
= PsGetProcessInheritedFromUniqueProcessId(current
);
476 ok(id
== (HANDLE
)info
.InheritedFromUniqueProcessId
, "unexpected process id %p\n", id
);
478 ret
= ZwClose(process_handle
);
479 ok(!ret
, "ZwClose failed: %#lx\n", ret
);
482 static void test_critical_region(BOOL is_dispatcher
)
486 KeEnterCriticalRegion();
487 KeEnterCriticalRegion();
489 result
= KeAreApcsDisabled();
490 ok(result
== TRUE
, "KeAreApcsDisabled returned %x\n", result
);
491 KeLeaveCriticalRegion();
493 result
= KeAreApcsDisabled();
494 ok(result
== TRUE
, "KeAreApcsDisabled returned %x\n", result
);
495 KeLeaveCriticalRegion();
497 result
= KeAreApcsDisabled();
498 ok(result
== is_dispatcher
|| broken(is_dispatcher
&& !result
),
499 "KeAreApcsDisabled returned %x\n", result
);
502 static void sleep_1ms(void)
504 LARGE_INTEGER timeout
;
506 timeout
.QuadPart
= -1 * 10000;
507 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
510 static void sleep(void)
512 LARGE_INTEGER timeout
;
513 timeout
.QuadPart
= -20 * 10000;
514 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
517 static HANDLE
create_thread(PKSTART_ROUTINE proc
, void *arg
)
519 OBJECT_ATTRIBUTES attr
= {0};
523 attr
.Length
= sizeof(attr
);
524 attr
.Attributes
= OBJ_KERNEL_HANDLE
;
525 ret
= PsCreateSystemThread(&thread
, THREAD_ALL_ACCESS
, &attr
, NULL
, NULL
, proc
, arg
);
526 ok(!ret
, "got %#lx\n", ret
);
531 static void join_thread(HANDLE thread
)
535 ret
= ZwWaitForSingleObject(thread
, FALSE
, NULL
);
536 ok(!ret
, "got %#lx\n", ret
);
537 ret
= ZwClose(thread
);
538 ok(!ret
, "got %#lx\n", ret
);
541 static void run_thread(PKSTART_ROUTINE proc
, void *arg
)
543 HANDLE thread
= create_thread(proc
, arg
);
547 static KMUTEX test_mutex
;
549 static void WINAPI
mutex_thread(void *arg
)
551 NTSTATUS ret
, expect
= (NTSTATUS
)(DWORD_PTR
)arg
;
553 ret
= wait_single(&test_mutex
, 0);
554 ok(ret
== expect
, "expected %#lx, got %#lx\n", expect
, ret
);
556 if (!ret
) KeReleaseMutex(&test_mutex
, FALSE
);
557 PsTerminateSystemThread(STATUS_SUCCESS
);
560 static KEVENT remove_lock_ready
;
562 static void WINAPI
remove_lock_thread(void *arg
)
564 IO_REMOVE_LOCK
*lock
= arg
;
567 ret
= IoAcquireRemoveLockEx(lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
568 ok(ret
== STATUS_SUCCESS
, "got %#lx\n", ret
);
569 KeSetEvent(&remove_lock_ready
, 0, FALSE
);
571 IoReleaseRemoveLockAndWaitEx(lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
572 PsTerminateSystemThread(STATUS_SUCCESS
);
575 struct test_sync_dpc_context
580 static void WINAPI
test_sync_dpc(KDPC
*dpc
, void *context
, void *system_argument1
, void *system_argument2
)
582 struct test_sync_dpc_context
*c
= context
;
587 static void test_sync(void)
589 static const ULONG wine_tag
= 0x454e4957; /* WINE */
590 struct test_sync_dpc_context dpc_context
;
591 KEVENT manual_event
, auto_event
, *event
;
592 KSEMAPHORE semaphore
, semaphore2
;
593 IO_REMOVE_LOCK remove_lock
;
594 LARGE_INTEGER timeout
;
595 OBJECT_ATTRIBUTES attr
;
596 HANDLE handle
, thread
;
603 KeInitializeEvent(&manual_event
, NotificationEvent
, FALSE
);
605 ret
= wait_single(&manual_event
, 0);
606 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
608 ret
= KeReadStateEvent(&manual_event
);
609 ok(ret
== 0, "got %ld\n", ret
);
611 KeSetEvent(&manual_event
, 0, FALSE
);
613 ret
= KeReadStateEvent(&manual_event
);
614 ok(ret
== 1, "got %ld\n", ret
);
616 ret
= wait_single(&manual_event
, 0);
617 ok(ret
== 0, "got %#lx\n", ret
);
619 ret
= wait_single(&manual_event
, 0);
620 ok(ret
== 0, "got %#lx\n", ret
);
622 KeResetEvent(&manual_event
);
624 ret
= wait_single(&manual_event
, 0);
625 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
627 KeInitializeEvent(&auto_event
, SynchronizationEvent
, FALSE
);
629 ret
= wait_single(&auto_event
, 0);
630 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
632 KeSetEvent(&auto_event
, 0, FALSE
);
634 ret
= wait_single(&auto_event
, 0);
635 ok(ret
== 0, "got %#lx\n", ret
);
637 ret
= wait_single(&auto_event
, 0);
638 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
640 KeInitializeEvent(&auto_event
, SynchronizationEvent
, TRUE
);
642 ret
= wait_single(&auto_event
, 0);
643 ok(ret
== 0, "got %#lx\n", ret
);
645 objs
[0] = &manual_event
;
646 objs
[1] = &auto_event
;
648 ret
= wait_multiple(2, objs
, WaitAny
, 0);
649 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
651 KeSetEvent(&manual_event
, 0, FALSE
);
652 KeSetEvent(&auto_event
, 0, FALSE
);
654 ret
= wait_multiple(2, objs
, WaitAny
, 0);
655 ok(ret
== 0, "got %#lx\n", ret
);
657 ret
= wait_single(&auto_event
, 0);
658 ok(ret
== 0, "got %#lx\n", ret
);
660 KeResetEvent(&manual_event
);
661 KeSetEvent(&auto_event
, 0, FALSE
);
663 ret
= wait_multiple(2, objs
, WaitAny
, 0);
664 ok(ret
== 1, "got %#lx\n", ret
);
666 ret
= wait_multiple(2, objs
, WaitAny
, 0);
667 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
669 KeSetEvent(&manual_event
, 0, FALSE
);
670 KeSetEvent(&auto_event
, 0, FALSE
);
672 ret
= wait_multiple(2, objs
, WaitAll
, 0);
673 ok(ret
== 0, "got %#lx\n", ret
);
675 ret
= wait_multiple(2, objs
, WaitAll
, 0);
676 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
678 KeSetEvent(&auto_event
, 0, FALSE
);
679 KeResetEvent(&manual_event
);
681 ret
= wait_multiple(2, objs
, WaitAll
, 0);
682 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
684 ret
= wait_single(&auto_event
, 0);
685 ok(ret
== 0, "got %#lx\n", ret
);
687 objs
[0] = &auto_event
;
688 objs
[1] = &manual_event
;
689 KeSetEvent(&manual_event
, 0, FALSE
);
690 KeSetEvent(&auto_event
, 0, FALSE
);
692 ret
= wait_multiple(2, objs
, WaitAny
, 0);
693 ok(ret
== 0, "got %#lx\n", ret
);
695 ret
= wait_multiple(2, objs
, WaitAny
, 0);
696 ok(ret
== 1, "got %#lx\n", ret
);
698 ret
= wait_multiple(2, objs
, WaitAny
, 0);
699 ok(ret
== 1, "got %#lx\n", ret
);
701 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
702 ret
= ZwCreateEvent(&handle
, SYNCHRONIZE
, &attr
, NotificationEvent
, TRUE
);
703 ok(!ret
, "ZwCreateEvent failed: %#lx\n", ret
);
705 ret
= ObReferenceObjectByHandle(handle
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, (void **)&event
, NULL
);
706 ok(!ret
, "ObReferenceObjectByHandle failed: %#lx\n", ret
);
709 ret
= wait_single(event
, 0);
710 ok(ret
== 0, "got %#lx\n", ret
);
711 ret
= KeReadStateEvent(event
);
712 ok(ret
== 1, "got %ld\n", ret
);
714 ret
= KeReadStateEvent(event
);
715 ok(ret
== 0, "got %ld\n", ret
);
716 ret
= wait_single(event
, 0);
717 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
718 ret
= wait_single_handle(handle
, 0);
719 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
721 KeSetEvent(event
, 0, FALSE
);
722 ret
= wait_single(event
, 0);
723 ok(ret
== 0, "got %#lx\n", ret
);
724 ret
= wait_single_handle(handle
, 0);
725 ok(!ret
, "got %#lx\n", ret
);
728 ObDereferenceObject(event
);
730 event
= IoCreateSynchronizationEvent(NULL
, &handle
);
731 ok(event
!= NULL
, "IoCreateSynchronizationEvent failed\n");
733 ret
= wait_single(event
, 0);
734 ok(ret
== 0, "got %#lx\n", ret
);
736 ret
= wait_single(event
, 0);
737 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
738 ret
= wait_single_handle(handle
, 0);
739 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
741 ret
= ZwSetEvent(handle
, NULL
);
742 ok(!ret
, "NtSetEvent returned %#lx\n", ret
);
743 ret
= wait_single(event
, 0);
744 ok(ret
== 0, "got %#lx\n", ret
);
745 ret
= wait_single_handle(handle
, 0);
746 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
748 KeSetEvent(event
, 0, FALSE
);
749 ret
= wait_single_handle(handle
, 0);
750 ok(!ret
, "got %#lx\n", ret
);
751 ret
= wait_single(event
, 0);
752 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
754 ret
= ZwClose(handle
);
755 ok(!ret
, "ZwClose returned %#lx\n", ret
);
757 /* test semaphores */
758 KeInitializeSemaphore(&semaphore
, 0, 5);
760 ret
= wait_single(&semaphore
, 0);
761 ok(ret
== STATUS_TIMEOUT
, "got %lu\n", ret
);
763 ret
= KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
764 ok(ret
== 0, "got prev %ld\n", ret
);
766 ret
= KeReleaseSemaphore(&semaphore
, 0, 2, FALSE
);
767 ok(ret
== 1, "got prev %ld\n", ret
);
769 ret
= KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
770 ok(ret
== 3, "got prev %ld\n", ret
);
772 for (i
= 0; i
< 4; i
++)
774 ret
= wait_single(&semaphore
, 0);
775 ok(ret
== 0, "got %#lx\n", ret
);
778 ret
= wait_single(&semaphore
, 0);
779 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
781 KeInitializeSemaphore(&semaphore2
, 3, 5);
783 ret
= KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
784 ok(ret
== 3, "got prev %ld\n", ret
);
786 for (i
= 0; i
< 4; i
++)
788 ret
= wait_single(&semaphore2
, 0);
789 ok(ret
== 0, "got %#lx\n", ret
);
792 objs
[0] = &semaphore
;
793 objs
[1] = &semaphore2
;
795 ret
= wait_multiple(2, objs
, WaitAny
, 0);
796 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
798 KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
799 KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
801 ret
= wait_multiple(2, objs
, WaitAny
, 0);
802 ok(ret
== 0, "got %#lx\n", ret
);
804 ret
= wait_multiple(2, objs
, WaitAny
, 0);
805 ok(ret
== 1, "got %#lx\n", ret
);
807 ret
= wait_multiple(2, objs
, WaitAny
, 0);
808 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
810 KeReleaseSemaphore(&semaphore
, 0, 1, FALSE
);
811 KeReleaseSemaphore(&semaphore2
, 0, 1, FALSE
);
813 ret
= wait_multiple(2, objs
, WaitAll
, 0);
814 ok(ret
== 0, "got %#lx\n", ret
);
816 ret
= wait_multiple(2, objs
, WaitAny
, 0);
817 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
820 KeInitializeMutex(&test_mutex
, 0);
822 for (i
= 0; i
< 10; i
++)
824 ret
= wait_single(&test_mutex
, 0);
825 ok(ret
== 0, "got %#lx\n", ret
);
828 for (i
= 0; i
< 10; i
++)
830 ret
= KeReleaseMutex(&test_mutex
, FALSE
);
831 ok(ret
== i
- 9, "expected %d, got %ld\n", i
- 9, ret
);
834 run_thread(mutex_thread
, (void *)0);
836 ret
= wait_single(&test_mutex
, 0);
837 ok(ret
== 0, "got %#lx\n", ret
);
839 run_thread(mutex_thread
, (void *)STATUS_TIMEOUT
);
841 ret
= KeReleaseMutex(&test_mutex
, 0);
842 ok(ret
== 0, "got %#lx\n", ret
);
844 run_thread(mutex_thread
, (void *)0);
847 KeInitializeTimerEx(&timer
, NotificationTimer
);
849 timeout
.QuadPart
= -20 * 10000;
850 KeSetTimerEx(&timer
, timeout
, 0, NULL
);
852 ret
= wait_single(&timer
, 0);
853 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
855 ret
= wait_single(&timer
, -40 * 10000);
856 ok(ret
== 0, "got %#lx\n", ret
);
858 ret
= wait_single(&timer
, 0);
859 ok(ret
== 0, "got %#lx\n", ret
);
861 KeCancelTimer(&timer
);
862 KeInitializeTimerEx(&timer
, SynchronizationTimer
);
864 memset(&dpc_context
, 0, sizeof(dpc_context
));
865 KeInitializeDpc(&dpc
, test_sync_dpc
, &dpc_context
);
867 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
869 ret
= wait_single(&timer
, 0);
870 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
871 ok(!dpc_context
.called
, "DPC was called unexpectedly.\n");
873 ret
= wait_single(&timer
, -40 * 10000);
874 ok(ret
== 0, "got %#lx\n", ret
);
876 ok(dpc_context
.called
, "DPC was not called.\n");
878 ret
= wait_single(&timer
, -40 * 10000);
879 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
881 KeCancelTimer(&timer
);
882 KeSetTimerEx(&timer
, timeout
, 20, NULL
);
884 ret
= wait_single(&timer
, 0);
885 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
887 ret
= wait_single(&timer
, -40 * 10000);
888 ok(ret
== 0, "got %#lx\n", ret
);
890 ret
= wait_single(&timer
, 0);
891 /* aliasing makes it sometimes succeeds, try again in that case */
892 if (ret
== 0) ret
= wait_single(&timer
, 0);
893 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
895 ret
= wait_single(&timer
, -40 * 10000);
896 ok(ret
== 0, "got %#lx\n", ret
);
898 ret
= wait_single(&timer
, -40 * 10000);
899 ok(ret
== 0, "got %#lx\n", ret
);
901 KeCancelTimer(&timer
);
903 /* Test cancelling timer. */
904 dpc_context
.called
= 0;
905 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
907 ret
= wait_single(&timer
, 0);
908 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
909 ok(!dpc_context
.called
, "DPC was called.\n");
911 KeCancelTimer(&timer
);
912 dpc_context
.called
= 0;
913 ret
= wait_single(&timer
, -40 * 10000);
914 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
915 ok(!dpc_context
.called
, "DPC was called.\n");
917 KeSetTimerEx(&timer
, timeout
, 20, &dpc
);
918 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
919 ret
= wait_single(&timer
, 0);
920 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
922 ret
= wait_single(&timer
, -40 * 10000);
923 ok(ret
== 0, "got %#lx\n", ret
);
925 ret
= wait_single(&timer
, 0);
926 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
928 ret
= wait_single(&timer
, -40 * 10000);
929 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
931 ret
= wait_single(&timer
, -40 * 10000);
932 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
934 KeCancelTimer(&timer
);
935 /* Test reinitializing timer. */
936 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
937 KeInitializeTimerEx(&timer
, SynchronizationTimer
);
938 dpc_context
.called
= 0;
939 ret
= wait_single(&timer
, -40 * 10000);
940 ok(ret
== 0, "got %#lx\n", ret
);
942 todo_wine
ok(dpc_context
.called
, "DPC was not called.\n");
944 ret
= wait_single(&timer
, 0);
945 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
947 todo_wine
ok(dpc_context
.called
, "DPC was not called.\n");
949 dpc_context
.called
= 0;
950 KeSetTimerEx(&timer
, timeout
, 0, &dpc
);
951 ret
= wait_single(&timer
, -40 * 10000);
952 ok(ret
== 0, "got %#lx\n", ret
);
954 ok(dpc_context
.called
, "DPC was not called.\n");
956 KeCancelTimer(&timer
);
959 IoInitializeRemoveLockEx(&remove_lock
, wine_tag
, 0, 0, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
961 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
962 ok(ret
== STATUS_SUCCESS
, "got %#lx\n", ret
);
964 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
966 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
967 ok(ret
== STATUS_SUCCESS
, "got %#lx\n", ret
);
969 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
970 ok(ret
== STATUS_SUCCESS
, "got %#lx\n", ret
);
972 KeInitializeEvent(&remove_lock_ready
, SynchronizationEvent
, FALSE
);
973 thread
= create_thread(remove_lock_thread
, &remove_lock
);
974 ret
= wait_single(&remove_lock_ready
, -1000 * 10000);
975 ok(!ret
, "got %#lx\n", ret
);
976 ret
= wait_single_handle(thread
, -50 * 10000);
977 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
979 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
980 ok(ret
== STATUS_DELETE_PENDING
, "got %#lx\n", ret
);
982 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
983 ret
= wait_single_handle(thread
, 0);
984 ok(ret
== STATUS_TIMEOUT
, "got %#lx\n", ret
);
986 IoReleaseRemoveLockEx(&remove_lock
, NULL
, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
987 ret
= wait_single_handle(thread
, -10000 * 10000);
988 ok(ret
== STATUS_SUCCESS
, "got %#lx\n", ret
);
990 ret
= IoAcquireRemoveLockEx(&remove_lock
, NULL
, "", 1, sizeof(IO_REMOVE_LOCK_COMMON_BLOCK
));
991 ok(ret
== STATUS_DELETE_PENDING
, "got %#lx\n", ret
);
994 static void test_call_driver(DEVICE_OBJECT
*device
)
996 IO_STACK_LOCATION
*irpsp
;
997 IO_STATUS_BLOCK iosb
;
1002 iosb
.Status
= 0xdeadbeef;
1003 iosb
.Information
= 0xdeadbeef;
1004 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1005 ok(irp
->UserIosb
== &iosb
, "unexpected UserIosb\n");
1006 ok(!irp
->Cancel
, "Cancel = %x\n", irp
->Cancel
);
1007 ok(!irp
->CancelRoutine
, "CancelRoutine = %p\n", irp
->CancelRoutine
);
1008 ok(!irp
->UserEvent
, "UserEvent = %p\n", irp
->UserEvent
);
1009 ok(irp
->CurrentLocation
== 2, "CurrentLocation = %u\n", irp
->CurrentLocation
);
1010 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
1011 "IRP thread is not the current thread\n");
1012 ok(!irp
->IoStatus
.Status
, "got status %#lx\n", irp
->IoStatus
.Status
);
1013 ok(!irp
->IoStatus
.Information
, "got information %#I64x\n", (UINT64
)irp
->IoStatus
.Information
);
1014 ok(iosb
.Status
== 0xdeadbeef, "got status %#lx\n", iosb
.Status
);
1015 ok(iosb
.Information
== 0xdeadbeef, "got information %#I64x\n", (UINT64
)iosb
.Information
);
1017 irpsp
= IoGetNextIrpStackLocation(irp
);
1018 ok(irpsp
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
, "MajorFunction = %u\n", irpsp
->MajorFunction
);
1019 ok(!irpsp
->DeviceObject
, "DeviceObject = %p\n", irpsp
->DeviceObject
);
1020 ok(!irpsp
->FileObject
, "FileObject = %p\n", irpsp
->FileObject
);
1021 ok(!irpsp
->CompletionRoutine
, "CompletionRoutine = %p\n", irpsp
->CompletionRoutine
);
1023 status
= IoCallDriver(device
, irp
);
1024 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1025 ok(!irp
->IoStatus
.Status
, "got status %#lx\n", irp
->IoStatus
.Status
);
1026 ok(!irp
->IoStatus
.Information
, "got information %#I64x\n", (UINT64
)irp
->IoStatus
.Information
);
1027 ok(iosb
.Status
== 0xdeadbeef, "got status %#lx\n", iosb
.Status
);
1028 ok(iosb
.Information
== 0xdeadbeef, "got information %#I64x\n", (UINT64
)iosb
.Information
);
1030 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1031 irp
->IoStatus
.Information
= 123;
1032 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1033 ok(iosb
.Status
== STATUS_SUCCESS
, "got status %#lx\n", iosb
.Status
);
1034 ok(iosb
.Information
== 123, "got information %#I64x\n", (UINT64
)iosb
.Information
);
1036 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
1038 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &event
, &iosb
);
1039 ok(irp
->UserIosb
== &iosb
, "unexpected UserIosb\n");
1040 ok(!irp
->Cancel
, "Cancel = %x\n", irp
->Cancel
);
1041 ok(!irp
->CancelRoutine
, "CancelRoutine = %p\n", irp
->CancelRoutine
);
1042 ok(irp
->UserEvent
== &event
, "UserEvent = %p\n", irp
->UserEvent
);
1043 ok(irp
->CurrentLocation
== 2, "CurrentLocation = %u\n", irp
->CurrentLocation
);
1044 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
1045 "IRP thread is not the current thread\n");
1047 irpsp
= IoGetNextIrpStackLocation(irp
);
1048 ok(irpsp
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
, "MajorFunction = %u\n", irpsp
->MajorFunction
);
1049 ok(!irpsp
->DeviceObject
, "DeviceObject = %p\n", irpsp
->DeviceObject
);
1050 ok(!irpsp
->FileObject
, "FileObject = %p\n", irpsp
->FileObject
);
1051 ok(!irpsp
->CompletionRoutine
, "CompletionRoutine = %p\n", irpsp
->CompletionRoutine
);
1053 status
= wait_single(&event
, 0);
1054 ok(status
== STATUS_TIMEOUT
, "got %#lx\n", status
);
1056 status
= IoCallDriver(device
, irp
);
1057 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1059 status
= wait_single(&event
, 0);
1060 ok(status
== STATUS_TIMEOUT
, "got %#lx\n", status
);
1062 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1063 irp
->IoStatus
.Information
= 0;
1064 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1066 status
= wait_single(&event
, 0);
1067 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
1070 static int cancel_cnt
;
1072 static void WINAPI
cancel_irp(DEVICE_OBJECT
*device
, IRP
*irp
)
1074 IoReleaseCancelSpinLock(irp
->CancelIrql
);
1075 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1076 ok(!irp
->CancelRoutine
, "CancelRoutine = %p\n", irp
->CancelRoutine
);
1077 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
1078 irp
->IoStatus
.Information
= 0;
1082 static void WINAPI
cancel_ioctl_irp(DEVICE_OBJECT
*device
, IRP
*irp
)
1084 IoReleaseCancelSpinLock(irp
->CancelIrql
);
1085 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
1086 irp
->IoStatus
.Information
= 0;
1088 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1091 static NTSTATUS WINAPI
cancel_test_completion(DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
1093 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1094 *(BOOL
*)context
= TRUE
;
1095 return STATUS_SUCCESS
;
1098 static void test_cancel_irp(DEVICE_OBJECT
*device
)
1100 IO_STACK_LOCATION
*irpsp
;
1101 IO_STATUS_BLOCK iosb
;
1103 BOOL completion_called
;
1107 /* cancel IRP with no cancel routine */
1108 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1110 r
= IoCancelIrp(irp
);
1111 ok(!r
, "IoCancelIrp returned %x\n", r
);
1112 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1114 r
= IoCancelIrp(irp
);
1115 ok(!r
, "IoCancelIrp returned %x\n", r
);
1118 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1120 /* cancel IRP with cancel routine */
1121 status
= IoCallDriver(device
, irp
);
1122 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1124 ok(irp
->CurrentLocation
== 1, "CurrentLocation = %u\n", irp
->CurrentLocation
);
1125 irpsp
= IoGetCurrentIrpStackLocation(irp
);
1126 ok(irpsp
->DeviceObject
== device
, "DeviceObject = %p\n", irpsp
->DeviceObject
);
1128 IoSetCancelRoutine(irp
, cancel_irp
);
1130 r
= IoCancelIrp(irp
);
1131 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1132 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1133 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1136 r
= IoCancelIrp(irp
);
1137 ok(!r
, "IoCancelIrp returned %x\n", r
);
1138 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1139 ok(!cancel_cnt
, "cancel_cnt = %d\n", cancel_cnt
);
1141 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1143 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_ERROR */
1144 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1145 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, FALSE
, TRUE
);
1147 status
= IoCallDriver(device
, irp
);
1148 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1150 IoSetCancelRoutine(irp
, cancel_irp
);
1152 r
= IoCancelIrp(irp
);
1153 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1154 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1155 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1157 completion_called
= FALSE
;
1158 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1159 ok(completion_called
, "completion not called\n");
1161 /* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_CANCEL flag */
1162 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1163 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, TRUE
, FALSE
);
1165 status
= IoCallDriver(device
, irp
);
1166 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1168 IoSetCancelRoutine(irp
, cancel_irp
);
1170 r
= IoCancelIrp(irp
);
1171 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1172 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1173 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1175 completion_called
= FALSE
;
1176 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1177 ok(completion_called
, "completion not called\n");
1179 /* cancel IRP with cancel and completion routines, but no SL_INVOKE_ON_ERROR nor SL_INVOKE_ON_CANCEL flag */
1180 irp
= IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0, NULL
, &iosb
);
1181 IoSetCompletionRoutine(irp
, cancel_test_completion
, &completion_called
, TRUE
, FALSE
, FALSE
);
1183 status
= IoCallDriver(device
, irp
);
1184 ok(status
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", status
);
1186 IoSetCancelRoutine(irp
, cancel_irp
);
1188 r
= IoCancelIrp(irp
);
1189 ok(r
== TRUE
, "IoCancelIrp returned %x\n", r
);
1190 ok(irp
->Cancel
== TRUE
, "Cancel = %x\n", irp
->Cancel
);
1191 ok(cancel_cnt
== 1, "cancel_cnt = %d\n", cancel_cnt
);
1193 completion_called
= FALSE
;
1194 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1195 ok(!completion_called
, "completion not called\n");
1198 static int callout_cnt
;
1200 static void WINAPI
callout(void *parameter
)
1202 ok(parameter
== (void*)0xdeadbeef, "parameter = %p\n", parameter
);
1206 static void test_stack_callout(void)
1208 NTSTATUS (WINAPI
*pKeExpandKernelStackAndCallout
)(PEXPAND_STACK_CALLOUT
,void*,SIZE_T
);
1209 NTSTATUS (WINAPI
*pKeExpandKernelStackAndCalloutEx
)(PEXPAND_STACK_CALLOUT
,void*,SIZE_T
,BOOLEAN
,void*);
1212 pKeExpandKernelStackAndCallout
= get_proc_address("KeExpandKernelStackAndCallout");
1213 if (pKeExpandKernelStackAndCallout
)
1216 ret
= pKeExpandKernelStackAndCallout(callout
, (void*)0xdeadbeef, 4096);
1217 ok(ret
== STATUS_SUCCESS
, "KeExpandKernelStackAndCallout failed: %#lx\n", ret
);
1218 ok(callout_cnt
== 1, "callout_cnt = %u\n", callout_cnt
);
1220 else win_skip("KeExpandKernelStackAndCallout is not available\n");
1222 pKeExpandKernelStackAndCalloutEx
= get_proc_address("KeExpandKernelStackAndCalloutEx");
1223 if (pKeExpandKernelStackAndCalloutEx
)
1226 ret
= pKeExpandKernelStackAndCalloutEx(callout
, (void*)0xdeadbeef, 4096, FALSE
, NULL
);
1227 ok(ret
== STATUS_SUCCESS
, "KeExpandKernelStackAndCalloutEx failed: %#lx\n", ret
);
1228 ok(callout_cnt
== 1, "callout_cnt = %u\n", callout_cnt
);
1230 else win_skip("KeExpandKernelStackAndCalloutEx is not available\n");
1233 static void test_lookaside_list(void)
1235 NPAGED_LOOKASIDE_LIST list
;
1236 PAGED_LOOKASIDE_LIST paged_list
;
1237 ULONG tag
= 0x454e4957; /* WINE */
1239 ExInitializeNPagedLookasideList(&list
, NULL
, NULL
, POOL_NX_ALLOCATION
, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 0);
1240 ok(list
.L
.Depth
== 4, "Expected 4 got %u\n", list
.L
.Depth
);
1241 ok(list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", list
.L
.MaximumDepth
);
1242 ok(list
.L
.TotalAllocates
== 0, "Expected 0 got %lu\n", list
.L
.TotalAllocates
);
1243 ok(list
.L
.AllocateMisses
== 0, "Expected 0 got %lu\n", list
.L
.AllocateMisses
);
1244 ok(list
.L
.TotalFrees
== 0, "Expected 0 got %lu\n", list
.L
.TotalFrees
);
1245 ok(list
.L
.FreeMisses
== 0, "Expected 0 got %lu\n", list
.L
.FreeMisses
);
1246 ok(list
.L
.Type
== (NonPagedPool
|POOL_NX_ALLOCATION
),
1247 "Expected NonPagedPool|POOL_NX_ALLOCATION got %u\n", list
.L
.Type
);
1248 ok(list
.L
.Tag
== tag
, "Expected %lx got %lx\n", tag
, list
.L
.Tag
);
1249 ok(list
.L
.Size
== LOOKASIDE_MINIMUM_BLOCK_SIZE
, "got %lu\n", list
.L
.Size
);
1250 ok(list
.L
.LastTotalAllocates
== 0,"Expected 0 got %lu\n", list
.L
.LastTotalAllocates
);
1251 ok(list
.L
.LastAllocateMisses
== 0,"Expected 0 got %lu\n", list
.L
.LastAllocateMisses
);
1252 ExDeleteNPagedLookasideList(&list
);
1255 ExInitializeNPagedLookasideList(&list
, NULL
, NULL
, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 20);
1256 ok(list
.L
.Depth
== 4, "Expected 4 got %u\n", list
.L
.Depth
);
1257 ok(list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", list
.L
.MaximumDepth
);
1258 ok(list
.L
.Type
== NonPagedPool
, "Expected NonPagedPool got %u\n", list
.L
.Type
);
1259 ExDeleteNPagedLookasideList(&list
);
1261 ExInitializePagedLookasideList(&paged_list
, NULL
, NULL
, POOL_NX_ALLOCATION
, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 0);
1262 ok(paged_list
.L
.Depth
== 4, "Expected 4 got %u\n", paged_list
.L
.Depth
);
1263 ok(paged_list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", paged_list
.L
.MaximumDepth
);
1264 ok(paged_list
.L
.TotalAllocates
== 0, "Expected 0 got %lu\n", paged_list
.L
.TotalAllocates
);
1265 ok(paged_list
.L
.AllocateMisses
== 0, "Expected 0 got %lu\n", paged_list
.L
.AllocateMisses
);
1266 ok(paged_list
.L
.TotalFrees
== 0, "Expected 0 got %lu\n", paged_list
.L
.TotalFrees
);
1267 ok(paged_list
.L
.FreeMisses
== 0, "Expected 0 got %lu\n", paged_list
.L
.FreeMisses
);
1268 ok(paged_list
.L
.Type
== (PagedPool
|POOL_NX_ALLOCATION
),
1269 "Expected PagedPool|POOL_NX_ALLOCATION got %u\n", paged_list
.L
.Type
);
1270 ok(paged_list
.L
.Tag
== tag
, "Expected %lx got %lx\n", tag
, paged_list
.L
.Tag
);
1271 ok(paged_list
.L
.Size
== LOOKASIDE_MINIMUM_BLOCK_SIZE
, "got %lu\n", paged_list
.L
.Size
);
1272 ok(paged_list
.L
.LastTotalAllocates
== 0,"Expected 0 got %lu\n", paged_list
.L
.LastTotalAllocates
);
1273 ok(paged_list
.L
.LastAllocateMisses
== 0,"Expected 0 got %lu\n", paged_list
.L
.LastAllocateMisses
);
1274 ExDeletePagedLookasideList(&paged_list
);
1276 paged_list
.L
.Depth
= 0;
1277 ExInitializePagedLookasideList(&paged_list
, NULL
, NULL
, 0, LOOKASIDE_MINIMUM_BLOCK_SIZE
, tag
, 20);
1278 ok(paged_list
.L
.Depth
== 4, "Expected 4 got %u\n", paged_list
.L
.Depth
);
1279 ok(paged_list
.L
.MaximumDepth
== 256, "Expected 256 got %u\n", paged_list
.L
.MaximumDepth
);
1280 ok(paged_list
.L
.Type
== PagedPool
, "Expected PagedPool got %u\n", paged_list
.L
.Type
);
1281 ExDeletePagedLookasideList(&paged_list
);
1284 static void test_version(void)
1286 USHORT
*pNtBuildNumber
;
1289 pNtBuildNumber
= get_proc_address("NtBuildNumber");
1290 ok(!!pNtBuildNumber
, "Could not get pointer to NtBuildNumber\n");
1292 PsGetVersion(NULL
, NULL
, &build
, NULL
);
1293 ok(*pNtBuildNumber
== build
, "Expected build number %lu, got %u\n", build
, *pNtBuildNumber
);
1296 static void WINAPI
thread_proc(void *arg
)
1298 PsTerminateSystemThread(STATUS_SUCCESS
);
1301 static void test_ob_reference(void)
1303 POBJECT_TYPE (WINAPI
*pObGetObjectType
)(void*);
1304 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
1305 HANDLE event_handle
, file_handle
, file_handle2
, thread_handle
, handle
;
1306 DISPATCHER_HEADER
*header
;
1309 POBJECT_TYPE obj1_type
;
1310 UNICODE_STRING pathU
;
1314 pObGetObjectType
= get_proc_address("ObGetObjectType");
1315 if (!pObGetObjectType
)
1316 win_skip("ObGetObjectType not found\n");
1318 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1319 status
= ZwCreateEvent(&event_handle
, SYNCHRONIZE
, &attr
, NotificationEvent
, TRUE
);
1320 ok(!status
, "ZwCreateEvent failed: %#lx\n", status
);
1322 RtlInitUnicodeString(&pathU
, L
"\\??\\C:\\windows\\winetest_ntoskrnl_file.tmp");
1323 attr
.ObjectName
= &pathU
;
1324 attr
.Attributes
= OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
;
1325 status
= ZwCreateFile(&file_handle
, DELETE
| FILE_WRITE_DATA
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0, 0, FILE_CREATE
,
1326 FILE_DELETE_ON_CLOSE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0);
1327 ok(!status
, "ZwCreateFile failed: %#lx\n", status
);
1329 status
= ZwDuplicateObject(NtCurrentProcess(), file_handle
, NtCurrentProcess(), &file_handle2
,
1330 0, OBJ_KERNEL_HANDLE
, DUPLICATE_SAME_ACCESS
);
1331 ok(!status
, "ZwDuplicateObject failed: %#lx\n", status
);
1333 InitializeObjectAttributes(&attr
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1334 status
= PsCreateSystemThread(&thread_handle
, SYNCHRONIZE
, &attr
, NULL
, NULL
, thread_proc
, NULL
);
1335 ok(!status
, "PsCreateSystemThread returned: %#lx\n", status
);
1337 status
= ObReferenceObjectByHandle(NULL
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, &obj1
, NULL
);
1338 ok(status
== STATUS_INVALID_HANDLE
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1340 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj1
, NULL
);
1341 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObReferenceObjectByHandle returned: %#lx\n", status
);
1343 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, NULL
, KernelMode
, &obj1
, NULL
);
1344 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1346 if (pObGetObjectType
)
1348 obj1_type
= pObGetObjectType(obj1
);
1349 ok(obj1_type
== *pExEventObjectType
, "ObGetObjectType returned %p\n", obj1_type
);
1352 if (sizeof(void *) != 4) /* avoid dealing with fastcall */
1354 ObfReferenceObject(obj1
);
1355 ObDereferenceObject(obj1
);
1358 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj2
, NULL
);
1359 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObReferenceObjectByHandle returned: %#lx\n", status
);
1361 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, *pExEventObjectType
, KernelMode
, &obj2
, NULL
);
1362 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1363 ok(obj1
== obj2
, "obj1 != obj2\n");
1365 ObDereferenceObject(obj2
);
1367 status
= ObReferenceObjectByHandle(event_handle
, SYNCHRONIZE
, NULL
, KernelMode
, &obj2
, NULL
);
1368 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1369 ok(obj1
== obj2
, "obj1 != obj2\n");
1371 ObDereferenceObject(obj2
);
1372 ObDereferenceObject(obj1
);
1374 status
= ObReferenceObjectByHandle(file_handle
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj1
, NULL
);
1375 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1377 status
= ObReferenceObjectByHandle(file_handle2
, SYNCHRONIZE
, *pIoFileObjectType
, KernelMode
, &obj2
, NULL
);
1378 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1379 ok(obj1
== obj2
, "obj1 != obj2\n");
1382 ok(file
->Type
== 5, "Type = %u\n", file
->Type
);
1384 ObDereferenceObject(obj1
);
1385 ObDereferenceObject(obj2
);
1387 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj1
, NULL
);
1388 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1390 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj2
, NULL
);
1391 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1392 ok(obj1
== obj2
, "obj1 != obj2\n");
1395 ok(header
->Type
== 6, "Type = %u\n", header
->Type
);
1397 status
= wait_single(header
, 0);
1398 ok(status
== 0 || status
== STATUS_TIMEOUT
, "got %#lx\n", status
);
1400 ObDereferenceObject(obj2
);
1402 status
= ObOpenObjectByPointer(obj1
, OBJ_KERNEL_HANDLE
, NULL
, 0, NULL
, KernelMode
, &handle
);
1403 ok(status
== STATUS_SUCCESS
, "ObOpenObjectByPointer failed: %#lx\n", status
);
1405 status
= ZwClose(handle
);
1406 ok(!status
, "ZwClose failed: %#lx\n", status
);
1408 status
= ObReferenceObjectByHandle(thread_handle
, SYNCHRONIZE
, *pPsThreadType
, KernelMode
, &obj2
, NULL
);
1409 ok(!status
, "ObReferenceObjectByHandle failed: %#lx\n", status
);
1410 ok(obj1
== obj2
, "obj1 != obj2\n");
1411 ObDereferenceObject(obj2
);
1413 status
= ObOpenObjectByPointer(obj1
, OBJ_KERNEL_HANDLE
, NULL
, 0, *pIoFileObjectType
, KernelMode
, &handle
);
1414 ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "ObOpenObjectByPointer returned: %#lx\n", status
);
1416 ObDereferenceObject(obj1
);
1418 status
= ZwClose(thread_handle
);
1419 ok(!status
, "ZwClose failed: %#lx\n", status
);
1421 status
= ZwClose(event_handle
);
1422 ok(!status
, "ZwClose failed: %#lx\n", status
);
1424 status
= ZwClose(file_handle
);
1425 ok(!status
, "ZwClose failed: %#lx\n", status
);
1427 status
= ZwClose(file_handle2
);
1428 ok(!status
, "ZwClose failed: %#lx\n", status
);
1431 static void check_resource_(int line
, ERESOURCE
*resource
, ULONG exclusive_waiters
,
1432 ULONG shared_waiters
, BOOLEAN exclusive
, ULONG shared_count
)
1437 count
= ExGetExclusiveWaiterCount(resource
);
1438 ok_(__FILE__
, line
)(count
== exclusive_waiters
,
1439 "expected %lu exclusive waiters, got %lu\n", exclusive_waiters
, count
);
1440 count
= ExGetSharedWaiterCount(resource
);
1441 ok_(__FILE__
, line
)(count
== shared_waiters
,
1442 "expected %lu shared waiters, got %lu\n", shared_waiters
, count
);
1443 ret
= ExIsResourceAcquiredExclusiveLite(resource
);
1444 ok_(__FILE__
, line
)(ret
== exclusive
,
1445 "expected exclusive %u, got %u\n", exclusive
, ret
);
1446 count
= ExIsResourceAcquiredSharedLite(resource
);
1447 ok_(__FILE__
, line
)(count
== shared_count
,
1448 "expected shared %lu, got %lu\n", shared_count
, count
);
1450 #define check_resource(a,b,c,d,e) check_resource_(__LINE__,a,b,c,d,e)
1452 static KEVENT resource_shared_ready
, resource_shared_done
, resource_exclusive_ready
, resource_exclusive_done
;
1454 static void WINAPI
resource_shared_thread(void *arg
)
1456 ERESOURCE
*resource
= arg
;
1459 check_resource(resource
, 0, 0, FALSE
, 0);
1461 ret
= ExAcquireResourceSharedLite(resource
, TRUE
);
1462 ok(ret
== TRUE
, "got ret %u\n", ret
);
1464 check_resource(resource
, 0, 0, FALSE
, 1);
1466 KeSetEvent(&resource_shared_ready
, IO_NO_INCREMENT
, FALSE
);
1467 KeWaitForSingleObject(&resource_shared_done
, Executive
, KernelMode
, FALSE
, NULL
);
1469 ExReleaseResourceForThreadLite(resource
, (ULONG_PTR
)PsGetCurrentThread());
1471 PsTerminateSystemThread(STATUS_SUCCESS
);
1474 static void WINAPI
resource_exclusive_thread(void *arg
)
1476 ERESOURCE
*resource
= arg
;
1479 check_resource(resource
, 0, 0, FALSE
, 0);
1481 ret
= ExAcquireResourceExclusiveLite(resource
, TRUE
);
1482 ok(ret
== TRUE
, "got ret %u\n", ret
);
1484 check_resource(resource
, 0, 0, TRUE
, 1);
1486 KeSetEvent(&resource_exclusive_ready
, IO_NO_INCREMENT
, FALSE
);
1487 KeWaitForSingleObject(&resource_exclusive_done
, Executive
, KernelMode
, FALSE
, NULL
);
1489 ExReleaseResourceForThreadLite(resource
, (ULONG_PTR
)PsGetCurrentThread());
1491 PsTerminateSystemThread(STATUS_SUCCESS
);
1494 static void test_resource(void)
1499 HANDLE thread
, thread2
;
1501 memset(&resource
, 0xcc, sizeof(resource
));
1503 status
= ExInitializeResourceLite(&resource
);
1504 ok(status
== STATUS_SUCCESS
, "got status %#lx\n", status
);
1505 check_resource(&resource
, 0, 0, FALSE
, 0);
1507 KeEnterCriticalRegion();
1509 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1510 ok(ret
== TRUE
, "got ret %u\n", ret
);
1511 check_resource(&resource
, 0, 0, TRUE
, 1);
1513 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1514 ok(ret
== TRUE
, "got ret %u\n", ret
);
1515 check_resource(&resource
, 0, 0, TRUE
, 2);
1517 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1518 ok(ret
== TRUE
, "got ret %u\n", ret
);
1519 check_resource(&resource
, 0, 0, TRUE
, 3);
1521 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1522 check_resource(&resource
, 0, 0, TRUE
, 2);
1524 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1525 check_resource(&resource
, 0, 0, TRUE
, 1);
1527 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1528 check_resource(&resource
, 0, 0, FALSE
, 0);
1530 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1531 ok(ret
== TRUE
, "got ret %u\n", ret
);
1532 check_resource(&resource
, 0, 0, FALSE
, 1);
1534 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1535 ok(ret
== TRUE
, "got ret %u\n", ret
);
1536 check_resource(&resource
, 0, 0, FALSE
, 2);
1538 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1539 ok(ret
== FALSE
, "got ret %u\n", ret
);
1540 check_resource(&resource
, 0, 0, FALSE
, 2);
1542 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1543 check_resource(&resource
, 0, 0, FALSE
, 1);
1545 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1546 check_resource(&resource
, 0, 0, FALSE
, 0);
1548 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1549 ok(ret
== TRUE
, "got ret %u\n", ret
);
1550 check_resource(&resource
, 0, 0, FALSE
, 1);
1552 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1553 check_resource(&resource
, 0, 0, FALSE
, 0);
1555 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1556 ok(ret
== TRUE
, "got ret %u\n", ret
);
1557 check_resource(&resource
, 0, 0, FALSE
, 1);
1559 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1560 check_resource(&resource
, 0, 0, FALSE
, 0);
1562 /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */
1564 KeInitializeEvent(&resource_shared_ready
, SynchronizationEvent
, FALSE
);
1565 KeInitializeEvent(&resource_shared_done
, SynchronizationEvent
, FALSE
);
1566 thread
= create_thread(resource_shared_thread
, &resource
);
1567 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1568 check_resource(&resource
, 0, 0, FALSE
, 0);
1570 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1571 ok(ret
== FALSE
, "got ret %u\n", ret
);
1573 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1574 ok(ret
== TRUE
, "got ret %u\n", ret
);
1575 check_resource(&resource
, 0, 0, FALSE
, 1);
1577 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1578 check_resource(&resource
, 0, 0, FALSE
, 0);
1580 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1581 ok(ret
== TRUE
, "got ret %u\n", ret
);
1582 check_resource(&resource
, 0, 0, FALSE
, 1);
1584 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1585 check_resource(&resource
, 0, 0, FALSE
, 0);
1587 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1588 ok(ret
== TRUE
, "got ret %u\n", ret
);
1589 check_resource(&resource
, 0, 0, FALSE
, 1);
1591 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1592 check_resource(&resource
, 0, 0, FALSE
, 0);
1594 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1595 join_thread(thread
);
1596 check_resource(&resource
, 0, 0, FALSE
, 0);
1598 /* Acquire the resource as exclusive, and then spawn a shared thread. */
1600 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1601 ok(ret
== TRUE
, "got ret %u\n", ret
);
1602 check_resource(&resource
, 0, 0, TRUE
, 1);
1604 thread
= create_thread(resource_shared_thread
, &resource
);
1606 check_resource(&resource
, 0, 1, TRUE
, 1);
1608 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1609 ok(ret
== TRUE
, "got ret %u\n", ret
);
1610 check_resource(&resource
, 0, 1, TRUE
, 2);
1612 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1613 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1614 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1615 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1616 join_thread(thread
);
1617 check_resource(&resource
, 0, 0, FALSE
, 0);
1619 /* Do not acquire the resource ourselves, but spawn an exclusive thread holding it. */
1621 KeInitializeEvent(&resource_exclusive_ready
, SynchronizationEvent
, FALSE
);
1622 KeInitializeEvent(&resource_exclusive_done
, SynchronizationEvent
, FALSE
);
1623 thread
= create_thread(resource_exclusive_thread
, &resource
);
1624 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1625 check_resource(&resource
, 0, 0, FALSE
, 0);
1627 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1628 ok(ret
== FALSE
, "got ret %u\n", ret
);
1629 check_resource(&resource
, 0, 0, FALSE
, 0);
1631 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1632 ok(ret
== FALSE
, "got ret %u\n", ret
);
1633 check_resource(&resource
, 0, 0, FALSE
, 0);
1635 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1636 ok(ret
== FALSE
, "got ret %u\n", ret
);
1637 check_resource(&resource
, 0, 0, FALSE
, 0);
1639 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1640 ok(ret
== FALSE
, "got ret %u\n", ret
);
1641 check_resource(&resource
, 0, 0, FALSE
, 0);
1643 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1644 join_thread(thread
);
1645 check_resource(&resource
, 0, 0, FALSE
, 0);
1647 /* Acquire the resource as shared, and then spawn an exclusive waiter. */
1649 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1650 ok(ret
== TRUE
, "got ret %u\n", ret
);
1651 check_resource(&resource
, 0, 0, FALSE
, 1);
1653 thread
= create_thread(resource_exclusive_thread
, &resource
);
1655 check_resource(&resource
, 1, 0, FALSE
, 1);
1657 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1658 ok(ret
== TRUE
, "got ret %u\n", ret
);
1659 check_resource(&resource
, 1, 0, FALSE
, 2);
1660 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1662 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1663 ok(ret
== TRUE
, "got ret %u\n", ret
);
1664 check_resource(&resource
, 1, 0, FALSE
, 2);
1665 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1667 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1668 ok(ret
== FALSE
, "got ret %u\n", ret
);
1669 check_resource(&resource
, 1, 0, FALSE
, 1);
1671 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1672 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1673 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1674 join_thread(thread
);
1675 check_resource(&resource
, 0, 0, FALSE
, 0);
1677 /* Spawn a shared and then exclusive waiter. */
1679 KeInitializeEvent(&resource_shared_ready
, SynchronizationEvent
, FALSE
);
1680 KeInitializeEvent(&resource_shared_done
, SynchronizationEvent
, FALSE
);
1681 thread
= create_thread(resource_shared_thread
, &resource
);
1682 KeWaitForSingleObject(&resource_shared_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1683 check_resource(&resource
, 0, 0, FALSE
, 0);
1685 thread2
= create_thread(resource_exclusive_thread
, &resource
);
1687 check_resource(&resource
, 1, 0, FALSE
, 0);
1689 ret
= ExAcquireResourceExclusiveLite(&resource
, FALSE
);
1690 ok(ret
== FALSE
, "got ret %u\n", ret
);
1691 check_resource(&resource
, 1, 0, FALSE
, 0);
1693 ret
= ExAcquireResourceSharedLite(&resource
, FALSE
);
1694 ok(ret
== FALSE
, "got ret %u\n", ret
);
1695 check_resource(&resource
, 1, 0, FALSE
, 0);
1697 ret
= ExAcquireSharedStarveExclusive(&resource
, FALSE
);
1698 ok(ret
== TRUE
, "got ret %u\n", ret
);
1699 check_resource(&resource
, 1, 0, FALSE
, 1);
1700 ExReleaseResourceForThreadLite(&resource
, (ULONG_PTR
)PsGetCurrentThread());
1702 ret
= ExAcquireSharedWaitForExclusive(&resource
, FALSE
);
1703 ok(ret
== FALSE
, "got ret %u\n", ret
);
1704 check_resource(&resource
, 1, 0, FALSE
, 0);
1706 KeSetEvent(&resource_shared_done
, IO_NO_INCREMENT
, FALSE
);
1707 join_thread(thread
);
1708 KeWaitForSingleObject(&resource_exclusive_ready
, Executive
, KernelMode
, FALSE
, NULL
);
1709 KeSetEvent(&resource_exclusive_done
, IO_NO_INCREMENT
, FALSE
);
1710 join_thread(thread2
);
1711 check_resource(&resource
, 0, 0, FALSE
, 0);
1713 KeLeaveCriticalRegion();
1715 status
= ExDeleteResourceLite(&resource
);
1716 ok(status
== STATUS_SUCCESS
, "got status %#lx\n", status
);
1719 static void test_lookup_thread(void)
1722 PETHREAD thread
= NULL
;
1724 status
= PsLookupThreadByThreadId(PsGetCurrentThreadId(), &thread
);
1725 ok(!status
, "PsLookupThreadByThreadId failed: %#lx\n", status
);
1726 ok((PKTHREAD
)thread
== KeGetCurrentThread(), "thread != KeGetCurrentThread\n");
1727 if (thread
) ObDereferenceObject(thread
);
1729 status
= PsLookupThreadByThreadId(NULL
, &thread
);
1730 ok(status
== STATUS_INVALID_CID
|| broken(status
== STATUS_INVALID_PARAMETER
) /* winxp */,
1731 "PsLookupThreadByThreadId returned %#lx\n", status
);
1734 static void test_stack_limits(void)
1736 ULONG_PTR low
= 0, high
= 0;
1738 IoGetStackLimits(&low
, &high
);
1739 ok(low
, "low = 0\n");
1740 ok(low
< high
, "low >= high\n");
1741 ok(low
< (ULONG_PTR
)&low
&& (ULONG_PTR
)&low
< high
, "stack variable is not in stack limits\n");
1744 static unsigned int got_completion
, completion_lower_pending
, completion_upper_pending
;
1746 static NTSTATUS WINAPI
completion_cb(DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
1748 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
1749 ok(device
== context
, "Got device %p; expected %p.\n", device
, context
);
1751 if (device
== upper_device
)
1753 ok(irp
->PendingReturned
== completion_lower_pending
, "Got PendingReturned %u, expected %u.\n",
1754 irp
->PendingReturned
, completion_lower_pending
);
1756 ok(irp
->CurrentLocation
== 2, "Got current location %u.\n", irp
->CurrentLocation
);
1757 ok(stack
->Control
== (SL_INVOKE_ON_CANCEL
| SL_INVOKE_ON_ERROR
| SL_INVOKE_ON_SUCCESS
),
1758 "Got control flags %#x.\n", stack
->Control
);
1759 stack
= IoGetNextIrpStackLocation(irp
);
1760 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
1761 stack
= irp
->Tail
.Overlay
.CurrentStackLocation
+ 1; /* previous location */
1762 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
1764 if (irp
->PendingReturned
&& completion_upper_pending
)
1765 IoMarkIrpPending(irp
);
1769 ok(irp
->PendingReturned
== completion_upper_pending
, "Got PendingReturned %u, expected %u.\n",
1770 irp
->PendingReturned
, completion_upper_pending
);
1772 ok(irp
->CurrentLocation
== 3, "Got current location %u.\n", irp
->CurrentLocation
);
1773 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
1774 stack
= IoGetNextIrpStackLocation(irp
);
1775 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
1776 stack
= irp
->Tail
.Overlay
.CurrentStackLocation
- 2; /* lowest location */
1777 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
1781 return STATUS_SUCCESS
;
1784 static void test_completion(void)
1791 completion_lower_pending
= completion_upper_pending
= FALSE
;
1793 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
1795 irp
= IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION
, upper_device
,
1796 NULL
, 0, NULL
, 0, FALSE
, &event
, &io
);
1797 IoSetCompletionRoutine(irp
, completion_cb
, NULL
, TRUE
, TRUE
, TRUE
);
1798 ret
= IoCallDriver(upper_device
, irp
);
1799 ok(ret
== STATUS_SUCCESS
, "IoCallDriver returned %#lx\n", ret
);
1800 ok(got_completion
== 2, "got %u calls to completion routine\n", got_completion
);
1802 completion_lower_pending
= TRUE
;
1805 irp
= IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION
, upper_device
,
1806 NULL
, 0, NULL
, 0, FALSE
, &event
, &io
);
1807 IoSetCompletionRoutine(irp
, completion_cb
, NULL
, TRUE
, TRUE
, TRUE
);
1808 ret
= IoCallDriver(upper_device
, irp
);
1809 ok(ret
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", ret
);
1810 ok(!got_completion
, "got %u calls to completion routine\n", got_completion
);
1812 ok(irp
->CurrentLocation
== 1, "Got current location %u.\n", irp
->CurrentLocation
);
1813 ok(!irp
->PendingReturned
, "Got pending flag %u.\n", irp
->PendingReturned
);
1815 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1816 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1817 ok(got_completion
== 2, "got %u calls to completion routine\n", got_completion
);
1819 completion_upper_pending
= TRUE
;
1822 irp
= IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION
, upper_device
,
1823 NULL
, 0, NULL
, 0, FALSE
, &event
, &io
);
1824 IoSetCompletionRoutine(irp
, completion_cb
, NULL
, TRUE
, TRUE
, TRUE
);
1825 ret
= IoCallDriver(upper_device
, irp
);
1826 ok(ret
== STATUS_PENDING
, "IoCallDriver returned %#lx\n", ret
);
1827 ok(!got_completion
, "got %u calls to completion routine\n", got_completion
);
1829 ok(irp
->CurrentLocation
== 1, "Got current location %u.\n", irp
->CurrentLocation
);
1830 ok(!irp
->PendingReturned
, "Got pending flag %u.\n", irp
->PendingReturned
);
1832 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1833 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1834 ok(got_completion
== 2, "got %u calls to completion routine\n", got_completion
);
1837 static void test_IoAttachDeviceToDeviceStack(void)
1839 DEVICE_OBJECT
*dev1
, *dev2
, *dev3
, *ret
;
1842 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1843 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev1
);
1844 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1845 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1846 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev2
);
1847 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1848 status
= IoCreateDevice(driver_obj
, 0, NULL
, FILE_DEVICE_UNKNOWN
,
1849 FILE_DEVICE_SECURE_OPEN
, FALSE
, &dev3
);
1850 ok(status
== STATUS_SUCCESS
, "IoCreateDevice failed\n");
1852 /* TODO: initialize devices properly */
1853 dev1
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1854 dev2
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1856 ret
= IoAttachDeviceToDeviceStack(dev2
, dev1
);
1857 ok(ret
== dev1
, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret
, dev1
);
1858 ok(dev1
->AttachedDevice
== dev2
, "dev1->AttachedDevice = %p, expected %p\n",
1859 dev1
->AttachedDevice
, dev2
);
1860 ok(!dev2
->AttachedDevice
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1861 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1862 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1864 ret
= IoAttachDeviceToDeviceStack(dev3
, dev1
);
1865 ok(ret
== dev2
, "IoAttachDeviceToDeviceStack returned %p, expected %p\n", ret
, dev2
);
1866 ok(dev1
->AttachedDevice
== dev2
, "dev1->AttachedDevice = %p, expected %p\n",
1867 dev1
->AttachedDevice
, dev2
);
1868 ok(dev2
->AttachedDevice
== dev3
, "dev2->AttachedDevice = %p, expected %p\n",
1869 dev2
->AttachedDevice
, dev3
);
1870 ok(!dev3
->AttachedDevice
, "dev3->AttachedDevice = %p\n", dev3
->AttachedDevice
);
1871 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1872 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1873 ok(dev3
->StackSize
== 3, "dev3->StackSize = %d\n", dev3
->StackSize
);
1875 IoDetachDevice(dev1
);
1876 ok(!dev1
->AttachedDevice
, "dev1->AttachedDevice = %p\n", dev1
->AttachedDevice
);
1877 ok(dev2
->AttachedDevice
== dev3
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1879 IoDetachDevice(dev2
);
1880 ok(!dev2
->AttachedDevice
, "dev2->AttachedDevice = %p\n", dev2
->AttachedDevice
);
1881 ok(dev1
->StackSize
== 1, "dev1->StackSize = %d\n", dev1
->StackSize
);
1882 ok(dev2
->StackSize
== 2, "dev2->StackSize = %d\n", dev2
->StackSize
);
1883 ok(dev3
->StackSize
== 3, "dev3->StackSize = %d\n", dev3
->StackSize
);
1885 IoDeleteDevice(dev1
);
1886 IoDeleteDevice(dev2
);
1887 IoDeleteDevice(dev3
);
1890 static void test_object_name(void)
1892 static const WCHAR event_nameW
[] = L
"\\wine_test_event";
1893 static const WCHAR device_nameW
[] = L
"\\Device\\WineTestDriver";
1895 OBJECT_NAME_INFORMATION
*name
= (OBJECT_NAME_INFORMATION
*)buffer
;
1896 OBJECT_ATTRIBUTES attr
;
1897 UNICODE_STRING string
;
1904 ret
= ObQueryNameString(lower_device
, name
, 0, &ret_size
);
1905 ok(ret
== STATUS_INFO_LENGTH_MISMATCH
, "got status %#lx\n", ret
);
1906 ok(ret_size
== sizeof(*name
) + sizeof(device_nameW
), "got size %lu\n", ret_size
);
1909 ret
= ObQueryNameString(lower_device
, name
, sizeof(buffer
), &ret_size
);
1910 ok(!ret
, "got status %#lx\n", ret
);
1911 ok(!wcscmp(name
->Name
.Buffer
, device_nameW
), "got name %ls\n", name
->Name
.Buffer
);
1912 ok(ret_size
== sizeof(*name
) + sizeof(device_nameW
), "got size %lu\n", ret_size
);
1913 ok(name
->Name
.Length
== wcslen(device_nameW
) * sizeof(WCHAR
), "got length %u\n", name
->Name
.Length
);
1914 ok(name
->Name
.MaximumLength
== sizeof(device_nameW
), "got maximum length %u\n", name
->Name
.MaximumLength
);
1916 event
= IoCreateSynchronizationEvent(NULL
, &handle
);
1917 ok(!!event
, "failed to create event\n");
1920 ret
= ObQueryNameString(event
, name
, sizeof(buffer
), &ret_size
);
1921 ok(!ret
, "got status %#lx\n", ret
);
1922 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1923 ok(ret_size
== sizeof(*name
), "got size %lu\n", ret_size
);
1924 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1925 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1927 ret
= ZwClose(handle
);
1928 ok(!ret
, "got status %#lx\n", ret
);
1930 RtlInitUnicodeString(&string
, event_nameW
);
1931 InitializeObjectAttributes(&attr
, &string
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1932 ret
= ZwCreateEvent(&handle
, 0, &attr
, NotificationEvent
, TRUE
);
1933 ok(!ret
, "got status %#lx\n", ret
);
1934 ret
= ObReferenceObjectByHandle(handle
, 0, *pExEventObjectType
, KernelMode
, (void **)&event
, NULL
);
1935 ok(!ret
, "got status %#lx\n", ret
);
1938 ret
= ObQueryNameString(event
, name
, sizeof(buffer
), &ret_size
);
1939 ok(!ret
, "got status %#lx\n", ret
);
1940 ok(!wcscmp(name
->Name
.Buffer
, event_nameW
), "got name %ls\n", name
->Name
.Buffer
);
1941 ok(ret_size
== sizeof(*name
) + sizeof(event_nameW
), "got size %lu\n", ret_size
);
1942 ok(name
->Name
.Length
== wcslen(event_nameW
) * sizeof(WCHAR
), "got length %u\n", name
->Name
.Length
);
1943 ok(name
->Name
.MaximumLength
== sizeof(event_nameW
), "got maximum length %u\n", name
->Name
.MaximumLength
);
1945 ObDereferenceObject(event
);
1946 ret
= ZwClose(handle
);
1947 ok(!ret
, "got status %#lx\n", ret
);
1950 ret
= ObQueryNameString(KeGetCurrentThread(), name
, sizeof(buffer
), &ret_size
);
1951 ok(!ret
, "got status %#lx\n", ret
);
1952 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1953 ok(ret_size
== sizeof(*name
), "got size %lu\n", ret_size
);
1954 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1955 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1958 ret
= ObQueryNameString(IoGetCurrentProcess(), name
, sizeof(buffer
), &ret_size
);
1959 ok(!ret
, "got status %#lx\n", ret
);
1960 ok(!name
->Name
.Buffer
, "got name %ls\n", name
->Name
.Buffer
);
1961 ok(ret_size
== sizeof(*name
), "got size %lu\n", ret_size
);
1962 ok(!name
->Name
.Length
, "got length %u\n", name
->Name
.Length
);
1963 ok(!name
->Name
.MaximumLength
, "got maximum length %u\n", name
->Name
.MaximumLength
);
1966 static PIO_WORKITEM work_item
;
1968 static void WINAPI
main_test_task(DEVICE_OBJECT
*device
, void *context
)
1972 test_current_thread(TRUE
);
1973 test_critical_region(FALSE
);
1974 test_call_driver(device
);
1975 test_cancel_irp(device
);
1976 test_stack_limits();
1979 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1980 irp
->IoStatus
.Information
= 0;
1981 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
1984 #if defined(__i386__) || defined(__x86_64__)
1985 static void test_executable_pool(void)
1987 static const unsigned char bytes
[] =
1988 { 0xb8, 0xef, 0xbe, 0xad, 0xde, 0xc3 }; /* mov $0xdeadbeef,%eax ; ret */
1989 static const ULONG tag
= 0x74736574; /* test */
1993 func
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(bytes
), tag
);
1994 ok(!!func
, "Got NULL memory.\n");
1996 memcpy(func
, bytes
, sizeof(bytes
));
1998 ok(ret
== 0xdeadbeef, "Got %#x.\n", ret
);
2000 ExFreePoolWithTag(func
, tag
);
2004 static void test_affinity(void)
2006 KAFFINITY (WINAPI
*pKeSetSystemAffinityThreadEx
)(KAFFINITY affinity
);
2007 void (WINAPI
*pKeRevertToUserAffinityThreadEx
)(KAFFINITY affinity
);
2008 ULONG (WINAPI
*pKeQueryActiveProcessorCountEx
)(USHORT
);
2009 KAFFINITY (WINAPI
*pKeQueryActiveProcessors
)(void);
2010 KAFFINITY mask
, mask_all_cpus
;
2011 ULONG cpu_count
, count
;
2013 pKeQueryActiveProcessorCountEx
= get_proc_address("KeQueryActiveProcessorCountEx");
2014 if (!pKeQueryActiveProcessorCountEx
)
2016 win_skip("KeQueryActiveProcessorCountEx is not available.\n");
2020 pKeQueryActiveProcessors
= get_proc_address("KeQueryActiveProcessors");
2021 ok(!!pKeQueryActiveProcessors
, "KeQueryActiveProcessors is not available.\n");
2023 pKeSetSystemAffinityThreadEx
= get_proc_address("KeSetSystemAffinityThreadEx");
2024 ok(!!pKeSetSystemAffinityThreadEx
, "KeSetSystemAffinityThreadEx is not available.\n");
2026 pKeRevertToUserAffinityThreadEx
= get_proc_address("KeRevertToUserAffinityThreadEx");
2027 ok(!!pKeRevertToUserAffinityThreadEx
, "KeRevertToUserAffinityThreadEx is not available.\n");
2029 count
= pKeQueryActiveProcessorCountEx(1);
2030 ok(!count
, "Got unexpected count %lu.\n", count
);
2032 cpu_count
= pKeQueryActiveProcessorCountEx(0);
2033 ok(cpu_count
, "Got unexpected cpu_count %lu.\n", cpu_count
);
2035 count
= pKeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
2036 ok(count
== cpu_count
, "Got unexpected count %lu.\n", count
);
2038 if (cpu_count
>= 8 * sizeof(KAFFINITY
))
2039 mask_all_cpus
= ~(KAFFINITY
)0;
2041 mask_all_cpus
= ((KAFFINITY
)1 << cpu_count
) - 1;
2043 mask
= pKeQueryActiveProcessors();
2044 ok(mask
== mask_all_cpus
, "Got unexpected mask %#Ix.\n", mask
);
2046 pKeRevertToUserAffinityThreadEx(0x2);
2048 mask
= pKeSetSystemAffinityThreadEx(0);
2049 ok(!mask
, "Got unexpected mask %#Ix.\n", mask
);
2051 pKeRevertToUserAffinityThreadEx(0x2);
2053 mask
= pKeSetSystemAffinityThreadEx(0x1);
2054 ok(mask
== 0x2, "Got unexpected mask %#Ix.\n", mask
);
2056 mask
= pKeSetSystemAffinityThreadEx(~(KAFFINITY
)0);
2057 ok(mask
== 0x1, "Got unexpected mask %#Ix.\n", mask
);
2059 pKeRevertToUserAffinityThreadEx(~(KAFFINITY
)0);
2060 mask
= pKeSetSystemAffinityThreadEx(0x1);
2061 ok(mask
== mask_all_cpus
, "Got unexpected mask %#Ix.\n", mask
);
2063 pKeRevertToUserAffinityThreadEx(0);
2065 mask
= pKeSetSystemAffinityThreadEx(0x1);
2066 ok(!mask
, "Got unexpected mask %#Ix.\n", mask
);
2068 KeRevertToUserAffinityThread();
2070 mask
= pKeSetSystemAffinityThreadEx(0x1);
2071 ok(!mask
, "Got unexpected mask %#Ix.\n", mask
);
2073 KeRevertToUserAffinityThread();
2076 struct test_dpc_func_context
2078 volatile LONG call_count
;
2079 volatile LONG selected_count
;
2080 volatile DEFERRED_REVERSE_BARRIER sync_barrier_start_value
, sync_barrier_mid_value
, sync_barrier_end_value
;
2081 volatile LONG done_barrier_start_value
;
2084 static BOOLEAN (WINAPI
*pKeSignalCallDpcSynchronize
)(void *barrier
);
2085 static void (WINAPI
*pKeSignalCallDpcDone
)(void *barrier
);
2087 static void WINAPI
test_dpc_func(PKDPC Dpc
, void *context
, void *cpu_count
,
2088 void *reverse_barrier
)
2090 DEFERRED_REVERSE_BARRIER
*barrier
= reverse_barrier
;
2091 struct test_dpc_func_context
*data
= context
;
2093 InterlockedIncrement(&data
->call_count
);
2095 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_start_value
.Barrier
,
2096 *(volatile LONG
*)&barrier
->Barrier
, 0);
2097 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_start_value
.TotalProcessors
,
2098 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
2100 if (pKeSignalCallDpcSynchronize(reverse_barrier
))
2101 InterlockedIncrement(&data
->selected_count
);
2103 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_mid_value
.Barrier
,
2104 *(volatile LONG
*)&barrier
->Barrier
, 0);
2105 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_mid_value
.TotalProcessors
,
2106 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
2108 data
->done_barrier_start_value
= *(volatile LONG
*)cpu_count
;
2110 if (pKeSignalCallDpcSynchronize(reverse_barrier
))
2111 InterlockedIncrement(&data
->selected_count
);
2113 pKeSignalCallDpcSynchronize(reverse_barrier
);
2114 pKeSignalCallDpcSynchronize(reverse_barrier
);
2116 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_end_value
.Barrier
,
2117 *(volatile LONG
*)&barrier
->Barrier
, 0);
2118 InterlockedCompareExchange((volatile LONG
*)&data
->sync_barrier_end_value
.TotalProcessors
,
2119 *(volatile LONG
*)&barrier
->TotalProcessors
, 0);
2121 pKeSignalCallDpcDone(cpu_count
);
2124 static void test_dpc(void)
2126 void (WINAPI
*pKeGenericCallDpc
)(PKDEFERRED_ROUTINE routine
, void *context
);
2127 void (WINAPI
*pKeInitializeDpc
)(PKDPC dpc
, PKDEFERRED_ROUTINE routine
, void *context
);
2128 struct test_dpc_func_context data
;
2131 struct _KDPC dpc
= {0};
2133 pKeInitializeDpc
= get_proc_address("KeInitializeDpc");
2134 if(!pKeInitializeDpc
)
2136 win_skip("KeInitializeDpc is not available.\n");
2140 pKeInitializeDpc(&dpc
, test_dpc_func
, &data
);
2142 ok(dpc
.Number
== 0, "Got unexpected Dpc Number %u.\n", dpc
.Number
);
2143 todo_wine
ok(dpc
.Type
== 0x13, "Got unexpected Dpc Type %u.\n", dpc
.Type
);
2144 todo_wine
ok(dpc
.Importance
== MediumImportance
, "Got unexpected Dpc Importance %u.\n", dpc
.Importance
);
2145 ok(dpc
.DeferredRoutine
== test_dpc_func
, "Got unexpected Dpc DeferredRoutine %p.\n", dpc
.DeferredRoutine
);
2146 ok(dpc
.DeferredContext
== &data
, "Got unexpected Dpc DeferredContext %p.\n", dpc
.DeferredContext
);
2148 pKeGenericCallDpc
= get_proc_address("KeGenericCallDpc");
2149 if (!pKeGenericCallDpc
)
2151 win_skip("KeGenericCallDpc is not available.\n");
2155 pKeSignalCallDpcDone
= get_proc_address("KeSignalCallDpcDone");
2156 ok(!!pKeSignalCallDpcDone
, "KeSignalCallDpcDone is not available.\n");
2157 pKeSignalCallDpcSynchronize
= get_proc_address("KeSignalCallDpcSynchronize");
2158 ok(!!pKeSignalCallDpcSynchronize
, "KeSignalCallDpcSynchronize is not available.\n");
2161 cpu_mask
= KeQueryActiveProcessors();
2171 memset(&data
, 0, sizeof(data
));
2173 KeSetSystemAffinityThread(0x1);
2175 pKeGenericCallDpc(test_dpc_func
, &data
);
2176 ok(data
.call_count
== cpu_count
, "Got unexpected call_count %lu.\n", data
.call_count
);
2177 ok(data
.selected_count
== 2, "Got unexpected selected_count %lu.\n", data
.selected_count
);
2178 ok(data
.sync_barrier_start_value
.Barrier
== cpu_count
,
2179 "Got unexpected sync_barrier_start_value.Barrier %ld.\n",
2180 data
.sync_barrier_start_value
.Barrier
);
2181 ok(data
.sync_barrier_start_value
.TotalProcessors
== cpu_count
,
2182 "Got unexpected sync_barrier_start_value.TotalProcessors %ld.\n",
2183 data
.sync_barrier_start_value
.TotalProcessors
);
2185 ok(data
.sync_barrier_mid_value
.Barrier
== (0x80000000 | cpu_count
),
2186 "Got unexpected sync_barrier_mid_value.Barrier %ld.\n",
2187 data
.sync_barrier_mid_value
.Barrier
);
2188 ok(data
.sync_barrier_mid_value
.TotalProcessors
== cpu_count
,
2189 "Got unexpected sync_barrier_mid_value.TotalProcessors %ld.\n",
2190 data
.sync_barrier_mid_value
.TotalProcessors
);
2192 ok(data
.sync_barrier_end_value
.Barrier
== cpu_count
,
2193 "Got unexpected sync_barrier_end_value.Barrier %ld.\n",
2194 data
.sync_barrier_end_value
.Barrier
);
2195 ok(data
.sync_barrier_end_value
.TotalProcessors
== cpu_count
,
2196 "Got unexpected sync_barrier_end_value.TotalProcessors %ld.\n",
2197 data
.sync_barrier_end_value
.TotalProcessors
);
2199 ok(data
.done_barrier_start_value
== cpu_count
, "Got unexpected done_barrier_start_value %ld.\n", data
.done_barrier_start_value
);
2201 KeRevertToUserAffinityThread();
2204 static void test_process_memory(const struct main_test_input
*test_input
)
2206 NTSTATUS (WINAPI
*pMmCopyVirtualMemory
)(PEPROCESS fromprocess
, void *fromaddress
, PEPROCESS toprocess
,
2207 void *toaddress
, SIZE_T bufsize
, KPROCESSOR_MODE mode
, SIZE_T
*copied
);
2208 char buffer
[sizeof(teststr
)];
2209 ULONG64 modified_value
;
2216 pMmCopyVirtualMemory
= get_proc_address("MmCopyVirtualMemory");
2218 status
= PsLookupProcessByProcessId((HANDLE
)(ULONG_PTR
)test_input
->process_id
, &process
);
2219 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
2224 if (0) /* Crashes on Windows. */
2225 PsGetProcessSectionBaseAddress(NULL
);
2227 base
= PsGetProcessSectionBaseAddress(process
);
2228 ok(!!base
, "Got NULL base address.\n");
2230 ok(process
== PsGetCurrentProcess(), "Got unexpected process %p, PsGetCurrentProcess() %p.\n",
2231 process
, PsGetCurrentProcess());
2233 modified_value
= 0xdeadbeeffeedcafe;
2234 if (pMmCopyVirtualMemory
)
2237 status
= pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2238 buffer
, sizeof(buffer
), UserMode
, &size
);
2239 todo_wine
ok(status
== STATUS_ACCESS_VIOLATION
, "Got unexpected status %#lx.\n", status
);
2240 ok(!size
, "Got unexpected size %#Ix.\n", size
);
2242 memset(buffer
, 0, sizeof(buffer
));
2244 if (0) /* Passing NULL for the copied size address hangs Windows. */
2245 pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2246 buffer
, sizeof(buffer
), KernelMode
, NULL
);
2247 status
= pMmCopyVirtualMemory(process
, base
+ test_input
->teststr_offset
, PsGetCurrentProcess(),
2248 buffer
, sizeof(buffer
), KernelMode
, &size
);
2249 todo_wine
ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
2250 todo_wine
ok(size
== sizeof(buffer
), "Got unexpected size %Iu.\n", size
);
2251 todo_wine
ok(!strcmp(buffer
, teststr
), "Got unexpected test string.\n");
2255 win_skip("MmCopyVirtualMemory is not available.\n");
2258 if (!winetest_platform_is_wine
)
2260 KeStackAttachProcess((PKPROCESS
)process
, &state
);
2261 todo_wine
ok(!strcmp(teststr
, (char *)(base
+ test_input
->teststr_offset
)),
2262 "Strings do not match.\n");
2263 *test_input
->modified_value
= modified_value
;
2264 KeUnstackDetachProcess(&state
);
2266 ObDereferenceObject(process
);
2269 static void test_permanence(void)
2271 OBJECT_ATTRIBUTES attr
;
2272 HANDLE handle
, handle2
;
2276 RtlInitUnicodeString(&str
, L
"\\BaseNamedObjects\\wine_test_dir");
2277 InitializeObjectAttributes(&attr
, &str
, 0, 0, NULL
);
2278 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2279 ok(!status
, "got %#lx\n", status
);
2280 status
= ZwClose( handle
);
2281 ok(!status
, "got %#lx\n", status
);
2282 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2283 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#lx\n", status
);
2285 attr
.Attributes
= OBJ_PERMANENT
;
2286 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2287 ok(!status
, "got %#lx\n", status
);
2288 status
= ZwClose( handle
);
2289 ok(!status
, "got %#lx\n", status
);
2291 attr
.Attributes
= 0;
2292 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2293 ok(!status
, "got %#lx\n", status
);
2294 status
= ZwMakeTemporaryObject( handle
);
2295 ok(!status
, "got %#lx\n", status
);
2296 status
= ZwMakeTemporaryObject( handle
);
2297 ok(!status
, "got %#lx\n", status
);
2298 status
= ZwClose( handle
);
2299 ok(!status
, "got %#lx\n", status
);
2300 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2301 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#lx\n", status
);
2303 status
= ZwCreateDirectoryObject( &handle
, GENERIC_ALL
, &attr
);
2304 ok(!status
, "got %#lx\n", status
);
2305 attr
.Attributes
= OBJ_PERMANENT
;
2306 status
= ZwOpenDirectoryObject( &handle2
, 0, &attr
);
2307 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2308 status
= ZwClose( handle2
);
2309 ok(!status
, "got %#lx\n", status
);
2310 status
= ZwClose( handle
);
2311 ok(!status
, "got %#lx\n", status
);
2312 attr
.Attributes
= 0;
2313 status
= ZwOpenDirectoryObject( &handle
, 0, &attr
);
2314 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#lx\n", status
);
2317 static void test_driver_object_extension(void)
2319 NTSTATUS (WINAPI
*pIoAllocateDriverObjectExtension
)(PDRIVER_OBJECT
, PVOID
, ULONG
, PVOID
*);
2320 PVOID (WINAPI
*pIoGetDriverObjectExtension
)(PDRIVER_OBJECT
, PVOID
);
2322 void *driver_obj_ext
= NULL
;
2323 void *get_obj_ext
= NULL
;
2325 pIoAllocateDriverObjectExtension
= get_proc_address("IoAllocateDriverObjectExtension");
2326 pIoGetDriverObjectExtension
= get_proc_address("IoGetDriverObjectExtension");
2328 if (!pIoAllocateDriverObjectExtension
)
2330 win_skip("IoAllocateDriverObjectExtension is not available.\n");
2334 status
= pIoAllocateDriverObjectExtension(driver_obj
, NULL
, 100, &driver_obj_ext
);
2335 todo_wine
ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2336 todo_wine
ok(driver_obj_ext
!= NULL
, "got NULL\n");
2338 get_obj_ext
= pIoGetDriverObjectExtension(driver_obj
, NULL
);
2339 todo_wine
ok(get_obj_ext
== driver_obj_ext
&& get_obj_ext
!= NULL
, "got %p != %p\n", get_obj_ext
, driver_obj_ext
);
2341 status
= pIoAllocateDriverObjectExtension(driver_obj
, NULL
, 100, &driver_obj_ext
);
2342 todo_wine
ok(status
== STATUS_OBJECT_NAME_COLLISION
, "got %#lx\n", status
);
2343 ok(driver_obj_ext
== NULL
, "got %p\n", driver_obj_ext
);
2345 get_obj_ext
= pIoGetDriverObjectExtension(driver_obj
, (void *)0xdead);
2346 ok(get_obj_ext
== NULL
, "got %p\n", get_obj_ext
);
2349 static void test_default_security(void)
2351 PSECURITY_DESCRIPTOR sd
= NULL
;
2353 PSID group
= NULL
, owner
= NULL
;
2354 BOOLEAN isdefault
, present
;
2356 PACCESS_ALLOWED_ACE ace
;
2357 SID_IDENTIFIER_AUTHORITY auth
= { SECURITY_NULL_SID_AUTHORITY
};
2358 SID_IDENTIFIER_AUTHORITY authwine7
= { SECURITY_NT_AUTHORITY
};
2359 PSID sid1
, sid2
, sidwin7
;
2362 status
= FltBuildDefaultSecurityDescriptor(&sd
, STANDARD_RIGHTS_ALL
);
2363 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2364 if (status
!= STATUS_SUCCESS
)
2366 win_skip("Skipping FltBuildDefaultSecurityDescriptor tests\n");
2369 ok(sd
!= NULL
, "Failed to return descriptor\n");
2371 status
= RtlGetGroupSecurityDescriptor(sd
, &group
, &isdefault
);
2372 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2373 ok(group
== NULL
, "group isn't NULL\n");
2375 status
= RtlGetOwnerSecurityDescriptor(sd
, &owner
, &isdefault
);
2376 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2377 ok(owner
== NULL
, "owner isn't NULL\n");
2379 status
= RtlGetDaclSecurityDescriptor(sd
, &present
, &acl
, &isdefault
);
2380 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2381 ok(acl
!= NULL
, "acl is NULL\n");
2382 ok(acl
->AceCount
== 2, "got %d\n", acl
->AceCount
);
2384 sid1
= ExAllocatePool(NonPagedPool
, RtlLengthRequiredSid(2));
2385 status
= RtlInitializeSid(sid1
, &auth
, 2);
2386 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2387 *RtlSubAuthoritySid(sid1
, 0) = SECURITY_BUILTIN_DOMAIN_RID
;
2388 *RtlSubAuthoritySid(sid1
, 1) = DOMAIN_GROUP_RID_ADMINS
;
2390 sidwin7
= ExAllocatePool(NonPagedPool
, RtlLengthRequiredSid(2));
2391 status
= RtlInitializeSid(sidwin7
, &authwine7
, 2);
2392 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2393 *RtlSubAuthoritySid(sidwin7
, 0) = SECURITY_BUILTIN_DOMAIN_RID
;
2394 *RtlSubAuthoritySid(sidwin7
, 1) = DOMAIN_ALIAS_RID_ADMINS
;
2396 sid2
= ExAllocatePool(NonPagedPool
, RtlLengthRequiredSid(1));
2397 RtlInitializeSid(sid2
, &auth
, 1);
2398 *RtlSubAuthoritySid(sid2
, 0) = SECURITY_LOCAL_SYSTEM_RID
;
2400 /* SECURITY_BUILTIN_DOMAIN_RID */
2401 status
= RtlGetAce(acl
, 0, (void**)&ace
);
2402 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2404 ok(ace
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
, "got %#x\n", ace
->Header
.AceType
);
2405 ok(ace
->Header
.AceFlags
== 0, "got %#x\n", ace
->Header
.AceFlags
);
2406 ok(ace
->Mask
== STANDARD_RIGHTS_ALL
, "got %#lx\n", ace
->Mask
);
2408 ret
= RtlEqualSid(sid1
, (PSID
)&ace
->SidStart
) || RtlEqualSid(sidwin7
, (PSID
)&ace
->SidStart
);
2409 ok(ret
, "SID not equal\n");
2411 /* SECURITY_LOCAL_SYSTEM_RID */
2412 status
= RtlGetAce(acl
, 1, (void**)&ace
);
2413 ok(status
== STATUS_SUCCESS
, "got %#lx\n", status
);
2415 ok(ace
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
, "got %#x\n", ace
->Header
.AceType
);
2416 ok(ace
->Header
.AceFlags
== 0, "got %#x\n", ace
->Header
.AceFlags
);
2417 ok(ace
->Mask
== STANDARD_RIGHTS_ALL
, "got %#lx\n", ace
->Mask
);
2419 ret
= RtlEqualSid(sid2
, (PSID
)&ace
->SidStart
) || RtlEqualSid(sidwin7
, (PSID
)&ace
->SidStart
);
2420 ok(ret
, "SID not equal\n");
2425 FltFreeSecurityDescriptor(sd
);
2428 static NTSTATUS
main_test(DEVICE_OBJECT
*device
, IRP
*irp
, IO_STACK_LOCATION
*stack
)
2430 void *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2431 struct main_test_input
*test_input
= buffer
;
2434 return STATUS_ACCESS_VIOLATION
;
2436 pExEventObjectType
= get_proc_address("ExEventObjectType");
2437 ok(!!pExEventObjectType
, "ExEventObjectType not found\n");
2439 pIoFileObjectType
= get_proc_address("IoFileObjectType");
2440 ok(!!pIoFileObjectType
, "IofileObjectType not found\n");
2442 pPsThreadType
= get_proc_address("PsThreadType");
2443 ok(!!pPsThreadType
, "IofileObjectType not found\n");
2445 pPsInitialSystemProcess
= get_proc_address("PsInitialSystemProcess");
2446 ok(!!pPsInitialSystemProcess
, "PsInitialSystemProcess not found\n");
2448 test_irp_struct(irp
, device
);
2449 test_current_thread(FALSE
);
2450 test_critical_region(TRUE
);
2457 test_stack_callout();
2458 test_lookaside_list();
2459 test_ob_reference();
2461 test_lookup_thread();
2462 test_IoAttachDeviceToDeviceStack();
2464 #if defined(__i386__) || defined(__x86_64__)
2465 test_executable_pool();
2469 test_process_memory(test_input
);
2471 test_driver_object_extension();
2472 test_default_security();
2474 IoMarkIrpPending(irp
);
2475 IoQueueWorkItem(work_item
, main_test_task
, DelayedWorkQueue
, irp
);
2477 return STATUS_PENDING
;
2480 static NTSTATUS
test_basic_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2482 ULONG length
= min(stack
->Parameters
.DeviceIoControl
.OutputBufferLength
, sizeof(teststr
));
2483 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2486 return STATUS_ACCESS_VIOLATION
;
2488 memcpy(buffer
, teststr
, length
);
2491 return STATUS_SUCCESS
;
2494 static NTSTATUS
get_dword(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
, DWORD value
)
2496 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2497 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2500 return STATUS_ACCESS_VIOLATION
;
2502 if (length
< sizeof(DWORD
))
2503 return STATUS_BUFFER_TOO_SMALL
;
2505 *(DWORD
*)buffer
= value
;
2506 *info
= sizeof(DWORD
);
2507 return STATUS_SUCCESS
;
2510 static NTSTATUS
get_fscontext(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2512 ULONG length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2513 char *buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2514 struct file_context
*context
= stack
->FileObject
->FsContext
;
2517 return STATUS_ACCESS_VIOLATION
;
2519 if (length
< sizeof(DWORD
))
2520 return STATUS_BUFFER_TOO_SMALL
;
2522 *(DWORD
*)buffer
= context
->id
;
2523 *info
= sizeof(DWORD
);
2524 return STATUS_SUCCESS
;
2527 static NTSTATUS
return_status(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG code
)
2529 ULONG input_length
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
2530 ULONG output_length
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2531 const struct return_status_params
*input_buffer
;
2532 struct return_status_params params
;
2533 void *output_buffer
;
2535 if (code
== IOCTL_WINETEST_RETURN_STATUS_NEITHER
)
2537 input_buffer
= stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
2538 output_buffer
= irp
->UserBuffer
;
2540 else if (code
== IOCTL_WINETEST_RETURN_STATUS_DIRECT
)
2542 input_buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2543 output_buffer
= MmGetSystemAddressForMdlSafe(irp
->MdlAddress
, NormalPagePriority
);
2547 input_buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2548 output_buffer
= irp
->AssociatedIrp
.SystemBuffer
;
2551 if (!input_buffer
|| !output_buffer
)
2553 irp
->IoStatus
.Status
= STATUS_ACCESS_VIOLATION
;
2554 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2555 return STATUS_ACCESS_VIOLATION
;
2558 if (input_length
< sizeof(params
) || output_length
< 6)
2560 irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
2561 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2562 return STATUS_BUFFER_TOO_SMALL
;
2565 params
= *input_buffer
;
2567 if (params
.ret_status
== STATUS_PENDING
&& !params
.pending
)
2569 /* this causes kernel hangs under certain conditions */
2570 irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2571 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2572 return STATUS_INVALID_PARAMETER
;
2576 IoMarkIrpPending(irp
);
2578 /* intentionally report the wrong information (and status) */
2579 memcpy(output_buffer
, "ghijkl", 6);
2580 irp
->IoStatus
.Information
= 3;
2581 irp
->IoStatus
.Status
= params
.iosb_status
;
2582 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2584 return params
.ret_status
;
2587 static NTSTATUS
test_load_driver_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG_PTR
*info
)
2589 BOOL
*load
= irp
->AssociatedIrp
.SystemBuffer
;
2590 UNICODE_STRING name
;
2593 return STATUS_ACCESS_VIOLATION
;
2597 RtlInitUnicodeString(&name
, driver2_path
);
2599 return ZwLoadDriver(&name
);
2601 return ZwUnloadDriver(&name
);
2604 static NTSTATUS
completion_ioctl(DEVICE_OBJECT
*device
, IRP
*irp
, IO_STACK_LOCATION
*stack
)
2606 if (device
== upper_device
)
2608 ok(irp
->CurrentLocation
== 2, "Got current location %u.\n", irp
->CurrentLocation
);
2609 ok(!irp
->PendingReturned
, "Got pending flag %u.\n", irp
->PendingReturned
);
2610 ok(stack
->Control
== (SL_INVOKE_ON_CANCEL
| SL_INVOKE_ON_ERROR
| SL_INVOKE_ON_SUCCESS
),
2611 "Got control flags %#x.\n", stack
->Control
);
2612 stack
= IoGetNextIrpStackLocation(irp
);
2613 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
2614 stack
= irp
->Tail
.Overlay
.CurrentStackLocation
+ 1; /* previous location */
2615 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
2617 IoCopyCurrentIrpStackLocationToNext(irp
);
2618 IoSetCompletionRoutine(irp
, completion_cb
, upper_device
, TRUE
, TRUE
, TRUE
);
2619 return IoCallDriver(lower_device
, irp
);
2623 ok(device
== lower_device
, "Got wrong device.\n");
2624 ok(irp
->CurrentLocation
== 1, "Got current location %u.\n", irp
->CurrentLocation
);
2625 ok(!irp
->PendingReturned
, "Got pending flag %u.\n", irp
->PendingReturned
);
2626 ok(stack
->Control
== (SL_INVOKE_ON_CANCEL
| SL_INVOKE_ON_ERROR
| SL_INVOKE_ON_SUCCESS
),
2627 "Got control flags %#x.\n", stack
->Control
);
2628 stack
= irp
->Tail
.Overlay
.CurrentStackLocation
+ 1; /* previous location */
2629 ok(stack
->Control
== (SL_INVOKE_ON_CANCEL
| SL_INVOKE_ON_ERROR
| SL_INVOKE_ON_SUCCESS
),
2630 "Got control flags %#x.\n", stack
->Control
);
2631 stack
= irp
->Tail
.Overlay
.CurrentStackLocation
+ 2; /* top location */
2632 ok(!stack
->Control
, "Got control flags %#x.\n", stack
->Control
);
2634 if (completion_lower_pending
)
2636 IoMarkIrpPending(irp
);
2637 return STATUS_PENDING
;
2641 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2642 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2643 return STATUS_SUCCESS
;
2648 static NTSTATUS WINAPI
driver_Create(DEVICE_OBJECT
*device
, IRP
*irp
)
2650 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
2651 struct file_context
*context
= ExAllocatePool(PagedPool
, sizeof(*context
));
2655 irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
2656 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2657 return STATUS_NO_MEMORY
;
2660 context
->id
= ++create_count
;
2661 context
->namelen
= min(irpsp
->FileObject
->FileName
.Length
, sizeof(context
->name
));
2662 memcpy(context
->name
, irpsp
->FileObject
->FileName
.Buffer
, context
->namelen
);
2663 irpsp
->FileObject
->FsContext
= context
;
2665 last_created_file
= irpsp
->FileObject
;
2666 create_caller_thread
= KeGetCurrentThread();
2667 create_irp_thread
= irp
->Tail
.Overlay
.Thread
;
2669 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2670 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2671 return STATUS_SUCCESS
;
2674 static NTSTATUS WINAPI
driver_IoControl(DEVICE_OBJECT
*device
, IRP
*irp
)
2676 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2677 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
2679 switch (stack
->Parameters
.DeviceIoControl
.IoControlCode
)
2681 case IOCTL_WINETEST_BASIC_IOCTL
:
2682 status
= test_basic_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
2684 case IOCTL_WINETEST_MAIN_TEST
:
2685 status
= main_test(device
, irp
, stack
);
2687 case IOCTL_WINETEST_LOAD_DRIVER
:
2688 status
= test_load_driver_ioctl(irp
, stack
, &irp
->IoStatus
.Information
);
2690 case IOCTL_WINETEST_RESET_CANCEL
:
2692 status
= STATUS_SUCCESS
;
2694 case IOCTL_WINETEST_TEST_CANCEL
:
2695 IoSetCancelRoutine(irp
, cancel_ioctl_irp
);
2696 IoMarkIrpPending(irp
);
2697 return STATUS_PENDING
;
2698 case IOCTL_WINETEST_GET_CANCEL_COUNT
:
2699 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, cancel_cnt
);
2701 case IOCTL_WINETEST_GET_CREATE_COUNT
:
2702 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, create_count
);
2704 case IOCTL_WINETEST_GET_CLOSE_COUNT
:
2705 status
= get_dword(irp
, stack
, &irp
->IoStatus
.Information
, close_count
);
2707 case IOCTL_WINETEST_GET_FSCONTEXT
:
2708 status
= get_fscontext(irp
, stack
, &irp
->IoStatus
.Information
);
2710 case IOCTL_WINETEST_RETURN_STATUS_BUFFERED
:
2711 case IOCTL_WINETEST_RETURN_STATUS_DIRECT
:
2712 case IOCTL_WINETEST_RETURN_STATUS_NEITHER
:
2713 return return_status(irp
, stack
, stack
->Parameters
.DeviceIoControl
.IoControlCode
);
2714 case IOCTL_WINETEST_DETACH
:
2715 IoDetachDevice(lower_device
);
2716 status
= STATUS_SUCCESS
;
2718 case IOCTL_WINETEST_COMPLETION
:
2719 return completion_ioctl(device
, irp
, stack
);
2724 if (status
!= STATUS_PENDING
)
2726 irp
->IoStatus
.Status
= status
;
2727 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2732 static NTSTATUS WINAPI
driver_FlushBuffers(DEVICE_OBJECT
*device
, IRP
*irp
)
2734 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation(irp
);
2735 ok(device
== lower_device
, "Expected device %p, got %p.\n", lower_device
, device
);
2736 ok(irpsp
->DeviceObject
== device
, "device != DeviceObject\n");
2737 ok(irp
->Tail
.Overlay
.Thread
== (PETHREAD
)KeGetCurrentThread(),
2738 "IRP thread is not the current thread\n");
2739 IoMarkIrpPending(irp
);
2740 return STATUS_PENDING
;
2743 static void WINAPI
blocking_irp_task(DEVICE_OBJECT
*device
, void *context
)
2745 LARGE_INTEGER timeout
;
2748 timeout
.QuadPart
= -100 * 10000;
2749 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
2751 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2752 irp
->IoStatus
.Information
= 0;
2753 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2756 static void WINAPI
blocking_irp_failure_task(DEVICE_OBJECT
*device
, void *context
)
2758 LARGE_INTEGER timeout
;
2761 timeout
.QuadPart
= -100 * 10000;
2762 KeDelayExecutionThread( KernelMode
, FALSE
, &timeout
);
2764 irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_READY
;
2765 irp
->IoStatus
.Information
= 0;
2766 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2769 static BOOL
compare_file_name(const struct file_context
*context
, const WCHAR
*expect
)
2771 return context
->namelen
== wcslen(expect
) * sizeof(WCHAR
)
2772 && !kmemcmp(context
->name
, expect
, context
->namelen
);
2775 static NTSTATUS WINAPI
driver_QueryInformation(DEVICE_OBJECT
*device
, IRP
*irp
)
2777 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2780 switch (stack
->Parameters
.QueryFile
.FileInformationClass
)
2782 case FileNameInformation
:
2784 const struct file_context
*context
= stack
->FileObject
->FsContext
;
2785 FILE_NAME_INFORMATION
*info
= irp
->AssociatedIrp
.SystemBuffer
;
2788 if (stack
->Parameters
.QueryFile
.Length
< sizeof(*info
))
2790 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2794 if (compare_file_name(context
, L
"\\notimpl"))
2796 ret
= STATUS_NOT_IMPLEMENTED
;
2799 else if (compare_file_name(context
, L
""))
2801 ret
= STATUS_INVALID_DEVICE_REQUEST
;
2804 else if (compare_file_name(context
, L
"\\badparam"))
2806 ret
= STATUS_INVALID_PARAMETER
;
2809 else if (compare_file_name(context
, L
"\\genfail"))
2811 ret
= STATUS_UNSUCCESSFUL
;
2814 else if (compare_file_name(context
, L
"\\badtype"))
2816 ret
= STATUS_OBJECT_TYPE_MISMATCH
;
2820 len
= stack
->Parameters
.QueryFile
.Length
- FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
);
2821 if (len
< context
->namelen
)
2822 ret
= STATUS_BUFFER_OVERFLOW
;
2825 len
= context
->namelen
;
2826 ret
= STATUS_SUCCESS
;
2828 irp
->IoStatus
.Information
= FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
) + len
;
2829 info
->FileNameLength
= context
->namelen
;
2830 memcpy(info
->FileName
, context
->name
, len
);
2835 ret
= STATUS_NOT_IMPLEMENTED
;
2839 irp
->IoStatus
.Status
= ret
;
2840 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2844 static NTSTATUS WINAPI
driver_QueryVolumeInformation(DEVICE_OBJECT
*device
, IRP
*irp
)
2846 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2847 ULONG length
= stack
->Parameters
.QueryVolume
.Length
;
2850 switch (stack
->Parameters
.QueryVolume
.FsInformationClass
)
2852 case FileFsVolumeInformation
:
2854 FILE_FS_VOLUME_INFORMATION
*info
= irp
->AssociatedIrp
.SystemBuffer
;
2855 static const WCHAR label
[] = L
"WineTestDriver";
2856 ULONG serial
= 0xdeadbeef;
2858 if (length
< sizeof(FILE_FS_VOLUME_INFORMATION
))
2860 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2864 info
->VolumeCreationTime
.QuadPart
= 0;
2865 info
->VolumeSerialNumber
= serial
;
2866 info
->VolumeLabelLength
= min( lstrlenW(label
) * sizeof(WCHAR
),
2867 length
- offsetof( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) );
2868 info
->SupportsObjects
= TRUE
;
2869 memcpy( info
->VolumeLabel
, label
, info
->VolumeLabelLength
);
2871 irp
->IoStatus
.Information
= offsetof( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
) + info
->VolumeLabelLength
;
2872 ret
= STATUS_SUCCESS
;
2876 case FileFsSizeInformation
:
2878 IoMarkIrpPending(irp
);
2879 IoQueueWorkItem(work_item
, blocking_irp_task
, DelayedWorkQueue
, irp
);
2880 return STATUS_PENDING
;
2883 case FileFsFullSizeInformation
:
2885 IoMarkIrpPending(irp
);
2886 IoQueueWorkItem(work_item
, blocking_irp_failure_task
, DelayedWorkQueue
, irp
);
2887 return STATUS_PENDING
;
2891 ret
= STATUS_NOT_IMPLEMENTED
;
2895 irp
->IoStatus
.Status
= ret
;
2896 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2900 static NTSTATUS WINAPI
driver_Close(DEVICE_OBJECT
*device
, IRP
*irp
)
2902 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
2904 if (stack
->FileObject
->FsContext
)
2905 ExFreePool(stack
->FileObject
->FsContext
);
2906 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2907 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
2908 return STATUS_SUCCESS
;
2911 static VOID WINAPI
driver_Unload(DRIVER_OBJECT
*driver
)
2913 UNICODE_STRING linkW
;
2915 DbgPrint("unloading driver\n");
2917 IoFreeWorkItem(work_item
);
2920 RtlInitUnicodeString(&linkW
, L
"\\DosDevices\\WineTestDriver");
2921 IoDeleteSymbolicLink(&linkW
);
2923 IoDeleteDevice(upper_device
);
2924 IoDeleteDevice(lower_device
);
2929 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, PUNICODE_STRING registry
)
2931 UNICODE_STRING nameW
, linkW
;
2935 if ((status
= winetest_init()))
2938 DbgPrint("loading driver\n");
2940 driver_obj
= driver
;
2942 /* Allow unloading of the driver */
2943 driver
->DriverUnload
= driver_Unload
;
2945 /* Set driver functions */
2946 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_Create
;
2947 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_IoControl
;
2948 driver
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = driver_FlushBuffers
;
2949 driver
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] = driver_QueryInformation
;
2950 driver
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = driver_QueryVolumeInformation
;
2951 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_Close
;
2953 RtlInitUnicodeString(&nameW
, L
"IoDriverObjectType");
2954 pIoDriverObjectType
= MmGetSystemRoutineAddress(&nameW
);
2956 RtlInitUnicodeString(&nameW
, L
"\\Driver\\WineTestDriver");
2957 status
= ObReferenceObjectByName(&nameW
, 0, NULL
, 0, *pIoDriverObjectType
, KernelMode
, NULL
, &obj
);
2958 ok(!status
, "got %#lx\n", status
);
2959 ok(obj
== driver
, "expected %p, got %p\n", driver
, obj
);
2960 ObDereferenceObject(obj
);
2962 RtlInitUnicodeString(&nameW
, L
"\\Device\\WineTestDriver");
2963 RtlInitUnicodeString(&linkW
, L
"\\DosDevices\\WineTestDriver");
2965 status
= IoCreateDevice(driver
, 0, &nameW
, FILE_DEVICE_UNKNOWN
, FILE_DEVICE_SECURE_OPEN
, FALSE
, &lower_device
);
2966 ok(!status
, "failed to create device, status %#lx\n", status
);
2967 status
= IoCreateSymbolicLink(&linkW
, &nameW
);
2968 ok(!status
, "failed to create link, status %#lx\n", status
);
2969 lower_device
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2971 RtlInitUnicodeString(&nameW
, L
"\\Device\\WineTestUpper");
2972 status
= IoCreateDevice(driver
, 0, &nameW
, FILE_DEVICE_UNKNOWN
, FILE_DEVICE_SECURE_OPEN
, FALSE
, &upper_device
);
2973 ok(!status
, "failed to create device, status %#lx\n", status
);
2975 IoAttachDeviceToDeviceStack(upper_device
, lower_device
);
2976 upper_device
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2978 work_item
= IoAllocateWorkItem(lower_device
);
2979 ok(work_item
!= NULL
, "work_item = NULL\n");
2981 return STATUS_SUCCESS
;