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
);
17 /* flag for messages that contain pointers */
18 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
20 #define SET(msg) (1 << ((msg) & 31))
22 static const unsigned int message_pointer_flags
[] =
25 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
26 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
28 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
31 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
32 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
34 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
36 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
38 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
40 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
42 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
48 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
49 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
50 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
54 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
55 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
56 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
58 SET(LB_FINDSTRINGEXACT
),
64 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
66 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
67 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
81 SET(WM_ASKCBFORMATNAME
)
84 /* check whether a given message type includes pointers */
85 static inline int is_pointer_message( UINT message
)
87 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
88 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
91 /* DDE message exchange
93 * - Session initialization
94 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
95 * this message contains a pair of global atoms, the Application and Topic atoms.
96 * The client must destroy the atoms.
97 * Server window proc handles the WM_DDE_INITIATE message and if the Application
98 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
99 * of the reply message contains another pair of global atoms (Application and
100 * Topic again), which must be destroyed by the server.
103 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
104 * is a global memory handle containing the string to execute. After the command has
105 * been executed the server posts a WM_DDE_ACK message to the client, which contains
106 * a packed lParam which in turn contains that global memory handle. The client takes
107 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
108 * it and the global memory handle.
109 * This might work nice and easy in Win3.1, but things are more complicated for NT.
110 * Global memory handles in NT are not really global, they're still local to the
111 * process. So, what happens under the hood is that PostMessage must handle the
112 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
113 * area, repack that into a new structure together with the original memory handle
114 * and pass that off to the win32k. Win32k will marshall that data over to the target
115 * (server) process where it will be unpacked and stored in a newly allocated global
116 * memory area. The handle of that area will then be sent to the window proc, after
117 * storing it together with the "original" (client) handle in a table.
118 * The server will eventually post the WM_DDE_ACK response, containing the global
119 * memory handle it received. PostMessage must then lookup that memory handle (only
120 * valid in the server process) and replace it with the corresponding client memory
121 * handle. To avoid memory leaks, the server-side global memory block must be freed.
122 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
123 * individual components are handed to win32k.sys to post to the client side. Since
124 * the server side app hands over ownership of the packed lParam when it calls
125 * PostMessage(), the packed lParam needs to be freed on the server side too.
126 * When the WM_DDE_ACK message (containing the client-side global memory handle)
127 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
128 * to the client side window proc which is expected to free/reuse it.
131 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
132 * to the memory handle, we keep track (in the server side) of all pairs of handle
133 * used (the client passes its value and the content of the memory handle), and
134 * the server stored both values (the client, and the local one, created after the
135 * content). When a ACK message is generated, the list of pair is searched for a
136 * matching pair, so that the client memory handle can be returned.
139 typedef struct tagDDEPAIR
143 } DDEPAIR
, *PDDEPAIR
;
145 static PDDEPAIR DdePairs
= NULL
;
146 static unsigned DdeNumAlloc
= 0;
147 static unsigned DdeNumUsed
= 0;
148 static CRITICAL_SECTION DdeCrst
;
151 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
155 EnterCriticalSection(&DdeCrst
);
157 /* now remember the pair of hMem on both sides */
158 if (DdeNumUsed
== DdeNumAlloc
)
162 if (NULL
!= DdePairs
)
164 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
165 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
169 New
= HeapAlloc(GetProcessHeap(), 0,
170 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
175 LeaveCriticalSection(&DdeCrst
);
179 /* zero out newly allocated part */
180 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
181 DdeNumAlloc
+= GROWBY
;
185 for (i
= 0; i
< DdeNumAlloc
; i
++)
187 if (NULL
== DdePairs
[i
].ServerMem
)
189 DdePairs
[i
].ClientMem
= ClientMem
;
190 DdePairs
[i
].ServerMem
= ServerMem
;
195 LeaveCriticalSection(&DdeCrst
);
200 static HGLOBAL FASTCALL
201 DdeGetPair(HGLOBAL ServerMem
)
206 EnterCriticalSection(&DdeCrst
);
207 for (i
= 0; i
< DdeNumAlloc
; i
++)
209 if (DdePairs
[i
].ServerMem
== ServerMem
)
212 DdePairs
[i
].ServerMem
= 0;
214 Ret
= DdePairs
[i
].ClientMem
;
218 LeaveCriticalSection(&DdeCrst
);
225 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
229 switch (UMMsg
->message
)
233 PKMDDELPARAM DdeLparam
;
234 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
235 if (NULL
== DdeLparam
)
241 DdeLparam
->Packed
= TRUE
;
242 if (! UnpackDDElParam(UMMsg
->message
, UMMsg
->lParam
,
243 &DdeLparam
->Value
.Packed
.uiLo
,
244 &DdeLparam
->Value
.Packed
.uiHi
))
248 if (0 != HIWORD(DdeLparam
->Value
.Packed
.uiHi
))
250 /* uiHi should contain a hMem from WM_DDE_EXECUTE */
251 HGLOBAL h
= DdeGetPair((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
254 GlobalFree((HGLOBAL
)(ULONG_PTR
)DdeLparam
->Value
.Packed
.uiHi
);
255 DdeLparam
->Value
.Packed
.uiHi
= (UINT_PTR
) h
;
258 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
262 DdeLparam
->Packed
= FALSE
;
263 DdeLparam
->Value
.Unpacked
= UMMsg
->lParam
;
265 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
272 PKMDDEEXECUTEDATA KMDdeExecuteData
;
275 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
276 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
279 SetLastError(ERROR_INVALID_HANDLE
);
282 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
283 if (NULL
== KMDdeExecuteData
)
285 SetLastError(ERROR_OUTOFMEMORY
);
288 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
289 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
290 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
291 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
292 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
293 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
299 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
300 PCOPYDATASTRUCT pKMCopyData
;
302 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
303 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
304 if (pKMCopyData
== NULL
)
306 SetLastError(ERROR_OUTOFMEMORY
);
310 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
311 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
312 pKMCopyData
->lpData
= pKMCopyData
+ 1;
314 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
315 pUMCopyData
->cbData
);
317 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
330 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
332 switch (KMMsg
->message
)
337 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
347 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
351 switch (UMMsg
->message
)
356 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
358 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
359 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
360 if (L
'A' == *((WCHAR
*) Class
))
362 Class
+= sizeof(WCHAR
);
363 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
367 ASSERT(L
'S' == *((WCHAR
*) Class
));
368 Class
+= sizeof(WCHAR
);
369 Cs
->lpszClass
= (LPCWSTR
) Class
;
376 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
377 if (DdeLparam
->Packed
)
379 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
,
380 DdeLparam
->Value
.Packed
.uiLo
,
381 DdeLparam
->Value
.Packed
.uiHi
);
385 UMMsg
->lParam
= DdeLparam
->Value
.Unpacked
;
392 PKMDDEEXECUTEDATA KMDdeExecuteData
;
396 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
397 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
398 if (NULL
== GlobalData
)
402 Data
= GlobalLock(GlobalData
);
405 GlobalFree(GlobalData
);
408 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
409 GlobalUnlock(GlobalData
);
410 if (! DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
412 GlobalFree(GlobalData
);
415 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
416 UMMsg
->lParam
= (LPARAM
) GlobalData
;
422 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
423 pKMCopyData
->lpData
= pKMCopyData
+ 1;
435 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
437 switch (KMMsg
->message
)
441 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
442 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
453 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
455 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
461 MsgiAnsiToUnicodeMessage(HWND hwnd
, LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
463 UNICODE_STRING UnicodeString
;
465 *UnicodeMsg
= *AnsiMsg
;
467 switch (AnsiMsg
->message
)
470 case WM_ASKCBFORMATNAME
:
472 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
473 AnsiMsg
->wParam
* sizeof(WCHAR
));
478 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
482 /* AnsiMsg->lParam is string (0-terminated) */
484 case WM_WININICHANGE
:
485 case WM_DEVMODECHANGE
:
491 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
492 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
497 case LB_ADDSTRING_LOWER
:
498 case LB_ADDSTRING_UPPER
:
499 case LB_INSERTSTRING
:
500 case LB_INSERTSTRING_UPPER
:
501 case LB_INSERTSTRING_LOWER
:
503 case LB_FINDSTRINGEXACT
:
504 case LB_SELECTSTRING
:
506 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
507 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
508 (dwStyle
& LBS_HASSTRINGS
))
510 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
511 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
517 case CB_INSERTSTRING
:
519 case CB_FINDSTRINGEXACT
:
520 case CB_SELECTSTRING
:
522 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
523 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
524 (dwStyle
& CBS_HASSTRINGS
))
526 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
527 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
535 MDICREATESTRUCTW mdi_cs
;
538 CREATESTRUCTW cs
; /* new structure */
539 LPCWSTR lpszName
; /* allocated Name */
540 LPCWSTR lpszClass
; /* allocated Class */
543 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
548 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
549 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
551 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
552 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
554 if (!IS_ATOM(xs
->cs
.lpszClass
))
556 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
557 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
560 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
562 mdi_cs
= *(MDICREATESTRUCTW
*)xs
->cs
.lpCreateParams
;
563 mdi_cs
.szTitle
= xs
->cs
.lpszName
;
564 mdi_cs
.szClass
= xs
->cs
.lpszClass
;
565 xs
->cs
.lpCreateParams
= &mdi_cs
;
568 UnicodeMsg
->lParam
= (LPARAM
)xs
;
574 MDICREATESTRUCTW
*cs
=
575 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
582 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
584 if (!IS_ATOM(cs
->szClass
))
586 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
587 cs
->szClass
= UnicodeString
.Buffer
;
590 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
591 cs
->szTitle
= UnicodeString
.Buffer
;
593 UnicodeMsg
->lParam
= (LPARAM
)cs
;
603 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
605 UNICODE_STRING UnicodeString
;
607 switch (AnsiMsg
->message
)
610 case WM_ASKCBFORMATNAME
:
612 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
617 case WM_WININICHANGE
:
618 case WM_DEVMODECHANGE
:
624 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
625 RtlFreeUnicodeString(&UnicodeString
);
630 case LB_ADDSTRING_LOWER
:
631 case LB_ADDSTRING_UPPER
:
632 case LB_INSERTSTRING
:
633 case LB_INSERTSTRING_UPPER
:
634 case LB_INSERTSTRING_LOWER
:
636 case LB_FINDSTRINGEXACT
:
637 case LB_SELECTSTRING
:
639 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
640 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
641 (dwStyle
& LBS_HASSTRINGS
))
643 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
644 RtlFreeUnicodeString(&UnicodeString
);
650 case CB_INSERTSTRING
:
652 case CB_FINDSTRINGEXACT
:
653 case CB_SELECTSTRING
:
655 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
656 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
657 (dwStyle
& CBS_HASSTRINGS
))
659 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
660 RtlFreeUnicodeString(&UnicodeString
);
670 CREATESTRUCTW cs
; /* new structure */
671 LPWSTR lpszName
; /* allocated Name */
672 LPWSTR lpszClass
; /* allocated Class */
675 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
678 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
679 RtlFreeUnicodeString(&UnicodeString
);
683 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
684 RtlFreeUnicodeString(&UnicodeString
);
686 HeapFree(GetProcessHeap(), 0, xs
);
692 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
693 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
694 RtlFreeUnicodeString(&UnicodeString
);
695 if (!IS_ATOM(cs
->szClass
))
697 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
698 RtlFreeUnicodeString(&UnicodeString
);
700 HeapFree(GetProcessHeap(), 0, cs
);
710 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
712 switch (AnsiMsg
->message
)
715 case WM_ASKCBFORMATNAME
:
717 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
718 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
719 if (UnicodeMsg
->wParam
> 0 &&
720 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1,
721 AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
723 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
729 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
736 MsgiUnicodeToAnsiMessage(HWND hwnd
, LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
738 ANSI_STRING AnsiString
;
739 UNICODE_STRING UnicodeString
;
741 *AnsiMsg
= *UnicodeMsg
;
743 switch(UnicodeMsg
->message
)
748 MDICREATESTRUCTA mdi_cs
;
753 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
754 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
759 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
761 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
762 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
763 if (! NT_SUCCESS(Status
))
765 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
768 CsA
->lpszName
= AnsiString
.Buffer
;
769 if (HIWORD((ULONG_PTR
)CsW
->lpszClass
) != 0)
771 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
772 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
773 if (! NT_SUCCESS(Status
))
775 RtlInitAnsiString(&AnsiString
, CsA
->lpszName
);
776 RtlFreeAnsiString(&AnsiString
);
777 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
780 CsA
->lpszClass
= AnsiString
.Buffer
;
783 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
785 mdi_cs
= *(MDICREATESTRUCTA
*)CsW
->lpCreateParams
;
786 mdi_cs
.szTitle
= CsA
->lpszName
;
787 mdi_cs
.szClass
= CsA
->lpszClass
;
788 CsA
->lpCreateParams
= &mdi_cs
;
791 AnsiMsg
->lParam
= (LPARAM
)CsA
;
796 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
797 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
798 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
799 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
810 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
811 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
817 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
822 case LB_ADDSTRING_LOWER
:
823 case LB_ADDSTRING_UPPER
:
824 case LB_INSERTSTRING
:
825 case LB_INSERTSTRING_UPPER
:
826 case LB_INSERTSTRING_LOWER
:
828 case LB_FINDSTRINGEXACT
:
829 case LB_SELECTSTRING
:
831 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
832 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
833 (dwStyle
& LBS_HASSTRINGS
))
835 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
836 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
842 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
848 case CB_INSERTSTRING
:
850 case CB_FINDSTRINGEXACT
:
851 case CB_SELECTSTRING
:
853 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
854 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
855 (dwStyle
& CBS_HASSTRINGS
))
857 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
858 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
864 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
871 MDICREATESTRUCTA
*cs
=
872 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
879 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
881 if (!IS_ATOM(cs
->szClass
))
883 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
884 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
890 cs
->szClass
= AnsiString
.Buffer
;
893 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
894 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
898 if (!IS_ATOM(cs
->szClass
))
900 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
901 RtlFreeAnsiString(&AnsiString
);
905 cs
->szTitle
= AnsiString
.Buffer
;
907 AnsiMsg
->lParam
= (LPARAM
)cs
;
917 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
919 ANSI_STRING AnsiString
;
921 switch(UnicodeMsg
->message
)
925 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
930 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
931 RtlFreeAnsiString(&AnsiString
);
939 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
940 RtlInitAnsiString(&AnsiString
, Cs
->lpszName
);
941 RtlFreeAnsiString(&AnsiString
);
942 if (HIWORD((ULONG_PTR
)Cs
->lpszClass
) != 0)
944 RtlInitAnsiString(&AnsiString
, Cs
->lpszClass
);
945 RtlFreeAnsiString(&AnsiString
);
947 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
952 case LB_ADDSTRING_LOWER
:
953 case LB_ADDSTRING_UPPER
:
954 case LB_INSERTSTRING
:
955 case LB_INSERTSTRING_UPPER
:
956 case LB_INSERTSTRING_LOWER
:
958 case LB_FINDSTRINGEXACT
:
959 case LB_SELECTSTRING
:
961 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
962 if (!(dwStyle
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) &&
963 (dwStyle
& LBS_HASSTRINGS
))
965 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
966 RtlFreeAnsiString(&AnsiString
);
972 case CB_INSERTSTRING
:
974 case CB_FINDSTRINGEXACT
:
975 case CB_SELECTSTRING
:
977 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
978 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
979 (dwStyle
& CBS_HASSTRINGS
))
981 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
982 RtlFreeAnsiString(&AnsiString
);
989 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
990 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
991 RtlFreeAnsiString(&AnsiString
);
992 if (!IS_ATOM(cs
->szClass
))
994 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
995 RtlFreeAnsiString(&AnsiString
);
997 HeapFree(GetProcessHeap(), 0, cs
);
1007 static BOOL FASTCALL
1008 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
1010 switch (UnicodeMsg
->message
)
1013 case WM_ASKCBFORMATNAME
:
1015 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1016 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1017 if (0 < AnsiMsg
->wParam
&&
1018 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
1020 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
1026 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
1036 GetMessageExtraInfo(VOID
)
1038 return NtUserxGetMessageExtraInfo();
1049 return NtUserxGetMessagePos();
1057 GetMessageTime(VOID
)
1059 return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME
);
1070 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1073 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1078 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1090 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1091 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1092 return ISMEX_NOSEND
;
1094 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1103 ReplyMessage(LRESULT lResult
)
1105 return NtUserxReplyMessage(lResult
);
1114 SetMessageExtraInfo(
1117 return NtUserxSetMessageExtraInfo(lParam
);
1121 IntCallWindowProcW(BOOL IsAnsiProc
,
1131 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1132 LRESULT Result
= 0, PreResult
= 0;
1135 if (WndProc
== NULL
)
1137 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1142 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1146 Hook
= BeginIfHookedUserApiHook();
1150 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1152 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1157 UnicodeMsg
.hwnd
= hWnd
;
1158 UnicodeMsg
.message
= Msg
;
1159 UnicodeMsg
.wParam
= wParam
;
1160 UnicodeMsg
.lParam
= lParam
;
1161 if (! MsgiUnicodeToAnsiMessage(hWnd
, &AnsiMsg
, &UnicodeMsg
))
1166 if (Hook
&& MsgOverride
)
1171 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1173 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1181 if (PreResult
) goto Exit
;
1183 _SEH2_TRY
// wine does this.
1185 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1192 if (Hook
&& MsgOverride
)
1197 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1199 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1207 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1214 if (Hook
&& MsgOverride
)
1219 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1221 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1223 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1229 if (PreResult
) goto Exit
;
1233 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1240 if (Hook
&& MsgOverride
)
1245 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1247 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1249 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1257 if (Hook
) EndUserApiHook();
1261 static LRESULT FASTCALL
1262 IntCallWindowProcA(BOOL IsAnsiProc
,
1272 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1273 LRESULT Result
= 0, PreResult
= 0;
1276 if (WndProc
== NULL
)
1278 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1283 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1287 Hook
= BeginIfHookedUserApiHook();
1291 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1293 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1298 if (Hook
&& MsgOverride
)
1303 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1305 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1307 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1313 if (PreResult
) goto Exit
;
1317 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1324 if (Hook
&& MsgOverride
)
1329 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1331 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1341 AnsiMsg
.hwnd
= hWnd
;
1342 AnsiMsg
.message
= Msg
;
1343 AnsiMsg
.wParam
= wParam
;
1344 AnsiMsg
.lParam
= lParam
;
1345 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UnicodeMsg
, &AnsiMsg
))
1350 if (Hook
&& MsgOverride
)
1355 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1357 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1359 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1365 if (PreResult
) goto Exit
;
1369 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1370 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1377 if (Hook
&& MsgOverride
)
1382 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1384 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1392 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1399 if (Hook
) EndUserApiHook();
1404 static LRESULT WINAPI
1405 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1411 Class
= DesktopPtrToUser(Wnd
->pcls
);
1414 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
1415 { // Must be inside the same thread!
1416 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1420 This is the message exchange for user32. If there's a need to monitor messages,
1423 TRACE("HWND 0x%x, MSG %d, WPARAM 0x%x, LPARAM 0x%x, Ansi &d\n",hWnd
,Msg
,wParam
,lParam
,Ansi
);
1424 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1425 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1429 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1430 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1434 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1435 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1442 IsAnsi
= !Wnd
->Unicode
;
1443 WndProc
= Wnd
->lpfnWndProc
;
1448 IsAnsi
= !Wnd
->Unicode
;
1449 WndProc
= Wnd
->lpfnWndProc
;
1452 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1456 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1458 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1466 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1473 PCALLPROCDATA CallProc
;
1475 if (lpPrevWndFunc
== NULL
)
1477 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1481 pWnd
= ValidateHwnd(hWnd
);
1483 if (!IsCallProcHandle(lpPrevWndFunc
))
1484 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1487 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1488 if (CallProc
!= NULL
)
1490 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1491 CallProc
->pfnClientPrevious
,
1500 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1511 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1518 PCALLPROCDATA CallProc
;
1520 /* FIXME - can the first parameter be NULL? */
1521 if (lpPrevWndFunc
== NULL
)
1523 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1527 pWnd
= ValidateHwnd(hWnd
);
1529 if (!IsCallProcHandle(lpPrevWndFunc
))
1530 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1533 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1534 if (CallProc
!= NULL
)
1536 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1537 CallProc
->pfnClientPrevious
,
1546 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1557 DispatchMessageA(CONST MSG
*lpmsg
)
1563 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1565 SetLastError( ERROR_INVALID_PARAMETER
);
1569 if (lpmsg
->hwnd
!= NULL
)
1571 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1577 if (is_pointer_message(lpmsg
->message
))
1579 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1583 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1585 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1587 if ( lpmsg
->message
== WM_SYSTIMER
)
1588 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1590 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
)) return 0;
1592 _SEH2_TRY
// wine does this. Hint: Prevents call to another thread....
1594 Ret
= WndProc(lpmsg
->hwnd
,
1599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1604 else if (Wnd
!= NULL
)
1606 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1608 Ret
= IntCallMessageProc(Wnd
,
1617 if (!MsgiAnsiToUnicodeMessage(lpmsg
->hwnd
, &UnicodeMsg
, (LPMSG
)lpmsg
))
1622 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1624 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1638 DispatchMessageW(CONST MSG
*lpmsg
)
1643 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1645 SetLastError( ERROR_INVALID_PARAMETER
);
1649 if (lpmsg
->hwnd
!= NULL
)
1651 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1657 if (is_pointer_message(lpmsg
->message
))
1659 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1663 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1665 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1667 if ( lpmsg
->message
== WM_SYSTIMER
)
1668 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1670 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
)) return 0;
1674 Ret
= WndProc(lpmsg
->hwnd
,
1679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1684 else if (Wnd
!= NULL
)
1686 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1688 Ret
= IntCallMessageProc(Wnd
,
1696 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
1707 GetMessageA(LPMSG lpMsg
,
1714 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
1716 SetLastError( ERROR_INVALID_PARAMETER
);
1720 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1721 if (-1 == (int) Res
)
1733 GetMessageW(LPMSG lpMsg
,
1740 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
1742 SetLastError( ERROR_INVALID_PARAMETER
);
1746 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1747 if (-1 == (int) Res
)
1756 PeekMessageWorker( PMSG pMsg
,
1763 PCLIENTTHREADINFO pcti
;
1764 pci
= GetWin32ClientInfo();
1765 pcti
= pci
->pClientThreadInfo
;
1767 if (!hWnd
&& pci
&& pcti
)
1771 if ((pci
->cSpins
>= 100) && (pci
->dwTIFlags
& TIF_SPINNING
))
1772 { // Yield after 100 spin cycles and ready to swap vinyl.
1773 if (!(pci
->dwTIFlags
& TIF_WAITFORINPUTIDLE
))
1774 { // Not waiting for idle event.
1775 if (!pcti
->fsChangeBits
&& !pcti
->fsWakeBits
)
1776 { // No messages are available.
1777 if ((GetTickCount() - pcti
->tickLastMsgChecked
) > 1000)
1778 { // Up the msg read count if over 1 sec.
1779 NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD
);
1783 FIXME("seeSpins!\n");
1789 return NtUserPeekMessage(pMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1796 PeekMessageA(LPMSG lpMsg
,
1804 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1805 if (-1 == (int) Res
|| !Res
)
1828 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1829 if (-1 == (int) Res
|| !Res
)
1850 /* Check for combo box or a list box to send names. */
1851 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
1854 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
1855 combo/list box. Forces a call like DlgDirListComboBox.
1857 //wParam |= DDL_POSTMSGS;
1858 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1861 /* No drop files or current Process, just post message. */
1862 if ( (Msg
!= WM_DROPFILES
) ||
1863 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
1864 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
1866 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1869 /* We have drop files and this is not the same process for this window. */
1871 /* Just incase, check wParam for Global memory handle and send size. */
1872 Ret
= SendMessageA( hWnd
,
1874 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
1875 (LPARAM
)wParam
); // Send wParam as lParam.
1877 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
1895 /* Check for combo box or a list box to send names. */
1896 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
1899 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
1900 combo/list box. Forces a call like DlgDirListComboBox.
1902 //wParam |= DDL_POSTMSGS;
1903 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1906 /* No drop files or current Process, just post message. */
1907 if ( (Msg
!= WM_DROPFILES
) ||
1908 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
1909 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
1911 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1914 /* We have drop files and this is not the same process for this window. */
1916 /* Just incase, check wParam for Global memory handle and send size. */
1917 Ret
= SendMessageW( hWnd
,
1919 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
1920 (LPARAM
)wParam
); // Send wParam as lParam.
1922 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
1935 NtUserxPostQuitMessage(nExitCode
);
1950 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1965 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
1973 SendMessageW(HWND Wnd
,
1981 PTHREADINFO ti
= GetW32ThreadInfo();
1983 if ( Msg
& ~WM_MAXIMUM
)
1985 SetLastError( ERROR_INVALID_PARAMETER
);
1989 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
1991 Window
= ValidateHwnd(Wnd
);
1993 if ( Window
!= NULL
&&
1994 Window
->head
.pti
== ti
&&
1995 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
1996 !ISITHOOKED(WH_CALLWNDPROC
) &&
1997 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
1998 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2000 /* NOTE: We can directly send messages to the window procedure
2001 if *all* the following conditions are met:
2003 * Window belongs to calling thread
2004 * The calling thread is not being hooked for CallWndProc
2005 * Not calling a server side proc:
2006 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2009 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2014 UMMsg
.message
= Msg
;
2015 UMMsg
.wParam
= wParam
;
2016 UMMsg
.lParam
= lParam
;
2018 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2023 Result
= NtUserMessageCall( Wnd
,
2031 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2041 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2043 MSG AnsiMsg
, UcMsg
, KMMsg
;
2046 PTHREADINFO ti
= GetW32ThreadInfo();
2048 if ( Msg
& ~WM_MAXIMUM
)
2050 SetLastError( ERROR_INVALID_PARAMETER
);
2054 if (Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2056 Window
= ValidateHwnd(Wnd
);
2058 if ( Window
!= NULL
&&
2059 Window
->head
.pti
== ti
&&
2060 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
2061 !ISITHOOKED(WH_CALLWNDPROC
) &&
2062 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2063 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2065 /* NOTE: We can directly send messages to the window procedure
2066 if *all* the following conditions are met:
2068 * Window belongs to calling thread
2069 * The calling thread is not being hooked for CallWndProc
2070 * Not calling a server side proc:
2071 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2074 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2079 AnsiMsg
.message
= Msg
;
2080 AnsiMsg
.wParam
= wParam
;
2081 AnsiMsg
.lParam
= lParam
;
2083 if (!MsgiAnsiToUnicodeMessage(Wnd
, &UcMsg
, &AnsiMsg
))
2088 if (!MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2090 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2094 Result
= NtUserMessageCall( Wnd
,
2102 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2103 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2113 SendMessageCallbackA(
2118 SENDASYNCPROC lpCallBack
,
2123 CALL_BACK_INFO CallBackInfo
;
2125 if (is_pointer_message(Msg
))
2127 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2131 CallBackInfo
.CallBack
= lpCallBack
;
2132 CallBackInfo
.Context
= dwData
;
2134 AnsiMsg
.hwnd
= hWnd
;
2135 AnsiMsg
.message
= Msg
;
2136 AnsiMsg
.wParam
= wParam
;
2137 AnsiMsg
.lParam
= lParam
;
2139 if (!MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2144 Result
= NtUserMessageCall( hWnd
,
2148 (ULONG_PTR
)&CallBackInfo
,
2149 FNID_SENDMESSAGECALLBACK
,
2152 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2162 SendMessageCallbackW(
2167 SENDASYNCPROC lpCallBack
,
2170 CALL_BACK_INFO CallBackInfo
;
2172 if (is_pointer_message(Msg
))
2174 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2178 CallBackInfo
.CallBack
= lpCallBack
;
2179 CallBackInfo
.Context
= dwData
;
2181 return NtUserMessageCall(hWnd
,
2185 (ULONG_PTR
)&CallBackInfo
,
2186 FNID_SENDMESSAGECALLBACK
,
2195 SendMessageTimeoutA(
2202 PDWORD_PTR lpdwResult
)
2208 PTHREADINFO ti
= GetW32ThreadInfo();
2210 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2212 SetLastError( ERROR_INVALID_PARAMETER
);
2216 if (lpdwResult
) *lpdwResult
= 0;
2218 if (hWnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2220 Window
= ValidateHwnd(hWnd
);
2222 if ( Window
!= NULL
&&
2223 Window
->head
.pti
== ti
&&
2224 !ISITHOOKED(WH_CALLWNDPROC
) &&
2225 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2226 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2228 Result
= IntCallMessageProc(Window
, hWnd
, Msg
, wParam
, lParam
, TRUE
);
2229 if (lpdwResult
) *lpdwResult
= Result
;
2233 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2235 dsm
.uFlags
= fuFlags
;
2236 dsm
.uTimeout
= uTimeout
;
2238 AnsiMsg
.hwnd
= hWnd
;
2239 AnsiMsg
.message
= Msg
;
2240 AnsiMsg
.wParam
= wParam
;
2241 AnsiMsg
.lParam
= lParam
;
2243 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2248 Result
= NtUserMessageCall( hWnd
,
2253 FNID_SENDMESSAGETIMEOUT
,
2256 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2258 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2260 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2271 SendMessageTimeoutW(
2278 PDWORD_PTR lpdwResult
)
2283 PTHREADINFO ti
= GetW32ThreadInfo();
2285 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2287 SetLastError( ERROR_INVALID_PARAMETER
);
2291 if (lpdwResult
) *lpdwResult
= 0;
2293 if (hWnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2295 Window
= ValidateHwnd(hWnd
);
2297 if ( Window
!= NULL
&&
2298 Window
->head
.pti
== ti
&&
2299 !ISITHOOKED(WH_CALLWNDPROC
) &&
2300 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2301 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2303 Result
= IntCallMessageProc(Window
, hWnd
, Msg
, wParam
, lParam
, FALSE
);
2304 if (lpdwResult
) *lpdwResult
= Result
;
2308 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2310 dsm
.uFlags
= fuFlags
;
2311 dsm
.uTimeout
= uTimeout
;
2313 Result
= NtUserMessageCall( hWnd
,
2318 FNID_SENDMESSAGETIMEOUT
,
2321 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2323 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2342 if (is_pointer_message(Msg
))
2344 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2348 AnsiMsg
.hwnd
= hWnd
;
2349 AnsiMsg
.message
= Msg
;
2350 AnsiMsg
.wParam
= wParam
;
2351 AnsiMsg
.lParam
= lParam
;
2352 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2356 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2358 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2377 if (is_pointer_message(Msg
))
2379 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2384 UMMsg
.message
= Msg
;
2385 UMMsg
.wParam
= wParam
;
2386 UMMsg
.lParam
= lParam
;
2387 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2391 Result
= NtUserMessageCall( hWnd
,
2396 FNID_SENDNOTIFYMESSAGE
,
2399 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2408 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2410 switch (lpMsg
->message
)
2416 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2419 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2420 SetLastError(ERROR_INVALID_PARAMETER
);
2430 TranslateMessage(CONST MSG
*lpMsg
)
2434 // Ref: msdn ImmGetVirtualKey:
2435 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2437 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2438 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2443 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2453 RegisterWindowMessageA(LPCSTR lpString
)
2455 UNICODE_STRING String
;
2459 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
2464 Atom
= NtUserRegisterWindowMessage(&String
);
2465 RtlFreeUnicodeString(&String
);
2474 RegisterWindowMessageW(LPCWSTR lpString
)
2476 UNICODE_STRING String
;
2478 RtlInitUnicodeString(&String
, lpString
);
2479 return(NtUserRegisterWindowMessage(&String
));
2488 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2495 ReleaseCapture(VOID
)
2497 return NtUserxReleaseCapture();
2506 RealGetQueueStatus(UINT flags
)
2508 #define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT
2509 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_TEMPALLINPUT
))
2511 SetLastError( ERROR_INVALID_FLAGS
);
2514 return NtUserxGetQueueStatus(flags
);
2521 BOOL WINAPI
GetInputState(VOID
)
2523 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2525 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2526 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2533 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2535 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2538 PCLIENTINFO pci
= GetWin32ClientInfo();
2540 /* Make sure we don't try to access mem beyond what we were given */
2541 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2543 return STATUS_INFO_LENGTH_MISMATCH
;
2546 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2547 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2548 KMMsg
.message
= CallbackArgs
->Msg
;
2549 KMMsg
.wParam
= CallbackArgs
->wParam
;
2550 /* Check if lParam is really a pointer and adjust it if it is */
2551 if (0 <= CallbackArgs
->lParamBufferSize
)
2553 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2554 + CallbackArgs
->lParamBufferSize
)
2556 return STATUS_INFO_LENGTH_MISMATCH
;
2558 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2562 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2564 return STATUS_INFO_LENGTH_MISMATCH
;
2566 KMMsg
.lParam
= CallbackArgs
->lParam
;
2569 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2571 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2572 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2575 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2579 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2580 pWnd
= pci
->CallbackWnd
.pWnd
;
2582 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
2590 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2594 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2600 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
2602 /* Function does nothing on 32 bit windows */
2605 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
2606 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
2607 typedef BOOL (WINAPI
* RealInternalGetMessageProc
)(LPMSG
,HWND
,UINT
,UINT
,UINT
,BOOL
);
2608 typedef BOOL (WINAPI
* RealWaitMessageExProc
)(DWORD
,UINT
);
2610 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
2612 RealInternalGetMessageProc NtUserRealInternalGetMessage
;
2613 RealWaitMessageExProc NtUserRealWaitMessageEx
;
2614 RealGetQueueStatusProc RealGetQueueStatus
;
2615 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
2616 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
2620 RealMsgWaitForMultipleObjectsEx(
2622 CONST HANDLE
*pHandles
,
2623 DWORD dwMilliseconds
,
2627 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
2629 CRITICAL_SECTION gcsMPH
;
2630 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
2631 DWORD gcLoadMPH
= 0;
2632 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
2633 NtUserRealInternalGetMessage
,
2634 NtUserRealWaitMessageEx
,
2636 RealMsgWaitForMultipleObjectsEx
2639 DWORD gfMessagePumpHook
= 0;
2641 BOOL WINAPI
IsInsideMessagePumpHook()
2642 { // FF uses this and polls it when Min/Max
2643 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2644 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
2647 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
2649 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
2650 Addresses
->NtUserRealInternalGetMessage
= NtUserRealInternalGetMessage
;
2651 Addresses
->NtUserRealWaitMessageEx
= NtUserRealWaitMessageEx
;
2652 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
2653 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
2656 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
2658 EnterCriticalSection(&gcsMPH
);
2660 SetLastError(ERROR_INVALID_PARAMETER
);
2661 LeaveCriticalSection(&gcsMPH
);
2665 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
2667 ResetMessagePumpHook(&Addresses
);
2668 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
2669 LeaveCriticalSection(&gcsMPH
);
2672 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
2674 if(gpfnInitMPH
!= Hook
) {
2675 LeaveCriticalSection(&gcsMPH
);
2679 if(NtUserxInitMessagePump()) {
2680 LeaveCriticalSection(&gcsMPH
);
2684 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
2686 LeaveCriticalSection(&gcsMPH
);
2690 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
2692 EnterCriticalSection(&gcsMPH
);
2694 if(NtUserxUnInitMessagePump()) {
2697 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
2698 gpfnInitMPH(TRUE
, NULL
);
2699 ResetMessagePumpHook(&gmph
);
2702 LeaveCriticalSection(&gcsMPH
);
2706 LeaveCriticalSection(&gcsMPH
);
2710 DWORD WINAPI
GetQueueStatus(UINT flags
)
2712 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2716 * @name RealMsgWaitForMultipleObjectsEx
2718 * Wait either for either message arrival or for one of the passed events
2722 * Number of handles in the pHandles array.
2724 * Handles of events to wait for.
2725 * @param dwMilliseconds
2728 * Mask specifying on which message events we should wakeup.
2730 * Wait type (see MWMO_* constants).
2736 RealMsgWaitForMultipleObjectsEx(
2738 const HANDLE
*pHandles
,
2739 DWORD dwMilliseconds
,
2743 LPHANDLE RealHandles
;
2744 HANDLE MessageQueueHandle
;
2747 PCLIENTTHREADINFO pcti
;
2749 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2751 SetLastError(ERROR_INVALID_PARAMETER
);
2755 pci
= GetWin32ClientInfo();
2756 if (!pci
) return WAIT_FAILED
;
2758 pcti
= pci
->pClientThreadInfo
;
2759 if (pcti
&& ( !nCount
|| !(dwFlags
& MWMO_WAITALL
) ))
2761 if ( (pcti
->fsChangeBits
& LOWORD(dwWakeMask
)) ||
2762 ( (dwFlags
& MWMO_INPUTAVAILABLE
) && (pcti
->fsWakeBits
& LOWORD(dwWakeMask
)) ) )
2764 //FIXME("Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
2769 MessageQueueHandle
= NtUserxMsqSetWakeMask(MAKELONG(dwWakeMask
, dwFlags
));
2770 if (MessageQueueHandle
== NULL
)
2772 SetLastError(0); /* ? */
2776 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2777 if (RealHandles
== NULL
)
2779 NtUserxMsqClearWakeMask();
2780 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2784 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2785 RealHandles
[nCount
] = MessageQueueHandle
;
2787 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2788 dwFlags
& MWMO_WAITALL
,
2789 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
2791 HeapFree(GetProcessHeap(), 0, RealHandles
);
2792 NtUserxMsqClearWakeMask();
2793 //FIXME("Result 0X%x\n",Result);
2801 MsgWaitForMultipleObjectsEx(
2803 CONST HANDLE
*lpHandles
,
2804 DWORD dwMilliseconds
,
2808 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
2815 MsgWaitForMultipleObjects(
2817 CONST HANDLE
*lpHandles
,
2819 DWORD dwMilliseconds
,
2822 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
2823 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
2827 BOOL FASTCALL
MessageInit(VOID
)
2829 InitializeCriticalSection(&DdeCrst
);
2830 InitializeCriticalSection(&gcsMPH
);
2835 VOID FASTCALL
MessageCleanup(VOID
)
2837 DeleteCriticalSection(&DdeCrst
);
2838 DeleteCriticalSection(&gcsMPH
);
2841 /***********************************************************************
2844 * Convert the wparam of an ASCII message to Unicode.
2847 map_wparam_AtoW( UINT message
, WPARAM wparam
)
2852 case EM_SETPASSWORDCHAR
:
2856 case WM_SYSDEADCHAR
:
2861 ch
[0] = (wparam
& 0xff);
2862 ch
[1] = (wparam
>> 8);
2863 MultiByteToWideChar(CP_ACP
, 0, ch
, 2, wch
, 2);
2864 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
2871 ch
[0] = (wparam
>> 8);
2872 ch
[1] = (wparam
& 0xff);
2873 if (ch
[0]) MultiByteToWideChar(CP_ACP
, 0, ch
, 2, &wch
, 1);
2874 else MultiByteToWideChar(CP_ACP
, 0, &ch
[1], 1, &wch
, 1);
2875 wparam
= MAKEWPARAM( wch
, HIWORD(wparam
) );
2886 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
2889 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
2890 return IsDialogMessageW( hwndDlg
, &msg
);
2895 IntBroadcastSystemMessage(
2897 LPDWORD lpdwRecipients
,
2905 DWORD recips
= BSM_ALLCOMPONENTS
;
2906 BOOL ret
= -1; // Set to return fail
2907 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
2908 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
2909 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
2911 if ((dwflags
& ~all_flags
) ||
2912 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
2914 SetLastError(ERROR_INVALID_PARAMETER
);
2918 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
2920 SetLastError(ERROR_INVALID_PARAMETER
);
2924 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
2926 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
2928 if (!lpdwRecipients
)
2929 lpdwRecipients
= &recips
;
2931 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
2933 SetLastError(ERROR_INVALID_PARAMETER
);
2937 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2939 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
2941 SetLastError(ERROR_INVALID_PARAMETER
);
2948 parm
.flags
= dwflags
;
2949 parm
.recipients
= *lpdwRecipients
;
2951 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
2953 if (*lpdwRecipients
& BSM_APPLICATIONS
)
2955 ret
= NtUserMessageCall(GetDesktopWindow(),
2960 FNID_BROADCASTSYSTEMMESSAGE
,
2966 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
2968 pBSMInfo
->hdesk
= parm
.hDesk
;
2969 pBSMInfo
->hwnd
= parm
.hWnd
;
2980 BroadcastSystemMessageA(
2982 LPDWORD lpdwRecipients
,
2987 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
2995 BroadcastSystemMessageW(
2997 LPDWORD lpdwRecipients
,
3002 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3010 BroadcastSystemMessageExA(
3012 LPDWORD lpdwRecipients
,
3018 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3026 BroadcastSystemMessageExW(
3028 LPDWORD lpdwRecipients
,
3034 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);