From c6f2aacb5761801a17b930086111f4b2c4a30075 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Thu, 4 Feb 2021 13:44:18 +0100
Subject: [PATCH] server: Add a type descriptor to all server objects.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
 server/async.c      |   4 +-
 server/atom.c       |   2 +-
 server/change.c     |  10 +----
 server/clipboard.c  |   2 +-
 server/completion.c |  17 ++++---
 server/console.c    |  22 +++------
 server/debugger.c   |  19 ++++----
 server/device.c     |  23 +++++-----
 server/directory.c  | 107 ++++++++++++++++++++++++++------------------
 server/event.c      |  34 +++++++-------
 server/fd.c         |   8 ++--
 server/file.c       |  16 +++----
 server/file.h       |   1 -
 server/handle.c     |   2 +-
 server/hook.c       |   2 +-
 server/mailslot.c   |  16 ++-----
 server/mapping.c    |  22 ++++-----
 server/mutex.c      |  17 ++++---
 server/named_pipe.c |  18 +++-----
 server/object.c     |   7 +--
 server/object.h     |  36 +++++++++++++--
 server/process.c    |  38 +++++++---------
 server/queue.c      |   4 +-
 server/registry.c   |  17 ++++---
 server/request.c    |   2 +-
 server/semaphore.c  |  17 ++++---
 server/serial.c     |   2 +-
 server/signal.c     |   2 +-
 server/sock.c       |  14 ++----
 server/symlink.c    |  17 ++++---
 server/thread.c     |  21 +++++----
 server/timer.c      |  17 ++++---
 server/token.c      |  17 ++++---
 server/winstation.c |  34 +++++++-------
 34 files changed, 287 insertions(+), 300 deletions(-)

