[Wine-patches] [eterhack] [0018/0021] Add implementation of IRP_MJ_READ handling.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Ср Янв 28 21:10:15 MSK 2009


---
 dlls/ntdll/file.c            |   13 +++++++++++
 dlls/ntoskrnl.exe/ntoskrnl.c |   47 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 1c839b5..5c98e13 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -522,6 +522,16 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL
 }
 
 
+#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \
+        METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
+                                   PIO_APC_ROUTINE apc, PVOID apc_context,
+                                   IO_STATUS_BLOCK *io, ULONG code,
+                                   const void *in_buffer, ULONG in_size,
+                                   PVOID out_buffer, ULONG out_size );
+
+
 /******************************************************************************
  *  NtReadFile					[NTDLL.@]
  *  ZwReadFile					[NTDLL.@]
@@ -564,6 +574,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
 
     status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
                                  &needs_close, &type, &options );
+    if (status == STATUS_BAD_DEVICE_TYPE)
+        return server_ioctl_file( hFile, hEvent, apc, apc_user, io_status,
+                                  IOCTL_WINE_DRIVER_READ, buffer, length, buffer, length );
     if (status) return status;
 
     if (!virtual_check_buffer_for_write( buffer, length ))
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 48b16d7..57d7be3 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -105,6 +105,9 @@ struct InterfaceInstance
     UNICODE_STRING target;
 };
 
+#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \
+        METHOD_BUFFERED, FILE_ANY_ACCESS)
+
 #ifdef __i386__
 #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \
     __ASM_GLOBAL_FUNC( name, \
@@ -416,6 +419,40 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
     return status;
 }
 
+/* process IRP_MJ_READ request for a given device */
+static NTSTATUS process_read( DEVICE_OBJECT *device, void *buff, ULONG *size )
+{
+    PIRP irp;
+    PIO_STACK_LOCATION irpsp;
+    NTSTATUS status;
+    LARGE_INTEGER count;
+    MDL mdl;
+
+    irp = IoAllocateIrp( device->StackSize, FALSE );
+    if (irp == NULL)
+        return STATUS_NO_MEMORY;
+    irp->MdlAddress = &mdl;
+    irp->RequestorMode = UserMode;
+    irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+    irpsp->DeviceObject = device;
+    irpsp->MajorFunction = IRP_MJ_READ;
+    irpsp->Parameters.Read.Length = *size;
+    device->CurrentIrp = irp;
+
+    mdl.Next = NULL;
+    mdl.Size = 0;
+    mdl.StartVa = buff;
+    mdl.MappedSystemVa = buff;
+    mdl.ByteCount = *size;
+    mdl.ByteOffset = 0;
+
+    KeQueryTickCount( &count );  /* update the global KeTickCount */
+    status = __regs_IofCallDriver( device, irp );
+    *size = (status == STATUS_SUCCESS) ? irp->IoStatus.Information : 0;
+    IoFreeIrp( irp );
+    return status;
+}
+
 
 /***********************************************************************
  *           wine_ntoskrnl_main_loop   (Not a Windows API)
@@ -478,7 +515,15 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
             else out_buff = NULL;
             while (device->AttachedDevice)
                 device = device->AttachedDevice;
-            status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size );
+            if (code != IOCTL_WINE_DRIVER_READ)
+            {
+                status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size );
+            }
+            else
+            {
+                memcpy( out_buff, in_buff, min( in_size, out_size ) );
+                status = process_read( device, out_buff, &out_size );
+            }
             break;
         case STATUS_BUFFER_OVERFLOW:
             HeapFree( GetProcessHeap(), 0, in_buff );
-- 
1.6.0.2.GIT



Подробная информация о списке рассылки Wine-patches