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 &DdeLparam
->Value
.Packed
.uiLo
,
167 &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
) DdeLparam
->Value
.Packed
.uiHi
);
177 GlobalFree((HGLOBAL
) DdeLparam
->Value
.Packed
.uiHi
);
178 DdeLparam
->Value
.Packed
.uiHi
= (UINT
) 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 *UnicodeMsg
= *AnsiMsg
;
394 switch (AnsiMsg
->message
)
397 case WM_ASKCBFORMATNAME
:
399 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
400 AnsiMsg
->wParam
* sizeof(WCHAR
));
405 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
409 /* AnsiMsg->lParam is string (0-terminated) */
411 case WM_WININICHANGE
:
412 case WM_DEVMODECHANGE
:
418 goto ConvertLParamString
;
422 case LB_ADDSTRING_LOWER
:
423 case LB_ADDSTRING_UPPER
:
424 case LB_INSERTSTRING
:
425 case LB_INSERTSTRING_UPPER
:
426 case LB_INSERTSTRING_LOWER
:
428 case LB_FINDSTRINGEXACT
:
429 case LB_SELECTSTRING
:
431 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
432 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
433 (dwStyle
& LBS_HASSTRINGS
))
435 goto ConvertLParamString
;
441 case CB_INSERTSTRING
:
443 case CB_FINDSTRINGEXACT
:
444 case CB_SELECTSTRING
:
446 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
447 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
448 (dwStyle
& CBS_HASSTRINGS
))
450 UNICODE_STRING UnicodeString
;
453 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
454 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
462 UNICODE_STRING UnicodeBuffer
;
465 CREATESTRUCTW cs
; /* new structure */
466 LPCWSTR lpszName
; /* allocated Name */
467 LPCWSTR lpszClass
; /* allocated Class */
469 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
474 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
475 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
477 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszName
);
478 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeBuffer
.Buffer
;
480 if (!IS_ATOM(xs
->cs
.lpszClass
))
482 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)xs
->cs
.lpszClass
);
483 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeBuffer
.Buffer
;
485 UnicodeMsg
->lParam
= (LPARAM
)xs
;
491 UNICODE_STRING UnicodeBuffer
;
492 MDICREATESTRUCTW
*cs
=
493 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
500 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
502 if (!IS_ATOM(cs
->szClass
))
504 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szClass
);
505 cs
->szClass
= UnicodeBuffer
.Buffer
;
508 RtlCreateUnicodeStringFromAsciiz(&UnicodeBuffer
, (LPSTR
)cs
->szTitle
);
509 cs
->szTitle
= UnicodeBuffer
.Buffer
;
511 UnicodeMsg
->lParam
= (LPARAM
)cs
;
521 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
523 switch (AnsiMsg
->message
)
526 case WM_ASKCBFORMATNAME
:
528 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
533 case WM_WININICHANGE
:
534 case WM_DEVMODECHANGE
:
540 goto FreeLParamString
;
544 case LB_ADDSTRING_LOWER
:
545 case LB_ADDSTRING_UPPER
:
546 case LB_INSERTSTRING
:
547 case LB_INSERTSTRING_UPPER
:
548 case LB_INSERTSTRING_LOWER
:
550 case LB_FINDSTRINGEXACT
:
551 case LB_SELECTSTRING
:
553 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
554 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
555 (dwStyle
& LBS_HASSTRINGS
))
557 goto FreeLParamString
;
563 case CB_INSERTSTRING
:
565 case CB_FINDSTRINGEXACT
:
566 case CB_SELECTSTRING
:
568 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
569 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
570 (dwStyle
& CBS_HASSTRINGS
))
572 UNICODE_STRING UnicodeString
;
575 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
576 RtlFreeUnicodeString(&UnicodeString
);
585 UNICODE_STRING UnicodeString
;
588 CREATESTRUCTW cs
; /* new structure */
589 LPWSTR lpszName
; /* allocated Name */
590 LPWSTR lpszClass
; /* allocated Class */
592 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
595 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
596 RtlFreeUnicodeString(&UnicodeString
);
600 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
601 RtlFreeUnicodeString(&UnicodeString
);
603 HeapFree(GetProcessHeap(), 0, xs
);
609 UNICODE_STRING UnicodeString
;
610 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
611 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
612 RtlFreeUnicodeString(&UnicodeString
);
613 if (!IS_ATOM(cs
->szClass
))
615 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
616 RtlFreeUnicodeString(&UnicodeString
);
618 HeapFree(GetProcessHeap(), 0, cs
);
627 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
629 switch (AnsiMsg
->message
)
632 case WM_ASKCBFORMATNAME
:
634 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
635 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
636 if (UnicodeMsg
->wParam
> 0 &&
637 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
638 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
640 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
646 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
653 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
655 *AnsiMsg
= *UnicodeMsg
;
657 switch(UnicodeMsg
->message
)
664 UNICODE_STRING UString
;
668 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
669 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
674 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
676 RtlInitUnicodeString(&UString
, CsW
->lpszName
);
677 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
678 if (! NT_SUCCESS(Status
))
680 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
683 CsA
->lpszName
= AString
.Buffer
;
684 if (HIWORD((ULONG
)CsW
->lpszClass
) != 0)
686 RtlInitUnicodeString(&UString
, CsW
->lpszClass
);
687 Status
= RtlUnicodeStringToAnsiString(&AString
, &UString
, TRUE
);
688 if (! NT_SUCCESS(Status
))
690 RtlInitAnsiString(&AString
, CsA
->lpszName
);
691 RtlFreeAnsiString(&AString
);
692 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
695 CsA
->lpszClass
= AString
.Buffer
;
697 AnsiMsg
->lParam
= (LPARAM
)CsA
;
702 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
703 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
704 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
705 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
716 goto ConvertLParamString
;
720 case LB_ADDSTRING_LOWER
:
721 case LB_ADDSTRING_UPPER
:
722 case LB_INSERTSTRING
:
723 case LB_INSERTSTRING_UPPER
:
724 case LB_INSERTSTRING_LOWER
:
726 case LB_FINDSTRINGEXACT
:
727 case LB_SELECTSTRING
:
729 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
730 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
731 (dwStyle
& LBS_HASSTRINGS
))
733 goto ConvertLParamString
;
739 case CB_INSERTSTRING
:
741 case CB_FINDSTRINGEXACT
:
742 case CB_SELECTSTRING
:
744 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
745 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
746 (dwStyle
& CBS_HASSTRINGS
))
748 ANSI_STRING AnsiString
;
749 UNICODE_STRING UnicodeString
;
752 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
753 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
759 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
766 ANSI_STRING AnsiBuffer
;
767 UNICODE_STRING UnicodeString
;
768 MDICREATESTRUCTA
*cs
=
769 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
776 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
778 if (!IS_ATOM(cs
->szClass
))
780 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
781 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiBuffer
,
787 cs
->szClass
= AnsiBuffer
.Buffer
;
790 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
791 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiBuffer
,
795 if (!IS_ATOM(cs
->szClass
))
797 RtlInitAnsiString(&AnsiBuffer
, cs
->szClass
);
798 RtlFreeAnsiString(&AnsiBuffer
);
802 cs
->szTitle
= AnsiBuffer
.Buffer
;
804 AnsiMsg
->lParam
= (LPARAM
)cs
;
814 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
816 switch(UnicodeMsg
->message
)
820 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
825 goto FreeLParamString
;
833 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
834 RtlInitAnsiString(&AString
, Cs
->lpszName
);
835 RtlFreeAnsiString(&AString
);
836 if (HIWORD((ULONG
)Cs
->lpszClass
) != 0)
838 RtlInitAnsiString(&AString
, Cs
->lpszClass
);
839 RtlFreeAnsiString(&AString
);
841 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
846 case LB_ADDSTRING_LOWER
:
847 case LB_ADDSTRING_UPPER
:
848 case LB_INSERTSTRING
:
849 case LB_INSERTSTRING_UPPER
:
850 case LB_INSERTSTRING_LOWER
:
852 case LB_FINDSTRINGEXACT
:
853 case LB_SELECTSTRING
:
855 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
856 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
857 (dwStyle
& LBS_HASSTRINGS
))
859 goto FreeLParamString
;
865 case CB_INSERTSTRING
:
867 case CB_FINDSTRINGEXACT
:
868 case CB_SELECTSTRING
:
870 DWORD dwStyle
= GetWindowLongW(AnsiMsg
->hwnd
, GWL_STYLE
);
871 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
872 (dwStyle
& CBS_HASSTRINGS
))
877 RtlInitAnsiString(&AString
, (PSTR
) AnsiMsg
->lParam
);
878 RtlFreeAnsiString(&AString
);
885 ANSI_STRING AnsiString
;
886 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
887 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
888 RtlFreeAnsiString(&AnsiString
);
889 if (!IS_ATOM(cs
->szClass
))
891 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
892 RtlFreeAnsiString(&AnsiString
);
894 HeapFree(GetProcessHeap(), 0, cs
);
905 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
907 switch (UnicodeMsg
->message
)
910 case WM_ASKCBFORMATNAME
:
912 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
913 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
914 if (0 < AnsiMsg
->wParam
&&
915 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
917 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
923 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
928 typedef struct tagMSGCONVERSION
937 } MSGCONVERSION
, *PMSGCONVERSION
;
939 static PMSGCONVERSION MsgConversions
= NULL
;
940 static unsigned MsgConversionNumAlloc
= 0;
941 static unsigned MsgConversionNumUsed
= 0;
942 static CRITICAL_SECTION MsgConversionCrst
;
945 MsgConversionAdd(PMSGCONVERSION Conversion
)
949 EnterCriticalSection(&MsgConversionCrst
);
951 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
955 if (NULL
!= MsgConversions
)
957 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
958 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
962 New
= HeapAlloc(GetProcessHeap(), 0,
963 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
968 LeaveCriticalSection(&MsgConversionCrst
);
971 MsgConversions
= New
;
972 /* zero out newly allocated part */
973 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
974 MsgConversionNumAlloc
+= GROWBY
;
978 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
980 if (! MsgConversions
[i
].InUse
)
982 MsgConversions
[i
] = *Conversion
;
983 MsgConversions
[i
].InUse
= TRUE
;
984 MsgConversionNumUsed
++;
988 LeaveCriticalSection(&MsgConversionCrst
);
994 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
997 PMSGCONVERSION Conversion
;
1000 EnterCriticalSection(&MsgConversionCrst
);
1001 for (Conversion
= MsgConversions
;
1002 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
1005 if (Conversion
->InUse
&&
1006 ((Ansi
&& Conversion
->Ansi
) ||
1007 (! Ansi
&& ! Conversion
->Ansi
)))
1009 Found
= (Conversion
->FinalMsg
== Msg
);
1010 if (! Found
&& CheckMsgContents
)
1014 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
1018 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
1025 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
1026 NULL
== Result
? &Dummy
: Result
);
1028 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
1029 NULL
== Result
? &Dummy
: Result
);
1030 if (0 != Conversion
->LParamSize
)
1032 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
1033 &Conversion
->LParamSize
, MEM_DECOMMIT
);
1035 Conversion
->InUse
= FALSE
;
1036 MsgConversionNumUsed
--;
1040 LeaveCriticalSection(&MsgConversionCrst
);
1048 GetMessageExtraInfo(VOID
)
1050 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
1061 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1062 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
1070 GetMessageTime(VOID
)
1072 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1073 return(ThreadData
->LastMessage
.time
);
1084 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1085 // FIXME("ISM %x\n",pcti);
1088 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1094 /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND);*/
1106 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1107 // FIXME("ISMEX %x\n",pcti);
1108 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
)) return ISMEX_NOSEND
;
1110 /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
1133 SetMessageExtraInfo(
1136 return NtUserSetMessageExtraInfo(lParam
);
1140 IntCallWindowProcW(BOOL IsAnsiProc
,
1151 if (WndProc
== NULL
)
1153 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1159 UnicodeMsg
.hwnd
= hWnd
;
1160 UnicodeMsg
.message
= Msg
;
1161 UnicodeMsg
.wParam
= wParam
;
1162 UnicodeMsg
.lParam
= lParam
;
1163 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
1167 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1169 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1177 return WndProc(hWnd
, Msg
, wParam
, lParam
);
1181 static LRESULT FASTCALL
1182 IntCallWindowProcA(BOOL IsAnsiProc
,
1193 if (WndProc
== NULL
)
1195 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1201 return WndProc(hWnd
, Msg
, wParam
, lParam
);
1205 AnsiMsg
.hwnd
= hWnd
;
1206 AnsiMsg
.message
= Msg
;
1207 AnsiMsg
.wParam
= wParam
;
1208 AnsiMsg
.lParam
= lParam
;
1209 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
1213 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1214 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1216 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1224 static BOOL __inline
1225 IsCallProcHandle(IN WNDPROC lpWndProc
)
1227 /* FIXME - check for 64 bit architectures... */
1228 return ((ULONG_PTR
)lpWndProc
& 0xFFFF0000) == 0xFFFF0000;
1236 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1244 if (lpPrevWndFunc
== NULL
)
1246 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1250 if (!IsCallProcHandle(lpPrevWndFunc
))
1251 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1254 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1255 if (CallProc
!= NULL
)
1257 return IntCallWindowProcA(!CallProc
->Unicode
, CallProc
->WndProc
,
1258 hWnd
, Msg
, wParam
, lParam
);
1262 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1273 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1281 /* FIXME - can the first parameter be NULL? */
1282 if (lpPrevWndFunc
== NULL
)
1284 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1288 if (!IsCallProcHandle(lpPrevWndFunc
))
1289 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, hWnd
, Msg
, wParam
, lParam
);
1292 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1293 if (CallProc
!= NULL
)
1295 return IntCallWindowProcW(!CallProc
->Unicode
, CallProc
->WndProc
,
1296 hWnd
, Msg
, wParam
, lParam
);
1300 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1307 static LRESULT WINAPI
1308 IntCallMessageProc(IN PWINDOW Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1315 WndProc
= (Ansi
? Wnd
->WndProcExtra
: Wnd
->WndProc
);
1320 WndProc
= Wnd
->WndProc
;
1321 IsAnsi
= !Wnd
->Unicode
;
1325 return IntCallWindowProcW(IsAnsi
, WndProc
, hWnd
, Msg
, wParam
, lParam
);
1327 return IntCallWindowProcA(IsAnsi
, WndProc
, hWnd
, Msg
, wParam
, lParam
);
1335 DispatchMessageA(CONST MSG
*lpmsg
)
1341 if (lpmsg
->hwnd
!= NULL
)
1343 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1344 if (!Wnd
|| SharedPtrToUser(Wnd
->ti
) != GetW32ThreadInfo())
1350 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1352 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1354 if ( lpmsg
->message
== WM_SYSTIMER
)
1355 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1357 Ret
= WndProc(lpmsg
->hwnd
,
1362 else if (Wnd
!= NULL
)
1364 // FIXME Need to test for calling proc inside win32k!
1365 if ( (lpmsg
->message
!= WM_PAINT
) ) // && !(Wnd->flags & WNDF_CALLPROC) )
1367 Ret
= IntCallMessageProc(Wnd
,
1376 if (!MsgiAnsiToUnicodeMessage(&UnicodeMsg
, (LPMSG
)lpmsg
))
1381 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1383 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1397 DispatchMessageW(CONST MSG
*lpmsg
)
1402 if (lpmsg
->hwnd
!= NULL
)
1404 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1405 if (!Wnd
|| SharedPtrToUser(Wnd
->ti
) != GetW32ThreadInfo())
1411 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1413 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1415 if ( lpmsg
->message
== WM_SYSTIMER
)
1416 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1418 Ret
= WndProc(lpmsg
->hwnd
,
1423 else if (Wnd
!= NULL
)
1425 // FIXME Need to test for calling proc inside win32k!
1426 if ( (lpmsg
->message
!= WM_PAINT
) ) // && !(Wnd->flags & W32K_CALLPROC) )
1428 Ret
= IntCallMessageProc(Wnd
,
1436 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
1447 GetMessageA(LPMSG lpMsg
,
1453 MSGCONVERSION Conversion
;
1454 NTUSERGETMESSAGEINFO Info
;
1455 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1457 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1458 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1459 if (-1 == (int) Res
)
1463 Conversion
.LParamSize
= Info
.LParamSize
;
1464 Conversion
.KMMsg
= Info
.Msg
;
1466 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1470 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1472 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1477 SetLastError( ERROR_NOACCESS
);
1480 *lpMsg
= Conversion
.AnsiMsg
;
1481 Conversion
.Ansi
= TRUE
;
1482 Conversion
.FinalMsg
= lpMsg
;
1483 MsgConversionAdd(&Conversion
);
1484 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1486 ThreadData
->LastMessage
= Info
.Msg
;
1497 GetMessageW(LPMSG lpMsg
,
1503 MSGCONVERSION Conversion
;
1504 NTUSERGETMESSAGEINFO Info
;
1505 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1507 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1508 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1509 if (-1 == (int) Res
)
1513 Conversion
.LParamSize
= Info
.LParamSize
;
1514 Conversion
.KMMsg
= Info
.Msg
;
1516 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1522 SetLastError( ERROR_NOACCESS
);
1525 *lpMsg
= Conversion
.UnicodeMsg
;
1526 Conversion
.Ansi
= FALSE
;
1527 Conversion
.FinalMsg
= lpMsg
;
1528 MsgConversionAdd(&Conversion
);
1529 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1531 ThreadData
->LastMessage
= Info
.Msg
;
1542 PeekMessageA(LPMSG lpMsg
,
1549 MSGCONVERSION Conversion
;
1550 NTUSERGETMESSAGEINFO Info
;
1551 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1553 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1554 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1555 if (-1 == (int) Res
|| ! Res
)
1559 Conversion
.LParamSize
= Info
.LParamSize
;
1560 Conversion
.KMMsg
= Info
.Msg
;
1562 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1566 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1568 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1573 SetLastError( ERROR_NOACCESS
);
1576 *lpMsg
= Conversion
.AnsiMsg
;
1577 Conversion
.Ansi
= TRUE
;
1578 Conversion
.FinalMsg
= lpMsg
;
1579 MsgConversionAdd(&Conversion
);
1580 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1582 ThreadData
->LastMessage
= Info
.Msg
;
1602 MSGCONVERSION Conversion
;
1603 NTUSERGETMESSAGEINFO Info
;
1604 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1606 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1607 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1608 if (-1 == (int) Res
|| ! Res
)
1612 Conversion
.LParamSize
= Info
.LParamSize
;
1613 Conversion
.KMMsg
= Info
.Msg
;
1615 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1621 SetLastError( ERROR_NOACCESS
);
1624 *lpMsg
= Conversion
.UnicodeMsg
;
1625 Conversion
.Ansi
= FALSE
;
1626 Conversion
.FinalMsg
= lpMsg
;
1627 MsgConversionAdd(&Conversion
);
1628 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1630 ThreadData
->LastMessage
= Info
.Msg
;
1653 AnsiMsg
.message
= Msg
;
1654 AnsiMsg
.wParam
= wParam
;
1655 AnsiMsg
.lParam
= lParam
;
1656 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1661 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
1663 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1666 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1667 KMMsg
.wParam
, KMMsg
.lParam
);
1668 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1669 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1690 UMMsg
.message
= Msg
;
1691 UMMsg
.wParam
= wParam
;
1692 UMMsg
.lParam
= lParam
;
1693 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1697 Result
= NtUserPostMessage(KMMsg
.hwnd
, KMMsg
.message
,
1698 KMMsg
.wParam
, KMMsg
.lParam
);
1699 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1713 (void) NtUserPostMessage(NULL
, WM_QUIT
, nExitCode
, 0);
1728 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1743 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1751 SendMessageW(HWND Wnd
,
1757 NTUSERSENDMESSAGEINFO Info
;
1760 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
1763 PW32THREADINFO ti
= GetW32ThreadInfo();
1765 Window
= ValidateHwnd(Wnd
);
1766 if (Window
!= NULL
&& SharedPtrToUser(Window
->ti
) == ti
&& !IsThreadHooked(ti
))
1768 /* NOTE: We can directly send messages to the window procedure
1769 if *all* the following conditions are met:
1771 * Window belongs to calling thread
1772 * The calling thread is not being hooked
1775 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
1780 UMMsg
.message
= Msg
;
1781 UMMsg
.wParam
= wParam
;
1782 UMMsg
.lParam
= lParam
;
1783 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
1788 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1789 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1790 if (! Info
.HandledByKernel
)
1792 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1793 /* We need to send the message ourselves */
1794 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UMMsg
.hwnd
, UMMsg
.message
,
1795 UMMsg
.wParam
, UMMsg
.lParam
);
1797 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
1810 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1815 NTUSERSENDMESSAGEINFO Info
;
1817 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
1820 PW32THREADINFO ti
= GetW32ThreadInfo();
1822 Window
= ValidateHwnd(Wnd
);
1823 if (Window
!= NULL
&& SharedPtrToUser(Window
->ti
) == ti
&& !IsThreadHooked(ti
))
1825 /* NOTE: We can directly send messages to the window procedure
1826 if *all* the following conditions are met:
1828 * Window belongs to calling thread
1829 * The calling thread is not being hooked
1832 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
1837 AnsiMsg
.message
= Msg
;
1838 AnsiMsg
.wParam
= wParam
;
1839 AnsiMsg
.lParam
= lParam
;
1840 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1845 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
1847 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1851 Result
= NtUserSendMessage(KMMsg
.hwnd
, KMMsg
.message
,
1852 KMMsg
.wParam
, KMMsg
.lParam
, &Info
);
1853 if (! Info
.HandledByKernel
)
1855 /* We need to send the message ourselves */
1858 /* Ansi message and Ansi window proc, that's easy. Clean up
1859 the Unicode message though */
1860 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
1861 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1862 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Wnd
, Msg
, wParam
, lParam
);
1866 /* Unicode winproc. Although we started out with an Ansi message we
1867 already converted it to Unicode for the kernel call. Reuse that
1868 message to avoid another conversion */
1869 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1870 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1871 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1877 /* Message sent by kernel. Convert back to Ansi */
1878 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
1879 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1892 SendMessageCallbackA(
1897 SENDASYNCPROC lpCallBack
,
1900 return NtUserMessageCall(hWnd
,
1904 (ULONG_PTR
)&lpCallBack
,
1905 FNID_SENDMESSAGECALLBACK
,
1914 SendMessageCallbackW(
1919 SENDASYNCPROC lpCallBack
,
1922 return NtUserMessageCall(hWnd
,
1926 (ULONG_PTR
)&lpCallBack
,
1927 FNID_SENDMESSAGECALLBACK
,
1936 SendMessageTimeoutA(
1943 PDWORD_PTR lpdwResult
)
1948 NTUSERSENDMESSAGEINFO Info
;
1950 AnsiMsg
.hwnd
= hWnd
;
1951 AnsiMsg
.message
= Msg
;
1952 AnsiMsg
.wParam
= wParam
;
1953 AnsiMsg
.lParam
= lParam
;
1954 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1959 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
1962 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
1963 UcMsg
.wParam
, UcMsg
.lParam
,
1964 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
1967 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
1970 if (! Info
.HandledByKernel
)
1972 /* We need to send the message ourselves */
1975 /* Ansi message and Ansi window proc, that's easy. Clean up
1976 the Unicode message though */
1977 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1978 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
1982 /* Unicode winproc. Although we started out with an Ansi message we
1983 already converted it to Unicode for the kernel call. Reuse that
1984 message to avoid another conversion */
1985 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, UcMsg
.hwnd
,
1986 UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1987 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
1989 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
1994 *lpdwResult
= Result
;
1999 /* Message sent by kernel. Convert back to Ansi */
2000 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2002 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2007 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2017 SendMessageTimeoutW(
2024 PDWORD_PTR lpdwResult
)
2026 NTUSERSENDMESSAGEINFO Info
;
2029 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2032 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
2034 if (! Info
.HandledByKernel
)
2036 /* We need to send the message ourselves */
2037 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, hWnd
, Msg
, wParam
, lParam
);
2039 *lpdwResult
= Result
;
2041 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2045 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2065 AnsiMsg
.hwnd
= hWnd
;
2066 AnsiMsg
.message
= Msg
;
2067 AnsiMsg
.wParam
= wParam
;
2068 AnsiMsg
.lParam
= lParam
;
2069 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2074 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, TRUE
))
2076 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2079 Result
= NtUserSendNotifyMessage(KMMsg
.hwnd
, KMMsg
.message
,
2080 KMMsg
.wParam
, KMMsg
.lParam
);
2081 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2082 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2103 UMMsg
.message
= Msg
;
2104 UMMsg
.wParam
= wParam
;
2105 UMMsg
.lParam
= lParam
;
2106 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2110 Result
= NtUserSendNotifyMessage(KMMsg
.hwnd
, KMMsg
.message
,
2111 KMMsg
.wParam
, KMMsg
.lParam
);
2112 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2122 TranslateMessageEx(CONST MSG
*lpMsg
, DWORD unk
)
2124 switch (lpMsg
->message
)
2130 return(NtUserTranslateMessage((LPMSG
)lpMsg
, (HKL
)unk
));
2142 TranslateMessage(CONST MSG
*lpMsg
)
2144 return(TranslateMessageEx((LPMSG
)lpMsg
, 0));
2152 RegisterWindowMessageA(LPCSTR lpString
)
2154 UNICODE_STRING String
;
2158 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
2163 Atom
= NtUserRegisterWindowMessage(&String
);
2164 RtlFreeUnicodeString(&String
);
2173 RegisterWindowMessageW(LPCWSTR lpString
)
2175 UNICODE_STRING String
;
2177 RtlInitUnicodeString(&String
, lpString
);
2178 return(NtUserRegisterWindowMessage(&String
));
2187 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2194 ReleaseCapture(VOID
)
2196 NtUserSetCapture(NULL
);
2206 RealGetQueueStatus(UINT flags
)
2209 WORD changed_bits
, wake_bits
;
2211 #if 0 /* wine stuff. don't know what it does... */
2213 /* check for pending X events */
2214 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
2215 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
2218 ret
= NtUserCallOneParam(TRUE
, ONEPARAM_ROUTINE_GETQUEUESTATUS
);
2220 changed_bits
= LOWORD(ret
);
2221 wake_bits
= HIWORD(ret
);
2223 return MAKELONG(changed_bits
& flags
, wake_bits
& flags
);
2230 BOOL WINAPI
GetInputState(VOID
)
2235 #if 0 /* wine stuff. don't know what it does... */
2237 /* check for pending X events */
2238 if (USER_Driver
.pMsgWaitForMultipleObjectsEx
)
2239 USER_Driver
.pMsgWaitForMultipleObjectsEx( 0, NULL
, 0, 0, 0 );
2242 ret
= NtUserCallOneParam(FALSE
, ONEPARAM_ROUTINE_GETQUEUESTATUS
);
2244 wake_bits
= HIWORD(ret
);
2246 return wake_bits
& (QS_KEY
| QS_MOUSEBUTTON
);
2251 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2253 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2256 /* Make sure we don't try to access mem beyond what we were given */
2257 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2259 return STATUS_INFO_LENGTH_MISMATCH
;
2262 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2263 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2264 KMMsg
.message
= CallbackArgs
->Msg
;
2265 KMMsg
.wParam
= CallbackArgs
->wParam
;
2266 /* Check if lParam is really a pointer and adjust it if it is */
2267 if (0 <= CallbackArgs
->lParamBufferSize
)
2269 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2270 + CallbackArgs
->lParamBufferSize
)
2272 return STATUS_INFO_LENGTH_MISMATCH
;
2274 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2278 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2280 return STATUS_INFO_LENGTH_MISMATCH
;
2282 KMMsg
.lParam
= CallbackArgs
->lParam
;
2285 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2287 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2288 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2291 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2295 CallbackArgs
->Result
= IntCallWindowProcW(CallbackArgs
->IsAnsiProc
, CallbackArgs
->Proc
,
2296 UMMsg
.hwnd
, UMMsg
.message
,
2297 UMMsg
.wParam
, UMMsg
.lParam
);
2299 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2303 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2309 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
2311 /* Function does nothing on 32 bit windows */
2314 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
2315 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
2317 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
2319 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
2320 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
2321 RealGetQueueStatusProc RealGetQueueStatus
;
2322 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
2323 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
2327 RealMsgWaitForMultipleObjectsEx(
2329 CONST HANDLE
*pHandles
,
2330 DWORD dwMilliseconds
,
2334 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
2336 CRITICAL_SECTION gcsMPH
;
2337 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
2338 DWORD gcLoadMPH
= 0;
2339 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
2340 //NtUserRealInternalGetMessage,
2341 //NtUserRealInternalWaitMessageEx,
2343 RealMsgWaitForMultipleObjectsEx
2346 DWORD gfMessagePumpHook
= 0;
2348 BOOL WINAPI
IsInsideMessagePumpHook()
2349 { // Fixme: Need to fully implement this! FF uses this and polls it when Min/Max
2350 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2351 // FIXME("IIMPH %x\n",pcti);
2352 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
2355 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
2357 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
2358 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
2359 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
2360 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
2361 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
2364 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
2366 EnterCriticalSection(&gcsMPH
);
2368 SetLastError(ERROR_INVALID_PARAMETER
);
2369 LeaveCriticalSection(&gcsMPH
);
2373 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
2375 ResetMessagePumpHook(&Addresses
);
2376 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
2377 LeaveCriticalSection(&gcsMPH
);
2380 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
2382 if(gpfnInitMPH
!= Hook
) {
2383 LeaveCriticalSection(&gcsMPH
);
2387 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
2388 LeaveCriticalSection(&gcsMPH
);
2392 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
2394 LeaveCriticalSection(&gcsMPH
);
2398 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
2400 EnterCriticalSection(&gcsMPH
);
2402 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
2405 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
2406 gpfnInitMPH(TRUE
, NULL
);
2407 ResetMessagePumpHook(&gmph
);
2410 LeaveCriticalSection(&gcsMPH
);
2414 LeaveCriticalSection(&gcsMPH
);
2418 DWORD WINAPI
GetQueueStatus(UINT flags
)
2420 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2424 * @name RealMsgWaitForMultipleObjectsEx
2426 * Wait either for either message arrival or for one of the passed events
2430 * Number of handles in the pHandles array.
2432 * Handles of events to wait for.
2433 * @param dwMilliseconds
2436 * Mask specifying on which message events we should wakeup.
2438 * Wait type (see MWMO_* constants).
2444 RealMsgWaitForMultipleObjectsEx(
2446 const HANDLE
*pHandles
,
2447 DWORD dwMilliseconds
,
2451 LPHANDLE RealHandles
;
2452 HANDLE MessageQueueHandle
;
2455 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2457 SetLastError(ERROR_INVALID_PARAMETER
);
2462 if (dwFlags & MWMO_INPUTAVAILABLE)
2464 RealGetQueueStatus(dwWakeMask);
2468 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2469 if (MessageQueueHandle
== NULL
)
2471 SetLastError(0); /* ? */
2475 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2476 if (RealHandles
== NULL
)
2478 NtUserMsqClearWakeMask();
2479 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2483 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2484 RealHandles
[nCount
] = MessageQueueHandle
;
2486 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2487 dwFlags
& MWMO_WAITALL
,
2488 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2490 HeapFree(GetProcessHeap(), 0, RealHandles
);
2491 NtUserMsqClearWakeMask();
2500 MsgWaitForMultipleObjectsEx(
2502 CONST HANDLE
*lpHandles
,
2503 DWORD dwMilliseconds
,
2507 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2514 MsgWaitForMultipleObjects(
2516 CONST HANDLE
*lpHandles
,
2518 DWORD dwMilliseconds
,
2521 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2522 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2526 BOOL FASTCALL
MessageInit(VOID
)
2528 InitializeCriticalSection(&DdeCrst
);
2529 InitializeCriticalSection(&MsgConversionCrst
);
2530 InitializeCriticalSection(&gcsMPH
);
2535 VOID FASTCALL
MessageCleanup(VOID
)
2537 DeleteCriticalSection(&DdeCrst
);
2538 DeleteCriticalSection(&MsgConversionCrst
);
2539 DeleteCriticalSection(&gcsMPH
);
2542 /***********************************************************************
2545 * Convert the wparam of an ASCII message to Unicode.
2548 map_wparam_AtoW( UINT message
, WPARAM wparam
)
2553 case EM_SETPASSWORDCHAR
:
2557 case WM_SYSDEADCHAR
:
2562 ch
[0] = (wparam
& 0xff);
2563 ch
[1] = (wparam
>> 8);
2564 MultiByteToWideChar(CP_ACP
, 0, ch
, 2, wch
, 2);
2565 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
2572 ch
[0] = (wparam
>> 8);
2573 ch
[1] = (wparam
& 0xff);
2574 if (ch
[0]) MultiByteToWideChar(CP_ACP
, 0, ch
, 2, &wch
, 1);
2575 else MultiByteToWideChar(CP_ACP
, 0, &ch
[1], 1, &wch
, 1);
2576 wparam
= MAKEWPARAM( wch
, HIWORD(wparam
) );
2587 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
2590 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
2591 return IsDialogMessageW( hwndDlg
, &msg
);
2596 IntBroadcastSystemMessage(
2598 LPDWORD lpdwRecipients
,
2606 DWORD recips
= BSM_ALLCOMPONENTS
;
2607 BOOL ret
= -1; // Set to return fail
2608 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
2609 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
2610 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
2612 if ((dwflags
& ~all_flags
) ||
2613 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
2615 SetLastError(ERROR_INVALID_PARAMETER
);
2619 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
2621 SetLastError(ERROR_INVALID_PARAMETER
);
2625 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
2627 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
2629 if (!lpdwRecipients
)
2630 lpdwRecipients
= &recips
;
2632 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
2634 SetLastError(ERROR_INVALID_PARAMETER
);
2638 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2640 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
2642 SetLastError(ERROR_INVALID_PARAMETER
);
2649 parm
.flags
= dwflags
;
2650 parm
.recipients
= *lpdwRecipients
;
2652 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
2654 if (*lpdwRecipients
& BSM_APPLICATIONS
)
2656 ret
= NtUserMessageCall(GetDesktopWindow(),
2661 FNID_BROADCASTSYSTEMMESSAGE
,
2667 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2669 pBSMInfo
->hdesk
= parm
.hDesk
;
2670 pBSMInfo
->hwnd
= parm
.hWnd
;
2681 BroadcastSystemMessageA(
2683 LPDWORD lpdwRecipients
,
2688 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
2696 BroadcastSystemMessageW(
2698 LPDWORD lpdwRecipients
,
2703 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
2711 BroadcastSystemMessageExA(
2713 LPDWORD lpdwRecipients
,
2719 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
2727 BroadcastSystemMessageExW(
2729 LPDWORD lpdwRecipients
,
2735 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);