server: New scheme for cleaning up objects on server exit.

Objects stored in static variables can now be marked when they are
created and are automatically cleaned up on exit. This avoids having
to export a bunch of close_* functions.
diff --git a/server/directory.c b/server/directory.c
index e00687a..c7ad9ee 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -294,11 +294,6 @@
 
 /* Global initialization */
 
-static struct directory *dir_driver, *dir_device;
-static struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
-static struct named_pipe_device *dev_named_pipe;
-static struct mailslot_device *dev_mailslot;
-
 void init_directories(void)
 {
     /* Directories */
@@ -325,11 +320,15 @@
     static const struct unicode_str pipe_str = {pipeW, sizeof(pipeW)};
     static const struct unicode_str mailslot_str = {mailslotW, sizeof(mailslotW)};
 
-    struct directory *dir_global, *dir_basenamed;
+    struct directory *dir_driver, *dir_device, *dir_global, *dir_basenamed;
+    struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
 
     root_directory = create_directory( NULL, NULL, 0, HASH_SIZE );
     dir_driver     = create_directory( root_directory, &dir_driver_str, 0, HASH_SIZE );
     dir_device     = create_directory( root_directory, &dir_device_str, 0, HASH_SIZE );
+    make_object_static( &root_directory->obj );
+    make_object_static( &dir_driver->obj );
+    make_object_static( &dir_device->obj );
 
     dir_global     = create_directory( NULL, &dir_global_str, 0, HASH_SIZE );
     /* use a larger hash table for this one since it can contain a lot of objects */
@@ -340,32 +339,20 @@
     link_global1   = create_symlink( dir_global, &link_global_str, 0, &dir_global_str );
     link_global2   = create_symlink( dir_basenamed, &link_global_str, 0, &dir_basenamed_str );
     link_local     = create_symlink( dir_basenamed, &link_local_str, 0, &dir_basenamed_str );
+    make_object_static( (struct object *)link_dosdev );
+    make_object_static( (struct object *)link_global1 );
+    make_object_static( (struct object *)link_global2 );
+    make_object_static( (struct object *)link_local );
 
     /* devices */
-    dev_named_pipe = create_named_pipe_device( dir_global, &pipe_str );
-    dev_mailslot   = create_mailslot_device( dir_global, &mailslot_str );
+    create_named_pipe_device( dir_global, &pipe_str );
+    create_mailslot_device( dir_global, &mailslot_str );
 
     /* the symlinks or devices hold references so we can release these */
     release_object( dir_global );
     release_object( dir_basenamed );
 }
 
-void close_directories(void)
-{
-    release_object( dev_named_pipe );
-    release_object( dev_mailslot );
-
-    release_object( link_dosdev );
-    release_object( link_global1 );
-    release_object( link_global2 );
-    release_object( link_local );
-
-    release_object( dir_device );
-    release_object( dir_driver );
-    release_object( root_directory );
-}
-
-
 /* create a directory object */
 DECL_HANDLER(create_directory)
 {
diff --git a/server/handle.c b/server/handle.c
index 375539f..088c4c1 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -247,6 +247,7 @@
     {
         if (!(global_table = (struct handle_table *)alloc_handle_table( NULL, 0 )))
             return 0;
+        make_object_static( &global_table->obj );
     }
     return handle_local_to_global( alloc_entry( global_table, obj, access ));
 }
@@ -359,16 +360,6 @@
     return 1;
 }
 
-/* close all the global handles */
-void close_global_handles(void)
-{
-    if (global_table)
-    {
-        release_object( global_table );
-        global_table = NULL;
-    }
-}
-
 /* retrieve the object corresponding to one of the magic pseudo-handles */
 static inline struct object *get_magic_handle( obj_handle_t handle )
 {
diff --git a/server/handle.h b/server/handle.h
index ad71252..e0fe891 100644
--- a/server/handle.h
+++ b/server/handle.h
@@ -52,6 +52,4 @@
 extern unsigned int get_handle_table_count( struct process *process);
 extern int flush_cached_fd( struct process *process, obj_handle_t handle );
 
-extern void close_global_handles(void);
-
 #endif  /* __WINE_SERVER_HANDLE_H */
diff --git a/server/mailslot.c b/server/mailslot.c
index 12d9a78..eb550cf 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -310,7 +310,7 @@
     return 0;
 }
 
