Cleanup: Replace WINBOOL by BOOL
[reactos.git] / reactos / lib / user32 / windows / message.c
1 /* $Id: message.c,v 1.33 2004/01/23 23:38:26 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/message.c
6 * PURPOSE: Messages
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * 06-06-2001 CSH Created
10 */
11 #include <windows.h>
12 #include <user32.h>
13 #include <string.h>
14 #include <debug.h>
15
16 /*
17 * @implemented
18 */
19 LPARAM
20 STDCALL
21 GetMessageExtraInfo(VOID)
22 {
23 return (LPARAM)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO);
24 }
25
26
27 /*
28 * @implemented
29 */
30 DWORD
31 STDCALL
32 GetMessagePos(VOID)
33 {
34 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
35 return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y));
36 }
37
38
39 /*
40 * @implemented
41 */
42 LONG STDCALL
43 GetMessageTime(VOID)
44 {
45 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
46 return(ThreadData->LastMessage.time);
47 }
48
49
50 /*
51 * @unimplemented
52 */
53 BOOL
54 STDCALL
55 InSendMessage(VOID)
56 {
57 return FALSE;
58 }
59
60
61 /*
62 * @unimplemented
63 */
64 DWORD
65 STDCALL
66 InSendMessageEx(
67 LPVOID lpReserved)
68 {
69 UNIMPLEMENTED;
70 return 0;
71 }
72
73
74 /*
75 * @unimplemented
76 */
77 BOOL
78 STDCALL
79 ReplyMessage(
80 LRESULT lResult)
81 {
82 UNIMPLEMENTED;
83 return FALSE;
84 }
85
86
87 /*
88 * @implemented
89 */
90 LPARAM
91 STDCALL
92 SetMessageExtraInfo(
93 LPARAM lParam)
94 {
95 return (LPARAM)NtUserCallOneParam((DWORD)lParam, ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO);
96 }
97
98
99 BOOL
100 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg)
101 {
102 *UnicodeMsg = *AnsiMsg;
103 switch (AnsiMsg->message)
104 {
105 case WM_GETTEXT:
106 case WM_ASKCBFORMATNAME:
107 {
108 LPWSTR Buffer = HeapAlloc(GetProcessHeap(), 0,
109 AnsiMsg->wParam * sizeof(WCHAR));
110 if (!Buffer)
111 {
112 return FALSE;
113 }
114 UnicodeMsg->lParam = (LPARAM)Buffer;
115 break;
116 }
117
118 /* AnsiMsg->lParam is string (0-terminated) */
119 case WM_SETTEXT:
120 case WM_WININICHANGE:
121 case WM_DEVMODECHANGE:
122 case CB_DIR:
123 case LB_DIR:
124 case LB_ADDFILE:
125 case EM_REPLACESEL:
126 {
127 UNICODE_STRING UnicodeString;
128 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam);
129 UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer;
130 break;
131 }
132
133 case WM_NCCREATE:
134 case WM_CREATE:
135 {
136 UNICODE_STRING UnicodeBuffer;
137 struct s
138 {
139 CREATESTRUCTW cs; /* new structure */
140 LPCWSTR lpszName; /* allocated Name */
141 LPCWSTR lpszClass; /* allocated Class */
142 };
143 struct s *xs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
144 if (!xs)
145 {
146 return FALSE;
147 }
148 xs->cs = *(CREATESTRUCTW *)AnsiMsg->lParam;
149 if (HIWORD(xs->cs.lpszName))
150 {
151 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszName);
152 xs->lpszName = xs->cs.lpszName = UnicodeBuffer.Buffer;
153 }
154 if (HIWORD(xs->cs.lpszClass))
155 {
156 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)xs->cs.lpszClass);
157 xs->lpszClass = xs->cs.lpszClass = UnicodeBuffer.Buffer;
158 }
159 UnicodeMsg->lParam = (LPARAM)xs;
160 break;
161 }
162
163 case WM_MDICREATE:
164 {
165 UNICODE_STRING UnicodeBuffer;
166 MDICREATESTRUCTW *cs =
167 (MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs));
168
169 if (!cs)
170 {
171 return FALSE;
172 }
173
174 *cs = *(MDICREATESTRUCTW *)AnsiMsg->lParam;
175
176 if (HIWORD(cs->szClass))
177 {
178 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szClass);
179 cs->szClass = UnicodeBuffer.Buffer;
180 }
181
182 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer, (LPSTR)cs->szTitle);
183 cs->szTitle = UnicodeBuffer.Buffer;
184
185 UnicodeMsg->lParam = (LPARAM)cs;
186 break;
187 }
188 }
189
190 return TRUE;
191 }
192
193
194 BOOL
195 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg)
196 {
197 switch (AnsiMsg->message)
198 {
199 case WM_GETTEXT:
200 case WM_ASKCBFORMATNAME:
201 {
202 HeapFree(GetProcessHeap(), 0, (PVOID) UnicodeMsg->lParam);
203 break;
204 }
205
206 case WM_SETTEXT:
207 case WM_WININICHANGE:
208 case WM_DEVMODECHANGE:
209 case CB_DIR:
210 case LB_DIR:
211 case LB_ADDFILE:
212 case EM_REPLACESEL:
213 {
214 UNICODE_STRING UnicodeString;
215 RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam);
216 RtlFreeUnicodeString(&UnicodeString);
217 break;
218 }
219
220 case WM_NCCREATE:
221 case WM_CREATE:
222 {
223 UNICODE_STRING UnicodeString;
224 struct s
225 {
226 CREATESTRUCTW cs; /* new structure */
227 LPWSTR lpszName; /* allocated Name */
228 LPWSTR lpszClass; /* allocated Class */
229 };
230 struct s *xs = (struct s *)UnicodeMsg->lParam;
231 if (xs->lpszName)
232 {
233 RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszName);
234 RtlFreeUnicodeString(&UnicodeString);
235 }
236 if (xs->lpszClass)
237 {
238 RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszClass);
239 RtlFreeUnicodeString(&UnicodeString);
240 }
241 HeapFree(GetProcessHeap(), 0, xs);
242 }
243 break;
244
245 case WM_MDICREATE:
246 {
247 UNICODE_STRING UnicodeString;
248 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)UnicodeMsg->lParam;
249 if (HIWORD(cs->szTitle))
250 {
251 RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szTitle);
252 RtlFreeUnicodeString(&UnicodeString);
253 }
254 if (HIWORD(cs->szClass))
255 {
256 RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szClass);
257 RtlFreeUnicodeString(&UnicodeString);
258 }
259 HeapFree(GetProcessHeap(), 0, cs);
260 }
261 break;
262 }
263 return(TRUE);
264 }
265
266
267 BOOL
268 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result)
269 {
270 switch (AnsiMsg->message)
271 {
272 case WM_GETTEXT:
273 case WM_ASKCBFORMATNAME:
274 {
275 LPWSTR Buffer = (LPWSTR)UnicodeMsg->lParam;
276 LPSTR AnsiBuffer = (LPSTR)AnsiMsg->lParam;
277 if (UnicodeMsg->wParam > 0 &&
278 !WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
279 AnsiBuffer, UnicodeMsg->wParam, NULL, NULL))
280 {
281 AnsiBuffer[UnicodeMsg->wParam - 1] = 0;
282 }
283 break;
284 }
285
286 case WM_GETTEXTLENGTH:
287 case CB_GETLBTEXTLEN:
288 case LB_GETTEXTLEN:
289 {
290 /* FIXME: There may be one DBCS char for each Unicode char */
291 *Result *= 2;
292 break;
293 }
294 }
295
296 MsgiAnsiToUnicodeCleanup(UnicodeMsg, AnsiMsg);
297
298 return TRUE;
299 }
300
301
302 VOID STATIC
303 User32ConvertToAsciiMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam)
304 {
305 switch((*Msg))
306 {
307 case WM_CREATE:
308 case WM_NCCREATE:
309 {
310 CREATESTRUCTA* CsA;
311 CREATESTRUCTW* CsW;
312 UNICODE_STRING UString;
313 ANSI_STRING AString;
314
315 CsW = (CREATESTRUCTW*)(*lParam);
316 CsA = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(CREATESTRUCTA));
317 memcpy(CsA, CsW, sizeof(CREATESTRUCTW));
318
319 RtlInitUnicodeString(&UString, CsW->lpszName);
320 RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
321 CsA->lpszName = AString.Buffer;
322 if (HIWORD((ULONG)CsW->lpszClass) != 0)
323 {
324 RtlInitUnicodeString(&UString, CsW->lpszClass);
325 RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
326 CsA->lpszClass = AString.Buffer;
327 }
328 (*lParam) = (LPARAM)CsA;
329 break;
330 }
331 case WM_SETTEXT:
332 {
333 ANSI_STRING AnsiString;
334 UNICODE_STRING UnicodeString;
335 RtlInitUnicodeString(&UnicodeString, (PWSTR) *lParam);
336 if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString,
337 &UnicodeString,
338 TRUE)))
339 {
340 *lParam = (LPARAM) AnsiString.Buffer;
341 }
342 break;
343 }
344 }
345 }
346
347
348 VOID STATIC
349 User32FreeAsciiConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
350 {
351 switch(Msg)
352 {
353 case WM_GETTEXT:
354 {
355 ANSI_STRING AnsiString;
356 UNICODE_STRING UnicodeString;
357 LPSTR TempString;
358 LPSTR InString;
359 InString = (LPSTR)lParam;
360 TempString = RtlAllocateHeap(RtlGetProcessHeap(), 0, strlen(InString) + 1);
361 strcpy(TempString, InString);
362 RtlInitAnsiString(&AnsiString, TempString);
363 UnicodeString.Length = wParam * sizeof(WCHAR);
364 UnicodeString.MaximumLength = wParam * sizeof(WCHAR);
365 UnicodeString.Buffer = (PWSTR)lParam;
366 if (! NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeString,
367 &AnsiString,
368 FALSE)))
369 {
370 if (1 <= wParam)
371 {
372 UnicodeString.Buffer[0] = L'\0';
373 }
374 }
375 RtlFreeHeap(RtlGetProcessHeap(), 0, TempString);
376 break;
377 }
378 case WM_SETTEXT:
379 {
380 ANSI_STRING AnsiString;
381 RtlInitAnsiString(&AnsiString, (PSTR) lParam);
382 RtlFreeAnsiString(&AnsiString);
383 break;
384 }
385 case WM_CREATE:
386 case WM_NCCREATE:
387 {
388 CREATESTRUCTA* Cs;
389
390 Cs = (CREATESTRUCTA*)lParam;
391 RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszName);
392 if (HIWORD((ULONG)Cs->lpszClass) != 0)
393 {
394 RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszClass);
395 }
396 RtlFreeHeap(RtlGetProcessHeap(), 0, Cs);
397 break;
398 }
399 }
400 }
401
402 LRESULT FASTCALL
403 IntCallWindowProcW(BOOL IsAnsiProc,
404 WNDPROC WndProc,
405 HWND hWnd,
406 UINT Msg,
407 WPARAM wParam,
408 LPARAM lParam)
409 {
410 LRESULT Result;
411
412 if (IsAnsiProc)
413 {
414 User32ConvertToAsciiMessage(&Msg, &wParam, &lParam);
415 Result = WndProc(hWnd, Msg, wParam, lParam);
416 User32FreeAsciiConvertedMessage(Msg, wParam, lParam);
417 return Result;
418 }
419 else
420 {
421 return WndProc(hWnd, Msg, wParam, lParam);
422 }
423 }
424
425 STATIC LRESULT FASTCALL
426 IntCallWindowProcA(BOOL IsAnsiProc,
427 WNDPROC WndProc,
428 HWND hWnd,
429 UINT Msg,
430 WPARAM wParam,
431 LPARAM lParam)
432 {
433 MSG AnsiMsg;
434 MSG UnicodeMsg;
435 LRESULT Result;
436
437 if (IsAnsiProc)
438 {
439 return WndProc(hWnd, Msg, wParam, lParam);
440 }
441 else
442 {
443 AnsiMsg.hwnd = hWnd;
444 AnsiMsg.message = Msg;
445 AnsiMsg.wParam = wParam;
446 AnsiMsg.lParam = lParam;
447 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg, &AnsiMsg))
448 {
449 return FALSE;
450 }
451 Result = WndProc(UnicodeMsg.hwnd, UnicodeMsg.message,
452 UnicodeMsg.wParam, UnicodeMsg.lParam);
453 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result))
454 {
455 return FALSE;
456 }
457 return Result;
458 }
459 }
460
461
462 /*
463 * @implemented
464 */
465 LRESULT STDCALL
466 CallWindowProcA(WNDPROC lpPrevWndFunc,
467 HWND hWnd,
468 UINT Msg,
469 WPARAM wParam,
470 LPARAM lParam)
471 {
472 BOOL IsHandle;
473 WndProcHandle wphData;
474
475 IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
476 if (! IsHandle)
477 {
478 return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
479 }
480 else
481 {
482 return IntCallWindowProcA(! wphData.IsUnicode, wphData.WindowProc,
483 hWnd, Msg, wParam, lParam);
484 }
485 }
486
487
488 /*
489 * @implemented
490 */
491 LRESULT STDCALL
492 CallWindowProcW(WNDPROC lpPrevWndFunc,
493 HWND hWnd,
494 UINT Msg,
495 WPARAM wParam,
496 LPARAM lParam)
497 {
498 BOOL IsHandle;
499 WndProcHandle wphData;
500
501 IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
502 if (! IsHandle)
503 {
504 return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
505 }
506 else
507 {
508 return IntCallWindowProcW(! wphData.IsUnicode, wphData.WindowProc,
509 hWnd, Msg, wParam, lParam);
510 }
511 }
512
513
514 /*
515 * @implemented
516 */
517 LRESULT STDCALL
518 DispatchMessageA(CONST MSG *lpmsg)
519 {
520 return(NtUserDispatchMessage(lpmsg));
521 }
522
523
524 /*
525 * @implemented
526 */
527 LRESULT STDCALL
528 DispatchMessageW(CONST MSG *lpmsg)
529 {
530 return(NtUserDispatchMessage((LPMSG)lpmsg));
531 }
532
533
534 /*
535 * @implemented
536 */
537 BOOL STDCALL
538 GetMessageA(LPMSG lpMsg,
539 HWND hWnd,
540 UINT wMsgFilterMin,
541 UINT wMsgFilterMax)
542 {
543 BOOL Res;
544 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
545
546 Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
547 if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
548 {
549 ThreadData->LastMessage = *lpMsg;
550 }
551 return(Res);
552 }
553
554
555 /*
556 * @implemented
557 */
558 BOOL STDCALL
559 GetMessageW(LPMSG lpMsg,
560 HWND hWnd,
561 UINT wMsgFilterMin,
562 UINT wMsgFilterMax)
563 {
564 BOOL Res;
565 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
566
567 Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
568 if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
569 {
570 ThreadData->LastMessage = *lpMsg;
571 }
572 return(Res);
573 }
574
575
576 /*
577 * @implemented
578 */
579 BOOL STDCALL
580 PeekMessageA(LPMSG lpMsg,
581 HWND hWnd,
582 UINT wMsgFilterMin,
583 UINT wMsgFilterMax,
584 UINT wRemoveMsg)
585 {
586 BOOL Res;
587 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
588
589 Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
590 if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
591 {
592 ThreadData->LastMessage = *lpMsg;
593 }
594 return(Res);
595 }
596
597
598 /*
599 * @implemented
600 */
601 BOOL
602 STDCALL
603 PeekMessageW(
604 LPMSG lpMsg,
605 HWND hWnd,
606 UINT wMsgFilterMin,
607 UINT wMsgFilterMax,
608 UINT wRemoveMsg)
609 {
610 BOOL Res;
611 PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
612
613 Res = NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
614 if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
615 {
616 ThreadData->LastMessage = *lpMsg;
617 }
618 return(Res);
619 }
620
621
622 /*
623 * @implemented
624 */
625 BOOL
626 STDCALL
627 PostMessageA(
628 HWND hWnd,
629 UINT Msg,
630 WPARAM wParam,
631 LPARAM lParam)
632 {
633 return NtUserPostMessage(hWnd, Msg, wParam, lParam);
634 }
635
636
637 /*
638 * @implemented
639 */
640 BOOL
641 STDCALL
642 PostMessageW(
643 HWND hWnd,
644 UINT Msg,
645 WPARAM wParam,
646 LPARAM lParam)
647 {
648 return NtUserPostMessage(hWnd, Msg, wParam, lParam);
649 }
650
651
652 /*
653 * @implemented
654 */
655 VOID
656 STDCALL
657 PostQuitMessage(
658 int nExitCode)
659 {
660 (void) NtUserPostMessage(NULL, WM_QUIT, nExitCode, 0);
661 }
662
663
664 /*
665 * @implemented
666 */
667 BOOL
668 STDCALL
669 PostThreadMessageA(
670 DWORD idThread,
671 UINT Msg,
672 WPARAM wParam,
673 LPARAM lParam)
674 {
675 return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
676 }
677
678
679 /*
680 * @implemented
681 */
682 BOOL
683 STDCALL
684 PostThreadMessageW(
685 DWORD idThread,
686 UINT Msg,
687 WPARAM wParam,
688 LPARAM lParam)
689 {
690 return NtUserPostThreadMessage(idThread, Msg, wParam, lParam);
691 }
692
693
694 /*
695 * @implemented
696 */
697 LRESULT STDCALL
698 SendMessageW(HWND Wnd,
699 UINT Msg,
700 WPARAM wParam,
701 LPARAM lParam)
702 {
703 NTUSERSENDMESSAGEINFO Info;
704 LRESULT Result;
705
706 Result = NtUserSendMessage(Wnd, Msg, wParam, lParam, &Info);
707 if (! Info.HandledByKernel)
708 {
709 /* We need to send the message ourselves */
710 Result = IntCallWindowProcW(Info.Ansi, Info.Proc, Wnd, Msg, wParam, lParam);
711 }
712
713 return Result;
714 }
715
716
717 /*
718 * @implemented
719 */
720 LRESULT STDCALL
721 SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
722 {
723 MSG AnsiMsg;
724 MSG UcMsg;
725 LRESULT Result;
726 NTUSERSENDMESSAGEINFO Info;
727
728 AnsiMsg.hwnd = Wnd;
729 AnsiMsg.message = Msg;
730 AnsiMsg.wParam = wParam;
731 AnsiMsg.lParam = lParam;
732 if (! MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
733 {
734 return FALSE;
735 }
736
737 Result = NtUserSendMessage(UcMsg.hwnd, UcMsg.message,
738 UcMsg.wParam, UcMsg.lParam, &Info);
739 if (! Info.HandledByKernel)
740 {
741 /* We need to send the message ourselves */
742 if (Info.Ansi)
743 {
744 /* Ansi message and Ansi window proc, that's easy. Clean up
745 the Unicode message though */
746 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
747 Result = IntCallWindowProcA(Info.Ansi, Info.Proc, Wnd, Msg, wParam, lParam);
748 }
749 else
750 {
751 /* Unicode winproc. Although we started out with an Ansi message we
752 already converted it to Unicode for the kernel call. Reuse that
753 message to avoid another conversion */
754 Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UcMsg.hwnd,
755 UcMsg.message, UcMsg.wParam, UcMsg.lParam);
756 if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
757 {
758 return FALSE;
759 }
760 }
761 }
762 else
763 {
764 /* Message sent by kernel. Convert back to Ansi */
765 if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
766 {
767 return FALSE;
768 }
769 }
770
771 return Result;
772 }
773
774
775 /*
776 * @implemented
777 */
778 BOOL
779 STDCALL
780 SendMessageCallbackA(
781 HWND hWnd,
782 UINT Msg,
783 WPARAM wParam,
784 LPARAM lParam,
785 SENDASYNCPROC lpCallBack,
786 ULONG_PTR dwData)
787 {
788 return NtUserSendMessageCallback(
789 hWnd,
790 Msg,
791 wParam,
792 lParam,
793 lpCallBack,
794 dwData);
795 }
796
797
798 /*
799 * @implemented
800 */
801 BOOL
802 STDCALL
803 SendMessageCallbackW(
804 HWND hWnd,
805 UINT Msg,
806 WPARAM wParam,
807 LPARAM lParam,
808 SENDASYNCPROC lpCallBack,
809 ULONG_PTR dwData)
810 {
811 return NtUserSendMessageCallback(
812 hWnd,
813 Msg,
814 wParam,
815 lParam,
816 lpCallBack,
817 dwData);
818 }
819
820
821 /*
822 * @implemented
823 */
824 LRESULT
825 STDCALL
826 SendMessageTimeoutA(
827 HWND hWnd,
828 UINT Msg,
829 WPARAM wParam,
830 LPARAM lParam,
831 UINT fuFlags,
832 UINT uTimeout,
833 PDWORD_PTR lpdwResult)
834 {
835 UNIMPLEMENTED;
836 return (LRESULT)0;
837 }
838
839
840 /*
841 * @implemented
842 */
843 LRESULT
844 STDCALL
845 SendMessageTimeoutW(
846 HWND hWnd,
847 UINT Msg,
848 WPARAM wParam,
849 LPARAM lParam,
850 UINT fuFlags,
851 UINT uTimeout,
852 PDWORD_PTR lpdwResult)
853 {
854 UNIMPLEMENTED;
855 return (LRESULT)0;
856 }
857
858
859 /*
860 * @unimplemented
861 */
862 BOOL
863 STDCALL
864 SendNotifyMessageA(
865 HWND hWnd,
866 UINT Msg,
867 WPARAM wParam,
868 LPARAM lParam)
869 {
870 UNIMPLEMENTED;
871 return FALSE;
872 }
873
874
875 /*
876 * @unimplemented
877 */
878 BOOL
879 STDCALL
880 SendNotifyMessageW(
881 HWND hWnd,
882 UINT Msg,
883 WPARAM wParam,
884 LPARAM lParam)
885 {
886 UNIMPLEMENTED;
887 return FALSE;
888 }
889
890
891 /*
892 * @implemented
893 */
894 BOOL STDCALL
895 TranslateMessage(CONST MSG *lpMsg)
896 {
897 return(TranslateMessageEx((LPMSG)lpMsg, 0));
898 }
899
900 /*
901 * @implemented
902 */
903 BOOL STDCALL
904 TranslateMessageEx(CONST MSG *lpMsg, DWORD unk)
905 {
906 return(NtUserTranslateMessage((LPMSG)lpMsg, (HKL)unk));
907 }
908
909
910 /*
911 * @implemented
912 */
913 BOOL
914 STDCALL
915 WaitMessage(VOID)
916 {
917 return NtUserWaitMessage();
918 }
919
920
921 /*
922 * @implemented
923 */
924 UINT STDCALL
925 RegisterWindowMessageA(LPCSTR lpString)
926 {
927 UNICODE_STRING String;
928 BOOLEAN Result;
929 UINT Atom;
930
931 Result = RtlCreateUnicodeStringFromAsciiz(&String, (PCSZ)lpString);
932 if (!Result)
933 {
934 return(0);
935 }
936 Atom = NtUserRegisterWindowMessage(&String);
937 RtlFreeUnicodeString(&String);
938 return(Atom);
939 }
940
941
942 /*
943 * @implemented
944 */
945 UINT STDCALL
946 RegisterWindowMessageW(LPCWSTR lpString)
947 {
948 UNICODE_STRING String;
949
950 RtlInitUnicodeString(&String, lpString);
951 return(NtUserRegisterWindowMessage(&String));
952 }
953
954 /*
955 * @implemented
956 */
957 HWND STDCALL
958 SetCapture(HWND hWnd)
959 {
960 return(NtUserSetCapture(hWnd));
961 }
962
963 /*
964 * @implemented
965 */
966 HWND STDCALL
967 GetCapture(VOID)
968 {
969 return(NtUserGetCapture());
970 }
971
972 /*
973 * @implemented
974 */
975 BOOL STDCALL
976 ReleaseCapture(VOID)
977 {
978 NtUserSetCapture(NULL);
979 return(TRUE);
980 }
981
982
983 /*
984 * @unimplemented
985 */
986 DWORD
987 STDCALL
988 RealGetQueueStatus(UINT flags)
989 {
990 DWORD ret;
991 WORD changed_bits, wake_bits;
992
993 #if 0 /* wine stuff. don't know what it does... */
994
995 /* check for pending X events */
996 if (USER_Driver.pMsgWaitForMultipleObjectsEx)
997 USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
998 #endif
999
1000 ret = NtUserGetQueueStatus(TRUE /*ClearChanges*/);
1001
1002 changed_bits = LOWORD(ret);
1003 wake_bits = HIWORD(ret);
1004
1005 return MAKELONG(changed_bits & flags, wake_bits & flags);
1006 }
1007
1008
1009 /*
1010 * @unimplemented
1011 */
1012 BOOL STDCALL GetInputState(VOID)
1013 {
1014 DWORD ret;
1015 WORD wake_bits;
1016
1017 #if 0 /* wine stuff. don't know what it does... */
1018
1019 /* check for pending X events */
1020 if (USER_Driver.pMsgWaitForMultipleObjectsEx)
1021 USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
1022 #endif
1023
1024 ret = NtUserGetQueueStatus(FALSE /*ClearChanges*/);
1025
1026 wake_bits = HIWORD(ret);
1027
1028 return wake_bits & (QS_KEY | QS_MOUSEBUTTON);
1029 }
1030
1031 /*
1032 * @implemented
1033 */
1034 BOOL STDCALL SetMessageQueue(int cMessagesMax)
1035 {
1036 /* Function does nothing on 32 bit windows */
1037 return TRUE;
1038 }
1039 typedef DWORD (WINAPI * RealGetQueueStatusProc)(UINT flags);
1040 typedef DWORD (WINAPI * RealMsgWaitForMultipleObjectsExProc)(DWORD nCount, LPHANDLE lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags);
1041
1042 typedef struct _USER_MESSAGE_PUMP_ADDRESSES {
1043 DWORD cbSize;
1044 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
1045 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
1046 RealGetQueueStatusProc RealGetQueueStatus;
1047 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx;
1048 } USER_MESSAGE_PUMP_ADDRESSES, * PUSER_MESSAGE_PUMP_ADDRESSES;
1049
1050 DWORD
1051 STDCALL
1052 RealMsgWaitForMultipleObjectsEx(
1053 DWORD nCount,
1054 LPHANDLE pHandles,
1055 DWORD dwMilliseconds,
1056 DWORD dwWakeMask,
1057 DWORD dwFlags);
1058
1059 typedef BOOL (WINAPI * MESSAGEPUMPHOOKPROC)(BOOL Unregistering,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses);
1060
1061 RTL_CRITICAL_SECTION gcsMPH;
1062 MESSAGEPUMPHOOKPROC gpfnInitMPH;
1063 DWORD gcLoadMPH = 0;
1064 USER_MESSAGE_PUMP_ADDRESSES gmph = {sizeof(USER_MESSAGE_PUMP_ADDRESSES),
1065 //NtUserRealInternalGetMessage,
1066 //NtUserRealInternalWaitMessageEx,
1067 RealGetQueueStatus,
1068 RealMsgWaitForMultipleObjectsEx
1069 };
1070
1071 DWORD gfMessagePumpHook = 0;
1072
1073 BOOL WINAPI IsInsideMessagePumpHook()
1074 {
1075 if(!gfMessagePumpHook)
1076 return FALSE;
1077
1078 /* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
1079 PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
1080
1081 if(!*(PLONG*)&NtTeb[0x708])
1082 return FALSE;
1083
1084 if(**(PLONG*)&NtTeb[0x708] <= 0)
1085 return FALSE;*/
1086
1087 return TRUE;
1088 }
1089
1090 void WINAPI ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses)
1091 {
1092 Addresses->cbSize = sizeof(USER_MESSAGE_PUMP_ADDRESSES);
1093 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
1094 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
1095 Addresses->RealGetQueueStatus = RealGetQueueStatus;
1096 Addresses->RealMsgWaitForMultipleObjectsEx = RealMsgWaitForMultipleObjectsEx;
1097 }
1098
1099 BOOL WINAPI RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook)
1100 {
1101 RtlEnterCriticalSection(&gcsMPH);
1102 if(!Hook) {
1103 SetLastError(ERROR_INVALID_PARAMETER);
1104 RtlLeaveCriticalSection(&gcsMPH);
1105 return FALSE;
1106 }
1107 if(!gcLoadMPH) {
1108 USER_MESSAGE_PUMP_ADDRESSES Addresses;
1109 gpfnInitMPH = Hook;
1110 ResetMessagePumpHook(&Addresses);
1111 if(!Hook(FALSE, &Addresses) || !Addresses.cbSize) {
1112 RtlLeaveCriticalSection(&gcsMPH);
1113 return FALSE;
1114 }
1115 memcpy(&gmph, &Addresses, Addresses.cbSize);
1116 } else {
1117 if(gpfnInitMPH != Hook) {
1118 RtlLeaveCriticalSection(&gcsMPH);
1119 return FALSE;
1120 }
1121 }
1122 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP)) {
1123 RtlLeaveCriticalSection(&gcsMPH);
1124 return FALSE;
1125 }
1126 if (!gcLoadMPH++) {
1127 InterlockedExchange(&gfMessagePumpHook, 1);
1128 }
1129 RtlLeaveCriticalSection(&gcsMPH);
1130 return TRUE;
1131 }
1132
1133 BOOL WINAPI UnregisterMessagePumpHook(VOID)
1134 {
1135 RtlEnterCriticalSection(&gcsMPH);
1136 if(gcLoadMPH > 0) {
1137 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP)) {
1138 gcLoadMPH--;
1139 if(!gcLoadMPH) {
1140 InterlockedExchange(&gfMessagePumpHook, 0);
1141 gpfnInitMPH(TRUE, NULL);
1142 ResetMessagePumpHook(&gmph);
1143 gpfnInitMPH = 0;
1144 }
1145 RtlLeaveCriticalSection(&gcsMPH);
1146 return TRUE;
1147 }
1148 }
1149 RtlLeaveCriticalSection(&gcsMPH);
1150 return FALSE;
1151 }
1152
1153 DWORD WINAPI GetQueueStatus(UINT flags)
1154 {
1155 return IsInsideMessagePumpHook() ? gmph.RealGetQueueStatus(flags) : RealGetQueueStatus(flags);
1156 }
1157
1158 DWORD WINAPI MsgWaitForMultipleObjectsEx(DWORD nCount, LPHANDLE lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags)
1159 {
1160 return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags);
1161 }