diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 41b142065ff..f43e48fd5e0 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -209,6 +209,7 @@ static void *get_proc_address(const char *name) } static FILE_OBJECT *last_created_file; +static unsigned int create_count, close_count; static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device) { @@ -1631,7 +1632,7 @@ static NTSTATUS test_basic_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR * return STATUS_SUCCESS; } -static NTSTATUS get_cancel_count(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) +static NTSTATUS get_dword(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info, DWORD value) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; char *buffer = irp->AssociatedIrp.SystemBuffer; @@ -1642,7 +1643,24 @@ static NTSTATUS get_cancel_count(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR * if (length < sizeof(DWORD)) return STATUS_BUFFER_TOO_SMALL; - *(DWORD*)buffer = cancel_cnt; + *(DWORD*)buffer = value; + *info = sizeof(DWORD); + return STATUS_SUCCESS; +} + +static NTSTATUS get_fscontext(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) +{ + ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; + char *buffer = irp->AssociatedIrp.SystemBuffer; + DWORD *context = stack->FileObject->FsContext; + + if (!buffer || !context) + return STATUS_ACCESS_VIOLATION; + + if (length < sizeof(DWORD)) + return STATUS_BUFFER_TOO_SMALL; + + *(DWORD*)buffer = *context; *info = sizeof(DWORD); return STATUS_SUCCESS; } @@ -1667,8 +1685,13 @@ static NTSTATUS test_load_driver_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + DWORD *context = ExAllocatePool(PagedPool, sizeof(*context)); last_created_file = irpsp->FileObject; + ++create_count; + if (context) + *context = create_count; + irpsp->FileObject->FsContext = context; create_caller_thread = KeGetCurrentThread(); irp->IoStatus.Status = STATUS_SUCCESS; @@ -1701,7 +1724,16 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) IoMarkIrpPending(irp); return STATUS_PENDING; case IOCTL_WINETEST_GET_CANCEL_COUNT: - status = get_cancel_count(irp, stack, &irp->IoStatus.Information); + status = get_dword(irp, stack, &irp->IoStatus.Information, cancel_cnt); + break; + case IOCTL_WINETEST_GET_CREATE_COUNT: + status = get_dword(irp, stack, &irp->IoStatus.Information, create_count); + break; + case IOCTL_WINETEST_GET_CLOSE_COUNT: + status = get_dword(irp, stack, &irp->IoStatus.Information, close_count); + break; + case IOCTL_WINETEST_GET_FSCONTEXT: + status = get_fscontext(irp, stack, &irp->IoStatus.Information); break; case IOCTL_WINETEST_DETACH: IoDetachDevice(lower_device); @@ -1733,6 +1765,10 @@ static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp) static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp) { + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + ++close_count; + if (stack->FileObject->FsContext) + ExFreePool(stack->FileObject->FsContext); irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index d5ff09ac429..a468cbda9ec 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -29,6 +29,9 @@ #define IOCTL_WINETEST_TEST_CANCEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_GET_CANCEL_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_DETACH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_CREATE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_CLOSE_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_GET_FSCONTEXT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) static const char teststr[] = "Wine is not an emulator"; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 48ddb299cfd..dfd0cb3ba63 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -318,6 +318,76 @@ static void test_load_driver(SC_HANDLE service) ok(status.dwCurrentState == SERVICE_STOPPED, "got state %#x\n", status.dwCurrentState); } +static void test_file_handles(void) +{ + DWORD count, ret_size; + HANDLE file, dup, file2; + BOOL ret; + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CREATE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 2, "got %u\n", count); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CLOSE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 1, "got %u\n", count); + + file = CreateFileA("\\\\.\\WineTestDriver", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CREATE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 3, "got %u\n", count); + + file2 = CreateFileA("\\\\.\\WineTestDriver", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(file2 != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CREATE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 4, "got %u\n", count); + + ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup, 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(ret, "failed to duplicate handle: %u\n", GetLastError()); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CREATE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 4, "got %u\n", count); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_FSCONTEXT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 1, "got %u\n", count); + + ret = DeviceIoControl(file, IOCTL_WINETEST_GET_FSCONTEXT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 3, "got %u\n", count); + + ret = DeviceIoControl(file2, IOCTL_WINETEST_GET_FSCONTEXT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 4, "got %u\n", count); + + ret = DeviceIoControl(dup, IOCTL_WINETEST_GET_FSCONTEXT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 3, "got %u\n", count); + + CloseHandle(dup); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CLOSE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 1, "got %u\n", count); + + CloseHandle(file2); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CLOSE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 2, "got %u\n", count); + + CloseHandle(file); + + ret = DeviceIoControl(device, IOCTL_WINETEST_GET_CLOSE_COUNT, NULL, 0, &count, sizeof(count), &ret_size, NULL); + ok(ret, "ioctl failed: %u\n", GetLastError()); + ok(count == 3, "got %u\n", count); +} + static void test_driver3(void) { char filename[MAX_PATH]; @@ -369,6 +439,7 @@ START_TEST(ntoskrnl) main_test(); test_overlapped(); test_load_driver(service2); + test_file_handles(); /* We need a separate ioctl to call IoDetachDevice(); calling it in the * driver unload routine causes a live-lock. */