Commit 1a66d226 authored by Alexandre Julliard's avatar Alexandre Julliard

Added global management of user handles in the server.

Very preliminary support for shared window handles.
parent 724afcb0
......@@ -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 ### */
......
/*
* 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;
}
/*
* 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 */
/*
* 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 = ();
......
......@@ -478,30 +478,6 @@ HTASK16 WINAPI GetWindowTask16( HWND16 hwnd )
}
/***********************************************************************
* 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)
*/
HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment