3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/message.c
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 06-06-2001 CSH Created
15 #include <user32/callback.h>
18 /* DDE message exchange
20 * - Session initialization
21 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
22 * this message contains a pair of global atoms, the Application and Topic atoms.
23 * The client must destroy the atoms.
24 * Server window proc handles the WM_DDE_INITIATE message and if the Application
25 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
26 * of the reply message contains another pair of global atoms (Application and
27 * Topic again), which must be destroyed by the server.
30 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
31 * is a global memory handle containing the string to execute. After the command has
32 * been executed the server posts a WM_DDE_ACK message to the client, which contains
33 * a packed lParam which in turn contains that global memory handle. The client takes
34 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
35 * it and the global memory handle.
36 * This might work nice and easy in Win3.1, but things are more complicated for NT.
37 * Global memory handles in NT are not really global, they're still local to the
38 * process. So, what happens under the hood is that PostMessage must handle the
39 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
40 * area, repack that into a new structure together with the original memory handle
41 * and pass that off to the win32k. Win32k will marshall that data over to the target
42 * (server) process where it will be unpacked and stored in a newly allocated global
43 * memory area. The handle of that area will then be sent to the window proc, after
44 * storing it together with the "original" (client) handle in a table.
45 * The server will eventually post the WM_DDE_ACK response, containing the global
46 * memory handle it received. PostMessage must then lookup that memory handle (only
47 * valid in the server process) and replace it with the corresponding client memory
48 * handle. To avoid memory leaks, the server-side global memory block must be freed.
49 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
50 * individual components are handed to win32k.sys to post to the client side. Since
51 * the server side app hands over ownership of the packed lParam when it calls
52 * PostMessage(), the packed lParam needs to be freed on the server side too.
53 * When the WM_DDE_ACK message (containing the client-side global memory handle)
54 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
55 * to the client side window proc which is expected to free/reuse it.
58 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
59 * to the memory handle, we keep track (in the server side) of all pairs of handle
60 * used (the client passes its value and the content of the memory handle), and
61 * the server stored both values (the client, and the local one, created after the
62 * content). When a ACK message is generated, the list of pair is searched for a
63 * matching pair, so that the client memory handle can be returned.
65 typedef struct tagDDEPAIR
71 static PDDEPAIR DdePairs
= NULL
;
72 static unsigned DdeNumAlloc
= 0;
73 static unsigned DdeNumUsed
= 0;
74 static CRITICAL_SECTION DdeCrst
;
77 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
81 EnterCriticalSection(&DdeCrst
);
83 /* now remember the pair of hMem on both sides */
84 if (DdeNumUsed
== DdeNumAlloc
)
90 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
91 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
95 New
= HeapAlloc(GetProcessHeap(), 0,
96 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
101 LeaveCriticalSection(&DdeCrst
);
105 /* zero out newly allocated part */
106 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
107 DdeNumAlloc
+= GROWBY
;
111 for (i
= 0; i
< DdeNumAlloc
; i
++)
113 if (NULL
== DdePairs
[i
].ServerMem
)
115 DdePairs
[i
].ClientMem
= ClientMem
;
116 DdePairs
[i
].ServerMem
= ServerMem
;
121 LeaveCriticalSection(&DdeCrst
);
126 static HGLOBAL FASTCALL
127 DdeGetPair(HGLOBAL ServerMem
)
132 EnterCriticalSection(&DdeCrst
);
133 for (i
= 0; i
< DdeNumAlloc
; i
++)
135 if (DdePairs
[i
].ServerMem
== ServerMem
)
138 DdePairs
[i
].ServerMem
= 0;
140 Ret
= DdePairs
[i
].ClientMem
;
144 LeaveCriticalSection(&DdeCrst
);
150 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
154 switch (UMMsg
->message
)
158 PKMDDELPARAM DdeLparam
;
159 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
160 if (NULL
== DdeLparam
)
166 DdeLparam
->Packed
= TRUE
;
167 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
168 &DdeLparam
->Value
.Packed
.uiLo
,
169 &DdeLparam
->Value
.Packed
.uiHi
))
173 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
175 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
176 HGLOBAL h
= DdeGetPair((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
179 GlobalFree((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
180 DdeLparam
->Value
.Packed
.uiHi
= (UINT
) h
;
183 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
187 DdeLparam
->Packed
= FALSE
;
188 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
190 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
197 PKMDDEEXECUTEDATA KMDdeExecuteData
;
200 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
201 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
204 SetLastError(ERROR_INVALID_HANDLE
);
207 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
208 if (NULL
== KMDdeExecuteData
)
210 SetLastError(ERROR_OUTOFMEMORY
);
213 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
214 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
215 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
216 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
217 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
218 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
224 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
225 PCOPYDATASTRUCT pKMCopyData
;
227 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
228 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
229 if (pKMCopyData
== NULL
)
231 SetLastError(ERROR_OUTOFMEMORY
);
235 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
236 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
237 pKMCopyData
->lpData
= pKMCopyData
+ 1;
239 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
240 pUMCopyData
->cbData
);
242 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
254 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
256 switch (KMMsg
->message
)
261 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
271 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
273 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
279 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
283 switch (UMMsg
->message
)
288 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
290 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
291 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
292 if (L
'A' == *((WCHAR
*) Class
))
294 Class
+= sizeof(WCHAR
);
295 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
299 ASSERT(L
'S' == *((WCHAR
*) Class
));
300 Class
+= sizeof(WCHAR
);
301 Cs
->lpszClass
= (LPCWSTR
) Class
;
308 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
309 if (DdeLparam
->Packed
)
311 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
312 DdeLparam
->Value
.Packed
.uiLo
,
313 DdeLparam
->Value
.Packed
.uiHi
);
317 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
324 PKMDDEEXECUTEDATA KMDdeExecuteData
;
328 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
329 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
330 if (NULL
== GlobalData
)
334 Data
= GlobalLock(GlobalData
);
337 GlobalFree(GlobalData
);
340 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
341 GlobalUnlock(GlobalData
);
342 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
344 GlobalFree(GlobalData
);
347 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
348 UMMsg
->lParam
= (LPARAM
) GlobalData
;
354 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
355 pKMCopyData
->lpData
= pKMCopyData
+ 1;
367 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
369 switch (KMMsg
->message
)
373 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
374 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
385 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
387 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
393 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
395 *UnicodeMsg
= *AnsiMsg
;
396 switch (AnsiMsg
->message
)
399 case WM_ASKCBFORMATNAME
:
401 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
402 AnsiMsg
->wParam
* sizeof(WCHAR
));
407 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
411 /* AnsiMsg->lParam is string (0-terminated) */
413 case WM_WININICHANGE
:
414 case WM_DEVMODECHANGE
:
420 UNICODE_STRING UnicodeString
;
421 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
422 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
429 UNICODE_STRING UnicodeBuffer
;
432 CREATESTRUCTW cs
; /* new structure */
433 LPCWSTR lpszName
; /* allocated Name */
434 LPCWSTR lpszClass
; /* allocated Class */
436 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
441 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
442 if (HIWORD(xs
->cs
.lpszName
))
444 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszName
);
445 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeBuffer
.Buffer
;
447 if (HIWORD(xs
->cs
.lpszClass
))
449 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszClass
);
450 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeBuffer
.Buffer
;
452 UnicodeMsg
->lParam
= (LPARAM
)xs
;
458 UNICODE_STRING UnicodeBuffer
;
459 MDICREATESTRUCTW
*cs
=
460 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
467 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
469 if (HIWORD(cs
->szClass
))
471 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szClass
);
472 cs
->szClass
= UnicodeBuffer
.Buffer
;
475 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szTitle
);
476 cs
->szTitle
= UnicodeBuffer
.Buffer
;
478 UnicodeMsg
->lParam
= (LPARAM
)cs
;
488 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
490 switch (AnsiMsg
->message
)
493 case WM_ASKCBFORMATNAME
:
495 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
500 case WM_WININICHANGE
:
501 case WM_DEVMODECHANGE
:
507 UNICODE_STRING UnicodeString
;
508 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
509 RtlFreeUnicodeString(&UnicodeString
);
516 UNICODE_STRING UnicodeString
;
519 CREATESTRUCTW cs
; /* new structure */
520 LPWSTR lpszName
; /* allocated Name */
521 LPWSTR lpszClass
; /* allocated Class */
523 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
526 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
527 RtlFreeUnicodeString(&UnicodeString
);
531 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
532 RtlFreeUnicodeString(&UnicodeString
);
534 HeapFree(GetProcessHeap(), 0, xs
);
540 UNICODE_STRING UnicodeString
;
541 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
542 if (HIWORD(cs
->szTitle
))
544 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
545 RtlFreeUnicodeString(&UnicodeString
);
547 if (HIWORD(cs
->szClass
))
549 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
550 RtlFreeUnicodeString(&UnicodeString
);
552 HeapFree(GetProcessHeap(), 0, cs
);
561 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
563 switch (AnsiMsg
->message
)
566 case WM_ASKCBFORMATNAME
:
568 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
569 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
570 if (UnicodeMsg
->wParam
> 0 &&
571 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
572 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
574 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
580 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
587 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
589 *AnsiMsg
= *UnicodeMsg
;
591 switch(UnicodeMsg
->message
)
598 UNICODE_STRING UString
;
602 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
603 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
608 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
610 RtlInitUnicodeString(&UString
, CsW
->lpszName
);
611 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
612 if (! NT_SUCCESS(Status
))
614 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
617 CsA
->lpszName
= AString
.Buffer
;
618 if (HIWORD((ULONG
)CsW
->lpszClass
) != 0)
620 RtlInitUnicodeString(&UString
, CsW
->lpszClass
);
621 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
622 if (! NT_SUCCESS(Status
))
624 RtlInitAnsiString(&AString
, CsA
->lpszName
);
625 RtlFreeAnsiString(&AString
);
626 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
629 CsA
->lpszClass
= AString
.Buffer
;
631 AnsiMsg
->lParam
= (LPARAM
)CsA
;
636 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
637 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
638 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
639 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
647 ANSI_STRING AnsiString
;
648 UNICODE_STRING UnicodeString
;
649 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
650 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
656 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
666 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
668 switch(UnicodeMsg
->message
)
672 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
678 RtlInitAnsiString(&AString
, (PSTR
) AnsiMsg
->lParam
);
679 RtlFreeAnsiString(&AString
);
688 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
689 RtlInitAnsiString(&AString
, Cs
->lpszName
);
690 RtlFreeAnsiString(&AString
);
691 if (HIWORD((ULONG
)Cs
->lpszClass
) != 0)
693 RtlInitAnsiString(&AString
, Cs
->lpszClass
);
694 RtlFreeAnsiString(&AString
);
696 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
706 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
708 switch (UnicodeMsg
->message
)
711 case WM_ASKCBFORMATNAME
:
713 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
714 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
715 if (0 < AnsiMsg
->wParam
&&
716 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
718 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
724 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
729 typedef struct tagMSGCONVERSION
738 } MSGCONVERSION
, *PMSGCONVERSION
;
740 static PMSGCONVERSION MsgConversions
= NULL
;
741 static unsigned MsgConversionNumAlloc
= 0;
742 static unsigned MsgConversionNumUsed
= 0;
743 static CRITICAL_SECTION MsgConversionCrst
;
746 MsgConversionAdd(PMSGCONVERSION Conversion
)
750 EnterCriticalSection(&MsgConversionCrst
);
752 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
756 if (NULL
!= MsgConversions
)
758 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
759 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
763 New
= HeapAlloc(GetProcessHeap(), 0,
764 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
769 LeaveCriticalSection(&MsgConversionCrst
);
772 MsgConversions
= New
;
773 /* zero out newly allocated part */
774 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
775 MsgConversionNumAlloc
+= GROWBY
;
779 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
781 if (! MsgConversions
[i
].InUse
)
783 MsgConversions
[i
] = *Conversion
;
784 MsgConversions
[i
].InUse
= TRUE
;
785 MsgConversionNumUsed
++;
789 LeaveCriticalSection(&MsgConversionCrst
);
795 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
798 PMSGCONVERSION Conversion
;
801 EnterCriticalSection(&MsgConversionCrst
);
802 for (Conversion
= MsgConversions
;
803 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
806 if (Conversion
->InUse
&&
807 ((Ansi
&& Conversion
->Ansi
) ||
808 (! Ansi
&& ! Conversion
->Ansi
)))
810 Found
= (Conversion
->FinalMsg
== Msg
);
811 if (! Found
&& CheckMsgContents
)
815 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
819 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
826 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
827 NULL
== Result
? &Dummy
: Result
);
829 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
830 NULL
== Result
? &Dummy
: Result
);
831 if (0 != Conversion
->LParamSize
)
833 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
834 &Conversion
->LParamSize
, MEM_DECOMMIT
);
836 Conversion
->InUse
= FALSE
;
837 MsgConversionNumUsed
--;
841 LeaveCriticalSection(&MsgConversionCrst
);
849 GetMessageExtraInfo(VOID
)
851 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
862 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
863 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
873 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
874 return(ThreadData
->LastMessage
.time
);
885 static DWORD ShowNotImplemented
= TRUE
;
886 if (ShowNotImplemented
)
888 DbgPrint("InSendMessage is unimplemented\n");
889 ShowNotImplemented
= FALSE
;
891 /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
904 /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
931 return NtUserSetMessageExtraInfo(lParam
);
935 IntCallWindowProcW(BOOL IsAnsiProc
,
948 UnicodeMsg
.hwnd
= hWnd
;
949 UnicodeMsg
.message
= Msg
;
950 UnicodeMsg
.wParam
= wParam
;
951 UnicodeMsg
.lParam
= lParam
;
952 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
956 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
957 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
965 return WndProc(hWnd
, Msg
, wParam
, lParam
);
969 STATIC LRESULT FASTCALL
970 IntCallWindowProcA(BOOL IsAnsiProc
,
983 return WndProc(hWnd
, Msg
, wParam
, lParam
);
988 AnsiMsg
.message
= Msg
;
989 AnsiMsg
.wParam
= wParam
;
990 AnsiMsg
.lParam
= lParam
;
991 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
995 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
996 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
997 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1010 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1017 WndProcHandle wphData
;
1019 if (lpPrevWndFunc
== NULL
)
1020 lpPrevWndFunc
= (WNDPROC
)NtUserGetWindowLong(hWnd
, GWL_WNDPROC
, FALSE
);
1022 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1025 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1029 return IntCallWindowProcA(! wphData
.IsUnicode
, wphData
.WindowProc
,
1030 hWnd
, Msg
, wParam
, lParam
);
1039 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1046 WndProcHandle wphData
;
1048 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1051 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1055 return IntCallWindowProcW(! wphData
.IsUnicode
, wphData
.WindowProc
,
1056 hWnd
, Msg
, wParam
, lParam
);
1065 DispatchMessageA(CONST MSG
*lpmsg
)
1067 NTUSERDISPATCHMESSAGEINFO Info
;
1072 Result
= NtUserDispatchMessage(&Info
);
1073 if (! Info
.HandledByKernel
)
1075 /* We need to send the message ourselves */
1076 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1077 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1079 MsgConversionCleanup(lpmsg
, TRUE
, TRUE
, &Result
);
1089 DispatchMessageW(CONST MSG
*lpmsg
)
1091 NTUSERDISPATCHMESSAGEINFO Info
;
1096 Result
= NtUserDispatchMessage(&Info
);
1097 if (! Info
.HandledByKernel
)
1099 /* We need to send the message ourselves */
1100 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1101 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1103 MsgConversionCleanup(lpmsg
, FALSE
, TRUE
, &Result
);
1113 GetMessageA(LPMSG lpMsg
,
1119 MSGCONVERSION Conversion
;
1120 NTUSERGETMESSAGEINFO Info
;
1121 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1123 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1124 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1125 if (-1 == (int) Res
)
1129 Conversion
.LParamSize
= Info
.LParamSize
;
1130 Conversion
.KMMsg
= Info
.Msg
;
1132 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1136 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1138 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1141 *lpMsg
= Conversion
.AnsiMsg
;
1142 Conversion
.Ansi
= TRUE
;
1143 Conversion
.FinalMsg
= lpMsg
;
1144 MsgConversionAdd(&Conversion
);
1145 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1147 ThreadData
->LastMessage
= Info
.Msg
;
1158 GetMessageW(LPMSG lpMsg
,
1164 MSGCONVERSION Conversion
;
1165 NTUSERGETMESSAGEINFO Info
;
1166 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1168 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1169 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1170 if (-1 == (int) Res
)
1174 Conversion
.LParamSize
= Info
.LParamSize
;
1175 Conversion
.KMMsg
= Info
.Msg
;
1177 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1181 *lpMsg
= Conversion
.UnicodeMsg
;
1182 Conversion
.Ansi
= FALSE
;
1183 Conversion
.FinalMsg
= lpMsg
;
1184 MsgConversionAdd(&Conversion
);
1185 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1187 ThreadData
->LastMessage
= Info
.Msg
;
1198 PeekMessageA(LPMSG lpMsg
,
1205 MSGCONVERSION Conversion
;
1206 NTUSERGETMESSAGEINFO Info
;
1207 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1209 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1210 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1211 if (-1 == (int) Res
|| ! Res
)
1215 Conversion
.LParamSize
= Info
.LParamSize
;
1216 Conversion
.KMMsg
= Info
.Msg
;
1218 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1222 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1224 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1227 *lpMsg
= Conversion
.AnsiMsg
;
1228 Conversion
.Ansi
= TRUE
;
1229 Conversion
.FinalMsg
= lpMsg
;
1230 MsgConversionAdd(&Conversion
);
1231 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1233 ThreadData
->LastMessage
= Info
.Msg
;
1253 MSGCONVERSION Conversion
;
1254 NTUSERGETMESSAGEINFO Info
;
1255 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1257 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1258 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1259 if (-1 == (int) Res
|| ! Res
)
1263 Conversion
.LParamSize
= Info
.LParamSize
;
1264 Conversion
.KMMsg
= Info
.Msg
;
1266 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1270 *lpMsg
= Conversion
.UnicodeMsg
;
1271 Conversion
.Ansi
= FALSE
;
1272 Conversion
.FinalMsg
= lpMsg
;
1273 MsgConversionAdd(&Conversion
);
1274 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1276 ThreadData
->LastMessage
= Info
.Msg
;
1299 AnsiMsg
.message
= Msg
;
1300 AnsiMsg
.wParam
= wParam
;
1301 AnsiMsg
.lParam
= lParam
;
1302 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1307 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
1309 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1312 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1313 KMMsg
.wParam
, KMMsg
.lParam
);
1314 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1315 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1336 UMMsg
.message
= Msg
;
1337 UMMsg
.wParam
= wParam
;
1338 UMMsg
.lParam
= lParam
;
1339 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1343 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1344 KMMsg
.wParam
, KMMsg
.lParam
);
1345 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1359 (void) NtUserPostMessage(NULL
, WM_QUIT
, nExitCode
, 0);
1374 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1389 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1397 SendMessageW(HWND Wnd
,
1403 NTUSERSENDMESSAGEINFO Info
;
1407 UMMsg
.message
= Msg
;
1408 UMMsg
.wParam
= wParam
;
1409 UMMsg
.lParam
= lParam
;
1410 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
1415 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1416 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1417 if (! Info
.HandledByKernel
)
1419 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1420 /* We need to send the message ourselves */
1421 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UMMsg
.hwnd
, UMMsg
.message
,
1422 UMMsg
.wParam
, UMMsg
.lParam
);
1424 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
1437 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1442 NTUSERSENDMESSAGEINFO Info
;
1445 AnsiMsg
.message
= Msg
;
1446 AnsiMsg
.wParam
= wParam
;
1447 AnsiMsg
.lParam
= lParam
;
1448 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1453 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
1455 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1459 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1460 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1461 if (! Info
.HandledByKernel
)
1463 /* We need to send the message ourselves */
1466 /* Ansi message and Ansi window proc, that's easy. Clean up
1467 the Unicode message though */
1468 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1469 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1470 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Wnd
, Msg
, wParam
, lParam
);
1474 /* Unicode winproc. Although we started out with an Ansi message we
1475 already converted it to Unicode for the kernel call. Reuse that
1476 message to avoid another conversion */
1477 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1478 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1479 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1485 /* Message sent by kernel. Convert back to Ansi */
1486 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
1487 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1501 SendMessageCallbackA(
1506 SENDASYNCPROC lpCallBack
,
1509 return NtUserSendMessageCallback(
1524 SendMessageCallbackW(
1529 SENDASYNCPROC lpCallBack
,
1532 return NtUserSendMessageCallback(
1547 SendMessageTimeoutA(
1554 PDWORD_PTR lpdwResult
)
1559 NTUSERSENDMESSAGEINFO Info
;
1561 AnsiMsg
.hwnd
= hWnd
;
1562 AnsiMsg
.message
= Msg
;
1563 AnsiMsg
.wParam
= wParam
;
1564 AnsiMsg
.lParam
= lParam
;
1565 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1571 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
1572 UcMsg
.wParam
, UcMsg
.lParam
,
1573 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
1578 if (! Info
.HandledByKernel
)
1580 /* We need to send the message ourselves */
1583 /* Ansi message and Ansi window proc, that's easy. Clean up
1584 the Unicode message though */
1585 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1586 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1590 /* Unicode winproc. Although we started out with an Ansi message we
1591 already converted it to Unicode for the kernel call. Reuse that
1592 message to avoid another conversion */
1593 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1594 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1595 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1601 *lpdwResult
= Result
;
1606 /* Message sent by kernel. Convert back to Ansi */
1607 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1622 SendMessageTimeoutW(
1629 PDWORD_PTR lpdwResult
)
1631 NTUSERSENDMESSAGEINFO Info
;
1635 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
1637 if (! Info
.HandledByKernel
)
1639 /* We need to send the message ourselves */
1640 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1642 *lpdwResult
= Result
;
1686 TranslateMessageEx(CONST MSG
*lpMsg
, DWORD unk
)
1688 return(NtUserTranslateMessage((LPMSG
)lpMsg
, (HKL
)unk
));
1696 TranslateMessage(CONST MSG
*lpMsg
)
1698 return(TranslateMessageEx((LPMSG
)lpMsg
, 0));
1709 return NtUserWaitMessage();
1717 RegisterWindowMessageA(LPCSTR lpString
)
1719 UNICODE_STRING String
;
1723 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
1728 Atom
= NtUserRegisterWindowMessage(&String
);
1729 RtlFreeUnicodeString(&String
);
1738 RegisterWindowMessageW(LPCWSTR lpString
)
1740 UNICODE_STRING String
;
1742 RtlInitUnicodeString(&String
, lpString
);
1743 return(NtUserRegisterWindowMessage(&String
));
1750 SetCapture(HWND hWnd
)
1752 return(NtUserSetCapture(hWnd
));
1761 return(NtUserGetCapture());
1768 ReleaseCapture(VOID
)
1770 NtUserSetCapture(NULL
);
1780 RealGetQueueStatus(UINT flags
)
1783 WORD changed_bits
, wake_bits
;
1785 #if 0 /* wine stuff. don't know what it does... */
1787 /* check for pending X events */
1788 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1789 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1792 ret
= NtUserGetQueueStatus(TRUE
/*ClearChanges*/);
1794 changed_bits
= LOWORD(ret
);
1795 wake_bits
= HIWORD(ret
);
1797 return MAKELONG(changed_bits
& flags
, wake_bits
& flags
);
1804 BOOL STDCALL
GetInputState(VOID
)
1809 #if 0 /* wine stuff. don't know what it does... */
1811 /* check for pending X events */
1812 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1813 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1816 ret
= NtUserGetQueueStatus(FALSE
/*ClearChanges*/);
1818 wake_bits
= HIWORD(ret
);
1820 return wake_bits
& (QS_KEY
| QS_MOUSEBUTTON
);
1825 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
1827 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
1830 /* Make sure we don't try to access mem beyond what we were given */
1831 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1833 return STATUS_INFO_LENGTH_MISMATCH
;
1836 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
1837 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
1838 KMMsg
.message
= CallbackArgs
->Msg
;
1839 KMMsg
.wParam
= CallbackArgs
->wParam
;
1840 /* Check if lParam is really a pointer and adjust it if it is */
1841 if (0 <= CallbackArgs
->lParamBufferSize
)
1843 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
1844 + CallbackArgs
->lParamBufferSize
)
1846 return STATUS_INFO_LENGTH_MISMATCH
;
1848 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
1852 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1854 return STATUS_INFO_LENGTH_MISMATCH
;
1856 KMMsg
.lParam
= CallbackArgs
->lParam
;
1859 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
1861 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
1862 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
1865 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
1869 CallbackArgs
->Result
= IntCallWindowProcW(CallbackArgs
->IsAnsiProc
, CallbackArgs
->Proc
,
1870 UMMsg
.hwnd
, UMMsg
.message
,
1871 UMMsg
.wParam
, UMMsg
.lParam
);
1873 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
1877 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
1883 BOOL STDCALL
SetMessageQueue(int cMessagesMax
)
1885 /* Function does nothing on 32 bit windows */
1888 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
1889 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
1891 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
1893 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
1894 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
1895 RealGetQueueStatusProc RealGetQueueStatus
;
1896 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
1897 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
1901 RealMsgWaitForMultipleObjectsEx(
1903 CONST HANDLE
*pHandles
,
1904 DWORD dwMilliseconds
,
1908 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
1910 CRITICAL_SECTION gcsMPH
;
1911 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
1912 DWORD gcLoadMPH
= 0;
1913 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
1914 //NtUserRealInternalGetMessage,
1915 //NtUserRealInternalWaitMessageEx,
1917 RealMsgWaitForMultipleObjectsEx
1920 DWORD gfMessagePumpHook
= 0;
1922 BOOL WINAPI
IsInsideMessagePumpHook()
1924 if(!gfMessagePumpHook
)
1927 /* This code checks if we're inside SendMessage. */
1929 /* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
1930 PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
1932 if(!*(PLONG*)&NtTeb[0x708])
1935 if(**(PLONG*)&NtTeb[0x708] <= 0)
1942 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
1944 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
1945 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
1946 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
1947 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
1948 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
1951 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
1953 EnterCriticalSection(&gcsMPH
);
1955 SetLastError(ERROR_INVALID_PARAMETER
);
1956 LeaveCriticalSection(&gcsMPH
);
1960 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
1962 ResetMessagePumpHook(&Addresses
);
1963 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
1964 LeaveCriticalSection(&gcsMPH
);
1967 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
1969 if(gpfnInitMPH
!= Hook
) {
1970 LeaveCriticalSection(&gcsMPH
);
1974 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
1975 LeaveCriticalSection(&gcsMPH
);
1979 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
1981 LeaveCriticalSection(&gcsMPH
);
1985 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
1987 EnterCriticalSection(&gcsMPH
);
1989 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
1992 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
1993 gpfnInitMPH(TRUE
, NULL
);
1994 ResetMessagePumpHook(&gmph
);
1997 LeaveCriticalSection(&gcsMPH
);
2001 LeaveCriticalSection(&gcsMPH
);
2005 DWORD WINAPI
GetQueueStatus(UINT flags
)
2007 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2011 * @name RealMsgWaitForMultipleObjectsEx
2013 * Wait either for either message arrival or for one of the passed events
2017 * Number of handles in the pHandles array.
2019 * Handles of events to wait for.
2020 * @param dwMilliseconds
2023 * Mask specifying on which message events we should wakeup.
2025 * Wait type (see MWMO_* constants).
2031 RealMsgWaitForMultipleObjectsEx(
2033 const HANDLE
*pHandles
,
2034 DWORD dwMilliseconds
,
2038 LPHANDLE RealHandles
;
2039 HANDLE MessageQueueHandle
;
2042 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2044 SetLastError(ERROR_INVALID_PARAMETER
);
2049 if (dwFlags & MWMO_INPUTAVAILABLE)
2051 RealGetQueueStatus(dwWakeMask);
2055 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2056 if (MessageQueueHandle
== NULL
)
2058 SetLastError(0); /* ? */
2062 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2063 if (RealHandles
== NULL
)
2065 NtUserMsqClearWakeMask();
2066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2070 RtlCopyMemory(RealHandles
, pHandles
, nCount
);
2071 RealHandles
[nCount
] = MessageQueueHandle
;
2073 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2074 dwFlags
& MWMO_WAITALL
,
2075 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2077 HeapFree(GetProcessHeap(), 0, RealHandles
);
2078 NtUserMsqClearWakeMask();
2087 MsgWaitForMultipleObjectsEx(
2089 CONST HANDLE
*lpHandles
,
2090 DWORD dwMilliseconds
,
2094 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2101 MsgWaitForMultipleObjects(
2103 CONST HANDLE
*lpHandles
,
2105 DWORD dwMilliseconds
,
2108 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2109 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2113 BOOL FASTCALL
MessageInit()
2115 InitializeCriticalSection(&DdeCrst
);
2116 InitializeCriticalSection(&MsgConversionCrst
);