ntoskrnl.exe: Dispatch user IRPs to the top of the device stack.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3d011fcdff
commit
4820d9d76c
|
@ -516,6 +516,8 @@ static NTSTATUS dispatch_create( struct dispatch_context *context )
|
||||||
file->Size = sizeof(*file);
|
file->Size = sizeof(*file);
|
||||||
file->DeviceObject = device;
|
file->DeviceObject = device;
|
||||||
|
|
||||||
|
device = IoGetAttachedDevice( device );
|
||||||
|
|
||||||
if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return STATUS_NO_MEMORY;
|
if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
irpsp = IoGetNextIrpStackLocation( irp );
|
irpsp = IoGetNextIrpStackLocation( irp );
|
||||||
|
@ -550,7 +552,7 @@ static NTSTATUS dispatch_close( struct dispatch_context *context )
|
||||||
|
|
||||||
if (!file) return STATUS_INVALID_HANDLE;
|
if (!file) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
device = file->DeviceObject;
|
device = IoGetAttachedDevice( file->DeviceObject );
|
||||||
|
|
||||||
TRACE( "device %p file %p\n", device, file );
|
TRACE( "device %p file %p\n", device, file );
|
||||||
|
|
||||||
|
@ -590,7 +592,7 @@ static NTSTATUS dispatch_read( struct dispatch_context *context )
|
||||||
|
|
||||||
if (!file) return STATUS_INVALID_HANDLE;
|
if (!file) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
device = file->DeviceObject;
|
device = IoGetAttachedDevice( file->DeviceObject );
|
||||||
|
|
||||||
TRACE( "device %p file %p size %u\n", device, file, out_size );
|
TRACE( "device %p file %p size %u\n", device, file, out_size );
|
||||||
|
|
||||||
|
@ -630,7 +632,7 @@ static NTSTATUS dispatch_write( struct dispatch_context *context )
|
||||||
|
|
||||||
if (!file) return STATUS_INVALID_HANDLE;
|
if (!file) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
device = file->DeviceObject;
|
device = IoGetAttachedDevice( file->DeviceObject );
|
||||||
|
|
||||||
TRACE( "device %p file %p size %u\n", device, file, context->in_size );
|
TRACE( "device %p file %p size %u\n", device, file, context->in_size );
|
||||||
|
|
||||||
|
@ -665,7 +667,7 @@ static NTSTATUS dispatch_flush( struct dispatch_context *context )
|
||||||
|
|
||||||
if (!file) return STATUS_INVALID_HANDLE;
|
if (!file) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
device = file->DeviceObject;
|
device = IoGetAttachedDevice( file->DeviceObject );
|
||||||
|
|
||||||
TRACE( "device %p file %p\n", device, file );
|
TRACE( "device %p file %p\n", device, file );
|
||||||
|
|
||||||
|
@ -697,7 +699,7 @@ static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
|
||||||
|
|
||||||
if (!file) return STATUS_INVALID_HANDLE;
|
if (!file) return STATUS_INVALID_HANDLE;
|
||||||
|
|
||||||
device = file->DeviceObject;
|
device = IoGetAttachedDevice( file->DeviceObject );
|
||||||
|
|
||||||
TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
|
TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
|
||||||
context->params.ioctl.code, device, file, context->in_size, out_size );
|
context->params.ioctl.code, device, file, context->in_size, out_size );
|
||||||
|
|
|
@ -34,12 +34,15 @@
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
static const WCHAR driver_device[] = {'\\','D','e','v','i','c','e',
|
static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
|
||||||
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
|
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
|
||||||
|
static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
|
||||||
|
'\\','W','i','n','e','T','e','s','t','U','p','p','e','r',0};
|
||||||
static const WCHAR driver_link[] = {'\\','D','o','s','D','e','v','i','c','e','s',
|
static const WCHAR driver_link[] = {'\\','D','o','s','D','e','v','i','c','e','s',
|
||||||
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
|
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
|
||||||
|
|
||||||
static DRIVER_OBJECT *driver_obj;
|
static DRIVER_OBJECT *driver_obj;
|
||||||
|
static DEVICE_OBJECT *lower_device, *upper_device;
|
||||||
|
|
||||||
static HANDLE okfile;
|
static HANDLE okfile;
|
||||||
static LONG successes;
|
static LONG successes;
|
||||||
|
@ -234,10 +237,11 @@ static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
||||||
|
|
||||||
|
ok(device == upper_device, "Expected device %p, got %p.\n", upper_device, device);
|
||||||
ok(last_created_file != NULL, "last_created_file = NULL\n");
|
ok(last_created_file != NULL, "last_created_file = NULL\n");
|
||||||
ok(irpsp->FileObject == last_created_file, "FileObject != last_created_file\n");
|
ok(irpsp->FileObject == last_created_file, "FileObject != last_created_file\n");
|
||||||
ok(irpsp->DeviceObject == device, "unexpected DeviceObject\n");
|
ok(irpsp->DeviceObject == upper_device, "unexpected DeviceObject\n");
|
||||||
ok(irpsp->FileObject->DeviceObject == device, "unexpected FileObject->DeviceObject\n");
|
ok(irpsp->FileObject->DeviceObject == lower_device, "unexpected FileObject->DeviceObject\n");
|
||||||
ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
|
ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
|
||||||
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
|
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
|
||||||
"IRP thread is not the current thread\n");
|
"IRP thread is not the current thread\n");
|
||||||
|
@ -1591,7 +1595,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st
|
||||||
|
|
||||||
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
|
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
|
||||||
|
|
||||||
main_test_work_item = IoAllocateWorkItem(device);
|
main_test_work_item = IoAllocateWorkItem(lower_device);
|
||||||
ok(main_test_work_item != NULL, "main_test_work_item = NULL\n");
|
ok(main_test_work_item != NULL, "main_test_work_item = NULL\n");
|
||||||
|
|
||||||
IoQueueWorkItem(main_test_work_item, main_test_task, DelayedWorkQueue, irp);
|
IoQueueWorkItem(main_test_work_item, main_test_task, DelayedWorkQueue, irp);
|
||||||
|
@ -1687,6 +1691,10 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
case IOCTL_WINETEST_GET_CANCEL_COUNT:
|
case IOCTL_WINETEST_GET_CANCEL_COUNT:
|
||||||
status = get_cancel_count(irp, stack, &irp->IoStatus.Information);
|
status = get_cancel_count(irp, stack, &irp->IoStatus.Information);
|
||||||
break;
|
break;
|
||||||
|
case IOCTL_WINETEST_DETACH:
|
||||||
|
IoDetachDevice(lower_device);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1703,6 +1711,7 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
|
static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
|
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
|
||||||
|
ok(device == lower_device, "Expected device %p, got %p.\n", lower_device, device);
|
||||||
ok(irpsp->DeviceObject == device, "device != DeviceObject\n");
|
ok(irpsp->DeviceObject == device, "device != DeviceObject\n");
|
||||||
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
|
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
|
||||||
"IRP thread is not the current thread\n");
|
"IRP thread is not the current thread\n");
|
||||||
|
@ -1726,13 +1735,13 @@ static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
|
||||||
RtlInitUnicodeString(&linkW, driver_link);
|
RtlInitUnicodeString(&linkW, driver_link);
|
||||||
IoDeleteSymbolicLink(&linkW);
|
IoDeleteSymbolicLink(&linkW);
|
||||||
|
|
||||||
IoDeleteDevice(driver->DeviceObject);
|
IoDeleteDevice(upper_device);
|
||||||
|
IoDeleteDevice(lower_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
|
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
|
||||||
{
|
{
|
||||||
UNICODE_STRING nameW, linkW;
|
UNICODE_STRING nameW, linkW;
|
||||||
DEVICE_OBJECT *device;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
DbgPrint("loading driver\n");
|
DbgPrint("loading driver\n");
|
||||||
|
@ -1748,12 +1757,29 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
|
||||||
driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
|
driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
|
||||||
driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
|
driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
|
||||||
|
|
||||||
RtlInitUnicodeString(&nameW, driver_device);
|
RtlInitUnicodeString(&nameW, device_name);
|
||||||
RtlInitUnicodeString(&linkW, driver_link);
|
RtlInitUnicodeString(&linkW, driver_link);
|
||||||
|
|
||||||
if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
|
if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
|
||||||
FILE_DEVICE_SECURE_OPEN, FALSE, &device)))
|
FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device)))
|
||||||
|
{
|
||||||
status = IoCreateSymbolicLink(&linkW, &nameW);
|
status = IoCreateSymbolicLink(&linkW, &nameW);
|
||||||
|
lower_device->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
RtlInitUnicodeString(&nameW, upper_name);
|
||||||
|
|
||||||
|
status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
|
||||||
|
FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
IoAttachDeviceToDeviceStack(upper_device, lower_device);
|
||||||
|
upper_device->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#define IOCTL_WINETEST_RESET_CANCEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
#define IOCTL_WINETEST_RESET_CANCEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
#define IOCTL_WINETEST_TEST_CANCEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
#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_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)
|
||||||
|
|
||||||
static const char teststr[] = "Wine is not an emulator";
|
static const char teststr[] = "Wine is not an emulator";
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,6 @@ static void unload_driver(SC_HANDLE service)
|
||||||
{
|
{
|
||||||
SERVICE_STATUS status;
|
SERVICE_STATUS status;
|
||||||
|
|
||||||
CloseHandle(device);
|
|
||||||
|
|
||||||
ControlService(service, SERVICE_CONTROL_STOP, &status);
|
ControlService(service, SERVICE_CONTROL_STOP, &status);
|
||||||
while (status.dwCurrentState == SERVICE_STOP_PENDING)
|
while (status.dwCurrentState == SERVICE_STOP_PENDING)
|
||||||
{
|
{
|
||||||
|
@ -343,6 +341,8 @@ START_TEST(ntoskrnl)
|
||||||
{
|
{
|
||||||
char filename[MAX_PATH], filename2[MAX_PATH];
|
char filename[MAX_PATH], filename2[MAX_PATH];
|
||||||
SC_HANDLE service, service2;
|
SC_HANDLE service, service2;
|
||||||
|
DWORD written;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||||
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
|
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
|
||||||
|
@ -368,6 +368,13 @@ START_TEST(ntoskrnl)
|
||||||
test_overlapped();
|
test_overlapped();
|
||||||
test_load_driver(service2);
|
test_load_driver(service2);
|
||||||
|
|
||||||
|
/* We need a separate ioctl to call IoDetachDevice(); calling it in the
|
||||||
|
* driver unload routine causes a live-lock. */
|
||||||
|
ret = DeviceIoControl(device, IOCTL_WINETEST_DETACH, NULL, 0, NULL, 0, &written, NULL);
|
||||||
|
ok(ret, "DeviceIoControl failed: %u\n", GetLastError());
|
||||||
|
|
||||||
|
CloseHandle(device);
|
||||||
|
|
||||||
unload_driver(service2);
|
unload_driver(service2);
|
||||||
unload_driver(service);
|
unload_driver(service);
|
||||||
ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError());
|
ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError());
|
||||||
|
|
|
@ -130,6 +130,7 @@ typedef struct _FS_FILTER_CALLBACKS
|
||||||
} FS_FILTER_CALLBACKS, *PFS_FILTER_CALLBACKS;
|
} FS_FILTER_CALLBACKS, *PFS_FILTER_CALLBACKS;
|
||||||
|
|
||||||
BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING, PUNICODE_STRING, BOOLEAN, PWCH);
|
BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING, PUNICODE_STRING, BOOLEAN, PWCH);
|
||||||
|
DEVICE_OBJECT * WINAPI IoGetAttachedDevice(DEVICE_OBJECT*);
|
||||||
NTSTATUS WINAPI ObOpenObjectByPointer(void*,ULONG,PACCESS_STATE,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,HANDLE*);
|
NTSTATUS WINAPI ObOpenObjectByPointer(void*,ULONG,PACCESS_STATE,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,HANDLE*);
|
||||||
NTSTATUS WINAPI ObQueryNameString(PVOID,POBJECT_NAME_INFORMATION,ULONG,PULONG);
|
NTSTATUS WINAPI ObQueryNameString(PVOID,POBJECT_NAME_INFORMATION,ULONG,PULONG);
|
||||||
BOOLEAN WINAPI PsIsSystemThread(PETHREAD);
|
BOOLEAN WINAPI PsIsSystemThread(PETHREAD);
|
||||||
|
|
Loading…
Reference in New Issue