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 */