Commit bd13ab8d authored by Alexandre Julliard's avatar Alexandre Julliard

Store a pointer to the client-side class structure in the server and

return it on create_window and destroy_class. Only create a single instance of the desktop class for the whole session. Added some missing locking in the client-side class management.
parent 97fc6c3a
...@@ -137,11 +137,9 @@ inline static void unmap_str_16_to_32W( LPCWSTR str ) ...@@ -137,11 +137,9 @@ inline static void unmap_str_16_to_32W( LPCWSTR str )
/* Class functions */ /* Class functions */
struct tagCLASS; /* opaque structure */ struct tagCLASS; /* opaque structure */
struct tagDCE; struct tagWND;
extern void CLASS_RegisterBuiltinClasses( HINSTANCE inst ); extern void CLASS_RegisterBuiltinClasses( HINSTANCE inst );
extern struct tagCLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type, extern void CLASS_AddWindow( struct tagCLASS *class, struct tagWND *win, WINDOWPROCTYPE type );
INT *winExtra, WNDPROC *winproc,
DWORD *style, struct tagDCE **dce );
extern void CLASS_FreeModuleClasses( HMODULE16 hModule ); extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
/* Timer functions */ /* Timer functions */
......
...@@ -2526,12 +2526,13 @@ struct create_window_request ...@@ -2526,12 +2526,13 @@ struct create_window_request
user_handle_t owner; user_handle_t owner;
atom_t atom; atom_t atom;
void* instance; void* instance;
int extra;
}; };
struct create_window_reply struct create_window_reply
{ {
struct reply_header __header; struct reply_header __header;
user_handle_t handle; user_handle_t handle;
int extra;
void* class_ptr;
}; };
...@@ -3062,6 +3063,7 @@ struct create_class_request ...@@ -3062,6 +3063,7 @@ struct create_class_request
void* instance; void* instance;
int extra; int extra;
int win_extra; int win_extra;
void* client_ptr;
}; };
struct create_class_reply struct create_class_reply
{ {
...@@ -3079,6 +3081,7 @@ struct destroy_class_request ...@@ -3079,6 +3081,7 @@ struct destroy_class_request
struct destroy_class_reply struct destroy_class_reply
{ {
struct reply_header __header; struct reply_header __header;
void* client_ptr;
}; };
...@@ -3744,6 +3747,6 @@ union generic_reply ...@@ -3744,6 +3747,6 @@ union generic_reply
struct set_global_windows_reply set_global_windows_reply; struct set_global_windows_reply set_global_windows_reply;
}; };
#define SERVER_PROTOCOL_VERSION 129 #define SERVER_PROTOCOL_VERSION 130
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -44,10 +44,15 @@ struct window_class ...@@ -44,10 +44,15 @@ struct window_class
void *instance; /* module instance */ void *instance; /* module instance */
unsigned int style; /* class style */ unsigned int style; /* class style */
int win_extra; /* number of window extra bytes */ int win_extra; /* number of window extra bytes */
void *client_ptr; /* pointer to class in client address space */
int nb_extra_bytes; /* number of extra bytes */ int nb_extra_bytes; /* number of extra bytes */
char extra_bytes[1]; /* extra bytes storage */ char extra_bytes[1]; /* extra bytes storage */
}; };
#define DESKTOP_ATOM ((atom_t)32769)
static struct window_class *desktop_class;
static struct window_class *create_class( struct process *process, int extra_bytes, int local ) static struct window_class *create_class( struct process *process, int extra_bytes, int local )
{ {
struct window_class *class; struct window_class *class;
...@@ -67,6 +72,25 @@ static struct window_class *create_class( struct process *process, int extra_byt ...@@ -67,6 +72,25 @@ static struct window_class *create_class( struct process *process, int extra_byt
return class; return class;
} }
static struct window_class *create_desktop_class( unsigned int style, int win_extra )
{
struct window_class *class;
if (!(class = mem_alloc( sizeof(*class) - 1 ))) return NULL;
class->process = NULL;
class->count = 0;
class->local = 0;
class->nb_extra_bytes = 0;
class->atom = DESKTOP_ATOM;
class->instance = NULL;
class->style = style;
class->win_extra = win_extra;
class->client_ptr = NULL;
desktop_class = class;
return class;
}
static void destroy_class( struct window_class *class ) static void destroy_class( struct window_class *class )
{ {
list_remove( &class->entry ); list_remove( &class->entry );
...@@ -95,13 +119,19 @@ static struct window_class *find_class( struct process *process, atom_t atom, vo ...@@ -95,13 +119,19 @@ static struct window_class *find_class( struct process *process, atom_t atom, vo
if (class->atom != atom) continue; if (class->atom != atom) continue;
if (!instance || !class->local || class->instance == instance) return class; if (!instance || !class->local || class->instance == instance) return class;
} }
if (atom == DESKTOP_ATOM) return desktop_class;
return NULL; return NULL;
} }
struct window_class *grab_class( struct process *process, atom_t atom, void *instance ) struct window_class *grab_class( struct process *process, atom_t atom,
void *instance, int *extra_bytes )
{ {
struct window_class *class = find_class( process, atom, instance ); struct window_class *class = find_class( process, atom, instance );
if (class) class->count++; if (class)
{
class->count++;
*extra_bytes = class->win_extra;
}
else set_error( STATUS_INVALID_HANDLE ); else set_error( STATUS_INVALID_HANDLE );
return class; return class;
} }
...@@ -117,18 +147,31 @@ atom_t get_class_atom( struct window_class *class ) ...@@ -117,18 +147,31 @@ atom_t get_class_atom( struct window_class *class )
return class->atom; return class->atom;
} }
void *get_class_client_ptr( struct window_class *class )
{
return class->client_ptr;
}
/* create a window class */ /* create a window class */
DECL_HANDLER(create_class) DECL_HANDLER(create_class)
{ {
struct window_class *class = find_class( current->process, req->atom, req->instance ); struct window_class *class;
if (!req->local && req->atom == DESKTOP_ATOM)
{
if (!desktop_class) create_desktop_class( req->style, req->win_extra );
return; /* silently ignore further attempts to create the desktop class */
}
class = find_class( current->process, req->atom, req->instance );
if (class && !class->local == !req->local) if (class && !class->local == !req->local)
{ {
set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); set_win32_error( ERROR_CLASS_ALREADY_EXISTS );
return; return;
} }
if (req->extra < 0 || req->extra > 4096) /* don't allow stupid values here */ 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 ); set_error( STATUS_INVALID_PARAMETER );
return; return;
} }
...@@ -143,6 +186,7 @@ DECL_HANDLER(create_class) ...@@ -143,6 +186,7 @@ DECL_HANDLER(create_class)
class->instance = req->instance; class->instance = req->instance;
class->style = req->style; class->style = req->style;
class->win_extra = req->win_extra; class->win_extra = req->win_extra;
class->client_ptr = req->client_ptr;
} }
/* destroy a window class */ /* destroy a window class */
...@@ -151,11 +195,14 @@ DECL_HANDLER(destroy_class) ...@@ -151,11 +195,14 @@ DECL_HANDLER(destroy_class)
struct window_class *class = find_class( current->process, req->atom, req->instance ); struct window_class *class = find_class( current->process, req->atom, req->instance );
if (!class) if (!class)
set_error( STATUS_INVALID_HANDLE ); set_win32_error( ERROR_CLASS_DOES_NOT_EXIST );
else if (class->count) else if (class->count)
set_win32_error( ERROR_CLASS_HAS_WINDOWS ); set_win32_error( ERROR_CLASS_HAS_WINDOWS );
else else
destroy_class( class ); {
reply->client_ptr = class->client_ptr;
if (class != desktop_class) destroy_class( class );
}
} }
...@@ -166,6 +213,12 @@ DECL_HANDLER(set_class_info) ...@@ -166,6 +213,12 @@ DECL_HANDLER(set_class_info)
if (!class) return; if (!class) return;
if (req->flags && class->process != current->process)
{
set_error( STATUS_ACCESS_DENIED );
return;
}
if (req->extra_size > sizeof(req->extra_value) || if (req->extra_size > sizeof(req->extra_value) ||
req->extra_offset < -1 || req->extra_offset < -1 ||
req->extra_offset > class->nb_extra_bytes - (int)req->extra_size) req->extra_offset > class->nb_extra_bytes - (int)req->extra_size)
...@@ -173,6 +226,11 @@ DECL_HANDLER(set_class_info) ...@@ -173,6 +226,11 @@ DECL_HANDLER(set_class_info)
set_win32_error( ERROR_INVALID_INDEX ); set_win32_error( ERROR_INVALID_INDEX );
return; return;
} }
if ((req->flags & SET_CLASS_WINEXTRA) && (req->win_extra < 0 || req->win_extra > 4096))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (req->extra_offset != -1) if (req->extra_offset != -1)
{ {
memcpy( &reply->old_extra_value, class->extra_bytes + req->extra_offset, req->extra_size ); memcpy( &reply->old_extra_value, class->extra_bytes + req->extra_offset, req->extra_size );
...@@ -201,4 +259,3 @@ DECL_HANDLER(set_class_info) ...@@ -201,4 +259,3 @@ DECL_HANDLER(set_class_info)
if (req->flags & SET_CLASS_EXTRA) memcpy( class->extra_bytes + req->extra_offset, if (req->flags & SET_CLASS_EXTRA) memcpy( class->extra_bytes + req->extra_offset,
&req->extra_value, req->extra_size ); &req->extra_value, req->extra_size );
} }
...@@ -1781,9 +1781,10 @@ enum message_type ...@@ -1781,9 +1781,10 @@ enum message_type
user_handle_t owner; /* owner window */ user_handle_t owner; /* owner window */
atom_t atom; /* class atom */ atom_t atom; /* class atom */
void* instance; /* module instance */ void* instance; /* module instance */
int extra; /* number of extra bytes */
@REPLY @REPLY
user_handle_t handle; /* created window */ user_handle_t handle; /* created window */
int extra; /* number of extra bytes */
void* class_ptr; /* pointer to class in client address space */
@END @END
...@@ -2138,6 +2139,7 @@ enum message_type ...@@ -2138,6 +2139,7 @@ enum message_type
void* instance; /* module instance */ void* instance; /* module instance */
int extra; /* number of extra class bytes */ int extra; /* number of extra class bytes */
int win_extra; /* number of window extra bytes */ int win_extra; /* number of window extra bytes */
void* client_ptr; /* pointer to class in client address space */
@END @END
...@@ -2145,6 +2147,8 @@ enum message_type ...@@ -2145,6 +2147,8 @@ enum message_type
@REQ(destroy_class) @REQ(destroy_class)
atom_t atom; /* class atom */ atom_t atom; /* class atom */
void* instance; /* module instance */ void* instance; /* module instance */
@REPLY
void* client_ptr; /* pointer to class in client address space */
@END @END
......
...@@ -2096,13 +2096,14 @@ static void dump_create_window_request( const struct create_window_request *req ...@@ -2096,13 +2096,14 @@ static void dump_create_window_request( const struct create_window_request *req
fprintf( stderr, " parent=%p,", req->parent ); fprintf( stderr, " parent=%p,", req->parent );
fprintf( stderr, " owner=%p,", req->owner ); fprintf( stderr, " owner=%p,", req->owner );
fprintf( stderr, " atom=%04x,", req->atom ); fprintf( stderr, " atom=%04x,", req->atom );
fprintf( stderr, " instance=%p,", req->instance ); fprintf( stderr, " instance=%p", req->instance );
fprintf( stderr, " extra=%d", req->extra );
} }
static void dump_create_window_reply( const struct create_window_reply *req ) static void dump_create_window_reply( const struct create_window_reply *req )
{ {
fprintf( stderr, " handle=%p", req->handle ); fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " extra=%d,", req->extra );
fprintf( stderr, " class_ptr=%p", req->class_ptr );
} }
static void dump_link_window_request( const struct link_window_request *req ) static void dump_link_window_request( const struct link_window_request *req )
...@@ -2511,7 +2512,8 @@ static void dump_create_class_request( const struct create_class_request *req ) ...@@ -2511,7 +2512,8 @@ static void dump_create_class_request( const struct create_class_request *req )
fprintf( stderr, " style=%08x,", req->style ); fprintf( stderr, " style=%08x,", req->style );
fprintf( stderr, " instance=%p,", req->instance ); fprintf( stderr, " instance=%p,", req->instance );
fprintf( stderr, " extra=%d,", req->extra ); fprintf( stderr, " extra=%d,", req->extra );
fprintf( stderr, " win_extra=%d", req->win_extra ); fprintf( stderr, " win_extra=%d,", req->win_extra );
fprintf( stderr, " client_ptr=%p", req->client_ptr );
} }
static void dump_destroy_class_request( const struct destroy_class_request *req ) static void dump_destroy_class_request( const struct destroy_class_request *req )
...@@ -2520,6 +2522,11 @@ static void dump_destroy_class_request( const struct destroy_class_request *req ...@@ -2520,6 +2522,11 @@ static void dump_destroy_class_request( const struct destroy_class_request *req
fprintf( stderr, " instance=%p", req->instance ); fprintf( stderr, " instance=%p", req->instance );
} }
static void dump_destroy_class_reply( const struct destroy_class_reply *req )
{
fprintf( stderr, " client_ptr=%p", req->client_ptr );
}
static void dump_set_class_info_request( const struct set_class_info_request *req ) static void dump_set_class_info_request( const struct set_class_info_request *req )
{ {
fprintf( stderr, " window=%p,", req->window ); fprintf( stderr, " window=%p,", req->window );
...@@ -2952,7 +2959,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -2952,7 +2959,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0, (dump_func)0,
(dump_func)dump_get_next_hook_reply, (dump_func)dump_get_next_hook_reply,
(dump_func)0, (dump_func)0,
(dump_func)0, (dump_func)dump_destroy_class_reply,
(dump_func)dump_set_class_info_reply, (dump_func)dump_set_class_info_reply,
(dump_func)dump_set_clipboard_info_reply, (dump_func)dump_set_clipboard_info_reply,
(dump_func)dump_open_token_reply, (dump_func)dump_open_token_reply,
......
...@@ -78,8 +78,10 @@ extern struct window_class *get_window_class( user_handle_t window ); ...@@ -78,8 +78,10 @@ extern struct window_class *get_window_class( user_handle_t window );
/* window class functions */ /* window class functions */
extern void destroy_process_classes( struct process *process ); extern void destroy_process_classes( struct process *process );
extern struct window_class *grab_class( struct process *process, atom_t atom, void *instance ); extern struct window_class *grab_class( struct process *process, atom_t atom,
void *instance, int *extra_bytes );
extern void release_class( struct window_class *class ); extern void release_class( struct window_class *class );
extern atom_t get_class_atom( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class );
extern void *get_class_client_ptr( struct window_class *class );
#endif /* __WINE_SERVER_USER_H */ #endif /* __WINE_SERVER_USER_H */
...@@ -268,11 +268,12 @@ static void destroy_window( struct window *win ) ...@@ -268,11 +268,12 @@ static void destroy_window( struct window *win )
} }
/* create a new window structure (note: the window is not linked in the window tree) */ /* create a new window structure (note: the window is not linked in the window tree) */
static struct window *create_window( struct window *parent, struct window *owner, atom_t atom, static struct window *create_window( struct window *parent, struct window *owner,
void *instance, int extra_bytes ) atom_t atom, void *instance )
{ {
int extra_bytes;
struct window *win; struct window *win;
struct window_class *class = grab_class( current->process, atom, instance ); struct window_class *class = grab_class( current->process, atom, instance, &extra_bytes );
if (!class) return NULL; if (!class) return NULL;
...@@ -474,25 +475,22 @@ struct window_class* get_window_class( user_handle_t window ) ...@@ -474,25 +475,22 @@ struct window_class* get_window_class( user_handle_t window )
/* create a window */ /* create a window */
DECL_HANDLER(create_window) DECL_HANDLER(create_window)
{ {
struct window *win;
reply->handle = 0; reply->handle = 0;
if (req->extra < 0 || req->extra > 4096) /* don't allow stupid values here */
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (!req->parent) /* return desktop window */ if (!req->parent) /* return desktop window */
{ {
if (!top_window) if (!top_window)
{ {
if (!(top_window = create_window( NULL, NULL, req->atom, req->instance, req->extra ))) return; if (!(top_window = create_window( NULL, NULL, req->atom, req->instance ))) return;
top_window->thread = NULL; /* no thread owns the desktop */ top_window->thread = NULL; /* no thread owns the desktop */
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
} }
reply->handle = top_window->handle; win = top_window;
} }
else else
{ {
struct window *win, *parent, *owner = NULL; struct window *parent, *owner = NULL;
if (!(parent = get_window( req->parent ))) return; if (!(parent = get_window( req->parent ))) return;
if (req->owner && !(owner = get_window( req->owner ))) return; if (req->owner && !(owner = get_window( req->owner ))) return;
...@@ -503,9 +501,11 @@ DECL_HANDLER(create_window) ...@@ -503,9 +501,11 @@ DECL_HANDLER(create_window)
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return; return;
} }
if (!(win = create_window( parent, owner, req->atom, req->instance, req->extra ))) return; if (!(win = create_window( parent, owner, req->atom, req->instance ))) return;
reply->handle = win->handle;
} }
reply->handle = win->handle;
reply->extra = win->nb_extra_bytes;
reply->class_ptr = get_class_client_ptr( win->class );
} }
......
...@@ -65,23 +65,13 @@ static void *user_handles[NB_USER_HANDLES]; ...@@ -65,23 +65,13 @@ static void *user_handles[NB_USER_HANDLES];
static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
HINSTANCE instance, WINDOWPROCTYPE type ) HINSTANCE instance, WINDOWPROCTYPE type )
{ {
BOOL res;
WORD index; WORD index;
WND *win; WND *win;
DCE *dce; struct tagCLASS *class = NULL;
INT extra_bytes;
DWORD clsStyle;
WNDPROC winproc;
struct tagCLASS *class;
user_handle_t handle = 0; user_handle_t handle = 0;
int extra_bytes = 0;
if (!(class = CLASS_AddWindow( atom, instance, type, &extra_bytes, &winproc, &clsStyle, &dce ))) if (type == WIN_PROC_16) instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
return NULL;
if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
return NULL;
USER_Lock();
SERVER_START_REQ( create_window ) SERVER_START_REQ( create_window )
{ {
...@@ -89,29 +79,44 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, ...@@ -89,29 +79,44 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
req->owner = owner; req->owner = owner;
req->atom = atom; req->atom = atom;
req->instance = instance; req->instance = instance;
req->extra = extra_bytes; if (!wine_server_call_err( req ))
if ((res = !wine_server_call_err( req ))) handle = reply->handle; {
handle = reply->handle;
extra_bytes = reply->extra;
class = reply->class_ptr;
}
} }
SERVER_END_REQ; SERVER_END_REQ;
if (!res) if (!handle)
{ {
USER_Unlock(); WARN( "error %ld creating window\n", GetLastError() );
HeapFree( GetProcessHeap(), 0, win );
return NULL; return NULL;
} }
if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
{
SERVER_START_REQ( destroy_window )
{
req->handle = handle;
wine_server_call( req );
}
SERVER_END_REQ;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
USER_Lock();
index = LOWORD(handle) - FIRST_USER_HANDLE; index = LOWORD(handle) - FIRST_USER_HANDLE;
assert( index < NB_USER_HANDLES ); assert( index < NB_USER_HANDLES );
user_handles[index] = win; user_handles[index] = win;
win->hwndSelf = handle; win->hwndSelf = handle;
win->dwMagic = WND_MAGIC; win->dwMagic = WND_MAGIC;
win->irefCount = 1; win->irefCount = 1;
win->class = class;
win->winproc = winproc;
win->dce = dce;
win->clsStyle = clsStyle;
win->cbWndExtra = extra_bytes; win->cbWndExtra = extra_bytes;
memset( win->wExtra, 0, extra_bytes ); memset( win->wExtra, 0, extra_bytes );
CLASS_AddWindow( class, win, type );
return win; return win;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment