From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/class.c | 19 +++++++++++++++++++ server/class.c | 43 ++++++++++++++++++++++++++++++------------- server/protocol.def | 9 ++++++++- 3 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 6148fb6821d..fd6cd8b57a5 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -63,6 +63,7 @@ typedef struct tagCLASS WCHAR name[MAX_ATOM_LEN + 1]; WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */ struct client_menu_name menu_name; /* Default menu name */ + const shared_object_t *shared; /* class object in session shared memory */ } CLASS;
/* Built-in class descriptor */ @@ -455,6 +456,8 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam DWORD flags, DWORD *wow ) { const BOOL is_builtin = fnid, ansi = flags; + const shared_object_t *shared; + struct obj_locator locator; HINSTANCE instance; HICON sm_icon = 0; CLASS *class; @@ -505,6 +508,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam req->atom = wine_server_add_atom( req, name ); req->name_offset = version->Length / sizeof(WCHAR); ret = !wine_server_call_err( req ); + locator = reply->locator; atom = reply->atom; } SERVER_END_REQ; @@ -514,6 +518,20 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam return 0; }
+ if (!(shared = find_shared_session_object( locator.id, locator.offset ))) + { + ERR( "Failed to get shared session object for window class\n" ); + SERVER_START_REQ( destroy_class ) + { + req->instance = wine_server_client_ptr( instance ); + wine_server_add_data( req, name->Buffer, name->Length ); + wine_server_call( req ); + } + SERVER_END_REQ; + free( class ); + return 0; + } + /* Other non-null values must be set by caller */ if (wc->hIcon && !wc->hIconSm) sm_icon = CopyImage( wc->hIcon, IMAGE_ICON, @@ -537,6 +555,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam class->atom = atom; class->winproc = alloc_winproc( wc->lpfnWndProc, ansi ); if (client_menu_name) class->menu_name = *client_menu_name; + class->shared = shared; release_class_ptr( class ); return atom; } diff --git a/server/class.c b/server/class.c index 2a520bded17..9db68fdced6 100644 --- a/server/class.c +++ b/server/class.c @@ -35,23 +35,26 @@ #include "object.h" #include "process.h" #include "user.h" +#include "file.h" #include "winuser.h" #include "winternl.h"
struct window_class { - struct list entry; /* entry in process list */ - struct process *process; /* process owning the 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 */ - client_ptr_t client_ptr; /* pointer to class in client address space */ - int nb_extra_bytes; /* number of extra bytes */ - char extra_bytes[1]; /* extra bytes storage */ + struct list entry; /* entry in process list */ + struct winstation *winstation; /* winstation the class was created on */ + struct process *process; /* process owning the 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 */ + client_ptr_t client_ptr; /* pointer to class in client address space */ + class_shm_t *shared; /* class in session shared memory */ + int nb_extra_bytes; /* number of extra bytes */ + char extra_bytes[1]; /* extra bytes storage */ };
static struct window_class *create_class( struct process *process, int extra_bytes, int local ) @@ -65,12 +68,24 @@ static struct window_class *create_class( struct process *process, int extra_byt class->local = local; class->nb_extra_bytes = extra_bytes; memset( class->extra_bytes, 0, extra_bytes ); + + if (!(class->shared = alloc_shared_object())) goto failed; + SHARED_WRITE_BEGIN( class->shared, class_shm_t ) + { + shared->placeholder = 0; + } + SHARED_WRITE_END; + /* other fields are initialized by caller */
/* local classes have priority so we put them first in the list */ if (local) list_add_head( &process->classes, &class->entry ); else list_add_tail( &process->classes, &class->entry ); return class; + +failed: + free( class ); + return NULL; }
static void destroy_class( struct window_class *class ) @@ -81,6 +96,7 @@ static void destroy_class( struct window_class *class ) release_atom( table, class->base_atom ); list_remove( &class->entry ); release_object( class->process ); + if (class->shared) free_shared_object( class->shared ); free( class ); }
@@ -212,7 +228,8 @@ DECL_HANDLER(create_class) class->style = req->style; class->win_extra = req->win_extra; class->client_ptr = req->client_ptr; - reply->atom = base_atom; + reply->locator = get_shared_object_locator( class->shared ); + reply->atom = base_atom; }
/* destroy a window class */ diff --git a/server/protocol.def b/server/protocol.def index b87b7d6515a..5b2b1709499 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1014,6 +1014,11 @@ typedef volatile struct unsigned __int64 keystate_serial; /* keystate update counter at last sync */ } input_shm_t;
+typedef volatile struct +{ + int placeholder; +} class_shm_t; + typedef volatile struct { unsigned int dpi_context; /* DPI awareness context */ @@ -1024,6 +1029,7 @@ typedef volatile union desktop_shm_t desktop; queue_shm_t queue; input_shm_t input; + class_shm_t class; window_shm_t window; } object_shm_t;
@@ -3238,7 +3244,8 @@ enum caret_state data_size_t name_offset; /* base class name offset for specified atom */ VARARG(name,unicode_str); /* class name */ @REPLY - atom_t atom; /* resulting class atom */ + struct obj_locator locator; /* locator for the shared class object */ + atom_t atom; /* resulting class atom */ @END