From: Rémi Bernon rbernon@codeweavers.com
--- server/atom.c | 15 +++++++++++---- server/directory.c | 6 +++++- server/object.h | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/server/atom.c b/server/atom.c index 15c55d49813..1ff178bc3f6 100644 --- a/server/atom.c +++ b/server/atom.c @@ -97,8 +97,7 @@ static const struct object_ops atom_table_ops =
static struct atom_table *global_table;
-/* create an atom table */ -static struct atom_table *create_table(void) +struct object *create_atom_table(void) { struct atom_table *table;
@@ -107,7 +106,15 @@ static struct atom_table *create_table(void) memset( table->entries, 0, sizeof(*table->entries) * ARRAY_SIZE(table->entries) ); table->count = 1; /* atom 0xc000 is reserved */
- return table; + return &table->obj; +} + +void set_global_atom_table( struct object *obj ) +{ + assert( obj->ops == &atom_table_ops ); + global_table = (struct atom_table *)obj; + make_object_permanent( obj ); + grab_object( obj ); }
/* retrieve an entry pointer from its atom */ @@ -269,7 +276,7 @@ static struct atom_table *get_global_table( struct winstation *winstation, int c { if (create) { - table = create_table(); + table = (struct atom_table *)create_atom_table(); if (winstation) winstation->atom_table = table; else { diff --git a/server/directory.c b/server/directory.c index c8dc3d1901d..e2011a7e21e 100644 --- a/server/directory.c +++ b/server/directory.c @@ -449,7 +449,7 @@ void init_directories( struct fd *intl_fd ) static const struct unicode_str session_str = {sessionW, sizeof(sessionW)};
struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel, *dir_nls; - struct object *named_pipe_device, *mailslot_device, *null_device; + struct object *named_pipe_device, *mailslot_device, *null_device, *atom_table; struct mapping *session_mapping; unsigned int i;
@@ -502,6 +502,10 @@ void init_directories( struct fd *intl_fd ) set_session_mapping( session_mapping ); release_object( session_mapping );
+ atom_table = create_atom_table(); + set_global_atom_table( atom_table ); + release_object( atom_table ); + release_object( named_pipe_device ); release_object( mailslot_device ); release_object( null_device ); diff --git a/server/object.h b/server/object.h index 07f6ff7b16f..7861b3e6c40 100644 --- a/server/object.h +++ b/server/object.h @@ -284,6 +284,9 @@ extern void init_signals(void);
/* atom functions */
+extern struct object *create_atom_table(void); +extern void set_global_atom_table( struct object *obj ); + extern atom_t add_global_atom( struct winstation *winstation, const struct unicode_str *str ); extern atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str ); extern int grab_global_atom( struct winstation *winstation, atom_t atom );
From: Rémi Bernon rbernon@codeweavers.com
--- server/atom.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-)
diff --git a/server/atom.c b/server/atom.c index 1ff178bc3f6..1f8b9cd5502 100644 --- a/server/atom.c +++ b/server/atom.c @@ -342,44 +342,33 @@ void release_global_atom( struct winstation *winstation, atom_t atom ) DECL_HANDLER(add_atom) { struct unicode_str name = get_req_unicode_str(); - struct atom_table *table = get_global_table( NULL, 1 ); - - if (table) reply->atom = add_atom( table, &name ); + reply->atom = add_atom( global_table, &name ); }
/* delete a global atom */ DECL_HANDLER(delete_atom) { - struct atom_table *table = get_global_table( NULL, 0 ); - - if (table) delete_atom( table, req->atom, 0 ); + delete_atom( global_table, req->atom, 0 ); }
/* find a global atom */ DECL_HANDLER(find_atom) { struct unicode_str name = get_req_unicode_str(); - struct atom_table *table = get_global_table( NULL, 0 ); - - if (table) reply->atom = find_atom( table, &name ); + reply->atom = find_atom( global_table, &name ); }
/* get global atom name */ DECL_HANDLER(get_atom_information) { - struct atom_table *table = get_global_table( NULL, 0 ); + struct atom_entry *entry;
- if (table) + if ((entry = get_atom_entry( global_table, req->atom ))) { - struct atom_entry *entry; - - if ((entry = get_atom_entry( table, req->atom ))) - { - set_reply_data( entry->str, min( entry->len, get_reply_max_size() )); - reply->count = entry->count; - reply->pinned = 0; - reply->total = entry->len; - } - else reply->count = -1; + set_reply_data( entry->str, min( entry->len, get_reply_max_size() )); + reply->count = entry->count; + reply->pinned = 0; + reply->total = entry->len; } + else reply->count = -1; }
From: Rémi Bernon rbernon@codeweavers.com
--- server/atom.c | 72 +++++++++---------------------------------------- server/class.c | 42 ++++++++++++++++------------- server/object.h | 10 ++++--- server/window.c | 31 +++++++++++++-------- 4 files changed, 63 insertions(+), 92 deletions(-)
diff --git a/server/atom.c b/server/atom.c index 1f8b9cd5502..3a0992e33d5 100644 --- a/server/atom.c +++ b/server/atom.c @@ -117,6 +117,11 @@ void set_global_atom_table( struct object *obj ) grab_object( obj ); }
+struct atom_table *get_global_atom_table(void) +{ + return global_table; +} + /* retrieve an entry pointer from its atom */ static struct atom_entry *get_atom_entry( struct atom_table *table, atom_t atom ) { @@ -182,7 +187,7 @@ static struct atom_entry *find_atom_entry( struct atom_table *table, const struc }
/* add an atom to the table */ -static atom_t add_atom( struct atom_table *table, const struct unicode_str *str ) +atom_t add_atom( struct atom_table *table, const struct unicode_str *str ) { struct atom_entry *entry; unsigned short hash; @@ -244,7 +249,7 @@ static void delete_atom( struct atom_table *table, atom_t atom, int if_pinned ) }
/* find an atom in the table */ -static atom_t find_atom( struct atom_table *table, const struct unicode_str *str ) +atom_t find_atom( struct atom_table *table, const struct unicode_str *str ) { struct atom_entry *entry; unsigned short hash; @@ -269,73 +274,22 @@ static atom_t find_atom( struct atom_table *table, const struct unicode_str *str return entry->atom; }
-static struct atom_table *get_global_table( struct winstation *winstation, int create ) -{ - struct atom_table *table = winstation ? winstation->atom_table : global_table; - if (!table) - { - if (create) - { - table = (struct atom_table *)create_atom_table(); - if (winstation) winstation->atom_table = table; - else - { - global_table = table; - make_object_permanent( &global_table->obj ); - } - } - else set_error( STATUS_OBJECT_NAME_NOT_FOUND ); - } - return table; -} - -/* add an atom in the global table; used for window properties */ -atom_t add_global_atom( struct winstation *winstation, const struct unicode_str *str ) -{ - struct atom_table *table = get_global_table( winstation, 1 ); - if (!table) return 0; - return add_atom( table, str ); -} - -/* find an atom in the global table; used for window properties */ -atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str ) -{ - struct atom_table *table = get_global_table( winstation, 0 ); - struct atom_entry *entry; - unsigned short hash; - - if (!str->len || str->len > MAX_ATOM_LEN || !table) return 0; - - hash = hash_strW( str->str, str->len, ARRAY_SIZE(table->entries) ); - if (!(entry = find_atom_entry( table, str, hash ))) return 0; - return entry->atom; -} - /* increment the ref count of a global atom; used for window properties */ -int grab_global_atom( struct winstation *winstation, atom_t atom ) +int grab_atom( struct atom_table *table, atom_t atom ) { if (atom >= MIN_STR_ATOM) { - struct atom_table *table = get_global_table( winstation, 0 ); - if (table) - { - struct atom_entry *entry = get_atom_entry( table, atom ); - if (entry) entry->count++; - return (entry != NULL); - } - else return 0; + struct atom_entry *entry = get_atom_entry( table, atom ); + if (entry) entry->count++; + return (entry != NULL); } else return 1; }
/* decrement the ref count of a global atom; used for window properties */ -void release_global_atom( struct winstation *winstation, atom_t atom ) +void release_atom( struct atom_table *table, atom_t atom ) { - if (atom >= MIN_STR_ATOM) - { - struct atom_table *table = get_global_table( winstation, 0 ); - if (table) delete_atom( table, atom, 1 ); - } + if (atom >= MIN_STR_ATOM) delete_atom( table, atom, 1 ); }
/* add a global atom */ diff --git a/server/class.c b/server/class.c index 3231f366b26..090c8accaea 100644 --- a/server/class.c +++ b/server/class.c @@ -75,8 +75,10 @@ static struct window_class *create_class( struct process *process, int extra_byt
static void destroy_class( struct window_class *class ) { - release_global_atom( NULL, class->atom ); - release_global_atom( NULL, class->base_atom ); + struct atom_table *table = get_global_atom_table(); + + release_atom( table, class->atom ); + release_atom( table, class->base_atom ); list_remove( &class->entry ); release_object( class->process ); free( class ); @@ -137,8 +139,9 @@ int is_hwnd_message_class( struct window_class *class ) { static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; static const struct unicode_str name = { messageW, sizeof(messageW) }; + struct atom_table *table = get_global_atom_table();
- return (!class->local && class->atom == find_global_atom( NULL, &name )); + return (!class->local && class->atom == find_atom( table, &name )); }
int get_class_style( struct window_class *class ) @@ -161,58 +164,59 @@ DECL_HANDLER(create_class) { struct window_class *class; struct unicode_str name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); atom_t atom, base_atom;
if (name.len) { - atom = add_global_atom( NULL, &name ); + atom = add_atom( table, &name ); if (!atom) return; if (req->name_offset && req->name_offset < name.len / sizeof(WCHAR)) { name.str += req->name_offset; name.len -= req->name_offset * sizeof(WCHAR);
- base_atom = add_global_atom( NULL, &name ); + base_atom = add_atom( table, &name ); if (!base_atom) { - release_global_atom( NULL, atom ); + release_atom( table, atom ); return; } } else { base_atom = atom; - grab_global_atom( NULL, atom ); + grab_atom( table, atom ); } } else { base_atom = atom = req->atom; - if (!grab_global_atom( NULL, atom )) return; - grab_global_atom( NULL, base_atom ); + if (!grab_atom( table, atom )) return; + grab_atom( table, base_atom ); }
class = find_class( current->process, atom, req->instance ); if (class && !class->local == !req->local) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); - release_global_atom( NULL, atom ); - release_global_atom( NULL, base_atom ); + release_atom( table, atom ); + release_atom( table, base_atom ); return; } if (req->extra < 0 || req->extra > 4096 || req->win_extra < 0 || req->win_extra > 4096) { /* don't allow stupid values here */ set_error( STATUS_INVALID_PARAMETER ); - release_global_atom( NULL, atom ); - release_global_atom( NULL, base_atom ); + release_atom( table, atom ); + release_atom( table, base_atom ); return; }
if (!(class = create_class( current->process, req->extra, req->local ))) { - release_global_atom( NULL, atom ); - release_global_atom( NULL, base_atom ); + release_atom( table, atom ); + release_atom( table, base_atom ); return; } class->atom = atom; @@ -229,9 +233,10 @@ DECL_HANDLER(destroy_class) { struct window_class *class; struct unicode_str name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); atom_t atom = req->atom;
- if (name.len) atom = find_global_atom( NULL, &name ); + if (name.len) atom = find_atom( table, &name );
if (!(class = find_class( current->process, atom, req->instance ))) set_win32_error( ERROR_CLASS_DOES_NOT_EXIST ); @@ -249,6 +254,7 @@ DECL_HANDLER(destroy_class) DECL_HANDLER(set_class_info) { struct window_class *class = get_window_class( req->window ); + struct atom_table *table = get_global_atom_table();
if (!class) return;
@@ -289,8 +295,8 @@ DECL_HANDLER(set_class_info)
if (req->flags & SET_CLASS_ATOM) { - if (!grab_global_atom( NULL, req->atom )) return; - release_global_atom( NULL, class->atom ); + if (!grab_atom( table, req->atom )) return; + release_atom( table, class->atom ); class->atom = req->atom; } if (req->flags & SET_CLASS_STYLE) class->style = req->style; diff --git a/server/object.h b/server/object.h index 7861b3e6c40..848f6dc977e 100644 --- a/server/object.h +++ b/server/object.h @@ -287,10 +287,12 @@ extern void init_signals(void); extern struct object *create_atom_table(void); extern void set_global_atom_table( struct object *obj );
-extern atom_t add_global_atom( struct winstation *winstation, const struct unicode_str *str ); -extern atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str ); -extern int grab_global_atom( struct winstation *winstation, atom_t atom ); -extern void release_global_atom( struct winstation *winstation, atom_t atom ); +struct atom_table; +extern struct atom_table *get_global_atom_table(void); +extern atom_t add_atom( struct atom_table *table, const struct unicode_str *str ); +extern atom_t find_atom( struct atom_table *table, const struct unicode_str *str ); +extern int grab_atom( struct atom_table *table, atom_t atom ); +extern void release_atom( struct atom_table *table, atom_t atom );
/* directory functions */
diff --git a/server/window.c b/server/window.c index 6b45633f66d..6af3aa8f622 100644 --- a/server/window.c +++ b/server/window.c @@ -471,6 +471,7 @@ static int add_handle_to_array( struct user_handle_array *array, user_handle_t h /* set a window property */ static void set_property( struct window *win, atom_t atom, lparam_t data, enum property_type type ) { + struct atom_table *table = get_global_atom_table(); int i, free = -1; struct property *new_props;
@@ -491,7 +492,7 @@ static void set_property( struct window *win, atom_t atom, lparam_t data, enum p }
/* need to add an entry */ - if (!grab_global_atom( NULL, atom )) return; + if (!grab_atom( table, atom )) return; if (free == -1) { /* no free entry */ @@ -502,7 +503,7 @@ static void set_property( struct window *win, atom_t atom, lparam_t data, enum p sizeof(*new_props) * (win->prop_alloc + 16) ))) { set_error( STATUS_NO_MEMORY ); - release_global_atom( NULL, atom ); + release_atom( table, atom ); return; } win->prop_alloc += 16; @@ -518,6 +519,7 @@ static void set_property( struct window *win, atom_t atom, lparam_t data, enum p /* remove a window property */ static lparam_t remove_property( struct window *win, atom_t atom ) { + struct atom_table *table = get_global_atom_table(); int i;
for (i = 0; i < win->prop_inuse; i++) @@ -525,7 +527,7 @@ static lparam_t remove_property( struct window *win, atom_t atom ) if (win->properties[i].type == PROP_TYPE_FREE) continue; if (win->properties[i].atom == atom) { - release_global_atom( NULL, atom ); + release_atom( table, atom ); win->properties[i].type = PROP_TYPE_FREE; return win->properties[i].data; } @@ -551,13 +553,14 @@ static lparam_t get_property( struct window *win, atom_t atom ) /* destroy all properties of a window */ static inline void destroy_properties( struct window *win ) { + struct atom_table *table = get_global_atom_table(); int i;
if (!win->properties) return; for (i = 0; i < win->prop_inuse; i++) { if (win->properties[i].type == PROP_TYPE_FREE) continue; - release_global_atom( NULL, win->properties[i].atom ); + release_atom( table, win->properties[i].atom ); } free( win->properties ); } @@ -2200,6 +2203,7 @@ DECL_HANDLER(create_window) { struct window *win, *parent = NULL, *owner = NULL; struct unicode_str cls_name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); unsigned int dpi_context; atom_t atom;
@@ -2229,7 +2233,7 @@ DECL_HANDLER(create_window) owner = owner->parent; }
- atom = cls_name.len ? find_global_atom( NULL, &cls_name ) : req->atom; + atom = cls_name.len ? find_atom( table, &cls_name ) : req->atom;
if (!(win = create_window( parent, owner, atom, req->class_instance, req->instance ))) return;
@@ -2314,7 +2318,8 @@ DECL_HANDLER(get_desktop_window) { static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; static const struct unicode_str name = { messageW, sizeof(messageW) }; - atom_t atom = add_global_atom( NULL, &name ); + struct atom_table *table = get_global_atom_table(); + atom_t atom = add_atom( table, &name ); if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0, 0 ))) { detach_window_thread( desktop->msg_window ); @@ -2528,11 +2533,12 @@ DECL_HANDLER(get_class_windows) struct desktop *desktop = NULL; struct window *parent = NULL, *win = NULL; struct unicode_str cls_name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); atom_t atom = req->atom; user_handle_t *data; unsigned int count = 0, max_count = get_reply_max_size() / sizeof(*data);
- if (cls_name.len && !(atom = find_global_atom( NULL, &cls_name ))) return; + if (cls_name.len && !(atom = find_atom( table, &cls_name ))) return; if (req->parent && !(parent = get_window( req->parent ))) return;
if (req->child) @@ -3072,17 +3078,18 @@ DECL_HANDLER(redraw_window) DECL_HANDLER(set_window_property) { struct unicode_str name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); struct window *win = get_window( req->window );
if (!win) return;
if (name.len) { - atom_t atom = add_global_atom( NULL, &name ); + atom_t atom = add_atom( table, &name ); if (atom) { set_property( win, atom, req->data, PROP_TYPE_STRING ); - release_global_atom( NULL, atom ); + release_atom( table, atom ); } } else set_property( win, req->atom, req->data, PROP_TYPE_ATOM ); @@ -3093,11 +3100,12 @@ DECL_HANDLER(set_window_property) DECL_HANDLER(remove_window_property) { struct unicode_str name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); struct window *win = get_window( req->window );
if (win) { - atom_t atom = name.len ? find_global_atom( NULL, &name ) : req->atom; + atom_t atom = name.len ? find_atom( table, &name ) : req->atom; if (atom) reply->data = remove_property( win, atom ); } } @@ -3107,11 +3115,12 @@ DECL_HANDLER(remove_window_property) DECL_HANDLER(get_window_property) { struct unicode_str name = get_req_unicode_str(); + struct atom_table *table = get_global_atom_table(); struct window *win = get_window( req->window );
if (win) { - atom_t atom = name.len ? find_global_atom( NULL, &name ) : req->atom; + atom_t atom = name.len ? find_atom( table, &name ) : req->atom; if (atom) reply->data = get_property( win, atom ); } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/class.c | 52 ++++++++++++++++++++++++++++++++++++++------- server/atom.c | 12 +++++++++++ server/protocol.def | 9 ++++++++ 3 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 1180a62d055..abe94e6be62 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -302,6 +302,21 @@ ATOM get_int_atom_value( UNICODE_STRING *name ) return ret; }
+static ULONG integral_atom_name( WCHAR *buffer, ULONG len, RTL_ATOM atom ) +{ + char tmp[16]; + int ret = snprintf( tmp, sizeof(tmp), "#%u", atom ); + + len /= sizeof(WCHAR); + if (len) + { + if (len <= ret) ret = len - 1; + ascii_to_unicode( buffer, tmp, ret ); + buffer[ret] = 0; + } + return ret * sizeof(WCHAR); +} + /*********************************************************************** * get_class_ptr */ @@ -575,13 +590,34 @@ ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDC */ ULONG WINAPI NtUserGetAtomName( ATOM atom, UNICODE_STRING *name ) { - char buf[sizeof(ATOM_BASIC_INFORMATION) + MAX_ATOM_LEN * sizeof(WCHAR)]; - ATOM_BASIC_INFORMATION *abi = (ATOM_BASIC_INFORMATION *)buf; - UINT size; + WCHAR buffer[MAX_ATOM_LEN]; + UINT size = 0;
- if (!set_ntstatus( NtQueryInformationAtom( atom, AtomBasicInformation, - buf, sizeof(buf), NULL ))) - return 0; + if (atom < MAXINTATOM) + { + if (!atom) + { + set_ntstatus( STATUS_INVALID_PARAMETER ); + return 0; + } + + size = integral_atom_name( buffer, sizeof(buffer), atom ); + } + else + { + SERVER_START_REQ( get_user_atom_name ) + { + req->atom = atom; + wine_server_set_reply( req, buffer, sizeof(buffer) ); + if (!wine_server_call_err( req )) + { + size = wine_server_reply_size( reply ); + buffer[size / sizeof(WCHAR)] = 0; + } + } + SERVER_END_REQ; + if (!size) return 0; + }
if (name->MaximumLength < sizeof(WCHAR)) { @@ -589,8 +625,8 @@ ULONG WINAPI NtUserGetAtomName( ATOM atom, UNICODE_STRING *name ) return 0; }
- size = min( abi->NameLength, name->MaximumLength - sizeof(WCHAR) ); - if (size) memcpy( name->Buffer, abi->Name, size ); + size = min( size, name->MaximumLength - sizeof(WCHAR) ); + if (size) memcpy( name->Buffer, buffer, size ); name->Buffer[size / sizeof(WCHAR)] = 0; return size / sizeof(WCHAR); } diff --git a/server/atom.c b/server/atom.c index 3a0992e33d5..4fd9df14526 100644 --- a/server/atom.c +++ b/server/atom.c @@ -326,3 +326,15 @@ DECL_HANDLER(get_atom_information) } else reply->count = -1; } + +/* get a user atom name */ +DECL_HANDLER(get_user_atom_name) +{ + struct atom_entry *entry; + + if ((entry = get_atom_entry( global_table, req->atom ))) + { + set_reply_data( (void *)entry->str, min( entry->len, get_reply_max_size() )); + reply->total = entry->len; + } +} diff --git a/server/protocol.def b/server/protocol.def index 66d9f3e930b..cccb924e612 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2233,6 +2233,15 @@ struct process_info @END
+/* Get a user atom name */ +@REQ(get_user_atom_name) + atom_t atom; /* atom handle */ +@REPLY + data_size_t total; /* actual length of atom name */ + VARARG(name,unicode_str); /* atom name */ +@END + + /* Get a handle for the current thread message queue */ @REQ(get_msg_queue_handle) @REPLY
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/class.c | 50 +++++++++++++++++++++++++++++++++++++++++++-- server/atom.c | 7 +++++++ server/protocol.def | 8 ++++++++ 3 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index abe94e6be62..2c960a4060a 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -38,6 +38,9 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
SYSTEM_BASIC_INFORMATION system_info;
+#define MAX_ATOM_LEN 255 +#define IS_INTATOM(x) (((ULONG_PTR)(x) >> 16) == 0) + #define MAX_WINPROCS 4096 #define WINPROC_PROC16 ((void *)1) /* placeholder for 16-bit window procs */
@@ -302,6 +305,34 @@ ATOM get_int_atom_value( UNICODE_STRING *name ) return ret; }
+static unsigned int is_integral_atom( const WCHAR *atomstr, ULONG len, RTL_ATOM *ret_atom ) +{ + RTL_ATOM atom; + + if ((ULONG_PTR)atomstr >> 16) + { + const WCHAR* ptr = atomstr; + if (!len) return STATUS_OBJECT_NAME_INVALID; + + if (*ptr++ == '#') + { + atom = 0; + while (ptr < atomstr + len && *ptr >= '0' && *ptr <= '9') + { + atom = atom * 10 + *ptr++ - '0'; + } + if (ptr > atomstr + 1 && ptr == atomstr + len) goto done; + } + if (len > MAX_ATOM_LEN) return STATUS_INVALID_PARAMETER; + return STATUS_MORE_ENTRIES; + } + else if ((atom = LOWORD( atomstr )) >= MAXINTATOM) return STATUS_INVALID_PARAMETER; +done: + if (atom >= MAXINTATOM) atom = 0; + if (!(*ret_atom = atom)) return STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; +} + static ULONG integral_atom_name( WCHAR *buffer, ULONG len, RTL_ATOM atom ) { char tmp[16]; @@ -636,7 +667,8 @@ ULONG WINAPI NtUserGetAtomName( ATOM atom, UNICODE_STRING *name ) */ ATOM WINAPI NtUserRegisterWindowMessage( UNICODE_STRING *name ) { - RTL_ATOM atom; + unsigned int status; + RTL_ATOM atom = 0;
TRACE( "%s\n", debugstr_us(name) );
@@ -645,7 +677,21 @@ ATOM WINAPI NtUserRegisterWindowMessage( UNICODE_STRING *name ) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return 0; } - if (!set_ntstatus( NtAddAtom( name->Buffer, name->Length, &atom ) )) return 0; + + status = is_integral_atom( name->Buffer, name->Length / sizeof(WCHAR), &atom ); + if (status == STATUS_MORE_ENTRIES) + { + SERVER_START_REQ( add_user_atom ) + { + wine_server_add_data( req, name->Buffer, name->Length ); + status = wine_server_call( req ); + atom = reply->atom; + } + SERVER_END_REQ; + } + + TRACE( "%s -> %x\n", debugstr_us(name), status == STATUS_SUCCESS ? atom : 0 ); + set_ntstatus( status ); return atom; }
diff --git a/server/atom.c b/server/atom.c index 4fd9df14526..63e845d1bb1 100644 --- a/server/atom.c +++ b/server/atom.c @@ -327,6 +327,13 @@ DECL_HANDLER(get_atom_information) else reply->count = -1; }
+/* add a user atom */ +DECL_HANDLER(add_user_atom) +{ + struct unicode_str name = get_req_unicode_str(); + reply->atom = add_atom( global_table, &name ); +} + /* get a user atom name */ DECL_HANDLER(get_user_atom_name) { diff --git a/server/protocol.def b/server/protocol.def index cccb924e612..22470e33ae0 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2233,6 +2233,14 @@ struct process_info @END
+/* Add a user atom */ +@REQ(add_user_atom) + VARARG(name,unicode_str); /* atom name */ +@REPLY + atom_t atom; /* resulting atom */ +@END + + /* Get a user atom name */ @REQ(get_user_atom_name) atom_t atom; /* atom handle */