diff --git a/include/server.h b/include/server.h
index ee1afd848f5a1b08f2582d9fd956a73b5713471b..eae797135eebc2a7cc4d21235b4c4fdd54f2b71c 100644
--- a/include/server.h
+++ b/include/server.h
@@ -1117,38 +1117,49 @@ struct get_selector_entry_request
 };
 
 
-/* Add a global atom */
+/* Add an atom */
 struct add_atom_request
 {
+    IN  int           local;       /* is atom in local process table? */
     OUT int           atom;        /* resulting atom */
     IN  WCHAR         name[1];     /* atom name */
 };
 
 
-/* Delete a global atom */
+/* Delete an atom */
 struct delete_atom_request
 {
     IN  int           atom;        /* atom handle */
+    IN  int           local;       /* is atom in local process table? */
 };
 
 
-/* Find a global atom */
+/* Find an atom */
 struct find_atom_request
 {
+    IN  int          local;        /* is atom in local process table? */
     OUT int          atom;         /* atom handle */
     IN  WCHAR        name[1];      /* atom name */
 };
 
 
-/* Get a global atom name */
+/* Get an atom name */
 struct get_atom_name_request
 {
     IN  int          atom;         /* atom handle */
+    IN  int          local;        /* is atom in local process table? */
     OUT int          count;        /* atom lock count */
     OUT WCHAR        name[1];      /* atom name */
 };
 
 
+/* Init the process atom table */
+struct init_atom_table_request
+{
+    IN  int          entries;      /* number of entries */
+};
+
+
 /* Get the message queue of the current thread */
 struct get_msg_queue_request
 {
@@ -1279,13 +1290,14 @@ enum request
     REQ_DELETE_ATOM,
     REQ_FIND_ATOM,
     REQ_GET_ATOM_NAME,
+    REQ_INIT_ATOM_TABLE,
     REQ_GET_MSG_QUEUE,
     REQ_WAKE_QUEUE,
     REQ_WAIT_INPUT_IDLE,
     REQ_NB_REQUESTS
 };
 
-#define SERVER_PROTOCOL_VERSION 13
+#define SERVER_PROTOCOL_VERSION 14
 
 /* ### make_requests end ### */
 /* Everything above this line is generated automatically by tools/make_requests */
diff --git a/memory/atom.c b/memory/atom.c
index 36db711c52f8e4f67a74788d6c86612c5856816f..5ff65442bc0e4339731f760b46178b6f0a9d4568 100644
--- a/memory/atom.c
+++ b/memory/atom.c
@@ -212,7 +212,6 @@ WORD WINAPI InitAtomTable16( WORD entries )
     return handle;
 }
 
-
 /***********************************************************************
  *           GetAtomHandle   (KERNEL.73)
  */
@@ -400,122 +399,74 @@ UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
     return len;
 }
 
-
 /***********************************************************************
- *           AddAtomA   (KERNEL32.0)
- * Adds a string to the atom table and returns the atom identifying the
- * string.
- *
- * RETURNS
- *	Atom: Success
- *	0: Failure
+ *           InitAtomTable   (KERNEL32.471)
  */
