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

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

KSO: Implemented WM_COPYDATA

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