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

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

KOM: Updates

File size: 45.9 KB
Line 
1/* $Id: windowmsg.cpp,v 1.51 2004-05-24 09:02:01 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
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 CHAR charA[ 2 ];
565 INT lenA = 1;
566
567 if( IsDBCSLeadByte(( CHAR )( *pwparam >> 8 )))
568 {
569 charA[ 0 ] = ( CHAR )( *pwparam >> 8 );
570 charA[ 1 ] = ( CHAR )*pwparam;
571 lenA = 2;
572 }
573 else
574 charA[ 0 ] = ( CHAR )*pwparam;
575
576 MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, lenA, ( LPWSTR )pwparam, 1);
577
578 return 0;
579 }
580#endif
581
582 case WM_PAINTCLIPBOARD:
583 case WM_SIZECLIPBOARD:
584 // FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg), msg );
585 return -1;
586 default: /* No translation needed */
587 return 0;
588 }
589}
590
591
592/**********************************************************************
593 * WINPROC_UnmapMsg32ATo32W
594 *
595 * Unmap a message that was mapped from Ansi to Unicode.
596 */
597void WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
598{
599 switch(msg)
600 {
601 case WM_GETTEXT:
602 case WM_ASKCBFORMATNAME:
603 {
604 LPARAM *ptr = (LPARAM *)lParam - 1;
605 lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)lParam, wParam );
606 HeapFree( GetProcessHeap(), 0, ptr );
607 }
608 break;
609
610 case WM_NCCREATE:
611 case WM_CREATE:
612 {
613 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
614 if (HIWORD(cs->lpszName))
615 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
616 if (HIWORD(cs->lpszClass))
617 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
618 HeapFree( GetProcessHeap(), 0, cs );
619 }
620 break;
621
622 case WM_MDICREATE:
623 {
624 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
625 if (HIWORD(cs->szTitle))
626 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
627 if (HIWORD(cs->szClass))
628 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
629 HeapFree( GetProcessHeap(), 0, cs );
630 }
631 break;
632
633 case WM_SETTEXT:
634 case WM_WININICHANGE:
635 case WM_DEVMODECHANGE:
636 case CB_DIR:
637 case LB_DIR:
638 case LB_ADDFILE:
639#ifndef __WIN32OS2__
640 case CB_FINDSTRING:
641 case CB_FINDSTRINGEXACT:
642 case CB_SELECTSTRING:
643 case LB_FINDSTRING:
644 case LB_SELECTSTRING:
645#endif
646 case EM_REPLACESEL:
647 HeapFree( GetProcessHeap(), 0, (void *)lParam );
648 break;
649
650/* Listbox */
651 case LB_ADDSTRING:
652#ifdef __WIN32OS2__
653 case LB_FINDSTRING:
654 case LB_FINDSTRINGEXACT:
655 case LB_SELECTSTRING:
656#endif
657 case LB_INSERTSTRING:
658 if ( WINPROC_TestLBForStr( hwnd ))
659 HeapFree( GetProcessHeap(), 0, (void *)lParam );
660 break;
661
662 case LB_GETTEXT:
663 { if ( WINPROC_TestLBForStr( hwnd ))
664 { LPARAM *ptr = (LPARAM *)lParam - 1;
665 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
666 HeapFree( GetProcessHeap(), 0, ptr );
667 }
668 }
669 break;
670
671/* Combobox */
672 case CB_ADDSTRING:
673#ifdef __WIN32OS2__
674 case CB_FINDSTRING:
675 case CB_FINDSTRINGEXACT:
676 case CB_SELECTSTRING:
677#endif
678 case CB_INSERTSTRING:
679 if ( WINPROC_TestCBForStr( hwnd ))
680 HeapFree( GetProcessHeap(), 0, (void *)lParam );
681 break;
682
683 case CB_GETLBTEXT:
684 { if ( WINPROC_TestCBForStr( hwnd ))
685 { LPARAM *ptr = (LPARAM *)lParam - 1;
686 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
687 HeapFree( GetProcessHeap(), 0, ptr );
688 }
689 }
690 break;
691
692/* Multiline edit */
693 case EM_GETLINE:
694 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
695#ifdef __WIN32OS2__
696 WORD len = *(WORD *) ptr;
697#else
698 WORD len = *(WORD *) lParam;
699#endif
700 lstrcpynWtoA( (LPSTR)*ptr , (LPWSTR)lParam, len );
701 HeapFree( GetProcessHeap(), 0, ptr );
702 }
703 break;
704 }
705}
706
707
708/**********************************************************************
709 * WINPROC_MapMsg32WTo32A
710 *
711 * Map a message from Unicode to Ansi.
712 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
713 */
714INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam)
715{ switch(msg)
716 {
717 case WM_GETTEXT:
718 case WM_ASKCBFORMATNAME:
719 {
720#ifdef __WIN32OS2__
721 *pwparam = *pwparam * sizeof( WCHAR ); //DBCS
722#endif
723 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
724 *pwparam + sizeof(LPARAM) );
725 if (!ptr) return -1;
726 *ptr++ = *plparam; /* Store previous lParam */
727 *plparam = (LPARAM)ptr;
728 }
729 return 1;
730
731 case WM_SETTEXT:
732 case WM_WININICHANGE:
733 case WM_DEVMODECHANGE:
734 case CB_DIR:
735 case LB_DIR:
736 case LB_ADDFILE:
737#ifndef __WIN32OS2__
738 case CB_FINDSTRING:
739 case CB_FINDSTRINGEXACT:
740 case CB_SELECTSTRING:
741 case LB_FINDSTRING:
742 case LB_SELECTSTRING:
743#endif
744 case EM_REPLACESEL:
745 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
746 return (*plparam ? 1 : -1);
747
748 case WM_NCCREATE:
749 case WM_CREATE:
750 {
751 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
752 sizeof(*cs) );
753 if (!cs) return -1;
754 *cs = *(CREATESTRUCTA *)*plparam;
755 if (HIWORD(cs->lpszName))
756 cs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
757 (LPCWSTR)cs->lpszName );
758 if (HIWORD(cs->lpszClass))
759 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
760 (LPCWSTR)cs->lpszClass);
761 *plparam = (LPARAM)cs;
762 }
763 return 1;
764 case WM_MDICREATE:
765 {
766 MDICREATESTRUCTA *cs =
767 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
768
769 if (!cs) return -1;
770 *cs = *(MDICREATESTRUCTA *)*plparam;
771 if (HIWORD(cs->szTitle))
772 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
773 (LPCWSTR)cs->szTitle );
774 if (HIWORD(cs->szClass))
775 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
776 (LPCWSTR)cs->szClass );
777 *plparam = (LPARAM)cs;
778 }
779 return 1;
780
781/* Listbox */
782 case LB_ADDSTRING:
783#ifdef __WIN32OS2__
784 case LB_FINDSTRING:
785 case LB_FINDSTRINGEXACT:
786 case LB_SELECTSTRING:
787#endif
788 case LB_INSERTSTRING:
789 if ( WINPROC_TestLBForStr( hwnd ))
790 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
791 return (*plparam ? 1 : -1);
792
793 case LB_GETTEXT: /* fixme: fixed sized buffer */
794 { if ( WINPROC_TestLBForStr( hwnd ))
795 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
796 if (!ptr) return -1;
797 *ptr++ = *plparam; /* Store previous lParam */
798 *plparam = (LPARAM)ptr;
799 }
800 }
801 return 1;
802
803/* Combobox */
804 case CB_ADDSTRING:
805#ifdef __WIN32OS2__
806 case CB_FINDSTRING:
807 case CB_FINDSTRINGEXACT:
808 case CB_SELECTSTRING:
809#endif
810 case CB_INSERTSTRING:
811 if ( WINPROC_TestCBForStr( hwnd ))
812 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
813 return (*plparam ? 1 : -1);
814
815 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
816 { if ( WINPROC_TestCBForStr( hwnd ))
817 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
818 if (!ptr) return -1;
819 *ptr++ = *plparam; /* Store previous lParam */
820 *plparam = (LPARAM)ptr;
821 }
822 }
823 return 1;
824
825/* Multiline edit */
826 case EM_GETLINE:
827 { WORD len = (WORD)*plparam;
828#ifdef __WIN32OS2__
829 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
830#else
831 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
832#endif
833 if (!ptr) return -1;
834 *ptr++ = *plparam; /* Store previous lParam */
835#ifdef __WIN32OS2__
836 *((WORD *) ptr) = len * sizeof(WCHAR); /* Store the length */
837#else
838 *((WORD *) ptr) = len; /* Store the length */
839#endif
840 *plparam = (LPARAM)ptr;
841 }
842 return 1;
843
844 case WM_CHARTOITEM:
845 case WM_MENUCHAR:
846 case WM_CHAR:
847 case WM_DEADCHAR:
848 case WM_SYSCHAR:
849 case WM_SYSDEADCHAR:
850 case EM_SETPASSWORDCHAR:
851 {
852 WCHAR wch = LOWORD(*pwparam);
853 char ch;
854 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
855 *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
856 }
857 return 0;
858
859#ifdef __WIN32OS2__
860 case WM_IME_CHAR:
861 {
862 CHAR charA[ 2 ];
863 INT lenA;
864
865 lenA = WideCharToMultiByte( CP_ACP, 0, ( LPWSTR )pwparam, 1, ( LPSTR )charA, 2, 0, 0 );
866 if( lenA > 1 )
867 *pwparam = ( charA[ 0 ] << 8 ) | charA[ 1 ];
868 else
869 *pwparam = charA[ 0 ];
870
871 return 0;
872 }
873#endif
874
875 case WM_PAINTCLIPBOARD:
876 case WM_SIZECLIPBOARD:
877 // FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg),msg );
878 return -1;
879 default: /* No translation needed */
880 return 0;
881 }
882}
883
884
885/**********************************************************************
886 * WINPROC_UnmapMsg32WTo32A
887 *
888 * Unmap a message that was mapped from Unicode to Ansi.
889 */
890void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
891{
892 switch(msg)
893 {
894 case WM_GETTEXT:
895 case WM_ASKCBFORMATNAME:
896 {
897 LPARAM *ptr = (LPARAM *)lParam - 1;
898
899#ifdef __WIN32OS2__
900 wParam = wParam / sizeof( WCHAR );
901#endif
902 lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)lParam, wParam );
903 HeapFree( GetProcessHeap(), 0, ptr );
904 }
905 break;
906
907 case WM_SETTEXT:
908 case WM_WININICHANGE:
909 case WM_DEVMODECHANGE:
910 case CB_DIR:
911 case LB_DIR:
912 case LB_ADDFILE:
913#ifndef __WIN32OS2__
914 case CB_FINDSTRING:
915 case CB_FINDSTRINGEXACT:
916 case CB_SELECTSTRING:
917 case LB_FINDSTRING:
918 case LB_SELECTSTRING:
919#endif
920 case EM_REPLACESEL:
921 HeapFree( GetProcessHeap(), 0, (void *)lParam );
922 break;
923
924 case WM_NCCREATE:
925 case WM_CREATE:
926 {
927 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
928 if (HIWORD(cs->lpszName))
929 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
930 if (HIWORD(cs->lpszClass))
931 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
932 HeapFree( GetProcessHeap(), 0, cs );
933 }
934 break;
935
936 case WM_MDICREATE:
937 {
938 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
939 if (HIWORD(cs->szTitle))
940 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
941 if (HIWORD(cs->szClass))
942 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
943 HeapFree( GetProcessHeap(), 0, cs );
944 }
945 break;
946
947/* Listbox */
948 case LB_ADDSTRING:
949#ifdef __WIN32OS2__
950 case LB_FINDSTRING:
951 case LB_FINDSTRINGEXACT:
952 case LB_SELECTSTRING:
953#endif
954 case LB_INSERTSTRING:
955 if ( WINPROC_TestLBForStr( hwnd ))
956 HeapFree( GetProcessHeap(), 0, (void *)lParam );
957 break;
958
959 case LB_GETTEXT:
960 { if ( WINPROC_TestLBForStr( hwnd ))
961 { LPARAM *ptr = (LPARAM *)lParam - 1;
962 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
963 HeapFree(GetProcessHeap(), 0, ptr );
964 }
965 }
966 break;
967
968/* Combobox */
969 case CB_ADDSTRING:
970#ifdef __WIN32OS2__
971 case CB_FINDSTRING:
972 case CB_FINDSTRINGEXACT:
973 case CB_SELECTSTRING:
974#endif
975 case CB_INSERTSTRING:
976 if ( WINPROC_TestCBForStr( hwnd ))
977 HeapFree( GetProcessHeap(), 0, (void *)lParam );
978 break;
979
980 case CB_GETLBTEXT:
981 { if ( WINPROC_TestCBForStr( hwnd ))
982 { LPARAM *ptr = (LPARAM *)lParam - 1;
983 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
984 HeapFree( GetProcessHeap(), 0, ptr );
985 }
986 }
987 break;
988
989/* Multiline edit */
990 case EM_GETLINE:
991 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
992 WORD len = *(WORD *)ptr;
993
994 lstrcpynAtoW( (LPWSTR) *ptr, (LPSTR)lParam, len );
995 HeapFree( GetProcessHeap(), 0, ptr );
996 }
997 break;
998 }
999}
1000
1001/**********************************************************************
1002 * WINPROC_CallProc32ATo32W
1003 *
1004 * Call a window procedure, translating args from Ansi to Unicode.
1005 */
1006LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
1007 UINT msg, WPARAM wParam,
1008 LPARAM lParam )
1009{
1010 LRESULT result;
1011 LPARAM old = lParam;
1012
1013 if (WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam ) == -1) return 0;
1014
1015 result = func( hwnd, msg, wParam, lParam );
1016 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
1017
1018#ifdef __WIN32OS2__
1019 if(IsDBCSEnv())
1020 {
1021 switch( msg )
1022 {
1023 case WM_GETTEXTLENGTH :
1024 {
1025 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
1026 result = func( hwnd, WM_GETTEXT, ( WPARAM )( result + 1 ), ( LPARAM )ustr );
1027 result = lstrlenWtoA( ustr, result );
1028 HeapFree( GetProcessHeap(), 0, ustr );
1029 break;
1030 }
1031
1032 case LB_GETTEXTLEN :
1033 {
1034 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
1035 result = func( hwnd, LB_GETTEXT, wParam, ( LPARAM )ustr );
1036 if( result != LB_ERR )
1037 result = lstrlenWtoA( ustr, result );
1038
1039 HeapFree( GetProcessHeap(), 0, ustr );
1040 break;
1041 }
1042
1043
1044 case CB_GETLBTEXTLEN :
1045 {
1046 LPWSTR ustr = ( LPWSTR )HeapAlloc( GetProcessHeap(), 0, ( result + 1 ) * sizeof( WCHAR ));
1047 result = func( hwnd, CB_GETLBTEXT, wParam, ( LPARAM )ustr );
1048 if( result != CB_ERR )
1049 result = lstrlenWtoA( ustr, result );
1050
1051 HeapFree( GetProcessHeap(), 0, ustr );
1052 break;
1053 }
1054 }
1055 }
1056#endif
1057 return result;
1058}
1059
1060/**********************************************************************
1061 * WINPROC_CallProc32WTo32A
1062 *
1063 * Call a window procedure, translating args from Unicode to Ansi.
1064 */
1065LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
1066 UINT msg, WPARAM wParam,
1067 LPARAM lParam )
1068{
1069 LRESULT result;
1070
1071 if (WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam ) == -1) return 0;
1072
1073 result = func( hwnd, msg, wParam, lParam );
1074 WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
1075
1076#ifdef __WIN32OS2__
1077 if( IsDBCSEnv() )
1078 {
1079 switch( msg )
1080 {
1081 case WM_GETTEXTLENGTH :
1082 {
1083 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
1084 result = func( hwnd, WM_GETTEXT, ( WPARAM )( result + 1 ), ( LPARAM )astr );
1085 result = lstrlenAtoW( astr, result );
1086 HeapFree( GetProcessHeap(), 0, astr );
1087 break;
1088 }
1089
1090 case LB_GETTEXTLEN :
1091 {
1092 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
1093 result = func( hwnd, LB_GETTEXT, wParam, ( LPARAM )astr );
1094 if( result != LB_ERR )
1095 result = lstrlenAtoW( astr, result );
1096
1097 HeapFree( GetProcessHeap(), 0, astr );
1098 break;
1099 }
1100
1101
1102 case CB_GETLBTEXTLEN :
1103 {
1104 LPSTR astr = ( LPSTR )HeapAlloc( GetProcessHeap(), 0, result + 1 );
1105 result = func( hwnd, CB_GETLBTEXT, wParam, ( LPARAM )astr );
1106 if( result != CB_ERR )
1107 result = lstrlenAtoW( astr, result );
1108
1109 HeapFree( GetProcessHeap(), 0, astr );
1110 break;
1111 }
1112 }
1113 }
1114#endif
1115 return result;
1116}
1117//******************************************************************************
1118//TODO: QS_HOTKEY (oslibmsg.cpp) & low word bits
1119//high word = messages currently in queue
1120//low word = messages that have been added to the queue and are still in the
1121// queue since the last call to GetQueueStatus
1122//******************************************************************************
1123DWORD WIN32API GetQueueStatus( UINT flags)
1124{
1125 DWORD queueStatus;
1126
1127 queueStatus = OSLibWinQueryQueueStatus();
1128 queueStatus = MAKELONG(queueStatus, queueStatus);
1129
1130 dprintf(("USER32: GetQueueStatus %x returned %x", flags, queueStatus & MAKELONG(flags, flags)));
1131
1132 return queueStatus & MAKELONG(flags, flags);
1133}
1134/*****************************************************************************
1135 * Name : BOOL WIN32API GetInputState
1136 * Purpose : The GetInputState function determines whether there are
1137 * mouse-button or keyboard messages in the calling thread's message queue.
1138 * Parameters:
1139 * Variables :
1140 * Result : If the queue contains one or more new mouse-button or keyboard
1141 * messages, the return value is TRUE.
1142 * If the function fails, the return value is FALSE.
1143 * Remark :
1144 * Status : UNTESTED STUB
1145 *
1146 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1147 *****************************************************************************/
1148BOOL WIN32API GetInputState(VOID)
1149{
1150 DWORD queueStatus;
1151 BOOL rc;
1152
1153 queueStatus = OSLibWinQueryQueueStatus();
1154
1155 rc = (queueStatus & (QS_KEY | QS_MOUSEBUTTON)) ? TRUE : FALSE;
1156 dprintf(("USER32:GetInputState() returned %d", rc));
1157 return rc;
1158}
1159//******************************************************************************
1160/* Synchronization Functions */
1161//******************************************************************************
1162DWORD WIN32API MsgWaitForMultipleObjects(DWORD nCount, LPHANDLE pHandles, BOOL fWaitAll,
1163 DWORD dwMilliseconds, DWORD dwWakeMask)
1164{
1165 DWORD curtime, endtime, ret;
1166 MSG msg;
1167
1168 //TODO: Functions such as GetMessage, PeekMessage and WaitMessage can mark messages as old
1169 // MsgWaitForMultipleObjects shouldn't return until new input has arrived (MSDN)
1170 // We are not 100% correct with this implementation. GetQueueStatus checks all messages
1171 // in the queue.
1172 // Very obscure behaviour, so it's unlikely any application depends on it
1173
1174 //4 cases:
1175 //1: Wait for all -> check for message arrival, call WaitForMultipleObjects
1176 //2: Timeout = 0 ms -> call WaitForMultipleObjects with timeout 0, check for message arrival
1177 //3: nCount = 0 -> check for message arrival
1178 //4: rest -> check for either message arrival or signalled object
1179
1180 dprintf(("MsgWaitForMultipleObjects %x %x %d %d %x", nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask));
1181 if(fWaitAll) //case 1
1182 { //wait for message arrival first
1183 curtime = GetCurrentTime();
1184 endtime = curtime + dwMilliseconds;
1185 while(curtime < endtime || dwMilliseconds == INFINITE) {
1186 if(OSLibWinWaitMessage() == FALSE) {
1187 dprintf(("OSLibWinWaitMessage returned FALSE!"));
1188 return WAIT_ABANDONED;
1189 }
1190 if(GetQueueStatus(dwWakeMask) != 0) {
1191 break;
1192 }
1193 //TODO: Ignoring all messages could be dangerous. But processing them,
1194 //while the app doesn't expect any, isn't safe either.
1195 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1196 {
1197 if (msg.message == WM_QUIT) {
1198 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1199 return WAIT_ABANDONED;
1200 }
1201
1202 /* otherwise dispatch it */
1203 DispatchMessageA(&msg);
1204 }
1205 curtime = GetCurrentTime();
1206 }
1207 if(dwMilliseconds != INFINITE && curtime > endtime) {
1208 dprintf(("No messages found in specified time"));
1209 return WAIT_TIMEOUT;
1210 }
1211 //ok, the right message has arrived, now try to grab all objects
1212 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
1213 if(ret >= WAIT_OBJECT_0 + nCount) {
1214 //failure
1215 dprintf(("WaitForMultipleObjects failed with %d", ret));
1216 return ret;
1217 }
1218 return ret;
1219 }
1220 if(dwMilliseconds == 0) { //case 2
1221 if(nCount) {
1222 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
1223 if(ret < WAIT_OBJECT_0 + nCount) {
1224 return ret;
1225 }
1226 }
1227 if(GetQueueStatus(dwWakeMask) == 0) {
1228 return WAIT_TIMEOUT;
1229 }
1230 return WAIT_OBJECT_0 + nCount; //right message has arrived
1231 }
1232 if(nCount == 0) //case 3
1233 {
1234 //SvL: Check time, wait for any message, check msg type and determine if
1235 // we have to return
1236 //TODO: Timeout isn't handled correctly (can return too late)
1237 curtime = GetCurrentTime();
1238 endtime = curtime + dwMilliseconds;
1239 while(curtime < endtime || dwMilliseconds == INFINITE) {
1240 if(OSLibWinWaitMessage() == FALSE) {
1241 dprintf(("OSLibWinWaitMessage returned FALSE!"));
1242 return WAIT_ABANDONED;
1243 }
1244 if(GetQueueStatus(dwWakeMask) != 0) {
1245 return WAIT_OBJECT_0;
1246 }
1247 //TODO: Ignoring all messages could be dangerous. But processing them,
1248 //while the app doesn't expect any, isn't safe either.
1249 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1250 {
1251 if (msg.message == WM_QUIT) {
1252 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1253 return WAIT_ABANDONED;
1254 }
1255
1256 /* otherwise dispatch it */
1257 DispatchMessageA(&msg);
1258 }
1259 curtime = GetCurrentTime();
1260 }
1261 return WAIT_TIMEOUT;
1262 }
1263
1264 //Case 4:
1265#if 1
1266 //Note: The WGSS implementation of this function is flawed. Returns
1267 // when a message is sent to the msg queue, regardless of dwWakeMask
1268 TEB *teb = GetTEBFromThreadId(GetCurrentThreadId());
1269 if(teb == NULL) {
1270 DebugInt3();
1271 return WAIT_ABANDONED;
1272 }
1273 //check if any object is already signalled
1274 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 0);
1275 if(ret < WAIT_OBJECT_0 + nCount) {
1276 return ret;
1277 }
1278 //if the msg queue already contains the messages defined by dwWakeMask,
1279 //then return immediately
1280 if(GetQueueStatus(dwWakeMask) != 0) {
1281 return WAIT_OBJECT_0+nCount;
1282 }
1283 if(dwWakeMask & QS_POSTMESSAGE) {
1284 HANDLE *pHandlesTmp = (HANDLE *)alloca((nCount+1)*sizeof(HANDLE));
1285 if(pHandlesTmp == NULL || !teb->o.odin.hPostMsgEvent) {
1286 DebugInt3();
1287 return WAIT_ABANDONED;
1288 }
1289 memcpy(pHandlesTmp, pHandles, nCount*sizeof(HANDLE));
1290 pHandlesTmp[nCount] = teb->o.odin.hPostMsgEvent;
1291
1292 //mark this thread as waiting for window messages
1293 teb->o.odin.dwWakeMask = dwWakeMask;
1294
1295 ResetEvent(teb->o.odin.hPostMsgEvent);
1296 ret = HMMsgWaitForMultipleObjects(nCount+1,pHandlesTmp,fWaitAll,dwMilliseconds,dwWakeMask);
1297
1298 //unmark thread
1299 teb->o.odin.dwWakeMask = 0;
1300
1301 //nCount + 2 -> message event -> return nCount + 1
1302 return (ret == nCount + 2) ? (nCount + 1) : ret;
1303 }
1304 //Call handlemanager function as we need to translate handles (KERNEL32)
1305 ret = HMMsgWaitForMultipleObjects(nCount,pHandles,fWaitAll,dwMilliseconds,dwWakeMask);
1306 return ret;
1307#else
1308 //This method has a high latency (too high for some apps)
1309 //TODO: Timeout isn't handled correctly (can return too late)
1310 curtime = GetCurrentTime();
1311 endtime = curtime + dwMilliseconds;
1312 while(curtime < endtime || dwMilliseconds == INFINITE) {
1313 //check queue status for presence of requested message types
1314 if(GetQueueStatus(dwWakeMask) != 0) {
1315 dprintf(("Found message(s) we were looking for. Return success"));
1316 return WAIT_OBJECT_0 + nCount; //present, return success
1317 }
1318 //TODO: Ignoring all messages could be dangerous. But processing them,
1319 //while the app doesn't expect any, isn't safe either.
1320 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1321 {
1322 if (msg.message == WM_QUIT) {
1323 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1324 return WAIT_ABANDONED;
1325 }
1326
1327 /* otherwise dispatch it */
1328 DispatchMessageA(&msg);
1329 }
1330 //check if any object is signalled (timeout 10ms)
1331 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 4);
1332 if(ret < WAIT_OBJECT_0 + nCount) {
1333 //an object was signalled, return immediately
1334 dprintf(("WaitForMultipleObjects success with %d", ret));
1335 return ret;
1336 }
1337 else
1338 if(ret != WAIT_TIMEOUT) {
1339 //failure, abort
1340 dprintf(("WaitForMultipleObjects failed with %d", ret));
1341 return ret;
1342 }
1343 curtime = GetCurrentTime();
1344 }
1345 return WAIT_TIMEOUT;
1346#endif
1347}
Note: See TracBrowser for help on using the repository browser.