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
);
239 DWORD FASTCALL
get_input_codepage( void )
243 HKL hkl
= GetKeyboardLayout( 0 );
244 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
245 if (!ret
) cp
= CP_ACP
;
249 static WPARAM FASTCALL
map_wparam_char_WtoA( WPARAM wParam
, DWORD len
)
253 DWORD cp
= get_input_codepage();
255 len
= WideCharToMultiByte( cp
, 0, &wch
, 1, (LPSTR
)ch
, len
, NULL
, NULL
);
257 return MAKEWPARAM( (ch
[0] << 8) | ch
[1], HIWORD(wParam
) );
259 return MAKEWPARAM( ch
[0], HIWORD(wParam
) );
262 /***********************************************************************
265 * Convert the wparam of an ASCII message to Unicode.
267 static WPARAM FASTCALL
268 map_wparam_AtoW( UINT message
, WPARAM wparam
)
277 /* WM_CHAR is magic: a DBCS char can be sent/posted as two consecutive WM_CHAR
278 * messages, in which case the first char is stored, and the conversion
279 * to Unicode only takes place once the second char is sent/posted.
282 if (mapping
!= WMCHAR_MAP_NOMAPPING
) // NlsMbCodePageTag
284 PCLIENTINFO pci
= GetWin32ClientInfo();
286 struct wm_char_mapping_data
*data
= get_user_thread_info()->wmchar_data
;
288 BYTE low
= LOBYTE(wparam
);
293 ch
[1] = HIBYTE(wparam
);
294 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
295 TRACE( "map %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
296 if (data
) data
->lead_byte
[mapping
] = 0;
298 else if (data
&& data
->lead_byte
[mapping
])
300 ch
[0] = data
->lead_byte
[mapping
];
302 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
303 TRACE( "map stored %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
304 data
->lead_byte
[mapping
] = 0;
306 else if (!IsDBCSLeadByte( low
))
309 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 1 );
310 TRACE( "map %02x -> %04x\n", (BYTE
)ch
[0], wch
[0] );
311 if (data
) data
->lead_byte
[mapping
] = 0;
313 else /* store it and wait for trail byte */
317 if (!(data
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
) )))
319 get_user_thread_info()->wmchar_data
= data
;
321 TRACE( "storing lead byte %02x mapping %u\n", low
, mapping
);
322 data
->lead_byte
[mapping
] = low
;
325 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
329 /* else fall through */
331 case EM_SETPASSWORDCHAR
:
336 ch
[0] = LOBYTE(wparam
);
337 ch
[1] = HIBYTE(wparam
);
338 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
339 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
342 ch
[0] = HIBYTE(wparam
);
343 ch
[1] = LOBYTE(wparam
);
344 if (ch
[0]) RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
, 2 );
345 else RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
+ 1, 1 );
346 wparam
= MAKEWPARAM(wch
[0], HIWORD(wparam
));
354 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
358 switch (UMMsg
->message
)
362 PKMDDELPARAM DdeLparam
;
363 DdeLparam
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM
));
365 !UnpackDDElParam( UMMsg
->message
, UMMsg
->lParam
, &DdeLparam
->uiLo
, &DdeLparam
->uiHi
))
368 If this is a reply to WM_DDE_EXECUTE then
369 uiHi will contain a hMem, hence >= 0x10000.
370 Otherwise, it will be be an atom, a 16-bit value.
372 if (!IS_ATOM(DdeLparam
->uiHi
))
374 HGLOBAL h
= DdeGetPair((HGLOBAL
)(ULONG_PTR
)DdeLparam
->uiHi
);
377 GlobalFree((HGLOBAL
)(ULONG_PTR
)DdeLparam
->uiHi
);
378 DdeLparam
->uiHi
= (UINT_PTR
) h
;
381 FreeDDElParam(UMMsg
->message
, UMMsg
->lParam
);
382 KMMsg
->lParam
= (LPARAM
) DdeLparam
;
389 PKMDDEEXECUTEDATA KMDdeExecuteData
;
392 Size
= GlobalSize((HGLOBAL
) UMMsg
->lParam
);
393 Data
= GlobalLock((HGLOBAL
) UMMsg
->lParam
);
396 SetLastError(ERROR_INVALID_HANDLE
);
399 KMDdeExecuteData
= HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA
) + Size
);
400 if (!KMDdeExecuteData
)
402 SetLastError(ERROR_OUTOFMEMORY
);
405 KMDdeExecuteData
->Sender
= (HWND
) UMMsg
->wParam
;
406 KMDdeExecuteData
->ClientMem
= (HGLOBAL
) UMMsg
->lParam
;
407 memcpy((PVOID
) (KMDdeExecuteData
+ 1), Data
, Size
);
408 KMMsg
->wParam
= sizeof(KMDDEEXECUTEDATA
) + Size
;
409 KMMsg
->lParam
= (LPARAM
) KMDdeExecuteData
;
410 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
416 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
417 PCOPYDATASTRUCT pKMCopyData
;
419 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0,
420 sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
423 SetLastError(ERROR_OUTOFMEMORY
);
427 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
428 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
429 pKMCopyData
->lpData
= pKMCopyData
+ 1;
431 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
,
432 pUMCopyData
->cbData
);
434 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
447 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
449 switch (KMMsg
->message
)
454 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
464 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
468 switch (UMMsg
->message
)
473 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
475 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
476 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
477 if (L
'A' == *((WCHAR
*) Class
))
479 Class
+= sizeof(WCHAR
);
480 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
484 ASSERT(L
'S' == *((WCHAR
*) Class
));
485 Class
+= sizeof(WCHAR
);
486 Cs
->lpszClass
= (LPCWSTR
) Class
;
493 PKMDDELPARAM DdeLparam
= (PKMDDELPARAM
) KMMsg
->lParam
;
494 UMMsg
->lParam
= PackDDElParam(KMMsg
->message
, DdeLparam
->uiLo
, DdeLparam
->uiHi
);
500 PKMDDEEXECUTEDATA KMDdeExecuteData
;
504 KMDdeExecuteData
= (PKMDDEEXECUTEDATA
) KMMsg
->lParam
;
505 GlobalData
= GlobalAlloc(GMEM_MOVEABLE
, KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
510 Data
= GlobalLock(GlobalData
);
513 GlobalFree(GlobalData
);
516 memcpy(Data
, (PVOID
) (KMDdeExecuteData
+ 1), KMMsg
->wParam
- sizeof(KMDDEEXECUTEDATA
));
517 GlobalUnlock(GlobalData
);
518 if (!DdeAddPair(KMDdeExecuteData
->ClientMem
, GlobalData
))
520 GlobalFree(GlobalData
);
523 UMMsg
->wParam
= (WPARAM
) KMDdeExecuteData
->Sender
;
524 UMMsg
->lParam
= (LPARAM
) GlobalData
;
530 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
531 pKMCopyData
->lpData
= pKMCopyData
+ 1;
543 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
545 switch (KMMsg
->message
)
549 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
550 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
561 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
563 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
569 // Ansi to Unicode -> callout
572 MsgiAnsiToUnicodeMessage(HWND hwnd
, LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
574 UNICODE_STRING UnicodeString
;
576 *UnicodeMsg
= *AnsiMsg
;
578 switch (AnsiMsg
->message
)
581 case WM_ASKCBFORMATNAME
:
584 if (!AnsiMsg
->lParam
) break;
585 Buffer
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, AnsiMsg
->wParam
* sizeof(WCHAR
));
586 //ERR("WM_GETTEXT A2U Size %d\n",AnsiMsg->wParam);
587 if (!Buffer
) return FALSE
;
588 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
594 DWORD Size
= 1024 * sizeof(WCHAR
);
595 if (!AnsiMsg
->lParam
|| !listbox_has_strings( AnsiMsg
->hwnd
)) break;
596 /*Size = SendMessageW( AnsiMsg->hwnd, LB_GETTEXTLEN, AnsiMsg->wParam, 0 );
599 ERR("LB_GETTEXT LB_ERR\n");
600 Size = sizeof(ULONG_PTR);
602 Size = (Size + 1) * sizeof(WCHAR);*/
603 UnicodeMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
604 if (!UnicodeMsg
->lParam
) return FALSE
;
610 DWORD Size
= 1024 * sizeof(WCHAR
);
611 if (!AnsiMsg
->lParam
|| !combobox_has_strings( AnsiMsg
->hwnd
)) break;
612 /*Size = SendMessageW( AnsiMsg->hwnd, CB_GETLBTEXTLEN, AnsiMsg->wParam, 0 );
615 ERR("CB_GETTEXT LB_ERR\n");
616 Size = sizeof(ULONG_PTR);
618 Size = (Size + 1) * sizeof(WCHAR);*/
619 UnicodeMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
620 if (!UnicodeMsg
->lParam
) return FALSE
;
624 /* AnsiMsg->lParam is string (0-terminated) */
626 case WM_WININICHANGE
:
627 case WM_DEVMODECHANGE
:
633 if (!AnsiMsg
->lParam
) break;
634 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
635 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
640 case LB_ADDSTRING_LOWER
:
641 case LB_ADDSTRING_UPPER
:
642 case LB_INSERTSTRING
:
643 case LB_INSERTSTRING_UPPER
:
644 case LB_INSERTSTRING_LOWER
:
646 case LB_FINDSTRINGEXACT
:
647 case LB_SELECTSTRING
:
649 if (AnsiMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
651 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
652 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
658 case CB_INSERTSTRING
:
660 case CB_FINDSTRINGEXACT
:
661 case CB_SELECTSTRING
:
663 if (AnsiMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
665 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
666 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
674 MDICREATESTRUCTW mdi_cs
;
677 CREATESTRUCTW cs
; /* new structure */
678 LPCWSTR lpszName
; /* allocated Name */
679 LPCWSTR lpszClass
; /* allocated Class */
682 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
687 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
688 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
690 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
691 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
693 if (!IS_ATOM(xs
->cs
.lpszClass
))
695 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
696 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
699 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
701 mdi_cs
= *(MDICREATESTRUCTW
*)xs
->cs
.lpCreateParams
;
702 mdi_cs
.szTitle
= xs
->cs
.lpszName
;
703 mdi_cs
.szClass
= xs
->cs
.lpszClass
;
704 xs
->cs
.lpCreateParams
= &mdi_cs
;
707 UnicodeMsg
->lParam
= (LPARAM
)xs
;
713 MDICREATESTRUCTW
*cs
=
714 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
721 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
723 if (!IS_ATOM(cs
->szClass
))
725 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
726 cs
->szClass
= UnicodeString
.Buffer
;
729 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
730 cs
->szTitle
= UnicodeString
.Buffer
;
732 UnicodeMsg
->lParam
= (LPARAM
)cs
;
737 if (UnicodeMsg
->lParam
)
739 MSG newmsg
= *(MSG
*)UnicodeMsg
->lParam
;
740 newmsg
.wParam
= map_wparam_AtoW( newmsg
.message
, newmsg
.wParam
);
750 case EM_SETPASSWORDCHAR
:
752 UnicodeMsg
->wParam
= map_wparam_AtoW( AnsiMsg
->message
, AnsiMsg
->wParam
);
755 ERR("FIXME EM_GETLINE A2U\n");
764 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
766 UNICODE_STRING UnicodeString
;
768 switch (AnsiMsg
->message
)
771 if (!listbox_has_strings( UnicodeMsg
->hwnd
)) break;
773 if (UnicodeMsg
->message
== CB_GETLBTEXT
&& !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
775 case WM_ASKCBFORMATNAME
:
777 if (!UnicodeMsg
->lParam
) break;
778 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
783 case WM_WININICHANGE
:
784 case WM_DEVMODECHANGE
:
790 if (!UnicodeMsg
->lParam
) break;
791 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
792 RtlFreeUnicodeString(&UnicodeString
);
797 case LB_ADDSTRING_LOWER
:
798 case LB_ADDSTRING_UPPER
:
799 case LB_INSERTSTRING
:
800 case LB_INSERTSTRING_UPPER
:
801 case LB_INSERTSTRING_LOWER
:
803 case LB_FINDSTRINGEXACT
:
804 case LB_SELECTSTRING
:
806 if (UnicodeMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
808 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
809 RtlFreeUnicodeString(&UnicodeString
);
815 case CB_INSERTSTRING
:
817 case CB_FINDSTRINGEXACT
:
818 case CB_SELECTSTRING
:
820 if (UnicodeMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
822 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
823 RtlFreeUnicodeString(&UnicodeString
);
833 CREATESTRUCTW cs
; /* new structure */
834 LPWSTR lpszName
; /* allocated Name */
835 LPWSTR lpszClass
; /* allocated Class */
838 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
841 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
842 RtlFreeUnicodeString(&UnicodeString
);
846 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
847 RtlFreeUnicodeString(&UnicodeString
);
849 HeapFree(GetProcessHeap(), 0, xs
);
855 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
856 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
857 RtlFreeUnicodeString(&UnicodeString
);
858 if (!IS_ATOM(cs
->szClass
))
860 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
861 RtlFreeUnicodeString(&UnicodeString
);
863 HeapFree(GetProcessHeap(), 0, cs
);
872 * callout return -> Unicode Result to Ansi Result
875 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
877 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
878 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
880 switch (AnsiMsg
->message
)
883 case WM_ASKCBFORMATNAME
:
885 if (UnicodeMsg
->wParam
)
888 if (*Result
) RtlUnicodeToMultiByteN( AnsiBuffer
, UnicodeMsg
->wParam
- 1, &len
, Buffer
, strlenW(Buffer
) * sizeof(WCHAR
));
891 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam);
897 if (!AnsiBuffer
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
901 RtlUnicodeToMultiByteN( AnsiBuffer
, ~0u, &len
, Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
) );
908 if (!AnsiBuffer
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
912 RtlUnicodeToMultiByteN( AnsiBuffer
, ~0u, &len
, Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
) );
919 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
925 // Unicode to Ansi callout ->
928 MsgiUnicodeToAnsiMessage(HWND hwnd
, LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
930 ANSI_STRING AnsiString
;
931 UNICODE_STRING UnicodeString
;
933 *AnsiMsg
= *UnicodeMsg
;
935 switch(UnicodeMsg
->message
)
940 MDICREATESTRUCTA
*pmdi_cs
;
945 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
946 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
) + sizeof(MDICREATESTRUCTA
));
951 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
953 /* pmdi_cs starts right after CsA */
954 pmdi_cs
= (MDICREATESTRUCTA
*)(CsA
+ 1);
956 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
957 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
958 if (! NT_SUCCESS(Status
))
960 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
963 CsA
->lpszName
= AnsiString
.Buffer
;
964 if (HIWORD((ULONG_PTR
)CsW
->lpszClass
) != 0)
966 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
967 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, TRUE
);
968 if (! NT_SUCCESS(Status
))
970 RtlInitAnsiString(&AnsiString
, CsA
->lpszName
);
971 RtlFreeAnsiString(&AnsiString
);
972 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
975 CsA
->lpszClass
= AnsiString
.Buffer
;
978 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
980 *pmdi_cs
= *(MDICREATESTRUCTA
*)CsW
->lpCreateParams
;
981 pmdi_cs
->szTitle
= CsA
->lpszName
;
982 pmdi_cs
->szClass
= CsA
->lpszClass
;
983 CsA
->lpCreateParams
= pmdi_cs
;
986 AnsiMsg
->lParam
= (LPARAM
)CsA
;
990 case WM_ASKCBFORMATNAME
:
992 if (!UnicodeMsg
->lParam
) break;
993 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
994 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, UnicodeMsg
->wParam
* 2);
995 //ERR("WM_GETTEXT U2A Size %d\n",AnsiMsg->wParam);
996 if (!AnsiMsg
->lParam
) return FALSE
;
1003 if (!UnicodeMsg
->lParam
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
1004 /*Size = SendMessageA( UnicodeMsg->hwnd, LB_GETTEXTLEN, UnicodeMsg->wParam, 0 );
1007 ERR("LB_GETTEXT LB_ERR\n");
1008 Size = sizeof(ULONG_PTR);
1010 Size = (Size + 1) * sizeof(WCHAR);*/
1011 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
1012 if (!AnsiMsg
->lParam
) return FALSE
;
1019 if (!UnicodeMsg
->lParam
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
1020 /*Size = SendMessageA( UnicodeMsg->hwnd, CB_GETLBTEXTLEN, UnicodeMsg->wParam, 0 );
1023 ERR("CB_GETTEXT LB_ERR\n");
1024 Size = sizeof(ULONG_PTR);
1026 Size = (Size + 1) * sizeof(WCHAR);*/
1027 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
1028 if (!AnsiMsg
->lParam
) return FALSE
;
1033 case WM_WININICHANGE
:
1034 case WM_DEVMODECHANGE
:
1040 if (!UnicodeMsg
->lParam
) break;
1041 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
1042 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1048 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
1053 case LB_ADDSTRING_LOWER
:
1054 case LB_ADDSTRING_UPPER
:
1055 case LB_INSERTSTRING
:
1056 case LB_INSERTSTRING_UPPER
:
1057 case LB_INSERTSTRING_LOWER
:
1059 case LB_FINDSTRINGEXACT
:
1060 case LB_SELECTSTRING
:
1062 if (UnicodeMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
1064 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
1065 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1071 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
1077 case CB_INSERTSTRING
:
1079 case CB_FINDSTRINGEXACT
:
1080 case CB_SELECTSTRING
:
1082 if (UnicodeMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
1084 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
1085 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1091 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
1098 MDICREATESTRUCTA
*cs
=
1099 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
1106 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
1108 if (!IS_ATOM(cs
->szClass
))
1110 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
1111 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1115 HeapFree(GetProcessHeap(), 0, cs
);
1118 cs
->szClass
= AnsiString
.Buffer
;
1121 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
1122 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1126 if (!IS_ATOM(cs
->szClass
))
1128 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
1129 RtlFreeAnsiString(&AnsiString
);
1132 HeapFree(GetProcessHeap(), 0, cs
);
1135 cs
->szTitle
= AnsiString
.Buffer
;
1137 AnsiMsg
->lParam
= (LPARAM
)cs
;
1142 if (UnicodeMsg
->lParam
)
1144 MSG newmsg
= *(MSG
*)UnicodeMsg
->lParam
;
1145 switch(newmsg
.message
)
1150 case WM_SYSDEADCHAR
:
1151 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 1 );
1154 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 2 );
1162 WCHAR wch
= UnicodeMsg
->wParam
;
1164 DWORD cp
= get_input_codepage();
1165 DWORD len
= WideCharToMultiByte( cp
, 0, &wch
, 1, ch
, 2, NULL
, NULL
);
1166 AnsiMsg
->wParam
= (BYTE
)ch
[0];
1167 if (len
== 2) AnsiMsg
->wParam
= (BYTE
)ch
[1];
1175 case WM_SYSDEADCHAR
:
1176 case EM_SETPASSWORDCHAR
:
1177 AnsiMsg
->wParam
= map_wparam_char_WtoA(UnicodeMsg
->wParam
,1);
1181 AnsiMsg
->wParam
= map_wparam_char_WtoA(UnicodeMsg
->wParam
,2);
1184 ERR("FIXME EM_GETLINE U2A\n");
1190 static BOOL FASTCALL
1191 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
1193 ANSI_STRING AnsiString
;
1195 switch(UnicodeMsg
->message
)
1198 if (!listbox_has_strings( AnsiMsg
->hwnd
)) break;
1200 if (AnsiMsg
->message
== CB_GETLBTEXT
&& !combobox_has_strings( AnsiMsg
->hwnd
)) break;
1202 case WM_ASKCBFORMATNAME
:
1204 if (!AnsiMsg
->lParam
) break;
1205 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
1213 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
1214 RtlInitAnsiString(&AnsiString
, Cs
->lpszName
);
1215 RtlFreeAnsiString(&AnsiString
);
1216 if (HIWORD((ULONG_PTR
)Cs
->lpszClass
) != 0)
1218 RtlInitAnsiString(&AnsiString
, Cs
->lpszClass
);
1219 RtlFreeAnsiString(&AnsiString
);
1221 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
1226 case WM_WININICHANGE
:
1227 case WM_DEVMODECHANGE
:
1233 if (!AnsiMsg
->lParam
) break;
1234 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1235 RtlFreeAnsiString(&AnsiString
);
1240 case LB_ADDSTRING_LOWER
:
1241 case LB_ADDSTRING_UPPER
:
1242 case LB_INSERTSTRING
:
1243 case LB_INSERTSTRING_UPPER
:
1244 case LB_INSERTSTRING_LOWER
:
1246 case LB_FINDSTRINGEXACT
:
1247 case LB_SELECTSTRING
:
1249 if (AnsiMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
1251 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1252 RtlFreeAnsiString(&AnsiString
);
1258 case CB_INSERTSTRING
:
1260 case CB_FINDSTRINGEXACT
:
1261 case CB_SELECTSTRING
:
1263 if (AnsiMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
1265 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1266 RtlFreeAnsiString(&AnsiString
);
1273 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
1274 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
1275 RtlFreeAnsiString(&AnsiString
);
1276 if (!IS_ATOM(cs
->szClass
))
1278 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
1279 RtlFreeAnsiString(&AnsiString
);
1281 HeapFree(GetProcessHeap(), 0, cs
);
1291 * callout return -> Ansi Result to Unicode Result
1293 static BOOL FASTCALL
1294 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
1296 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1297 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1299 switch (UnicodeMsg
->message
)
1302 case WM_ASKCBFORMATNAME
:
1304 DWORD len
= AnsiMsg
->wParam
;// * 2;
1309 RtlMultiByteToUnicodeN( UBuffer
, AnsiMsg
->wParam
*sizeof(WCHAR
), &len
, Buffer
, strlen(Buffer
)+1 );
1310 *Result
= len
/sizeof(WCHAR
) - 1; /* do not count terminating null */
1311 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam);
1313 UBuffer
[*Result
] = 0;
1319 if (!UBuffer
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
1323 RtlMultiByteToUnicodeN( UBuffer
, ~0u, &len
, Buffer
, strlen(Buffer
) + 1 );
1324 *Result
= len
/ sizeof(WCHAR
) - 1;
1330 if (!UBuffer
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
1334 RtlMultiByteToUnicodeN( UBuffer
, ~0u, &len
, Buffer
, strlen(Buffer
) + 1 );
1335 *Result
= len
/ sizeof(WCHAR
) - 1;
1341 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
1349 DesktopWndProcA( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1354 TRACE("Desktop A Class Atom! hWnd 0x%x, Msg %d\n", hwnd
, message
);
1356 AnsiMsg
.hwnd
= hwnd
;
1357 AnsiMsg
.message
= message
;
1358 AnsiMsg
.wParam
= wParam
;
1359 AnsiMsg
.lParam
= lParam
;
1364 // Desktop is always Unicode so convert Ansi here.
1365 if (!MsgiAnsiToUnicodeMessage(hwnd
, &UcMsg
, &AnsiMsg
))
1370 Result
= DesktopWndProcW(hwnd
, message
, UcMsg
.wParam
, UcMsg
.lParam
);
1372 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1382 GetMessageExtraInfo(VOID
)
1384 return NtUserxGetMessageExtraInfo();
1395 return NtUserxGetMessagePos();
1403 GetMessageTime(VOID
)
1405 return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME
);
1416 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1419 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1424 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1436 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1437 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1438 return ISMEX_NOSEND
;
1440 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1449 ReplyMessage(LRESULT lResult
)
1451 return NtUserxReplyMessage(lResult
);
1460 SetMessageExtraInfo(
1463 return NtUserxSetMessageExtraInfo(lParam
);
1467 IntCallWindowProcW(BOOL IsAnsiProc
,
1477 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1478 LRESULT Result
= 0, PreResult
= 0;
1481 if (WndProc
== NULL
)
1483 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1488 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1492 Hook
= BeginIfHookedUserApiHook();
1496 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1498 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1503 UnicodeMsg
.hwnd
= hWnd
;
1504 UnicodeMsg
.message
= Msg
;
1505 UnicodeMsg
.wParam
= wParam
;
1506 UnicodeMsg
.lParam
= lParam
;
1507 UnicodeMsg
.time
= 0;
1508 UnicodeMsg
.pt
.x
= 0;
1509 UnicodeMsg
.pt
.y
= 0;
1510 if (! MsgiUnicodeToAnsiMessage(hWnd
, &AnsiMsg
, &UnicodeMsg
))
1515 if (Hook
&& MsgOverride
)
1520 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1522 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1524 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1530 if (PreResult
) goto Exit
;
1532 _SEH2_TRY
// wine does this.
1534 Result
= WndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1538 ERR("Exception when calling Ansi WndProc %p Msg %d pti %p Wndpti %p\n",WndProc
,Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1542 if (Hook
&& MsgOverride
)
1547 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1549 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1551 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1557 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1564 if (Hook
&& MsgOverride
)
1569 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1571 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1573 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1579 if (PreResult
) goto Exit
;
1583 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1585 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1587 ERR("Exception when calling unicode WndProc %p Msg %d pti %p Wndpti %p\n",WndProc
, Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1591 if (Hook
&& MsgOverride
)
1596 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1598 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1608 if (Hook
) EndUserApiHook();
1612 static LRESULT FASTCALL
1613 IntCallWindowProcA(BOOL IsAnsiProc
,
1623 //ULONG_PTR LowLimit;
1624 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
;
1625 LRESULT Result
= 0, PreResult
= 0;
1628 TRACE("IntCallWindowProcA: IsAnsiProc : %s, WndProc %p, pWnd %p, hWnd %p, Msg %u, wParam %Iu, lParam %Iu.\n",
1629 IsAnsiProc
? "TRUE" : "FALSE", WndProc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1631 if (WndProc
== NULL
)
1633 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1637 LowLimit
= (ULONG_PTR
)NtCurrentTeb()->NtTib
.StackLimit
;
1638 if (((ULONG_PTR
)&lParam
- LowLimit
) < PAGE_SIZE
)
1640 ERR("IntCallWindowsProcA() Exceeded Stack!\n");
1645 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1649 Hook
= BeginIfHookedUserApiHook();
1653 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1655 MsgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1660 if (Hook
&& MsgOverride
)
1665 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1667 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1675 if (PreResult
) goto Exit
;
1679 Result
= WndProc(hWnd
, Msg
, wParam
, lParam
);
1681 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1683 ERR("Exception when calling Ansi WndProc %p Msg %d pti %p Wndpti %p\n",WndProc
,Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1687 if (Hook
&& MsgOverride
)
1692 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1694 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1696 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1704 AnsiMsg
.hwnd
= hWnd
;
1705 AnsiMsg
.message
= Msg
;
1706 AnsiMsg
.wParam
= wParam
;
1707 AnsiMsg
.lParam
= lParam
;
1711 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UnicodeMsg
, &AnsiMsg
))
1716 if (Hook
&& MsgOverride
)
1721 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1723 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1725 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1731 if (PreResult
) goto Exit
;
1735 Result
= WndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
,
1736 UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1738 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1740 ERR("Exception when calling unicode WndProc %p Msg %d pti %p Wndpti %p\n",WndProc
, Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1744 if (Hook
&& MsgOverride
)
1749 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1751 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1753 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1759 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1766 if (Hook
) EndUserApiHook();
1771 static LRESULT WINAPI
1772 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1778 Class
= DesktopPtrToUser(Wnd
->pcls
);
1781 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
1782 { // Must be inside the same thread!
1783 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1787 This is the message exchange for user32. If there's a need to monitor messages,
1790 TRACE("HWND %p, MSG %u, WPARAM %p, LPARAM %p, Ansi %d\n", hWnd
, Msg
, wParam
, lParam
, Ansi
);
1791 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1792 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1796 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1797 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1801 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1802 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1809 IsAnsi
= !Wnd
->Unicode
;
1810 WndProc
= Wnd
->lpfnWndProc
;
1815 IsAnsi
= !Wnd
->Unicode
;
1816 WndProc
= Wnd
->lpfnWndProc
;
1819 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1823 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1825 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1833 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1840 PCALLPROCDATA CallProc
;
1842 if (lpPrevWndFunc
== NULL
)
1844 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1848 pWnd
= ValidateHwnd(hWnd
);
1850 if (!IsCallProcHandle(lpPrevWndFunc
))
1851 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1854 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1855 if (CallProc
!= NULL
)
1857 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1858 CallProc
->pfnClientPrevious
,
1867 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1878 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1885 PCALLPROCDATA CallProc
;
1887 /* FIXME - can the first parameter be NULL? */
1888 if (lpPrevWndFunc
== NULL
)
1890 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1894 pWnd
= ValidateHwnd(hWnd
);
1896 if (!IsCallProcHandle(lpPrevWndFunc
))
1897 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1900 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1901 if (CallProc
!= NULL
)
1903 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1904 CallProc
->pfnClientPrevious
,
1913 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1926 DispatchMessageA(CONST MSG
*lpmsg
)
1933 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1935 SetLastError( ERROR_INVALID_PARAMETER
);
1939 if (lpmsg
->hwnd
!= NULL
)
1941 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1947 if (is_pointer_message(lpmsg
->message
))
1949 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1953 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1955 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1957 if ( lpmsg
->message
== WM_SYSTIMER
)
1958 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1960 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
))
1962 WARN("Validating Timer Callback failed!\n");
1966 _SEH2_TRY
// wine does this. Hint: Prevents call to another thread....
1968 Ret
= WndProc(lpmsg
->hwnd
,
1973 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1979 else if (Wnd
!= NULL
)
1981 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1983 Ret
= IntCallMessageProc(Wnd
,
1992 if (!MsgiAnsiToUnicodeMessage(lpmsg
->hwnd
, &UnicodeMsg
, (LPMSG
)lpmsg
))
1997 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1999 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
2008 WARN("Exception in Timer Callback WndProcA!\n");
2020 DispatchMessageW(CONST MSG
*lpmsg
)
2026 if ( lpmsg
->message
& ~WM_MAXIMUM
)
2028 SetLastError( ERROR_INVALID_PARAMETER
);
2032 if (lpmsg
->hwnd
!= NULL
)
2034 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
2040 if (is_pointer_message(lpmsg
->message
))
2042 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2046 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
2048 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
2050 if ( lpmsg
->message
== WM_SYSTIMER
)
2051 return NtUserDispatchMessage( (PMSG
) lpmsg
);
2053 if (!NtUserValidateTimerCallback(lpmsg
->hwnd
, lpmsg
->wParam
, lpmsg
->lParam
))
2055 WARN("Validating Timer Callback failed!\n");
2061 Ret
= WndProc(lpmsg
->hwnd
,
2066 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2072 else if (Wnd
!= NULL
)
2074 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2076 Ret
= IntCallMessageProc(Wnd
,
2084 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
2089 WARN("Exception in Timer Callback WndProcW!\n");
2095 IntConvertMsgToAnsi(LPMSG lpMsg
)
2100 switch (lpMsg
->message
)
2105 case WM_SYSDEADCHAR
:
2107 wch
[0] = LOWORD(lpMsg
->wParam
);
2108 wch
[1] = HIWORD(lpMsg
->wParam
);
2110 WideCharToMultiByte(CP_THREAD_ACP
, 0, wch
, 2, ch
, 2, NULL
, NULL
);
2111 lpMsg
->wParam
= MAKEWPARAM(ch
[0] | (ch
[1] << 8), 0);
2122 GetMessageA(LPMSG lpMsg
,
2129 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
2131 SetLastError( ERROR_INVALID_PARAMETER
);
2135 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
2136 if (-1 == (int) Res
)
2141 IntConvertMsgToAnsi(lpMsg
);
2152 GetMessageW(LPMSG lpMsg
,
2159 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
2161 SetLastError( ERROR_INVALID_PARAMETER
);
2165 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
2166 if (-1 == (int) Res
)
2175 PeekMessageWorker( PMSG pMsg
,
2182 PCLIENTTHREADINFO pcti
;
2183 pci
= GetWin32ClientInfo();
2184 pcti
= pci
->pClientThreadInfo
;
2186 if (!hWnd
&& pci
&& pcti
)
2190 if ((pci
->cSpins
>= 100) && (pci
->dwTIFlags
& TIF_SPINNING
))
2191 { // Yield after 100 spin cycles and ready to swap vinyl.
2192 if (!(pci
->dwTIFlags
& TIF_WAITFORINPUTIDLE
))
2193 { // Not waiting for idle event.
2194 if (!pcti
->fsChangeBits
&& !pcti
->fsWakeBits
)
2195 { // No messages are available.
2196 if ((GetTickCount() - pcti
->tickLastMsgChecked
) > 1000)
2197 { // Up the msg read count if over 1 sec.
2198 NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD
);
2202 FIXME("seeSpins!\n");
2208 return NtUserPeekMessage(pMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2217 PeekMessageA(LPMSG lpMsg
,
2225 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2226 if (-1 == (int) Res
|| !Res
)
2231 IntConvertMsgToAnsi(lpMsg
);
2252 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2253 if (-1 == (int) Res
|| !Res
)
2274 /* Check for combo box or a list box to send names. */
2275 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2278 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2279 combo/list box. Forces a call like DlgDirListComboBox.
2281 //wParam |= DDL_POSTMSGS;
2282 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2285 /* No drop files or current Process, just post message. */
2286 if ( (Msg
!= WM_DROPFILES
) ||
2287 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2288 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2290 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2293 /* We have drop files and this is not the same process for this window. */
2295 /* Just incase, check wParam for Global memory handle and send size. */
2296 Ret
= SendMessageA( hWnd
,
2298 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2299 (LPARAM
)wParam
); // Send wParam as lParam.
2301 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2319 /* Check for combo box or a list box to send names. */
2320 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2323 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2324 combo/list box. Forces a call like DlgDirListComboBox.
2326 //wParam |= DDL_POSTMSGS;
2327 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2330 /* No drop files or current Process, just post message. */
2331 if ( (Msg
!= WM_DROPFILES
) ||
2332 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2333 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2335 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2338 /* We have drop files and this is not the same process for this window. */
2340 /* Just incase, check wParam for Global memory handle and send size. */
2341 Ret
= SendMessageW( hWnd
,
2343 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2344 (LPARAM
)wParam
); // Send wParam as lParam.
2346 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2359 NtUserxPostQuitMessage(nExitCode
);
2374 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2389 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2397 SendMessageW(HWND Wnd
,
2405 PTHREADINFO ti
= GetW32ThreadInfo();
2407 if ( Msg
& ~WM_MAXIMUM
)
2409 SetLastError( ERROR_INVALID_PARAMETER
);
2413 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2415 Window
= ValidateHwnd(Wnd
);
2417 if ( Window
!= NULL
&&
2418 Window
->head
.pti
== ti
&&
2419 !ISITHOOKED(WH_CALLWNDPROC
) &&
2420 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2421 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2423 /* NOTE: We can directly send messages to the window procedure
2424 if *all* the following conditions are met:
2426 * Window belongs to calling thread
2427 * The calling thread is not being hooked for CallWndProc
2428 * Not calling a server side proc:
2429 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2432 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2437 UMMsg
.message
= Msg
;
2438 UMMsg
.wParam
= wParam
;
2439 UMMsg
.lParam
= lParam
;
2444 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2449 Result
= NtUserMessageCall( Wnd
,
2457 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2467 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2469 MSG AnsiMsg
, UcMsg
, KMMsg
;
2472 PTHREADINFO ti
= GetW32ThreadInfo();
2474 if ( Msg
& ~WM_MAXIMUM
)
2476 SetLastError( ERROR_INVALID_PARAMETER
);
2480 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2482 Window
= ValidateHwnd(Wnd
);
2484 if ( Window
!= NULL
&&
2485 Window
->head
.pti
== ti
&&
2486 !ISITHOOKED(WH_CALLWNDPROC
) &&
2487 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2488 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2490 /* NOTE: We can directly send messages to the window procedure
2491 if *all* the following conditions are met:
2493 * Window belongs to calling thread
2494 * The calling thread is not being hooked for CallWndProc
2495 * Not calling a server side proc:
2496 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2499 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2504 AnsiMsg
.message
= Msg
;
2505 AnsiMsg
.wParam
= wParam
;
2506 AnsiMsg
.lParam
= lParam
;
2511 if (!MsgiAnsiToUnicodeMessage(Wnd
, &UcMsg
, &AnsiMsg
))
2516 if (!MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2518 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2522 Result
= NtUserMessageCall( Wnd
,
2530 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2531 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2541 SendMessageCallbackA(
2546 SENDASYNCPROC lpCallBack
,
2551 CALL_BACK_INFO CallBackInfo
;
2553 if (is_pointer_message(Msg
))
2555 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2559 CallBackInfo
.CallBack
= lpCallBack
;
2560 CallBackInfo
.Context
= dwData
;
2562 AnsiMsg
.hwnd
= hWnd
;
2563 AnsiMsg
.message
= Msg
;
2564 AnsiMsg
.wParam
= wParam
;
2565 AnsiMsg
.lParam
= lParam
;
2570 if (!MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2575 Result
= NtUserMessageCall( hWnd
,
2579 (ULONG_PTR
)&CallBackInfo
,
2580 FNID_SENDMESSAGECALLBACK
,
2583 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2593 SendMessageCallbackW(
2598 SENDASYNCPROC lpCallBack
,
2601 CALL_BACK_INFO CallBackInfo
;
2603 if (is_pointer_message(Msg
))
2605 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2609 CallBackInfo
.CallBack
= lpCallBack
;
2610 CallBackInfo
.Context
= dwData
;
2612 return NtUserMessageCall(hWnd
,
2616 (ULONG_PTR
)&CallBackInfo
,
2617 FNID_SENDMESSAGECALLBACK
,
2626 SendMessageTimeoutA(
2633 PDWORD_PTR lpdwResult
)
2639 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2641 SetLastError( ERROR_INVALID_PARAMETER
);
2645 if (lpdwResult
) *lpdwResult
= 0;
2647 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2649 dsm
.uFlags
= fuFlags
;
2650 dsm
.uTimeout
= uTimeout
;
2652 AnsiMsg
.hwnd
= hWnd
;
2653 AnsiMsg
.message
= Msg
;
2654 AnsiMsg
.wParam
= wParam
;
2655 AnsiMsg
.lParam
= lParam
;
2660 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2665 Result
= NtUserMessageCall( hWnd
,
2670 FNID_SENDMESSAGEWTOOPTION
,
2673 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2675 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2677 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2688 SendMessageTimeoutW(
2695 PDWORD_PTR lpdwResult
)
2700 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2702 SetLastError( ERROR_INVALID_PARAMETER
);
2706 if (lpdwResult
) *lpdwResult
= 0;
2708 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2710 dsm
.uFlags
= fuFlags
;
2711 dsm
.uTimeout
= uTimeout
;
2713 Result
= NtUserMessageCall( hWnd
,
2718 FNID_SENDMESSAGEWTOOPTION
,
2721 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2723 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2742 if (is_pointer_message(Msg
))
2744 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2748 AnsiMsg
.hwnd
= hWnd
;
2749 AnsiMsg
.message
= Msg
;
2750 AnsiMsg
.wParam
= wParam
;
2751 AnsiMsg
.lParam
= lParam
;
2755 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2759 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2761 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2780 if (is_pointer_message(Msg
))
2782 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2787 UMMsg
.message
= Msg
;
2788 UMMsg
.wParam
= wParam
;
2789 UMMsg
.lParam
= lParam
;
2793 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2797 Result
= NtUserMessageCall( hWnd
,
2802 FNID_SENDNOTIFYMESSAGE
,
2805 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2814 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2816 switch (lpMsg
->message
)
2822 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2825 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2826 SetLastError(ERROR_INVALID_PARAMETER
);
2836 TranslateMessage(CONST MSG
*lpMsg
)
2840 // Ref: msdn ImmGetVirtualKey:
2841 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2843 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2844 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2849 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2859 RegisterWindowMessageA(LPCSTR lpString
)
2861 UNICODE_STRING String
;
2864 if (!RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
))
2868 Atom
= NtUserRegisterWindowMessage(&String
);
2869 RtlFreeUnicodeString(&String
);
2878 RegisterWindowMessageW(LPCWSTR lpString
)
2880 UNICODE_STRING String
;
2882 RtlInitUnicodeString(&String
, lpString
);
2883 return(NtUserRegisterWindowMessage(&String
));
2892 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2899 ReleaseCapture(VOID
)
2901 return NtUserxReleaseCapture();
2910 RealGetQueueStatus(UINT flags
)
2912 #define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT
2913 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_TEMPALLINPUT
))
2915 SetLastError( ERROR_INVALID_FLAGS
);
2918 return NtUserxGetQueueStatus(flags
);
2925 BOOL WINAPI
GetInputState(VOID
)
2927 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2929 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2930 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2937 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2939 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2942 PCLIENTINFO pci
= GetWin32ClientInfo();
2944 /* Make sure we don't try to access mem beyond what we were given */
2945 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2947 return STATUS_INFO_LENGTH_MISMATCH
;
2950 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2951 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2952 KMMsg
.message
= CallbackArgs
->Msg
;
2953 KMMsg
.wParam
= CallbackArgs
->wParam
;
2957 /* Check if lParam is really a pointer and adjust it if it is */
2958 if (0 <= CallbackArgs
->lParamBufferSize
)
2960 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2961 + CallbackArgs
->lParamBufferSize
)
2963 return STATUS_INFO_LENGTH_MISMATCH
;
2965 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2966 switch(KMMsg
.message
)
2970 PRECT prect
= (PRECT
) KMMsg
.lParam
;
2971 TRACE("WM_SIZING 1 t %d l %d r %d b %d\n",prect
->top
,prect
->left
,prect
->right
,prect
->bottom
);
2980 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2982 return STATUS_INFO_LENGTH_MISMATCH
;
2984 KMMsg
.lParam
= CallbackArgs
->lParam
;
2987 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2989 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2990 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2993 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2997 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2998 pWnd
= pci
->CallbackWnd
.pWnd
;
3000 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
3008 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
3012 if (0 <= CallbackArgs
->lParamBufferSize
)
3014 switch(KMMsg
.message
)
3018 PRECT prect
= (PRECT
) KMMsg
.lParam
;
3019 TRACE("WM_SIZING 2 t %d l %d r %d b %d\n",prect
->top
,prect
->left
,prect
->right
,prect
->bottom
);
3026 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
3032 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
3034 /* Function does nothing on 32 bit windows */
3037 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
3038 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
3039 typedef BOOL (WINAPI
* RealInternalGetMessageProc
)(LPMSG
,HWND
,UINT
,UINT
,UINT
,BOOL
);
3040 typedef BOOL (WINAPI
* RealWaitMessageExProc
)(DWORD
,UINT
);
3042 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
3044 RealInternalGetMessageProc NtUserRealInternalGetMessage
;
3045 RealWaitMessageExProc NtUserRealWaitMessageEx
;
3046 RealGetQueueStatusProc RealGetQueueStatus
;
3047 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
3048 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
3052 RealMsgWaitForMultipleObjectsEx(
3054 CONST HANDLE
*pHandles
,
3055 DWORD dwMilliseconds
,
3059 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
3061 CRITICAL_SECTION gcsMPH
;
3062 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
3063 DWORD gcLoadMPH
= 0;
3064 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
3065 NtUserRealInternalGetMessage
,
3066 NtUserRealWaitMessageEx
,
3068 RealMsgWaitForMultipleObjectsEx
3071 DWORD gfMessagePumpHook
= 0;
3073 BOOL WINAPI
IsInsideMessagePumpHook()
3074 { // FF uses this and polls it when Min/Max
3075 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
3076 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
3079 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
3081 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
3082 Addresses
->NtUserRealInternalGetMessage
= NtUserRealInternalGetMessage
;
3083 Addresses
->NtUserRealWaitMessageEx
= NtUserRealWaitMessageEx
;
3084 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
3085 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
3088 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
3090 EnterCriticalSection(&gcsMPH
);
3092 SetLastError(ERROR_INVALID_PARAMETER
);
3093 LeaveCriticalSection(&gcsMPH
);
3097 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
3099 ResetMessagePumpHook(&Addresses
);
3100 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
3101 LeaveCriticalSection(&gcsMPH
);
3104 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
3106 if(gpfnInitMPH
!= Hook
) {
3107 LeaveCriticalSection(&gcsMPH
);
3111 if(NtUserxInitMessagePump()) {
3112 LeaveCriticalSection(&gcsMPH
);
3116 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
3118 LeaveCriticalSection(&gcsMPH
);
3122 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
3124 EnterCriticalSection(&gcsMPH
);
3126 if(NtUserxUnInitMessagePump()) {
3129 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
3130 gpfnInitMPH(TRUE
, NULL
);
3131 ResetMessagePumpHook(&gmph
);
3134 LeaveCriticalSection(&gcsMPH
);
3138 LeaveCriticalSection(&gcsMPH
);
3142 DWORD WINAPI
GetQueueStatus(UINT flags
)
3144 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
3148 * @name RealMsgWaitForMultipleObjectsEx
3150 * Wait either for either message arrival or for one of the passed events
3154 * Number of handles in the pHandles array.
3156 * Handles of events to wait for.
3157 * @param dwMilliseconds
3160 * Mask specifying on which message events we should wakeup.
3162 * Wait type (see MWMO_* constants).
3168 RealMsgWaitForMultipleObjectsEx(
3170 const HANDLE
*pHandles
,
3171 DWORD dwMilliseconds
,
3175 LPHANDLE RealHandles
;
3176 HANDLE MessageQueueHandle
;
3179 PCLIENTTHREADINFO pcti
;
3181 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
3183 SetLastError(ERROR_INVALID_PARAMETER
);
3187 pci
= GetWin32ClientInfo();
3188 if (!pci
) return WAIT_FAILED
;
3190 pcti
= pci
->pClientThreadInfo
;
3191 if (pcti
&& ( !nCount
|| !(dwFlags
& MWMO_WAITALL
) ))
3193 if ( (pcti
->fsChangeBits
& LOWORD(dwWakeMask
)) ||
3194 ( (dwFlags
& MWMO_INPUTAVAILABLE
) && (pcti
->fsWakeBits
& LOWORD(dwWakeMask
)) ) )
3196 //FIXME("Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
3201 MessageQueueHandle
= NtUserxMsqSetWakeMask(MAKELONG(dwWakeMask
, dwFlags
));
3202 if (MessageQueueHandle
== NULL
)
3204 SetLastError(0); /* ? */
3208 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
3209 if (RealHandles
== NULL
)
3211 NtUserxMsqClearWakeMask();
3212 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3216 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
3217 RealHandles
[nCount
] = MessageQueueHandle
;
3219 Result
= WaitForMultipleObjectsEx(nCount
+ 1, RealHandles
,
3220 dwFlags
& MWMO_WAITALL
,
3221 dwMilliseconds
, dwFlags
& MWMO_ALERTABLE
);
3223 HeapFree(GetProcessHeap(), 0, RealHandles
);
3224 NtUserxMsqClearWakeMask();
3225 //FIXME("Result 0X%x\n",Result);
3233 MsgWaitForMultipleObjectsEx(
3235 CONST HANDLE
*lpHandles
,
3236 DWORD dwMilliseconds
,
3240 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
3247 MsgWaitForMultipleObjects(
3249 CONST HANDLE
*lpHandles
,
3251 DWORD dwMilliseconds
,
3254 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
3255 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
3259 BOOL FASTCALL
MessageInit(VOID
)
3261 InitializeCriticalSection(&DdeCrst
);
3262 InitializeCriticalSection(&gcsMPH
);
3267 VOID FASTCALL
MessageCleanup(VOID
)
3269 DeleteCriticalSection(&DdeCrst
);
3270 DeleteCriticalSection(&gcsMPH
);
3277 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
3280 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
3281 return IsDialogMessageW( hwndDlg
, &msg
);
3286 IntBroadcastSystemMessage(
3288 LPDWORD lpdwRecipients
,
3296 DWORD recips
= BSM_ALLCOMPONENTS
;
3297 BOOL ret
= -1; // Set to return fail
3298 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
3299 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
3300 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
3302 if ((dwflags
& ~all_flags
) ||
3303 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
3305 SetLastError(ERROR_INVALID_PARAMETER
);
3309 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
3311 SetLastError(ERROR_INVALID_PARAMETER
);
3315 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
3317 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
3319 if (!lpdwRecipients
)
3320 lpdwRecipients
= &recips
;
3322 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
3324 SetLastError(ERROR_INVALID_PARAMETER
);
3328 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3330 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
3332 SetLastError(ERROR_INVALID_PARAMETER
);
3339 parm
.flags
= dwflags
;
3340 parm
.recipients
= *lpdwRecipients
;
3342 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
3344 ret
= NtUserMessageCall(GetDesktopWindow(),
3349 FNID_BROADCASTSYSTEMMESSAGE
,
3354 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3356 pBSMInfo
->hdesk
= parm
.hDesk
;
3357 pBSMInfo
->hwnd
= parm
.hWnd
;
3368 BroadcastSystemMessageA(
3370 LPDWORD lpdwRecipients
,
3375 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
3383 BroadcastSystemMessageW(
3385 LPDWORD lpdwRecipients
,
3390 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3398 BroadcastSystemMessageExA(
3400 LPDWORD lpdwRecipients
,
3406 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3414 BroadcastSystemMessageExW(
3416 LPDWORD lpdwRecipients
,
3422 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);