2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: lib/user32/windows/message.c
6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
13 #include <wine/debug.h>
14 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
16 /* DDE message exchange
18 * - Session initialization
19 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
20 * this message contains a pair of global atoms, the Application and Topic atoms.
21 * The client must destroy the atoms.
22 * Server window proc handles the WM_DDE_INITIATE message and if the Application
23 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
24 * of the reply message contains another pair of global atoms (Application and
25 * Topic again), which must be destroyed by the server.
28 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
29 * is a global memory handle containing the string to execute. After the command has
30 * been executed the server posts a WM_DDE_ACK message to the client, which contains
31 * a packed lParam which in turn contains that global memory handle. The client takes
32 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
33 * it and the global memory handle.
34 * This might work nice and easy in Win3.1, but things are more complicated for NT.
35 * Global memory handles in NT are not really global, they're still local to the
36 * process. So, what happens under the hood is that PostMessage must handle the
37 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
38 * area, repack that into a new structure together with the original memory handle
39 * and pass that off to the win32k. Win32k will marshall that data over to the target
40 * (server) process where it will be unpacked and stored in a newly allocated global
41 * memory area. The handle of that area will then be sent to the window proc, after
42 * storing it together with the "original" (client) handle in a table.
43 * The server will eventually post the WM_DDE_ACK response, containing the global
44 * memory handle it received. PostMessage must then lookup that memory handle (only
45 * valid in the server process) and replace it with the corresponding client memory
46 * handle. To avoid memory leaks, the server-side global memory block must be freed.
47 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
48 * individual components are handed to win32k.sys to post to the client side. Since
49 * the server side app hands over ownership of the packed lParam when it calls
50 * PostMessage(), the packed lParam needs to be freed on the server side too.
51 * When the WM_DDE_ACK message (containing the client-side global memory handle)
52 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
53 * to the client side window proc which is expected to free/reuse it.
56 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
57 * to the memory handle, we keep track (in the server side) of all pairs of handle
58 * used (the client passes its value and the content of the memory handle), and
59 * the server stored both values (the client, and the local one, created after the
60 * content). When a ACK message is generated, the list of pair is searched for a
61 * matching pair, so that the client memory handle can be returned.
63 typedef struct tagDDEPAIR
69 static PDDEPAIR DdePairs
= NULL
;
70 static unsigned DdeNumAlloc
= 0;
71 static unsigned DdeNumUsed
= 0;
72 static CRITICAL_SECTION DdeCrst
;
75 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
79 EnterCriticalSection(&DdeCrst
);
81 /* now remember the pair of hMem on both sides */
82 if (DdeNumUsed
== DdeNumAlloc
)
88 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
89 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
93 New
= HeapAlloc(GetProcessHeap(), 0,
94 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
99 LeaveCriticalSection(&DdeCrst
);
103 /* zero out newly allocated part */
104 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
105 DdeNumAlloc
+= GROWBY
;
109 for (i
= 0; i
< DdeNumAlloc
; i
++)
111 if (NULL
== DdePairs
[i
].ServerMem
)
113 DdePairs
[i
].ClientMem
= ClientMem
;
114 DdePairs
[i
].ServerMem
= ServerMem
;
119 LeaveCriticalSection(&DdeCrst
);
124 static HGLOBAL FASTCALL
125 DdeGetPair(HGLOBAL ServerMem
)
130 EnterCriticalSection(&DdeCrst
);
131 for (i
= 0; i
< DdeNumAlloc
; i
++)
133 if (DdePairs
[i
].ServerMem
== ServerMem
)
136 DdePairs
[i
].ServerMem
= 0;
138 Ret
= DdePairs
[i
].ClientMem
;
142 LeaveCriticalSection(&DdeCrst
);
148 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
152 switch (UMMsg
->message
)
156 PKMDDELPARAM DdeLparam
;
157 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
158 if (NULL
== DdeLparam
)
164 DdeLparam
->Packed
= TRUE
;
165 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
166 (PUINT_PTR
)&DdeLparam
->Value
.Packed
.uiLo
,
167 (PUINT_PTR
)&DdeLparam
->Value
.Packed
.uiHi
))
171 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
173 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
174 HGLOBAL h
= DdeGetPair((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
177 GlobalFree((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
178 DdeLparam
->Value
.Packed
.uiHi
= (UINT_PTR
) h
;
181 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
185 DdeLparam
->Packed
= FALSE
;
186 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
188 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
195 PKMDDEEXECUTEDATA KMDdeExecuteData
;
198 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
199 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
202 SetLastError(ERROR_INVALID_HANDLE
);
205 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
206 if (NULL
== KMDdeExecuteData
)
208 SetLastError(ERROR_OUTOFMEMORY
);
211 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
212 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
213 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
214 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
215 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
216 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
222 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
223 PCOPYDATASTRUCT pKMCopyData
;
225 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
226 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
227 if (pKMCopyData
== NULL
)
229 SetLastError(ERROR_OUTOFMEMORY
);
233 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
234 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
235 pKMCopyData
->lpData
= pKMCopyData
+ 1;
237 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
238 pUMCopyData
->cbData
);
240 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
252 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
254 switch (KMMsg
->message
)
259 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
269 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
271 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
277 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
281 switch (UMMsg
->message
)
286 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
288 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
289 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
290 if (L
'A' == *((WCHAR
*) Class
))
292 Class
+= sizeof(WCHAR
);
293 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
297 ASSERT(L
'S' == *((WCHAR
*) Class
));
298 Class
+= sizeof(WCHAR
);
299 Cs
->lpszClass
= (LPCWSTR
) Class
;
306 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
307 if (DdeLparam
->Packed
)
309 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
310 DdeLparam
->Value
.Packed
.uiLo
,
311 DdeLparam
->Value
.Packed
.uiHi
);
315 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
322 PKMDDEEXECUTEDATA KMDdeExecuteData
;
326 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
327 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
328 if (NULL
== GlobalData
)
332 Data
= GlobalLock(GlobalData
);
335 GlobalFree(GlobalData
);
338 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
339 GlobalUnlock(GlobalData
);
340 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
342 GlobalFree(GlobalData
);
345 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
346 UMMsg
->lParam
= (LPARAM
) GlobalData
;
352 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
353 pKMCopyData
->lpData
= pKMCopyData
+ 1;
365 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
367 switch (KMMsg
->message
)
371 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
372 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
383 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
385 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
391 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
393 UNICODE_STRING UnicodeString
;
395 *UnicodeMsg
= *AnsiMsg
;
397 switch (AnsiMsg
->message
)
400 case WM_ASKCBFORMATNAME
:
402 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
403 AnsiMsg
->wParam
* sizeof(WCHAR
));
408 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
412 /* AnsiMsg->lParam is string (0-terminated) */
414 case WM_WININICHANGE
:
415 case WM_DEVMODECHANGE
:
421 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
422 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
427 case LB_ADDSTRING_LOWER
:
428 case LB_ADDSTRING_UPPER
:
429 case LB_INSERTSTRING
:
430 case LB_INSERTSTRING_UPPER
:
431 case LB_INSERTSTRING_LOWER
:
433 case LB_FINDSTRINGEXACT
:
434 case LB_SELECTSTRING
:
436 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
437 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
438 (dwStyle
& LBS_HASSTRINGS
))
440 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
441 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
447 case CB_INSERTSTRING
:
449 case CB_FINDSTRINGEXACT
:
450 case CB_SELECTSTRING
:
452 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
453 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
454 (dwStyle
& CBS_HASSTRINGS
))
456 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
457 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
467 CREATESTRUCTW cs
; /* new structure */
468 LPCWSTR lpszName
; /* allocated Name */
469 LPCWSTR lpszClass
; /* allocated Class */
472 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
477 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
478 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
480 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
481 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
483 if (!IS_ATOM(xs
->cs
.lpszClass
))
485 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
486 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
488 UnicodeMsg
->lParam
= (LPARAM
)xs
;
494 MDICREATESTRUCTW
*cs
=
495 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
502 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
504 if (!IS_ATOM(cs
->szClass
))
506 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
507 cs
->szClass
= UnicodeString
.Buffer
;
510 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
511 cs
->szTitle
= UnicodeString
.Buffer
;
513 UnicodeMsg
->lParam
= (LPARAM
)cs
;
523 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
525 UNICODE_STRING UnicodeString
;
527 switch (AnsiMsg
->message
)
530 case WM_ASKCBFORMATNAME
:
532 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
537 case WM_WININICHANGE
:
538 case WM_DEVMODECHANGE
:
544 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
545 RtlFreeUnicodeString(&UnicodeString
);
550 case LB_ADDSTRING_LOWER
:
551 case LB_ADDSTRING_UPPER
:
552 case LB_INSERTSTRING
:
553 case LB_INSERTSTRING_UPPER
:
554 case LB_INSERTSTRING_LOWER
:
556 case LB_FINDSTRINGEXACT
:
557 case LB_SELECTSTRING
:
559 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
560 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
561 (dwStyle
& LBS_HASSTRINGS
))
563 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
564 RtlFreeUnicodeString(&UnicodeString
);
570 case CB_INSERTSTRING
:
572 case CB_FINDSTRINGEXACT
:
573 case CB_SELECTSTRING
:
575 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
576 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
577 (dwStyle
& CBS_HASSTRINGS
))
579 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
580 RtlFreeUnicodeString(&UnicodeString
);
590 CREATESTRUCTW cs
; /* new structure */
591 LPWSTR lpszName
; /* allocated Name */
592 LPWSTR lpszClass
; /* allocated Class */
595 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
598 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
599 RtlFreeUnicodeString(&UnicodeString
);
603 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
604 RtlFreeUnicodeString(&UnicodeString
);
606 HeapFree(GetProcessHeap(), 0, xs
);
612 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
613 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
614 RtlFreeUnicodeString(&UnicodeString
);
615 if (!IS_ATOM(cs
->szClass
))
617 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
618 RtlFreeUnicodeString(&UnicodeString
);
620 HeapFree(GetProcessHeap(), 0, cs
);
630 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
632 switch (AnsiMsg
->message
)
635 case WM_ASKCBFORMATNAME
:
637 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
638 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
639 if (UnicodeMsg
->wParam
> 0 &&
640 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
641 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
643 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
649 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
656 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
658 ANSI_STRING AnsiString
;
659 UNICODE_STRING UnicodeString
;
661 *AnsiMsg
= *UnicodeMsg
;
663 switch(UnicodeMsg
->message
)
672 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
673 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
678 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
680 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
681 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
682 if (! NT_SUCCESS(Status
))
684 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
687 CsA
->lpszName
= AnsiString
.Buffer
;
688 if (HIWORD((ULONG_PTR
)CsW
->lpszClass
) != 0)
690 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
691 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
692 if (! NT_SUCCESS(Status
))
694 RtlInitAnsiString(&AnsiString
, CsA
->lpszName
);
695 RtlFreeAnsiString(&AnsiString
);
696 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
699 CsA
->lpszClass
= AnsiString
.Buffer
;
701 AnsiMsg
->lParam
= (LPARAM
)CsA
;
706 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
707 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
708 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
709 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
720 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
721 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
727 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
732 case LB_ADDSTRING_LOWER
:
733 case LB_ADDSTRING_UPPER
:
734 case LB_INSERTSTRING
:
735 case LB_INSERTSTRING_UPPER
:
736 case LB_INSERTSTRING_LOWER
:
738 case LB_FINDSTRINGEXACT
:
739 case LB_SELECTSTRING
:
741 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
742 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
743 (dwStyle
& LBS_HASSTRINGS
))
745 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
746 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
752 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
758 case CB_INSERTSTRING
:
760 case CB_FINDSTRINGEXACT
:
761 case CB_SELECTSTRING
:
763 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
764 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
765 (dwStyle
& CBS_HASSTRINGS
))
767 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
768 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
774 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
781 MDICREATESTRUCTA
*cs
=
782 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
789 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
791 if (!IS_ATOM(cs
->szClass
))
793 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
794 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
800 cs
->szClass
= AnsiString
.Buffer
;
803 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
804 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
808 if (!IS_ATOM(cs
->szClass
))
810 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
811 RtlFreeAnsiString(&AnsiString
);
815 cs
->szTitle
= AnsiString
.Buffer
;
817 AnsiMsg
->lParam
= (LPARAM
)cs
;
827 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
829 ANSI_STRING AnsiString
;
831 switch(UnicodeMsg
->message
)
835 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
840 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
841 RtlFreeAnsiString(&AnsiString
);
849 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
850 RtlInitAnsiString(&AnsiString
, Cs
->lpszName
);
851 RtlFreeAnsiString(&AnsiString
);
852 if (HIWORD((ULONG_PTR
)Cs
->lpszClass
) != 0)
854 RtlInitAnsiString(&AnsiString
, Cs
->lpszClass
);
855 RtlFreeAnsiString(&AnsiString
);
857 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
862 case LB_ADDSTRING_LOWER
:
863 case LB_ADDSTRING_UPPER
:
864 case LB_INSERTSTRING
:
865 case LB_INSERTSTRING_UPPER
:
866 case LB_INSERTSTRING_LOWER
:
868 case LB_FINDSTRINGEXACT
:
869 case LB_SELECTSTRING
:
871 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
872 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
873 (dwStyle
& LBS_HASSTRINGS
))
875 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
876 RtlFreeAnsiString(&AnsiString
);
882 case CB_INSERTSTRING
:
884 case CB_FINDSTRINGEXACT
:
885 case CB_SELECTSTRING
:
887 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
888 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
889 (dwStyle
& CBS_HASSTRINGS
))
891 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
892 RtlFreeAnsiString(&AnsiString
);
899 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
900 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
901 RtlFreeAnsiString(&AnsiString
);
902 if (!IS_ATOM(cs
->szClass
))
904 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
905 RtlFreeAnsiString(&AnsiString
);
907 HeapFree(GetProcessHeap(), 0, cs
);
918 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
920 switch (UnicodeMsg
->message
)
923 case WM_ASKCBFORMATNAME
:
925 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
926 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
927 if (0 < AnsiMsg
->wParam
&&
928 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
930 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
936 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
941 typedef struct tagMSGCONVERSION
950 } MSGCONVERSION
, *PMSGCONVERSION
;
952 static PMSGCONVERSION MsgConversions
= NULL
;
953 static unsigned MsgConversionNumAlloc
= 0;
954 static unsigned MsgConversionNumUsed
= 0;
955 static CRITICAL_SECTION MsgConversionCrst
;
958 MsgConversionAdd(PMSGCONVERSION Conversion
)
962 EnterCriticalSection(&MsgConversionCrst
);
964 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
968 if (NULL
!= MsgConversions
)
970 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
971 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
975 New
= HeapAlloc(GetProcessHeap(), 0,
976 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
981 LeaveCriticalSection(&MsgConversionCrst
);
984 MsgConversions
= New
;
985 /* zero out newly allocated part */
986 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
987 MsgConversionNumAlloc
+= GROWBY
;
991 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
993 if (! MsgConversions
[i
].InUse
)
995 MsgConversions
[i
] = *Conversion
;
996 MsgConversions
[i
].InUse
= TRUE
;
997 MsgConversionNumUsed
++;
1001 LeaveCriticalSection(&MsgConversionCrst
);
1006 static void FASTCALL
1007 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
1010 PMSGCONVERSION Conversion
;
1013 EnterCriticalSection(&MsgConversionCrst
);
1014 for (Conversion
= MsgConversions
;
1015 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
1018 if (Conversion
->InUse
&&
1019 ((Ansi
&& Conversion
->Ansi
) ||
1020 (! Ansi
&& ! Conversion
->Ansi
)))
1022 Found
= (Conversion
->FinalMsg
== Msg
);
1023 if (! Found
&& CheckMsgContents
)
1027 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
1031 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
1038 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
1039 NULL
== Result
? &Dummy
: Result
);
1041 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
1042 NULL
== Result
? &Dummy
: Result
);
1043 if (0 != Conversion
->LParamSize
)
1045 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
1046 &Conversion
->LParamSize
, MEM_DECOMMIT
);
1048 Conversion
->InUse
= FALSE
;
1049 MsgConversionNumUsed
--;
1053 LeaveCriticalSection(&MsgConversionCrst
);
1061 GetMessageExtraInfo(VOID
)
1063 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
1074 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1075 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
1083 GetMessageTime(VOID
)
1085 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1086 return(ThreadData
->LastMessage
.time
);
1087 // return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME);
1098 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1099 // FIXME("ISM %x\n",pcti);
1102 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1107 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1119 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1120 // FIXME("ISMEX %x\n",pcti);
1121 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1122 return ISMEX_NOSEND
;
1124 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1136 return NtUserCallOneParam(lResult
, ONEPARAM_ROUTINE_REPLYMESSAGE
);
1145 SetMessageExtraInfo(
1148 return NtUserSetMessageExtraInfo(lParam
);
1152 IntCallWindowProcW(BOOL IsAnsiProc
,
1162 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1163 LRESULT Result
= 0, PreResult
= 0;
1166 if (WndProc
== NULL
)
1168 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1173 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1177 Hook
= BeginIfHookedUserApiHook();
1181 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1183 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1188 UnicodeMsg
.hwnd
= hWnd
;
1189 UnicodeMsg
.message
= Msg
;
1190 UnicodeMsg
.wParam
= wParam
;
1191 UnicodeMsg
.lParam
= lParam
;
1192 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
1197 if (Hook
&& MsgOverride
)
1202 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1204 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1212 if (PreResult
) goto Exit
;
1214 _SEH2_TRY
// wine does this.
1216 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1223 if (Hook
&& MsgOverride
)
1228 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1230 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1232 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1238 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1245 if (Hook
&& MsgOverride
)
1250 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1252 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1254 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1260 if (PreResult
) goto Exit
;
1264 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1266 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1271 if (Hook
&& MsgOverride
)
1276 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1278 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1280 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1288 if (Hook
) EndUserApiHook();
1292 static LRESULT FASTCALL
1293 IntCallWindowProcA(BOOL IsAnsiProc
,
1303 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1304 LRESULT Result
= 0, PreResult
= 0;
1307 if (WndProc
== NULL
)
1309 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1314 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1318 Hook
= BeginIfHookedUserApiHook();
1322 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1324 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1329 if (Hook
&& MsgOverride
)
1334 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1336 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1338 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1344 if (PreResult
) goto Exit
;
1348 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1355 if (Hook
&& MsgOverride
)
1360 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1362 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1372 AnsiMsg
.hwnd
= hWnd
;
1373 AnsiMsg
.message
= Msg
;
1374 AnsiMsg
.wParam
= wParam
;
1375 AnsiMsg
.lParam
= lParam
;
1376 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
1381 if (Hook
&& MsgOverride
)
1386 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1388 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1396 if (PreResult
) goto Exit
;
1400 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1401 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1408 if (Hook
&& MsgOverride
)
1413 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1415 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1417 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1423 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1430 if (Hook
) EndUserApiHook();
1435 static LRESULT WINAPI
1436 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1442 Class
= DesktopPtrToUser(Wnd
->pcls
);
1445 This is the message exchange for user32. If there's a need to monitor messages,
1448 TRACE("HWND 0x%x, MSG %d, WPARAM 0x%x, LPARAM 0x%x, Ansi &d\n",hWnd
,Msg
,wParam
,lParam
,Ansi
);
1449 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1450 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1454 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1455 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1459 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1460 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1467 IsAnsi
= !Wnd
->Unicode
;
1468 WndProc
= Wnd
->lpfnWndProc
;
1473 IsAnsi
= !Wnd
->Unicode
;
1474 WndProc
= Wnd
->lpfnWndProc
;
1477 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1481 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1483 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1491 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1498 PCALLPROCDATA CallProc
;
1500 if (lpPrevWndFunc
== NULL
)
1502 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1506 pWnd
= ValidateHwnd(hWnd
);
1508 if (!IsCallProcHandle(lpPrevWndFunc
))
1509 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1512 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1513 if (CallProc
!= NULL
)
1515 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1516 CallProc
->pfnClientPrevious
,
1525 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1536 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1543 PCALLPROCDATA CallProc
;
1545 /* FIXME - can the first parameter be NULL? */
1546 if (lpPrevWndFunc
== NULL
)
1548 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1552 pWnd
= ValidateHwnd(hWnd
);
1554 if (!IsCallProcHandle(lpPrevWndFunc
))
1555 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1558 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1559 if (CallProc
!= NULL
)
1561 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1562 CallProc
->pfnClientPrevious
,
1571 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1582 DispatchMessageA(CONST MSG
*lpmsg
)
1588 if (lpmsg
->hwnd
!= NULL
)
1590 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1591 if (!Wnd
|| Wnd
->head
.pti
!= GetW32ThreadInfo())
1597 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1599 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1601 if ( lpmsg
->message
== WM_SYSTIMER
)
1602 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1604 _SEH2_TRY
// wine does this.
1606 Ret
= WndProc(lpmsg
->hwnd
,
1611 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1617 else if (Wnd
!= NULL
)
1619 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1621 Ret
= IntCallMessageProc(Wnd
,
1630 if (!MsgiAnsiToUnicodeMessage(&UnicodeMsg
, (LPMSG
)lpmsg
))
1635 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1637 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1651 DispatchMessageW(CONST MSG
*lpmsg
)
1656 if (lpmsg
->hwnd
!= NULL
)
1658 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1659 if (!Wnd
|| Wnd
->head
.pti
!= GetW32ThreadInfo())
1665 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1667 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1669 if ( lpmsg
->message
== WM_SYSTIMER
)
1670 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1674 Ret
= WndProc(lpmsg
->hwnd
,
1679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1684 else if (Wnd
!= NULL
)
1686 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1688 Ret
= IntCallMessageProc(Wnd
,
1696 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
1707 GetMessageA(LPMSG lpMsg
,
1713 MSGCONVERSION Conversion
;
1714 NTUSERGETMESSAGEINFO Info
;
1715 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1717 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1718 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1719 if (-1 == (int) Res
)
1723 Conversion
.LParamSize
= Info
.LParamSize
;
1724 Conversion
.KMMsg
= Info
.Msg
;
1726 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1730 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1732 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1737 SetLastError( ERROR_NOACCESS
);
1740 *lpMsg
= Conversion
.AnsiMsg
;
1741 Conversion
.Ansi
= TRUE
;
1742 Conversion
.FinalMsg
= lpMsg
;
1743 MsgConversionAdd(&Conversion
);
1744 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1746 ThreadData
->LastMessage
= Info
.Msg
;
1757 GetMessageW(LPMSG lpMsg
,
1763 MSGCONVERSION Conversion
;
1764 NTUSERGETMESSAGEINFO Info
;
1765 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1767 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1768 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1769 if (-1 == (int) Res
)
1773 Conversion
.LParamSize
= Info
.LParamSize
;
1774 Conversion
.KMMsg
= Info
.Msg
;
1776 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1782 SetLastError( ERROR_NOACCESS
);
1785 *lpMsg
= Conversion
.UnicodeMsg
;
1786 Conversion
.Ansi
= FALSE
;
1787 Conversion
.FinalMsg
= lpMsg
;
1788 MsgConversionAdd(&Conversion
);
1789 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1791 ThreadData
->LastMessage
= Info
.Msg
;
1802 PeekMessageA(LPMSG lpMsg
,
1809 MSGCONVERSION Conversion
;
1810 NTUSERGETMESSAGEINFO Info
;
1811 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1813 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1814 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1815 if (-1 == (int) Res
|| !Res
)
1819 Conversion
.LParamSize
= Info
.LParamSize
;
1820 Conversion
.KMMsg
= Info
.Msg
;
1822 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1826 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1828 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1833 SetLastError( ERROR_NOACCESS
);
1836 *lpMsg
= Conversion
.AnsiMsg
;
1837 Conversion
.Ansi
= TRUE
;
1838 Conversion
.FinalMsg
= lpMsg
;
1839 MsgConversionAdd(&Conversion
);
1840 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1842 ThreadData
->LastMessage
= Info
.Msg
;
1862 MSGCONVERSION Conversion
;
1863 NTUSERGETMESSAGEINFO Info
;
1864 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1866 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1867 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1868 if (-1 == (int) Res
|| !Res
)
1872 Conversion
.LParamSize
= Info
.LParamSize
;
1873 Conversion
.KMMsg
= Info
.Msg
;
1875 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1881 SetLastError( ERROR_NOACCESS
);
1884 *lpMsg
= Conversion
.UnicodeMsg
;
1885 Conversion
.Ansi
= FALSE
;
1886 Conversion
.FinalMsg
= lpMsg
;
1887 MsgConversionAdd(&Conversion
);
1888 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1890 ThreadData
->LastMessage
= Info
.Msg
;
1897 // Worker function for post message.
1911 UMMsg
.message
= Msg
;
1912 UMMsg
.wParam
= wParam
;
1913 UMMsg
.lParam
= lParam
;
1914 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1918 Result
= NtUserPostMessage( Wnd
,
1923 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1942 AnsiMsg
.hwnd
= hWnd
;
1943 AnsiMsg
.message
= Msg
;
1944 AnsiMsg
.wParam
= wParam
;
1945 AnsiMsg
.lParam
= lParam
;
1947 if (!MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1952 Ret
= PostMessageW( hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1954 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1972 /* Check for combo box or a list box to send names. */
1973 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
1976 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
1977 combo/list box. Forces a call like DlgDirListComboBox.
1979 wParam
|= DDL_POSTMSGS
;
1980 return PostMessageWorker(hWnd
, Msg
, wParam
, lParam
);
1983 /* No drop files or current Process, just post message. */
1984 if ( (Msg
!= WM_DROPFILES
) ||
1985 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
1986 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
1988 return PostMessageWorker(hWnd
, Msg
, wParam
, lParam
);
1991 /* We have drop files and this is not the same process for this window. */
1993 /* Just incase, check wParam for Global memory handle and send size. */
1994 Ret
= SendMessageW( hWnd
,
1996 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
1997 (LPARAM
)wParam
); // Send wParam as lParam.
1999 if ( Ret
) return PostMessageWorker(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2012 NtUserCallOneParam(nExitCode
, ONEPARAM_ROUTINE_POSTQUITMESSAGE
);
2027 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2042 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2050 SendMessageW(HWND Wnd
,
2056 NTUSERSENDMESSAGEINFO Info
;
2059 PTHREADINFO ti
= GetW32ThreadInfo();
2061 Window
= ValidateHwnd(Wnd
);
2062 if (!Window
) return FALSE
;
2064 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2066 if (Window
!= NULL
&& Window
->head
.pti
== ti
&& !IsThreadHooked(GetWin32ClientInfo()))
2068 /* NOTE: We can directly send messages to the window procedure
2069 if *all* the following conditions are met:
2071 * Window belongs to calling thread
2072 * The calling thread is not being hooked
2075 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2080 UMMsg
.message
= Msg
;
2081 UMMsg
.wParam
= wParam
;
2082 UMMsg
.lParam
= lParam
;
2083 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2088 Result
= NtUserSendMessage( KMMsg
.hwnd
,
2093 if (! Info
.HandledByKernel
)
2095 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2096 /* We need to send the message ourselves */
2097 Result
= IntCallWindowProcW( Info
.Ansi
,
2105 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
2118 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2123 NTUSERSENDMESSAGEINFO Info
;
2125 PTHREADINFO ti
= GetW32ThreadInfo();
2127 Window
= ValidateHwnd(Wnd
);
2128 if (!Window
) return FALSE
;
2130 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2132 if (Window
!= NULL
&& Window
->head
.pti
== ti
&& !IsThreadHooked(GetWin32ClientInfo()))
2134 /* NOTE: We can directly send messages to the window procedure
2135 if *all* the following conditions are met:
2137 * Window belongs to calling thread
2138 * The calling thread is not being hooked
2141 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2146 AnsiMsg
.message
= Msg
;
2147 AnsiMsg
.wParam
= wParam
;
2148 AnsiMsg
.lParam
= lParam
;
2149 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2154 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2156 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2160 Result
= NtUserSendMessage( KMMsg
.hwnd
,
2165 if (! Info
.HandledByKernel
)
2167 /* We need to send the message ourselves */
2170 /* Ansi message and Ansi window proc, that's easy. Clean up
2171 the Unicode message though */
2172 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2173 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2174 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Window
, Wnd
, Msg
, wParam
, lParam
);
2178 /* Unicode winproc. Although we started out with an Ansi message we
2179 already converted it to Unicode for the kernel call. Reuse that
2180 message to avoid another conversion */
2181 Result
= IntCallWindowProcW( Info
.Ansi
,
2188 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2194 /* Message sent by kernel. Convert back to Ansi */
2195 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
2196 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2209 SendMessageCallbackA(
2214 SENDASYNCPROC lpCallBack
,
2217 return NtUserMessageCall(hWnd
,
2221 (ULONG_PTR
)&lpCallBack
,
2222 FNID_SENDMESSAGECALLBACK
,
2231 SendMessageCallbackW(
2236 SENDASYNCPROC lpCallBack
,
2239 return NtUserMessageCall(hWnd
,
2243 (ULONG_PTR
)&lpCallBack
,
2244 FNID_SENDMESSAGECALLBACK
,
2253 SendMessageTimeoutA(
2260 PDWORD_PTR lpdwResult
)
2265 NTUSERSENDMESSAGEINFO Info
;
2267 AnsiMsg
.hwnd
= hWnd
;
2268 AnsiMsg
.message
= Msg
;
2269 AnsiMsg
.wParam
= wParam
;
2270 AnsiMsg
.lParam
= lParam
;
2271 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2276 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2279 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
2280 UcMsg
.wParam
, UcMsg
.lParam
,
2281 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
2284 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2287 if (! Info
.HandledByKernel
)
2290 pWnd
= ValidateHwnd(hWnd
);
2291 /* We need to send the message ourselves */
2294 /* Ansi message and Ansi window proc, that's easy. Clean up
2295 the Unicode message though */
2296 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2297 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
2301 /* Unicode winproc. Although we started out with an Ansi message we
2302 already converted it to Unicode for the kernel call. Reuse that
2303 message to avoid another conversion */
2304 Result
= IntCallWindowProcW( Info
.Ansi
,
2311 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2313 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2318 *lpdwResult
= Result
;
2323 /* Message sent by kernel. Convert back to Ansi */
2324 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2326 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2331 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2341 SendMessageTimeoutW(
2348 PDWORD_PTR lpdwResult
)
2350 NTUSERSENDMESSAGEINFO Info
;
2353 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2356 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
2358 if (! Info
.HandledByKernel
)
2361 pWnd
= ValidateHwnd(hWnd
);
2362 /* We need to send the message ourselves */
2363 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
2365 *lpdwResult
= Result
;
2367 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2371 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2389 AnsiMsg
.hwnd
= hWnd
;
2390 AnsiMsg
.message
= Msg
;
2391 AnsiMsg
.wParam
= wParam
;
2392 AnsiMsg
.lParam
= lParam
;
2393 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2397 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2399 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2419 UMMsg
.message
= Msg
;
2420 UMMsg
.wParam
= wParam
;
2421 UMMsg
.lParam
= lParam
;
2422 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2426 Result
= NtUserMessageCall( hWnd
,
2431 FNID_SENDNOTIFYMESSAGE
,
2434 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2443 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2445 switch (lpMsg
->message
)
2451 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2454 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2455 SetLastError(ERROR_INVALID_PARAMETER
);
2465 TranslateMessage(CONST MSG
*lpMsg
)
2469 // Ref: msdn ImmGetVirtualKey:
2470 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2472 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2473 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2478 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2488 RegisterWindowMessageA(LPCSTR lpString
)
2490 UNICODE_STRING String
;
2494 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
2499 Atom
= NtUserRegisterWindowMessage(&String
);
2500 RtlFreeUnicodeString(&String
);
2509 RegisterWindowMessageW(LPCWSTR lpString
)
2511 UNICODE_STRING String
;
2513 RtlInitUnicodeString(&String
, lpString
);
2514 return(NtUserRegisterWindowMessage(&String
));
2523 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2530 ReleaseCapture(VOID
)
2532 NtUserSetCapture(NULL
);
2542 RealGetQueueStatus(UINT flags
)
2544 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_ALLINPUT
))
2546 SetLastError( ERROR_INVALID_FLAGS
);
2549 return NtUserCallOneParam(flags
, ONEPARAM_ROUTINE_GETQUEUESTATUS
);
2556 BOOL WINAPI
GetInputState(VOID
)
2558 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2560 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2561 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2568 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2570 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2573 PCLIENTINFO pci
= GetWin32ClientInfo();
2575 /* Make sure we don't try to access mem beyond what we were given */
2576 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2578 return STATUS_INFO_LENGTH_MISMATCH
;
2581 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2582 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2583 KMMsg
.message
= CallbackArgs
->Msg
;
2584 KMMsg
.wParam
= CallbackArgs
->wParam
;
2585 /* Check if lParam is really a pointer and adjust it if it is */
2586 if (0 <= CallbackArgs
->lParamBufferSize
)
2588 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2589 + CallbackArgs
->lParamBufferSize
)
2591 return STATUS_INFO_LENGTH_MISMATCH
;
2593 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2597 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2599 return STATUS_INFO_LENGTH_MISMATCH
;
2601 KMMsg
.lParam
= CallbackArgs
->lParam
;
2604 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2606 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2607 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2610 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2614 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2615 pWnd
= pci
->CallbackWnd
.pvWnd
;
2617 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
2625 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2629 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2635 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
2637 /* Function does nothing on 32 bit windows */
2640 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
2641 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
2643 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
2645 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
2646 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
2647 RealGetQueueStatusProc RealGetQueueStatus
;
2648 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
2649 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
2653 RealMsgWaitForMultipleObjectsEx(
2655 CONST HANDLE
*pHandles
,
2656 DWORD dwMilliseconds
,
2660 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
2662 CRITICAL_SECTION gcsMPH
;
2663 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
2664 DWORD gcLoadMPH
= 0;
2665 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
2666 //NtUserRealInternalGetMessage,
2667 //NtUserRealInternalWaitMessageEx,
2669 RealMsgWaitForMultipleObjectsEx
2672 DWORD gfMessagePumpHook
= 0;
2674 BOOL WINAPI
IsInsideMessagePumpHook()
2675 { // Fixme: Need to fully implement this! FF uses this and polls it when Min/Max
2676 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2677 // FIXME("IIMPH %x\n",pcti);
2678 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
2681 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
2683 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
2684 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
2685 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
2686 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
2687 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
2690 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
2692 EnterCriticalSection(&gcsMPH
);
2694 SetLastError(ERROR_INVALID_PARAMETER
);
2695 LeaveCriticalSection(&gcsMPH
);
2699 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
2701 ResetMessagePumpHook(&Addresses
);
2702 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
2703 LeaveCriticalSection(&gcsMPH
);
2706 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
2708 if(gpfnInitMPH
!= Hook
) {
2709 LeaveCriticalSection(&gcsMPH
);
2713 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
2714 LeaveCriticalSection(&gcsMPH
);
2718 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
2720 LeaveCriticalSection(&gcsMPH
);
2724 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
2726 EnterCriticalSection(&gcsMPH
);
2728 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
2731 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
2732 gpfnInitMPH(TRUE
, NULL
);
2733 ResetMessagePumpHook(&gmph
);
2736 LeaveCriticalSection(&gcsMPH
);
2740 LeaveCriticalSection(&gcsMPH
);
2744 DWORD WINAPI
GetQueueStatus(UINT flags
)
2746 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2750 * @name RealMsgWaitForMultipleObjectsEx
2752 * Wait either for either message arrival or for one of the passed events
2756 * Number of handles in the pHandles array.
2758 * Handles of events to wait for.
2759 * @param dwMilliseconds
2762 * Mask specifying on which message events we should wakeup.
2764 * Wait type (see MWMO_* constants).
2770 RealMsgWaitForMultipleObjectsEx(
2772 const HANDLE
*pHandles
,
2773 DWORD dwMilliseconds
,
2777 LPHANDLE RealHandles
;
2778 HANDLE MessageQueueHandle
;
2781 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2783 SetLastError(ERROR_INVALID_PARAMETER
);
2788 if (dwFlags & MWMO_INPUTAVAILABLE)
2790 RealGetQueueStatus(dwWakeMask);
2794 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2795 if (MessageQueueHandle
== NULL
)
2797 SetLastError(0); /* ? */
2801 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2802 if (RealHandles
== NULL
)
2804 NtUserMsqClearWakeMask();
2805 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2809 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2810 RealHandles
[nCount
] = MessageQueueHandle
;
2812 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2813 dwFlags
& MWMO_WAITALL
,
2814 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2816 HeapFree(GetProcessHeap(), 0, RealHandles
);
2817 NtUserMsqClearWakeMask();
2826 MsgWaitForMultipleObjectsEx(
2828 CONST HANDLE
*lpHandles
,
2829 DWORD dwMilliseconds
,
2833 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2840 MsgWaitForMultipleObjects(
2842 CONST HANDLE
*lpHandles
,
2844 DWORD dwMilliseconds
,
2847 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2848 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2852 BOOL FASTCALL
MessageInit(VOID
)
2854 InitializeCriticalSection(&DdeCrst
);
2855 InitializeCriticalSection(&MsgConversionCrst
);
2856 InitializeCriticalSection(&gcsMPH
);
2861 VOID FASTCALL
MessageCleanup(VOID
)
2863 DeleteCriticalSection(&DdeCrst
);
2864 DeleteCriticalSection(&MsgConversionCrst
);
2865 DeleteCriticalSection(&gcsMPH
);
2868 /***********************************************************************
2871 * Convert the wparam of an ASCII message to Unicode.
2874 map_wparam_AtoW( UINT message
, WPARAM wparam
)
2879 case EM_SETPASSWORDCHAR
:
2883 case WM_SYSDEADCHAR
:
2888 ch
[0] = (wparam
& 0xff);
2889 ch
[1] = (wparam
>> 8);
2890 MultiByteToWideChar(CP_ACP
, 0, ch
, 2, wch
, 2);
2891 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
2898 ch
[0] = (wparam
>> 8);
2899 ch
[1] = (wparam
& 0xff);
2900 if (ch
[0]) MultiByteToWideChar(CP_ACP
, 0, ch
, 2, &wch
, 1);
2901 else MultiByteToWideChar(CP_ACP
, 0, &ch
[1], 1, &wch
, 1);
2902 wparam
= MAKEWPARAM( wch
, HIWORD(wparam
) );
2913 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
2916 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
2917 return IsDialogMessageW( hwndDlg
, &msg
);
2922 IntBroadcastSystemMessage(
2924 LPDWORD lpdwRecipients
,
2932 DWORD recips
= BSM_ALLCOMPONENTS
;
2933 BOOL ret
= -1; // Set to return fail
2934 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
2935 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
2936 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
2938 if ((dwflags
& ~all_flags
) ||
2939 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
2941 SetLastError(ERROR_INVALID_PARAMETER
);
2945 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
2947 SetLastError(ERROR_INVALID_PARAMETER
);
2951 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
2953 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
2955 if (!lpdwRecipients
)
2956 lpdwRecipients
= &recips
;
2958 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
2960 SetLastError(ERROR_INVALID_PARAMETER
);
2964 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2966 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
2968 SetLastError(ERROR_INVALID_PARAMETER
);
2975 parm
.flags
= dwflags
;
2976 parm
.recipients
= *lpdwRecipients
;
2978 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
2980 if (*lpdwRecipients
& BSM_APPLICATIONS
)
2982 ret
= NtUserMessageCall(GetDesktopWindow(),
2987 FNID_BROADCASTSYSTEMMESSAGE
,
2993 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2995 pBSMInfo
->hdesk
= parm
.hDesk
;
2996 pBSMInfo
->hwnd
= parm
.hWnd
;
3007 BroadcastSystemMessageA(
3009 LPDWORD lpdwRecipients
,
3014 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
3022 BroadcastSystemMessageW(
3024 LPDWORD lpdwRecipients
,
3029 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3037 BroadcastSystemMessageExA(
3039 LPDWORD lpdwRecipients
,
3045 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3053 BroadcastSystemMessageExW(
3055 LPDWORD lpdwRecipients
,
3061 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);