Implemented local atoms in the server.

diff --git a/server/atom.c b/server/atom.c
index c69ae1f..8dd6f67 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -12,8 +12,12 @@
 #include "unicode.h"
 #include "request.h"
 #include "object.h"
+#include "process.h"
 
 #define HASH_SIZE     37
+#define MIN_HASH_SIZE 4
+#define MAX_HASH_SIZE 0x200
+
 #define MAX_ATOM_LEN  255
 #define MAX_ATOMS     0x4000
 
@@ -33,10 +37,10 @@
     int                 count;               /* count of atom handles */
     int                 last;                /* last handle in-use */
     struct atom_entry **handles;             /* atom handles */
-    struct atom_entry  *entries[HASH_SIZE];  /* hash table entries */
+    int                 entries_count;       /* humber of hash entries */
+    struct atom_entry **entries;             /* hash table entries */
 };
 
-
 static void atom_table_dump( struct object *obj, int verbose );
 static void atom_table_destroy( struct object *obj );
 
@@ -72,17 +76,26 @@
 }
 
 /* create an atom table */
-static struct atom_table *create_table(void)
+static struct atom_table *create_table(int entries_count)
 {
     struct atom_table *table;
 
     if ((table = alloc_object( &atom_table_ops, -1 )))
     {
+        if ((entries_count < MIN_HASH_SIZE) ||
+            (entries_count > MAX_HASH_SIZE)) entries_count = HASH_SIZE;
+        table->entries_count = entries_count;
+        if (!(table->entries = malloc( sizeof(*table->entries) * table->entries_count )))
+        {
+            set_error( STATUS_NO_MEMORY );
+            goto fail;
+        }
+        memset( table->entries, 0, sizeof(*table->entries) * table->entries_count );
         table->count = 64;
         table->last  = -1;
-        memset( table->entries, 0, sizeof(table->entries) );
         if ((table->handles = mem_alloc( sizeof(*table->handles) * table->count )))
             return table;
+fail:
         release_object( table );
         table = NULL;
     }
@@ -127,12 +140,12 @@
 }
 
 /* compute the hash code for a string */
-static int atom_hash( const WCHAR *str )
+static int atom_hash( struct atom_table *table, const WCHAR *str )
 {
     int i;
     WCHAR hash = 0;
     for (i = 0; str[i]; i++) hash ^= towupper(str[i]) + i;
-    return hash % HASH_SIZE;
+    return hash % table->entries_count;
 }
 
 /* dump an atom table */
@@ -142,7 +155,8 @@
     struct atom_table *table = (struct atom_table *)obj;
     assert( obj->ops == &atom_table_ops );
 
-    fprintf( stderr, "Atom table size=%d\n", table->last + 1 );
+    fprintf( stderr, "Atom table size=%d entries=%d\n",
+             table->last + 1, table->entries_count );
     if (!verbose) return;
     for (i = 0; i <= table->last; i++)
     {
@@ -160,8 +174,12 @@
     int i;
     struct atom_table *table = (struct atom_table *)obj;
     assert( obj->ops == &atom_table_ops );
-    for (i = 0; i <= table->last; i++) free( table->handles[i] );
-    free( table->handles );
+    if (table->handles)
+    {
+        for (i = 0; i <= table->last; i++) free( table->handles[i] );
+        free( table->handles );
+    }
+    if (table->entries) free( table->entries );
 }
 
 /* find an atom entry in its hash list */
