Module: wine Branch: master Commit: a5c2f043e688ca1dde9c272f92e0b0d993879570 URL: https://source.winehq.org/git/wine.git/?a=commit;h=a5c2f043e688ca1dde9c272f9...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Mar 25 14:38:30 2019 +0100
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
---
dlls/ntoskrnl.exe/ntoskrnl.c | 14 +++++++++++++- include/wine/server_protocol.h | 6 ++++++ server/device.c | 15 +++++++++++++++ server/protocol.def | 6 ++++++ 4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 14e85e6..1a4cc74 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -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 */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 54a5791..cd50894 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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;
diff --git a/server/device.c b/server/device.c index 9eec374..e9cf43f 100644 --- a/server/device.c +++ b/server/device.c @@ -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( ¶ms, 0, sizeof(params) ); + params.cleanup.major = IRP_MJ_CLEANUP; + params.cleanup.obj = kernel_object->user_ptr; + + if ((irp = create_irp( NULL, ¶ms, 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 ); diff --git a/server/protocol.def b/server/protocol.def index 3993ddd..f889e3b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -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 */