[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( &params, 0, sizeof(params) );
> +    params.volume.type = IRP_CALL_VOLUME;
> +    params.volume.info_class = info_class;
> +    return queue_irp( file, &params, 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