- changed ATOM support in wineserver to match NTDLL needs
- adapted accordingly kernel32 atom support
diff --git a/server/atom.c b/server/atom.c
index 341cf6b..c4de578 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -31,6 +31,7 @@
#include "request.h"
#include "object.h"
#include "process.h"
+#include "handle.h"
#define HASH_SIZE 37
#define MIN_HASH_SIZE 4
@@ -45,6 +46,7 @@
struct atom_entry *next; /* hash table list */
struct atom_entry *prev; /* hash table list */
int count; /* reference count */
+ int pinned; /* whether the atom is pinned or not */
int hash; /* string hash */
atom_t atom; /* atom handle */
WCHAR str[1]; /* atom string */
@@ -185,8 +187,9 @@
{
struct atom_entry *entry = table->handles[i];
if (!entry) continue;
- fprintf( stderr, " %04x: ref=%d hash=%d \"", entry->atom, entry->count, entry->hash );
- dump_strW( entry->str, strlenW(entry->str), stderr, "\"\"");
+ fprintf( stderr, " %04x: ref=%d pinned=%c hash=%d \"",
+ entry->atom, entry->count, entry->pinned ? 'Y' : 'N', entry->hash );
+ dump_strW( entry->str, strlenW( entry->str ), stderr, "\"\"");
fprintf( stderr, "\"\n" );
}
}
@@ -249,6 +252,7 @@
if ((entry->next = table->entries[hash])) entry->next->prev = entry;
table->entries[hash] = entry;
entry->count = 1;
+ entry->pinned = 0;
entry->hash = hash;
strcpyW( entry->str, str );
}
@@ -302,53 +306,128 @@
if (atom >= MIN_STR_ATOM) delete_atom( global_table, atom );
}
+static struct atom_table* get_table( obj_handle_t h )
+{
+ struct atom_table *table;
+
+ if (h)
+ {
+ table = (struct atom_table*)get_handle_obj( current->process, h,
+ 0, &atom_table_ops );
+ }
+ else
+ {
+ if (!global_table && !(global_table = create_table( HASH_SIZE )))
+ return NULL;
+ table = (struct atom_table*)grab_object( global_table );
+ }
+ return table;
+}
+
/* add a global atom */
DECL_HANDLER(add_atom)
{
- struct atom_table **table_ptr = req->local ? ¤t->process->atom_table : &global_table;
-
- if (!*table_ptr) *table_ptr = create_table(0);
- if (*table_ptr)
+ struct atom_table *table = get_table( req->table );
+ if (table)
{
const WCHAR *name = copy_request_name();
- if (name) reply->atom = add_atom( *table_ptr, name );
+ if (name) reply->atom = add_atom( table, name );
+ release_object( table );
}
}
/* delete a global atom */
DECL_HANDLER(delete_atom)
{
- delete_atom( req->local ? current->process->atom_table : global_table, req->atom );
+ struct atom_table *table = get_table( req->table );
+ if (table)
+ {
+ delete_atom( table, req->atom );
+ release_object( table );
+ }
}
/* find a global atom */
DECL_HANDLER(find_atom)
{
- const WCHAR *name = copy_request_name();
- if (name)
- reply->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
-}
-
-/* get global atom name */
-DECL_HANDLER(get_atom_name)
-{
- struct atom_entry *entry;
- size_t len = 0;
-
- reply->count = -1;
- if ((entry = get_atom_entry( req->local ? current->process->atom_table : global_table,
- req->atom )))
+ struct atom_table *table = get_table( req->table );
+ if (table)
{
- reply->count = entry->count;
- len = strlenW( entry->str ) * sizeof(WCHAR);
- if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
- else set_error( STATUS_BUFFER_OVERFLOW );
+ const WCHAR *name = copy_request_name();
+ if (name)
+ reply->atom = find_atom( table, name );
+ release_object( table );
}
}
-/* init the process atom table */
+/* get global atom name */
+DECL_HANDLER(get_atom_information)
+{
+ struct atom_table *table = get_table( req->table );
+ if (table)
+ {
+ struct atom_entry *entry;
+
+ if ((entry = get_atom_entry( table, req->atom )))
+ {
+ size_t len = strlenW( entry->str ) * sizeof(WCHAR);
+ if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
+ else set_error( STATUS_BUFFER_OVERFLOW );
+ reply->count = entry->count;
+ reply->pinned = entry->pinned;
+ }
+ else reply->count = -1;
+ release_object( table );
+ }
+}
+
+/* set global atom name */
+DECL_HANDLER(set_atom_information)
+{
+ struct atom_table *table = get_table( req->table );
+ if (table)
+ {
+ struct atom_entry *entry;
+
+ if ((entry = get_atom_entry( table, req->atom )))
+ {
+ if (req->pinned) entry->pinned = 1;
+ }
+ release_object( table );
+ }
+}
+
+/* init a (local) atom table */
DECL_HANDLER(init_atom_table)
{
- if (!current->process->atom_table)
- current->process->atom_table = create_table( req->entries );
+ struct atom_table* table;
+
+ table = create_table( req->entries );
+ reply->table = alloc_handle( current->process, table, 0, FALSE);
+ release_object( table );
+}
+
+/* set global atom name */
+DECL_HANDLER(empty_atom_table)
+{
+ struct atom_table *table = get_table( req->table );
+ if (table)
+ {
+ int i;
+ struct atom_entry *entry;
+
+ for (i = 0; i <= table->last; i++)
+ {
+ entry = table->handles[i];
+ if (entry && (!entry->pinned || req->if_pinned))
+ {
+ if (entry->next) entry->next->prev = entry->prev;
+ if (entry->prev) entry->prev->next = entry->next;
+ else table->entries[entry->hash] = entry->next;
+ table->handles[i] = NULL;
+ free( entry );
+ }
+ }
+ release_object( table );
+ }
}
diff --git a/server/process.c b/server/process.c
index d2f8c89..24a34c8 100644
--- a/server/process.c
+++ b/server/process.c
@@ -278,7 +278,6 @@
process->startup_info = NULL;
process->idle_event = NULL;
process->queue = NULL;
- process->atom_table = NULL;
process->peb = NULL;
process->ldt_copy = NULL;
process->exe.file = NULL;
@@ -422,7 +421,6 @@
list_remove( &process->entry );
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 );
if (process->exe.filename) free( process->exe.filename );
if (process->id) free_ptid( process->id );
diff --git a/server/process.h b/server/process.h
index 8c90117..d203ebd 100644
--- a/server/process.h
+++ b/server/process.h
@@ -72,7 +72,6 @@
struct startup_info *startup_info; /* startup info while init is in progress */
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 token *token; /* security token associated with this process */
struct process_dll exe; /* main exe file */
struct list dlls; /* list of loaded dlls */
diff --git a/server/protocol.def b/server/protocol.def
index 97b51bf..c21c8f5 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1418,7 +1418,7 @@
/* Add an atom */
@REQ(add_atom)
- int local; /* is atom in local process table? */
+ obj_handle_t table; /* which table to add atom to */
VARARG(name,unicode_str); /* atom name */
@REPLY
atom_t atom; /* resulting atom */
@@ -1427,33 +1427,51 @@
/* Delete an atom */
@REQ(delete_atom)
+ obj_handle_t table; /* which table to delete atom from */
atom_t atom; /* atom handle */
- int local; /* is atom in local process table? */
@END
/* Find an atom */
@REQ(find_atom)
- int local; /* is atom in local process table? */
+ obj_handle_t table; /* which table to find atom from */
VARARG(name,unicode_str); /* atom name */
@REPLY
atom_t atom; /* atom handle */
@END
-/* Get an atom name */
-@REQ(get_atom_name)
+/* Get information about an atom */
+@REQ(get_atom_information)
+ obj_handle_t table; /* which table to find atom from */
atom_t atom; /* atom handle */
- int local; /* is atom in local process table? */
@REPLY
int count; /* atom lock count */
+ int pinned; /* whether the atom has been pinned */
VARARG(name,unicode_str); /* atom name */
@END
-/* Init the process atom table */
+/* Set information about an atom */
+@REQ(set_atom_information)
+ obj_handle_t table; /* which table to find atom from */
+ atom_t atom; /* atom handle */
+ int pinned; /* whether to bump atom information */
+@END
+
+
+/* Empty an atom table */
+@REQ(empty_atom_table)
+ obj_handle_t table; /* which table to find atom from */
+ int if_pinned; /* whether to delete pinned atoms */
+@END
+
+
+/* Init an atom table */
@REQ(init_atom_table)
- int entries; /* number of entries */
+ int entries; /* number of entries (only for local) */
+@REPLY
+ obj_handle_t table; /* handle to the atom table */
@END
diff --git a/server/request.h b/server/request.h
index 8a6ac16..29b53a0 100644
--- a/server/request.h
+++ b/server/request.h
@@ -216,7 +216,9 @@
DECL_HANDLER(add_atom);
DECL_HANDLER(delete_atom);
DECL_HANDLER(find_atom);
-DECL_HANDLER(get_atom_name);
+DECL_HANDLER(get_atom_information);
+DECL_HANDLER(set_atom_information);
+DECL_HANDLER(empty_atom_table);
DECL_HANDLER(init_atom_table);
DECL_HANDLER(get_msg_queue);
DECL_HANDLER(set_queue_mask);
@@ -412,7 +414,9 @@
(req_handler)req_add_atom,
(req_handler)req_delete_atom,
(req_handler)req_find_atom,
- (req_handler)req_get_atom_name,
+ (req_handler)req_get_atom_information,
+ (req_handler)req_set_atom_information,
+ (req_handler)req_empty_atom_table,
(req_handler)req_init_atom_table,
(req_handler)req_get_msg_queue,
(req_handler)req_set_queue_mask,
diff --git a/server/trace.c b/server/trace.c
index f79e8e3..65ee3e9 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1758,7 +1758,7 @@
static void dump_add_atom_request( const struct add_atom_request *req )
{
- fprintf( stderr, " local=%d,", req->local );
+ fprintf( stderr, " table=%p,", req->table );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size );
}
@@ -1770,13 +1770,13 @@
static void dump_delete_atom_request( const struct delete_atom_request *req )
{
- fprintf( stderr, " atom=%04x,", req->atom );
- fprintf( stderr, " local=%d", req->local );
+ fprintf( stderr, " table=%p,", req->table );
+ fprintf( stderr, " atom=%04x", req->atom );
}
static void dump_find_atom_request( const struct find_atom_request *req )
{
- fprintf( stderr, " local=%d,", req->local );
+ fprintf( stderr, " table=%p,", req->table );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size );
}
@@ -1786,24 +1786,43 @@
fprintf( stderr, " atom=%04x", req->atom );
}
-static void dump_get_atom_name_request( const struct get_atom_name_request *req )
+static void dump_get_atom_information_request( const struct get_atom_information_request *req )
{
- fprintf( stderr, " atom=%04x,", req->atom );
- fprintf( stderr, " local=%d", req->local );
+ fprintf( stderr, " table=%p,", req->table );
+ fprintf( stderr, " atom=%04x", req->atom );
}
-static void dump_get_atom_name_reply( const struct get_atom_name_reply *req )
+static void dump_get_atom_information_reply( const struct get_atom_information_reply *req )
{
fprintf( stderr, " count=%d,", req->count );
+ fprintf( stderr, " pinned=%d,", req->pinned );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size );
}
+static void dump_set_atom_information_request( const struct set_atom_information_request *req )
+{
+ fprintf( stderr, " table=%p,", req->table );
+ fprintf( stderr, " atom=%04x,", req->atom );
+ fprintf( stderr, " pinned=%d", req->pinned );
+}
+
+static void dump_empty_atom_table_request( const struct empty_atom_table_request *req )
+{
+ fprintf( stderr, " table=%p,", req->table );
+ fprintf( stderr, " if_pinned=%d", req->if_pinned );
+}
+
static void dump_init_atom_table_request( const struct init_atom_table_request *req )
{
fprintf( stderr, " entries=%d", req->entries );
}
+static void dump_init_atom_table_reply( const struct init_atom_table_reply *req )
+{
+ fprintf( stderr, " table=%p", req->table );
+}
+
static void dump_get_msg_queue_request( const struct get_msg_queue_request *req )
{
}
@@ -2885,7 +2904,9 @@
(dump_func)dump_add_atom_request,
(dump_func)dump_delete_atom_request,
(dump_func)dump_find_atom_request,
- (dump_func)dump_get_atom_name_request,
+ (dump_func)dump_get_atom_information_request,
+ (dump_func)dump_set_atom_information_request,
+ (dump_func)dump_empty_atom_table_request,
(dump_func)dump_init_atom_table_request,
(dump_func)dump_get_msg_queue_request,
(dump_func)dump_set_queue_mask_request,
@@ -3078,8 +3099,10 @@
(dump_func)dump_add_atom_reply,
(dump_func)0,
(dump_func)dump_find_atom_reply,
- (dump_func)dump_get_atom_name_reply,
+ (dump_func)dump_get_atom_information_reply,
(dump_func)0,
+ (dump_func)0,
+ (dump_func)dump_init_atom_table_reply,
(dump_func)dump_get_msg_queue_reply,
(dump_func)dump_set_queue_mask_reply,
(dump_func)dump_get_queue_status_reply,
@@ -3271,7 +3294,9 @@
"add_atom",
"delete_atom",
"find_atom",
- "get_atom_name",
+ "get_atom_information",
+ "set_atom_information",
+ "empty_atom_table",
"init_atom_table",
"get_msg_queue",
"set_queue_mask",