From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/main.c | 3 ++- dlls/winedmo/unixlib.c | 26 ++++++++++++++++++-------- dlls/winedmo/unixlib.h | 4 ++++ 3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/dlls/winedmo/main.c b/dlls/winedmo/main.c index 5bd66733d86..9de56e64902 100644 --- a/dlls/winedmo/main.c +++ b/dlls/winedmo/main.c @@ -27,9 +27,10 @@ static struct stream_context *stream_context_create(void) { struct stream_context *context;
- if (!(context = malloc( sizeof(*context) ))) return NULL; + if (!(context = malloc( 0x10000 ))) return NULL; context->length = 0; context->position = 0; + context->buffer_size = 0x10000 - offsetof(struct stream_context, buffer);
return context; } diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index 33c8bea54aa..59c83554c0d 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -57,18 +57,28 @@ int64_t unix_seek_callback( void *opaque, int64_t offset, int whence )
int unix_read_callback( void *opaque, uint8_t *buffer, int size ) { - struct read_callback_params params = {.dispatch = {.callback = read_callback}, .context = (UINT_PTR)opaque}; struct stream_context *context = opaque; - int status, total; - void *ret_ptr; - ULONG ret_len; + int ret, status, total = 0;
TRACE( "opaque %p, buffer %p, size %#x\n", opaque, buffer, size );
- params.size = size; - status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); - if (status || ret_len != sizeof(ULONG)) return AVERROR( EINVAL ); - total = *(ULONG *)ret_ptr; + if (!size) return AVERROR_EOF; + + do + { + struct read_callback_params params = {.dispatch = {.callback = read_callback}, .context = (UINT_PTR)context}; + void *ret_ptr; + ULONG ret_len; + + params.size = min( size, context->buffer_size ); + status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); + if (status || ret_len != sizeof(ULONG)) return AVERROR( EINVAL ); + if (!(ret = *(ULONG *)ret_ptr)) break; + memcpy( buffer, context->buffer, ret ); + buffer += ret; + total += ret; + size -= ret; + } while (size && ret == context->buffer_size);
if (!total) return AVERROR_EOF; context->position += total; diff --git a/dlls/winedmo/unixlib.h b/dlls/winedmo/unixlib.h index e97e47ea259..5aa4cc42ba2 100644 --- a/dlls/winedmo/unixlib.h +++ b/dlls/winedmo/unixlib.h @@ -41,8 +41,12 @@ struct stream_context { UINT64 length; UINT64 position; + UINT64 buffer_size; + BYTE buffer[]; };
+C_ASSERT( sizeof(struct stream_context) == offsetof( struct stream_context, buffer[0] ) ); + struct seek_callback_params { struct dispatch_callback_params dispatch;