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

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

Merged Rewind menu control

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