-struct mailslot_device *create_mailslot_device( struct directory *root, const struct unicode_str *name )
+void create_mailslot_device( struct directory *root, const struct unicode_str *name )
 {
     struct mailslot_device *dev;
 
@@ -325,7 +325,7 @@
             dev = NULL;
         }
     }
-    return dev;
+    if (dev) make_object_static( &dev->obj );
 }
 
 static struct mailslot *create_mailslot( struct directory *root,
diff --git a/server/named_pipe.c b/server/named_pipe.c
index ef298bb..c3937b2 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -443,8 +443,7 @@
     return 0;
 }
 
-struct named_pipe_device *create_named_pipe_device( struct directory *root,
-                                                    const struct unicode_str *name )
+void create_named_pipe_device( struct directory *root, const struct unicode_str *name )
 {
     struct named_pipe_device *dev;
 
@@ -459,7 +458,7 @@
             dev = NULL;
         }
     }
-    return dev;
+    if (dev) make_object_static( &dev->obj );
 }
 
 static int pipe_data_remaining( struct pipe_server *server )
diff --git a/server/object.c b/server/object.c
index fbef1a1..a6f6fa8 100644
--- a/server/object.c
+++ b/server/object.c
@@ -56,11 +56,18 @@
 
 #ifdef DEBUG_OBJECTS
 static struct list object_list = LIST_INIT(object_list);
+static struct list static_object_list = LIST_INIT(static_object_list);
 
 void dump_objects(void)
 {
     struct list *p;
 
+    LIST_FOR_EACH( p, &static_object_list )
+    {
+        struct object *ptr = LIST_ENTRY( p, struct object, obj_list );
+        fprintf( stderr, "%p:%d: ", ptr, ptr->refcount );
+        ptr->ops->dump( ptr, 1 );
+    }
     LIST_FOR_EACH( p, &object_list )
     {
         struct object *ptr = LIST_ENTRY( p, struct object, obj_list );
@@ -68,7 +75,25 @@
         ptr->ops->dump( ptr, 1 );
     }
 }
-#endif
+
+void close_objects(void)
+{
+    struct list *ptr;
+
+    /* release the static objects */
+    while ((ptr = list_head( &static_object_list )))
+    {
+        struct object *obj = LIST_ENTRY( ptr, struct object, obj_list );
+        /* move it back to the standard list before freeing */
+        list_remove( &obj->obj_list );
+        list_add_head( &object_list, &obj->obj_list );
+        release_object( obj );
+    }
+
+    dump_objects();  /* dump any remaining objects */
+}
+
+#endif  /* DEBUG_OBJECTS */
 
 /*****************************************************************/
 
@@ -224,6 +249,15 @@
     obj->name = NULL;
 }
 
+/* mark an object as being stored statically, i.e. only released at shutdown */
+void make_object_static( struct object *obj )
+{
+#ifdef DEBUG_OBJECTS
+    list_remove( &obj->obj_list );
+    list_add_head( &static_object_list, &obj->obj_list );
+#endif
+}
+
 /* grab an object (i.e. increment its refcount) and return the object */
 struct object *grab_object( void *ptr )
 {
diff --git a/server/object.h b/server/object.h
index 319bbba..dbf6cac 100644
--- a/server/object.h
+++ b/server/object.h
@@ -110,6 +110,7 @@
 extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
                                   const struct unicode_str *name, unsigned int attributes );
 extern void unlink_named_object( struct object *obj );
+extern void make_object_static( struct object *obj );
 extern struct namespace *create_namespace( unsigned int hash_size );
 /* grab/release_object can take any pointer, but you better make sure */
 /* that the thing pointed to starts with a struct object... */
@@ -127,6 +128,7 @@
 extern void no_destroy( struct object *obj );
 #ifdef DEBUG_OBJECTS
 extern void dump_objects(void);
+extern void close_objects(void);
 #endif
 
 /* event functions */
@@ -167,7 +169,6 @@
 
 extern void init_registry(void);
 extern void flush_registry(void);
-extern void close_registry(void);
 
 /* signal functions */
 
@@ -175,7 +176,6 @@
 extern void stop_watchdog(void);
 extern int watchdog_triggered(void);
 extern void init_signals(void);
-extern void close_signals(void);
 
 /* atom functions */
 
@@ -194,7 +194,6 @@
 extern void *open_object_dir( struct directory *root, const struct unicode_str *name,
                               unsigned int attr, const struct object_ops *ops );
 extern void init_directories(void);
-extern void close_directories(void);
 
 /* symbolic link functions */
 
