2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: lib/user32/windows/message.c
6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
13 /* DDE message exchange
15 * - Session initialization
16 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
17 * this message contains a pair of global atoms, the Application and Topic atoms.
18 * The client must destroy the atoms.
19 * Server window proc handles the WM_DDE_INITIATE message and if the Application
20 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
21 * of the reply message contains another pair of global atoms (Application and
22 * Topic again), which must be destroyed by the server.
25 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
26 * is a global memory handle containing the string to execute. After the command has
27 * been executed the server posts a WM_DDE_ACK message to the client, which contains
28 * a packed lParam which in turn contains that global memory handle. The client takes
29 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
30 * it and the global memory handle.
31 * This might work nice and easy in Win3.1, but things are more complicated for NT.
32 * Global memory handles in NT are not really global, they're still local to the
33 * process. So, what happens under the hood is that PostMessage must handle the
34 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
35 * area, repack that into a new structure together with the original memory handle
36 * and pass that off to the win32k. Win32k will marshall that data over to the target
37 * (server) process where it will be unpacked and stored in a newly allocated global
38 * memory area. The handle of that area will then be sent to the window proc, after
39 * storing it together with the "original" (client) handle in a table.
40 * The server will eventually post the WM_DDE_ACK response, containing the global
41 * memory handle it received. PostMessage must then lookup that memory handle (only
42 * valid in the server process) and replace it with the corresponding client memory
43 * handle. To avoid memory leaks, the server-side global memory block must be freed.
44 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
45 * individual components are handed to win32k.sys to post to the client side. Since
46 * the server side app hands over ownership of the packed lParam when it calls
47 * PostMessage(), the packed lParam needs to be freed on the server side too.
48 * When the WM_DDE_ACK message (containing the client-side global memory handle)
49 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
50 * to the client side window proc which is expected to free/reuse it.
53 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
54 * to the memory handle, we keep track (in the server side) of all pairs of handle
55 * used (the client passes its value and the content of the memory handle), and
56 * the server stored both values (the client, and the local one, created after the
57 * content). When a ACK message is generated, the list of pair is searched for a
58 * matching pair, so that the client memory handle can be returned.
60 typedef struct tagDDEPAIR
66 static PDDEPAIR DdePairs
= NULL
;
67 static unsigned DdeNumAlloc
= 0;
68 static unsigned DdeNumUsed
= 0;
69 static CRITICAL_SECTION DdeCrst
;
72 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
76 EnterCriticalSection(&DdeCrst
);
78 /* now remember the pair of hMem on both sides */
79 if (DdeNumUsed
== DdeNumAlloc
)
85 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
86 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
90 New
= HeapAlloc(GetProcessHeap(), 0,
91 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
96 LeaveCriticalSection(&DdeCrst
);
100 /* zero out newly allocated part */
101 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
102 DdeNumAlloc
+= GROWBY
;
106 for (i
= 0; i
< DdeNumAlloc
; i
++)
108 if (NULL
== DdePairs
[i
].ServerMem
)
110 DdePairs
[i
].ClientMem
= ClientMem
;
111 DdePairs
[i
].ServerMem
= ServerMem
;
116 LeaveCriticalSection(&DdeCrst
);
121 static HGLOBAL FASTCALL
122 DdeGetPair(HGLOBAL ServerMem
)
127 EnterCriticalSection(&DdeCrst
);
128 for (i
= 0; i
< DdeNumAlloc
; i
++)
130 if (DdePairs
[i
].ServerMem
== ServerMem
)
133 DdePairs
[i
].ServerMem
= 0;
135 Ret
= DdePairs
[i
].ClientMem
;
139 LeaveCriticalSection(&DdeCrst
);
145 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
149 switch (UMMsg
->message
)
153 PKMDDELPARAM DdeLparam
;
154 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
155 if (NULL
== DdeLparam
)
161 DdeLparam
->Packed
= TRUE
;
162 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
163 &DdeLparam
->Value
.Packed
.uiLo
,
164 &DdeLparam
->Value
.Packed
.uiHi
))
168 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
170 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
171 HGLOBAL h
= DdeGetPair((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
174 GlobalFree((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
175 DdeLparam
->Value
.Packed
.uiHi
= (UINT
) h
;
178 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
182 DdeLparam
->Packed
= FALSE
;
183 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
185 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
192 PKMDDEEXECUTEDATA KMDdeExecuteData
;
195 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
196 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
199 SetLastError(ERROR_INVALID_HANDLE
);
202 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
203 if (NULL
== KMDdeExecuteData
)
205 SetLastError(ERROR_OUTOFMEMORY
);
208 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
209 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
210 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
211 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
212 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
213 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
219 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
220 PCOPYDATASTRUCT pKMCopyData
;
222 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
223 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
224 if (pKMCopyData
== NULL
)
226 SetLastError(ERROR_OUTOFMEMORY
);
230 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
231 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
232 pKMCopyData
->lpData
= pKMCopyData
+ 1;
234 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
235 pUMCopyData
->cbData
);
237 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
249 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
251 switch (KMMsg
->message
)
256 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
266 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
268 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
274 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
278 switch (UMMsg
->message
)
283 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
285 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
286 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
287 if (L
'A' == *((WCHAR
*) Class
))
289 Class
+= sizeof(WCHAR
);
290 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
294 ASSERT(L
'S' == *((WCHAR
*) Class
));
295 Class
+= sizeof(WCHAR
);
296 Cs
->lpszClass
= (LPCWSTR
) Class
;
303 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
304 if (DdeLparam
->Packed
)
306 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
307 DdeLparam
->Value
.Packed
.uiLo
,
308 DdeLparam
->Value
.Packed
.uiHi
);
312 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
319 PKMDDEEXECUTEDATA KMDdeExecuteData
;
323 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
324 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
325 if (NULL
== GlobalData
)
329 Data
= GlobalLock(GlobalData
);
332 GlobalFree(GlobalData
);
335 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
336 GlobalUnlock(GlobalData
);
337 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
339 GlobalFree(GlobalData
);
342 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
343 UMMsg
->lParam
= (LPARAM
) GlobalData
;
349 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
350 pKMCopyData
->lpData
= pKMCopyData
+ 1;
362 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
364 switch (KMMsg
->message
)
368 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
369 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
380 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
382 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
388 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
390 *UnicodeMsg
= *AnsiMsg
;
391 switch (AnsiMsg
->message
)
394 case WM_ASKCBFORMATNAME
:
396 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
397 AnsiMsg
->wParam
* sizeof(WCHAR
));
402 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
406 /* AnsiMsg->lParam is string (0-terminated) */
408 case WM_WININICHANGE
:
409 case WM_DEVMODECHANGE
:
415 UNICODE_STRING UnicodeString
;
416 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
417 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
424 UNICODE_STRING UnicodeBuffer
;
427 CREATESTRUCTW cs
; /* new structure */
428 LPCWSTR lpszName
; /* allocated Name */
429 LPCWSTR lpszClass
; /* allocated Class */
431 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
436 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
437 if (HIWORD(xs
->cs
.lpszName
))
439 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszName
);
440 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeBuffer
.Buffer
;
442 if (HIWORD(xs
->cs
.lpszClass
))
444 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszClass
);
445 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeBuffer
.Buffer
;
447 UnicodeMsg
->lParam
= (LPARAM
)xs
;
453 UNICODE_STRING UnicodeBuffer
;
454 MDICREATESTRUCTW
*cs
=
455 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
462 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
464 if (HIWORD(cs
->szClass
))
466 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szClass
);
467 cs
->szClass
= UnicodeBuffer
.Buffer
;
470 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szTitle
);
471 cs
->szTitle
= UnicodeBuffer
.Buffer
;
473 UnicodeMsg
->lParam
= (LPARAM
)cs
;
483 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
485 switch (AnsiMsg
->message
)
488 case WM_ASKCBFORMATNAME
:
490 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
495 case WM_WININICHANGE
:
496 case WM_DEVMODECHANGE
:
502 UNICODE_STRING UnicodeString
;
503 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
504 RtlFreeUnicodeString(&UnicodeString
);
511 UNICODE_STRING UnicodeString
;
514 CREATESTRUCTW cs
; /* new structure */
515 LPWSTR lpszName
; /* allocated Name */
516 LPWSTR lpszClass
; /* allocated Class */
518 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
521 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
522 RtlFreeUnicodeString(&UnicodeString
);
526 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
527 RtlFreeUnicodeString(&UnicodeString
);
529 HeapFree(GetProcessHeap(), 0, xs
);
535 UNICODE_STRING UnicodeString
;
536 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
537 if (HIWORD(cs
->szTitle
))
539 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
540 RtlFreeUnicodeString(&UnicodeString
);
542 if (HIWORD(cs
->szClass
))
544 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
545 RtlFreeUnicodeString(&UnicodeString
);
547 HeapFree(GetProcessHeap(), 0, cs
);
556 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
558 switch (AnsiMsg
->message
)
561 case WM_ASKCBFORMATNAME
:
563 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
564 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
565 if (UnicodeMsg
->wParam
> 0 &&
566 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
567 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
569 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
575 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
582 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
584 *AnsiMsg
= *UnicodeMsg
;
586 switch(UnicodeMsg
->message
)
593 UNICODE_STRING UString
;
597 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
598 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
603 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
605 RtlInitUnicodeString(&UString
, CsW
->lpszName
);
606 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
607 if (! NT_SUCCESS(Status
))
609 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
612 CsA
->lpszName
= AString
.Buffer
;
613 if (HIWORD((ULONG
)CsW
->lpszClass
) != 0)
615 RtlInitUnicodeString(&UString
, CsW
->lpszClass
);
616 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
617 if (! NT_SUCCESS(Status
))
619 RtlInitAnsiString(&AString
, CsA
->lpszName
);
620 RtlFreeAnsiString(&AString
);
621 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
624 CsA
->lpszClass
= AString
.Buffer
;
626 AnsiMsg
->lParam
= (LPARAM
)CsA
;
631 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
632 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
633 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
634 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
642 ANSI_STRING AnsiString
;
643 UNICODE_STRING UnicodeString
;
644 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
645 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
651 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
661 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
663 switch(UnicodeMsg
->message
)
667 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
673 RtlInitAnsiString(&AString
, (PSTR
) AnsiMsg
->lParam
);
674 RtlFreeAnsiString(&AString
);
683 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
684 RtlInitAnsiString(&AString
, Cs
->lpszName
);
685 RtlFreeAnsiString(&AString
);
686 if (HIWORD((ULONG
)Cs
->lpszClass
) != 0)
688 RtlInitAnsiString(&AString
, Cs
->lpszClass
);
689 RtlFreeAnsiString(&AString
);
691 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
701 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
703 switch (UnicodeMsg
->message
)
706 case WM_ASKCBFORMATNAME
:
708 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
709 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
710 if (0 < AnsiMsg
->wParam
&&
711 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
713 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
719 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
724 typedef struct tagMSGCONVERSION
733 } MSGCONVERSION
, *PMSGCONVERSION
;
735 static PMSGCONVERSION MsgConversions
= NULL
;
736 static unsigned MsgConversionNumAlloc
= 0;
737 static unsigned MsgConversionNumUsed
= 0;
738 static CRITICAL_SECTION MsgConversionCrst
;
741 MsgConversionAdd(PMSGCONVERSION Conversion
)
745 EnterCriticalSection(&MsgConversionCrst
);
747 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
751 if (NULL
!= MsgConversions
)
753 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
754 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
758 New
= HeapAlloc(GetProcessHeap(), 0,
759 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
764 LeaveCriticalSection(&MsgConversionCrst
);
767 MsgConversions
= New
;
768 /* zero out newly allocated part */
769 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
770 MsgConversionNumAlloc
+= GROWBY
;
774 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
776 if (! MsgConversions
[i
].InUse
)
778 MsgConversions
[i
] = *Conversion
;
779 MsgConversions
[i
].InUse
= TRUE
;
780 MsgConversionNumUsed
++;
784 LeaveCriticalSection(&MsgConversionCrst
);
790 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
793 PMSGCONVERSION Conversion
;
796 EnterCriticalSection(&MsgConversionCrst
);
797 for (Conversion
= MsgConversions
;
798 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
801 if (Conversion
->InUse
&&
802 ((Ansi
&& Conversion
->Ansi
) ||
803 (! Ansi
&& ! Conversion
->Ansi
)))
805 Found
= (Conversion
->FinalMsg
== Msg
);
806 if (! Found
&& CheckMsgContents
)
810 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
814 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
821 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
822 NULL
== Result
? &Dummy
: Result
);
824 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
825 NULL
== Result
? &Dummy
: Result
);
826 if (0 != Conversion
->LParamSize
)
828 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
829 &Conversion
->LParamSize
, MEM_DECOMMIT
);
831 Conversion
->InUse
= FALSE
;
832 MsgConversionNumUsed
--;
836 LeaveCriticalSection(&MsgConversionCrst
);
844 GetMessageExtraInfo(VOID
)
846 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
857 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
858 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
868 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
869 return(ThreadData
->LastMessage
.time
);
880 static DWORD ShowNotImplemented
= TRUE
;
881 if (ShowNotImplemented
)
883 DbgPrint("InSendMessage is unimplemented\n");
884 ShowNotImplemented
= FALSE
;
886 /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
899 /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
926 return NtUserSetMessageExtraInfo(lParam
);
930 IntCallWindowProcW(BOOL IsAnsiProc
,
943 UnicodeMsg
.hwnd
= hWnd
;
944 UnicodeMsg
.message
= Msg
;
945 UnicodeMsg
.wParam
= wParam
;
946 UnicodeMsg
.lParam
= lParam
;
947 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
951 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
952 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
960 return WndProc(hWnd
, Msg
, wParam
, lParam
);
964 STATIC LRESULT FASTCALL
965 IntCallWindowProcA(BOOL IsAnsiProc
,
978 return WndProc(hWnd
, Msg
, wParam
, lParam
);
983 AnsiMsg
.message
= Msg
;
984 AnsiMsg
.wParam
= wParam
;
985 AnsiMsg
.lParam
= lParam
;
986 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
990 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
991 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
992 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1005 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1012 WndProcHandle wphData
;
1014 if (lpPrevWndFunc
== NULL
)
1015 lpPrevWndFunc
= (WNDPROC
)NtUserGetWindowLong(hWnd
, GWL_WNDPROC
, FALSE
);
1017 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1020 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1024 return IntCallWindowProcA(! wphData
.IsUnicode
, wphData
.WindowProc
,
1025 hWnd
, Msg
, wParam
, lParam
);
1034 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1041 WndProcHandle wphData
;
1043 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1046 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1050 return IntCallWindowProcW(! wphData
.IsUnicode
, wphData
.WindowProc
,
1051 hWnd
, Msg
, wParam
, lParam
);
1060 DispatchMessageA(CONST MSG
*lpmsg
)
1062 NTUSERDISPATCHMESSAGEINFO Info
;
1067 Result
= NtUserDispatchMessage(&Info
);
1068 if (! Info
.HandledByKernel
)
1070 /* We need to send the message ourselves */
1071 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1072 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1074 MsgConversionCleanup(lpmsg
, TRUE
, TRUE
, &Result
);
1084 DispatchMessageW(CONST MSG
*lpmsg
)
1086 NTUSERDISPATCHMESSAGEINFO Info
;
1091 Result
= NtUserDispatchMessage(&Info
);
1092 if (! Info
.HandledByKernel
)
1094 /* We need to send the message ourselves */
1095 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1096 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1098 MsgConversionCleanup(lpmsg
, FALSE
, TRUE
, &Result
);
1108 GetMessageA(LPMSG lpMsg
,
1114 MSGCONVERSION Conversion
;
1115 NTUSERGETMESSAGEINFO Info
;
1116 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1118 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1119 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1120 if (-1 == (int) Res
)
1124 Conversion
.LParamSize
= Info
.LParamSize
;
1125 Conversion
.KMMsg
= Info
.Msg
;
1127 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1131 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1133 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1136 *lpMsg
= Conversion
.AnsiMsg
;
1137 Conversion
.Ansi
= TRUE
;
1138 Conversion
.FinalMsg
= lpMsg
;
1139 MsgConversionAdd(&Conversion
);
1140 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1142 ThreadData
->LastMessage
= Info
.Msg
;
1153 GetMessageW(LPMSG lpMsg
,
1159 MSGCONVERSION Conversion
;
1160 NTUSERGETMESSAGEINFO Info
;
1161 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1163 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1164 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1165 if (-1 == (int) Res
)
1169 Conversion
.LParamSize
= Info
.LParamSize
;
1170 Conversion
.KMMsg
= Info
.Msg
;
1172 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1176 *lpMsg
= Conversion
.UnicodeMsg
;
1177 Conversion
.Ansi
= FALSE
;
1178 Conversion
.FinalMsg
= lpMsg
;
1179 MsgConversionAdd(&Conversion
);
1180 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1182 ThreadData
->LastMessage
= Info
.Msg
;
1193 PeekMessageA(LPMSG lpMsg
,
1200 MSGCONVERSION Conversion
;
1201 NTUSERGETMESSAGEINFO Info
;
1202 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1204 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1205 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1206 if (-1 == (int) Res
|| ! Res
)
1210 Conversion
.LParamSize
= Info
.LParamSize
;
1211 Conversion
.KMMsg
= Info
.Msg
;
1213 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1217 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1219 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1222 *lpMsg
= Conversion
.AnsiMsg
;
1223 Conversion
.Ansi
= TRUE
;
1224 Conversion
.FinalMsg
= lpMsg
;
1225 MsgConversionAdd(&Conversion
);
1226 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1228 ThreadData
->LastMessage
= Info
.Msg
;
1248 MSGCONVERSION Conversion
;
1249 NTUSERGETMESSAGEINFO Info
;
1250 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1252 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1253 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1254 if (-1 == (int) Res
|| ! Res
)
1258 Conversion
.LParamSize
= Info
.LParamSize
;
1259 Conversion
.KMMsg
= Info
.Msg
;
1261 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1265 *lpMsg
= Conversion
.UnicodeMsg
;
1266 Conversion
.Ansi
= FALSE
;
1267 Conversion
.FinalMsg
= lpMsg
;
1268 MsgConversionAdd(&Conversion
);
1269 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1271 ThreadData
->LastMessage
= Info
.Msg
;
1294 AnsiMsg
.message
= Msg
;
1295 AnsiMsg
.wParam
= wParam
;
1296 AnsiMsg
.lParam
= lParam
;
1297 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1302 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
1304 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1307 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1308 KMMsg
.wParam
, KMMsg
.lParam
);
1309 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1310 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1331 UMMsg
.message
= Msg
;
1332 UMMsg
.wParam
= wParam
;
1333 UMMsg
.lParam
= lParam
;
1334 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1338 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1339 KMMsg
.wParam
, KMMsg
.lParam
);
1340 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1354 (void) NtUserPostMessage(NULL
, WM_QUIT
, nExitCode
, 0);
1369 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1384 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1392 SendMessageW(HWND Wnd
,
1398 NTUSERSENDMESSAGEINFO Info
;
1402 UMMsg
.message
= Msg
;
1403 UMMsg
.wParam
= wParam
;
1404 UMMsg
.lParam
= lParam
;
1405 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
1410 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1411 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1412 if (! Info
.HandledByKernel
)
1414 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1415 /* We need to send the message ourselves */
1416 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UMMsg
.hwnd
, UMMsg
.message
,
1417 UMMsg
.wParam
, UMMsg
.lParam
);
1419 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
1432 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1437 NTUSERSENDMESSAGEINFO Info
;
1440 AnsiMsg
.message
= Msg
;
1441 AnsiMsg
.wParam
= wParam
;
1442 AnsiMsg
.lParam
= lParam
;
1443 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1448 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
1450 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1454 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1455 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1456 if (! Info
.HandledByKernel
)
1458 /* We need to send the message ourselves */
1461 /* Ansi message and Ansi window proc, that's easy. Clean up
1462 the Unicode message though */
1463 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1464 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1465 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Wnd
, Msg
, wParam
, lParam
);
1469 /* Unicode winproc. Although we started out with an Ansi message we
1470 already converted it to Unicode for the kernel call. Reuse that
1471 message to avoid another conversion */
1472 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1473 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1474 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1480 /* Message sent by kernel. Convert back to Ansi */
1481 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
1482 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1496 SendMessageCallbackA(
1501 SENDASYNCPROC lpCallBack
,
1504 return NtUserSendMessageCallback(
1519 SendMessageCallbackW(
1524 SENDASYNCPROC lpCallBack
,
1527 return NtUserSendMessageCallback(
1542 SendMessageTimeoutA(
1549 PDWORD_PTR lpdwResult
)
1554 NTUSERSENDMESSAGEINFO Info
;
1556 AnsiMsg
.hwnd
= hWnd
;
1557 AnsiMsg
.message
= Msg
;
1558 AnsiMsg
.wParam
= wParam
;
1559 AnsiMsg
.lParam
= lParam
;
1560 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1566 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
1567 UcMsg
.wParam
, UcMsg
.lParam
,
1568 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
1573 if (! Info
.HandledByKernel
)
1575 /* We need to send the message ourselves */
1578 /* Ansi message and Ansi window proc, that's easy. Clean up
1579 the Unicode message though */
1580 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1581 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1585 /* Unicode winproc. Although we started out with an Ansi message we
1586 already converted it to Unicode for the kernel call. Reuse that
1587 message to avoid another conversion */
1588 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1589 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1590 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1596 *lpdwResult
= Result
;
1601 /* Message sent by kernel. Convert back to Ansi */
1602 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1617 SendMessageTimeoutW(
1624 PDWORD_PTR lpdwResult
)
1626 NTUSERSENDMESSAGEINFO Info
;
1630 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
1632 if (! Info
.HandledByKernel
)
1634 /* We need to send the message ourselves */
1635 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1637 *lpdwResult
= Result
;
1681 TranslateMessageEx(CONST MSG
*lpMsg
, DWORD unk
)
1683 return(NtUserTranslateMessage((LPMSG
)lpMsg
, (HKL
)unk
));
1691 TranslateMessage(CONST MSG
*lpMsg
)
1693 return(TranslateMessageEx((LPMSG
)lpMsg
, 0));
1704 return NtUserWaitMessage();
1712 RegisterWindowMessageA(LPCSTR lpString
)
1714 UNICODE_STRING String
;
1718 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
1723 Atom
= NtUserRegisterWindowMessage(&String
);
1724 RtlFreeUnicodeString(&String
);
1733 RegisterWindowMessageW(LPCWSTR lpString
)
1735 UNICODE_STRING String
;
1737 RtlInitUnicodeString(&String
, lpString
);
1738 return(NtUserRegisterWindowMessage(&String
));
1745 SetCapture(HWND hWnd
)
1747 return(NtUserSetCapture(hWnd
));
1756 return(NtUserGetCapture());
1763 ReleaseCapture(VOID
)
1765 NtUserSetCapture(NULL
);
1775 RealGetQueueStatus(UINT flags
)
1778 WORD changed_bits
, wake_bits
;
1780 #if 0 /* wine stuff. don't know what it does... */
1782 /* check for pending X events */
1783 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1784 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1787 ret
= NtUserGetQueueStatus(TRUE
/*ClearChanges*/);
1789 changed_bits
= LOWORD(ret
);
1790 wake_bits
= HIWORD(ret
);
1792 return MAKELONG(changed_bits
& flags
, wake_bits
& flags
);
1799 BOOL STDCALL
GetInputState(VOID
)
1804 #if 0 /* wine stuff. don't know what it does... */
1806 /* check for pending X events */
1807 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1808 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1811 ret
= NtUserGetQueueStatus(FALSE
/*ClearChanges*/);
1813 wake_bits
= HIWORD(ret
);
1815 return wake_bits
& (QS_KEY
| QS_MOUSEBUTTON
);
1820 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
1822 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
1825 /* Make sure we don't try to access mem beyond what we were given */
1826 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1828 return STATUS_INFO_LENGTH_MISMATCH
;
1831 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
1832 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
1833 KMMsg
.message
= CallbackArgs
->Msg
;
1834 KMMsg
.wParam
= CallbackArgs
->wParam
;
1835 /* Check if lParam is really a pointer and adjust it if it is */
1836 if (0 <= CallbackArgs
->lParamBufferSize
)
1838 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
1839 + CallbackArgs
->lParamBufferSize
)
1841 return STATUS_INFO_LENGTH_MISMATCH
;
1843 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
1847 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1849 return STATUS_INFO_LENGTH_MISMATCH
;
1851 KMMsg
.lParam
= CallbackArgs
->lParam
;
1854 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
1856 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
1857 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
1860 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
1864 CallbackArgs
->Result
= IntCallWindowProcW(CallbackArgs
->IsAnsiProc
, CallbackArgs
->Proc
,
1865 UMMsg
.hwnd
, UMMsg
.message
,
1866 UMMsg
.wParam
, UMMsg
.lParam
);
1868 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
1872 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
1878 BOOL STDCALL
SetMessageQueue(int cMessagesMax
)
1880 /* Function does nothing on 32 bit windows */
1883 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
1884 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
1886 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
1888 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
1889 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
1890 RealGetQueueStatusProc RealGetQueueStatus
;
1891 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
1892 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
1896 RealMsgWaitForMultipleObjectsEx(
1898 CONST HANDLE
*pHandles
,
1899 DWORD dwMilliseconds
,
1903 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
1905 CRITICAL_SECTION gcsMPH
;
1906 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
1907 DWORD gcLoadMPH
= 0;
1908 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
1909 //NtUserRealInternalGetMessage,
1910 //NtUserRealInternalWaitMessageEx,
1912 RealMsgWaitForMultipleObjectsEx
1915 DWORD gfMessagePumpHook
= 0;
1917 BOOL WINAPI
IsInsideMessagePumpHook()
1919 if(!gfMessagePumpHook
)
1922 /* This code checks if we're inside SendMessage. */
1924 /* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
1925 PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
1927 if(!*(PLONG*)&NtTeb[0x708])
1930 if(**(PLONG*)&NtTeb[0x708] <= 0)
1937 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
1939 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
1940 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
1941 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
1942 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
1943 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
1946 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
1948 EnterCriticalSection(&gcsMPH
);
1950 SetLastError(ERROR_INVALID_PARAMETER
);
1951 LeaveCriticalSection(&gcsMPH
);
1955 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
1957 ResetMessagePumpHook(&Addresses
);
1958 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
1959 LeaveCriticalSection(&gcsMPH
);
1962 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
1964 if(gpfnInitMPH
!= Hook
) {
1965 LeaveCriticalSection(&gcsMPH
);
1969 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
1970 LeaveCriticalSection(&gcsMPH
);
1974 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
1976 LeaveCriticalSection(&gcsMPH
);
1980 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
1982 EnterCriticalSection(&gcsMPH
);
1984 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
1987 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
1988 gpfnInitMPH(TRUE
, NULL
);
1989 ResetMessagePumpHook(&gmph
);
1992 LeaveCriticalSection(&gcsMPH
);
1996 LeaveCriticalSection(&gcsMPH
);
2000 DWORD WINAPI
GetQueueStatus(UINT flags
)
2002 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2006 * @name RealMsgWaitForMultipleObjectsEx
2008 * Wait either for either message arrival or for one of the passed events
2012 * Number of handles in the pHandles array.
2014 * Handles of events to wait for.
2015 * @param dwMilliseconds
2018 * Mask specifying on which message events we should wakeup.
2020 * Wait type (see MWMO_* constants).
2026 RealMsgWaitForMultipleObjectsEx(
2028 const HANDLE
*pHandles
,
2029 DWORD dwMilliseconds
,
2033 LPHANDLE RealHandles
;
2034 HANDLE MessageQueueHandle
;
2037 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2039 SetLastError(ERROR_INVALID_PARAMETER
);
2044 if (dwFlags & MWMO_INPUTAVAILABLE)
2046 RealGetQueueStatus(dwWakeMask);
2050 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2051 if (MessageQueueHandle
== NULL
)
2053 SetLastError(0); /* ? */
2057 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2058 if (RealHandles
== NULL
)
2060 NtUserMsqClearWakeMask();
2061 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2065 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2066 RealHandles
[nCount
] = MessageQueueHandle
;
2068 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2069 dwFlags
& MWMO_WAITALL
,
2070 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2072 HeapFree(GetProcessHeap(), 0, RealHandles
);
2073 NtUserMsqClearWakeMask();
2082 MsgWaitForMultipleObjectsEx(
2084 CONST HANDLE
*lpHandles
,
2085 DWORD dwMilliseconds
,
2089 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2096 MsgWaitForMultipleObjects(
2098 CONST HANDLE
*lpHandles
,
2100 DWORD dwMilliseconds
,
2103 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2104 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2108 BOOL FASTCALL
MessageInit()
2110 InitializeCriticalSection(&DdeCrst
);
2111 InitializeCriticalSection(&MsgConversionCrst
);