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

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

Handle SetFocus(0) correctly: keystrokes are converted into WM_SYSKEYDOWN/(WM_SYSCHAR)/WM_SYSKEYUP messages

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