mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
Added global management of user handles in the server.
Very preliminary support for shared window handles.
This commit is contained in:
parent
724afcb0c9
commit
1a66d226eb
18 changed files with 818 additions and 194 deletions
|
@ -555,8 +555,8 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
|
|||
|
||||
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
|
||||
{
|
||||
if ( WIN_UnlinkWindow( winpos->hwnd ) )
|
||||
WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
|
||||
HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
|
||||
if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
|
||||
}
|
||||
|
||||
/* FIXME: actually do something with WVR_VALIDRECTS */
|
||||
|
|
|
@ -55,6 +55,7 @@ static DWORD CALLBACK desktop_thread( LPVOID driver_data )
|
|||
|
||||
/* patch the desktop window queue to point to our queue */
|
||||
win = WIN_FindWndPtr( hwnd );
|
||||
win->tid = GetCurrentThreadId();
|
||||
win->hmemTaskQ = InitThreadInput16( 0, 0 );
|
||||
X11DRV_register_window( display, hwnd, win->pDriverData );
|
||||
WIN_ReleaseWndPtr( win );
|
||||
|
|
|
@ -863,9 +863,9 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
|
|||
(unsigned int)data->whole_window, (unsigned int)data->client_window );
|
||||
|
||||
if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
|
||||
WIN_LinkWindow( hwnd, HWND_BOTTOM );
|
||||
WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_BOTTOM );
|
||||
else
|
||||
WIN_LinkWindow( hwnd, HWND_TOP );
|
||||
WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_TOP );
|
||||
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
|
||||
|
@ -997,9 +997,7 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
|
|||
{
|
||||
struct x11drv_win_data *data = wndPtr->pDriverData;
|
||||
|
||||
WIN_UnlinkWindow(wndPtr->hwndSelf);
|
||||
wndPtr->parent = pWndParent;
|
||||
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
|
||||
WIN_LinkWindow( hwnd, parent, HWND_TOP );
|
||||
|
||||
if (parent != GetDesktopWindow()) /* a child window */
|
||||
{
|
||||
|
|
|
@ -722,8 +722,8 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
|
|||
|
||||
if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
|
||||
{
|
||||
if ( WIN_UnlinkWindow( winpos->hwnd ) )
|
||||
WIN_LinkWindow( winpos->hwnd, winpos->hwndInsertAfter );
|
||||
HWND parent = GetAncestor( winpos->hwnd, GA_PARENT );
|
||||
if (parent) WIN_LinkWindow( winpos->hwnd, parent, winpos->hwndInsertAfter );
|
||||
}
|
||||
|
||||
/* Reset active DCEs */
|
||||
|
|
|
@ -29,6 +29,7 @@ typedef struct tagWND
|
|||
struct tagCLASS *class; /* Window class */
|
||||
HWINDOWPROC winproc; /* Window procedure */
|
||||
DWORD dwMagic; /* Magic number (must be WND_MAGIC) */
|
||||
DWORD tid; /* Owner thread id */
|
||||
HWND hwndSelf; /* Handle of this window */
|
||||
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
|
||||
RECT rectClient; /* Client area rel. to parent client area */
|
||||
|
@ -86,8 +87,8 @@ extern void WIN_ReleaseWndPtr(WND *wndPtr);
|
|||
extern void WIN_UpdateWndPtr(WND **oldPtr,WND *newPtr);
|
||||
extern void WIN_DumpWindow( HWND hwnd );
|
||||
extern void WIN_WalkWindows( HWND hwnd, int indent );
|
||||
extern BOOL WIN_UnlinkWindow( HWND hwnd );
|
||||
extern BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter );
|
||||
extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
|
||||
extern void WIN_UnlinkWindow( HWND hwnd );
|
||||
extern HWND WIN_FindWinToRepaint( HWND hwnd );
|
||||
extern void WIN_DestroyThreadWindows( HWND hwnd );
|
||||
extern BOOL WIN_CreateDesktopWindow(void);
|
||||
|
|
|
@ -38,6 +38,7 @@ struct request_max_size
|
|||
#define REQUEST_MAX_VAR_SIZE 1024
|
||||
|
||||
typedef int handle_t;
|
||||
typedef unsigned int user_handle_t;
|
||||
|
||||
|
||||
struct debug_event_exception
|
||||
|
@ -1340,7 +1341,7 @@ struct send_message_request
|
|||
struct request_header __header;
|
||||
void* id;
|
||||
int type;
|
||||
handle_t win;
|
||||
user_handle_t win;
|
||||
unsigned int msg;
|
||||
unsigned int wparam;
|
||||
unsigned int lparam;
|
||||
|
@ -1370,11 +1371,11 @@ struct get_message_request
|
|||
{
|
||||
struct request_header __header;
|
||||
int flags;
|
||||
handle_t get_win;
|
||||
user_handle_t get_win;
|
||||
unsigned int get_first;
|
||||
unsigned int get_last;
|
||||
int type;
|
||||
handle_t win;
|
||||
user_handle_t win;
|
||||
unsigned int msg;
|
||||
unsigned int wparam;
|
||||
unsigned int lparam;
|
||||
|
@ -1412,7 +1413,7 @@ struct get_message_reply_request
|
|||
struct cleanup_window_queue_request
|
||||
{
|
||||
struct request_header __header;
|
||||
handle_t win;
|
||||
user_handle_t win;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1420,7 +1421,7 @@ struct cleanup_window_queue_request
|
|||
struct set_win_timer_request
|
||||
{
|
||||
struct request_header __header;
|
||||
handle_t win;
|
||||
user_handle_t win;
|
||||
unsigned int msg;
|
||||
unsigned int id;
|
||||
unsigned int rate;
|
||||
|
@ -1432,7 +1433,7 @@ struct set_win_timer_request
|
|||
struct kill_win_timer_request
|
||||
{
|
||||
struct request_header __header;
|
||||
handle_t win;
|
||||
user_handle_t win;
|
||||
unsigned int msg;
|
||||
unsigned int id;
|
||||
};
|
||||
|
@ -1549,6 +1550,7 @@ struct disconnect_named_pipe_request
|
|||
handle_t handle;
|
||||
};
|
||||
|
||||
|
||||
struct get_named_pipe_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -1561,6 +1563,50 @@ struct get_named_pipe_info_request
|
|||
|
||||
|
||||
|
||||
struct create_desktop_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct create_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct link_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
user_handle_t parent;
|
||||
user_handle_t previous;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct destroy_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct get_window_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
user_handle_t full_handle;
|
||||
void* pid;
|
||||
void* tid;
|
||||
};
|
||||
|
||||
|
||||
enum request
|
||||
{
|
||||
REQ_new_process,
|
||||
|
@ -1686,6 +1732,11 @@ enum request
|
|||
REQ_wait_named_pipe,
|
||||
REQ_disconnect_named_pipe,
|
||||
REQ_get_named_pipe_info,
|
||||
REQ_create_desktop_window,
|
||||
REQ_create_window,
|
||||
REQ_link_window,
|
||||
REQ_destroy_window,
|
||||
REQ_get_window_info,
|
||||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
|
@ -1816,8 +1867,13 @@ union generic_request
|
|||
struct wait_named_pipe_request wait_named_pipe;
|
||||
struct disconnect_named_pipe_request disconnect_named_pipe;
|
||||
struct get_named_pipe_info_request get_named_pipe_info;
|
||||
struct create_desktop_window_request create_desktop_window;
|
||||
struct create_window_request create_window;
|
||||
struct link_window_request link_window;
|
||||
struct destroy_window_request destroy_window;
|
||||
struct get_window_info_request get_window_info;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 51
|
||||
#define SERVER_PROTOCOL_VERSION 52
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -36,7 +36,9 @@ C_SRCS = \
|
|||
thread.c \
|
||||
timer.c \
|
||||
trace.c \
|
||||
unicode.c
|
||||
unicode.c \
|
||||
user.c \
|
||||
window.c
|
||||
|
||||
PROGRAMS = wineserver
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ struct request_max_size
|
|||
#define REQUEST_MAX_VAR_SIZE 1024
|
||||
|
||||
typedef int handle_t;
|
||||
typedef unsigned int user_handle_t;
|
||||
|
||||
/* definitions of the event data depending on the event code */
|
||||
struct debug_event_exception
|
||||
|
@ -1197,7 +1198,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
|||
@REQ(send_message)
|
||||
void* id; /* thread id */
|
||||
int type; /* message type (see below) */
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message code */
|
||||
unsigned int wparam; /* parameters */
|
||||
unsigned int lparam; /* parameters */
|
||||
|
@ -1225,12 +1226,12 @@ enum message_type
|
|||
/* Get a message from the current queue */
|
||||
@REQ(get_message)
|
||||
int flags; /* see below */
|
||||
handle_t get_win; /* window handle to get */
|
||||
user_handle_t get_win; /* window handle to get */
|
||||
unsigned int get_first; /* first message code to get */
|
||||
unsigned int get_last; /* last message code to get */
|
||||
@REPLY
|
||||
int type; /* message type */
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message code */
|
||||
unsigned int wparam; /* parameters */
|
||||
unsigned int lparam; /* parameters */
|
||||
|
@ -1263,13 +1264,13 @@ enum message_type
|
|||
|
||||
/* Cleanup a queue when a window is deleted */
|
||||
@REQ(cleanup_window_queue)
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
@END
|
||||
|
||||
|
||||
/* Set a window timer */
|
||||
@REQ(set_win_timer)
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message to post */
|
||||
unsigned int id; /* timer id */
|
||||
unsigned int rate; /* timer rate in ms */
|
||||
|
@ -1279,7 +1280,7 @@ enum message_type
|
|||
|
||||
/* Kill a window timer */
|
||||
@REQ(kill_win_timer)
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message to post */
|
||||
unsigned int id; /* timer id */
|
||||
@END
|
||||
|
@ -1383,6 +1384,7 @@ enum message_type
|
|||
handle_t handle;
|
||||
@END
|
||||
|
||||
|
||||
@REQ(get_named_pipe_info)
|
||||
handle_t handle;
|
||||
@REPLY
|
||||
|
@ -1392,3 +1394,41 @@ enum message_type
|
|||
unsigned int insize;
|
||||
@END
|
||||
|
||||
|
||||
/* Create the desktop window */
|
||||
@REQ(create_desktop_window)
|
||||
@REPLY
|
||||
user_handle_t handle; /* handle to the window */
|
||||
@END
|
||||
|
||||
|
||||
/* Create a window */
|
||||
@REQ(create_window)
|
||||
@REPLY
|
||||
user_handle_t handle; /* handle to the window */
|
||||
@END
|
||||
|
||||
|
||||
/* Link a window into the tree */
|
||||
@REQ(link_window)
|
||||
user_handle_t handle; /* handle to the window */
|
||||
user_handle_t parent; /* handle to the parent */
|
||||
user_handle_t previous; /* previous child in Z-order */
|
||||
@REPLY
|
||||
@END
|
||||
|
||||
|
||||
/* Destroy a window */
|
||||
@REQ(destroy_window)
|
||||
user_handle_t handle; /* handle to the window */
|
||||
@END
|
||||
|
||||
|
||||
/* Get information from a window handle */
|
||||
@REQ(get_window_info)
|
||||
user_handle_t handle; /* handle to the window */
|
||||
@REPLY
|
||||
user_handle_t full_handle; /* full 32-bit handle */
|
||||
void* pid; /* process owning the window */
|
||||
void* tid; /* thread owning the window */
|
||||
@END
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "thread.h"
|
||||
#include "process.h"
|
||||
#include "request.h"
|
||||
#include "user.h"
|
||||
|
||||
enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
|
||||
#define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
|
||||
|
@ -40,7 +41,7 @@ struct message
|
|||
struct message *next; /* next message in list */
|
||||
struct message *prev; /* prev message in list */
|
||||
enum message_type type; /* message type */
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message code */
|
||||
unsigned int wparam; /* parameters */
|
||||
unsigned int lparam; /* parameters */
|
||||
|
@ -65,7 +66,7 @@ struct timer
|
|||
struct timer *prev; /* prev timer in list */
|
||||
struct timeval when; /* next expiration */
|
||||
unsigned int rate; /* timer rate in ms */
|
||||
handle_t win; /* window handle */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message to post */
|
||||
unsigned int id; /* timer id */
|
||||
unsigned int lparam; /* lparam for message */
|
||||
|
@ -550,7 +551,7 @@ static void restart_timer( struct msg_queue *queue, struct timer *timer )
|
|||
}
|
||||
|
||||
/* find an expired timer matching the filtering parameters */
|
||||
static struct timer *find_expired_timer( struct msg_queue *queue, handle_t win,
|
||||
static struct timer *find_expired_timer( struct msg_queue *queue, user_handle_t win,
|
||||
unsigned int get_first, unsigned int get_last,
|
||||
int remove )
|
||||
{
|
||||
|
@ -568,7 +569,8 @@ static struct timer *find_expired_timer( struct msg_queue *queue, handle_t win,
|
|||
}
|
||||
|
||||
/* kill a timer */
|
||||
static int kill_timer( struct msg_queue *queue, handle_t win, unsigned int msg, unsigned int id )
|
||||
static int kill_timer( struct msg_queue *queue, user_handle_t win,
|
||||
unsigned int msg, unsigned int id )
|
||||
{
|
||||
struct timer *timer;
|
||||
|
||||
|
@ -597,12 +599,15 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
|
|||
}
|
||||
|
||||
/* remove all messages and timers belonging to a certain window */
|
||||
static void cleanup_window( struct msg_queue *queue, handle_t win )
|
||||
void queue_cleanup_window( struct thread *thread, user_handle_t win )
|
||||
{
|
||||
struct msg_queue *queue = thread->queue;
|
||||
struct timer *timer;
|
||||
struct message *msg;
|
||||
int i;
|
||||
|
||||
if (!queue) return;
|
||||
|
||||
/* remove timers */
|
||||
timer = queue->first_timer;
|
||||
while (timer)
|
||||
|
@ -818,7 +823,8 @@ static void return_message_to_app( struct msg_queue *queue, struct get_message_r
|
|||
}
|
||||
|
||||
|
||||
inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
|
||||
inline static struct message *find_matching_message( const struct message_list *list,
|
||||
user_handle_t win,
|
||||
unsigned int first, unsigned int last )
|
||||
{
|
||||
struct message *msg;
|
||||
|
@ -981,7 +987,7 @@ DECL_HANDLER(get_message_reply)
|
|||
/* cleanup a queue when a window is deleted */
|
||||
DECL_HANDLER(cleanup_window_queue)
|
||||
{
|
||||
if (current->queue) cleanup_window( current->queue, req->win );
|
||||
queue_cleanup_window( current, req->win );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -188,6 +188,11 @@ DECL_HANDLER(connect_named_pipe);
|
|||
DECL_HANDLER(wait_named_pipe);
|
||||
DECL_HANDLER(disconnect_named_pipe);
|
||||
DECL_HANDLER(get_named_pipe_info);
|
||||
DECL_HANDLER(create_desktop_window);
|
||||
DECL_HANDLER(create_window);
|
||||
DECL_HANDLER(link_window);
|
||||
DECL_HANDLER(destroy_window);
|
||||
DECL_HANDLER(get_window_info);
|
||||
|
||||
#ifdef WANT_REQUEST_HANDLERS
|
||||
|
||||
|
@ -317,6 +322,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_wait_named_pipe,
|
||||
(req_handler)req_disconnect_named_pipe,
|
||||
(req_handler)req_get_named_pipe_info,
|
||||
(req_handler)req_create_desktop_window,
|
||||
(req_handler)req_create_window,
|
||||
(req_handler)req_link_window,
|
||||
(req_handler)req_destroy_window,
|
||||
(req_handler)req_get_window_info,
|
||||
};
|
||||
#endif /* WANT_REQUEST_HANDLERS */
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "process.h"
|
||||
#include "thread.h"
|
||||
#include "request.h"
|
||||
#include "user.h"
|
||||
|
||||
|
||||
/* thread queues */
|
||||
|
@ -179,6 +180,7 @@ static void cleanup_thread( struct thread *thread )
|
|||
release_object( thread->queue );
|
||||
thread->queue = NULL;
|
||||
}
|
||||
destroy_thread_windows( thread );
|
||||
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
|
||||
{
|
||||
if (thread->inflight[i].client != -1)
|
||||
|
|
|
@ -1459,7 +1459,7 @@ static void dump_send_message_request( const struct send_message_request *req )
|
|||
{
|
||||
fprintf( stderr, " id=%p,", req->id );
|
||||
fprintf( stderr, " type=%d,", req->type );
|
||||
fprintf( stderr, " win=%d,", req->win );
|
||||
fprintf( stderr, " win=%08x,", req->win );
|
||||
fprintf( stderr, " msg=%08x,", req->msg );
|
||||
fprintf( stderr, " wparam=%08x,", req->wparam );
|
||||
fprintf( stderr, " lparam=%08x,", req->lparam );
|
||||
|
@ -1475,7 +1475,7 @@ static void dump_send_message_request( const struct send_message_request *req )
|
|||
static void dump_get_message_request( const struct get_message_request *req )
|
||||
{
|
||||
fprintf( stderr, " flags=%d,", req->flags );
|
||||
fprintf( stderr, " get_win=%d,", req->get_win );
|
||||
fprintf( stderr, " get_win=%08x,", req->get_win );
|
||||
fprintf( stderr, " get_first=%08x,", req->get_first );
|
||||
fprintf( stderr, " get_last=%08x", req->get_last );
|
||||
}
|
||||
|
@ -1483,7 +1483,7 @@ static void dump_get_message_request( const struct get_message_request *req )
|
|||
static void dump_get_message_reply( const struct get_message_request *req )
|
||||
{
|
||||
fprintf( stderr, " type=%d,", req->type );
|
||||
fprintf( stderr, " win=%d,", req->win );
|
||||
fprintf( stderr, " win=%08x,", req->win );
|
||||
fprintf( stderr, " msg=%08x,", req->msg );
|
||||
fprintf( stderr, " wparam=%08x,", req->wparam );
|
||||
fprintf( stderr, " lparam=%08x,", req->lparam );
|
||||
|
@ -1517,12 +1517,12 @@ static void dump_get_message_reply_reply( const struct get_message_reply_request
|
|||
|
||||
static void dump_cleanup_window_queue_request( const struct cleanup_window_queue_request *req )
|
||||
{
|
||||
fprintf( stderr, " win=%d", req->win );
|
||||
fprintf( stderr, " win=%08x", req->win );
|
||||
}
|
||||
|
||||
static void dump_set_win_timer_request( const struct set_win_timer_request *req )
|
||||
{
|
||||
fprintf( stderr, " win=%d,", req->win );
|
||||
fprintf( stderr, " win=%08x,", req->win );
|
||||
fprintf( stderr, " msg=%08x,", req->msg );
|
||||
fprintf( stderr, " id=%08x,", req->id );
|
||||
fprintf( stderr, " rate=%08x,", req->rate );
|
||||
|
@ -1531,7 +1531,7 @@ static void dump_set_win_timer_request( const struct set_win_timer_request *req
|
|||
|
||||
static void dump_kill_win_timer_request( const struct kill_win_timer_request *req )
|
||||
{
|
||||
fprintf( stderr, " win=%d,", req->win );
|
||||
fprintf( stderr, " win=%08x,", req->win );
|
||||
fprintf( stderr, " msg=%08x,", req->msg );
|
||||
fprintf( stderr, " id=%08x", req->id );
|
||||
}
|
||||
|
@ -1652,6 +1652,48 @@ static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_req
|
|||
fprintf( stderr, " insize=%08x", req->insize );
|
||||
}
|
||||
|
||||
static void dump_create_desktop_window_request( const struct create_desktop_window_request *req )
|
||||
{
|
||||
}
|
||||
|
||||
static void dump_create_desktop_window_reply( const struct create_desktop_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_create_window_request( const struct create_window_request *req )
|
||||
{
|
||||
}
|
||||
|
||||
static void dump_create_window_reply( const struct create_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_link_window_request( const struct link_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x,", req->handle );
|
||||
fprintf( stderr, " parent=%08x,", req->parent );
|
||||
fprintf( stderr, " previous=%08x", req->previous );
|
||||
}
|
||||
|
||||
static void dump_destroy_window_request( const struct destroy_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_get_window_info_request( const struct get_window_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_get_window_info_reply( const struct get_window_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " full_handle=%08x,", req->full_handle );
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " tid=%p", req->tid );
|
||||
}
|
||||
|
||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||
(dump_func)dump_new_process_request,
|
||||
(dump_func)dump_get_new_process_info_request,
|
||||
|
@ -1776,6 +1818,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_wait_named_pipe_request,
|
||||
(dump_func)dump_disconnect_named_pipe_request,
|
||||
(dump_func)dump_get_named_pipe_info_request,
|
||||
(dump_func)dump_create_desktop_window_request,
|
||||
(dump_func)dump_create_window_request,
|
||||
(dump_func)dump_link_window_request,
|
||||
(dump_func)dump_destroy_window_request,
|
||||
(dump_func)dump_get_window_info_request,
|
||||
};
|
||||
|
||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||
|
@ -1902,6 +1949,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_named_pipe_info_reply,
|
||||
(dump_func)dump_create_desktop_window_reply,
|
||||
(dump_func)dump_create_window_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_window_info_reply,
|
||||
};
|
||||
|
||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||
|
@ -2028,6 +2080,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"wait_named_pipe",
|
||||
"disconnect_named_pipe",
|
||||
"get_named_pipe_info",
|
||||
"create_desktop_window",
|
||||
"create_window",
|
||||
"link_window",
|
||||
"destroy_window",
|
||||
"get_window_info",
|
||||
};
|
||||
|
||||
/* ### make_requests end ### */
|
||||
|
|
149
server/user.c
Normal file
149
server/user.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Server-side USER handles
|
||||
*
|
||||
* Copyright (C) 2001 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include "thread.h"
|
||||
#include "user.h"
|
||||
|
||||
struct user_handle
|
||||
{
|
||||
void *ptr; /* pointer to object */
|
||||
unsigned short type; /* object type (0 if free) */
|
||||
unsigned short generation; /* generation counter */
|
||||
};
|
||||
|
||||
static struct user_handle *handles;
|
||||
static struct user_handle *freelist;
|
||||
static int nb_handles;
|
||||
static int allocated_handles;
|
||||
|
||||
#define FIRST_HANDLE 32 /* handle value for first table entry */
|
||||
#define MAX_HANDLES (65536-FIRST_HANDLE)
|
||||
|
||||
static struct user_handle *handle_to_entry( user_handle_t handle )
|
||||
{
|
||||
int index = (handle & 0xffff) - FIRST_HANDLE;
|
||||
if (index < 0 || index >= nb_handles) return NULL;
|
||||
if (!handles[index].type) return NULL;
|
||||
if ((handle >> 16) && (handle >> 16 != handles[index].generation)) return NULL;
|
||||
return &handles[index];
|
||||
}
|
||||
|
||||
inline static user_handle_t entry_to_handle( struct user_handle *ptr )
|
||||
{
|
||||
int index = ptr - handles;
|
||||
return (index + FIRST_HANDLE) + (ptr->generation << 16);
|
||||
}
|
||||
|
||||
inline static struct user_handle *alloc_user_entry(void)
|
||||
{
|
||||
struct user_handle *handle;
|
||||
|
||||
if (freelist)
|
||||
{
|
||||
handle = freelist;
|
||||
freelist = handle->ptr;
|
||||
return handle;
|
||||
}
|
||||
if (nb_handles >= allocated_handles) /* need to grow the array */
|
||||
{
|
||||
struct user_handle *new_handles;
|
||||
/* grow array by 50% (but at minimum 32 entries) */
|
||||
int growth = max( 32, allocated_handles / 2 );
|
||||
int new_size = min( allocated_handles + growth, MAX_HANDLES );
|
||||
if (new_size <= allocated_handles) return NULL;
|
||||
if (!(new_handles = realloc( handles, new_size * sizeof(*handles) )))
|
||||
return NULL;
|
||||
handles = new_handles;
|
||||
allocated_handles = new_size;
|
||||
}
|
||||
handle = &handles[nb_handles++];
|
||||
handle->generation = 0;
|
||||
return handle;
|
||||
}
|
||||
|
||||
inline static void *free_user_entry( struct user_handle *ptr )
|
||||
{
|
||||
void *ret;
|
||||
ret = ptr->ptr;
|
||||
ptr->ptr = freelist;
|
||||
ptr->type = 0;
|
||||
freelist = ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* allocate a user handle for a given object */
|
||||
user_handle_t alloc_user_handle( void *ptr, enum user_object type )
|
||||
{
|
||||
struct user_handle *entry = alloc_user_entry();
|
||||
if (!entry) return 0;
|
||||
entry->ptr = ptr;
|
||||
entry->type = type;
|
||||
if (++entry->generation >= 0xffff) entry->generation = 1;
|
||||
return entry_to_handle( entry );
|
||||
}
|
||||
|
||||
/* return a pointer to a user object from its handle */
|
||||
void *get_user_object( user_handle_t handle, enum user_object type )
|
||||
{
|
||||
struct user_handle *entry;
|
||||
|
||||
if (!(entry = handle_to_entry( handle )) || entry->type != type)
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
return NULL;
|
||||
}
|
||||
return entry->ptr;
|
||||
}
|
||||
|
||||
/* same as get_user_object plus set the handle to the full 32-bit value */
|
||||
void *get_user_object_handle( user_handle_t *handle, enum user_object type )
|
||||
{
|
||||
struct user_handle *entry;
|
||||
|
||||
if (!(entry = handle_to_entry( *handle )) || entry->type != type)
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
return NULL;
|
||||
}
|
||||
*handle = entry_to_handle( entry );
|
||||
return entry->ptr;
|
||||
}
|
||||
|
||||
/* free a user handle and return a pointer to the object */
|
||||
void *free_user_handle( user_handle_t handle )
|
||||
{
|
||||
struct user_handle *entry;
|
||||
|
||||
if (!(entry = handle_to_entry( handle )))
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
return NULL;
|
||||
}
|
||||
return free_user_entry( entry );
|
||||
}
|
||||
|
||||
/* return the next user handle after 'handle' that is of a given type */
|
||||
void *next_user_handle( user_handle_t *handle, enum user_object type )
|
||||
{
|
||||
struct user_handle *entry;
|
||||
|
||||
if (!*handle) entry = handles;
|
||||
else
|
||||
{
|
||||
if (!(entry = handle_to_entry( *handle ))) return NULL;
|
||||
entry++; /* start from the next one */
|
||||
}
|
||||
while (entry < handles + nb_handles)
|
||||
{
|
||||
if (!type || entry->type == type)
|
||||
{
|
||||
*handle = entry_to_handle( entry );
|
||||
return entry->ptr;
|
||||
}
|
||||
entry++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
36
server/user.h
Normal file
36
server/user.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Wine server USER definitions
|
||||
*
|
||||
* Copyright (C) 2001 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#ifndef __WINE_SERVER_USER_H
|
||||
#define __WINE_SERVER_USER_H
|
||||
|
||||
#include "wine/server_protocol.h"
|
||||
|
||||
struct thread;
|
||||
struct window;
|
||||
|
||||
enum user_object
|
||||
{
|
||||
USER_WINDOW = 1
|
||||
};
|
||||
|
||||
/* user handles functions */
|
||||
|
||||
extern user_handle_t alloc_user_handle( void *ptr, enum user_object type );
|
||||
extern void *get_user_object( user_handle_t handle, enum user_object type );
|
||||
extern void *get_user_object_handle( user_handle_t *handle, enum user_object type );
|
||||
extern void *free_user_handle( user_handle_t handle );
|
||||
extern void *next_user_handle( user_handle_t *handle, enum user_object type );
|
||||
|
||||
/* queue functions */
|
||||
|
||||
extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
|
||||
|
||||
/* window functions */
|
||||
|
||||
extern void destroy_thread_windows( struct thread *thread );
|
||||
|
||||
#endif /* __WINE_SERVER_USER_H */
|
179
server/window.c
Normal file
179
server/window.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Server-side window handling
|
||||
*
|
||||
* Copyright (C) 2001 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "object.h"
|
||||
#include "request.h"
|
||||
#include "thread.h"
|
||||
#include "process.h"
|
||||
#include "user.h"
|
||||
|
||||
struct window
|
||||
{
|
||||
struct window *parent; /* parent window */
|
||||
struct window *child; /* first child window */
|
||||
struct window *next; /* next window in Z-order */
|
||||
struct window *prev; /* prev window in Z-order */
|
||||
user_handle_t handle; /* full handle for this window */
|
||||
struct thread *thread; /* thread owning the window */
|
||||
};
|
||||
|
||||
static struct window *top_window; /* top-level (desktop) window */
|
||||
|
||||
/* link a window into the tree (or unlink it if the new parent is NULL) */
|
||||
static void link_window( struct window *win, struct window *parent, struct window *previous )
|
||||
{
|
||||
if (win->parent) /* unlink it from the previous location */
|
||||
{
|
||||
if (win->next) win->next->prev = win->prev;
|
||||
if (win->prev) win->prev->next = win->next;
|
||||
else win->parent->child = win->next;
|
||||
}
|
||||
if ((win->parent = parent))
|
||||
{
|
||||
if ((win->prev = previous))
|
||||
{
|
||||
if ((win->next = previous->next)) win->next->prev = win;
|
||||
win->prev->next = win;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((win->next = parent->child)) win->next->prev = win;
|
||||
parent->child = win;
|
||||
}
|
||||
}
|
||||
else win->next = win->prev = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* free a window structure */
|
||||
static void free_window( struct window *win )
|
||||
{
|
||||
assert( win != top_window );
|
||||
|
||||
while (win->child) free_window( win->child );
|
||||
if (win->thread->queue) queue_cleanup_window( win->thread, win->handle );
|
||||
free_user_handle( win->handle );
|
||||
if (win->parent) link_window( win, NULL, NULL );
|
||||
memset( win, 0x55, sizeof(*win) );
|
||||
free( win );
|
||||
}
|
||||
|
||||
/* create a new window structure */
|
||||
static struct window *create_window(void)
|
||||
{
|
||||
struct window *win = mem_alloc( sizeof(*win) );
|
||||
if (!win) return NULL;
|
||||
|
||||
if (!(win->handle = alloc_user_handle( win, USER_WINDOW )))
|
||||
{
|
||||
free( win );
|
||||
return NULL;
|
||||
}
|
||||
win->parent = NULL;
|
||||
win->child = NULL;
|
||||
win->next = NULL;
|
||||
win->prev = NULL;
|
||||
win->thread = current;
|
||||
return win;
|
||||
}
|
||||
|
||||
/* destroy all windows belonging to a given thread */
|
||||
void destroy_thread_windows( struct thread *thread )
|
||||
{
|
||||
user_handle_t handle = 0;
|
||||
struct window *win;
|
||||
|
||||
while ((win = next_user_handle( &handle, USER_WINDOW )))
|
||||
{
|
||||
if (win->thread != thread) continue;
|
||||
free_window( win );
|
||||
}
|
||||
}
|
||||
|
||||
/* create a window */
|
||||
DECL_HANDLER(create_window)
|
||||
{
|
||||
struct window *win;
|
||||
|
||||
req->handle = 0;
|
||||
if ((win = create_window())) req->handle = win->handle;
|
||||
}
|
||||
|
||||
|
||||
/* create the desktop window */
|
||||
DECL_HANDLER(create_desktop_window)
|
||||
{
|
||||
req->handle = 0;
|
||||
if (!top_window)
|
||||
{
|
||||
if (!(top_window = create_window())) return;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
}
|
||||
req->handle = top_window->handle;
|
||||
}
|
||||
|
||||
|
||||
/* link a window into the tree */
|
||||
DECL_HANDLER(link_window)
|
||||
{
|
||||
struct window *win, *parent = NULL, *previous = NULL;
|
||||
|
||||
if (!(win = get_user_object( req->handle, USER_WINDOW ))) return;
|
||||
if (req->parent && !(parent = get_user_object( req->parent, USER_WINDOW ))) return;
|
||||
if (parent && req->previous)
|
||||
{
|
||||
if (req->previous == 1) /* special case: HWND_BOTTOM */
|
||||
{
|
||||
if ((previous = parent->child))
|
||||
{
|
||||
/* make it the last of the list */
|
||||
while (previous->next) previous = previous->next;
|
||||
}
|
||||
}
|
||||
else if (!(previous = get_user_object( req->previous, USER_WINDOW ))) return;
|
||||
|
||||
if (previous && previous->parent != parent) /* previous must be a child of parent */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
}
|
||||
link_window( win, parent, previous );
|
||||
}
|
||||
|
||||
|
||||
/* destroy a window */
|
||||
DECL_HANDLER(destroy_window)
|
||||
{
|
||||
struct window *win = get_user_object( req->handle, USER_WINDOW );
|
||||
if (win)
|
||||
{
|
||||
if (win != top_window) free_window( win );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get information from a window handle */
|
||||
DECL_HANDLER(get_window_info)
|
||||
{
|
||||
user_handle_t handle = req->handle;
|
||||
struct window *win = get_user_object_handle( &handle, USER_WINDOW );
|
||||
|
||||
req->full_handle = 0;
|
||||
req->tid = req->pid = 0;
|
||||
if (win)
|
||||
{
|
||||
req->full_handle = handle;
|
||||
if (win->thread)
|
||||
{
|
||||
req->tid = get_thread_id( win->thread );
|
||||
req->pid = get_process_id( win->thread->process );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
"void*" => "%p",
|
||||
"time_t" => "%ld",
|
||||
"handle_t" => "%d",
|
||||
"user_handle_t" => "%08x",
|
||||
);
|
||||
|
||||
my @requests = ();
|
||||
|
|
|
@ -477,30 +477,6 @@ HTASK16 WINAPI GetWindowTask16( HWND16 hwnd )
|
|||
return retvalue;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetWindowThreadProcessId (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
|
||||
{
|
||||
DWORD retvalue;
|
||||
MESSAGEQUEUE *queue;
|
||||
|
||||
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (!wndPtr) return 0;
|
||||
|
||||
queue = QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
|
||||
if (!queue) return 0;
|
||||
|
||||
if ( process ) *process = (DWORD)queue->teb->pid;
|
||||
retvalue = (DWORD)queue->teb->tid;
|
||||
|
||||
QUEUE_Unlock( queue );
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* InitThreadInput (USER.409)
|
||||
*/
|
||||
|
|
374
windows/win.c
374
windows/win.c
|
@ -9,6 +9,7 @@
|
|||
#include "windef.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "win.h"
|
||||
#include "heap.h"
|
||||
|
@ -38,6 +39,8 @@ static HWND hwndSysModal = 0;
|
|||
static WORD wDragWidth = 4;
|
||||
static WORD wDragHeight= 3;
|
||||
|
||||
static void *user_handles[65536];
|
||||
|
||||
/* thread safeness */
|
||||
extern SYSLEVEL USER_SysLevel; /* FIXME */
|
||||
|
||||
|
@ -69,6 +72,80 @@ void WIN_RestoreWndsLock( int ipreviousLocks )
|
|||
_EnterSysLevel( &USER_SysLevel );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* create_window_handle
|
||||
*
|
||||
* Create a window handle with the server.
|
||||
*/
|
||||
static WND *create_window_handle( BOOL desktop, INT size )
|
||||
{
|
||||
BOOL res;
|
||||
unsigned int handle = 0;
|
||||
WND *win = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
|
||||
if (!win) return NULL;
|
||||
|
||||
USER_Lock();
|
||||
|
||||
if (desktop)
|
||||
{
|
||||
SERVER_START_REQ( create_desktop_window )
|
||||
{
|
||||
if ((res = !SERVER_CALL_ERR())) handle = req->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
if ((res = !SERVER_CALL_ERR())) handle = req->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
{
|
||||
USER_Unlock();
|
||||
HeapFree( GetProcessHeap(), 0, win );
|
||||
return NULL;
|
||||
}
|
||||
user_handles[LOWORD(handle)] = win;
|
||||
win->hwndSelf = (HWND)handle;
|
||||
win->dwMagic = WND_MAGIC;
|
||||
win->irefCount = 1;
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* free_window_handle
|
||||
*
|
||||
* Free a window handle.
|
||||
*/
|
||||
static WND *free_window_handle( HWND hwnd )
|
||||
{
|
||||
WND *ptr;
|
||||
|
||||
USER_Lock();
|
||||
if ((ptr = user_handles[LOWORD(hwnd)]))
|
||||
{
|
||||
SERVER_START_REQ( destroy_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
user_handles[LOWORD(hwnd)] = NULL;
|
||||
else
|
||||
ptr = NULL;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
USER_Unlock();
|
||||
if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_FindWndPtr
|
||||
*
|
||||
|
@ -77,34 +154,35 @@ void WIN_RestoreWndsLock( int ipreviousLocks )
|
|||
WND * WIN_FindWndPtr( HWND hwnd )
|
||||
{
|
||||
WND * ptr;
|
||||
|
||||
if (!hwnd || HIWORD(hwnd)) goto error2;
|
||||
ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
|
||||
/* Lock all WND structures for thread safeness*/
|
||||
USER_Lock();
|
||||
/*and increment destruction monitoring*/
|
||||
ptr->irefCount++;
|
||||
|
||||
if (ptr->dwMagic != WND_MAGIC) goto error;
|
||||
if (ptr->hwndSelf != hwnd)
|
||||
if (!hwnd) return NULL;
|
||||
|
||||
USER_Lock();
|
||||
if (!(ptr = user_handles[LOWORD(hwnd)]))
|
||||
{
|
||||
ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
|
||||
/* check other processes */
|
||||
if (IsWindow( hwnd ))
|
||||
{
|
||||
ERR( "window %04x belongs to other process\n", hwnd );
|
||||
/* DbgBreakPoint(); */
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
/* returns a locked pointer */
|
||||
if (ptr->dwMagic != WND_MAGIC) goto error;
|
||||
/* verify that handle highword (if any) matches the window */
|
||||
if (HIWORD(hwnd) && hwnd != ptr->hwndSelf) goto error;
|
||||
/*and increment destruction monitoring*/
|
||||
ptr->irefCount++;
|
||||
return ptr;
|
||||
|
||||
error:
|
||||
/* Unlock all WND structures for thread safeness*/
|
||||
USER_Unlock();
|
||||
/* and decrement destruction monitoring value */
|
||||
ptr->irefCount--;
|
||||
|
||||
error2:
|
||||
if ( hwnd!=0 )
|
||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_LockWndPtr
|
||||
*
|
||||
|
@ -140,8 +218,7 @@ void WIN_ReleaseWndPtr(WND *wndPtr)
|
|||
if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
|
||||
{
|
||||
/* Release memory */
|
||||
USER_HEAP_FREE( wndPtr->hwndSelf);
|
||||
wndPtr->hwndSelf = 0;
|
||||
free_window_handle( wndPtr->hwndSelf );
|
||||
}
|
||||
else if(wndPtr->irefCount < 0)
|
||||
{
|
||||
|
@ -173,27 +250,9 @@ void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
|
|||
*
|
||||
* Remove a window from the siblings linked list.
|
||||
*/
|
||||
BOOL WIN_UnlinkWindow( HWND hwnd )
|
||||
{
|
||||
WND *wndPtr, **ppWnd;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
|
||||
else if(!wndPtr->parent)
|
||||
{
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ppWnd = &wndPtr->parent->child;
|
||||
while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
|
||||
if (*ppWnd)
|
||||
{
|
||||
*ppWnd = wndPtr->next;
|
||||
ret = TRUE;
|
||||
}
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return ret;
|
||||
void WIN_UnlinkWindow( HWND hwnd )
|
||||
{
|
||||
WIN_LinkWindow( hwnd, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,38 +262,62 @@ BOOL WIN_UnlinkWindow( HWND hwnd )
|
|||
* Insert a window into the siblings linked list.
|
||||
* The window is inserted after the specified window, which can also
|
||||
* be specified as HWND_TOP or HWND_BOTTOM.
|
||||
* If parent is 0, window is unlinked from the tree.
|
||||
*/
|
||||
BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
|
||||
{
|
||||
WND *wndPtr, **ppWnd;
|
||||
void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
||||
{
|
||||
WND *wndPtr, **ppWnd, *parentPtr = NULL;
|
||||
BOOL ret;
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
|
||||
else if(!wndPtr->parent)
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
|
||||
if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
|
||||
{
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return FALSE;
|
||||
return;
|
||||
}
|
||||
if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
|
||||
|
||||
SERVER_START_REQ( link_window )
|
||||
{
|
||||
ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
|
||||
if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
|
||||
while (*ppWnd) ppWnd = &(*ppWnd)->next;
|
||||
req->handle = hwnd;
|
||||
req->parent = parent;
|
||||
req->previous = hwndInsertAfter;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
else /* Normal case */
|
||||
SERVER_END_REQ;
|
||||
if (!ret) goto done;
|
||||
|
||||
/* first unlink it if it is linked */
|
||||
if (wndPtr->parent)
|
||||
{
|
||||
WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
|
||||
if (!afterPtr)
|
||||
{
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return FALSE;
|
||||
}
|
||||
ppWnd = &afterPtr->next;
|
||||
WIN_ReleaseWndPtr(afterPtr);
|
||||
ppWnd = &wndPtr->parent->child;
|
||||
while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
|
||||
if (*ppWnd) *ppWnd = wndPtr->next;
|
||||
}
|
||||
wndPtr->next = *ppWnd;
|
||||
*ppWnd = wndPtr;
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return TRUE;
|
||||
|
||||
wndPtr->parent = parentPtr;
|
||||
|
||||
if (parentPtr)
|
||||
{
|
||||
if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
|
||||
{
|
||||
ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
|
||||
if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
|
||||
while (*ppWnd) ppWnd = &(*ppWnd)->next;
|
||||
}
|
||||
else /* Normal case */
|
||||
{
|
||||
WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
|
||||
if (!afterPtr) goto done;
|
||||
ppWnd = &afterPtr->next;
|
||||
WIN_ReleaseWndPtr(afterPtr);
|
||||
}
|
||||
wndPtr->next = *ppWnd;
|
||||
*ppWnd = wndPtr;
|
||||
}
|
||||
|
||||
done:
|
||||
WIN_ReleaseWndPtr( parentPtr );
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,17 +499,16 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
&wndExtra, &winproc, &clsStyle, &dce )))
|
||||
return FALSE;
|
||||
|
||||
hwndDesktop = USER_HEAP_ALLOC( sizeof(WND) + wndExtra );
|
||||
if (!hwndDesktop) return FALSE;
|
||||
pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
|
||||
pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra );
|
||||
if (!pWndDesktop) return FALSE;
|
||||
hwndDesktop = pWndDesktop->hwndSelf;
|
||||
|
||||
pWndDesktop->tid = 0; /* nobody owns the desktop */
|
||||
pWndDesktop->next = NULL;
|
||||
pWndDesktop->child = NULL;
|
||||
pWndDesktop->parent = NULL;
|
||||
pWndDesktop->owner = 0;
|
||||
pWndDesktop->class = class;
|
||||
pWndDesktop->dwMagic = WND_MAGIC;
|
||||
pWndDesktop->hwndSelf = hwndDesktop;
|
||||
pWndDesktop->hInstance = 0;
|
||||
pWndDesktop->rectWindow.left = 0;
|
||||
pWndDesktop->rectWindow.top = 0;
|
||||
|
@ -452,7 +534,6 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
pWndDesktop->userdata = 0;
|
||||
pWndDesktop->winproc = winproc;
|
||||
pWndDesktop->cbWndExtra = wndExtra;
|
||||
pWndDesktop->irefCount = 0;
|
||||
|
||||
cs.lpCreateParams = NULL;
|
||||
cs.hInstance = 0;
|
||||
|
@ -470,6 +551,7 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
|
||||
|
||||
pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
|
||||
WIN_ReleaseWndPtr( pWndDesktop );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -613,15 +695,17 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
/* Create the window structure */
|
||||
|
||||
if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
|
||||
if (!(wndPtr = create_window_handle( FALSE,
|
||||
sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
|
||||
{
|
||||
TRACE("out of memory\n" );
|
||||
return 0;
|
||||
}
|
||||
hwnd = wndPtr->hwndSelf;
|
||||
|
||||
/* Fill the window structure */
|
||||
|
||||
wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
|
||||
wndPtr->tid = GetCurrentThreadId();
|
||||
wndPtr->next = NULL;
|
||||
wndPtr->child = NULL;
|
||||
|
||||
|
@ -643,8 +727,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
wndPtr->class = classPtr;
|
||||
wndPtr->winproc = winproc;
|
||||
wndPtr->dwMagic = WND_MAGIC;
|
||||
wndPtr->hwndSelf = hwnd;
|
||||
wndPtr->hInstance = cs->hInstance;
|
||||
wndPtr->text = NULL;
|
||||
wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
|
||||
|
@ -664,7 +746,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
|
||||
? MENU_GetSysMenu( hwnd, 0 ) : 0;
|
||||
wndPtr->cbWndExtra = wndExtra;
|
||||
wndPtr->irefCount = 1;
|
||||
|
||||
if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
|
||||
|
||||
|
@ -685,7 +766,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
if (ret)
|
||||
{
|
||||
TRACE("CBT-hook returned 0\n");
|
||||
USER_HEAP_FREE( hwnd );
|
||||
free_window_handle( hwnd );
|
||||
CLASS_RemoveWindow( classPtr );
|
||||
hwnd = 0;
|
||||
goto end;
|
||||
|
@ -1978,14 +2059,64 @@ BOOL16 WINAPI IsWindow16( HWND16 hwnd )
|
|||
*/
|
||||
BOOL WINAPI IsWindow( HWND hwnd )
|
||||
{
|
||||
WND * wndPtr;
|
||||
BOOL retvalue;
|
||||
|
||||
if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
|
||||
retvalue = (wndPtr->dwMagic == WND_MAGIC);
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return retvalue;
|
||||
|
||||
WND *ptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
USER_Lock();
|
||||
if ((ptr = user_handles[LOWORD(hwnd)]))
|
||||
{
|
||||
ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
|
||||
}
|
||||
USER_Unlock();
|
||||
|
||||
if (!ret) /* check other processes */
|
||||
{
|
||||
SERVER_START_REQ( get_window_info )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetWindowThreadProcessId (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
|
||||
{
|
||||
WND *ptr;
|
||||
DWORD tid = 0;
|
||||
|
||||
USER_Lock();
|
||||
if ((ptr = user_handles[LOWORD(hwnd)]))
|
||||
{
|
||||
if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
|
||||
{
|
||||
/* got a valid window */
|
||||
tid = ptr->tid;
|
||||
if (process) *process = GetCurrentProcessId();
|
||||
}
|
||||
else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
|
||||
USER_Unlock();
|
||||
return tid;
|
||||
}
|
||||
USER_Unlock();
|
||||
|
||||
/* check other processes */
|
||||
SERVER_START_REQ( get_window_info )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
{
|
||||
tid = (DWORD)req->tid;
|
||||
if (process) *process = (DWORD)req->pid;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2071,11 +2202,13 @@ HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
|
|||
HWND WINAPI SetParent( HWND hwnd, HWND parent )
|
||||
{
|
||||
WND *wndPtr;
|
||||
WND *pWndParent;
|
||||
DWORD dwStyle;
|
||||
HWND retvalue;
|
||||
|
||||
if (hwnd == GetDesktopWindow()) /* sanity check */
|
||||
if (!parent) parent = GetDesktopWindow();
|
||||
|
||||
/* sanity checks */
|
||||
if (hwnd == GetDesktopWindow() || !IsWindow( parent ))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return 0;
|
||||
|
@ -2088,38 +2221,24 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
|
|||
|
||||
dwStyle = wndPtr->dwStyle;
|
||||
|
||||
if (!parent) parent = GetDesktopWindow();
|
||||
|
||||
if (!(pWndParent = WIN_FindWndPtr(parent)))
|
||||
{
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Windows hides the window first, then shows it again
|
||||
* including the WM_SHOWWINDOW messages and all */
|
||||
if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
|
||||
|
||||
retvalue = wndPtr->parent->hwndSelf; /* old parent */
|
||||
if (pWndParent != wndPtr->parent)
|
||||
if (parent != retvalue)
|
||||
{
|
||||
WIN_UnlinkWindow(wndPtr->hwndSelf);
|
||||
wndPtr->parent = pWndParent;
|
||||
WIN_LinkWindow( hwnd, parent, HWND_TOP );
|
||||
|
||||
if (parent != GetDesktopWindow()) /* a child window */
|
||||
{
|
||||
if( !( wndPtr->dwStyle & WS_CHILD ) )
|
||||
if (!(dwStyle & WS_CHILD))
|
||||
{
|
||||
if( wndPtr->wIDmenu != 0)
|
||||
{
|
||||
DestroyMenu( (HMENU) wndPtr->wIDmenu );
|
||||
wndPtr->wIDmenu = 0;
|
||||
}
|
||||
HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
|
||||
if (menu) DestroyMenu( menu );
|
||||
}
|
||||
}
|
||||
WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
|
||||
}
|
||||
WIN_ReleaseWndPtr( pWndParent );
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
|
||||
/* SetParent additionally needs to make hwnd the topmost window
|
||||
|
@ -2828,45 +2947,36 @@ BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
|
|||
|
||||
if (!IsIconic( hQueryWnd ))
|
||||
{
|
||||
WND *ptrWnd, *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd);
|
||||
|
||||
tempRect = ptrQueryWnd->rectClient;
|
||||
if(ptrQueryWnd->parent)
|
||||
MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
|
||||
(LPPOINT)&tempRect, 2 );
|
||||
GetClientRect( hQueryWnd, &tempRect );
|
||||
MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
|
||||
|
||||
if (PtInRect( &tempRect, pt))
|
||||
{
|
||||
int i;
|
||||
HWND *list = WIN_ListChildren( hQueryWnd );
|
||||
|
||||
wParam = 0;
|
||||
|
||||
for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
|
||||
if (list)
|
||||
{
|
||||
if( ptrWnd->dwStyle & WS_VISIBLE )
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
GetWindowRect( ptrWnd->hwndSelf, &tempRect );
|
||||
if (PtInRect( &tempRect, pt )) break;
|
||||
if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
|
||||
{
|
||||
GetWindowRect( list[i], &tempRect );
|
||||
if (PtInRect( &tempRect, pt )) break;
|
||||
}
|
||||
}
|
||||
if (list[i])
|
||||
{
|
||||
if (IsWindowEnabled( list[i] ))
|
||||
bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
if(ptrWnd)
|
||||
{
|
||||
TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
|
||||
ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
|
||||
ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
|
||||
if( !(ptrWnd->dwStyle & WS_DISABLED) )
|
||||
bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
|
||||
|
||||
WIN_ReleaseWndPtr(ptrWnd);
|
||||
}
|
||||
|
||||
if(bResult)
|
||||
{
|
||||
WIN_ReleaseWndPtr(ptrQueryWnd);
|
||||
return bResult;
|
||||
}
|
||||
if(bResult) return bResult;
|
||||
}
|
||||
else wParam = 1;
|
||||
WIN_ReleaseWndPtr(ptrQueryWnd);
|
||||
}
|
||||
else wParam = 1;
|
||||
|
||||
|
|
Loading…
Reference in a new issue