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;
93 /* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
94 static BOOL FASTCALL
combobox_has_strings( HWND hwnd
)
96 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
97 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
100 /* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */
101 static BOOL FASTCALL
listbox_has_strings( HWND hwnd
)
103 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
104 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
107 /* DDE message exchange
109 * - Session initialization
110 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
111 * this message contains a pair of global atoms, the Application and Topic atoms.
112 * The client must destroy the atoms.
113 * Server window proc handles the WM_DDE_INITIATE message and if the Application
114 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
115 * of the reply message contains another pair of global atoms (Application and
116 * Topic again), which must be destroyed by the server.
119 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
120 * is a global memory handle containing the string to execute. After the command has
121 * been executed the server posts a WM_DDE_ACK message to the client, which contains
122 * a packed lParam which in turn contains that global memory handle. The client takes
123 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
124 * it and the global memory handle.
125 * This might work nice and easy in Win3.1, but things are more complicated for NT.
126 * Global memory handles in NT are not really global, they're still local to the
127 * process. So, what happens under the hood is that PostMessage must handle the
128 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
129 * area, repack that into a new structure together with the original memory handle
130 * and pass that off to the win32k. Win32k will marshall that data over to the target
131 * (server) process where it will be unpacked and stored in a newly allocated global
132 * memory area. The handle of that area will then be sent to the window proc, after
133 * storing it together with the "original" (client) handle in a table.
134 * The server will eventually post the WM_DDE_ACK response, containing the global
135 * memory handle it received. PostMessage must then lookup that memory handle (only
136 * valid in the server process) and replace it with the corresponding client memory
137 * handle. To avoid memory leaks, the server-side global memory block must be freed.
138 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
139 * individual components are handed to win32k.sys to post to the client side. Since
140 * the server side app hands over ownership of the packed lParam when it calls
141 * PostMessage(), the packed lParam needs to be freed on the server side too.
142 * When the WM_DDE_ACK message (containing the client-side global memory handle)
143 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
144 * to the client side window proc which is expected to free/reuse it.
147 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
148 * to the memory handle, we keep track (in the server side) of all pairs of handle
149 * used (the client passes its value and the content of the memory handle), and
150 * the server stored both values (the client, and the local one, created after the
151 * content). When a ACK message is generated, the list of pair is searched for a
152 * matching pair, so that the client memory handle can be returned.
155 typedef struct tagDDEPAIR
159 } DDEPAIR
, *PDDEPAIR
;
161 static PDDEPAIR DdePairs
= NULL
;
162 static unsigned DdeNumAlloc
= 0;
163 static unsigned DdeNumUsed
= 0;
164 static CRITICAL_SECTION DdeCrst
;
167 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
171 EnterCriticalSection(&DdeCrst
);
173 /* now remember the pair of hMem on both sides */
174 if (DdeNumUsed
== DdeNumAlloc
)
178 if (NULL
!= DdePairs
)
180 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
181 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
185 New
= HeapAlloc(GetProcessHeap(), 0,
186 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
191 LeaveCriticalSection(&DdeCrst
);
195 /* zero out newly allocated part */
196 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
197 DdeNumAlloc
+= GROWBY
;
201 for (i
= 0; i
< DdeNumAlloc
; i
++)
203 if (NULL
== DdePairs
[i
].ServerMem
)
205 DdePairs
[i
].ClientMem
= ClientMem
;
206 DdePairs
[i
].ServerMem
= ServerMem
;
211 LeaveCriticalSection(&DdeCrst
);
216 static HGLOBAL FASTCALL
217 DdeGetPair(HGLOBAL ServerMem
)
222 EnterCriticalSection(&DdeCrst
);
223 for (i
= 0; i
< DdeNumAlloc
; i
++)
225 if (DdePairs
[i
].ServerMem
== ServerMem
)
228 DdePairs
[i
].ServerMem
= 0;
230 Ret
= DdePairs
[i
].ClientMem
;
234 LeaveCriticalSection(&DdeCrst
);
241 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
245 switch (UMMsg
->message
)
249 PKMDDELPARAM DdeLparam
;
250 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
252 !UnpackDDElParam( UMMsg
->message
, UMMsg
->lParam
, &DdeLparam
->uiLo
, &DdeLparam
->uiHi
))
255 If this is a reply to WM_DDE_EXECUTE then
256 uiHi will contain a hMem, hence >= 0x10000.
257 Otherwise, it will be be an atom, a 16-bit value.
259 if (!IS_ATOM(DdeLparam
->uiHi
))
261 HGLOBAL h
= DdeGetPair((HGLOBAL
)(ULONG_PTR
)DdeLparam
->uiHi
);
264 GlobalFree((HGLOBAL
)(ULONG_PTR
)DdeLparam
->uiHi
);
265 DdeLparam
->uiHi
= (UINT_PTR
) h
;
268 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
269 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
276 PKMDDEEXECUTEDATA KMDdeExecuteData
;
279 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
280 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
283 SetLastError(ERROR_INVALID_HANDLE
);
286 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
287 if (!KMDdeExecuteData
)
289 SetLastError(ERROR_OUTOFMEMORY
);
292 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
293 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
294 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
295 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
296 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
297 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
303 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
304 PCOPYDATASTRUCT pKMCopyData
;
306 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
307 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
310 SetLastError(ERROR_OUTOFMEMORY
);
314 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
315 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
316 pKMCopyData
->lpData
= pKMCopyData
+ 1;
318 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
319 pUMCopyData
->cbData
);
321 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
334 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
336 switch (KMMsg
->message
)
341 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
351 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
355 switch (UMMsg
->message
)
360 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
362 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
363 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
364 if (L
'A' == *((WCHAR
*) Class
))
366 Class
+= sizeof(WCHAR
);
367 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
371 ASSERT(L
'S' == *((WCHAR
*) Class
));
372 Class
+= sizeof(WCHAR
);
373 Cs
->lpszClass
= (LPCWSTR
) Class
;
380 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
381 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
, DdeLparam
->uiLo
, DdeLparam
->uiHi
);
387 PKMDDEEXECUTEDATA KMDdeExecuteData
;
391 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
392 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
397 Data
= GlobalLock(GlobalData
);
400 GlobalFree(GlobalData
);
403 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
404 GlobalUnlock(GlobalData
);
405 if (!DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
407 GlobalFree(GlobalData
);
410 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
411 UMMsg
->lParam
= (LPARAM
) GlobalData
;
417 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
418 pKMCopyData
->lpData
= pKMCopyData
+ 1;
430 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
432 switch (KMMsg
->message
)
436 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
437 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
448 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
450 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
456 MsgiAnsiToUnicodeMessage(HWND hwnd
, LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
458 UNICODE_STRING UnicodeString
;
460 *UnicodeMsg
= *AnsiMsg
;
462 switch (AnsiMsg
->message
)
465 case WM_ASKCBFORMATNAME
:
467 LPWSTR Buffer
= HeapAlloc(GetProcessHeap(), 0,
468 AnsiMsg
->wParam
* sizeof(WCHAR
));
473 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
477 /* AnsiMsg->lParam is string (0-terminated) */
479 case WM_WININICHANGE
:
480 case WM_DEVMODECHANGE
:
486 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
487 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
492 case LB_ADDSTRING_LOWER
:
493 case LB_ADDSTRING_UPPER
:
494 case LB_INSERTSTRING
:
495 case LB_INSERTSTRING_UPPER
:
496 case LB_INSERTSTRING_LOWER
:
498 case LB_FINDSTRINGEXACT
:
499 case LB_SELECTSTRING
:
501 if (listbox_has_strings(AnsiMsg
->hwnd
))
503 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
504 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
510 case CB_INSERTSTRING
:
512 case CB_FINDSTRINGEXACT
:
513 case CB_SELECTSTRING
:
515 if (combobox_has_strings(AnsiMsg
->hwnd
))
517 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
518 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
526 MDICREATESTRUCTW mdi_cs
;
529 CREATESTRUCTW cs
; /* new structure */
530 LPCWSTR lpszName
; /* allocated Name */
531 LPCWSTR lpszClass
; /* allocated Class */
534 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
539 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
540 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
542 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
543 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
545 if (!IS_ATOM(xs
->cs
.lpszClass
))
547 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
548 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
551 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
553 mdi_cs
= *(MDICREATESTRUCTW
*)xs
->cs
.lpCreateParams
;
554 mdi_cs
.szTitle
= xs
->cs
.lpszName
;
555 mdi_cs
.szClass
= xs
->cs
.lpszClass
;
556 xs
->cs
.lpCreateParams
= &mdi_cs
;
559 UnicodeMsg
->lParam
= (LPARAM
)xs
;
565 MDICREATESTRUCTW
*cs
=
566 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
573 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
575 if (!IS_ATOM(cs
->szClass
))
577 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
578 cs
->szClass
= UnicodeString
.Buffer
;
581 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
582 cs
->szTitle
= UnicodeString
.Buffer
;
584 UnicodeMsg
->lParam
= (LPARAM
)cs
;
593 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
595 UNICODE_STRING UnicodeString
;
597 switch (AnsiMsg
->message
)
600 case WM_ASKCBFORMATNAME
:
602 HeapFree(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
607 case WM_WININICHANGE
:
608 case WM_DEVMODECHANGE
:
614 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
615 RtlFreeUnicodeString(&UnicodeString
);
620 case LB_ADDSTRING_LOWER
:
621 case LB_ADDSTRING_UPPER
:
622 case LB_INSERTSTRING
:
623 case LB_INSERTSTRING_UPPER
:
624 case LB_INSERTSTRING_LOWER
:
626 case LB_FINDSTRINGEXACT
:
627 case LB_SELECTSTRING
:
629 if (listbox_has_strings(AnsiMsg
->hwnd
))
631 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
632 RtlFreeUnicodeString(&UnicodeString
);
638 case CB_INSERTSTRING
:
640 case CB_FINDSTRINGEXACT
:
641 case CB_SELECTSTRING
:
643 if (combobox_has_strings(AnsiMsg
->hwnd
))
645 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
646 RtlFreeUnicodeString(&UnicodeString
);
656 CREATESTRUCTW cs
; /* new structure */
657 LPWSTR lpszName
; /* allocated Name */
658 LPWSTR lpszClass
; /* allocated Class */
661 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
664 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
665 RtlFreeUnicodeString(&UnicodeString
);
669 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
670 RtlFreeUnicodeString(&UnicodeString
);
672 HeapFree(GetProcessHeap(), 0, xs
);
678 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
679 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
680 RtlFreeUnicodeString(&UnicodeString
);
681 if (!IS_ATOM(cs
->szClass
))
683 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
684 RtlFreeUnicodeString(&UnicodeString
);
686 HeapFree(GetProcessHeap(), 0, cs
);
695 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
698 switch (AnsiMsg
->message
)
701 case WM_ASKCBFORMATNAME
:
703 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
704 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
705 if (UnicodeMsg
->wParam
> 0 &&
706 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1, AnsiBuffer
, UnicodeMsg
->wParam
, NULL
, NULL
))
708 AnsiBuffer
[UnicodeMsg
->wParam
- 1] = 0;
714 LPWSTR Buffer
= (LPWSTR
) UnicodeMsg
->lParam
;
715 LPSTR AnsiBuffer
= (LPSTR
) AnsiMsg
->lParam
;
716 if (!listbox_has_strings( UnicodeMsg
->hwnd
)) break;
717 Size
= SendMessageW( UnicodeMsg
->hwnd
, LB_GETTEXTLEN
, UnicodeMsg
->wParam
, 0 );
718 if (Size
== LB_ERR
) break;
721 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1, AnsiBuffer
, Size
, NULL
, NULL
))
723 AnsiBuffer
[Size
- 1] = 0;
729 LPWSTR Buffer
= (LPWSTR
) UnicodeMsg
->lParam
;
730 LPSTR AnsiBuffer
= (LPSTR
) AnsiMsg
->lParam
;
731 if (!combobox_has_strings( UnicodeMsg
->hwnd
)) break;
732 Size
= SendMessageW( UnicodeMsg
->hwnd
, CB_GETLBTEXTLEN
, UnicodeMsg
->wParam
, 0 );
733 if (Size
== CB_ERR
) break;
736 !WideCharToMultiByte(CP_ACP
, 0, Buffer
, -1, AnsiBuffer
, Size
, NULL
, NULL
))
738 AnsiBuffer
[Size
- 1] = 0;
744 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
750 MsgiUnicodeToAnsiMessage(HWND hwnd
, LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
752 ANSI_STRING AnsiString
;
753 UNICODE_STRING UnicodeString
;
755 *AnsiMsg
= *UnicodeMsg
;
757 switch(UnicodeMsg
->message
)
762 MDICREATESTRUCTA mdi_cs
;
767 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
768 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
));
773 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
775 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
776 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
777 if (! NT_SUCCESS(Status
))
779 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
782 CsA
->lpszName
= AnsiString
.Buffer
;
783 if (HIWORD((ULONG_PTR
)CsW
->lpszClass
) != 0)
785 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
786 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
787 if (! NT_SUCCESS(Status
))
789 RtlInitAnsiString(&AnsiString
, CsA
->lpszName
);
790 RtlFreeAnsiString(&AnsiString
);
791 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
794 CsA
->lpszClass
= AnsiString
.Buffer
;
797 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
799 mdi_cs
= *(MDICREATESTRUCTA
*)CsW
->lpCreateParams
;
800 mdi_cs
.szTitle
= CsA
->lpszName
;
801 mdi_cs
.szClass
= CsA
->lpszClass
;
802 CsA
->lpCreateParams
= &mdi_cs
;
805 AnsiMsg
->lParam
= (LPARAM
)CsA
;
810 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
811 AnsiMsg
->wParam
= UnicodeMsg
->wParam
* 2;
812 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), 0, AnsiMsg
->wParam
);
813 if (NULL
== (PVOID
) AnsiMsg
->lParam
)
824 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
825 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
831 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
836 case LB_ADDSTRING_LOWER
:
837 case LB_ADDSTRING_UPPER
:
838 case LB_INSERTSTRING
:
839 case LB_INSERTSTRING_UPPER
:
840 case LB_INSERTSTRING_LOWER
:
842 case LB_FINDSTRINGEXACT
:
843 case LB_SELECTSTRING
:
845 if (listbox_has_strings(AnsiMsg
->hwnd
))
847 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
848 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
854 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
860 case CB_INSERTSTRING
:
862 case CB_FINDSTRINGEXACT
:
863 case CB_SELECTSTRING
:
865 if (combobox_has_strings(AnsiMsg
->hwnd
))
867 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
868 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
874 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
881 MDICREATESTRUCTA
*cs
=
882 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
889 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
891 if (!IS_ATOM(cs
->szClass
))
893 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
894 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
898 HeapFree(GetProcessHeap(), 0, cs
);
901 cs
->szClass
= AnsiString
.Buffer
;
904 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
905 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
909 if (!IS_ATOM(cs
->szClass
))
911 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
912 RtlFreeAnsiString(&AnsiString
);
915 HeapFree(GetProcessHeap(), 0, cs
);
918 cs
->szTitle
= AnsiString
.Buffer
;
920 AnsiMsg
->lParam
= (LPARAM
)cs
;
929 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
931 ANSI_STRING AnsiString
;
933 switch(UnicodeMsg
->message
)
937 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
942 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
943 RtlFreeAnsiString(&AnsiString
);
951 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
952 RtlInitAnsiString(&AnsiString
, Cs
->lpszName
);
953 RtlFreeAnsiString(&AnsiString
);
954 if (HIWORD((ULONG_PTR
)Cs
->lpszClass
) != 0)
956 RtlInitAnsiString(&AnsiString
, Cs
->lpszClass
);
957 RtlFreeAnsiString(&AnsiString
);
959 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
964 case LB_ADDSTRING_LOWER
:
965 case LB_ADDSTRING_UPPER
:
966 case LB_INSERTSTRING
:
967 case LB_INSERTSTRING_UPPER
:
968 case LB_INSERTSTRING_LOWER
:
970 case LB_FINDSTRINGEXACT
:
971 case LB_SELECTSTRING
:
973 if (listbox_has_strings(AnsiMsg
->hwnd
))
975 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
976 RtlFreeAnsiString(&AnsiString
);
982 case CB_INSERTSTRING
:
984 case CB_FINDSTRINGEXACT
:
985 case CB_SELECTSTRING
:
987 DWORD dwStyle
= GetWindowLongPtrW(AnsiMsg
->hwnd
, GWL_STYLE
);
988 if (!(dwStyle
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) &&
989 (dwStyle
& CBS_HASSTRINGS
))
991 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
992 RtlFreeAnsiString(&AnsiString
);
999 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
1000 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
1001 RtlFreeAnsiString(&AnsiString
);
1002 if (!IS_ATOM(cs
->szClass
))
1004 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
1005 RtlFreeAnsiString(&AnsiString
);
1007 HeapFree(GetProcessHeap(), 0, cs
);
1016 static BOOL FASTCALL
1017 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
1020 switch (UnicodeMsg
->message
)
1023 case WM_ASKCBFORMATNAME
:
1025 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1026 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1027 if (0 < AnsiMsg
->wParam
&&
1028 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, UnicodeMsg
->wParam
))
1030 UBuffer
[UnicodeMsg
->wParam
- 1] = L
'\0';
1036 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1037 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1038 if (!listbox_has_strings( UnicodeMsg
->hwnd
)) break;
1039 Size
= SendMessageW( UnicodeMsg
->hwnd
, LB_GETTEXTLEN
, UnicodeMsg
->wParam
, 0 );
1040 if (Size
== LB_ERR
) break;
1043 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, Size
))
1045 UBuffer
[Size
- 1] = L
'\0';
1051 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1052 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1053 if (!combobox_has_strings( UnicodeMsg
->hwnd
)) break;
1054 Size
= SendMessageW( UnicodeMsg
->hwnd
, CB_GETLBTEXTLEN
, UnicodeMsg
->wParam
, 0 );
1055 if (Size
== CB_ERR
) break;
1058 ! MultiByteToWideChar(CP_ACP
, 0, Buffer
, -1, UBuffer
, Size
))
1060 UBuffer
[Size
- 1] = L
'\0';
1066 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
1071 /***********************************************************************
1074 * Convert the wparam of an ASCII message to Unicode.
1077 map_wparam_AtoW( UINT message
, WPARAM wparam
)
1082 wch
[0] = wch
[1] = 0;
1086 /* WM_CHAR is magic: a DBCS char can be sent/posted as two consecutive WM_CHAR
1087 * messages, in which case the first char is stored, and the conversion
1088 * to Unicode only takes place once the second char is sent/posted.
1091 if (mapping
!= WMCHAR_MAP_NOMAPPING
) // NlsMbCodePageTag
1093 PCLIENTINFO pci
= GetWin32ClientInfo();
1095 struct wm_char_mapping_data
*data
= get_user_thread_info()->wmchar_data
;
1097 BYTE low
= LOBYTE(wparam
);
1102 ch
[1] = HIBYTE(wparam
);
1103 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
1104 TRACE( "map %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
1105 if (data
) data
->lead_byte
[mapping
] = 0;
1107 else if (data
&& data
->lead_byte
[mapping
])
1109 ch
[0] = data
->lead_byte
[mapping
];
1111 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
1112 TRACE( "map stored %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
1113 data
->lead_byte
[mapping
] = 0;
1115 else if (!IsDBCSLeadByte( low
))
1118 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 1 );
1119 TRACE( "map %02x -> %04x\n", (BYTE
)ch
[0], wch
[0] );
1120 if (data
) data
->lead_byte
[mapping
] = 0;
1122 else /* store it and wait for trail byte */
1126 if (!(data
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
) )))
1128 get_user_thread_info()->wmchar_data
= data
;
1130 TRACE( "storing lead byte %02x mapping %u\n", low
, mapping
);
1131 data
->lead_byte
[mapping
] = low
;
1134 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
1138 /* else fall through */
1140 case EM_SETPASSWORDCHAR
:
1143 case WM_SYSDEADCHAR
:
1145 ch
[0] = LOBYTE(wparam
);
1146 ch
[1] = HIBYTE(wparam
);
1147 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
1148 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
1151 ch
[0] = HIBYTE(wparam
);
1152 ch
[1] = LOBYTE(wparam
);
1153 if (ch
[0]) RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
, 2 );
1154 else RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
+ 1, 1 );
1155 wparam
= MAKEWPARAM(wch
[0], HIWORD(wparam
));
1167 GetMessageExtraInfo(VOID
)
1169 return NtUserxGetMessageExtraInfo();
1180 return NtUserxGetMessagePos();
1188 GetMessageTime(VOID
)
1190 return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME
);
1201 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1204 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1209 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1221 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1222 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1223 return ISMEX_NOSEND
;
1225 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1234 ReplyMessage(LRESULT lResult
)
1236 return NtUserxReplyMessage(lResult
);
1245 SetMessageExtraInfo(
1248 return NtUserxSetMessageExtraInfo(lParam
);
1252 IntCallWindowProcW(BOOL IsAnsiProc
,
1263 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1264 LRESULT Result
= 0, PreResult
= 0;
1267 if (WndProc
== NULL
)
1269 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1273 // Safeguard against excessive recursions.
1274 LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
1275 if (((ULONG_PTR
)&lParam
- LowLimit
) < PAGE_SIZE
)
1277 ERR("IntCallWindowsProcW() Exceeded Stack!\n");
1282 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1286 Hook
= BeginIfHookedUserApiHook();
1290 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1292 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1297 UnicodeMsg
.hwnd
= hWnd
;
1298 UnicodeMsg
.message
= Msg
;
1299 UnicodeMsg
.wParam
= wParam
;
1300 UnicodeMsg
.lParam
= lParam
;
1301 if (! MsgiUnicodeToAnsiMessage(hWnd
, &AnsiMsg
, &UnicodeMsg
))
1306 if (Hook
&& MsgOverride
)
1311 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1313 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1321 if (PreResult
) goto Exit
;
1323 _SEH2_TRY
// wine does this.
1325 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1329 ERR("Got exception when calling Ansi WndProc %p Msg %d \n",WndProc
,Msg
);
1333 if (Hook
&& MsgOverride
)
1338 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1340 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1348 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1355 if (Hook
&& MsgOverride
)
1360 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1362 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1370 if (PreResult
) goto Exit
;
1374 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1378 ERR("Got exception when calling unicode WndProc %p Msg %d \n",WndProc
, Msg
);
1382 if (Hook
&& MsgOverride
)
1387 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1389 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1391 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1399 if (Hook
) EndUserApiHook();
1403 static LRESULT FASTCALL
1404 IntCallWindowProcA(BOOL IsAnsiProc
,
1415 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1416 LRESULT Result
= 0, PreResult
= 0;
1419 if (WndProc
== NULL
)
1421 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1425 LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
1426 if (((ULONG_PTR
)&lParam
- LowLimit
) < PAGE_SIZE
)
1428 ERR("IntCallWindowsProcA() Exceeded Stack!\n");
1433 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1437 Hook
= BeginIfHookedUserApiHook();
1441 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1443 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1448 if (Hook
&& MsgOverride
)
1453 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1455 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1457 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1463 if (PreResult
) goto Exit
;
1467 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1471 ERR("Got exception when calling Ansi WndProc %p Msg %d \n",WndProc
,Msg
);
1475 if (Hook
&& MsgOverride
)
1480 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1482 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1492 AnsiMsg
.hwnd
= hWnd
;
1493 AnsiMsg
.message
= Msg
;
1494 AnsiMsg
.wParam
= wParam
;
1495 AnsiMsg
.lParam
= lParam
;
1496 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UnicodeMsg
, &AnsiMsg
))
1501 if (Hook
&& MsgOverride
)
1506 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1508 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1510 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1516 if (PreResult
) goto Exit
;
1520 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1521 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1523 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1525 ERR("Got exception when calling unicode WndProc %p Msg %d \n",WndProc
, Msg
);
1529 if (Hook
&& MsgOverride
)
1534 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1536 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1544 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1551 if (Hook
) EndUserApiHook();
1556 static LRESULT WINAPI
1557 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1563 Class
= DesktopPtrToUser(Wnd
->pcls
);
1566 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
1567 { // Must be inside the same thread!
1568 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1572 This is the message exchange for user32. If there's a need to monitor messages,
1575 TRACE("HWND %p, MSG %u, WPARAM %p, LPARAM %p, Ansi %d\n", hWnd
, Msg
, wParam
, lParam
, Ansi
);
1576 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1577 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1581 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1582 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1586 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1587 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1594 IsAnsi
= !Wnd
->Unicode
;
1595 WndProc
= Wnd
->lpfnWndProc
;
1600 IsAnsi
= !Wnd
->Unicode
;
1601 WndProc
= Wnd
->lpfnWndProc
;
1604 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1608 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1610 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1618 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1625 PCALLPROCDATA CallProc
;
1627 if (lpPrevWndFunc
== NULL
)
1629 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1633 pWnd
= ValidateHwnd(hWnd
);
1635 if (!IsCallProcHandle(lpPrevWndFunc
))
1636 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1639 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1640 if (CallProc
!= NULL
)
1642 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1643 CallProc
->pfnClientPrevious
,
1652 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1663 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1670 PCALLPROCDATA CallProc
;
1672 /* FIXME - can the first parameter be NULL? */
1673 if (lpPrevWndFunc
== NULL
)
1675 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1679 pWnd
= ValidateHwnd(hWnd
);
1681 if (!IsCallProcHandle(lpPrevWndFunc
))
1682 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1685 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1686 if (CallProc
!= NULL
)
1688 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1689 CallProc
->pfnClientPrevious
,
1698 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1709 DispatchMessageA(CONST MSG
*lpmsg
)
1716 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1718 SetLastError( ERROR_INVALID_PARAMETER
);
1722 if (lpmsg
->hwnd
!= NULL
)
1724 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1730 if (is_pointer_message(lpmsg
->message
))
1732 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1736 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1738 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1740 if ( lpmsg
->message
== WM_SYSTIMER
)
1741 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1743 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
))
1745 WARN("Validating Timer Callback failed!\n");
1749 _SEH2_TRY
// wine does this. Hint: Prevents call to another thread....
1751 Ret
= WndProc(lpmsg
->hwnd
,
1756 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1762 else if (Wnd
!= NULL
)
1764 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1766 Ret
= IntCallMessageProc(Wnd
,
1775 if (!MsgiAnsiToUnicodeMessage(lpmsg
->hwnd
, &UnicodeMsg
, (LPMSG
)lpmsg
))
1780 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1782 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1791 WARN("Exception in Timer Callback WndProcA!\n");
1801 DispatchMessageW(CONST MSG
*lpmsg
)
1807 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1809 SetLastError( ERROR_INVALID_PARAMETER
);
1813 if (lpmsg
->hwnd
!= NULL
)
1815 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1821 if (is_pointer_message(lpmsg
->message
))
1823 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1827 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1829 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1831 if ( lpmsg
->message
== WM_SYSTIMER
)
1832 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1834 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
))
1836 WARN("Validating Timer Callback failed!\n");
1842 Ret
= WndProc(lpmsg
->hwnd
,
1847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1853 else if (Wnd
!= NULL
)
1855 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1857 Ret
= IntCallMessageProc(Wnd
,
1865 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
1870 WARN("Exception in Timer Callback WndProcW!\n");
1876 IntConvertMsgToAnsi(LPMSG lpMsg
)
1881 switch (lpMsg
->message
)
1886 case WM_SYSDEADCHAR
:
1888 wch
[0] = LOWORD(lpMsg
->wParam
);
1889 wch
[1] = HIWORD(lpMsg
->wParam
);
1891 WideCharToMultiByte(CP_THREAD_ACP
, 0, wch
, 2, ch
, 2, NULL
, NULL
);
1892 lpMsg
->wParam
= MAKEWPARAM(ch
[0] | (ch
[1] << 8), 0);
1901 GetMessageA(LPMSG lpMsg
,
1908 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
1910 SetLastError( ERROR_INVALID_PARAMETER
);
1914 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1915 if (-1 == (int) Res
)
1920 IntConvertMsgToAnsi(lpMsg
);
1929 GetMessageW(LPMSG lpMsg
,
1936 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
1938 SetLastError( ERROR_INVALID_PARAMETER
);
1942 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
1943 if (-1 == (int) Res
)
1952 PeekMessageWorker( PMSG pMsg
,
1959 PCLIENTTHREADINFO pcti
;
1960 pci
= GetWin32ClientInfo();
1961 pcti
= pci
->pClientThreadInfo
;
1963 if (!hWnd
&& pci
&& pcti
)
1967 if ((pci
->cSpins
>= 100) && (pci
->dwTIFlags
& TIF_SPINNING
))
1968 { // Yield after 100 spin cycles and ready to swap vinyl.
1969 if (!(pci
->dwTIFlags
& TIF_WAITFORINPUTIDLE
))
1970 { // Not waiting for idle event.
1971 if (!pcti
->fsChangeBits
&& !pcti
->fsWakeBits
)
1972 { // No messages are available.
1973 if ((GetTickCount() - pcti
->tickLastMsgChecked
) > 1000)
1974 { // Up the msg read count if over 1 sec.
1975 NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD
);
1979 FIXME("seeSpins!\n");
1985 return NtUserPeekMessage(pMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1992 PeekMessageA(LPMSG lpMsg
,
2000 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2001 if (-1 == (int) Res
|| !Res
)
2006 IntConvertMsgToAnsi(lpMsg
);
2026 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2027 if (-1 == (int) Res
|| !Res
)
2048 /* Check for combo box or a list box to send names. */
2049 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2052 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2053 combo/list box. Forces a call like DlgDirListComboBox.
2055 //wParam |= DDL_POSTMSGS;
2056 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2059 /* No drop files or current Process, just post message. */
2060 if ( (Msg
!= WM_DROPFILES
) ||
2061 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2062 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2064 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2067 /* We have drop files and this is not the same process for this window. */
2069 /* Just incase, check wParam for Global memory handle and send size. */
2070 Ret
= SendMessageA( hWnd
,
2072 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2073 (LPARAM
)wParam
); // Send wParam as lParam.
2075 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2093 /* Check for combo box or a list box to send names. */
2094 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2097 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2098 combo/list box. Forces a call like DlgDirListComboBox.
2100 //wParam |= DDL_POSTMSGS;
2101 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2104 /* No drop files or current Process, just post message. */
2105 if ( (Msg
!= WM_DROPFILES
) ||
2106 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2107 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2109 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2112 /* We have drop files and this is not the same process for this window. */
2114 /* Just incase, check wParam for Global memory handle and send size. */
2115 Ret
= SendMessageW( hWnd
,
2117 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2118 (LPARAM
)wParam
); // Send wParam as lParam.
2120 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2133 NtUserxPostQuitMessage(nExitCode
);
2148 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2163 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2171 SendMessageW(HWND Wnd
,
2179 PTHREADINFO ti
= GetW32ThreadInfo();
2181 if ( Msg
& ~WM_MAXIMUM
)
2183 SetLastError( ERROR_INVALID_PARAMETER
);
2187 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2189 Window
= ValidateHwnd(Wnd
);
2191 if ( Window
!= NULL
&&
2192 Window
->head
.pti
== ti
&&
2193 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
2194 !ISITHOOKED(WH_CALLWNDPROC
) &&
2195 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2196 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2198 /* NOTE: We can directly send messages to the window procedure
2199 if *all* the following conditions are met:
2201 * Window belongs to calling thread
2202 * The calling thread is not being hooked for CallWndProc
2203 * Not calling a server side proc:
2204 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2207 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2212 UMMsg
.message
= Msg
;
2213 UMMsg
.wParam
= wParam
;
2214 UMMsg
.lParam
= lParam
;
2216 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2221 Result
= NtUserMessageCall( Wnd
,
2229 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2239 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2241 MSG AnsiMsg
, UcMsg
, KMMsg
;
2244 PTHREADINFO ti
= GetW32ThreadInfo();
2246 if ( Msg
& ~WM_MAXIMUM
)
2248 SetLastError( ERROR_INVALID_PARAMETER
);
2252 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2254 Window
= ValidateHwnd(Wnd
);
2256 if ( Window
!= NULL
&&
2257 Window
->head
.pti
== ti
&&
2258 // !IsThreadHooked(GetWin32ClientInfo()) && // Enable to test message system bug.
2259 !ISITHOOKED(WH_CALLWNDPROC
) &&
2260 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2261 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2263 /* NOTE: We can directly send messages to the window procedure
2264 if *all* the following conditions are met:
2266 * Window belongs to calling thread
2267 * The calling thread is not being hooked for CallWndProc
2268 * Not calling a server side proc:
2269 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2272 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2277 AnsiMsg
.message
= Msg
;
2278 AnsiMsg
.wParam
= wParam
;
2279 AnsiMsg
.lParam
= lParam
;
2281 if (!MsgiAnsiToUnicodeMessage(Wnd
, &UcMsg
, &AnsiMsg
))
2286 if (!MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2288 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2292 Result
= NtUserMessageCall( Wnd
,
2300 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2301 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2311 SendMessageCallbackA(
2316 SENDASYNCPROC lpCallBack
,
2321 CALL_BACK_INFO CallBackInfo
;
2323 if (is_pointer_message(Msg
))
2325 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2329 CallBackInfo
.CallBack
= lpCallBack
;
2330 CallBackInfo
.Context
= dwData
;
2332 AnsiMsg
.hwnd
= hWnd
;
2333 AnsiMsg
.message
= Msg
;
2334 AnsiMsg
.wParam
= wParam
;
2335 AnsiMsg
.lParam
= lParam
;
2337 if (!MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2342 Result
= NtUserMessageCall( hWnd
,
2346 (ULONG_PTR
)&CallBackInfo
,
2347 FNID_SENDMESSAGECALLBACK
,
2350 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2360 SendMessageCallbackW(
2365 SENDASYNCPROC lpCallBack
,
2368 CALL_BACK_INFO CallBackInfo
;
2370 if (is_pointer_message(Msg
))
2372 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2376 CallBackInfo
.CallBack
= lpCallBack
;
2377 CallBackInfo
.Context
= dwData
;
2379 return NtUserMessageCall(hWnd
,
2383 (ULONG_PTR
)&CallBackInfo
,
2384 FNID_SENDMESSAGECALLBACK
,
2393 SendMessageTimeoutA(
2400 PDWORD_PTR lpdwResult
)
2406 PTHREADINFO ti
= GetW32ThreadInfo();
2408 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2410 SetLastError( ERROR_INVALID_PARAMETER
);
2414 if (lpdwResult
) *lpdwResult
= 0;
2416 //// This is due to message system bug.
2417 if (hWnd
!= HWND_TOPMOST
&& hWnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2419 Window
= ValidateHwnd(hWnd
);
2421 if ( Window
!= NULL
&&
2422 Window
->head
.pti
== ti
&&
2423 !ISITHOOKED(WH_CALLWNDPROC
) &&
2424 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2425 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2427 Result
= IntCallMessageProc(Window
, hWnd
, Msg
, wParam
, lParam
, TRUE
);
2428 if (lpdwResult
) *lpdwResult
= Result
;
2433 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2435 dsm
.uFlags
= fuFlags
;
2436 dsm
.uTimeout
= uTimeout
;
2438 AnsiMsg
.hwnd
= hWnd
;
2439 AnsiMsg
.message
= Msg
;
2440 AnsiMsg
.wParam
= wParam
;
2441 AnsiMsg
.lParam
= lParam
;
2443 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2448 Result
= NtUserMessageCall( hWnd
,
2453 FNID_SENDMESSAGEWTOOPTION
,
2456 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2458 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2460 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2471 SendMessageTimeoutW(
2478 PDWORD_PTR lpdwResult
)
2483 PTHREADINFO ti
= GetW32ThreadInfo();
2485 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2487 SetLastError( ERROR_INVALID_PARAMETER
);
2491 if (lpdwResult
) *lpdwResult
= 0;
2493 //// This is due to message system bug.
2494 if (hWnd
!= HWND_TOPMOST
&& hWnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2496 Window
= ValidateHwnd(hWnd
);
2498 if ( Window
!= NULL
&&
2499 Window
->head
.pti
== ti
&&
2500 !ISITHOOKED(WH_CALLWNDPROC
) &&
2501 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2502 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2504 Result
= IntCallMessageProc(Window
, hWnd
, Msg
, wParam
, lParam
, FALSE
);
2505 if (lpdwResult
) *lpdwResult
= Result
;
2510 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2512 dsm
.uFlags
= fuFlags
;
2513 dsm
.uTimeout
= uTimeout
;
2515 Result
= NtUserMessageCall( hWnd
,
2520 FNID_SENDMESSAGEWTOOPTION
,
2523 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2525 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2544 if (is_pointer_message(Msg
))
2546 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2550 AnsiMsg
.hwnd
= hWnd
;
2551 AnsiMsg
.message
= Msg
;
2552 AnsiMsg
.wParam
= wParam
;
2553 AnsiMsg
.lParam
= lParam
;
2554 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2558 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2560 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2579 if (is_pointer_message(Msg
))
2581 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2586 UMMsg
.message
= Msg
;
2587 UMMsg
.wParam
= wParam
;
2588 UMMsg
.lParam
= lParam
;
2589 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2593 Result
= NtUserMessageCall( hWnd
,
2598 FNID_SENDNOTIFYMESSAGE
,
2601 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2610 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2612 switch (lpMsg
->message
)
2618 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2621 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2622 SetLastError(ERROR_INVALID_PARAMETER
);
2632 TranslateMessage(CONST MSG
*lpMsg
)
2636 // Ref: msdn ImmGetVirtualKey:
2637 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2639 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2640 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2645 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2655 RegisterWindowMessageA(LPCSTR lpString
)
2657 UNICODE_STRING String
;
2661 Result
= RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
);
2666 Atom
= NtUserRegisterWindowMessage(&String
);
2667 RtlFreeUnicodeString(&String
);
2676 RegisterWindowMessageW(LPCWSTR lpString
)
2678 UNICODE_STRING String
;
2680 RtlInitUnicodeString(&String
, lpString
);
2681 return(NtUserRegisterWindowMessage(&String
));
2690 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2697 ReleaseCapture(VOID
)
2699 return NtUserxReleaseCapture();
2708 RealGetQueueStatus(UINT flags
)
2710 #define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT
2711 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_TEMPALLINPUT
))
2713 SetLastError( ERROR_INVALID_FLAGS
);
2716 return NtUserxGetQueueStatus(flags
);
2723 BOOL WINAPI
GetInputState(VOID
)
2725 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2727 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2728 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2735 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2737 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2741 PCLIENTINFO pci
= GetWin32ClientInfo();
2743 /* Make sure we don't try to access mem beyond what we were given */
2744 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2746 return STATUS_INFO_LENGTH_MISMATCH
;
2749 LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
2750 if (((ULONG_PTR
)&ArgumentLength
- LowLimit
) < PAGE_SIZE
)
2752 ERR("Callback from Win32k Exceeded Stack!\n");
2753 return STATUS_BAD_STACK
;
2756 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2757 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2758 KMMsg
.message
= CallbackArgs
->Msg
;
2759 KMMsg
.wParam
= CallbackArgs
->wParam
;
2760 /* Check if lParam is really a pointer and adjust it if it is */
2761 if (0 <= CallbackArgs
->lParamBufferSize
)
2763 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2764 + CallbackArgs
->lParamBufferSize
)
2766 return STATUS_INFO_LENGTH_MISMATCH
;
2768 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2772 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2774 return STATUS_INFO_LENGTH_MISMATCH
;
2776 KMMsg
.lParam
= CallbackArgs
->lParam
;
2779 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2781 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2782 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2785 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2789 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2790 pWnd
= pci
->CallbackWnd
.pWnd
;
2792 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
2800 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2804 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2810 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
2812 /* Function does nothing on 32 bit windows */
2815 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
2816 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
2817 typedef BOOL (WINAPI
* RealInternalGetMessageProc
)(LPMSG
,HWND
,UINT
,UINT
,UINT
,BOOL
);
2818 typedef BOOL (WINAPI
* RealWaitMessageExProc
)(DWORD
,UINT
);
2820 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
2822 RealInternalGetMessageProc NtUserRealInternalGetMessage
;
2823 RealWaitMessageExProc NtUserRealWaitMessageEx
;
2824 RealGetQueueStatusProc RealGetQueueStatus
;
2825 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
2826 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
2830 RealMsgWaitForMultipleObjectsEx(
2832 CONST HANDLE
*pHandles
,
2833 DWORD dwMilliseconds
,
2837 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
2839 CRITICAL_SECTION gcsMPH
;
2840 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
2841 DWORD gcLoadMPH
= 0;
2842 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
2843 NtUserRealInternalGetMessage
,
2844 NtUserRealWaitMessageEx
,
2846 RealMsgWaitForMultipleObjectsEx
2849 DWORD gfMessagePumpHook
= 0;
2851 BOOL WINAPI
IsInsideMessagePumpHook()
2852 { // FF uses this and polls it when Min/Max
2853 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2854 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
2857 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
2859 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
2860 Addresses
->NtUserRealInternalGetMessage
= NtUserRealInternalGetMessage
;
2861 Addresses
->NtUserRealWaitMessageEx
= NtUserRealWaitMessageEx
;
2862 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
2863 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
2866 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
2868 EnterCriticalSection(&gcsMPH
);
2870 SetLastError(ERROR_INVALID_PARAMETER
);
2871 LeaveCriticalSection(&gcsMPH
);
2875 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
2877 ResetMessagePumpHook(&Addresses
);
2878 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
2879 LeaveCriticalSection(&gcsMPH
);
2882 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
2884 if(gpfnInitMPH
!= Hook
) {
2885 LeaveCriticalSection(&gcsMPH
);
2889 if(NtUserxInitMessagePump()) {
2890 LeaveCriticalSection(&gcsMPH
);
2894 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
2896 LeaveCriticalSection(&gcsMPH
);
2900 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
2902 EnterCriticalSection(&gcsMPH
);
2904 if(NtUserxUnInitMessagePump()) {
2907 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
2908 gpfnInitMPH(TRUE
, NULL
);
2909 ResetMessagePumpHook(&gmph
);
2912 LeaveCriticalSection(&gcsMPH
);
2916 LeaveCriticalSection(&gcsMPH
);
2920 DWORD WINAPI
GetQueueStatus(UINT flags
)
2922 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
2926 * @name RealMsgWaitForMultipleObjectsEx
2928 * Wait either for either message arrival or for one of the passed events
2932 * Number of handles in the pHandles array.
2934 * Handles of events to wait for.
2935 * @param dwMilliseconds
2938 * Mask specifying on which message events we should wakeup.
2940 * Wait type (see MWMO_* constants).
2946 RealMsgWaitForMultipleObjectsEx(
2948 const HANDLE
*pHandles
,
2949 DWORD dwMilliseconds
,
2953 LPHANDLE RealHandles
;
2954 HANDLE MessageQueueHandle
;
2957 PCLIENTTHREADINFO pcti
;
2959 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
2961 SetLastError(ERROR_INVALID_PARAMETER
);
2965 pci
= GetWin32ClientInfo();
2966 if (!pci
) return WAIT_FAILED
;
2968 pcti
= pci
->pClientThreadInfo
;
2969 if (pcti
&& ( !nCount
|| !(dwFlags
& MWMO_WAITALL
) ))
2971 if ( (pcti
->fsChangeBits
& LOWORD(dwWakeMask
)) ||
2972 ( (dwFlags
& MWMO_INPUTAVAILABLE
) && (pcti
->fsWakeBits
& LOWORD(dwWakeMask
)) ) )
2974 //FIXME("Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
2979 MessageQueueHandle
= NtUserxMsqSetWakeMask(MAKELONG(dwWakeMask
, dwFlags
));
2980 if (MessageQueueHandle
== NULL
)
2982 SetLastError(0); /* ? */
2986 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
2987 if (RealHandles
== NULL
)
2989 NtUserxMsqClearWakeMask();
2990 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2994 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
2995 RealHandles
[nCount
] = MessageQueueHandle
;
2997 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
2998 dwFlags
& MWMO_WAITALL
,
2999 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
3001 HeapFree(GetProcessHeap(), 0, RealHandles
);
3002 NtUserxMsqClearWakeMask();
3003 //FIXME("Result 0X%x\n",Result);
3011 MsgWaitForMultipleObjectsEx(
3013 CONST HANDLE
*lpHandles
,
3014 DWORD dwMilliseconds
,
3018 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
3025 MsgWaitForMultipleObjects(
3027 CONST HANDLE
*lpHandles
,
3029 DWORD dwMilliseconds
,
3032 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
3033 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
3037 BOOL FASTCALL
MessageInit(VOID
)
3039 InitializeCriticalSection(&DdeCrst
);
3040 InitializeCriticalSection(&gcsMPH
);
3045 VOID FASTCALL
MessageCleanup(VOID
)
3047 DeleteCriticalSection(&DdeCrst
);
3048 DeleteCriticalSection(&gcsMPH
);
3055 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
3058 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
3059 return IsDialogMessageW( hwndDlg
, &msg
);
3064 IntBroadcastSystemMessage(
3066 LPDWORD lpdwRecipients
,
3074 DWORD recips
= BSM_ALLCOMPONENTS
;
3075 BOOL ret
= -1; // Set to return fail
3076 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
3077 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
3078 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
3080 if ((dwflags
& ~all_flags
) ||
3081 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
3083 SetLastError(ERROR_INVALID_PARAMETER
);
3087 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
3089 SetLastError(ERROR_INVALID_PARAMETER
);
3093 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
3095 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
3097 if (!lpdwRecipients
)
3098 lpdwRecipients
= &recips
;
3100 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
3102 SetLastError(ERROR_INVALID_PARAMETER
);
3106 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3108 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
3110 SetLastError(ERROR_INVALID_PARAMETER
);
3117 parm
.flags
= dwflags
;
3118 parm
.recipients
= *lpdwRecipients
;
3120 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
3122 ret
= NtUserMessageCall(GetDesktopWindow(),
3127 FNID_BROADCASTSYSTEMMESSAGE
,
3132 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3134 pBSMInfo
->hdesk
= parm
.hDesk
;
3135 pBSMInfo
->hwnd
= parm
.hWnd
;
3146 BroadcastSystemMessageA(
3148 LPDWORD lpdwRecipients
,
3153 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
3161 BroadcastSystemMessageW(
3163 LPDWORD lpdwRecipients
,
3168 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3176 BroadcastSystemMessageExA(
3178 LPDWORD lpdwRecipients
,
3184 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3192 BroadcastSystemMessageExW(
3194 LPDWORD lpdwRecipients
,
3200 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);