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

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

Updates

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