diff --git a/server/async.c b/server/async.c
index 81d575b52bd..b6133928ac9 100644
--- a/server/async.c
+++ b/server/async.c
@@ -65,8 +65,8 @@ static void async_destroy( struct object *obj );
 static const struct object_ops async_ops =
 {
     sizeof(struct async),      /* size */
+    &no_type,                  /* type */
     async_dump,                /* dump */
-    no_get_type,               /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     async_signaled,            /* signaled */
@@ -479,8 +479,8 @@ static void iosb_destroy( struct object *obj );
 static const struct object_ops iosb_ops =
 {
     sizeof(struct iosb),      /* size */
+    &no_type,                 /* type */
     iosb_dump,                /* dump */
-    no_get_type,              /* get_type */
     no_add_queue,             /* add_queue */
     NULL,                     /* remove_queue */
     NULL,                     /* signaled */
diff --git a/server/atom.c b/server/atom.c
index b61fa276661..b64d13a1f43 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -75,8 +75,8 @@ static void atom_table_destroy( struct object *obj );
 static const struct object_ops atom_table_ops =
 {
     sizeof(struct atom_table),    /* size */
+    &no_type,                     /* type */
     atom_table_dump,              /* dump */
-    no_get_type,                  /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
diff --git a/server/change.c b/server/change.c
index 8e4a272bc8b..d4f4c543f11 100644
--- a/server/change.c
+++ b/server/change.c
@@ -103,15 +103,14 @@ static struct security_descriptor *dir_get_sd( struct object *obj );
 static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
                        unsigned int set_info );
 static void dir_dump( struct object *obj, int verbose );
-static struct object_type *dir_get_type( struct object *obj );
 static int dir_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static void dir_destroy( struct object *obj );
 
 static const struct object_ops dir_ops =
 {
     sizeof(struct dir),       /* size */
+    &file_type,               /* type */
     dir_dump,                 /* dump */
-    dir_get_type,             /* get_type */
     add_queue,                /* add_queue */
     remove_queue,             /* remove_queue */
     default_fd_signaled,      /* signaled */
@@ -292,13 +291,6 @@ static void dir_dump( struct object *obj, int verbose )
     fprintf( stderr, "Dirfile fd=%p filter=%08x\n", dir->fd, dir->filter );
 }
 
-static struct object_type *dir_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'F','i','l','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 /* enter here directly from SIGIO signal handler */
 void do_change_notify( int unix_fd )
 {
diff --git a/server/clipboard.c b/server/clipboard.c
index e4546832620..36cbd954c1f 100644
--- a/server/clipboard.c
+++ b/server/clipboard.c
@@ -72,8 +72,8 @@ static void clipboard_destroy( struct object *obj );
 static const struct object_ops clipboard_ops =
 {
     sizeof(struct clipboard),     /* size */
+    &no_type,                     /* type */
     clipboard_dump,               /* dump */
-    no_get_type,                  /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
diff --git a/server/completion.c b/server/completion.c
index 0bad4d7a260..76fe2b2d231 100644
--- a/server/completion.c
+++ b/server/completion.c
@@ -43,6 +43,13 @@
 #include "request.h"
 
 
+static const WCHAR completion_name[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
+
+struct type_descr completion_type =
+{
+    { completion_name, sizeof(completion_name) },   /* name */
+};
+
 struct completion
 {
     struct object  obj;
@@ -51,7 +58,6 @@ struct completion
 };
 
 static void completion_dump( struct object*, int );
-static struct object_type *completion_get_type( struct object *obj );
 static int completion_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int completion_map_access( struct object *obj, unsigned int access );
 static void completion_destroy( struct object * );
@@ -59,8 +65,8 @@ static void completion_destroy( struct object * );
 static const struct object_ops completion_ops =
 {
     sizeof(struct completion), /* size */
+    &completion_type,          /* type */
     completion_dump,           /* dump */
-    completion_get_type,       /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     completion_signaled,       /* signaled */
@@ -108,13 +114,6 @@ static void completion_dump( struct object *obj, int verbose )
     fprintf( stderr, "Completion depth=%u\n", completion->depth );
 }
 
-static struct object_type *completion_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int completion_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct completion *completion = (struct completion *)obj;
diff --git a/server/console.c b/server/console.c
index d1f948b23a6..70040bf8531 100644
--- a/server/console.c
+++ b/server/console.c
@@ -76,8 +76,8 @@ static struct object *console_open_file( struct object *obj, unsigned int access
 static const struct object_ops console_ops =
 {
     sizeof(struct console),           /* size */
+    &file_type,                       /* type */
     console_dump,                     /* dump */
-    no_get_type,                      /* get_type */
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     console_signaled,                 /* signaled */
@@ -151,8 +151,8 @@ static struct object *console_server_open_file( struct object *obj, unsigned int
 static const struct object_ops console_server_ops =
 {
     sizeof(struct console_server),    /* size */
+    &file_type,                       /* type */
     console_server_dump,              /* dump */
-    no_get_type,                      /* get_type */
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     console_server_signaled,          /* signaled */
@@ -219,8 +219,8 @@ static struct object *screen_buffer_open_file( struct object *obj, unsigned int
 static const struct object_ops screen_buffer_ops =
 {
     sizeof(struct screen_buffer),     /* size */
+    &file_type,                       /* type */
     screen_buffer_dump,               /* dump */
-    no_get_type,                      /* get_type */
     screen_buffer_add_queue,          /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -258,7 +258,6 @@ static const struct fd_ops screen_buffer_fd_ops =
     default_fd_reselect_async     /* reselect_async */
 };
 
-static struct object_type *console_device_get_type( struct object *obj );
 static void console_device_dump( struct object *obj, int verbose );
 static struct object *console_device_lookup_name( struct object *obj, struct unicode_str *name,
                                                 unsigned int attr, struct object *root );
@@ -268,8 +267,8 @@ static struct object *console_device_open_file( struct object *obj, unsigned int
 static const struct object_ops console_device_ops =
 {
     sizeof(struct object),            /* size */
+    &device_type,                     /* type */
     console_device_dump,              /* dump */
-    console_device_get_type,          /* get_type */
     no_add_queue,                     /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -305,8 +304,8 @@ static void console_input_destroy( struct object *obj );
 static const struct object_ops console_input_ops =
 {
     sizeof(struct console_input),     /* size */
+    &device_type,                     /* type */
     console_input_dump,               /* dump */
-    console_device_get_type,          /* get_type */
     console_input_add_queue,          /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -361,8 +360,8 @@ static void console_output_destroy( struct object *obj );
 static const struct object_ops console_output_ops =
 {
     sizeof(struct console_output),    /* size */
+    &device_type,                     /* type */
     console_output_dump,              /* dump */
-    console_device_get_type,          /* get_type */
     console_output_add_queue,         /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -418,8 +417,8 @@ static void console_connection_destroy( struct object *obj );
 static const struct object_ops console_connection_ops =
 {
     sizeof(struct console_connection),/* size */
+    &device_type,                     /* type */
     console_connection_dump,          /* dump */
-    console_device_get_type,          /* get_type */
     no_add_queue,                     /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -1192,13 +1191,6 @@ static void console_connection_destroy( struct object *obj )
     if (connection->fd) release_object( connection->fd );
 }
 
-static struct object_type *console_device_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','v','i','c','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static void console_device_dump( struct object *obj, int verbose )
 {
     fputs( "Console device\n", stderr );
diff --git a/server/debugger.c b/server/debugger.c
index fcc45ad46cc..21ab3c4bab4 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -52,6 +52,13 @@ struct debug_event
     debug_event_t          data;      /* event data */
 };
 
+static const WCHAR debug_obj_name[] = {'D','e','b','u','g','O','b','j','e','c','t'};
+
+struct type_descr debug_obj_type =
+{
+    { debug_obj_name, sizeof(debug_obj_name) },   /* name */
+};
+
 /* debug object */
 struct debug_obj
 {
@@ -68,8 +75,8 @@ static void debug_event_destroy( struct object *obj );
 static const struct object_ops debug_event_ops =
 {
     sizeof(struct debug_event),    /* size */
+    &no_type,                      /* type */
     debug_event_dump,              /* dump */
-    no_get_type,                   /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     debug_event_signaled,          /* signaled */
@@ -90,7 +97,6 @@ static const struct object_ops debug_event_ops =
 };
 
 static void debug_obj_dump( struct object *obj, int verbose );
-static struct object_type *debug_obj_get_type( struct object *obj );
 static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int debug_obj_map_access( struct object *obj, unsigned int access );
 static void debug_obj_destroy( struct object *obj );
@@ -98,8 +104,8 @@ static void debug_obj_destroy( struct object *obj );
 static const struct object_ops debug_obj_ops =
 {
     sizeof(struct debug_obj),      /* size */
+    &debug_obj_type,               /* type */
     debug_obj_dump,                /* dump */
-    debug_obj_get_type,            /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     debug_obj_signaled,            /* signaled */
@@ -307,13 +313,6 @@ static void debug_obj_dump( struct object *obj, int verbose )
              debug_obj->event_queue.next, debug_obj->event_queue.prev );
 }
 
-static struct object_type *debug_obj_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','b','u','g','O','b','j','e','c','t'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct debug_obj *debug_obj = (struct debug_obj *)obj;
diff --git a/server/device.c b/server/device.c
index 652da83e1e2..e583c974c5f 100644
--- a/server/device.c
+++ b/server/device.c
@@ -63,8 +63,8 @@ static void irp_call_destroy( struct object *obj );
 static const struct object_ops irp_call_ops =
 {
     sizeof(struct irp_call),          /* size */
+    &no_type,                         /* type */
     irp_call_dump,                    /* dump */
-    no_get_type,                      /* get_type */
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     irp_call_signaled,                /* signaled */
@@ -103,8 +103,8 @@ static void device_manager_destroy( struct object *obj );
 static const struct object_ops device_manager_ops =
 {
     sizeof(struct device_manager),    /* size */
+    &no_type,                         /* type */
     device_manager_dump,              /* dump */
-    no_get_type,                      /* get_type */
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     device_manager_signaled,          /* signaled */
@@ -127,6 +127,13 @@ static const struct object_ops device_manager_ops =
 
 /* device (a single device object) */
 
+static const WCHAR device_name[] = {'D','e','v','i','c','e'};
+
+struct type_descr device_type =
+{
+    { device_name, sizeof(device_name) },   /* name */
+};
+
 struct device
 {
     struct object          obj;           /* object header */
@@ -138,7 +145,6 @@ struct device
 };
 
 static void device_dump( struct object *obj, int verbose );
-static struct object_type *device_get_type( struct object *obj );
 static void device_destroy( struct object *obj );
 static struct object *device_open_file( struct object *obj, unsigned int access,
                                         unsigned int sharing, unsigned int options );
@@ -147,8 +153,8 @@ static struct list *device_get_kernel_obj_list( struct object *obj );
 static const struct object_ops device_ops =
 {
     sizeof(struct device),            /* size */
+    &device_type,                     /* type */
     device_dump,                      /* dump */
-    device_get_type,                  /* get_type */
     no_add_queue,                     /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -198,8 +204,8 @@ static void device_file_reselect_async( struct fd *fd, struct async_queue *queue
 static const struct object_ops device_file_ops =
 {
     sizeof(struct device_file),       /* size */
+    &file_type,                       /* type */
     device_file_dump,                 /* dump */
-    file_get_type,                    /* get_type */
     add_queue,                        /* add_queue */
     remove_queue,                     /* remove_queue */
     default_fd_signaled,              /* signaled */
@@ -409,13 +415,6 @@ static void device_dump( struct object *obj, int verbose )
     fputs( "Device\n", stderr );
 }
 
-static struct object_type *device_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','v','i','c','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static void device_destroy( struct object *obj )
 {
     struct device *device = (struct device *)obj;
diff --git a/server/directory.c b/server/directory.c
index ca9f978ff7f..e57b97c3ede 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -41,19 +41,25 @@
 
 #define HASH_SIZE 7  /* default hash size */
 
+static const WCHAR objtype_name[] = {'T','y','p','e'};
+
+struct type_descr objtype_type =
+{
+    { objtype_name, sizeof(objtype_name) },   /* name */
+};
+
 struct object_type
 {
     struct object     obj;        /* object header */
 };
 
 static void object_type_dump( struct object *obj, int verbose );
-static struct object_type *object_type_get_type( struct object *obj );
 
 static const struct object_ops object_type_ops =
 {
     sizeof(struct object_type),   /* size */
+    &objtype_type,                /* type */
     object_type_dump,             /* dump */
-    object_type_get_type,         /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -74,6 +80,13 @@ static const struct object_ops object_type_ops =
 };
 
 
+static const WCHAR directory_name[] = {'D','i','r','e','c','t','o','r','y'};
+
+struct type_descr directory_type =
+{
+    { directory_name, sizeof(directory_name) },   /* name */
+};
+
 struct directory
 {
     struct object     obj;        /* object header */
@@ -81,7 +94,6 @@ struct directory
 };
 
 static void directory_dump( struct object *obj, int verbose );
-static struct object_type *directory_get_type( struct object *obj );
 static struct object *directory_lookup_name( struct object *obj, struct unicode_str *name,
                                              unsigned int attr, struct object *root );
 static void directory_destroy( struct object *obj );
@@ -89,8 +101,8 @@ static void directory_destroy( struct object *obj );
 static const struct object_ops directory_ops =
 {
     sizeof(struct directory),     /* size */
+    &directory_type,              /* type */
     directory_dump,               /* dump */
-    directory_get_type,           /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -114,16 +126,46 @@ static struct directory *root_directory;
 static struct directory *dir_objtype;
 
 
+static struct type_descr *types[] =
+{
+    &objtype_type,
+    &directory_type,
+    &symlink_type,
+    &token_type,
+    &job_type,
+    &process_type,
+    &thread_type,
+    &debug_obj_type,
+    &event_type,
+    &mutex_type,
+    &semaphore_type,
+    &timer_type,
+    &keyed_event_type,
+    &winstation_type,
+    &desktop_type,
+    &device_type,
+    &completion_type,
+    &file_type,
+    &mapping_type,
+    &key_type,
+};
+
 static void object_type_dump( struct object *obj, int verbose )
 {
     fputs( "Object type\n", stderr );
 }
 
-static struct object_type *object_type_get_type( struct object *obj )
+static struct object_type *create_object_type( struct object *root, unsigned int index,
+                                               unsigned int attr, const struct security_descriptor *sd )
 {
-    static const WCHAR name[] = {'O','b','j','e','c','t','T','y','p','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
+    struct type_descr *descr = types[index];
+    struct object_type *type;
+
+    if ((type = create_named_object( root, &object_type_ops, &descr->name, attr, sd )))
+    {
+        descr->index = index;
+    }
+    return type;
 }
 
 static void directory_dump( struct object *obj, int verbose )
@@ -131,13 +173,6 @@ static void directory_dump( struct object *obj, int verbose )
     fputs( "Directory\n", stderr );
 }
 
-static struct object_type *directory_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','i','r','e','c','t','o','r','y'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static struct object *directory_lookup_name( struct object *obj, struct unicode_str *name,
                                              unsigned int attr, struct object *root )
 {
@@ -229,17 +264,6 @@ struct object *get_directory_obj( struct process *process, obj_handle_t handle )
     return get_handle_obj( process, handle, 0, &directory_ops );
 }
 
-/* retrieve an object type, creating it if needed */
-struct object_type *get_object_type( const struct unicode_str *name )
-{
-    struct object_type *type;
-
-    if ((type = create_named_object( &dir_objtype->obj, &object_type_ops, name,
-                                     OBJ_OPENIF | OBJ_PERMANENT, NULL )))
-        clear_error();
-    return type;
-}
-
 /* Global initialization */
 
 static void create_session( unsigned int id )
@@ -426,6 +450,11 @@ void init_directories( struct fd *intl_fd )
     create_session( 0 );
     create_session( 1 );
 
+    /* object types */
+
+    for (i = 0; i < ARRAY_SIZE(types); i++)
+        release_object( create_object_type( &dir_objtype->obj, i, OBJ_PERMANENT, NULL ));
+
     /* symlinks */
     release_object( create_obj_symlink( &root_directory->obj, &link_dosdev_str, OBJ_PERMANENT, &dir_global->obj, NULL ));
     release_object( create_obj_symlink( &dir_global->obj, &link_global_str, OBJ_PERMANENT, &dir_global->obj, NULL ));
@@ -497,26 +526,22 @@ DECL_HANDLER(get_directory_entry)
         struct object *obj = find_object_index( dir->entries, req->index );
         if (obj)
         {
-            data_size_t name_len, type_len = 0;
-            const WCHAR *type_name = NULL;
+            data_size_t name_len;
+            const struct unicode_str *type_name = &obj->ops->type->name;
             const WCHAR *name = get_object_name( obj, &name_len );
-            struct object_type *type = obj->ops->get_type( obj );
-
-            if (type) type_name = get_object_name( &type->obj, &type_len );
 
-            if (name_len + type_len <= get_reply_max_size())
+            if (name_len + type_name->len <= get_reply_max_size())
             {
-                void *ptr = set_reply_data_size( name_len + type_len );
+                void *ptr = set_reply_data_size( name_len + type_name->len );
                 if (ptr)
                 {
                     reply->name_len = name_len;
                     memcpy( ptr, name, name_len );
-                    memcpy( (char *)ptr + name_len, type_name, type_len );
+                    memcpy( (char *)ptr + name_len, type_name->str, type_name->len );
                 }
             }
             else set_error( STATUS_BUFFER_OVERFLOW );
 
-            if (type) release_object( type );
             release_object( obj );
         }
         release_object( dir );
@@ -527,16 +552,12 @@ DECL_HANDLER(get_directory_entry)
 DECL_HANDLER(get_object_type)
 {
     struct object *obj;
-    struct object_type *type;
-    const WCHAR *name;
+    struct type_descr *type;
 
     if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
 
-    if ((type = obj->ops->get_type( obj )))
-    {
-        if ((name = get_object_name( &type->obj, &reply->total )))
-            set_reply_data( name, min( reply->total, get_reply_max_size() ) );
-        release_object( type );
-    }
+    type = obj->ops->type;
+    reply->total = type->name.len;
+    set_reply_data( type->name.str, min( reply->total, get_reply_max_size() ) );
     release_object( obj );
 }
diff --git a/server/event.c b/server/event.c
index cba9472aa3d..9be073bda9e 100644
--- a/server/event.c
+++ b/server/event.c
@@ -36,6 +36,13 @@
 #include "request.h"
 #include "security.h"
 
+static const WCHAR event_name[] = {'E','v','e','n','t'};
+
+struct type_descr event_type =
+{
+    { event_name, sizeof(event_name) },   /* name */
+};
+
 struct event
 {
     struct object  obj;             /* object header */
@@ -45,7 +52,6 @@ struct event
 };
 
 static void event_dump( struct object *obj, int verbose );
-static struct object_type *event_get_type( struct object *obj );
 static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int event_map_access( struct object *obj, unsigned int access );
@@ -55,8 +61,8 @@ static struct list *event_get_kernel_obj_list( struct object *obj );
 static const struct object_ops event_ops =
 {
     sizeof(struct event),      /* size */
+    &event_type,               /* type */
     event_dump,                /* dump */
-    event_get_type,            /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     event_signaled,            /* signaled */
@@ -77,21 +83,27 @@ static const struct object_ops event_ops =
 };
 
 
+static const WCHAR keyed_event_name[] = {'K','e','y','e','d','E','v','e','n','t'};
+
+struct type_descr keyed_event_type =
+{
+    { keyed_event_name, sizeof(keyed_event_name) },   /* name */
+};
+
 struct keyed_event
 {
     struct object  obj;             /* object header */
 };
 
 static void keyed_event_dump( struct object *obj, int verbose );
-static struct object_type *keyed_event_get_type( struct object *obj );
 static int keyed_event_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int keyed_event_map_access( struct object *obj, unsigned int access );
 
 static const struct object_ops keyed_event_ops =
 {
     sizeof(struct keyed_event),  /* size */
+    &keyed_event_type,           /* type */
     keyed_event_dump,            /* dump */
-    keyed_event_get_type,        /* get_type */
     add_queue,                   /* add_queue */
     remove_queue,                /* remove_queue */
     keyed_event_signaled,        /* signaled */
@@ -164,13 +176,6 @@ static void event_dump( struct object *obj, int verbose )
              event->manual_reset, event->signaled );
 }
 
-static struct object_type *event_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'E','v','e','n','t'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int event_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct event *event = (struct event *)obj;
@@ -240,13 +245,6 @@ static void keyed_event_dump( struct object *obj, int verbose )
     fputs( "Keyed event\n", stderr );
 }
 
-static struct object_type *keyed_event_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'K','e','y','e','d','E','v','e','n','t'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static enum select_op matching_op( enum select_op op )
 {
     return op ^ (SELECT_KEYED_EVENT_WAIT ^ SELECT_KEYED_EVENT_RELEASE);
diff --git a/server/fd.c b/server/fd.c
index edb59b0d540..1b21583fe7c 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -205,8 +205,8 @@ static void fd_destroy( struct object *obj );
 static const struct object_ops fd_ops =
 {
     sizeof(struct fd),        /* size */
+    &no_type,                 /* type */
     fd_dump,                  /* dump */
-    no_get_type,              /* get_type */
     no_add_queue,             /* add_queue */
     NULL,                     /* remove_queue */
     NULL,                     /* signaled */
@@ -246,8 +246,8 @@ static void device_destroy( struct object *obj );
 static const struct object_ops device_ops =
 {
     sizeof(struct device),    /* size */
+    &no_type,                 /* type */
     device_dump,              /* dump */
-    no_get_type,              /* get_type */
     no_add_queue,             /* add_queue */
     NULL,                     /* remove_queue */
     NULL,                     /* signaled */
@@ -286,8 +286,8 @@ static void inode_destroy( struct object *obj );
 static const struct object_ops inode_ops =
 {
     sizeof(struct inode),     /* size */
+    &no_type,                 /* type */
     inode_dump,               /* dump */
-    no_get_type,              /* get_type */
     no_add_queue,             /* add_queue */
     NULL,                     /* remove_queue */
     NULL,                     /* signaled */
@@ -328,8 +328,8 @@ static int file_lock_signaled( struct object *obj, struct wait_queue_entry *entr
 static const struct object_ops file_lock_ops =
 {
     sizeof(struct file_lock),   /* size */
+    &no_type,                   /* type */
     file_lock_dump,             /* dump */
-    no_get_type,                /* get_type */
     add_queue,                  /* add_queue */
     remove_queue,               /* remove_queue */
     file_lock_signaled,         /* signaled */
diff --git a/server/file.c b/server/file.c
index fd8e3f96033..ba0e2705881 100644
--- a/server/file.c
+++ b/server/file.c
@@ -52,6 +52,13 @@
 #include "process.h"
 #include "security.h"
 
+static const WCHAR file_name[] = {'F','i','l','e'};
+
+struct type_descr file_type =
+{
+    { file_name, sizeof(file_name) },   /* name */
+};
+
 struct file
 {
     struct object       obj;            /* object header */
@@ -80,8 +87,8 @@ static enum server_fd_type file_get_fd_type( struct fd *fd );
 static const struct object_ops file_ops =
 {
     sizeof(struct file),          /* size */
+    &file_type,                   /* type */
     file_dump,                    /* dump */
-    file_get_type,                /* get_type */
     add_queue,                    /* add_queue */
     remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
@@ -279,13 +286,6 @@ static void file_dump( struct object *obj, int verbose )
     fprintf( stderr, "File fd=%p\n", file->fd );
 }
 
-struct object_type *file_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'F','i','l','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static enum server_fd_type file_get_fd_type( struct fd *fd )
 {
     struct file *file = get_fd_user( fd );
diff --git a/server/file.h b/server/file.h
index 9e46da3242e..21aa8e467e2 100644
--- a/server/file.h
+++ b/server/file.h
@@ -159,7 +159,6 @@ extern int get_file_unix_fd( struct file *file );
 extern struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing );
 extern struct file *create_file_for_fd_obj( struct fd *fd, unsigned int access, unsigned int sharing );
 extern void file_set_error(void);
-extern struct object_type *file_get_type( struct object *obj );
 extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group );
 extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
 extern int is_file_executable( const char *name );
diff --git a/server/handle.c b/server/handle.c
index 2556a03901e..2333107b724 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -118,8 +118,8 @@ static void handle_table_destroy( struct object *obj );
 static const struct object_ops handle_table_ops =
 {
     sizeof(struct handle_table),     /* size */
+    &no_type,                        /* type */
     handle_table_dump,               /* dump */
-    no_get_type,                     /* get_type */
     no_add_queue,                    /* add_queue */
     NULL,                            /* remove_queue */
     NULL,                            /* signaled */
diff --git a/server/hook.c b/server/hook.c
index 2a3da247313..3c329f35c9b 100644
--- a/server/hook.c
+++ b/server/hook.c
@@ -76,8 +76,8 @@ static void hook_table_destroy( struct object *obj );
 static const struct object_ops hook_table_ops =
 {
     sizeof(struct hook_table),    /* size */
+    &no_type,                     /* type */
     hook_table_dump,              /* dump */
-    no_get_type,                  /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
diff --git a/server/mailslot.c b/server/mailslot.c
index 5d26c606080..ef691efbb9c 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -73,8 +73,8 @@ static void mailslot_destroy( struct object * );
 static const struct object_ops mailslot_ops =
 {
     sizeof(struct mailslot),   /* size */
+    &file_type,                /* type */
     mailslot_dump,             /* dump */
-    file_get_type,             /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     default_fd_signaled,       /* signaled */
@@ -131,8 +131,8 @@ static void mail_writer_destroy( struct object *obj);
 static const struct object_ops mail_writer_ops =
 {
     sizeof(struct mail_writer), /* size */
+    &file_type,                 /* type */
     mail_writer_dump,           /* dump */
-    file_get_type,              /* get_type */
     no_add_queue,               /* add_queue */
     NULL,                       /* remove_queue */
     NULL,                       /* signaled */
@@ -184,7 +184,6 @@ struct mailslot_device_file
 };
 
 static void mailslot_device_dump( struct object *obj, int verbose );
-static struct object_type *mailslot_device_get_type( struct object *obj );
 static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
                                                    unsigned int attr, struct object *root );
 static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
@@ -194,8 +193,8 @@ static void mailslot_device_destroy( struct object *obj );
 static const struct object_ops mailslot_device_ops =
 {
     sizeof(struct mailslot_device), /* size */
+    &device_type,                   /* type */
     mailslot_device_dump,           /* dump */
-    mailslot_device_get_type,       /* get_type */
     no_add_queue,                   /* add_queue */
     NULL,                           /* remove_queue */
     NULL,                           /* signaled */
@@ -224,8 +223,8 @@ static enum server_fd_type mailslot_device_file_get_fd_type( struct fd *fd );
 static const struct object_ops mailslot_device_file_ops =
 {
     sizeof(struct mailslot_device_file),    /* size */
+    &file_type,                             /* type */
     mailslot_device_file_dump,              /* dump */
-    file_get_type,                          /* get_type */
     add_queue,                              /* add_queue */
     remove_queue,                           /* remove_queue */
     default_fd_signaled,                    /* signaled */
@@ -387,13 +386,6 @@ static void mailslot_device_dump( struct object *obj, int verbose )
     fputs( "Mailslot device\n", stderr );
 }
 
-static struct object_type *mailslot_device_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','v','i','c','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
                                                    unsigned int attr, struct object *root )
 {
diff --git a/server/mapping.c b/server/mapping.c
index 32ac9247144..0ae214f4aba 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -63,8 +63,8 @@ static void ranges_destroy( struct object *obj );
 static const struct object_ops ranges_ops =
 {
     sizeof(struct ranges),     /* size */
+    &no_type,                  /* type */
     ranges_dump,               /* dump */
-    no_get_type,               /* get_type */
     no_add_queue,              /* add_queue */
     NULL,                      /* remove_queue */
     NULL,                      /* signaled */
@@ -99,8 +99,8 @@ static void shared_map_destroy( struct object *obj );
 static const struct object_ops shared_map_ops =
 {
     sizeof(struct shared_map), /* size */
+    &no_type,                  /* type */
     shared_map_dump,           /* dump */
-    no_get_type,               /* get_type */
     no_add_queue,              /* add_queue */
     NULL,                      /* remove_queue */
     NULL,                      /* signaled */
@@ -136,6 +136,14 @@ struct memory_view
     file_pos_t      start;           /* start offset in mapping */
 };
 
+
+static const WCHAR mapping_name[] = {'S','e','c','t','i','o','n'};
+
+struct type_descr mapping_type =
+{
+    { mapping_name, sizeof(mapping_name) },   /* name */
+};
+
 struct mapping
 {
     struct object   obj;             /* object header */
@@ -148,7 +156,6 @@ struct mapping
 };
 
 static void mapping_dump( struct object *obj, int verbose );
-static struct object_type *mapping_get_type( struct object *obj );
 static struct fd *mapping_get_fd( struct object *obj );
 static unsigned int mapping_map_access( struct object *obj, unsigned int access );
 static void mapping_destroy( struct object *obj );
@@ -157,8 +164,8 @@ static enum server_fd_type mapping_get_fd_type( struct fd *fd );
 static const struct object_ops mapping_ops =
 {
     sizeof(struct mapping),      /* size */
+    &mapping_type,               /* type */
     mapping_dump,                /* dump */
-    mapping_get_type,            /* get_type */
     no_add_queue,                /* add_queue */
     NULL,                        /* remove_queue */
     NULL,                        /* signaled */
@@ -977,13 +984,6 @@ static void mapping_dump( struct object *obj, int verbose )
              mapping->flags, mapping->fd, mapping->shared );
 }
 
-static struct object_type *mapping_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'S','e','c','t','i','o','n'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static struct fd *mapping_get_fd( struct object *obj )
 {
     struct mapping *mapping = (struct mapping *)obj;
diff --git a/server/mutex.c b/server/mutex.c
index 823ad54ffc3..c85db0b323d 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -36,6 +36,13 @@
 #include "request.h"
 #include "security.h"
 
+static const WCHAR mutex_name[] = {'M','u','t','a','n','t'};
+
+struct type_descr mutex_type =
+{
+    { mutex_name, sizeof(mutex_name) },   /* name */
+};
+
 struct mutex
 {
     struct object  obj;             /* object header */
@@ -46,7 +53,6 @@ struct mutex
 };
 
 static void mutex_dump( struct object *obj, int verbose );
-static struct object_type *mutex_get_type( struct object *obj );
 static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void mutex_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int mutex_map_access( struct object *obj, unsigned int access );
@@ -56,8 +62,8 @@ static int mutex_signal( struct object *obj, unsigned int access );
 static const struct object_ops mutex_ops =
 {
     sizeof(struct mutex),      /* size */
+    &mutex_type,               /* type */
     mutex_dump,                /* dump */
-    mutex_get_type,            /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     mutex_signaled,            /* signaled */
@@ -141,13 +147,6 @@ static void mutex_dump( struct object *obj, int verbose )
     fprintf( stderr, "Mutex count=%u owner=%p\n", mutex->count, mutex->owner );
 }
 
-static struct object_type *mutex_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'M','u','t','a','n','t'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int mutex_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct mutex *mutex = (struct mutex *)obj;
diff --git a/server/named_pipe.c b/server/named_pipe.c
index ff1fdbe3f07..ae284c3d40a 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -114,8 +114,8 @@ static void named_pipe_destroy( struct object *obj );
 static const struct object_ops named_pipe_ops =
 {
     sizeof(struct named_pipe),    /* size */
+    &no_type,                     /* type */
     named_pipe_dump,              /* dump */
-    no_get_type,                  /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -162,8 +162,8 @@ static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *as
 static const struct object_ops pipe_server_ops =
 {
     sizeof(struct pipe_server),   /* size */
+    &file_type,                   /* type */
     pipe_server_dump,             /* dump */
-    file_get_type,                /* get_type */
     add_queue,                    /* add_queue */
     remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
@@ -205,8 +205,8 @@ static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *as
 static const struct object_ops pipe_client_ops =
 {
     sizeof(struct pipe_end),      /* size */
+    &file_type,                   /* type */
     pipe_client_dump,             /* dump */
-    file_get_type,                /* get_type */
     add_queue,                    /* add_queue */
     remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
@@ -242,7 +242,6 @@ static const struct fd_ops pipe_client_fd_ops =
 };
 
 static void named_pipe_device_dump( struct object *obj, int verbose );
-static struct object_type *named_pipe_device_get_type( struct object *obj );
 static struct object *named_pipe_device_lookup_name( struct object *obj,
     struct unicode_str *name, unsigned int attr, struct object *root );
 static struct object *named_pipe_device_open_file( struct object *obj, unsigned int access,
@@ -252,8 +251,8 @@ static void named_pipe_device_destroy( struct object *obj );
 static const struct object_ops named_pipe_device_ops =
 {
     sizeof(struct named_pipe_device), /* size */
+    &device_type,                     /* type */
     named_pipe_device_dump,           /* dump */
-    named_pipe_device_get_type,       /* get_type */
     no_add_queue,                     /* add_queue */
     NULL,                             /* remove_queue */
     NULL,                             /* signaled */
@@ -283,8 +282,8 @@ static void named_pipe_device_file_destroy( struct object *obj );
 static const struct object_ops named_pipe_device_file_ops =
 {
     sizeof(struct named_pipe_device_file),   /* size */
+    &file_type,                              /* type */
     named_pipe_device_file_dump,             /* dump */
-    file_get_type,                           /* get_type */
     add_queue,                               /* add_queue */
     remove_queue,                            /* remove_queue */
     default_fd_signaled,                     /* signaled */
@@ -491,13 +490,6 @@ static void named_pipe_device_dump( struct object *obj, int verbose )
     fputs( "Named pipe device\n", stderr );
 }
 
-static struct object_type *named_pipe_device_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','v','i','c','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static struct object *named_pipe_device_lookup_name( struct object *obj, struct unicode_str *name,
                                                      unsigned int attr, struct object *root )
 {
diff --git a/server/object.c b/server/object.c
index 4453c84ced8..56f7b72dfa5 100644
--- a/server/object.c
+++ b/server/object.c
@@ -50,6 +50,8 @@ struct namespace
 };
 
 
+struct type_descr no_type = {{ 0 }};
+
 #ifdef DEBUG_OBJECTS
 static struct list object_list = LIST_INIT(object_list);
 
@@ -491,11 +493,6 @@ struct namespace *create_namespace( unsigned int hash_size )
 
 /* functions for unimplemented/default object operations */
 
-struct object_type *no_get_type( struct object *obj )
-{
-    return NULL;
-}
-
 int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
 {
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
diff --git a/server/object.h b/server/object.h
index 877c52bab5c..8a4ec0660ed 100644
--- a/server/object.h
+++ b/server/object.h
@@ -53,15 +53,22 @@ struct unicode_str
     data_size_t  len;
 };
 
+/* object type descriptor */
+struct type_descr
+{
+    struct unicode_str name;          /* type name */
+    unsigned int       index;         /* index in global array of types */
+};
+
 /* operations valid on all objects */
 struct object_ops
 {
     /* size of this object type */
     size_t size;
+    /* type descriptor */
+    struct type_descr *type;
     /* dump the object (for debugging) */
     void (*dump)(struct object *,int);
-    /* return the object type */
-    struct object_type *(*get_type)(struct object *);
     /* add a thread to the object wait queue */
     int  (*add_queue)(struct object *,struct wait_queue_entry *);
     /* remove a thread from the object wait queue */
@@ -154,7 +161,6 @@ extern void release_object( void *obj );
 extern struct object *find_object( const struct namespace *namespace, const struct unicode_str *name,
                                    unsigned int attributes );
 extern struct object *find_object_index( const struct namespace *namespace, unsigned int index );
-extern struct object_type *no_get_type( struct object *obj );
 extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
 extern void no_satisfied( struct object *obj, struct wait_queue_entry *entry );
 extern int no_signal( struct object *obj, unsigned int access );
@@ -240,7 +246,6 @@ extern void release_global_atom( struct winstation *winstation, atom_t atom );
 
 extern struct object *get_root_directory(void);
 extern struct object *get_directory_obj( struct process *process, obj_handle_t handle );
-extern struct object_type *get_object_type( const struct unicode_str *name );
 extern int directory_link_name( struct object *obj, struct object_name *name, struct object *parent );
 extern void init_directories( struct fd *intl_fd );
 
@@ -264,6 +269,29 @@ extern const char *server_argv0;
   /* server start time used for GetTickCount() */
 extern timeout_t server_start_time;
 
+/* object types */
+extern struct type_descr no_type;
+extern struct type_descr objtype_type;
+extern struct type_descr directory_type;
+extern struct type_descr symlink_type;
+extern struct type_descr token_type;
+extern struct type_descr job_type;
+extern struct type_descr process_type;
+extern struct type_descr thread_type;
+extern struct type_descr debug_obj_type;
+extern struct type_descr event_type;
+extern struct type_descr mutex_type;
+extern struct type_descr semaphore_type;
+extern struct type_descr timer_type;
+extern struct type_descr keyed_event_type;
+extern struct type_descr winstation_type;
+extern struct type_descr desktop_type;
+extern struct type_descr device_type;
+extern struct type_descr completion_type;
+extern struct type_descr file_type;
+extern struct type_descr mapping_type;
+extern struct type_descr key_type;
+
 #define KEYEDEVENT_WAIT       0x0001
 #define KEYEDEVENT_WAKE       0x0002
 #define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
diff --git a/server/process.c b/server/process.c
index 7da33178f6d..3e795f4bb16 100644
--- a/server/process.c
+++ b/server/process.c
@@ -50,7 +50,7 @@
 #include "user.h"
 #include "security.h"
 
-/* process structure */
+/* process object */
 
 static struct list process_list = LIST_INIT(process_list);
 static int running_processes, user_processes;
@@ -58,10 +58,14 @@ static struct event *shutdown_event;           /* signaled when shutdown starts
 static struct timeout_user *shutdown_timeout;  /* timeout for server shutdown */
 static int shutdown_stage;  /* current stage in the shutdown process */
 
-/* process operations */
+static const WCHAR process_name[] = {'P','r','o','c','e','s','s'};
+
+struct type_descr process_type =
+{
+    { process_name, sizeof(process_name) },   /* name */
+};
 
 static void process_dump( struct object *obj, int verbose );
-static struct object_type *process_get_type( struct object *obj );
 static int process_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int process_map_access( struct object *obj, unsigned int access );
 static struct security_descriptor *process_get_sd( struct object *obj );
@@ -73,8 +77,8 @@ static void terminate_process( struct process *process, struct thread *skip, int
 static const struct object_ops process_ops =
 {
     sizeof(struct process),      /* size */
+    &process_type,               /* type */
     process_dump,                /* dump */
-    process_get_type,            /* get_type */
     add_queue,                   /* add_queue */
     remove_queue,                /* remove_queue */
     process_signaled,            /* signaled */
@@ -124,8 +128,8 @@ static void startup_info_destroy( struct object *obj );
 static const struct object_ops startup_info_ops =
 {
     sizeof(struct startup_info),   /* size */
+    &no_type,                      /* type */
     startup_info_dump,             /* dump */
-    no_get_type,                   /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     startup_info_signaled,         /* signaled */
@@ -147,8 +151,14 @@ static const struct object_ops startup_info_ops =
 
 /* job object */
 
+static const WCHAR job_name[] = {'J','o','b'};
+
+struct type_descr job_type =
+{
+    { job_name, sizeof(job_name) },   /* name */
+};
+
 static void job_dump( struct object *obj, int verbose );
-static struct object_type *job_get_type( struct object *obj );
 static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int job_map_access( struct object *obj, unsigned int access );
 static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
@@ -170,8 +180,8 @@ struct job
 static const struct object_ops job_ops =
 {
     sizeof(struct job),            /* size */
+    &job_type,                     /* type */
     job_dump,                      /* dump */
-    job_get_type,                  /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     job_signaled,                  /* signaled */
@@ -219,13 +229,6 @@ static struct job *get_job_obj( struct process *process, obj_handle_t handle, un
     return (struct job *)get_handle_obj( process, handle, access, &job_ops );
 }
 
-static struct object_type *job_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'J','o','b'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-};
-
 static unsigned int job_map_access( struct object *obj, unsigned int access )
 {
     if (access & GENERIC_READ)    access |= STANDARD_RIGHTS_READ;
@@ -654,13 +657,6 @@ static void process_dump( struct object *obj, int verbose )
     fprintf( stderr, "Process id=%04x handles=%p\n", process->id, process->handles );
 }
 
-static struct object_type *process_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'P','r','o','c','e','s','s'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int process_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct process *process = (struct process *)obj;
diff --git a/server/queue.c b/server/queue.c
index 7e7e6fbdf29..954bd5d5312 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -166,8 +166,8 @@ static void timer_callback( void *private );
 static const struct object_ops msg_queue_ops =
 {
     sizeof(struct msg_queue),  /* size */
+    &no_type,                  /* type */
     msg_queue_dump,            /* dump */
-    no_get_type,               /* get_type */
     msg_queue_add_queue,       /* add_queue */
     msg_queue_remove_queue,    /* remove_queue */
     msg_queue_signaled,        /* signaled */
@@ -203,8 +203,8 @@ static const struct fd_ops msg_queue_fd_ops =
 static const struct object_ops thread_input_ops =
 {
     sizeof(struct thread_input),  /* size */
+    &no_type,                     /* type */
     thread_input_dump,            /* dump */
-    no_get_type,                  /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
diff --git a/server/registry.c b/server/registry.c
index 64aec1d83c9..d9c82630937 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -60,6 +60,13 @@ struct notify
     struct process   *process;  /* process in which the hkey is valid */
 };
 
+static const WCHAR key_name[] = {'K','e','y'};
+
+struct type_descr key_type =
+{
+    { key_name, sizeof(key_name) },   /* name */
+};
+
 /* a registry key */
 struct key
 {
@@ -146,7 +153,6 @@ struct file_load_info
 
 
 static void key_dump( struct object *obj, int verbose );
-static struct object_type *key_get_type( struct object *obj );
 static unsigned int key_map_access( struct object *obj, unsigned int access );
 static struct security_descriptor *key_get_sd( struct object *obj );
 static WCHAR *key_get_full_name( struct object *obj, data_size_t *len );
@@ -156,8 +162,8 @@ static void key_destroy( struct object *obj );
 static const struct object_ops key_ops =
 {
     sizeof(struct key),      /* size */
+    &key_type,               /* type */
     key_dump,                /* dump */
-    key_get_type,            /* get_type */
     no_add_queue,            /* add_queue */
     NULL,                    /* remove_queue */
     NULL,                    /* signaled */
@@ -305,13 +311,6 @@ static void key_dump( struct object *obj, int verbose )
     fprintf( stderr, "\n" );
 }
 
-static struct object_type *key_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'K','e','y'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 /* notify waiter and maybe delete the notification */
 static void do_notification( struct key *key, struct notify *notify, int del )
 {
diff --git a/server/request.c b/server/request.c
index 24cfda26110..835c869216c 100644
--- a/server/request.c
+++ b/server/request.c
@@ -92,8 +92,8 @@ static void master_socket_poll_event( struct fd *fd, int event );
 static const struct object_ops master_socket_ops =
 {
     sizeof(struct master_socket),  /* size */
+    &no_type,                      /* type */
     master_socket_dump,            /* dump */
-    no_get_type,                   /* get_type */
     no_add_queue,                  /* add_queue */
     NULL,                          /* remove_queue */
     NULL,                          /* signaled */
diff --git a/server/semaphore.c b/server/semaphore.c
index cbcf4a4f942..5dcadb12778 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -36,6 +36,13 @@
 #include "request.h"
 #include "security.h"
 
+static const WCHAR semaphore_name[] = {'S','e','m','a','p','h','o','r','e'};
+
+struct type_descr semaphore_type =
+{
+    { semaphore_name, sizeof(semaphore_name) },   /* name */
+};
+
 struct semaphore
 {
     struct object  obj;    /* object header */
@@ -44,7 +51,6 @@ struct semaphore
 };
 
 static void semaphore_dump( struct object *obj, int verbose );
-static struct object_type *semaphore_get_type( struct object *obj );
 static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void semaphore_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int semaphore_map_access( struct object *obj, unsigned int access );
@@ -53,8 +59,8 @@ static int semaphore_signal( struct object *obj, unsigned int access );
 static const struct object_ops semaphore_ops =
 {
     sizeof(struct semaphore),      /* size */
+    &semaphore_type,               /* type */
     semaphore_dump,                /* dump */
-    semaphore_get_type,            /* get_type */
     add_queue,                     /* add_queue */
     remove_queue,                  /* remove_queue */
     semaphore_signaled,            /* signaled */
@@ -127,13 +133,6 @@ static void semaphore_dump( struct object *obj, int verbose )
     fprintf( stderr, "Semaphore count=%d max=%d\n", sem->count, sem->max );
 }
 
-static struct object_type *semaphore_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'S','e','m','a','p','h','o','r','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int semaphore_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct semaphore *sem = (struct semaphore *)obj;
diff --git a/server/serial.c b/server/serial.c
index 30fe6e8380f..68779606055 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -87,8 +87,8 @@ struct serial
 static const struct object_ops serial_ops =
 {
     sizeof(struct serial),        /* size */
+    &file_type,                   /* type */
     serial_dump,                  /* dump */
-    no_get_type,                  /* get_type */
     add_queue,                    /* add_queue */
     remove_queue,                 /* remove_queue */
     default_fd_signaled,          /* signaled */
diff --git a/server/signal.c b/server/signal.c
index 7c2bf2cc154..0746cfc9284 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -62,8 +62,8 @@ static void handler_destroy( struct object *obj );
 static const struct object_ops handler_ops =
 {
     sizeof(struct handler),   /* size */
+    &no_type,                 /* type */
     handler_dump,             /* dump */
-    no_get_type,              /* get_type */
     no_add_queue,             /* add_queue */
     NULL,                     /* remove_queue */
     NULL,                     /* signaled */
diff --git a/server/sock.c b/server/sock.c
index 8c146a0a8f8..a9f32556c29 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -183,8 +183,8 @@ static unsigned int sock_get_error( int err );
 static const struct object_ops sock_ops =
 {
     sizeof(struct sock),          /* size */
+    &file_type,                   /* type */
     sock_dump,                    /* dump */
-    no_get_type,                  /* get_type */
     add_queue,                    /* add_queue */
     remove_queue,                 /* remove_queue */
     sock_signaled,                /* signaled */
@@ -1528,8 +1528,8 @@ struct ifchange
 static const struct object_ops ifchange_ops =
 {
     sizeof(struct ifchange), /* size */
+    &no_type,                /* type */
     ifchange_dump,           /* dump */
-    no_get_type,             /* get_type */
     add_queue,               /* add_queue */
     NULL,                    /* remove_queue */
     NULL,                    /* signaled */
@@ -1739,7 +1739,6 @@ static void sock_release_ifchange( struct sock *sock )
     }
 }
 
-static struct object_type *socket_device_get_type( struct object *obj );
 static void socket_device_dump( struct object *obj, int verbose );
 static struct object *socket_device_lookup_name( struct object *obj, struct unicode_str *name,
                                                  unsigned int attr, struct object *root );
@@ -1749,8 +1748,8 @@ static struct object *socket_device_open_file( struct object *obj, unsigned int
 static const struct object_ops socket_device_ops =
 {
     sizeof(struct object),      /* size */
+    &device_type,               /* type */
     socket_device_dump,         /* dump */
-    socket_device_get_type,     /* get_type */
     no_add_queue,               /* add_queue */
     NULL,                       /* remove_queue */
     NULL,                       /* signaled */
@@ -1770,13 +1769,6 @@ static const struct object_ops socket_device_ops =
     no_destroy                  /* destroy */
 };
 
-static struct object_type *socket_device_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','v','i','c','e'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static void socket_device_dump( struct object *obj, int verbose )
 {
     fputs( "Socket device\n", stderr );
diff --git a/server/symlink.c b/server/symlink.c
index 0b85350e1a5..49edf4347dc 100644
--- a/server/symlink.c
+++ b/server/symlink.c
@@ -38,6 +38,13 @@
 #include "object.h"
 #include "unicode.h"
 
+static const WCHAR symlink_name[] = {'S','y','m','b','o','l','i','c','L','i','n','k'};
+
+struct type_descr symlink_type =
+{
+    { symlink_name, sizeof(symlink_name) },   /* name */
+};
+
 struct symlink
 {
     struct object    obj;       /* object header */
@@ -46,7 +53,6 @@ struct symlink
 };
 
 static void symlink_dump( struct object *obj, int verbose );
-static struct object_type *symlink_get_type( struct object *obj );
 static unsigned int symlink_map_access( struct object *obj, unsigned int access );
 static struct object *symlink_lookup_name( struct object *obj, struct unicode_str *name,
                                            unsigned int attr, struct object *root );
@@ -55,8 +61,8 @@ static void symlink_destroy( struct object *obj );
 static const struct object_ops symlink_ops =
 {
     sizeof(struct symlink),       /* size */
+    &symlink_type,                /* type */
     symlink_dump,                 /* dump */
-    symlink_get_type,             /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -86,13 +92,6 @@ static void symlink_dump( struct object *obj, int verbose )
     fputs( "\"\n", stderr );
 }
 
-static struct object_type *symlink_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'S','y','m','b','o','l','i','c','L','i','n','k'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static struct object *symlink_lookup_name( struct object *obj, struct unicode_str *name,
                                            unsigned int attr, struct object *root )
 {
diff --git a/server/thread.c b/server/thread.c
index b9d78c8c5c6..f29ba92f961 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -105,8 +105,8 @@ static void clear_apc_queue( struct list *queue );
 static const struct object_ops thread_apc_ops =
 {
     sizeof(struct thread_apc),  /* size */
+    &no_type,                   /* type */
     dump_thread_apc,            /* dump */
-    no_get_type,                /* get_type */
     add_queue,                  /* add_queue */
     remove_queue,               /* remove_queue */
     thread_apc_signaled,        /* signaled */
@@ -142,8 +142,8 @@ static int context_signaled( struct object *obj, struct wait_queue_entry *entry
 static const struct object_ops context_ops =
 {
     sizeof(struct context),     /* size */
+    &no_type,                   /* type */
     dump_context,               /* dump */
-    no_get_type,                /* get_type */
     add_queue,                  /* add_queue */
     remove_queue,               /* remove_queue */
     context_signaled,           /* signaled */
@@ -166,8 +166,14 @@ static const struct object_ops context_ops =
 
 /* thread operations */
 
+static const WCHAR thread_name[] = {'T','h','r','e','a','d'};
+
+struct type_descr thread_type =
+{
+    { thread_name, sizeof(thread_name) },   /* name */
+};
+
 static void dump_thread( struct object *obj, int verbose );
-static struct object_type *thread_get_type( struct object *obj );
 static int thread_signaled( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int thread_map_access( struct object *obj, unsigned int access );
 static void thread_poll_event( struct fd *fd, int event );
@@ -177,8 +183,8 @@ static void destroy_thread( struct object *obj );
 static const struct object_ops thread_ops =
 {
     sizeof(struct thread),      /* size */
+    &thread_type,               /* type */
     dump_thread,                /* dump */
-    thread_get_type,            /* get_type */
     add_queue,                  /* add_queue */
     remove_queue,               /* remove_queue */
     thread_signaled,            /* signaled */
@@ -445,13 +451,6 @@ static void dump_thread( struct object *obj, int verbose )
              thread->id, thread->unix_pid, thread->unix_tid, thread->state );
 }
 
-static struct object_type *thread_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'T','h','r','e','a','d'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct thread *mythread = (struct thread *)obj;
diff --git a/server/timer.c b/server/timer.c
index d4e5c56267c..0c50f8616bf 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -37,6 +37,13 @@
 #include "handle.h"
 #include "request.h"
 
+static const WCHAR timer_name[] = {'T','i','m','e','r'};
+
+struct type_descr timer_type =
+{
+    { timer_name, sizeof(timer_name) },   /* name */
+};
+
 struct timer
 {
     struct object        obj;       /* object header */
@@ -51,7 +58,6 @@ struct timer
 };
 
 static void timer_dump( struct object *obj, int verbose );
-static struct object_type *timer_get_type( struct object *obj );
 static int timer_signaled( struct object *obj, struct wait_queue_entry *entry );
 static void timer_satisfied( struct object *obj, struct wait_queue_entry *entry );
 static unsigned int timer_map_access( struct object *obj, unsigned int access );
@@ -60,8 +66,8 @@ static void timer_destroy( struct object *obj );
 static const struct object_ops timer_ops =
 {
     sizeof(struct timer),      /* size */
+    &timer_type,               /* type */
     timer_dump,                /* dump */
-    timer_get_type,            /* get_type */
     add_queue,                 /* add_queue */
     remove_queue,              /* remove_queue */
     timer_signaled,            /* signaled */
@@ -192,13 +198,6 @@ static void timer_dump( struct object *obj, int verbose )
              timer->manual, get_timeout_str(timeout), timer->period );
 }
 
-static struct object_type *timer_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'T','i','m','e','r'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int timer_signaled( struct object *obj, struct wait_queue_entry *entry )
 {
     struct timer *timer = (struct timer *)obj;
diff --git a/server/token.c b/server/token.c
index e471292167b..774950ff5fb 100644
--- a/server/token.c
+++ b/server/token.c
@@ -97,6 +97,13 @@ const PSID security_high_label_sid = (PSID)&high_label_sid;
 
 static luid_t prev_luid_value = { 1000, 0 };
 
+static const WCHAR token_name[] = {'T','o','k','e','n'};
+
+struct type_descr token_type =
+{
+    { token_name, sizeof(token_name) },   /* name */
+};
+
 struct token
 {
     struct object  obj;             /* object header */
@@ -135,15 +142,14 @@ struct group
 };
 
 static void token_dump( struct object *obj, int verbose );
-static struct object_type *token_get_type( struct object *obj );
 static unsigned int token_map_access( struct object *obj, unsigned int access );
 static void token_destroy( struct object *obj );
 
 static const struct object_ops token_ops =
 {
     sizeof(struct token),      /* size */
+    &token_type,               /* type */
     token_dump,                /* dump */
-    token_get_type,            /* get_type */
     no_add_queue,              /* add_queue */
     NULL,                      /* remove_queue */
     NULL,                      /* signaled */
@@ -171,13 +177,6 @@ static void token_dump( struct object *obj, int verbose )
              token->token_id.low_part, token->primary, token->impersonation_level );
 }
 
-static struct object_type *token_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'T','o','k','e','n'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static unsigned int token_map_access( struct object *obj, unsigned int access )
 {
     if (access & GENERIC_READ)    access |= TOKEN_READ;
diff --git a/server/winstation.c b/server/winstation.c
index 95e5c0c7d0d..801496173b2 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -43,24 +43,29 @@
 static struct list winstation_list = LIST_INIT(winstation_list);
 
 static void winstation_dump( struct object *obj, int verbose );
-static struct object_type *winstation_get_type( struct object *obj );
 static int winstation_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static struct object *winstation_lookup_name( struct object *obj, struct unicode_str *name,
                                               unsigned int attr, struct object *root );
 static void winstation_destroy( struct object *obj );
 static unsigned int winstation_map_access( struct object *obj, unsigned int access );
 static void desktop_dump( struct object *obj, int verbose );
-static struct object_type *desktop_get_type( struct object *obj );
 static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent );
 static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
 static void desktop_destroy( struct object *obj );
 static unsigned int desktop_map_access( struct object *obj, unsigned int access );
 
+static const WCHAR winstation_name[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'};
+
+struct type_descr winstation_type =
+{
+    { winstation_name, sizeof(winstation_name) },   /* name */
+};
+
 static const struct object_ops winstation_ops =
 {
     sizeof(struct winstation),    /* size */
+    &winstation_type,             /* type */
     winstation_dump,              /* dump */
-    winstation_get_type,          /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -81,11 +86,18 @@ static const struct object_ops winstation_ops =
 };
 
 
+static const WCHAR desktop_name[] = {'D','e','s','k','t','o','p'};
+
+struct type_descr desktop_type =
+{
+    { desktop_name, sizeof(desktop_name) },   /* name */
+};
+
 static const struct object_ops desktop_ops =
 {
     sizeof(struct desktop),       /* size */
+    &desktop_type,                /* type */
     desktop_dump,                 /* dump */
-    desktop_get_type,             /* get_type */
     no_add_queue,                 /* add_queue */
     NULL,                         /* remove_queue */
     NULL,                         /* signaled */
@@ -142,13 +154,6 @@ static void winstation_dump( struct object *obj, int verbose )
              winstation->flags, winstation->clipboard, winstation->atom_table );
 }
 
-static struct object_type *winstation_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int winstation_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
 {
     return (process->winstation != handle);
@@ -247,13 +252,6 @@ static void desktop_dump( struct object *obj, int verbose )
              desktop->flags, desktop->winstation, desktop->top_window, desktop->global_hooks );
 }
 
-static struct object_type *desktop_get_type( struct object *obj )
-{
-    static const WCHAR name[] = {'D','e','s','k','t','o','p'};
-    static const struct unicode_str str = { name, sizeof(name) };
-    return get_object_type( &str );
-}
-
 static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent )
 {
     struct winstation *winstation = (struct winstation *)parent;
-- 
GitLab