source: trunk/src/user32/windowmsg.cpp

Last change on this file was 22033, checked in by dmik, 13 years ago

user32: Partly implement MsgWaitForMultipleObjectsEx.

Needed for Flash 11.4.

File size: 46.9 KB
RevLine 
[10607]1/* $Id: windowmsg.cpp,v 1.51 2004-05-24 09:02:01 sandervl Exp $ */
[2469]2/*
3 * Win32 window message APIs for OS/2
4 *
[7801]5 * Copyright 1999-2001 Sander van Leeuwen
[2469]6 *
7 * Parts based on Wine Windows code (windows\message.c) 990508
8 *
9 * Copyright 1993, 1994 Alexandre Julliard
10 *
11 * TODO: GetQueueStatus: QS_HOTKEY (oslibmsg.cpp) & low word bits
12 * TODO: MsgWaitForMultipleObjects: timeout isn't handled correctly (can return too late)
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
[6848]17
18#include <odin.h>
19#include <odinwrap.h>
20#include <os2sel.h>
21
[8954]22#include <string.h>
[2469]23#include <os2win.h>
24#include <misc.h>
[21916]25#include "win32wbase.h"
[2469]26#include <win.h>
27#include <heapstring.h>
28#include <handlemanager.h>
[8954]29#include <wprocess.h>
[2469]30#include "oslibutil.h"
31#include "oslibwin.h"
32#include "oslibmsg.h"
[5606]33#include "hook.h"
[10104]34#define INCL_TIMERWIN32
35#include "timer.h"
[21303]36#include "callwrap.h"
[2469]37
[10216]38#define DBG_LOCALLOG DBG_windowmsg
[2803]39#include "dbglocal.h"
40
[6848]41ODINDEBUGCHANNEL(USER32-WINDOWMSG)
42
[2469]43//******************************************************************************
44//******************************************************************************
45LONG WIN32API DispatchMessageA(const MSG * msg)
46{
[8689]47 dprintf2(("DispatchMessageA %x %x %x %x %x", msg->hwnd, msg->message, msg->wParam, msg->lParam, msg->time));
[10104]48
49 /* Process timer messages */
50 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
51 {
[10216]52 if (msg->lParam)
[10104]53 {
54/* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
55
56 /* before calling window proc, verify whether timer is still valid;
57 there's a slim chance that the application kills the timer
[10216]58 between GetMessage and DispatchMessage API calls */
[10104]59 if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, msg->lParam))
60 return 0; /* invalid winproc */
61
[10216]62 return CallWindowProcA( (WNDPROC)msg->lParam, msg->hwnd,
[10104]63 msg->message, msg->wParam, GetTickCount() );
64 }
65 }
66
[8689]67 return OSLibWinDispatchMsg((MSG *)msg);
[2469]68}
69//******************************************************************************
70//******************************************************************************
71LONG WIN32API DispatchMessageW( const MSG * msg)
72{
[8689]73 dprintf2(("DispatchMessageW %x %x %x %x %x", msg->hwnd, msg->message, msg->wParam, msg->lParam, msg->time));
[10104]74
75 /* Process timer messages */
76 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
77 {
[10216]78 if (msg->lParam)
[10104]79 {
80/* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
81
82 /* before calling window proc, verify whether timer is still valid;
83 there's a slim chance that the application kills the timer
[10216]84 between GetMessage and DispatchMessage API calls */
[10104]85 if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, msg->lParam))
86 return 0; /* invalid winproc */
87
[10216]88 return CallWindowProcW( (WNDPROC)msg->lParam, msg->hwnd,
[10104]89 msg->message, msg->wParam, GetTickCount() );
90 }
91 }
[8689]92 return OSLibWinDispatchMsg((MSG *)msg, TRUE);
[2469]93}
94//******************************************************************************
95//******************************************************************************
[6848]96BOOL WIN32API TranslateMessage(const MSG *msg)
[2469]97{
[8689]98 // check the message code
99 if ( (msg->message < WM_KEYDOWN) ||
100 (msg->message > WM_SYSKEYUP)||
101 (msg->message == WM_CHAR) ||
[10216]102#ifdef __WIN32OS2__
103 (msg->message == WM_DEADCHAR)||
104 (msg->message == WM_IME_CHAR) )
105#else
[8689]106 (msg->message == WM_DEADCHAR) )
[10216]107#endif
[8689]108 {
[21340]109 /* TODO: Investigate - is this really invalid parameters? */
[8689]110 SetLastError(ERROR_INVALID_PARAMETER);
111 return FALSE;
112 }
[10185]113
[8689]114 // only WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP
115 // can go into TranslateMessage
[10185]116
[8689]117 return OSLibWinTranslateMessage((MSG *)msg);
[2469]118}
119//******************************************************************************
120//******************************************************************************
121BOOL WIN32API GetMessageA( LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax)
122{
[8689]123 BOOL ret;
[10430]124 TEB *pTeb = GetThreadTEB();
[5606]125
[6420]126 dprintf2(("GetMessageA %x %x-%x", hwnd, uMsgFilterMin, uMsgFilterMax));
[10430]127 do
128 {
129 ret = OSLibWinGetMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax);
130 if(ret) dprintf2(("GetMessageA %x %x %x %x", hwnd, pMsg->message, pMsg->wParam, pMsg->lParam));
131 } while ( pTeb->o.odin.tidAttachedInputThread
132 && OSLibForwardMessageToAttachedThread(pTeb, pMsg, NULL));
[5606]133 HOOK_CallHooksA(WH_GETMESSAGE, HC_ACTION, PM_REMOVE, (LPARAM)pMsg);
134 return ret;
[2469]135}
136//******************************************************************************
137//******************************************************************************
138BOOL WIN32API GetMessageW( LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax)
139{
[8689]140 BOOL ret;
[10430]141 TEB *pTeb = GetThreadTEB();
[5606]142
[6420]143 dprintf2(("GetMessageW %x %x-%x", hwnd, uMsgFilterMin, uMsgFilterMax));
[10430]144 do
145 {
146 ret = OSLibWinGetMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, TRUE);
147 } while ( pTeb->o.odin.tidAttachedInputThread
148 && OSLibForwardMessageToAttachedThread(pTeb, pMsg, NULL));
[5606]149 HOOK_CallHooksW(WH_GETMESSAGE, HC_ACTION, PM_REMOVE, (LPARAM)pMsg);
150 return ret;
[2469]151}
152//******************************************************************************
153//******************************************************************************
154BOOL WIN32API PeekMessageA(LPMSG msg, HWND hwndOwner, UINT uMsgFilterMin,
155 UINT uMsgFilterMax, UINT fuRemoveMsg)
156{
[8689]157 BOOL fFoundMsg;
[10430]158 TEB *pTeb = GetThreadTEB();
[10185]159
[5805]160 dprintf2(("PeekMessageA %x %d-%d %d", hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg));
[10430]161 do
162 {
163 fFoundMsg = OSLibWinPeekMsg(msg, hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg, FALSE);
164 if ( fFoundMsg
165 && pTeb->o.odin.tidAttachedInputThread
[10439]166 && OSLibForwardMessageToAttachedThread(pTeb, msg, NULL))
[10430]167 {
168 if (!fuRemoveMsg)
169 OSLibWinPeekMsg(msg, hwndOwner, uMsgFilterMin, uMsgFilterMax, TRUE, FALSE);
170 continue;
171 }
172 } while (0);
173
174 if (fFoundMsg) {
[5805]175 dprintf2(("PeekMessageA %x %d-%d %d found message %x %d %x %x", hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg, msg->hwnd, msg->message, msg->wParam, msg->lParam));
[5606]176 HOOK_CallHooksA(WH_GETMESSAGE, HC_ACTION, fuRemoveMsg & PM_REMOVE, (LPARAM)msg );
[2469]177 if (msg->message == WM_QUIT && (fuRemoveMsg & PM_REMOVE)) {
178 //TODO: Post WM_QUERYENDSESSION message when WM_QUIT received and system is shutting down
179 }
180 }
181 return fFoundMsg;
182}
183//******************************************************************************
184//******************************************************************************
185BOOL WIN32API PeekMessageW(LPMSG msg, HWND hwndOwner, UINT uMsgFilterMin,
186 UINT uMsgFilterMax, UINT fuRemoveMsg)
187{
[8689]188 BOOL fFoundMsg;
[10430]189 TEB *pTeb = GetThreadTEB();
[2469]190
[5805]191 dprintf2(("PeekMessageW %x %d-%d %d", hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg));
[10430]192 do
193 {
194 fFoundMsg = OSLibWinPeekMsg(msg, hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg, TRUE);
195 if ( fFoundMsg
196 && pTeb->o.odin.tidAttachedInputThread
[10439]197 && OSLibForwardMessageToAttachedThread(pTeb, msg, NULL))
[10430]198 {
199 if (!fuRemoveMsg)
200 OSLibWinPeekMsg(msg, hwndOwner, uMsgFilterMin, uMsgFilterMax, TRUE, TRUE);
201 continue;
202 }
203 } while (0);
204
[2469]205 if(fFoundMsg) {
[5805]206 dprintf2(("PeekMessageW %x %d-%d %d found message %x %d %x %x", hwndOwner, uMsgFilterMin, uMsgFilterMax, fuRemoveMsg, msg->hwnd, msg->message, msg->wParam, msg->lParam));
[5606]207 HOOK_CallHooksW(WH_GETMESSAGE, HC_ACTION, fuRemoveMsg & PM_REMOVE, (LPARAM)msg );
[2469]208 if (msg->message == WM_QUIT && (fuRemoveMsg & (PM_REMOVE))) {
209 //TODO: Post WM_QUERYENDSESSION message when WM_QUIT received and system is shutting down
210 }
211 }
212 return fFoundMsg;
213}
214//******************************************************************************
215//TODO:
216//******************************************************************************
217LONG WIN32API GetMessageExtraInfo()
218{
[7620]219 dprintf(("USER32: GetMessageExtraInfo %x", GetThreadMessageExtraInfo()));
[2469]220 return GetThreadMessageExtraInfo();
221}
222//******************************************************************************
223//******************************************************************************
[7620]224LPARAM WIN32API SetMessageExtraInfo(LPARAM lParam)
225{
[8689]226 dprintf(("USER32: SetMessageExtraInfo %x", lParam));
227 return SetThreadMessageExtraInfo(lParam);
[7620]228}
229//******************************************************************************
230//******************************************************************************
[2469]231DWORD WIN32API GetMessagePos(void)
232{
[8689]233 DWORD pos;
[5606]234
235 pos = OSLibWinGetMessagePos();
[9865]236 dprintf(("USER32: GetMessagePos -> (%d,%d)", LOWORD(pos), HIWORD(pos)));
[5606]237 return pos;
[2469]238}
239//******************************************************************************
240//******************************************************************************
241LONG WIN32API GetMessageTime(void)
242{
243 dprintf(("USER32: GetMessageTime"));
244 return OSLibWinGetMessageTime();
245}
246//******************************************************************************
247//******************************************************************************
248BOOL WIN32API WaitMessage(void)
249{
[9928]250#ifdef DEBUG
251 MSG msg;
252
253 if(PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE) == FALSE) {
254 dprintf2(("USER32: WaitMessage %x", GetThreadHAB()));
255 }
256 else dprintf2(("USER32: WaitMessage %x; message %x present", GetThreadHAB(), msg.message));
257#endif
258
259 BOOL ret = OSLibWinWaitMessage();
260#ifdef DEBUG
261 if(PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE) == FALSE) {
262 dprintf2(("USER32: WaitMessage returned with no message in the queue"));
263 }
264#endif
265 return ret;
[2469]266}
267//******************************************************************************
268//******************************************************************************
269BOOL WIN32API InSendMessage(void)
270{
271 dprintf(("USER32: InSendMessage"));
272 return OSLibWinInSendMessage();
273}
274//******************************************************************************
275//******************************************************************************
276BOOL WIN32API ReplyMessage(LRESULT result)
277{
278 dprintf(("USER32: ReplyMessage %x", result));
279 return OSLibWinReplyMessage(result);
280}
281//******************************************************************************
282//******************************************************************************
[7801]283VOID WIN32API PostQuitMessage( int nExitCode)
284{
285 dprintf(("USER32: PostQuitMessage\n"));
286 OSLibWinPostQuitMessage(nExitCode);
287}
288//******************************************************************************
289//******************************************************************************
[5373]290UINT WIN32API RegisterWindowMessageA(LPCSTR lpString)
[2469]291{
[8689]292 UINT rc;
[2469]293
[5373]294 rc = GlobalAddAtomA(lpString);
295 dprintf(("USER32: RegisterWindowMessageA %s returned %X\n", lpString, rc));
[2469]296 return(rc);
297}
298//******************************************************************************
299//******************************************************************************
[5373]300UINT WIN32API RegisterWindowMessageW( LPCWSTR lpString)
[2469]301{
[3209]302 dprintf(("USER32: RegisterWindowMessageW\n"));
[5373]303 return GlobalAddAtomW(lpString);
[2469]304}
305//******************************************************************************
306//No need to support this (obsolete, not implemented by Win32)
307//******************************************************************************
308BOOL WIN32API SetMessageQueue(int cMessagesMax)
309{
[8689]310 dprintf(("USER32: SetMessageQueue\n"));
311 return(TRUE);
[2469]312}
313//******************************************************************************
[10430]314
315/**
316 * Attach one threads input queue to another thread.
317 *
318 * @returns Success indicator.
319 * @param idAttach Thread ID of the thread to attach/detach the input
320 * of idAttachTo to.
321 * @param idAttachTo The Thread ID of the thread which input is to be taken
322 * over or reattached.
323 * @param fAttach If set attach the input queue of thread idAttachTo
324 * to idAttach.
325 * If clear detach the input queue of thread idAttach
326 * reattaching it to idAttachTo.
327 * @status partially implemented.
328 * @author knut st. osmundsen <bird-srcspam@anduin.net>
329 * @remark One cannot attach a threads input queue to it self.
[21303]330 * @remark This implemenation requires the thread which input is 'forwarded' to
331 * process it's message queue. Window (and wine) will not bother that thread
332 * at all with the messages. (DEADLOCK WARNING)
[10430]333 * @todo Not sure if all this is 100% ok according to the windows reality.
334 * I'm sure some error cases aren't caught.
335 */
336BOOL WIN32API AttachThreadInput(DWORD idAttach, DWORD idAttachTo, BOOL fAttach)
337{
338 dprintf(("USER32: AttachThreadInput\n"));
339 if (idAttach != idAttachTo)
340 {
341 /* pray noone frees the TEB while we're working on it... */
342 TEB *pTeb = GetTEBFromThreadId(idAttach);
343 if (pTeb)
344 {
345 TEB *pTebTo = GetTEBFromThreadId(idAttachTo);
346 if (pTebTo)
347 {
348 if (fAttach)
349 { /* attach. */
350 if (pTebTo->o.odin.tidAttachedInputThread)
351 {
352 dprintf(("USER32: AttachThreadInput: WARNING! %#x is already attached to %#x\n", idAttachTo, pTebTo->o.odin.tidAttachedInputThread));
353 DebugInt3();
354 }
355 pTebTo->o.odin.tidAttachedInputThread = idAttach;
356 dprintf(("USER32: AttachThreadInput: Attached input from %#x to %#x\n", idAttachTo, idAttach));
357 }
358 else
359 { /* deattach - i.e. undo previous AttachThreadInput(,,TRUE). */
360 if (pTebTo->o.odin.tidAttachedInputThread != idAttach)
361 {
362 dprintf(("USER32: AttachThreadInput: WARNING! %#x is not attached to %#x\n", idAttachTo, pTebTo->o.odin.tidAttachedInputThread));
363 DebugInt3();
364 }
365 pTebTo->o.odin.tidAttachedInputThread = 0;
366 dprintf(("USER32: AttachThreadInput: Detached input from %#x to %#x\n", idAttach, idAttachTo));
367 }
368 return TRUE;
369 }
370 else
371 {
372 dprintf(("USER32: AttachThreadInput: Invalid tid=%#x\n", idAttachTo));
373 SetLastError(ERROR_INVALID_PARAMETER);
374 }
375 }
376 else
377 {
378 dprintf(("USER32: AttachThreadInput: Invalid tid=%#x\n", idAttach));
379 SetLastError(ERROR_INVALID_PARAMETER);
380 }
381 }
382 else
383 {
384 dprintf(("USER32: AttachThreadInput idAttach == idAttachTo (== %#x)\n", idAttach));
385 SetLastError(ERROR_ACCESS_DENIED);
386 }
387 return FALSE;
388}
389
[2469]390//******************************************************************************
391/**********************************************************************
392 * WINPROC_TestCBForStr
393 *
394 * Return TRUE if the lparam is a string
395 */
396BOOL WINPROC_TestCBForStr ( HWND hwnd )
397{
398 BOOL retvalue;
399 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
400 retvalue = ( !(LOWORD(dwStyle) & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ||
401 (LOWORD(dwStyle) & CBS_HASSTRINGS) );
402 return retvalue;
403}
404/**********************************************************************
405 * WINPROC_TestLBForStr
406 *
407 * Return TRUE if the lparam is a string
408 */
409BOOL WINPROC_TestLBForStr ( HWND hwnd )
410{
411 BOOL retvalue;
412 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
413 retvalue = ( !(LOWORD(dwStyle) & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) ||
414 (LOWORD(dwStyle) & LBS_HASSTRINGS) );
415 return retvalue;
416}
417
418/**********************************************************************
419 * WINPROC_MapMsg32ATo32W
420 *
421 * Map a message from Ansi to Unicode.
422 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
423 *
424 * FIXME:
425 * WM_CHAR, WM_CHARTOITEM, WM_DEADCHAR, WM_MENUCHAR, WM_SYSCHAR, WM_SYSDEADCHAR
426 *
427 * FIXME:
428 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
429 * the first four bytes are the handle of the icon
430 * when the WM_SETTEXT message has been used to set the icon
431 */
[10185]432INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
[2469]433{
434 switch(msg)
435 {
436 case WM_GETTEXT:
[10190]437 case WM_ASKCBFORMATNAME:
[2469]438 {
439 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
[10185]440 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
[2469]441 if (!ptr) return -1;
442 *ptr++ = *plparam; /* Store previous lParam */
443 *plparam = (LPARAM)ptr;
444 }
445 return 1;
446 /* lparam is string (0-terminated) */
447 case WM_SETTEXT:
448 case WM_WININICHANGE:
[10190]449 case WM_DEVMODECHANGE:
[2469]450 case CB_DIR:
[5124]451 case LB_DIR:
452 case LB_ADDFILE:
453#ifndef __WIN32OS2__
[2469]454 case CB_FINDSTRING:
455 case CB_FINDSTRINGEXACT:
456 case CB_SELECTSTRING:
457 case LB_FINDSTRING:
458 case LB_SELECTSTRING:
[5124]459#endif
[2469]460 case EM_REPLACESEL:
461 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
462 return (*plparam ? 1 : -1);
463
464 case WM_NCCREATE:
465 case WM_CREATE:
466 {
467 CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
468 sizeof(*cs) );
469 if (!cs) return -1;
470 *cs = *(CREATESTRUCTW *)*plparam;
471 if (HIWORD(cs->lpszName))
472 cs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
473 (LPCSTR)cs->lpszName );
474 if (HIWORD(cs->lpszClass))
475 cs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
476 (LPCSTR)cs->lpszClass );
477 *plparam = (LPARAM)cs;
478 }
479 return 1;
480 case WM_MDICREATE:
481 {
482 MDICREATESTRUCTW *cs =
483 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
484 if (!cs) return -1;
485 *cs = *(MDICREATESTRUCTW *)*plparam;
486 if (HIWORD(cs->szClass))
487 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
488 (LPCSTR)cs->szClass );
489 if (HIWORD(cs->szTitle))
490 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
491 (LPCSTR)cs->szTitle );
492 *plparam = (LPARAM)cs;
493 }
494 return 1;
495
496/* Listbox */
497 case LB_ADDSTRING:
[5124]498#ifdef __WIN32OS2__
499 case LB_FINDSTRING:
500 case LB_FINDSTRINGEXACT:
501 case LB_SELECTSTRING:
502#endif
[2469]503 case LB_INSERTSTRING:
504 if ( WINPROC_TestLBForStr( hwnd ))
505 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
506 return (*plparam ? 1 : -1);
507
508 case LB_GETTEXT: /* fixme: fixed sized buffer */
509 { if ( WINPROC_TestLBForStr( hwnd ))
510 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
511 if (!ptr) return -1;
512 *ptr++ = *plparam; /* Store previous lParam */
513 *plparam = (LPARAM)ptr;
514 }
515 }
516 return 1;
517
518/* Combobox */
519 case CB_ADDSTRING:
[5124]520#ifdef __WIN32OS2__
521 case CB_FINDSTRING:
522 case CB_FINDSTRINGEXACT:
523 case CB_SELECTSTRING:
524#endif
[2469]525 case CB_INSERTSTRING:
526 if ( WINPROC_TestCBForStr( hwnd ))
527 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
528 return (*plparam ? 1 : -1);
529
530 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
531 { if ( WINPROC_TestCBForStr( hwnd ))
532 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
533 if (!ptr) return -1;
534 *ptr++ = *plparam; /* Store previous lParam */
535 *plparam = (LPARAM)ptr;
536 }
537 }
538 return 1;
539
540/* Multiline edit */
541 case EM_GETLINE:
542 { WORD len = (WORD)*plparam;
543 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
544 if (!ptr) return -1;
545 *ptr++ = *plparam; /* Store previous lParam */
546 *((WORD *) ptr) = len; /* Store the length */
547 *plparam = (LPARAM)ptr;
548 }
549 return 1;
550
[10190]551 case WM_CHARTOITEM:
552 case WM_MENUCHAR:
553 case WM_CHAR:
554 case WM_DEADCHAR:
555 case WM_SYSCHAR:
556 case WM_SYSDEADCHAR:
[10185]557 case EM_SETPASSWORDCHAR:
558 {
[10190]559 char ch = LOWORD(*pwparam);
560 WCHAR wch;
561 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
[10185]562 *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
563 }
564 return 0;
565
[10216]566#ifdef __WIN32OS2__
567 case WM_IME_CHAR:
568 {
[21303]569 // always DBCS char
[10216]570 CHAR charA[ 2 ];
571
[10607]572 charA[ 0 ] = ( CHAR )( *pwparam >> 8 );
573 charA[ 1 ] = ( CHAR )*pwparam;
[10216]574
[21303]575 MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, 2, ( LPWSTR )pwparam, 1);
[10216]576
577 return 0;
578 }
579#endif
580
[2469]581 case WM_PAINTCLIPBOARD:
582 case WM_SIZECLIPBOARD:
583 // FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg), msg );
584 return -1;
585 default: /* No translation needed */
586 return 0;
587 }
588}
589
590
591/**********************************************************************
592 * WINPROC_UnmapMsg32ATo32W
593 *
594 * Unmap a message that was mapped from Ansi to Unicode.
595 */
596void WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
597{
598 switch(msg)
599 {
600 case WM_GETTEXT:
[10190]601 case WM_ASKCBFORMATNAME:
[2469]602 {
603 LPARAM *ptr = (LPARAM *)lParam - 1;
604 lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)lParam, wParam );
605 HeapFree( GetProcessHeap(), 0, ptr );
606 }
607 break;
608
609 case WM_NCCREATE:
610 case WM_CREATE:
611 {
612 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
613 if (HIWORD(cs->lpszName))
614 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
615 if (HIWORD(cs->lpszClass))
616 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
617 HeapFree( GetProcessHeap(), 0, cs );
618 }
619 break;
620
621 case WM_MDICREATE:
622 {
623 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
624 if (HIWORD(cs->szTitle))
625 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
626 if (HIWORD(cs->szClass))
627 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
628 HeapFree( GetProcessHeap(), 0, cs );
629 }
630 break;
631
632 case WM_SETTEXT:
633 case WM_WININICHANGE:
[10190]634 case WM_DEVMODECHANGE:
[2469]635 case CB_DIR:
[5124]636 case LB_DIR:
637 case LB_ADDFILE:
638#ifndef __WIN32OS2__
[2469]639 case CB_FINDSTRING:
640 case CB_FINDSTRINGEXACT:
641 case CB_SELECTSTRING:
642 case LB_FINDSTRING:
643 case LB_SELECTSTRING:
[5124]644#endif
[2469]645 case EM_REPLACESEL:
646 HeapFree( GetProcessHeap(), 0, (void *)lParam );
647 break;
648
649/* Listbox */
650 case LB_ADDSTRING:
[5124]651#ifdef __WIN32OS2__
652 case LB_FINDSTRING:
653 case LB_FINDSTRINGEXACT:
654 case LB_SELECTSTRING:
655#endif
[2469]656 case LB_INSERTSTRING:
657 if ( WINPROC_TestLBForStr( hwnd ))
658 HeapFree( GetProcessHeap(), 0, (void *)lParam );
659 break;
660
661 case LB_GETTEXT:
662 { if ( WINPROC_TestLBForStr( hwnd ))
663 { LPARAM *ptr = (LPARAM *)lParam - 1;
664 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
665 HeapFree( GetProcessHeap(), 0, ptr );
666 }
667 }
668 break;
669
670/* Combobox */
671 case CB_ADDSTRING:
[5124]672#ifdef __WIN32OS2__
673 case CB_FINDSTRING:
674 case CB_FINDSTRINGEXACT:
675 case CB_SELECTSTRING:
676#endif
[2469]677 case CB_INSERTSTRING:
678 if ( WINPROC_TestCBForStr( hwnd ))
679 HeapFree( GetProcessHeap(), 0, (void *)lParam );
680 break;
681
682 case CB_GETLBTEXT:
683 { if ( WINPROC_TestCBForStr( hwnd ))
684 { LPARAM *ptr = (LPARAM *)lParam - 1;
685 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
686 HeapFree( GetProcessHeap(), 0, ptr );
687 }
688 }
689 break;
690
691/* Multiline edit */
692 case EM_GETLINE:
693 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
[10204]694#ifdef __WIN32OS2__
695 WORD len = *(WORD *) ptr;
696#else
[2469]697 WORD len = *(WORD *) lParam;
[10204]698#endif
[2469]699 lstrcpynWtoA( (LPSTR)*ptr , (LPWSTR)lParam, len );
700 HeapFree( GetProcessHeap(), 0, ptr );
701 }
702 break;
703 }
704}
705
706
707/**********************************************************************
708 * WINPROC_MapMsg32WTo32A
709 *
710 * Map a message from Unicode to Ansi.
711 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
712 */
[10190]713INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam)
[2469]714{ switch(msg)
715 {
716 case WM_GETTEXT:
[10190]717 case WM_ASKCBFORMATNAME:
[2469]718 {
[10190]719#ifdef __WIN32OS2__
720 *pwparam = *pwparam * sizeof( WCHAR ); //DBCS
721#endif
[2469]722 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
[10190]723 *pwparam + sizeof(LPARAM) );
[2469]724 if (!ptr) return -1;
725 *ptr++ = *plparam; /* Store previous lParam */
726 *plparam = (LPARAM)ptr;
727 }
728 return 1;
729
730 case WM_SETTEXT:
731 case WM_WININICHANGE:
[10190]732 case WM_DEVMODECHANGE:
[2469]733 case CB_DIR:
[5124]734 case LB_DIR:
735 case LB_ADDFILE:
736#ifndef __WIN32OS2__
[2469]737 case CB_FINDSTRING:
738 case CB_FINDSTRINGEXACT:
739 case CB_SELECTSTRING:
740 case LB_FINDSTRING:
741 case LB_SELECTSTRING:
[5124]742#endif
[2469]743 case EM_REPLACESEL:
744 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
745 return (*plparam ? 1 : -1);
746
747 case WM_NCCREATE:
748 case WM_CREATE:
749 {
750 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
751 sizeof(*cs) );
752 if (!cs) return -1;
753 *cs = *(CREATESTRUCTA *)*plparam;
754 if (HIWORD(cs->lpszName))
755 cs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
756 (LPCWSTR)cs->lpszName );
757 if (HIWORD(cs->lpszClass))
758 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
759 (LPCWSTR)cs->lpszClass);
760 *plparam = (LPARAM)cs;
761 }
762 return 1;
763 case WM_MDICREATE:
764 {
765 MDICREATESTRUCTA *cs =
766 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
767
768 if (!cs) return -1;
769 *cs = *(MDICREATESTRUCTA *)*plparam;
770 if (HIWORD(cs->szTitle))
771 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
772 (LPCWSTR)cs->szTitle );
773 if (HIWORD(cs->szClass))
774 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
775 (LPCWSTR)cs->szClass );
776 *plparam = (LPARAM)cs;
777 }
778 return 1;
779
780/* Listbox */
781 case LB_ADDSTRING:
[5124]782#ifdef __WIN32OS2__
783 case LB_FINDSTRING:
784 case LB_FINDSTRINGEXACT:
785 case LB_SELECTSTRING:
786#endif
[2469]787 case LB_INSERTSTRING:
788 if ( WINPROC_TestLBForStr( hwnd ))
789 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
790 return (*plparam ? 1 : -1);
791
792 case LB_GETTEXT: /* fixme: fixed sized buffer */
793 { if ( WINPROC_TestLBForStr( hwnd ))
794 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
795 if (!ptr) return -1;
796 *ptr++ = *plparam; /* Store previous lParam */
797 *plparam = (LPARAM)ptr;
798 }
799 }
800 return 1;
801
802/* Combobox */
803 case CB_ADDSTRING:
[5124]804#ifdef __WIN32OS2__
805 case CB_FINDSTRING:
806 case CB_FINDSTRINGEXACT:
807 case CB_SELECTSTRING:
808#endif
[2469]809 case CB_INSERTSTRING:
810 if ( WINPROC_TestCBForStr( hwnd ))
811 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
812 return (*plparam ? 1 : -1);
813
814 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
815 { if ( WINPROC_TestCBForStr( hwnd ))
816 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
817 if (!ptr) return -1;
818 *ptr++ = *plparam; /* Store previous lParam */
819 *plparam = (LPARAM)ptr;
820 }
821 }
822 return 1;
823
824/* Multiline edit */
825 case EM_GETLINE:
826 { WORD len = (WORD)*plparam;
[10203]827#ifdef __WIN32OS2__
828 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
829#else
[2469]830 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
[10203]831#endif
[2469]832 if (!ptr) return -1;
833 *ptr++ = *plparam; /* Store previous lParam */
[10190]834#ifdef __WIN32OS2__
835 *((WORD *) ptr) = len * sizeof(WCHAR); /* Store the length */
836#else
[2469]837 *((WORD *) ptr) = len; /* Store the length */
[10190]838#endif
[2469]839 *plparam = (LPARAM)ptr;
840 }
841 return 1;
842
[10190]843 case WM_CHARTOITEM:
844 case WM_MENUCHAR:
845 case WM_CHAR:
846 case WM_DEADCHAR:
847 case WM_SYSCHAR:
848 case WM_SYSDEADCHAR:
849 case EM_SETPASSWORDCHAR:
850 {
851 WCHAR wch = LOWORD(*pwparam);
852 char ch;
853 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
854 *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
855 }
856 return 0;
857
[10216]858#ifdef __WIN32OS2__
859 case WM_IME_CHAR:
[21303]860 { // always DBCS char
[10216]861 CHAR charA[ 2 ];
862
[21303]863 WideCharToMultiByte( CP_ACP, 0, ( LPWSTR )pwparam, 1, ( LPSTR )charA, 2, 0, 0 );
[10607]864 *pwparam = ( charA[ 0 ] << 8 ) | charA[ 1 ];
[10216]865
866 return 0;
867 }
868#endif
869
[2469]870 case WM_PAINTCLIPBOARD:
871 case WM_SIZECLIPBOARD:
872 // FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg),msg );
873 return -1;
874 default: /* No translation needed */
875 return 0;
876 }
877}
878
879
880/**********************************************************************
881 * WINPROC_UnmapMsg32WTo32A
882 *
883 * Unmap a message that was mapped from Unicode to Ansi.
884 */
885void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
886{
887 switch(msg)
888 {
889 case WM_GETTEXT:
[10190]890 case WM_ASKCBFORMATNAME:
[2469]891 {
892 LPARAM *ptr = (LPARAM *)lParam - 1;
[10190]893
894#ifdef __WIN32OS2__
895 wParam = wParam / sizeof( WCHAR );
896#endif
[2469]897 lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)lParam, wParam );
898 HeapFree( GetProcessHeap(), 0, ptr );
899 }
900 break;
901
902 case WM_SETTEXT:
903 case WM_WININICHANGE:
[10190]904 case WM_DEVMODECHANGE:
[2469]905 case CB_DIR:
[5124]906 case LB_DIR:
907 case LB_ADDFILE:
908#ifndef __WIN32OS2__
[2469]909 case CB_FINDSTRING:
910 case CB_FINDSTRINGEXACT:
911 case CB_SELECTSTRING:
912 case LB_FINDSTRING:
913 case LB_SELECTSTRING:
[5124]914#endif
[2469]915 case EM_REPLACESEL:
916 HeapFree( GetProcessHeap(), 0, (void *)lParam );
917 break;
918
919 case WM_NCCREATE:
920 case WM_CREATE:
921 {
922 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
923 if (HIWORD(cs->lpszName))
924 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
925 if (HIWORD(cs->lpszClass))
926 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
927 HeapFree( GetProcessHeap(), 0, cs );
928 }
929 break;
930
931 case WM_MDICREATE:
932 {
933 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
934 if (HIWORD(cs->szTitle))
935 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
936 if (HIWORD(cs->szClass))
937 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
938 HeapFree( GetProcessHeap(), 0, cs );
939 }
940 break;
941
942/* Listbox */
943 case LB_ADDSTRING:
[5124]944#ifdef __WIN32OS2__
945 case LB_FINDSTRING:
946 case LB_FINDSTRINGEXACT:
947 case LB_SELECTSTRING:
948#endif
[2469]949 case LB_INSERTSTRING:
950 if ( WINPROC_TestLBForStr( hwnd ))
951 HeapFree( GetProcessHeap(), 0, (void *)lParam );
952 break;
953
954 case LB_GETTEXT:
955 { if ( WINPROC_TestLBForStr( hwnd ))
956 { LPARAM *ptr = (LPARAM *)lParam - 1;
957 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
958 HeapFree(GetProcessHeap(), 0, ptr );
959 }
960 }
961 break;
962
963/* Combobox */
964 case CB_ADDSTRING:
[5124]965#ifdef __WIN32OS2__
966 case CB_FINDSTRING:
967 case CB_FINDSTRINGEXACT:
968 case CB_SELECTSTRING:
969#endif
[2469]970 case CB_INSERTSTRING:
971 if ( WINPROC_TestCBForStr( hwnd ))
972 HeapFree( GetProcessHeap(), 0, (void *)lParam );
973 break;
974
975 case CB_GETLBTEXT:
976 { if ( WINPROC_TestCBForStr( hwnd ))
977 { LPARAM *ptr = (LPARAM *)lParam - 1;
978 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
979 HeapFree( GetProcessHeap(), 0, ptr );
980 }
981 }
982 break;
983
984/* Multiline edit */
985 case EM_GETLINE:
986 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
987 WORD len = *(WORD *)ptr;
[10203]988
[2469]989 lstrcpynAtoW( (LPWSTR) *ptr, (LPSTR)lParam, len );
990 HeapFree( GetProcessHeap(), 0, ptr );
991 }
992 break;
993 }
994}
995
996/**********************************************************************
997 * WINPROC_CallProc32ATo32W
998 *
999 * Call a window procedure, translating args from Ansi to Unicode.
1000 */
1001LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
1002 UINT msg, WPARAM wParam,
1003 LPARAM lParam )
1004{
1005 LRESULT result;
1006
[10185]1007 if (WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam ) == -1) return 0;
[10190]1008
[21303]1009 result = WrapCallback4(func, hwnd, msg, wParam, lParam );
[2469]1010 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
[10190]1011
1012#ifdef __WIN32OS2__
[10216]1013 if(IsDBCSEnv())
[10190]1014 {
1015 switch( msg )
1016 {
1017 case WM_GETTEXTLENGTH :
1018 {
1019 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
[21303]1020 result = WrapCallback4(func, hwnd, WM_GETTEXT, ( WPARAM )( result + 1 ), ( LPARAM )ustr );
[10190]1021 result = lstrlenWtoA( ustr, result );
1022 HeapFree( GetProcessHeap(), 0, ustr );
1023 break;
1024 }
1025
1026 case LB_GETTEXTLEN :
1027 {
1028 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
[21303]1029 result = WrapCallback4(func, hwnd, LB_GETTEXT, wParam, ( LPARAM )ustr );
[10190]1030 if( result != LB_ERR )
1031 result = lstrlenWtoA( ustr, result );
1032
1033 HeapFree( GetProcessHeap(), 0, ustr );
1034 break;
1035 }
1036
1037
1038 case CB_GETLBTEXTLEN :
1039 {
1040 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
[21303]1041 result = WrapCallback4(func, hwnd, CB_GETLBTEXT, wParam, ( LPARAM )ustr );
[10190]1042 if( result != CB_ERR )
1043 result = lstrlenWtoA( ustr, result );
1044
1045 HeapFree( GetProcessHeap(), 0, ustr );
1046 break;
1047 }
1048 }
1049 }
1050#endif
[2469]1051 return result;
1052}
1053
1054/**********************************************************************
1055 * WINPROC_CallProc32WTo32A
1056 *
1057 * Call a window procedure, translating args from Unicode to Ansi.
1058 */
1059LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
1060 UINT msg, WPARAM wParam,
1061 LPARAM lParam )
1062{
1063 LRESULT result;
1064
[10190]1065 if (WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam ) == -1) return 0;
1066
[21303]1067 result = WrapCallback4(func, hwnd, msg, wParam, lParam );
[2469]1068 WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
[10190]1069
1070#ifdef __WIN32OS2__
1071 if( IsDBCSEnv() )
1072 {
1073 switch( msg )
1074 {
1075 case WM_GETTEXTLENGTH :
1076 {
1077 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
[21303]1078 result = WrapCallback4(func, hwnd, WM_GETTEXT, ( WPARAM )( result + 1 ), ( LPARAM )astr );
[10190]1079 result = lstrlenAtoW( astr, result );
1080 HeapFree( GetProcessHeap(), 0, astr );
1081 break;
1082 }
1083
1084 case LB_GETTEXTLEN :
1085 {
1086 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
[21303]1087 result = WrapCallback4(func, hwnd, LB_GETTEXT, wParam, ( LPARAM )astr );
[10190]1088 if( result != LB_ERR )
1089 result = lstrlenAtoW( astr, result );
1090
1091 HeapFree( GetProcessHeap(), 0, astr );
1092 break;
1093 }
1094
1095
1096 case CB_GETLBTEXTLEN :
1097 {
1098 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
[21303]1099 result = WrapCallback4(func, hwnd, CB_GETLBTEXT, wParam, ( LPARAM )astr );
[10190]1100 if( result != CB_ERR )
1101 result = lstrlenAtoW( astr, result );
1102
1103 HeapFree( GetProcessHeap(), 0, astr );
1104 break;
1105 }
1106 }
1107 }
1108#endif
[2469]1109 return result;
1110}
1111//******************************************************************************
1112//TODO: QS_HOTKEY (oslibmsg.cpp) & low word bits
1113//high word = messages currently in queue
1114//low word = messages that have been added to the queue and are still in the
1115// queue since the last call to GetQueueStatus
1116//******************************************************************************
[21955]1117DWORD WIN32API GetQueueStatus(UINT flags)
[2469]1118{
1119 DWORD queueStatus;
1120
[21955]1121 queueStatus = OSLibWinQueryQueueStatus(flags);
[2469]1122
[5606]1123 dprintf(("USER32: GetQueueStatus %x returned %x", flags, queueStatus & MAKELONG(flags, flags)));
1124
[2469]1125 return queueStatus & MAKELONG(flags, flags);
1126}
1127/*****************************************************************************
1128 * Name : BOOL WIN32API GetInputState
1129 * Purpose : The GetInputState function determines whether there are
1130 * mouse-button or keyboard messages in the calling thread's message queue.
1131 * Parameters:
1132 * Variables :
1133 * Result : If the queue contains one or more new mouse-button or keyboard
1134 * messages, the return value is TRUE.
1135 * If the function fails, the return value is FALSE.
1136 * Remark :
1137 * Status : UNTESTED STUB
1138 *
1139 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1140 *****************************************************************************/
1141BOOL WIN32API GetInputState(VOID)
1142{
1143 DWORD queueStatus;
1144 BOOL rc;
1145
[21955]1146 queueStatus = OSLibWinQueryQueueStatus(QS_INPUT);
[2469]1147
1148 rc = (queueStatus & (QS_KEY | QS_MOUSEBUTTON)) ? TRUE : FALSE;
1149 dprintf(("USER32:GetInputState() returned %d", rc));
1150 return rc;
1151}
1152//******************************************************************************
1153/* Synchronization Functions */
1154//******************************************************************************
[5805]1155DWORD WIN32API MsgWaitForMultipleObjects(DWORD nCount, LPHANDLE pHandles, BOOL fWaitAll,
1156 DWORD dwMilliseconds, DWORD dwWakeMask)
[2469]1157{
[5805]1158 DWORD curtime, endtime, ret;
[5606]1159 MSG msg;
[2469]1160
[8949]1161 //TODO: Functions such as GetMessage, PeekMessage and WaitMessage can mark messages as old
1162 // MsgWaitForMultipleObjects shouldn't return until new input has arrived (MSDN)
1163 // We are not 100% correct with this implementation. GetQueueStatus checks all messages
1164 // in the queue.
1165 // Very obscure behaviour, so it's unlikely any application depends on it
[8954]1166
1167 //4 cases:
1168 //1: Wait for all -> check for message arrival, call WaitForMultipleObjects
[8962]1169 //2: Timeout = 0 ms -> call WaitForMultipleObjects with timeout 0, check for message arrival
[8954]1170 //3: nCount = 0 -> check for message arrival
1171 //4: rest -> check for either message arrival or signalled object
1172
[8949]1173 dprintf(("MsgWaitForMultipleObjects %x %x %d %d %x", nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask));
[8954]1174 if(fWaitAll) //case 1
[8949]1175 { //wait for message arrival first
[2469]1176 curtime = GetCurrentTime();
1177 endtime = curtime + dwMilliseconds;
1178 while(curtime < endtime || dwMilliseconds == INFINITE) {
[8949]1179 if(OSLibWinWaitMessage() == FALSE) {
1180 dprintf(("OSLibWinWaitMessage returned FALSE!"));
1181 return WAIT_ABANDONED;
1182 }
1183 if(GetQueueStatus(dwWakeMask) != 0) {
1184 break;
1185 }
1186 //TODO: Ignoring all messages could be dangerous. But processing them,
1187 //while the app doesn't expect any, isn't safe either.
[10185]1188 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
[8949]1189 {
1190 if (msg.message == WM_QUIT) {
1191 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1192 return WAIT_ABANDONED;
1193 }
1194
1195 /* otherwise dispatch it */
1196 DispatchMessageA(&msg);
1197 }
1198 curtime = GetCurrentTime();
[2469]1199 }
[8949]1200 if(dwMilliseconds != INFINITE && curtime > endtime) {
1201 dprintf(("No messages found in specified time"));
1202 return WAIT_TIMEOUT;
1203 }
1204 //ok, the right message has arrived, now try to grab all objects
1205 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
1206 if(ret >= WAIT_OBJECT_0 + nCount) {
1207 //failure
1208 dprintf(("WaitForMultipleObjects failed with %d", ret));
1209 return ret;
1210 }
1211 return ret;
1212 }
[8954]1213 if(dwMilliseconds == 0) { //case 2
[8960]1214 if(nCount) {
1215 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
1216 if(ret < WAIT_OBJECT_0 + nCount) {
1217 return ret;
1218 }
1219 }
[8949]1220 if(GetQueueStatus(dwWakeMask) == 0) {
1221 return WAIT_TIMEOUT;
1222 }
1223 return WAIT_OBJECT_0 + nCount; //right message has arrived
1224 }
[8954]1225 if(nCount == 0) //case 3
1226 {
1227 //SvL: Check time, wait for any message, check msg type and determine if
1228 // we have to return
1229 //TODO: Timeout isn't handled correctly (can return too late)
1230 curtime = GetCurrentTime();
1231 endtime = curtime + dwMilliseconds;
1232 while(curtime < endtime || dwMilliseconds == INFINITE) {
1233 if(OSLibWinWaitMessage() == FALSE) {
1234 dprintf(("OSLibWinWaitMessage returned FALSE!"));
1235 return WAIT_ABANDONED;
1236 }
1237 if(GetQueueStatus(dwWakeMask) != 0) {
1238 return WAIT_OBJECT_0;
1239 }
1240 //TODO: Ignoring all messages could be dangerous. But processing them,
1241 //while the app doesn't expect any, isn't safe either.
[10185]1242 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
[8954]1243 {
1244 if (msg.message == WM_QUIT) {
1245 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1246 return WAIT_ABANDONED;
1247 }
[10185]1248
[8954]1249 /* otherwise dispatch it */
1250 DispatchMessageA(&msg);
1251 }
1252 curtime = GetCurrentTime();
1253 }
1254 return WAIT_TIMEOUT;
1255 }
1256
1257 //Case 4:
1258#if 1
1259 //Note: The WGSS implementation of this function is flawed. Returns
1260 // when a message is sent to the msg queue, regardless of dwWakeMask
1261 TEB *teb = GetTEBFromThreadId(GetCurrentThreadId());
1262 if(teb == NULL) {
1263 DebugInt3();
1264 return WAIT_ABANDONED;
1265 }
[8960]1266 //check if any object is already signalled
1267 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 0);
1268 if(ret < WAIT_OBJECT_0 + nCount) {
1269 return ret;
1270 }
[8956]1271 //if the msg queue already contains the messages defined by dwWakeMask,
1272 //then return immediately
1273 if(GetQueueStatus(dwWakeMask) != 0) {
1274 return WAIT_OBJECT_0+nCount;
1275 }
[8954]1276 if(dwWakeMask & QS_POSTMESSAGE) {
1277 HANDLE *pHandlesTmp = (HANDLE *)alloca((nCount+1)*sizeof(HANDLE));
1278 if(pHandlesTmp == NULL || !teb->o.odin.hPostMsgEvent) {
1279 DebugInt3();
1280 return WAIT_ABANDONED;
1281 }
1282 memcpy(pHandlesTmp, pHandles, nCount*sizeof(HANDLE));
1283 pHandlesTmp[nCount] = teb->o.odin.hPostMsgEvent;
[8960]1284
1285 //mark this thread as waiting for window messages
[8954]1286 teb->o.odin.dwWakeMask = dwWakeMask;
1287
1288 ResetEvent(teb->o.odin.hPostMsgEvent);
1289 ret = HMMsgWaitForMultipleObjects(nCount+1,pHandlesTmp,fWaitAll,dwMilliseconds,dwWakeMask);
[8960]1290
1291 //unmark thread
1292 teb->o.odin.dwWakeMask = 0;
1293
[8954]1294 //nCount + 2 -> message event -> return nCount + 1
1295 return (ret == nCount + 2) ? (nCount + 1) : ret;
1296 }
1297 //Call handlemanager function as we need to translate handles (KERNEL32)
1298 ret = HMMsgWaitForMultipleObjects(nCount,pHandles,fWaitAll,dwMilliseconds,dwWakeMask);
1299 return ret;
1300#else
1301 //This method has a high latency (too high for some apps)
[8949]1302 //TODO: Timeout isn't handled correctly (can return too late)
1303 curtime = GetCurrentTime();
1304 endtime = curtime + dwMilliseconds;
1305 while(curtime < endtime || dwMilliseconds == INFINITE) {
1306 //check queue status for presence of requested message types
1307 if(GetQueueStatus(dwWakeMask) != 0) {
1308 dprintf(("Found message(s) we were looking for. Return success"));
1309 return WAIT_OBJECT_0 + nCount; //present, return success
1310 }
1311 //TODO: Ignoring all messages could be dangerous. But processing them,
1312 //while the app doesn't expect any, isn't safe either.
[10185]1313 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
[8949]1314 {
1315 if (msg.message == WM_QUIT) {
1316 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1317 return WAIT_ABANDONED;
1318 }
1319
1320 /* otherwise dispatch it */
1321 DispatchMessageA(&msg);
1322 }
1323 //check if any object is signalled (timeout 10ms)
[8954]1324 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 4);
[8949]1325 if(ret < WAIT_OBJECT_0 + nCount) {
1326 //an object was signalled, return immediately
1327 dprintf(("WaitForMultipleObjects success with %d", ret));
1328 return ret;
1329 }
1330 else
1331 if(ret != WAIT_TIMEOUT) {
1332 //failure, abort
1333 dprintf(("WaitForMultipleObjects failed with %d", ret));
1334 return ret;
1335 }
1336 curtime = GetCurrentTime();
1337 }
1338 return WAIT_TIMEOUT;
[8954]1339#endif
[2469]1340}
[22033]1341//******************************************************************************
1342/* Synchronization Functions */
1343//******************************************************************************
1344DWORD WIN32API MsgWaitForMultipleObjectsEx(DWORD nCount, LPHANDLE pHandles,
1345 DWORD dwMilliseconds, DWORD dwWakeMask,
1346 DWORD dwFlags)
1347{
1348 if (dwFlags == 0) {
1349 return MsgWaitForMultipleObjects(nCount, pHandles, FALSE, dwMilliseconds, dwWakeMask);
1350 }
1351 if (dwFlags == 0x0001 /*MWMO_WAITALL*/) {
1352 return MsgWaitForMultipleObjects(nCount, pHandles, TRUE, dwMilliseconds, dwWakeMask);
1353 }
1354
1355 dprintf(("USER32: MsgWaitForMultipleObjectsEx() with dwFlags=%x not implemented\n",
1356 dwFlags));
1357 SetLastError(ERROR_NOT_SUPPORTED);
1358 return WAIT_FAILED;
1359}
Note: See TracBrowser for help on using the repository browser.