Commit 51ab43bd authored by Alexandre Julliard's avatar Alexandre Julliard

Moved the major part of message queue and window timer handling into

the server. Implemented MsgWaitForMultipleObjectsEx.
parent cd8d181a
......@@ -414,7 +414,7 @@ debug_channels (accel caret class clipboard combo cursor dc ddeml dialog driver
@ stdcall ModifyMenuW(long long long long ptr) ModifyMenuW
@ stdcall MoveWindow(long long long long long long) MoveWindow
@ stdcall MsgWaitForMultipleObjects(long ptr long long long) MsgWaitForMultipleObjects
@ stub MsgWaitForMultipleObjectsEx
@ stdcall MsgWaitForMultipleObjectsEx(long ptr long long long) MsgWaitForMultipleObjectsEx
@ stdcall OemKeyScan(long) OemKeyScan
@ stdcall OemToCharA(ptr ptr) OemToCharA
@ stdcall OemToCharBuffA(ptr ptr long) OemToCharBuffA
......
......@@ -88,7 +88,7 @@ static BOOL load_driver(void)
GET_USER_FUNC(DestroyWindow);
GET_USER_FUNC(GetDC);
GET_USER_FUNC(EnableWindow);
GET_USER_FUNC(MsgWaitForMultipleObjects);
GET_USER_FUNC(MsgWaitForMultipleObjectsEx);
GET_USER_FUNC(ScrollWindowEx);
GET_USER_FUNC(SetFocus);
GET_USER_FUNC(SetParent);
......
......@@ -31,7 +31,7 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
@ cdecl DestroyWindow(long) X11DRV_DestroyWindow
@ cdecl GetDC(long long long long) X11DRV_GetDC
@ cdecl EnableWindow(long long) X11DRV_EnableWindow
@ cdecl MsgWaitForMultipleObjects(long ptr long long) X11DRV_MsgWaitForMultipleObjects
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
@ cdecl ScrollWindowEx(long long long ptr ptr long ptr long) X11DRV_ScrollWindowEx
@ cdecl SetFocus(long) X11DRV_SetFocus
@ cdecl SetParent(long long) X11DRV_SetParent
......
......@@ -21,8 +21,6 @@ extern BOOL MSG_InternalGetMessage( struct tagMSG *msg, HWND hwnd, HWND hwndOwne
/* timer.c */
extern void TIMER_RemoveWindowTimers( HWND hwnd );
extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue );
extern BOOL TIMER_GetTimerMsg( struct tagMSG *msg, HWND hwnd,
HQUEUE16 hQueue, BOOL remove );
extern BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc );
/* input.c */
......
......@@ -31,43 +31,6 @@ typedef struct tagQMSG
#define QMSG_HARDWARE 3
typedef struct tagSMSG
{
struct tagSMSG *nextProcessing; /* next SMSG in the processing list */
struct tagSMSG *nextPending; /* next SMSG in the pending list */
struct tagSMSG *nextWaiting; /* next SMSG in the waiting list */
HQUEUE16 hSrcQueue; /* sending Queue, (NULL if it didn't wait) */
HQUEUE16 hDstQueue; /* destination Queue */
HWND hWnd; /* destination window */
UINT msg; /* message sent */
WPARAM wParam; /* wParam of the sent message */
LPARAM lParam; /* lParam of the sent message */
LRESULT lResult; /* result of SendMessage */
WORD flags; /* see below SMSG_XXXX */
} SMSG;
/* SMSG -> flags values */
/* set when lResult contains a good value */
#define SMSG_HAVE_RESULT 0x0001
/* protection for multiple call to ReplyMessage16() */
#define SMSG_ALREADY_REPLIED 0x0002
/* use with EARLY_REPLY for forcing the receiver to clean SMSG */
#define SMSG_RECEIVER_CLEANS 0x0010
/* used with EARLY_REPLY to indicate to sender, receiver is done with SMSG */
#define SMSG_RECEIVED 0x0020
/* set in ReceiveMessage() to indicate it's not an early reply */
#define SMSG_SENDING_REPLY 0x0040
/* set when ReplyMessage16() is called by the application */
#define SMSG_EARLY_REPLY 0x0080
/* set when sender is Win32 thread */
#define SMSG_WIN32 0x1000
/* set when sender is a unicode thread */
#define SMSG_UNICODE 0x2000
/* Per-queue data for the message queue
* Note that we currently only store the current values for
* Active, Capture and Focus windows currently.
......@@ -87,7 +50,6 @@ typedef struct tagPERQUEUEDATA
/* Message queue */
typedef struct tagMESSAGEQUEUE
{
HQUEUE16 next; /* Next queue */
HQUEUE16 self; /* Handle to self (was: reserved) */
TEB* teb; /* Thread owning queue */
HANDLE server_queue; /* Handle to server-side queue */
......@@ -96,27 +58,17 @@ typedef struct tagMESSAGEQUEUE
DWORD magic; /* magic number should be QUEUE_MAGIC */
DWORD lockCount; /* reference counter */
WORD msgCount; /* Number of waiting messages */
QMSG* firstMsg; /* First message in linked list */
QMSG* lastMsg; /* Last message in linked list */
WORD wPostQMsg; /* PostQuitMessage flag */
WORD wExitCode; /* PostQuitMessage exit code */
WORD wPaintCount; /* Number of WM_PAINT needed */
WORD wTimerCount; /* Number of timers for this task */
WORD changeBits; /* Changed wake-up bits */
WORD wakeBits; /* Queue wake-up bits */
WORD wakeMask; /* Queue wake-up mask */
DWORD GetMessageTimeVal; /* Value for GetMessageTime */
DWORD GetMessagePosVal; /* Value for GetMessagePos */
DWORD GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
SMSG* smWaiting; /* SendMessage waiting for reply */
SMSG* smProcessing; /* SendMessage currently being processed */
SMSG* smPending; /* SendMessage waiting to be received */
HANDLE16 hCurHook; /* Current hook */
HANDLE16 hooks[WH_NB_HOOKS]; /* Task hooks list */
......@@ -125,14 +77,6 @@ typedef struct tagMESSAGEQUEUE
} MESSAGEQUEUE;
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
#define QS_SMRESULT 0x8000 /* Queue has a SendMessage() result */
/* Types of SMSG stack */
#define SM_PROCESSING_LIST 1 /* list of SM currently being processed */
#define SM_PENDING_LIST 2 /* list of SM wating to be received */
#define SM_WAITING_LIST 3 /* list of SM waiting for reply */
#define QUEUE_MAGIC 0xD46E80AF
/* Per queue data management methods */
......@@ -152,28 +96,22 @@ INT16 PERQDATA_SetCaptureInfo( PERQUEUEDATA *pQData, INT16 nCaptureHT );
extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern void QUEUE_DumpQueue( HQUEUE16 hQueue );
extern void QUEUE_WalkQueues(void);
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear );
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern WORD QUEUE_TestWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern BOOL QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
extern void QUEUE_IncPaintCount( HQUEUE16 hQueue );
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
extern void QUEUE_IncTimerCount( HQUEUE16 hQueue );
extern void QUEUE_DecTimerCount( HQUEUE16 hQueue );
extern BOOL QUEUE_CreateSysMsgQueue( int size );
extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern BOOL QUEUE_AddMsg( HQUEUE16 hQueue, int type, MSG * msg, DWORD extraInfo );
extern QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND hwnd,
int first, int last );
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove,
BOOL sent_only, QMSG *msg );
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
extern SMSG *QUEUE_RemoveSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg );
extern BOOL QUEUE_AddSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg );
extern void QUEUE_CleanupWindow( HWND hwnd );
extern void hardware_event( UINT message, WPARAM wParam, LPARAM lParam,
int xPos, int yPos, DWORD time, DWORD extraInfo );
......
......@@ -1296,14 +1296,41 @@ struct get_msg_queue_request
OUT handle_t handle; /* handle to the queue */
};
/* Wake up a message queue */
struct wake_queue_request
/* Set the message queue wake bits */
struct set_queue_bits_request
{
REQUEST_HEADER; /* request header */
IN handle_t handle; /* handle to the queue */
IN unsigned int bits; /* wake bits */
IN unsigned int set; /* wake bits to set */
IN unsigned int clear; /* wake bits to clear */
IN unsigned int mask_cond; /* mask for conditional bit setting */
OUT unsigned int changed_mask; /* changed bits wake mask */
};
/* Set the current message queue wakeup mask */
struct set_queue_mask_request
{
REQUEST_HEADER; /* request header */
IN unsigned int wake_mask; /* wakeup bits mask */
IN unsigned int changed_mask; /* changed bits mask */
IN int skip_wait; /* will we skip waiting if signaled? */
OUT unsigned int wake_bits; /* current wake bits */
OUT unsigned int changed_bits; /* current changed bits */
};
/* Get the current message queue status */
struct get_queue_status_request
{
REQUEST_HEADER; /* request header */
IN int clear; /* should we clear the change bits? */
OUT unsigned int wake_bits; /* wake bits */
OUT unsigned int changed_bits; /* changed bits since last time */
};
/* Wait for a process to start waiting on input */
struct wait_input_idle_request
{
......@@ -1313,6 +1340,97 @@ struct wait_input_idle_request
OUT handle_t event; /* handle to idle event */
};
/* Send a message to a thread queue */
struct send_message_request
{
REQUEST_HEADER; /* request header */
IN int posted; /* posted instead of sent message? */
IN void* id; /* thread id */
IN int type; /* message type */
IN handle_t win; /* window handle */
IN unsigned int msg; /* message code */
IN unsigned int wparam; /* parameters */
IN unsigned int lparam; /* parameters */
IN unsigned int info; /* extra info */
};
/* Get a message from the current queue */
struct get_message_request
{
REQUEST_HEADER; /* request header */
IN int remove; /* remove it? */
IN int posted; /* check posted messages too? */
IN handle_t get_win; /* window handle to get */
IN unsigned int get_first; /* first message code to get */
IN unsigned int get_last; /* last message code to get */
OUT int sent; /* it is a sent message */
OUT int type; /* message type */
OUT handle_t win; /* window handle */
OUT unsigned int msg; /* message code */
OUT unsigned int wparam; /* parameters */
OUT unsigned int lparam; /* parameters */
OUT unsigned int info; /* extra info */
};
/* Reply to a sent message */
struct reply_message_request
{
REQUEST_HEADER; /* request header */
IN unsigned int result; /* message result */
IN int remove; /* should we remove the message? */
};
/* Retrieve the reply for the last message sent */
struct get_message_reply_request
{
REQUEST_HEADER; /* request header */
IN int cancel; /* cancel message if not ready? */
OUT unsigned int result; /* message result */
};
/* Check if we are processing a sent message */
struct in_send_message_request
{
REQUEST_HEADER; /* request header */
OUT int flags; /* ISMEX_* flags */
};
/* Cleanup a queue when a window is deleted */
struct cleanup_window_queue_request
{
REQUEST_HEADER; /* request header */
IN handle_t win; /* window handle */
};
/* Set a window timer */
struct set_win_timer_request
{
REQUEST_HEADER; /* request header */
IN handle_t win; /* window handle */
IN unsigned int msg; /* message to post */
IN unsigned int id; /* timer id */
IN unsigned int rate; /* timer rate in ms */
IN unsigned int lparam; /* message lparam (callback proc) */
};
/* Kill a window timer */
struct kill_win_timer_request
{
REQUEST_HEADER; /* request header */
IN handle_t win; /* window handle */
IN unsigned int msg; /* message to post */
IN unsigned int id; /* timer id */
};
struct create_serial_request
{
REQUEST_HEADER; /* request header */
......@@ -1473,8 +1591,18 @@ enum request
REQ_get_atom_name,
REQ_init_atom_table,
REQ_get_msg_queue,
REQ_wake_queue,
REQ_set_queue_bits,
REQ_set_queue_mask,
REQ_get_queue_status,
REQ_wait_input_idle,
REQ_send_message,
REQ_get_message,
REQ_reply_message,
REQ_get_message_reply,
REQ_in_send_message,
REQ_cleanup_window_queue,
REQ_set_win_timer,
REQ_kill_win_timer,
REQ_create_serial,
REQ_get_serial_info,
REQ_set_serial_info,
......@@ -1588,15 +1716,25 @@ union generic_request
struct get_atom_name_request get_atom_name;
struct init_atom_table_request init_atom_table;
struct get_msg_queue_request get_msg_queue;
struct wake_queue_request wake_queue;
struct set_queue_bits_request set_queue_bits;
struct set_queue_mask_request set_queue_mask;
struct get_queue_status_request get_queue_status;
struct wait_input_idle_request wait_input_idle;
struct send_message_request send_message;
struct get_message_request get_message;
struct reply_message_request reply_message;
struct get_message_reply_request get_message_reply;
struct in_send_message_request in_send_message;
struct cleanup_window_queue_request cleanup_window_queue;
struct set_win_timer_request set_win_timer;
struct kill_win_timer_request kill_win_timer;
struct create_serial_request create_serial;
struct get_serial_info_request get_serial_info;
struct set_serial_info_request set_serial_info;
struct create_async_request create_async;
};
#define SERVER_PROTOCOL_VERSION 44
#define SERVER_PROTOCOL_VERSION 45
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
......
......@@ -73,7 +73,7 @@ typedef struct tagUSER_DRIVER {
BOOL (*pDestroyWindow)(HWND);
BOOL (*pGetDC)(HWND,HDC,HRGN,DWORD);
BOOL (*pEnableWindow)(HWND,BOOL);
DWORD (*pMsgWaitForMultipleObjects)(DWORD,HANDLE*,BOOL,DWORD);
DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD);
INT (*pScrollWindowEx)(HWND,INT,INT,const RECT*,const RECT*,HRGN,LPRECT,UINT);
void (*pSetFocus)(HWND);
HWND (*pSetParent)(HWND,HWND);
......
......@@ -902,6 +902,10 @@ typedef struct
#define WM_APP 0x8000
/* MsgWaitForMultipleObjectsEx flags */
#define MWMO_WAITALL 0x0001
#define MWMO_ALERTABLE 0x0002
#define MWMO_INPUTAVAILABLE 0x0004
#define DLGC_WANTARROWS 0x0001
#define DLGC_WANTTAB 0x0002
......@@ -3026,6 +3030,16 @@ typedef struct
#define QS_ALLEVENTS (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY)
#define QS_ALLINPUT (QS_ALLEVENTS | QS_SENDMESSAGE)
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
#define QS_SMRESULT 0x8000
/* InSendMessageEx flags */
#define ISMEX_NOSEND 0x00000000
#define ISMEX_SEND 0x00000001
#define ISMEX_NOTIFY 0x00000002
#define ISMEX_CALLBACK 0x00000004
#define ISMEX_REPLIED 0x00000008
#define DDL_READWRITE 0x0000
#define DDL_READONLY 0x0001
#define DDL_HIDDEN 0x0002
......@@ -3184,10 +3198,11 @@ INT WINAPI MessageBoxExW(HWND,LPCWSTR,LPCWSTR,UINT,WORD);
HMONITOR WINAPI MonitorFromPoint(POINT,DWORD);
HMONITOR WINAPI MonitorFromRect(LPRECT,DWORD);
HMONITOR WINAPI MonitorFromWindow(HWND,DWORD);
DWORD WINAPI MsgWaitForMultipleObjects(DWORD,HANDLE*,BOOL,DWORD,DWORD);
BOOL WINAPI PaintDesktop(HDC);
BOOL WINAPI PostThreadMessageA(DWORD, UINT, WPARAM, LPARAM);
BOOL WINAPI PostThreadMessageW(DWORD, UINT, WPARAM, LPARAM);
DWORD WINAPI MsgWaitForMultipleObjects(DWORD,CONST HANDLE*,BOOL,DWORD,DWORD);
DWORD WINAPI MsgWaitForMultipleObjectsEx(DWORD,CONST HANDLE*,DWORD,DWORD,DWORD);
BOOL WINAPI PaintDesktop(HDC);
BOOL WINAPI PostThreadMessageA(DWORD,UINT,WPARAM,LPARAM);
BOOL WINAPI PostThreadMessageW(DWORD,UINT,WPARAM,LPARAM);
#define PostThreadMessage WINELIB_NAME_AW(PostThreadMessage)
BOOL WINAPI RegisterHotKey(HWND,INT,UINT,UINT);
HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE,LPVOID,DWORD);
......@@ -3229,7 +3244,6 @@ LONG WINAPI GetMessageTime(void);
DWORD WINAPI OemKeyScan(WORD);
BOOL WINAPI ReleaseCapture(void);
BOOL WINAPI SetKeyboardState(LPBYTE);
VOID WINAPI WaitMessage(void);
/* Declarations for functions that change between Win16 and Win32 */
......@@ -3589,12 +3603,13 @@ BOOL WINAPI GrayStringA(HDC,HBRUSH,GRAYSTRINGPROC,LPARAM,
BOOL WINAPI GrayStringW(HDC,HBRUSH,GRAYSTRINGPROC,LPARAM,
INT,INT,INT,INT,INT);
#define GrayString WINELIB_NAME_AW(GrayString)
BOOL WINAPI HideCaret(HWND);
BOOL WINAPI HiliteMenuItem(HWND,HMENU,UINT,UINT);
BOOL WINAPI InflateRect(LPRECT,INT,INT);
BOOL WINAPI InSendMessage(void);
BOOL WINAPI InsertMenuA(HMENU,UINT,UINT,UINT,LPCSTR);
BOOL WINAPI InsertMenuW(HMENU,UINT,UINT,UINT,LPCWSTR);
BOOL WINAPI HideCaret(HWND);
BOOL WINAPI HiliteMenuItem(HWND,HMENU,UINT,UINT);
BOOL WINAPI InflateRect(LPRECT,INT,INT);
BOOL WINAPI InSendMessage(void);
DWORD WINAPI InSendMessageEx(LPVOID);
BOOL WINAPI InsertMenuA(HMENU,UINT,UINT,UINT,LPCSTR);
BOOL WINAPI InsertMenuW(HMENU,UINT,UINT,UINT,LPCWSTR);
#define InsertMenu WINELIB_NAME_AW(InsertMenu)
BOOL WINAPI InsertMenuItemA(HMENU,UINT,BOOL,const MENUITEMINFOA*);
BOOL WINAPI InsertMenuItemW(HMENU,UINT,BOOL,const MENUITEMINFOW*);
......@@ -3837,6 +3852,7 @@ WORD WINAPI VkKeyScanW(WCHAR);
WORD WINAPI VkKeyScanExA(CHAR, HKL);
WORD WINAPI VkKeyScanExW(WCHAR, HKL);
#define VkKeyScanEx WINELIB_NAME_AW(VkKeyScanEx)
BOOL WINAPI WaitMessage(void);
HWND WINAPI WindowFromDC(HDC);
HWND WINAPI WindowFromPoint(POINT);
BOOL WINAPI WinHelpA(HWND,LPCSTR,UINT,DWORD);
......
......@@ -170,8 +170,18 @@ DECL_HANDLER(find_atom);
DECL_HANDLER(get_atom_name);
DECL_HANDLER(init_atom_table);
DECL_HANDLER(get_msg_queue);
DECL_HANDLER(wake_queue);
DECL_HANDLER(set_queue_bits);
DECL_HANDLER(set_queue_mask);
DECL_HANDLER(get_queue_status);
DECL_HANDLER(wait_input_idle);
DECL_HANDLER(send_message);
DECL_HANDLER(get_message);
DECL_HANDLER(reply_message);
DECL_HANDLER(get_message_reply);
DECL_HANDLER(in_send_message);
DECL_HANDLER(cleanup_window_queue);
DECL_HANDLER(set_win_timer);
DECL_HANDLER(kill_win_timer);
DECL_HANDLER(create_serial);
DECL_HANDLER(get_serial_info);
DECL_HANDLER(set_serial_info);
......@@ -284,8 +294,18 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_atom_name,
(req_handler)req_init_atom_table,
(req_handler)req_get_msg_queue,
(req_handler)req_wake_queue,
(req_handler)req_set_queue_bits,
(req_handler)req_set_queue_mask,
(req_handler)req_get_queue_status,
(req_handler)req_wait_input_idle,
(req_handler)req_send_message,
(req_handler)req_get_message,
(req_handler)req_reply_message,
(req_handler)req_get_message_reply,
(req_handler)req_in_send_message,
(req_handler)req_cleanup_window_queue,
(req_handler)req_set_win_timer,
(req_handler)req_kill_win_timer,
(req_handler)req_create_serial,
(req_handler)req_get_serial_info,
(req_handler)req_set_serial_info,
......
......@@ -169,6 +169,16 @@ static void cleanup_thread( struct thread *thread )
if (thread->reply_fd != -1) close( thread->reply_fd );
if (thread->wait_fd != -1) close( thread->wait_fd );
if (thread->request_fd) release_object( thread->request_fd );
if (thread->queue)
{
if (thread->process->queue == thread->queue)
{
release_object( thread->process->queue );
thread->process->queue = NULL;
}
release_object( thread->queue );
thread->queue = NULL;
}
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
{
if (thread->inflight[i].client != -1)
......@@ -191,14 +201,13 @@ static void destroy_thread( struct object *obj )
assert( obj->ops == &thread_ops );
assert( !thread->debug_ctx ); /* cannot still be debugging something */
release_object( thread->process );
if (thread->next) thread->next->prev = thread->prev;
if (thread->prev) thread->prev->next = thread->next;
else first_thread = thread->next;
while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
if (thread->info) release_object( thread->info );
if (thread->queue) release_object( thread->queue );
cleanup_thread( thread );
release_object( thread->process );
}
/* dump a thread on stdout for debugging purposes */
......@@ -223,6 +232,7 @@ struct thread *get_thread_from_id( void *id )
struct thread *t = first_thread;
while (t && (t != id)) t = t->next;
if (t) grab_object( t );
else set_error( STATUS_INVALID_PARAMETER );
return t;
}
......
......@@ -1414,10 +1414,41 @@ static void dump_get_msg_queue_reply( const struct get_msg_queue_request *req )
fprintf( stderr, " handle=%d", req->handle );
}
static void dump_wake_queue_request( const struct wake_queue_request *req )
static void dump_set_queue_bits_request( const struct set_queue_bits_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " bits=%08x", req->bits );
fprintf( stderr, " set=%08x,", req->set );
fprintf( stderr, " clear=%08x,", req->clear );
fprintf( stderr, " mask_cond=%08x", req->mask_cond );
}
static void dump_set_queue_bits_reply( const struct set_queue_bits_request *req )
{
fprintf( stderr, " changed_mask=%08x", req->changed_mask );
}
static void dump_set_queue_mask_request( const struct set_queue_mask_request *req )
{
fprintf( stderr, " wake_mask=%08x,", req->wake_mask );
fprintf( stderr, " changed_mask=%08x,", req->changed_mask );
fprintf( stderr, " skip_wait=%d", req->skip_wait );
}
static void dump_set_queue_mask_reply( const struct set_queue_mask_request *req )
{
fprintf( stderr, " wake_bits=%08x,", req->wake_bits );
fprintf( stderr, " changed_bits=%08x", req->changed_bits );
}
static void dump_get_queue_status_request( const struct get_queue_status_request *req )
{
fprintf( stderr, " clear=%d", req->clear );
}
static void dump_get_queue_status_reply( const struct get_queue_status_request *req )
{
fprintf( stderr, " wake_bits=%08x,", req->wake_bits );
fprintf( stderr, " changed_bits=%08x", req->changed_bits );
}
static void dump_wait_input_idle_request( const struct wait_input_idle_request *req )
......@@ -1431,6 +1462,84 @@ static void dump_wait_input_idle_reply( const struct wait_input_idle_request *re
fprintf( stderr, " event=%d", req->event );
}
static void dump_send_message_request( const struct send_message_request *req )
{
fprintf( stderr, " posted=%d,", req->posted );
fprintf( stderr, " id=%p,", req->id );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam );
fprintf( stderr, " lparam=%08x,", req->lparam );
fprintf( stderr, " info=%08x", req->info );
}
static void dump_get_message_request( const struct get_message_request *req )
{
fprintf( stderr, " remove=%d,", req->remove );
fprintf( stderr, " posted=%d,", req->posted );
fprintf( stderr, " get_win=%d,", req->get_win );
fprintf( stderr, " get_first=%08x,", req->get_first );
fprintf( stderr, " get_last=%08x", req->get_last );
}
static void dump_get_message_reply( const struct get_message_request *req )
{
fprintf( stderr, " sent=%d,", req->sent );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam );
fprintf( stderr, " lparam=%08x,", req->lparam );
fprintf( stderr, " info=%08x", req->info );
}
static void dump_reply_message_request( const struct reply_message_request *req )
{
fprintf( stderr, " result=%08x,", req->result );
fprintf( stderr, " remove=%d", req->remove );
}
static void dump_get_message_reply_request( const struct get_message_reply_request *req )
{
fprintf( stderr, " cancel=%d", req->cancel );
}
static void dump_get_message_reply_reply( const struct get_message_reply_request *req )
{
fprintf( stderr, " result=%08x", req->result );
}
static void dump_in_send_message_request( const struct in_send_message_request *req )
{
}
static void dump_in_send_message_reply( const struct in_send_message_request *req )
{
fprintf( stderr, " flags=%d", req->flags );
}
static void dump_cleanup_window_queue_request( const struct cleanup_window_queue_request *req )
{
fprintf( stderr, " win=%d", req->win );
}
static void dump_set_win_timer_request( const struct set_win_timer_request *req )
{
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " id=%08x,", req->id );
fprintf( stderr, " rate=%08x,", req->rate );
fprintf( stderr, " lparam=%08x", req->lparam );
}
static void dump_kill_win_timer_request( const struct kill_win_timer_request *req )
{
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " id=%08x", req->id );
}
static void dump_create_serial_request( const struct create_serial_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
......@@ -1589,8 +1698,18 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_atom_name_request,
(dump_func)dump_init_atom_table_request,
(dump_func)dump_get_msg_queue_request,
(dump_func)dump_wake_queue_request,
(dump_func)dump_set_queue_bits_request,
(dump_func)dump_set_queue_mask_request,
(dump_func)dump_get_queue_status_request,
(dump_func)dump_wait_input_idle_request,
(dump_func)dump_send_message_request,
(dump_func)dump_get_message_request,
(dump_func)dump_reply_message_request,
(dump_func)dump_get_message_reply_request,
(dump_func)dump_in_send_message_request,
(dump_func)dump_cleanup_window_queue_request,
(dump_func)dump_set_win_timer_request,
(dump_func)dump_kill_win_timer_request,
(dump_func)dump_create_serial_request,
(dump_func)dump_get_serial_info_request,
(dump_func)dump_set_serial_info_request,
......@@ -1700,8 +1819,18 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_atom_name_reply,
(dump_func)0,
(dump_func)dump_get_msg_queue_reply,
(dump_func)0,
(dump_func)dump_set_queue_bits_reply,
(dump_func)dump_set_queue_mask_reply,
(dump_func)dump_get_queue_status_reply,
(dump_func)dump_wait_input_idle_reply,
(dump_func)0,
(dump_func)dump_get_message_reply,
(dump_func)0,
(dump_func)dump_get_message_reply_reply,
(dump_func)dump_in_send_message_reply,
(dump_func)0,
(dump_func)0,
(dump_func)0,
(dump_func)dump_create_serial_reply,
(dump_func)dump_get_serial_info_reply,
(dump_func)0,
......@@ -1811,8 +1940,18 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_atom_name",
"init_atom_table",
"get_msg_queue",
"wake_queue",
"set_queue_bits",
"set_queue_mask",
"get_queue_status",
"wait_input_idle",
"send_message",
"get_message",
"reply_message",
"get_message_reply",
"in_send_message",
"cleanup_window_queue",
"set_win_timer",
"kill_win_timer",
"create_serial",
"get_serial_info",
"set_serial_info",
......
......@@ -131,6 +131,7 @@ BOOL CLIPBOARD_IsLocked()
* by another client. However the handler must have access to the
* clipboard in order to update data in response to this message.
*/
#if 0
MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
if ( queue
......@@ -141,6 +142,10 @@ BOOL CLIPBOARD_IsLocked()
bIsLocked = FALSE;
QUEUE_Unlock( queue );
#else
/* FIXME: queue check no longer possible */
bIsLocked = FALSE;
#endif
}
return bIsLocked;
......
......@@ -8,10 +8,12 @@
#include "wingdi.h"
#include "wine/winuser16.h"
#include "winuser.h"
#include "winerror.h"
#include "queue.h"
#include "winproc.h"
#include "services.h"
#include "message.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(timer);
......@@ -24,15 +26,13 @@ typedef struct tagTIMER
UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
UINT id;
UINT timeout;
HANDLE hService;
BOOL expired;
HWINDOWPROC proc;
} TIMER;
#define NB_TIMERS 34
#define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
#define SYS_TIMER_RATE 54925
#define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
static TIMER TimersArray[NB_TIMERS];
......@@ -46,18 +46,6 @@ static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT;
*/
static void TIMER_ClearTimer( TIMER * pTimer )
{
if ( pTimer->hService != INVALID_HANDLE_VALUE )
{
SERVICE_Delete( pTimer->hService );
pTimer->hService = INVALID_HANDLE_VALUE;
}
if ( pTimer->expired )
{
QUEUE_DecTimerCount( pTimer->hq );
pTimer->expired = FALSE;
}
pTimer->hwnd = 0;
pTimer->msg = 0;
pTimer->id = 0;
......@@ -81,7 +69,7 @@ void TIMER_RemoveWindowTimers( HWND hwnd )
for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
if ((pTimer->hwnd == hwnd) && pTimer->timeout)
TIMER_ClearTimer( pTimer );
LeaveCriticalSection( &csTimer );
}
......@@ -107,85 +95,6 @@ void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
/***********************************************************************
* TIMER_CheckTimer
*/
static void CALLBACK TIMER_CheckTimer( ULONG_PTR timer_ptr )
{
TIMER *pTimer = (TIMER *)timer_ptr;
HQUEUE16 wakeQueue = 0;
EnterCriticalSection( &csTimer );
/* Paranoid check to prevent a race condition ... */
if ( !pTimer->timeout )
{
LeaveCriticalSection( &csTimer );
return;
}
if ( !pTimer->expired )
{
TRACE("Timer expired: %04x, %04x, %04x, %08lx\n",
pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
pTimer->expired = TRUE;
wakeQueue = pTimer->hq;
}
LeaveCriticalSection( &csTimer );
/* Note: This has to be done outside the csTimer critical section,
otherwise we'll get deadlocks. */
if ( wakeQueue )
QUEUE_IncTimerCount( wakeQueue );
}
/***********************************************************************
* TIMER_GetTimerMsg
*
* Build a message for an expired timer.
*/
BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
HQUEUE16 hQueue, BOOL remove )
{
TIMER *pTimer;
int i;
EnterCriticalSection( &csTimer );
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
if ( pTimer->timeout != 0 && pTimer->expired
&& (hwnd? (pTimer->hwnd == hwnd) : (pTimer->hq == hQueue)) )
break;
if ( i == NB_TIMERS )
{
LeaveCriticalSection( &csTimer );
return FALSE; /* No timer */
}
TRACE("Timer got message: %04x, %04x, %04x, %08lx\n",
pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
if (remove)
pTimer->expired = FALSE;
/* Build the message */
msg->hwnd = pTimer->hwnd;
msg->message = pTimer->msg;
msg->wParam = pTimer->id;
msg->lParam = (LONG)pTimer->proc;
msg->time = GetTickCount();
LeaveCriticalSection( &csTimer );
return TRUE;
}
/***********************************************************************
* TIMER_SetTimer
*/
static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
......@@ -193,12 +102,20 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
{
int i;
TIMER * pTimer;
HWINDOWPROC winproc = 0;
if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId())
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if (!timeout)
{ /* timeout==0 is a legal argument UB 990821*/
WARN("Timeout== 0 not implemented, using timeout=1\n");
timeout=1;
}
EnterCriticalSection( &csTimer );
/* Check if there's already a timer with the same hwnd and id */
......@@ -228,21 +145,28 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
if (!hwnd) id = i + 1;
if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
SERVER_START_REQ( set_win_timer )
{
req->win = hwnd;
req->msg = sys ? WM_SYSTIMER : WM_TIMER;
req->id = id;
req->rate = max( timeout, SYS_TIMER_RATE );
req->lparam = (unsigned int)winproc;
SERVER_CALL();
}
SERVER_END_REQ;
/* Add the timer */
pTimer->hwnd = hwnd;
pTimer->hq = (hwnd) ? GetThreadQueue16( GetWindowThreadProcessId( hwnd, NULL ) )
: GetFastQueue16( );
pTimer->hq = GetFastQueue16();
pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
pTimer->id = id;
pTimer->timeout = timeout;
pTimer->proc = (HWINDOWPROC)0;
if (proc) WINPROC_SetProc( &pTimer->proc, proc, type, WIN_PROC_TIMER );
pTimer->proc = winproc;
pTimer->expired = FALSE;
pTimer->hService = SERVICE_AddTimer( max( timeout, (SYS_TIMER_RATE+500)/1000 ),
TIMER_CheckTimer, (ULONG_PTR)pTimer );
TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
(DWORD)pTimer->proc );
......@@ -262,6 +186,15 @@ static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
int i;
TIMER * pTimer;
SERVER_START_REQ( kill_win_timer )
{
req->win = hwnd;
req->msg = sys ? WM_SYSTIMER : WM_TIMER;
req->id = id;
SERVER_CALL();
}
SERVER_END_REQ;
EnterCriticalSection( &csTimer );
/* Find the timer */
......
......@@ -458,29 +458,8 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
/* toss stale messages from the queue */
if( wndPtr->hmemTaskQ )
{
BOOL bPostQuit = FALSE;
WPARAM wQuitParam = 0;
MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
QMSG *qmsg;
while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
{
if( qmsg->msg.message == WM_QUIT )
{
bPostQuit = TRUE;
wQuitParam = qmsg->msg.wParam;
}
QUEUE_RemoveMsg(msgQ, qmsg);
}
QUEUE_Unlock(msgQ);
/* repost WM_QUIT to make sure this app exits its message loop */
if( bPostQuit ) PostQuitMessage(wQuitParam);
wndPtr->hmemTaskQ = 0;
}
QUEUE_CleanupWindow( hwnd );
wndPtr->hmemTaskQ = 0;
if (!(wndPtr->dwStyle & WS_CHILD))
if (wndPtr->wIDmenu)
......
......@@ -167,17 +167,18 @@ void X11DRV_Synchronize( void )
/***********************************************************************
* MsgWaitForMultipleObjects (X11DRV.@)
* MsgWaitForMultipleObjectsEx (X11DRV.@)
*/
DWORD X11DRV_MsgWaitForMultipleObjects( DWORD count, HANDLE *handles,
BOOL wait_all, DWORD timeout )
DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
DWORD timeout, DWORD mask, DWORD flags )
{
HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
DWORD i, ret;
struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
if (!data || data->process_event_count)
return WaitForMultipleObjects( count, handles, wait_all, timeout );
return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
timeout, flags & MWMO_ALERTABLE );
for (i = 0; i < count; i++) new_handles[i] = handles[i];
new_handles[count] = data->display_fd;
......@@ -187,7 +188,8 @@ DWORD X11DRV_MsgWaitForMultipleObjects( DWORD count, HANDLE *handles,
XFlush( gdi_display );
XFlush( data->display );
wine_tsx11_unlock();
ret = WaitForMultipleObjects( count+1, new_handles, wait_all, timeout );
ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
timeout, flags & MWMO_ALERTABLE );
if (ret == count) process_events( data->display );
data->process_event_count--;
return ret;
......
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