From 4cbe5b78d3f2406776e512b7688853c60ccf907c Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 16 May 2007 21:13:34 +0200 Subject: [PATCH] ntoskrnl.exe: Export a Wine-internal function to run the device request handling loop. --- dlls/ntoskrnl.exe/ntoskrnl.c | 124 ++++++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 8 +++ 2 files changed, 132 insertions(+) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 46cf8201e5b..b14fca505a3 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -36,6 +36,7 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); +WINE_DECLARE_DEBUG_CHANNEL(relay); KSYSTEM_TIME KeTickCount; @@ -101,6 +102,129 @@ static HANDLE get_device_manager(void) return ret; } +/* process an ioctl request for a given device */ +static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size, + void *out_buff, ULONG *out_size ) +{ + IRP irp; + MDL mdl; + IO_STACK_LOCATION irpsp; + PDRIVER_DISPATCH dispatch = device->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]; + NTSTATUS status; + + TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, *out_size ); + + /* so we can spot things that we should initialize */ + memset( &irp, 0x55, sizeof(irp) ); + memset( &irpsp, 0x66, sizeof(irpsp) ); + memset( &mdl, 0x77, sizeof(mdl) ); + + irp.RequestorMode = UserMode; + irp.AssociatedIrp.SystemBuffer = in_buff; + irp.UserBuffer = out_buff; + irp.MdlAddress = &mdl; + irp.Tail.Overlay.s.u.CurrentStackLocation = &irpsp; + + irpsp.MajorFunction = IRP_MJ_DEVICE_CONTROL; + irpsp.Parameters.DeviceIoControl.OutputBufferLength = *out_size; + irpsp.Parameters.DeviceIoControl.InputBufferLength = in_size; + irpsp.Parameters.DeviceIoControl.IoControlCode = code; + irpsp.Parameters.DeviceIoControl.Type3InputBuffer = in_buff; + irpsp.DeviceObject = device; + + mdl.Next = NULL; + mdl.Size = 0; + mdl.StartVa = out_buff; + mdl.ByteCount = *out_size; + mdl.ByteOffset = 0; + + device->CurrentIrp = &irp; + + if (TRACE_ON(relay)) + DPRINTF( "%04x:Call driver dispatch %p (device=%p,irp=%p)\n", + GetCurrentThreadId(), dispatch, device, &irp ); + + status = dispatch( device, &irp ); + + if (TRACE_ON(relay)) + DPRINTF( "%04x:Ret driver dispatch %p (device=%p,irp=%p) retval=%08x\n", + GetCurrentThreadId(), dispatch, device, &irp, status ); + + *out_size = irp.IoStatus.u.Status ? 0 : irp.IoStatus.Information; + return irp.IoStatus.u.Status; +} + + +/*********************************************************************** + * wine_ntoskrnl_main_loop (Not a Windows API) + */ +NTSTATUS wine_ntoskrnl_main_loop( HANDLE stop_event ) +{ + HANDLE manager = get_device_manager(); + HANDLE ioctl = 0; + NTSTATUS status = STATUS_SUCCESS; + ULONG code = 0; + void *in_buff, *out_buff = NULL; + DEVICE_OBJECT *device = NULL; + ULONG in_size = 4096, out_size = 0; + HANDLE handles[2]; + + if (!(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size ))) + { + ERR( "failed to allocate buffer\n" ); + return STATUS_NO_MEMORY; + } + + handles[0] = stop_event; + handles[1] = manager; + + for (;;) + { + SERVER_START_REQ( get_next_device_request ) + { + req->manager = manager; + req->prev = ioctl; + req->status = status; + wine_server_add_data( req, out_buff, out_size ); + wine_server_set_reply( req, in_buff, in_size ); + if (!(status = wine_server_call( req ))) + { + code = reply->code; + ioctl = reply->next; + device = reply->user_ptr; + in_size = reply->in_size; + out_size = reply->out_size; + } + else + { + ioctl = 0; /* no previous ioctl */ + out_size = 0; + in_size = reply->in_size; + } + } + SERVER_END_REQ; + + switch(status) + { + case STATUS_SUCCESS: + HeapFree( GetProcessHeap(), 0, out_buff ); + if (out_size) out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ); + else out_buff = NULL; + status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size ); + break; + case STATUS_BUFFER_OVERFLOW: + HeapFree( GetProcessHeap(), 0, in_buff ); + in_buff = HeapAlloc( GetProcessHeap(), 0, in_size ); + /* restart with larger buffer */ + break; + case STATUS_PENDING: + if (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) == WAIT_OBJECT_0) + return STATUS_SUCCESS; + break; + } + } +} + /*********************************************************************** * IoCreateDevice (NTOSKRNL.EXE.@) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 963a2db1b2b..9aaa01e196d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1481,3 +1481,11 @@ @ cdecl -private wcsstr(wstr wstr) msvcrt.wcsstr @ cdecl -private wcstombs(ptr ptr long) msvcrt.wcstombs @ cdecl -private wctomb(ptr long) msvcrt.wctomb + +################################################################ +# Wine internal extensions +# +# All functions must be prefixed with '__wine_' (for internal functions) +# or 'wine_' (for user-visible functions) to avoid namespace conflicts. + +@ cdecl wine_ntoskrnl_main_loop(long) -- 2.11.4.GIT