source: trunk/src/user32/windowmsg.cpp@ 10602

Last change on this file since 10602 was 10602, checked in by sandervl, 21 years ago

DT: Added wrappers for calling window handlers

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