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

Last change on this file since 21555 was 21555, checked in by dmik, 15 years ago

user32: Make GetQueueStatus() return actual message summary in high word instead of the copy of the low word (WinQueryQueueStatus() API provides this functionality according to my tests, despite unclear docs).

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