diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index fbea0f4a1d3..5443aa79571 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1028,8 +1028,11 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost ) req->manager = wine_server_obj_handle( manager ); req->handle = wine_server_obj_handle( handle ); req->status = irp->IoStatus.u.Status; - if (irp->IoStatus.u.Status >= 0 && out_buff) - wine_server_add_data( req, out_buff, irp->IoStatus.Information ); + if (irp->IoStatus.u.Status >= 0) + { + req->size = irp->IoStatus.Information; + if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information ); + } wine_server_call( req ); } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index b09ca138ebe..ef0d181f1bd 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3134,7 +3134,9 @@ struct set_irp_result_request obj_handle_t manager; obj_handle_t handle; unsigned int status; + data_size_t size; /* VARARG(data,bytes); */ + char __pad_28[4]; }; struct set_irp_result_reply { @@ -3152,7 +3154,9 @@ struct get_irp_result_request struct get_irp_result_reply { struct reply_header __header; + data_size_t size; /* VARARG(out_data,bytes); */ + char __pad_12[4]; }; @@ -5973,6 +5977,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 470 +#define SERVER_PROTOCOL_VERSION 471 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/device.c b/server/device.c index f7fa9704784..aabff7950e7 100644 --- a/server/device.c +++ b/server/device.c @@ -47,6 +47,7 @@ struct irp_call unsigned int type; /* request type (IRP_MJ_*) */ unsigned int status; /* resulting status (or STATUS_PENDING) */ ioctl_code_t code; /* ioctl code */ + data_size_t result; /* size of result (input or output depending on the type) */ data_size_t in_size; /* size of input data */ void *in_data; /* input data */ data_size_t out_size; /* size of output data */ @@ -203,6 +204,7 @@ static struct irp_call *create_irp( struct device *device, unsigned int type, co irp->type = type; irp->code = 0; irp->status = STATUS_PENDING; + irp->result = 0; irp->in_size = in_size; irp->in_data = NULL; irp->out_size = out_size; @@ -218,7 +220,7 @@ static struct irp_call *create_irp( struct device *device, unsigned int type, co } static void set_irp_result( struct irp_call *irp, unsigned int status, - const void *out_data, data_size_t out_size ) + const void *out_data, data_size_t out_size, data_size_t result ) { struct device *device = irp->device; @@ -226,6 +228,7 @@ static void set_irp_result( struct irp_call *irp, unsigned int status, /* FIXME: handle the STATUS_PENDING case */ irp->status = status; + irp->result = result; irp->out_size = min( irp->out_size, out_size ); if (irp->out_size && !(irp->out_data = memdup( out_data, irp->out_size ))) irp->out_size = 0; @@ -233,7 +236,7 @@ static void set_irp_result( struct irp_call *irp, unsigned int status, irp->device = NULL; if (irp->async) { - if (irp->out_size) status = STATUS_ALERTED; + if (result) status = STATUS_ALERTED; async_terminate( irp->async, status ); release_object( irp->async ); irp->async = NULL; @@ -385,7 +388,7 @@ static void delete_device( struct device *device ) LIST_FOR_EACH_ENTRY_SAFE( irp, next, &device->requests, struct irp_call, dev_entry ) { list_remove( &irp->mgr_entry ); - set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0 ); + set_irp_result( irp, STATUS_FILE_DELETED, NULL, 0, 0 ); } unlink_named_object( &device->obj ); list_remove( &device->entry ); @@ -503,7 +506,7 @@ DECL_HANDLER(get_next_device_request) if ((irp = (struct irp_call *)get_handle_obj( current->process, req->prev, 0, &irp_call_ops ))) { - set_irp_result( irp, req->status, NULL, 0 ); + set_irp_result( irp, req->status, NULL, 0, 0 ); close_handle( current->process, req->prev ); /* avoid an extra round-trip for close */ release_object( irp ); } @@ -548,7 +551,7 @@ DECL_HANDLER(set_irp_result) if ((irp = (struct irp_call *)get_handle_obj( current->process, req->handle, 0, &irp_call_ops ))) { - set_irp_result( irp, req->status, get_req_data(), get_req_data_size() ); + set_irp_result( irp, req->status, get_req_data(), get_req_data_size(), req->size ); close_handle( current->process, req->handle ); /* avoid an extra round-trip for close */ release_object( irp ); } @@ -576,6 +579,7 @@ DECL_HANDLER(get_irp_result) irp->out_data = NULL; } } + reply->size = irp->result; set_error( irp->status ); list_remove( &irp->dev_entry ); release_object( irp ); /* no longer on the device queue */ diff --git a/server/protocol.def b/server/protocol.def index 7e4737a2a3d..51ad56bbbf1 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2267,6 +2267,7 @@ enum message_type obj_handle_t manager; /* handle to the device manager */ obj_handle_t handle; /* handle to the irp */ unsigned int status; /* status of the irp */ + data_size_t size; /* result size (input or output depending on the operation) */ VARARG(data,bytes); /* output data of the irp */ @END @@ -2276,6 +2277,7 @@ enum message_type obj_handle_t handle; /* handle to the device */ client_ptr_t user_arg; /* user arg used to identify the request */ @REPLY + data_size_t size; /* result size (input or output depending on the operation) */ VARARG(out_data,bytes); /* irp output data */ @END diff --git a/server/request.h b/server/request.h index bce80a14df3..0a6096cb104 100644 --- a/server/request.h +++ b/server/request.h @@ -1530,11 +1530,13 @@ C_ASSERT( sizeof(struct ioctl_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, manager) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, handle) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, status) == 20 ); -C_ASSERT( sizeof(struct set_irp_result_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_irp_result_request, size) == 24 ); +C_ASSERT( sizeof(struct set_irp_result_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct get_irp_result_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_irp_result_request, user_arg) == 16 ); C_ASSERT( sizeof(struct get_irp_result_request) == 24 ); -C_ASSERT( sizeof(struct get_irp_result_reply) == 8 ); +C_ASSERT( FIELD_OFFSET(struct get_irp_result_reply, size) == 8 ); +C_ASSERT( sizeof(struct get_irp_result_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_named_pipe_request, access) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_named_pipe_request, attributes) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_named_pipe_request, options) == 20 ); diff --git a/server/trace.c b/server/trace.c index e9127b4850f..27180ed7fc2 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2745,6 +2745,7 @@ static void dump_set_irp_result_request( const struct set_irp_result_request *re fprintf( stderr, " manager=%04x", req->manager ); fprintf( stderr, ", handle=%04x", req->handle ); fprintf( stderr, ", status=%08x", req->status ); + fprintf( stderr, ", size=%u", req->size ); dump_varargs_bytes( ", data=", cur_size ); } @@ -2756,7 +2757,8 @@ static void dump_get_irp_result_request( const struct get_irp_result_request *re static void dump_get_irp_result_reply( const struct get_irp_result_reply *req ) { - dump_varargs_bytes( " out_data=", cur_size ); + fprintf( stderr, " size=%u", req->size ); + dump_varargs_bytes( ", out_data=", cur_size ); } static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )