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

Last change on this file since 10367 was 10216, checked in by sandervl, 22 years ago

KOM: WM_IME_CHAR generation + processing added for DBCS input

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