diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c index f5f75c66237..b337444494d 100644 --- a/dlls/ntdll/om.c +++ b/dlls/ntdll/om.c @@ -77,7 +77,7 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle, memset( p, 0, sizeof(*p) ); p->GrantedAccess = reply->access; p->PointerCount = reply->ref_count; - p->HandleCount = 1; /* at least one */ + p->HandleCount = reply->handle_count; if (used_len) *used_len = sizeof(*p); } } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 3e61c5c32b7..de6302c28f3 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4690,9 +4690,9 @@ struct get_object_info_reply struct reply_header __header; unsigned int access; unsigned int ref_count; + unsigned int handle_count; data_size_t total; /* VARARG(name,unicode_str); */ - char __pad_20[4]; }; @@ -5955,6 +5955,6 @@ union generic_reply struct set_job_completion_port_reply set_job_completion_port_reply; }; -#define SERVER_PROTOCOL_VERSION 465 +#define SERVER_PROTOCOL_VERSION 466 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/handle.c b/server/handle.c index 0293ed6f99b..5043ff70b71 100644 --- a/server/handle.c +++ b/server/handle.c @@ -97,6 +97,20 @@ static inline obj_handle_t handle_global_to_local( obj_handle_t handle ) return handle ^ HANDLE_OBFUSCATOR; } +/* grab an object and increment its handle count */ +static struct object *grab_object_for_handle( struct object *obj ) +{ + obj->handle_count++; + return grab_object( obj ); +} + +/* release an object and decrement its handle count */ +static void release_object_from_handle( struct object *obj ) +{ + assert( obj->handle_count ); + obj->handle_count--; + release_object( obj ); +} static void handle_table_dump( struct object *obj, int verbose ); static void handle_table_destroy( struct object *obj ); @@ -166,7 +180,7 @@ static void handle_table_destroy( struct object *obj ) { struct object *obj = entry->ptr; entry->ptr = NULL; - if (obj) release_object( obj ); + if (obj) release_object_from_handle( obj ); } free( table->entries ); } @@ -229,7 +243,7 @@ static obj_handle_t alloc_entry( struct handle_table *table, void *obj, unsigned table->last = i; found: table->free = i + 1; - entry->ptr = grab_object( obj ); + entry->ptr = grab_object_for_handle( obj ); entry->access = access; return index_to_handle(i); } @@ -355,7 +369,7 @@ struct handle_table *copy_handle_table( struct process *process, struct process for (i = 0; i <= table->last; i++, ptr++) { if (!ptr->ptr) continue; - if (ptr->access & RESERVED_INHERIT) grab_object( ptr->ptr ); + if (ptr->access & RESERVED_INHERIT) grab_object_for_handle( ptr->ptr ); else ptr->ptr = NULL; /* don't inherit this entry */ } } @@ -379,7 +393,7 @@ unsigned int close_handle( struct process *process, obj_handle_t handle ) table = handle_is_global(handle) ? global_table : process->handles; if (entry < table->entries + table->free) table->free = entry - table->entries; if (entry == table->entries + table->last) shrink_handle_table( table ); - release_object( obj ); + release_object_from_handle( obj ); return STATUS_SUCCESS; } @@ -630,6 +644,7 @@ DECL_HANDLER(get_object_info) reply->access = get_handle_access( current->process, req->handle ); reply->ref_count = obj->refcount; + reply->handle_count = obj->handle_count; if ((name = get_object_full_name( obj, &reply->total ))) set_reply_data_ptr( name, min( reply->total, get_reply_max_size() )); release_object( obj ); diff --git a/server/object.c b/server/object.c index d4afefd9222..965c11c0486 100644 --- a/server/object.c +++ b/server/object.c @@ -206,10 +206,11 @@ void *alloc_object( const struct object_ops *ops ) struct object *obj = mem_alloc( ops->size ); if (obj) { - obj->refcount = 1; - obj->ops = ops; - obj->name = NULL; - obj->sd = NULL; + obj->refcount = 1; + obj->handle_count = 0; + obj->ops = ops; + obj->name = NULL; + obj->sd = NULL; list_init( &obj->wait_queue ); #ifdef DEBUG_OBJECTS list_add_head( &object_list, &obj->obj_list ); @@ -306,6 +307,7 @@ void release_object( void *ptr ) assert( obj->refcount ); if (!--obj->refcount) { + assert( !obj->handle_count ); /* if the refcount is 0, nobody can be in the wait queue */ assert( list_empty( &obj->wait_queue )); obj->ops->destroy( obj ); diff --git a/server/object.h b/server/object.h index 3817c75f538..72b52eeaa04 100644 --- a/server/object.h +++ b/server/object.h @@ -95,6 +95,7 @@ struct object_ops struct object { unsigned int refcount; /* reference count */ + unsigned int handle_count;/* handle count */ const struct object_ops *ops; struct list wait_queue; struct object_name *name; diff --git a/server/protocol.def b/server/protocol.def index 9199c7f317e..625b3c940e2 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3269,6 +3269,7 @@ enum coords_relative @REPLY unsigned int access; /* granted access mask */ unsigned int ref_count; /* object ref count */ + unsigned int handle_count; /* object handle count */ data_size_t total; /* total needed size for name */ VARARG(name,unicode_str); /* object name */ @END diff --git a/server/request.h b/server/request.h index ba699d1c2c4..dd6e4e2a755 100644 --- a/server/request.h +++ b/server/request.h @@ -2088,7 +2088,8 @@ C_ASSERT( FIELD_OFFSET(struct get_object_info_request, handle) == 12 ); C_ASSERT( sizeof(struct get_object_info_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, access) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, ref_count) == 12 ); -C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, total) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, handle_count) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_object_info_reply, total) == 20 ); C_ASSERT( sizeof(struct get_object_info_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct unlink_object_request, handle) == 12 ); C_ASSERT( sizeof(struct unlink_object_request) == 16 ); diff --git a/server/trace.c b/server/trace.c index e4188ba4765..0e2e7e22500 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3842,6 +3842,7 @@ static void dump_get_object_info_reply( const struct get_object_info_reply *req { fprintf( stderr, " access=%08x", req->access ); fprintf( stderr, ", ref_count=%08x", req->ref_count ); + fprintf( stderr, ", handle_count=%08x", req->handle_count ); fprintf( stderr, ", total=%u", req->total ); dump_varargs_unicode_str( ", name=", cur_size ); }