-ATOM WINAPI AddAtomA(
-            LPCSTR str /* [in] Pointer to string to add */
-) {
-    return GlobalAddAtomA( str );  /* FIXME */
+BOOL WINAPI InitAtomTable( DWORD entries )
+{
+    struct init_atom_table_request *req = get_req_buffer();
+    req->entries = entries;
+    return !server_call( REQ_INIT_ATOM_TABLE );
 }
 
 
-/***********************************************************************
- *           AddAtomW   (KERNEL32.1)
- * See AddAtomA
- */
-ATOM WINAPI AddAtomW( LPCWSTR str )
+static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
 {
-    return GlobalAddAtomW( str );  /* FIXME */
+    ATOM atom = 0;
+    if (!ATOM_IsIntAtomA( str, &atom ))
+    {
+        struct add_atom_request *req = get_req_buffer();
+        server_strcpyAtoW( req->name, str );
+	req->local = local;
+        if (!server_call( REQ_ADD_ATOM )) atom = req->atom + MIN_STR_ATOM;
+    }
+    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
+    return atom;
 }
 
 
 /***********************************************************************
- *           DeleteAtom   (KERNEL32.69)
- * Decrements the reference count of a string atom.  If count becomes
- * zero, the string associated with the atom is removed from the table.
+ *           GlobalAddAtomA   (USER.268) (KERNEL32.313)
  *
- * RETURNS
- *	0: Success
- *	Atom: Failure
- */
-ATOM WINAPI DeleteAtom(
-            ATOM atom /* [in] Atom to delete */
-) {
-    return GlobalDeleteAtom( atom );  /* FIXME */
-}
-
-
-/***********************************************************************
- *           FindAtomA   (KERNEL32.117)
- * Searches the local atom table for the string and returns the atom
- * associated with that string.
+ * Adds a character string to the global atom table and returns a unique
+ * value identifying the string.
  *
  * RETURNS
  *	Atom: Success
  *	0: Failure
  */
-ATOM WINAPI FindAtomA(
-            LPCSTR str /* [in] Pointer to string to find */
-) {
-    return GlobalFindAtomA( str );  /* FIXME */
-}
-
-
-/***********************************************************************
- *           FindAtomW   (KERNEL32.118)
- * See FindAtomA
- */
-ATOM WINAPI FindAtomW( LPCWSTR str )
+ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
 {
-    return GlobalFindAtomW( str );  /* FIXME */
+    return ATOM_AddAtomA( str, FALSE );
 }
 
 
 /***********************************************************************
- *           GetAtomNameA   (KERNEL32.149)
- * Retrieves a copy of the string associated with the atom.
+ *           AddAtomA   (KERNEL32.0)
+ * Adds a string to the atom table and returns the atom identifying the
+ * string.
  *
  * RETURNS
- *	Length of string: Success
+ *	Atom: Success
  *	0: Failure
  */
-UINT WINAPI GetAtomNameA(
-              ATOM atom,    /* [in]  Atom */
-              LPSTR buffer, /* [out] Pointer to string for atom string */
-              INT count   /* [in]  Size of buffer */
-) {
-    return GlobalGetAtomNameA( atom, buffer, count );  /* FIXME */
-}
-
-
-/***********************************************************************
- *           GetAtomNameW   (KERNEL32.150)
- * See GetAtomNameA
- */
-UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
+ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
 {
-    return GlobalGetAtomNameW( atom, buffer, count );  /* FIXME */
+    return ATOM_AddAtomA( str, TRUE );
 }
 
 
-/***********************************************************************
- *           GlobalAddAtomA   (USER.268) (KERNEL32.313)
- *
- * Adds a character string to the global atom table and returns a unique
- * value identifying the string.
- *
- * RETURNS
- *	Atom: Success
- *	0: Failure
- */
-ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
+static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
 {
     ATOM atom = 0;
-    if (!ATOM_IsIntAtomA( str, &atom ))
+    if (!ATOM_IsIntAtomW( str, &atom ))
     {
         struct add_atom_request *req = get_req_buffer();
-        server_strcpyAtoW( req->name, str );
+        server_strcpyW( req->name, str );
+	req->local = local;
         if (!server_call( REQ_ADD_ATOM )) atom = req->atom + MIN_STR_ATOM;
     }
-    TRACE( "%s -> %x\n", debugres_a(str), atom );
+    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
     return atom;
 }
 
@@ -525,14 +476,30 @@ ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
  */
 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
 {
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomW( str, &atom ))
+    return ATOM_AddAtomW( str, FALSE );
+}
+
+
+/***********************************************************************
+ *           AddAtomW   (KERNEL32.1)
+ */
+ATOM WINAPI AddAtomW( LPCWSTR str )
+{
+    return ATOM_AddAtomW( str, TRUE );
+}
+
+
+static ATOM ATOM_DeleteAtom( ATOM atom,  BOOL local)
+{
+    TRACE( "(%s) %x\n", local ? "local" : "glbal", atom );
+    if (atom < MIN_STR_ATOM) atom = 0;
+    else
     {
-        struct add_atom_request *req = get_req_buffer();
-        server_strcpyW( req->name, str );
-        if (!server_call( REQ_ADD_ATOM )) atom = req->atom + MIN_STR_ATOM;
+        struct delete_atom_request *req = get_req_buffer();
+        req->atom = atom - MIN_STR_ATOM;
+	req->local = local;
+        if (!server_call( REQ_DELETE_ATOM )) atom = 0;
     }
-    TRACE( "%s -> %x\n", debugres_w(str), atom );
     return atom;
 }
 
