ntoskrnl/tests: Add FltBuildDefaultSecurityDescriptor test.
[wine.git] / dlls / ntoskrnl.exe / tests / driver.c
blob751f2acff9675caf7b4c961a385c02b657dd1d4e
1 /*
2 * ntoskrnl.exe testing framework
4 * Copyright 2015 Sebastian Lackner
5 * Copyright 2015 Michael Müller
6 * Copyright 2015 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep testdll
25 #endif
27 #include <stdarg.h>
28 #include <stdio.h>
30 #include "ntstatus.h"
31 #define WIN32_NO_STATUS
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winternl.h"
35 #include "winioctl.h"
36 #include "ddk/ntddk.h"
37 #include "ddk/ntifs.h"
38 #include "ddk/wdm.h"
39 #include "ddk/fltkernel.h"
41 #include "driver.h"
43 #include "utils.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;
55 return 0;
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*);
69 struct file_context
71 DWORD id;
72 ULONG namelen;
73 WCHAR name[10];
76 static void *get_proc_address(const char *name)
78 UNICODE_STRING name_u;
79 ANSI_STRING name_a;
80 NTSTATUS status;
81 void *ret;
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);
90 return ret;
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;
100 *result = 1;
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,
126 TRUE, TRUE, TRUE);
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);
146 IoFreeIrp(irp);
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;
158 cancel_queue_cnt++;
161 static void test_queue(void)
163 KDEVICE_QUEUE_ENTRY *entry;
164 KDEVICE_QUEUE queue;
165 BOOLEAN ret;
166 KIRQL irql;
167 IRP *irp;
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");
218 IoCancelIrp(irp);
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");
243 IoFreeIrp(irp);
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");
259 IoCancelIrp(irp);
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");
273 IoFreeIrp(irp);
276 static void test_mdl_map(void)
278 char buffer[20] = "test buffer";
279 void *addr;
280 MDL *mdl;
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);
288 todo_wine
289 ok(addr != NULL, "MmMapLockedPagesSpecifyCache failed\n");
291 MmUnmapLockedPages(addr, mdl);
293 IoFreeMdl(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;
337 IO_STATUS_BLOCK io;
338 NTSTATUS ret;
339 HANDLE file;
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);
365 if (!ret)
367 ret = ZwQueryObject(file, ObjectNameInformation, full_name_buffer, sizeof(full_name_buffer), NULL);
368 ok(!ret, "Got unexpected status %#lx.\n", ret);
369 ZwClose(file);
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;
436 PEPROCESS current;
437 PETHREAD thread;
438 NTSTATUS ret;
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);
448 if (is_system)
449 ok(current == *pPsInitialSystemProcess, "current != PsInitialSystemProcess\n");
450 else
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");
463 if (!is_system)
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)
484 BOOLEAN result;
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};
520 HANDLE thread;
521 NTSTATUS ret;
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);
528 return thread;
531 static void join_thread(HANDLE thread)
533 NTSTATUS ret;
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);
544 join_thread(thread);
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;
565 NTSTATUS ret;
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
577 BOOL called;
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;
584 c->called = TRUE;
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;
597 void *objs[2];
598 KTIMER timer;
599 NTSTATUS ret;
600 KDPC dpc;
601 int i;
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);
713 KeResetEvent(event);
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);
727 ZwClose(handle);
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);
735 KeResetEvent(event);
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);
819 /* test mutexes */
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);
846 /* test timers */
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);
875 sleep_1ms();
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);
941 sleep_1ms();
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);
946 sleep_1ms();
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);
953 sleep_1ms();
954 ok(dpc_context.called, "DPC was not called.\n");
956 KeCancelTimer(&timer);
957 /* remove locks */
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;
998 IRP *irp = NULL;
999 KEVENT event;
1000 NTSTATUS status;
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;
1079 cancel_cnt++;
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;
1087 cancel_cnt++;
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;
1102 IRP *irp = NULL;
1103 BOOL completion_called;
1104 BOOLEAN r;
1105 NTSTATUS status;
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);
1116 IoFreeIrp(irp);
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);
1129 cancel_cnt = 0;
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);
1135 cancel_cnt = 0;
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);
1151 cancel_cnt = 0;
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);
1169 cancel_cnt = 0;
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);
1187 cancel_cnt = 0;
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);
1203 callout_cnt++;
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*);
1210 NTSTATUS ret;
1212 pKeExpandKernelStackAndCallout = get_proc_address("KeExpandKernelStackAndCallout");
1213 if (pKeExpandKernelStackAndCallout)
1215 callout_cnt = 0;
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)
1225 callout_cnt = 0;
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);
1254 list.L.Depth = 0;
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;
1287 ULONG build;
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;
1307 FILE_OBJECT *file;
1308 void *obj1, *obj2;
1309 POBJECT_TYPE obj1_type;
1310 UNICODE_STRING pathU;
1311 IO_STATUS_BLOCK io;
1312 NTSTATUS status;
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");
1381 file = obj1;
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");
1394 header = obj1;
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)
1434 BOOLEAN ret;
1435 ULONG 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;
1457 BOOLEAN ret;
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;
1477 BOOLEAN ret;
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)
1496 ERESOURCE resource;
1497 NTSTATUS status;
1498 BOOLEAN ret;
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);
1605 sleep();
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);
1654 sleep();
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);
1686 sleep();
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)
1721 NTSTATUS status;
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);
1767 else
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);
1780 ++got_completion;
1781 return STATUS_SUCCESS;
1784 static void test_completion(void)
1786 IO_STATUS_BLOCK io;
1787 NTSTATUS ret;
1788 KEVENT event;
1789 IRP *irp;
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;
1803 got_completion = 0;
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;
1820 got_completion = 0;
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;
1840 NTSTATUS status;
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";
1894 char buffer[1024];
1895 OBJECT_NAME_INFORMATION *name = (OBJECT_NAME_INFORMATION *)buffer;
1896 OBJECT_ATTRIBUTES attr;
1897 UNICODE_STRING string;
1898 ULONG ret_size;
1899 HANDLE handle;
1900 KEVENT *event;
1901 NTSTATUS ret;
1903 ret_size = 0;
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);
1908 ret_size = 0;
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");
1919 ret_size = 0;
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);
1937 ret_size = 0;
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);
1949 ret_size = 0;
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);
1957 ret_size = 0;
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)
1970 IRP *irp = 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();
1977 test_completion();
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 */
1990 int (*func)(void);
1991 int ret;
1993 func = ExAllocatePoolWithTag(NonPagedPool, sizeof(bytes), tag);
1994 ok(!!func, "Got NULL memory.\n");
1996 memcpy(func, bytes, sizeof(bytes));
1997 ret = func();
1998 ok(ret == 0xdeadbeef, "Got %#x.\n", ret);
2000 ExFreePoolWithTag(func, tag);
2002 #endif
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");
2017 return;
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;
2040 else
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;
2129 KAFFINITY cpu_mask;
2130 ULONG cpu_count;
2131 struct _KDPC dpc = {0};
2133 pKeInitializeDpc = get_proc_address("KeInitializeDpc");
2134 if(!pKeInitializeDpc)
2136 win_skip("KeInitializeDpc is not available.\n");
2137 return;
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");
2152 return;
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();
2162 cpu_count = 0;
2163 while (cpu_mask)
2165 if (cpu_mask & 1)
2166 ++cpu_count;
2168 cpu_mask >>= 1;
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;
2210 PEPROCESS process;
2211 KAPC_STATE state;
2212 NTSTATUS status;
2213 SIZE_T size;
2214 BYTE *base;
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);
2221 if (status)
2222 return;
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)
2236 size = 0xdeadbeef;
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));
2243 size = 0xdeadbeef;
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");
2253 else
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;
2273 UNICODE_STRING str;
2274 NTSTATUS status;
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);
2321 NTSTATUS status;
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");
2331 return;
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;
2352 NTSTATUS status;
2353 PSID group = NULL, owner = NULL;
2354 BOOLEAN isdefault, present;
2355 PACL acl = NULL;
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;
2360 BOOL ret;
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");
2367 return;
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");
2422 ExFreePool(sid1);
2423 ExFreePool(sid2);
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;
2433 if (!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);
2451 test_mdl_map();
2452 test_init_funcs();
2453 test_load_driver();
2454 test_sync();
2455 test_queue();
2456 test_version();
2457 test_stack_callout();
2458 test_lookaside_list();
2459 test_ob_reference();
2460 test_resource();
2461 test_lookup_thread();
2462 test_IoAttachDeviceToDeviceStack();
2463 test_object_name();
2464 #if defined(__i386__) || defined(__x86_64__)
2465 test_executable_pool();
2466 #endif
2467 test_affinity();
2468 test_dpc();
2469 test_process_memory(test_input);
2470 test_permanence();
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;
2485 if (!buffer)
2486 return STATUS_ACCESS_VIOLATION;
2488 memcpy(buffer, teststr, length);
2489 *info = 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;
2499 if (!buffer)
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;
2516 if (!buffer)
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);
2545 else
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;
2575 if (params.pending)
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;
2592 if (!load)
2593 return STATUS_ACCESS_VIOLATION;
2595 *info = 0;
2597 RtlInitUnicodeString(&name, driver2_path);
2598 if (*load)
2599 return ZwLoadDriver(&name);
2600 else
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);
2621 else
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;
2639 else
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));
2653 if (!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);
2683 break;
2684 case IOCTL_WINETEST_MAIN_TEST:
2685 status = main_test(device, irp, stack);
2686 break;
2687 case IOCTL_WINETEST_LOAD_DRIVER:
2688 status = test_load_driver_ioctl(irp, stack, &irp->IoStatus.Information);
2689 break;
2690 case IOCTL_WINETEST_RESET_CANCEL:
2691 cancel_cnt = 0;
2692 status = STATUS_SUCCESS;
2693 break;
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);
2700 break;
2701 case IOCTL_WINETEST_GET_CREATE_COUNT:
2702 status = get_dword(irp, stack, &irp->IoStatus.Information, create_count);
2703 break;
2704 case IOCTL_WINETEST_GET_CLOSE_COUNT:
2705 status = get_dword(irp, stack, &irp->IoStatus.Information, close_count);
2706 break;
2707 case IOCTL_WINETEST_GET_FSCONTEXT:
2708 status = get_fscontext(irp, stack, &irp->IoStatus.Information);
2709 break;
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;
2717 break;
2718 case IOCTL_WINETEST_COMPLETION:
2719 return completion_ioctl(device, irp, stack);
2720 default:
2721 break;
2724 if (status != STATUS_PENDING)
2726 irp->IoStatus.Status = status;
2727 IoCompleteRequest(irp, IO_NO_INCREMENT);
2729 return status;
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;
2746 IRP *irp = context;
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;
2759 IRP *irp = context;
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);
2778 NTSTATUS ret;
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;
2786 ULONG len;
2788 if (stack->Parameters.QueryFile.Length < sizeof(*info))
2790 ret = STATUS_INFO_LENGTH_MISMATCH;
2791 break;
2794 if (compare_file_name(context, L"\\notimpl"))
2796 ret = STATUS_NOT_IMPLEMENTED;
2797 break;
2799 else if (compare_file_name(context, L""))
2801 ret = STATUS_INVALID_DEVICE_REQUEST;
2802 break;
2804 else if (compare_file_name(context, L"\\badparam"))
2806 ret = STATUS_INVALID_PARAMETER;
2807 break;
2809 else if (compare_file_name(context, L"\\genfail"))
2811 ret = STATUS_UNSUCCESSFUL;
2812 break;
2814 else if (compare_file_name(context, L"\\badtype"))
2816 ret = STATUS_OBJECT_TYPE_MISMATCH;
2817 break;
2820 len = stack->Parameters.QueryFile.Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2821 if (len < context->namelen)
2822 ret = STATUS_BUFFER_OVERFLOW;
2823 else
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);
2831 break;
2834 default:
2835 ret = STATUS_NOT_IMPLEMENTED;
2836 break;
2839 irp->IoStatus.Status = ret;
2840 IoCompleteRequest(irp, IO_NO_INCREMENT);
2841 return ret;
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;
2848 NTSTATUS ret;
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;
2861 break;
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;
2873 break;
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;
2890 default:
2891 ret = STATUS_NOT_IMPLEMENTED;
2892 break;
2895 irp->IoStatus.Status = ret;
2896 IoCompleteRequest(irp, IO_NO_INCREMENT);
2897 return ret;
2900 static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
2902 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
2903 ++close_count;
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);
2918 work_item = NULL;
2920 RtlInitUnicodeString(&linkW, L"\\DosDevices\\WineTestDriver");
2921 IoDeleteSymbolicLink(&linkW);
2923 IoDeleteDevice(upper_device);
2924 IoDeleteDevice(lower_device);
2926 winetest_cleanup();
2929 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
2931 UNICODE_STRING nameW, linkW;
2932 NTSTATUS status;
2933 void *obj;
2935 if ((status = winetest_init()))
2936 return status;
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;