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

Last change on this file since 8960 was 8960, checked in by sandervl, 23 years ago

MsgWaitForMultipleObjects changes; check objects before message queue status

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