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

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

KOM: another bugfix

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