Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
51ab43bd
Commit
51ab43bd
authored
May 18, 2001
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved the major part of message queue and window timer handling into
the server. Implemented MsgWaitForMultipleObjectsEx.
parent
cd8d181a
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1516 additions
and
1263 deletions
+1516
-1263
user32.spec
dlls/user/user32.spec
+1
-1
user_main.c
dlls/user/user_main.c
+1
-1
x11drv.spec
dlls/x11drv/x11drv.spec
+1
-1
message.h
include/message.h
+0
-2
queue.h
include/queue.h
+5
-67
server.h
include/server.h
+144
-6
user.h
include/user.h
+1
-1
winuser.h
include/winuser.h
+27
-11
queue.c
server/queue.c
+684
-17
request.h
server/request.h
+22
-2
thread.c
server/thread.c
+12
-2
trace.c
server/trace.c
+144
-5
clipboard.c
windows/clipboard.c
+5
-0
message.c
windows/message.c
+251
-379
queue.c
windows/queue.c
+172
-636
timer.c
windows/timer.c
+37
-104
win.c
windows/win.c
+2
-23
event.c
windows/x11drv/event.c
+7
-5
No files found.
dlls/user/user32.spec
View file @
51ab43bd
...
...
@@ -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
@ st
ub
MsgWaitForMultipleObjectsEx
@ st
dcall MsgWaitForMultipleObjectsEx(long ptr long long long)
MsgWaitForMultipleObjectsEx
@ stdcall OemKeyScan(long) OemKeyScan
@ stdcall OemToCharA(ptr ptr) OemToCharA
@ stdcall OemToCharBuffA(ptr ptr long) OemToCharBuffA
...
...
dlls/user/user_main.c
View file @
51ab43bd
...
...
@@ -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
(
MsgWaitForMultipleObjects
Ex
);
GET_USER_FUNC
(
ScrollWindowEx
);
GET_USER_FUNC
(
SetFocus
);
GET_USER_FUNC
(
SetParent
);
...
...
dlls/x11drv/x11drv.spec
View file @
51ab43bd
...
...
@@ -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 MsgWaitForMultipleObjects
Ex(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
...
...
include/message.h
View file @
51ab43bd
...
...
@@ -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 */
...
...
include/queue.h
View file @
51ab43bd
...
...
@@ -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
);
...
...
include/server.h
View file @
51ab43bd
...
...
@@ -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 4
4
#define SERVER_PROTOCOL_VERSION 4
5
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
include/user.h
View file @
51ab43bd
...
...
@@ -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
(
*
pMsgWaitForMultipleObjects
Ex
)(
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
);
...
...
include/winuser.h
View file @
51ab43bd
...
...
@@ -902,6 +902,10 @@ typedef struct
#define WM_APP 0x8000
/* MsgWaitForMultipleObjectsEx flags */
#define MWMO_WAITALL 0x0001
#define MWMO_ALERTABLE 0x0002
#define MWMO_INPUTAVAILABLE 0x0004
#define DLGC_WANTARROWS 0x0001
#define DLGC_WANTTAB 0x0002
...
...
@@ -3026,6 +3030,16 @@ typedef struct
#define QS_ALLEVENTS (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY)
#define QS_ALLINPUT (QS_ALLEVENTS | QS_SENDMESSAGE)
/* Extra (undocumented) queue wake bits - see "Undoc. Windows" */
#define QS_SMRESULT 0x8000
/* InSendMessageEx flags */
#define ISMEX_NOSEND 0x00000000
#define ISMEX_SEND 0x00000001
#define ISMEX_NOTIFY 0x00000002
#define ISMEX_CALLBACK 0x00000004
#define ISMEX_REPLIED 0x00000008
#define DDL_READWRITE 0x0000
#define DDL_READONLY 0x0001
#define DDL_HIDDEN 0x0002
...
...
@@ -3184,10 +3198,11 @@ INT WINAPI MessageBoxExW(HWND,LPCWSTR,LPCWSTR,UINT,WORD);
HMONITOR
WINAPI
MonitorFromPoint
(
POINT
,
DWORD
);
HMONITOR
WINAPI
MonitorFromRect
(
LPRECT
,
DWORD
);
HMONITOR
WINAPI
MonitorFromWindow
(
HWND
,
DWORD
);
DWORD
WINAPI
MsgWaitForMultipleObjects
(
DWORD
,
HANDLE
*
,
BOOL
,
DWORD
,
DWORD
);
BOOL
WINAPI
PaintDesktop
(
HDC
);
BOOL
WINAPI
PostThreadMessageA
(
DWORD
,
UINT
,
WPARAM
,
LPARAM
);
BOOL
WINAPI
PostThreadMessageW
(
DWORD
,
UINT
,
WPARAM
,
LPARAM
);
DWORD
WINAPI
MsgWaitForMultipleObjects
(
DWORD
,
CONST
HANDLE
*
,
BOOL
,
DWORD
,
DWORD
);
DWORD
WINAPI
MsgWaitForMultipleObjectsEx
(
DWORD
,
CONST
HANDLE
*
,
DWORD
,
DWORD
,
DWORD
);
BOOL
WINAPI
PaintDesktop
(
HDC
);
BOOL
WINAPI
PostThreadMessageA
(
DWORD
,
UINT
,
WPARAM
,
LPARAM
);
BOOL
WINAPI
PostThreadMessageW
(
DWORD
,
UINT
,
WPARAM
,
LPARAM
);
#define PostThreadMessage WINELIB_NAME_AW(PostThreadMessage)
BOOL
WINAPI
RegisterHotKey
(
HWND
,
INT
,
UINT
,
UINT
);
HDEVNOTIFY
WINAPI
RegisterDeviceNotificationA
(
HANDLE
,
LPVOID
,
DWORD
);
...
...
@@ -3229,7 +3244,6 @@ LONG WINAPI GetMessageTime(void);
DWORD
WINAPI
OemKeyScan
(
WORD
);
BOOL
WINAPI
ReleaseCapture
(
void
);
BOOL
WINAPI
SetKeyboardState
(
LPBYTE
);
VOID
WINAPI
WaitMessage
(
void
);
/* Declarations for functions that change between Win16 and Win32 */
...
...
@@ -3589,12 +3603,13 @@ BOOL WINAPI GrayStringA(HDC,HBRUSH,GRAYSTRINGPROC,LPARAM,
BOOL
WINAPI
GrayStringW
(
HDC
,
HBRUSH
,
GRAYSTRINGPROC
,
LPARAM
,
INT
,
INT
,
INT
,
INT
,
INT
);
#define GrayString WINELIB_NAME_AW(GrayString)
BOOL
WINAPI
HideCaret
(
HWND
);
BOOL
WINAPI
HiliteMenuItem
(
HWND
,
HMENU
,
UINT
,
UINT
);
BOOL
WINAPI
InflateRect
(
LPRECT
,
INT
,
INT
);
BOOL
WINAPI
InSendMessage
(
void
);
BOOL
WINAPI
InsertMenuA
(
HMENU
,
UINT
,
UINT
,
UINT
,
LPCSTR
);
BOOL
WINAPI
InsertMenuW
(
HMENU
,
UINT
,
UINT
,
UINT
,
LPCWSTR
);
BOOL
WINAPI
HideCaret
(
HWND
);
BOOL
WINAPI
HiliteMenuItem
(
HWND
,
HMENU
,
UINT
,
UINT
);
BOOL
WINAPI
InflateRect
(
LPRECT
,
INT
,
INT
);
BOOL
WINAPI
InSendMessage
(
void
);
DWORD
WINAPI
InSendMessageEx
(
LPVOID
);
BOOL
WINAPI
InsertMenuA
(
HMENU
,
UINT
,
UINT
,
UINT
,
LPCSTR
);
BOOL
WINAPI
InsertMenuW
(
HMENU
,
UINT
,
UINT
,
UINT
,
LPCWSTR
);
#define InsertMenu WINELIB_NAME_AW(InsertMenu)
BOOL
WINAPI
InsertMenuItemA
(
HMENU
,
UINT
,
BOOL
,
const
MENUITEMINFOA
*
);
BOOL
WINAPI
InsertMenuItemW
(
HMENU
,
UINT
,
BOOL
,
const
MENUITEMINFOW
*
);
...
...
@@ -3837,6 +3852,7 @@ WORD WINAPI VkKeyScanW(WCHAR);
WORD
WINAPI
VkKeyScanExA
(
CHAR
,
HKL
);
WORD
WINAPI
VkKeyScanExW
(
WCHAR
,
HKL
);
#define VkKeyScanEx WINELIB_NAME_AW(VkKeyScanEx)
BOOL
WINAPI
WaitMessage
(
void
);
HWND
WINAPI
WindowFromDC
(
HDC
);
HWND
WINAPI
WindowFromPoint
(
POINT
);
BOOL
WINAPI
WinHelpA
(
HWND
,
LPCSTR
,
UINT
,
DWORD
);
...
...
server/queue.c
View file @
51ab43bd
...
...
@@ -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 */
struct
object
obj
;
/* object header */
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
);
}
server/request.h
View file @
51ab43bd
...
...
@@ -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
,
...
...
server/thread.c
View file @
51ab43bd
...
...
@@ -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
;
}
...
...
server/trace.c
View file @
51ab43bd
...
...
@@ -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"
,
...
...
windows/clipboard.c
View file @
51ab43bd
...
...
@@ -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
;
...
...
windows/message.c
View file @
51ab43bd
...
...
@@ -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
)
||
(
message
==
WM_RBUTTONDOWN
)
||
(
message
==
WM_MBUTTONDOWN
))
?
1
:
0
;
int
mouseClick
=
((
message
==
WM_LBUTTONDOWN
)
||
(
message
==
WM_RBUTTONDOWN
)
||
(
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
;
int
iWndsLocks
;
if
(
pRes
)
*
pRes
=
0
;
MESSAGEQUEUE
*
destQ
;
BOOL
ret
;
int
iWndsLocks
;
LRESULT
result
=
0
;
if
(
IsTaskLocked16
()
||
!
IsWindow
(
hwnd
))
return
0
;
TRACE
(
"hwnd %x msg %x (%s) wp %x lp %lx
\n
"
,
hwnd
,
msg
,
SPY_GetMsgName
(
msg
),
wParam
,
lParam
);
/* 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
)))
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
();
}
SERVER_END_REQ
;
QUEUE_Unlock
(
destQ
);
if
(
!
ret
)
return
0
;
TRACE_
(
sendmsg
)(
"SM: %s [%04x] (%04x -> %04x)
\n
"
,
SPY_GetMsgName
(
msg
),
msg
,
queue
->
self
,
hDestQueue
);
iWndsLocks
=
WIN_SuspendWndsLock
();
/* 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
;
}
/* wait for the result */
QUEUE_WaitBits
(
QS_SMRESULT
,
timeout
);
/* add smsg struct in the pending list of the destination queue */
if
(
QUEUE_AddSMSG
(
destQ
,
SM_PENDING_LIST
,
smsg
)
==
FALSE
)
SERVER_START_REQ
(
get_message_reply
)
{
re
tVal
=
0
;
goto
CLEANUP
;
re
q
->
cancel
=
1
;
if
((
ret
=
!
SERVER_CALL_ERR
()))
result
=
req
->
result
;
}
SERVER_END_REQ
;
if
(
!
pRes
)
goto
CLEANUP
;
/* don't need a reply */
iWndsLocks
=
WIN_SuspendWndsLock
();
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
()
);
/* wait for the result */
while
(
TRUE
)
if
(
!
ret
&&
(
GetLastError
()
==
ERROR_IO_PENDING
))
{
/*
* 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.
*/
if
(
smsg
->
flags
&
SMSG_HAVE_RESULT
)
{
got:
*
pRes
=
smsg
->
lResult
;
TRACE_
(
sendmsg
)(
"smResult = %08x
\n
"
,
(
unsigned
)
*
pRes
);
break
;
}
QUEUE_ClearWakeBit
(
queue
,
QS_SMRESULT
);
if
(
smsg
->
flags
&
SMSG_HAVE_RESULT
)
goto
got
;
if
(
QUEUE_WaitBits
(
QS_SMRESULT
,
timeout
)
==
0
)
{
/* return with timeout */
SetLastError
(
0
);
retVal
=
0
;
break
;
}
if
(
timeout
==
INFINITE
)
ERR
(
"no timeout but no result
\n
"
);
SetLastError
(
0
);
/* timeout */
}
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
);
if
(
pRes
)
*
pRes
=
result
;
CLEANUP:
QUEUE_Unlock
(
queue
);
QUEUE_Unlock
(
destQ
);
TRACE_
(
sendmsg
)(
"done!
\n
"
);
return
retVal
;
WIN_RestoreWndsLock
(
iWndsLocks
);
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
)
)
{
/* This is the first reply, so pass result to sender */
TRACE_
(
sendmsg
)(
"
\t
rpm: 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
;
}
if
(
smsg
->
flags
&
SMSG_SENDING_REPLY
)
BOOL
ret
;
SERVER_START_REQ
(
reply_message
)
{
/* 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
);
req
->
result
=
result
;
req
->
remove
=
0
;
ret
=
!
SERVER_CALL_ERR
();
}
ReplyMessageEnd:
if
(
senderQ
)
QUEUE_Unlock
(
senderQ
);
if
(
queue
)
QUEUE_Unlock
(
queue
);
SERVER_END_REQ
;
return
ret
;
}
...
...
@@ -1116,9 +987,9 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
iWndsLocks
=
WIN_SuspendWndsLock
();
while
(
1
)
{
QMSG
*
qmsg
;
{
WORD
wakeBits
=
HIWORD
(
GetQueueStatus
(
mask
))
;
hQueue
=
GetFastQueue16
();
msgQueue
=
QUEUE_Lock
(
hQueue
);
if
(
!
msgQueue
)
...
...
@@ -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,36 +1020,69 @@ 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
))
{
/* Try to convert message to requested type */
MSG
tmpMsg
=
qmsg
->
msg
;
if
(
!
MSG_ConvertMsg
(
&
tmpMsg
,
qmsg
->
type
,
type
)
)
QMSG
qmsg
;
if
(
QUEUE_FindMsg
(
hwnd
,
first
,
last
,
flags
&
PM_REMOVE
,
FALSE
,
&
qmsg
))
{
ERR
(
"Message %s of wrong type contains pointer parameters. Skipped!
\n
"
,
SPY_GetMsgName
(
tmpMsg
.
message
));
QUEUE_RemoveMsg
(
msgQueue
,
qmsg
);
goto
retry
;
}
/* Try to convert message to requested 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
));
/* 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
;
msg
=
tmpMsg
;
msgQueue
->
GetMessageTimeVal
=
msg
.
time
;
msgQueue
->
GetMessagePosVal
=
MAKELONG
(
(
INT16
)
msg
.
pt
.
x
,
(
INT16
)
msg
.
pt
.
y
);
msgQueue
->
GetMessageExtraInfoVal
=
qmsg
.
extraInfo
;
if
(
flags
&
PM_REMOVE
)
QUEUE_RemoveMsg
(
msgQueue
,
qmsg
);
break
;
/* need to fill the window handle for WM_PAINT message */
if
(
msg
.
message
==
WM_PAINT
)
{
WND
*
wndPtr
;
msg
.
hwnd
=
WIN_FindWinToRepaint
(
hwnd
,
hQueue
);
if
((
wndPtr
=
WIN_FindWndPtr
(
msg
.
hwnd
)))
{
if
(
wndPtr
->
dwStyle
&
WS_MINIMIZE
&&
(
HICON
)
GetClassLongA
(
wndPtr
->
hwndSelf
,
GCL_HICON
)
)
{
msg
.
message
=
WM_PAINTICON
;
msg
.
wParam
=
1
;
}
if
(
!
hwnd
||
msg
.
hwnd
==
hwnd
||
IsChild16
(
hwnd
,
msg
.
hwnd
)
)
{
if
(
wndPtr
->
flags
&
WIN_INTERNAL_PAINT
&&
!
wndPtr
->
hrgnUpdate
)
{
wndPtr
->
flags
&=
~
WIN_INTERNAL_PAINT
;
QUEUE_DecPaintCount
(
hQueue
);
}
WIN_ReleaseWndPtr
(
wndPtr
);
break
;
}
WIN_ReleaseWndPtr
(
wndPtr
);
}
}
else
break
;
}
}
changeBits
=
MSG_JournalPlayBackMsg
();
#if 0 /* FIXME */
EnterCriticalSection( &msgQueue->cSection );
msgQueue->changeBits |= changeBits;
LeaveCriticalSection( &msgQueue->cSection );
#endif
/* Now find a hardware event */
...
...
@@ -1194,68 +1095,14 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
break
;
}
/* Check again for SendMessage */
while
(
QUEUE_ReceiveMessage
(
msgQueue
)
)
;
/* Now find a WM_PAINT message */
if
(
QUEUE_TestWakeBit
(
msgQueue
,
mask
&
QS_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
&&
(
HICON
)
GetClassLongA
(
wndPtr
->
hwndSelf
,
GCL_HICON
)
)
{
msg
.
message
=
WM_PAINTICON
;
msg
.
wParam
=
1
;
}
if
(
!
hwnd
||
msg
.
hwnd
==
hwnd
||
IsChild16
(
hwnd
,
msg
.
hwnd
)
)
{
if
(
wndPtr
->
flags
&
WIN_INTERNAL_PAINT
&&
!
wndPtr
->
hrgnUpdate
)
{
wndPtr
->
flags
&=
~
WIN_INTERNAL_PAINT
;
QUEUE_DecPaintCount
(
hQueue
);
}
WIN_ReleaseWndPtr
(
wndPtr
);
break
;
}
WIN_ReleaseWndPtr
(
wndPtr
);
}
}
/* Check for timer messages, but yield first */
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD))
{
UserYield16();
while ( QUEUE_ReceiveMessage( msgQueue ) )
;
}
#endif
if
(
QUEUE_TestWakeBit
(
msgQueue
,
mask
&
QS_TIMER
))
{
if
(
TIMER_GetTimerMsg
(
&
msg
,
hwnd
,
hQueue
,
flags
&
PM_REMOVE
))
break
;
}
if
(
peek
)
{
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD)) UserYield16();
#endif
/* check for graphics events */
if
(
USER_Driver
.
pMsgWaitForMultipleObjects
)
USER_Driver
.
pMsgWaitForMultipleObjects
(
0
,
NULL
,
FALSE
,
0
);
if
(
USER_Driver
.
pMsgWaitForMultipleObjects
Ex
)
USER_Driver
.
pMsgWaitForMultipleObjects
Ex
(
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,29 +1682,35 @@ 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
)
{
LPCWPSTRUCT16
pmsg
;
case
QMSG_WIN16
:
{
LPCWPSTRUCT16
pmsg
;
if
((
pmsg
=
SEGPTR_NEW
(
CWPSTRUCT16
)))
{
pmsg
->
hwnd
=
hwnd
&
0xffff
;
pmsg
->
message
=
msg
&
0xffff
;
pmsg
->
wParam
=
wParam
&
0xffff
;
pmsg
->
lParam
=
lParam
;
HOOK_CallHooks16
(
WH_CALLWNDPROC
,
HC_ACTION
,
1
,
(
LPARAM
)
SEGPTR_GET
(
pmsg
)
);
hwnd
=
pmsg
->
hwnd
;
msg
=
pmsg
->
message
;
wParam
=
pmsg
->
wParam
;
lParam
=
pmsg
->
lParam
;
SEGPTR_FREE
(
pmsg
);
}
}
if
((
pmsg
=
SEGPTR_NEW
(
CWPSTRUCT16
)))
{
pmsg
->
hwnd
=
hwnd
&
0xffff
;
pmsg
->
message
=
msg
&
0xffff
;
pmsg
->
wParam
=
wParam
&
0xffff
;
pmsg
->
lParam
=
lParam
;
HOOK_CallHooks16
(
WH_CALLWNDPROC
,
HC_ACTION
,
1
,
(
LPARAM
)
SEGPTR_GET
(
pmsg
)
);
hwnd
=
pmsg
->
hwnd
;
msg
=
pmsg
->
message
;
wParam
=
pmsg
->
wParam
;
lParam
=
pmsg
->
lParam
;
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.@)
* MsgWaitForMultipleObjects
Ex
(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
(
nC
ount
>
MAXIMUM_WAIT_OBJECTS
-
1
)
if
(
c
ount
>
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
=
nC
ount
;
/* pretend the msg queue is ready */
ret
=
USER_Driver
.
pMsgWaitForMultipleObjects
Ex
(
count
+
1
,
handles
,
timeout
,
mask
,
flags
);
if
(
ret
==
count
+
1
)
ret
=
c
ount
;
/* pretend the msg queue is ready */
}
else
ret
=
WaitForMultipleObjects
(
nCount
+
1
,
handles
,
fWaitAll
,
dwMilliseconds
);
ret
=
WaitForMultipleObjects
Ex
(
count
+
1
,
handles
,
flags
&
MWMO_WAITALL
,
timeout
,
flags
&
MWMO_ALERTABLE
);
QUEUE_Unlock
(
msgQueue
);
return
ret
;
}
/***********************************************************************
* MsgWaitForMultipleObjects (USER32.@)
*/
DWORD
WINAPI
MsgWaitForMultipleObjects
(
DWORD
count
,
CONST
HANDLE
*
handles
,
BOOL
wait_all
,
DWORD
timeout
,
DWORD
mask
)
{
return
MsgWaitForMultipleObjectsEx
(
count
,
handles
,
timeout
,
mask
,
wait_all
?
MWMO_WAITALL
:
0
);
}
/***********************************************************************
* MsgWaitForMultipleObjects (USER.640)
* MsgWaitForMultipleObjects
16
(USER.640)
*/
DWORD
WINAPI
MsgWaitForMultipleObjects16
(
DWORD
nCount
,
HANDLE
*
pHandles
,
BOOL
fWaitAll
,
DWORD
dwMilliseconds
,
DWORD
dwWakeMask
)
DWORD
WINAPI
MsgWaitForMultipleObjects16
(
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
);
}
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
);
}
/***********************************************************************
...
...
windows/queue.c
View file @
51ab43bd
/* * Message queues related functions
/*
* Message queues related functions
*
* Copyright 1993, 1994 Alexandre Julliard
*/
...
...
@@ -20,12 +21,11 @@
#include "server.h"
#include "spy.h"
DECLARE_DEBUG_CHANNEL
(
msg
);
DECLARE_DEBUG_CHANNEL
(
sendmsg
);
DEFAULT_DEBUG_CHANNEL
(
msg
);
#define MAX_QUEUE_SIZE 120
/* Max. size of a message queue */
static
HQUEUE16
hFirstQueue
=
0
;
static
HQUEUE16
hExitingQueue
=
0
;
static
HQUEUE16
hmemSysMsgQueue
=
0
;
static
MESSAGEQUEUE
*
sysMsgQueue
=
NULL
;
...
...
@@ -59,7 +59,7 @@ PERQUEUEDATA * PERQDATA_CreateInstance( )
TRACE_
(
msg
)(
"()
\n
"
);
/* Share a single instance of perQData for all 16 bit tasks */
if
(
(
bIsWin16
=
THREAD_IsWin16
(
NtCurrentTeb
()
)
)
)
if
(
(
bIsWin16
=
!
(
NtCurrentTeb
()
->
tibflags
&
TEBF_WIN32
)
)
)
{
/* If previously allocated, just bump up ref count */
if
(
pQDataWin16
)
...
...
@@ -363,21 +363,14 @@ void QUEUE_DumpQueue( HQUEUE16 hQueue )
EnterCriticalSection
(
&
pq
->
cSection
);
DPRINTF
(
"next: %12.4x Intertask SendMessage:
\n
"
"thread: %10p ----------------------
\n
"
"firstMsg: %8p smWaiting: %10p
\n
"
"lastMsg: %8p smPending: %10p
\n
"
"msgCount: %8.4x smProcessing: %10p
\n
"
DPRINTF
(
"thread: %10p Intertask SendMessage:
\n
"
"firstMsg: %8p lastMsg: %8p
\n
"
"lockCount: %7.4x
\n
"
"paints: %10.4x
\n
"
"timers: %10.4x
\n
"
"wakeBits: %8.4x
\n
"
"wakeMask: %8.4x
\n
"
"hCurHook: %8.4x
\n
"
,
pq
->
next
,
pq
->
teb
,
pq
->
firstMsg
,
pq
->
smWaiting
,
pq
->
lastMsg
,
pq
->
smPending
,
pq
->
msgCount
,
pq
->
smProcessing
,
(
unsigned
)
pq
->
lockCount
,
pq
->
wPaintCount
,
pq
->
wTimerCount
,
pq
->
wakeBits
,
pq
->
wakeMask
,
pq
->
hCurHook
);
pq
->
teb
,
pq
->
firstMsg
,
pq
->
lastMsg
,
(
unsigned
)
pq
->
lockCount
,
pq
->
wPaintCount
,
pq
->
hCurHook
);
LeaveCriticalSection
(
&
pq
->
cSection
);
...
...
@@ -386,34 +379,6 @@ void QUEUE_DumpQueue( HQUEUE16 hQueue )
/***********************************************************************
* QUEUE_WalkQueues
*/
void
QUEUE_WalkQueues
(
void
)
{
char
module
[
10
];
HQUEUE16
hQueue
=
hFirstQueue
;
DPRINTF
(
"Queue Msgs Thread Task Module
\n
"
);
while
(
hQueue
)
{
MESSAGEQUEUE
*
queue
=
QUEUE_Lock
(
hQueue
);
if
(
!
queue
)
{
WARN_
(
msg
)(
"Bad queue handle %04x
\n
"
,
hQueue
);
return
;
}
if
(
!
GetModuleName16
(
queue
->
teb
->
htask16
,
module
,
sizeof
(
module
)))
strcpy
(
module
,
"???"
);
DPRINTF
(
"%04x %4d %p %04x %s
\n
"
,
hQueue
,
queue
->
msgCount
,
queue
->
teb
,
queue
->
teb
->
htask16
,
module
);
hQueue
=
queue
->
next
;
QUEUE_Unlock
(
queue
);
}
DPRINTF
(
"
\n
"
);
}
/***********************************************************************
* QUEUE_IsExitingQueue
*/
BOOL
QUEUE_IsExitingQueue
(
HQUEUE16
hQueue
)
...
...
@@ -452,24 +417,25 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
if
(
!
msgQueue
)
return
0
;
SERVER_START_REQ
(
get_msg_queue
)
if
(
bCreatePerQData
)
{
SERVER_CALL_ERR
();
handle
=
req
->
handle
;
}
SERVER_END_REQ
;
if
(
!
handle
)
{
ERR_
(
msg
)(
"Cannot get thread queue"
);
GlobalFree16
(
hQueue
);
return
0
;
SERVER_START_REQ
(
get_msg_queue
)
{
SERVER_CALL_ERR
();
handle
=
req
->
handle
;
}
SERVER_END_REQ
;
if
(
!
handle
)
{
ERR_
(
msg
)(
"Cannot get thread queue"
);
GlobalFree16
(
hQueue
);
return
0
;
}
msgQueue
->
server_queue
=
handle
;
}
msgQueue
->
server_queue
=
handle
;
msgQueue
->
server_queue
=
ConvertToGlobalHandle
(
msgQueue
->
server_queue
);
msgQueue
->
self
=
hQueue
;
msgQueue
->
wakeBits
=
msgQueue
->
changeBits
=
0
;
msgQueue
->
self
=
hQueue
;
InitializeCriticalSection
(
&
msgQueue
->
cSection
);
MakeCriticalSectionGlobal
(
&
msgQueue
->
cSection
);
...
...
@@ -484,44 +450,6 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
/***********************************************************************
* QUEUE_FlushMessage
*
* Try to reply to all pending sent messages on exit.
*/
static
void
QUEUE_FlushMessages
(
MESSAGEQUEUE
*
queue
)
{
SMSG
*
smsg
;
MESSAGEQUEUE
*
senderQ
=
0
;
if
(
queue
)
{
EnterCriticalSection
(
&
queue
->
cSection
);
/* empty the list of pending SendMessage waiting to be received */
while
(
queue
->
smPending
)
{
smsg
=
QUEUE_RemoveSMSG
(
queue
,
SM_PENDING_LIST
,
0
);
senderQ
=
QUEUE_Lock
(
smsg
->
hSrcQueue
);
if
(
!
senderQ
)
continue
;
/* return 0, to unblock other thread */
smsg
->
lResult
=
0
;
smsg
->
flags
|=
SMSG_HAVE_RESULT
;
QUEUE_SetWakeBit
(
senderQ
,
QS_SMRESULT
);
QUEUE_Unlock
(
senderQ
);
}
QUEUE_ClearWakeBit
(
queue
,
QS_SENDMESSAGE
);
LeaveCriticalSection
(
&
queue
->
cSection
);
}
}
/***********************************************************************
* QUEUE_DeleteMsgQueue
*
* Unlinks and deletes a message queue.
...
...
@@ -532,7 +460,6 @@ static void QUEUE_FlushMessages( MESSAGEQUEUE *queue )
BOOL
QUEUE_DeleteMsgQueue
(
HQUEUE16
hQueue
)
{
MESSAGEQUEUE
*
msgQueue
=
QUEUE_Lock
(
hQueue
);
HQUEUE16
*
pPrev
;
TRACE_
(
msg
)(
"(): Deleting message queue %04x
\n
"
,
hQueue
);
...
...
@@ -547,9 +474,6 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
if
(
hCursorQueue
==
hQueue
)
hCursorQueue
=
0
;
if
(
hActiveQueue
==
hQueue
)
hActiveQueue
=
0
;
/* flush sent messages */
QUEUE_FlushMessages
(
msgQueue
);
HeapLock
(
GetProcessHeap
()
);
/* FIXME: a bit overkill */
/* Release per queue data if present */
...
...
@@ -558,24 +482,7 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
PERQDATA_Release
(
msgQueue
->
pQData
);
msgQueue
->
pQData
=
0
;
}
/* remove the message queue from the global link list */
pPrev
=
&
hFirstQueue
;
while
(
*
pPrev
&&
(
*
pPrev
!=
hQueue
))
{
MESSAGEQUEUE
*
msgQ
=
(
MESSAGEQUEUE
*
)
GlobalLock16
(
*
pPrev
);
/* sanity check */
if
(
!
msgQ
||
(
msgQ
->
magic
!=
QUEUE_MAGIC
)
)
{
/* HQUEUE link list is corrupted, try to exit gracefully */
ERR_
(
msg
)(
"HQUEUE link list corrupted!
\n
"
);
pPrev
=
0
;
break
;
}
pPrev
=
&
msgQ
->
next
;
}
if
(
pPrev
&&
*
pPrev
)
*
pPrev
=
msgQueue
->
next
;
msgQueue
->
self
=
0
;
HeapUnlock
(
GetProcessHeap
()
);
...
...
@@ -619,47 +526,34 @@ MESSAGEQUEUE *QUEUE_GetSysQueue(void)
*
* See "Windows Internals", p.449
*/
static
BOOL
QUEUE_TrySetWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
bit
,
BOOL
always
)
static
BOOL
QUEUE_TrySetWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
set
,
WORD
clear
,
BOOL
always
)
{
BOOL
wake
=
FALSE
;
EnterCriticalSection
(
&
queue
->
cSection
);
TRACE_
(
msg
)(
"queue = %04x, set = %04x, clear = %04x, always = %d
\n
"
,
queue
->
self
,
set
,
clear
,
always
);
if
(
!
queue
->
server_queue
)
return
FALSE
;
TRACE_
(
msg
)(
"queue = %04x (wm=%04x), bit = %04x, always = %d
\n
"
,
queue
->
self
,
queue
->
wakeMask
,
bit
,
always
);
if
((
queue
->
wakeMask
&
bit
)
||
always
)
SERVER_START_REQ
(
set_queue_bits
)
{
if
(
bit
&
QS_MOUSE
)
pMouseQueue
=
queue
;
if
(
bit
&
QS_KEY
)
pKbdQueue
=
queue
;
queue
->
changeBits
|=
bit
;
queue
->
wakeBits
|=
bit
;
req
->
handle
=
queue
->
server_queue
;
req
->
set
=
set
;
req
->
clear
=
clear
;
req
->
mask_cond
=
always
?
0
:
set
;
if
(
!
SERVER_CALL
())
wake
=
(
req
->
changed_mask
&
set
)
!=
0
;
}
if
(
queue
->
wakeMask
&
bit
)
{
queue
->
wakeMask
=
0
;
wake
=
TRUE
;
}
LeaveCriticalSection
(
&
queue
->
cSection
);
SERVER_END_REQ
;
if
(
wake
)
if
(
wake
||
always
)
{
/* Wake up thread waiting for message */
SERVER_START_REQ
(
wake_queue
)
{
req
->
handle
=
queue
->
server_queue
;
req
->
bits
=
bit
;
SERVER_CALL
();
}
SERVER_END_REQ
;
if
(
set
&
QS_MOUSE
)
pMouseQueue
=
queue
;
if
(
set
&
QS_KEY
)
pKbdQueue
=
queue
;
}
return
wake
;
}
void
QUEUE_SetWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
bit
)
void
QUEUE_SetWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
set
,
WORD
clear
)
{
QUEUE_TrySetWakeBit
(
queue
,
bit
,
TRUE
);
QUEUE_TrySetWakeBit
(
queue
,
set
,
clear
,
TRUE
);
}
...
...
@@ -668,25 +562,9 @@ void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
*/
void
QUEUE_ClearWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
bit
)
{
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
changeBits
&=
~
bit
;
queue
->
wakeBits
&=
~
bit
;
LeaveCriticalSection
(
&
queue
->
cSection
);
}
/***********************************************************************
* QUEUE_TestWakeBit
*/
WORD
QUEUE_TestWakeBit
(
MESSAGEQUEUE
*
queue
,
WORD
bit
)
{
WORD
ret
;
EnterCriticalSection
(
&
queue
->
cSection
);
ret
=
queue
->
wakeBits
&
bit
;
LeaveCriticalSection
(
&
queue
->
cSection
);
return
ret
;
QUEUE_SetWakeBit
(
queue
,
0
,
bit
);
}
/***********************************************************************
* QUEUE_WaitBits
*
...
...
@@ -708,38 +586,44 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
for
(;;)
{
unsigned
int
wake_bits
=
0
,
changed_bits
=
0
;
DWORD
dwlc
;
EnterCriticalSection
(
&
queue
->
cSection
);
SERVER_START_REQ
(
set_queue_mask
)
{
req
->
wake_mask
=
QS_SENDMESSAGE
;
req
->
changed_mask
=
bits
|
QS_SENDMESSAGE
;
req
->
skip_wait
=
1
;
if
(
!
SERVER_CALL
())
{
wake_bits
=
req
->
wake_bits
;
changed_bits
=
req
->
changed_bits
;
}
}
SERVER_END_REQ
;
if
(
queue
->
changeB
its
&
bits
)
if
(
changed_b
its
&
bits
)
{
/* One of the bits is set; we can return */
queue
->
wakeMask
=
0
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
return
1
;
}
if
(
queue
->
wakeB
its
&
QS_SENDMESSAGE
)
if
(
wake_b
its
&
QS_SENDMESSAGE
)
{
/* Process the sent message immediately */
queue
->
wakeMask
=
0
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_ReceiveMessage
(
queue
);
continue
;
/* nested sm crux */
QMSG
msg
;
QUEUE_FindMsg
(
0
,
0
,
0
,
TRUE
,
TRUE
,
&
msg
);
continue
;
/* nested sm crux */
}
queue
->
wakeMask
=
bits
|
QS_SENDMESSAGE
;
TRACE_
(
msg
)(
"%04x: wakeMask is %04x, waiting
\n
"
,
queue
->
self
,
queue
->
wakeMask
);
LeaveCriticalSection
(
&
queue
->
cSection
);
TRACE_
(
msg
)(
"(%04x) mask=%08x, bits=%08x, changed=%08x, waiting
\n
"
,
queue
->
self
,
bits
,
wake_bits
,
changed_bits
);
ReleaseThunkLock
(
&
dwlc
);
if
(
dwlc
)
TRACE_
(
msg
)(
"had win16 lock
\n
"
);
if
(
USER_Driver
.
pMsgWaitForMultipleObjects
)
USER_Driver
.
pMsgWaitForMultipleObjects
(
1
,
&
queue
->
server_queue
,
FALSE
,
timeout
);
if
(
USER_Driver
.
pMsgWaitForMultipleObjects
Ex
)
USER_Driver
.
pMsgWaitForMultipleObjects
Ex
(
1
,
&
queue
->
server_queue
,
timeout
,
0
,
0
);
else
WaitForSingleObject
(
queue
->
server_queue
,
timeout
);
if
(
dwlc
)
RestoreThunkLock
(
dwlc
);
...
...
@@ -747,323 +631,98 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
}
/***********************************************************************
* QUEUE_AddSMSG
*
* This routine is called when a SMSG need to be added to one of the three
* SM list. (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST)
*/
BOOL
QUEUE_AddSMSG
(
MESSAGEQUEUE
*
queue
,
int
list
,
SMSG
*
smsg
)
/* handle the reception of a sent message by calling the corresponding window proc */
static
void
handle_sent_message
(
QMSG
*
msg
)
{
TRACE_
(
sendmsg
)(
"queue=%x, list=%d, smsg=%p msg=%s
\n
"
,
queue
->
self
,
list
,
smsg
,
SPY_GetMsgName
(
smsg
->
msg
));
switch
(
list
)
{
case
SM_PROCESSING_LIST
:
/* don't need to be thread safe, only accessed by the
thread associated with the sender queue */
smsg
->
nextProcessing
=
queue
->
smProcessing
;
queue
->
smProcessing
=
smsg
;
break
;
case
SM_WAITING_LIST
:
/* don't need to be thread safe, only accessed by the
thread associated with the receiver queue */
smsg
->
nextWaiting
=
queue
->
smWaiting
;
queue
->
smWaiting
=
smsg
;
break
;
case
SM_PENDING_LIST
:
{
/* make it thread safe, could be accessed by the sender and
receiver thread */
SMSG
**
prev
;
EnterCriticalSection
(
&
queue
->
cSection
);
smsg
->
nextPending
=
NULL
;
prev
=
&
queue
->
smPending
;
while
(
*
prev
)
prev
=
&
(
*
prev
)
->
nextPending
;
*
prev
=
smsg
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_SetWakeBit
(
queue
,
QS_SENDMESSAGE
);
break
;
}
LRESULT
result
=
0
;
MESSAGEQUEUE
*
queue
=
QUEUE_Lock
(
GetFastQueue16
()
);
DWORD
extraInfo
=
queue
->
GetMessageExtraInfoVal
;
/* save ExtraInfo */
WND
*
wndPtr
=
WIN_FindWndPtr
(
msg
->
msg
.
hwnd
);
default:
ERR_
(
sendmsg
)(
"Invalid list: %d"
,
list
);
break
;
}
return
TRUE
;
}
TRACE
(
"got hwnd %x msg %x (%s) wp %x lp %lx
\n
"
,
msg
->
msg
.
hwnd
,
msg
->
msg
.
message
,
SPY_GetMsgName
(
msg
->
msg
.
message
),
msg
->
msg
.
wParam
,
msg
->
msg
.
lParam
);
queue
->
GetMessageExtraInfoVal
=
msg
->
extraInfo
;
/***********************************************************************
* QUEUE_RemoveSMSG
*
* This routine is called when a SMSG needs to be removed from one of the three
* SM lists (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST).
* If smsg == 0, remove the first smsg from the specified list
*/
SMSG
*
QUEUE_RemoveSMSG
(
MESSAGEQUEUE
*
queue
,
int
list
,
SMSG
*
smsg
)
{
switch
(
list
)
/* call the right version of CallWindowProcXX */
switch
(
msg
->
type
)
{
case
SM_PROCESSING_LIST
:
/* don't need to be thread safe, only accessed by the
thread associated with the sender queue */
/* if smsg is equal to null, it means the first in the list */
if
(
!
smsg
)
smsg
=
queue
->
smProcessing
;
TRACE_
(
sendmsg
)(
"queue=%x, list=%d, smsg=%p msg=%s
\n
"
,
queue
->
self
,
list
,
smsg
,
SPY_GetMsgName
(
smsg
->
msg
));
/* In fact SM_PROCESSING_LIST is a stack, and smsg
should be always at the top of the list */
if
(
(
smsg
!=
queue
->
smProcessing
)
||
!
queue
->
smProcessing
)
{
ERR_
(
sendmsg
)(
"smsg not at the top of Processing list, smsg=0x%p queue=0x%p
\n
"
,
smsg
,
queue
);
return
0
;
}
else
{
queue
->
smProcessing
=
smsg
->
nextProcessing
;
smsg
->
nextProcessing
=
0
;
}
return
smsg
;
case
SM_WAITING_LIST
:
/* don't need to be thread safe, only accessed by the
thread associated with the receiver queue */
/* if smsg is equal to null, it means the first in the list */
if
(
!
smsg
)
smsg
=
queue
->
smWaiting
;
TRACE_
(
sendmsg
)(
"queue=%x, list=%d, smsg=%p msg=%s
\n
"
,
queue
->
self
,
list
,
smsg
,
SPY_GetMsgName
(
smsg
->
msg
));
/* In fact SM_WAITING_LIST is a stack, and smsg
should be always at the top of the list */
if
(
(
smsg
!=
queue
->
smWaiting
)
||
!
queue
->
smWaiting
)
{
ERR_
(
sendmsg
)(
"smsg not at the top of Waiting list, smsg=0x%p queue=0x%p
\n
"
,
smsg
,
queue
);
return
0
;
}
else
{
queue
->
smWaiting
=
smsg
->
nextWaiting
;
smsg
->
nextWaiting
=
0
;
}
return
smsg
;
case
SM_PENDING_LIST
:
/* make it thread safe, could be accessed by the sender and
receiver thread */
EnterCriticalSection
(
&
queue
->
cSection
);
if
(
!
smsg
)
smsg
=
queue
->
smPending
;
if
(
(
smsg
!=
queue
->
smPending
)
||
!
queue
->
smPending
)
{
ERR_
(
sendmsg
)(
"should always remove the top one in Pending list, smsg=0x%p queue=0x%p
\n
"
,
smsg
,
queue
);
LeaveCriticalSection
(
&
queue
->
cSection
);
return
0
;
}
TRACE_
(
sendmsg
)(
"queue=%x, list=%d, smsg=%p msg=%s
\n
"
,
queue
->
self
,
list
,
smsg
,
SPY_GetMsgName
(
smsg
->
msg
));
queue
->
smPending
=
smsg
->
nextPending
;
smsg
->
nextPending
=
0
;
/* if no more SMSG in Pending list, clear QS_SENDMESSAGE flag */
if
(
!
queue
->
smPending
)
QUEUE_ClearWakeBit
(
queue
,
QS_SENDMESSAGE
);
LeaveCriticalSection
(
&
queue
->
cSection
);
return
smsg
;
default:
ERR_
(
sendmsg
)(
"Invalid list: %d
\n
"
,
list
);
break
;
}
return
0
;
}
/***********************************************************************
* QUEUE_ReceiveMessage
*
* This routine is called to check whether a sent message is waiting
* for the queue. If so, it is received and processed.
*/
BOOL
QUEUE_ReceiveMessage
(
MESSAGEQUEUE
*
queue
)
{
LRESULT
result
=
0
;
SMSG
*
smsg
;
MESSAGEQUEUE
*
senderQ
;
EnterCriticalSection
(
&
queue
->
cSection
);
if
(
!
((
queue
->
wakeBits
&
QS_SENDMESSAGE
)
&&
queue
->
smPending
)
)
{
LeaveCriticalSection
(
&
queue
->
cSection
);
return
FALSE
;
case
QMSG_WIN16
:
result
=
CallWindowProc16
(
(
WNDPROC16
)
wndPtr
->
winproc
,
(
HWND16
)
msg
->
msg
.
hwnd
,
(
UINT16
)
msg
->
msg
.
message
,
LOWORD
(
msg
->
msg
.
wParam
),
msg
->
msg
.
lParam
);
break
;
case
QMSG_WIN32A
:
result
=
CallWindowProcA
(
wndPtr
->
winproc
,
msg
->
msg
.
hwnd
,
msg
->
msg
.
message
,
msg
->
msg
.
wParam
,
msg
->
msg
.
lParam
);
break
;
case
QMSG_WIN32W
:
result
=
CallWindowProcW
(
wndPtr
->
winproc
,
msg
->
msg
.
hwnd
,
msg
->
msg
.
message
,
msg
->
msg
.
wParam
,
msg
->
msg
.
lParam
);
break
;
}
LeaveCriticalSection
(
&
queue
->
cSection
);
TRACE_
(
sendmsg
)(
"queue %04x
\n
"
,
queue
->
self
);
/* remove smsg on the top of the pending list and put it in the processing list */
smsg
=
QUEUE_RemoveSMSG
(
queue
,
SM_PENDING_LIST
,
0
);
QUEUE_AddSMSG
(
queue
,
SM_WAITING_LIST
,
smsg
);
TRACE_
(
sendmsg
)(
"RM: %s [%04x] (%04x -> %04x)
\n
"
,
SPY_GetMsgName
(
smsg
->
msg
),
smsg
->
msg
,
smsg
->
hSrcQueue
,
smsg
->
hDstQueue
);
if
(
IsWindow
(
smsg
->
hWnd
))
{
WND
*
wndPtr
=
WIN_FindWndPtr
(
smsg
->
hWnd
);
DWORD
extraInfo
=
queue
->
GetMessageExtraInfoVal
;
/* save ExtraInfo */
/* use sender queue extra info value while calling the window proc */
senderQ
=
QUEUE_Lock
(
smsg
->
hSrcQueue
);
if
(
senderQ
)
{
queue
->
GetMessageExtraInfoVal
=
senderQ
->
GetMessageExtraInfoVal
;
QUEUE_Unlock
(
senderQ
);
}
/* call the right version of CallWindowProcXX */
if
(
smsg
->
flags
&
SMSG_WIN32
)
{
TRACE_
(
sendmsg
)(
"
\t
rcm: msg is Win32
\n
"
);
if
(
smsg
->
flags
&
SMSG_UNICODE
)
result
=
CallWindowProcW
(
wndPtr
->
winproc
,
smsg
->
hWnd
,
smsg
->
msg
,
smsg
->
wParam
,
smsg
->
lParam
);
else
result
=
CallWindowProcA
(
wndPtr
->
winproc
,
smsg
->
hWnd
,
smsg
->
msg
,
smsg
->
wParam
,
smsg
->
lParam
);
}
else
/* Win16 message */
result
=
CallWindowProc16
(
(
WNDPROC16
)
wndPtr
->
winproc
,
(
HWND16
)
smsg
->
hWnd
,
(
UINT16
)
smsg
->
msg
,
LOWORD
(
smsg
->
wParam
),
smsg
->
lParam
);
queue
->
GetMessageExtraInfoVal
=
extraInfo
;
/* Restore extra info */
WIN_ReleaseWndPtr
(
wndPtr
);
TRACE_
(
sendmsg
)(
"result = %08x
\n
"
,
(
unsigned
)
result
);
}
else
WARN_
(
sendmsg
)(
"
\t
rcm: bad hWnd
\n
"
);
/* set SMSG_SENDING_REPLY flag to tell ReplyMessage16, it's not
an early reply */
smsg
->
flags
|=
SMSG_SENDING_REPLY
;
ReplyMessage
(
result
);
TRACE_
(
sendmsg
)(
"done!
\n
"
);
return
TRUE
;
}
queue
->
GetMessageExtraInfoVal
=
extraInfo
;
/* Restore extra info */
WIN_ReleaseWndPtr
(
wndPtr
);
QUEUE_Unlock
(
queue
);
/***********************************************************************
* QUEUE_AddMsg
*
* Add a message to the queue. Return FALSE if queue is full.
*/
BOOL
QUEUE_AddMsg
(
HQUEUE16
hQueue
,
int
type
,
MSG
*
msg
,
DWORD
extraInfo
)
{
MESSAGEQUEUE
*
msgQueue
;
QMSG
*
qmsg
;
if
(
!
(
msgQueue
=
QUEUE_Lock
(
hQueue
)))
return
FALSE
;
/* allocate new message in global heap for now */
if
(
!
(
qmsg
=
(
QMSG
*
)
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
QMSG
)
)
))
SERVER_START_REQ
(
reply_message
)
{
QUEUE_Unlock
(
msgQueue
);
return
0
;
req
->
result
=
result
;
req
->
remove
=
1
;
SERVER_CALL
();
}
EnterCriticalSection
(
&
msgQueue
->
cSection
);
/* Store message */
qmsg
->
type
=
type
;
qmsg
->
msg
=
*
msg
;
qmsg
->
extraInfo
=
extraInfo
;
/* insert the message in the link list */
qmsg
->
nextMsg
=
0
;
qmsg
->
prevMsg
=
msgQueue
->
lastMsg
;
if
(
msgQueue
->
lastMsg
)
msgQueue
->
lastMsg
->
nextMsg
=
qmsg
;
/* update first and last anchor in message queue */
msgQueue
->
lastMsg
=
qmsg
;
if
(
!
msgQueue
->
firstMsg
)
msgQueue
->
firstMsg
=
qmsg
;
msgQueue
->
msgCount
++
;
LeaveCriticalSection
(
&
msgQueue
->
cSection
);
QUEUE_SetWakeBit
(
msgQueue
,
QS_POSTMESSAGE
);
QUEUE_Unlock
(
msgQueue
);
return
TRUE
;
SERVER_END_REQ
;
}
/***********************************************************************
* QUEUE_FindMsg
*
* Find a message matching the given parameters. Return -1 if none available.
*/
QMSG
*
QUEUE_FindMsg
(
MESSAGEQUEUE
*
msgQueue
,
HWND
hwnd
,
int
first
,
int
last
)
BOOL
QUEUE_FindMsg
(
HWND
hwnd
,
UINT
first
,
UINT
last
,
BOOL
remove
,
BOOL
sent_only
,
QMSG
*
msg
)
{
QMSG
*
qmsg
;
BOOL
ret
=
FALSE
,
sent
=
FALSE
;
EnterCriticalSection
(
&
msgQueue
->
cSection
)
;
if
(
!
first
&&
!
last
)
last
=
~
0
;
if
(
!
msgQueue
->
msgCount
)
qmsg
=
0
;
else
if
(
!
hwnd
&&
!
first
&&
!
last
)
qmsg
=
msgQueue
->
firstMsg
;
else
for
(;;)
{
/* look in linked list for message matching first and last criteria */
for
(
qmsg
=
msgQueue
->
firstMsg
;
qmsg
;
qmsg
=
qmsg
->
nextMsg
)
SERVER_START_REQ
(
get_message
)
{
MSG
*
msg
=
&
(
qmsg
->
msg
);
if
(
!
hwnd
||
(
msg
->
hwnd
==
hwnd
))
req
->
remove
=
remove
;
req
->
posted
=
!
sent_only
;
req
->
get_win
=
hwnd
;
req
->
get_first
=
first
;
req
->
get_last
=
last
;
if
((
ret
=
!
SERVER_CALL
()))
{
if
(
!
first
&&
!
last
)
break
;
/* found it */
if
((
msg
->
message
>=
first
)
&&
(
!
last
||
(
msg
->
message
<=
last
)))
break
;
/* found it */
sent
=
req
->
sent
;
msg
->
type
=
req
->
type
;
msg
->
msg
.
hwnd
=
req
->
win
;
msg
->
msg
.
message
=
req
->
msg
;
msg
->
msg
.
wParam
=
req
->
wparam
;
msg
->
msg
.
lParam
=
req
->
lparam
;
msg
->
msg
.
time
=
0
;
/* FIXME */
msg
->
msg
.
pt
.
x
=
0
;
/* FIXME */
msg
->
msg
.
pt
.
y
=
0
;
/* FIXME */
msg
->
extraInfo
=
req
->
info
;
}
}
}
SERVER_END_REQ
;
if
(
!
ret
||
!
sent
)
break
;
handle_sent_message
(
msg
);
}
LeaveCriticalSection
(
&
msgQueue
->
cSection
);
return
qmsg
;
if
(
ret
)
TRACE
(
"got hwnd %x msg %x (%s) wp %x lp %lx
\n
"
,
msg
->
msg
.
hwnd
,
msg
->
msg
.
message
,
SPY_GetMsgName
(
msg
->
msg
.
message
),
msg
->
msg
.
wParam
,
msg
->
msg
.
lParam
);
return
ret
;
}
...
...
@@ -1092,82 +751,25 @@ void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg )
/* deallocate the memory for the message */
HeapFree
(
GetProcessHeap
(),
0
,
qmsg
);
msgQueue
->
msgCount
--
;
if
(
!
msgQueue
->
msgCount
)
msgQueue
->
wakeBits
&=
~
QS_POSTMESSAGE
;
LeaveCriticalSection
(
&
msgQueue
->
cSection
);
}
#if 0
/***********************************************************************
* QUEUE_
WakeSomeone
* QUEUE_
CleanupWindow
*
*
Wake a queue upon reception of a hardware event
.
*
Cleanup the queue to account for a window being deleted
.
*/
static void QUEUE_WakeSomeone( UINT message
)
void
QUEUE_CleanupWindow
(
HWND
hwnd
)
{
WND* wndPtr = NULL;
WORD wakeBit;
HWND hwnd;
HQUEUE16 hQueue = 0;
MESSAGEQUEUE *queue = NULL;
if (hCursorQueue)
hQueue = hCursorQueue;
if( (message >= WM_KEYFIRST) && (message <= WM_KEYLAST) )
{
wakeBit = QS_KEY;
if( hActiveQueue )
hQueue = hActiveQueue;
}
else
{
wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
if( (hwnd = GetCapture()) )
if( (wndPtr = WIN_FindWndPtr( hwnd )) )
{
hQueue = wndPtr->hmemTaskQ;
WIN_ReleaseWndPtr(wndPtr);
}
}
if( (hwnd = GetSysModalWindow16()) )
{
if( (wndPtr = WIN_FindWndPtr( hwnd )) )
{
hQueue = wndPtr->hmemTaskQ;
WIN_ReleaseWndPtr(wndPtr);
}
}
if (hQueue)
{
queue = QUEUE_Lock( hQueue );
QUEUE_SetWakeBit( queue, wakeBit );
QUEUE_Unlock( queue );
return;
}
/* Search for someone to wake */
hQueue = hFirstQueue;
while ( (queue = QUEUE_Lock( hQueue )) )
SERVER_START_REQ
(
cleanup_window_queue
)
{
if (QUEUE_TrySetWakeBit( queue, wakeBit, FALSE ))
{
QUEUE_Unlock( queue );
return;
}
hQueue = queue->next;
QUEUE_Unlock( queue );
req
->
win
=
hwnd
;
SERVER_CALL
();
}
WARN_(msg)("couldn't find queue\n");
SERVER_END_REQ
;
}
#endif
/***********************************************************************
...
...
@@ -1227,8 +829,6 @@ void hardware_event( UINT message, WPARAM wParam, LPARAM lParam,
sysMsgQueue
->
lastMsg
=
qmsg
;
if
(
!
sysMsgQueue
->
firstMsg
)
sysMsgQueue
->
firstMsg
=
qmsg
;
sysMsgQueue
->
msgCount
++
;
}
/* Store message */
...
...
@@ -1252,7 +852,7 @@ void hardware_event( UINT message, WPARAM wParam, LPARAM lParam,
if
((
message
>=
WM_KEYFIRST
)
&&
(
message
<=
WM_KEYLAST
))
wakeBit
=
QS_KEY
;
else
wakeBit
=
(
message
==
WM_MOUSEMOVE
)
?
QS_MOUSEMOVE
:
QS_MOUSEBUTTON
;
QUEUE_SetWakeBit
(
queue
,
wakeBit
);
QUEUE_SetWakeBit
(
queue
,
wakeBit
,
0
);
QUEUE_Unlock
(
queue
);
}
}
...
...
@@ -1289,7 +889,7 @@ void QUEUE_IncPaintCount( HQUEUE16 hQueue )
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
wPaintCount
++
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_SetWakeBit
(
queue
,
QS_PAINT
);
QUEUE_SetWakeBit
(
queue
,
QS_PAINT
,
0
);
QUEUE_Unlock
(
queue
);
}
...
...
@@ -1304,39 +904,7 @@ void QUEUE_DecPaintCount( HQUEUE16 hQueue )
if
(
!
(
queue
=
QUEUE_Lock
(
hQueue
)))
return
;
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
wPaintCount
--
;
if
(
!
queue
->
wPaintCount
)
queue
->
wakeBits
&=
~
QS_PAINT
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
}
/***********************************************************************
* QUEUE_IncTimerCount
*/
void
QUEUE_IncTimerCount
(
HQUEUE16
hQueue
)
{
MESSAGEQUEUE
*
queue
;
if
(
!
(
queue
=
QUEUE_Lock
(
hQueue
)))
return
;
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
wTimerCount
++
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_SetWakeBit
(
queue
,
QS_TIMER
);
QUEUE_Unlock
(
queue
);
}
/***********************************************************************
* QUEUE_DecTimerCount
*/
void
QUEUE_DecTimerCount
(
HQUEUE16
hQueue
)
{
MESSAGEQUEUE
*
queue
;
if
(
!
(
queue
=
QUEUE_Lock
(
hQueue
)))
return
;
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
wTimerCount
--
;
if
(
!
queue
->
wTimerCount
)
queue
->
wakeBits
&=
~
QS_TIMER
;
if
(
!
queue
->
wPaintCount
)
QUEUE_ClearWakeBit
(
queue
,
QS_PAINT
);
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
}
...
...
@@ -1367,14 +935,7 @@ void WINAPI PostQuitMessage16( INT16 exitCode )
*/
void
WINAPI
PostQuitMessage
(
INT
exitCode
)
{
MESSAGEQUEUE
*
queue
;
if
(
!
(
queue
=
QUEUE_Lock
(
GetFastQueue16
()
)))
return
;
EnterCriticalSection
(
&
queue
->
cSection
);
queue
->
wPostQMsg
=
TRUE
;
queue
->
wExitCode
=
(
WORD
)
exitCode
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
PostThreadMessageW
(
GetCurrentThreadId
(),
WM_QUIT
,
exitCode
,
0
);
}
...
...
@@ -1470,9 +1031,6 @@ HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
HeapLock
(
GetProcessHeap
()
);
/* FIXME: a bit overkill */
SetThreadQueue16
(
0
,
hQueue
);
teb
->
queue
=
hQueue
;
queuePtr
->
next
=
hFirstQueue
;
hFirstQueue
=
hQueue
;
HeapUnlock
(
GetProcessHeap
()
);
QUEUE_Unlock
(
queuePtr
);
...
...
@@ -1486,17 +1044,7 @@ HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
*/
DWORD
WINAPI
GetQueueStatus16
(
UINT16
flags
)
{
MESSAGEQUEUE
*
queue
;
DWORD
ret
;
if
(
!
(
queue
=
QUEUE_Lock
(
GetFastQueue16
()
)))
return
0
;
EnterCriticalSection
(
&
queue
->
cSection
);
ret
=
MAKELONG
(
queue
->
changeBits
,
queue
->
wakeBits
);
queue
->
changeBits
=
0
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
return
ret
&
MAKELONG
(
flags
,
flags
);
return
GetQueueStatus
(
flags
);
}
/***********************************************************************
...
...
@@ -1504,17 +1052,16 @@ DWORD WINAPI GetQueueStatus16( UINT16 flags )
*/
DWORD
WINAPI
GetQueueStatus
(
UINT
flags
)
{
MESSAGEQUEUE
*
queue
;
DWORD
ret
;
DWORD
ret
=
0
;
if
(
!
(
queue
=
QUEUE_Lock
(
GetFastQueue16
()
)))
return
0
;
EnterCriticalSection
(
&
queue
->
cSection
);
ret
=
MAKELONG
(
queue
->
changeBits
,
queue
->
wakeBits
)
;
queue
->
changeBits
=
0
;
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
return
ret
&
MAKELONG
(
flags
,
flags
)
;
SERVER_START_REQ
(
get_queue_status
)
{
req
->
clear
=
1
;
SERVER_CALL
()
;
ret
=
MAKELONG
(
req
->
changed_bits
&
flags
,
req
->
wake_bits
&
flags
);
}
SERVER_END_REQ
;
return
ret
;
}
...
...
@@ -1527,6 +1074,23 @@ BOOL16 WINAPI GetInputState16(void)
}
/***********************************************************************
* GetInputState (USER32.@)
*/
BOOL
WINAPI
GetInputState
(
void
)
{
DWORD
ret
=
0
;
SERVER_START_REQ
(
get_queue_status
)
{
req
->
clear
=
0
;
SERVER_CALL
();
ret
=
req
->
wake_bits
&
(
QS_KEY
|
QS_MOUSEBUTTON
);
}
SERVER_END_REQ
;
return
ret
;
}
/***********************************************************************
* WaitForInputIdle (USER32.@)
*/
DWORD
WINAPI
WaitForInputIdle
(
HANDLE
hProcess
,
DWORD
dwTimeOut
)
...
...
@@ -1552,10 +1116,8 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
ret
=
MsgWaitForMultipleObjects
(
1
,
&
idle_event
,
FALSE
,
dwTimeOut
,
QS_SENDMESSAGE
);
if
(
ret
==
(
WAIT_OBJECT_0
+
1
))
{
MESSAGEQUEUE
*
queue
;
if
(
!
(
queue
=
QUEUE_Lock
(
GetFastQueue16
()
)))
return
0xFFFFFFFF
;
QUEUE_ReceiveMessage
(
queue
);
QUEUE_Unlock
(
queue
);
QMSG
msg
;
QUEUE_FindMsg
(
0
,
0
,
0
,
TRUE
,
TRUE
,
&
msg
);
continue
;
}
if
(
ret
==
WAIT_TIMEOUT
||
ret
==
0xFFFFFFFF
)
...
...
@@ -1574,49 +1136,23 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
}
/***********************************************************************
* GetInputState (USER32.@)
*/
BOOL
WINAPI
GetInputState
(
void
)
{
MESSAGEQUEUE
*
queue
;
BOOL
ret
;
if
(
!
(
queue
=
QUEUE_Lock
(
GetFastQueue16
()
)))
return
FALSE
;
EnterCriticalSection
(
&
queue
->
cSection
);
ret
=
queue
->
wakeBits
&
(
QS_KEY
|
QS_MOUSEBUTTON
);
LeaveCriticalSection
(
&
queue
->
cSection
);
QUEUE_Unlock
(
queue
);
return
ret
;
}
/***********************************************************************
* UserYield (USER.332)
* UserYield16 (USER32.@)
*/
void
WINAPI
UserYield16
(
void
)
{
MESSAGEQUEUE
*
queue
;
QMSG
msg
;
/* Handle sent messages */
queue
=
QUEUE_Lock
(
GetFastQueue16
()
);
while
(
queue
&&
QUEUE_ReceiveMessage
(
queue
)
)
while
(
QUEUE_FindMsg
(
0
,
0
,
0
,
TRUE
,
TRUE
,
&
msg
))
;
QUEUE_Unlock
(
queue
);
/* Yield */
OldYield16
();
/* Handle sent messages again */
queue
=
QUEUE_Lock
(
GetFastQueue16
()
);
while
(
queue
&&
QUEUE_ReceiveMessage
(
queue
)
)
while
(
QUEUE_FindMsg
(
0
,
0
,
0
,
TRUE
,
TRUE
,
&
msg
))
;
QUEUE_Unlock
(
queue
);
}
/***********************************************************************
...
...
windows/timer.c
View file @
51ab43bd
...
...
@@ -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 5
4925
#define SYS_TIMER_RATE 5
5
/* min. timer rate in ms (actually 54.925)*/
static
TIMER
TimersArray
[
NB_TIMERS
];
...
...
@@ -46,18 +46,6 @@ static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT;
*/
static
void
TIMER_ClearTimer
(
TIMER
*
pTimer
)
{
if
(
pTimer
->
hService
!=
INVALID_HANDLE_VALUE
)
{
SERVICE_Delete
(
pTimer
->
hService
);
pTimer
->
hService
=
INVALID_HANDLE_VALUE
;
}
if
(
pTimer
->
expired
)
{
QUEUE_DecTimerCount
(
pTimer
->
hq
);
pTimer
->
expired
=
FALSE
;
}
pTimer
->
hwnd
=
0
;
pTimer
->
msg
=
0
;
pTimer
->
id
=
0
;
...
...
@@ -81,7 +69,7 @@ void TIMER_RemoveWindowTimers( HWND hwnd )
for
(
i
=
NB_TIMERS
,
pTimer
=
TimersArray
;
i
>
0
;
i
--
,
pTimer
++
)
if
((
pTimer
->
hwnd
==
hwnd
)
&&
pTimer
->
timeout
)
TIMER_ClearTimer
(
pTimer
);
LeaveCriticalSection
(
&
csTimer
);
}
...
...
@@ -107,85 +95,6 @@ void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
/***********************************************************************
* TIMER_CheckTimer
*/
static
void
CALLBACK
TIMER_CheckTimer
(
ULONG_PTR
timer_ptr
)
{
TIMER
*
pTimer
=
(
TIMER
*
)
timer_ptr
;
HQUEUE16
wakeQueue
=
0
;
EnterCriticalSection
(
&
csTimer
);
/* Paranoid check to prevent a race condition ... */
if
(
!
pTimer
->
timeout
)
{
LeaveCriticalSection
(
&
csTimer
);
return
;
}
if
(
!
pTimer
->
expired
)
{
TRACE
(
"Timer expired: %04x, %04x, %04x, %08lx
\n
"
,
pTimer
->
hwnd
,
pTimer
->
msg
,
pTimer
->
id
,
(
DWORD
)
pTimer
->
proc
);
pTimer
->
expired
=
TRUE
;
wakeQueue
=
pTimer
->
hq
;
}
LeaveCriticalSection
(
&
csTimer
);
/* Note: This has to be done outside the csTimer critical section,
otherwise we'll get deadlocks. */
if
(
wakeQueue
)
QUEUE_IncTimerCount
(
wakeQueue
);
}
/***********************************************************************
* TIMER_GetTimerMsg
*
* Build a message for an expired timer.
*/
BOOL
TIMER_GetTimerMsg
(
MSG
*
msg
,
HWND
hwnd
,
HQUEUE16
hQueue
,
BOOL
remove
)
{
TIMER
*
pTimer
;
int
i
;
EnterCriticalSection
(
&
csTimer
);
for
(
i
=
0
,
pTimer
=
TimersArray
;
i
<
NB_TIMERS
;
i
++
,
pTimer
++
)
if
(
pTimer
->
timeout
!=
0
&&
pTimer
->
expired
&&
(
hwnd
?
(
pTimer
->
hwnd
==
hwnd
)
:
(
pTimer
->
hq
==
hQueue
))
)
break
;
if
(
i
==
NB_TIMERS
)
{
LeaveCriticalSection
(
&
csTimer
);
return
FALSE
;
/* No timer */
}
TRACE
(
"Timer got message: %04x, %04x, %04x, %08lx
\n
"
,
pTimer
->
hwnd
,
pTimer
->
msg
,
pTimer
->
id
,
(
DWORD
)
pTimer
->
proc
);
if
(
remove
)
pTimer
->
expired
=
FALSE
;
/* Build the message */
msg
->
hwnd
=
pTimer
->
hwnd
;
msg
->
message
=
pTimer
->
msg
;
msg
->
wParam
=
pTimer
->
id
;
msg
->
lParam
=
(
LONG
)
pTimer
->
proc
;
msg
->
time
=
GetTickCount
();
LeaveCriticalSection
(
&
csTimer
);
return
TRUE
;
}
/***********************************************************************
* TIMER_SetTimer
*/
static
UINT
TIMER_SetTimer
(
HWND
hwnd
,
UINT
id
,
UINT
timeout
,
...
...
@@ -193,12 +102,20 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
{
int
i
;
TIMER
*
pTimer
;
HWINDOWPROC
winproc
=
0
;
if
(
GetWindowThreadProcessId
(
hwnd
,
NULL
)
!=
GetCurrentThreadId
())
{
SetLastError
(
ERROR_INVALID_WINDOW_HANDLE
);
return
0
;
}
if
(
!
timeout
)
{
/* timeout==0 is a legal argument UB 990821*/
WARN
(
"Timeout== 0 not implemented, using timeout=1
\n
"
);
timeout
=
1
;
}
EnterCriticalSection
(
&
csTimer
);
/* Check if there's already a timer with the same hwnd and id */
...
...
@@ -228,21 +145,28 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
if
(
!
hwnd
)
id
=
i
+
1
;
if
(
proc
)
WINPROC_SetProc
(
&
winproc
,
proc
,
type
,
WIN_PROC_TIMER
);
SERVER_START_REQ
(
set_win_timer
)
{
req
->
win
=
hwnd
;
req
->
msg
=
sys
?
WM_SYSTIMER
:
WM_TIMER
;
req
->
id
=
id
;
req
->
rate
=
max
(
timeout
,
SYS_TIMER_RATE
);
req
->
lparam
=
(
unsigned
int
)
winproc
;
SERVER_CALL
();
}
SERVER_END_REQ
;
/* Add the timer */
pTimer
->
hwnd
=
hwnd
;
pTimer
->
hq
=
(
hwnd
)
?
GetThreadQueue16
(
GetWindowThreadProcessId
(
hwnd
,
NULL
)
)
:
GetFastQueue16
(
);
pTimer
->
hq
=
GetFastQueue16
();
pTimer
->
msg
=
sys
?
WM_SYSTIMER
:
WM_TIMER
;
pTimer
->
id
=
id
;
pTimer
->
timeout
=
timeout
;
pTimer
->
proc
=
(
HWINDOWPROC
)
0
;
if
(
proc
)
WINPROC_SetProc
(
&
pTimer
->
proc
,
proc
,
type
,
WIN_PROC_TIMER
);
pTimer
->
proc
=
winproc
;
pTimer
->
expired
=
FALSE
;
pTimer
->
hService
=
SERVICE_AddTimer
(
max
(
timeout
,
(
SYS_TIMER_RATE
+
500
)
/
1000
),
TIMER_CheckTimer
,
(
ULONG_PTR
)
pTimer
);
TRACE
(
"Timer added: %p, %04x, %04x, %04x, %08lx
\n
"
,
pTimer
,
pTimer
->
hwnd
,
pTimer
->
msg
,
pTimer
->
id
,
(
DWORD
)
pTimer
->
proc
);
...
...
@@ -262,6 +186,15 @@ static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
int
i
;
TIMER
*
pTimer
;
SERVER_START_REQ
(
kill_win_timer
)
{
req
->
win
=
hwnd
;
req
->
msg
=
sys
?
WM_SYSTIMER
:
WM_TIMER
;
req
->
id
=
id
;
SERVER_CALL
();
}
SERVER_END_REQ
;
EnterCriticalSection
(
&
csTimer
);
/* Find the timer */
...
...
windows/win.c
View file @
51ab43bd
...
...
@@ -458,29 +458,8 @@ static WND* WIN_DestroyWindow( WND* wndPtr )
/* toss stale messages from the queue */
if
(
wndPtr
->
hmemTaskQ
)
{
BOOL
bPostQuit
=
FALSE
;
WPARAM
wQuitParam
=
0
;
MESSAGEQUEUE
*
msgQ
=
(
MESSAGEQUEUE
*
)
QUEUE_Lock
(
wndPtr
->
hmemTaskQ
);
QMSG
*
qmsg
;
while
(
(
qmsg
=
QUEUE_FindMsg
(
msgQ
,
hwnd
,
0
,
0
))
!=
0
)
{
if
(
qmsg
->
msg
.
message
==
WM_QUIT
)
{
bPostQuit
=
TRUE
;
wQuitParam
=
qmsg
->
msg
.
wParam
;
}
QUEUE_RemoveMsg
(
msgQ
,
qmsg
);
}
QUEUE_Unlock
(
msgQ
);
/* repost WM_QUIT to make sure this app exits its message loop */
if
(
bPostQuit
)
PostQuitMessage
(
wQuitParam
);
wndPtr
->
hmemTaskQ
=
0
;
}
QUEUE_CleanupWindow
(
hwnd
);
wndPtr
->
hmemTaskQ
=
0
;
if
(
!
(
wndPtr
->
dwStyle
&
WS_CHILD
))
if
(
wndPtr
->
wIDmenu
)
...
...
windows/x11drv/event.c
View file @
51ab43bd
...
...
@@ -167,17 +167,18 @@ void X11DRV_Synchronize( void )
/***********************************************************************
* MsgWaitForMultipleObjects (X11DRV.@)
* MsgWaitForMultipleObjects
Ex
(X11DRV.@)
*/
DWORD
X11DRV_MsgWaitForMultipleObjects
(
DWORD
count
,
HANDLE
*
handles
,
BOOL
wait_all
,
DWORD
timeout
)
DWORD
X11DRV_MsgWaitForMultipleObjects
Ex
(
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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment