Added window classes in the server, and support for inter-process
GetClassWord/Long (based on a patch by Mike McCormack). Various fixes to the class instance handling.
This commit is contained in:
parent
08d01923e5
commit
bfce151ae5
|
@ -127,41 +127,6 @@ static BOOL load_driver(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* controls_init
|
||||
*
|
||||
* Register the classes for the builtin controls
|
||||
*/
|
||||
static void controls_init(void)
|
||||
{
|
||||
extern const struct builtin_class_descr BUTTON_builtin_class;
|
||||
extern const struct builtin_class_descr COMBO_builtin_class;
|
||||
extern const struct builtin_class_descr COMBOLBOX_builtin_class;
|
||||
extern const struct builtin_class_descr DIALOG_builtin_class;
|
||||
extern const struct builtin_class_descr DESKTOP_builtin_class;
|
||||
extern const struct builtin_class_descr EDIT_builtin_class;
|
||||
extern const struct builtin_class_descr ICONTITLE_builtin_class;
|
||||
extern const struct builtin_class_descr LISTBOX_builtin_class;
|
||||
extern const struct builtin_class_descr MDICLIENT_builtin_class;
|
||||
extern const struct builtin_class_descr MENU_builtin_class;
|
||||
extern const struct builtin_class_descr SCROLL_builtin_class;
|
||||
extern const struct builtin_class_descr STATIC_builtin_class;
|
||||
|
||||
CLASS_RegisterBuiltinClass( &BUTTON_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &COMBO_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &COMBOLBOX_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &DIALOG_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &DESKTOP_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &EDIT_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &ICONTITLE_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &LISTBOX_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &MDICLIENT_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &MENU_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &SCROLL_builtin_class );
|
||||
CLASS_RegisterBuiltinClass( &STATIC_builtin_class );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* palette_init
|
||||
*
|
||||
|
@ -219,7 +184,7 @@ static void tweak_init(void)
|
|||
/***********************************************************************
|
||||
* USER initialisation routine
|
||||
*/
|
||||
static BOOL process_attach(void)
|
||||
static BOOL process_attach( HINSTANCE inst )
|
||||
{
|
||||
HINSTANCE16 instance;
|
||||
|
||||
|
@ -243,7 +208,7 @@ static BOOL process_attach(void)
|
|||
palette_init();
|
||||
|
||||
/* Initialize built-in window classes */
|
||||
controls_init();
|
||||
CLASS_RegisterBuiltinClasses( inst );
|
||||
|
||||
/* Initialize menus */
|
||||
if (!MENU_Init()) return FALSE;
|
||||
|
@ -304,7 +269,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
|
|||
switch(reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
ret = process_attach();
|
||||
ret = process_attach( inst );
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
thread_detach();
|
||||
|
|
|
@ -137,13 +137,11 @@ inline static void unmap_str_16_to_32W( LPCWSTR str )
|
|||
|
||||
/* Class functions */
|
||||
struct tagCLASS; /* opaque structure */
|
||||
struct builtin_class_descr;
|
||||
struct tagDCE;
|
||||
extern ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr );
|
||||
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_RemoveWindow( struct tagCLASS *cls );
|
||||
extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
|
||||
|
||||
/* Timer functions */
|
||||
|
|
|
@ -2525,6 +2525,7 @@ struct create_window_request
|
|||
user_handle_t parent;
|
||||
user_handle_t owner;
|
||||
atom_t atom;
|
||||
void* instance;
|
||||
int extra;
|
||||
};
|
||||
struct create_window_reply
|
||||
|
@ -3052,6 +3053,67 @@ struct get_next_hook_reply
|
|||
|
||||
|
||||
|
||||
struct create_class_request
|
||||
{
|
||||
struct request_header __header;
|
||||
int local;
|
||||
atom_t atom;
|
||||
unsigned int style;
|
||||
void* instance;
|
||||
int extra;
|
||||
int win_extra;
|
||||
};
|
||||
struct create_class_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct destroy_class_request
|
||||
{
|
||||
struct request_header __header;
|
||||
atom_t atom;
|
||||
void* instance;
|
||||
};
|
||||
struct destroy_class_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_class_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t window;
|
||||
unsigned int flags;
|
||||
atom_t atom;
|
||||
unsigned int style;
|
||||
int win_extra;
|
||||
void* instance;
|
||||
int extra_offset;
|
||||
size_t extra_size;
|
||||
unsigned int extra_value;
|
||||
};
|
||||
struct set_class_info_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
atom_t old_atom;
|
||||
unsigned int old_style;
|
||||
int old_extra;
|
||||
int old_win_extra;
|
||||
void* old_instance;
|
||||
unsigned int old_extra_value;
|
||||
};
|
||||
#define SET_CLASS_ATOM 0x0001
|
||||
#define SET_CLASS_STYLE 0x0002
|
||||
#define SET_CLASS_WINEXTRA 0x0004
|
||||
#define SET_CLASS_INSTANCE 0x0008
|
||||
#define SET_CLASS_EXTRA 0x0010
|
||||
|
||||
|
||||
|
||||
struct set_clipboard_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -3298,6 +3360,9 @@ enum request
|
|||
REQ_start_hook_chain,
|
||||
REQ_finish_hook_chain,
|
||||
REQ_get_next_hook,
|
||||
REQ_create_class,
|
||||
REQ_destroy_class,
|
||||
REQ_set_class_info,
|
||||
REQ_set_clipboard_info,
|
||||
REQ_open_token,
|
||||
REQ_set_global_windows,
|
||||
|
@ -3484,6 +3549,9 @@ union generic_request
|
|||
struct start_hook_chain_request start_hook_chain_request;
|
||||
struct finish_hook_chain_request finish_hook_chain_request;
|
||||
struct get_next_hook_request get_next_hook_request;
|
||||
struct create_class_request create_class_request;
|
||||
struct destroy_class_request destroy_class_request;
|
||||
struct set_class_info_request set_class_info_request;
|
||||
struct set_clipboard_info_request set_clipboard_info_request;
|
||||
struct open_token_request open_token_request;
|
||||
struct set_global_windows_request set_global_windows_request;
|
||||
|
@ -3668,11 +3736,14 @@ union generic_reply
|
|||
struct start_hook_chain_reply start_hook_chain_reply;
|
||||
struct finish_hook_chain_reply finish_hook_chain_reply;
|
||||
struct get_next_hook_reply get_next_hook_reply;
|
||||
struct create_class_reply create_class_reply;
|
||||
struct destroy_class_reply destroy_class_reply;
|
||||
struct set_class_info_reply set_class_info_reply;
|
||||
struct set_clipboard_info_reply set_clipboard_info_reply;
|
||||
struct open_token_reply open_token_reply;
|
||||
struct set_global_windows_reply set_global_windows_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 128
|
||||
#define SERVER_PROTOCOL_VERSION 129
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -9,6 +9,7 @@ C_SRCS = \
|
|||
async.c \
|
||||
atom.c \
|
||||
change.c \
|
||||
class.c \
|
||||
clipboard.c \
|
||||
console.c \
|
||||
context_i386.c \
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Server-side window class management
|
||||
*
|
||||
* Copyright (C) 2002 Mike McCormack
|
||||
* Copyright (C) 2003 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "request.h"
|
||||
#include "object.h"
|
||||
#include "process.h"
|
||||
#include "user.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 */
|
||||
void *instance; /* module instance */
|
||||
unsigned int style; /* class style */
|
||||
int win_extra; /* number of window extra bytes */
|
||||
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 )
|
||||
{
|
||||
struct window_class *class;
|
||||
|
||||
if (!(class = mem_alloc( sizeof(*class) + extra_bytes - 1 ))) return NULL;
|
||||
|
||||
class->process = (struct process *)grab_object( process );
|
||||
class->count = 0;
|
||||
class->local = local;
|
||||
class->nb_extra_bytes = extra_bytes;
|
||||
memset( class->extra_bytes, 0, extra_bytes );
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void destroy_class( struct window_class *class )
|
||||
{
|
||||
list_remove( &class->entry );
|
||||
release_object( class->process );
|
||||
free( class );
|
||||
}
|
||||
|
||||
void destroy_process_classes( struct process *process )
|
||||
{
|
||||
struct list *ptr;
|
||||
|
||||
while ((ptr = list_head( &process->classes )))
|
||||
{
|
||||
struct window_class *class = LIST_ENTRY( ptr, struct window_class, entry );
|
||||
destroy_class( class );
|
||||
}
|
||||
}
|
||||
|
||||
static struct window_class *find_class( struct process *process, atom_t atom, void *instance )
|
||||
{
|
||||
struct list *ptr;
|
||||
|
||||
LIST_FOR_EACH( ptr, &process->classes )
|
||||
{
|
||||
struct window_class *class = LIST_ENTRY( ptr, struct window_class, entry );
|
||||
if (class->atom != atom) continue;
|
||||
if (!instance || !class->local || class->instance == instance) return class;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct window_class *grab_class( struct process *process, atom_t atom, void *instance )
|
||||
{
|
||||
struct window_class *class = find_class( process, atom, instance );
|
||||
if (class) class->count++;
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
return class;
|
||||
}
|
||||
|
||||
void release_class( struct window_class *class )
|
||||
{
|
||||
assert( class->count > 0 );
|
||||
class->count--;
|
||||
}
|
||||
|
||||
atom_t get_class_atom( struct window_class *class )
|
||||
{
|
||||
return class->atom;
|
||||
}
|
||||
|
||||
/* create a window class */
|
||||
DECL_HANDLER(create_class)
|
||||
{
|
||||
struct window_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 */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if (!grab_global_atom( req->atom )) return;
|
||||
|
||||
if (!(class = create_class( current->process, req->extra, req->local )))
|
||||
{
|
||||
release_global_atom( req->atom );
|
||||
return;
|
||||
}
|
||||
class->atom = req->atom;
|
||||
class->instance = req->instance;
|
||||
class->style = req->style;
|
||||
class->win_extra = req->win_extra;
|
||||
}
|
||||
|
||||
/* destroy a window class */
|
||||
DECL_HANDLER(destroy_class)
|
||||
{
|
||||
struct window_class *class = find_class( current->process, req->atom, req->instance );
|
||||
|
||||
if (!class)
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
else if (class->count)
|
||||
set_win32_error( ERROR_CLASS_HAS_WINDOWS );
|
||||
else
|
||||
destroy_class( class );
|
||||
}
|
||||
|
||||
|
||||
/* set some information in a class */
|
||||
DECL_HANDLER(set_class_info)
|
||||
{
|
||||
struct window_class *class = get_window_class( req->window );
|
||||
|
||||
if (!class) return;
|
||||
|
||||
if (req->extra_size > sizeof(req->extra_value) ||
|
||||
req->extra_offset < -1 ||
|
||||
req->extra_offset > class->nb_extra_bytes - (int)req->extra_size)
|
||||
{
|
||||
set_win32_error( ERROR_INVALID_INDEX );
|
||||
return;
|
||||
}
|
||||
if (req->extra_offset != -1)
|
||||
{
|
||||
memcpy( &reply->old_extra_value, class->extra_bytes + req->extra_offset, req->extra_size );
|
||||
}
|
||||
else if (req->flags & SET_CLASS_EXTRA)
|
||||
{
|
||||
set_win32_error( ERROR_INVALID_INDEX );
|
||||
return;
|
||||
}
|
||||
|
||||
reply->old_atom = class->atom;
|
||||
reply->old_style = class->style;
|
||||
reply->old_extra = class->nb_extra_bytes;
|
||||
reply->old_win_extra = class->win_extra;
|
||||
reply->old_instance = class->instance;
|
||||
|
||||
if (req->flags & SET_CLASS_ATOM)
|
||||
{
|
||||
if (!grab_global_atom( req->atom )) return;
|
||||
release_global_atom( class->atom );
|
||||
class->atom = req->atom;
|
||||
}
|
||||
if (req->flags & SET_CLASS_STYLE) class->style = req->style;
|
||||
if (req->flags & SET_CLASS_WINEXTRA) class->win_extra = req->win_extra;
|
||||
if (req->flags & SET_CLASS_INSTANCE) class->instance = req->instance;
|
||||
if (req->flags & SET_CLASS_EXTRA) memcpy( class->extra_bytes + req->extra_offset,
|
||||
&req->extra_value, req->extra_size );
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
#include "thread.h"
|
||||
#include "request.h"
|
||||
#include "console.h"
|
||||
#include "user.h"
|
||||
|
||||
/* process structure */
|
||||
|
||||
|
@ -283,6 +284,7 @@ struct thread *create_process( int fd )
|
|||
process->group_id = 0;
|
||||
process->token = create_token();
|
||||
list_init( &process->locks );
|
||||
list_init( &process->classes );
|
||||
|
||||
gettimeofday( &process->start_time, NULL );
|
||||
if ((process->next = first_process) != NULL) process->next->prev = process;
|
||||
|
@ -597,6 +599,7 @@ static void process_killed( struct process *process )
|
|||
if (dll->filename) free( dll->filename );
|
||||
free( dll );
|
||||
}
|
||||
destroy_process_classes( process );
|
||||
set_process_startup_state( process, STARTUP_ABORTED );
|
||||
if (process->exe.file) release_object( process->exe.file );
|
||||
process->exe.file = NULL;
|
||||
|
|
|
@ -68,6 +68,7 @@ struct process
|
|||
int suspend; /* global process suspend count */
|
||||
int create_flags; /* process creation flags */
|
||||
struct list locks; /* list of file locks owned by the process */
|
||||
struct list classes; /* window classes owned by the process */
|
||||
struct console_input*console; /* console input */
|
||||
enum startup_state startup_state; /* startup state */
|
||||
struct startup_info *startup_info; /* startup info while init is in progress */
|
||||
|
|
|
@ -1780,6 +1780,7 @@ enum message_type
|
|||
user_handle_t parent; /* parent window */
|
||||
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 */
|
||||
|
@ -2129,6 +2130,50 @@ enum message_type
|
|||
@END
|
||||
|
||||
|
||||
/* Create a window class */
|
||||
@REQ(create_class)
|
||||
int local; /* is it a local class? */
|
||||
atom_t atom; /* class atom */
|
||||
unsigned int style; /* class style */
|
||||
void* instance; /* module instance */
|
||||
int extra; /* number of extra class bytes */
|
||||
int win_extra; /* number of window extra bytes */
|
||||
@END
|
||||
|
||||
|
||||
/* Destroy a window class */
|
||||
@REQ(destroy_class)
|
||||
atom_t atom; /* class atom */
|
||||
void* instance; /* module instance */
|
||||
@END
|
||||
|
||||
|
||||
/* Set some information in a class */
|
||||
@REQ(set_class_info)
|
||||
user_handle_t window; /* handle to the window */
|
||||
unsigned int flags; /* flags for info to set (see below) */
|
||||
atom_t atom; /* class atom */
|
||||
unsigned int style; /* class style */
|
||||
int win_extra; /* number of window extra bytes */
|
||||
void* instance; /* module instance */
|
||||
int extra_offset; /* offset to set in extra bytes */
|
||||
size_t extra_size; /* size to set in extra bytes */
|
||||
unsigned int extra_value; /* value to set in extra bytes */
|
||||
@REPLY
|
||||
atom_t old_atom; /* previous class atom */
|
||||
unsigned int old_style; /* previous class style */
|
||||
int old_extra; /* previous number of class extra bytes */
|
||||
int old_win_extra; /* previous number of window extra bytes */
|
||||
void* old_instance; /* previous module instance */
|
||||
unsigned int old_extra_value; /* old value in extra bytes */
|
||||
@END
|
||||
#define SET_CLASS_ATOM 0x0001
|
||||
#define SET_CLASS_STYLE 0x0002
|
||||
#define SET_CLASS_WINEXTRA 0x0004
|
||||
#define SET_CLASS_INSTANCE 0x0008
|
||||
#define SET_CLASS_EXTRA 0x0010
|
||||
|
||||
|
||||
/* Set/get clipboard information */
|
||||
@REQ(set_clipboard_info)
|
||||
unsigned int flags; /* flags for fields to set (see below) */
|
||||
|
|
|
@ -279,6 +279,9 @@ DECL_HANDLER(remove_hook);
|
|||
DECL_HANDLER(start_hook_chain);
|
||||
DECL_HANDLER(finish_hook_chain);
|
||||
DECL_HANDLER(get_next_hook);
|
||||
DECL_HANDLER(create_class);
|
||||
DECL_HANDLER(destroy_class);
|
||||
DECL_HANDLER(set_class_info);
|
||||
DECL_HANDLER(set_clipboard_info);
|
||||
DECL_HANDLER(open_token);
|
||||
DECL_HANDLER(set_global_windows);
|
||||
|
@ -464,6 +467,9 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_start_hook_chain,
|
||||
(req_handler)req_finish_hook_chain,
|
||||
(req_handler)req_get_next_hook,
|
||||
(req_handler)req_create_class,
|
||||
(req_handler)req_destroy_class,
|
||||
(req_handler)req_set_class_info,
|
||||
(req_handler)req_set_clipboard_info,
|
||||
(req_handler)req_open_token,
|
||||
(req_handler)req_set_global_windows,
|
||||
|
|
|
@ -2096,6 +2096,7 @@ 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 );
|
||||
}
|
||||
|
||||
|
@ -2503,6 +2504,45 @@ static void dump_get_next_hook_reply( const struct get_next_hook_reply *req )
|
|||
dump_varargs_unicode_str( cur_size );
|
||||
}
|
||||
|
||||
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, " style=%08x,", req->style );
|
||||
fprintf( stderr, " instance=%p,", req->instance );
|
||||
fprintf( stderr, " extra=%d,", req->extra );
|
||||
fprintf( stderr, " win_extra=%d", req->win_extra );
|
||||
}
|
||||
|
||||
static void dump_destroy_class_request( const struct destroy_class_request *req )
|
||||
{
|
||||
fprintf( stderr, " atom=%04x,", req->atom );
|
||||
fprintf( stderr, " instance=%p", req->instance );
|
||||
}
|
||||
|
||||
static void dump_set_class_info_request( const struct set_class_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " window=%p,", req->window );
|
||||
fprintf( stderr, " flags=%08x,", req->flags );
|
||||
fprintf( stderr, " atom=%04x,", req->atom );
|
||||
fprintf( stderr, " style=%08x,", req->style );
|
||||
fprintf( stderr, " win_extra=%d,", req->win_extra );
|
||||
fprintf( stderr, " instance=%p,", req->instance );
|
||||
fprintf( stderr, " extra_offset=%d,", req->extra_offset );
|
||||
fprintf( stderr, " extra_size=%d,", req->extra_size );
|
||||
fprintf( stderr, " extra_value=%08x", req->extra_value );
|
||||
}
|
||||
|
||||
static void dump_set_class_info_reply( const struct set_class_info_reply *req )
|
||||
{
|
||||
fprintf( stderr, " old_atom=%04x,", req->old_atom );
|
||||
fprintf( stderr, " old_style=%08x,", req->old_style );
|
||||
fprintf( stderr, " old_extra=%d,", req->old_extra );
|
||||
fprintf( stderr, " old_win_extra=%d,", req->old_win_extra );
|
||||
fprintf( stderr, " old_instance=%p,", req->old_instance );
|
||||
fprintf( stderr, " old_extra_value=%08x", req->old_extra_value );
|
||||
}
|
||||
|
||||
static void dump_set_clipboard_info_request( const struct set_clipboard_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " flags=%08x,", req->flags );
|
||||
|
@ -2726,6 +2766,9 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_start_hook_chain_request,
|
||||
(dump_func)dump_finish_hook_chain_request,
|
||||
(dump_func)dump_get_next_hook_request,
|
||||
(dump_func)dump_create_class_request,
|
||||
(dump_func)dump_destroy_class_request,
|
||||
(dump_func)dump_set_class_info_request,
|
||||
(dump_func)dump_set_clipboard_info_request,
|
||||
(dump_func)dump_open_token_request,
|
||||
(dump_func)dump_set_global_windows_request,
|
||||
|
@ -2908,6 +2951,9 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_start_hook_chain_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_next_hook_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_set_class_info_reply,
|
||||
(dump_func)dump_set_clipboard_info_reply,
|
||||
(dump_func)dump_open_token_reply,
|
||||
(dump_func)dump_set_global_windows_reply,
|
||||
|
@ -3090,6 +3136,9 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"start_hook_chain",
|
||||
"finish_hook_chain",
|
||||
"get_next_hook",
|
||||
"create_class",
|
||||
"destroy_class",
|
||||
"set_class_info",
|
||||
"set_clipboard_info",
|
||||
"open_token",
|
||||
"set_global_windows",
|
||||
|
|
|
@ -27,6 +27,7 @@ struct thread;
|
|||
struct window;
|
||||
struct msg_queue;
|
||||
struct hook_table;
|
||||
struct window_class;
|
||||
|
||||
enum user_object
|
||||
{
|
||||
|
@ -72,5 +73,13 @@ extern int make_window_active( user_handle_t window );
|
|||
extern struct thread *get_window_thread( user_handle_t handle );
|
||||
extern user_handle_t window_from_point( int x, int y );
|
||||
extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
|
||||
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 void release_class( struct window_class *class );
|
||||
extern atom_t get_class_atom( struct window_class *class );
|
||||
|
||||
#endif /* __WINE_SERVER_USER_H */
|
||||
|
|
|
@ -63,6 +63,7 @@ struct window
|
|||
struct window *prev; /* prev window in Z-order */
|
||||
user_handle_t handle; /* full handle for this window */
|
||||
struct thread *thread; /* thread owning the window */
|
||||
struct window_class *class; /* window class */
|
||||
atom_t atom; /* class atom */
|
||||
user_handle_t last_active; /* last active popup */
|
||||
rectangle_t window_rect; /* window rectangle */
|
||||
|
@ -260,6 +261,7 @@ static void destroy_window( struct window *win )
|
|||
free_user_handle( win->handle );
|
||||
destroy_properties( win );
|
||||
unlink_window( win );
|
||||
release_class( win->class );
|
||||
if (win->text) free( win->text );
|
||||
memset( win, 0x55, sizeof(*win) );
|
||||
free( win );
|
||||
|
@ -267,13 +269,23 @@ 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,
|
||||
int extra_bytes )
|
||||
void *instance, int extra_bytes )
|
||||
{
|
||||
struct window *win = mem_alloc( sizeof(*win) + extra_bytes - 1 );
|
||||
if (!win) return NULL;
|
||||
struct window *win;
|
||||
struct window_class *class = grab_class( current->process, atom, instance );
|
||||
|
||||
if (!class) return NULL;
|
||||
|
||||
win = mem_alloc( sizeof(*win) + extra_bytes - 1 );
|
||||
if (!win)
|
||||
{
|
||||
release_class( class );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(win->handle = alloc_user_handle( win, USER_WINDOW )))
|
||||
{
|
||||
release_class( class );
|
||||
free( win );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -283,6 +295,7 @@ static struct window *create_window( struct window *parent, struct window *owner
|
|||
win->last_child = NULL;
|
||||
win->first_unlinked = NULL;
|
||||
win->thread = current;
|
||||
win->class = class;
|
||||
win->atom = atom;
|
||||
win->last_active = win->handle;
|
||||
win->style = 0;
|
||||
|
@ -449,6 +462,15 @@ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *threa
|
|||
}
|
||||
|
||||
|
||||
/* get the window class of a window */
|
||||
struct window_class* get_window_class( user_handle_t window )
|
||||
{
|
||||
struct window *win;
|
||||
if (!(win = get_window( window ))) return NULL;
|
||||
return win->class;
|
||||
}
|
||||
|
||||
|
||||
/* create a window */
|
||||
DECL_HANDLER(create_window)
|
||||
{
|
||||
|
@ -462,7 +484,7 @@ DECL_HANDLER(create_window)
|
|||
{
|
||||
if (!top_window)
|
||||
{
|
||||
if (!(top_window = create_window( NULL, NULL, req->atom, req->extra ))) return;
|
||||
if (!(top_window = create_window( NULL, NULL, req->atom, req->instance, req->extra ))) return;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
}
|
||||
|
@ -481,7 +503,7 @@ DECL_HANDLER(create_window)
|
|||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
if (!(win = create_window( parent, owner, req->atom, req->extra ))) return;
|
||||
if (!(win = create_window( parent, owner, req->atom, req->instance, req->extra ))) return;
|
||||
reply->handle = win->handle;
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +591,7 @@ DECL_HANDLER(get_window_info)
|
|||
{
|
||||
reply->tid = get_thread_id( win->thread );
|
||||
reply->pid = get_process_id( win->thread->process );
|
||||
reply->atom = win->atom;
|
||||
reply->atom = get_class_atom( win->class );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -648,7 +670,7 @@ DECL_HANDLER(get_window_children)
|
|||
if (parent)
|
||||
for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next)
|
||||
{
|
||||
if (req->atom && ptr->atom != req->atom) continue;
|
||||
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||
total++;
|
||||
}
|
||||
|
@ -659,7 +681,7 @@ DECL_HANDLER(get_window_children)
|
|||
{
|
||||
for (ptr = parent->first_child; ptr && len; ptr = ptr->next)
|
||||
{
|
||||
if (req->atom && ptr->atom != req->atom) continue;
|
||||
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||
*data++ = ptr->handle;
|
||||
len -= sizeof(*data);
|
||||
|
|
538
windows/class.c
538
windows/class.c
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Window classes functions
|
||||
*
|
||||
* Copyright 1993, 1996 Alexandre Julliard
|
||||
* 1998 Juergen Schmied (jsch)
|
||||
* Copyright 1993, 1996, 2003 Alexandre Julliard
|
||||
* Copyright 1998 Juergen Schmied (jsch)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -17,18 +17,12 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* FIXME: In win32 all classes are local. They are registered at
|
||||
* program start. Processes CANNOT share classes. (Source: some
|
||||
* win31->NT migration book)
|
||||
*
|
||||
* FIXME: There seems to be a general problem with hInstance in WINE
|
||||
* classes are getting registered with wrong hInstance.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -46,16 +40,17 @@
|
|||
#include "controls.h"
|
||||
#include "dce.h"
|
||||
#include "winproc.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(class);
|
||||
|
||||
typedef struct tagCLASS
|
||||
{
|
||||
struct tagCLASS *next; /* Next class */
|
||||
struct tagCLASS *prev; /* Prev class */
|
||||
UINT cWindows; /* Count of existing windows */
|
||||
struct list entry; /* Entry in class list */
|
||||
UINT style; /* Class style */
|
||||
BOOL local; /* Local class? */
|
||||
WNDPROC winprocA; /* Window procedure (ASCII) */
|
||||
WNDPROC winprocW; /* Window procedure (Unicode) */
|
||||
INT cbClsExtra; /* Class extra bytes */
|
||||
|
@ -71,7 +66,10 @@ typedef struct tagCLASS
|
|||
ATOM atomName; /* Name of the class */
|
||||
} CLASS;
|
||||
|
||||
static CLASS *firstClass;
|
||||
static struct list class_list = LIST_INIT( class_list );
|
||||
static HMODULE user32_module;
|
||||
|
||||
#define CLASS_OTHER_PROCESS ((CLASS *)1)
|
||||
|
||||
/***********************************************************************
|
||||
* get_class_ptr
|
||||
|
@ -83,17 +81,13 @@ static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
|
|||
if (ptr)
|
||||
{
|
||||
if (ptr != WND_OTHER_PROCESS) return ptr->class;
|
||||
if (IsWindow( hwnd )) /* check other processes */
|
||||
if (write_access && IsWindow( hwnd )) /* check other processes */
|
||||
{
|
||||
if (write_access)
|
||||
{
|
||||
/* modifying classes in other processes is not allowed */
|
||||
SetLastError( ERROR_ACCESS_DENIED );
|
||||
return NULL;
|
||||
}
|
||||
FIXME( "reading from class of other process window %p\n", hwnd );
|
||||
/* DbgBreakPoint(); */
|
||||
/* modifying classes in other processes is not allowed */
|
||||
SetLastError( ERROR_ACCESS_DENIED );
|
||||
return NULL;
|
||||
}
|
||||
return CLASS_OTHER_PROCESS;
|
||||
}
|
||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return NULL;
|
||||
|
@ -109,6 +103,51 @@ inline static void release_class_ptr( CLASS *ptr )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_server_info
|
||||
*
|
||||
* Set class info with the wine server.
|
||||
*/
|
||||
static BOOL set_server_info( HWND hwnd, INT offset, LONG newval )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( set_class_info )
|
||||
{
|
||||
req->window = hwnd;
|
||||
req->extra_offset = -1;
|
||||
switch(offset)
|
||||
{
|
||||
case GCW_ATOM:
|
||||
req->flags = SET_CLASS_ATOM;
|
||||
req->atom = newval;
|
||||
case GCL_STYLE:
|
||||
req->flags = SET_CLASS_STYLE;
|
||||
req->style = newval;
|
||||
break;
|
||||
case GCL_CBWNDEXTRA:
|
||||
req->flags = SET_CLASS_WINEXTRA;
|
||||
req->win_extra = newval;
|
||||
break;
|
||||
case GCL_HMODULE:
|
||||
req->flags = SET_CLASS_INSTANCE;
|
||||
req->instance = (void *)newval;
|
||||
break;
|
||||
default:
|
||||
assert( offset >= 0 );
|
||||
req->flags = SET_CLASS_EXTRA;
|
||||
req->extra_offset = offset;
|
||||
req->extra_size = sizeof(newval);
|
||||
memcpy( &req->extra_value, &newval, sizeof(newval) );
|
||||
break;
|
||||
}
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_GetProc
|
||||
*
|
||||
|
@ -256,34 +295,35 @@ static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
|
|||
*/
|
||||
static BOOL CLASS_FreeClass( CLASS *classPtr )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("%p\n", classPtr);
|
||||
|
||||
/* Check if we can remove this class */
|
||||
|
||||
if (classPtr->cWindows > 0)
|
||||
SERVER_START_REQ( destroy_class )
|
||||
{
|
||||
SetLastError( ERROR_CLASS_HAS_WINDOWS );
|
||||
return FALSE;
|
||||
req->atom = classPtr->atomName;
|
||||
req->instance = classPtr->hInstance;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* Remove the class from the linked list */
|
||||
if (ret)
|
||||
{
|
||||
list_remove( &classPtr->entry );
|
||||
|
||||
if (classPtr->next) classPtr->next->prev = classPtr->prev;
|
||||
if (classPtr->prev) classPtr->prev->next = classPtr->next;
|
||||
else firstClass = classPtr->next;
|
||||
/* Delete the class */
|
||||
|
||||
/* 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 TRUE;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -292,15 +332,16 @@ static BOOL CLASS_FreeClass( CLASS *classPtr )
|
|||
*/
|
||||
void CLASS_FreeModuleClasses( HMODULE16 hModule )
|
||||
{
|
||||
CLASS *ptr, *next;
|
||||
struct list *ptr, *next;
|
||||
|
||||
TRACE("0x%08x\n", hModule);
|
||||
|
||||
USER_Lock();
|
||||
for (ptr = firstClass; ptr; ptr = next)
|
||||
for (ptr = list_head( &class_list ); ptr; ptr = next)
|
||||
{
|
||||
next = ptr->next;
|
||||
if (ptr->hInstance == HINSTANCE_32(hModule)) CLASS_FreeClass( ptr );
|
||||
CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
|
||||
next = list_next( &class_list, ptr );
|
||||
if (class->hInstance == HINSTANCE_32(hModule)) CLASS_FreeClass( class );
|
||||
}
|
||||
USER_Unlock();
|
||||
}
|
||||
|
@ -311,69 +352,23 @@ void CLASS_FreeModuleClasses( HMODULE16 hModule )
|
|||
*
|
||||
* Return a pointer to the class.
|
||||
* hinstance has been normalized by the caller.
|
||||
*
|
||||
* NOTES
|
||||
* 980805 a local class will be found now if registred with hInst=0
|
||||
* and looed up with a hInst!=0. msmoney does it (jsch)
|
||||
*
|
||||
* Local class registered with a USER instance handle are found as if
|
||||
* they were global classes.
|
||||
*/
|
||||
static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
|
||||
{
|
||||
CLASS * class, *tclass = 0, *user_class = 0;
|
||||
HINSTANCE16 hUser = GetModuleHandle16("USER");
|
||||
struct list *ptr;
|
||||
|
||||
TRACE("0x%08x %p\n", atom, hinstance);
|
||||
|
||||
/* First search task-specific classes */
|
||||
|
||||
for (class = firstClass; (class); class = class->next)
|
||||
LIST_FOR_EACH( ptr, &class_list )
|
||||
{
|
||||
if (class->style & CS_GLOBALCLASS) continue;
|
||||
if (class->atomName == atom)
|
||||
CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
|
||||
if (class->atomName != atom) continue;
|
||||
if (!hinstance || !class->local || class->hInstance == hinstance)
|
||||
{
|
||||
if (hinstance==class->hInstance || hinstance == (HINSTANCE)0xffff)
|
||||
{
|
||||
TRACE("-- found local %p\n", class);
|
||||
return class;
|
||||
}
|
||||
if (class->hInstance == 0) tclass = class;
|
||||
else if(class->hInstance == HINSTANCE_32(hUser))
|
||||
{
|
||||
user_class = class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Then search global classes */
|
||||
|
||||
for (class = firstClass; (class); class = class->next)
|
||||
{
|
||||
if (!(class->style & CS_GLOBALCLASS)) continue;
|
||||
if (class->atomName == atom)
|
||||
{
|
||||
TRACE("-- found global %p\n", class);
|
||||
TRACE("0x%04x %p -> %p\n", atom, hinstance, class);
|
||||
return class;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if there was a local class registered with USER */
|
||||
if( user_class )
|
||||
{
|
||||
TRACE("--found local USER class %p\n", user_class);
|
||||
return user_class;
|
||||
}
|
||||
|
||||
/* Then check if there was a local class with hInst=0*/
|
||||
if ( tclass )
|
||||
{
|
||||
WARN("-- found local Class registred with hInst=0\n");
|
||||
return tclass;
|
||||
}
|
||||
|
||||
TRACE("-- not found\n");
|
||||
return 0;
|
||||
TRACE("0x%04x %p -> not found\n", atom, hinstance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -382,28 +377,15 @@ static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
|
|||
*
|
||||
* The real RegisterClass() functionality.
|
||||
*/
|
||||
static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
|
||||
static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
|
||||
DWORD style, INT classExtra, INT winExtra )
|
||||
{
|
||||
CLASS *classPtr;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("atom=0x%x hinst=%p style=0x%lx clExtr=0x%x winExtr=0x%x\n",
|
||||
atom, hInstance, style, classExtra, winExtra );
|
||||
|
||||
/* Check if a class with this name already exists */
|
||||
classPtr = CLASS_FindClassByAtom( atom, hInstance );
|
||||
if (classPtr)
|
||||
{
|
||||
/* Class can be created only if it is local and */
|
||||
/* if the class with the same name is global. */
|
||||
|
||||
if ((style & CS_GLOBALCLASS) || !(classPtr->style & CS_GLOBALCLASS))
|
||||
{
|
||||
SetLastError( ERROR_CLASS_ALREADY_EXISTS );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the extra bytes value */
|
||||
|
||||
if (classExtra < 0) classExtra = 0;
|
||||
|
@ -413,11 +395,28 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
|
|||
else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
|
||||
WARN("Win extra bytes %d is > 40\n", winExtra );
|
||||
|
||||
/* Create the class */
|
||||
|
||||
classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
|
||||
if (!classPtr) 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;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, classPtr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
classPtr->style = style;
|
||||
classPtr->local = local;
|
||||
classPtr->cbWndExtra = winExtra;
|
||||
classPtr->cbClsExtra = classExtra;
|
||||
classPtr->hInstance = hInstance;
|
||||
|
@ -426,50 +425,27 @@ static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
|
|||
|
||||
/* Other non-null values must be set by caller */
|
||||
|
||||
if ((classPtr->next = firstClass)) firstClass->prev = classPtr;
|
||||
firstClass = classPtr;
|
||||
if (local) list_add_head( &class_list, &classPtr->entry );
|
||||
else list_add_tail( &class_list, &classPtr->entry );
|
||||
return classPtr;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_UnregisterClass
|
||||
*
|
||||
* The real UnregisterClass() functionality.
|
||||
*/
|
||||
static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
|
||||
{
|
||||
CLASS *classPtr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
USER_Lock();
|
||||
if (atom &&
|
||||
(classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
|
||||
(!hInstance || classPtr->hInstance == hInstance))
|
||||
{
|
||||
ret = CLASS_FreeClass( classPtr );
|
||||
}
|
||||
else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
|
||||
USER_Unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_RegisterBuiltinClass
|
||||
* register_builtin
|
||||
*
|
||||
* Register a builtin control class.
|
||||
* This allows having both ASCII and Unicode winprocs for the same class.
|
||||
*/
|
||||
ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
|
||||
static ATOM register_builtin( const struct builtin_class_descr *descr )
|
||||
{
|
||||
ATOM atom;
|
||||
CLASS *classPtr;
|
||||
|
||||
if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
|
||||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, 0, descr->style, 0, descr->extra )))
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, user32_module, FALSE,
|
||||
descr->style, 0, descr->extra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
|
@ -486,6 +462,40 @@ ATOM CLASS_RegisterBuiltinClass( const struct builtin_class_descr *descr )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_RegisterBuiltinClasses
|
||||
*/
|
||||
void CLASS_RegisterBuiltinClasses( HMODULE user32 )
|
||||
{
|
||||
extern const struct builtin_class_descr BUTTON_builtin_class;
|
||||
extern const struct builtin_class_descr COMBO_builtin_class;
|
||||
extern const struct builtin_class_descr COMBOLBOX_builtin_class;
|
||||
extern const struct builtin_class_descr DIALOG_builtin_class;
|
||||
extern const struct builtin_class_descr DESKTOP_builtin_class;
|
||||
extern const struct builtin_class_descr EDIT_builtin_class;
|
||||
extern const struct builtin_class_descr ICONTITLE_builtin_class;
|
||||
extern const struct builtin_class_descr LISTBOX_builtin_class;
|
||||
extern const struct builtin_class_descr MDICLIENT_builtin_class;
|
||||
extern const struct builtin_class_descr MENU_builtin_class;
|
||||
extern const struct builtin_class_descr SCROLL_builtin_class;
|
||||
extern const struct builtin_class_descr STATIC_builtin_class;
|
||||
|
||||
user32_module = user32;
|
||||
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 );
|
||||
register_builtin( &MDICLIENT_builtin_class );
|
||||
register_builtin( &MENU_builtin_class );
|
||||
register_builtin( &SCROLL_builtin_class );
|
||||
register_builtin( &STATIC_builtin_class );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_AddWindow
|
||||
*
|
||||
|
@ -499,7 +509,6 @@ CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
|
|||
if (type == WIN_PROC_16) inst = HINSTANCE_32(GetExePtr(HINSTANCE_16(inst)));
|
||||
|
||||
if (!(class = CLASS_FindClassByAtom( atom, inst ))) return NULL;
|
||||
class->cWindows++;
|
||||
|
||||
if (type == WIN_PROC_32W)
|
||||
{
|
||||
|
@ -516,17 +525,6 @@ CLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTYPE type,
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLASS_RemoveWindow
|
||||
*
|
||||
* Remove a window from the class window count.
|
||||
*/
|
||||
void CLASS_RemoveWindow( CLASS *cls )
|
||||
{
|
||||
if (cls && cls->cWindows) cls->cWindows--;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RegisterClass (USER.57)
|
||||
*/
|
||||
|
@ -606,11 +604,14 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
|
|||
{
|
||||
ATOM atom;
|
||||
CLASS *classPtr;
|
||||
HINSTANCE hInstance = HINSTANCE_32(GetExePtr( wc->hInstance ));
|
||||
HINSTANCE hInstance;
|
||||
|
||||
if (!(hInstance = HINSTANCE_32(GetExePtr(wc->hInstance))))
|
||||
hInstance = HINSTANCE_32(GetModuleHandle16(NULL));
|
||||
|
||||
if (!(atom = GlobalAddAtomA( MapSL(wc->lpszClassName) ))) return 0;
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
|
||||
wc->cbClsExtra, wc->cbWndExtra )))
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, hInstance, !(wc->style & CS_GLOBALCLASS),
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra )))
|
||||
{
|
||||
GlobalDeleteAtom( atom );
|
||||
return 0;
|
||||
|
@ -640,20 +641,28 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
|
|||
{
|
||||
ATOM atom;
|
||||
CLASS *classPtr;
|
||||
HINSTANCE instance;
|
||||
|
||||
if (wc->hInstance == user32_module)
|
||||
{
|
||||
/* we can't register a class for user32 */
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
|
||||
|
||||
if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
|
||||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
|
||||
wc->cbClsExtra, wc->cbWndExtra )))
|
||||
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, wc->hInstance,
|
||||
wc->hbrBackground, wc->style, wc->cbClsExtra,
|
||||
wc->cbWndExtra, classPtr );
|
||||
atom, wc->lpfnWndProc, instance, wc->hbrBackground,
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
|
||||
|
||||
classPtr->hIcon = wc->hIcon;
|
||||
classPtr->hIconSm = wc->hIconSm;
|
||||
|
@ -672,20 +681,28 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
|
|||
{
|
||||
ATOM atom;
|
||||
CLASS *classPtr;
|
||||
HINSTANCE instance;
|
||||
|
||||
if (wc->hInstance == user32_module)
|
||||
{
|
||||
/* we can't register a class for user32 */
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
|
||||
|
||||
if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
|
||||
|
||||
if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
|
||||
wc->cbClsExtra, wc->cbWndExtra )))
|
||||
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, wc->hInstance,
|
||||
wc->hbrBackground, wc->style, wc->cbClsExtra,
|
||||
wc->cbWndExtra, classPtr );
|
||||
atom, wc->lpfnWndProc, instance, wc->hbrBackground,
|
||||
wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
|
||||
|
||||
classPtr->hIcon = wc->hIcon;
|
||||
classPtr->hIconSm = wc->hIconSm;
|
||||
|
@ -702,17 +719,17 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
|
|||
*/
|
||||
BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
|
||||
{
|
||||
if (hInstance == GetModuleHandle16("user")) hInstance = 0;
|
||||
return UnregisterClassA( className, HINSTANCE_32(GetExePtr( hInstance )) );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UnregisterClassA (USER32.@)
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
|
||||
{
|
||||
TRACE("%s %p\n",debugstr_a(className), hInstance);
|
||||
return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
|
||||
ATOM atom = HIWORD(className) ? GlobalFindAtomA( className ) : LOWORD(className);
|
||||
return UnregisterClassW( MAKEINTATOMW(atom), hInstance );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -720,8 +737,22 @@ BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
|
|||
*/
|
||||
BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
|
||||
{
|
||||
TRACE("%s %p\n",debugstr_w(className), hInstance);
|
||||
return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
|
||||
CLASS *classPtr;
|
||||
BOOL ret = FALSE;
|
||||
ATOM atom = HIWORD(className) ? GlobalFindAtomW( className ) : LOWORD(className);
|
||||
|
||||
TRACE("%s %p %x\n",debugstr_w(className), hInstance, atom);
|
||||
|
||||
if (!hInstance) hInstance = GetModuleHandleW( NULL );
|
||||
|
||||
USER_Lock();
|
||||
if (atom && (classPtr = CLASS_FindClassByAtom( atom, hInstance )))
|
||||
{
|
||||
ret = CLASS_FreeClass( classPtr );
|
||||
}
|
||||
else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
USER_Unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -739,6 +770,21 @@ WORD WINAPI GetClassWord( HWND hwnd, INT offset )
|
|||
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
|
||||
|
||||
if (class == CLASS_OTHER_PROCESS)
|
||||
{
|
||||
SERVER_START_REQ( set_class_info )
|
||||
{
|
||||
req->window = hwnd;
|
||||
req->flags = 0;
|
||||
req->extra_offset = offset;
|
||||
req->extra_size = sizeof(retvalue);
|
||||
if (!wine_server_call_err( req ))
|
||||
memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
if (offset <= class->cbClsExtra - sizeof(WORD))
|
||||
memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
|
||||
else
|
||||
|
@ -763,17 +809,22 @@ LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
|
|||
{
|
||||
case GCL_WNDPROC:
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
|
||||
if (class == CLASS_OTHER_PROCESS) break;
|
||||
ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
|
||||
release_class_ptr( class );
|
||||
return ret;
|
||||
case GCL_MENUNAME:
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
|
||||
if (class == CLASS_OTHER_PROCESS) break;
|
||||
ret = (LONG)CLASS_GetMenuName16( class );
|
||||
release_class_ptr( class );
|
||||
return ret;
|
||||
default:
|
||||
return GetClassLongA( hwnd, offset );
|
||||
}
|
||||
FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -789,6 +840,53 @@ LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
|
|||
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
|
||||
|
||||
if (class == CLASS_OTHER_PROCESS)
|
||||
{
|
||||
SERVER_START_REQ( set_class_info )
|
||||
{
|
||||
req->window = hwnd;
|
||||
req->flags = 0;
|
||||
req->extra_offset = (offset >= 0) ? offset : -1;
|
||||
req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case GCL_HBRBACKGROUND:
|
||||
case GCL_HCURSOR:
|
||||
case GCL_HICON:
|
||||
case GCL_HICONSM:
|
||||
case GCL_WNDPROC:
|
||||
case GCL_MENUNAME:
|
||||
FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
break;
|
||||
case GCL_STYLE:
|
||||
retvalue = reply->old_style;
|
||||
break;
|
||||
case GCL_CBWNDEXTRA:
|
||||
retvalue = reply->old_win_extra;
|
||||
break;
|
||||
case GCL_CBCLSEXTRA:
|
||||
retvalue = reply->old_extra;
|
||||
break;
|
||||
case GCL_HMODULE:
|
||||
retvalue = (LONG)reply->old_instance;
|
||||
break;
|
||||
case GCW_ATOM:
|
||||
retvalue = reply->old_atom;
|
||||
break;
|
||||
default:
|
||||
if (offset >= 0) memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
|
||||
else SetLastError( ERROR_INVALID_INDEX );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
if (offset >= 0)
|
||||
{
|
||||
if (offset <= class->cbClsExtra - sizeof(LONG))
|
||||
|
@ -858,6 +956,13 @@ LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
|
|||
|
||||
if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
|
||||
|
||||
if (class == CLASS_OTHER_PROCESS)
|
||||
{
|
||||
FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset == GCL_WNDPROC)
|
||||
retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
|
||||
else /* GCL_MENUNAME */
|
||||
|
@ -882,14 +987,21 @@ WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
|
|||
|
||||
if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
|
||||
|
||||
if (offset <= class->cbClsExtra - sizeof(WORD))
|
||||
SERVER_START_REQ( set_class_info )
|
||||
{
|
||||
void *ptr = (char *)(class + 1) + offset;
|
||||
memcpy( &retval, ptr, sizeof(retval) );
|
||||
memcpy( ptr, &newval, sizeof(newval) );
|
||||
req->window = hwnd;
|
||||
req->flags = SET_CLASS_EXTRA;
|
||||
req->extra_offset = offset;
|
||||
req->extra_size = sizeof(newval);
|
||||
memcpy( &req->extra_value, &newval, sizeof(newval) );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
void *ptr = (char *)(class + 1) + offset;
|
||||
memcpy( &retval, ptr, sizeof(retval) );
|
||||
memcpy( ptr, &newval, sizeof(newval) );
|
||||
}
|
||||
}
|
||||
else SetLastError( ERROR_INVALID_INDEX );
|
||||
|
||||
SERVER_END_REQ;
|
||||
release_class_ptr( class );
|
||||
return retval;
|
||||
}
|
||||
|
@ -936,13 +1048,12 @@ LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
|
|||
|
||||
if (offset >= 0)
|
||||
{
|
||||
if (offset <= class->cbClsExtra - sizeof(LONG))
|
||||
if (set_server_info( hwnd, offset, newval ))
|
||||
{
|
||||
void *ptr = (char *)(class + 1) + offset;
|
||||
memcpy( &retval, ptr, sizeof(retval) );
|
||||
memcpy( ptr, &newval, sizeof(newval) );
|
||||
}
|
||||
else SetLastError( ERROR_INVALID_INDEX );
|
||||
}
|
||||
else switch(offset)
|
||||
{
|
||||
|
@ -970,18 +1081,22 @@ LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
|
|||
class->hIconSm = (HICON)newval;
|
||||
break;
|
||||
case GCL_STYLE:
|
||||
if (!set_server_info( hwnd, offset, newval )) break;
|
||||
retval = (LONG)class->style;
|
||||
class->style = newval;
|
||||
break;
|
||||
case GCL_CBWNDEXTRA:
|
||||
if (!set_server_info( hwnd, offset, newval )) break;
|
||||
retval = (LONG)class->cbWndExtra;
|
||||
class->cbWndExtra = newval;
|
||||
break;
|
||||
case GCL_HMODULE:
|
||||
if (!set_server_info( hwnd, offset, newval )) break;
|
||||
retval = (LONG)class->hInstance;
|
||||
class->hInstance = (HINSTANCE)newval;
|
||||
break;
|
||||
case GCW_ATOM:
|
||||
if (!set_server_info( hwnd, offset, newval )) break;
|
||||
retval = (DWORD)class->atomName;
|
||||
class->atomName = newval;
|
||||
break;
|
||||
|
@ -1149,20 +1264,21 @@ BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
|
|||
*/
|
||||
BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *wc )
|
||||
{
|
||||
ATOM atom;
|
||||
ATOM atom = HIWORD(name) ? GlobalFindAtomA( MapSL(name) ) : LOWORD(name);
|
||||
CLASS *classPtr;
|
||||
HINSTANCE hInstance = HINSTANCE_32(GetExePtr( hInst16 ));
|
||||
HINSTANCE hInstance;
|
||||
|
||||
TRACE("%p %s %p\n",hInstance,debugstr_a( MapSL(name) ), wc);
|
||||
if (hInst16 == GetModuleHandle16("user")) hInstance = user32_module;
|
||||
else hInstance = HINSTANCE_32(GetExePtr( hInst16 ));
|
||||
|
||||
if (!(atom = GlobalFindAtomA( MapSL(name) )) ||
|
||||
!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
|
||||
(hInstance != classPtr->hInstance)) return FALSE;
|
||||
TRACE("%p %s %x %p\n", hInstance, debugstr_a( MapSL(name) ), atom, wc);
|
||||
|
||||
if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance ))) return FALSE;
|
||||
wc->style = classPtr->style;
|
||||
wc->lpfnWndProc = CLASS_GetProc( classPtr, WIN_PROC_16 );
|
||||
wc->cbClsExtra = (INT16)classPtr->cbClsExtra;
|
||||
wc->cbWndExtra = (INT16)classPtr->cbWndExtra;
|
||||
wc->hInstance = HINSTANCE_16(classPtr->hInstance);
|
||||
wc->hInstance = (classPtr->hInstance == user32_module) ? GetModuleHandle16("user") : HINSTANCE_16(classPtr->hInstance);
|
||||
wc->hIcon = HICON_16(classPtr->hIcon);
|
||||
wc->hIconSm = HICON_16(classPtr->hIconSm);
|
||||
wc->hCursor = HCURSOR_16(classPtr->hCursor);
|
||||
|
@ -1179,22 +1295,25 @@ BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInst16, SEGPTR name, WNDCLASSEX16 *
|
|||
/***********************************************************************
|
||||
* GetClassInfoExA (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
|
||||
WNDCLASSEXA *wc )
|
||||
BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
|
||||
{
|
||||
ATOM atom;
|
||||
ATOM atom = HIWORD(name) ? GlobalFindAtomA( name ) : LOWORD(name);
|
||||
CLASS *classPtr;
|
||||
|
||||
TRACE("%p %p %p\n",hInstance, name, wc);
|
||||
TRACE("%p %s %x %p\n", hInstance, debugstr_a(name), atom, wc);
|
||||
|
||||
if (!(atom = GlobalFindAtomA( name )) ||
|
||||
!(classPtr = CLASS_FindClassByAtom( atom, hInstance ))
|
||||
/*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
|
||||
if (!hInstance) hInstance = user32_module;
|
||||
|
||||
if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
|
||||
{
|
||||
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
return FALSE;
|
||||
}
|
||||
wc->style = classPtr->style;
|
||||
wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
|
||||
wc->cbClsExtra = classPtr->cbClsExtra;
|
||||
wc->cbWndExtra = classPtr->cbWndExtra;
|
||||
wc->hInstance = classPtr->hInstance;
|
||||
wc->hInstance = (hInstance == user32_module) ? 0 : hInstance;
|
||||
wc->hIcon = (HICON)classPtr->hIcon;
|
||||
wc->hIconSm = (HICON)classPtr->hIconSm;
|
||||
wc->hCursor = (HCURSOR)classPtr->hCursor;
|
||||
|
@ -1210,22 +1329,25 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
|
|||
/***********************************************************************
|
||||
* GetClassInfoExW (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
|
||||
WNDCLASSEXW *wc )
|
||||
BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
|
||||
{
|
||||
ATOM atom;
|
||||
ATOM atom = HIWORD(name) ? GlobalFindAtomW( name ) : LOWORD(name);
|
||||
CLASS *classPtr;
|
||||
|
||||
TRACE("%p %p %p\n",hInstance, name, wc);
|
||||
TRACE("%p %s %x %p\n", hInstance, debugstr_w(name), atom, wc);
|
||||
|
||||
if (!(atom = GlobalFindAtomW( name )) ||
|
||||
!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
|
||||
(hInstance != classPtr->hInstance)) return FALSE;
|
||||
if (!hInstance) hInstance = user32_module;
|
||||
|
||||
if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
|
||||
{
|
||||
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
|
||||
return FALSE;
|
||||
}
|
||||
wc->style = classPtr->style;
|
||||
wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
|
||||
wc->cbClsExtra = classPtr->cbClsExtra;
|
||||
wc->cbWndExtra = classPtr->cbWndExtra;
|
||||
wc->hInstance = classPtr->hInstance;
|
||||
wc->hInstance = (hInstance == user32_module) ? 0 : hInstance;
|
||||
wc->hIcon = (HICON)classPtr->hIcon;
|
||||
wc->hIconSm = (HICON)classPtr->hIconSm;
|
||||
wc->hCursor = (HCURSOR)classPtr->hCursor;
|
||||
|
|
|
@ -62,23 +62,34 @@ static void *user_handles[NB_USER_HANDLES];
|
|||
*
|
||||
* Create a window handle with the server.
|
||||
*/
|
||||
static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, unsigned int extra_bytes )
|
||||
static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
|
||||
HINSTANCE instance, WINDOWPROCTYPE type )
|
||||
{
|
||||
BOOL res;
|
||||
user_handle_t handle = 0;
|
||||
WORD index;
|
||||
WND *win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) );
|
||||
WND *win;
|
||||
DCE *dce;
|
||||
INT extra_bytes;
|
||||
DWORD clsStyle;
|
||||
WNDPROC winproc;
|
||||
struct tagCLASS *class;
|
||||
user_handle_t handle = 0;
|
||||
|
||||
if (!win) return NULL;
|
||||
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();
|
||||
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
req->parent = parent;
|
||||
req->owner = owner;
|
||||
req->atom = atom;
|
||||
req->extra = extra_bytes;
|
||||
req->parent = parent;
|
||||
req->owner = owner;
|
||||
req->atom = atom;
|
||||
req->instance = instance;
|
||||
req->extra = extra_bytes;
|
||||
if ((res = !wine_server_call_err( req ))) handle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -92,9 +103,15 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, unsigned i
|
|||
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->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 );
|
||||
return win;
|
||||
}
|
||||
|
||||
|
@ -669,7 +686,6 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
|
|||
DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
|
||||
USER_Driver.pDestroyWindow( hwnd );
|
||||
WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
|
||||
CLASS_RemoveWindow( wndPtr->class );
|
||||
wndPtr->class = NULL;
|
||||
wndPtr->dwMagic = 0; /* Mark it as invalid */
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
|
@ -705,41 +721,28 @@ void WIN_DestroyThreadWindows( HWND hwnd )
|
|||
*/
|
||||
BOOL WIN_CreateDesktopWindow(void)
|
||||
{
|
||||
struct tagCLASS *class;
|
||||
HWND hwndDesktop;
|
||||
INT wndExtra;
|
||||
DWORD clsStyle;
|
||||
WNDPROC winproc;
|
||||
DCE *dce;
|
||||
CREATESTRUCTA cs;
|
||||
RECT rect;
|
||||
|
||||
TRACE("Creating desktop window\n");
|
||||
|
||||
if (!WINPOS_CreateInternalPosAtom() ||
|
||||
!(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
|
||||
&wndExtra, &winproc, &clsStyle, &dce )))
|
||||
return FALSE;
|
||||
if (!WINPOS_CreateInternalPosAtom()) return FALSE;
|
||||
|
||||
pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), wndExtra );
|
||||
pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W );
|
||||
if (!pWndDesktop) return FALSE;
|
||||
hwndDesktop = pWndDesktop->hwndSelf;
|
||||
|
||||
pWndDesktop->tid = 0; /* nobody owns the desktop */
|
||||
pWndDesktop->parent = 0;
|
||||
pWndDesktop->owner = 0;
|
||||
pWndDesktop->class = class;
|
||||
pWndDesktop->text = NULL;
|
||||
pWndDesktop->hrgnUpdate = 0;
|
||||
pWndDesktop->clsStyle = clsStyle;
|
||||
pWndDesktop->dce = NULL;
|
||||
pWndDesktop->pVScroll = NULL;
|
||||
pWndDesktop->pHScroll = NULL;
|
||||
pWndDesktop->helpContext = 0;
|
||||
pWndDesktop->flags = 0;
|
||||
pWndDesktop->hSysMenu = 0;
|
||||
pWndDesktop->winproc = winproc;
|
||||
pWndDesktop->cbWndExtra = wndExtra;
|
||||
|
||||
cs.lpCreateParams = NULL;
|
||||
cs.hInstance = 0;
|
||||
|
@ -970,13 +973,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
WINDOWPROCTYPE type )
|
||||
{
|
||||
INT sw = SW_SHOW;
|
||||
struct tagCLASS *classPtr;
|
||||
WND *wndPtr;
|
||||
HWND hwnd, parent, owner;
|
||||
INT wndExtra;
|
||||
DWORD clsStyle;
|
||||
WNDPROC winproc;
|
||||
DCE *dce;
|
||||
BOOL unicode = (type == WIN_PROC_32W);
|
||||
|
||||
TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
|
||||
|
@ -1021,14 +1019,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
|
||||
}
|
||||
|
||||
/* Find the window class */
|
||||
if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
|
||||
&wndExtra, &winproc, &clsStyle, &dce )))
|
||||
{
|
||||
WARN("Bad class '%s'\n", cs->lpszClass );
|
||||
return 0;
|
||||
}
|
||||
|
||||
WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
|
||||
|
||||
/* Correct the window style - stage 1
|
||||
|
@ -1052,7 +1042,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
/* Create the window structure */
|
||||
|
||||
if (!(wndPtr = create_window_handle( parent, owner, classAtom, wndExtra )))
|
||||
if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
|
||||
{
|
||||
TRACE("out of memory\n" );
|
||||
return 0;
|
||||
|
@ -1064,15 +1054,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
wndPtr->tid = GetCurrentThreadId();
|
||||
wndPtr->owner = owner;
|
||||
wndPtr->parent = parent;
|
||||
wndPtr->class = classPtr;
|
||||
wndPtr->winproc = winproc;
|
||||
wndPtr->hInstance = cs->hInstance;
|
||||
wndPtr->text = NULL;
|
||||
wndPtr->hrgnUpdate = 0;
|
||||
wndPtr->hrgnWnd = 0;
|
||||
wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
|
||||
wndPtr->dwExStyle = cs->dwExStyle;
|
||||
wndPtr->clsStyle = clsStyle;
|
||||
wndPtr->wIDmenu = 0;
|
||||
wndPtr->helpContext = 0;
|
||||
wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
|
||||
|
@ -1080,9 +1067,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
wndPtr->pHScroll = NULL;
|
||||
wndPtr->userdata = 0;
|
||||
wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0;
|
||||
wndPtr->cbWndExtra = wndExtra;
|
||||
|
||||
if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
|
||||
|
||||
/* Correct the window style - stage 2 */
|
||||
|
||||
|
@ -1109,9 +1093,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
/* Get class or window DC if needed */
|
||||
|
||||
if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
|
||||
else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
|
||||
else wndPtr->dce = NULL;
|
||||
if (wndPtr->clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
|
||||
|
||||
/* Set the window menu */
|
||||
|
||||
|
@ -1248,9 +1230,6 @@ HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
|
|||
CREATESTRUCTA cs;
|
||||
char buffer[256];
|
||||
|
||||
if(!instance)
|
||||
instance=GetModuleHandleA(NULL);
|
||||
|
||||
if(exStyle & WS_EX_MDICHILD)
|
||||
return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
|
||||
|
||||
|
@ -1307,9 +1286,6 @@ HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
|
|||
CREATESTRUCTW cs;
|
||||
WCHAR buffer[256];
|
||||
|
||||
if(!instance)
|
||||
instance=GetModuleHandleW(NULL);
|
||||
|
||||
if(exStyle & WS_EX_MDICHILD)
|
||||
return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
|
||||
|
||||
|
|
Loading…
Reference in New Issue