ntoskrnl: Add support for read and write requests.
This commit is contained in:
parent
a78f8f298a
commit
2cd717a604
|
@ -128,43 +128,15 @@ static HANDLE get_device_manager(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process an ioctl request for a given device */
|
static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
|
||||||
static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
|
|
||||||
ULONG in_size, ULONG out_size, HANDLE ioctl )
|
|
||||||
{
|
{
|
||||||
IRP *irp;
|
|
||||||
void *out_buff = NULL;
|
|
||||||
FILE_OBJECT file;
|
|
||||||
LARGE_INTEGER count;
|
LARGE_INTEGER count;
|
||||||
|
FILE_OBJECT file;
|
||||||
|
|
||||||
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( &file, 0x88, sizeof(file) );
|
|
||||||
|
|
||||||
if ((code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
|
|
||||||
|
|
||||||
if (out_size)
|
|
||||||
{
|
|
||||||
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
|
|
||||||
if ((code & 3) == METHOD_BUFFERED)
|
|
||||||
{
|
|
||||||
memcpy( out_buff, in_buff, in_size );
|
|
||||||
in_buff = out_buff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note: we abuse UserIosb to store the server handle to the ioctl */
|
|
||||||
irp = IoBuildDeviceIoControlRequest( code, device, in_buff, in_size, out_buff, out_size,
|
|
||||||
FALSE, NULL, (IO_STATUS_BLOCK *)ioctl );
|
|
||||||
if (!irp)
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, out_buff );
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
irp->RequestorMode = UserMode;
|
irp->RequestorMode = UserMode;
|
||||||
irp->Tail.Overlay.OriginalFileObject = &file;
|
irp->Tail.Overlay.OriginalFileObject = &file;
|
||||||
|
|
||||||
|
memset( &file, 0x88, sizeof(file) );
|
||||||
file.FsContext = NULL;
|
file.FsContext = NULL;
|
||||||
file.FsContext2 = NULL;
|
file.FsContext2 = NULL;
|
||||||
|
|
||||||
|
@ -179,6 +151,125 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* process a read request for a given device */
|
||||||
|
static NTSTATUS dispatch_read( DEVICE_OBJECT *device, const irp_params_t *params,
|
||||||
|
void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
|
||||||
|
{
|
||||||
|
IRP *irp;
|
||||||
|
void *out_buff;
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
IO_STACK_LOCATION *irpsp;
|
||||||
|
|
||||||
|
TRACE( "device %p size %u\n", device, out_size );
|
||||||
|
|
||||||
|
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
offset.QuadPart = params->read.pos;
|
||||||
|
|
||||||
|
/* note: we abuse UserIosb to store the server irp handle */
|
||||||
|
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
|
||||||
|
&offset, NULL, irp_handle )))
|
||||||
|
{
|
||||||
|
HeapFree( GetProcessHeap(), 0, out_buff );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
irpsp = IoGetNextIrpStackLocation( irp );
|
||||||
|
irpsp->Parameters.Read.Key = params->read.key;
|
||||||
|
|
||||||
|
return dispatch_irp( device, irp );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process a write request for a given device */
|
||||||
|
static NTSTATUS dispatch_write( DEVICE_OBJECT *device, const irp_params_t *params,
|
||||||
|
void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
|
||||||
|
{
|
||||||
|
IRP *irp;
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
IO_STACK_LOCATION *irpsp;
|
||||||
|
|
||||||
|
TRACE( "device %p size %u\n", device, in_size );
|
||||||
|
|
||||||
|
offset.QuadPart = params->write.pos;
|
||||||
|
|
||||||
|
/* note: we abuse UserIosb to store the server irp handle */
|
||||||
|
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size,
|
||||||
|
&offset, NULL, irp_handle )))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
irpsp = IoGetNextIrpStackLocation( irp );
|
||||||
|
irpsp->Parameters.Write.Key = params->write.key;
|
||||||
|
|
||||||
|
return dispatch_irp( device, irp );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process an ioctl request for a given device */
|
||||||
|
static NTSTATUS dispatch_ioctl( DEVICE_OBJECT *device, const irp_params_t *params,
|
||||||
|
void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
|
||||||
|
{
|
||||||
|
IRP *irp;
|
||||||
|
void *out_buff = NULL;
|
||||||
|
|
||||||
|
TRACE( "ioctl %x device %p in_size %u out_size %u\n", params->ioctl.code, device, in_size, out_size );
|
||||||
|
|
||||||
|
if ((params->ioctl.code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
|
||||||
|
|
||||||
|
if (out_size)
|
||||||
|
{
|
||||||
|
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
|
||||||
|
if ((params->ioctl.code & 3) == METHOD_BUFFERED)
|
||||||
|
{
|
||||||
|
memcpy( out_buff, in_buff, in_size );
|
||||||
|
in_buff = out_buff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note: we abuse UserIosb to store the server handle to the ioctl */
|
||||||
|
irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
|
||||||
|
FALSE, NULL, irp_handle );
|
||||||
|
if (!irp)
|
||||||
|
{
|
||||||
|
HeapFree( GetProcessHeap(), 0, out_buff );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
return dispatch_irp( device, irp );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef NTSTATUS (*dispatch_func)( DEVICE_OBJECT *device, const irp_params_t *params,
|
||||||
|
void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle );
|
||||||
|
|
||||||
|
static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
|
||||||
|
{
|
||||||
|
NULL, /* IRP_MJ_CREATE */
|
||||||
|
NULL, /* IRP_MJ_CREATE_NAMED_PIPE */
|
||||||
|
NULL, /* IRP_MJ_CLOSE */
|
||||||
|
dispatch_read, /* IRP_MJ_READ */
|
||||||
|
dispatch_write, /* IRP_MJ_WRITE */
|
||||||
|
NULL, /* IRP_MJ_QUERY_INFORMATION */
|
||||||
|
NULL, /* IRP_MJ_SET_INFORMATION */
|
||||||
|
NULL, /* IRP_MJ_QUERY_EA */
|
||||||
|
NULL, /* IRP_MJ_SET_EA */
|
||||||
|
NULL, /* IRP_MJ_FLUSH_BUFFERS */
|
||||||
|
NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */
|
||||||
|
NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */
|
||||||
|
NULL, /* IRP_MJ_DIRECTORY_CONTROL */
|
||||||
|
NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */
|
||||||
|
dispatch_ioctl, /* IRP_MJ_DEVICE_CONTROL */
|
||||||
|
NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
|
||||||
|
NULL, /* IRP_MJ_SHUTDOWN */
|
||||||
|
NULL, /* IRP_MJ_LOCK_CONTROL */
|
||||||
|
NULL, /* IRP_MJ_CLEANUP */
|
||||||
|
NULL, /* IRP_MJ_CREATE_MAILSLOT */
|
||||||
|
NULL, /* IRP_MJ_QUERY_SECURITY */
|
||||||
|
NULL, /* IRP_MJ_SET_SECURITY */
|
||||||
|
NULL, /* IRP_MJ_POWER */
|
||||||
|
NULL, /* IRP_MJ_SYSTEM_CONTROL */
|
||||||
|
NULL, /* IRP_MJ_DEVICE_CHANGE */
|
||||||
|
NULL, /* IRP_MJ_QUERY_QUOTA */
|
||||||
|
NULL, /* IRP_MJ_SET_QUOTA */
|
||||||
|
NULL, /* IRP_MJ_PNP */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* wine_ntoskrnl_main_loop (Not a Windows API)
|
* wine_ntoskrnl_main_loop (Not a Windows API)
|
||||||
|
@ -235,16 +326,16 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
||||||
switch(status)
|
switch(status)
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
switch (irp_params.major)
|
if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION ||
|
||||||
|
!dispatch_funcs[irp_params.major] ||
|
||||||
|
!device->DriverObject->MajorFunction[irp_params.major])
|
||||||
{
|
{
|
||||||
case IRP_MJ_DEVICE_CONTROL:
|
WARN( "unsupported request %u\n", irp_params.major );
|
||||||
status = process_ioctl( device, irp_params.ioctl.code, in_buff, in_size, out_size, irp );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
FIXME( "unsupported request %u\n", irp_params.major );
|
|
||||||
status = STATUS_NOT_SUPPORTED;
|
status = STATUS_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
status = dispatch_funcs[irp_params.major]( device, &irp_params,
|
||||||
|
in_buff, in_size, out_size, irp );
|
||||||
if (status == STATUS_SUCCESS) irp = 0; /* status reported by IoCompleteRequest */
|
if (status == STATUS_SUCCESS) irp = 0; /* status reported by IoCompleteRequest */
|
||||||
break;
|
break;
|
||||||
case STATUS_BUFFER_OVERFLOW:
|
case STATUS_BUFFER_OVERFLOW:
|
||||||
|
|
Loading…
Reference in New Issue