[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