@@ -202,10 +201,8 @@
                                        unsigned int attr, const struct unicode_str *target );
 
 /* devices */
-extern struct named_pipe_device *create_named_pipe_device( struct directory *root,
-                                                           const struct unicode_str *name );
-extern struct mailslot_device *create_mailslot_device( struct directory *root,
-                                                       const struct unicode_str *name );
+extern void create_named_pipe_device( struct directory *root, const struct unicode_str *name );
+extern void create_mailslot_device( struct directory *root, const struct unicode_str *name );
 
 /* global variables */
 
diff --git a/server/registry.c b/server/registry.c
index c57ef38..63b3c12 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -1442,7 +1442,10 @@
     assert( save_branch_count < MAX_SAVE_BRANCH_INFO );
 
     if ((save_branch_info[save_branch_count].path = strdup( filename )))
+    {
         save_branch_info[save_branch_count++].key = (struct key *)grab_object( key );
+        make_object_static( &key->obj );
+    }
 }
 
 static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *path )
@@ -1488,6 +1491,7 @@
     /* create the root key */
     root_key = alloc_key( &root_name, time(NULL) );
     assert( root_key );
+    make_object_static( &root_key->obj );
 
     if (!(filename = malloc( strlen(config) + 16 ))) fatal_error( "out of memory\n" );
     strcpy( filename, config );
@@ -1694,21 +1698,6 @@
     }
 }
 
-/* close the top-level keys; used on server exit */
-void close_registry(void)
-{
-    int i;
-
-    if (save_timeout_user) remove_timeout_user( save_timeout_user );
-    save_timeout_user = NULL;
-    for (i = 0; i < save_branch_count; i++)
-    {
-        release_object( save_branch_info[i].key );
-        free( save_branch_info[i].path );
-    }
-    release_object( root_key );
-}
-
 
 /* create a registry key */
 DECL_HANDLER(create_key)
diff --git a/server/request.c b/server/request.c
index f1580d2..7eb1f83 100644
--- a/server/request.c
+++ b/server/request.c
@@ -58,10 +58,7 @@
 #include "wine/library.h"
 
 #include "file.h"
-#include "handle.h"
-#include "thread.h"
 #include "process.h"
-#include "user.h"
 #define WANT_REQUEST_HANDLERS
 #include "request.h"
 
@@ -715,6 +712,7 @@
         fatal_error( "out of memory\n" );
     master_socket->timeout = NULL;
     set_fd_events( master_socket->fd, POLLIN );
+    make_object_static( &master_socket->obj );
 }
 
 /* open the master server socket and start waiting for new clients */
@@ -798,16 +796,9 @@
     if (debug_level) fprintf( stderr, "wineserver: exiting (pid=%ld)\n", (long) getpid() );
 
 #ifdef DEBUG_OBJECTS
-    /* shut down everything properly */
-    release_object( master_socket );
-    close_signals();
-    close_global_handles();
-    close_registry();
-    close_directories();
-    dump_objects();  /* dump any remaining objects */
-#else
-    exit(0);
+    close_objects();  /* shut down everything properly */
 #endif
+    exit(0);
 }
 
 /* close the master socket and stop waiting for new clients */
diff --git a/server/signal.c b/server/signal.c
index e12532e..c873344 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -91,8 +91,6 @@
 static struct handler *handler_sigchld;
 static struct handler *handler_sigio;
 
-static sigset_t blocked_sigset;
-
 static int watchdog;
 
 /* create a signal handler */
@@ -118,6 +116,7 @@
         return NULL;
     }
     set_fd_events( handler->fd, POLLIN );
+    make_object_static( &handler->obj );
     return handler;
 }
 
@@ -265,6 +264,7 @@
 void init_signals(void)
 {
     struct sigaction action;
+    sigset_t blocked_sigset;
 
     if (!(handler_sighup  = create_handler( sighup_callback ))) goto error;
     if (!(handler_sigterm = create_handler( sigterm_callback ))) goto error;
@@ -318,13 +318,3 @@
     fprintf( stderr, "failed to initialize signal handlers\n" );
     exit(1);
 }
-
-void close_signals(void)
-{
-    sigprocmask( SIG_BLOCK, &blocked_sigset, NULL );
-    release_object( handler_sighup );
-    release_object( handler_sigterm );
-    release_object( handler_sigint );
-    release_object( handler_sigchld );
-    release_object( handler_sigio );
-}