[PATCH v3 resend 1/4] server: Allow get_volume_info to issue IRP_MJ_QUERY_VOLUME_INFORMATION.
Zebediah Figura
z.figura12 at gmail.com
Wed Oct 28 11:27:58 CDT 2020
On 9/8/20 3:01 PM, Erich E. Hoover wrote:
> From 399b72df5cc2b6ba09ca67286b2bcefb49503aff Mon Sep 17 00:00:00 2001
> From: "Erich E. Hoover" <erich.e.hoover at gmail.com>
> Date: Sat, 23 May 2020 21:39:41 -0600
> Subject: server: Allow get_volume_info to issue
> IRP_MJ_QUERY_VOLUME_INFORMATION.
>
> Signed-off-by: Erich E. Hoover <erich.e.hoover at gmail.com>
> ---
> dlls/ntoskrnl.exe/ntoskrnl.c | 64 ++++++++++++++++++++++++++++++++++++
> server/device.c | 18 +++++++++-
> server/fd.c | 15 ++++++---
> server/file.h | 4 +--
> server/named_pipe.c | 5 +--
> server/protocol.def | 11 +++++++
> 6 files changed, 107 insertions(+), 10 deletions(-)
>
> diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
> index e94feabc826..5ce7702a06b 100644
> --- a/dlls/ntoskrnl.exe/ntoskrnl.c
> +++ b/dlls/ntoskrnl.exe/ntoskrnl.c
> @@ -760,6 +760,69 @@ static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
> return STATUS_SUCCESS;
> }
>
> +/* process a volume information request for a given device */
> +static NTSTATUS dispatch_volume( struct dispatch_context *context )
> +{
> + IO_STACK_LOCATION *irpsp;
> + IRP *irp;
> + void *out_buff = NULL;
> + void *to_free = NULL;
> + DEVICE_OBJECT *device;
> + FILE_OBJECT *file = wine_server_get_ptr( context->params.ioctl.file );
> + ULONG out_size = context->params.ioctl.out_size;
There seem to be a couple of copy-paste errors here.
> +
> + if (!file) return STATUS_INVALID_HANDLE;
> +
> + device = IoGetAttachedDevice( file->DeviceObject );
> +
> + TRACE( "volume %x device %p file %p in_size %u out_size %u\n",
Maybe "class" instead of "volume" is a bit clearer? I also am a big fan
of marking hex numbers as hex...
> + context->params.volume.info_class, device, file, context->in_size, out_size );
> +
> + if (out_size)
> + {
> + if (out_size > context->in_size)
> + {
> + if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
> + memcpy( out_buff, context->in_buff, context->in_size );
> + to_free = context->in_buff;
> + context->in_buff = out_buff;
> + }
> + else
> + out_buff = context->in_buff;
> + }
> +
> +
> + irp = IoAllocateIrp( device->StackSize, FALSE );
> + if (!irp)
> + {
> + HeapFree( GetProcessHeap(), 0, out_buff );
> + return STATUS_NO_MEMORY;
> + }
> +
> + irpsp = IoGetNextIrpStackLocation( irp );
> + irpsp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
> + irpsp->Parameters.QueryVolume.FsInformationClass = context->params.volume.info_class;
> + irpsp->Parameters.QueryVolume.Length = out_size;
> + irpsp->DeviceObject = NULL;
> + irpsp->CompletionRoutine = NULL;
> + irpsp->FileObject = file;
> + irp->AssociatedIrp.SystemBuffer = context->in_buff;
> + irp->RequestorMode = KernelMode;
> + irp->UserBuffer = out_buff;
> + irp->UserIosb = NULL;
> + irp->UserEvent = NULL;
> + irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
> + irp->Tail.Overlay.OriginalFileObject = file;
> + irp->RequestorMode = UserMode;
> + context->in_buff = NULL;
> +
> + irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
> + dispatch_irp( device, irp, context );
> +
> + HeapFree( GetProcessHeap(), 0, to_free );
> + return STATUS_SUCCESS;
> +}
> +
> static NTSTATUS dispatch_free( struct dispatch_context *context )
> {
> void *obj = wine_server_get_ptr( context->params.free.obj );
> @@ -791,6 +854,7 @@ static const dispatch_func dispatch_funcs[] =
> dispatch_write, /* IRP_CALL_WRITE */
> dispatch_flush, /* IRP_CALL_FLUSH */
> dispatch_ioctl, /* IRP_CALL_IOCTL */
> + dispatch_volume, /* IRP_CALL_VOLUME */
> dispatch_free, /* IRP_CALL_FREE */
> dispatch_cancel /* IRP_CALL_CANCEL */
> };
> diff --git a/server/device.c b/server/device.c
> index 01e08f295f7..6bacb859187 100644
> --- a/server/device.c
> +++ b/server/device.c
> @@ -190,6 +190,7 @@ static int device_file_write( struct fd *fd, struct async *async, file_pos_t pos
> static int device_file_flush( struct fd *fd, struct async *async );
> static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
> static void device_file_reselect_async( struct fd *fd, struct async_queue *queue );
> +static int device_file_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class );
>
> static const struct object_ops device_file_ops =
> {
> @@ -223,7 +224,7 @@ static const struct fd_ops device_file_fd_ops =
> device_file_write, /* write */
> device_file_flush, /* flush */
> default_fd_get_file_info, /* get_file_info */
> - no_fd_get_volume_info, /* get_volume_info */
> + device_file_get_volume_info, /* get_volume_info */
> device_file_ioctl, /* ioctl */
> default_fd_queue_async, /* queue_async */
> device_file_reselect_async /* reselect_async */
> @@ -575,6 +576,10 @@ static int fill_irp_params( struct device_manager *manager, struct irp_call *irp
> irp->params.ioctl.file = get_kernel_object_ptr( manager, &irp->file->obj );
> irp->params.ioctl.out_size = irp->iosb->out_size;
> break;
> + case IRP_CALL_VOLUME:
> + irp->params.volume.file = get_kernel_object_ptr( manager, &irp->file->obj );
> + irp->params.volume.out_size = irp->iosb->out_size;
> + break;
> }
>
> *params = irp->params;
> @@ -612,6 +617,17 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd )
> return FD_TYPE_DEVICE;
> }
>
> +static int device_file_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class )
> +{
> + struct device_file *file = get_fd_user( fd );
> + irp_params_t params;
> +
> + memset( ¶ms, 0, sizeof(params) );
> + params.volume.type = IRP_CALL_VOLUME;
> + params.volume.info_class = info_class;
> + return queue_irp( file, ¶ms, async );
> +}
> +
> static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos )
> {
> struct device_file *file = get_fd_user( fd );
> diff --git a/server/fd.c b/server/fd.c
> index 7ea8ac273e5..29f36d801c5 100644
> --- a/server/fd.c
> +++ b/server/fd.c
> @@ -2324,9 +2324,10 @@ void default_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int
> }
>
> /* default get_volume_info() routine */
> -void no_fd_get_volume_info( struct fd *fd, unsigned int info_class )
> +int no_fd_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class )
> {
> set_error( STATUS_OBJECT_TYPE_MISMATCH );
> + return 0;
> }
>
> /* default ioctl() routine */
> @@ -2618,13 +2619,17 @@ DECL_HANDLER(get_file_info)
> /* query volume info */
> DECL_HANDLER(get_volume_info)
> {
> - struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
> + struct fd *fd = get_handle_fd_obj( current->process, req->async.handle, 0 );
> + struct async *async;
>
> - if (fd)
> + if (!fd) return;
> +
> + if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
> {
> - fd->fd_ops->get_volume_info( fd, req->info_class );
> - release_object( fd );
> + reply->wait = async_handoff( async, fd->fd_ops->get_volume_info( fd, async, req->info_class ), NULL, 0 );
> + release_object( async );
> }
> + release_object( fd );
> }
>
> /* open a file object */
> diff --git a/server/file.h b/server/file.h
> index e8ace7f49e4..53c03c006bc 100644
> --- a/server/file.h
> +++ b/server/file.h
> @@ -65,7 +65,7 @@ struct fd_ops
> /* query file info */
> void (*get_file_info)( struct fd *, obj_handle_t, unsigned int );
> /* query volume info */
> - void (*get_volume_info)( struct fd *, unsigned int );
> + int (*get_volume_info)( struct fd *, struct async *, unsigned int );
> /* perform an ioctl on the file */
> int (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async );
> /* queue an async operation */
> @@ -114,7 +114,7 @@ extern int no_fd_write( struct fd *fd, struct async *async, file_pos_t pos );
> extern int no_fd_flush( struct fd *fd, struct async *async );
> extern void no_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class );
> extern void default_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class );
> -extern void no_fd_get_volume_info( struct fd *fd, unsigned int info_class );
> +extern int no_fd_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class );
> extern int no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
> extern int default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
> extern void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count );
> diff --git a/server/named_pipe.c b/server/named_pipe.c
> index e7e5436c0e5..c57e7891953 100644
> --- a/server/named_pipe.c
> +++ b/server/named_pipe.c
> @@ -143,7 +143,7 @@ static int pipe_end_set_sd( struct object *obj, const struct security_descriptor
> static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos );
> static int pipe_end_write( struct fd *fd, struct async *async_data, file_pos_t pos );
> static int pipe_end_flush( struct fd *fd, struct async *async );
> -static void pipe_end_get_volume_info( struct fd *fd, unsigned int info_class );
> +static int pipe_end_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class );
> static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue );
> static void pipe_end_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class );
>
> @@ -699,7 +699,7 @@ static int pipe_end_set_sd( struct object *obj, const struct security_descriptor
> return 0;
> }
>
> -static void pipe_end_get_volume_info( struct fd *fd, unsigned int info_class )
> +static int pipe_end_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class )
> {
> switch (info_class)
> {
> @@ -719,6 +719,7 @@ static void pipe_end_get_volume_info( struct fd *fd, unsigned int info_class )
> default:
> set_error( STATUS_NOT_IMPLEMENTED );
> }
> + return 0;
> }
>
> static void message_queue_read( struct pipe_end *pipe_end, struct iosb *iosb )
> diff --git a/server/protocol.def b/server/protocol.def
> index 92290af701c..86f27f7aebd 100644
> --- a/server/protocol.def
> +++ b/server/protocol.def
> @@ -675,6 +675,7 @@ enum irp_type
> IRP_CALL_WRITE,
> IRP_CALL_FLUSH,
> IRP_CALL_IOCTL,
> + IRP_CALL_VOLUME,
> IRP_CALL_FREE,
> IRP_CALL_CANCEL
> };
> @@ -728,6 +729,14 @@ typedef union
> client_ptr_t file; /* opaque ptr for the file object */
> } ioctl;
> struct
> + {
> + enum irp_type type; /* IRP_CALL_VOLUME */
> + unsigned int info_class;/* information class */
> + data_size_t out_size; /* needed output size */
> + int __pad;
> + client_ptr_t file; /* opaque ptr for the file object */
> + } volume;
> + struct
> {
> enum irp_type type; /* IRP_CALL_FREE */
> int __pad;
> @@ -1353,9 +1362,11 @@ enum server_fd_type
>
> /* Query volume information */
> @REQ(get_volume_info)
> + async_data_t async; /* async I/O parameters */
> obj_handle_t handle; /* handle to the file */
> unsigned int info_class; /* queried information class */
> @REPLY
> + obj_handle_t wait; /* handle to wait on for blocking read */
> VARARG(data,bytes); /* volume info data */
> @END
>
> --
> 2.17.1
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20201028/471f1a36/attachment-0001.sig>
More information about the wine-devel
mailing list