server: Notify client about freed object so that it may free associated kernel object.

Long term, we may consider making interface between server and device
manager more generic so that it could be used for messages other than IRPs.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-03-25 14:38:30 +01:00 committed by Alexandre Julliard
parent 4db5879742
commit a5c2f043e6
4 changed files with 40 additions and 1 deletions

View File

@ -833,6 +833,18 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG
return STATUS_SUCCESS;
}
/* This is not a real IRP_MJ_CLEANUP dispatcher. We use it to notify client that server
* object associated with kernel object is freed so that we may free it on client side
* as well. */
static NTSTATUS dispatch_cleanup( const irp_params_t *params, void *in_buff, ULONG in_size,
ULONG out_size, HANDLE irp_handle )
{
void *obj = wine_server_get_ptr( params->cleanup.obj );
TRACE( "freeing %p object\n", obj );
free_kernel_object( obj );
return STATUS_SUCCESS;
}
typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size,
ULONG out_size, HANDLE irp_handle );
@ -856,7 +868,7 @@ static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
NULL, /* IRP_MJ_SHUTDOWN */
NULL, /* IRP_MJ_LOCK_CONTROL */
NULL, /* IRP_MJ_CLEANUP */
dispatch_cleanup, /* IRP_MJ_CLEANUP */
NULL, /* IRP_MJ_CREATE_MAILSLOT */
NULL, /* IRP_MJ_QUERY_SECURITY */
NULL, /* IRP_MJ_SET_SECURITY */

View File

@ -683,6 +683,12 @@ typedef union
ioctl_code_t code;
client_ptr_t file;
} ioctl;
struct
{
unsigned int major;
int __pad;
client_ptr_t obj;
} cleanup;
} irp_params_t;

View File

@ -739,7 +739,22 @@ void free_kernel_objects( struct object *obj )
while ((ptr = list_head( list )))
{
struct kernel_object *kernel_object = LIST_ENTRY( ptr, struct kernel_object, list_entry );
struct irp_call *irp;
irp_params_t params;
assert( !kernel_object->owned );
/* abuse IRP_MJ_CLEANUP to request client to free no longer valid kernel object */
memset( &params, 0, sizeof(params) );
params.cleanup.major = IRP_MJ_CLEANUP;
params.cleanup.obj = kernel_object->user_ptr;
if ((irp = create_irp( NULL, &params, NULL )))
{
add_irp_to_queue( kernel_object->manager, irp, NULL );
release_object( irp );
}
list_remove( &kernel_object->list_entry );
wine_rb_remove( &kernel_object->manager->kernel_objects, &kernel_object->rb_entry );
free( kernel_object );

View File

@ -699,6 +699,12 @@ typedef union
ioctl_code_t code; /* ioctl code */
client_ptr_t file; /* opaque ptr for the file object */
} ioctl;
struct
{
unsigned int major; /* IRP_MJ_DEVICE_CLEANUP */
int __pad;
client_ptr_t obj; /* opaque ptr for the freed object */
} cleanup;
} irp_params_t;
/* information about a PE image mapping, roughly equivalent to SECTION_IMAGE_INFORMATION */