Andrew Cook : server: Track handle count of objects.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Apr 3 07:14:59 CDT 2015


Module: wine
Branch: master
Commit: 5d85f57814f023c105948636094e5e07654605ec
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5d85f57814f023c105948636094e5e07654605ec

Author: Andrew Cook <ariscop at gmail.com>
Date:   Thu Apr  2 10:24:24 2015 +1100

server: Track handle count of objects.

---

 dlls/ntdll/om.c                |  2 +-
 include/wine/server_protocol.h |  4 ++--
 server/handle.c                | 23 +++++++++++++++++++----
 server/object.c                | 10 ++++++----
 server/object.h                |  1 +
 server/protocol.def            |  1 +
 server/request.h               |  3 ++-
 server/trace.c                 |  1 +
 8 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index f5f75c6..b337444 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 3e61c5c..de6302c 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 0293ed6..5043ff7 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 d4afefd..965c11c 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 3817c75..72b52ee 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 9199c7f..625b3c9 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 ba699d1..dd6e4e2 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 e4188ba..0e2e7e2 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 );
 }




More information about the wine-cvs mailing list