2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: win32ss/user/user32/windows/message.c
6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
13 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
16 /* For bad applications which provide bad (non stdcall) WndProc */
27 # define CALL_EXTERN_WNDPROC(proc, h, m, w, l) proc(h, m, w, l)
31 /* flag for messages that contain pointers */
32 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
34 #define SET(msg) (1 << ((msg) & 31))
36 static const unsigned int message_pointer_flags
[] =
39 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
40 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
42 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
45 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) | SET(WM_COPYGLOBALDATA
) | SET(WM_HELP
),
47 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
49 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
51 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
53 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
55 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
61 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
62 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
63 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
67 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
68 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
69 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
71 SET(LB_FINDSTRINGEXACT
),
77 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
79 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
80 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
94 SET(WM_ASKCBFORMATNAME
)
97 /* check whether a given message type includes pointers */
98 static inline int is_pointer_message( UINT message
)
100 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
101 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
106 /* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
107 static BOOL FASTCALL
combobox_has_strings( HWND hwnd
)
109 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
110 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
113 /* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */
114 static BOOL FASTCALL
listbox_has_strings( HWND hwnd
)
116 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
117 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
120 /* DDE message exchange
122 * - Session initialization
123 * Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
124 * this message contains a pair of global atoms, the Application and Topic atoms.
125 * The client must destroy the atoms.
126 * Server window proc handles the WM_DDE_INITIATE message and if the Application
127 * and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
128 * of the reply message contains another pair of global atoms (Application and
129 * Topic again), which must be destroyed by the server.
132 * Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
133 * is a global memory handle containing the string to execute. After the command has
134 * been executed the server posts a WM_DDE_ACK message to the client, which contains
135 * a packed lParam which in turn contains that global memory handle. The client takes
136 * ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
137 * it and the global memory handle.
138 * This might work nice and easy in Win3.1, but things are more complicated for NT.
139 * Global memory handles in NT are not really global, they're still local to the
140 * process. So, what happens under the hood is that PostMessage must handle the
141 * WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
142 * area, repack that into a new structure together with the original memory handle
143 * and pass that off to the win32k. Win32k will marshall that data over to the target
144 * (server) process where it will be unpacked and stored in a newly allocated global
145 * memory area. The handle of that area will then be sent to the window proc, after
146 * storing it together with the "original" (client) handle in a table.
147 * The server will eventually post the WM_DDE_ACK response, containing the global
148 * memory handle it received. PostMessage must then lookup that memory handle (only
149 * valid in the server process) and replace it with the corresponding client memory
150 * handle. To avoid memory leaks, the server-side global memory block must be freed.
151 * Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
152 * individual components are handed to win32k.sys to post to the client side. Since
153 * the server side app hands over ownership of the packed lParam when it calls
154 * PostMessage(), the packed lParam needs to be freed on the server side too.
155 * When the WM_DDE_ACK message (containing the client-side global memory handle)
156 * arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
157 * to the client side window proc which is expected to free/reuse it.
160 /* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
161 * to the memory handle, we keep track (in the server side) of all pairs of handle
162 * used (the client passes its value and the content of the memory handle), and
163 * the server stored both values (the client, and the local one, created after the
164 * content). When a ACK message is generated, the list of pair is searched for a
165 * matching pair, so that the client memory handle can be returned.
168 typedef struct tagDDEPAIR
172 } DDEPAIR
, *PDDEPAIR
;
174 static PDDEPAIR DdePairs
= NULL
;
175 static unsigned DdeNumAlloc
= 0;
176 static unsigned DdeNumUsed
= 0;
177 static CRITICAL_SECTION DdeCrst
;
180 DdeAddPair(HGLOBAL ClientMem
, HGLOBAL ServerMem
)
184 EnterCriticalSection(&DdeCrst
);
186 /* now remember the pair of hMem on both sides */
187 if (DdeNumUsed
== DdeNumAlloc
)
191 if (NULL
!= DdePairs
)
193 New
= HeapReAlloc(GetProcessHeap(), 0, DdePairs
,
194 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
198 New
= HeapAlloc(GetProcessHeap(), 0,
199 (DdeNumAlloc
+ GROWBY
) * sizeof(DDEPAIR
));
204 LeaveCriticalSection(&DdeCrst
);
208 /* zero out newly allocated part */
209 memset(&DdePairs
[DdeNumAlloc
], 0, GROWBY
* sizeof(DDEPAIR
));
210 DdeNumAlloc
+= GROWBY
;
214 for (i
= 0; i
< DdeNumAlloc
; i
++)
216 if (NULL
== DdePairs
[i
].ServerMem
)
218 DdePairs
[i
].ClientMem
= ClientMem
;
219 DdePairs
[i
].ServerMem
= ServerMem
;
224 LeaveCriticalSection(&DdeCrst
);
230 DdeGetPair(HGLOBAL ServerMem
)
235 EnterCriticalSection(&DdeCrst
);
236 for (i
= 0; i
< DdeNumAlloc
; i
++)
238 if (DdePairs
[i
].ServerMem
== ServerMem
)
241 DdePairs
[i
].ServerMem
= 0;
243 Ret
= DdePairs
[i
].ClientMem
;
247 LeaveCriticalSection(&DdeCrst
);
252 DWORD FASTCALL
get_input_codepage( void )
256 HKL hkl
= GetKeyboardLayout( 0 );
257 ret
= GetLocaleInfoW( LOWORD(hkl
), LOCALE_IDEFAULTANSICODEPAGE
| LOCALE_RETURN_NUMBER
, (WCHAR
*)&cp
, sizeof(cp
) / sizeof(WCHAR
) );
258 if (!ret
) cp
= CP_ACP
;
262 static WPARAM FASTCALL
map_wparam_char_WtoA( WPARAM wParam
, DWORD len
)
266 DWORD cp
= get_input_codepage();
268 len
= WideCharToMultiByte( cp
, 0, &wch
, 1, (LPSTR
)ch
, len
, NULL
, NULL
);
270 return MAKEWPARAM( (ch
[0] << 8) | ch
[1], HIWORD(wParam
) );
272 return MAKEWPARAM( ch
[0], HIWORD(wParam
) );
275 /***********************************************************************
278 * Convert the wparam of an ASCII message to Unicode.
280 static WPARAM FASTCALL
281 map_wparam_AtoW( UINT message
, WPARAM wparam
)
290 /* WM_CHAR is magic: a DBCS char can be sent/posted as two consecutive WM_CHAR
291 * messages, in which case the first char is stored, and the conversion
292 * to Unicode only takes place once the second char is sent/posted.
295 if (mapping
!= WMCHAR_MAP_NOMAPPING
) // NlsMbCodePageTag
297 PCLIENTINFO pci
= GetWin32ClientInfo();
299 struct wm_char_mapping_data
*data
= get_user_thread_info()->wmchar_data
;
301 BYTE low
= LOBYTE(wparam
);
306 ch
[1] = HIBYTE(wparam
);
307 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
308 TRACE( "map %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
309 if (data
) data
->lead_byte
[mapping
] = 0;
311 else if (data
&& data
->lead_byte
[mapping
])
313 ch
[0] = data
->lead_byte
[mapping
];
315 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
316 TRACE( "map stored %02x,%02x -> %04x mapping %u\n", (BYTE
)ch
[0], (BYTE
)ch
[1], wch
[0], mapping
);
317 data
->lead_byte
[mapping
] = 0;
319 else if (!IsDBCSLeadByte( low
))
322 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 1 );
323 TRACE( "map %02x -> %04x\n", (BYTE
)ch
[0], wch
[0] );
324 if (data
) data
->lead_byte
[mapping
] = 0;
326 else /* store it and wait for trail byte */
330 if (!(data
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
) )))
332 get_user_thread_info()->wmchar_data
= data
;
334 TRACE( "storing lead byte %02x mapping %u\n", low
, mapping
);
335 data
->lead_byte
[mapping
] = low
;
338 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
342 /* else fall through */
344 case EM_SETPASSWORDCHAR
:
349 ch
[0] = LOBYTE(wparam
);
350 ch
[1] = HIBYTE(wparam
);
351 RtlMultiByteToUnicodeN( wch
, sizeof(wch
), NULL
, ch
, 2 );
352 wparam
= MAKEWPARAM(wch
[0], wch
[1]);
355 ch
[0] = HIBYTE(wparam
);
356 ch
[1] = LOBYTE(wparam
);
357 if (ch
[0]) RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
, 2 );
358 else RtlMultiByteToUnicodeN( wch
, sizeof(wch
[0]), NULL
, ch
+ 1, 1 );
359 wparam
= MAKEWPARAM(wch
[0], HIWORD(wparam
));
367 MsgiUMToKMMessage(PMSG UMMsg
, PMSG KMMsg
, BOOL Posted
)
371 switch (UMMsg
->message
)
375 PCOPYDATASTRUCT pUMCopyData
= (PCOPYDATASTRUCT
)UMMsg
->lParam
;
376 PCOPYDATASTRUCT pKMCopyData
;
378 pKMCopyData
= HeapAlloc(GetProcessHeap(), 0, sizeof(COPYDATASTRUCT
) + pUMCopyData
->cbData
);
381 SetLastError(ERROR_OUTOFMEMORY
);
385 pKMCopyData
->dwData
= pUMCopyData
->dwData
;
386 pKMCopyData
->cbData
= pUMCopyData
->cbData
;
387 pKMCopyData
->lpData
= pKMCopyData
+ 1;
389 RtlCopyMemory(pKMCopyData
+ 1, pUMCopyData
->lpData
, pUMCopyData
->cbData
);
391 KMMsg
->lParam
= (LPARAM
)pKMCopyData
;
404 MsgiUMToKMCleanup(PMSG UMMsg
, PMSG KMMsg
)
406 switch (KMMsg
->message
)
409 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
419 MsgiKMToUMMessage(PMSG KMMsg
, PMSG UMMsg
)
423 if (KMMsg
->lParam
== 0) return TRUE
;
425 switch (UMMsg
->message
)
430 CREATESTRUCTW
*Cs
= (CREATESTRUCTW
*) KMMsg
->lParam
;
432 Cs
->lpszName
= (LPCWSTR
) ((PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszName
);
433 Class
= (PCHAR
) Cs
+ (DWORD_PTR
) Cs
->lpszClass
;
434 if (L
'A' == *((WCHAR
*) Class
))
436 Class
+= sizeof(WCHAR
);
437 Cs
->lpszClass
= (LPCWSTR
)(DWORD_PTR
) (*((ATOM
*) Class
));
441 ASSERT(L
'S' == *((WCHAR
*) Class
));
442 Class
+= sizeof(WCHAR
);
443 Cs
->lpszClass
= (LPCWSTR
) Class
;
450 PCOPYDATASTRUCT pKMCopyData
= (PCOPYDATASTRUCT
)KMMsg
->lParam
;
451 pKMCopyData
->lpData
= pKMCopyData
+ 1;
463 MsgiKMToUMCleanup(PMSG KMMsg
, PMSG UMMsg
)
465 switch (KMMsg
->message
)
469 HeapFree(GetProcessHeap(), 0, (LPVOID
) KMMsg
->lParam
);
470 GlobalUnlock((HGLOBAL
) UMMsg
->lParam
);
481 MsgiKMToUMReply(PMSG KMMsg
, PMSG UMMsg
, LRESULT
*Result
)
483 MsgiKMToUMCleanup(KMMsg
, UMMsg
);
489 // Ansi to Unicode -> callout
492 MsgiAnsiToUnicodeMessage(HWND hwnd
, LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
494 UNICODE_STRING UnicodeString
;
496 *UnicodeMsg
= *AnsiMsg
;
498 switch (AnsiMsg
->message
)
501 case WM_ASKCBFORMATNAME
:
504 if (!AnsiMsg
->lParam
) break;
505 Buffer
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, AnsiMsg
->wParam
* sizeof(WCHAR
));
506 //ERR("WM_GETTEXT A2U Size %d\n",AnsiMsg->wParam);
507 if (!Buffer
) return FALSE
;
508 UnicodeMsg
->lParam
= (LPARAM
)Buffer
;
514 DWORD Size
= 1024 * sizeof(WCHAR
);
515 if (!AnsiMsg
->lParam
|| !listbox_has_strings( AnsiMsg
->hwnd
)) break;
516 /*Size = SendMessageW( AnsiMsg->hwnd, LB_GETTEXTLEN, AnsiMsg->wParam, 0 );
519 ERR("LB_GETTEXT LB_ERR\n");
520 Size = sizeof(ULONG_PTR);
522 Size = (Size + 1) * sizeof(WCHAR);*/
523 UnicodeMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
524 if (!UnicodeMsg
->lParam
) return FALSE
;
530 DWORD Size
= 1024 * sizeof(WCHAR
);
531 if (!AnsiMsg
->lParam
|| !combobox_has_strings( AnsiMsg
->hwnd
)) break;
532 /*Size = SendMessageW( AnsiMsg->hwnd, CB_GETLBTEXTLEN, AnsiMsg->wParam, 0 );
535 ERR("CB_GETTEXT LB_ERR\n");
536 Size = sizeof(ULONG_PTR);
538 Size = (Size + 1) * sizeof(WCHAR);*/
539 UnicodeMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
540 if (!UnicodeMsg
->lParam
) return FALSE
;
544 /* AnsiMsg->lParam is string (0-terminated) */
546 case WM_WININICHANGE
:
547 case WM_DEVMODECHANGE
:
553 if (!AnsiMsg
->lParam
) break;
554 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
555 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
560 case LB_ADDSTRING_LOWER
:
561 case LB_ADDSTRING_UPPER
:
562 case LB_INSERTSTRING
:
563 case LB_INSERTSTRING_UPPER
:
564 case LB_INSERTSTRING_LOWER
:
566 case LB_FINDSTRINGEXACT
:
567 case LB_SELECTSTRING
:
569 if (AnsiMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
571 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
572 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
578 case CB_INSERTSTRING
:
580 case CB_FINDSTRINGEXACT
:
581 case CB_SELECTSTRING
:
583 if (AnsiMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
585 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)AnsiMsg
->lParam
);
586 UnicodeMsg
->lParam
= (LPARAM
)UnicodeString
.Buffer
;
596 CREATESTRUCTW cs
; /* new structure */
597 MDICREATESTRUCTW mdi_cs
; /* MDI info */
598 LPCWSTR lpszName
; /* allocated Name */
599 LPCWSTR lpszClass
; /* allocated Class */
602 struct s
*xs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct s
));
607 xs
->cs
= *(CREATESTRUCTW
*)AnsiMsg
->lParam
;
608 if (!IS_INTRESOURCE(xs
->cs
.lpszName
))
610 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszName
);
611 xs
->lpszName
= xs
->cs
.lpszName
= UnicodeString
.Buffer
;
613 if (!IS_ATOM(xs
->cs
.lpszClass
))
615 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)xs
->cs
.lpszClass
);
616 xs
->lpszClass
= xs
->cs
.lpszClass
= UnicodeString
.Buffer
;
619 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
621 xs
->mdi_cs
= *(MDICREATESTRUCTW
*)xs
->cs
.lpCreateParams
;
622 xs
->mdi_cs
.szTitle
= xs
->cs
.lpszName
;
623 xs
->mdi_cs
.szClass
= xs
->cs
.lpszClass
;
624 xs
->cs
.lpCreateParams
= &xs
->mdi_cs
;
627 UnicodeMsg
->lParam
= (LPARAM
)xs
;
633 MDICREATESTRUCTW
*cs
=
634 (MDICREATESTRUCTW
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
641 *cs
= *(MDICREATESTRUCTW
*)AnsiMsg
->lParam
;
643 if (!IS_ATOM(cs
->szClass
))
645 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szClass
);
646 cs
->szClass
= UnicodeString
.Buffer
;
649 RtlCreateUnicodeStringFromAsciiz(&UnicodeString
, (LPSTR
)cs
->szTitle
);
650 cs
->szTitle
= UnicodeString
.Buffer
;
652 UnicodeMsg
->lParam
= (LPARAM
)cs
;
657 if (UnicodeMsg
->lParam
)
659 MSG newmsg
= *(MSG
*)UnicodeMsg
->lParam
;
660 newmsg
.wParam
= map_wparam_AtoW( newmsg
.message
, newmsg
.wParam
);
670 case EM_SETPASSWORDCHAR
:
672 UnicodeMsg
->wParam
= map_wparam_AtoW( AnsiMsg
->message
, AnsiMsg
->wParam
);
675 ERR("FIXME EM_GETLINE A2U\n");
684 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg
, LPMSG AnsiMsg
)
686 UNICODE_STRING UnicodeString
;
688 switch (AnsiMsg
->message
)
691 if (!listbox_has_strings( UnicodeMsg
->hwnd
)) break;
693 if (UnicodeMsg
->message
== CB_GETLBTEXT
&& !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
695 case WM_ASKCBFORMATNAME
:
697 if (!UnicodeMsg
->lParam
) break;
698 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) UnicodeMsg
->lParam
);
703 case WM_WININICHANGE
:
704 case WM_DEVMODECHANGE
:
710 if (!UnicodeMsg
->lParam
) break;
711 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
712 RtlFreeUnicodeString(&UnicodeString
);
717 case LB_ADDSTRING_LOWER
:
718 case LB_ADDSTRING_UPPER
:
719 case LB_INSERTSTRING
:
720 case LB_INSERTSTRING_UPPER
:
721 case LB_INSERTSTRING_LOWER
:
723 case LB_FINDSTRINGEXACT
:
724 case LB_SELECTSTRING
:
726 if (UnicodeMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
728 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
729 RtlFreeUnicodeString(&UnicodeString
);
735 case CB_INSERTSTRING
:
737 case CB_FINDSTRINGEXACT
:
738 case CB_SELECTSTRING
:
740 if (UnicodeMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
742 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)UnicodeMsg
->lParam
);
743 RtlFreeUnicodeString(&UnicodeString
);
753 CREATESTRUCTW cs
; /* new structure */
754 MDICREATESTRUCTW mdi_cs
; /* MDI info */
755 LPWSTR lpszName
; /* allocated Name */
756 LPWSTR lpszClass
; /* allocated Class */
759 struct s
*xs
= (struct s
*)UnicodeMsg
->lParam
;
762 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszName
);
763 RtlFreeUnicodeString(&UnicodeString
);
767 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)xs
->lpszClass
);
768 RtlFreeUnicodeString(&UnicodeString
);
770 HeapFree(GetProcessHeap(), 0, xs
);
776 MDICREATESTRUCTW
*cs
= (MDICREATESTRUCTW
*)UnicodeMsg
->lParam
;
777 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szTitle
);
778 RtlFreeUnicodeString(&UnicodeString
);
779 if (!IS_ATOM(cs
->szClass
))
781 RtlInitUnicodeString(&UnicodeString
, (PCWSTR
)cs
->szClass
);
782 RtlFreeUnicodeString(&UnicodeString
);
784 HeapFree(GetProcessHeap(), 0, cs
);
793 * callout return -> Unicode Result to Ansi Result
796 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg
, LPMSG AnsiMsg
, LRESULT
*Result
)
798 LPWSTR Buffer
= (LPWSTR
)UnicodeMsg
->lParam
;
799 LPSTR AnsiBuffer
= (LPSTR
)AnsiMsg
->lParam
;
801 switch (AnsiMsg
->message
)
804 case WM_ASKCBFORMATNAME
:
806 if (UnicodeMsg
->wParam
)
809 if (*Result
) RtlUnicodeToMultiByteN( AnsiBuffer
, UnicodeMsg
->wParam
- 1, &len
, Buffer
, strlenW(Buffer
) * sizeof(WCHAR
));
812 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam);
818 if (!AnsiBuffer
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
822 RtlUnicodeToMultiByteN( AnsiBuffer
, ~0u, &len
, Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
) );
829 if (!AnsiBuffer
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
833 RtlUnicodeToMultiByteN( AnsiBuffer
, ~0u, &len
, Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
) );
840 MsgiAnsiToUnicodeCleanup(UnicodeMsg
, AnsiMsg
);
846 // Unicode to Ansi callout ->
849 MsgiUnicodeToAnsiMessage(HWND hwnd
, LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
851 ANSI_STRING AnsiString
;
852 UNICODE_STRING UnicodeString
;
854 *AnsiMsg
= *UnicodeMsg
;
856 switch(UnicodeMsg
->message
)
861 MDICREATESTRUCTA
*pmdi_cs
;
864 ULONG NameSize
, ClassSize
;
867 CsW
= (CREATESTRUCTW
*)(UnicodeMsg
->lParam
);
868 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
869 NameSize
= RtlUnicodeStringToAnsiSize(&UnicodeString
);
875 if (!IS_ATOM(CsW
->lpszClass
))
877 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
878 ClassSize
= RtlUnicodeStringToAnsiSize(&UnicodeString
);
885 CsA
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA
) + sizeof(MDICREATESTRUCTA
) + NameSize
+ ClassSize
);
890 memcpy(CsA
, CsW
, sizeof(CREATESTRUCTW
));
892 /* pmdi_cs starts right after CsA */
893 pmdi_cs
= (MDICREATESTRUCTA
*)(CsA
+ 1);
895 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszName
);
896 RtlInitEmptyAnsiString(&AnsiString
, (PCHAR
)(pmdi_cs
+ 1), NameSize
);
897 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
898 if (! NT_SUCCESS(Status
))
900 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
903 CsA
->lpszName
= AnsiString
.Buffer
;
904 if (!IS_ATOM(CsW
->lpszClass
))
906 RtlInitUnicodeString(&UnicodeString
, CsW
->lpszClass
);
907 RtlInitEmptyAnsiString(&AnsiString
, (PCHAR
)(pmdi_cs
+ 1) + NameSize
, ClassSize
);
908 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
909 if (! NT_SUCCESS(Status
))
911 RtlFreeHeap(GetProcessHeap(), 0, CsA
);
914 CsA
->lpszClass
= AnsiString
.Buffer
;
917 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
919 *pmdi_cs
= *(MDICREATESTRUCTA
*)CsW
->lpCreateParams
;
920 pmdi_cs
->szTitle
= CsA
->lpszName
;
921 pmdi_cs
->szClass
= CsA
->lpszClass
;
922 CsA
->lpCreateParams
= pmdi_cs
;
925 AnsiMsg
->lParam
= (LPARAM
)CsA
;
929 case WM_ASKCBFORMATNAME
:
931 if (!UnicodeMsg
->lParam
) break;
932 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */
933 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, UnicodeMsg
->wParam
* 2);
934 //ERR("WM_GETTEXT U2A Size %d\n",AnsiMsg->wParam);
936 if (!AnsiMsg
->lParam
) return FALSE
;
943 if (!UnicodeMsg
->lParam
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
944 /*Size = SendMessageA( UnicodeMsg->hwnd, LB_GETTEXTLEN, UnicodeMsg->wParam, 0 );
947 ERR("LB_GETTEXT LB_ERR\n");
948 Size = sizeof(ULONG_PTR);
950 Size = (Size + 1) * sizeof(WCHAR);*/
951 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
952 if (!AnsiMsg
->lParam
) return FALSE
;
959 if (!UnicodeMsg
->lParam
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
960 /*Size = SendMessageA( UnicodeMsg->hwnd, CB_GETLBTEXTLEN, UnicodeMsg->wParam, 0 );
963 ERR("CB_GETTEXT LB_ERR\n");
964 Size = sizeof(ULONG_PTR);
966 Size = (Size + 1) * sizeof(WCHAR);*/
967 AnsiMsg
->lParam
= (LPARAM
) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
968 if (!AnsiMsg
->lParam
) return FALSE
;
973 case WM_WININICHANGE
:
974 case WM_DEVMODECHANGE
:
980 if (!UnicodeMsg
->lParam
) break;
981 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
982 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
988 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
993 case LB_ADDSTRING_LOWER
:
994 case LB_ADDSTRING_UPPER
:
995 case LB_INSERTSTRING
:
996 case LB_INSERTSTRING_UPPER
:
997 case LB_INSERTSTRING_LOWER
:
999 case LB_FINDSTRINGEXACT
:
1000 case LB_SELECTSTRING
:
1002 if (UnicodeMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
1004 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
1005 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1011 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
1017 case CB_INSERTSTRING
:
1019 case CB_FINDSTRINGEXACT
:
1020 case CB_SELECTSTRING
:
1022 if (UnicodeMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
1024 RtlInitUnicodeString(&UnicodeString
, (PWSTR
) UnicodeMsg
->lParam
);
1025 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1031 AnsiMsg
->lParam
= (LPARAM
) AnsiString
.Buffer
;
1038 MDICREATESTRUCTA
*cs
=
1039 (MDICREATESTRUCTA
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs
));
1046 *cs
= *(MDICREATESTRUCTA
*)UnicodeMsg
->lParam
;
1048 if (!IS_ATOM(cs
->szClass
))
1050 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szClass
);
1051 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1055 HeapFree(GetProcessHeap(), 0, cs
);
1058 cs
->szClass
= AnsiString
.Buffer
;
1061 RtlInitUnicodeString(&UnicodeString
, (LPCWSTR
)cs
->szTitle
);
1062 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString
,
1066 if (!IS_ATOM(cs
->szClass
))
1068 RtlInitAnsiString(&AnsiString
, cs
->szClass
);
1069 RtlFreeAnsiString(&AnsiString
);
1072 HeapFree(GetProcessHeap(), 0, cs
);
1075 cs
->szTitle
= AnsiString
.Buffer
;
1077 AnsiMsg
->lParam
= (LPARAM
)cs
;
1082 if (UnicodeMsg
->lParam
)
1084 MSG newmsg
= *(MSG
*)UnicodeMsg
->lParam
;
1085 switch(newmsg
.message
)
1090 case WM_SYSDEADCHAR
:
1091 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 1 );
1094 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 2 );
1102 WCHAR wch
= UnicodeMsg
->wParam
;
1104 DWORD cp
= get_input_codepage();
1105 DWORD len
= WideCharToMultiByte( cp
, 0, &wch
, 1, ch
, 2, NULL
, NULL
);
1106 AnsiMsg
->wParam
= (BYTE
)ch
[0];
1107 if (len
== 2) AnsiMsg
->wParam
= (BYTE
)ch
[1];
1115 case WM_SYSDEADCHAR
:
1116 case EM_SETPASSWORDCHAR
:
1117 AnsiMsg
->wParam
= map_wparam_char_WtoA(UnicodeMsg
->wParam
,1);
1121 AnsiMsg
->wParam
= map_wparam_char_WtoA(UnicodeMsg
->wParam
,2);
1124 ERR("FIXME EM_GETLINE U2A\n");
1130 static BOOL FASTCALL
1131 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg
, LPMSG UnicodeMsg
)
1133 ANSI_STRING AnsiString
;
1135 switch(UnicodeMsg
->message
)
1138 if (!listbox_has_strings( AnsiMsg
->hwnd
)) break;
1140 if (AnsiMsg
->message
== CB_GETLBTEXT
&& !combobox_has_strings( AnsiMsg
->hwnd
)) break;
1142 case WM_ASKCBFORMATNAME
:
1144 if (!AnsiMsg
->lParam
) break;
1145 RtlFreeHeap(GetProcessHeap(), 0, (PVOID
) AnsiMsg
->lParam
);
1153 Cs
= (CREATESTRUCTA
*) AnsiMsg
->lParam
;
1154 RtlFreeHeap(GetProcessHeap(), 0, Cs
);
1159 case WM_WININICHANGE
:
1160 case WM_DEVMODECHANGE
:
1166 if (!AnsiMsg
->lParam
) break;
1167 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1168 RtlFreeAnsiString(&AnsiString
);
1173 case LB_ADDSTRING_LOWER
:
1174 case LB_ADDSTRING_UPPER
:
1175 case LB_INSERTSTRING
:
1176 case LB_INSERTSTRING_UPPER
:
1177 case LB_INSERTSTRING_LOWER
:
1179 case LB_FINDSTRINGEXACT
:
1180 case LB_SELECTSTRING
:
1182 if (AnsiMsg
->lParam
&& listbox_has_strings(AnsiMsg
->hwnd
))
1184 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1185 RtlFreeAnsiString(&AnsiString
);
1191 case CB_INSERTSTRING
:
1193 case CB_FINDSTRINGEXACT
:
1194 case CB_SELECTSTRING
:
1196 if (AnsiMsg
->lParam
&& combobox_has_strings(AnsiMsg
->hwnd
))
1198 RtlInitAnsiString(&AnsiString
, (PSTR
) AnsiMsg
->lParam
);
1199 RtlFreeAnsiString(&AnsiString
);
1206 MDICREATESTRUCTA
*cs
= (MDICREATESTRUCTA
*)AnsiMsg
->lParam
;
1207 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szTitle
);
1208 RtlFreeAnsiString(&AnsiString
);
1209 if (!IS_ATOM(cs
->szClass
))
1211 RtlInitAnsiString(&AnsiString
, (PCSTR
)cs
->szClass
);
1212 RtlFreeAnsiString(&AnsiString
);
1214 HeapFree(GetProcessHeap(), 0, cs
);
1224 * callout return -> Ansi Result to Unicode Result
1226 static BOOL FASTCALL
1227 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg
, LPMSG UnicodeMsg
, LRESULT
*Result
)
1229 LPSTR Buffer
= (LPSTR
) AnsiMsg
->lParam
;
1230 LPWSTR UBuffer
= (LPWSTR
) UnicodeMsg
->lParam
;
1232 switch (UnicodeMsg
->message
)
1235 case WM_ASKCBFORMATNAME
:
1237 DWORD len
= AnsiMsg
->wParam
;// * 2;
1242 RtlMultiByteToUnicodeN( UBuffer
, AnsiMsg
->wParam
*sizeof(WCHAR
), &len
, Buffer
, strlen(Buffer
)+1 );
1243 *Result
= len
/sizeof(WCHAR
) - 1; /* do not count terminating null */
1244 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam);
1246 UBuffer
[*Result
] = 0;
1252 if (!UBuffer
|| !listbox_has_strings( UnicodeMsg
->hwnd
)) break;
1256 RtlMultiByteToUnicodeN( UBuffer
, ~0u, &len
, Buffer
, strlen(Buffer
) + 1 );
1257 *Result
= len
/ sizeof(WCHAR
) - 1;
1263 if (!UBuffer
|| !combobox_has_strings( UnicodeMsg
->hwnd
)) break;
1267 RtlMultiByteToUnicodeN( UBuffer
, ~0u, &len
, Buffer
, strlen(Buffer
) + 1 );
1268 *Result
= len
/ sizeof(WCHAR
) - 1;
1274 MsgiUnicodeToAnsiCleanup(AnsiMsg
, UnicodeMsg
);
1282 DesktopWndProcA( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1287 TRACE("Desktop A Class Atom! hWnd 0x%x, Msg %d\n", hwnd
, message
);
1289 AnsiMsg
.hwnd
= hwnd
;
1290 AnsiMsg
.message
= message
;
1291 AnsiMsg
.wParam
= wParam
;
1292 AnsiMsg
.lParam
= lParam
;
1297 // Desktop is always Unicode so convert Ansi here.
1298 if (!MsgiAnsiToUnicodeMessage(hwnd
, &UcMsg
, &AnsiMsg
))
1303 Result
= DesktopWndProcW(hwnd
, message
, UcMsg
.wParam
, UcMsg
.lParam
);
1305 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
1315 GetMessageExtraInfo(VOID
)
1317 return NtUserxGetMessageExtraInfo();
1328 return NtUserxGetMessagePos();
1336 GetMessageTime(VOID
)
1338 return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME
);
1349 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1352 if (pcti
->CTI_flags
& CTI_INSENDMESSAGE
)
1357 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
) != ISMEX_NOSEND
);
1369 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
1370 if (pcti
&& !(pcti
->CTI_flags
& CTI_INSENDMESSAGE
))
1371 return ISMEX_NOSEND
;
1373 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE
);
1382 ReplyMessage(LRESULT lResult
)
1384 return NtUserxReplyMessage(lResult
);
1393 SetMessageExtraInfo(
1396 return NtUserxSetMessageExtraInfo(lParam
);
1400 IntCallWindowProcW(BOOL IsAnsiProc
,
1410 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
, DlgOverride
= FALSE
;
1411 LRESULT Result
= 0, PreResult
= 0;
1414 if (WndProc
== NULL
)
1416 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n");
1421 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1425 Hook
= BeginIfHookedUserApiHook();
1429 DlgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1430 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1435 UnicodeMsg
.hwnd
= hWnd
;
1436 UnicodeMsg
.message
= Msg
;
1437 UnicodeMsg
.wParam
= wParam
;
1438 UnicodeMsg
.lParam
= lParam
;
1439 UnicodeMsg
.time
= 0;
1440 UnicodeMsg
.pt
.x
= 0;
1441 UnicodeMsg
.pt
.y
= 0;
1442 if (! MsgiUnicodeToAnsiMessage(hWnd
, &AnsiMsg
, &UnicodeMsg
))
1447 if (Hook
&& (MsgOverride
|| DlgOverride
))
1452 PreResult
= guah
.PreWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1454 PreResult
= guah
.PreDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1456 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1458 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride
);
1463 if (PreResult
) goto Exit
;
1466 Result
= CALL_EXTERN_WNDPROC(WndProc
, AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1471 Result
= CALL_EXTERN_WNDPROC(WndProc
, AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
);
1473 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1475 ERR("Exception Dialog Ansi %p Msg %d pti %p Wndpti %p\n",WndProc
,Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1480 if (Hook
&& (MsgOverride
|| DlgOverride
))
1485 guah
.PostWndProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1487 guah
.PostDefDlgProc(AnsiMsg
.hwnd
, AnsiMsg
.message
, AnsiMsg
.wParam
, AnsiMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1489 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1491 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride
);
1496 if (! MsgiUnicodeToAnsiReply(&AnsiMsg
, &UnicodeMsg
, &Result
))
1503 if (Hook
&& (MsgOverride
|| DlgOverride
))
1508 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1510 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1512 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1514 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride
);
1519 if (PreResult
) goto Exit
;
1522 Result
= CALL_EXTERN_WNDPROC(WndProc
, hWnd
, Msg
, wParam
, lParam
);
1527 Result
= CALL_EXTERN_WNDPROC(WndProc
, hWnd
, Msg
, wParam
, lParam
);
1529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1531 ERR("Exception Dialog unicode %p Msg %d pti %p Wndpti %p\n",WndProc
, Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1536 if (Hook
&& (MsgOverride
|| DlgOverride
))
1541 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1543 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1547 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride
);
1554 if (Hook
) EndUserApiHook();
1558 static LRESULT FASTCALL
1559 IntCallWindowProcA(BOOL IsAnsiProc
,
1569 BOOL Hook
= FALSE
, MsgOverride
= FALSE
, Dialog
, DlgOverride
= FALSE
;
1570 LRESULT Result
= 0, PreResult
= 0;
1573 TRACE("IntCallWindowProcA: IsAnsiProc : %s, WndProc %p, pWnd %p, hWnd %p, Msg %u, wParam %Iu, lParam %Iu.\n",
1574 IsAnsiProc
? "TRUE" : "FALSE", WndProc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1576 if (WndProc
== NULL
)
1578 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n");
1583 Dialog
= (pWnd
->fnid
== FNID_DIALOG
);
1587 Hook
= BeginIfHookedUserApiHook();
1591 DlgOverride
= IsMsgOverride( Msg
, &guah
.DlgProcArray
);
1592 MsgOverride
= IsMsgOverride( Msg
, &guah
.WndProcArray
);
1597 if (Hook
&& (MsgOverride
|| DlgOverride
))
1602 PreResult
= guah
.PreWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1604 PreResult
= guah
.PreDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1608 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride
);
1613 if (PreResult
) goto Exit
;
1616 Result
= CALL_EXTERN_WNDPROC(WndProc
, hWnd
, Msg
, wParam
, lParam
);
1621 Result
= CALL_EXTERN_WNDPROC(WndProc
, hWnd
, Msg
, wParam
, lParam
);
1623 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1625 ERR("Exception Dialog Ansi %p Msg %d pti %p Wndpti %p\n",WndProc
,Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1630 if (Hook
&& (MsgOverride
|| DlgOverride
))
1635 guah
.PostWndProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1637 guah
.PostDefDlgProc(hWnd
, Msg
, wParam
, lParam
, (ULONG_PTR
)&Result
, &Data
);
1639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1641 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride
);
1648 AnsiMsg
.hwnd
= hWnd
;
1649 AnsiMsg
.message
= Msg
;
1650 AnsiMsg
.wParam
= wParam
;
1651 AnsiMsg
.lParam
= lParam
;
1655 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UnicodeMsg
, &AnsiMsg
))
1660 if (Hook
&& (MsgOverride
|| DlgOverride
))
1665 PreResult
= guah
.PreWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1667 PreResult
= guah
.PreDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1671 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride
);
1676 if (PreResult
) goto Exit
;
1679 Result
= CALL_EXTERN_WNDPROC(WndProc
, UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1684 Result
= CALL_EXTERN_WNDPROC(WndProc
, UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
);
1686 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1688 ERR("Exception Dialog unicode %p Msg %d pti %p Wndpti %p\n",WndProc
, Msg
,GetW32ThreadInfo(),pWnd
->head
.pti
);
1693 if (Hook
&& (MsgOverride
|| DlgOverride
))
1698 guah
.PostWndProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1700 guah
.PostDefDlgProc(UnicodeMsg
.hwnd
, UnicodeMsg
.message
, UnicodeMsg
.wParam
, UnicodeMsg
.lParam
, (ULONG_PTR
)&Result
, &Data
);
1702 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1704 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride
);
1709 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg
, &AnsiMsg
, &Result
))
1716 if (Hook
) EndUserApiHook();
1721 static LRESULT WINAPI
1722 IntCallMessageProc(IN PWND Wnd
, IN HWND hWnd
, IN UINT Msg
, IN WPARAM wParam
, IN LPARAM lParam
, IN BOOL Ansi
)
1728 Class
= DesktopPtrToUser(Wnd
->pcls
);
1731 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
1732 { // Must be inside the same thread!
1733 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1737 This is the message exchange for user32. If there's a need to monitor messages,
1740 TRACE("HWND %p, MSG %u, WPARAM %p, LPARAM %p, Ansi %d\n", hWnd
, Msg
, wParam
, lParam
, Ansi
);
1741 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON )
1742 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_FIRST
)
1746 if (GETPFNCLIENTW(Class
->fnid
) == Wnd
->lpfnWndProc
)
1747 WndProc
= GETPFNCLIENTA(Class
->fnid
);
1751 if (GETPFNCLIENTA(Class
->fnid
) == Wnd
->lpfnWndProc
)
1752 WndProc
= GETPFNCLIENTW(Class
->fnid
);
1759 IsAnsi
= !Wnd
->Unicode
;
1760 WndProc
= Wnd
->lpfnWndProc
;
1765 IsAnsi
= !Wnd
->Unicode
;
1766 WndProc
= Wnd
->lpfnWndProc
;
1769 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or
1773 return IntCallWindowProcW(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1775 return IntCallWindowProcA(IsAnsi
, WndProc
, Wnd
, hWnd
, Msg
, wParam
, lParam
);
1783 CallWindowProcA(WNDPROC lpPrevWndFunc
,
1790 PCALLPROCDATA CallProc
;
1792 if (lpPrevWndFunc
== NULL
)
1794 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1798 pWnd
= ValidateHwnd(hWnd
);
1800 if (!IsCallProcHandle(lpPrevWndFunc
))
1801 return IntCallWindowProcA(TRUE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1804 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1805 if (CallProc
!= NULL
)
1807 return IntCallWindowProcA(!(CallProc
->wType
& UserGetCPDA2U
),
1808 CallProc
->pfnClientPrevious
,
1817 WARN("CallWindowProcA: can not dereference WndProcHandle\n");
1828 CallWindowProcW(WNDPROC lpPrevWndFunc
,
1835 PCALLPROCDATA CallProc
;
1837 /* FIXME - can the first parameter be NULL? */
1838 if (lpPrevWndFunc
== NULL
)
1840 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
1844 pWnd
= ValidateHwnd(hWnd
);
1846 if (!IsCallProcHandle(lpPrevWndFunc
))
1847 return IntCallWindowProcW(FALSE
, lpPrevWndFunc
, pWnd
, hWnd
, Msg
, wParam
, lParam
);
1850 CallProc
= ValidateCallProc((HANDLE
)lpPrevWndFunc
);
1851 if (CallProc
!= NULL
)
1853 return IntCallWindowProcW(!(CallProc
->wType
& UserGetCPDA2U
),
1854 CallProc
->pfnClientPrevious
,
1863 WARN("CallWindowProcW: can not dereference WndProcHandle\n");
1876 DispatchMessageA(CONST MSG
*lpmsg
)
1882 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1884 SetLastError( ERROR_INVALID_PARAMETER
);
1888 if (lpmsg
->hwnd
!= NULL
)
1890 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1896 if (is_pointer_message(lpmsg
->message
))
1898 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1902 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1904 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1906 if ( lpmsg
->message
== WM_SYSTIMER
)
1907 return NtUserDispatchMessage( (PMSG
)lpmsg
);
1909 if (!NtUserValidateTimerCallback(lpmsg
->lParam
))
1911 WARN("Validating Timer Callback failed!\n");
1915 _SEH2_TRY
// wine does this. Hint: Prevents call to another thread....
1917 Ret
= WndProc(lpmsg
->hwnd
,
1922 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1924 ERR("Exception in Timer Callback!\n");
1928 else if (Wnd
!= NULL
)
1930 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
1932 Ret
= IntCallMessageProc(Wnd
,
1941 if (!MsgiAnsiToUnicodeMessage(lpmsg
->hwnd
, &UnicodeMsg
, (LPMSG
)lpmsg
))
1946 Ret
= NtUserDispatchMessage(&UnicodeMsg
);
1948 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg
, (LPMSG
)lpmsg
, &Ret
))
1965 DispatchMessageW(CONST MSG
*lpmsg
)
1971 if ( lpmsg
->message
& ~WM_MAXIMUM
)
1973 SetLastError( ERROR_INVALID_PARAMETER
);
1977 if (lpmsg
->hwnd
!= NULL
)
1979 Wnd
= ValidateHwnd(lpmsg
->hwnd
);
1985 if (is_pointer_message(lpmsg
->message
))
1987 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
1991 if ((lpmsg
->message
== WM_TIMER
|| lpmsg
->message
== WM_SYSTIMER
) && lpmsg
->lParam
!= 0)
1993 WNDPROC WndProc
= (WNDPROC
)lpmsg
->lParam
;
1995 if ( lpmsg
->message
== WM_SYSTIMER
)
1996 return NtUserDispatchMessage( (PMSG
) lpmsg
);
1998 if (!NtUserValidateTimerCallback(lpmsg
->lParam
))
2000 WARN("Validating Timer Callback failed!\n");
2006 Ret
= WndProc(lpmsg
->hwnd
,
2011 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2017 else if (Wnd
!= NULL
)
2019 if ( (lpmsg
->message
!= WM_PAINT
) && !(Wnd
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2021 Ret
= IntCallMessageProc(Wnd
,
2029 Ret
= NtUserDispatchMessage( (PMSG
) lpmsg
);
2034 WARN("Exception in Timer Callback WndProcW!\n");
2040 IntConvertMsgToAnsi(LPMSG lpMsg
)
2045 switch (lpMsg
->message
)
2050 case WM_SYSDEADCHAR
:
2052 wch
[0] = LOWORD(lpMsg
->wParam
);
2053 wch
[1] = HIWORD(lpMsg
->wParam
);
2055 WideCharToMultiByte(CP_THREAD_ACP
, 0, wch
, 2, ch
, 2, NULL
, NULL
);
2056 lpMsg
->wParam
= MAKEWPARAM(ch
[0] | (ch
[1] << 8), 0);
2067 GetMessageA(LPMSG lpMsg
,
2074 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
2076 SetLastError( ERROR_INVALID_PARAMETER
);
2080 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
2081 if (-1 == (int) Res
)
2086 IntConvertMsgToAnsi(lpMsg
);
2097 GetMessageW(LPMSG lpMsg
,
2104 if ( (wMsgFilterMin
|wMsgFilterMax
) & ~WM_MAXIMUM
)
2106 SetLastError( ERROR_INVALID_PARAMETER
);
2110 Res
= NtUserGetMessage(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
);
2111 if (-1 == (int) Res
)
2120 PeekMessageWorker( PMSG pMsg
,
2127 PCLIENTTHREADINFO pcti
;
2128 pci
= GetWin32ClientInfo();
2129 pcti
= pci
->pClientThreadInfo
;
2131 if (!hWnd
&& pci
&& pcti
)
2135 if ((pci
->cSpins
>= 100) && (pci
->dwTIFlags
& TIF_SPINNING
))
2136 { // Yield after 100 spin cycles and ready to swap vinyl.
2137 if (!(pci
->dwTIFlags
& TIF_WAITFORINPUTIDLE
))
2138 { // Not waiting for idle event.
2139 if (!pcti
->fsChangeBits
&& !pcti
->fsWakeBits
)
2140 { // No messages are available.
2141 if ((GetTickCount() - pcti
->tickLastMsgChecked
) > 1000)
2142 { // Up the msg read count if over 1 sec.
2143 NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD
);
2147 FIXME("seeSpins!\n");
2153 return NtUserPeekMessage(pMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2162 PeekMessageA(LPMSG lpMsg
,
2170 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2171 if (-1 == (int) Res
|| !Res
)
2176 IntConvertMsgToAnsi(lpMsg
);
2197 Res
= PeekMessageWorker(lpMsg
, hWnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
2198 if (-1 == (int) Res
|| !Res
)
2219 /* Check for combo box or a list box to send names. */
2220 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2223 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2224 combo/list box. Forces a call like DlgDirListComboBox.
2226 //wParam |= DDL_POSTMSGS;
2227 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2230 /* No drop files or current Process, just post message. */
2231 if ( (Msg
!= WM_DROPFILES
) ||
2232 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2233 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2235 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2238 /* We have drop files and this is not the same process for this window. */
2240 /* Just incase, check wParam for Global memory handle and send size. */
2241 Ret
= SendMessageA( hWnd
,
2243 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2244 (LPARAM
)wParam
); // Send wParam as lParam.
2246 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2264 /* Check for combo box or a list box to send names. */
2265 if (Msg
== CB_DIR
|| Msg
== LB_DIR
)
2268 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the
2269 combo/list box. Forces a call like DlgDirListComboBox.
2271 //wParam |= DDL_POSTMSGS;
2272 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2275 /* No drop files or current Process, just post message. */
2276 if ( (Msg
!= WM_DROPFILES
) ||
2277 ( NtUserQueryWindow( hWnd
, QUERY_WINDOW_UNIQUE_PROCESS_ID
) ==
2278 PtrToUint(NtCurrentTeb()->ClientId
.UniqueProcess
) ) )
2280 return NtUserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2283 /* We have drop files and this is not the same process for this window. */
2285 /* Just incase, check wParam for Global memory handle and send size. */
2286 Ret
= SendMessageW( hWnd
,
2288 (WPARAM
)GlobalSize((HGLOBAL
)wParam
), // Zero if not a handle.
2289 (LPARAM
)wParam
); // Send wParam as lParam.
2291 if ( Ret
) return NtUserPostMessage(hWnd
, Msg
, (WPARAM
)Ret
, lParam
);
2304 NtUserxPostQuitMessage(nExitCode
);
2319 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2334 return NtUserPostThreadMessage(idThread
, Msg
, wParam
, lParam
);
2342 SendMessageW(HWND Wnd
,
2351 PTHREADINFO ti
= GetW32ThreadInfo();
2353 if ( Msg
& ~WM_MAXIMUM
)
2355 SetLastError( ERROR_INVALID_PARAMETER
);
2359 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2361 Window
= ValidateHwnd(Wnd
);
2363 if ( Window
!= NULL
&&
2364 Window
->head
.pti
== ti
&&
2365 !ISITHOOKED(WH_CALLWNDPROC
) &&
2366 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2367 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2369 /* NOTE: We can directly send messages to the window procedure
2370 if *all* the following conditions are met:
2372 * Window belongs to calling thread
2373 * The calling thread is not being hooked for CallWndProc
2374 * Not calling a server side proc:
2375 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2378 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
2383 UMMsg
.message
= Msg
;
2384 UMMsg
.wParam
= wParam
;
2385 UMMsg
.lParam
= lParam
;
2390 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, FALSE
))
2395 Ret
= NtUserMessageCall( Wnd
,
2404 ERR("SendMessageW Error\n");
2407 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2417 SendMessageA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
2419 MSG AnsiMsg
, UcMsg
, KMMsg
;
2423 PTHREADINFO ti
= GetW32ThreadInfo();
2425 if ( Msg
& ~WM_MAXIMUM
)
2427 SetLastError( ERROR_INVALID_PARAMETER
);
2431 if (Wnd
!= HWND_TOPMOST
&& Wnd
!= HWND_BROADCAST
&& (Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
))
2433 Window
= ValidateHwnd(Wnd
);
2435 if ( Window
!= NULL
&&
2436 Window
->head
.pti
== ti
&&
2437 !ISITHOOKED(WH_CALLWNDPROC
) &&
2438 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
2439 !(Window
->state
& WNDS_SERVERSIDEWINDOWPROC
) )
2441 /* NOTE: We can directly send messages to the window procedure
2442 if *all* the following conditions are met:
2444 * Window belongs to calling thread
2445 * The calling thread is not being hooked for CallWndProc
2446 * Not calling a server side proc:
2447 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
2450 return IntCallMessageProc(Window
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
2455 AnsiMsg
.message
= Msg
;
2456 AnsiMsg
.wParam
= wParam
;
2457 AnsiMsg
.lParam
= lParam
;
2462 if (!MsgiAnsiToUnicodeMessage(Wnd
, &UcMsg
, &AnsiMsg
))
2467 if (!MsgiUMToKMMessage(&UcMsg
, &KMMsg
, FALSE
))
2469 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2473 Ret
= NtUserMessageCall( Wnd
,
2482 ERR("SendMessageA Error\n");
2485 MsgiUMToKMCleanup(&UcMsg
, &KMMsg
);
2486 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2496 SendMessageCallbackA(
2501 SENDASYNCPROC lpCallBack
,
2506 CALL_BACK_INFO CallBackInfo
;
2508 if (is_pointer_message(Msg
))
2510 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2514 CallBackInfo
.CallBack
= lpCallBack
;
2515 CallBackInfo
.Context
= dwData
;
2517 AnsiMsg
.hwnd
= hWnd
;
2518 AnsiMsg
.message
= Msg
;
2519 AnsiMsg
.wParam
= wParam
;
2520 AnsiMsg
.lParam
= lParam
;
2525 if (!MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2530 Result
= NtUserMessageCall( hWnd
,
2534 (ULONG_PTR
)&CallBackInfo
,
2535 FNID_SENDMESSAGECALLBACK
,
2538 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2548 SendMessageCallbackW(
2553 SENDASYNCPROC lpCallBack
,
2556 CALL_BACK_INFO CallBackInfo
;
2558 if (is_pointer_message(Msg
))
2560 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2564 CallBackInfo
.CallBack
= lpCallBack
;
2565 CallBackInfo
.Context
= dwData
;
2567 return NtUserMessageCall(hWnd
,
2571 (ULONG_PTR
)&CallBackInfo
,
2572 FNID_SENDMESSAGECALLBACK
,
2581 SendMessageTimeoutA(
2588 PDWORD_PTR lpdwResult
)
2594 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2596 SetLastError( ERROR_INVALID_PARAMETER
);
2600 if (lpdwResult
) *lpdwResult
= 0;
2602 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2604 dsm
.uFlags
= fuFlags
;
2605 dsm
.uTimeout
= uTimeout
;
2608 AnsiMsg
.hwnd
= hWnd
;
2609 AnsiMsg
.message
= Msg
;
2610 AnsiMsg
.wParam
= wParam
;
2611 AnsiMsg
.lParam
= lParam
;
2616 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2621 Result
= NtUserMessageCall( hWnd
,
2626 FNID_SENDMESSAGEWTOOPTION
,
2629 MsgiAnsiToUnicodeReply(&UcMsg
, &AnsiMsg
, &Result
);
2631 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2633 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2644 SendMessageTimeoutW(
2651 PDWORD_PTR lpdwResult
)
2656 if ( Msg
& ~WM_MAXIMUM
|| fuFlags
& ~(SMTO_NOTIMEOUTIFNOTHUNG
|SMTO_ABORTIFHUNG
|SMTO_BLOCK
))
2658 SetLastError( ERROR_INVALID_PARAMETER
);
2662 if (lpdwResult
) *lpdwResult
= 0;
2664 SPY_EnterMessage(SPY_SENDMESSAGE
, hWnd
, Msg
, wParam
, lParam
);
2666 dsm
.uFlags
= fuFlags
;
2667 dsm
.uTimeout
= uTimeout
;
2670 Result
= NtUserMessageCall( hWnd
,
2675 FNID_SENDMESSAGEWTOOPTION
,
2678 if (lpdwResult
) *lpdwResult
= dsm
.Result
;
2680 SPY_ExitMessage(SPY_RESULT_OK
, hWnd
, Msg
, Result
, wParam
, lParam
);
2699 if (is_pointer_message(Msg
))
2701 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2705 AnsiMsg
.hwnd
= hWnd
;
2706 AnsiMsg
.message
= Msg
;
2707 AnsiMsg
.wParam
= wParam
;
2708 AnsiMsg
.lParam
= lParam
;
2712 if (! MsgiAnsiToUnicodeMessage(hWnd
, &UcMsg
, &AnsiMsg
))
2716 Ret
= SendNotifyMessageW(hWnd
, UcMsg
.message
, UcMsg
.wParam
, UcMsg
.lParam
);
2718 MsgiAnsiToUnicodeCleanup(&UcMsg
, &AnsiMsg
);
2737 if (is_pointer_message(Msg
))
2739 SetLastError( ERROR_MESSAGE_SYNC_ONLY
);
2744 UMMsg
.message
= Msg
;
2745 UMMsg
.wParam
= wParam
;
2746 UMMsg
.lParam
= lParam
;
2750 if (! MsgiUMToKMMessage(&UMMsg
, &KMMsg
, TRUE
))
2754 Result
= NtUserMessageCall( hWnd
,
2759 FNID_SENDNOTIFYMESSAGE
,
2762 MsgiUMToKMCleanup(&UMMsg
, &KMMsg
);
2771 TranslateMessageEx(CONST MSG
*lpMsg
, UINT Flags
)
2773 switch (lpMsg
->message
)
2779 return(NtUserTranslateMessage((LPMSG
)lpMsg
, Flags
));
2782 if ( lpMsg
->message
& ~WM_MAXIMUM
)
2783 SetLastError(ERROR_INVALID_PARAMETER
);
2793 TranslateMessage(CONST MSG
*lpMsg
)
2797 // Ref: msdn ImmGetVirtualKey:
2798 // http://msdn.microsoft.com/en-us/library/aa912145.aspx
2800 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) ||
2801 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd,
2806 Ret
= TranslateMessageEx((LPMSG
)lpMsg
, 0);
2816 RegisterWindowMessageA(LPCSTR lpString
)
2818 UNICODE_STRING String
;
2821 if (!RtlCreateUnicodeStringFromAsciiz(&String
, (PCSZ
)lpString
))
2825 Atom
= NtUserRegisterWindowMessage(&String
);
2826 RtlFreeUnicodeString(&String
);
2835 RegisterWindowMessageW(LPCWSTR lpString
)
2837 UNICODE_STRING String
;
2839 RtlInitUnicodeString(&String
, lpString
);
2840 return(NtUserRegisterWindowMessage(&String
));
2849 return (HWND
)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW
);
2856 ReleaseCapture(VOID
)
2858 return NtUserxReleaseCapture();
2867 RealGetQueueStatus(UINT flags
)
2869 #define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT
2870 if (flags
& ~(QS_SMRESULT
|QS_ALLPOSTMESSAGE
|QS_TEMPALLINPUT
))
2872 SetLastError( ERROR_INVALID_FLAGS
);
2875 return NtUserxGetQueueStatus(flags
);
2882 BOOL WINAPI
GetInputState(VOID
)
2884 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
2886 if ((!pcti
) || (pcti
->fsChangeBits
& (QS_KEY
|QS_MOUSEBUTTON
)))
2887 return (BOOL
)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE
);
2894 User32CallWindowProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
2896 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs
;
2899 PCLIENTINFO pci
= GetWin32ClientInfo();
2901 /* Make sure we don't try to access mem beyond what we were given */
2902 if (ArgumentLength
< sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2904 return STATUS_INFO_LENGTH_MISMATCH
;
2907 CallbackArgs
= (PWINDOWPROC_CALLBACK_ARGUMENTS
) Arguments
;
2908 KMMsg
.hwnd
= CallbackArgs
->Wnd
;
2909 KMMsg
.message
= CallbackArgs
->Msg
;
2910 KMMsg
.wParam
= CallbackArgs
->wParam
;
2914 /* Check if lParam is really a pointer and adjust it if it is */
2915 if (0 <= CallbackArgs
->lParamBufferSize
)
2917 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
)
2918 + CallbackArgs
->lParamBufferSize
)
2920 return STATUS_INFO_LENGTH_MISMATCH
;
2922 KMMsg
.lParam
= (LPARAM
) ((char *) CallbackArgs
+ sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
));
2923 switch(KMMsg
.message
)
2927 TRACE("WM_CREATE CB %p lParam %p\n",CallbackArgs
, KMMsg
.lParam
);
2932 TRACE("WM_SYSTIMER %p\n",KMMsg
.hwnd
);
2937 PRECT prect
= (PRECT
) KMMsg
.lParam
;
2938 TRACE("WM_SIZING 1 t %d l %d r %d b %d\n",prect
->top
,prect
->left
,prect
->right
,prect
->bottom
);
2947 if (ArgumentLength
!= sizeof(WINDOWPROC_CALLBACK_ARGUMENTS
))
2949 return STATUS_INFO_LENGTH_MISMATCH
;
2951 KMMsg
.lParam
= CallbackArgs
->lParam
;
2954 if (WM_NCCALCSIZE
== CallbackArgs
->Msg
&& CallbackArgs
->wParam
)
2956 NCCALCSIZE_PARAMS
*Params
= (NCCALCSIZE_PARAMS
*) KMMsg
.lParam
;
2957 Params
->lppos
= (PWINDOWPOS
) (Params
+ 1);
2960 if (! MsgiKMToUMMessage(&KMMsg
, &UMMsg
))
2964 if (pci
->CallbackWnd
.hWnd
== UMMsg
.hwnd
)
2965 pWnd
= pci
->CallbackWnd
.pWnd
;
2967 CallbackArgs
->Result
= IntCallWindowProcW( CallbackArgs
->IsAnsiProc
,
2975 if (! MsgiKMToUMReply(&KMMsg
, &UMMsg
, &CallbackArgs
->Result
))
2979 if (0 <= CallbackArgs
->lParamBufferSize
)
2981 switch(KMMsg
.message
)
2985 PRECT prect
= (PRECT
) KMMsg
.lParam
;
2986 TRACE("WM_SIZING 2 t %d l %d r %d b %d\n",prect
->top
,prect
->left
,prect
->right
,prect
->bottom
);
2993 return ZwCallbackReturn(CallbackArgs
, ArgumentLength
, STATUS_SUCCESS
);
2999 BOOL WINAPI
SetMessageQueue(int cMessagesMax
)
3001 /* Function does nothing on 32 bit windows */
3004 typedef DWORD (WINAPI
* RealGetQueueStatusProc
)(UINT flags
);
3005 typedef DWORD (WINAPI
* RealMsgWaitForMultipleObjectsExProc
)(DWORD nCount
, CONST HANDLE
*lpHandles
, DWORD dwMilliseconds
, DWORD dwWakeMask
, DWORD dwFlags
);
3006 typedef BOOL (WINAPI
* RealInternalGetMessageProc
)(LPMSG
,HWND
,UINT
,UINT
,UINT
,BOOL
);
3007 typedef BOOL (WINAPI
* RealWaitMessageExProc
)(DWORD
,UINT
);
3009 typedef struct _USER_MESSAGE_PUMP_ADDRESSES
{
3011 RealInternalGetMessageProc NtUserRealInternalGetMessage
;
3012 RealWaitMessageExProc NtUserRealWaitMessageEx
;
3013 RealGetQueueStatusProc RealGetQueueStatus
;
3014 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx
;
3015 } USER_MESSAGE_PUMP_ADDRESSES
, * PUSER_MESSAGE_PUMP_ADDRESSES
;
3019 RealMsgWaitForMultipleObjectsEx(
3021 CONST HANDLE
*pHandles
,
3022 DWORD dwMilliseconds
,
3026 typedef BOOL (WINAPI
* MESSAGEPUMPHOOKPROC
)(BOOL Unregistering
,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses
);
3028 CRITICAL_SECTION gcsMPH
;
3029 MESSAGEPUMPHOOKPROC gpfnInitMPH
;
3030 DWORD gcLoadMPH
= 0;
3031 USER_MESSAGE_PUMP_ADDRESSES gmph
= {sizeof(USER_MESSAGE_PUMP_ADDRESSES
),
3032 NtUserRealInternalGetMessage
,
3033 NtUserRealWaitMessageEx
,
3035 RealMsgWaitForMultipleObjectsEx
3038 DWORD gfMessagePumpHook
= 0;
3040 BOOL WINAPI
IsInsideMessagePumpHook()
3041 { // FF uses this and polls it when Min/Max
3042 PCLIENTTHREADINFO pcti
= GetWin32ClientInfo()->pClientThreadInfo
;
3043 return (gfMessagePumpHook
&& pcti
&& (pcti
->dwcPumpHook
> 0));
3046 void WINAPI
ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses
)
3048 Addresses
->cbSize
= sizeof(USER_MESSAGE_PUMP_ADDRESSES
);
3049 Addresses
->NtUserRealInternalGetMessage
= NtUserRealInternalGetMessage
;
3050 Addresses
->NtUserRealWaitMessageEx
= NtUserRealWaitMessageEx
;
3051 Addresses
->RealGetQueueStatus
= RealGetQueueStatus
;
3052 Addresses
->RealMsgWaitForMultipleObjectsEx
= RealMsgWaitForMultipleObjectsEx
;
3055 BOOL WINAPI
RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook
)
3057 EnterCriticalSection(&gcsMPH
);
3059 SetLastError(ERROR_INVALID_PARAMETER
);
3060 LeaveCriticalSection(&gcsMPH
);
3064 USER_MESSAGE_PUMP_ADDRESSES Addresses
;
3066 ResetMessagePumpHook(&Addresses
);
3067 if(!Hook(FALSE
, &Addresses
) || !Addresses
.cbSize
) {
3068 LeaveCriticalSection(&gcsMPH
);
3071 memcpy(&gmph
, &Addresses
, Addresses
.cbSize
);
3073 if(gpfnInitMPH
!= Hook
) {
3074 LeaveCriticalSection(&gcsMPH
);
3078 if(NtUserxInitMessagePump()) {
3079 LeaveCriticalSection(&gcsMPH
);
3083 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 1);
3085 LeaveCriticalSection(&gcsMPH
);
3089 BOOL WINAPI
UnregisterMessagePumpHook(VOID
)
3091 EnterCriticalSection(&gcsMPH
);
3093 if(NtUserxUnInitMessagePump()) {
3096 InterlockedExchange((PLONG
)&gfMessagePumpHook
, 0);
3097 gpfnInitMPH(TRUE
, NULL
);
3098 ResetMessagePumpHook(&gmph
);
3101 LeaveCriticalSection(&gcsMPH
);
3105 LeaveCriticalSection(&gcsMPH
);
3109 DWORD WINAPI
GetQueueStatus(UINT flags
)
3111 return IsInsideMessagePumpHook() ? gmph
.RealGetQueueStatus(flags
) : RealGetQueueStatus(flags
);
3115 * @name RealMsgWaitForMultipleObjectsEx
3117 * Wait either for either message arrival or for one of the passed events
3121 * Number of handles in the pHandles array.
3123 * Handles of events to wait for.
3124 * @param dwMilliseconds
3127 * Mask specifying on which message events we should wakeup.
3129 * Wait type (see MWMO_* constants).
3135 RealMsgWaitForMultipleObjectsEx(
3137 const HANDLE
*pHandles
,
3138 DWORD dwMilliseconds
,
3142 LPHANDLE RealHandles
;
3143 HANDLE MessageQueueHandle
;
3146 PCLIENTTHREADINFO pcti
;
3148 if (dwFlags
& ~(MWMO_WAITALL
| MWMO_ALERTABLE
| MWMO_INPUTAVAILABLE
))
3150 SetLastError(ERROR_INVALID_PARAMETER
);
3154 pci
= GetWin32ClientInfo();
3155 if (!pci
) return WAIT_FAILED
;
3157 pcti
= pci
->pClientThreadInfo
;
3158 if (pcti
&& ( !nCount
|| !(dwFlags
& MWMO_WAITALL
) ))
3160 if ( (pcti
->fsChangeBits
& LOWORD(dwWakeMask
)) ||
3161 ( (dwFlags
& MWMO_INPUTAVAILABLE
) && (pcti
->fsWakeBits
& LOWORD(dwWakeMask
)) ) )
3163 //FIXME("Return Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
3168 MessageQueueHandle
= NtUserxMsqSetWakeMask(MAKELONG(dwWakeMask
, dwFlags
));
3169 if (MessageQueueHandle
== NULL
)
3171 SetLastError(0); /* ? */
3175 RealHandles
= HeapAlloc(GetProcessHeap(), 0, (nCount
+ 1) * sizeof(HANDLE
));
3176 if (RealHandles
== NULL
)
3178 NtUserxMsqClearWakeMask();
3179 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3183 RtlCopyMemory(RealHandles
, pHandles
, nCount
* sizeof(HANDLE
));
3184 RealHandles
[nCount
] = MessageQueueHandle
;
3186 //FIXME("1 Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
3188 Result
= WaitForMultipleObjectsEx( nCount
+ 1,
3190 dwFlags
& MWMO_WAITALL
,
3192 dwFlags
& MWMO_ALERTABLE
);
3194 //FIXME("2 Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount);
3196 HeapFree(GetProcessHeap(), 0, RealHandles
);
3197 NtUserxMsqClearWakeMask();
3199 // wine hack! MSDN: If dwMilliseconds is zero,,specified objects are not signaled; it always returns immediately.
3200 if (!Result
&& !nCount
&& !dwMilliseconds
) Result
= WAIT_TIMEOUT
;
3202 //FIXME("Result 0X%x\n",Result);
3210 MsgWaitForMultipleObjectsEx(
3212 CONST HANDLE
*lpHandles
,
3213 DWORD dwMilliseconds
,
3217 return IsInsideMessagePumpHook() ? gmph
.RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
, dwWakeMask
, dwFlags
) : RealMsgWaitForMultipleObjectsEx(nCount
, lpHandles
,dwMilliseconds
, dwWakeMask
, dwFlags
);
3224 MsgWaitForMultipleObjects(
3226 CONST HANDLE
*lpHandles
,
3228 DWORD dwMilliseconds
,
3231 return MsgWaitForMultipleObjectsEx(nCount
, lpHandles
, dwMilliseconds
,
3232 dwWakeMask
, fWaitAll
? MWMO_WAITALL
: 0);
3236 BOOL FASTCALL
MessageInit(VOID
)
3238 InitializeCriticalSection(&DdeCrst
);
3239 InitializeCriticalSection(&gcsMPH
);
3244 VOID FASTCALL
MessageCleanup(VOID
)
3246 DeleteCriticalSection(&DdeCrst
);
3247 DeleteCriticalSection(&gcsMPH
);
3254 IsDialogMessageA( HWND hwndDlg
, LPMSG pmsg
)
3257 msg
.wParam
= map_wparam_AtoW( msg
.message
, msg
.wParam
);
3258 return IsDialogMessageW( hwndDlg
, &msg
);
3263 IntBroadcastSystemMessage(
3265 LPDWORD lpdwRecipients
,
3273 DWORD recips
= BSM_ALLCOMPONENTS
;
3274 BOOL ret
= -1; // Set to return fail
3275 static const DWORD all_flags
= ( BSF_QUERY
| BSF_IGNORECURRENTTASK
| BSF_FLUSHDISK
| BSF_NOHANG
3276 | BSF_POSTMESSAGE
| BSF_FORCEIFHUNG
| BSF_NOTIMEOUTIFNOTHUNG
3277 | BSF_ALLOWSFW
| BSF_SENDNOTIFYMESSAGE
| BSF_RETURNHDESK
| BSF_LUID
);
3279 if ((dwflags
& ~all_flags
) ||
3280 (!pBSMInfo
&& (dwflags
& (BSF_RETURNHDESK
|BSF_LUID
))) )
3282 SetLastError(ERROR_INVALID_PARAMETER
);
3286 if(uiMessage
>= WM_USER
&& uiMessage
< 0xC000)
3288 SetLastError(ERROR_INVALID_PARAMETER
);
3292 if (dwflags
& BSF_FORCEIFHUNG
) dwflags
|= BSF_NOHANG
;
3294 if (dwflags
& BSF_QUERY
) dwflags
&= ~BSF_SENDNOTIFYMESSAGE
|BSF_POSTMESSAGE
;
3296 if (!lpdwRecipients
)
3297 lpdwRecipients
= &recips
;
3299 if (*lpdwRecipients
& ~(BSM_APPLICATIONS
|BSM_ALLDESKTOPS
|BSM_INSTALLABLEDRIVERS
|BSM_NETDRIVER
|BSM_VXDS
))
3301 SetLastError(ERROR_INVALID_PARAMETER
);
3305 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3307 if (pBSMInfo
->cbSize
!= sizeof(BSMINFO
))
3309 SetLastError(ERROR_INVALID_PARAMETER
);
3316 parm
.flags
= dwflags
;
3317 parm
.recipients
= *lpdwRecipients
;
3319 if (dwflags
& BSF_LUID
) parm
.luid
= pBSMInfo
->luid
;
3321 ret
= NtUserMessageCall(GetDesktopWindow(),
3326 FNID_BROADCASTSYSTEMMESSAGE
,
3331 if ( pBSMInfo
&& (dwflags
& BSF_QUERY
) )
3333 pBSMInfo
->hdesk
= parm
.hDesk
;
3334 pBSMInfo
->hwnd
= parm
.hWnd
;
3345 BroadcastSystemMessageA(
3347 LPDWORD lpdwRecipients
,
3352 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, TRUE
);
3360 BroadcastSystemMessageW(
3362 LPDWORD lpdwRecipients
,
3367 return IntBroadcastSystemMessage( dwFlags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, NULL
, FALSE
);
3375 BroadcastSystemMessageExA(
3377 LPDWORD lpdwRecipients
,
3383 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, TRUE
);
3391 BroadcastSystemMessageExW(
3393 LPDWORD lpdwRecipients
,
3399 return IntBroadcastSystemMessage( dwflags
, lpdwRecipients
, uiMessage
, wParam
, lParam
, pBSMInfo
, FALSE
);