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
15 /* DDE message exchange
17 * - Session initialization
18 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
19 * this message contains a pair of global atoms, the Application and Topic atoms.
20 * The client must destroy the atoms.
21 * Server window proc handles the WM_DDE_INITIATE message and if the Application
22 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
23 * of the reply message contains another pair of global atoms (Application and
24 * Topic again), which must be destroyed by the server.
27 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
28 * is a global memory handle containing the string to execute. After the command has
29 * been executed the server posts a WM_DDE_ACK message to the client, which contains
30 * a packed lParam which in turn contains that global memory handle. The client takes
31 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
32 * it and the global memory handle.
33 * This might work nice and easy in Win3.1, but things are more complicated for NT.
34 * Global memory handles in NT are not really global, they're still local to the
35 * process. So, what happens under the hood is that PostMessage must handle the
36 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
37 * area, repack that into a new structure together with the original memory handle
38 * and pass that off to the win32k. Win32k will marshall that data over to the target
39 * (server) process where it will be unpacked and stored in a newly allocated global
40 * memory area. The handle of that area will then be sent to the window proc, after
41 * storing it together with the "original" (client) handle in a table.
42 * The server will eventually post the WM_DDE_ACK response, containing the global
43 * memory handle it received. PostMessage must then lookup that memory handle (only
44 * valid in the server process) and replace it with the corresponding client memory
45 * handle. To avoid memory leaks, the server-side global memory block must be freed.
46 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
47 * individual components are handed to win32k.sys to post to the client side. Since
48 * the server side app hands over ownership of the packed lParam when it calls
49 * PostMessage(), the packed lParam needs to be freed on the server side too.
50 * When the WM_DDE_ACK message (containing the client-side global memory handle)
51 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
52 * to the client side window proc which is expected to free/reuse it.
55 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
56 * to the memory handle, we keep track (in the server side) of all pairs of handle
57 * used (the client passes its value and the content of the memory handle), and
58 * the server stored both values (the client, and the local one, created after the
59 * content). When a ACK message is generated, the list of pair is searched for a
60 * matching pair, so that the client memory handle can be returned.
62 typedef struct tagDDEPAIR
68 static PDDEPAIR DdePairs
= NULL
;
69 static unsigned DdeNumAlloc
= 0;
70 static unsigned DdeNumUsed
= 0;
71 static CRITICAL_SECTION DdeCrst
;
74 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
78 EnterCriticalSection(&DdeCrst
);
80 /* now remember the pair of hMem on both sides */
81 if (DdeNumUsed
== DdeNumAlloc
)
87 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
88 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
92 New
= HeapAlloc(GetProcessHeap(), 0,
93 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
98 LeaveCriticalSection(&DdeCrst
);
102 /* zero out newly allocated part */
103 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
104 DdeNumAlloc
+= GROWBY
;
108 for (i
= 0; i
< DdeNumAlloc
; i
++)
110 if (NULL
== DdePairs
[i
].ServerMem
)
112 DdePairs
[i
].ClientMem
= ClientMem
;
113 DdePairs
[i
].ServerMem
= ServerMem
;
118 LeaveCriticalSection(&DdeCrst
);
123 static HGLOBAL FASTCALL
124 DdeGetPair(HGLOBAL ServerMem
)
129 EnterCriticalSection(&DdeCrst
);
130 for (i
= 0; i
< DdeNumAlloc
; i
++)
132 if (DdePairs
[i
].ServerMem
== ServerMem
)
135 DdePairs
[i
].ServerMem
= 0;
137 Ret
= DdePairs
[i
].ClientMem
;
141 LeaveCriticalSection(&DdeCrst
);
147 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
151 switch (UMMsg
->message
)
155 PKMDDELPARAM DdeLparam
;
156 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
157 if (NULL
== DdeLparam
)
163 DdeLparam
->Packed
= TRUE
;
164 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
165 &DdeLparam
->Value
.Packed
.uiLo
,
166 &DdeLparam
->Value
.Packed
.uiHi
))
170 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
172 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
173 HGLOBAL h
= DdeGetPair((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
176 GlobalFree((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
177 DdeLparam
->Value
.Packed
.uiHi
= (UINT
) h
;
180 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
184 DdeLparam
->Packed
= FALSE
;
185 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
187 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
194 PKMDDEEXECUTEDATA KMDdeExecuteData
;
197 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
198 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
201 SetLastError(ERROR_INVALID_HANDLE
);
204 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
205 if (NULL
== KMDdeExecuteData
)
207 SetLastError(ERROR_OUTOFMEMORY
);
210 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
211 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
212 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
213 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
214 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
215 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
221 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
222 PCOPYDATASTRUCT pKMCopyData
;
224 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
225 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
226 if (pKMCopyData
== NULL
)
228 SetLastError(ERROR_OUTOFMEMORY
);
232 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
233 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
234 pKMCopyData
->lpData
= pKMCopyData
+ 1;
236 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
237 pUMCopyData
->cbData
);
239 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
251 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
253 switch (KMMsg
->message
)
258 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
268 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
270 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
276 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
280 switch (UMMsg
->message
)
285 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
287 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
288 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
289 if (L
'A' == *((WCHAR
*) Class
))
291 Class
+= sizeof(WCHAR
);
292 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
296 ASSERT(L
'S' == *((WCHAR
*) Class
));
297 Class
+= sizeof(WCHAR
);
298 Cs
->lpszClass
= (LPCWSTR
) Class
;
305 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
306 if (DdeLparam
->Packed
)
308 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
309 DdeLparam
->Value
.Packed
.uiLo
,
310 DdeLparam
->Value
.Packed
.uiHi
);
314 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
321 PKMDDEEXECUTEDATA KMDdeExecuteData
;
325 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
326 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
327 if (NULL
== GlobalData
)
331 Data
= GlobalLock(GlobalData
);
334 GlobalFree(GlobalData
);
337 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
338 GlobalUnlock(GlobalData
);
339 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
341 GlobalFree(GlobalData
);
344 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
345 UMMsg
->lParam
= (LPARAM
) GlobalData
;
351 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
352 pKMCopyData
->lpData
= pKMCopyData
+ 1;
364 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
366 switch (KMMsg
->message
)
370 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
371 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
382 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
384 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
390 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
392 *UnicodeMsg
= *AnsiMsg
;
393 switch (AnsiMsg
->message
)
396 case WM_ASKCBFORMATNAME
:
398 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
399 AnsiMsg
->wParam
* sizeof(WCHAR
));
404 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
408 /* AnsiMsg->lParam is string (0-terminated) */
410 case WM_WININICHANGE
:
411 case WM_DEVMODECHANGE
:
417 UNICODE_STRING UnicodeString
;
418 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
419 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
426 UNICODE_STRING UnicodeBuffer
;
429 CREATESTRUCTW cs
; /* new structure */
430 LPCWSTR lpszName
; /* allocated Name */
431 LPCWSTR lpszClass
; /* allocated Class */
433 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
438 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
439 if (HIWORD(xs
->cs
.lpszName
))
441 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszName
);
442 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeBuffer
.Buffer
;
444 if (HIWORD(xs
->cs
.lpszClass
))
446 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszClass
);
447 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeBuffer
.Buffer
;
449 UnicodeMsg
->lParam
= (LPARAM
)xs
;
455 UNICODE_STRING UnicodeBuffer
;
456 MDICREATESTRUCTW
*cs
=
457 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
464 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
466 if (HIWORD(cs
->szClass
))
468 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szClass
);
469 cs
->szClass
= UnicodeBuffer
.Buffer
;
472 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szTitle
);
473 cs
->szTitle
= UnicodeBuffer
.Buffer
;
475 UnicodeMsg
->lParam
= (LPARAM
)cs
;
485 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
487 switch (AnsiMsg
->message
)
490 case WM_ASKCBFORMATNAME
:
492 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
497 case WM_WININICHANGE
:
498 case WM_DEVMODECHANGE
:
504 UNICODE_STRING UnicodeString
;
505 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
506 RtlFreeUnicodeString(&UnicodeString
);
513 UNICODE_STRING UnicodeString
;
516 CREATESTRUCTW cs
; /* new structure */
517 LPWSTR lpszName
; /* allocated Name */
518 LPWSTR lpszClass
; /* allocated Class */
520 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
523 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
524 RtlFreeUnicodeString(&UnicodeString
);
528 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
529 RtlFreeUnicodeString(&UnicodeString
);
531 HeapFree(GetProcessHeap(), 0, xs
);
537 UNICODE_STRING UnicodeString
;
538 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
539 if (HIWORD(cs
->szTitle
))
541 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
542 RtlFreeUnicodeString(&UnicodeString
);
544 if (HIWORD(cs
->szClass
))
546 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
547 RtlFreeUnicodeString(&UnicodeString
);
549 HeapFree(GetProcessHeap(), 0, cs
);
558 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
560 switch (AnsiMsg
->message
)
563 case WM_ASKCBFORMATNAME
:
565 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
566 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
567 if (UnicodeMsg
->wParam
> 0 &&
568 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
569 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
571 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
577 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
584 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
586 *AnsiMsg
= *UnicodeMsg
;
588 switch(UnicodeMsg
->message
)
595 UNICODE_STRING UString
;
599 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
600 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
605 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
607 RtlInitUnicodeString(&UString
, CsW
->lpszName
);
608 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
609 if (! NT_SUCCESS(Status
))
611 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
614 CsA
->lpszName
= AString
.Buffer
;
615 if (HIWORD((ULONG
)CsW
->lpszClass
) != 0)
617 RtlInitUnicodeString(&UString
, CsW
->lpszClass
);
618 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
619 if (! NT_SUCCESS(Status
))
621 RtlInitAnsiString(&AString
, CsA
->lpszName
);
622 RtlFreeAnsiString(&AString
);
623 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
626 CsA
->lpszClass
= AString
.Buffer
;
628 AnsiMsg
->lParam
= (LPARAM
)CsA
;
633 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
634 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
635 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
636 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
644 ANSI_STRING AnsiString
;
645 UNICODE_STRING UnicodeString
;
646 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
647 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
653 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
663 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
665 switch(UnicodeMsg
->message
)
669 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
675 RtlInitAnsiString(&AString
, (PSTR
) AnsiMsg
->lParam
);
676 RtlFreeAnsiString(&AString
);
685 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
686 RtlInitAnsiString(&AString
, Cs
->lpszName
);
687 RtlFreeAnsiString(&AString
);
688 if (HIWORD((ULONG
)Cs
->lpszClass
) != 0)
690 RtlInitAnsiString(&AString
, Cs
->lpszClass
);
691 RtlFreeAnsiString(&AString
);
693 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
703 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
705 switch (UnicodeMsg
->message
)
708 case WM_ASKCBFORMATNAME
:
710 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
711 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
712 if (0 < AnsiMsg
->wParam
&&
713 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
715 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
721 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
726 typedef struct tagMSGCONVERSION
735 } MSGCONVERSION
, *PMSGCONVERSION
;
737 static PMSGCONVERSION MsgConversions
= NULL
;
738 static unsigned MsgConversionNumAlloc
= 0;
739 static unsigned MsgConversionNumUsed
= 0;
740 static CRITICAL_SECTION MsgConversionCrst
;
743 MsgConversionAdd(PMSGCONVERSION Conversion
)
747 EnterCriticalSection(&MsgConversionCrst
);
749 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
753 if (NULL
!= MsgConversions
)
755 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
756 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
760 New
= HeapAlloc(GetProcessHeap(), 0,
761 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
766 LeaveCriticalSection(&MsgConversionCrst
);
769 MsgConversions
= New
;
770 /* zero out newly allocated part */
771 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
772 MsgConversionNumAlloc
+= GROWBY
;
776 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
778 if (! MsgConversions
[i
].InUse
)
780 MsgConversions
[i
] = *Conversion
;
781 MsgConversions
[i
].InUse
= TRUE
;
782 MsgConversionNumUsed
++;
786 LeaveCriticalSection(&MsgConversionCrst
);
792 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
795 PMSGCONVERSION Conversion
;
798 EnterCriticalSection(&MsgConversionCrst
);
799 for (Conversion
= MsgConversions
;
800 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
803 if (Conversion
->InUse
&&
804 ((Ansi
&& Conversion
->Ansi
) ||
805 (! Ansi
&& ! Conversion
->Ansi
)))
807 Found
= (Conversion
->FinalMsg
== Msg
);
808 if (! Found
&& CheckMsgContents
)
812 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
816 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
823 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
824 NULL
== Result
? &Dummy
: Result
);
826 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
827 NULL
== Result
? &Dummy
: Result
);
828 if (0 != Conversion
->LParamSize
)
830 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
831 &Conversion
->LParamSize
, MEM_DECOMMIT
);
833 Conversion
->InUse
= FALSE
;
834 MsgConversionNumUsed
--;
838 LeaveCriticalSection(&MsgConversionCrst
);
846 GetMessageExtraInfo(VOID
)
848 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
859 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
860 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
870 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
871 return(ThreadData
->LastMessage
.time
);
882 static DWORD ShowNotImplemented
= TRUE
;
883 if (ShowNotImplemented
)
885 DbgPrint("InSendMessage is unimplemented\n");
886 ShowNotImplemented
= FALSE
;
888 /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
901 /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
928 return NtUserSetMessageExtraInfo(lParam
);
932 IntCallWindowProcW(BOOL IsAnsiProc
,
945 UnicodeMsg
.hwnd
= hWnd
;
946 UnicodeMsg
.message
= Msg
;
947 UnicodeMsg
.wParam
= wParam
;
948 UnicodeMsg
.lParam
= lParam
;
949 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
953 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
954 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
962 return WndProc(hWnd
, Msg
, wParam
, lParam
);
966 static LRESULT FASTCALL
967 IntCallWindowProcA(BOOL IsAnsiProc
,
980 return WndProc(hWnd
, Msg
, wParam
, lParam
);
985 AnsiMsg
.message
= Msg
;
986 AnsiMsg
.wParam
= wParam
;
987 AnsiMsg
.lParam
= lParam
;
988 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
992 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
993 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
994 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1007 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1014 WndProcHandle wphData
;
1016 if (lpPrevWndFunc
== NULL
)
1017 lpPrevWndFunc
= (WNDPROC
)NtUserGetWindowLong(hWnd
, GWL_WNDPROC
, FALSE
);
1019 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1022 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1026 return IntCallWindowProcA(! wphData
.IsUnicode
, wphData
.WindowProc
,
1027 hWnd
, Msg
, wParam
, lParam
);
1036 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1043 WndProcHandle wphData
;
1045 IsHandle
= NtUserDereferenceWndProcHandle(lpPrevWndFunc
,&wphData
);
1048 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1052 return IntCallWindowProcW(! wphData
.IsUnicode
, wphData
.WindowProc
,
1053 hWnd
, Msg
, wParam
, lParam
);
1062 DispatchMessageA(CONST MSG
*lpmsg
)
1064 NTUSERDISPATCHMESSAGEINFO Info
;
1069 Result
= NtUserDispatchMessage(&Info
);
1070 if (! Info
.HandledByKernel
)
1072 /* We need to send the message ourselves */
1073 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1074 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1076 MsgConversionCleanup(lpmsg
, TRUE
, TRUE
, &Result
);
1086 DispatchMessageW(CONST MSG
*lpmsg
)
1088 NTUSERDISPATCHMESSAGEINFO Info
;
1093 Result
= NtUserDispatchMessage(&Info
);
1094 if (! Info
.HandledByKernel
)
1096 /* We need to send the message ourselves */
1097 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, Info
.Msg
.hwnd
,
1098 Info
.Msg
.message
, Info
.Msg
.wParam
, Info
.Msg
.lParam
);
1100 MsgConversionCleanup(lpmsg
, FALSE
, TRUE
, &Result
);
1110 GetMessageA(LPMSG lpMsg
,
1116 MSGCONVERSION Conversion
;
1117 NTUSERGETMESSAGEINFO Info
;
1118 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1120 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1121 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1122 if (-1 == (int) Res
)
1126 Conversion
.LParamSize
= Info
.LParamSize
;
1127 Conversion
.KMMsg
= Info
.Msg
;
1129 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1133 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1135 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1138 *lpMsg
= Conversion
.AnsiMsg
;
1139 Conversion
.Ansi
= TRUE
;
1140 Conversion
.FinalMsg
= lpMsg
;
1141 MsgConversionAdd(&Conversion
);
1142 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1144 ThreadData
->LastMessage
= Info
.Msg
;
1155 GetMessageW(LPMSG lpMsg
,
1161 MSGCONVERSION Conversion
;
1162 NTUSERGETMESSAGEINFO Info
;
1163 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1165 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1166 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1167 if (-1 == (int) Res
)
1171 Conversion
.LParamSize
= Info
.LParamSize
;
1172 Conversion
.KMMsg
= Info
.Msg
;
1174 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1178 *lpMsg
= Conversion
.UnicodeMsg
;
1179 Conversion
.Ansi
= FALSE
;
1180 Conversion
.FinalMsg
= lpMsg
;
1181 MsgConversionAdd(&Conversion
);
1182 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1184 ThreadData
->LastMessage
= Info
.Msg
;
1195 PeekMessageA(LPMSG lpMsg
,
1202 MSGCONVERSION Conversion
;
1203 NTUSERGETMESSAGEINFO Info
;
1204 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1206 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1207 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1208 if (-1 == (int) Res
|| ! Res
)
1212 Conversion
.LParamSize
= Info
.LParamSize
;
1213 Conversion
.KMMsg
= Info
.Msg
;
1215 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1219 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1221 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1224 *lpMsg
= Conversion
.AnsiMsg
;
1225 Conversion
.Ansi
= TRUE
;
1226 Conversion
.FinalMsg
= lpMsg
;
1227 MsgConversionAdd(&Conversion
);
1228 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1230 ThreadData
->LastMessage
= Info
.Msg
;
1250 MSGCONVERSION Conversion
;
1251 NTUSERGETMESSAGEINFO Info
;
1252 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1254 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1255 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1256 if (-1 == (int) Res
|| ! Res
)
1260 Conversion
.LParamSize
= Info
.LParamSize
;
1261 Conversion
.KMMsg
= Info
.Msg
;
1263 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1267 *lpMsg
= Conversion
.UnicodeMsg
;
1268 Conversion
.Ansi
= FALSE
;
1269 Conversion
.FinalMsg
= lpMsg
;
1270 MsgConversionAdd(&Conversion
);
1271 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1273 ThreadData
->LastMessage
= Info
.Msg
;
1296 AnsiMsg
.message
= Msg
;
1297 AnsiMsg
.wParam
= wParam
;
1298 AnsiMsg
.lParam
= lParam
;
1299 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1304 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
1306 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1309 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1310 KMMsg
.wParam
, KMMsg
.lParam
);
1311 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1312 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1333 UMMsg
.message
= Msg
;
1334 UMMsg
.wParam
= wParam
;
1335 UMMsg
.lParam
= lParam
;
1336 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1340 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1341 KMMsg
.wParam
, KMMsg
.lParam
);
1342 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1356 (void) NtUserPostMessage(NULL
, WM_QUIT
, nExitCode
, 0);
1371 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1386 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1394 SendMessageW(HWND Wnd
,
1400 NTUSERSENDMESSAGEINFO Info
;
1404 UMMsg
.message
= Msg
;
1405 UMMsg
.wParam
= wParam
;
1406 UMMsg
.lParam
= lParam
;
1407 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
1412 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1413 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1414 if (! Info
.HandledByKernel
)
1416 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1417 /* We need to send the message ourselves */
1418 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UMMsg
.hwnd
, UMMsg
.message
,
1419 UMMsg
.wParam
, UMMsg
.lParam
);
1421 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
1434 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1439 NTUSERSENDMESSAGEINFO Info
;
1442 AnsiMsg
.message
= Msg
;
1443 AnsiMsg
.wParam
= wParam
;
1444 AnsiMsg
.lParam
= lParam
;
1445 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1450 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
1452 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1456 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1457 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1458 if (! Info
.HandledByKernel
)
1460 /* We need to send the message ourselves */
1463 /* Ansi message and Ansi window proc, that's easy. Clean up
1464 the Unicode message though */
1465 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1466 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1467 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Wnd
, Msg
, wParam
, lParam
);
1471 /* Unicode winproc. Although we started out with an Ansi message we
1472 already converted it to Unicode for the kernel call. Reuse that
1473 message to avoid another conversion */
1474 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1475 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1476 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1482 /* Message sent by kernel. Convert back to Ansi */
1483 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
1484 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1498 SendMessageCallbackA(
1503 SENDASYNCPROC lpCallBack
,
1506 return NtUserSendMessageCallback(
1521 SendMessageCallbackW(
1526 SENDASYNCPROC lpCallBack
,
1529 return NtUserSendMessageCallback(
1544 SendMessageTimeoutA(
1551 PDWORD_PTR lpdwResult
)
1556 NTUSERSENDMESSAGEINFO Info
;
1558 AnsiMsg
.hwnd
= hWnd
;
1559 AnsiMsg
.message
= Msg
;
1560 AnsiMsg
.wParam
= wParam
;
1561 AnsiMsg
.lParam
= lParam
;
1562 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1568 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
1569 UcMsg
.wParam
, UcMsg
.lParam
,
1570 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
1575 if (! Info
.HandledByKernel
)
1577 /* We need to send the message ourselves */
1580 /* Ansi message and Ansi window proc, that's easy. Clean up
1581 the Unicode message though */
1582 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1583 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1587 /* Unicode winproc. Although we started out with an Ansi message we
1588 already converted it to Unicode for the kernel call. Reuse that
1589 message to avoid another conversion */
1590 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1591 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1592 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1598 *lpdwResult
= Result
;
1603 /* Message sent by kernel. Convert back to Ansi */
1604 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1619 SendMessageTimeoutW(
1626 PDWORD_PTR lpdwResult
)
1628 NTUSERSENDMESSAGEINFO Info
;
1632 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
1634 if (! Info
.HandledByKernel
)
1636 /* We need to send the message ourselves */
1637 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1639 *lpdwResult
= Result
;
1683 TranslateMessageEx(CONST MSG
*lpMsg
, DWORD unk
)
1685 return(NtUserTranslateMessage((LPMSG
)lpMsg
, (HKL
)unk
));
1693 TranslateMessage(CONST MSG
*lpMsg
)
1695 return(TranslateMessageEx((LPMSG
)lpMsg
, 0));
1706 return NtUserWaitMessage();
1714 RegisterWindowMessageA(LPCSTR lpString
)
1716 UNICODE_STRING String
;
1720 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
1725 Atom
= NtUserRegisterWindowMessage(&String
);
1726 RtlFreeUnicodeString(&String
);
1735 RegisterWindowMessageW(LPCWSTR lpString
)
1737 UNICODE_STRING String
;
1739 RtlInitUnicodeString(&String
, lpString
);
1740 return(NtUserRegisterWindowMessage(&String
));
1747 SetCapture(HWND hWnd
)
1749 return(NtUserSetCapture(hWnd
));
1758 return(NtUserGetCapture());
1765 ReleaseCapture(VOID
)
1767 NtUserSetCapture(NULL
);
1777 RealGetQueueStatus(UINT flags
)
1780 WORD changed_bits
, wake_bits
;
1782 #if 0 /* wine stuff. don't know what it does... */
1784 /* check for pending X events */
1785 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1786 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1789 ret
= NtUserGetQueueStatus(TRUE
/*ClearChanges*/);
1791 changed_bits
= LOWORD(ret
);
1792 wake_bits
= HIWORD(ret
);
1794 return MAKELONG(changed_bits
& flags
, wake_bits
& flags
);
1801 BOOL STDCALL
GetInputState(VOID
)
1806 #if 0 /* wine stuff. don't know what it does... */
1808 /* check for pending X events */
1809 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
1810 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
1813 ret
= NtUserGetQueueStatus(FALSE
/*ClearChanges*/);
1815 wake_bits
= HIWORD(ret
);
1817 return wake_bits
& (QS_KEY
| QS_MOUSEBUTTON
);
1822 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
1824 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
1827 /* Make sure we don't try to access mem beyond what we were given */
1828 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1830 return STATUS_INFO_LENGTH_MISMATCH
;
1833 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
1834 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
1835 KMMsg
.message
= CallbackArgs
->Msg
;
1836 KMMsg
.wParam
= CallbackArgs
->wParam
;
1837 /* Check if lParam is really a pointer and adjust it if it is */
1838 if (0 <= CallbackArgs
->lParamBufferSize
)
1840 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
1841 + CallbackArgs
->lParamBufferSize
)
1843 return STATUS_INFO_LENGTH_MISMATCH
;
1845 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
1849 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
1851 return STATUS_INFO_LENGTH_MISMATCH
;
1853 KMMsg
.lParam
= CallbackArgs
->lParam
;
1856 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
1858 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
1859 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
1862 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
1866 CallbackArgs
->Result
= IntCallWindowProcW(CallbackArgs
->IsAnsiProc
, CallbackArgs
->Proc
,
1867 UMMsg
.hwnd
, UMMsg
.message
,
1868 UMMsg
.wParam
, UMMsg
.lParam
);
1870 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
1874 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
1880 BOOL STDCALL
SetMessageQueue(int cMessagesMax
)
1882 /* Function does nothing on 32 bit windows */
1885 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
1886 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
1888 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
1890 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
1891 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
1892 RealGetQueueStatusProc RealGetQueueStatus
;
1893 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
1894 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
1898 RealMsgWaitForMultipleObjectsEx(
1900 CONST HANDLE
*pHandles
,
1901 DWORD dwMilliseconds
,
1905 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
1907 CRITICAL_SECTION gcsMPH
;
1908 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
1909 DWORD gcLoadMPH
= 0;
1910 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
1911 //NtUserRealInternalGetMessage,
1912 //NtUserRealInternalWaitMessageEx,
1914 RealMsgWaitForMultipleObjectsEx
1917 DWORD gfMessagePumpHook
= 0;
1919 BOOL WINAPI
IsInsideMessagePumpHook()
1921 if(!gfMessagePumpHook
)
1924 /* This code checks if we're inside SendMessage. */
1926 /* Since our TEB doesnt match that of real windows, testing this value is useless until we know what it does
1927 PUCHAR NtTeb = (PUCHAR)NtCurrentTeb();
1929 if(!*(PLONG*)&NtTeb[0x708])
1932 if(**(PLONG*)&NtTeb[0x708] <= 0)
1939 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
1941 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
1942 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
1943 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
1944 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
1945 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
1948 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
1950 EnterCriticalSection(&gcsMPH
);
1952 SetLastError(ERROR_INVALID_PARAMETER
);
1953 LeaveCriticalSection(&gcsMPH
);
1957 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
1959 ResetMessagePumpHook(&Addresses
);
1960 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
1961 LeaveCriticalSection(&gcsMPH
);
1964 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
1966 if(gpfnInitMPH
!= Hook
) {
1967 LeaveCriticalSection(&gcsMPH
);
1971 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
1972 LeaveCriticalSection(&gcsMPH
);
1976 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
1978 LeaveCriticalSection(&gcsMPH
);
1982 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
1984 EnterCriticalSection(&gcsMPH
);
1986 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
1989 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
1990 gpfnInitMPH(TRUE
, NULL
);
1991 ResetMessagePumpHook(&gmph
);
1994 LeaveCriticalSection(&gcsMPH
);
1998 LeaveCriticalSection(&gcsMPH
);
2002 DWORD WINAPI
GetQueueStatus(UINT flags
)
2004 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2008 * @name RealMsgWaitForMultipleObjectsEx
2010 * Wait either for either message arrival or for one of the passed events
2014 * Number of handles in the pHandles array.
2016 * Handles of events to wait for.
2017 * @param dwMilliseconds
2020 * Mask specifying on which message events we should wakeup.
2022 * Wait type (see MWMO_* constants).
2028 RealMsgWaitForMultipleObjectsEx(
2030 const HANDLE
*pHandles
,
2031 DWORD dwMilliseconds
,
2035 LPHANDLE RealHandles
;
2036 HANDLE MessageQueueHandle
;
2039 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2041 SetLastError(ERROR_INVALID_PARAMETER
);
2046 if (dwFlags & MWMO_INPUTAVAILABLE)
2048 RealGetQueueStatus(dwWakeMask);
2052 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2053 if (MessageQueueHandle
== NULL
)
2055 SetLastError(0); /* ? */
2059 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2060 if (RealHandles
== NULL
)
2062 NtUserMsqClearWakeMask();
2063 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2067 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2068 RealHandles
[nCount
] = MessageQueueHandle
;
2070 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2071 dwFlags
& MWMO_WAITALL
,
2072 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2074 HeapFree(GetProcessHeap(), 0, RealHandles
);
2075 NtUserMsqClearWakeMask();
2084 MsgWaitForMultipleObjectsEx(
2086 CONST HANDLE
*lpHandles
,
2087 DWORD dwMilliseconds
,
2091 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2098 MsgWaitForMultipleObjects(
2100 CONST HANDLE
*lpHandles
,
2102 DWORD dwMilliseconds
,
2105 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2106 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2110 BOOL FASTCALL
MessageInit()
2112 InitializeCriticalSection(&DdeCrst
);
2113 InitializeCriticalSection(&MsgConversionCrst
);
2118 /***********************************************************************
2121 * Convert the wparam of an ASCII message to Unicode.
2124 map_wparam_AtoW( UINT message
, WPARAM wparam
)
2129 case EM_SETPASSWORDCHAR
:
2133 case WM_SYSDEADCHAR
:
2138 ch
[0] = (wparam
& 0xff);
2139 ch
[1] = (wparam
>> 8);
2140 MultiByteToWideChar(CP_ACP
, 0, ch
, 2, wch
, 2);
2141 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
2148 ch
[0] = (wparam
>> 8);
2149 ch
[1] = (wparam
& 0xff);
2150 if (ch
[0]) MultiByteToWideChar(CP_ACP
, 0, ch
, 2, &wch
, 1);
2151 else MultiByteToWideChar(CP_ACP
, 0, &ch
[1], 1, &wch
, 1);
2152 wparam
= MAKEWPARAM( wch
, HIWORD(wparam
) );
2163 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
2166 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
2167 return IsDialogMessageW( hwndDlg
, &msg
);