@@ -548,14 +515,36 @@ ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
  */
 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
 {
-    TRACE( "%x\n", atom );
-    if (atom < MIN_STR_ATOM) atom = 0;
-    else
+    return ATOM_DeleteAtom( atom, FALSE);
+}
+
+
+/***********************************************************************
+ *           DeleteAtom   (KERNEL32.69)
+ * Decrements the reference count of a string atom.  If count becomes
+ * zero, the string associated with the atom is removed from the table.
+ *
+ * RETURNS
+ *	0: Success
+ *	Atom: Failure
+ */
+ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
+{
+    return ATOM_DeleteAtom( atom, TRUE ); 
+}
+
+
+static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
+{
+    ATOM atom = 0;
+    if (!ATOM_IsIntAtomA( str, &atom ))
     {
-        struct delete_atom_request *req = get_req_buffer();
-        req->atom = atom - MIN_STR_ATOM;
-        if (!server_call( REQ_DELETE_ATOM )) atom = 0;
+        struct find_atom_request *req = get_req_buffer();
+        server_strcpyAtoW( req->name, str );
+	req->local = local;
+        if (!server_call( REQ_FIND_ATOM )) atom = req->atom + MIN_STR_ATOM;
     }
+    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
     return atom;
 }
 
@@ -571,15 +560,36 @@ ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
  *	0: Failure
  */
 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
+{
+    return ATOM_FindAtomA( str, FALSE );
+}
+
+/***********************************************************************
+ *           FindAtomA   (KERNEL32.117)
+ * Searches the local atom table for the string and returns the atom
+ * associated with that string.
+ *
+ * RETURNS
+ *	Atom: Success
+ *	0: Failure
+ */
+ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
+{
+    return ATOM_FindAtomA( str, TRUE );
+}
+
+
+static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
 {
     ATOM atom = 0;
-    if (!ATOM_IsIntAtomA( str, &atom ))
+    if (!ATOM_IsIntAtomW( str, &atom ))
     {
         struct find_atom_request *req = get_req_buffer();
-        server_strcpyAtoW( req->name, str );
+        server_strcpyW( req->name, str );
+	req->local = local;
         if (!server_call( REQ_FIND_ATOM )) atom = req->atom + MIN_STR_ATOM;
     }
-    TRACE( "%s -> %x\n", debugres_a(str), atom );
+    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
     return atom;
 }
 
@@ -589,31 +599,20 @@ ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for
  */
 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
 {
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomW( str, &atom ))
-    {
-        struct find_atom_request *req = get_req_buffer();
-        server_strcpyW( req->name, str );
-        if (!server_call( REQ_FIND_ATOM )) atom = req->atom + MIN_STR_ATOM;
-    }
-    TRACE( "%s -> %x\n", debugres_w(str), atom );
-    return atom;
+    return ATOM_FindAtomW( str, FALSE );
 }
 
 
 /***********************************************************************
- *           GlobalGetAtomNameA   (USER.271) (KERNEL32.323)
- *
- * Retrieves a copy of the string associated with an atom.
- *
- * RETURNS
- *	Length of string in characters: Success
- *	0: Failure
+ *           FindAtomW   (KERNEL32.118)
  */
