source: trunk/src/user32/oslibmsg.cpp@ 9356

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

Fix for WinPeekMsg bug (?); sometimes returns a message we didn't ask for (filter)

File size: 26.0 KB
Line 
1/* $Id: oslibmsg.cpp,v 1.63 2002-10-28 12:22:31 sandervl Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 * TODO: Some messages that are sent to the frame window are directly passed on to the client
12 * -> Get/PeekMessage never gets them as we return a dummy message for non-client windows
13 * (i.e. menu WM_COMMAND messages)
14 *
15 * TODO: Filter translation isn't correct! (for posted messages or messages that don't have
16 * a PM version.
17 *
18 */
19#define INCL_WIN
20#define INCL_PM
21#define INCL_DOSPROCESS
22#include <os2wrap.h>
23#include <odinwrap.h>
24#include <string.h>
25#include <misc.h>
26#include "oslibmsg.h"
27#include <winconst.h>
28#include <win32api.h>
29#include <winuser32.h>
30#include "oslibutil.h"
31#include "timer.h"
32#include <thread.h>
33#include <wprocess.h>
34#include "pmwindow.h"
35#include "oslibwin.h"
36#include <win\hook.h>
37#include <winscan.h>
38#include <winkeyboard.h>
39
40#define DBG_LOCALLOG DBG_oslibmsg
41#include "dbglocal.h"
42
43
44ODINDEBUGCHANNEL(USER32-OSLIBMSG)
45
46
47
48typedef BOOL (EXPENTRY FNTRANS)(MSG *, QMSG *);
49typedef FNTRANS *PFNTRANS;
50
51typedef struct
52{
53 ULONG msgOS2;
54 ULONG msgWin32;
55// PFNTRANS toOS2;
56// PFNTRANS toWIN32;
57} MSGTRANSTAB, *PMSGTRANSTAB;
58
59//NOTE: Must be ordered by win32 message id!!
60MSGTRANSTAB MsgTransTab[] = {
61 WM_NULL, WINWM_NULL,
62 WM_CREATE, WINWM_CREATE,
63 WM_DESTROY, WINWM_DESTROY,
64 WM_MOVE, WINWM_MOVE, //TODO: Sent directly
65 WM_SIZE, WINWM_SIZE, //TODO: Sent directly
66 WM_ACTIVATE, WINWM_ACTIVATE,
67 WM_SETFOCUS, WINWM_SETFOCUS,
68 WM_SETFOCUS, WINWM_KILLFOCUS,
69 WM_ENABLE, WINWM_ENABLE,
70 WM_PAINT, WINWM_PAINT,
71 WM_CLOSE, WINWM_CLOSE,
72 WM_QUIT, WINWM_QUIT,
73 WM_SHOW, WINWM_SHOWWINDOW,
74
75 WM_HITTEST, WINWM_NCHITTEST,
76
77 //todo: not always right if mouse msg turns out to be for the client window
78 WM_MOUSEMOVE, WINWM_NCMOUSEMOVE,
79 WM_BUTTON1DOWN, WINWM_NCLBUTTONDOWN,
80 WM_BUTTON1UP, WINWM_NCLBUTTONUP,
81 WM_BUTTON1DBLCLK, WINWM_NCLBUTTONDBLCLK,
82 WM_BUTTON2DOWN, WINWM_NCRBUTTONDOWN,
83 WM_BUTTON2UP, WINWM_NCRBUTTONUP,
84 WM_BUTTON2DBLCLK, WINWM_NCRBUTTONDBLCLK,
85 WM_BUTTON3DOWN, WINWM_NCMBUTTONDOWN,
86 WM_BUTTON3UP, WINWM_NCMBUTTONUP,
87 WM_BUTTON3DBLCLK, WINWM_NCMBUTTONDBLCLK,
88
89 //TODO: Needs better translation!
90 WM_CHAR, WINWM_KEYDOWN, //WM_KEYFIRST
91 WM_CHAR, WINWM_KEYUP,
92 WM_CHAR, WINWM_CHAR,
93 WM_CHAR, WINWM_DEADCHAR,
94 WM_CHAR, WINWM_SYSKEYDOWN,
95 WM_CHAR, WINWM_SYSKEYUP,
96 WM_CHAR, WINWM_SYSCHAR,
97 WM_CHAR, WINWM_SYSDEADCHAR,
98 WM_CHAR, WINWM_KEYLAST,
99
100 //
101 WM_TIMER, WINWM_TIMER,
102
103 //
104 //todo: not always right if mouse msg turns out to be for the nonclient window
105 WM_MOUSEMOVE, WINWM_MOUSEMOVE, //WM_MOUSEFIRST
106 WM_BUTTON1DOWN, WINWM_LBUTTONDOWN,
107 WM_BUTTON1UP, WINWM_LBUTTONUP,
108 WM_BUTTON1DBLCLK, WINWM_LBUTTONDBLCLK,
109 WM_BUTTON2DOWN, WINWM_RBUTTONDOWN,
110 WM_BUTTON2UP, WINWM_RBUTTONUP,
111 WM_BUTTON2DBLCLK, WINWM_RBUTTONDBLCLK,
112 WM_BUTTON3DOWN, WINWM_MBUTTONDOWN,
113 WM_BUTTON3UP, WINWM_MBUTTONUP,
114 WM_BUTTON3DBLCLK, WINWM_MBUTTONDBLCLK,
115 WM_BUTTON3DBLCLK, WINWM_MOUSEWHEEL, //WM_MOUSELAST
116 999999999, 999999999,
117};
118#define MAX_MSGTRANSTAB (sizeof(MsgTransTab)/sizeof(MsgTransTab[0]))
119
120//******************************************************************************
121//******************************************************************************
122void WinToOS2MsgTranslate(MSG *winMsg, QMSG *os2Msg, BOOL isUnicode)
123{
124 dprintf(("WinToOS2MsgTranslate not implemented"));
125// memcpy(os2Msg, winMsg, sizeof(MSG));
126// os2Msg->hwnd = Win32ToOS2Handle(winMsg->hwnd);
127// os2Msg->reserved = 0;
128}
129//******************************************************************************
130//TODO: NOT COMPLETE nor 100% CORRECT!!!
131//If both the minimum & maximum message are unknown, the result can be wrong (max > min)!
132//******************************************************************************
133ULONG TranslateWinMsg(ULONG msg, BOOL fMinFilter, BOOL fExactMatch = FALSE)
134{
135 if(msg == 0)
136 return 0;
137
138 if(msg >= WINWM_USER)
139 return msg + WIN32APP_POSTMSG;
140
141 for(int i=0;i<MAX_MSGTRANSTAB;i++)
142 {
143 if(fExactMatch) {
144 if(MsgTransTab[i].msgWin32 == msg)
145 return MsgTransTab[i].msgOS2;
146 }
147 else {
148 if(fMinFilter && MsgTransTab[i].msgWin32 >= msg) {
149 return MsgTransTab[i].msgOS2;
150 }
151 else
152 if(!fMinFilter && MsgTransTab[i].msgWin32 >= msg) {
153 if(MsgTransTab[i].msgWin32 == msg)
154 return MsgTransTab[i].msgOS2;
155 else return MsgTransTab[i-1].msgOS2;
156 }
157 }
158 }
159
160 //not found, get everything
161 dprintf2(("WARNING: TranslateWinMsg: message %x not found", msg));
162 return 0;
163}
164//******************************************************************************
165//******************************************************************************
166void OSLibWinPostQuitMessage(ULONG nExitCode)
167{
168 APIRET rc;
169
170 //NOTE: mp2 must always be zero or else we won't be able to distinguish
171 // between the WM_QUIT sent by us and the one sent by the window list!!
172 rc = WinPostQueueMsg(NULLHANDLE, WM_QUIT, MPFROMLONG(nExitCode), 0);
173 dprintf(("WinPostQueueMsg %d returned %d", nExitCode, rc));
174}
175//******************************************************************************
176//******************************************************************************
177LONG OSLibWinDispatchMsg(MSG *msg, BOOL isUnicode)
178{
179 TEB *teb;
180 QMSG os2msg;
181 LONG rc;
182
183 teb = GetThreadTEB();
184 if(teb == NULL) {
185 DebugInt3();
186 return FALSE;
187 }
188
189 //TODO: What to do if app changed msg? (translate)
190 // WinToOS2MsgTranslate(msg, &qmsg, isUnicode);
191
192 if(!memcmp(msg, &teb->o.odin.winmsg, sizeof(MSG)) || msg->hwnd == 0) {
193 memcpy(&os2msg, &teb->o.odin.os2msg, sizeof(QMSG));
194 teb->o.odin.os2msg.time = -1;
195 teb->o.odin.winmsg.time = -1;
196 if(msg->hwnd) {
197 teb->o.odin.nrOfMsgs = 1;
198 teb->o.odin.msgstate++; //odd -> next call to our PM window handler should dispatch the translated msg
199 memcpy(&teb->o.odin.msg, msg, sizeof(MSG));
200 }
201 if(os2msg.hwnd || os2msg.msg == WM_QUIT) {
202 memset(&teb->o.odin.os2msg, 0, sizeof(teb->o.odin.os2msg));
203 memset(&teb->o.odin.winmsg, 0, sizeof(teb->o.odin.winmsg));
204 return (LONG)WinDispatchMsg(teb->o.odin.hab, &os2msg);
205 }
206 //SvL: Don't dispatch messages sent by PostThreadMessage (correct??)
207 // Or WM_TIMER msgs with no window handle or timer proc
208 return 0;
209
210 }
211 else {//is this allowed?
212// dprintf(("WARNING: OSLibWinDispatchMsg: called with own message!"));
213 return SendMessageA(msg->hwnd, msg->message, msg->wParam, msg->lParam);
214 }
215}
216//******************************************************************************
217//******************************************************************************
218BOOL OSLibWinGetMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax,
219 BOOL isUnicode)
220{
221 BOOL rc, eaten;
222 TEB *teb;
223 QMSG os2msg;
224 HWND hwndOS2 = 0;
225 ULONG filtermin, filtermax;
226
227 if(hwnd) {
228 hwndOS2 = Win32ToOS2Handle(hwnd);
229 if(hwndOS2 == NULL) {
230 memset(pMsg, 0, sizeof(MSG));
231 dprintf(("GetMsg: window %x NOT FOUND!", hwnd));
232 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
233 return TRUE;
234 }
235 }
236
237 teb = GetThreadTEB();
238 if(teb == NULL) {
239 DebugInt3();
240 return TRUE;
241 }
242
243 if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd))
244 {
245 dprintf(("Return queued WM_CHAR message hwnd=%x msg=%d wParam=%x lParam=%x", teb->o.odin.msgWCHAR.hwnd, teb->o.odin.msgWCHAR.message, teb->o.odin.msgWCHAR.wParam, teb->o.odin.msgWCHAR.lParam));
246 if(uMsgFilterMin) {
247 if(teb->o.odin.msgWCHAR.message < uMsgFilterMin)
248 goto continuegetmsg;
249 }
250 if(uMsgFilterMax) {
251 if(teb->o.odin.msgWCHAR.message > uMsgFilterMax)
252 goto continuegetmsg;
253 }
254 teb->o.odin.fTranslated = FALSE;
255 memcpy(pMsg, &teb->o.odin.msgWCHAR, sizeof(MSG));
256 teb->o.odin.os2msg.msg = 0;
257 teb->o.odin.os2msg.hwnd = 0;
258
259 if(!IsWindow(pMsg->hwnd)) {
260 //could be a queued char message for a window that was just destroyed
261 //when that's the case, we ignore it (MFC assertions are triggered by this)
262 goto continuegetmsg;
263 }
264
265 // @@@PH verify this
266 // if this is a keyup or keydown message, we've got to
267 // call the keyboard hook here
268 // send keyboard messages to the registered hooks
269 switch (pMsg->message)
270 {
271 case WINWM_KEYDOWN:
272 case WINWM_KEYUP:
273 case WINWM_SYSKEYDOWN:
274 case WINWM_SYSKEYUP:
275 // only supposed to be called upon WM_KEYDOWN
276 // and WM_KEYUP according to docs.
277 if(ProcessKbdHook(pMsg, TRUE))
278 goto continuegetmsg;
279 break;
280 }
281
282 return (pMsg->message != WINWM_QUIT);
283 }
284
285continuegetmsg:
286 if(hwnd) {
287 filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
288 filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
289 if(filtermin > filtermax) {
290 ULONG tmp = filtermin;
291 filtermin = filtermax;
292 filtermax = filtermin;
293 }
294 do {
295 WinWaitMsg(teb->o.odin.hab, filtermin, filtermax);
296 rc = OSLibWinPeekMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, PM_REMOVE_W, isUnicode);
297 }
298 while(rc == FALSE);
299
300 return (pMsg->message != WINWM_QUIT);
301 }
302 else
303 {
304 filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
305 filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
306 if(filtermin > filtermax) {
307 ULONG tmp = filtermin;
308 filtermin = filtermax;
309 filtermax = filtermin;
310 }
311 do {
312 eaten = FALSE;
313 rc = WinGetMsg(teb->o.odin.hab, &os2msg, 0, filtermin, filtermax);
314 if (os2msg.msg == WM_TIMER)
315 eaten = TIMER_HandleTimer(&os2msg);
316 if (os2msg.msg == WM_QUIT && ((ULONG)os2msg.mp2 != 0) ) {
317 // Don't return FALSE when the window list sends us
318 // a WM_QUIT message, improper killing can lead to
319 // application crashes.
320 // In the WM_QUIT handler in pmwindow we send a WM_CLOSE
321 // in this case. When the app calls PostQuitMessage (mp2 == 0),
322 // then we handle it the normal way
323 rc = 1;
324 }
325 }
326 while (eaten);
327 }
328 if(OS2ToWinMsgTranslate((PVOID)teb, &os2msg, pMsg, isUnicode, MSG_REMOVE) == FALSE) {
329 //dispatch untranslated message immediately
330 WinDispatchMsg(teb->o.odin.hab, &os2msg);
331 //and get the next one
332 return OSLibWinGetMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, isUnicode);
333 }
334
335 memcpy(&teb->o.odin.os2msg, &os2msg, sizeof(QMSG));
336 memcpy(&teb->o.odin.winmsg, pMsg, sizeof(MSG));
337
338 // send keyboard messages to the registered hooks
339 switch (pMsg->message)
340 {
341 case WINWM_KEYDOWN:
342 case WINWM_KEYUP:
343 case WINWM_SYSKEYDOWN:
344 case WINWM_SYSKEYUP:
345 // only supposed to be called upon WM_KEYDOWN
346 // and WM_KEYUP according to docs.
347 if(ProcessKbdHook(pMsg, TRUE))
348 goto continuegetmsg;
349 break;
350 }
351 return rc;
352}
353
354
355//******************************************************************************
356//PeekMessage retrieves only messages associated with the window identified by the
357//hwnd parameter or any of its children as specified by the IsChild function, and within
358//the range of message values given by the uMsgFilterMin and uMsgFilterMax
359//parameters. If hwnd is NULL, PeekMessage retrieves messages for any window that
360//belongs to the current thread making the call. (PeekMessage does not retrieve
361//messages for windows that belong to other threads.) If hwnd is -1, PeekMessage only
362//returns messages with a hwnd value of NULL, as posted by the PostAppMessage
363//function. If uMsgFilterMin and uMsgFilterMax are both zero, PeekMessage returns all
364//available messages (no range filtering is performed).
365//TODO: Not working as specified right now!
366//******************************************************************************
367BOOL OSLibWinPeekMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax,
368 DWORD fRemove, BOOL isUnicode)
369{
370 BOOL rc, eaten;
371 TEB *teb;
372 QMSG os2msg;
373 HWND hwndOS2 = 0;
374
375 if(uMsgFilterMin > uMsgFilterMax) {
376 //TODO: is this correct behaviour?
377 dprintf(("!ERROR!: invalid message filter range!!!"));
378 SetLastError(ERROR_INVALID_PARAMETER_W);
379 return FALSE;
380 }
381 if(hwnd && hwnd != -1) {
382 hwndOS2 = Win32ToOS2Handle(hwnd);
383 if(hwndOS2 == NULL) {
384 dprintf(("PeekMsg: window %x NOT FOUND!", hwnd));
385 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
386 return FALSE;
387 }
388 }
389
390 teb = GetThreadTEB();
391 if(teb == NULL) {
392 DebugInt3();
393 return FALSE;
394 }
395
396 if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd))
397 {
398 dprintf(("Return queued WM_CHAR message hwnd=%x msg=%d wParam=%x lParam=%x", teb->o.odin.msgWCHAR.hwnd, teb->o.odin.msgWCHAR.message, teb->o.odin.msgWCHAR.wParam, teb->o.odin.msgWCHAR.lParam));
399 if(uMsgFilterMin) {
400 if(teb->o.odin.msgWCHAR.message < uMsgFilterMin)
401 goto continuepeekmsg;
402 }
403 if(uMsgFilterMax) {
404 if(teb->o.odin.msgWCHAR.message > uMsgFilterMax)
405 goto continuepeekmsg;
406 }
407
408 if(fRemove & PM_REMOVE_W) {
409 teb->o.odin.fTranslated = FALSE;
410 teb->o.odin.os2msg.msg = 0;
411 teb->o.odin.os2msg.hwnd = 0;
412 }
413 memcpy(pMsg, &teb->o.odin.msgWCHAR, sizeof(MSG));
414
415 if(!IsWindow(pMsg->hwnd)) {
416 //could be a queued char message for a window that was just destroyed
417 //when that's the case, we ignore it (MFC assertions are triggered by this)
418 teb->o.odin.fTranslated = FALSE;
419 teb->o.odin.os2msg.msg = 0;
420 teb->o.odin.os2msg.hwnd = 0;
421 goto continuepeekmsg;
422 }
423
424 // @@@PH verify this
425 // if this is a keyup or keydown message, we've got to
426 // call the keyboard hook here
427 // send keyboard messages to the registered hooks
428 if(fRemove & PM_REMOVE_W) {
429 switch (pMsg->message)
430 {
431 case WINWM_KEYDOWN:
432 case WINWM_KEYUP:
433 case WINWM_SYSKEYDOWN:
434 case WINWM_SYSKEYUP:
435 // only supposed to be called upon WM_KEYDOWN
436 // and WM_KEYUP according to docs.
437 if(ProcessKbdHook(pMsg, fRemove))
438 goto continuepeekmsg;
439 break;
440 }
441 }
442
443 return TRUE;
444 }
445
446continuepeekmsg:
447 if(uMsgFilterMin && uMsgFilterMax)
448 { //we can't use the PM message filter (since the message nrs aren't similar), so we must
449 //filter each message seperately
450 //to do so, we will translate each win32 message in the filter range and call WinPeekMsg
451 ULONG ulPMFilter;
452
453 for(int i=0;i<uMsgFilterMax-uMsgFilterMin+1;i++) {
454 rc = 0;
455
456 ulPMFilter = TranslateWinMsg(uMsgFilterMin+i, TRUE, TRUE);
457 if(ulPMFilter) {
458 do {
459 eaten = FALSE;
460
461 rc = WinPeekMsg(teb->o.odin.hab, &os2msg, hwndOS2, ulPMFilter, ulPMFilter,
462 (fRemove & PM_REMOVE_W) ? PM_REMOVE : PM_NOREMOVE);
463 //Sadly indeed WinPeekMsg sometimes does not filter well!
464 if (rc && (os2msg.msg != ulPMFilter)) {// drop this message
465 dprintf(("WARNING: WinPeekMsg returns %x even though we filter for %x", os2msg.msg, ulPMFilter));
466 rc = 0;
467 }
468 if (rc && (fRemove & PM_REMOVE_W) && os2msg.msg == WM_TIMER) {
469 eaten = TIMER_HandleTimer(&os2msg);
470 }
471 }
472 while (eaten && rc);
473 }
474 if(rc) {
475 break;
476 }
477 }
478 }
479 else {
480 do {
481 eaten = FALSE;
482
483 rc = WinPeekMsg(teb->o.odin.hab, &os2msg, hwndOS2, 0, 0, (fRemove & PM_REMOVE_W) ? PM_REMOVE : PM_NOREMOVE);
484
485 if (rc && (fRemove & PM_REMOVE_W) && os2msg.msg == WM_TIMER) {
486 eaten = TIMER_HandleTimer(&os2msg);
487 }
488 }
489 while (eaten && rc);
490 }
491 if(rc == FALSE) {
492 return FALSE;
493 }
494
495 // @@@PH
496 // warning - OS2ToWinMsgTranslate might insert additional messages
497 // into the queue
498 if(OS2ToWinMsgTranslate((PVOID)teb, &os2msg, pMsg, isUnicode, (fRemove & PM_REMOVE_W) ? MSG_REMOVE : MSG_NOREMOVE) == FALSE)
499 {
500 //unused PM message; dispatch immediately and grab next one
501 dprintf2(("OSLibWinPeekMsg: Untranslated message; dispatched immediately"));
502 if(!(fRemove & PM_REMOVE_W)) {
503 rc = WinPeekMsg(teb->o.odin.hab, &os2msg, hwndOS2, TranslateWinMsg(uMsgFilterMin, TRUE),
504 TranslateWinMsg(uMsgFilterMax, FALSE), PM_REMOVE);
505 }
506 WinDispatchMsg(teb->o.odin.hab, &os2msg);
507 return OSLibWinPeekMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, fRemove, isUnicode);
508 }
509 //TODO: This is not safe! There's no guarantee this message will be dispatched and it might overwrite a previous message
510 if(fRemove & PM_REMOVE_W) {
511 memcpy(&teb->o.odin.os2msg, &os2msg, sizeof(QMSG));
512 memcpy(&teb->o.odin.winmsg, pMsg, sizeof(MSG));
513 }
514
515 // send keyboard messages to the registered hooks
516 if(fRemove & PM_REMOVE_W) {
517 switch (pMsg->message)
518 {
519 case WINWM_KEYDOWN:
520 case WINWM_KEYUP:
521 case WINWM_SYSKEYDOWN:
522 case WINWM_SYSKEYUP:
523 // only supposed to be called upon WM_KEYDOWN
524 // and WM_KEYUP according to docs.
525 if(ProcessKbdHook(pMsg, fRemove))
526 goto continuepeekmsg;
527 break;
528 }
529 }
530
531 return rc;
532}
533//******************************************************************************
534//******************************************************************************
535ULONG OSLibWinQueryMsgTime()
536{
537 return WinQueryMsgTime(GetThreadHAB());
538}
539//******************************************************************************
540//******************************************************************************
541BOOL OSLibWinWaitMessage()
542{
543 return WinWaitMsg(GetThreadHAB(), 0, 0);
544}
545//******************************************************************************
546//TODO: QS_HOTKEY
547//******************************************************************************
548ULONG OSLibWinQueryQueueStatus()
549{
550 ULONG statusOS2, statusWin32 = 0;
551
552 statusOS2 = WinQueryQueueStatus(HWND_DESKTOP);
553
554 if(statusOS2 & QS_KEY)
555 statusWin32 |= QS_KEY_W;
556 if(statusOS2 & QS_MOUSEBUTTON)
557 statusWin32 |= QS_MOUSEBUTTON_W;
558 if(statusOS2 & QS_MOUSEMOVE)
559 statusWin32 |= QS_MOUSEMOVE_W;
560 if(statusOS2 & QS_TIMER)
561 statusWin32 |= QS_TIMER_W;
562 if(statusOS2 & QS_PAINT)
563 statusWin32 |= QS_PAINT_W;
564 if(statusOS2 & QS_POSTMSG)
565 statusWin32 |= QS_POSTMESSAGE_W;
566 if(statusOS2 & QS_SENDMSG)
567 statusWin32 |= QS_SENDMESSAGE_W;
568
569 return statusWin32;
570}
571//******************************************************************************
572//******************************************************************************
573BOOL OSLibWinInSendMessage()
574{
575 return WinInSendMsg(GetThreadHAB());
576}
577//******************************************************************************
578//******************************************************************************
579DWORD OSLibWinGetMessagePos()
580{
581 APIRET rc;
582 POINTL ptl;
583
584 rc = WinQueryMsgPos(GetThreadHAB(), &ptl);
585 if(!rc) {
586 return 0;
587 }
588 //convert to windows coordinates
589 return MAKEULONG(ptl.x,mapScreenY(ptl.y));
590}
591//******************************************************************************
592//******************************************************************************
593LONG OSLibWinGetMessageTime()
594{
595 return (LONG)WinQueryMsgTime(GetThreadHAB());
596}
597//******************************************************************************
598//******************************************************************************
599BOOL OSLibWinReplyMessage(ULONG result)
600{
601 return (BOOL)WinReplyMsg( NULLHANDLE, NULLHANDLE, HMQ_CURRENT, (MRESULT)result);
602}
603//******************************************************************************
604//******************************************************************************
605ULONG OSLibSendMessage(HWND hwnd, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
606{
607 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
608
609 if(NULL == packet)
610 {
611 dprintf(("user32::oslibmsg::OSLibSendMessage - allocated packet structure is NULL"));
612
613 // PH: we cannot provide a correct returncode :(
614 DebugInt3();
615 return 0;
616 }
617
618 packet->wParam = wParam;
619 packet->lParam = lParam;
620
621 return (ULONG)WinSendMsg(hwnd, WIN32APP_POSTMSG+msg, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
622}
623//******************************************************************************
624//******************************************************************************
625ULONG OSLibWinBroadcastMsg(ULONG msg, ULONG wParam, ULONG lParam, BOOL fSend)
626{
627 return WinBroadcastMsg(HWND_DESKTOP, WIN32APP_POSTMSG+msg, (MPARAM)wParam, (MPARAM)lParam,
628 (fSend) ? BMSG_SEND : BMSG_POST);
629}
630//******************************************************************************
631//******************************************************************************
632BOOL OSLibPostMessage(HWND hwndWin32, HWND hwndOS2, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
633{
634 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
635 BOOL ret;
636
637 if (NULL == packet)
638 {
639 dprintf(("user32::oslibmsg::OSLibPostMessage - allocated packet structure is NULL"));
640
641 // PH: we can provide a correct returncode
642 DebugInt3();
643 return FALSE;
644 }
645 TEB *teb = GetTEBFromThreadId(GetWindowThreadProcessId(hwndWin32, NULL));
646
647 packet->wParam = wParam;
648 packet->lParam = lParam;
649 ret = WinPostMsg(hwndOS2, WIN32APP_POSTMSG+msg, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
650
651 if(teb && (teb->o.odin.dwWakeMask & QS_POSTMESSAGE_W)) {
652 //thread is blocked in MsgWaitForMultipleObjects waiting for
653 //posted messages
654 dprintf(("PostMessage: Wake up thread %x which is blocked in MsgWaitForMultipleObjects", teb->o.odin.threadId));
655 SetEvent(teb->o.odin.hPostMsgEvent);
656 }
657 return ret;
658}
659//******************************************************************************
660//Direct posting of messages that must remain invisible to the win32 app
661//******************************************************************************
662BOOL OSLibPostMessageDirect(HWND hwnd, ULONG msg, ULONG wParam, ULONG lParam)
663{
664 return WinPostMsg(hwnd, msg, (MPARAM)wParam, (MPARAM)lParam);
665}
666//******************************************************************************
667//******************************************************************************
668BOOL OSLibPostThreadMessage(ULONG threadid, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fUnicode)
669{
670 TEB *teb = GetTEBFromThreadId(threadid);
671 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
672 BOOL ret;
673
674 if(NULL == packet)
675 {
676 dprintf(("user32::oslibmsg::OSLibPostMessage - allocated packet structure is NULL"));
677
678 DebugInt3();
679 // PH: we can provide a correct returncode
680 return FALSE;
681 }
682
683 if(teb == NULL) {
684 dprintf(("OSLibPostThreadMessage: thread %x not found!", threadid));
685 return FALSE;
686 }
687 dprintf(("PostThreadMessageA %x %x %x %x -> hmq %x", threadid, msg, wParam, lParam, teb->o.odin.hmq));
688 packet->wParam = wParam;
689 packet->lParam = lParam;
690
691 ret = WinPostQueueMsg((HMQ)teb->o.odin.hmq, WIN32APP_POSTMSG+msg,
692 (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA),
693 (MPARAM)packet);
694
695 if(ret == FALSE)
696 {
697 SetLastError(ERROR_INVALID_PARAMETER_W);
698 return FALSE;
699 }
700
701 if(teb->o.odin.dwWakeMask & QS_POSTMESSAGE_W) {
702 //thread is blocked in MsgWaitForMultipleObjects waiting for
703 //posted messages
704 dprintf(("PostMessage: Wake up thread %x which is blocked in MsgWaitForMultipleObjects", teb->o.odin.threadId));
705 SetEvent(teb->o.odin.hPostMsgEvent);
706 }
707
708 SetLastError(ERROR_SUCCESS_W);
709 return TRUE;
710}
711//******************************************************************************
712//******************************************************************************
713DWORD GetThreadMessageExtraInfo()
714{
715 TEB *teb;
716
717 teb = GetThreadTEB();
718 if(teb)
719 {
720 return teb->o.odin.dwMsgExtraInfo;
721 }
722 dprintf(("GetThreadMessageExtraInfo: teb == NULL!!"));
723 return 0;
724}
725//******************************************************************************
726//******************************************************************************
727DWORD SetThreadMessageExtraInfo(DWORD lParam)
728{
729 TEB *teb;
730
731 teb = GetThreadTEB();
732 if(teb)
733 {
734 teb->o.odin.dwMsgExtraInfo = lParam;
735 }
736 else dprintf(("SetThreadMessageExtraInfo: teb == NULL!!"));
737 return 0;
738}
739//******************************************************************************
740//******************************************************************************
Note: See TracBrowser for help on using the repository browser.