[PATCH] hidclass.sys: When processing reads fill all the buffers

Sebastian Lackner sebastian at fds-team.de
Thu Jan 26 08:03:41 CST 2017


On 26.01.2017 13:57, Aric Stewart wrote:
> This is a follow-up fix for continuing work on bug 42225
> 
> Signed-off-by: Aric Stewart <aric at codeweavers.com>
> ---
>  dlls/hidclass.sys/buffer.c | 34 +++++++++++++++++++++++++++++++++-
>  dlls/hidclass.sys/device.c |  2 +-
>  dlls/hidclass.sys/hid.h    |  3 ++-
>  3 files changed, 36 insertions(+), 3 deletions(-)
> 
> 
> 
> 0001-hidclass.sys-When-processing-reads-fill-all-the-buffer.txt
> 
> 
> diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c
> index 0b29f97b69..41bbb8e241 100644
> --- a/dlls/hidclass.sys/buffer.c
> +++ b/dlls/hidclass.sys/buffer.c
> @@ -127,7 +127,7 @@ NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *ring, UINT size)
>      return STATUS_SUCCESS;
>  }
>  
> -void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size)
> +void RingBuffer_ReadNew(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size)
>  {
>      void *ret = NULL;
>  
> @@ -155,6 +155,38 @@ void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UI
>      }
>  }
>  
> +void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size)
> +{
> +    int pointer = ring->pointers[index];
> +    void *ret = NULL;
> +
> +    EnterCriticalSection(&ring->lock);
> +    if (index >= ring->pointer_alloc || ring->pointers[index] == POINTER_UNUSED
> +        || ring->end == ring->start)
> +    {
> +        LeaveCriticalSection(&ring->lock);
> +        *size = 0;
> +        return;
> +    }
> +
> +    if (pointer == ring->end)
> +        pointer--;
> +
> +    if (pointer < 0)
> +        pointer = ring->size - 1;
> +
> +    ret = &ring->buffer[pointer * ring->buffer_size];
> +    memcpy(output, ret, ring->buffer_size);
> +    if (pointer == ring->pointers[index])
> +    {
> +        ring->pointers[index]++;
> +        if (ring->pointers[index] == ring->size)
> +            ring->pointers[index] = 0;
> +    }
> +    LeaveCriticalSection(&ring->lock);
> +    *size = ring->buffer_size;

Have you been able to reproduce a similar behavior on Windows? The new code
looks very suspicious and I'm not sure if this is the right approach to fix
it. Also please note that this will effectively disable any asynchronous
Read requests - HID_Device_read() will always use the first code path when
there is at least one package in the ring buffer and never return
STATUS_PENDING.

> +}
> +
>  UINT RingBuffer_AddPointer(struct ReportRingBuffer *ring)
>  {
>      UINT idx;
> diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
> index b241016e72..d6a0a358e3 100644
> --- a/dlls/hidclass.sys/device.c
> +++ b/dlls/hidclass.sys/device.c
> @@ -662,7 +662,7 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp)
>      ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
>  
>      irp->IoStatus.Information = 0;
> -    RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size);
> +    RingBuffer_ReadNew(ext->ring_buffer, ptr, packet, &buffer_size);
>  
>      if (buffer_size)
>      {
> diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h
> index adc547cc43..1829319ccf 100644
> --- a/dlls/hidclass.sys/hid.h
> +++ b/dlls/hidclass.sys/hid.h
> @@ -62,7 +62,8 @@ typedef struct _BASE_DEVICE_EXTENSION {
>  void RingBuffer_Write(struct ReportRingBuffer *buffer, void *data) DECLSPEC_HIDDEN;
>  UINT RingBuffer_AddPointer(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
>  void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) DECLSPEC_HIDDEN;
> -void RingBuffer_Read(struct ReportRingBuffer *buffer, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN;
> +void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN;
> +void RingBuffer_ReadNew(struct ReportRingBuffer *buffer, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN;
>  UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
>  UINT RingBuffer_GetSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
>  void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
> 
> 
> 




More information about the wine-devel mailing list