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
14 #include <user32/callback.h>
17 /* DDE message exchange
19 * - Session initialization
20 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
21 * this message contains a pair of global atoms, the Application and Topic atoms.
22 * The client must destroy the atoms.
23 * Server window proc handles the WM_DDE_INITIATE message and if the Application
24 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
25 * of the reply message contains another pair of global atoms (Application and
26 * Topic again), which must be destroyed by the server.
29 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
30 * is a global memory handle containing the string to execute. After the command has
31 * been executed the server posts a WM_DDE_ACK message to the client, which contains
32 * a packed lParam which in turn contains that global memory handle. The client takes
33 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
34 * it and the global memory handle.
35 * This might work nice and easy in Win3.1, but things are more complicated for NT.
36 * Global memory handles in NT are not really global, they're still local to the
37 * process. So, what happens under the hood is that PostMessage must handle the
38 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
39 * area, repack that into a new structure together with the original memory handle
40 * and pass that off to the win32k. Win32k will marshall that data over to the target
41 * (server) process where it will be unpacked and stored in a newly allocated global
42 * memory area. The handle of that area will then be sent to the window proc, after
43 * storing it together with the "original" (client) handle in a table.
44 * The server will eventually post the WM_DDE_ACK response, containing the global
45 * memory handle it received. PostMessage must then lookup that memory handle (only
46 * valid in the server process) and replace it with the corresponding client memory
47 * handle. To avoid memory leaks, the server-side global memory block must be freed.
48 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
49 * individual components are handed to win32k.sys to post to the client side. Since
50 * the server side app hands over ownership of the packed lParam when it calls
51 * PostMessage(), the packed lParam needs to be freed on the server side too.
52 * When the WM_DDE_ACK message (containing the client-side global memory handle)
53 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
54 * to the client side window proc which is expected to free/reuse it.
57 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
58 * to the memory handle, we keep track (in the server side) of all pairs of handle
59 * used (the client passes its value and the content of the memory handle), and
60 * the server stored both values (the client, and the local one, created after the
61 * content). When a ACK message is generated, the list of pair is searched for a
62 * matching pair, so that the client memory handle can be returned.
64 typedef struct tagDDEPAIR
70 static PDDEPAIR DdePairs
= NULL
;
71 static unsigned DdeNumAlloc
= 0;
72 static unsigned DdeNumUsed
= 0;
73 static CRITICAL_SECTION DdeCrst
;
76 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
80 EnterCriticalSection(&DdeCrst
);
82 /* now remember the pair of hMem on both sides */
83 if (DdeNumUsed
== DdeNumAlloc
)
89 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
90 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
94 New
= HeapAlloc(GetProcessHeap(), 0,
95 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
100 LeaveCriticalSection(&DdeCrst
);
104 /* zero out newly allocated part */
105 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
106 DdeNumAlloc
+= GROWBY
;
110 for (i
= 0; i
< DdeNumAlloc
; i
++)
112 if (NULL
== DdePairs
[i
].ServerMem
)
114 DdePairs
[i
].ClientMem
= ClientMem
;
115 DdePairs
[i
].ServerMem
= ServerMem
;
120 LeaveCriticalSection(&DdeCrst
);
125 static HGLOBAL FASTCALL
126 DdeGetPair(HGLOBAL ServerMem
)
131 EnterCriticalSection(&DdeCrst
);
132 for (i
= 0; i
< DdeNumAlloc
; i
++)
134 if (DdePairs
[i
].ServerMem
== ServerMem
)
137 DdePairs
[i
].ServerMem
= 0;
139 Ret
= DdePairs
[i
].ClientMem
;
143 LeaveCriticalSection(&DdeCrst
);
149 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
153 switch (UMMsg
->message
)
157 PKMDDELPARAM DdeLparam
;
158 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
159 if (NULL
== DdeLparam
)
165 DdeLparam
->Packed
= TRUE
;
166 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
167 &DdeLparam
->Value
.Packed
.uiLo
,
168 &DdeLparam
->Value
.Packed
.uiHi
))
172 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
174 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
175 HGLOBAL h
= DdeGetPair((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
178 GlobalFree((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
179 DdeLparam
->Value
.Packed
.uiHi
= (UINT
) h
;
182 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
186 DdeLparam
->Packed
= FALSE
;
187 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
189 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
196 PKMDDEEXECUTEDATA KMDdeExecuteData
;
199 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
200 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
203 SetLastError(ERROR_INVALID_HANDLE
);
206 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
207 if (NULL
== KMDdeExecuteData
)
209 SetLastError(ERROR_OUTOFMEMORY
);
212 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
213 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
214 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
215 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
216 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
217 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
223 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
224 PCOPYDATASTRUCT pKMCopyData
;
226 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
227 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
228 if (pKMCopyData
== NULL
)
230 SetLastError(ERROR_OUTOFMEMORY
);
234 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
235 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
236 pKMCopyData
->lpData
= pKMCopyData
+ 1;
238 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
239 pUMCopyData
->cbData
);
241 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
253 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
255 switch (KMMsg
->message
)
260 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
270 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
272 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
278 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
282 switch (UMMsg
->message
)
287 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
289 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
290 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
291 if (L
'A' == *((WCHAR
*) Class
))
293 Class
+= sizeof(WCHAR
);
294 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
298 ASSERT(L
'S' == *((WCHAR
*) Class
));
299 Class
+= sizeof(WCHAR
);
300 Cs
->lpszClass
= (LPCWSTR
) Class
;
307 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
308 if (DdeLparam
->Packed
)
310 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
311 DdeLparam
->Value
.Packed
.uiLo
,
312 DdeLparam
->Value
.Packed
.uiHi
);
316 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
323 PKMDDEEXECUTEDATA KMDdeExecuteData
;
327 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
328 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
329 if (NULL
== GlobalData
)
333 Data
= GlobalLock(GlobalData
);
336 GlobalFree(GlobalData
);
339 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
340 GlobalUnlock(GlobalData
);
341 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
343 GlobalFree(GlobalData
);
346 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
347 UMMsg
->lParam
= (LPARAM
) GlobalData
;
353 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
354 pKMCopyData
->lpData
= pKMCopyData
+ 1;
366 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
368 switch (KMMsg
->message
)
372 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
373 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
384 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
386 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
392 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
394 *UnicodeMsg
= *AnsiMsg
;
395 switch (AnsiMsg
->message
)
398 case WM_ASKCBFORMATNAME
:
400 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
401 AnsiMsg
->wParam
* sizeof(WCHAR
));
406 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
410 /* AnsiMsg->lParam is string (0-terminated) */
412 case WM_WININICHANGE
:
413 case WM_DEVMODECHANGE
:
419 UNICODE_STRING UnicodeString
;
420 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
421 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
428 UNICODE_STRING UnicodeBuffer
;
431 CREATESTRUCTW cs
; /* new structure */
432 LPCWSTR lpszName
; /* allocated Name */
433 LPCWSTR lpszClass
; /* allocated Class */
435 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
440 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
441 if (HIWORD(xs
->cs
.lpszName
))
443 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszName
);
444 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeBuffer
.Buffer
;
446 if (HIWORD(xs
->cs
.lpszClass
))
448 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszClass
);
449 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeBuffer
.Buffer
;
451 UnicodeMsg
->lParam
= (LPARAM
)xs
;
457 UNICODE_STRING UnicodeBuffer
;
458 MDICREATESTRUCTW
*cs
=
459 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
466 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
468 if (HIWORD(cs
->szClass
))
470 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szClass
);
471 cs
->szClass
= UnicodeBuffer
.Buffer
;
474 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szTitle
);
475 cs
->szTitle
= UnicodeBuffer
.Buffer
;
477 UnicodeMsg
->lParam
= (LPARAM
)cs
;
487 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
489 switch (AnsiMsg
->message
)
492 case WM_ASKCBFORMATNAME
:
494 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
499 case WM_WININICHANGE
:
500 case WM_DEVMODECHANGE
:
506 UNICODE_STRING UnicodeString
;
507 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
508 RtlFreeUnicodeString(&UnicodeString
);
515 UNICODE_STRING UnicodeString
;
518 CREATESTRUCTW cs
; /* new structure */
519 LPWSTR lpszName
; /* allocated Name */
520 LPWSTR lpszClass
; /* allocated Class */
522 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
525 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
526 RtlFreeUnicodeString(&UnicodeString
);
530 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
531 RtlFreeUnicodeString(&UnicodeString
);
533 HeapFree(GetProcessHeap(), 0, xs
);
539 UNICODE_STRING UnicodeString
;
540 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
541 if (HIWORD(cs
->szTitle
))
543 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
544 RtlFreeUnicodeString(&UnicodeString
);
546 if (HIWORD(cs
->szClass
))
548 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
549 RtlFreeUnicodeString(&UnicodeString
);
551 HeapFree(GetProcessHeap(), 0, cs
);
560 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
562 switch (AnsiMsg
->message
)
565 case WM_ASKCBFORMATNAME
:
567 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
568 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
569 if (UnicodeMsg
->wParam
> 0 &&
570 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
571 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
573 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
579 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
586 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
588 *AnsiMsg
= *UnicodeMsg
;
590 switch(UnicodeMsg
->message
)
597 UNICODE_STRING UString
;
601 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
602 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
607 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
609 RtlInitUnicodeString(&UString
, CsW
->lpszName
);
610 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
611 if (! NT_SUCCESS(Status
))
613 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
616 CsA
->lpszName
= AString
.Buffer
;
617 if (HIWORD((ULONG
)CsW
->lpszClass
) != 0)
619 RtlInitUnicodeString(&UString
, CsW
->lpszClass
);
620 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
621 if (! NT_SUCCESS(Status
))
623 RtlInitAnsiString(&AString
, CsA
->lpszName
);
624 RtlFreeAnsiString(&AString
);
625 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
628 CsA
->lpszClass
= AString
.Buffer
;
630 AnsiMsg
->lParam
= (LPARAM
)CsA
;
635 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
636 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
637 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
638 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
646 ANSI_STRING AnsiString
;
647 UNICODE_STRING UnicodeString
;
648 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
649 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
655 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
665 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
667 switch(UnicodeMsg
->message
)
671 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
677 RtlInitAnsiString(&AString
, (PSTR
) AnsiMsg
->lParam
);
678 RtlFreeAnsiString(&AString
);
687 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
688 RtlInitAnsiString(&AString
, Cs
->lpszName
);
689 RtlFreeAnsiString(&AString
);
690 if (HIWORD((ULONG
)Cs
->lpszClass
) != 0)
692 RtlInitAnsiString(&AString
, Cs
->lpszClass
);
693 RtlFreeAnsiString(&AString
);
695 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
705 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
707 switch (UnicodeMsg
->message
)
710 case WM_ASKCBFORMATNAME
:
712 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
713 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
714 if (0 < AnsiMsg
->wParam
&&
715 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
717 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
723 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
728 typedef struct tagMSGCONVERSION
737 } MSGCONVERSION
, *PMSGCONVERSION
;
739 static PMSGCONVERSION MsgConversions
= NULL
;
740 static unsigned MsgConversionNumAlloc
= 0;
741 static unsigned MsgConversionNumUsed
= 0;
742 static CRITICAL_SECTION MsgConversionCrst
;
745 MsgConversionAdd(PMSGCONVERSION Conversion
)
749 EnterCriticalSection(&MsgConversionCrst
);
751 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
755 if (NULL
!= MsgConversions
)
757 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
758 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
762 New
= HeapAlloc(GetProcessHeap(), 0,
763 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
768 LeaveCriticalSection(&MsgConversionCrst
);
771 MsgConversions
= New
;
772 /* zero out newly allocated part */
773 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
774 MsgConversionNumAlloc
+= GROWBY
;
778 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
780 if (! MsgConversions
[i
].InUse
)
782 MsgConversions
[i
] = *Conversion
;
783 MsgConversions
[i
].InUse
= TRUE
;
784 MsgConversionNumUsed
++;
788 LeaveCriticalSection(&MsgConversionCrst
);
794 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
797 PMSGCONVERSION Conversion
;
800 EnterCriticalSection(&MsgConversionCrst
);
801 for (Conversion
= MsgConversions
;
802 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
805 if (Conversion
->InUse
&&
806 ((Ansi
&& Conversion
->Ansi
) ||
807 (! Ansi
&& ! Conversion
->Ansi
)))
809 Found
= (Conversion
->FinalMsg
== Msg
);
810 if (! Found
&& CheckMsgContents
)
814 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
818 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
825 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
826 NULL
== Result
? &Dummy
: Result
);
828 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
829 NULL
== Result
? &Dummy
: Result
);
830 if (0 != Conversion
->LParamSize
)
832 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
833 &Conversion
->LParamSize
, MEM_DECOMMIT
);
835 Conversion
->InUse
= FALSE
;
836 MsgConversionNumUsed
--;
840 LeaveCriticalSection(&MsgConversionCrst
);
848 GetMessageExtraInfo(VOID
)
850 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
861 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
862 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
872 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
873 return(ThreadData
->LastMessage
.time
);
884 static DWORD ShowNotImplemented
= TRUE
;
885 if (ShowNotImplemented
)
887 DbgPrint("InSendMessage is unimplemented\n");
888 ShowNotImplemented
= FALSE
;
890 /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
903 /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
930 return NtUserSetMessageExtraInfo(lParam
);
934 IntCallWindowProcW(BOOL IsAnsiProc
,
947 UnicodeMsg
.hwnd
= hWnd
;
948 UnicodeMsg
.message
= Msg
;
949 UnicodeMsg
.wParam
= wParam
;
950 UnicodeMsg
.lParam
= lParam
;
951 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
955 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
956 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
964 return WndProc(hWnd
, Msg
, wParam
, lParam
);
968 STATIC LRESULT FASTCALL
969 IntCallWindowProcA(BOOL IsAnsiProc
,
982 return WndProc(hWnd
, Msg
, wParam
, lParam
);
987 AnsiMsg
.message
= Msg
;
988 AnsiMsg
.wParam
= wParam
;
989 AnsiMsg
.lParam
= lParam
;
990 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
994 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
995 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
996 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1009 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1016 WndProcHandle wphData
;
1018 if (lpPrevWndFunc
== NULL
)
1019 lpPrevWndFunc
= (WNDPROC
)NtUserGetWindowLong(hWnd
, GWL_WNDPROC
, FALSE
);
1021 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1024 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1028 return IntCallWindowProcA(! wphData
.IsUnicode
, wphData
.WindowProc
,
1029 hWnd
, Msg
, wParam
, lParam
);
1038 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1045 WndProcHandle wphData
;
1047 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1050 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1054 return IntCallWindowProcW(! wphData
.IsUnicode
, wphData
.WindowProc
,
1055 hWnd
, Msg
, wParam
, lParam
);
1064 DispatchMessageA(CONST MSG
*lpmsg
)
1066 NTUSERDISPATCHMESSAGEINFO Info
;
1071 Result
= NtUserDispatchMessage(&Info
);
1072 if (! Info
.HandledByKernel
)
1074 /* We need to send the message ourselves */
1075 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1076 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1078 MsgConversionCleanup(lpmsg
, TRUE
, TRUE
, &Result
);
1088 DispatchMessageW(CONST MSG
*lpmsg
)
1090 NTUSERDISPATCHMESSAGEINFO Info
;
1095 Result
= NtUserDispatchMessage(&Info
);
1096 if (! Info
.HandledByKernel
)
1098 /* We need to send the message ourselves */
1099 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1100 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1102 MsgConversionCleanup(lpmsg
, FALSE
, TRUE
, &Result
);
1112 GetMessageA(LPMSG lpMsg
,
1118 MSGCONVERSION Conversion
;
1119 NTUSERGETMESSAGEINFO Info
;
1120 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1122 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1123 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1124 if (-1 == (int) Res
)
1128 Conversion
.LParamSize
= Info
.LParamSize
;
1129 Conversion
.KMMsg
= Info
.Msg
;
1131 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1135 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1137 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1140 *lpMsg
= Conversion
.AnsiMsg
;
1141 Conversion
.Ansi
= TRUE
;
1142 Conversion
.FinalMsg
= lpMsg
;
1143 MsgConversionAdd(&Conversion
);
1144 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1146 ThreadData
->LastMessage
= Info
.Msg
;
1157 GetMessageW(LPMSG lpMsg
,
1163 MSGCONVERSION Conversion
;
1164 NTUSERGETMESSAGEINFO Info
;
1165 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1167 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1168 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1169 if (-1 == (int) Res
)
1173 Conversion
.LParamSize
= Info
.LParamSize
;
1174 Conversion
.KMMsg
= Info
.Msg
;
1176 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1180 *lpMsg
= Conversion
.UnicodeMsg
;
1181 Conversion
.Ansi
= FALSE
;
1182 Conversion
.FinalMsg
= lpMsg
;
1183 MsgConversionAdd(&Conversion
);
1184 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1186 ThreadData
->LastMessage
= Info
.Msg
;
1197 PeekMessageA(LPMSG lpMsg
,
1204 MSGCONVERSION Conversion
;
1205 NTUSERGETMESSAGEINFO Info
;
1206 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1208 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1209 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1210 if (-1 == (int) Res
|| ! Res
)
1214 Conversion
.LParamSize
= Info
.LParamSize
;
1215 Conversion
.KMMsg
= Info
.Msg
;
1217 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1221 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1223 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1226 *lpMsg
= Conversion
.AnsiMsg
;
1227 Conversion
.Ansi
= TRUE
;
1228 Conversion
.FinalMsg
= lpMsg
;
1229 MsgConversionAdd(&Conversion
);
1230 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1232 ThreadData
->LastMessage
= Info
.Msg
;
1252 MSGCONVERSION Conversion
;
1253 NTUSERGETMESSAGEINFO Info
;
1254 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1256 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1257 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1258 if (-1 == (int) Res
|| ! Res
)
1262 Conversion
.LParamSize
= Info
.LParamSize
;
1263 Conversion
.KMMsg
= Info
.Msg
;
1265 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1269 *lpMsg
= Conversion
.UnicodeMsg
;
1270 Conversion
.Ansi
= FALSE
;
1271 Conversion
.FinalMsg
= lpMsg
;
1272 MsgConversionAdd(&Conversion
);
1273 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1275 ThreadData
->LastMessage
= Info
.Msg
;
1298 AnsiMsg
.message
= Msg
;
1299 AnsiMsg
.wParam
= wParam
;
1300 AnsiMsg
.lParam
= lParam
;
1301 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1306 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
1308 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1311 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1312 KMMsg
.wParam
, KMMsg
.lParam
);
1313 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1314 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1335 UMMsg
.message
= Msg
;
1336 UMMsg
.wParam
= wParam
;
1337 UMMsg
.lParam
= lParam
;
1338 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1342 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1343 KMMsg
.wParam
, KMMsg
.lParam
);
1344 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1358 (void) NtUserPostMessage(NULL
, WM_QUIT
, nExitCode
, 0);
1373 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1388 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1396 SendMessageW(HWND Wnd
,
1402 NTUSERSENDMESSAGEINFO Info
;
1406 UMMsg
.message
= Msg
;
1407 UMMsg
.wParam
= wParam
;
1408 UMMsg
.lParam
= lParam
;
1409 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
1414 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1415 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1416 if (! Info
.HandledByKernel
)
1418 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1419 /* We need to send the message ourselves */
1420 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UMMsg
.hwnd
, UMMsg
.message
,
1421 UMMsg
.wParam
, UMMsg
.lParam
);
1423 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
1436 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1441 NTUSERSENDMESSAGEINFO Info
;
1444 AnsiMsg
.message
= Msg
;
1445 AnsiMsg
.wParam
= wParam
;
1446 AnsiMsg
.lParam
= lParam
;
1447 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1452 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
1454 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1458 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1459 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1460 if (! Info
.HandledByKernel
)
1462 /* We need to send the message ourselves */
1465 /* Ansi message and Ansi window proc, that's easy. Clean up
1466 the Unicode message though */
1467 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1468 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1469 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Wnd
, Msg
, wParam
, lParam
);
1473 /* Unicode winproc. Although we started out with an Ansi message we
1474 already converted it to Unicode for the kernel call. Reuse that
1475 message to avoid another conversion */
1476 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1477 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1478 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1484 /* Message sent by kernel. Convert back to Ansi */
1485 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
1486 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1500 SendMessageCallbackA(
1505 SENDASYNCPROC lpCallBack
,
1508 return NtUserSendMessageCallback(
1523 SendMessageCallbackW(
1528 SENDASYNCPROC lpCallBack
,
1531 return NtUserSendMessageCallback(
1546 SendMessageTimeoutA(
1553 PDWORD_PTR lpdwResult
)
1558 NTUSERSENDMESSAGEINFO Info
;
1560 AnsiMsg
.hwnd
= hWnd
;
1561 AnsiMsg
.message
= Msg
;
1562 AnsiMsg
.wParam
= wParam
;
1563 AnsiMsg
.lParam
= lParam
;
1564 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1570 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
1571 UcMsg
.wParam
, UcMsg
.lParam
,
1572 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
1577 if (! Info
.HandledByKernel
)
1579 /* We need to send the message ourselves */
1582 /* Ansi message and Ansi window proc, that's easy. Clean up
1583 the Unicode message though */
1584 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1585 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1589 /* Unicode winproc. Although we started out with an Ansi message we
1590 already converted it to Unicode for the kernel call. Reuse that
1591 message to avoid another conversion */
1592 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1593 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1594 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1600 *lpdwResult
= Result
;
1605 /* Message sent by kernel. Convert back to Ansi */
1606 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1621 SendMessageTimeoutW(
1628 PDWORD_PTR lpdwResult
)
1630 NTUSERSENDMESSAGEINFO Info
;
1634 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
1636 if (! Info
.HandledByKernel
)
1638 /* We need to send the message ourselves */
1639 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1641 *lpdwResult
= Result
;
1685 TranslateMessageEx(CONST MSG
*lpMsg
, DWORD unk
)
1687 return(NtUserTranslateMessage((LPMSG
)lpMsg
, (HKL
)unk
));
1695 TranslateMessage(CONST MSG
*lpMsg
)
1697 return(TranslateMessageEx((LPMSG
)lpMsg
, 0));
1708 return NtUserWaitMessage();
1716 RegisterWindowMessageA(LPCSTR lpString
)
1718 UNICODE_STRING String
;
1722 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
1727 Atom
= NtUserRegisterWindowMessage(&String
);
1728 RtlFreeUnicodeString(&String
);
1737 RegisterWindowMessageW(LPCWSTR lpString
)
1739 UNICODE_STRING String
;
1741 RtlInitUnicodeString(&String
, lpString
);
1742 return(NtUserRegisterWindowMessage(&String
));
1749 SetCapture(HWND hWnd
)
1751 return(NtUserSetCapture(hWnd
));
1760 return(NtUserGetCapture());
1767 ReleaseCapture(VOID
)
1769 NtUserSetCapture(NULL
);
1779 RealGetQueueStatus(UINT flags
)
1782 WORD changed_bits
, wake_bits
;
1784 #if 0 /* wine stuff. don't know what it does... */
1786 /* check for pending X events */
1787 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1788 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1791 ret
= NtUserGetQueueStatus(TRUE
/*ClearChanges*/);
1793 changed_bits
= LOWORD(ret
);
1794 wake_bits
= HIWORD(ret
);
1796 return MAKELONG(changed_bits
& flags
, wake_bits
& flags
);
1803 BOOL STDCALL
GetInputState(VOID
)
1808 #if 0 /* wine stuff. don't know what it does... */
1810 /* check for pending X events */
1811 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1812 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1815 ret
= NtUserGetQueueStatus(FALSE
/*ClearChanges*/);
1817 wake_bits
= HIWORD(ret
);
1819 return wake_bits
& (QS_KEY
| QS_MOUSEBUTTON
);
1824 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
1826 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
1829 /* Make sure we don't try to access mem beyond what we were given */
1830 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1832 return STATUS_INFO_LENGTH_MISMATCH
;
1835 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
1836 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
1837 KMMsg
.message
= CallbackArgs
->Msg
;
1838 KMMsg
.wParam
= CallbackArgs
->wParam
;
1839 /* Check if lParam is really a pointer and adjust it if it is */
1840 if (0 <= CallbackArgs
->lParamBufferSize
)
1842 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
1843 + CallbackArgs
->lParamBufferSize
)
1845 return STATUS_INFO_LENGTH_MISMATCH
;
1847 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
1851 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1853 return STATUS_INFO_LENGTH_MISMATCH
;
1855 KMMsg
.lParam
= CallbackArgs
->lParam
;
1858 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
1860 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
1861 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
1864 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
1868 CallbackArgs
->Result
= IntCallWindowProcW(CallbackArgs
->IsAnsiProc
, CallbackArgs
->Proc
,
1869 UMMsg
.hwnd
, UMMsg
.message
,
1870 UMMsg
.wParam
, UMMsg
.lParam
);
1872 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
1876 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
1882 BOOL STDCALL
SetMessageQueue(int cMessagesMax
)
1884 /* Function does nothing on 32 bit windows */
1887 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
1888 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
1890 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
1892 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
1893 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
1894 RealGetQueueStatusProc RealGetQueueStatus
;
1895 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
1896 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
1900 RealMsgWaitForMultipleObjectsEx(
1902 CONST HANDLE
*pHandles
,
1903 DWORD dwMilliseconds
,
1907 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
1909 CRITICAL_SECTION gcsMPH
;
1910 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
1911 DWORD gcLoadMPH
= 0;
1912 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
1913 //NtUserRealInternalGetMessage,
1914 //NtUserRealInternalWaitMessageEx,
1916 RealMsgWaitForMultipleObjectsEx
1919 DWORD gfMessagePumpHook
= 0;
1921 BOOL WINAPI
IsInsideMessagePumpHook()
1923 if(!gfMessagePumpHook
)
1926 /* This code checks if we're inside SendMessage. */
1928 /* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
1929 PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
1931 if(!*(PLONG*)&NtTeb[0x708])
1934 if(**(PLONG*)&NtTeb[0x708] <= 0)
1941 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
1943 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
1944 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
1945 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
1946 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
1947 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
1950 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
1952 EnterCriticalSection(&gcsMPH
);
1954 SetLastError(ERROR_INVALID_PARAMETER
);
1955 LeaveCriticalSection(&gcsMPH
);
1959 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
1961 ResetMessagePumpHook(&Addresses
);
1962 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
1963 LeaveCriticalSection(&gcsMPH
);
1966 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
1968 if(gpfnInitMPH
!= Hook
) {
1969 LeaveCriticalSection(&gcsMPH
);
1973 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
1974 LeaveCriticalSection(&gcsMPH
);
1978 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
1980 LeaveCriticalSection(&gcsMPH
);
1984 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
1986 EnterCriticalSection(&gcsMPH
);
1988 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
1991 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
1992 gpfnInitMPH(TRUE
, NULL
);
1993 ResetMessagePumpHook(&gmph
);
1996 LeaveCriticalSection(&gcsMPH
);
2000 LeaveCriticalSection(&gcsMPH
);
2004 DWORD WINAPI
GetQueueStatus(UINT flags
)
2006 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2010 * @name RealMsgWaitForMultipleObjectsEx
2012 * Wait either for either message arrival or for one of the passed events
2016 * Number of handles in the pHandles array.
2018 * Handles of events to wait for.
2019 * @param dwMilliseconds
2022 * Mask specifying on which message events we should wakeup.
2024 * Wait type (see MWMO_* constants).
2030 RealMsgWaitForMultipleObjectsEx(
2032 const HANDLE
*pHandles
,
2033 DWORD dwMilliseconds
,
2037 LPHANDLE RealHandles
;
2038 HANDLE MessageQueueHandle
;
2041 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2043 SetLastError(ERROR_INVALID_PARAMETER
);
2048 if (dwFlags & MWMO_INPUTAVAILABLE)
2050 RealGetQueueStatus(dwWakeMask);
2054 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2055 if (MessageQueueHandle
== NULL
)
2057 SetLastError(0); /* ? */
2061 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2062 if (RealHandles
== NULL
)
2064 NtUserMsqClearWakeMask();
2065 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2069 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2070 RealHandles
[nCount
] = MessageQueueHandle
;
2072 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2073 dwFlags
& MWMO_WAITALL
,
2074 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2076 HeapFree(GetProcessHeap(), 0, RealHandles
);
2077 NtUserMsqClearWakeMask();
2086 MsgWaitForMultipleObjectsEx(
2088 CONST HANDLE
*lpHandles
,
2089 DWORD dwMilliseconds
,
2093 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2100 MsgWaitForMultipleObjects(
2102 CONST HANDLE
*lpHandles
,
2104 DWORD dwMilliseconds
,
2107 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2108 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2112 BOOL FASTCALL
MessageInit()
2114 InitializeCriticalSection(&DdeCrst
);
2115 InitializeCriticalSection(&MsgConversionCrst
);