-UINT WINAPI GlobalGetAtomNameA(
-              ATOM atom,    /* [in]  Atom identifier */
-              LPSTR buffer, /* [out] Pointer to buffer for atom string */
-              INT count )   /* [in]  Size of buffer */
+ATOM WINAPI FindAtomW( LPCWSTR str )
+{
+    return ATOM_FindAtomW( str, TRUE );
+}
+
+
+static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
 {
     INT len;
     if (atom < MIN_STR_ATOM)
@@ -631,6 +630,7 @@ UINT WINAPI GlobalGetAtomNameA(
     {
         struct get_atom_name_request *req = get_req_buffer();
         req->atom = atom - MIN_STR_ATOM;
+	req->local = local;
         if (server_call( REQ_GET_ATOM_NAME )) return 0;
         lstrcpynWtoA( buffer, req->name, count );
         len = lstrlenW( req->name );
@@ -640,15 +640,47 @@ UINT WINAPI GlobalGetAtomNameA(
         SetLastError( ERROR_MORE_DATA );
         return 0;
     }
-    TRACE( "%x -> %s\n", atom, debugstr_a(buffer) );
+    TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
     return len;
 }
 
 
 /***********************************************************************
- *           GlobalGetAtomNameW   (KERNEL32.324)
+ *           GlobalGetAtomNameA   (USER.271) (KERNEL32.323)
+ *
+ * Retrieves a copy of the string associated with an atom.
+ *
+ * RETURNS
+ *	Length of string in characters: Success
+ *	0: Failure
  */
-UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
+UINT WINAPI GlobalGetAtomNameA(
+              ATOM atom,    /* [in]  Atom identifier */
+              LPSTR buffer, /* [out] Pointer to buffer for atom string */
+              INT count )   /* [in]  Size of buffer */
+{
+    return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
+}
+
+
+/***********************************************************************
+ *           GetAtomNameA   (KERNEL32.149)
+ * Retrieves a copy of the string associated with the atom.
+ *
+ * RETURNS
+ *	Length of string: Success
+ *	0: Failure
+ */
+UINT WINAPI GetAtomNameA(
+              ATOM atom,    /* [in]  Atom */
+              LPSTR buffer, /* [out] Pointer to string for atom string */
+              INT count)    /* [in]  Size of buffer */
+{
+    return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
+}
+
+
+static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
 {
     INT len;
     if (atom < MIN_STR_ATOM)
@@ -666,6 +698,7 @@ UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
     {
         struct get_atom_name_request *req = get_req_buffer();
         req->atom = atom - MIN_STR_ATOM;
+	req->local = local;
         if (server_call( REQ_GET_ATOM_NAME )) return 0;
         lstrcpynW( buffer, req->name, count );
         len = lstrlenW( req->name );
@@ -675,6 +708,24 @@ UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
         SetLastError( ERROR_MORE_DATA );
         return 0;
     }
-    TRACE( "%x -> %s\n", atom, debugstr_w(buffer) );
+    TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
     return len;
 }
+
+
+/***********************************************************************
+ *           GlobalGetAtomNameW   (KERNEL32.324)
+ */
+UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
+{
+    return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
+}
+
+
+/***********************************************************************
+ *           GetAtomNameW   (KERNEL32.150)
+ */
+UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
+{
+    return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
+}
diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index 41c8662560b94fd4097b483c1ce6feed8d61107c..58599cf787786196f44686038b9ccb35b6944525 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -486,7 +486,7 @@ import  ntdll.dll
 468 stdcall HeapUnlock(long) HeapUnlock
 469 stdcall HeapValidate(long long ptr) HeapValidate
 470 stdcall HeapWalk(long ptr) HeapWalk
-471 stub InitAtomTable
+471 stdcall InitAtomTable(long) InitAtomTable
 472 stdcall InitializeCriticalSection(ptr) InitializeCriticalSection
 473 stdcall InterlockedDecrement(ptr) InterlockedDecrement
 474 stdcall InterlockedExchange(ptr long) InterlockedExchange
diff --git a/server/atom.c b/server/atom.c
index c69ae1f42a036689649475abd63c8cc0bff13272..8dd6f67e32d4b1cf973ae6a3b055aceda1afc9c7 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 @@ struct atom_table
     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 @@ static const WCHAR *copy_name( const WCHAR *str )
 }
 
 /* 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 @@ static int add_atom_entry( struct atom_table *table, struct atom_entry *entry )
 }
 
 /* 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 @@ static void atom_table_dump( struct object *obj, int verbose )
     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 @@ static void atom_table_destroy( struct object *obj )
     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 @@ void close_atom_table(void)
 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 @@ static int find_atom( struct atom_table *table, const WCHAR *str )
 {
     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 @@ static int get_atom_name( struct atom_table *table, int atom, WCHAR *str )
 /* 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 987bdd85c36e1e4c8fa60df54e8bb9009192086a..e6fba62e80e9e227e8ce7070d192d13068e523b5 100644
--- a/server/process.c
+++ b/server/process.c
@@ -169,6 +169,7 @@ struct thread *create_process( int fd )
     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 @@ static void process_destroy( struct object *obj )
     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 2b7a699d39fe783e1a3730cc9586223d36da1924..204fd04f44f553b5a591da2614614b90999c637e 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 process
     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 6e3c94327a3f76fa7e7e38dc41f999b356e92318..7876540f18a0d2a4e16a1111dc2f7f2556e365e8 100644
--- a/server/request.h
+++ b/server/request.h
@@ -173,6 +173,7 @@ DECL_HANDLER(add_atom);
 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 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (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 369fed0110a72fee15f7afde7fcad00edef0dbee..dc8dd0722d56cb482c1336eb681ad86d20579cb1 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1297,6 +1297,7 @@ static void dump_get_selector_entry_reply( const struct get_selector_entry_reque
 
 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_add_atom_reply( const struct add_atom_request *req )
 
 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_find_atom_reply( const struct find_atom_request *req )
 
 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 @@ static void dump_get_atom_name_reply( const struct get_atom_name_request *req )
     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 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (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 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (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 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "delete_atom",
     "find_atom",
     "get_atom_name",
+    "init_atom_table",
     "get_msg_queue",
     "wake_queue",
     "wait_input_idle",