Rewrote most of SendMessage/PeekMessage.
Implemented inter-process messaging.
Moved most message routines to dlls/user, and split off 16-bit
routines to a separate file.
diff --git a/dlls/user/Makefile.in b/dlls/user/Makefile.in
index eb6f038..5975585 100644
--- a/dlls/user/Makefile.in
+++ b/dlls/user/Makefile.in
@@ -18,8 +18,10 @@
display.c \
exticon.c \
lstr.c \
+ message.c \
misc.c \
mouse.c \
+ msg16.c \
network.c \
resource.c \
text.c \
diff --git a/dlls/user/message.c b/dlls/user/message.c
new file mode 100644
index 0000000..13ab74e
--- /dev/null
+++ b/dlls/user/message.c
@@ -0,0 +1,1814 @@
+/*
+ * Window messaging support
+ *
+ * Copyright 2001 Alexandre Julliard
+ */
+
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "winnls.h"
+#include "wine/unicode.h"
+#include "wine/server.h"
+#include "queue.h"
+#include "input.h"
+#include "message.h"
+#include "hook.h"
+#include "spy.h"
+#include "user.h"
+#include "win.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(msg);
+
+#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
+#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
+
+#define MAX_PACK_COUNT 4
+
+/* description of the data fields that need to be packed along with a sent message */
+struct packed_message
+{
+ int count;
+ const void *data[MAX_PACK_COUNT];
+ size_t size[MAX_PACK_COUNT];
+};
+
+/* info about the message currently being received by the current thread */
+struct received_message_info
+{
+ enum message_type type;
+ MSG msg;
+ UINT flags; /* InSendMessageEx return flags */
+};
+
+/* structure to group all parameters for sent messages of the various kinds */
+struct send_message_info
+{
+ enum message_type type;
+ HWND hwnd;
+ UINT msg;
+ WPARAM wparam;
+ LPARAM lparam;
+ UINT flags; /* flags for SendMessageTimeout */
+ UINT timeout; /* timeout for SendMessageTimeout */
+ SENDASYNCPROC callback; /* callback function for SendMessageCallback */
+ ULONG_PTR data; /* callback data */
+};
+
+
+
+/* flag for messages that contain pointers */
+/* 16 messages per entry, messages 0..15 map to bits 0..15 */
+
+#define SET(msg) (1 << ((msg) & 15))
+
+static const unsigned short message_pointer_flags[] =
+{
+ /* 0x00 - 0x0f */
+ SET(WM_CREATE) | SET(WM_GETTEXT) | SET(WM_SETTEXT),
+ /* 0x10 - 0x1f */
+ SET(WM_WININICHANGE),
+ /* 0x20 - 0x2f */
+ SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM),
+ /* 0x30 - 0x3f */
+ SET(WM_COMPAREITEM),
+ /* 0x40 - 0x4f */
+ SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) | SET(WM_NOTIFY),
+ /* 0x50 - 0x5f */
+ SET(WM_HELP),
+ /* 0x60 - 0x6f */
+ 0,
+ /* 0x70 - 0x7f */
+ SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED),
+ /* 0x80 - 0x8f */
+ SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE),
+ /* 0x90 - 0x9f */
+ 0,
+ /* 0xa0 - 0xaf */
+ 0,
+ /* 0xb0 - 0xbf */
+ SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP),
+ /* 0xc0 - 0xcf */
+ SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS),
+ /* 0xd0 - 0xdf */
+ 0,
+ /* 0xe0 - 0xef */
+ 0,
+ /* 0xf0 - 0xff */
+ 0,
+ /* 0x100 - 0x10f */
+ 0,
+ /* 0x110 - 0x11f */
+ 0,
+ /* 0x120 - 0x12f */
+ 0,
+ /* 0x130 - 0x13f */
+ 0,
+ /* 0x140 - 0x14f */
+ SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) | SET(CB_INSERTSTRING) |
+ SET(CB_FINDSTRING) | SET(CB_SELECTSTRING),
+ /* 0x150 - 0x15f */
+ SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT),
+ /* 0x160 - 0x16f */
+ 0,
+ /* 0x170 - 0x17f */
+ 0,
+ /* 0x180 - 0x18f */
+ SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) |
+ SET(LB_DIR) | SET(LB_FINDSTRING),
+ /* 0x190 - 0x19f */
+ SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT),
+ /* 0x1a0 - 0x1af */
+ SET(LB_FINDSTRINGEXACT),
+ /* 0x1b0 - 0x1bf */
+ 0,
+ /* 0x1c0 - 0x1cf */
+ 0,
+ /* 0x1d0 - 0x1df */
+ 0,
+ /* 0x1e0 - 0x1ef */
+ 0,
+ /* 0x1f0 - 0x1ff */
+ 0,
+ /* 0x200 - 0x20f */
+ 0,
+ /* 0x210 - 0x21f */
+ 0,
+ /* 0x220 - 0x22f */
+ SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) |
+ SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE)
+};
+
+#undef SET
+
+/* check whether a given message type includes pointers */
+inline static int is_pointer_message( UINT message )
+{
+ if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
+ return (message_pointer_flags[message / 16] & (1 << (message & 15))) != 0;
+}
+
+
+/* compute the total size of the packed data */
+inline static size_t get_data_total_size( const struct packed_message *data )
+{
+ int i;
+ size_t total = 0;
+ for (i = 0; i < data->count; i++) total += data->size[i];
+ return total;
+}
+
+/* copy all the data of a packed message into a single dest buffer */
+inline static void copy_all_data( void *dest, const struct packed_message *data )
+{
+ int i;
+ for (i = 0; i < data->count; i++)
+ {
+ memcpy( dest, data->data[i], data->size[i] );
+ dest = (char *)dest + data->size[i];
+ }
+}
+
+/* add a data field to a packed message */
+inline static void push_data( struct packed_message *data, const void *ptr, size_t size )
+{
+ data->data[data->count] = ptr;
+ data->size[data->count] = size;
+ data->count++;
+}
+
+/* add a string to a packed message */
+inline static void push_string( struct packed_message *data, LPCWSTR str )
+{
+ push_data( data, str, (strlenW(str) + 1) * sizeof(WCHAR) );
+}
+
+/* retrieve a pointer to data from a packed message and increment the buffer pointer */
+inline static void *get_data( void **buffer, size_t size )
+{
+ void *ret = *buffer;
+ *buffer = (char *)*buffer + size;
+ return ret;
+}
+
+/* make sure that the buffer contains a valid null-terminated Unicode string */
+inline static BOOL check_string( LPCWSTR str, size_t size )
+{
+ for (size /= sizeof(WCHAR); size; size--, str++)
+ if (!*str) return TRUE;
+ return FALSE;
+}
+
+/* make sure that there is space for 'size' bytes in buffer, growing it if needed */
+inline static void *get_buffer_space( void **buffer, size_t size )
+{
+ void *ret;
+ if (!(ret = HeapReAlloc( GetProcessHeap(), 0, *buffer, size )))
+ HeapFree( GetProcessHeap(), 0, *buffer );
+ *buffer = ret;
+ return ret;
+}
+
+/* retrieve a string pointer from packed data */
+inline static LPWSTR get_string( void **buffer )
+{
+ return get_data( buffer, (strlenW( (LPWSTR)*buffer ) + 1) * sizeof(WCHAR) );
+}
+
+/* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
+inline static BOOL combobox_has_strings( HWND hwnd )
+{
+ DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
+ return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
+}
+
+/* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */
+inline static BOOL listbox_has_strings( HWND hwnd )
+{
+ DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
+ return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
+}
+
+/* check if hwnd is a broadcast magic handle */
+inline static BOOL is_broadcast( HWND hwnd )
+{
+ return (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST);
+}
+
+
+/***********************************************************************
+ * broadcast_message_callback
+ *
+ * Helper callback for broadcasting messages.
+ */
+static BOOL CALLBACK broadcast_message_callback( HWND hwnd, LPARAM lparam )
+{
+ struct send_message_info *info = (struct send_message_info *)lparam;
+ if (!(GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CAPTION))) return TRUE;
+ switch(info->type)
+ {
+ case MSG_UNICODE:
+ SendMessageTimeoutW( hwnd, info->msg, info->wparam, info->lparam,
+ info->flags, info->timeout, NULL );
+ break;
+ case MSG_ASCII:
+ SendMessageTimeoutA( hwnd, info->msg, info->wparam, info->lparam,
+ info->flags, info->timeout, NULL );
+ break;
+ case MSG_NOTIFY:
+ SendNotifyMessageW( hwnd, info->msg, info->wparam, info->lparam );
+ break;
+ case MSG_CALLBACK:
+ SendMessageCallbackW( hwnd, info->msg, info->wparam, info->lparam,
+ info->callback, info->data );
+ break;
+ case MSG_POSTED:
+ PostMessageW( hwnd, info->msg, info->wparam, info->lparam );
+ break;
+ default:
+ ERR( "bad type %d\n", info->type );
+ break;
+ }
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * map_wparam_AtoW
+ *
+ * Convert the wparam of an ASCII message to Unicode.
+ */
+static WPARAM map_wparam_AtoW( UINT message, WPARAM wparam )
+{
+ if (message == WM_CHARTOITEM ||
+ message == EM_SETPASSWORDCHAR ||
+ message == WM_CHAR ||
+ message == WM_DEADCHAR ||
+ message == WM_SYSCHAR ||
+ message == WM_SYSDEADCHAR ||
+ message == WM_MENUCHAR)
+ {
+ char ch = LOWORD(wparam);
+ WCHAR wch;
+ MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
+ wparam = MAKEWPARAM( wch, HIWORD(wparam) );
+ }
+ return wparam;
+}
+
+
+/***********************************************************************
+ * map_wparam_WtoA
+ *
+ * Convert the wparam of a Unicode message to ASCII.
+ */
+static WPARAM map_wparam_WtoA( UINT message, WPARAM wparam )
+{
+ if (message == WM_CHARTOITEM ||
+ message == EM_SETPASSWORDCHAR ||
+ message == WM_CHAR ||
+ message == WM_DEADCHAR ||
+ message == WM_SYSCHAR ||
+ message == WM_SYSDEADCHAR ||
+ message == WM_MENUCHAR)
+ {
+ WCHAR wch = LOWORD(wparam);
+ char ch;
+ WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
+ wparam = MAKEWPARAM( ch, HIWORD(wparam) );
+ }
+ return wparam;
+}
+
+
+/***********************************************************************
+ * pack_message
+ *
+ * Pack a message for sending to another process.
+ * Return the size of the data we expect in the message reply.
+ * Set data->count to -1 if there is an error.
+ */
+static size_t pack_message( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
+ struct packed_message *data )
+{
+ data->count = 0;
+ switch(message)
+ {
+ case WM_NCCREATE:
+ case WM_CREATE:
+ {
+ CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
+ push_data( data, cs, sizeof(*cs) );
+ if (HIWORD(cs->lpszName)) push_string( data, cs->lpszName );
+ if (HIWORD(cs->lpszClass)) push_string( data, cs->lpszClass );
+ return sizeof(*cs);
+ }
+ case WM_GETTEXT:
+ return wparam * sizeof(WCHAR);
+ case WM_SETTEXT:
+ case WM_WININICHANGE:
+ case CB_DIR:
+ case CB_FINDSTRING:
+ case CB_FINDSTRINGEXACT:
+ case CB_SELECTSTRING:
+ case LB_DIR:
+ case LB_ADDFILE:
+ case LB_FINDSTRING:
+ case LB_FINDSTRINGEXACT:
+ case LB_SELECTSTRING:
+ case EM_REPLACESEL:
+ push_string( data, (LPWSTR)lparam );
+ return 0;
+ case WM_GETMINMAXINFO:
+ push_data( data, (MINMAXINFO *)lparam, sizeof(MINMAXINFO) );
+ return sizeof(MINMAXINFO);
+ case WM_DRAWITEM:
+ push_data( data, (DRAWITEMSTRUCT *)lparam, sizeof(DRAWITEMSTRUCT) );
+ return 0;
+ case WM_MEASUREITEM:
+ push_data( data, (MEASUREITEMSTRUCT *)lparam, sizeof(MEASUREITEMSTRUCT) );
+ return sizeof(MEASUREITEMSTRUCT);
+ case WM_DELETEITEM:
+ push_data( data, (DELETEITEMSTRUCT *)lparam, sizeof(DELETEITEMSTRUCT) );
+ return 0;
+ case WM_COMPAREITEM:
+ push_data( data, (COMPAREITEMSTRUCT *)lparam, sizeof(COMPAREITEMSTRUCT) );
+ return 0;
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ push_data( data, (WINDOWPOS *)lparam, sizeof(WINDOWPOS) );
+ return sizeof(WINDOWPOS);
+ case WM_COPYDATA:
+ {
+ COPYDATASTRUCT *cp = (COPYDATASTRUCT *)lparam;
+ push_data( data, cp, sizeof(*cp) );
+ if (cp->lpData) push_data( data, cp->lpData, cp->cbData );
+ return 0;
+ }
+ case WM_NOTIFY:
+ /* WM_NOTIFY cannot be sent across processes (MSDN) */
+ data->count = -1;
+ return 0;
+ case WM_HELP:
+ push_data( data, (HELPINFO *)lparam, sizeof(HELPINFO) );
+ return 0;
+ case WM_STYLECHANGING:
+ case WM_STYLECHANGED:
+ push_data( data, (STYLESTRUCT *)lparam, sizeof(STYLESTRUCT) );
+ return 0;
+ case WM_NCCALCSIZE:
+ if (!wparam)
+ {
+ push_data( data, (RECT *)lparam, sizeof(RECT) );
+ return sizeof(RECT);
+ }
+ else
+ {
+ NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lparam;
+ push_data( data, nc, sizeof(*nc) );
+ push_data( data, nc->lppos, sizeof(*nc->lppos) );
+ return sizeof(*nc) + sizeof(*nc->lppos);
+ }
+ case WM_GETDLGCODE:
+ if (lparam) push_data( data, (MSG *)lparam, sizeof(MSG) );
+ return sizeof(MSG);
+ case EM_GETSEL:
+ {
+ size_t size = 0;
+ if (wparam) size += sizeof(DWORD);
+ if (lparam) size += sizeof(DWORD);
+ return size;
+ }
+ case EM_GETRECT:
+ case LB_GETITEMRECT:
+ case CB_GETDROPPEDCONTROLRECT:
+ return sizeof(RECT);
+ case EM_SETRECT:
+ case EM_SETRECTNP:
+ push_data( data, (RECT *)lparam, sizeof(RECT) );
+ return 0;
+ case EM_GETLINE:
+ {
+ WORD *pw = (WORD *)lparam;
+ push_data( data, pw, sizeof(*pw) );
+ return *pw * sizeof(WCHAR);
+ }
+ case EM_SETTABSTOPS:
+ case LB_SETTABSTOPS:
+ if (wparam) push_data( data, (UINT *)lparam, sizeof(UINT) * wparam );
+ return 0;
+ case CB_ADDSTRING:
+ case CB_INSERTSTRING:
+ if (combobox_has_strings( hwnd )) push_string( data, (LPWSTR)lparam );
+ return 0;
+ case CB_GETLBTEXT:
+ if (!combobox_has_strings( hwnd )) return sizeof(ULONG_PTR);
+ return (SendMessageW( hwnd, CB_GETLBTEXTLEN, wparam, 0 ) + 1) * sizeof(WCHAR);
+ case LB_ADDSTRING:
+ case LB_INSERTSTRING:
+ if (listbox_has_strings( hwnd )) push_string( data, (LPWSTR)lparam );
+ return 0;
+ case LB_GETTEXT:
+ if (!listbox_has_strings( hwnd )) return sizeof(ULONG_PTR);
+ return (SendMessageW( hwnd, LB_GETTEXTLEN, wparam, 0 ) + 1) * sizeof(WCHAR);
+ case LB_GETSELITEMS:
+ return wparam * sizeof(UINT);
+ case WM_MDICREATE:
+ {
+ MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lparam;
+ push_data( data, cs, sizeof(*cs) );
+ if (HIWORD(cs->szTitle)) push_string( data, cs->szTitle );
+ if (HIWORD(cs->szClass)) push_string( data, cs->szClass );
+ return sizeof(*cs);
+ }
+ case WM_MDIGETACTIVE:
+ if (lparam) return sizeof(BOOL);
+ return 0;
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ FIXME("msg %x not supported yet\n",message);
+ return 0;
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * unpack_message
+ *
+ * Unpack a message received from another process.
+ */
+static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
+ void **buffer, size_t size )
+{
+ size_t minsize = 0;
+
+ switch(message)
+ {
+ case WM_NCCREATE:
+ case WM_CREATE:
+ {
+ CREATESTRUCTW *cs = *buffer;
+ WCHAR *str = (WCHAR *)(cs + 1);
+ if (size < sizeof(*cs)) return FALSE;
+ size -= sizeof(*cs);
+ if (HIWORD(cs->lpszName))
+ {
+ if (!check_string( str, size )) return FALSE;
+ cs->lpszName = str;
+ size -= (strlenW(str) + 1) * sizeof(WCHAR);
+ str += strlenW(str) + 1;
+ }
+ if (HIWORD(cs->lpszClass))
+ {
+ if (!check_string( str, size )) return FALSE;
+ cs->lpszClass = str;
+ }
+ break;
+ }
+ case WM_GETTEXT:
+ if (!get_buffer_space( buffer, (*wparam * sizeof(WCHAR)) )) return FALSE;
+ break;
+ case WM_SETTEXT:
+ case WM_WININICHANGE:
+ case CB_DIR:
+ case CB_FINDSTRING:
+ case CB_FINDSTRINGEXACT:
+ case CB_SELECTSTRING:
+ case LB_DIR:
+ case LB_ADDFILE:
+ case LB_FINDSTRING:
+ case LB_FINDSTRINGEXACT:
+ case LB_SELECTSTRING:
+ case EM_REPLACESEL:
+ if (!check_string( *buffer, size )) return FALSE;
+ break;
+ case WM_GETMINMAXINFO:
+ minsize = sizeof(MINMAXINFO);
+ break;
+ case WM_DRAWITEM:
+ minsize = sizeof(DRAWITEMSTRUCT);
+ break;
+ case WM_MEASUREITEM:
+ minsize = sizeof(MEASUREITEMSTRUCT);
+ break;
+ case WM_DELETEITEM:
+ minsize = sizeof(DELETEITEMSTRUCT);
+ break;
+ case WM_COMPAREITEM:
+ minsize = sizeof(COMPAREITEMSTRUCT);
+ break;
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ minsize = sizeof(WINDOWPOS);
+ break;
+ case WM_COPYDATA:
+ {
+ COPYDATASTRUCT *cp = *buffer;
+ if (size < sizeof(*cp)) return FALSE;
+ if (cp->lpData)
+ {
+ minsize = sizeof(*cp) + cp->cbData;
+ cp->lpData = cp + 1;
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ /* WM_NOTIFY cannot be sent across processes (MSDN) */
+ return FALSE;
+ case WM_HELP:
+ minsize = sizeof(HELPINFO);
+ break;
+ case WM_STYLECHANGING:
+ case WM_STYLECHANGED:
+ minsize = sizeof(STYLESTRUCT);
+ break;
+ case WM_NCCALCSIZE:
+ if (!*wparam) minsize = sizeof(RECT);
+ else
+ {
+ NCCALCSIZE_PARAMS *nc = *buffer;
+ if (size < sizeof(*nc) + sizeof(*nc->lppos)) return FALSE;
+ nc->lppos = (WINDOWPOS *)(nc + 1);
+ }
+ break;
+ case WM_GETDLGCODE:
+ if (!*lparam) return TRUE;
+ minsize = sizeof(MSG);
+ break;
+ case EM_GETSEL:
+ if (*wparam || *lparam)
+ {
+ if (!get_buffer_space( buffer, 2*sizeof(DWORD) )) return FALSE;
+ if (*wparam) *wparam = (WPARAM)*buffer;
+ if (*lparam) *lparam = (LPARAM)((DWORD *)*buffer + 1);
+ }
+ return TRUE;
+ case EM_GETRECT:
+ case LB_GETITEMRECT:
+ case CB_GETDROPPEDCONTROLRECT:
+ if (!get_buffer_space( buffer, sizeof(RECT) )) return FALSE;
+ break;
+ case EM_SETRECT:
+ case EM_SETRECTNP:
+ minsize = sizeof(RECT);
+ break;
+ case EM_GETLINE:
+ {
+ WORD len;
+ if (size < sizeof(WORD)) return FALSE;
+ len = *(WORD *)*buffer;
+ if (!get_buffer_space( buffer, (len + 1) * sizeof(WCHAR) )) return FALSE;
+ *lparam = (LPARAM)*buffer + sizeof(WORD); /* don't erase WORD at start of buffer */
+ return TRUE;
+ }
+ case EM_SETTABSTOPS:
+ case LB_SETTABSTOPS:
+ if (!*wparam) return TRUE;
+ minsize = *wparam * sizeof(UINT);
+ break;
+ case CB_ADDSTRING:
+ case CB_INSERTSTRING:
+ case LB_ADDSTRING:
+ case LB_INSERTSTRING:
+ if (!*buffer) return TRUE;
+ if (!check_string( *buffer, size )) return FALSE;
+ break;
+ case CB_GETLBTEXT:
+ {
+ size = sizeof(ULONG_PTR);
+ if (combobox_has_strings( hwnd ))
+ size = (SendMessageW( hwnd, CB_GETLBTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
+ if (!get_buffer_space( buffer, size )) return FALSE;
+ break;
+ }
+ case LB_GETTEXT:
+ {
+ size = sizeof(ULONG_PTR);
+ if (listbox_has_strings( hwnd ))
+ size = (SendMessageW( hwnd, LB_GETTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
+ if (!get_buffer_space( buffer, size )) return FALSE;
+ break;
+ }
+ case LB_GETSELITEMS:
+ if (!get_buffer_space( buffer, *wparam * sizeof(UINT) )) return FALSE;
+ break;
+ case WM_MDICREATE:
+ {
+ MDICREATESTRUCTW *cs = *buffer;
+ WCHAR *str = (WCHAR *)(cs + 1);
+ if (size < sizeof(*cs)) return FALSE;
+ size -= sizeof(*cs);
+ if (HIWORD(cs->szTitle))
+ {
+ if (!check_string( str, size )) return FALSE;
+ cs->szTitle = str;
+ size -= (strlenW(str) + 1) * sizeof(WCHAR);
+ str += strlenW(str) + 1;
+ }
+ if (HIWORD(cs->szClass))
+ {
+ if (!check_string( str, size )) return FALSE;
+ cs->szClass = str;
+ }
+ break;
+ }
+ case WM_MDIGETACTIVE:
+ if (!*lparam) return TRUE;
+ if (!get_buffer_space( buffer, sizeof(BOOL) )) return FALSE;
+ break;
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ FIXME("msg %x not supported yet\n",message);
+ return FALSE;
+ default:
+ return TRUE; /* message doesn't need any unpacking */
+ }
+
+ /* default exit for most messages: check minsize and store buffer in lparam */
+ if (size < minsize) return FALSE;
+ *lparam = (LPARAM)*buffer;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * pack_reply
+ *
+ * Pack a reply to a message for sending to another process.
+ */
+static void pack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
+ LRESULT res, struct packed_message *data )
+{
+ data->count = 0;
+ switch(message)
+ {
+ case WM_NCCREATE:
+ case WM_CREATE:
+ push_data( data, (CREATESTRUCTW *)lparam, sizeof(CREATESTRUCTW) );
+ break;
+ case WM_GETTEXT:
+ case CB_GETLBTEXT:
+ case LB_GETTEXT:
+ push_data( data, (WCHAR *)lparam, (res + 1) * sizeof(WCHAR) );
+ break;
+ case WM_GETMINMAXINFO:
+ push_data( data, (MINMAXINFO *)lparam, sizeof(MINMAXINFO) );
+ break;
+ case WM_MEASUREITEM:
+ push_data( data, (MEASUREITEMSTRUCT *)lparam, sizeof(MEASUREITEMSTRUCT) );
+ break;
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ push_data( data, (WINDOWPOS *)lparam, sizeof(WINDOWPOS) );
+ break;
+ case WM_GETDLGCODE:
+ if (lparam) push_data( data, (MSG *)lparam, sizeof(MSG) );
+ break;
+ case EM_GETRECT:
+ case LB_GETITEMRECT:
+ case CB_GETDROPPEDCONTROLRECT:
+ push_data( data, (RECT *)lparam, sizeof(RECT) );
+ break;
+ case EM_GETLINE:
+ {
+ WORD *ptr = (WORD *)lparam;
+ push_data( data, ptr, ptr[-1] * sizeof(WCHAR) );
+ break;
+ }
+ case LB_GETSELITEMS:
+ push_data( data, (UINT *)lparam, wparam * sizeof(UINT) );
+ break;
+ case WM_MDIGETACTIVE:
+ if (lparam) push_data( data, (BOOL *)lparam, sizeof(BOOL) );
+ break;
+ case WM_NCCALCSIZE:
+ if (!wparam)
+ push_data( data, (RECT *)lparam, sizeof(RECT) );
+ else
+ {
+ NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lparam;
+ push_data( data, nc, sizeof(*nc) );
+ push_data( data, nc->lppos, sizeof(*nc->lppos) );
+ }
+ break;
+ case EM_GETSEL:
+ if (wparam) push_data( data, (DWORD *)wparam, sizeof(DWORD) );
+ if (lparam) push_data( data, (DWORD *)lparam, sizeof(DWORD) );
+ break;
+ case WM_MDICREATE:
+ push_data( data, (MDICREATESTRUCTW *)lparam, sizeof(MDICREATESTRUCTW) );
+ break;
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ FIXME("not implemented yet\n");
+ break;
+ }
+}
+
+
+/***********************************************************************
+ * unpack_reply
+ *
+ * Unpack a message reply received from another process.
+ */
+static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
+ void *buffer, size_t size )
+{
+ switch(message)
+ {
+ case WM_NCCREATE:
+ case WM_CREATE:
+ {
+ CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
+ LPCWSTR name = cs->lpszName, class = cs->lpszClass;
+ memcpy( cs, buffer, min( sizeof(*cs), size ));
+ cs->lpszName = name; /* restore the original pointers */
+ cs->lpszClass = class;
+ break;
+ }
+ case WM_GETTEXT:
+ memcpy( (WCHAR *)lparam, buffer, min( wparam*sizeof(WCHAR), size ));
+ break;
+ case WM_GETMINMAXINFO:
+ memcpy( (MINMAXINFO *)lparam, buffer, min( sizeof(MINMAXINFO), size ));
+ break;
+ case WM_MEASUREITEM:
+ memcpy( (MEASUREITEMSTRUCT *)lparam, buffer, min( sizeof(MEASUREITEMSTRUCT), size ));
+ break;
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ memcpy( (WINDOWPOS *)lparam, buffer, min( sizeof(WINDOWPOS), size ));
+ break;
+ case WM_GETDLGCODE:
+ if (lparam) memcpy( (MSG *)lparam, buffer, min( sizeof(MSG), size ));
+ break;
+ case EM_GETRECT:
+ case CB_GETDROPPEDCONTROLRECT:
+ case LB_GETITEMRECT:
+ memcpy( (RECT *)lparam, buffer, min( sizeof(RECT), size ));
+ break;
+ case EM_GETLINE:
+ size = min( size, *(WORD *)lparam );
+ memcpy( (WCHAR *)lparam, buffer, size );
+ break;
+ case LB_GETSELITEMS:
+ memcpy( (UINT *)lparam, buffer, min( wparam*sizeof(UINT), size ));
+ break;
+ case LB_GETTEXT:
+ case CB_GETLBTEXT:
+ memcpy( (WCHAR *)lparam, buffer, size );
+ break;
+ case WM_MDIGETACTIVE:
+ if (lparam) memcpy( (BOOL *)lparam, buffer, min( sizeof(BOOL), size ));
+ break;
+ case WM_NCCALCSIZE:
+ if (!wparam)
+ memcpy( (RECT *)lparam, buffer, min( sizeof(RECT), size ));
+ else
+ {
+ NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lparam;
+ WINDOWPOS *wp = nc->lppos;
+ memcpy( nc, buffer, min( sizeof(*nc), size ));
+ if (size > sizeof(*nc))
+ {
+ size -= sizeof(*nc);
+ memcpy( wp, (NCCALCSIZE_PARAMS*)buffer + 1, min( sizeof(*wp), size ));
+ }
+ nc->lppos = wp; /* restore the original pointer */
+ }
+ break;
+ case EM_GETSEL:
+ if (wparam)
+ {
+ memcpy( (DWORD *)wparam, buffer, min( sizeof(DWORD), size ));
+ if (size <= sizeof(DWORD)) break;
+ size -= sizeof(DWORD);
+ buffer = (DWORD *)buffer + 1;
+ }
+ if (lparam) memcpy( (DWORD *)lparam, buffer, min( sizeof(DWORD), size ));
+ break;
+ case WM_MDICREATE:
+ {
+ MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lparam;
+ LPCWSTR title = cs->szTitle, class = cs->szClass;
+ memcpy( cs, buffer, min( sizeof(*cs), size ));
+ cs->szTitle = title; /* restore the original pointers */
+ cs->szClass = class;
+ break;
+ }
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ FIXME("not implemented yet\n");
+ break;
+ default:
+ ERR( "should not happen: unexpected message %x\n", message );
+ break;
+ }
+}
+
+
+/***********************************************************************
+ * reply_message
+ *
+ * Send a reply to a sent message.
+ */
+static void reply_message( struct received_message_info *info, LRESULT result, BOOL remove )
+{
+ struct packed_message data;
+ int replied = info->flags & ISMEX_REPLIED;
+
+ if (info->flags & ISMEX_NOTIFY) return; /* notify messages don't get replies */
+ if (!remove && replied) return; /* replied already */
+
+ data.count = 0;
+ info->flags |= ISMEX_REPLIED;
+
+ if (info->type == MSG_OTHER_PROCESS && !replied)
+ {
+ pack_reply( info->msg.hwnd, info->msg.message, info->msg.wParam,
+ info->msg.lParam, result, &data );
+ if (data.count)
+ {
+ size_t total = get_data_total_size( &data );
+
+ if (total > REQUEST_MAX_VAR_SIZE)
+ {
+ FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
+ total );
+ total = REQUEST_MAX_VAR_SIZE;
+ }
+
+ SERVER_START_VAR_REQ( reply_message, total )
+ {
+ req->result = result;
+ req->remove = remove;
+ copy_all_data( server_data_ptr(req), &data );
+ SERVER_CALL();
+ }
+ SERVER_END_VAR_REQ;
+ return;
+ }
+ }
+
+ SERVER_START_REQ( reply_message )
+ {
+ req->result = result;
+ req->remove = remove;
+ SERVER_CALL();
+ }
+ SERVER_END_REQ;
+}
+
+
+/***********************************************************************
+ * call_window_proc
+ *
+ * Call a window procedure and the corresponding hooks.
+ */
+static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL unicode )
+{
+ LRESULT result;
+ WND *wndPtr;
+ WNDPROC winproc;
+
+ /* FIXME: should check for exiting queue */
+
+ /* first the WH_CALLWNDPROC hook */
+ if (HOOK_IsHooked( WH_CALLWNDPROC ))
+ {
+ CWPSTRUCT cwp;
+ cwp.lParam = lparam;
+ cwp.wParam = wparam;
+ cwp.message = msg;
+ cwp.hwnd = hwnd;
+ if (unicode) HOOK_CallHooksW( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
+ else HOOK_CallHooksA( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
+ lparam = cwp.lParam;
+ wparam = cwp.wParam;
+ msg = cwp.message;
+ hwnd = cwp.hwnd;
+ }
+
+ /* now call the window procedure */
+ if (!(wndPtr = WIN_FindWndPtr( hwnd )))
+ {
+ WARN( "bad window %x\n", hwnd );
+ return 0;
+ }
+ winproc = wndPtr->winproc;
+ WIN_ReleaseWndPtr(wndPtr);
+
+ if (unicode)
+ result = CallWindowProcW( winproc, hwnd, msg, wparam, lparam );
+ else
+ result = CallWindowProcA( winproc, hwnd, msg, wparam, lparam );
+
+ /* and finally the WH_CALLWNDPROCRET hook */
+ if (HOOK_IsHooked( WH_CALLWNDPROCRET ))
+ {
+ CWPRETSTRUCT cwp;
+ cwp.lResult = result;
+ cwp.lParam = lparam;
+ cwp.wParam = wparam;
+ cwp.message = msg;
+ cwp.hwnd = hwnd;
+ if (unicode) HOOK_CallHooksW( WH_CALLWNDPROCRET, HC_ACTION, 1, (LPARAM)&cwp );
+ else HOOK_CallHooksA( WH_CALLWNDPROCRET, HC_ACTION, 1, (LPARAM)&cwp );
+ }
+ return result;
+}
+
+
+/***********************************************************************
+ * MSG_peek_message
+ *
+ * Peek for a message matching the given parameters. Return FALSE if none available.
+ * All pending sent messages are processed before returning.
+ */
+BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
+{
+ BOOL ret;
+ LRESULT result;
+ ULONG_PTR extra_info = 0;
+ MESSAGEQUEUE *queue = QUEUE_Current();
+ struct received_message_info info, *old_info;
+
+ if (!first && !last) last = ~0;
+
+ for (;;)
+ {
+ void *buffer = NULL;
+ size_t size = 0;
+
+ SERVER_START_VAR_REQ( get_message, REQUEST_MAX_VAR_SIZE )
+ {
+ req->flags = flags;
+ req->get_win = hwnd;
+ req->get_first = first;
+ req->get_last = last;
+ if ((ret = !SERVER_CALL()))
+ {
+ info.type = req->type;
+ info.msg.hwnd = req->win;
+ info.msg.message = req->msg;
+ info.msg.wParam = req->wparam;
+ info.msg.lParam = req->lparam;
+ info.msg.time = req->time;
+ info.msg.pt.x = req->x;
+ info.msg.pt.y = req->y;
+ extra_info = req->info;
+
+ if ((size = server_data_size(req)))
+ {
+ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
+ {
+ ERR("out of memory for message data\n");
+ ret = FALSE;
+ }
+ else memcpy( buffer, server_data_ptr(req), size );
+ }
+ }
+ }
+ SERVER_END_VAR_REQ;
+
+ if (!ret) return FALSE; /* no message available */
+
+ TRACE( "got type %d msg %x hwnd %x wp %x lp %lx\n",
+ info.type, info.msg.message, info.msg.hwnd, info.msg.wParam, info.msg.lParam );
+
+ switch(info.type)
+ {
+ case MSG_ASCII:
+ case MSG_UNICODE:
+ info.flags = ISMEX_SEND;
+ break;
+ case MSG_NOTIFY:
+ info.flags = ISMEX_NOTIFY;
+ break;
+ case MSG_CALLBACK:
+ info.flags = ISMEX_CALLBACK;
+ break;
+ case MSG_OTHER_PROCESS:
+ info.flags = ISMEX_SEND;
+ if (!unpack_message( info.msg.hwnd, info.msg.message, &info.msg.wParam,
+ &info.msg.lParam, &buffer, size ))
+ {
+ ERR( "invalid packed message %x (%s) hwnd %x wp %x lp %lx size %d\n",
+ info.msg.message, SPY_GetMsgName(info.msg.message), info.msg.hwnd,
+ info.msg.wParam, info.msg.lParam, size );
+ /* ignore it */
+ reply_message( &info, 0, TRUE );
+ continue;
+ }
+ break;
+ case MSG_POSTED:
+ goto got_one;
+ case MSG_HARDWARE_RAW:
+ if (!MSG_process_raw_hardware_message( &info.msg, extra_info,
+ hwnd, first, last, flags & GET_MSG_REMOVE ))
+ continue;
+ /* fall through */
+ case MSG_HARDWARE_COOKED:
+ if (!MSG_process_cooked_hardware_message( &info.msg, flags & GET_MSG_REMOVE ))
+ {
+ flags |= GET_MSG_REMOVE_LAST;
+ continue;
+ }
+ queue->GetMessageExtraInfoVal = extra_info;
+ goto got_one;
+ }
+
+ /* if we get here, we have a sent message; call the window procedure */
+ old_info = queue->receive_info;
+ queue->receive_info = &info;
+ result = call_window_proc( info.msg.hwnd, info.msg.message, info.msg.wParam,
+ info.msg.lParam, (info.type != MSG_ASCII) );
+ reply_message( &info, result, TRUE );
+ queue->receive_info = old_info;
+
+ if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
+ }
+
+ got_one:
+ *msg = info.msg;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * wait_message_reply
+ *
+ * Wait until a sent message gets replied to.
+ */
+static void wait_message_reply( UINT flags )
+{
+ MESSAGEQUEUE *queue;
+
+ if (!(queue = QUEUE_Current())) return;
+
+ for (;;)
+ {
+ unsigned int wake_bits = 0, changed_bits = 0;
+ DWORD dwlc, res;
+
+ SERVER_START_REQ( set_queue_mask )
+ {
+ req->wake_mask = (flags & SMTO_BLOCK) ? 0 : QS_SENDMESSAGE;
+ req->changed_mask = QS_SMRESULT | req->wake_mask;
+ req->skip_wait = 1;
+ if (!SERVER_CALL())
+ {
+ wake_bits = req->wake_bits;
+ changed_bits = req->changed_bits;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (changed_bits & QS_SMRESULT) return; /* got a result */
+ if (wake_bits & QS_SENDMESSAGE)
+ {
+ /* Process the sent message immediately */
+ MSG msg;
+ MSG_peek_message( &msg, 0, 0, 0, GET_MSG_REMOVE | GET_MSG_SENT_ONLY );
+ continue;
+ }
+
+ /* now wait for it */
+
+ ReleaseThunkLock( &dwlc );
+
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
+ res = USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue,
+ INFINITE, 0, 0 );
+ else
+ res = WaitForSingleObject( queue->server_queue, INFINITE );
+
+ if (dwlc) RestoreThunkLock( dwlc );
+ }
+}
+
+/***********************************************************************
+ * put_message_in_queue
+ *
+ * Put a sent message into the destination queue.
+ * For inter-process message, reply_size is set to expected size of reply data.
+ */
+static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info *info,
+ size_t *reply_size )
+{
+ unsigned int res;
+ int timeout = -1;
+
+ /* FIXME: should check for exiting queue */
+
+ if (info->type != MSG_NOTIFY &&
+ info->type != MSG_CALLBACK &&
+ info->type != MSG_POSTED &&
+ info->timeout != INFINITE)
+ timeout = info->timeout;
+
+ if (info->type == MSG_OTHER_PROCESS)
+ {
+ struct packed_message data;
+ *reply_size = pack_message( info->hwnd, info->msg, info->wparam, info->lparam, &data );
+
+ if (data.count == -1)
+ {
+ WARN( "cannot pack message %x\n", info->msg );
+ return FALSE;
+ }
+
+ if (data.size[0]) /* need to send extra data along with the message */
+ {
+ size_t total = get_data_total_size( &data );
+
+ if (total > REQUEST_MAX_VAR_SIZE)
+ {
+ FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
+ total );
+ total = REQUEST_MAX_VAR_SIZE;
+ }
+
+ SERVER_START_VAR_REQ( send_message, total )
+ {
+ req->id = (void *)dest_tid;
+ req->type = MSG_OTHER_PROCESS;
+ req->win = info->hwnd;
+ req->msg = info->msg;
+ req->wparam = info->wparam;
+ req->lparam = info->lparam;
+ req->time = GetCurrentTime();
+ req->timeout = timeout;
+ copy_all_data( server_data_ptr(req), &data );
+ res = SERVER_CALL();
+ }
+ SERVER_END_VAR_REQ;
+ goto done;
+ }
+ }
+
+ /* no extra data, or not inter-process message */
+ SERVER_START_REQ( send_message )
+ {
+ req->id = (void *)dest_tid;
+ req->type = info->type;
+ req->win = info->hwnd;
+ req->msg = info->msg;
+ req->wparam = info->wparam;
+ req->lparam = info->lparam;
+ req->time = GetCurrentTime();
+ req->timeout = timeout;
+ res = SERVER_CALL();
+ }
+ SERVER_END_REQ;
+
+ done:
+ if (res)
+ {
+ if (res == STATUS_INVALID_PARAMETER)
+ /* FIXME: find a STATUS_ value for this one */
+ SetLastError( ERROR_INVALID_THREAD_ID );
+ else
+ SetLastError( RtlNtStatusToDosError(res) );
+ }
+ return !res;
+}
+
+
+/***********************************************************************
+ * retrieve_reply
+ *
+ * Retrieve a message reply from the server.
+ */
+static LRESULT retrieve_reply( const struct send_message_info *info,
+ size_t reply_size, LRESULT *result )
+{
+ NTSTATUS status;
+
+ if (reply_size)
+ {
+ if (reply_size > REQUEST_MAX_VAR_SIZE)
+ {
+ WARN( "reply_size %d too large, reply may be truncated\n", reply_size );
+ reply_size = REQUEST_MAX_VAR_SIZE;
+ }
+ SERVER_START_VAR_REQ( get_message_reply, reply_size )
+ {
+ req->cancel = 1;
+ if (!(status = SERVER_CALL()))
+ {
+ *result = req->result;
+ unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam,
+ server_data_ptr(req), server_data_size(req) );
+ }
+ }
+ SERVER_END_VAR_REQ;
+ }
+ else
+ {
+ SERVER_START_REQ( get_message_reply )
+ {
+ req->cancel = 1;
+ if (!(status = SERVER_CALL())) *result = req->result;
+ }
+ SERVER_END_REQ;
+ }
+
+ TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
+ info->hwnd, info->msg, SPY_GetMsgName(info->msg), info->wparam,
+ info->lparam, *result, status );
+
+ if (!status) return 1;
+ if (status == STATUS_TIMEOUT) SetLastError(0); /* timeout */
+ else SetLastError( RtlNtStatusToDosError(status) );
+ return 0;
+}
+
+
+/***********************************************************************
+ * send_inter_thread_message
+ */
+static LRESULT send_inter_thread_message( DWORD dest_tid, const struct send_message_info *info,
+ LRESULT *res_ptr )
+{
+ LRESULT ret;
+ int locks;
+ size_t reply_size = 0;
+
+ TRACE( "hwnd %x msg %x (%s) wp %x lp %lx\n",
+ info->hwnd, info->msg, SPY_GetMsgName(info->msg), info->wparam, info->lparam );
+
+ if (!put_message_in_queue( dest_tid, info, &reply_size )) return 0;
+
+ /* there's no reply to wait for on notify/callback messages */
+ if (info->type == MSG_NOTIFY || info->type == MSG_CALLBACK) return 1;
+
+ locks = WIN_SuspendWndsLock();
+
+ wait_message_reply( info->flags );
+ ret = retrieve_reply( info, reply_size, res_ptr );
+
+ WIN_RestoreWndsLock( locks );
+ return ret;
+}
+
+
+/***********************************************************************
+ * SendMessageTimeoutW (USER32.@)
+ */
+LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
+ UINT flags, UINT timeout, LPDWORD res_ptr )
+{
+ struct send_message_info info;
+ DWORD dest_tid, dest_pid;
+ LRESULT ret, result;
+
+ info.type = MSG_UNICODE;
+ info.hwnd = hwnd;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+ info.flags = flags;
+ info.timeout = timeout;
+
+ if (is_broadcast(hwnd))
+ {
+ EnumWindows( broadcast_message_callback, (LPARAM)&info );
+ if (res_ptr) *res_ptr = 1;
+ return 1;
+ }
+
+ SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
+
+ dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
+
+ if (dest_tid == GetCurrentThreadId())
+ {
+ result = call_window_proc( hwnd, msg, wparam, lparam, TRUE );
+ ret = 1;
+ }
+ else
+ {
+ if (dest_pid != GetCurrentProcessId()) info.type = MSG_OTHER_PROCESS;
+ ret = send_inter_thread_message( dest_tid, &info, &result );
+ }
+
+ SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, result, wparam, lparam );
+ if (ret && res_ptr) *res_ptr = result;
+ return ret;
+}
+
+
+/***********************************************************************
+ * SendMessageTimeoutA (USER32.@)
+ */
+LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
+ UINT flags, UINT timeout, LPDWORD res_ptr )
+{
+ struct send_message_info info;
+ DWORD dest_tid, dest_pid;
+ LRESULT ret, result;
+
+ info.type = MSG_ASCII;
+ info.hwnd = hwnd;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+ info.flags = flags;
+ info.timeout = timeout;
+
+ if (is_broadcast(hwnd))
+ {
+ EnumWindows( broadcast_message_callback, (LPARAM)&info );
+ if (res_ptr) *res_ptr = 1;
+ return 1;
+ }
+
+ SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
+
+ dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
+
+ if (dest_tid == GetCurrentThreadId())
+ {
+ result = call_window_proc( hwnd, msg, wparam, lparam, FALSE );
+ ret = 1;
+ }
+ else if (dest_pid == GetCurrentProcessId())
+ {
+ ret = send_inter_thread_message( dest_tid, &info, &result );
+ }
+ else
+ {
+ /* inter-process message: need to map to Unicode */
+ info.type = MSG_OTHER_PROCESS;
+ if (WINPROC_MapMsg32ATo32W( info.hwnd, info.msg, &info.wparam, &info.lparam ) == -1)
+ return 0;
+ ret = send_inter_thread_message( dest_tid, &info, &result );
+ WINPROC_UnmapMsg32ATo32W( info.hwnd, info.msg, info.wparam, info.lparam );
+ }
+ SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, result, wparam, lparam );
+ if (ret && res_ptr) *res_ptr = result;
+ return ret;
+}
+
+
+/***********************************************************************
+ * SendMessageW (USER32.@)
+ */
+LRESULT WINAPI SendMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ LRESULT res = 0;
+ SendMessageTimeoutW( hwnd, msg, wparam, lparam, SMTO_NORMAL, INFINITE, &res );
+ return res;
+}
+
+
+/***********************************************************************
+ * SendMessageA (USER32.@)
+ */
+LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ LRESULT res = 0;
+ SendMessageTimeoutA( hwnd, msg, wparam, lparam, SMTO_NORMAL, INFINITE, &res );
+ return res;
+}
+
+
+/***********************************************************************
+ * SendNotifyMessageA (USER32.@)
+ */
+BOOL WINAPI SendNotifyMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ return SendNotifyMessageW( hwnd, msg, map_wparam_AtoW( msg, wparam ), lparam );
+}
+
+
+/***********************************************************************
+ * SendNotifyMessageW (USER32.@)
+ */
+BOOL WINAPI SendNotifyMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ struct send_message_info info;
+ DWORD dest_tid;
+ LRESULT result;
+
+ if (is_pointer_message(msg))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ info.type = MSG_NOTIFY;
+ info.hwnd = hwnd;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+
+ if (is_broadcast(hwnd))
+ {
+ EnumWindows( broadcast_message_callback, (LPARAM)&info );
+ return TRUE;
+ }
+
+ dest_tid = GetWindowThreadProcessId( hwnd, NULL );
+
+ if (dest_tid == GetCurrentThreadId())
+ {
+ call_window_proc( hwnd, msg, wparam, lparam, TRUE );
+ return TRUE;
+ }
+ return send_inter_thread_message( dest_tid, &info, &result );
+}
+
+
+/***********************************************************************
+ * SendMessageCallbackA (USER32.@)
+ */
+BOOL WINAPI SendMessageCallbackA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
+ SENDASYNCPROC callback, ULONG_PTR data )
+{
+ return SendMessageCallbackW( hwnd, msg, map_wparam_AtoW( msg, wparam ),
+ lparam, callback, data );
+}
+
+
+/***********************************************************************
+ * SendMessageCallbackW (USER32.@)
+ */
+BOOL WINAPI SendMessageCallbackW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
+ SENDASYNCPROC callback, ULONG_PTR data )
+{
+ struct send_message_info info;
+ LRESULT result;
+ DWORD dest_tid;
+
+ if (is_pointer_message(msg))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ info.type = MSG_CALLBACK;
+ info.hwnd = hwnd;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+ info.callback = callback;
+ info.data = data;
+
+ if (is_broadcast(hwnd))
+ {
+ EnumWindows( broadcast_message_callback, (LPARAM)&info );
+ return TRUE;
+ }
+
+ dest_tid = GetWindowThreadProcessId( hwnd, NULL );
+
+ if (dest_tid == GetCurrentThreadId())
+ {
+ result = call_window_proc( hwnd, msg, wparam, lparam, TRUE );
+ callback( hwnd, msg, data, result );
+ return TRUE;
+ }
+ FIXME( "callback will not be called\n" );
+ return send_inter_thread_message( dest_tid, &info, &result );
+}
+
+
+/***********************************************************************
+ * ReplyMessage (USER32.@)
+ */
+BOOL WINAPI ReplyMessage( LRESULT result )
+{
+ MESSAGEQUEUE *queue = QUEUE_Current();
+ struct received_message_info *info = queue->receive_info;
+
+ if (!info) return FALSE;
+ reply_message( info, result, FALSE );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * InSendMessage (USER32.@)
+ */
+BOOL WINAPI InSendMessage(void)
+{
+ return (InSendMessageEx(NULL) & (ISMEX_SEND|ISMEX_REPLIED)) == ISMEX_SEND;
+}
+
+
+/***********************************************************************
+ * InSendMessageEx (USER32.@)
+ */
+DWORD WINAPI InSendMessageEx( LPVOID reserved )
+{
+ MESSAGEQUEUE *queue = QUEUE_Current();
+ struct received_message_info *info = queue->receive_info;
+
+ if (info) return info->flags;
+ return ISMEX_NOSEND;
+}
+
+
+/***********************************************************************
+ * PostMessageA (USER32.@)
+ */
+BOOL WINAPI PostMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ return PostMessageW( hwnd, msg, map_wparam_AtoW( msg, wparam ), lparam );
+}
+
+
+/***********************************************************************
+ * PostMessageW (USER32.@)
+ */
+BOOL WINAPI PostMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ struct send_message_info info;
+
+ if (is_pointer_message( msg ))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ info.type = MSG_POSTED;
+ info.hwnd = hwnd;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+
+ if (is_broadcast(hwnd))
+ {
+ EnumWindows( broadcast_message_callback, (LPARAM)&info );
+ return TRUE;
+ }
+ return put_message_in_queue( GetWindowThreadProcessId( hwnd, NULL ), &info, NULL );
+}
+
+
+/**********************************************************************
+ * PostThreadMessageA (USER32.@)
+ */
+BOOL WINAPI PostThreadMessageA( DWORD thread, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ return PostThreadMessageW( thread, msg, map_wparam_AtoW( msg, wparam ), lparam );
+}
+
+
+/**********************************************************************
+ * PostThreadMessageW (USER32.@)
+ */
+BOOL WINAPI PostThreadMessageW( DWORD thread, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+ struct send_message_info info;
+
+ if (is_pointer_message( msg ))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ info.type = MSG_POSTED;
+ info.hwnd = 0;
+ info.msg = msg;
+ info.wparam = wparam;
+ info.lparam = lparam;
+ return put_message_in_queue( thread, &info, NULL );
+}
+
+
+/***********************************************************************
+ * PostQuitMessage (USER32.@)
+ */
+void WINAPI PostQuitMessage( INT exitCode )
+{
+ PostThreadMessageW( GetCurrentThreadId(), WM_QUIT, exitCode, 0 );
+}
+
+
+/***********************************************************************
+ * PeekMessageW (USER32.@)
+ */
+BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT flags )
+{
+ MESSAGEQUEUE *queue;
+ MSG msg;
+ int locks;
+
+ /* check for graphics events */
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
+ USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
+
+ locks = WIN_SuspendWndsLock();
+
+ if (!MSG_peek_message( &msg, hwnd, first, last,
+ (flags & PM_REMOVE) ? GET_MSG_REMOVE : 0 ))
+ {
+ /* FIXME: should be done before checking for hw events */
+ MSG_JournalPlayBackMsg();
+
+ if (!(flags & PM_NOYIELD))
+ {
+ DWORD count;
+ ReleaseThunkLock(&count);
+ if (count) RestoreThunkLock(count);
+ }
+ WIN_RestoreWndsLock( locks );
+ return FALSE;
+ }
+
+ WIN_RestoreWndsLock( locks );
+
+ /* need to fill the window handle for WM_PAINT message */
+ if (msg.message == WM_PAINT)
+ {
+ if (!(msg.hwnd = WIN_FindWinToRepaint( hwnd ))) return FALSE;
+
+ if (IsIconic( msg.hwnd ) && GetClassLongA( msg.hwnd, GCL_HICON ))
+ {
+ msg.message = WM_PAINTICON;
+ msg.wParam = 1;
+ }
+
+ /* check hwnd filter */
+ if (hwnd && msg.hwnd != hwnd && !IsChild( hwnd, msg.hwnd )) return FALSE;
+
+ /* clear internal paint flag */
+ RedrawWindow( msg.hwnd, NULL, 0, RDW_NOINTERNALPAINT | RDW_NOCHILDREN );
+ }
+
+ if ((queue = QUEUE_Current()))
+ {
+ queue->GetMessageTimeVal = msg.time;
+ queue->GetMessagePosVal = MAKELONG( msg.pt.x, msg.pt.y );
+ }
+
+ /* We got a message */
+ if (flags & PM_REMOVE)
+ {
+ if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
+ {
+ BYTE *p = &QueueKeyStateTable[msg.wParam & 0xff];
+
+ if (!(*p & 0x80)) *p ^= 0x01;
+ *p |= 0x80;
+ }
+ else if (msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
+ QueueKeyStateTable[msg.wParam & 0xff] &= ~0x80;
+ }
+
+ HOOK_CallHooksW( WH_GETMESSAGE, HC_ACTION, flags & PM_REMOVE, (LPARAM)&msg );
+
+ /* copy back our internal safe copy of message data to msg_out.
+ * msg_out is a variable from the *program*, so it can't be used
+ * internally as it can get "corrupted" by our use of SendMessage()
+ * (back to the program) inside the message handling itself. */
+ *msg_out = msg;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * PeekMessageA (USER32.@)
+ */
+BOOL WINAPI PeekMessageA( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags )
+{
+ BOOL ret = PeekMessageW( msg, hwnd, first, last, flags );
+ if (ret) msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
+ return ret;
+}
+
+
+/***********************************************************************
+ * GetMessageW (USER32.@)
+ */
+BOOL WINAPI GetMessageW( MSG *msg, HWND hwnd, UINT first, UINT last )
+{
+ MESSAGEQUEUE *queue = QUEUE_Current();
+ int mask, locks;
+
+ mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
+ if (first || last)
+ {
+ if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
+ if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
+ ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
+ if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
+ if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
+ if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
+ }
+ else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
+
+ locks = WIN_SuspendWndsLock();
+
+ while (!PeekMessageW( msg, hwnd, first, last, PM_REMOVE ))
+ {
+ /* wait until one of the bits is set */
+ unsigned int wake_bits = 0, changed_bits = 0;
+ DWORD dwlc;
+
+ SERVER_START_REQ( set_queue_mask )
+ {
+ req->wake_mask = QS_SENDMESSAGE;
+ req->changed_mask = mask;
+ req->skip_wait = 1;
+ if (!SERVER_CALL())
+ {
+ wake_bits = req->wake_bits;
+ changed_bits = req->changed_bits;
+ }
+ }
+ SERVER_END_REQ;
+
+ if (changed_bits & mask) continue;
+ if (wake_bits & QS_SENDMESSAGE) continue;
+
+ TRACE( "(%04x) mask=%08x, bits=%08x, changed=%08x, waiting\n",
+ queue->self, mask, wake_bits, changed_bits );
+
+ ReleaseThunkLock( &dwlc );
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
+ USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, INFINITE, 0, 0 );
+ else
+ WaitForSingleObject( queue->server_queue, INFINITE );
+ if (dwlc) RestoreThunkLock( dwlc );
+ }
+
+ WIN_RestoreWndsLock( locks );
+
+ return (msg->message != WM_QUIT);
+}
+
+
+/***********************************************************************
+ * GetMessageA (USER32.@)
+ */
+BOOL WINAPI GetMessageA( MSG *msg, HWND hwnd, UINT first, UINT last )
+{
+ GetMessageW( msg, hwnd, first, last );
+ msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
+ return (msg->message != WM_QUIT);
+}
+
+
+/***********************************************************************
+ * SetMessageQueue (USER32.@)
+ */
+BOOL WINAPI SetMessageQueue( INT size )
+{
+ /* now obsolete the message queue will be expanded dynamically as necessary */
+ return TRUE;
+}
diff --git a/dlls/user/msg16.c b/dlls/user/msg16.c
new file mode 100644
index 0000000..55a4317
--- /dev/null
+++ b/dlls/user/msg16.c
@@ -0,0 +1,383 @@
+/*
+ * 16-bit messaging support
+ *
+ * Copyright 2001 Alexandre Julliard
+ */
+
+#include "wine/winuser16.h"
+#include "heap.h"
+#include "hook.h"
+#include "message.h"
+#include "spy.h"
+#include "task.h"
+#include "thread.h"
+#include "win.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(msg);
+
+
+/***********************************************************************
+ * SendMessage (USER.111)
+ */
+LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
+{
+ LRESULT result;
+
+ if (hwnd != HWND_BROADCAST &&
+ GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId())
+ {
+ /* call 16-bit window proc directly */
+ WND *wndPtr;
+ WNDPROC16 winproc;
+
+ /* first the WH_CALLWNDPROC hook */
+ if (HOOK_IsHooked( WH_CALLWNDPROC ))
+ {
+ CWPSTRUCT16 *cwp;
+
+ if ((cwp = SEGPTR_NEW(CWPSTRUCT16)))
+ {
+ cwp->hwnd = hwnd;
+ cwp->message = msg;
+ cwp->wParam = wparam;
+ cwp->lParam = lparam;
+ HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1, SEGPTR_GET(cwp) );
+ hwnd = cwp->hwnd;
+ msg = cwp->message;
+ wparam = cwp->wParam;
+ lparam = cwp->lParam;
+ SEGPTR_FREE( cwp );
+ }
+ }
+
+ if (!(wndPtr = WIN_FindWndPtr( hwnd )))
+ {
+ WARN("invalid hwnd %04x\n", hwnd );
+ return 0;
+ }
+ winproc = (WNDPROC16)wndPtr->winproc;
+ WIN_ReleaseWndPtr( wndPtr );
+
+ SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
+ result = CallWindowProc16( (WNDPROC16)winproc, hwnd, msg, wparam, lparam );
+ SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
+ }
+ else /* map to 32-bit unicode for inter-thread/process message */
+ {
+ UINT msg32;
+ WPARAM wparam32;
+
+ if (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ) == -1)
+ return 0;
+ result = WINPROC_UnmapMsg16To32W( hwnd, msg32, wparam32, lparam,
+ SendMessageW( hwnd, msg32, wparam32, lparam ) );
+ }
+ return result;
+}
+
+
+/***********************************************************************
+ * PostMessage (USER.110)
+ */
+BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
+{
+ WPARAM wparam32;
+ UINT msg32;
+
+ switch (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ))
+ {
+ case 0:
+ return PostMessageW( hwnd, msg32, wparam32, lparam );
+ case 1:
+ ERR( "16-bit message %x contains pointer, cannot post\n", msg );
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/***********************************************************************
+ * PostAppMessage (USER.116)
+ * PostAppMessage16 (USER32.@)
+ */
+BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
+{
+ WPARAM wparam32;
+ UINT msg32;
+ TDB *pTask = TASK_GetPtr( hTask );
+ if (!pTask) return FALSE;
+
+ switch (WINPROC_MapMsg16To32W( 0, msg, wparam, &msg32, &wparam32, &lparam ))
+ {
+ case 0:
+ return PostThreadMessageW( (DWORD)pTask->teb->tid, msg32, wparam32, lparam );
+ case 1:
+ ERR( "16-bit message %x contains pointer, cannot post\n", msg );
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/***********************************************************************
+ * InSendMessage (USER.192)
+ */
+BOOL16 WINAPI InSendMessage16(void)
+{
+ return InSendMessage();
+}
+
+
+/***********************************************************************
+ * ReplyMessage (USER.115)
+ */
+void WINAPI ReplyMessage16( LRESULT result )
+{
+ ReplyMessage( result );
+}
+
+
+/***********************************************************************
+ * PeekMessage32 (USER.819)
+ */
+BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd,
+ UINT16 first, UINT16 last, UINT16 flags,
+ BOOL16 wHaveParamHigh )
+{
+ MSG msg;
+
+ if (!PeekMessageW( &msg, hwnd, first, last, flags )) return FALSE;
+
+ msg16->msg.hwnd = msg.hwnd;
+ msg16->msg.lParam = msg.lParam;
+ msg16->msg.time = msg.time;
+ msg16->msg.pt.x = (INT16)msg.pt.x;
+ msg16->msg.pt.y = (INT16)msg.pt.y;
+ if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
+
+ return (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
+ &msg16->msg.message, &msg16->msg.wParam,
+ &msg16->msg.lParam ) != -1);
+}
+
+
+/***********************************************************************
+ * PeekMessage (USER.109)
+ */
+BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
+ UINT16 first, UINT16 last, UINT16 flags )
+{
+ return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
+}
+
+
+/***********************************************************************
+ * GetMessage32 (USER.820)
+ */
+BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd, UINT16 first,
+ UINT16 last, BOOL16 wHaveParamHigh )
+{
+ MSG msg;
+
+ do
+ {
+ GetMessageW( &msg, hwnd, first, last );
+ msg16->msg.hwnd = msg.hwnd;
+ msg16->msg.lParam = msg.lParam;
+ msg16->msg.time = msg.time;
+ msg16->msg.pt.x = (INT16)msg.pt.x;
+ msg16->msg.pt.y = (INT16)msg.pt.y;
+ if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
+ }
+ while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
+ &msg16->msg.message, &msg16->msg.wParam,
+ &msg16->msg.lParam ) == -1);
+
+ TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
+ msg16->msg.message, hwnd, first, last );
+
+ return msg16->msg.message != WM_QUIT;
+}
+
+
+/***********************************************************************
+ * GetMessage (USER.108)
+ */
+BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
+{
+ return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
+}
+
+
+/***********************************************************************
+ * TranslateMessage32 (USER.821)
+ */
+BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
+{
+ MSG msg32;
+
+ msg32.hwnd = msg->msg.hwnd;
+ msg32.message = msg->msg.message;
+ msg32.wParam = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
+ msg32.lParam = msg->msg.lParam;
+ return TranslateMessage( &msg32 );
+}
+
+
+/***********************************************************************
+ * TranslateMessage (USER.113)
+ */
+BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
+{
+ return TranslateMessage32_16( (MSG32_16 *)msg, FALSE );
+}
+
+
+/***********************************************************************
+ * DispatchMessage (USER.114)
+ */
+LONG WINAPI DispatchMessage16( const MSG16* msg )
+{
+ WND * wndPtr;
+ WNDPROC16 winproc;
+ LONG retval;
+ int painting;
+
+ /* Process timer messages */
+ if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
+ {
+ if (msg->lParam)
+ {
+ /* before calling window proc, verify whether timer is still valid;
+ there's a slim chance that the application kills the timer
+ between GetMessage and DispatchMessage API calls */
+ if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
+ return 0; /* invalid winproc */
+
+ return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
+ msg->message, msg->wParam, GetTickCount() );
+ }
+ }
+
+ if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
+ if (!wndPtr->winproc)
+ {
+ WIN_ReleaseWndPtr( wndPtr );
+ return 0;
+ }
+ winproc = (WNDPROC16)wndPtr->winproc;
+ painting = (msg->message == WM_PAINT);
+ if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
+ WIN_ReleaseWndPtr( wndPtr );
+
+ SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message, msg->wParam, msg->lParam );
+ retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
+ SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval, msg->wParam, msg->lParam );
+
+ if (!painting) return retval;
+
+ if ((wndPtr = WIN_FindWndPtr( msg->hwnd )))
+ {
+ if ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
+ {
+ ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
+ wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+ /* Validate the update region to avoid infinite WM_PAINT loop */
+ RedrawWindow( wndPtr->hwndSelf, NULL, 0,
+ RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
+ }
+ WIN_ReleaseWndPtr( wndPtr );
+ }
+ return retval;
+}
+
+
+/***********************************************************************
+ * DispatchMessage32 (USER.822)
+ */
+LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
+{
+ if (wHaveParamHigh == FALSE)
+ return DispatchMessage16( &msg16->msg );
+ else
+ {
+ MSG msg;
+
+ msg.hwnd = msg16->msg.hwnd;
+ msg.message = msg16->msg.message;
+ msg.wParam = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
+ msg.lParam = msg16->msg.lParam;
+ msg.time = msg16->msg.time;
+ msg.pt.x = msg16->msg.pt.x;
+ msg.pt.y = msg16->msg.pt.y;
+ return DispatchMessageA( &msg );
+ }
+}
+
+
+/***********************************************************************
+ * MsgWaitForMultipleObjects (USER.640)
+ */
+DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
+ BOOL wait_all, DWORD timeout, DWORD mask )
+{
+ return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
+ wait_all ? MWMO_WAITALL : 0 );
+}
+
+
+/**********************************************************************
+ * SetDoubleClickTime (USER.20)
+ */
+void WINAPI SetDoubleClickTime16( UINT16 interval )
+{
+ SetDoubleClickTime( interval );
+}
+
+
+/**********************************************************************
+ * GetDoubleClickTime (USER.21)
+ */
+UINT16 WINAPI GetDoubleClickTime16(void)
+{
+ return GetDoubleClickTime();
+}
+
+
+/***********************************************************************
+ * PostQuitMessage (USER.6)
+ */
+void WINAPI PostQuitMessage16( INT16 exitCode )
+{
+ PostQuitMessage( exitCode );
+}
+
+
+/***********************************************************************
+ * SetMessageQueue (USER.266)
+ */
+BOOL16 WINAPI SetMessageQueue16( INT16 size )
+{
+ return SetMessageQueue( size );
+}
+
+
+/***********************************************************************
+ * GetQueueStatus (USER.334)
+ */
+DWORD WINAPI GetQueueStatus16( UINT16 flags )
+{
+ return GetQueueStatus( flags );
+}
+
+
+/***********************************************************************
+ * GetInputState (USER.335)
+ */
+BOOL16 WINAPI GetInputState16(void)
+{
+ return GetInputState();
+}
diff --git a/dlls/user/user.spec b/dlls/user/user.spec
index 6288023..bc215b1 100644
--- a/dlls/user/user.spec
+++ b/dlls/user/user.spec
@@ -112,8 +112,8 @@
105 pascal16 FlashWindow(word word) FlashWindow16
106 pascal16 GetKeyState(word) GetKeyState16
107 pascal DefWindowProc(word word word long) DefWindowProc16
-108 pascal16 GetMessage(segptr word word word) GetMessage16
-109 pascal16 PeekMessage(segptr word word word word) PeekMessage16
+108 pascal16 GetMessage(ptr word word word) GetMessage16
+109 pascal16 PeekMessage(ptr word word word word) PeekMessage16
110 pascal16 PostMessage(word word word long) PostMessage16
111 pascal SendMessage(word word word long) SendMessage16
112 pascal16 WaitMessage() WaitMessage
@@ -538,8 +538,8 @@
802 stub OPENFILENAME_CALLBACK16
803 stub PRINTDLG_CALLBACK16
804 stub CHOOSECOLOR_CALLBACK16
-819 pascal16 PeekMessage32(segptr word word word word word) PeekMessage32_16
-820 pascal GetMessage32(segptr word word word word) GetMessage32_16
+819 pascal16 PeekMessage32(ptr word word word word word) PeekMessage32_16
+820 pascal GetMessage32(ptr word word word word) GetMessage32_16
821 pascal16 TranslateMessage32(ptr word) TranslateMessage32_16
#821 stub IsDialogMessage32 # FIXME: two ordinal 821???
822 pascal DispatchMessage32(ptr word) DispatchMessage32_16
diff --git a/include/message.h b/include/message.h
index 1d9968b..f27bc6b 100644
--- a/include/message.h
+++ b/include/message.h
@@ -11,12 +11,14 @@
#include "wine/windef16.h"
#include "winproc.h"
-struct tagMSG;
-
/* message.c */
-extern BOOL MSG_InternalGetMessage( struct tagMSG *msg, HWND hwnd, HWND hwndOwner,
- UINT first, UINT last, WPARAM code,
- WORD flags, BOOL sendIdle, BOOL* idleSent );
+extern BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd_filter,
+ UINT first, UINT last, BOOL remove );
+extern BOOL MSG_process_cooked_hardware_message( MSG *msg, BOOL remove );
+extern void MSG_JournalPlayBackMsg(void);
+
+/* sendmsg.c */
+extern BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags );
/* timer.c */
extern void TIMER_RemoveWindowTimers( HWND hwnd );
diff --git a/include/queue.h b/include/queue.h
index b43eb16..2c94c73 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -30,12 +30,15 @@
CRITICAL_SECTION cSection; /* Critical section for thread safe access */
} PERQUEUEDATA;
+struct received_message_info;
+
/* Message queue */
typedef struct tagMESSAGEQUEUE
{
HQUEUE16 self; /* Handle to self (was: reserved) */
TEB* teb; /* Thread owning queue */
HANDLE server_queue; /* Handle to server-side queue */
+ struct received_message_info *receive_info; /* Info about message being currently received */
DWORD magic; /* magic number should be QUEUE_MAGIC */
DWORD lockCount; /* reference counter */
@@ -69,7 +72,6 @@
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_DeleteMsgQueue(void);
-extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern void QUEUE_CleanupWindow( HWND hwnd );
#endif /* __WINE_QUEUE_H */
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index a8d8a8a..ebf2721 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1338,20 +1338,31 @@
struct send_message_request
{
struct request_header __header;
- int kind;
void* id;
int type;
handle_t win;
unsigned int msg;
unsigned int wparam;
unsigned int lparam;
- unsigned short x;
- unsigned short y;
+ int x;
+ int y;
unsigned int time;
unsigned int info;
+ int timeout;
+ /* VARARG(data,bytes); */
};
-enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
-#define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
+
+enum message_type
+{
+ MSG_ASCII,
+ MSG_UNICODE,
+ MSG_NOTIFY,
+ MSG_CALLBACK,
+ MSG_OTHER_PROCESS,
+ MSG_POSTED,
+ MSG_HARDWARE_RAW,
+ MSG_HARDWARE_COOKED
+};
@@ -1362,16 +1373,16 @@
handle_t get_win;
unsigned int get_first;
unsigned int get_last;
- int kind;
int type;
handle_t win;
unsigned int msg;
unsigned int wparam;
unsigned int lparam;
- unsigned short x;
- unsigned short y;
+ int x;
+ int y;
unsigned int time;
unsigned int info;
+ /* VARARG(data,bytes); */
};
#define GET_MSG_REMOVE 1
#define GET_MSG_SENT_ONLY 2
@@ -1383,6 +1394,7 @@
struct request_header __header;
unsigned int result;
int remove;
+ /* VARARG(data,bytes); */
};
@@ -1392,14 +1404,7 @@
struct request_header __header;
int cancel;
unsigned int result;
-};
-
-
-
-struct in_send_message_request
-{
- struct request_header __header;
- int flags;
+ /* VARARG(data,bytes); */
};
@@ -1639,7 +1644,6 @@
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,
@@ -1767,7 +1771,6 @@
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;
@@ -1780,6 +1783,6 @@
struct connect_named_pipe_request connect_named_pipe;
};
-#define SERVER_PROTOCOL_VERSION 48
+#define SERVER_PROTOCOL_VERSION 49
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/include/wine/winuser16.h b/include/wine/winuser16.h
index 7fe3745..522cac2 100644
--- a/include/wine/winuser16.h
+++ b/include/wine/winuser16.h
@@ -561,8 +561,6 @@
BOOL16 WINAPI IsWindow16(HWND16);
INT16 WINAPI LookupIconIdFromDirectory16(LPBYTE,BOOL16);
UINT16 WINAPI MapVirtualKey16(UINT16,UINT16);
-LRESULT WINAPI SendMessageTimeout16(HWND16,UINT16,WPARAM16,LPARAM,UINT16,
- UINT16,LPWORD);
FARPROC16 WINAPI SetWindowsHook16(INT16,HOOKPROC16);
HHOOK WINAPI SetWindowsHookEx16(INT16,HOOKPROC16,HINSTANCE16,HTASK16);
BOOL16 WINAPI UnhookWindowsHook16(INT16,HOOKPROC16);
@@ -746,8 +744,8 @@
BOOL16 WINAPI GetMenuItemRect16(HWND16,HMENU16,UINT16,LPRECT16);
UINT16 WINAPI GetMenuState16(HMENU16,UINT16,UINT16);
INT16 WINAPI GetMenuString16(HMENU16,UINT16,LPSTR,INT16,UINT16);
-BOOL16 WINAPI GetMessage16(SEGPTR,HWND16,UINT16,UINT16);
-BOOL16 WINAPI GetMessage32_16(SEGPTR,HWND16,UINT16,UINT16,BOOL16);
+BOOL16 WINAPI GetMessage16(MSG16*,HWND16,UINT16,UINT16);
+BOOL16 WINAPI GetMessage32_16(MSG32_16*,HWND16,UINT16,UINT16,BOOL16);
HWND16 WINAPI GetNextDlgGroupItem16(HWND16,HWND16,BOOL16);
HWND16 WINAPI GetNextDlgTabItem16(HWND16,HWND16,BOOL16);
HWND16 WINAPI GetNextWindow16(HWND16,WORD);
@@ -825,8 +823,8 @@
void WINAPI OffsetRect16(LPRECT16,INT16,INT16);
BOOL16 WINAPI OpenClipboard16(HWND16);
BOOL16 WINAPI OpenIcon16(HWND16);
-BOOL16 WINAPI PeekMessage16(SEGPTR,HWND16,UINT16,UINT16,UINT16);
-BOOL16 WINAPI PeekMessage32_16(SEGPTR,HWND16,UINT16,UINT16,UINT16,BOOL16);
+BOOL16 WINAPI PeekMessage16(MSG16*,HWND16,UINT16,UINT16,UINT16);
+BOOL16 WINAPI PeekMessage32_16(MSG32_16*,HWND16,UINT16,UINT16,UINT16,BOOL16);
BOOL16 WINAPI PostAppMessage16(HTASK16,UINT16,WPARAM16,LPARAM);
BOOL16 WINAPI PostMessage16(HWND16,UINT16,WPARAM16,LPARAM);
void WINAPI PostQuitMessage16(INT16);
diff --git a/server/protocol.def b/server/protocol.def
index 32e9697..a4a7af8 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1195,20 +1195,31 @@
/* Send a message to a thread queue */
@REQ(send_message)
- int kind; /* message kind (see below) */
void* id; /* thread id */
- int type; /* message type */
+ int type; /* message type (see below) */
handle_t win; /* window handle */
unsigned int msg; /* message code */
unsigned int wparam; /* parameters */
unsigned int lparam; /* parameters */
- unsigned short x; /* x position */
- unsigned short y; /* y position */
+ int x; /* x position */
+ int y; /* y position */
unsigned int time; /* message time */
unsigned int info; /* extra info */
+ int timeout; /* timeout for reply */
+ VARARG(data,bytes); /* message data for sent messages */
@END
-enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
-#define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
+
+enum message_type
+{
+ MSG_ASCII, /* Ascii message (from SendMessageA) */
+ MSG_UNICODE, /* Unicode message (from SendMessageW) */
+ MSG_NOTIFY, /* notify message (from SendNotifyMessageW), always Unicode */
+ MSG_CALLBACK, /* callback message (from SendMessageCallbackW), always Unicode */
+ MSG_OTHER_PROCESS, /* sent from other process, may include vararg data, always Unicode */
+ MSG_POSTED, /* posted message (from PostMessageW), always Unicode */
+ MSG_HARDWARE_RAW, /* raw hardware message */
+ MSG_HARDWARE_COOKED /* cooked hardware message */
+};
/* Get a message from the current queue */
@@ -1218,16 +1229,16 @@
unsigned int get_first; /* first message code to get */
unsigned int get_last; /* last message code to get */
@REPLY
- int kind; /* message kind */
int type; /* message type */
handle_t win; /* window handle */
unsigned int msg; /* message code */
unsigned int wparam; /* parameters */
unsigned int lparam; /* parameters */
- unsigned short x; /* x position */
- unsigned short y; /* y position */
+ int x; /* x position */
+ int y; /* y position */
unsigned int time; /* message time */
unsigned int info; /* extra info */
+ VARARG(data,bytes); /* message data for sent messages */
@END
#define GET_MSG_REMOVE 1 /* remove the message */
#define GET_MSG_SENT_ONLY 2 /* only get sent messages */
@@ -1237,6 +1248,7 @@
@REQ(reply_message)
unsigned int result; /* message result */
int remove; /* should we remove the message? */
+ VARARG(data,bytes); /* message data for sent messages */
@END
@@ -1245,13 +1257,7 @@
int cancel; /* cancel message if not ready? */
@REPLY
unsigned int result; /* message result */
-@END
-
-
-/* Check if we are processing a sent message */
-@REQ(in_send_message)
-@REPLY
- int flags; /* ISMEX_* flags */
+ VARARG(data,bytes); /* message data for sent messages */
@END
diff --git a/server/queue.c b/server/queue.c
index 2c53a92..238e3a9 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -17,6 +17,10 @@
#include "process.h"
#include "request.h"
+enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
+#define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
+
+
struct message_result
{
struct message_result *send_next; /* next in sender list */
@@ -26,21 +30,26 @@
int replied; /* has it been replied to? */
unsigned int result; /* reply result */
unsigned int error; /* error code to pass back to sender */
+ void *data; /* message reply data */
+ unsigned int data_size; /* size of message reply data */
+ struct timeout_user *timeout; /* result timeout */
};
struct message
{
struct message *next; /* next message in list */
struct message *prev; /* prev message in list */
- int type; /* message type (FIXME) */
+ enum message_type type; /* message type */
handle_t win; /* window handle */
unsigned int msg; /* message code */
unsigned int wparam; /* parameters */
unsigned int lparam; /* parameters */
- unsigned short x; /* x position */
- unsigned short y; /* y position */
+ int x; /* x position */
+ int y; /* y position */
unsigned int time; /* message time */
unsigned int info; /* extra info */
+ void *data; /* message data for sent messages */
+ unsigned int data_size; /* size of message data */
struct message_result *result; /* result in sender queue */
};
@@ -141,14 +150,21 @@
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 )
+/* set some queue bits */
+inline static void set_queue_bits( struct msg_queue *queue, unsigned int bits )
{
- queue->wake_bits = (queue->wake_bits | set) & ~clear;
- queue->changed_bits = (queue->changed_bits | set) & ~clear;
+ queue->wake_bits |= bits;
+ queue->changed_bits |= bits;
if (is_signaled( queue )) wake_up( &queue->obj, 0 );
}
+/* clear some queue bits */
+inline static void clear_queue_bits( struct msg_queue *queue, unsigned int bits )
+{
+ queue->wake_bits &= ~bits;
+ queue->changed_bits &= ~bits;
+}
+
/* get the QS_* bit corresponding to a given hardware message */
inline static int get_hardware_msg_bit( struct message *msg )
{
@@ -203,6 +219,31 @@
return 1;
}
+/* free a result structure */
+static void free_result( struct message_result *result )
+{
+ if (result->timeout) remove_timeout_user( result->timeout );
+ if (result->data) free( result->data );
+ free( result );
+}
+
+/* store the message result in the appropriate structure */
+static void store_message_result( struct message_result *res, unsigned int result,
+ unsigned int error )
+{
+ res->result = result;
+ res->error = error;
+ res->replied = 1;
+ if (res->timeout)
+ {
+ remove_timeout_user( res->timeout );
+ res->timeout = NULL;
+ }
+ /* wake sender queue if waiting on this result */
+ if (res->sender && res->sender->send_result == res)
+ set_queue_bits( res->sender, QS_SMRESULT );
+}
+
/* free a message when deleting a queue or window */
static void free_message( struct message *msg )
{
@@ -211,16 +252,12 @@
{
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 );
+ store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
}
- else free( result );
+ else free_result( result );
}
+ if (msg->data) free( msg->data );
free( msg );
}
@@ -236,41 +273,59 @@
switch(kind)
{
case SEND_MESSAGE:
- if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
+ if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_SENDMESSAGE );
break;
case POST_MESSAGE:
- if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
+ if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_POSTMESSAGE );
break;
case COOKED_HW_MESSAGE:
case RAW_HW_MESSAGE:
clr_bit = get_hardware_msg_bit( msg );
for (other = queue->msg_list[kind].first; other; other = other->next)
if (get_hardware_msg_bit( other ) == clr_bit) break;
- if (!other) change_queue_bits( queue, 0, clr_bit );
+ if (!other) clear_queue_bits( queue, clr_bit );
break;
}
free_message( msg );
}
-/* 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 )
+/* message timed out without getting a reply */
+static void result_timeout( void *private )
+{
+ struct message_result *result = private;
+
+ assert( !result->replied );
+
+ result->timeout = NULL;
+ store_message_result( result, 0, STATUS_TIMEOUT );
+}
+
+/* allocate and fill a message result structure */
+static struct message_result *alloc_message_result( struct msg_queue *send_queue,
+ struct msg_queue *recv_queue,
+ unsigned int timeout )
{
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->msg_list[SEND_MESSAGE], msg );
- change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 );
- return 1;
+ if (result)
+ {
+ /* put the result on the sender result stack */
+ result->sender = send_queue;
+ result->receiver = recv_queue;
+ result->replied = 0;
+ result->data = NULL;
+ result->data_size = 0;
+ result->timeout = NULL;
+ result->send_next = send_queue->send_result;
+ send_queue->send_result = result;
+ if (timeout != -1)
+ {
+ struct timeval when;
+ gettimeofday( &when, 0 );
+ add_timeout( &when, timeout );
+ result->timeout = add_timeout_user( &when, result_timeout, result );
+ }
+ }
+ return result;
}
/* receive a message, removing it from the sent queue */
@@ -280,15 +335,19 @@
unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
/* put the result on the receiver result stack */
- result->recv_next = queue->recv_result;
- queue->recv_result = result;
+ if (result)
+ {
+ result->recv_next = queue->recv_result;
+ queue->recv_result = result;
+ }
+ if (msg->data) free( msg->data );
free( msg );
- if (!queue->msg_list[SEND_MESSAGE].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
+ if (!queue->msg_list[SEND_MESSAGE].first) clear_queue_bits( queue, 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 )
+ unsigned int error, int remove, void *data, size_t len )
{
struct message_result *res = queue->recv_result;
@@ -298,45 +357,17 @@
res->receiver = NULL;
if (!res->sender) /* no one waiting for it */
{
- free( res );
+ free_result( 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 );
+ if (len && (res->data = memdup( data, len ))) res->data_size = len;
+ store_message_result( res, result, error );
}
}
-/* 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 )
{
@@ -359,11 +390,12 @@
{
next = result->send_next;
result->sender = NULL;
- if (!result->receiver) free( result );
+ if (!result->receiver) free_result( result );
result = next;
}
- while (queue->recv_result) reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1 );
+ while (queue->recv_result)
+ reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
}
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
@@ -454,9 +486,9 @@
/* set/clear QS_TIMER bit */
if (queue->next_timer == queue->first_timer)
- change_queue_bits( queue, 0, QS_TIMER );
+ clear_queue_bits( queue, QS_TIMER );
else
- change_queue_bits( queue, QS_TIMER, 0 );
+ set_queue_bits( queue, QS_TIMER );
}
/* callback for the next timer expiration */
@@ -504,7 +536,7 @@
else queue->first_timer = timer->next;
/* check if we removed the next timer */
if (queue->next_timer == timer) set_next_timer( queue, timer->next );
- else if (queue->next_timer == queue->first_timer) change_queue_bits( queue, 0, QS_TIMER );
+ else if (queue->next_timer == queue->first_timer) clear_queue_bits( queue, QS_TIMER );
}
/* restart an expired timer */
@@ -620,9 +652,9 @@
if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
if (queue->paint_count)
- change_queue_bits( queue, QS_PAINT, 0 );
+ set_queue_bits( queue, QS_PAINT );
else
- change_queue_bits( queue, 0, QS_PAINT );
+ clear_queue_bits( queue, QS_PAINT );
}
else set_error( STATUS_INVALID_PARAMETER );
@@ -685,40 +717,64 @@
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->x = req->x;
- msg->y = req->y;
- msg->time = req->time;
- msg->info = req->info;
- msg->result = NULL;
- switch(req->kind)
+ msg->type = req->type;
+ msg->win = req->win;
+ msg->msg = req->msg;
+ msg->wparam = req->wparam;
+ msg->lparam = req->lparam;
+ msg->time = req->time;
+ msg->x = req->x;
+ msg->y = req->y;
+ msg->info = req->info;
+ msg->result = NULL;
+ msg->data = NULL;
+ msg->data_size = 0;
+
+ switch(msg->type)
{
- case SEND_MESSAGE:
- send_message( send_queue, recv_queue, msg );
- break;
- case POST_MESSAGE:
- append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
- change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 );
- break;
- case COOKED_HW_MESSAGE:
- case RAW_HW_MESSAGE:
- if (msg->msg == WM_MOUSEMOVE && merge_message( &recv_queue->msg_list[req->kind], msg ))
+ case MSG_OTHER_PROCESS:
+ msg->data_size = get_req_data_size(req);
+ if (msg->data_size && !(msg->data = memdup( get_req_data(req), msg->data_size )))
{
free( msg );
+ break;
}
- else
+ /* fall through */
+ case MSG_ASCII:
+ case MSG_UNICODE:
+ case MSG_CALLBACK:
+ if (!(msg->result = alloc_message_result( send_queue, recv_queue, req->timeout )))
{
- append_message( &recv_queue->msg_list[req->kind], msg );
- change_queue_bits( recv_queue, get_hardware_msg_bit(msg), 0 );
+ free( msg );
+ break;
}
+ /* fall through */
+ case MSG_NOTIFY:
+ append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
+ set_queue_bits( recv_queue, QS_SENDMESSAGE );
break;
+ case MSG_POSTED:
+ append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
+ set_queue_bits( recv_queue, QS_POSTMESSAGE );
+ break;
+ case MSG_HARDWARE_RAW:
+ case MSG_HARDWARE_COOKED:
+ {
+ struct message_list *list = ((msg->type == MSG_HARDWARE_RAW) ?
+ &recv_queue->msg_list[RAW_HW_MESSAGE] :
+ &recv_queue->msg_list[COOKED_HW_MESSAGE]);
+ if (msg->msg == WM_MOUSEMOVE && merge_message( list, msg ))
+ {
+ free( msg );
+ break;
+ }
+ append_message( list, msg );
+ set_queue_bits( recv_queue, get_hardware_msg_bit(msg) );
+ break;
+ }
default:
- free( msg );
set_error( STATUS_INVALID_PARAMETER );
+ free( msg );
break;
}
}
@@ -728,6 +784,8 @@
/* store a message contents into the request buffer; helper for get_message */
inline static void put_req_message( struct get_message_request *req, const struct message *msg )
{
+ int len = min( get_req_data_size(req), msg->data_size );
+
req->type = msg->type;
req->win = msg->win;
req->msg = msg->msg;
@@ -737,16 +795,17 @@
req->y = msg->y;
req->time = msg->time;
req->info = msg->info;
+ if (len) memcpy( get_req_data(req), msg->data, len );
+ set_req_data_size( req, len );
}
/* return a message to the application, removing it from the queue if needed */
static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
struct message *msg, enum message_kind kind )
{
- req->kind = kind;
put_req_message( req, msg );
/* raw messages always get removed */
- if ((kind == RAW_HW_MESSAGE) || (req->flags & GET_MSG_REMOVE))
+ if ((msg->type == MSG_HARDWARE_RAW) || (req->flags & GET_MSG_REMOVE))
{
queue->last_msg = NULL;
remove_queue_message( queue, msg, kind );
@@ -784,16 +843,20 @@
struct message *msg;
struct msg_queue *queue = get_current_queue();
- if (!queue) return;
+ if (!queue)
+ {
+ set_req_data_size( req, 0 );
+ return;
+ }
/* first check for sent messages */
if ((msg = queue->msg_list[SEND_MESSAGE].first))
{
- req->kind = SEND_MESSAGE;
put_req_message( req, msg );
receive_message( queue, msg );
return;
}
+ set_req_data_size( req, 0 ); /* only sent messages can have data */
if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
/* if requested, remove the last returned but not yet removed message */
@@ -831,8 +894,7 @@
if ((queue->wake_bits & QS_PAINT) &&
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
{
- req->kind = POST_MESSAGE;
- req->type = 0;
+ req->type = MSG_POSTED;
req->win = 0;
req->msg = WM_PAINT;
req->wparam = 0;
@@ -848,8 +910,7 @@
if ((timer = find_expired_timer( queue, req->get_win, req->get_first,
req->get_last, (req->flags & GET_MSG_REMOVE) )))
{
- req->kind = POST_MESSAGE;
- req->type = 0;
+ req->type = MSG_POSTED;
req->win = timer->win;
req->msg = timer->msg;
req->wparam = timer->id;
@@ -870,7 +931,8 @@
DECL_HANDLER(reply_message)
{
if (current->queue && current->queue->recv_result)
- reply_message( current->queue, req->result, 0, req->remove );
+ reply_message( current->queue, req->result, 0, req->remove,
+ get_req_data(req), get_req_data_size(req) );
else
set_error( STATUS_ACCESS_DENIED );
}
@@ -879,26 +941,40 @@
/* 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 );
-}
+ struct msg_queue *queue = current->queue;
+ size_t data_len = 0;
-
-/* check if we are processing a sent message */
-DECL_HANDLER(in_send_message)
-{
- int flags = 0;
-
- if (current->queue)
+ if (queue)
{
- struct message_result *result = current->queue->recv_result;
- if (result)
+ struct message_result *result = queue->send_result;
+
+ set_error( STATUS_PENDING );
+ req->result = 0;
+
+ if (result && (result->replied || req->cancel))
{
- flags |= ISMEX_SEND; /* FIXME */
- if (result->replied || !result->sender) flags |= ISMEX_REPLIED;
+ if (result->replied)
+ {
+ req->result = result->result;
+ set_error( result->error );
+ if (result->data)
+ {
+ data_len = min( result->data_size, get_req_data_size(req) );
+ memcpy( get_req_data(req), result->data, data_len );
+ free( result->data );
+ result->data = NULL;
+ result->data_size = 0;
+ }
+ }
+ queue->send_result = result->send_next;
+ result->sender = NULL;
+ if (!result->receiver) free_result( result );
+ if (!queue->send_result || !queue->send_result->replied)
+ clear_queue_bits( queue, QS_SMRESULT );
}
}
- req->flags = flags;
+ else set_error( STATUS_ACCESS_DENIED );
+ set_req_data_size( req, data_len );
}
diff --git a/server/request.h b/server/request.h
index 12725b4..c9882b5 100644
--- a/server/request.h
+++ b/server/request.h
@@ -175,7 +175,6 @@
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);
@@ -302,7 +301,6 @@
(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,
diff --git a/server/trace.c b/server/trace.c
index 438121c..225be9c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1457,17 +1457,19 @@
static void dump_send_message_request( const struct send_message_request *req )
{
- fprintf( stderr, " kind=%d,", req->kind );
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, " x=%04x,", req->x );
- fprintf( stderr, " y=%04x,", req->y );
+ fprintf( stderr, " x=%d,", req->x );
+ fprintf( stderr, " y=%d,", req->y );
fprintf( stderr, " time=%08x,", req->time );
- fprintf( stderr, " info=%08x", req->info );
+ fprintf( stderr, " info=%08x,", req->info );
+ fprintf( stderr, " timeout=%d,", req->timeout );
+ fprintf( stderr, " data=" );
+ cur_pos += dump_varargs_bytes( req );
}
static void dump_get_message_request( const struct get_message_request *req )
@@ -1480,22 +1482,25 @@
static void dump_get_message_reply( const struct get_message_request *req )
{
- fprintf( stderr, " kind=%d,", req->kind );
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, " x=%04x,", req->x );
- fprintf( stderr, " y=%04x,", req->y );
+ fprintf( stderr, " x=%d,", req->x );
+ fprintf( stderr, " y=%d,", req->y );
fprintf( stderr, " time=%08x,", req->time );
- fprintf( stderr, " info=%08x", req->info );
+ fprintf( stderr, " info=%08x,", req->info );
+ fprintf( stderr, " data=" );
+ cur_pos += dump_varargs_bytes( req );
}
static void dump_reply_message_request( const struct reply_message_request *req )
{
fprintf( stderr, " result=%08x,", req->result );
- fprintf( stderr, " remove=%d", req->remove );
+ fprintf( stderr, " remove=%d,", req->remove );
+ fprintf( stderr, " data=" );
+ cur_pos += dump_varargs_bytes( req );
}
static void dump_get_message_reply_request( const struct get_message_reply_request *req )
@@ -1505,16 +1510,9 @@
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 );
+ fprintf( stderr, " result=%08x,", req->result );
+ fprintf( stderr, " data=" );
+ cur_pos += dump_varargs_bytes( req );
}
static void dump_cleanup_window_queue_request( const struct cleanup_window_queue_request *req )
@@ -1739,7 +1737,6 @@
(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,
@@ -1863,7 +1860,6 @@
(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,
@@ -1987,7 +1983,6 @@
"get_message",
"reply_message",
"get_message_reply",
- "in_send_message",
"cleanup_window_queue",
"set_win_timer",
"kill_win_timer",
diff --git a/windows/input.c b/windows/input.c
index 62c7518..f371e61 100644
--- a/windows/input.c
+++ b/windows/input.c
@@ -85,9 +85,8 @@
{
SERVER_START_REQ( send_message )
{
- req->kind = RAW_HW_MESSAGE;
req->id = (void *)GetCurrentThreadId();
- req->type = 0;
+ req->type = MSG_HARDWARE_RAW;
req->win = 0;
req->msg = message;
req->wparam = wParam;
@@ -96,6 +95,7 @@
req->y = yPos;
req->time = time;
req->info = extraInfo;
+ req->timeout = 0;
SERVER_CALL();
}
SERVER_END_REQ;
diff --git a/windows/message.c b/windows/message.c
index 7658e52..7134d04 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -10,8 +10,9 @@
#include <sys/time.h>
#include <sys/types.h>
-#include "wine/winbase16.h"
-#include "wine/winuser16.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
#include "message.h"
#include "winerror.h"
#include "wine/server.h"
@@ -36,109 +37,8 @@
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
-#define QMSG_WIN16 1
-#define QMSG_WIN32A 2
-#define QMSG_WIN32W 3
-
static UINT doubleClickSpeed = 452;
-static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType );
-
-
-
-/* flag for messages that contain pointers */
-/* 16 messages per entry, messages 0..15 map to bits 0..15 */
-
-#define SET(msg) (1 << ((msg) & 15))
-
-static const unsigned short message_pointer_flags[] =
-{
- /* 0x00 - 0x0f */
- SET(WM_CREATE) | SET(WM_GETTEXT) | SET(WM_SETTEXT),
- /* 0x10 - 0x1f */
- SET(WM_WININICHANGE),
- /* 0x20 - 0x2f */
- SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM),
- /* 0x30 - 0x3f */
- SET(WM_COMPAREITEM),
- /* 0x40 - 0x4f */
- SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) | SET(WM_NOTIFY),
- /* 0x50 - 0x5f */
- SET(WM_HELP),
- /* 0x60 - 0x6f */
- 0,
- /* 0x70 - 0x7f */
- SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED),
- /* 0x80 - 0x8f */
- SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE),
- /* 0x90 - 0x9f */
- 0,
- /* 0xa0 - 0xaf */
- 0,
- /* 0xb0 - 0xbf */
- SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP),
- /* 0xc0 - 0xcf */
- SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS),
- /* 0xd0 - 0xdf */
- 0,
- /* 0xe0 - 0xef */
- 0,
- /* 0xf0 - 0xff */
- 0,
- /* 0x100 - 0x10f */
- 0,
- /* 0x110 - 0x11f */
- 0,
- /* 0x120 - 0x12f */
- 0,
- /* 0x130 - 0x13f */
- 0,
- /* 0x140 - 0x14f */
- SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) | SET(CB_INSERTSTRING) |
- SET(CB_FINDSTRING) | SET(CB_SELECTSTRING),
- /* 0x150 - 0x15f */
- SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT),
- /* 0x160 - 0x16f */
- 0,
- /* 0x170 - 0x17f */
- 0,
- /* 0x180 - 0x18f */
- SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) |
- SET(LB_DIR) | SET(LB_FINDSTRING),
- /* 0x190 - 0x19f */
- SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT),
- /* 0x1a0 - 0x1af */
- SET(LB_FINDSTRINGEXACT),
- /* 0x1b0 - 0x1bf */
- 0,
- /* 0x1c0 - 0x1cf */
- 0,
- /* 0x1d0 - 0x1df */
- 0,
- /* 0x1e0 - 0x1ef */
- 0,
- /* 0x1f0 - 0x1ff */
- 0,
- /* 0x200 - 0x20f */
- 0,
- /* 0x210 - 0x21f */
- 0,
- /* 0x220 - 0x22f */
- SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) |
- SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE)
-};
-
-#undef SET
-
-/***********************************************************************
- * is_pointer_message
- */
-inline static int is_pointer_message( UINT message )
-{
- if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
- return (message_pointer_flags[message / 16] & (1 << (message & 15))) != 0;
-}
-
/***********************************************************************
* is_keyboard_message
@@ -177,50 +77,14 @@
/***********************************************************************
- * map_wparam_AtoW
+ * process_sent_messages
*
- * Convert the wparam of an ASCII message to Unicode.
+ * Process all pending sent messages.
*/
-static WPARAM map_wparam_AtoW( UINT message, WPARAM wparam )
+inline static void process_sent_messages(void)
{
- if (message == WM_CHARTOITEM ||
- message == EM_SETPASSWORDCHAR ||
- message == WM_CHAR ||
- message == WM_DEADCHAR ||
- message == WM_SYSCHAR ||
- message == WM_SYSDEADCHAR ||
- message == WM_MENUCHAR)
- {
- char ch = LOWORD(wparam);
- WCHAR wch;
- MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
- wparam = MAKEWPARAM( wch, HIWORD(wparam) );
- }
- return wparam;
-}
-
-
-/***********************************************************************
- * map_wparam_WtoA
- *
- * Convert the wparam of a Unicode message to ASCII.
- */
-static WPARAM map_wparam_WtoA( UINT message, WPARAM wparam )
-{
- if (message == WM_CHARTOITEM ||
- message == EM_SETPASSWORDCHAR ||
- message == WM_CHAR ||
- message == WM_DEADCHAR ||
- message == WM_SYSCHAR ||
- message == WM_SYSDEADCHAR ||
- message == WM_MENUCHAR)
- {
- WCHAR wch = LOWORD(wparam);
- char ch;
- WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
- wparam = MAKEWPARAM( ch, HIWORD(wparam) );
- }
- return wparam;
+ MSG msg;
+ MSG_peek_message( &msg, 0, 0, 0, GET_MSG_REMOVE | GET_MSG_SENT_ONLY );
}
@@ -229,13 +93,12 @@
*
* store a hardware message in the thread queue
*/
-static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message_kind kind )
+static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message_type type )
{
SERVER_START_REQ( send_message )
{
- req->kind = kind;
+ req->type = type;
req->id = (void *)GetWindowThreadProcessId( msg->hwnd, NULL );
- req->type = 0;
req->win = msg->hwnd;
req->msg = msg->message;
req->wparam = msg->wParam;
@@ -244,6 +107,7 @@
req->y = msg->pt.y;
req->time = msg->time;
req->info = extra_info;
+ req->timeout = 0;
SERVER_CALL();
}
SERVER_END_REQ;
@@ -283,7 +147,7 @@
*
* Get an EVENTMSG struct via call JOURNALPLAYBACK hook function
*/
-static void MSG_JournalPlayBackMsg(void)
+void MSG_JournalPlayBackMsg(void)
{
EVENTMSG tmpMsg;
MSG msg;
@@ -324,7 +188,7 @@
msg.lParam |= 0x01000000;
msg.pt.x = msg.pt.y = 0;
- queue_hardware_message( &msg, 0, RAW_HW_MESSAGE );
+ queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW );
}
else if ((tmpMsg.message>= WM_MOUSEFIRST) && (tmpMsg.message <= WM_MOUSELAST))
{
@@ -355,7 +219,7 @@
msg.pt.x = tmpMsg.paramL;
msg.pt.y = tmpMsg.paramH;
- queue_hardware_message( &msg, 0, RAW_HW_MESSAGE );
+ queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW );
}
HOOK_CallHooksA( WH_JOURNALPLAYBACK, HC_SKIP, 0, (LPARAM)&tmpMsg);
}
@@ -626,8 +490,8 @@
*
* returns TRUE if the contents of 'msg' should be passed to the application
*/
-static BOOL process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd_filter,
- UINT first, UINT last, BOOL remove )
+BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd_filter,
+ UINT first, UINT last, BOOL remove )
{
if (is_keyboard_message( msg->message ))
{
@@ -648,22 +512,22 @@
GetWindowThreadProcessId( msg->hwnd, NULL ) != GetCurrentThreadId())
{
/* queue it for later, or for another thread */
- queue_hardware_message( msg, extra_info, COOKED_HW_MESSAGE );
+ queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED );
return FALSE;
}
/* save the message in the cooked queue if we didn't want to remove it */
- if (!remove) queue_hardware_message( msg, extra_info, COOKED_HW_MESSAGE );
+ if (!remove) queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED );
return TRUE;
}
/***********************************************************************
- * process_cooked_hardware_message
+ * MSG_process_cooked_hardware_message
*
* returns TRUE if the contents of 'msg' should be passed to the application
*/
-static BOOL process_cooked_hardware_message( MSG *msg, BOOL remove )
+BOOL MSG_process_cooked_hardware_message( MSG *msg, BOOL remove )
{
if (is_keyboard_message( msg->message ))
return process_cooked_keyboard_message( msg, remove );
@@ -676,249 +540,6 @@
}
-/***********************************************************************
- * handle_sent_message
- *
- * Handle the reception of a sent message by calling the corresponding window proc
- */
-static void handle_sent_message( MSG *msg, int type, ULONG_PTR extra_info )
-{
- LRESULT result = 0;
- MESSAGEQUEUE *queue = QUEUE_Current();
- ULONG_PTR old_extra_info = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
- WND *wndPtr = WIN_FindWndPtr( msg->hwnd );
-
- TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
- msg->hwnd, msg->message, SPY_GetMsgName(msg->message),
- msg->wParam, msg->lParam );
-
- queue->GetMessageExtraInfoVal = extra_info;
-
- /* call the right version of CallWindowProcXX */
- switch(type)
- {
- case QMSG_WIN16:
- result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
- (HWND16) msg->hwnd,
- (UINT16) msg->message,
- LOWORD(msg->wParam),
- msg->lParam );
- break;
- case QMSG_WIN32A:
- result = CallWindowProcA( wndPtr->winproc, msg->hwnd, msg->message,
- msg->wParam, msg->lParam );
- break;
- case QMSG_WIN32W:
- result = CallWindowProcW( wndPtr->winproc, msg->hwnd, msg->message,
- msg->wParam, msg->lParam );
- break;
- }
-
- queue->GetMessageExtraInfoVal = old_extra_info; /* Restore extra info */
- WIN_ReleaseWndPtr(wndPtr);
-
- SERVER_START_REQ( reply_message )
- {
- req->result = result;
- req->remove = 1;
- SERVER_CALL();
- }
- SERVER_END_REQ;
-}
-
-
-/***********************************************************************
- * process_sent_messages
- *
- * Process all pending sent messages
- */
-static void process_sent_messages(void)
-{
- MSG msg;
- int type;
- unsigned int res;
- ULONG_PTR extra_info;
-
- for (;;)
- {
- SERVER_START_REQ( get_message )
- {
- req->flags = GET_MSG_REMOVE | GET_MSG_SENT_ONLY;
- req->get_win = 0;
- req->get_first = 0;
- req->get_last = ~0;
- if (!(res = SERVER_CALL()))
- {
- type = req->type;
- msg.hwnd = req->win;
- msg.message = req->msg;
- msg.wParam = req->wparam;
- msg.lParam = req->lparam;
- msg.time = req->time;
- msg.pt.x = req->x;
- msg.pt.y = req->y;
- extra_info = req->info;
- }
- }
- SERVER_END_REQ;
-
- if (res) break;
- handle_sent_message( &msg, type, extra_info );
- }
-}
-
-
-
-/***********************************************************************
- * peek_message
- *
- * Peek for a message matching the given parameters. Return FALSE if none available.
- */
-static BOOL peek_message( HWND hwnd, UINT first, UINT last, int flags, int type,
- MSG *msg, ULONG_PTR *extra_info )
-{
- BOOL ret = FALSE;
- enum message_kind kind;
- int msg_type;
-
- if (!first && !last) last = ~0;
-
- for (;;)
- {
- SERVER_START_REQ( get_message )
- {
- req->flags = flags;
- req->get_win = hwnd;
- req->get_first = first;
- req->get_last = last;
- if ((ret = !SERVER_CALL()))
- {
- kind = req->kind;
- msg_type = req->type;
- msg->hwnd = req->win;
- msg->message = req->msg;
- msg->wParam = req->wparam;
- msg->lParam = req->lparam;
- msg->time = req->time;
- msg->pt.x = req->x;
- msg->pt.y = req->y;
- *extra_info = req->info;
- }
- }
- SERVER_END_REQ;
-
- if (!ret) return FALSE;
-
- switch(kind)
- {
- case SEND_MESSAGE:
- handle_sent_message( msg, msg_type, *extra_info );
- continue;
- case POST_MESSAGE:
- /* try to convert message to requested type */
- if (!MSG_ConvertMsg( msg, msg_type, type ))
- {
- ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
- SPY_GetMsgName(msg->message));
- /* remove it */
- flags |= GET_MSG_REMOVE_LAST;
- continue;
- }
- break;
- case RAW_HW_MESSAGE:
- if (!process_raw_hardware_message( msg, *extra_info,
- hwnd, first, last, flags & GET_MSG_REMOVE ))
- continue;
- /* fall through */
- case COOKED_HW_MESSAGE:
- if (!process_cooked_hardware_message( msg, flags & GET_MSG_REMOVE ))
- {
- flags |= GET_MSG_REMOVE_LAST;
- continue;
- }
- break;
- }
-
- /* now we got something */
- TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
- msg->hwnd, msg->message, SPY_GetMsgName(msg->message),
- msg->wParam, msg->lParam );
- return TRUE;
- }
-}
-
-
-/***********************************************************************
- * wait_queue_bits
- *
- * See "Windows Internals", p.447
- *
- * return values:
- * 0 if exit with timeout
- * 1 otherwise
- */
-static int wait_queue_bits( WORD bits, DWORD timeout )
-{
- MESSAGEQUEUE *queue;
-
- if (!(queue = QUEUE_Current())) return 0;
-
- TRACE("q %04x waiting for %04x\n", queue->self, bits);
-
- for (;;)
- {
- unsigned int wake_bits = 0, changed_bits = 0;
- DWORD dwlc;
-
- 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 (changed_bits & bits)
- {
- /* One of the bits is set; we can return */
- return 1;
- }
- if (wake_bits & QS_SENDMESSAGE)
- {
- /* Process the sent message immediately */
- process_sent_messages();
- continue; /* nested sm crux */
- }
-
- 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.pMsgWaitForMultipleObjectsEx)
- USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, timeout, 0, 0 );
- else
- WaitForSingleObject( queue->server_queue, timeout );
- if (dwlc) RestoreThunkLock( dwlc );
- }
-}
-
-
-/**********************************************************************
- * SetDoubleClickTime (USER.20)
- */
-void WINAPI SetDoubleClickTime16( UINT16 interval )
-{
- SetDoubleClickTime( interval );
-}
-
-
/**********************************************************************
* SetDoubleClickTime (USER32.@)
*/
@@ -930,15 +551,6 @@
/**********************************************************************
- * GetDoubleClickTime (USER.21)
- */
-UINT16 WINAPI GetDoubleClickTime16(void)
-{
- return doubleClickSpeed;
-}
-
-
-/**********************************************************************
* GetDoubleClickTime (USER32.@)
*/
UINT WINAPI GetDoubleClickTime(void)
@@ -948,986 +560,6 @@
/***********************************************************************
- * MSG_SendMessageInterThread
- *
- * Implementation of an inter-task SendMessage.
- * Return values:
- * 0 if error or timeout
- * 1 if successful
- */
-static LRESULT MSG_SendMessageInterThread( DWORD dest_tid, HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam,
- DWORD timeout, WORD type,
- LRESULT *pRes)
-{
- BOOL ret;
- int iWndsLocks;
- LRESULT result = 0;
-
- TRACE( "hwnd %x msg %x (%s) wp %x lp %lx\n", hwnd, msg, SPY_GetMsgName(msg), wParam, lParam );
-
- SERVER_START_REQ( send_message )
- {
- req->kind = SEND_MESSAGE;
- req->id = (void *)dest_tid;
- req->type = type;
- req->win = hwnd;
- req->msg = msg;
- req->wparam = wParam;
- req->lparam = lParam;
- req->x = 0;
- req->y = 0;
- req->time = GetCurrentTime();
- req->info = 0;
- ret = !SERVER_CALL_ERR();
- }
- SERVER_END_REQ;
- if (!ret) return 0;
-
- iWndsLocks = WIN_SuspendWndsLock();
-
- /* wait for the result */
- wait_queue_bits( QS_SMRESULT, timeout );
-
- SERVER_START_REQ( get_message_reply )
- {
- req->cancel = 1;
- if ((ret = !SERVER_CALL_ERR())) result = req->result;
- }
- SERVER_END_REQ;
-
- TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
- hwnd, msg, SPY_GetMsgName(msg), wParam, lParam, result, GetLastError() );
-
- if (!ret && (GetLastError() == ERROR_IO_PENDING))
- {
- if (timeout == INFINITE) ERR("no timeout but no result\n");
- SetLastError(0); /* timeout */
- }
-
- if (pRes) *pRes = result;
-
- WIN_RestoreWndsLock(iWndsLocks);
- return ret;
-}
-
-
-/***********************************************************************
- * ReplyMessage (USER.115)
- */
-void WINAPI ReplyMessage16( LRESULT result )
-{
- ReplyMessage( result );
-}
-
-/***********************************************************************
- * ReplyMessage (USER32.@)
- */
-BOOL WINAPI ReplyMessage( LRESULT result )
-{
- BOOL ret;
- SERVER_START_REQ( reply_message )
- {
- req->result = result;
- req->remove = 0;
- ret = !SERVER_CALL_ERR();
- }
- SERVER_END_REQ;
- return ret;
-}
-
-/***********************************************************************
- * MSG_ConvertMsg
- */
-static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType )
-{
- if (srcType == QMSG_WIN32A || dstType == QMSG_WIN32A)
- {
- /* posted messages are always either Win16 or Unicode Win32,
- * QMSG_WIN32A is only for sent messages */
- ERR( "invalid type %d/%d\n", srcType, dstType );
- return FALSE;
- }
-
- if (!srcType || srcType == dstType) return TRUE;
-
- if (srcType == QMSG_WIN16)
- {
- if (dstType == QMSG_WIN32W)
- {
- switch ( WINPROC_MapMsg16To32W( msg->hwnd, msg->message, msg->wParam,
- &msg->message, &msg->wParam, &msg->lParam ) )
- {
- case 0:
- return TRUE;
- case 1:
- /* Pointer messages were mapped --> need to free allocated memory and fail */
- WINPROC_UnmapMsg16To32W( msg->hwnd, msg->message, msg->wParam, msg->lParam, 0 );
- default:
- return FALSE;
- }
- }
- }
- else if (srcType == QMSG_WIN32W)
- {
- if (dstType == QMSG_WIN16)
- {
- UINT16 msg16;
- MSGPARAM16 mp16;
-
- mp16.lParam = msg->lParam;
- switch ( WINPROC_MapMsg32WTo16( msg->hwnd, msg->message, msg->wParam,
- &msg16, &mp16.wParam, &mp16.lParam ) )
- {
- case 0:
- msg->message = msg16;
- msg->wParam = mp16.wParam;
- msg->lParam = mp16.lParam;
- return TRUE;
- case 1:
- /* Pointer messages were mapped --> need to free allocated memory and fail */
- WINPROC_UnmapMsg32WTo16( msg->hwnd, msg->message, msg->wParam, msg->lParam, &mp16 );
- default:
- return FALSE;
- }
- }
- }
-
- FIXME( "Invalid message type(s): %d / %d\n", srcType, dstType );
- return FALSE;
-}
-
-
-/***********************************************************************
- * MSG_PeekMessage
- */
-static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
- DWORD first, DWORD last, WORD flags, BOOL peek )
-{
- int mask, msg_flags = 0;
- MESSAGEQUEUE *msgQueue;
- int iWndsLocks;
- MSG msg;
- ULONG_PTR extra_info;
-
- mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
- if (first || last)
- {
- if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
- if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
- ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
- if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
- if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
- if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
- }
- else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
-
- if (IsTaskLocked16()) flags |= PM_NOYIELD;
-
- iWndsLocks = WIN_SuspendWndsLock();
-
- /* check for graphics events */
- if (USER_Driver.pMsgWaitForMultipleObjectsEx)
- USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
-
- if (flags & PM_REMOVE) msg_flags |= GET_MSG_REMOVE;
-
- while(1)
- {
- if (peek_message( hwnd, first, last, msg_flags, type, &msg, &extra_info ))
- {
- /* need to fill the window handle for WM_PAINT message */
- if (msg.message == WM_PAINT)
- {
- if ((msg.hwnd = WIN_FindWinToRepaint( hwnd )))
- {
- if (IsIconic( msg.hwnd ) && GetClassLongA( msg.hwnd, GCL_HICON ))
- {
- msg.message = WM_PAINTICON;
- msg.wParam = 1;
- }
- if( !hwnd || msg.hwnd == hwnd || IsChild(hwnd,msg.hwnd) )
- {
- /* clear internal paint flag */
- RedrawWindow( msg.hwnd, NULL, 0,
- RDW_NOINTERNALPAINT | RDW_NOCHILDREN );
- break;
- }
- }
- }
- else break;
- }
-
- /* FIXME: should be done before checking for hw events */
- MSG_JournalPlayBackMsg();
-
- if (peek)
- {
-#if 0 /* FIXME */
- if (!(flags & PM_NOYIELD)) UserYield16();
-#endif
- WIN_RestoreWndsLock(iWndsLocks);
- return FALSE;
- }
-
- wait_queue_bits( mask, INFINITE );
- }
-
- WIN_RestoreWndsLock(iWndsLocks);
-
- if ((msgQueue = QUEUE_Current()))
- {
- msgQueue->GetMessageTimeVal = msg.time;
- msgQueue->GetMessagePosVal = MAKELONG( msg.pt.x, msg.pt.y );
- msgQueue->GetMessageExtraInfoVal = extra_info;
- }
-
- /* We got a message */
- if (flags & PM_REMOVE)
- {
- if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
- {
- BYTE *p = &QueueKeyStateTable[msg.wParam & 0xff];
-
- if (!(*p & 0x80))
- *p ^= 0x01;
- *p |= 0x80;
- }
- else if (msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
- QueueKeyStateTable[msg.wParam & 0xff] &= ~0x80;
- }
-
- /* copy back our internal safe copy of message data to msg_out.
- * msg_out is a variable from the *program*, so it can't be used
- * internally as it can get "corrupted" by our use of SendMessage()
- * (back to the program) inside the message handling itself. */
- *msg_out = msg;
- if (peek)
- return TRUE;
-
- else
- return (msg.message != WM_QUIT);
-}
-
-/***********************************************************************
- * MSG_InternalGetMessage
- *
- * GetMessage() function for internal use. Behave like GetMessage(),
- * but also call message filters and optionally send WM_ENTERIDLE messages.
- * 'hwnd' must be the handle of the dialog or menu window.
- * 'code' is the message filter value (MSGF_??? codes).
- */
-BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd, HWND hwndOwner, UINT first, UINT last,
- WPARAM code, WORD flags, BOOL sendIdle, BOOL* idleSent )
-{
- for (;;)
- {
- if (sendIdle)
- {
- if (!MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, TRUE ))
- {
- /* No message present -> send ENTERIDLE and wait */
- if (IsWindow(hwndOwner))
- {
- SendMessageA( hwndOwner, WM_ENTERIDLE,
- code, (LPARAM)hwnd );
-
- if (idleSent!=NULL)
- *idleSent=TRUE;
- }
- MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, FALSE );
- }
- }
- else /* Always wait for a message */
- MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, FALSE );
-
- /* Call message filters */
-
- if (HOOK_IsHooked( WH_SYSMSGFILTER ) || HOOK_IsHooked( WH_MSGFILTER ))
- {
- MSG tmp_msg = *msg;
-
- if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)&tmp_msg ) ||
- HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)&tmp_msg ))
- {
- /* Message filtered -> remove it from the queue if it's still there. */
- if (!(flags & PM_REMOVE))
- MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, PM_REMOVE, TRUE );
- continue;
- }
- }
- /* need to return an ASCII message (FIXME) */
- msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
- return (msg->message != WM_QUIT);
- }
-}
-
-
-/***********************************************************************
- * PeekMessage32 (USER.819)
- */
-BOOL16 WINAPI PeekMessage32_16( SEGPTR msg16_32, HWND16 hwnd,
- UINT16 first, UINT16 last, UINT16 flags,
- BOOL16 wHaveParamHigh )
-{
- BOOL ret;
- MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
- MSG msg;
-
- ret = MSG_PeekMessage( QMSG_WIN16, &msg, hwnd, first, last, flags, TRUE );
-
- lpmsg16_32->msg.hwnd = msg.hwnd;
- lpmsg16_32->msg.message = msg.message;
- lpmsg16_32->msg.wParam = LOWORD(msg.wParam);
- lpmsg16_32->msg.lParam = msg.lParam;
- lpmsg16_32->msg.time = msg.time;
- lpmsg16_32->msg.pt.x = (INT16)msg.pt.x;
- lpmsg16_32->msg.pt.y = (INT16)msg.pt.y;
-
- if ( wHaveParamHigh )
- lpmsg16_32->wParamHigh = HIWORD(msg.wParam);
-
- HOOK_CallHooks16( WH_GETMESSAGE, HC_ACTION, flags & PM_REMOVE, (LPARAM)msg16_32 );
- return ret;
-}
-
-/***********************************************************************
- * PeekMessage (USER.109)
- */
-BOOL16 WINAPI PeekMessage16( SEGPTR msg, HWND16 hwnd,
- UINT16 first, UINT16 last, UINT16 flags )
-{
- return PeekMessage32_16( msg, hwnd, first, last, flags, FALSE );
-}
-
-/***********************************************************************
- * PeekMessageA (USER32.@)
- */
-BOOL WINAPI PeekMessageA( LPMSG lpmsg, HWND hwnd, UINT min, UINT max, UINT flags )
-{
- BOOL ret = PeekMessageW( lpmsg, hwnd, min, max, flags );
- if (ret) lpmsg->wParam = map_wparam_WtoA( lpmsg->message, lpmsg->wParam );
- return ret;
-}
-
-/***********************************************************************
- * PeekMessageW (USER32.@) Check queue for messages
- *
- * Checks for a message in the thread's queue, filtered as for
- * GetMessage(). Returns immediately whether a message is available
- * or not.
- *
- * Whether a retrieved message is removed from the queue is set by the
- * _wRemoveMsg_ flags, which should be one of the following values:
- *
- * PM_NOREMOVE Do not remove the message from the queue.
- *
- * PM_REMOVE Remove the message from the queue.
- *
- * In addition, PM_NOYIELD may be combined into _wRemoveMsg_ to
- * request that the system not yield control during PeekMessage();
- * however applications may not rely on scheduling behavior.
- *
- * RETURNS
- *
- * Nonzero if a message is available and is retrieved, zero otherwise.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- *
- */
-BOOL WINAPI PeekMessageW(
- LPMSG lpmsg, /* [out] buffer to receive message */
- HWND hwnd, /* [in] restrict to messages for hwnd */
- UINT min, /* [in] minimum message to receive */
- UINT max, /* [in] maximum message to receive */
- UINT wRemoveMsg /* [in] removal flags */
-)
-{
- BOOL ret = MSG_PeekMessage( QMSG_WIN32W, lpmsg, hwnd, min, max, wRemoveMsg, TRUE );
- if (ret) HOOK_CallHooksW( WH_GETMESSAGE, HC_ACTION,
- wRemoveMsg & PM_REMOVE, (LPARAM)lpmsg );
- return ret;
-}
-
-
-/***********************************************************************
- * GetMessage32 (USER.820)
- */
-BOOL16 WINAPI GetMessage32_16( SEGPTR msg16_32, HWND16 hWnd, UINT16 first,
- UINT16 last, BOOL16 wHaveParamHigh )
-{
- MSG32_16 *lpmsg16_32 = MapSL(msg16_32);
- MSG msg;
-
- MSG_PeekMessage( QMSG_WIN16, &msg, hWnd, first, last, PM_REMOVE, FALSE );
-
- lpmsg16_32->msg.hwnd = msg.hwnd;
- lpmsg16_32->msg.message = msg.message;
- lpmsg16_32->msg.wParam = LOWORD(msg.wParam);
- lpmsg16_32->msg.lParam = msg.lParam;
- lpmsg16_32->msg.time = msg.time;
- lpmsg16_32->msg.pt.x = (INT16)msg.pt.x;
- lpmsg16_32->msg.pt.y = (INT16)msg.pt.y;
-
- if ( wHaveParamHigh )
- lpmsg16_32->wParamHigh = HIWORD(msg.wParam);
-
- TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
- lpmsg16_32->msg.message, hWnd, first, last );
-
- HOOK_CallHooks16( WH_GETMESSAGE, HC_ACTION, PM_REMOVE, (LPARAM)msg16_32 );
- return lpmsg16_32->msg.message != WM_QUIT;
-}
-
-/***********************************************************************
- * GetMessage (USER.108)
- */
-BOOL16 WINAPI GetMessage16( SEGPTR msg, HWND16 hwnd, UINT16 first, UINT16 last)
-{
- return GetMessage32_16( msg, hwnd, first, last, FALSE );
-}
-
-/***********************************************************************
- * GetMessageA (USER32.@)
- */
-BOOL WINAPI GetMessageA( MSG *lpmsg, HWND hwnd, UINT min, UINT max )
-{
- GetMessageW( lpmsg, hwnd, min, max );
- lpmsg->wParam = map_wparam_WtoA( lpmsg->message, lpmsg->wParam );
- return lpmsg->message != WM_QUIT;
-}
-
-/***********************************************************************
- * GetMessageW (USER32.@) Retrieve next message
- *
- * GetMessage retrieves the next event from the calling thread's
- * queue and deposits it in *lpmsg.
- *
- * If _hwnd_ is not NULL, only messages for window _hwnd_ and its
- * children as specified by IsChild() are retrieved. If _hwnd_ is NULL
- * all application messages are retrieved.
- *
- * _min_ and _max_ specify the range of messages of interest. If
- * min==max==0, no filtering is performed. Useful examples are
- * WM_KEYFIRST and WM_KEYLAST to retrieve keyboard input, and
- * WM_MOUSEFIRST and WM_MOUSELAST to retrieve mouse input.
- *
- * WM_PAINT messages are not removed from the queue; they remain until
- * processed. Other messages are removed from the queue.
- *
- * RETURNS
- *
- * -1 on error, 0 if message is WM_QUIT, nonzero otherwise.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- *
- */
-BOOL WINAPI GetMessageW(
- MSG* lpmsg, /* [out] buffer to receive message */
- HWND hwnd, /* [in] restrict to messages for hwnd */
- UINT min, /* [in] minimum message to receive */
- UINT max /* [in] maximum message to receive */
-)
-{
- MSG_PeekMessage( QMSG_WIN32W, lpmsg, hwnd, min, max, PM_REMOVE, FALSE );
-
- TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
- lpmsg->message, hwnd, min, max );
-
- HOOK_CallHooksW( WH_GETMESSAGE, HC_ACTION, PM_REMOVE, (LPARAM)lpmsg );
- return lpmsg->message != WM_QUIT;
-}
-
-/***********************************************************************
- * MSG_PostToQueue
- */
-static BOOL MSG_PostToQueue( DWORD tid, int type, HWND hwnd,
- UINT message, WPARAM wParam, LPARAM lParam )
-{
- unsigned int res;
-
- TRACE( "posting %x %x (%s) %x %lx\n", hwnd, message, SPY_GetMsgName(message), wParam, lParam );
-
- SERVER_START_REQ( send_message )
- {
- req->kind = POST_MESSAGE;
- req->id = (void *)tid;
- req->type = type;
- req->win = hwnd;
- req->msg = message;
- req->wparam = wParam;
- req->lparam = lParam;
- req->x = 0;
- req->y = 0;
- req->time = GetCurrentTime();
- req->info = 0;
- res = SERVER_CALL();
- }
- SERVER_END_REQ;
-
- if (res)
- {
- if (res == STATUS_INVALID_PARAMETER)
- SetLastError( ERROR_INVALID_THREAD_ID );
- else
- SetLastError( RtlNtStatusToDosError(res) );
- }
- return !res;
-}
-
-
-/***********************************************************************
- * MSG_PostMessage
- */
-static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam )
-{
- WND *wndPtr;
-
- if (hwnd == HWND_BROADCAST)
- {
- WND *pDesktop = WIN_GetDesktop();
- TRACE("HWND_BROADCAST !\n");
-
- for (wndPtr=WIN_LockWndPtr(pDesktop->child); wndPtr; WIN_UpdateWndPtr(&wndPtr,wndPtr->next))
- {
- if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
- {
- TRACE("BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
- wndPtr->hwndSelf, message, wParam, lParam);
- MSG_PostToQueue( GetWindowThreadProcessId( wndPtr->hwndSelf, NULL ), type,
- wndPtr->hwndSelf, message, wParam, lParam );
- }
- }
- WIN_ReleaseDesktop();
- TRACE("End of HWND_BROADCAST !\n");
- return TRUE;
- }
-
- return MSG_PostToQueue( GetWindowThreadProcessId( hwnd, NULL ),
- type, hwnd, message, wParam, lParam );
-}
-
-
-/***********************************************************************
- * PostMessage (USER.110)
- */
-BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 message, WPARAM16 wParam,
- LPARAM lParam )
-{
- return (BOOL16) MSG_PostMessage( QMSG_WIN16, hwnd, message, wParam, lParam );
-}
-
-/***********************************************************************
- * PostMessageA (USER32.@)
- */
-BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam,
- LPARAM lParam )
-{
- return PostMessageW( hwnd, message, map_wparam_AtoW( message, wParam ), lParam );
-}
-
-/***********************************************************************
- * PostMessageW (USER32.@)
- */
-BOOL WINAPI PostMessageW( HWND hwnd, UINT message, WPARAM wParam,
- LPARAM lParam )
-{
- /* See thread on wine-devel around 6.2.2001. Basically posted messages
- * that are known to contain pointers are dropped by the Windows 32bit
- * PostMessage() with return FALSE; and invalid parameter last error.
- * (tested against NT4 by Gerard Patel)
- */
- if (is_pointer_message(message))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return MSG_PostMessage( QMSG_WIN32W, hwnd, message, wParam, lParam );
-}
-
-/***********************************************************************
- * PostAppMessage (USER.116)
- * PostAppMessage16 (USER32.@)
- */
-BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message,
- WPARAM16 wParam, LPARAM lParam )
-{
- TDB *pTask = TASK_GetPtr( hTask );
- if (!pTask) return FALSE;
- return MSG_PostToQueue( (DWORD)pTask->teb->tid, QMSG_WIN16, 0, message, wParam, lParam );
-}
-
-/**********************************************************************
- * PostThreadMessageA (USER32.@)
- */
-BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
- WPARAM wParam, LPARAM lParam )
-{
- return PostThreadMessageW( idThread, message, map_wparam_AtoW( message, wParam ), lParam );
-}
-
-/**********************************************************************
- * PostThreadMessageW (USER32.@)
- */
-BOOL WINAPI PostThreadMessageW( DWORD idThread, UINT message,
- WPARAM wParam, LPARAM lParam )
-{
- if (is_pointer_message( message ))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
- return MSG_PostToQueue( idThread, QMSG_WIN32W, 0, message, wParam, lParam );
-}
-
-
-/************************************************************************
- * MSG_CallWndProcHook32
- */
-static void MSG_CallWndProcHook( LPMSG pmsg, BOOL bUnicode )
-{
- CWPSTRUCT cwp;
-
- cwp.lParam = pmsg->lParam;
- cwp.wParam = pmsg->wParam;
- cwp.message = pmsg->message;
- cwp.hwnd = pmsg->hwnd;
-
- if (bUnicode) HOOK_CallHooksW(WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp);
- else HOOK_CallHooksA( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
-
- pmsg->lParam = cwp.lParam;
- pmsg->wParam = cwp.wParam;
- pmsg->message = cwp.message;
- pmsg->hwnd = cwp.hwnd;
-}
-
-
-/***********************************************************************
- * MSG_SendMessage
- *
- * return values: 0 if timeout occurs
- * 1 otherwise
- */
-static LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam, DWORD timeout, WORD type,
- LRESULT *pRes)
-{
- WND * wndPtr = 0;
- WND **list, **ppWnd;
- LRESULT ret = 1;
- DWORD dest_tid;
- WNDPROC winproc;
-
- if (pRes) *pRes = 0;
-
- if (hwnd == HWND_BROADCAST|| hwnd == HWND_TOPMOST)
- {
- if (pRes) *pRes = 1;
-
- if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
- {
- WIN_ReleaseDesktop();
- return 1;
- }
- WIN_ReleaseDesktop();
-
- TRACE("HWND_BROADCAST !\n");
- for (ppWnd = list; *ppWnd; ppWnd++)
- {
- WIN_UpdateWndPtr(&wndPtr,*ppWnd);
- if (!IsWindow(wndPtr->hwndSelf)) continue;
- if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
- {
- 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, type, pRes);
- }
- }
- WIN_ReleaseWndPtr(wndPtr);
- WIN_ReleaseWinArray(list);
- TRACE("End of HWND_BROADCAST !\n");
- return 1;
- }
-
- if (HOOK_IsHooked( WH_CALLWNDPROC ))
- {
- switch(type)
- {
- 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 );
- }
- }
- break;
- case QMSG_WIN32A:
- MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
- break;
- case QMSG_WIN32W:
- MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
- break;
- }
- }
-
- if (!(wndPtr = WIN_FindWndPtr( hwnd )))
- {
- WARN("invalid hwnd %04x\n", hwnd );
- return 0;
- }
- if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
- {
- WIN_ReleaseWndPtr( wndPtr );
- return 0; /* Don't send anything if the task is dying */
- }
- winproc = (WNDPROC)wndPtr->winproc;
- WIN_ReleaseWndPtr( wndPtr );
-
- if (type != QMSG_WIN16)
- SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
- else
- SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
-
- dest_tid = GetWindowThreadProcessId( hwnd, NULL );
- if (dest_tid && dest_tid != GetCurrentThreadId())
- {
- ret = MSG_SendMessageInterThread( dest_tid, hwnd, msg,
- wParam, lParam, timeout, type, pRes );
- }
- else
- {
- LRESULT res = 0;
-
- /* Call the right CallWindowProc flavor */
- switch(type)
- {
- case QMSG_WIN16:
- res = CallWindowProc16( (WNDPROC16)winproc, hwnd, msg, wParam, lParam );
- break;
- case QMSG_WIN32A:
- res = CallWindowProcA( winproc, hwnd, msg, wParam, lParam );
- break;
- case QMSG_WIN32W:
- res = CallWindowProcW( winproc, hwnd, msg, wParam, lParam );
- break;
- }
- if (pRes) *pRes = res;
- }
-
- 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 );
-
- return ret;
-}
-
-
-/***********************************************************************
- * SendMessage (USER.111)
- */
-LRESULT WINAPI SendMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
- LPARAM lParam)
-{
- LRESULT res;
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN16, &res);
- return res;
-}
-
-
-/***********************************************************************
- * SendMessageA (USER32.@)
- */
-LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam )
- {
- LRESULT res;
-
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32A, &res);
-
- return res;
-}
-
-
-/***********************************************************************
- * SendMessageW (USER32.@) Send Window Message
- *
- * Sends a message to the window procedure of the specified window.
- * SendMessage() will not return until the called window procedure
- * either returns or calls ReplyMessage().
- *
- * Use PostMessage() to send message and return immediately. A window
- * procedure may use InSendMessage() to detect
- * SendMessage()-originated messages.
- *
- * Applications which communicate via HWND_BROADCAST may use
- * RegisterWindowMessage() to obtain a unique message to avoid conflicts
- * with other applications.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- */
-LRESULT WINAPI SendMessageW(
- HWND hwnd, /* [in] Window to send message to. If HWND_BROADCAST,
- the message will be sent to all top-level windows. */
-
- UINT msg, /* [in] message */
- WPARAM wParam, /* [in] message parameter */
- LPARAM lParam /* [in] additional message parameter */
-) {
- LRESULT res;
-
- MSG_SendMessage(hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, &res);
-
- return res;
-}
-
-
-/***********************************************************************
- * SendMessageTimeout (not a WINAPI)
- */
-LRESULT WINAPI SendMessageTimeout16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam,
- LPARAM lParam, UINT16 flags,
- UINT16 timeout, LPWORD resultp)
-{
- LRESULT ret;
- LRESULT msgRet;
-
- /* FIXME: need support for SMTO_BLOCK */
-
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN16, &msgRet);
- if (resultp) *resultp = (WORD) msgRet;
- return ret;
-}
-
-
-/***********************************************************************
- * SendMessageTimeoutA (USER32.@)
- */
-LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam, UINT flags,
- UINT timeout, LPDWORD resultp)
-{
- LRESULT ret;
- LRESULT msgRet;
-
- /* FIXME: need support for SMTO_BLOCK */
-
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32A, &msgRet);
-
- if (resultp) *resultp = (DWORD) msgRet;
- return ret;
-}
-
-
-/***********************************************************************
- * SendMessageTimeoutW (USER32.@)
- */
-LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wParam,
- LPARAM lParam, UINT flags,
- UINT timeout, LPDWORD resultp)
-{
- LRESULT ret;
- LRESULT msgRet;
-
- /* FIXME: need support for SMTO_BLOCK */
-
- ret = MSG_SendMessage(hwnd, msg, wParam, lParam, timeout, QMSG_WIN32W, &msgRet);
-
- if (resultp) *resultp = (DWORD) msgRet;
- return ret;
-}
-
-
-/***********************************************************************
- * SendNotifyMessageA (USER32.@)
- */
-BOOL WINAPI SendNotifyMessageA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
- return SendNotifyMessageW( hwnd, msg, map_wparam_AtoW( msg, wParam ), lParam );
-}
-
-
-/***********************************************************************
- * SendNotifyMessageW (USER32.@)
- */
-BOOL WINAPI SendNotifyMessageW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
- if (is_pointer_message(msg))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return MSG_SendMessage( hwnd, msg, wParam, lParam, INFINITE, QMSG_WIN32W, NULL );
-}
-
-
-/***********************************************************************
- * SendMessageCallbackA (USER32.@)
- */
-BOOL WINAPI SendMessageCallbackA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
- SENDASYNCPROC callback, ULONG_PTR data )
-{
- return SendMessageCallbackW( hwnd, msg, map_wparam_AtoW( msg, wParam ),
- lParam, callback, data );
-}
-
-
-/***********************************************************************
- * SendMessageCallbackW (USER32.@)
- *
- * FIXME: It's like PostMessage. The callback gets called when the message
- * is processed. We have to modify the message processing for an exact
- * implementation...
- * The callback is only called when the thread that called us calls one of
- * Get/Peek/WaitMessage.
- */
-BOOL WINAPI SendMessageCallbackW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
- SENDASYNCPROC callback, ULONG_PTR data )
-{
- LRESULT result;
-
- if (is_pointer_message(msg))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- FIXME( "(0x%04x,0x%04x,0x%08x,0x%08lx,%p,0x%08x),stub!\n",
- hwnd, msg, wParam, lParam, callback, data );
-
- if (hwnd == HWND_BROADCAST)
- {
- PostMessageW( hwnd, msg, wParam, lParam );
- FIXME("Broadcast: Callback will not be called!\n");
- return TRUE;
- }
- result = SendMessageW( hwnd, msg, wParam, lParam );
- callback( hwnd, msg, data, result );
- return TRUE;
-}
-
-
-/***********************************************************************
* WaitMessage (USER.112) Suspend thread pending messages
* WaitMessage (USER32.@) Suspend thread pending messages
*
@@ -1997,17 +629,6 @@
/***********************************************************************
- * MsgWaitForMultipleObjects (USER.640)
- */
-DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
- BOOL wait_all, DWORD timeout, DWORD mask )
-{
- return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
- wait_all ? MWMO_WAITALL : 0 );
-}
-
-
-/***********************************************************************
* WaitForInputIdle (USER32.@)
*/
DWORD WINAPI WaitForInputIdle( HANDLE hProcess, DWORD dwTimeOut )
@@ -2058,14 +679,19 @@
*/
void WINAPI UserYield16(void)
{
+ DWORD count;
+
/* Handle sent messages */
process_sent_messages();
/* Yield */
- OldYield16();
-
- /* Handle sent messages again */
- process_sent_messages();
+ ReleaseThunkLock(&count);
+ if (count)
+ {
+ RestoreThunkLock(count);
+ /* Handle sent messages again */
+ process_sent_messages();
+ }
}
@@ -2188,7 +814,7 @@
/***********************************************************************
- * MSG_DoTranslateMessage
+ * TranslateMessage (USER32.@)
*
* Implementation of TranslateMessage.
*
@@ -2199,29 +825,26 @@
* This produces WM_CHAR messages only for keys mapped to ASCII characters
* by the keyboard driver.
*/
-static BOOL MSG_DoTranslateMessage( UINT message, HWND hwnd,
- WPARAM wParam, LPARAM lParam )
+BOOL WINAPI TranslateMessage( const MSG *msg )
{
static int dead_char;
+ UINT message;
WCHAR wp[2];
-
- if (message != WM_MOUSEMOVE && message != WM_TIMER)
- TRACE("(%s, %04X, %08lX)\n",
- SPY_GetMsgName(message), wParam, lParam );
- if(message >= WM_KEYFIRST && message <= WM_KEYLAST)
- TRACE_(key)("(%s, %04X, %08lX)\n",
- SPY_GetMsgName(message), wParam, lParam );
- if ((message != WM_KEYDOWN) && (message != WM_SYSKEYDOWN)) return FALSE;
+ if (msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST)
+ TRACE_(key)("(%s, %04X, %08lX)\n",
+ SPY_GetMsgName(msg->message), msg->wParam, msg->lParam );
+
+ if ((msg->message != WM_KEYDOWN) && (msg->message != WM_SYSKEYDOWN)) return FALSE;
TRACE_(key)("Translating key %s (%04x), scancode %02x\n",
- SPY_GetVKeyName(wParam), wParam, LOBYTE(HIWORD(lParam)));
+ SPY_GetVKeyName(msg->wParam), msg->wParam, LOBYTE(HIWORD(msg->lParam)));
/* FIXME : should handle ToUnicode yielding 2 */
- switch (ToUnicode(wParam, HIWORD(lParam), QueueKeyStateTable, wp, 2, 0))
+ switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), QueueKeyStateTable, wp, 2, 0))
{
case 1:
- message = (message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
+ message = (msg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
/* Should dead chars handling go in ToAscii ? */
if (dead_char)
{
@@ -2245,14 +868,14 @@
dead_char = 0;
}
TRACE_(key)("1 -> PostMessage(%s)\n", SPY_GetMsgName(message));
- PostMessageW( hwnd, message, wp[0], lParam );
+ PostMessageW( msg->hwnd, message, wp[0], msg->lParam );
return TRUE;
case -1:
- message = (message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
+ message = (msg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
dead_char = wp[0];
TRACE_(key)("-1 -> PostMessage(%s)\n", SPY_GetMsgName(message));
- PostMessageW( hwnd, message, wp[0], lParam );
+ PostMessageW( msg->hwnd, message, wp[0], msg->lParam );
return TRUE;
}
return FALSE;
@@ -2260,125 +883,6 @@
/***********************************************************************
- * TranslateMessage (USER.113)
- */
-BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
-{
- return MSG_DoTranslateMessage( msg->message, msg->hwnd,
- msg->wParam, msg->lParam );
-}
-
-
-/***********************************************************************
- * TranslateMessage32 (USER.821)
- */
-BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
-{
- WPARAM wParam;
-
- if (wHaveParamHigh)
- wParam = MAKELONG(msg->msg.wParam, msg->wParamHigh);
- else
- wParam = (WPARAM)msg->msg.wParam;
-
- return MSG_DoTranslateMessage( msg->msg.message, msg->msg.hwnd,
- wParam, msg->msg.lParam );
-}
-
-/***********************************************************************
- * TranslateMessage (USER32.@)
- */
-BOOL WINAPI TranslateMessage( const MSG *msg )
-{
- return MSG_DoTranslateMessage( msg->message, msg->hwnd,
- msg->wParam, msg->lParam );
-}
-
-
-/***********************************************************************
- * DispatchMessage (USER.114)
- */
-LONG WINAPI DispatchMessage16( const MSG16* msg )
-{
- WND * wndPtr;
- LONG retval;
- int painting;
-
- /* Process timer messages */
- if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
- {
- if (msg->lParam)
- {
- /* before calling window proc, verify whether timer is still valid;
- there's a slim chance that the application kills the timer
- between GetMessage and DispatchMessage API calls */
- if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
- return 0; /* invalid winproc */
-
- return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
- msg->message, msg->wParam, GetTickCount() );
- }
- }
-
- if (!msg->hwnd) return 0;
- if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
- if (!wndPtr->winproc)
- {
- retval = 0;
- goto END;
- }
- painting = (msg->message == WM_PAINT);
- if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
-
- SPY_EnterMessage( SPY_DISPATCHMESSAGE16, msg->hwnd, msg->message,
- msg->wParam, msg->lParam );
- retval = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
- msg->hwnd, msg->message,
- msg->wParam, msg->lParam );
- SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval,
- msg->wParam, msg->lParam );
-
- WIN_ReleaseWndPtr(wndPtr);
- wndPtr = WIN_FindWndPtr(msg->hwnd);
- if (painting && wndPtr &&
- (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
- {
- ERR("BeginPaint not called on WM_PAINT for hwnd %04x!\n",
- msg->hwnd);
- wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
- /* Validate the update region to avoid infinite WM_PAINT loop */
- RedrawWindow( wndPtr->hwndSelf, NULL, 0,
- RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
- }
-END:
- WIN_ReleaseWndPtr(wndPtr);
- return retval;
-}
-
-
-/***********************************************************************
- * DispatchMessage32 (USER.822)
- */
-LONG WINAPI DispatchMessage32_16( const MSG32_16* lpmsg16_32, BOOL16 wHaveParamHigh )
-{
- if (wHaveParamHigh == FALSE)
- return DispatchMessage16(&(lpmsg16_32->msg));
- else
- {
- MSG msg;
-
- msg.hwnd = lpmsg16_32->msg.hwnd;
- msg.message = lpmsg16_32->msg.message;
- msg.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
- msg.lParam = lpmsg16_32->msg.lParam;
- msg.time = lpmsg16_32->msg.time;
- msg.pt.x = (INT)lpmsg16_32->msg.pt.x;
- msg.pt.y = (INT)lpmsg16_32->msg.pt.y;
- return DispatchMessageA(&msg);
- }
-}
-
-/***********************************************************************
* DispatchMessageA (USER32.@)
*/
LONG WINAPI DispatchMessageA( const MSG* msg )
@@ -2548,39 +1052,6 @@
/***********************************************************************
- * InSendMessage (USER.192)
- */
-BOOL16 WINAPI InSendMessage16(void)
-{
- return InSendMessage();
-}
-
-
-/***********************************************************************
- * InSendMessage (USER32.@)
- */
-BOOL WINAPI InSendMessage(void)
-{
- return (InSendMessageEx(NULL) & (ISMEX_SEND|ISMEX_REPLIED)) == ISMEX_SEND;
-}
-
-
-/***********************************************************************
- * 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.@)
*/
LONG WINAPI BroadcastSystemMessage(
diff --git a/windows/queue.c b/windows/queue.c
index 4f9fd73..d4400ba 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -456,64 +456,24 @@
/***********************************************************************
- * QUEUE_GetQueueTask
- */
-HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
-{
- HTASK16 hTask = 0;
-
- MESSAGEQUEUE *queue = QUEUE_Lock( hQueue );
-
- if (queue)
- {
- hTask = queue->teb->htask16;
- QUEUE_Unlock( queue );
- }
-
- return hTask;
-}
-
-
-/***********************************************************************
- * PostQuitMessage (USER.6)
- */
-void WINAPI PostQuitMessage16( INT16 exitCode )
-{
- PostQuitMessage( exitCode );
-}
-
-
-/***********************************************************************
- * PostQuitMessage (USER32.@)
- *
- * PostQuitMessage() posts a message to the system requesting an
- * application to terminate execution. As a result of this function,
- * the WM_QUIT message is posted to the application, and
- * PostQuitMessage() returns immediately. The exitCode parameter
- * specifies an application-defined exit code, which appears in the
- * _wParam_ parameter of the WM_QUIT message posted to the application.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- */
-void WINAPI PostQuitMessage( INT exitCode )
-{
- PostThreadMessageW( GetCurrentThreadId(), WM_QUIT, exitCode, 0 );
-}
-
-
-/***********************************************************************
* GetWindowTask (USER.224)
*/
HTASK16 WINAPI GetWindowTask16( HWND16 hwnd )
{
HTASK16 retvalue;
- WND *wndPtr = WIN_FindWndPtr( hwnd );
+ MESSAGEQUEUE *queue;
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return 0;
- retvalue = QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
+
+ queue = QUEUE_Lock( wndPtr->hmemTaskQ );
WIN_ReleaseWndPtr(wndPtr);
+
+ if (!queue) return 0;
+
+ retvalue = queue->teb->htask16;
+ QUEUE_Unlock( queue );
+
return retvalue;
}
@@ -542,25 +502,6 @@
/***********************************************************************
- * SetMessageQueue (USER.266)
- */
-BOOL16 WINAPI SetMessageQueue16( INT16 size )
-{
- return SetMessageQueue( size );
-}
-
-
-/***********************************************************************
- * SetMessageQueue (USER32.@)
- */
-BOOL WINAPI SetMessageQueue( INT size )
-{
- /* now obsolete the message queue will be expanded dynamically
- as necessary */
- return TRUE;
-}
-
-/***********************************************************************
* InitThreadInput (USER.409)
*/
HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
@@ -593,14 +534,6 @@
}
/***********************************************************************
- * GetQueueStatus (USER.334)
- */
-DWORD WINAPI GetQueueStatus16( UINT16 flags )
-{
- return GetQueueStatus( flags );
-}
-
-/***********************************************************************
* GetQueueStatus (USER32.@)
*/
DWORD WINAPI GetQueueStatus( UINT flags )
@@ -619,14 +552,6 @@
/***********************************************************************
- * GetInputState (USER.335)
- */
-BOOL16 WINAPI GetInputState16(void)
-{
- return GetInputState();
-}
-
-/***********************************************************************
* GetInputState (USER32.@)
*/
BOOL WINAPI GetInputState(void)