From b95027f0481b164cec2fbc45cca2da4c3d1dcb14 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 8 Oct 2015 14:35:27 -0500 Subject: [PATCH] hidclass.sys: Implement IOCTL_GET(SET)_NUM_DEVICE_INPUT_BUFFERS. Signed-off-by: Aric Stewart Signed-off-by: Alexandre Julliard --- dlls/hidclass.sys/buffer.c | 35 +++++++++++++++++++++++++++++++++++ dlls/hidclass.sys/device.c | 28 ++++++++++++++++++++++++++++ dlls/hidclass.sys/hid.h | 2 ++ 3 files changed, 65 insertions(+) diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c index d7770f61562..23636e0eed5 100644 --- a/dlls/hidclass.sys/buffer.c +++ b/dlls/hidclass.sys/buffer.c @@ -27,6 +27,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(hid); #define BASE_BUFFER_SIZE 32 +#define MIN_BUFFER_SIZE 2 +#define MAX_BUFFER_SIZE 512 struct ReportRingBuffer { @@ -85,6 +87,39 @@ UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *ring) return ring->buffer_size; } +UINT RingBuffer_GetSize(struct ReportRingBuffer *ring) +{ + return ring->size; +} + +NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *ring, UINT size) +{ + BYTE* new_buffer; + int i; + + if (size < MIN_BUFFER_SIZE || size > MAX_BUFFER_SIZE || size == ring->size) + return STATUS_INVALID_PARAMETER; + + EnterCriticalSection(&ring->lock); + ring->start = ring->end = 0; + for (i = 0; i < ring->pointer_alloc; i++) + { + if (ring->pointers[i] != 0xffffffff) + ring->pointers[i] = 0; + } + new_buffer = HeapAlloc(GetProcessHeap(), 0, ring->buffer_size * size); + if (!new_buffer) + { + LeaveCriticalSection(&ring->lock); + return STATUS_NO_MEMORY; + } + HeapFree(GetProcessHeap(), 0, ring->buffer); + ring->buffer = new_buffer; + ring->size = size; + LeaveCriticalSection(&ring->lock); + return STATUS_SUCCESS; +} + void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) { void *ret = NULL; diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index f2f5f065fcd..e7e7e11a5c7 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -512,6 +512,34 @@ NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp) irp->IoStatus.u.Status = STATUS_SUCCESS; break; } + case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS: + { + irp->IoStatus.Information = 0; + + if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG)) + { + irp->IoStatus.u.Status = rc = STATUS_BUFFER_OVERFLOW; + } + else + { + rc = RingBuffer_SetSize(extension->ring_buffer, *(ULONG*)irp->AssociatedIrp.SystemBuffer); + irp->IoStatus.u.Status = rc; + } + break; + } + case IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS: + { + if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) + { + irp->IoStatus.u.Status = rc = STATUS_BUFFER_TOO_SMALL; + } + else + { + *(ULONG*)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize(extension->ring_buffer); + rc = irp->IoStatus.u.Status = STATUS_SUCCESS; + } + break; + } default: { ULONG code = irpsp->Parameters.DeviceIoControl.IoControlCode; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 1fccc5b6043..0dcc3a66fe0 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -61,8 +61,10 @@ 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; UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; +UINT RingBuffer_GetSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN; +NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *buffer, UINT size) DECLSPEC_HIDDEN; typedef struct _minidriver {