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.
64 typedef struct tagDDEPAIR
70 static PDDEPAIR DdePairs
= NULL
;
71 static unsigned DdeNumAlloc
= 0;
72 static unsigned DdeNumUsed
= 0;
73 static CRITICAL_SECTION DdeCrst
;
76 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
80 EnterCriticalSection(&DdeCrst
);
82 /* now remember the pair of hMem on both sides */
83 if (DdeNumUsed
== DdeNumAlloc
)
89 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
90 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
94 New
= HeapAlloc(GetProcessHeap(), 0,
95 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
100 LeaveCriticalSection(&DdeCrst
);
104 /* zero out newly allocated part */
105 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
106 DdeNumAlloc
+= GROWBY
;
110 for (i
= 0; i
< DdeNumAlloc
; i
++)
112 if (NULL
== DdePairs
[i
].ServerMem
)
114 DdePairs
[i
].ClientMem
= ClientMem
;
115 DdePairs
[i
].ServerMem
= ServerMem
;
120 LeaveCriticalSection(&DdeCrst
);
125 static HGLOBAL FASTCALL
126 DdeGetPair(HGLOBAL ServerMem
)
131 EnterCriticalSection(&DdeCrst
);
132 for (i
= 0; i
< DdeNumAlloc
; i
++)
134 if (DdePairs
[i
].ServerMem
== ServerMem
)
137 DdePairs
[i
].ServerMem
= 0;
139 Ret
= DdePairs
[i
].ClientMem
;
143 LeaveCriticalSection(&DdeCrst
);
149 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
153 switch (UMMsg
->message
)
157 PKMDDELPARAM DdeLparam
;
158 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
159 if (NULL
== DdeLparam
)
165 DdeLparam
->Packed
= TRUE
;
166 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
167 &DdeLparam
->Value
.Packed
.uiLo
,
168 &DdeLparam
->Value
.Packed
.uiHi
))
172 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
174 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
175 HGLOBAL h
= DdeGetPair((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
178 GlobalFree((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
179 DdeLparam
->Value
.Packed
.uiHi
= (UINT_PTR
) h
;
182 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
186 DdeLparam
->Packed
= FALSE
;
187 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
189 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
196 PKMDDEEXECUTEDATA KMDdeExecuteData
;
199 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
200 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
203 SetLastError(ERROR_INVALID_HANDLE
);
206 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
207 if (NULL
== KMDdeExecuteData
)
209 SetLastError(ERROR_OUTOFMEMORY
);
212 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
213 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
214 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
215 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
216 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
217 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
223 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
224 PCOPYDATASTRUCT pKMCopyData
;
226 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
227 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
228 if (pKMCopyData
== NULL
)
230 SetLastError(ERROR_OUTOFMEMORY
);
234 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
235 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
236 pKMCopyData
->lpData
= pKMCopyData
+ 1;
238 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
239 pUMCopyData
->cbData
);
241 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
253 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
255 switch (KMMsg
->message
)
260 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
270 MsgiUMToKMReply(PMSG UMMsg
, PMSG KMMsg
, LRESULT
*Result
)
272 MsgiUMToKMCleanup(UMMsg
, KMMsg
);
278 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
282 switch (UMMsg
->message
)
287 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
289 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
290 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
291 if (L
'A' == *((WCHAR
*) Class
))
293 Class
+= sizeof(WCHAR
);
294 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
298 ASSERT(L
'S' == *((WCHAR
*) Class
));
299 Class
+= sizeof(WCHAR
);
300 Cs
->lpszClass
= (LPCWSTR
) Class
;
307 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
308 if (DdeLparam
->Packed
)
310 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
311 DdeLparam
->Value
.Packed
.uiLo
,
312 DdeLparam
->Value
.Packed
.uiHi
);
316 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
323 PKMDDEEXECUTEDATA KMDdeExecuteData
;
327 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
328 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
329 if (NULL
== GlobalData
)
333 Data
= GlobalLock(GlobalData
);
336 GlobalFree(GlobalData
);
339 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
340 GlobalUnlock(GlobalData
);
341 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
343 GlobalFree(GlobalData
);
346 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
347 UMMsg
->lParam
= (LPARAM
) GlobalData
;
353 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
354 pKMCopyData
->lpData
= pKMCopyData
+ 1;
366 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
368 switch (KMMsg
->message
)
372 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
373 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
384 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
386 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
392 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
394 UNICODE_STRING UnicodeString
;
396 *UnicodeMsg
= *AnsiMsg
;
398 switch (AnsiMsg
->message
)
401 case WM_ASKCBFORMATNAME
:
403 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
404 AnsiMsg
->wParam
* sizeof(WCHAR
));
409 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
413 /* AnsiMsg->lParam is string (0-terminated) */
415 case WM_WININICHANGE
:
416 case WM_DEVMODECHANGE
:
422 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
423 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
428 case LB_ADDSTRING_LOWER
:
429 case LB_ADDSTRING_UPPER
:
430 case LB_INSERTSTRING
:
431 case LB_INSERTSTRING_UPPER
:
432 case LB_INSERTSTRING_LOWER
:
434 case LB_FINDSTRINGEXACT
:
435 case LB_SELECTSTRING
:
437 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
438 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
439 (dwStyle
& LBS_HASSTRINGS
))
441 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
442 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
448 case CB_INSERTSTRING
:
450 case CB_FINDSTRINGEXACT
:
451 case CB_SELECTSTRING
:
453 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
454 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
455 (dwStyle
& CBS_HASSTRINGS
))
457 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
458 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
468 CREATESTRUCTW cs
; /* new structure */
469 LPCWSTR lpszName
; /* allocated Name */
470 LPCWSTR lpszClass
; /* allocated Class */
473 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
478 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
479 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
481 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
482 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
484 if (!IS_ATOM(xs
->cs
.lpszClass
))
486 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
487 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
489 UnicodeMsg
->lParam
= (LPARAM
)xs
;
495 MDICREATESTRUCTW
*cs
=
496 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
503 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
505 if (!IS_ATOM(cs
->szClass
))
507 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
508 cs
->szClass
= UnicodeString
.Buffer
;
511 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
512 cs
->szTitle
= UnicodeString
.Buffer
;
514 UnicodeMsg
->lParam
= (LPARAM
)cs
;
524 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
526 UNICODE_STRING UnicodeString
;
528 switch (AnsiMsg
->message
)
531 case WM_ASKCBFORMATNAME
:
533 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
538 case WM_WININICHANGE
:
539 case WM_DEVMODECHANGE
:
545 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
546 RtlFreeUnicodeString(&UnicodeString
);
551 case LB_ADDSTRING_LOWER
:
552 case LB_ADDSTRING_UPPER
:
553 case LB_INSERTSTRING
:
554 case LB_INSERTSTRING_UPPER
:
555 case LB_INSERTSTRING_LOWER
:
557 case LB_FINDSTRINGEXACT
:
558 case LB_SELECTSTRING
:
560 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
561 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
562 (dwStyle
& LBS_HASSTRINGS
))
564 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
565 RtlFreeUnicodeString(&UnicodeString
);
571 case CB_INSERTSTRING
:
573 case CB_FINDSTRINGEXACT
:
574 case CB_SELECTSTRING
:
576 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
577 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
578 (dwStyle
& CBS_HASSTRINGS
))
580 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
581 RtlFreeUnicodeString(&UnicodeString
);
591 CREATESTRUCTW cs
; /* new structure */
592 LPWSTR lpszName
; /* allocated Name */
593 LPWSTR lpszClass
; /* allocated Class */
596 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
599 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
600 RtlFreeUnicodeString(&UnicodeString
);
604 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
605 RtlFreeUnicodeString(&UnicodeString
);
607 HeapFree(GetProcessHeap(), 0, xs
);
613 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
614 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
615 RtlFreeUnicodeString(&UnicodeString
);
616 if (!IS_ATOM(cs
->szClass
))
618 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
619 RtlFreeUnicodeString(&UnicodeString
);
621 HeapFree(GetProcessHeap(), 0, cs
);
631 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
633 switch (AnsiMsg
->message
)
636 case WM_ASKCBFORMATNAME
:
638 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
639 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
640 if (UnicodeMsg
->wParam
> 0 &&
641 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
642 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
644 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
650 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
657 MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
659 ANSI_STRING AnsiString
;
660 UNICODE_STRING UnicodeString
;
662 *AnsiMsg
= *UnicodeMsg
;
664 switch(UnicodeMsg
->message
)
673 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
674 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
679 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
681 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
682 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
683 if (! NT_SUCCESS(Status
))
685 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
688 CsA
->lpszName
= AnsiString
.Buffer
;
689 if (HIWORD((ULONG_PTR
)CsW
->lpszClass
) != 0)
691 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
692 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
693 if (! NT_SUCCESS(Status
))
695 RtlInitAnsiString(&AnsiString
, CsA
->lpszName
);
696 RtlFreeAnsiString(&AnsiString
);
697 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
700 CsA
->lpszClass
= AnsiString
.Buffer
;
702 AnsiMsg
->lParam
= (LPARAM
)CsA
;
707 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
708 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
709 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
710 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
721 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
722 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
728 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
733 case LB_ADDSTRING_LOWER
:
734 case LB_ADDSTRING_UPPER
:
735 case LB_INSERTSTRING
:
736 case LB_INSERTSTRING_UPPER
:
737 case LB_INSERTSTRING_LOWER
:
739 case LB_FINDSTRINGEXACT
:
740 case LB_SELECTSTRING
:
742 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
743 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
744 (dwStyle
& LBS_HASSTRINGS
))
746 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
747 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
753 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
759 case CB_INSERTSTRING
:
761 case CB_FINDSTRINGEXACT
:
762 case CB_SELECTSTRING
:
764 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
765 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
766 (dwStyle
& CBS_HASSTRINGS
))
768 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
769 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
775 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
782 MDICREATESTRUCTA
*cs
=
783 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
790 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
792 if (!IS_ATOM(cs
->szClass
))
794 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
795 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
801 cs
->szClass
= AnsiString
.Buffer
;
804 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
805 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
809 if (!IS_ATOM(cs
->szClass
))
811 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
812 RtlFreeAnsiString(&AnsiString
);
816 cs
->szTitle
= AnsiString
.Buffer
;
818 AnsiMsg
->lParam
= (LPARAM
)cs
;
828 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
830 ANSI_STRING AnsiString
;
832 switch(UnicodeMsg
->message
)
836 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
841 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
842 RtlFreeAnsiString(&AnsiString
);
850 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
851 RtlInitAnsiString(&AnsiString
, Cs
->lpszName
);
852 RtlFreeAnsiString(&AnsiString
);
853 if (HIWORD((ULONG_PTR
)Cs
->lpszClass
) != 0)
855 RtlInitAnsiString(&AnsiString
, Cs
->lpszClass
);
856 RtlFreeAnsiString(&AnsiString
);
858 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
863 case LB_ADDSTRING_LOWER
:
864 case LB_ADDSTRING_UPPER
:
865 case LB_INSERTSTRING
:
866 case LB_INSERTSTRING_UPPER
:
867 case LB_INSERTSTRING_LOWER
:
869 case LB_FINDSTRINGEXACT
:
870 case LB_SELECTSTRING
:
872 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
873 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
874 (dwStyle
& LBS_HASSTRINGS
))
876 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
877 RtlFreeAnsiString(&AnsiString
);
883 case CB_INSERTSTRING
:
885 case CB_FINDSTRINGEXACT
:
886 case CB_SELECTSTRING
:
888 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
889 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
890 (dwStyle
& CBS_HASSTRINGS
))
892 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
893 RtlFreeAnsiString(&AnsiString
);
900 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
901 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
902 RtlFreeAnsiString(&AnsiString
);
903 if (!IS_ATOM(cs
->szClass
))
905 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
906 RtlFreeAnsiString(&AnsiString
);
908 HeapFree(GetProcessHeap(), 0, cs
);
919 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
921 switch (UnicodeMsg
->message
)
924 case WM_ASKCBFORMATNAME
:
926 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
927 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
928 if (0 < AnsiMsg
->wParam
&&
929 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
931 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
937 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
942 typedef struct tagMSGCONVERSION
951 } MSGCONVERSION
, *PMSGCONVERSION
;
953 static PMSGCONVERSION MsgConversions
= NULL
;
954 static unsigned MsgConversionNumAlloc
= 0;
955 static unsigned MsgConversionNumUsed
= 0;
956 static CRITICAL_SECTION MsgConversionCrst
;
959 MsgConversionAdd(PMSGCONVERSION Conversion
)
963 EnterCriticalSection(&MsgConversionCrst
);
965 if (MsgConversionNumUsed
== MsgConversionNumAlloc
)
969 if (NULL
!= MsgConversions
)
971 New
= HeapReAlloc(GetProcessHeap(), 0, MsgConversions
,
972 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
976 New
= HeapAlloc(GetProcessHeap(), 0,
977 (MsgConversionNumAlloc
+ GROWBY
) * sizeof(MSGCONVERSION
));
982 LeaveCriticalSection(&MsgConversionCrst
);
985 MsgConversions
= New
;
986 /* zero out newly allocated part */
987 memset(MsgConversions
+ MsgConversionNumAlloc
, 0, GROWBY
* sizeof(MSGCONVERSION
));
988 MsgConversionNumAlloc
+= GROWBY
;
992 for (i
= 0; i
< MsgConversionNumAlloc
; i
++)
994 if (! MsgConversions
[i
].InUse
)
996 MsgConversions
[i
] = *Conversion
;
997 MsgConversions
[i
].InUse
= TRUE
;
998 MsgConversionNumUsed
++;
1002 LeaveCriticalSection(&MsgConversionCrst
);
1007 static void FASTCALL
1008 MsgConversionCleanup(CONST MSG
*Msg
, BOOL Ansi
, BOOL CheckMsgContents
, LRESULT
*Result
)
1011 PMSGCONVERSION Conversion
;
1014 EnterCriticalSection(&MsgConversionCrst
);
1015 for (Conversion
= MsgConversions
;
1016 Conversion
< MsgConversions
+ MsgConversionNumAlloc
;
1019 if (Conversion
->InUse
&&
1020 ((Ansi
&& Conversion
->Ansi
) ||
1021 (! Ansi
&& ! Conversion
->Ansi
)))
1023 Found
= (Conversion
->FinalMsg
== Msg
);
1024 if (! Found
&& CheckMsgContents
)
1028 Found
= (0 == memcmp(Msg
, &Conversion
->AnsiMsg
, sizeof(MSG
)));
1032 Found
= (0 == memcmp(Msg
, &Conversion
->UnicodeMsg
, sizeof(MSG
)));
1039 MsgiUnicodeToAnsiReply(&Conversion
->AnsiMsg
, &Conversion
->UnicodeMsg
,
1040 NULL
== Result
? &Dummy
: Result
);
1042 MsgiKMToUMReply(&Conversion
->KMMsg
, &Conversion
->UnicodeMsg
,
1043 NULL
== Result
? &Dummy
: Result
);
1044 if (0 != Conversion
->LParamSize
)
1046 NtFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &Conversion
->KMMsg
.lParam
,
1047 &Conversion
->LParamSize
, MEM_DECOMMIT
);
1049 Conversion
->InUse
= FALSE
;
1050 MsgConversionNumUsed
--;
1054 LeaveCriticalSection(&MsgConversionCrst
);
1062 GetMessageExtraInfo(VOID
)
1064 return (LPARAM
)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
);
1075 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1076 return(MAKELONG(ThreadData
->LastMessage
.pt
.x
, ThreadData
->LastMessage
.pt
.y
));
1084 GetMessageTime(VOID
)
1086 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1087 return(ThreadData
->LastMessage
.time
);
1088 // return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME);
1099 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1100 // FIXME("ISM %x\n",pcti);
1103 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1108 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1120 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1121 // FIXME("ISMEX %x\n",pcti);
1122 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1123 return ISMEX_NOSEND
;
1125 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1137 return NtUserCallOneParam(lResult
, ONEPARAM_ROUTINE_REPLYMESSAGE
);
1146 SetMessageExtraInfo(
1149 return NtUserSetMessageExtraInfo(lParam
);
1153 IntCallWindowProcW(BOOL IsAnsiProc
,
1163 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1164 LRESULT Result
= 0, PreResult
= 0;
1167 if (WndProc
== NULL
)
1169 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1174 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1178 Hook
= BeginIfHookedUserApiHook();
1182 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1184 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1189 UnicodeMsg
.hwnd
= hWnd
;
1190 UnicodeMsg
.message
= Msg
;
1191 UnicodeMsg
.wParam
= wParam
;
1192 UnicodeMsg
.lParam
= lParam
;
1193 if (! MsgiUnicodeToAnsiMessage(&AnsiMsg
, &UnicodeMsg
))
1198 if (Hook
&& MsgOverride
)
1203 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1205 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1213 if (PreResult
) goto Exit
;
1215 _SEH2_TRY
// wine does this.
1217 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1224 if (Hook
&& MsgOverride
)
1229 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1231 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1239 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1246 if (Hook
&& MsgOverride
)
1251 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1253 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1255 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1261 if (PreResult
) goto Exit
;
1265 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1267 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1272 if (Hook
&& MsgOverride
)
1277 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1279 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1281 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1289 if (Hook
) EndUserApiHook();
1293 static LRESULT FASTCALL
1294 IntCallWindowProcA(BOOL IsAnsiProc
,
1304 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1305 LRESULT Result
= 0, PreResult
= 0;
1308 if (WndProc
== NULL
)
1310 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1315 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1319 Hook
= BeginIfHookedUserApiHook();
1323 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1325 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1330 if (Hook
&& MsgOverride
)
1335 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1337 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1345 if (PreResult
) goto Exit
;
1349 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1351 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1356 if (Hook
&& MsgOverride
)
1361 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1363 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1373 AnsiMsg
.hwnd
= hWnd
;
1374 AnsiMsg
.message
= Msg
;
1375 AnsiMsg
.wParam
= wParam
;
1376 AnsiMsg
.lParam
= lParam
;
1377 if (! MsgiAnsiToUnicodeMessage(&UnicodeMsg
, &AnsiMsg
))
1382 if (Hook
&& MsgOverride
)
1387 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1389 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1391 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1397 if (PreResult
) goto Exit
;
1401 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1402 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1404 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1409 if (Hook
&& MsgOverride
)
1414 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1416 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1418 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1424 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1431 if (Hook
) EndUserApiHook();
1436 static LRESULT WINAPI
1437 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1443 Class
= DesktopPtrToUser(Wnd
->pcls
);
1446 This is the message exchange for user32. If there's a need to monitor messages,
1449 TRACE("HWND 0x%x, MSG %d, WPARAM 0x%x, LPARAM 0x%x, Ansi &d\n",hWnd
,Msg
,wParam
,lParam
,Ansi
);
1450 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1451 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1455 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1456 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1460 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1461 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1468 IsAnsi
= !Wnd
->Unicode
;
1469 WndProc
= Wnd
->lpfnWndProc
;
1474 IsAnsi
= !Wnd
->Unicode
;
1475 WndProc
= Wnd
->lpfnWndProc
;
1478 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1482 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1484 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1492 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1499 PCALLPROCDATA CallProc
;
1501 if (lpPrevWndFunc
== NULL
)
1503 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1507 pWnd
= ValidateHwnd(hWnd
);
1509 if (!IsCallProcHandle(lpPrevWndFunc
))
1510 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1513 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1514 if (CallProc
!= NULL
)
1516 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1517 CallProc
->pfnClientPrevious
,
1526 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1537 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1544 PCALLPROCDATA CallProc
;
1546 /* FIXME - can the first parameter be NULL? */
1547 if (lpPrevWndFunc
== NULL
)
1549 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1553 pWnd
= ValidateHwnd(hWnd
);
1555 if (!IsCallProcHandle(lpPrevWndFunc
))
1556 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1559 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1560 if (CallProc
!= NULL
)
1562 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1563 CallProc
->pfnClientPrevious
,
1572 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1583 DispatchMessageA(CONST MSG
*lpmsg
)
1589 if (lpmsg
->hwnd
!= NULL
)
1591 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1592 if (!Wnd
|| Wnd
->head
.pti
!= GetW32ThreadInfo())
1598 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1600 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1602 if ( lpmsg
->message
== WM_SYSTIMER
)
1603 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1605 _SEH2_TRY
// wine does this.
1607 Ret
= WndProc(lpmsg
->hwnd
,
1612 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1618 else if (Wnd
!= NULL
)
1620 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1622 Ret
= IntCallMessageProc(Wnd
,
1631 if (!MsgiAnsiToUnicodeMessage(&UnicodeMsg
, (LPMSG
)lpmsg
))
1636 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1638 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1652 DispatchMessageW(CONST MSG
*lpmsg
)
1657 if (lpmsg
->hwnd
!= NULL
)
1659 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1660 if (!Wnd
|| Wnd
->head
.pti
!= GetW32ThreadInfo())
1666 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1668 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1670 if ( lpmsg
->message
== WM_SYSTIMER
)
1671 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1675 Ret
= WndProc(lpmsg
->hwnd
,
1680 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1685 else if (Wnd
!= NULL
)
1687 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1689 Ret
= IntCallMessageProc(Wnd
,
1697 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
1708 GetMessageA(LPMSG lpMsg
,
1714 MSGCONVERSION Conversion
;
1715 NTUSERGETMESSAGEINFO Info
;
1716 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1718 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1719 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1720 if (-1 == (int) Res
)
1724 Conversion
.LParamSize
= Info
.LParamSize
;
1725 Conversion
.KMMsg
= Info
.Msg
;
1727 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1731 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1733 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1738 SetLastError( ERROR_NOACCESS
);
1741 *lpMsg
= Conversion
.AnsiMsg
;
1742 Conversion
.Ansi
= TRUE
;
1743 Conversion
.FinalMsg
= lpMsg
;
1744 MsgConversionAdd(&Conversion
);
1745 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1747 ThreadData
->LastMessage
= Info
.Msg
;
1758 GetMessageW(LPMSG lpMsg
,
1764 MSGCONVERSION Conversion
;
1765 NTUSERGETMESSAGEINFO Info
;
1766 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1768 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1769 Res
= NtUserGetMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1770 if (-1 == (int) Res
)
1774 Conversion
.LParamSize
= Info
.LParamSize
;
1775 Conversion
.KMMsg
= Info
.Msg
;
1777 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1783 SetLastError( ERROR_NOACCESS
);
1786 *lpMsg
= Conversion
.UnicodeMsg
;
1787 Conversion
.Ansi
= FALSE
;
1788 Conversion
.FinalMsg
= lpMsg
;
1789 MsgConversionAdd(&Conversion
);
1790 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1792 ThreadData
->LastMessage
= Info
.Msg
;
1803 PeekMessageA(LPMSG lpMsg
,
1810 MSGCONVERSION Conversion
;
1811 NTUSERGETMESSAGEINFO Info
;
1812 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1814 MsgConversionCleanup(lpMsg
, TRUE
, FALSE
, NULL
);
1815 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1816 if (-1 == (int) Res
|| !Res
)
1820 Conversion
.LParamSize
= Info
.LParamSize
;
1821 Conversion
.KMMsg
= Info
.Msg
;
1823 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1827 if (! MsgiUnicodeToAnsiMessage(&Conversion
.AnsiMsg
, &Conversion
.UnicodeMsg
))
1829 MsgiKMToUMCleanup(&Info
.Msg
, &Conversion
.UnicodeMsg
);
1834 SetLastError( ERROR_NOACCESS
);
1837 *lpMsg
= Conversion
.AnsiMsg
;
1838 Conversion
.Ansi
= TRUE
;
1839 Conversion
.FinalMsg
= lpMsg
;
1840 MsgConversionAdd(&Conversion
);
1841 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1843 ThreadData
->LastMessage
= Info
.Msg
;
1863 MSGCONVERSION Conversion
;
1864 NTUSERGETMESSAGEINFO Info
;
1865 PUSER32_THREAD_DATA ThreadData
= User32GetThreadData();
1867 MsgConversionCleanup(lpMsg
, FALSE
, FALSE
, NULL
);
1868 Res
= NtUserPeekMessage(&Info
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1869 if (-1 == (int) Res
|| !Res
)
1873 Conversion
.LParamSize
= Info
.LParamSize
;
1874 Conversion
.KMMsg
= Info
.Msg
;
1876 if (! MsgiKMToUMMessage(&Conversion
.KMMsg
, &Conversion
.UnicodeMsg
))
1882 SetLastError( ERROR_NOACCESS
);
1885 *lpMsg
= Conversion
.UnicodeMsg
;
1886 Conversion
.Ansi
= FALSE
;
1887 Conversion
.FinalMsg
= lpMsg
;
1888 MsgConversionAdd(&Conversion
);
1889 if (Res
&& lpMsg
->message
!= WM_PAINT
&& lpMsg
->message
!= WM_QUIT
)
1891 ThreadData
->LastMessage
= Info
.Msg
;
1898 // Worker function for post message.
1912 UMMsg
.message
= Msg
;
1913 UMMsg
.wParam
= wParam
;
1914 UMMsg
.lParam
= lParam
;
1915 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
1919 Result
= NtUserPostMessage( Wnd
,
1924 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
1943 AnsiMsg
.hwnd
= hWnd
;
1944 AnsiMsg
.message
= Msg
;
1945 AnsiMsg
.wParam
= wParam
;
1946 AnsiMsg
.lParam
= lParam
;
1948 if (!MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
1953 Ret
= PostMessageW( hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
1955 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1973 /* Check for combo box or a list box to send names. */
1974 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
1977 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
1978 combo/list box. Forces a call like DlgDirListComboBox.
1980 wParam
|= DDL_POSTMSGS
;
1981 return PostMessageWorker(hWnd
, Msg
, wParam
, lParam
);
1984 /* No drop files or current Process, just post message. */
1985 if ( (Msg
!= WM_DROPFILES
) ||
1986 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
1987 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
1989 return PostMessageWorker(hWnd
, Msg
, wParam
, lParam
);
1992 /* We have drop files and this is not the same process for this window. */
1994 /* Just incase, check wParam for Global memory handle and send size. */
1995 Ret
= SendMessageW( hWnd
,
1997 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
1998 (LPARAM
)wParam
); // Send wParam as lParam.
2000 if ( Ret
) return PostMessageWorker(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2013 NtUserCallOneParam(nExitCode
, ONEPARAM_ROUTINE_POSTQUITMESSAGE
);
2028 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2043 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2051 SendMessageW(HWND Wnd
,
2057 NTUSERSENDMESSAGEINFO Info
;
2060 PTHREADINFO ti
= GetW32ThreadInfo();
2062 Window
= ValidateHwnd(Wnd
);
2063 if (!Window
) return FALSE
;
2065 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2067 if ( Window
!= NULL
&&
2068 Window
->head
.pti
== ti
&&
2069 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
2070 !ISITHOOKED(WH_CALLWNDPROC
) &&
2071 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2072 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2074 /* NOTE: We can directly send messages to the window procedure
2075 if *all* the following conditions are met:
2077 * Window belongs to calling thread
2078 * The calling thread is not being hooked for CallWndProc
2079 * Not calling a server side proc:
2080 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2083 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2088 UMMsg
.message
= Msg
;
2089 UMMsg
.wParam
= wParam
;
2090 UMMsg
.lParam
= lParam
;
2091 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2096 Result
= NtUserSendMessage( KMMsg
.hwnd
,
2101 if (! Info
.HandledByKernel
)
2103 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2104 /* We need to send the message ourselves */
2105 Result
= IntCallWindowProcW( Info
.Ansi
,
2113 else if (! MsgiUMToKMReply(&UMMsg
, &KMMsg
, &Result
))
2126 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2131 NTUSERSENDMESSAGEINFO Info
;
2133 PTHREADINFO ti
= GetW32ThreadInfo();
2135 Window
= ValidateHwnd(Wnd
);
2136 if (!Window
) return FALSE
;
2138 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2140 if ( Window
!= NULL
&&
2141 Window
->head
.pti
== ti
&&
2142 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
2143 !ISITHOOKED(WH_CALLWNDPROC
) &&
2144 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2145 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2147 /* NOTE: We can directly send messages to the window procedure
2148 if *all* the following conditions are met:
2150 * Window belongs to calling thread
2151 * The calling thread is not being hooked for CallWndProc
2152 * Not calling a server side proc:
2153 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2156 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2161 AnsiMsg
.message
= Msg
;
2162 AnsiMsg
.wParam
= wParam
;
2163 AnsiMsg
.lParam
= lParam
;
2164 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2169 if (! MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2171 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2175 Result
= NtUserSendMessage( KMMsg
.hwnd
,
2180 if (! Info
.HandledByKernel
)
2182 /* We need to send the message ourselves */
2185 /* Ansi message and Ansi window proc, that's easy. Clean up
2186 the Unicode message though */
2187 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2188 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2189 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, Window
, Wnd
, Msg
, wParam
, lParam
);
2193 /* Unicode winproc. Although we started out with an Ansi message we
2194 already converted it to Unicode for the kernel call. Reuse that
2195 message to avoid another conversion */
2196 Result
= IntCallWindowProcW( Info
.Ansi
,
2203 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2209 /* Message sent by kernel. Convert back to Ansi */
2210 else if (! MsgiUMToKMReply(&UcMsg
, &KMMsg
, &Result
) ||
2211 ! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2224 SendMessageCallbackA(
2229 SENDASYNCPROC lpCallBack
,
2232 CALL_BACK_INFO CallBackInfo
;
2234 CallBackInfo
.CallBack
= lpCallBack
;
2235 CallBackInfo
.Context
= dwData
;
2237 return NtUserMessageCall(hWnd
,
2241 (ULONG_PTR
)&CallBackInfo
,
2242 FNID_SENDMESSAGECALLBACK
,
2251 SendMessageCallbackW(
2256 SENDASYNCPROC lpCallBack
,
2260 CALL_BACK_INFO CallBackInfo
;
2262 CallBackInfo
.CallBack
= lpCallBack
;
2263 CallBackInfo
.Context
= dwData
;
2265 return NtUserMessageCall(hWnd
,
2269 (ULONG_PTR
)&CallBackInfo
,
2270 FNID_SENDMESSAGECALLBACK
,
2279 SendMessageTimeoutA(
2286 PDWORD_PTR lpdwResult
)
2291 NTUSERSENDMESSAGEINFO Info
;
2293 AnsiMsg
.hwnd
= hWnd
;
2294 AnsiMsg
.message
= Msg
;
2295 AnsiMsg
.wParam
= wParam
;
2296 AnsiMsg
.lParam
= lParam
;
2297 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2302 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2305 Result
= NtUserSendMessageTimeout(UcMsg
.hwnd
, UcMsg
.message
,
2306 UcMsg
.wParam
, UcMsg
.lParam
,
2307 fuFlags
, uTimeout
, (ULONG_PTR
*)lpdwResult
, &Info
);
2310 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2313 if (! Info
.HandledByKernel
)
2316 pWnd
= ValidateHwnd(hWnd
);
2317 /* We need to send the message ourselves */
2320 /* Ansi message and Ansi window proc, that's easy. Clean up
2321 the Unicode message though */
2322 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2323 Result
= IntCallWindowProcA(Info
.Ansi
, Info
.Proc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
2327 /* Unicode winproc. Although we started out with an Ansi message we
2328 already converted it to Unicode for the kernel call. Reuse that
2329 message to avoid another conversion */
2330 Result
= IntCallWindowProcW( Info
.Ansi
,
2337 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2339 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2344 *lpdwResult
= Result
;
2349 /* Message sent by kernel. Convert back to Ansi */
2350 if (! MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
))
2352 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2357 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2367 SendMessageTimeoutW(
2374 PDWORD_PTR lpdwResult
)
2376 NTUSERSENDMESSAGEINFO Info
;
2379 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2382 Result
= NtUserSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, fuFlags
, uTimeout
,
2384 if (! Info
.HandledByKernel
)
2387 pWnd
= ValidateHwnd(hWnd
);
2388 /* We need to send the message ourselves */
2389 Result
= IntCallWindowProcW(Info
.Ansi
, Info
.Proc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
2391 *lpdwResult
= Result
;
2393 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2397 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2415 AnsiMsg
.hwnd
= hWnd
;
2416 AnsiMsg
.message
= Msg
;
2417 AnsiMsg
.wParam
= wParam
;
2418 AnsiMsg
.lParam
= lParam
;
2419 if (! MsgiAnsiToUnicodeMessage(&UcMsg
, &AnsiMsg
))
2423 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2425 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2445 UMMsg
.message
= Msg
;
2446 UMMsg
.wParam
= wParam
;
2447 UMMsg
.lParam
= lParam
;
2448 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2452 Result
= NtUserMessageCall( hWnd
,
2457 FNID_SENDNOTIFYMESSAGE
,
2460 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2469 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2471 switch (lpMsg
->message
)
2477 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2480 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2481 SetLastError(ERROR_INVALID_PARAMETER
);
2491 TranslateMessage(CONST MSG
*lpMsg
)
2495 // Ref: msdn ImmGetVirtualKey:
2496 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2498 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2499 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2504 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2514 RegisterWindowMessageA(LPCSTR lpString
)
2516 UNICODE_STRING String
;
2520 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
2525 Atom
= NtUserRegisterWindowMessage(&String
);
2526 RtlFreeUnicodeString(&String
);
2535 RegisterWindowMessageW(LPCWSTR lpString
)
2537 UNICODE_STRING String
;
2539 RtlInitUnicodeString(&String
, lpString
);
2540 return(NtUserRegisterWindowMessage(&String
));
2549 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2556 ReleaseCapture(VOID
)
2558 NtUserSetCapture(NULL
);
2568 RealGetQueueStatus(UINT flags
)
2570 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_ALLINPUT
))
2572 SetLastError( ERROR_INVALID_FLAGS
);
2575 return NtUserCallOneParam(flags
, ONEPARAM_ROUTINE_GETQUEUESTATUS
);
2582 BOOL WINAPI
GetInputState(VOID
)
2584 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2586 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2587 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2594 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2596 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2599 PCLIENTINFO pci
= GetWin32ClientInfo();
2601 /* Make sure we don't try to access mem beyond what we were given */
2602 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2604 return STATUS_INFO_LENGTH_MISMATCH
;
2607 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2608 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2609 KMMsg
.message
= CallbackArgs
->Msg
;
2610 KMMsg
.wParam
= CallbackArgs
->wParam
;
2611 /* Check if lParam is really a pointer and adjust it if it is */
2612 if (0 <= CallbackArgs
->lParamBufferSize
)
2614 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2615 + CallbackArgs
->lParamBufferSize
)
2617 return STATUS_INFO_LENGTH_MISMATCH
;
2619 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2623 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2625 return STATUS_INFO_LENGTH_MISMATCH
;
2627 KMMsg
.lParam
= CallbackArgs
->lParam
;
2630 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2632 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2633 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2636 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2640 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2641 pWnd
= pci
->CallbackWnd
.pWnd
;
2643 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
2651 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2655 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2661 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
2663 /* Function does nothing on 32 bit windows */
2666 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
2667 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
2669 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
2671 //NtUserRealInternalGetMessageProc NtUserRealInternalGetMessage;
2672 //NtUserRealWaitMessageExProc NtUserRealWaitMessageEx;
2673 RealGetQueueStatusProc RealGetQueueStatus
;
2674 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
2675 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
2679 RealMsgWaitForMultipleObjectsEx(
2681 CONST HANDLE
*pHandles
,
2682 DWORD dwMilliseconds
,
2686 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
2688 CRITICAL_SECTION gcsMPH
;
2689 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
2690 DWORD gcLoadMPH
= 0;
2691 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
2692 //NtUserRealInternalGetMessage,
2693 //NtUserRealInternalWaitMessageEx,
2695 RealMsgWaitForMultipleObjectsEx
2698 DWORD gfMessagePumpHook
= 0;
2700 BOOL WINAPI
IsInsideMessagePumpHook()
2701 { // FF uses this and polls it when Min/Max
2702 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2703 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
2706 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
2708 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
2709 //Addresses->NtUserRealInternalGetMessage = (NtUserRealInternalGetMessageProc)NtUserRealInternalGetMessage;
2710 //Addresses->NtUserRealWaitMessageEx = (NtUserRealWaitMessageExProc)NtUserRealInternalWaitMessageEx;
2711 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
2712 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
2715 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
2717 EnterCriticalSection(&gcsMPH
);
2719 SetLastError(ERROR_INVALID_PARAMETER
);
2720 LeaveCriticalSection(&gcsMPH
);
2724 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
2726 ResetMessagePumpHook(&Addresses
);
2727 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
2728 LeaveCriticalSection(&gcsMPH
);
2731 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
2733 if(gpfnInitMPH
!= Hook
) {
2734 LeaveCriticalSection(&gcsMPH
);
2738 if(NtUserCallNoParam(NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
)) {
2739 LeaveCriticalSection(&gcsMPH
);
2743 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
2745 LeaveCriticalSection(&gcsMPH
);
2749 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
2751 EnterCriticalSection(&gcsMPH
);
2753 if(NtUserCallNoParam(NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
)) {
2756 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
2757 gpfnInitMPH(TRUE
, NULL
);
2758 ResetMessagePumpHook(&gmph
);
2761 LeaveCriticalSection(&gcsMPH
);
2765 LeaveCriticalSection(&gcsMPH
);
2769 DWORD WINAPI
GetQueueStatus(UINT flags
)
2771 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2775 * @name RealMsgWaitForMultipleObjectsEx
2777 * Wait either for either message arrival or for one of the passed events
2781 * Number of handles in the pHandles array.
2783 * Handles of events to wait for.
2784 * @param dwMilliseconds
2787 * Mask specifying on which message events we should wakeup.
2789 * Wait type (see MWMO_* constants).
2795 RealMsgWaitForMultipleObjectsEx(
2797 const HANDLE
*pHandles
,
2798 DWORD dwMilliseconds
,
2802 LPHANDLE RealHandles
;
2803 HANDLE MessageQueueHandle
;
2806 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2808 SetLastError(ERROR_INVALID_PARAMETER
);
2813 if (dwFlags & MWMO_INPUTAVAILABLE)
2815 RealGetQueueStatus(dwWakeMask);
2819 MessageQueueHandle
= NtUserMsqSetWakeMask(dwWakeMask
);
2820 if (MessageQueueHandle
== NULL
)
2822 SetLastError(0); /* ? */
2826 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2827 if (RealHandles
== NULL
)
2829 NtUserMsqClearWakeMask();
2830 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2834 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2835 RealHandles
[nCount
] = MessageQueueHandle
;
2837 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2838 dwFlags
& MWMO_WAITALL
,
2839 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2841 HeapFree(GetProcessHeap(), 0, RealHandles
);
2842 NtUserMsqClearWakeMask();
2851 MsgWaitForMultipleObjectsEx(
2853 CONST HANDLE
*lpHandles
,
2854 DWORD dwMilliseconds
,
2858 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2865 MsgWaitForMultipleObjects(
2867 CONST HANDLE
*lpHandles
,
2869 DWORD dwMilliseconds
,
2872 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2873 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2877 BOOL FASTCALL
MessageInit(VOID
)
2879 InitializeCriticalSection(&DdeCrst
);
2880 InitializeCriticalSection(&MsgConversionCrst
);
2881 InitializeCriticalSection(&gcsMPH
);
2886 VOID FASTCALL
MessageCleanup(VOID
)
2888 DeleteCriticalSection(&DdeCrst
);
2889 DeleteCriticalSection(&MsgConversionCrst
);
2890 DeleteCriticalSection(&gcsMPH
);
2893 /***********************************************************************
2896 * Convert the wparam of an ASCII message to Unicode.
2899 map_wparam_AtoW( UINT message
, WPARAM wparam
)
2904 case EM_SETPASSWORDCHAR
:
2908 case WM_SYSDEADCHAR
:
2913 ch
[0] = (wparam
& 0xff);
2914 ch
[1] = (wparam
>> 8);
2915 MultiByteToWideChar(CP_ACP
, 0, ch
, 2, wch
, 2);
2916 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
2923 ch
[0] = (wparam
>> 8);
2924 ch
[1] = (wparam
& 0xff);
2925 if (ch
[0]) MultiByteToWideChar(CP_ACP
, 0, ch
, 2, &wch
, 1);
2926 else MultiByteToWideChar(CP_ACP
, 0, &ch
[1], 1, &wch
, 1);
2927 wparam
= MAKEWPARAM( wch
, HIWORD(wparam
) );
2938 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
2941 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
2942 return IsDialogMessageW( hwndDlg
, &msg
);
2947 IntBroadcastSystemMessage(
2949 LPDWORD lpdwRecipients
,
2957 DWORD recips
= BSM_ALLCOMPONENTS
;
2958 BOOL ret
= -1; // Set to return fail
2959 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
2960 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
2961 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
2963 if ((dwflags
& ~all_flags
) ||
2964 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
2966 SetLastError(ERROR_INVALID_PARAMETER
);
2970 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
2972 SetLastError(ERROR_INVALID_PARAMETER
);
2976 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
2978 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
2980 if (!lpdwRecipients
)
2981 lpdwRecipients
= &recips
;
2983 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
2985 SetLastError(ERROR_INVALID_PARAMETER
);
2989 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2991 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
2993 SetLastError(ERROR_INVALID_PARAMETER
);
3000 parm
.flags
= dwflags
;
3001 parm
.recipients
= *lpdwRecipients
;
3003 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
3005 if (*lpdwRecipients
& BSM_APPLICATIONS
)
3007 ret
= NtUserMessageCall(GetDesktopWindow(),
3012 FNID_BROADCASTSYSTEMMESSAGE
,
3018 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3020 pBSMInfo
->hdesk
= parm
.hDesk
;
3021 pBSMInfo
->hwnd
= parm
.hWnd
;
3032 BroadcastSystemMessageA(
3034 LPDWORD lpdwRecipients
,
3039 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
3047 BroadcastSystemMessageW(
3049 LPDWORD lpdwRecipients
,
3054 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3062 BroadcastSystemMessageExA(
3064 LPDWORD lpdwRecipients
,
3070 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3078 BroadcastSystemMessageExW(
3080 LPDWORD lpdwRecipients
,
3086 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);