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

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

Handle WM_(SYS)TIMER timer calls in DispatchMessageA/W

File size: 37.3 KB
Line 
1/* $Id: windowmsg.cpp,v 1.42 2003-05-16 10:59:28 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 CallWindowProcA( (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 wParam, LPARAM *plparam )
317{
318 switch(msg)
319 {
320 case WM_GETTEXT:
321 {
322 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
323 wParam * sizeof(WCHAR) + sizeof(LPARAM) );
324 if (!ptr) return -1;
325 *ptr++ = *plparam; /* Store previous lParam */
326 *plparam = (LPARAM)ptr;
327 }
328 return 1;
329 /* lparam is string (0-terminated) */
330 case WM_SETTEXT:
331 case WM_WININICHANGE:
332 case CB_DIR:
333 case LB_DIR:
334 case LB_ADDFILE:
335#ifndef __WIN32OS2__
336 case CB_FINDSTRING:
337 case CB_FINDSTRINGEXACT:
338 case CB_SELECTSTRING:
339 case LB_FINDSTRING:
340 case LB_SELECTSTRING:
341#endif
342 case EM_REPLACESEL:
343 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
344 return (*plparam ? 1 : -1);
345
346 case WM_NCCREATE:
347 case WM_CREATE:
348 {
349 CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
350 sizeof(*cs) );
351 if (!cs) return -1;
352 *cs = *(CREATESTRUCTW *)*plparam;
353 if (HIWORD(cs->lpszName))
354 cs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
355 (LPCSTR)cs->lpszName );
356 if (HIWORD(cs->lpszClass))
357 cs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
358 (LPCSTR)cs->lpszClass );
359 *plparam = (LPARAM)cs;
360 }
361 return 1;
362 case WM_MDICREATE:
363 {
364 MDICREATESTRUCTW *cs =
365 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
366 if (!cs) return -1;
367 *cs = *(MDICREATESTRUCTW *)*plparam;
368 if (HIWORD(cs->szClass))
369 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
370 (LPCSTR)cs->szClass );
371 if (HIWORD(cs->szTitle))
372 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
373 (LPCSTR)cs->szTitle );
374 *plparam = (LPARAM)cs;
375 }
376 return 1;
377
378/* Listbox */
379 case LB_ADDSTRING:
380#ifdef __WIN32OS2__
381 case LB_FINDSTRING:
382 case LB_FINDSTRINGEXACT:
383 case LB_SELECTSTRING:
384#endif
385 case LB_INSERTSTRING:
386 if ( WINPROC_TestLBForStr( hwnd ))
387 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
388 return (*plparam ? 1 : -1);
389
390 case LB_GETTEXT: /* fixme: fixed sized buffer */
391 { if ( WINPROC_TestLBForStr( hwnd ))
392 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
393 if (!ptr) return -1;
394 *ptr++ = *plparam; /* Store previous lParam */
395 *plparam = (LPARAM)ptr;
396 }
397 }
398 return 1;
399
400/* Combobox */
401 case CB_ADDSTRING:
402#ifdef __WIN32OS2__
403 case CB_FINDSTRING:
404 case CB_FINDSTRINGEXACT:
405 case CB_SELECTSTRING:
406#endif
407 case CB_INSERTSTRING:
408 if ( WINPROC_TestCBForStr( hwnd ))
409 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
410 return (*plparam ? 1 : -1);
411
412 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
413 { if ( WINPROC_TestCBForStr( hwnd ))
414 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
415 if (!ptr) return -1;
416 *ptr++ = *plparam; /* Store previous lParam */
417 *plparam = (LPARAM)ptr;
418 }
419 }
420 return 1;
421
422/* Multiline edit */
423 case EM_GETLINE:
424 { WORD len = (WORD)*plparam;
425 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
426 if (!ptr) return -1;
427 *ptr++ = *plparam; /* Store previous lParam */
428 *((WORD *) ptr) = len; /* Store the length */
429 *plparam = (LPARAM)ptr;
430 }
431 return 1;
432
433 case WM_ASKCBFORMATNAME:
434 case WM_DEVMODECHANGE:
435 case WM_PAINTCLIPBOARD:
436 case WM_SIZECLIPBOARD:
437 case EM_SETPASSWORDCHAR:
438 // FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg), msg );
439 return -1;
440 default: /* No translation needed */
441 return 0;
442 }
443}
444
445
446/**********************************************************************
447 * WINPROC_UnmapMsg32ATo32W
448 *
449 * Unmap a message that was mapped from Ansi to Unicode.
450 */
451void WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
452{
453 switch(msg)
454 {
455 case WM_GETTEXT:
456 {
457 LPARAM *ptr = (LPARAM *)lParam - 1;
458 lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)lParam, wParam );
459 HeapFree( GetProcessHeap(), 0, ptr );
460 }
461 break;
462
463 case WM_NCCREATE:
464 case WM_CREATE:
465 {
466 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
467 if (HIWORD(cs->lpszName))
468 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
469 if (HIWORD(cs->lpszClass))
470 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
471 HeapFree( GetProcessHeap(), 0, cs );
472 }
473 break;
474
475 case WM_MDICREATE:
476 {
477 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
478 if (HIWORD(cs->szTitle))
479 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
480 if (HIWORD(cs->szClass))
481 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
482 HeapFree( GetProcessHeap(), 0, cs );
483 }
484 break;
485
486 case WM_SETTEXT:
487 case WM_WININICHANGE:
488 case CB_DIR:
489 case LB_DIR:
490 case LB_ADDFILE:
491#ifndef __WIN32OS2__
492 case CB_FINDSTRING:
493 case CB_FINDSTRINGEXACT:
494 case CB_SELECTSTRING:
495 case LB_FINDSTRING:
496 case LB_SELECTSTRING:
497#endif
498 case EM_REPLACESEL:
499 HeapFree( GetProcessHeap(), 0, (void *)lParam );
500 break;
501
502/* Listbox */
503 case LB_ADDSTRING:
504#ifdef __WIN32OS2__
505 case LB_FINDSTRING:
506 case LB_FINDSTRINGEXACT:
507 case LB_SELECTSTRING:
508#endif
509 case LB_INSERTSTRING:
510 if ( WINPROC_TestLBForStr( hwnd ))
511 HeapFree( GetProcessHeap(), 0, (void *)lParam );
512 break;
513
514 case LB_GETTEXT:
515 { if ( WINPROC_TestLBForStr( hwnd ))
516 { LPARAM *ptr = (LPARAM *)lParam - 1;
517 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
518 HeapFree( GetProcessHeap(), 0, ptr );
519 }
520 }
521 break;
522
523/* Combobox */
524 case CB_ADDSTRING:
525#ifdef __WIN32OS2__
526 case CB_FINDSTRING:
527 case CB_FINDSTRINGEXACT:
528 case CB_SELECTSTRING:
529#endif
530 case CB_INSERTSTRING:
531 if ( WINPROC_TestCBForStr( hwnd ))
532 HeapFree( GetProcessHeap(), 0, (void *)lParam );
533 break;
534
535 case CB_GETLBTEXT:
536 { if ( WINPROC_TestCBForStr( hwnd ))
537 { LPARAM *ptr = (LPARAM *)lParam - 1;
538 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
539 HeapFree( GetProcessHeap(), 0, ptr );
540 }
541 }
542 break;
543
544/* Multiline edit */
545 case EM_GETLINE:
546 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
547 WORD len = *(WORD *) lParam;
548 lstrcpynWtoA( (LPSTR)*ptr , (LPWSTR)lParam, len );
549 HeapFree( GetProcessHeap(), 0, ptr );
550 }
551 break;
552 }
553}
554
555
556/**********************************************************************
557 * WINPROC_MapMsg32WTo32A
558 *
559 * Map a message from Unicode to Ansi.
560 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
561 */
562INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM *plparam)
563{ switch(msg)
564 {
565 case WM_GETTEXT:
566 {
567 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
568 wParam + sizeof(LPARAM) );
569 if (!ptr) return -1;
570 *ptr++ = *plparam; /* Store previous lParam */
571 *plparam = (LPARAM)ptr;
572 }
573 return 1;
574
575 case WM_SETTEXT:
576 case WM_WININICHANGE:
577 case CB_DIR:
578 case LB_DIR:
579 case LB_ADDFILE:
580#ifndef __WIN32OS2__
581 case CB_FINDSTRING:
582 case CB_FINDSTRINGEXACT:
583 case CB_SELECTSTRING:
584 case LB_FINDSTRING:
585 case LB_SELECTSTRING:
586#endif
587 case EM_REPLACESEL:
588 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
589 return (*plparam ? 1 : -1);
590
591 case WM_NCCREATE:
592 case WM_CREATE:
593 {
594 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
595 sizeof(*cs) );
596 if (!cs) return -1;
597 *cs = *(CREATESTRUCTA *)*plparam;
598 if (HIWORD(cs->lpszName))
599 cs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
600 (LPCWSTR)cs->lpszName );
601 if (HIWORD(cs->lpszClass))
602 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
603 (LPCWSTR)cs->lpszClass);
604 *plparam = (LPARAM)cs;
605 }
606 return 1;
607 case WM_MDICREATE:
608 {
609 MDICREATESTRUCTA *cs =
610 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
611
612 if (!cs) return -1;
613 *cs = *(MDICREATESTRUCTA *)*plparam;
614 if (HIWORD(cs->szTitle))
615 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
616 (LPCWSTR)cs->szTitle );
617 if (HIWORD(cs->szClass))
618 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
619 (LPCWSTR)cs->szClass );
620 *plparam = (LPARAM)cs;
621 }
622 return 1;
623
624/* Listbox */
625 case LB_ADDSTRING:
626#ifdef __WIN32OS2__
627 case LB_FINDSTRING:
628 case LB_FINDSTRINGEXACT:
629 case LB_SELECTSTRING:
630#endif
631 case LB_INSERTSTRING:
632 if ( WINPROC_TestLBForStr( hwnd ))
633 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
634 return (*plparam ? 1 : -1);
635
636 case LB_GETTEXT: /* fixme: fixed sized buffer */
637 { if ( WINPROC_TestLBForStr( hwnd ))
638 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
639 if (!ptr) return -1;
640 *ptr++ = *plparam; /* Store previous lParam */
641 *plparam = (LPARAM)ptr;
642 }
643 }
644 return 1;
645
646/* Combobox */
647 case CB_ADDSTRING:
648#ifdef __WIN32OS2__
649 case CB_FINDSTRING:
650 case CB_FINDSTRINGEXACT:
651 case CB_SELECTSTRING:
652#endif
653 case CB_INSERTSTRING:
654 if ( WINPROC_TestCBForStr( hwnd ))
655 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
656 return (*plparam ? 1 : -1);
657
658 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
659 { if ( WINPROC_TestCBForStr( hwnd ))
660 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
661 if (!ptr) return -1;
662 *ptr++ = *plparam; /* Store previous lParam */
663 *plparam = (LPARAM)ptr;
664 }
665 }
666 return 1;
667
668/* Multiline edit */
669 case EM_GETLINE:
670 { WORD len = (WORD)*plparam;
671 LPARAM *ptr = (LPARAM *) HEAP_xalloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
672 if (!ptr) return -1;
673 *ptr++ = *plparam; /* Store previous lParam */
674 *((WORD *) ptr) = len; /* Store the length */
675 *plparam = (LPARAM)ptr;
676 }
677 return 1;
678
679 case WM_ASKCBFORMATNAME:
680 case WM_DEVMODECHANGE:
681 case WM_PAINTCLIPBOARD:
682 case WM_SIZECLIPBOARD:
683 case EM_SETPASSWORDCHAR:
684 // FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg),msg );
685 return -1;
686 default: /* No translation needed */
687 return 0;
688 }
689}
690
691
692/**********************************************************************
693 * WINPROC_UnmapMsg32WTo32A
694 *
695 * Unmap a message that was mapped from Unicode to Ansi.
696 */
697void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
698{
699 switch(msg)
700 {
701 case WM_GETTEXT:
702 {
703 LPARAM *ptr = (LPARAM *)lParam - 1;
704 lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)lParam, wParam );
705 HeapFree( GetProcessHeap(), 0, ptr );
706 }
707 break;
708
709 case WM_SETTEXT:
710 case WM_WININICHANGE:
711 case CB_DIR:
712 case LB_DIR:
713 case LB_ADDFILE:
714#ifndef __WIN32OS2__
715 case CB_FINDSTRING:
716 case CB_FINDSTRINGEXACT:
717 case CB_SELECTSTRING:
718 case LB_FINDSTRING:
719 case LB_SELECTSTRING:
720#endif
721 case EM_REPLACESEL:
722 HeapFree( GetProcessHeap(), 0, (void *)lParam );
723 break;
724
725 case WM_NCCREATE:
726 case WM_CREATE:
727 {
728 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
729 if (HIWORD(cs->lpszName))
730 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
731 if (HIWORD(cs->lpszClass))
732 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
733 HeapFree( GetProcessHeap(), 0, cs );
734 }
735 break;
736
737 case WM_MDICREATE:
738 {
739 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
740 if (HIWORD(cs->szTitle))
741 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
742 if (HIWORD(cs->szClass))
743 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
744 HeapFree( GetProcessHeap(), 0, cs );
745 }
746 break;
747
748/* Listbox */
749 case LB_ADDSTRING:
750#ifdef __WIN32OS2__
751 case LB_FINDSTRING:
752 case LB_FINDSTRINGEXACT:
753 case LB_SELECTSTRING:
754#endif
755 case LB_INSERTSTRING:
756 if ( WINPROC_TestLBForStr( hwnd ))
757 HeapFree( GetProcessHeap(), 0, (void *)lParam );
758 break;
759
760 case LB_GETTEXT:
761 { if ( WINPROC_TestLBForStr( hwnd ))
762 { LPARAM *ptr = (LPARAM *)lParam - 1;
763 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
764 HeapFree(GetProcessHeap(), 0, ptr );
765 }
766 }
767 break;
768
769/* Combobox */
770 case CB_ADDSTRING:
771#ifdef __WIN32OS2__
772 case CB_FINDSTRING:
773 case CB_FINDSTRINGEXACT:
774 case CB_SELECTSTRING:
775#endif
776 case CB_INSERTSTRING:
777 if ( WINPROC_TestCBForStr( hwnd ))
778 HeapFree( GetProcessHeap(), 0, (void *)lParam );
779 break;
780
781 case CB_GETLBTEXT:
782 { if ( WINPROC_TestCBForStr( hwnd ))
783 { LPARAM *ptr = (LPARAM *)lParam - 1;
784 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
785 HeapFree( GetProcessHeap(), 0, ptr );
786 }
787 }
788 break;
789
790/* Multiline edit */
791 case EM_GETLINE:
792 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
793 WORD len = *(WORD *)ptr;
794 lstrcpynAtoW( (LPWSTR) *ptr, (LPSTR)lParam, len );
795 HeapFree( GetProcessHeap(), 0, ptr );
796 }
797 break;
798 }
799}
800
801/**********************************************************************
802 * WINPROC_CallProc32ATo32W
803 *
804 * Call a window procedure, translating args from Ansi to Unicode.
805 */
806LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
807 UINT msg, WPARAM wParam,
808 LPARAM lParam )
809{
810 LRESULT result;
811
812 if (WINPROC_MapMsg32ATo32W( hwnd, msg, wParam, &lParam ) == -1) return 0;
813 result = func( hwnd, msg, wParam, lParam );
814 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
815 return result;
816}
817
818/**********************************************************************
819 * WINPROC_CallProc32WTo32A
820 *
821 * Call a window procedure, translating args from Unicode to Ansi.
822 */
823LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
824 UINT msg, WPARAM wParam,
825 LPARAM lParam )
826{
827 LRESULT result;
828
829 if (WINPROC_MapMsg32WTo32A( hwnd, msg, wParam, &lParam ) == -1) return 0;
830
831 result = func( hwnd, msg, wParam, lParam );
832 WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
833 return result;
834}
835//******************************************************************************
836//TODO: QS_HOTKEY (oslibmsg.cpp) & low word bits
837//high word = messages currently in queue
838//low word = messages that have been added to the queue and are still in the
839// queue since the last call to GetQueueStatus
840//******************************************************************************
841DWORD WIN32API GetQueueStatus( UINT flags)
842{
843 DWORD queueStatus;
844
845 queueStatus = OSLibWinQueryQueueStatus();
846 queueStatus = MAKELONG(queueStatus, queueStatus);
847
848 dprintf(("USER32: GetQueueStatus %x returned %x", flags, queueStatus & MAKELONG(flags, flags)));
849
850 return queueStatus & MAKELONG(flags, flags);
851}
852/*****************************************************************************
853 * Name : BOOL WIN32API GetInputState
854 * Purpose : The GetInputState function determines whether there are
855 * mouse-button or keyboard messages in the calling thread's message queue.
856 * Parameters:
857 * Variables :
858 * Result : If the queue contains one or more new mouse-button or keyboard
859 * messages, the return value is TRUE.
860 * If the function fails, the return value is FALSE.
861 * Remark :
862 * Status : UNTESTED STUB
863 *
864 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
865 *****************************************************************************/
866BOOL WIN32API GetInputState(VOID)
867{
868 DWORD queueStatus;
869 BOOL rc;
870
871 queueStatus = OSLibWinQueryQueueStatus();
872
873 rc = (queueStatus & (QS_KEY | QS_MOUSEBUTTON)) ? TRUE : FALSE;
874 dprintf(("USER32:GetInputState() returned %d", rc));
875 return rc;
876}
877//******************************************************************************
878/* Synchronization Functions */
879//******************************************************************************
880DWORD WIN32API MsgWaitForMultipleObjects(DWORD nCount, LPHANDLE pHandles, BOOL fWaitAll,
881 DWORD dwMilliseconds, DWORD dwWakeMask)
882{
883 DWORD curtime, endtime, ret;
884 MSG msg;
885
886 //TODO: Functions such as GetMessage, PeekMessage and WaitMessage can mark messages as old
887 // MsgWaitForMultipleObjects shouldn't return until new input has arrived (MSDN)
888 // We are not 100% correct with this implementation. GetQueueStatus checks all messages
889 // in the queue.
890 // Very obscure behaviour, so it's unlikely any application depends on it
891
892 //4 cases:
893 //1: Wait for all -> check for message arrival, call WaitForMultipleObjects
894 //2: Timeout = 0 ms -> call WaitForMultipleObjects with timeout 0, check for message arrival
895 //3: nCount = 0 -> check for message arrival
896 //4: rest -> check for either message arrival or signalled object
897
898 dprintf(("MsgWaitForMultipleObjects %x %x %d %d %x", nCount, pHandles, fWaitAll, dwMilliseconds, dwWakeMask));
899 if(fWaitAll) //case 1
900 { //wait for message arrival first
901 curtime = GetCurrentTime();
902 endtime = curtime + dwMilliseconds;
903 while(curtime < endtime || dwMilliseconds == INFINITE) {
904 if(OSLibWinWaitMessage() == FALSE) {
905 dprintf(("OSLibWinWaitMessage returned FALSE!"));
906 return WAIT_ABANDONED;
907 }
908 if(GetQueueStatus(dwWakeMask) != 0) {
909 break;
910 }
911 //TODO: Ignoring all messages could be dangerous. But processing them,
912 //while the app doesn't expect any, isn't safe either.
913 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
914 {
915 if (msg.message == WM_QUIT) {
916 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
917 return WAIT_ABANDONED;
918 }
919
920 /* otherwise dispatch it */
921 DispatchMessageA(&msg);
922 }
923 curtime = GetCurrentTime();
924 }
925 if(dwMilliseconds != INFINITE && curtime > endtime) {
926 dprintf(("No messages found in specified time"));
927 return WAIT_TIMEOUT;
928 }
929 //ok, the right message has arrived, now try to grab all objects
930 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
931 if(ret >= WAIT_OBJECT_0 + nCount) {
932 //failure
933 dprintf(("WaitForMultipleObjects failed with %d", ret));
934 return ret;
935 }
936 return ret;
937 }
938 if(dwMilliseconds == 0) { //case 2
939 if(nCount) {
940 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, dwMilliseconds);
941 if(ret < WAIT_OBJECT_0 + nCount) {
942 return ret;
943 }
944 }
945 if(GetQueueStatus(dwWakeMask) == 0) {
946 return WAIT_TIMEOUT;
947 }
948 return WAIT_OBJECT_0 + nCount; //right message has arrived
949 }
950 if(nCount == 0) //case 3
951 {
952 //SvL: Check time, wait for any message, check msg type and determine if
953 // we have to return
954 //TODO: Timeout isn't handled correctly (can return too late)
955 curtime = GetCurrentTime();
956 endtime = curtime + dwMilliseconds;
957 while(curtime < endtime || dwMilliseconds == INFINITE) {
958 if(OSLibWinWaitMessage() == FALSE) {
959 dprintf(("OSLibWinWaitMessage returned FALSE!"));
960 return WAIT_ABANDONED;
961 }
962 if(GetQueueStatus(dwWakeMask) != 0) {
963 return WAIT_OBJECT_0;
964 }
965 //TODO: Ignoring all messages could be dangerous. But processing them,
966 //while the app doesn't expect any, isn't safe either.
967 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
968 {
969 if (msg.message == WM_QUIT) {
970 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
971 return WAIT_ABANDONED;
972 }
973
974 /* otherwise dispatch it */
975 DispatchMessageA(&msg);
976 }
977 curtime = GetCurrentTime();
978 }
979 return WAIT_TIMEOUT;
980 }
981
982 //Case 4:
983#if 1
984 //Note: The WGSS implementation of this function is flawed. Returns
985 // when a message is sent to the msg queue, regardless of dwWakeMask
986 TEB *teb = GetTEBFromThreadId(GetCurrentThreadId());
987 if(teb == NULL) {
988 DebugInt3();
989 return WAIT_ABANDONED;
990 }
991 //check if any object is already signalled
992 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 0);
993 if(ret < WAIT_OBJECT_0 + nCount) {
994 return ret;
995 }
996 //if the msg queue already contains the messages defined by dwWakeMask,
997 //then return immediately
998 if(GetQueueStatus(dwWakeMask) != 0) {
999 return WAIT_OBJECT_0+nCount;
1000 }
1001 if(dwWakeMask & QS_POSTMESSAGE) {
1002 HANDLE *pHandlesTmp = (HANDLE *)alloca((nCount+1)*sizeof(HANDLE));
1003 if(pHandlesTmp == NULL || !teb->o.odin.hPostMsgEvent) {
1004 DebugInt3();
1005 return WAIT_ABANDONED;
1006 }
1007 memcpy(pHandlesTmp, pHandles, nCount*sizeof(HANDLE));
1008 pHandlesTmp[nCount] = teb->o.odin.hPostMsgEvent;
1009
1010 //mark this thread as waiting for window messages
1011 teb->o.odin.dwWakeMask = dwWakeMask;
1012
1013 ResetEvent(teb->o.odin.hPostMsgEvent);
1014 ret = HMMsgWaitForMultipleObjects(nCount+1,pHandlesTmp,fWaitAll,dwMilliseconds,dwWakeMask);
1015
1016 //unmark thread
1017 teb->o.odin.dwWakeMask = 0;
1018
1019 //nCount + 2 -> message event -> return nCount + 1
1020 return (ret == nCount + 2) ? (nCount + 1) : ret;
1021 }
1022 //Call handlemanager function as we need to translate handles (KERNEL32)
1023 ret = HMMsgWaitForMultipleObjects(nCount,pHandles,fWaitAll,dwMilliseconds,dwWakeMask);
1024 return ret;
1025#else
1026 //This method has a high latency (too high for some apps)
1027 //TODO: Timeout isn't handled correctly (can return too late)
1028 curtime = GetCurrentTime();
1029 endtime = curtime + dwMilliseconds;
1030 while(curtime < endtime || dwMilliseconds == INFINITE) {
1031 //check queue status for presence of requested message types
1032 if(GetQueueStatus(dwWakeMask) != 0) {
1033 dprintf(("Found message(s) we were looking for. Return success"));
1034 return WAIT_OBJECT_0 + nCount; //present, return success
1035 }
1036 //TODO: Ignoring all messages could be dangerous. But processing them,
1037 //while the app doesn't expect any, isn't safe either.
1038 if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1039 {
1040 if (msg.message == WM_QUIT) {
1041 dprintf(("ERROR: MsgWaitForMultipleObjects call abandoned because WM_QUIT msg was received!!"));
1042 return WAIT_ABANDONED;
1043 }
1044
1045 /* otherwise dispatch it */
1046 DispatchMessageA(&msg);
1047 }
1048 //check if any object is signalled (timeout 10ms)
1049 ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 4);
1050 if(ret < WAIT_OBJECT_0 + nCount) {
1051 //an object was signalled, return immediately
1052 dprintf(("WaitForMultipleObjects success with %d", ret));
1053 return ret;
1054 }
1055 else
1056 if(ret != WAIT_TIMEOUT) {
1057 //failure, abort
1058 dprintf(("WaitForMultipleObjects failed with %d", ret));
1059 return ret;
1060 }
1061 curtime = GetCurrentTime();
1062 }
1063 return WAIT_TIMEOUT;
1064#endif
1065}
Note: See TracBrowser for help on using the repository browser.