@@ -186,7 +204,7 @@
 static int add_atom( struct atom_table *table, const WCHAR *str )
 {
     struct atom_entry *entry;
-    int hash = atom_hash( str );
+    int hash = atom_hash( table, str );
     int atom = -1;
 
     if (!*str)
@@ -236,7 +254,7 @@
 {
     struct atom_entry *entry;
 
-    if (table && ((entry = find_atom_entry( table, str, atom_hash(str) )))) return entry->atom;
+    if (table && ((entry = find_atom_entry( table, str, atom_hash(table, str) )))) return entry->atom;
     if (!*str) set_error( STATUS_OBJECT_NAME_INVALID );
     else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
     return -1;
@@ -258,25 +276,37 @@
 /* add a global atom */
 DECL_HANDLER(add_atom)
 {
-    if (!global_table) global_table = create_table();
-    if (global_table) req->atom = add_atom( global_table, copy_name( req->name ) );
+    struct atom_table **table_ptr = req->local ? &current->process->atom_table : &global_table;
+
+    if (!*table_ptr) *table_ptr = create_table(0);
+    if (*table_ptr) req->atom = add_atom( *table_ptr, copy_name( req->name ) );
 }
 
 /* delete a global atom */
 DECL_HANDLER(delete_atom)
 {
-    delete_atom( global_table, req->atom );
+    delete_atom( req->local ? current->process->atom_table : global_table,
+                 req->atom );
 }
 
 /* find a global atom */
 DECL_HANDLER(find_atom)
 {
-    req->atom = find_atom( global_table, copy_name( req->name ) );
+    req->atom = find_atom( req->local ? current->process->atom_table : global_table,
+                           copy_name( req->name ) );
 }
 
 /* get global atom name */
 DECL_HANDLER(get_atom_name)
 {
     req->name[0] = 0;
-    req->count = get_atom_name( global_table, req->atom, req->name );
+    req->count = get_atom_name( req->local ? current->process->atom_table : global_table,
+                                req->atom, req->name );
+}
+
+/* init the process atom table */
+DECL_HANDLER(init_atom_table)
+{
+    if (!current->process->atom_table)
+        current->process->atom_table = create_table( req->entries );
 }
diff --git a/server/process.c b/server/process.c
index 987bdd8..e6fba62 100644
--- a/server/process.c
+++ b/server/process.c
@@ -169,6 +169,7 @@
     process->init_event      = NULL;
     process->idle_event      = NULL;
     process->queue           = NULL;
+    process->atom_table      = NULL;
     process->ldt_copy        = NULL;
     process->ldt_flags       = NULL;
     process->exe.next        = NULL;
@@ -288,6 +289,7 @@
     if (process->init_event) release_object( process->init_event );
     if (process->idle_event) release_object( process->idle_event );
     if (process->queue) release_object( process->queue );
+    if (process->atom_table) release_object( process->atom_table );
     if (process->exe.file) release_object( process->exe.file );
 }
 
diff --git a/server/process.h b/server/process.h
index 2b7a699..204fd04 100644
--- a/server/process.h
+++ b/server/process.h
@@ -14,6 +14,7 @@
 #include "object.h"
 
 struct msg_queue;
+struct atom_table;
 
 /* process structures */
 
@@ -49,6 +50,7 @@
     struct event        *init_event;      /* event for init done */
     struct event        *idle_event;      /* event for input idle */
     struct msg_queue    *queue;           /* main message queue */
+    struct atom_table   *atom_table;      /* pointer to local atom table */
     struct process_dll   exe;             /* main exe file */
     void                *ldt_copy;        /* pointer to LDT copy in client addr space */
     void                *ldt_flags;       /* pointer to LDT flags in client addr space */
diff --git a/server/request.h b/server/request.h
index 6e3c943..7876540 100644
--- a/server/request.h
+++ b/server/request.h
@@ -173,6 +173,7 @@
 DECL_HANDLER(delete_atom);
 DECL_HANDLER(find_atom);
 DECL_HANDLER(get_atom_name);
+DECL_HANDLER(init_atom_table);
 DECL_HANDLER(get_msg_queue);
 DECL_HANDLER(wake_queue);
 DECL_HANDLER(wait_input_idle);
@@ -285,6 +286,7 @@
     (req_handler)req_delete_atom,
     (req_handler)req_find_atom,
     (req_handler)req_get_atom_name,
+    (req_handler)req_init_atom_table,
     (req_handler)req_get_msg_queue,
     (req_handler)req_wake_queue,
     (req_handler)req_wait_input_idle,
diff --git a/server/trace.c b/server/trace.c
index 369fed0..dc8dd07 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1297,6 +1297,7 @@
 
 static void dump_add_atom_request( const struct add_atom_request *req )
 {
+    fprintf( stderr, " local=%d,", req->local );
     fprintf( stderr, " name=" );
     dump_unicode_string( req, req->name );
 }
@@ -1308,11 +1309,13 @@
 
 static void dump_delete_atom_request( const struct delete_atom_request *req )
 {
-    fprintf( stderr, " atom=%d", req->atom );
+    fprintf( stderr, " atom=%d,", req->atom );
+    fprintf( stderr, " local=%d", req->local );
 }
 
 static void dump_find_atom_request( const struct find_atom_request *req )
 {
+    fprintf( stderr, " local=%d,", req->local );
     fprintf( stderr, " name=" );
     dump_unicode_string( req, req->name );
 }
@@ -1324,7 +1327,8 @@
 
 static void dump_get_atom_name_request( const struct get_atom_name_request *req )
 {
-    fprintf( stderr, " atom=%d", req->atom );
+    fprintf( stderr, " atom=%d,", req->atom );
+    fprintf( stderr, " local=%d", req->local );
 }
 
 static void dump_get_atom_name_reply( const struct get_atom_name_request *req )
@@ -1334,6 +1338,11 @@
     dump_unicode_string( req, req->name );
 }
 
+static void dump_init_atom_table_request( const struct init_atom_table_request *req )
+{
+    fprintf( stderr, " entries=%d", req->entries );
+}
+
 static void dump_get_msg_queue_request( const struct get_msg_queue_request *req )
 {
 }
@@ -1464,6 +1473,7 @@
     (dump_func)dump_delete_atom_request,
     (dump_func)dump_find_atom_request,
     (dump_func)dump_get_atom_name_request,
+    (dump_func)dump_init_atom_table_request,
     (dump_func)dump_get_msg_queue_request,
     (dump_func)dump_wake_queue_request,
     (dump_func)dump_wait_input_idle_request,
@@ -1573,6 +1583,7 @@
     (dump_func)0,
     (dump_func)dump_find_atom_reply,
     (dump_func)dump_get_atom_name_reply,
+    (dump_func)0,
     (dump_func)dump_get_msg_queue_reply,
     (dump_func)0,
     (dump_func)dump_wait_input_idle_reply,
@@ -1682,6 +1693,7 @@
     "delete_atom",
     "find_atom",
     "get_atom_name",
+    "init_atom_table",
     "get_msg_queue",
     "wake_queue",
     "wait_input_idle",