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

Last change on this file since 10439 was 10439, checked in by bird, 22 years ago

Urg! if (); isn't such a good idea.

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