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.
This commit is contained in:
parent
97fc6c3a06
commit
bd13ab8d78
|
@ -137,11 +137,9 @@ inline static void unmap_str_16_to_32W( LPCWSTR str )
|
|||
|
||||
/* Class functions */
|
||||
struct tagCLASS; /* opaque structure */
|
||||
struct tagDCE;
|
||||
struct tagWND;
|
||||
extern void CLASS_RegisterBuiltinClasses( HINSTANCE inst );
|
||||
extern struct tagCLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
|
||||
INT *winExtra, WNDPROC *winproc,
|
||||
DWORD *style, struct tagDCE **dce );
|
||||
extern void CLASS_AddWindow( struct tagCLASS *class, struct tagWND *win, WINDOWPROCTYPE type );
|
||||
extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
|
||||
|
||||
/* Timer functions */
|
||||
|
|
|
@ -2526,12 +2526,13 @@ struct create_window_request
|
|||
user_handle_t owner;
|
||||
atom_t atom;
|
||||
void* instance;
|
||||
int extra;
|
||||
};
|
||||
struct create_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t handle;
|
||||
int extra;
|
||||
void* class_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3062,6 +3063,7 @@ struct create_class_request
|
|||
void* instance;
|
||||
int extra;
|
||||
int win_extra;
|
||||
void* client_ptr;
|
||||
};
|
||||
struct create_class_reply
|
||||
{
|
||||
|
@ -3079,6 +3081,7 @@ struct destroy_class_request
|
|||
struct destroy_class_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
void* client_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3744,6 +3747,6 @@ union generic_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 */
|
||||
|
|
|
@ -44,10 +44,15 @@ struct window_class
|
|||
void *instance; /* module instance */
|
||||
unsigned int style; /* class style */
|
||||
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 */
|
||||
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 )
|
||||
{
|
||||
struct window_class *class;
|
||||
|
@ -67,6 +72,25 @@ static struct window_class *create_class( struct process *process, int extra_byt
|
|||
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 )
|
||||
{
|
||||
list_remove( &class->entry );
|
||||
|
@ -95,13 +119,19 @@ static struct window_class *find_class( struct process *process, atom_t atom, vo
|
|||
if (class->atom != atom) continue;
|
||||
if (!instance || !class->local || class->instance == instance) return class;
|
||||
}
|
||||
if (atom == DESKTOP_ATOM) return desktop_class;
|
||||
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 );
|
||||
if (class) class->count++;
|
||||
if (class)
|
||||
{
|
||||
class->count++;
|
||||
*extra_bytes = class->win_extra;
|
||||
}
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
return class;
|
||||
}
|
||||
|
@ -117,18 +147,31 @@ atom_t get_class_atom( struct window_class *class )
|
|||
return class->atom;
|
||||
}
|
||||
|
||||
void *get_class_client_ptr( struct window_class *class )
|
||||
{
|
||||
return class->client_ptr;
|
||||
}
|
||||
|
||||
/* create a window 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)
|
||||
{
|
||||
set_win32_error( ERROR_CLASS_ALREADY_EXISTS );
|
||||
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 );
|
||||
return;
|
||||
}
|
||||
|
@ -139,10 +182,11 @@ DECL_HANDLER(create_class)
|
|||
release_global_atom( req->atom );
|
||||
return;
|
||||
}
|
||||
class->atom = req->atom;
|
||||
class->instance = req->instance;
|
||||
class->style = req->style;
|
||||
class->win_extra = req->win_extra;
|
||||
class->atom = req->atom;
|
||||
class->instance = req->instance;
|
||||
class->style = req->style;
|
||||
class->win_extra = req->win_extra;
|
||||
class->client_ptr = req->client_ptr;
|
||||
}
|
||||
|
||||
/* destroy a window class */
|
||||
|
@ -151,11 +195,14 @@ DECL_HANDLER(destroy_class)
|
|||
struct window_class *class = find_class( current->process, req->atom, req->instance );
|
||||
|
||||
if (!class)
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
set_win32_error( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
else if (class->count)
|
||||
set_win32_error( ERROR_CLASS_HAS_WINDOWS );
|
||||
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)
|
|||
|
||||
if (!class) return;
|
||||
|
||||
if (req->flags && class->process != current->process)
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->extra_size > sizeof(req->extra_value) ||
|
||||
req->extra_offset < -1 ||
|
||||
req->extra_offset > class->nb_extra_bytes - (int)req->extra_size)
|
||||
|
@ -173,6 +226,11 @@ DECL_HANDLER(set_class_info)
|
|||
set_win32_error( ERROR_INVALID_INDEX );
|
||||
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)
|
||||
{
|
||||
memcpy( &reply->old_extra_value, class->extra_bytes + req->extra_offset, req->extra_size );
|
||||
|
@ -201,4 +259,3 @@ DECL_HANDLER(set_class_info)
|
|||
if (req->flags & SET_CLASS_EXTRA) memcpy( class->extra_bytes + req->extra_offset,
|
||||
&req->extra_value, req->extra_size );
|
||||
}
|
||||
|
||||
|
|
|
@ -1781,9 +1781,10 @@ enum message_type
|
|||
user_handle_t owner; /* owner window */
|
||||
atom_t atom; /* class atom */
|
||||
void* instance; /* module instance */
|
||||
int extra; /* number of extra bytes */
|
||||
@REPLY
|
||||
user_handle_t handle; /* created window */
|
||||
int extra; /* number of extra bytes */
|
||||
void* class_ptr; /* pointer to class in client address space */
|
||||
@END
|
||||
|
||||
|
||||
|
@ -2138,6 +2139,7 @@ enum message_type
|
|||
void* instance; /* module instance */
|
||||
int extra; /* number of extra class bytes */
|
||||
int win_extra; /* number of window extra bytes */
|
||||
void* client_ptr; /* pointer to class in client address space */
|
||||
@END
|
||||
|
||||
|
||||
|
@ -2145,6 +2147,8 @@ enum message_type
|
|||
@REQ(destroy_class)
|
||||
atom_t atom; /* class atom */
|
||||
void* instance; /* module instance */
|
||||
@REPLY
|
||||
void* client_ptr; /* pointer to class in client address space */
|
||||
@END
|
||||
|
||||
|
||||
|
|
|
@ -2096,13 +2096,14 @@ static void dump_create_window_request( const struct create_window_request *req
|
|||
fprintf( stderr, " parent=%p,", req->parent );
|
||||
fprintf( stderr, " owner=%p,", req->owner );
|
||||
fprintf( stderr, " atom=%04x,", req->atom );
|
||||
fprintf( stderr, " instance=%p,", req->instance );
|
||||
fprintf( stderr, " extra=%d", req->extra );
|
||||
fprintf( stderr, " instance=%p", req->instance );
|
||||
}
|
||||
|
||||
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 )
|
||||
|
@ -2511,7 +2512,8 @@ static void dump_create_class_request( const struct create_class_request *req )
|
|||
fprintf( stderr, " style=%08x,", req->style );
|
||||
fprintf( stderr, " instance=%p,", req->instance );
|
||||
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 )
|
||||
|
@ -2520,6 +2522,11 @@ static void dump_destroy_class_request( const struct destroy_class_request *req
|
|||
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 )
|
||||
{
|
||||
fprintf( stderr, " window=%p,", req->window );
|
||||
|
@ -2952,7 +2959,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)0,
|
||||
(dump_func)dump_get_next_hook_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_destroy_class_reply,
|
||||
(dump_func)dump_set_class_info_reply,
|
||||
(dump_func)dump_set_clipboard_info_reply,
|
||||
(dump_func)dump_open_token_reply,
|
||||
|
|
|
@ -78,8 +78,10 @@ extern struct window_class *get_window_class( user_handle_t window );
|
|||
/* window class functions */
|
||||
|
||||
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 atom_t get_class_atom( struct window_class *class );
|
||||
extern void *get_class_client_ptr( struct window_class *class );
|
||||
|
||||
#endif /* __WINE_SERVER_USER_H */
|
||||
|
|
|
@ -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) */
|
||||
static struct window *create_window( struct window *parent, struct window *owner, atom_t atom,
|
||||
void *instance, int extra_bytes )
|
||||
static struct window *create_window( struct window *parent, struct window *owner,
|
||||
atom_t atom, void *instance )
|
||||
{
|
||||
int extra_bytes;
|
||||
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;
|
||||
|
||||
|
@ -474,25 +475,22 @@ struct window_class* get_window_class( user_handle_t window )
|
|||
/* create a window */
|
||||
DECL_HANDLER(create_window)
|
||||
{
|
||||
struct window *win;
|
||||
|
||||
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 (!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->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
}
|
||||
reply->handle = top_window->handle;
|
||||
win = top_window;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct window *win, *parent, *owner = NULL;
|
||||
struct window *parent, *owner = NULL;
|
||||
|
||||
if (!(parent = get_window( req->parent ))) return;
|
||||
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||
|
@ -503,9 +501,11 @@ DECL_HANDLER(create_window)
|
|||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
if (!(win = create_window( parent, owner, req->atom, req->instance, req->extra ))) return;
|
||||
reply->handle = win->handle;
|
||||
if (!(win = create_window( parent, owner, req->atom, req->instance ))) return;
|
||||
}
|
||||
reply->handle = win->handle;
|
||||
reply->extra = win->nb_extra_bytes;
|
||||
reply->class_ptr = get_class_client_ptr( win->class );
|
||||
}
|
||||
|
||||
|
||||
|
|
153
windows/class.c
153
windows/class.c
|
@ -67,6 +67,7 @@ typedef struct tagCLASS
|
|||
} CLASS;
|
||||
|
||||
static struct list class_list = LIST_INIT( class_list );
|
||||
static CLASS *desktop_class;
|
||||
static HMODULE user32_module;
|
||||
|
||||
#define CLASS_OTHER_PROCESS ((CLASS *)1)
|
||||
|
@ -293,37 +294,22 @@ static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
|
|||
*
|
||||
* Free a class structure.
|
||||
*/
|
||||
static BOOL CLASS_FreeClass( CLASS *classPtr )
|
||||
static void CLASS_FreeClass( CLASS *classPtr )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p\n", classPtr);
|
||||
|
||||
SERVER_START_REQ( destroy_class )
|
||||
{
|
||||
req->atom = classPtr->atomName;
|
||||
req->instance = classPtr->hInstance;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
USER_Lock();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
list_remove( &classPtr->entry );
|
||||
|
||||
/* Delete the class */
|
||||
|
||||
if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
|
||||
if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
|
||||
DeleteObject( classPtr->hbrBackground );
|
||||
GlobalDeleteAtom( classPtr->atomName );
|
||||
WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
|
||||
WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
|
||||
UnMapLS( classPtr->segMenuName );
|
||||
HeapFree( GetProcessHeap(), 0, classPtr->menuName );
|
||||
HeapFree( GetProcessHeap(), 0, classPtr );
|
||||
}
|
||||
return ret;
|
||||
list_remove( &classPtr->entry );
|
||||
if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
|
||||
if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
|
||||
DeleteObject( classPtr->hbrBackground );
|
||||
WINPROC_FreeProc( classPtr->winprocA, WIN_PROC_CLASS );
|
||||
WINPROC_FreeProc( classPtr->winprocW, WIN_PROC_CLASS );
|
||||
UnMapLS( classPtr->segMenuName );
|
||||
HeapFree( GetProcessHeap(), 0, classPtr->menuName );
|
||||
HeapFree( GetProcessHeap(), 0, classPtr );
|
||||
USER_Unlock();
|
||||
}
|
||||
|
||||
|
||||
|
@ -341,7 +327,19 @@ void CLASS_FreeModuleClasses( HMODULE16 hModule )
|
|||
{
|
||||
CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
|
||||
next = list_next( &class_list, ptr );
|
||||
if (class->hInstance == HINSTANCE_32(hModule)) CLASS_FreeClass( class );
|
||||
if (class->hInstance == HINSTANCE_32(hModule))
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( destroy_class )
|
||||
{
|
||||
req->atom = class->atomName;
|
||||
req->instance = class->hInstance;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) CLASS_FreeClass( class );
|
||||
}
|
||||
}
|
||||
USER_Unlock();
|
||||
}
|
||||
|
@ -357,6 +355,8 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
|
|||
{
|
||||
struct list *ptr;
|
||||
|
||||
USER_Lock();
|
||||
|
||||
LIST_FOR_EACH( ptr, &class_list )
|
||||
{
|
||||
CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
|
||||
|
@ -367,6 +367,7 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
|
|||
return class;
|
||||
}
|
||||
}
|
||||
USER_Unlock();
|
||||
TRACE("0x%04x %p -> not found\n", atom, hinstance);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -376,6 +377,7 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
|
|||
* CLASS_RegisterClass
|
||||
*
|
||||
* The real RegisterClass() functionality.
|
||||
* The atom is deleted no matter what.
|
||||
*/
|
||||
static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
|
||||
DWORD style, INT classExtra, INT winExtra )
|
||||
|
@ -396,19 +398,25 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
|
|||
WARN("Win extra bytes %d is > 40\n", winExtra );
|
||||
|
||||
classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
|
||||
if (!classPtr) return NULL;
|
||||
if (!classPtr)
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( create_class )
|
||||
{
|
||||
req->local = local;
|
||||
req->atom = atom;
|
||||
req->style = style;
|
||||
req->instance = hInstance;
|
||||
req->extra = classExtra;
|
||||
req->win_extra = winExtra;
|
||||
req->local = local;
|
||||
req->atom = atom;
|
||||
req->style = style;
|
||||
req->instance = hInstance;
|
||||
req->extra = classExtra;
|
||||
req->win_extra = winExtra;
|
||||
req->client_ptr = classPtr;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
GlobalDeleteAtom( atom ); /* the server increased the atom ref count */
|
||||
if (!ret)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, classPtr );
|
||||
|
@ -425,6 +433,7 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
|
|||
|
||||
/* Other non-null values must be set by caller */
|
||||
|
||||
USER_Lock();
|
||||
if (local) list_add_head( &class_list, &classPtr->entry );
|
||||
else list_add_tail( &class_list, &classPtr->entry );
|
||||
return classPtr;
|
||||
|
@ -437,7 +446,7 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
|
|||
* Register a builtin control class.
|
||||
* This allows having both ASCII and Unicode winprocs for the same class.
|
||||
*/
|
||||
static ATOM register_builtin( const struct builtin_class_descr *descr )
|
||||
static CLASS *register_builtin( const struct builtin_class_descr *descr )
|
||||
{
|
||||
ATOM atom;
|
||||
CLASS *classPtr;
|
||||
|
@ -445,11 +454,7 @@ static ATOM register_builtin( const struct builtin_class_descr *descr )
|
|||
if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
|
||||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, user32_module, FALSE,
|
||||
descr->style, 0, descr->extra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
}
|
||||
descr->style, 0, descr->extra ))) return 0;
|
||||
|
||||
classPtr->hCursor = LoadCursorA( 0, (LPSTR)descr->cursor );
|
||||
classPtr->hbrBackground = descr->brush;
|
||||
|
@ -458,7 +463,8 @@ static ATOM register_builtin( const struct builtin_class_descr *descr )
|
|||
WIN_PROC_32A, WIN_PROC_CLASS );
|
||||
if (descr->procW) WINPROC_SetProc( &classPtr->winprocW, descr->procW,
|
||||
WIN_PROC_32W, WIN_PROC_CLASS );
|
||||
return atom;
|
||||
release_class_ptr( classPtr );
|
||||
return classPtr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -481,11 +487,11 @@ void CLASS_RegisterBuiltinClasses( HMODULE user32 )
|
|||
extern const struct builtin_class_descr STATIC_builtin_class;
|
||||
|
||||
user32_module = user32;
|
||||
desktop_class = register_builtin( &DESKTOP_builtin_class );
|
||||
register_builtin( &BUTTON_builtin_class );
|
||||
register_builtin( &COMBO_builtin_class );
|
||||
register_builtin( &COMBOLBOX_builtin_class );
|
||||
register_builtin( &DIALOG_builtin_class );
|
||||
register_builtin( &DESKTOP_builtin_class );
|
||||
register_builtin( &EDIT_builtin_class );
|
||||
register_builtin( &ICONTITLE_builtin_class );
|
||||
register_builtin( &LISTBOX_builtin_class );
|
||||
|
@ -499,29 +505,24 @@ void CLASS_RegisterBuiltinClasses( HMODULE user32 )
|
|||
/***********************************************************************
|
||||
* CLASS_AddWindow
|
||||
*
|
||||
* Add a new window using this class, and return the necessary
|
||||
* information for creating the window.
|
||||
* Add a new window using this class, and set the necessary
|
||||
* information inside the window structure.
|
||||
*/
|
||||
CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
|
||||
INT *winExtra, WNDPROC *winproc, DWORD *style, struct tagDCE **dce )
|
||||
void CLASS_AddWindow( CLASS *class, WND *win, WINDOWPROCTYPE type )
|
||||
{
|
||||
CLASS *class;
|
||||
if (type == WIN_PROC_16) inst = HINSTANCE_32(GetExePtr(HINSTANCE_16(inst)));
|
||||
|
||||
if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
|
||||
if (!class) class = desktop_class;
|
||||
|
||||
if (type == WIN_PROC_32W)
|
||||
{
|
||||
if (!(*winproc = class->winprocW)) *winproc = class->winprocA;
|
||||
if (!(win->winproc = class->winprocW)) win->winproc = class->winprocA;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(*winproc = class->winprocA)) *winproc = class->winprocW;
|
||||
if (!(win->winproc = class->winprocA)) win->winproc = class->winprocW;
|
||||
}
|
||||
*winExtra = class->cbWndExtra;
|
||||
*style = class->style;
|
||||
*dce = class->dce;
|
||||
return class;
|
||||
win->class = class;
|
||||
win->clsStyle = class->style;
|
||||
win->dce = class->dce;
|
||||
}
|
||||
|
||||
|
||||
|
@ -612,10 +613,7 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
|
|||
if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, hInstance, !(wc->style & CS_GLOBALCLASS),
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE("atom=%04x wndproc=%p hinst=%p bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
|
||||
atom, wc->lpfnWndProc, hInstance,
|
||||
|
@ -630,6 +628,7 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
|
|||
WINPROC_SetProc( &classPtr->winprocA, (WNDPROC)wc->lpfnWndProc,
|
||||
WIN_PROC_16, WIN_PROC_CLASS );
|
||||
CLASS_SetMenuNameA( classPtr, MapSL(wc->lpszMenuName) );
|
||||
release_class_ptr( classPtr );
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -655,10 +654,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
|
|||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
|
||||
atom, wc->lpfnWndProc, instance, wc->hbrBackground,
|
||||
|
@ -670,6 +666,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
|
|||
classPtr->hbrBackground = wc->hbrBackground;
|
||||
WINPROC_SetProc( &classPtr->winprocA, wc->lpfnWndProc, WIN_PROC_32A, WIN_PROC_CLASS );
|
||||
CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
|
||||
release_class_ptr( classPtr );
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -695,10 +692,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
|
|||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
|
||||
atom, wc->lpfnWndProc, instance, wc->hbrBackground,
|
||||
|
@ -710,6 +704,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
|
|||
classPtr->hbrBackground = wc->hbrBackground;
|
||||
WINPROC_SetProc( &classPtr->winprocW, wc->lpfnWndProc, WIN_PROC_32W, WIN_PROC_CLASS );
|
||||
CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
|
||||
release_class_ptr( classPtr );
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -737,22 +732,29 @@ BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
|
|||
*/
|
||||
BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
|
||||
{
|
||||
CLASS *classPtr;
|
||||
BOOL ret = FALSE;
|
||||
CLASS *classPtr = NULL;
|
||||
ATOM atom = HIWORD(className) ? GlobalFindAtomW( className ) : LOWORD(className);
|
||||
|
||||
TRACE("%s %p %x\n",debugstr_w(className), hInstance, atom);
|
||||
|
||||
if (!atom)
|
||||
{
|
||||
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!hInstance) hInstance = GetModuleHandleW( NULL );
|
||||
|
||||
USER_Lock();
|
||||
if (atom && (classPtr = CLASS_FindClassByAtom( atom, hInstance )))
|
||||
SERVER_START_REQ( destroy_class )
|
||||
{
|
||||
ret = CLASS_FreeClass( classPtr );
|
||||
req->atom = atom;
|
||||
req->instance = hInstance;
|
||||
if (!wine_server_call_err( req )) classPtr = reply->client_ptr;
|
||||
}
|
||||
else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
USER_Unlock();
|
||||
return ret;
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (classPtr) CLASS_FreeClass( classPtr );
|
||||
return (classPtr != NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1286,6 +1288,7 @@ BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *
|
|||
wc->lpszClassName = (SEGPTR)0;
|
||||
wc->lpszMenuName = CLASS_GetMenuName16( classPtr );
|
||||
wc->lpszClassName = name;
|
||||
release_class_ptr( classPtr );
|
||||
|
||||
/* We must return the atom of the class here instead of just TRUE. */
|
||||
return atom;
|
||||
|
@ -1320,6 +1323,7 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
|
|||
wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
|
||||
wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
|
||||
wc->lpszClassName = name;
|
||||
release_class_ptr( classPtr );
|
||||
|
||||
/* We must return the atom of the class here instead of just TRUE. */
|
||||
return atom;
|
||||
|
@ -1354,6 +1358,7 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc
|
|||
wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
|
||||
wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
|
||||
wc->lpszClassName = name;
|
||||
release_class_ptr( classPtr );
|
||||
|
||||
/* We must return the atom of the class here instead of just TRUE. */
|
||||
return atom;
|
||||
|
|
|
@ -65,23 +65,13 @@ static void *user_handles[NB_USER_HANDLES];
|
|||
static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
|
||||
HINSTANCE instance, WINDOWPROCTYPE type )
|
||||
{
|
||||
BOOL res;
|
||||
WORD index;
|
||||
WND *win;
|
||||
DCE *dce;
|
||||
INT extra_bytes;
|
||||
DWORD clsStyle;
|
||||
WNDPROC winproc;
|
||||
struct tagCLASS *class;
|
||||
struct tagCLASS *class = NULL;
|
||||
user_handle_t handle = 0;
|
||||
int extra_bytes = 0;
|
||||
|
||||
if (!(class = CLASS_AddWindow( atom, instance, type, &extra_bytes, &winproc, &clsStyle, &dce )))
|
||||
return NULL;
|
||||
|
||||
if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
|
||||
return NULL;
|
||||
|
||||
USER_Lock();
|
||||
if (type == WIN_PROC_16) instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
|
||||
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
|
@ -89,29 +79,44 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
|
|||
req->owner = owner;
|
||||
req->atom = atom;
|
||||
req->instance = instance;
|
||||
req->extra = extra_bytes;
|
||||
if ((res = !wine_server_call_err( req ))) handle = reply->handle;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
handle = reply->handle;
|
||||
extra_bytes = reply->extra;
|
||||
class = reply->class_ptr;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (!res)
|
||||
if (!handle)
|
||||
{
|
||||
USER_Unlock();
|
||||
HeapFree( GetProcessHeap(), 0, win );
|
||||
WARN( "error %ld creating window\n", GetLastError() );
|
||||
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;
|
||||
assert( index < NB_USER_HANDLES );
|
||||
user_handles[index] = win;
|
||||
win->hwndSelf = handle;
|
||||
win->dwMagic = WND_MAGIC;
|
||||
win->irefCount = 1;
|
||||
win->class = class;
|
||||
win->winproc = winproc;
|
||||
win->dce = dce;
|
||||
win->clsStyle = clsStyle;
|
||||
win->cbWndExtra = extra_bytes;
|
||||
memset( win->wExtra, 0, extra_bytes );
|
||||
CLASS_AddWindow( class, win, type );
|
||||
return win;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue