Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/user32/class.c | 1 + include/wine/server_protocol.h | 4 +++- server/class.c | 27 +++++++++++++++++++++++++-- server/protocol.def | 2 ++ server/request.h | 14 ++++++++------ server/trace.c | 2 ++ 6 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index ce2830fe25..2b2d07f888 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -487,6 +487,7 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE req->win_extra = winExtra; req->client_ptr = wine_server_client_ptr( classPtr ); req->atom = classPtr->atomName; + req->name_offset = basename_offset; if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) ); ret = !wine_server_call_err( req ); classPtr->atomName = reply->atom; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 98dbcb7e61..5358af20b8 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4475,6 +4475,8 @@ struct create_class_request struct request_header __header; int local; atom_t atom; + int name_offset; + int _pad; unsigned int style; mod_handle_t instance; int extra; @@ -6510,6 +6512,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; };
-#define SERVER_PROTOCOL_VERSION 553 +#define SERVER_PROTOCOL_VERSION 554
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/class.c b/server/class.c index cc6e52d9b1..d5f6712006 100644 --- a/server/class.c +++ b/server/class.c @@ -46,6 +46,7 @@ struct window_class int count; /* reference count */ int local; /* local class? */ atom_t atom; /* class atom */ + atom_t base_atom; /* base class atom for versioned class */ mod_handle_t instance; /* module instance */ unsigned int style; /* class style */ int win_extra; /* number of window extra bytes */ @@ -151,17 +152,35 @@ DECL_HANDLER(create_class) { struct window_class *class; struct unicode_str name = get_req_unicode_str(); - atom_t atom; + atom_t atom, base_atom;
if (name.len) { atom = add_global_atom( NULL, &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 ); + if (!base_atom) + { + release_global_atom( NULL, atom ); + return; + } + } + else + { + base_atom = atom; + grab_global_atom( NULL, atom ); + } } else { - atom = req->atom; + base_atom = atom = req->atom; if (!grab_global_atom( NULL, atom )) return; + grab_global_atom( NULL, base_atom ); }
class = find_class( current->process, atom, req->instance ); @@ -169,6 +188,7 @@ DECL_HANDLER(create_class) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; } if (req->extra < 0 || req->extra > 4096 || req->win_extra < 0 || req->win_extra > 4096) @@ -176,15 +196,18 @@ DECL_HANDLER(create_class) /* don't allow stupid values here */ set_error( STATUS_INVALID_PARAMETER ); release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; }
if (!(class = create_class( current->process, req->extra, req->local ))) { release_global_atom( NULL, atom ); + release_global_atom( NULL, base_atom ); return; } class->atom = atom; + class->base_atom = base_atom; class->instance = req->instance; class->style = req->style; class->win_extra = req->win_extra; diff --git a/server/protocol.def b/server/protocol.def index 99e7221c4b..032b03822b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3144,6 +3144,8 @@ enum caret_state @REQ(create_class) int local; /* is it a local class? */ atom_t atom; /* class atom */ + int name_offset; /* base class name offset for specified atom */ + int _pad; unsigned int style; /* class style */ mod_handle_t instance; /* module instance */ int extra; /* number of extra class bytes */ diff --git a/server/request.h b/server/request.h index 2d55dfbd98..9cf81a1f09 100644 --- a/server/request.h +++ b/server/request.h @@ -2031,12 +2031,14 @@ C_ASSERT( FIELD_OFFSET(struct get_hook_info_reply, unicode) == 32 ); C_ASSERT( sizeof(struct get_hook_info_reply) == 40 ); C_ASSERT( FIELD_OFFSET(struct create_class_request, local) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_class_request, atom) == 16 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 20 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 24 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 32 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 36 ); -C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 40 ); -C_ASSERT( sizeof(struct create_class_request) == 48 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, name_offset) == 20 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, _pad) == 24 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 28 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 32 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 40 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 44 ); +C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 48 ); +C_ASSERT( sizeof(struct create_class_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct create_class_reply, atom) == 8 ); C_ASSERT( sizeof(struct create_class_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct destroy_class_request, atom) == 12 ); diff --git a/server/trace.c b/server/trace.c index e2980a3e31..999532a425 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3753,6 +3753,8 @@ static void dump_create_class_request( const struct create_class_request *req ) { fprintf( stderr, " local=%d", req->local ); fprintf( stderr, ", atom=%04x", req->atom ); + fprintf( stderr, ", name_offset=%d", req->name_offset ); + fprintf( stderr, ", _pad=%d", req->_pad ); fprintf( stderr, ", style=%08x", req->style ); dump_uint64( ", instance=", &req->instance ); fprintf( stderr, ", extra=%d", req->extra );