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

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

KOMH: DBCS updates/fixes

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