Moved the major part of message queue and window timer handling into
the server. Implemented MsgWaitForMultipleObjectsEx.
This commit is contained in:
parent
cd8d181a0b
commit
51ab43bd13
|
@ -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 );
|
||||
|
||||
|
|
150
include/server.h
150
include/server.h
|
@ -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);
|
||||
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);
|
||||
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 */
|
||||
|
||||
|
@ -3593,6 +3607,7 @@ 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)
|
||||
|
@ -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);
|
||||
|
|
699
server/queue.c
699
server/queue.c
|
@ -8,16 +8,72 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#include "handle.h"
|
||||
#include "thread.h"
|
||||
#include "process.h"
|
||||
#include "request.h"
|
||||
|
||||
struct message_result
|
||||
{
|
||||
struct message_result *send_next; /* next in sender list */
|
||||
struct message_result *recv_next; /* next in receiver list */
|
||||
struct msg_queue *sender; /* sender queue */
|
||||
struct msg_queue *receiver; /* receiver queue */
|
||||
int replied; /* has it been replied to? */
|
||||
unsigned int result; /* reply result */
|
||||
unsigned int error; /* error code to pass back to sender */
|
||||
};
|
||||
|
||||
struct message
|
||||
{
|
||||
struct message *next; /* next message in list */
|
||||
struct message *prev; /* prev message in list */
|
||||
int type; /* message type (FIXME) */
|
||||
handle_t win; /* window handle */
|
||||
unsigned int msg; /* message code */
|
||||
unsigned int wparam; /* parameters */
|
||||
unsigned int lparam; /* parameters */
|
||||
unsigned int info; /* extra info */
|
||||
struct message_result *result; /* result in sender queue */
|
||||
};
|
||||
|
||||
struct message_list
|
||||
{
|
||||
struct message *first; /* head of list */
|
||||
struct message *last; /* tail of list */
|
||||
};
|
||||
|
||||
struct timer
|
||||
{
|
||||
struct timer *next; /* next timer in list */
|
||||
struct timer *prev; /* prev timer in list */
|
||||
struct timeval when; /* next expiration */
|
||||
unsigned int rate; /* timer rate in ms */
|
||||
handle_t win; /* window handle */
|
||||
unsigned int msg; /* message to post */
|
||||
unsigned int id; /* timer id */
|
||||
unsigned int lparam; /* lparam for message */
|
||||
};
|
||||
|
||||
struct msg_queue
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
struct thread *thread; /* thread owning this queue */
|
||||
int signaled; /* queue has been signaled */
|
||||
unsigned int wake_bits; /* wakeup bits */
|
||||
unsigned int wake_mask; /* wakeup mask */
|
||||
unsigned int changed_bits; /* changed wakeup bits */
|
||||
unsigned int changed_mask; /* changed wakeup mask */
|
||||
struct message_list send_list; /* list of sent messages */
|
||||
struct message_list post_list; /* list of posted messages */
|
||||
struct message_result *send_result; /* stack of sent messages waiting for result */
|
||||
struct message_result *recv_result; /* stack of received messages waiting for result */
|
||||
struct timer *first_timer; /* head of timer list */
|
||||
struct timer *last_timer; /* tail of timer list */
|
||||
struct timer *next_timer; /* next timer to expire */
|
||||
struct timeout_user *timeout; /* timeout for next timer to expire */
|
||||
};
|
||||
|
||||
static void msg_queue_dump( struct object *obj, int verbose );
|
||||
|
@ -25,6 +81,8 @@ static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *ent
|
|||
static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
static int msg_queue_signaled( struct object *obj, struct thread *thread );
|
||||
static int msg_queue_satisfied( struct object *obj, struct thread *thread );
|
||||
static void msg_queue_destroy( struct object *obj );
|
||||
static void timer_callback( void *private );
|
||||
|
||||
static const struct object_ops msg_queue_ops =
|
||||
{
|
||||
|
@ -39,7 +97,7 @@ static const struct object_ops msg_queue_ops =
|
|||
no_get_fd, /* get_fd */
|
||||
no_flush, /* flush */
|
||||
no_get_file_info, /* get_file_info */
|
||||
no_destroy /* destroy */
|
||||
msg_queue_destroy /* destroy */
|
||||
};
|
||||
|
||||
|
||||
|
@ -49,8 +107,20 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
|
|||
|
||||
if ((queue = alloc_object( &msg_queue_ops, -1 )))
|
||||
{
|
||||
queue->signaled = 0;
|
||||
queue->thread = thread;
|
||||
queue->wake_bits = 0;
|
||||
queue->wake_mask = 0;
|
||||
queue->changed_bits = 0;
|
||||
queue->changed_mask = 0;
|
||||
queue->send_list.first = NULL;
|
||||
queue->send_list.last = NULL;
|
||||
queue->post_list.first = NULL;
|
||||
queue->post_list.last = NULL;
|
||||
queue->send_result = NULL;
|
||||
queue->recv_result = NULL;
|
||||
queue->first_timer = NULL;
|
||||
queue->last_timer = NULL;
|
||||
queue->next_timer = NULL;
|
||||
queue->timeout = NULL;
|
||||
thread->queue = queue;
|
||||
if (!thread->process->queue)
|
||||
thread->process->queue = (struct msg_queue *)grab_object( queue );
|
||||
|
@ -58,13 +128,211 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
|
|||
return queue;
|
||||
}
|
||||
|
||||
/* check the queue status */
|
||||
inline static int is_signaled( struct msg_queue *queue )
|
||||
{
|
||||
return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
|
||||
}
|
||||
|
||||
/* set/clear some queue bits */
|
||||
inline static void change_queue_bits( struct msg_queue *queue, unsigned int set, unsigned int clear )
|
||||
{
|
||||
queue->wake_bits = (queue->wake_bits | set) & ~clear;
|
||||
queue->changed_bits = (queue->changed_bits | set) & ~clear;
|
||||
if (is_signaled( queue )) wake_up( &queue->obj, 0 );
|
||||
}
|
||||
|
||||
/* get the current thread queue, creating it if needed */
|
||||
inline struct msg_queue *get_current_queue(void)
|
||||
{
|
||||
struct msg_queue *queue = current->queue;
|
||||
if (!queue) queue = create_msg_queue( current );
|
||||
return queue;
|
||||
}
|
||||
|
||||
/* append a message to the end of a list */
|
||||
inline static void append_message( struct message_list *list, struct message *msg )
|
||||
{
|
||||
msg->next = NULL;
|
||||
if ((msg->prev = list->last)) msg->prev->next = msg;
|
||||
else list->first = msg;
|
||||
list->last = msg;
|
||||
}
|
||||
|
||||
/* unlink a message from a list it */
|
||||
inline static void unlink_message( struct message_list *list, struct message *msg )
|
||||
{
|
||||
if (msg->next) msg->next->prev = msg->prev;
|
||||
else list->last = msg->prev;
|
||||
if (msg->prev) msg->prev->next = msg->next;
|
||||
else list->first = msg->next;
|
||||
}
|
||||
|
||||
/* free a message when deleting a queue or window */
|
||||
static void free_message( struct message *msg )
|
||||
{
|
||||
struct message_result *result = msg->result;
|
||||
if (result)
|
||||
{
|
||||
if (result->sender)
|
||||
{
|
||||
result->result = 0;
|
||||
result->error = STATUS_ACCESS_DENIED; /* FIXME */
|
||||
result->replied = 1;
|
||||
result->receiver = NULL;
|
||||
/* wake sender queue if waiting on this result */
|
||||
if (result->sender->send_result == result)
|
||||
change_queue_bits( result->sender, QS_SMRESULT, 0 );
|
||||
}
|
||||
else free( result );
|
||||
}
|
||||
free( msg );
|
||||
}
|
||||
|
||||
/* remove (and free) a message from the sent messages list */
|
||||
static void remove_sent_message( struct msg_queue *queue, struct message *msg )
|
||||
{
|
||||
unlink_message( &queue->send_list, msg );
|
||||
free_message( msg );
|
||||
if (!queue->send_list.first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
|
||||
}
|
||||
|
||||
/* remove (and free) a message from the posted messages list */
|
||||
static void remove_posted_message( struct msg_queue *queue, struct message *msg )
|
||||
{
|
||||
unlink_message( &queue->post_list, msg );
|
||||
free_message( msg );
|
||||
if (!queue->post_list.first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
|
||||
}
|
||||
|
||||
/* send a message from the sender queue to the receiver queue */
|
||||
static int send_message( struct msg_queue *send_queue, struct msg_queue *recv_queue,
|
||||
struct message *msg )
|
||||
{
|
||||
struct message_result *result = mem_alloc( sizeof(*result) );
|
||||
if (!result) return 0;
|
||||
|
||||
/* put the result on the sender result stack */
|
||||
result->sender = send_queue;
|
||||
result->receiver = recv_queue;
|
||||
result->replied = 0;
|
||||
result->send_next = send_queue->send_result;
|
||||
send_queue->send_result = result;
|
||||
|
||||
/* and put the message on the receiver queue */
|
||||
msg->result = result;
|
||||
append_message( &recv_queue->send_list, msg );
|
||||
change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* receive a message, removing it from the sent queue */
|
||||
static void receive_message( struct msg_queue *queue, struct message *msg )
|
||||
{
|
||||
struct message_result *result = msg->result;
|
||||
|
||||
unlink_message( &queue->send_list, msg );
|
||||
/* put the result on the receiver result stack */
|
||||
result->recv_next = queue->recv_result;
|
||||
queue->recv_result = result;
|
||||
free( msg );
|
||||
if (!queue->send_list.first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
|
||||
}
|
||||
|
||||
/* set the result of the current received message */
|
||||
static void reply_message( struct msg_queue *queue, unsigned int result,
|
||||
unsigned int error, int remove )
|
||||
{
|
||||
struct message_result *res = queue->recv_result;
|
||||
if (!res) set_error( STATUS_ACCESS_DENIED ); /* FIXME */
|
||||
|
||||
if (remove)
|
||||
{
|
||||
queue->recv_result = res->recv_next;
|
||||
res->receiver = NULL;
|
||||
if (!res->sender) /* no one waiting for it */
|
||||
{
|
||||
free( res );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!res->replied)
|
||||
{
|
||||
res->result = result;
|
||||
res->error = error;
|
||||
res->replied = 1;
|
||||
/* wake sender queue if waiting on this result */
|
||||
if (res->sender && res->sender->send_result == res)
|
||||
change_queue_bits( res->sender, QS_SMRESULT, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* retrieve the reply of the current message being sent */
|
||||
static unsigned int get_message_reply( struct msg_queue *queue, int cancel )
|
||||
{
|
||||
struct message_result *res = queue->send_result;
|
||||
unsigned int ret = 0;
|
||||
|
||||
set_error( STATUS_PENDING );
|
||||
|
||||
if (res && (res->replied || cancel))
|
||||
{
|
||||
if (res->replied)
|
||||
{
|
||||
ret = res->result;
|
||||
set_error( res->error );
|
||||
}
|
||||
queue->send_result = res->send_next;
|
||||
res->sender = NULL;
|
||||
if (!res->receiver) free( res );
|
||||
if (!queue->send_result || !queue->send_result->replied)
|
||||
change_queue_bits( queue, 0, QS_SMRESULT );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* empty a message list and free all the messages */
|
||||
static void empty_msg_list( struct message_list *list )
|
||||
{
|
||||
struct message *msg = list->first;
|
||||
while (msg)
|
||||
{
|
||||
struct message *next = msg->next;
|
||||
free_message( msg );
|
||||
msg = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup all pending results when deleting a queue */
|
||||
static void cleanup_results( struct msg_queue *queue )
|
||||
{
|
||||
struct message_result *result, *next;
|
||||
|
||||
result = queue->send_result;
|
||||
while (result)
|
||||
{
|
||||
next = result->send_next;
|
||||
result->sender = NULL;
|
||||
if (!result->receiver) free( result );
|
||||
result = next;
|
||||
}
|
||||
|
||||
while (queue->recv_result) reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1 );
|
||||
}
|
||||
|
||||
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
struct process *process = entry->thread->process;
|
||||
|
||||
/* a thread can only wait on its own queue */
|
||||
if (entry->thread->queue != queue)
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return 0;
|
||||
}
|
||||
/* if waiting on the main process queue, set the idle event */
|
||||
if (entry->thread == queue->thread && process->queue == queue)
|
||||
if (process->queue == queue)
|
||||
{
|
||||
if (process->idle_event) set_event( process->idle_event );
|
||||
}
|
||||
|
@ -79,8 +347,10 @@ static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *
|
|||
|
||||
remove_queue( obj, entry );
|
||||
|
||||
assert( entry->thread->queue == queue );
|
||||
|
||||
/* if waiting on the main process queue, reset the idle event */
|
||||
if (entry->thread == queue->thread && process->queue == queue)
|
||||
if (process->queue == queue)
|
||||
{
|
||||
if (process->idle_event) reset_event( process->idle_event );
|
||||
}
|
||||
|
@ -89,41 +359,438 @@ static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *
|
|||
static void msg_queue_dump( struct object *obj, int verbose )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
fprintf( stderr, "Msg queue signaled=%d owner=%p\n", queue->signaled, queue->thread );
|
||||
fprintf( stderr, "Msg queue bits=%x mask=%x\n",
|
||||
queue->wake_bits, queue->wake_mask );
|
||||
}
|
||||
|
||||
static int msg_queue_signaled( struct object *obj, struct thread *thread )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
return queue->signaled;
|
||||
return is_signaled( queue );
|
||||
}
|
||||
|
||||
static int msg_queue_satisfied( struct object *obj, struct thread *thread )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
queue->signaled = 0;
|
||||
queue->wake_mask = 0;
|
||||
queue->changed_mask = 0;
|
||||
return 0; /* Not abandoned */
|
||||
}
|
||||
|
||||
static void msg_queue_destroy( struct object *obj )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
struct timer *timer = queue->first_timer;
|
||||
|
||||
cleanup_results( queue );
|
||||
empty_msg_list( &queue->send_list );
|
||||
empty_msg_list( &queue->post_list );
|
||||
|
||||
while (timer)
|
||||
{
|
||||
struct timer *next = timer->next;
|
||||
free( timer );
|
||||
timer = next;
|
||||
}
|
||||
if (queue->timeout) remove_timeout_user( queue->timeout );
|
||||
}
|
||||
|
||||
/* set the next timer to expire */
|
||||
static void set_next_timer( struct msg_queue *queue, struct timer *timer )
|
||||
{
|
||||
if (queue->timeout)
|
||||
{
|
||||
remove_timeout_user( queue->timeout );
|
||||
queue->timeout = NULL;
|
||||
}
|
||||
if ((queue->next_timer = timer))
|
||||
queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
|
||||
|
||||
/* set/clear QS_TIMER bit */
|
||||
if (queue->next_timer == queue->first_timer)
|
||||
change_queue_bits( queue, 0, QS_TIMER );
|
||||
else
|
||||
change_queue_bits( queue, QS_TIMER, 0 );
|
||||
}
|
||||
|
||||
/* callback for the next timer expiration */
|
||||
static void timer_callback( void *private )
|
||||
{
|
||||
struct msg_queue *queue = private;
|
||||
|
||||
queue->timeout = NULL;
|
||||
/* move on to the next timer */
|
||||
set_next_timer( queue, queue->next_timer->next );
|
||||
}
|
||||
|
||||
/* link a timer at its rightful place in the queue list */
|
||||
static void link_timer( struct msg_queue *queue, struct timer *timer )
|
||||
{
|
||||
struct timer *pos = queue->next_timer;
|
||||
|
||||
while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
|
||||
|
||||
if (pos) /* insert before pos */
|
||||
{
|
||||
if ((timer->prev = pos->prev)) timer->prev->next = timer;
|
||||
else queue->first_timer = timer;
|
||||
timer->next = pos;
|
||||
pos->prev = timer;
|
||||
}
|
||||
else /* insert at end */
|
||||
{
|
||||
timer->next = NULL;
|
||||
timer->prev = queue->last_timer;
|
||||
if (queue->last_timer) queue->last_timer->next = timer;
|
||||
else queue->first_timer = timer;
|
||||
queue->last_timer = timer;
|
||||
}
|
||||
/* check if we replaced the next timer */
|
||||
if (pos == queue->next_timer) set_next_timer( queue, timer );
|
||||
}
|
||||
|
||||
/* remove a timer from the queue timer list */
|
||||
static void unlink_timer( struct msg_queue *queue, struct timer *timer )
|
||||
{
|
||||
if (timer->next) timer->next->prev = timer->prev;
|
||||
else queue->last_timer = timer->prev;
|
||||
if (timer->prev) timer->prev->next = timer->next;
|
||||
else queue->first_timer = timer->next;
|
||||
/* check if we removed the next timer */
|
||||
if (queue->next_timer == timer) set_next_timer( queue, timer->next );
|
||||
}
|
||||
|
||||
/* restart an expired timer */
|
||||
static void restart_timer( struct msg_queue *queue, struct timer *timer )
|
||||
{
|
||||
struct timeval now;
|
||||
unlink_timer( queue, timer );
|
||||
gettimeofday( &now, 0 );
|
||||
while (!time_before( &now, &timer->when )) add_timeout( &timer->when, timer->rate );
|
||||
link_timer( queue, timer );
|
||||
}
|
||||
|
||||
/* find an expired timer matching the filtering parameters */
|
||||
static struct timer *find_expired_timer( struct msg_queue *queue, handle_t win,
|
||||
unsigned int get_first, unsigned int get_last,
|
||||
int remove )
|
||||
{
|
||||
struct timer *timer;
|
||||
for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
|
||||
{
|
||||
if (win && timer->win != win) continue;
|
||||
if (timer->msg >= get_first && timer->msg <= get_last)
|
||||
{
|
||||
if (remove) restart_timer( queue, timer );
|
||||
return timer;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* kill a timer */
|
||||
static int kill_timer( struct msg_queue *queue, handle_t win, unsigned int msg, unsigned int id )
|
||||
{
|
||||
struct timer *timer;
|
||||
|
||||
for (timer = queue->first_timer; timer; timer = timer->next)
|
||||
{
|
||||
if (timer->win != win || timer->msg != msg || timer->id != id) continue;
|
||||
unlink_timer( queue, timer );
|
||||
free( timer );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add a timer */
|
||||
static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
|
||||
{
|
||||
struct timer *timer = mem_alloc( sizeof(*timer) );
|
||||
if (timer)
|
||||
{
|
||||
timer->rate = rate;
|
||||
gettimeofday( &timer->when, 0 );
|
||||
add_timeout( &timer->when, rate );
|
||||
link_timer( queue, timer );
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
/* remove all messages and timers belonging to a certain window */
|
||||
static void cleanup_window( struct msg_queue *queue, handle_t win )
|
||||
{
|
||||
struct timer *timer;
|
||||
struct message *msg;
|
||||
|
||||
/* remove timers */
|
||||
timer = queue->first_timer;
|
||||
while (timer)
|
||||
{
|
||||
struct timer *next = timer->next;
|
||||
if (timer->win == win)
|
||||
{
|
||||
unlink_timer( queue, timer );
|
||||
free( timer );
|
||||
}
|
||||
timer = next;
|
||||
}
|
||||
|
||||
/* remove sent messages */
|
||||
msg = queue->send_list.first;
|
||||
while (msg)
|
||||
{
|
||||
struct message *next = msg->next;
|
||||
if (msg->win == win) remove_sent_message( queue, msg );
|
||||
msg = next;
|
||||
}
|
||||
|
||||
/* remove posted messages */
|
||||
msg = queue->post_list.first;
|
||||
while (msg)
|
||||
{
|
||||
struct message *next = msg->next;
|
||||
if (msg->win == win) remove_posted_message( queue, msg );
|
||||
msg = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the message queue of the current thread */
|
||||
DECL_HANDLER(get_msg_queue)
|
||||
{
|
||||
struct msg_queue *queue = current->queue;
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
req->handle = 0;
|
||||
if (!queue) queue = create_msg_queue( current );
|
||||
if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
|
||||
}
|
||||
|
||||
/* wake up a message queue */
|
||||
DECL_HANDLER(wake_queue)
|
||||
|
||||
/* set the message queue wake bits */
|
||||
DECL_HANDLER(set_queue_bits)
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)get_handle_obj( current->process, req->handle,
|
||||
0, &msg_queue_ops );
|
||||
if (queue)
|
||||
{
|
||||
queue->signaled = 1;
|
||||
wake_up( &queue->obj, 0 );
|
||||
req->changed_mask = queue->changed_mask;
|
||||
if (!req->mask_cond || (queue->changed_mask & req->mask_cond))
|
||||
change_queue_bits( queue, req->set, req->clear );
|
||||
release_object( queue );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* set the current message queue wakeup mask */
|
||||
DECL_HANDLER(set_queue_mask)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
if (queue)
|
||||
{
|
||||
queue->wake_mask = req->wake_mask;
|
||||
queue->changed_mask = req->changed_mask;
|
||||
req->wake_bits = queue->wake_bits;
|
||||
req->changed_bits = queue->changed_bits;
|
||||
if (is_signaled( queue ))
|
||||
{
|
||||
/* if skip wait is set, do what would have been done in the subsequent wait */
|
||||
if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
|
||||
else wake_up( &queue->obj, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get the current message queue status */
|
||||
DECL_HANDLER(get_queue_status)
|
||||
{
|
||||
struct msg_queue *queue = current->queue;
|
||||
if (queue)
|
||||
{
|
||||
req->wake_bits = queue->wake_bits;
|
||||
req->changed_bits = queue->changed_bits;
|
||||
if (req->clear) queue->changed_bits = 0;
|
||||
}
|
||||
else req->wake_bits = req->changed_bits = 0;
|
||||
}
|
||||
|
||||
|
||||
/* send a message to a thread queue */
|
||||
DECL_HANDLER(send_message)
|
||||
{
|
||||
struct message *msg;
|
||||
struct msg_queue *send_queue = get_current_queue();
|
||||
struct msg_queue *recv_queue;
|
||||
struct thread *thread = get_thread_from_id( req->id );
|
||||
|
||||
if (!thread) return;
|
||||
|
||||
if (!(recv_queue = thread->queue))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
release_object( thread );
|
||||
return;
|
||||
}
|
||||
|
||||
if ((msg = mem_alloc( sizeof(*msg) )))
|
||||
{
|
||||
msg->type = req->type;
|
||||
msg->win = req->win;
|
||||
msg->msg = req->msg;
|
||||
msg->wparam = req->wparam;
|
||||
msg->lparam = req->lparam;
|
||||
msg->info = req->info;
|
||||
msg->result = NULL;
|
||||
if (!req->posted) send_message( send_queue, recv_queue, msg );
|
||||
else
|
||||
{
|
||||
append_message( &recv_queue->post_list, msg );
|
||||
change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 );
|
||||
}
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
|
||||
/* get a message from the current queue */
|
||||
DECL_HANDLER(get_message)
|
||||
{
|
||||
struct timer *timer;
|
||||
struct message *msg;
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
if (!queue) return;
|
||||
|
||||
/* first check for sent messages */
|
||||
if ((msg = queue->send_list.first))
|
||||
{
|
||||
req->sent = 1;
|
||||
req->type = msg->type;
|
||||
req->win = msg->win;
|
||||
req->msg = msg->msg;
|
||||
req->wparam = msg->wparam;
|
||||
req->lparam = msg->lparam;
|
||||
req->info = msg->info;
|
||||
receive_message( queue, msg );
|
||||
return;
|
||||
}
|
||||
if (!req->posted) goto done; /* nothing else to check */
|
||||
|
||||
/* then try a posted message */
|
||||
req->sent = 0;
|
||||
for (msg = queue->post_list.first; msg; msg = msg->next)
|
||||
{
|
||||
/* check against the filters */
|
||||
if (req->get_win && msg->win != req->get_win) continue;
|
||||
if (req->msg >= req->get_first && req->msg <= req->get_last)
|
||||
{
|
||||
/* found one */
|
||||
req->type = msg->type;
|
||||
req->win = msg->win;
|
||||
req->msg = msg->msg;
|
||||
req->wparam = msg->wparam;
|
||||
req->lparam = msg->lparam;
|
||||
req->info = msg->info;
|
||||
if (req->remove) remove_posted_message( queue, msg );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* now check for WM_PAINT */
|
||||
if (queue->wake_bits & QS_PAINT)
|
||||
{
|
||||
req->type = 0;
|
||||
req->win = 0;
|
||||
req->msg = WM_PAINT;
|
||||
req->wparam = 0;
|
||||
req->lparam = 0;
|
||||
req->info = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* now check for timer */
|
||||
if ((timer = find_expired_timer( queue, req->get_win, req->get_first,
|
||||
req->get_last, req->remove )))
|
||||
{
|
||||
req->type = 0;
|
||||
req->win = timer->win;
|
||||
req->msg = timer->msg;
|
||||
req->wparam = timer->id;
|
||||
req->lparam = timer->lparam;
|
||||
req->info = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
done:
|
||||
set_error( STATUS_PENDING ); /* FIXME */
|
||||
}
|
||||
|
||||
|
||||
/* reply to a sent message */
|
||||
DECL_HANDLER(reply_message)
|
||||
{
|
||||
if (current->queue) reply_message( current->queue, req->result, 0, req->remove );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
|
||||
|
||||
/* retrieve the reply for the last message sent */
|
||||
DECL_HANDLER(get_message_reply)
|
||||
{
|
||||
if (current->queue) req->result = get_message_reply( current->queue, req->cancel );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
|
||||
|
||||
/* check if we are processing a sent message */
|
||||
DECL_HANDLER(in_send_message)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (current->queue)
|
||||
{
|
||||
struct message_result *result = current->queue->recv_result;
|
||||
if (result)
|
||||
{
|
||||
flags |= ISMEX_SEND; /* FIXME */
|
||||
if (result->replied || !result->sender) flags |= ISMEX_REPLIED;
|
||||
}
|
||||
}
|
||||
req->flags = flags;
|
||||
}
|
||||
|
||||
|
||||
/* cleanup a queue when a window is deleted */
|
||||
DECL_HANDLER(cleanup_window_queue)
|
||||
{
|
||||
if (current->queue) cleanup_window( current->queue, req->win );
|
||||
}
|
||||
|
||||
|
||||
/* set a window timer */
|
||||
DECL_HANDLER(set_win_timer)
|
||||
{
|
||||
struct timer *timer;
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
if (!queue) return;
|
||||
|
||||
/* remove it if it existed already */
|
||||
if (req->win) kill_timer( queue, req->win, req->msg, req->id );
|
||||
|
||||
if ((timer = set_timer( queue, req->rate )))
|
||||
{
|
||||
timer->win = req->win;
|
||||
timer->msg = req->msg;
|
||||
timer->id = req->id;
|
||||
timer->lparam = req->lparam;
|
||||
}
|
||||
}
|
||||
|
||||
/* kill a window timer */
|
||||
DECL_HANDLER(kill_win_timer)
|
||||
{
|
||||
struct msg_queue *queue = current->queue;
|
||||
|
||||
if (!queue || !kill_timer( queue, req->win, req->msg, req->id ))
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
149
server/trace.c
149
server/trace.c
|
@ -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;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "wine/winbase16.h"
|
||||
#include "message.h"
|
||||
#include "winerror.h"
|
||||
#include "server.h"
|
||||
#include "win.h"
|
||||
#include "heap.h"
|
||||
#include "hook.h"
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "winproc.h"
|
||||
#include "user.h"
|
||||
#include "thread.h"
|
||||
#include "task.h"
|
||||
#include "options.h"
|
||||
#include "controls.h"
|
||||
#include "struct32.h"
|
||||
|
@ -115,9 +117,9 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last,
|
|||
POINT16 pt;
|
||||
HANDLE16 hQ = GetFastQueue16();
|
||||
MESSAGEQUEUE *queue = QUEUE_Lock(hQ);
|
||||
BOOL mouseClick = ((message == WM_LBUTTONDOWN) ||
|
||||
int mouseClick = ((message == WM_LBUTTONDOWN) ||
|
||||
(message == WM_RBUTTONDOWN) ||
|
||||
(message == WM_MBUTTONDOWN))?1:0;
|
||||
(message == WM_MBUTTONDOWN));
|
||||
DWORD retvalue;
|
||||
|
||||
/* Find the window to dispatch this mouse message to */
|
||||
|
@ -155,7 +157,7 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last,
|
|||
/* Wake up the other task */
|
||||
QUEUE_Unlock( queue );
|
||||
queue = QUEUE_Lock( pWnd->hmemTaskQ );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE, 0 );
|
||||
|
||||
QUEUE_Unlock( queue );
|
||||
retvalue = SYSQ_MSG_ABANDON;
|
||||
|
@ -387,7 +389,7 @@ static DWORD MSG_TranslateKbdMsg( HWND hTopWnd, DWORD first, DWORD last,
|
|||
|
||||
/* Wake up the other task */
|
||||
queue = QUEUE_Lock( pWnd->hmemTaskQ );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_KEY, 0 );
|
||||
QUEUE_Unlock( queue );
|
||||
WIN_ReleaseWndPtr(pWnd);
|
||||
return SYSQ_MSG_ABANDON;
|
||||
|
@ -771,127 +773,59 @@ UINT WINAPI GetDoubleClickTime(void)
|
|||
static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
|
||||
HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam,
|
||||
DWORD timeout, WORD flags,
|
||||
DWORD timeout, WORD type,
|
||||
LRESULT *pRes)
|
||||
{
|
||||
MESSAGEQUEUE *queue, *destQ;
|
||||
SMSG *smsg;
|
||||
LRESULT retVal = 1;
|
||||
MESSAGEQUEUE *destQ;
|
||||
BOOL ret;
|
||||
int iWndsLocks;
|
||||
LRESULT result = 0;
|
||||
|
||||
if (pRes) *pRes = 0;
|
||||
TRACE( "hwnd %x msg %x (%s) wp %x lp %lx\n", hwnd, msg, SPY_GetMsgName(msg), wParam, lParam );
|
||||
|
||||
if (IsTaskLocked16() || !IsWindow(hwnd))
|
||||
return 0;
|
||||
if (!(destQ = QUEUE_Lock( hDestQueue ))) return 0;
|
||||
|
||||
/* create a SMSG structure to hold SendMessage() parameters */
|
||||
if (! (smsg = (SMSG *) HeapAlloc( GetProcessHeap(), 0, sizeof(SMSG) )) )
|
||||
return 0;
|
||||
if (!(queue = QUEUE_Lock( GetFastQueue16() ))) return 0;
|
||||
|
||||
if (!(destQ = QUEUE_Lock( hDestQueue )))
|
||||
SERVER_START_REQ( send_message )
|
||||
{
|
||||
QUEUE_Unlock( queue );
|
||||
return 0;
|
||||
req->posted = FALSE;
|
||||
req->id = destQ->teb->tid;
|
||||
req->type = type;
|
||||
req->win = hwnd;
|
||||
req->msg = msg;
|
||||
req->wparam = wParam;
|
||||
req->lparam = lParam;
|
||||
req->info = 0;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
|
||||
TRACE_(sendmsg)("SM: %s [%04x] (%04x -> %04x)\n",
|
||||
SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
|
||||
|
||||
/* fill up SMSG structure */
|
||||
smsg->hWnd = hwnd;
|
||||
smsg->msg = msg;
|
||||
smsg->wParam = wParam;
|
||||
smsg->lParam = lParam;
|
||||
|
||||
smsg->lResult = 0;
|
||||
smsg->hSrcQueue = pRes ? GetFastQueue16() : 0;
|
||||
smsg->hDstQueue = hDestQueue;
|
||||
smsg->flags = flags;
|
||||
|
||||
if (pRes) {
|
||||
/* add smsg struct in the processing SM list of the source queue */
|
||||
QUEUE_AddSMSG(queue, SM_PROCESSING_LIST, smsg);
|
||||
} else {
|
||||
/* this is a notification message, we don't need a reply */
|
||||
smsg->flags |= SMSG_ALREADY_REPLIED | SMSG_RECEIVER_CLEANS;
|
||||
}
|
||||
|
||||
/* add smsg struct in the pending list of the destination queue */
|
||||
if (QUEUE_AddSMSG(destQ, SM_PENDING_LIST, smsg) == FALSE)
|
||||
{
|
||||
retVal = 0;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (!pRes) goto CLEANUP; /* don't need a reply */
|
||||
SERVER_END_REQ;
|
||||
QUEUE_Unlock( destQ );
|
||||
if (!ret) return 0;
|
||||
|
||||
iWndsLocks = WIN_SuspendWndsLock();
|
||||
|
||||
/* wait for the result */
|
||||
while ( TRUE )
|
||||
{
|
||||
/*
|
||||
* The sequence is crucial to avoid deadlock situations:
|
||||
* - first, we clear the QS_SMRESULT bit
|
||||
* - then, we check the SMSG_HAVE_RESULT bit
|
||||
* - only if this isn't set, we enter the wait state.
|
||||
*
|
||||
* As the receiver first sets the SMSG_HAVE_RESULT and then wakes us,
|
||||
* we are guaranteed that -should we now clear the QS_SMRESULT that
|
||||
* was signalled already by the receiver- we will not start waiting.
|
||||
*/
|
||||
QUEUE_WaitBits( QS_SMRESULT, timeout );
|
||||
|
||||
if ( smsg->flags & SMSG_HAVE_RESULT )
|
||||
SERVER_START_REQ( get_message_reply )
|
||||
{
|
||||
got:
|
||||
*pRes = smsg->lResult;
|
||||
TRACE_(sendmsg)("smResult = %08x\n", (unsigned)*pRes );
|
||||
break;
|
||||
req->cancel = 1;
|
||||
if ((ret = !SERVER_CALL_ERR())) result = req->result;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
|
||||
hwnd, msg, SPY_GetMsgName(msg), wParam, lParam, result, GetLastError() );
|
||||
|
||||
if (!ret && (GetLastError() == ERROR_IO_PENDING))
|
||||
{
|
||||
if (timeout == INFINITE) ERR("no timeout but no result\n");
|
||||
SetLastError(0); /* timeout */
|
||||
}
|
||||
|
||||
QUEUE_ClearWakeBit( queue, QS_SMRESULT );
|
||||
if (pRes) *pRes = result;
|
||||
|
||||
if ( smsg->flags & SMSG_HAVE_RESULT )
|
||||
goto got;
|
||||
|
||||
if( QUEUE_WaitBits( QS_SMRESULT, timeout ) == 0 )
|
||||
{
|
||||
/* return with timeout */
|
||||
SetLastError( 0 );
|
||||
retVal = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
WIN_RestoreWndsLock(iWndsLocks);
|
||||
|
||||
/* remove the smsg from the processing list of the source queue */
|
||||
QUEUE_RemoveSMSG( queue, SM_PROCESSING_LIST, smsg );
|
||||
|
||||
/* Note: the destination thread is in charge of removing the smsg from
|
||||
the pending list */
|
||||
|
||||
/* In the case of an early reply (or a timeout), sender thread will
|
||||
released the smsg structure if the receiver thread is done
|
||||
(SMSG_RECEIVED set). If the receiver thread isn't done,
|
||||
SMSG_RECEIVER_CLEANS_UP flag is set, and it will be the receiver
|
||||
responsibility to release smsg */
|
||||
EnterCriticalSection( &queue->cSection );
|
||||
|
||||
if (smsg->flags & SMSG_RECEIVED)
|
||||
HeapFree(GetProcessHeap(), 0, smsg);
|
||||
else
|
||||
smsg->flags |= SMSG_RECEIVER_CLEANS;
|
||||
|
||||
LeaveCriticalSection( &queue->cSection );
|
||||
|
||||
|
||||
CLEANUP:
|
||||
QUEUE_Unlock( queue );
|
||||
QUEUE_Unlock( destQ );
|
||||
|
||||
TRACE_(sendmsg)("done!\n");
|
||||
return retVal;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -908,77 +842,14 @@ void WINAPI ReplyMessage16( LRESULT result )
|
|||
*/
|
||||
BOOL WINAPI ReplyMessage( LRESULT result )
|
||||
{
|
||||
MESSAGEQUEUE *senderQ = 0;
|
||||
MESSAGEQUEUE *queue = 0;
|
||||
SMSG *smsg;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!(queue = QUEUE_Lock( GetFastQueue16() )))
|
||||
return FALSE;
|
||||
|
||||
TRACE_(sendmsg)("ReplyMessage, queue %04x\n", queue->self);
|
||||
|
||||
|
||||
if ( !(smsg = queue->smWaiting)
|
||||
|| !( (senderQ = QUEUE_Lock( smsg->hSrcQueue ))
|
||||
|| (smsg->flags & SMSG_ALREADY_REPLIED)) )
|
||||
goto ReplyMessageEnd;
|
||||
|
||||
if ( !(smsg->flags & SMSG_ALREADY_REPLIED) )
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( reply_message )
|
||||
{
|
||||
/* This is the first reply, so pass result to sender */
|
||||
|
||||
TRACE_(sendmsg)("\trpm: smResult = %08lx\n", (long) result );
|
||||
|
||||
EnterCriticalSection(&senderQ->cSection);
|
||||
|
||||
smsg->lResult = result;
|
||||
smsg->flags |= SMSG_ALREADY_REPLIED;
|
||||
|
||||
/* check if it's an early reply (called by the application) or
|
||||
a regular reply (called by ReceiveMessage) */
|
||||
if ( !(smsg->flags & SMSG_SENDING_REPLY) )
|
||||
smsg->flags |= SMSG_EARLY_REPLY;
|
||||
|
||||
smsg->flags |= SMSG_HAVE_RESULT;
|
||||
|
||||
LeaveCriticalSection(&senderQ->cSection);
|
||||
|
||||
/* tell the sending task that its reply is ready */
|
||||
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
|
||||
|
||||
ret = TRUE;
|
||||
req->result = result;
|
||||
req->remove = 0;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
|
||||
if (smsg->flags & SMSG_SENDING_REPLY)
|
||||
{
|
||||
/* remove msg from the waiting list, since this is the last
|
||||
ReplyMessage */
|
||||
QUEUE_RemoveSMSG( queue, SM_WAITING_LIST, smsg );
|
||||
|
||||
if (senderQ) EnterCriticalSection(&senderQ->cSection);
|
||||
|
||||
/* tell the sender we're all done with smsg structure */
|
||||
smsg->flags |= SMSG_RECEIVED;
|
||||
|
||||
/* sender will set SMSG_RECEIVER_CLEANS_UP if it wants the
|
||||
receiver to clean up smsg, it could only happen when there is
|
||||
an early reply or a timeout */
|
||||
if ( smsg->flags & SMSG_RECEIVER_CLEANS )
|
||||
{
|
||||
TRACE_(sendmsg)("Receiver cleans up!\n" );
|
||||
HeapFree( GetProcessHeap(), 0, smsg );
|
||||
}
|
||||
|
||||
if (senderQ) LeaveCriticalSection(&senderQ->cSection);
|
||||
}
|
||||
|
||||
ReplyMessageEnd:
|
||||
if ( senderQ )
|
||||
QUEUE_Unlock( senderQ );
|
||||
if ( queue )
|
||||
QUEUE_Unlock( queue );
|
||||
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1117,7 +988,7 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
|
|||
|
||||
while(1)
|
||||
{
|
||||
QMSG *qmsg;
|
||||
WORD wakeBits = HIWORD(GetQueueStatus( mask ));
|
||||
|
||||
hQueue = GetFastQueue16();
|
||||
msgQueue = QUEUE_Lock( hQueue );
|
||||
|
@ -1127,10 +998,7 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection( &msgQueue->cSection );
|
||||
msgQueue->changeBits = 0;
|
||||
LeaveCriticalSection( &msgQueue->cSection );
|
||||
|
||||
#if 0
|
||||
/* First handle a message put by SendMessage() */
|
||||
|
||||
while ( QUEUE_ReceiveMessage( msgQueue ) )
|
||||
|
@ -1152,63 +1020,37 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
|
|||
break;
|
||||
}
|
||||
LeaveCriticalSection( &msgQueue->cSection );
|
||||
#endif
|
||||
|
||||
/* Now find a normal message */
|
||||
|
||||
retry:
|
||||
if ((QUEUE_TestWakeBit(msgQueue, mask & QS_POSTMESSAGE)) &&
|
||||
((qmsg = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != 0))
|
||||
if (wakeBits & (QS_POSTMESSAGE|QS_TIMER|QS_PAINT))
|
||||
{
|
||||
QMSG qmsg;
|
||||
if (QUEUE_FindMsg( hwnd, first, last, flags & PM_REMOVE, FALSE, &qmsg ))
|
||||
{
|
||||
/* Try to convert message to requested type */
|
||||
MSG tmpMsg = qmsg->msg;
|
||||
if ( !MSG_ConvertMsg( &tmpMsg, qmsg->type, type ) )
|
||||
MSG tmpMsg = qmsg.msg;
|
||||
if ( !MSG_ConvertMsg( &tmpMsg, qmsg.type, type ) )
|
||||
{
|
||||
ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
|
||||
SPY_GetMsgName(tmpMsg.message));
|
||||
QUEUE_RemoveMsg( msgQueue, qmsg );
|
||||
/* remove it (FIXME) */
|
||||
if (!(flags & PM_REMOVE)) QUEUE_FindMsg( hwnd, first, last, TRUE, FALSE, &qmsg );
|
||||
goto retry;
|
||||
}
|
||||
|
||||
msg = tmpMsg;
|
||||
msgQueue->GetMessageTimeVal = msg.time;
|
||||
msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
|
||||
msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
|
||||
msgQueue->GetMessageExtraInfoVal = qmsg.extraInfo;
|
||||
|
||||
if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, qmsg );
|
||||
break;
|
||||
}
|
||||
|
||||
changeBits = MSG_JournalPlayBackMsg();
|
||||
EnterCriticalSection( &msgQueue->cSection );
|
||||
msgQueue->changeBits |= changeBits;
|
||||
LeaveCriticalSection( &msgQueue->cSection );
|
||||
|
||||
/* Now find a hardware event */
|
||||
|
||||
if (MSG_PeekHardwareMsg( &msg, hwnd, first, last, flags & PM_REMOVE ))
|
||||
{
|
||||
/* Got one */
|
||||
msgQueue->GetMessageTimeVal = msg.time;
|
||||
msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
|
||||
msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check again for SendMessage */
|
||||
|
||||
while ( QUEUE_ReceiveMessage( msgQueue ) )
|
||||
;
|
||||
|
||||
/* Now find a WM_PAINT message */
|
||||
|
||||
if (QUEUE_TestWakeBit(msgQueue, mask & QS_PAINT))
|
||||
/* need to fill the window handle for WM_PAINT message */
|
||||
if (msg.message == WM_PAINT)
|
||||
{
|
||||
WND* wndPtr;
|
||||
msg.hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
|
||||
msg.message = WM_PAINT;
|
||||
msg.wParam = 0;
|
||||
msg.lParam = 0;
|
||||
|
||||
if ((wndPtr = WIN_FindWndPtr(msg.hwnd)))
|
||||
{
|
||||
if( wndPtr->dwStyle & WS_MINIMIZE &&
|
||||
|
@ -1231,21 +1073,26 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
|
|||
WIN_ReleaseWndPtr(wndPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for timer messages, but yield first */
|
||||
|
||||
#if 0 /* FIXME */
|
||||
if (!(flags & PM_NOYIELD))
|
||||
{
|
||||
UserYield16();
|
||||
while ( QUEUE_ReceiveMessage( msgQueue ) )
|
||||
;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
changeBits = MSG_JournalPlayBackMsg();
|
||||
#if 0 /* FIXME */
|
||||
EnterCriticalSection( &msgQueue->cSection );
|
||||
msgQueue->changeBits |= changeBits;
|
||||
LeaveCriticalSection( &msgQueue->cSection );
|
||||
#endif
|
||||
|
||||
if (QUEUE_TestWakeBit(msgQueue, mask & QS_TIMER))
|
||||
/* Now find a hardware event */
|
||||
|
||||
if (MSG_PeekHardwareMsg( &msg, hwnd, first, last, flags & PM_REMOVE ))
|
||||
{
|
||||
if (TIMER_GetTimerMsg(&msg, hwnd, hQueue, flags & PM_REMOVE)) break;
|
||||
/* Got one */
|
||||
msgQueue->GetMessageTimeVal = msg.time;
|
||||
msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
|
||||
msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek)
|
||||
|
@ -1254,8 +1101,8 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
|
|||
if (!(flags & PM_NOYIELD)) UserYield16();
|
||||
#endif
|
||||
/* check for graphics events */
|
||||
if (USER_Driver.pMsgWaitForMultipleObjects)
|
||||
USER_Driver.pMsgWaitForMultipleObjects( 0, NULL, FALSE, 0 );
|
||||
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
|
||||
USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
|
||||
|
||||
QUEUE_Unlock( msgQueue );
|
||||
WIN_RestoreWndsLock(iWndsLocks);
|
||||
|
@ -1556,23 +1403,38 @@ BOOL WINAPI GetMessageW(
|
|||
/***********************************************************************
|
||||
* MSG_PostToQueue
|
||||
*/
|
||||
static BOOL MSG_PostToQueue( HQUEUE16 hQueue, int type, HWND hwnd,
|
||||
static BOOL MSG_PostToQueue( DWORD tid, int type, HWND hwnd,
|
||||
UINT message, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
MSG msg;
|
||||
unsigned int res;
|
||||
|
||||
if ( !hQueue ) return FALSE;
|
||||
TRACE( "posting %x %x (%s) %x %lx\n", hwnd, message, SPY_GetMsgName(message), wParam, lParam );
|
||||
|
||||
msg.hwnd = hwnd;
|
||||
msg.message = message;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.time = GetTickCount();
|
||||
GetCursorPos(&msg.pt);
|
||||
SERVER_START_REQ( send_message )
|
||||
{
|
||||
req->posted = TRUE;
|
||||
req->id = (void *)tid;
|
||||
req->type = type;
|
||||
req->win = hwnd;
|
||||
req->msg = message;
|
||||
req->wparam = wParam;
|
||||
req->lparam = lParam;
|
||||
req->info = 0;
|
||||
res = SERVER_CALL();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
return QUEUE_AddMsg( hQueue, type, &msg, 0 );
|
||||
if (res)
|
||||
{
|
||||
if (res == STATUS_INVALID_PARAMETER)
|
||||
SetLastError( ERROR_INVALID_THREAD_ID );
|
||||
else
|
||||
SetLastError( RtlNtStatusToDosError(res) );
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MSG_IsPointerMessage
|
||||
*
|
||||
|
@ -1652,7 +1514,6 @@ static BOOL MSG_IsPointerMessage(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HQUEUE16 hQueue;
|
||||
WND *wndPtr;
|
||||
|
||||
/* See thread on wine-devel around 6.2.2001. Basically posted messages
|
||||
|
@ -1680,7 +1541,7 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
|
|||
{
|
||||
TRACE("BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
|
||||
wndPtr->hwndSelf, message, wParam, lParam);
|
||||
MSG_PostToQueue( wndPtr->hmemTaskQ, type,
|
||||
MSG_PostToQueue( GetWindowThreadProcessId( wndPtr->hwndSelf, NULL ), type,
|
||||
wndPtr->hwndSelf, message, wParam, lParam );
|
||||
}
|
||||
}
|
||||
|
@ -1689,11 +1550,8 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
wndPtr = WIN_FindWndPtr( hwnd );
|
||||
hQueue = wndPtr? wndPtr->hmemTaskQ : 0;
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
|
||||
return MSG_PostToQueue( hQueue, type, hwnd, message, wParam, lParam );
|
||||
return MSG_PostToQueue( GetWindowThreadProcessId( hwnd, NULL ),
|
||||
type, hwnd, message, wParam, lParam );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1730,8 +1588,9 @@ BOOL WINAPI PostMessageW( HWND hwnd, UINT message, WPARAM wParam,
|
|||
BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message,
|
||||
WPARAM16 wParam, LPARAM lParam )
|
||||
{
|
||||
return MSG_PostToQueue( GetTaskQueue16(hTask), QMSG_WIN16,
|
||||
0, message, wParam, lParam );
|
||||
TDB *pTask = TASK_GetPtr( hTask );
|
||||
if (!pTask) return FALSE;
|
||||
return MSG_PostToQueue( (DWORD)pTask->teb->tid, QMSG_WIN16, 0, message, wParam, lParam );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -1740,8 +1599,7 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message,
|
|||
BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
|
||||
WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
return MSG_PostToQueue( GetThreadQueue16(idThread), QMSG_WIN32A,
|
||||
0, message, wParam, lParam );
|
||||
return MSG_PostToQueue( idThread, QMSG_WIN32A, 0, message, wParam, lParam );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -1750,8 +1608,7 @@ BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
|
|||
BOOL WINAPI PostThreadMessageW( DWORD idThread, UINT message,
|
||||
WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
return MSG_PostToQueue( GetThreadQueue16(idThread), QMSG_WIN32W,
|
||||
0, message, wParam, lParam );
|
||||
return MSG_PostToQueue( idThread, QMSG_WIN32W, 0, message, wParam, lParam );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1784,7 +1641,7 @@ static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
|
|||
* 1 otherwise
|
||||
*/
|
||||
static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam, DWORD timeout, WORD flags,
|
||||
LPARAM lParam, DWORD timeout, WORD type,
|
||||
LRESULT *pRes)
|
||||
{
|
||||
WND * wndPtr = 0;
|
||||
|
@ -1814,7 +1671,7 @@ static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
TRACE("BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
|
||||
wndPtr->hwndSelf, msg, (DWORD)wParam, lParam);
|
||||
MSG_SendMessage( wndPtr->hwndSelf, msg, wParam, lParam,
|
||||
timeout, flags, pRes);
|
||||
timeout, type, pRes);
|
||||
}
|
||||
}
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
|
@ -1825,11 +1682,9 @@ static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
|
||||
if (HOOK_IsHooked( WH_CALLWNDPROC ))
|
||||
{
|
||||
if (flags & SMSG_UNICODE)
|
||||
MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
|
||||
else if (flags & SMSG_WIN32)
|
||||
MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
|
||||
else
|
||||
switch(type)
|
||||
{
|
||||
case QMSG_WIN16:
|
||||
{
|
||||
LPCWPSTRUCT16 pmsg;
|
||||
|
||||
|
@ -1848,6 +1703,14 @@ static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
SEGPTR_FREE( pmsg );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QMSG_WIN32A:
|
||||
MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
|
||||
break;
|
||||
case QMSG_WIN32W:
|
||||
MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
|
||||
|
@ -1860,33 +1723,35 @@ static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
ret = 0; /* Don't send anything if the task is dying */
|
||||
goto END;
|
||||
}
|
||||
if (flags & SMSG_WIN32)
|
||||
if (type != QMSG_WIN16)
|
||||
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
|
||||
else
|
||||
SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
|
||||
|
||||
if (wndPtr->hmemTaskQ && wndPtr->hmemTaskQ != GetFastQueue16())
|
||||
ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
|
||||
wParam, lParam, timeout, flags, pRes );
|
||||
wParam, lParam, timeout, type, pRes );
|
||||
else
|
||||
{
|
||||
LRESULT res;
|
||||
LRESULT res = 0;
|
||||
|
||||
/* Call the right CallWindowProc flavor */
|
||||
if (flags & SMSG_UNICODE)
|
||||
res = CallWindowProcW( (WNDPROC)wndPtr->winproc,
|
||||
hwnd, msg, wParam, lParam );
|
||||
else if (flags & SMSG_WIN32)
|
||||
res = CallWindowProcA( (WNDPROC)wndPtr->winproc,
|
||||
hwnd, msg, wParam, lParam );
|
||||
else
|
||||
res = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
|
||||
(HWND16) hwnd, (UINT16) msg,
|
||||
(WPARAM16) wParam, lParam );
|
||||
switch(type)
|
||||
{
|
||||
case QMSG_WIN16:
|
||||
res = CallWindowProc16( (WNDPROC16)wndPtr->winproc, hwnd, msg, wParam, lParam );
|
||||
break;
|
||||
case QMSG_WIN32A:
|
||||
res = CallWindowProcA( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
|
||||
break;
|
||||
case QMSG_WIN32W:
|
||||
res = CallWindowProcW( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
|
||||
break;
|
||||
}
|
||||
if (pRes) *pRes = res;
|
||||
}
|
||||
|
||||
if (flags & SMSG_WIN32)
|
||||
if (type != QMSG_WIN16)
|
||||
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, pRes?*pRes:0, wParam, lParam );
|
||||
else
|
||||
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, pRes?*pRes:0, wParam, lParam );
|
||||
|
@ -1903,7 +1768,7 @@ LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
|
|||
LPARAM lParam)
|
||||
{
|
||||
LRESULT res;
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, 0, &res);
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN16, &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1916,8 +1781,7 @@ LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
{
|
||||
LRESULT res;
|
||||
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||
SMSG_WIN32, &res);
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32A, &res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1952,8 +1816,7 @@ LRESULT WINAPI SendMessageW(
|
|||
) {
|
||||
LRESULT res;
|
||||
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||
SMSG_WIN32 | SMSG_UNICODE, &res);
|
||||
MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, &res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1971,7 +1834,7 @@ LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
|
|||
|
||||
/* FIXME: need support for SMTO_BLOCK */
|
||||
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, 0, &msgRet);
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN16, &msgRet);
|
||||
if (resultp) *resultp = (WORD) msgRet;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1989,8 +1852,7 @@ LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
|
||||
/* FIXME: need support for SMTO_BLOCK */
|
||||
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, SMSG_WIN32,
|
||||
&msgRet);
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32A, &msgRet);
|
||||
|
||||
if (resultp) *resultp = (DWORD) msgRet;
|
||||
return ret;
|
||||
|
@ -2009,8 +1871,7 @@ LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
|
||||
/* FIXME: need support for SMTO_BLOCK */
|
||||
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout,
|
||||
SMSG_WIN32 | SMSG_UNICODE, &msgRet);
|
||||
ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32W, &msgRet);
|
||||
|
||||
if (resultp) *resultp = (DWORD) msgRet;
|
||||
return ret;
|
||||
|
@ -2022,77 +1883,82 @@ LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
|
|||
*
|
||||
* WaitMessage() suspends a thread until events appear in the thread's
|
||||
* queue.
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* Is supposed to return BOOL under Win32.
|
||||
*
|
||||
* Thread-local message queues are not supported.
|
||||
*
|
||||
* CONFORMANCE
|
||||
*
|
||||
* ECMA-234, Win32
|
||||
*
|
||||
*/
|
||||
void WINAPI WaitMessage( void )
|
||||
BOOL WINAPI WaitMessage(void)
|
||||
{
|
||||
QUEUE_WaitBits( QS_ALLINPUT, INFINITE );
|
||||
return (MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, 0 ) != WAIT_FAILED);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MsgWaitForMultipleObjects (USER32.@)
|
||||
* MsgWaitForMultipleObjectsEx (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
|
||||
BOOL fWaitAll, DWORD dwMilliseconds,
|
||||
DWORD dwWakeMask )
|
||||
DWORD WINAPI MsgWaitForMultipleObjectsEx( DWORD count, CONST HANDLE *pHandles,
|
||||
DWORD timeout, DWORD mask, DWORD flags )
|
||||
{
|
||||
DWORD i;
|
||||
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD ret;
|
||||
|
||||
DWORD i, ret;
|
||||
HQUEUE16 hQueue = GetFastQueue16();
|
||||
MESSAGEQUEUE *msgQueue = QUEUE_Lock( hQueue );
|
||||
if (!msgQueue) return WAIT_FAILED;
|
||||
MESSAGEQUEUE *msgQueue;
|
||||
|
||||
if (nCount > MAXIMUM_WAIT_OBJECTS-1)
|
||||
if (count > MAXIMUM_WAIT_OBJECTS-1)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
QUEUE_Unlock( msgQueue );
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
EnterCriticalSection( &msgQueue->cSection );
|
||||
msgQueue->changeBits = 0;
|
||||
msgQueue->wakeMask = dwWakeMask;
|
||||
LeaveCriticalSection( &msgQueue->cSection );
|
||||
if (!(msgQueue = QUEUE_Lock( hQueue ))) return WAIT_FAILED;
|
||||
|
||||
/* set the queue mask */
|
||||
SERVER_START_REQ( set_queue_mask )
|
||||
{
|
||||
req->wake_mask = (flags & MWMO_INPUTAVAILABLE) ? mask : 0;
|
||||
req->changed_mask = mask;
|
||||
req->skip_wait = 0;
|
||||
SERVER_CALL();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* Add the thread event to the handle list */
|
||||
for (i = 0; i < nCount; i++) handles[i] = pHandles[i];
|
||||
handles[nCount] = msgQueue->server_queue;
|
||||
if (USER_Driver.pMsgWaitForMultipleObjects)
|
||||
for (i = 0; i < count; i++) handles[i] = pHandles[i];
|
||||
handles[count] = msgQueue->server_queue;
|
||||
|
||||
|
||||
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
|
||||
{
|
||||
ret = USER_Driver.pMsgWaitForMultipleObjects(nCount+1, handles, fWaitAll, dwMilliseconds);
|
||||
if (ret == nCount+1) ret = nCount; /* pretend the msg queue is ready */
|
||||
ret = USER_Driver.pMsgWaitForMultipleObjectsEx( count+1, handles, timeout, mask, flags );
|
||||
if (ret == count+1) ret = count; /* pretend the msg queue is ready */
|
||||
}
|
||||
else
|
||||
ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
|
||||
|
||||
ret = WaitForMultipleObjectsEx( count+1, handles, flags & MWMO_WAITALL,
|
||||
timeout, flags & MWMO_ALERTABLE );
|
||||
QUEUE_Unlock( msgQueue );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MsgWaitForMultipleObjects (USER.640)
|
||||
* MsgWaitForMultipleObjects (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI MsgWaitForMultipleObjects16( DWORD nCount, HANDLE *pHandles,
|
||||
BOOL fWaitAll, DWORD dwMilliseconds,
|
||||
DWORD dwWakeMask )
|
||||
DWORD WINAPI MsgWaitForMultipleObjects( DWORD count, CONST HANDLE *handles,
|
||||
BOOL wait_all, DWORD timeout, DWORD mask )
|
||||
{
|
||||
TRACE("(%lu,%p,%u,%lu,0x%lx)\n",
|
||||
nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask);
|
||||
return MsgWaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask);
|
||||
return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
|
||||
wait_all ? MWMO_WAITALL : 0 );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MsgWaitForMultipleObjects16 (USER.640)
|
||||
*/
|
||||
DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
|
||||
BOOL wait_all, DWORD timeout, DWORD mask )
|
||||
{
|
||||
return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
|
||||
wait_all ? MWMO_WAITALL : 0 );
|
||||
}
|
||||
|
||||
|
||||
struct accent_char
|
||||
{
|
||||
BYTE ac_accent;
|
||||
|
@ -2594,17 +2460,25 @@ BOOL16 WINAPI InSendMessage16(void)
|
|||
*/
|
||||
BOOL WINAPI InSendMessage(void)
|
||||
{
|
||||
MESSAGEQUEUE *queue;
|
||||
BOOL ret;
|
||||
return (InSendMessageEx(NULL) & (ISMEX_SEND|ISMEX_REPLIED)) == ISMEX_SEND;
|
||||
}
|
||||
|
||||
if (!(queue = QUEUE_Lock( GetFastQueue16() )))
|
||||
return 0;
|
||||
ret = (BOOL)queue->smWaiting;
|
||||
|
||||
QUEUE_Unlock( queue );
|
||||
/***********************************************************************
|
||||
* InSendMessageEx (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI InSendMessageEx( LPVOID reserved )
|
||||
{
|
||||
DWORD ret = 0;
|
||||
SERVER_START_REQ( in_send_message )
|
||||
{
|
||||
if (!SERVER_CALL_ERR()) ret = req->flags;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BroadcastSystemMessage (USER32.@)
|
||||
*/
|
||||
|
@ -2623,8 +2497,7 @@ LONG WINAPI BroadcastSystemMessage(
|
|||
*/
|
||||
BOOL WINAPI SendNotifyMessageA(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||
SMSG_WIN32, NULL);
|
||||
return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32A, NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -2632,8 +2505,7 @@ BOOL WINAPI SendNotifyMessageA(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|||
*/
|
||||
BOOL WINAPI SendNotifyMessageW(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE,
|
||||
SMSG_WIN32 | SMSG_UNICODE, NULL);
|
||||
return MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
770
windows/queue.c
770
windows/queue.c
File diff suppressed because it is too large
Load Diff
139
windows/timer.c
139
windows/timer.c
|
@ -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;
|
||||
|
@ -106,85 +94,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
|
||||
*/
|
||||
|
@ -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,20 +145,27 @@ 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->expired = FALSE;
|
||||
pTimer->hService = SERVICE_AddTimer( max( timeout, (SYS_TIMER_RATE+500)/1000 ),
|
||||
TIMER_CheckTimer, (ULONG_PTR)pTimer );
|
||||
pTimer->proc = winproc;
|
||||
|
||||
TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
|
||||
pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
|
||||
|
@ -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);
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue