1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS user32.dll 4 * FILE: win32ss/user/user32/windows/message.c 5 * PURPOSE: Messages 6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * UPDATE HISTORY: 8 * 06-06-2001 CSH Created 9 */ 10 11 #include <user32.h> 12 13 WINE_DEFAULT_DEBUG_CHANNEL(user32); 14 15 #ifdef __i386__ 16 /* For bad applications which provide bad (non stdcall) WndProc */ 17 extern 18 LRESULT 19 __cdecl 20 CALL_EXTERN_WNDPROC( 21 WNDPROC WndProc, 22 HWND hWnd, 23 UINT Msg, 24 WPARAM wParam, 25 LPARAM lParam); 26 #else 27 # define CALL_EXTERN_WNDPROC(proc, h, m, w, l) proc(h, m, w, l) 28 #endif 29 30 /* From wine: */ 31 /* flag for messages that contain pointers */ 32 /* 32 messages per entry, messages 0..31 map to bits 0..31 */ 33 34 #define SET(msg) (1 << ((msg) & 31)) 35 36 static const unsigned int message_pointer_flags[] = 37 { 38 /* 0x00 - 0x1f */ 39 SET(WM_CREATE) | SET(WM_SETTEXT) | SET(WM_GETTEXT) | 40 SET(WM_WININICHANGE) | SET(WM_DEVMODECHANGE), 41 /* 0x20 - 0x3f */ 42 SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM) | 43 SET(WM_COMPAREITEM), 44 /* 0x40 - 0x5f */ 45 SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) | SET(WM_COPYGLOBALDATA) | SET(WM_HELP), 46 /* 0x60 - 0x7f */ 47 SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED), 48 /* 0x80 - 0x9f */ 49 SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE), 50 /* 0xa0 - 0xbf */ 51 SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP), 52 /* 0xc0 - 0xdf */ 53 SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS), 54 /* 0xe0 - 0xff */ 55 SET(SBM_GETRANGE) | SET(SBM_SETSCROLLINFO) | SET(SBM_GETSCROLLINFO) | SET(SBM_GETSCROLLBARINFO), 56 /* 0x100 - 0x11f */ 57 0, 58 /* 0x120 - 0x13f */ 59 0, 60 /* 0x140 - 0x15f */ 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), 64 /* 0x160 - 0x17f */ 65 0, 66 /* 0x180 - 0x19f */ 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), 70 /* 0x1a0 - 0x1bf */ 71 SET(LB_FINDSTRINGEXACT), 72 /* 0x1c0 - 0x1df */ 73 0, 74 /* 0x1e0 - 0x1ff */ 75 0, 76 /* 0x200 - 0x21f */ 77 SET(WM_NEXTMENU) | SET(WM_SIZING) | SET(WM_MOVING) | SET(WM_DEVICECHANGE), 78 /* 0x220 - 0x23f */ 79 SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) | 80 SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGLOOP) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE), 81 /* 0x240 - 0x25f */ 82 0, 83 /* 0x260 - 0x27f */ 84 0, 85 /* 0x280 - 0x29f */ 86 0, 87 /* 0x2a0 - 0x2bf */ 88 0, 89 /* 0x2c0 - 0x2df */ 90 0, 91 /* 0x2e0 - 0x2ff */ 92 0, 93 /* 0x300 - 0x31f */ 94 SET(WM_ASKCBFORMATNAME) 95 }; 96 97 /* check whether a given message type includes pointers */ 98 static inline int is_pointer_message( UINT message ) 99 { 100 if (message >= 8*sizeof(message_pointer_flags)) return FALSE; 101 return (message_pointer_flags[message / 32] & SET(message)) != 0; 102 } 103 104 #undef SET 105 106 /* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */ 107 static BOOL FASTCALL combobox_has_strings( HWND hwnd ) 108 { 109 DWORD style = GetWindowLongA( hwnd, GWL_STYLE ); 110 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS)); 111 } 112 113 /* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */ 114 static BOOL FASTCALL listbox_has_strings( HWND hwnd ) 115 { 116 DWORD style = GetWindowLongA( hwnd, GWL_STYLE ); 117 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS)); 118 } 119 120 /* DDE message exchange 121 * 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. 130 * 131 * - Execute 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. 158 */ 159 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. 166 */ 167 168 typedef struct tagDDEPAIR 169 { 170 HGLOBAL ClientMem; 171 HGLOBAL ServerMem; 172 } DDEPAIR, *PDDEPAIR; 173 174 static PDDEPAIR DdePairs = NULL; 175 static unsigned DdeNumAlloc = 0; 176 static unsigned DdeNumUsed = 0; 177 static CRITICAL_SECTION DdeCrst; 178 179 BOOL FASTCALL 180 DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem) 181 { 182 unsigned i; 183 184 EnterCriticalSection(&DdeCrst); 185 186 /* now remember the pair of hMem on both sides */ 187 if (DdeNumUsed == DdeNumAlloc) 188 { 189 #define GROWBY 4 190 PDDEPAIR New; 191 if (NULL != DdePairs) 192 { 193 New = HeapReAlloc(GetProcessHeap(), 0, DdePairs, 194 (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR)); 195 } 196 else 197 { 198 New = HeapAlloc(GetProcessHeap(), 0, 199 (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR)); 200 } 201 202 if (NULL == New) 203 { 204 LeaveCriticalSection(&DdeCrst); 205 return FALSE; 206 } 207 DdePairs = New; 208 /* zero out newly allocated part */ 209 memset(&DdePairs[DdeNumAlloc], 0, GROWBY * sizeof(DDEPAIR)); 210 DdeNumAlloc += GROWBY; 211 #undef GROWBY 212 } 213 214 for (i = 0; i < DdeNumAlloc; i++) 215 { 216 if (NULL == DdePairs[i].ServerMem) 217 { 218 DdePairs[i].ClientMem = ClientMem; 219 DdePairs[i].ServerMem = ServerMem; 220 DdeNumUsed++; 221 break; 222 } 223 } 224 LeaveCriticalSection(&DdeCrst); 225 226 return TRUE; 227 } 228 229 HGLOBAL FASTCALL 230 DdeGetPair(HGLOBAL ServerMem) 231 { 232 unsigned i; 233 HGLOBAL Ret = NULL; 234 235 EnterCriticalSection(&DdeCrst); 236 for (i = 0; i < DdeNumAlloc; i++) 237 { 238 if (DdePairs[i].ServerMem == ServerMem) 239 { 240 /* free this pair */ 241 DdePairs[i].ServerMem = 0; 242 DdeNumUsed--; 243 Ret = DdePairs[i].ClientMem; 244 break; 245 } 246 } 247 LeaveCriticalSection(&DdeCrst); 248 249 return Ret; 250 } 251 252 DWORD FASTCALL get_input_codepage( void ) 253 { 254 DWORD cp; 255 int ret; 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; 259 return cp; 260 } 261 262 static WPARAM FASTCALL map_wparam_char_WtoA( WPARAM wParam, DWORD len ) 263 { 264 WCHAR wch = wParam; 265 BYTE ch[2]; 266 DWORD cp = get_input_codepage(); 267 268 len = WideCharToMultiByte( cp, 0, &wch, 1, (LPSTR)ch, len, NULL, NULL ); 269 if (len == 2) 270 return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) ); 271 else 272 return MAKEWPARAM( ch[0], HIWORD(wParam) ); 273 } 274 275 /*********************************************************************** 276 * map_wparam_AtoW 277 * 278 * Convert the wparam of an ASCII message to Unicode. 279 */ 280 static WPARAM FASTCALL 281 map_wparam_AtoW( UINT message, WPARAM wparam ) 282 { 283 char ch[2]; 284 WCHAR wch[2]; 285 286 wch[0] = wch[1] = 0; 287 switch(message) 288 { 289 case WM_CHAR: 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. 293 */ 294 #if 0 295 if (mapping != WMCHAR_MAP_NOMAPPING) // NlsMbCodePageTag 296 { 297 PCLIENTINFO pci = GetWin32ClientInfo(); 298 299 struct wm_char_mapping_data *data = get_user_thread_info()->wmchar_data; 300 301 BYTE low = LOBYTE(wparam); 302 303 if (HIBYTE(wparam)) 304 { 305 ch[0] = low; 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; 310 } 311 else if (data && data->lead_byte[mapping]) 312 { 313 ch[0] = data->lead_byte[mapping]; 314 ch[1] = low; 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; 318 } 319 else if (!IsDBCSLeadByte( low )) 320 { 321 ch[0] = 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; 325 } 326 else /* store it and wait for trail byte */ 327 { 328 if (!data) 329 { 330 if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) 331 return FALSE; 332 get_user_thread_info()->wmchar_data = data; 333 } 334 TRACE( "storing lead byte %02x mapping %u\n", low, mapping ); 335 data->lead_byte[mapping] = low; 336 return FALSE; 337 } 338 wparam = MAKEWPARAM(wch[0], wch[1]); 339 break; 340 } 341 #endif 342 /* else fall through */ 343 case WM_CHARTOITEM: 344 case EM_SETPASSWORDCHAR: 345 case WM_DEADCHAR: 346 case WM_SYSCHAR: 347 case WM_SYSDEADCHAR: 348 case WM_MENUCHAR: 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]); 353 break; 354 case WM_IME_CHAR: 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)); 360 break; 361 } 362 return wparam; 363 } 364 365 static 366 BOOL FASTCALL 367 MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted) 368 { 369 *KMMsg = *UMMsg; 370 371 switch (UMMsg->message) 372 { 373 case WM_COPYDATA: 374 { 375 PCOPYDATASTRUCT pUMCopyData = (PCOPYDATASTRUCT)UMMsg->lParam; 376 PCOPYDATASTRUCT pKMCopyData; 377 378 pKMCopyData = HeapAlloc(GetProcessHeap(), 0, sizeof(COPYDATASTRUCT) + pUMCopyData->cbData); 379 if (!pKMCopyData) 380 { 381 SetLastError(ERROR_OUTOFMEMORY); 382 return FALSE; 383 } 384 385 pKMCopyData->dwData = pUMCopyData->dwData; 386 pKMCopyData->cbData = pUMCopyData->cbData; 387 pKMCopyData->lpData = pKMCopyData + 1; 388 389 RtlCopyMemory(pKMCopyData + 1, pUMCopyData->lpData, pUMCopyData->cbData); 390 391 KMMsg->lParam = (LPARAM)pKMCopyData; 392 } 393 break; 394 395 case WM_COPYGLOBALDATA: 396 { 397 KMMsg->lParam = (LPARAM)GlobalLock((HGLOBAL)UMMsg->lParam);; 398 TRACE("WM_COPYGLOBALDATA get data ptr %p\n",KMMsg->lParam); 399 } 400 break; 401 402 default: 403 break; 404 } 405 406 return TRUE; 407 } 408 409 static 410 VOID FASTCALL 411 MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg) 412 { 413 switch (KMMsg->message) 414 { 415 case WM_COPYDATA: 416 HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam); 417 break; 418 case WM_COPYGLOBALDATA: 419 TRACE("WM_COPYGLOBALDATA cleanup return\n"); 420 GlobalUnlock((HGLOBAL)UMMsg->lParam); 421 GlobalFree((HGLOBAL)UMMsg->lParam); 422 break; 423 default: 424 break; 425 } 426 427 return; 428 } 429 430 static BOOL FASTCALL 431 MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg) 432 { 433 *UMMsg = *KMMsg; 434 435 if (KMMsg->lParam == 0) return TRUE; 436 437 switch (UMMsg->message) 438 { 439 case WM_CREATE: 440 case WM_NCCREATE: 441 { 442 CREATESTRUCTW *Cs = (CREATESTRUCTW *) KMMsg->lParam; 443 PCHAR Class; 444 Cs->lpszName = (LPCWSTR) ((PCHAR) Cs + (DWORD_PTR) Cs->lpszName); 445 Class = (PCHAR) Cs + (DWORD_PTR) Cs->lpszClass; 446 if (L'A' == *((WCHAR *) Class)) 447 { 448 Class += sizeof(WCHAR); 449 Cs->lpszClass = (LPCWSTR)(DWORD_PTR) (*((ATOM *) Class)); 450 } 451 else 452 { 453 ASSERT(L'S' == *((WCHAR *) Class)); 454 Class += sizeof(WCHAR); 455 Cs->lpszClass = (LPCWSTR) Class; 456 } 457 } 458 break; 459 460 case WM_COPYDATA: 461 { 462 PCOPYDATASTRUCT pKMCopyData = (PCOPYDATASTRUCT)KMMsg->lParam; 463 pKMCopyData->lpData = pKMCopyData + 1; 464 } 465 break; 466 467 case WM_COPYGLOBALDATA: 468 { 469 PVOID Data; 470 HGLOBAL hGlobal = GlobalAlloc(GHND | GMEM_SHARE, KMMsg->wParam); 471 Data = GlobalLock(hGlobal); 472 if (Data) RtlCopyMemory(Data, (PVOID)KMMsg->lParam, KMMsg->wParam); 473 GlobalUnlock(hGlobal); 474 TRACE("WM_COPYGLOBALDATA to User hGlobal %p\n",hGlobal); 475 UMMsg->lParam = (LPARAM)hGlobal; 476 } 477 break; 478 479 default: 480 break; 481 } 482 483 return TRUE; 484 } 485 486 static VOID FASTCALL 487 MsgiKMToUMCleanup(PMSG KMMsg, PMSG UMMsg) 488 { 489 switch (KMMsg->message) 490 { 491 case WM_DDE_EXECUTE: 492 #ifdef TODO // Kept as historic. 493 HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam); 494 GlobalUnlock((HGLOBAL) UMMsg->lParam); 495 #endif 496 break; 497 default: 498 break; 499 } 500 501 return; 502 } 503 504 static BOOL FASTCALL 505 MsgiKMToUMReply(PMSG KMMsg, PMSG UMMsg, LRESULT *Result) 506 { 507 MsgiKMToUMCleanup(KMMsg, UMMsg); 508 509 return TRUE; 510 } 511 512 // 513 // Ansi to Unicode -> callout 514 // 515 static BOOL FASTCALL 516 MsgiAnsiToUnicodeMessage(HWND hwnd, LPMSG UnicodeMsg, LPMSG AnsiMsg) 517 { 518 UNICODE_STRING UnicodeString; 519 520 *UnicodeMsg = *AnsiMsg; 521 522 switch (AnsiMsg->message) 523 { 524 case WM_GETTEXT: 525 case WM_ASKCBFORMATNAME: 526 { 527 LPWSTR Buffer; 528 if (!AnsiMsg->lParam) break; 529 Buffer = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, AnsiMsg->wParam * sizeof(WCHAR)); 530 //ERR("WM_GETTEXT A2U Size %d\n",AnsiMsg->wParam); 531 if (!Buffer) return FALSE; 532 UnicodeMsg->lParam = (LPARAM)Buffer; 533 break; 534 } 535 536 case LB_GETTEXT: 537 { 538 DWORD Size = 1024 * sizeof(WCHAR); 539 if (!AnsiMsg->lParam || !listbox_has_strings( AnsiMsg->hwnd )) break; 540 /*Size = SendMessageW( AnsiMsg->hwnd, LB_GETTEXTLEN, AnsiMsg->wParam, 0 ); 541 if (Size == LB_ERR) 542 { 543 ERR("LB_GETTEXT LB_ERR\n"); 544 Size = sizeof(ULONG_PTR); 545 } 546 Size = (Size + 1) * sizeof(WCHAR);*/ 547 UnicodeMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); 548 if (!UnicodeMsg->lParam) return FALSE; 549 break; 550 } 551 552 case CB_GETLBTEXT: 553 { 554 DWORD Size = 1024 * sizeof(WCHAR); 555 if (!AnsiMsg->lParam || !combobox_has_strings( AnsiMsg->hwnd )) break; 556 /*Size = SendMessageW( AnsiMsg->hwnd, CB_GETLBTEXTLEN, AnsiMsg->wParam, 0 ); 557 if (Size == LB_ERR) 558 { 559 ERR("CB_GETTEXT LB_ERR\n"); 560 Size = sizeof(ULONG_PTR); 561 } 562 Size = (Size + 1) * sizeof(WCHAR);*/ 563 UnicodeMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); 564 if (!UnicodeMsg->lParam) return FALSE; 565 break; 566 } 567 568 /* AnsiMsg->lParam is string (0-terminated) */ 569 case WM_SETTEXT: 570 case WM_WININICHANGE: 571 case WM_DEVMODECHANGE: 572 case CB_DIR: 573 case LB_DIR: 574 case LB_ADDFILE: 575 case EM_REPLACESEL: 576 { 577 if (!AnsiMsg->lParam) break; 578 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam); 579 UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer; 580 break; 581 } 582 583 case LB_ADDSTRING: 584 case LB_ADDSTRING_LOWER: 585 case LB_ADDSTRING_UPPER: 586 case LB_INSERTSTRING: 587 case LB_INSERTSTRING_UPPER: 588 case LB_INSERTSTRING_LOWER: 589 case LB_FINDSTRING: 590 case LB_FINDSTRINGEXACT: 591 case LB_SELECTSTRING: 592 { 593 if (AnsiMsg->lParam && listbox_has_strings(AnsiMsg->hwnd)) 594 { 595 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam); 596 UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer; 597 } 598 break; 599 } 600 601 case CB_ADDSTRING: 602 case CB_INSERTSTRING: 603 case CB_FINDSTRING: 604 case CB_FINDSTRINGEXACT: 605 case CB_SELECTSTRING: 606 { 607 if (AnsiMsg->lParam && combobox_has_strings(AnsiMsg->hwnd)) 608 { 609 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)AnsiMsg->lParam); 610 UnicodeMsg->lParam = (LPARAM)UnicodeString.Buffer; 611 } 612 break; 613 } 614 615 case WM_NCCREATE: 616 case WM_CREATE: 617 { 618 struct s 619 { 620 CREATESTRUCTW cs; /* new structure */ 621 MDICREATESTRUCTW mdi_cs; /* MDI info */ 622 LPCWSTR lpszName; /* allocated Name */ 623 LPCWSTR lpszClass; /* allocated Class */ 624 }; 625 626 struct s *xs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s)); 627 if (!xs) 628 { 629 return FALSE; 630 } 631 xs->cs = *(CREATESTRUCTW *)AnsiMsg->lParam; 632 if (!IS_INTRESOURCE(xs->cs.lpszName)) 633 { 634 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)xs->cs.lpszName); 635 xs->lpszName = xs->cs.lpszName = UnicodeString.Buffer; 636 } 637 if (!IS_ATOM(xs->cs.lpszClass)) 638 { 639 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)xs->cs.lpszClass); 640 xs->lpszClass = xs->cs.lpszClass = UnicodeString.Buffer; 641 } 642 643 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD) 644 { 645 xs->mdi_cs = *(MDICREATESTRUCTW *)xs->cs.lpCreateParams; 646 xs->mdi_cs.szTitle = xs->cs.lpszName; 647 xs->mdi_cs.szClass = xs->cs.lpszClass; 648 xs->cs.lpCreateParams = &xs->mdi_cs; 649 } 650 651 UnicodeMsg->lParam = (LPARAM)xs; 652 break; 653 } 654 655 case WM_MDICREATE: 656 { 657 MDICREATESTRUCTW *cs = 658 (MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs)); 659 660 if (!cs) 661 { 662 return FALSE; 663 } 664 665 *cs = *(MDICREATESTRUCTW *)AnsiMsg->lParam; 666 667 if (!IS_ATOM(cs->szClass)) 668 { 669 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)cs->szClass); 670 cs->szClass = UnicodeString.Buffer; 671 } 672 673 RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)cs->szTitle); 674 cs->szTitle = UnicodeString.Buffer; 675 676 UnicodeMsg->lParam = (LPARAM)cs; 677 break; 678 } 679 680 case WM_GETDLGCODE: 681 if (UnicodeMsg->lParam) 682 { 683 MSG newmsg = *(MSG *)UnicodeMsg->lParam; 684 newmsg.wParam = map_wparam_AtoW( newmsg.message, newmsg.wParam); 685 } 686 break; 687 688 case WM_CHARTOITEM: 689 case WM_MENUCHAR: 690 case WM_CHAR: 691 case WM_DEADCHAR: 692 case WM_SYSCHAR: 693 case WM_SYSDEADCHAR: 694 case EM_SETPASSWORDCHAR: 695 case WM_IME_CHAR: 696 UnicodeMsg->wParam = map_wparam_AtoW( AnsiMsg->message, AnsiMsg->wParam ); 697 break; 698 case EM_GETLINE: 699 ERR("FIXME EM_GETLINE A2U\n"); 700 break; 701 702 } 703 704 return TRUE; 705 } 706 707 static BOOL FASTCALL 708 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg) 709 { 710 UNICODE_STRING UnicodeString; 711 712 switch (AnsiMsg->message) 713 { 714 case LB_GETTEXT: 715 if (!listbox_has_strings( UnicodeMsg->hwnd )) break; 716 case CB_GETLBTEXT: 717 if (UnicodeMsg->message == CB_GETLBTEXT && !combobox_has_strings( UnicodeMsg->hwnd )) break; 718 case WM_GETTEXT: 719 case WM_ASKCBFORMATNAME: 720 { 721 if (!UnicodeMsg->lParam) break; 722 RtlFreeHeap(GetProcessHeap(), 0, (PVOID) UnicodeMsg->lParam); 723 break; 724 } 725 726 case WM_SETTEXT: 727 case WM_WININICHANGE: 728 case WM_DEVMODECHANGE: 729 case CB_DIR: 730 case LB_DIR: 731 case LB_ADDFILE: 732 case EM_REPLACESEL: 733 { 734 if (!UnicodeMsg->lParam) break; 735 RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam); 736 RtlFreeUnicodeString(&UnicodeString); 737 break; 738 } 739 740 case LB_ADDSTRING: 741 case LB_ADDSTRING_LOWER: 742 case LB_ADDSTRING_UPPER: 743 case LB_INSERTSTRING: 744 case LB_INSERTSTRING_UPPER: 745 case LB_INSERTSTRING_LOWER: 746 case LB_FINDSTRING: 747 case LB_FINDSTRINGEXACT: 748 case LB_SELECTSTRING: 749 { 750 if (UnicodeMsg->lParam && listbox_has_strings(AnsiMsg->hwnd)) 751 { 752 RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam); 753 RtlFreeUnicodeString(&UnicodeString); 754 } 755 break; 756 } 757 758 case CB_ADDSTRING: 759 case CB_INSERTSTRING: 760 case CB_FINDSTRING: 761 case CB_FINDSTRINGEXACT: 762 case CB_SELECTSTRING: 763 { 764 if (UnicodeMsg->lParam && combobox_has_strings(AnsiMsg->hwnd)) 765 { 766 RtlInitUnicodeString(&UnicodeString, (PCWSTR)UnicodeMsg->lParam); 767 RtlFreeUnicodeString(&UnicodeString); 768 } 769 break; 770 } 771 772 case WM_NCCREATE: 773 case WM_CREATE: 774 { 775 struct s 776 { 777 CREATESTRUCTW cs; /* new structure */ 778 MDICREATESTRUCTW mdi_cs; /* MDI info */ 779 LPWSTR lpszName; /* allocated Name */ 780 LPWSTR lpszClass; /* allocated Class */ 781 }; 782 783 struct s *xs = (struct s *)UnicodeMsg->lParam; 784 if (xs->lpszName) 785 { 786 RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszName); 787 RtlFreeUnicodeString(&UnicodeString); 788 } 789 if (xs->lpszClass) 790 { 791 RtlInitUnicodeString(&UnicodeString, (PCWSTR)xs->lpszClass); 792 RtlFreeUnicodeString(&UnicodeString); 793 } 794 HeapFree(GetProcessHeap(), 0, xs); 795 break; 796 } 797 798 case WM_MDICREATE: 799 { 800 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)UnicodeMsg->lParam; 801 RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szTitle); 802 RtlFreeUnicodeString(&UnicodeString); 803 if (!IS_ATOM(cs->szClass)) 804 { 805 RtlInitUnicodeString(&UnicodeString, (PCWSTR)cs->szClass); 806 RtlFreeUnicodeString(&UnicodeString); 807 } 808 HeapFree(GetProcessHeap(), 0, cs); 809 break; 810 } 811 } 812 813 return(TRUE); 814 } 815 816 /* 817 * callout return -> Unicode Result to Ansi Result 818 */ 819 static BOOL FASTCALL 820 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result) 821 { 822 LPWSTR Buffer = (LPWSTR)UnicodeMsg->lParam; 823 LPSTR AnsiBuffer = (LPSTR)AnsiMsg->lParam; 824 825 switch (AnsiMsg->message) 826 { 827 case WM_GETTEXT: 828 case WM_ASKCBFORMATNAME: 829 { 830 if (UnicodeMsg->wParam) 831 { 832 DWORD len = 0; 833 if (*Result) RtlUnicodeToMultiByteN( AnsiBuffer, UnicodeMsg->wParam - 1, &len, Buffer, strlenW(Buffer) * sizeof(WCHAR)); 834 AnsiBuffer[len] = 0; 835 *Result = len; 836 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam); 837 } 838 break; 839 } 840 case LB_GETTEXT: 841 { 842 if (!AnsiBuffer || !listbox_has_strings( UnicodeMsg->hwnd )) break; 843 if (*Result >= 0) 844 { 845 DWORD len; 846 RtlUnicodeToMultiByteN( AnsiBuffer, ~0u, &len, Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR) ); 847 *Result = len - 1; 848 } 849 break; 850 } 851 case CB_GETLBTEXT: 852 { 853 if (!AnsiBuffer || !combobox_has_strings( UnicodeMsg->hwnd )) break; 854 if (*Result >= 0) 855 { 856 DWORD len; 857 RtlUnicodeToMultiByteN( AnsiBuffer, ~0u, &len, Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR) ); 858 *Result = len - 1; 859 } 860 break; 861 } 862 } 863 864 MsgiAnsiToUnicodeCleanup(UnicodeMsg, AnsiMsg); 865 866 return TRUE; 867 } 868 869 // 870 // Unicode to Ansi callout -> 871 // 872 static BOOL FASTCALL 873 MsgiUnicodeToAnsiMessage(HWND hwnd, LPMSG AnsiMsg, LPMSG UnicodeMsg) 874 { 875 ANSI_STRING AnsiString; 876 UNICODE_STRING UnicodeString; 877 878 *AnsiMsg = *UnicodeMsg; 879 880 switch(UnicodeMsg->message) 881 { 882 case WM_CREATE: 883 case WM_NCCREATE: 884 { 885 MDICREATESTRUCTA *pmdi_cs; 886 CREATESTRUCTA* CsA; 887 CREATESTRUCTW* CsW; 888 ULONG NameSize, ClassSize; 889 NTSTATUS Status; 890 891 CsW = (CREATESTRUCTW*)(UnicodeMsg->lParam); 892 RtlInitUnicodeString(&UnicodeString, CsW->lpszName); 893 NameSize = RtlUnicodeStringToAnsiSize(&UnicodeString); 894 if (NameSize == 0) 895 { 896 return FALSE; 897 } 898 ClassSize = 0; 899 if (!IS_ATOM(CsW->lpszClass)) 900 { 901 RtlInitUnicodeString(&UnicodeString, CsW->lpszClass); 902 ClassSize = RtlUnicodeStringToAnsiSize(&UnicodeString); 903 if (ClassSize == 0) 904 { 905 return FALSE; 906 } 907 } 908 909 CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA) + sizeof(MDICREATESTRUCTA) + NameSize + ClassSize); 910 if (NULL == CsA) 911 { 912 return FALSE; 913 } 914 memcpy(CsA, CsW, sizeof(CREATESTRUCTW)); 915 916 /* pmdi_cs starts right after CsA */ 917 pmdi_cs = (MDICREATESTRUCTA*)(CsA + 1); 918 919 RtlInitUnicodeString(&UnicodeString, CsW->lpszName); 920 RtlInitEmptyAnsiString(&AnsiString, (PCHAR)(pmdi_cs + 1), NameSize); 921 Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); 922 if (! NT_SUCCESS(Status)) 923 { 924 RtlFreeHeap(GetProcessHeap(), 0, CsA); 925 return FALSE; 926 } 927 CsA->lpszName = AnsiString.Buffer; 928 if (!IS_ATOM(CsW->lpszClass)) 929 { 930 RtlInitUnicodeString(&UnicodeString, CsW->lpszClass); 931 RtlInitEmptyAnsiString(&AnsiString, (PCHAR)(pmdi_cs + 1) + NameSize, ClassSize); 932 Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); 933 if (! NT_SUCCESS(Status)) 934 { 935 RtlFreeHeap(GetProcessHeap(), 0, CsA); 936 return FALSE; 937 } 938 CsA->lpszClass = AnsiString.Buffer; 939 } 940 941 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD) 942 { 943 *pmdi_cs = *(MDICREATESTRUCTA *)CsW->lpCreateParams; 944 pmdi_cs->szTitle = CsA->lpszName; 945 pmdi_cs->szClass = CsA->lpszClass; 946 CsA->lpCreateParams = pmdi_cs; 947 } 948 949 AnsiMsg->lParam = (LPARAM)CsA; 950 break; 951 } 952 case WM_GETTEXT: 953 case WM_ASKCBFORMATNAME: 954 { 955 if (!UnicodeMsg->lParam) break; 956 /* Ansi string might contain MBCS chars so we need 2 * the number of chars */ 957 AnsiMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, UnicodeMsg->wParam * 2); 958 //ERR("WM_GETTEXT U2A Size %d\n",AnsiMsg->wParam); 959 960 if (!AnsiMsg->lParam) return FALSE; 961 break; 962 } 963 964 case LB_GETTEXT: 965 { 966 DWORD Size = 1024; 967 if (!UnicodeMsg->lParam || !listbox_has_strings( UnicodeMsg->hwnd )) break; 968 /*Size = SendMessageA( UnicodeMsg->hwnd, LB_GETTEXTLEN, UnicodeMsg->wParam, 0 ); 969 if (Size == LB_ERR) 970 { 971 ERR("LB_GETTEXT LB_ERR\n"); 972 Size = sizeof(ULONG_PTR); 973 } 974 Size = (Size + 1) * sizeof(WCHAR);*/ 975 AnsiMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); 976 if (!AnsiMsg->lParam) return FALSE; 977 break; 978 } 979 980 case CB_GETLBTEXT: 981 { 982 DWORD Size = 1024; 983 if (!UnicodeMsg->lParam || !combobox_has_strings( UnicodeMsg->hwnd )) break; 984 /*Size = SendMessageA( UnicodeMsg->hwnd, CB_GETLBTEXTLEN, UnicodeMsg->wParam, 0 ); 985 if (Size == LB_ERR) 986 { 987 ERR("CB_GETTEXT LB_ERR\n"); 988 Size = sizeof(ULONG_PTR); 989 } 990 Size = (Size + 1) * sizeof(WCHAR);*/ 991 AnsiMsg->lParam = (LPARAM) RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); 992 if (!AnsiMsg->lParam) return FALSE; 993 break; 994 } 995 996 case WM_SETTEXT: 997 case WM_WININICHANGE: 998 case WM_DEVMODECHANGE: 999 case CB_DIR: 1000 case LB_DIR: 1001 case LB_ADDFILE: 1002 case EM_REPLACESEL: 1003 { 1004 if (!UnicodeMsg->lParam) break; 1005 RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam); 1006 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, 1007 &UnicodeString, 1008 TRUE))) 1009 { 1010 return FALSE; 1011 } 1012 AnsiMsg->lParam = (LPARAM) AnsiString.Buffer; 1013 break; 1014 } 1015 1016 case LB_ADDSTRING: 1017 case LB_ADDSTRING_LOWER: 1018 case LB_ADDSTRING_UPPER: 1019 case LB_INSERTSTRING: 1020 case LB_INSERTSTRING_UPPER: 1021 case LB_INSERTSTRING_LOWER: 1022 case LB_FINDSTRING: 1023 case LB_FINDSTRINGEXACT: 1024 case LB_SELECTSTRING: 1025 { 1026 if (UnicodeMsg->lParam && listbox_has_strings(AnsiMsg->hwnd)) 1027 { 1028 RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam); 1029 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, 1030 &UnicodeString, 1031 TRUE))) 1032 { 1033 return FALSE; 1034 } 1035 AnsiMsg->lParam = (LPARAM) AnsiString.Buffer; 1036 } 1037 break; 1038 } 1039 1040 case CB_ADDSTRING: 1041 case CB_INSERTSTRING: 1042 case CB_FINDSTRING: 1043 case CB_FINDSTRINGEXACT: 1044 case CB_SELECTSTRING: 1045 { 1046 if (UnicodeMsg->lParam && combobox_has_strings(AnsiMsg->hwnd)) 1047 { 1048 RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam); 1049 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, 1050 &UnicodeString, 1051 TRUE))) 1052 { 1053 return FALSE; 1054 } 1055 AnsiMsg->lParam = (LPARAM) AnsiString.Buffer; 1056 } 1057 break; 1058 } 1059 1060 case WM_MDICREATE: 1061 { 1062 MDICREATESTRUCTA *cs = 1063 (MDICREATESTRUCTA *)HeapAlloc(GetProcessHeap(), 0, sizeof(*cs)); 1064 1065 if (!cs) 1066 { 1067 return FALSE; 1068 } 1069 1070 *cs = *(MDICREATESTRUCTA *)UnicodeMsg->lParam; 1071 1072 if (!IS_ATOM(cs->szClass)) 1073 { 1074 RtlInitUnicodeString(&UnicodeString, (LPCWSTR)cs->szClass); 1075 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, 1076 &UnicodeString, 1077 TRUE))) 1078 { 1079 HeapFree(GetProcessHeap(), 0, cs); 1080 return FALSE; 1081 } 1082 cs->szClass = AnsiString.Buffer; 1083 } 1084 1085 RtlInitUnicodeString(&UnicodeString, (LPCWSTR)cs->szTitle); 1086 if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString, 1087 &UnicodeString, 1088 TRUE))) 1089 { 1090 if (!IS_ATOM(cs->szClass)) 1091 { 1092 RtlInitAnsiString(&AnsiString, cs->szClass); 1093 RtlFreeAnsiString(&AnsiString); 1094 } 1095 1096 HeapFree(GetProcessHeap(), 0, cs); 1097 return FALSE; 1098 } 1099 cs->szTitle = AnsiString.Buffer; 1100 1101 AnsiMsg->lParam = (LPARAM)cs; 1102 break; 1103 } 1104 1105 case WM_GETDLGCODE: 1106 if (UnicodeMsg->lParam) 1107 { 1108 MSG newmsg = *(MSG *)UnicodeMsg->lParam; 1109 switch(newmsg.message) 1110 { 1111 case WM_CHAR: 1112 case WM_DEADCHAR: 1113 case WM_SYSCHAR: 1114 case WM_SYSDEADCHAR: 1115 newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 1 ); 1116 break; 1117 case WM_IME_CHAR: 1118 newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 2 ); 1119 break; 1120 } 1121 } 1122 break; 1123 1124 case WM_CHAR: 1125 { 1126 WCHAR wch = UnicodeMsg->wParam; 1127 char ch[2]; 1128 DWORD cp = get_input_codepage(); 1129 DWORD len = WideCharToMultiByte( cp, 0, &wch, 1, ch, 2, NULL, NULL ); 1130 AnsiMsg->wParam = (BYTE)ch[0]; 1131 if (len == 2) AnsiMsg->wParam = (BYTE)ch[1]; 1132 } 1133 break; 1134 1135 case WM_CHARTOITEM: 1136 case WM_MENUCHAR: 1137 case WM_DEADCHAR: 1138 case WM_SYSCHAR: 1139 case WM_SYSDEADCHAR: 1140 case EM_SETPASSWORDCHAR: 1141 AnsiMsg->wParam = map_wparam_char_WtoA(UnicodeMsg->wParam,1); 1142 break; 1143 1144 case WM_IME_CHAR: 1145 AnsiMsg->wParam = map_wparam_char_WtoA(UnicodeMsg->wParam,2); 1146 break; 1147 case EM_GETLINE: 1148 ERR("FIXME EM_GETLINE U2A\n"); 1149 break; 1150 } 1151 return TRUE; 1152 } 1153 1154 static BOOL FASTCALL 1155 MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg, LPMSG UnicodeMsg) 1156 { 1157 ANSI_STRING AnsiString; 1158 1159 switch(UnicodeMsg->message) 1160 { 1161 case LB_GETTEXT: 1162 if (!listbox_has_strings( AnsiMsg->hwnd )) break; 1163 case CB_GETLBTEXT: 1164 if (AnsiMsg->message == CB_GETLBTEXT && !combobox_has_strings( AnsiMsg->hwnd )) break; 1165 case WM_GETTEXT: 1166 case WM_ASKCBFORMATNAME: 1167 { 1168 if (!AnsiMsg->lParam) break; 1169 RtlFreeHeap(GetProcessHeap(), 0, (PVOID) AnsiMsg->lParam); 1170 break; 1171 } 1172 case WM_CREATE: 1173 case WM_NCCREATE: 1174 { 1175 CREATESTRUCTA* Cs; 1176 1177 Cs = (CREATESTRUCTA*) AnsiMsg->lParam; 1178 RtlFreeHeap(GetProcessHeap(), 0, Cs); 1179 break; 1180 } 1181 1182 case WM_SETTEXT: 1183 case WM_WININICHANGE: 1184 case WM_DEVMODECHANGE: 1185 case CB_DIR: 1186 case LB_DIR: 1187 case LB_ADDFILE: 1188 case EM_REPLACESEL: 1189 { 1190 if (!AnsiMsg->lParam) break; 1191 RtlInitAnsiString(&AnsiString, (PSTR) AnsiMsg->lParam); 1192 RtlFreeAnsiString(&AnsiString); 1193 break; 1194 } 1195 1196 case LB_ADDSTRING: 1197 case LB_ADDSTRING_LOWER: 1198 case LB_ADDSTRING_UPPER: 1199 case LB_INSERTSTRING: 1200 case LB_INSERTSTRING_UPPER: 1201 case LB_INSERTSTRING_LOWER: 1202 case LB_FINDSTRING: 1203 case LB_FINDSTRINGEXACT: 1204 case LB_SELECTSTRING: 1205 { 1206 if (AnsiMsg->lParam && listbox_has_strings(AnsiMsg->hwnd)) 1207 { 1208 RtlInitAnsiString(&AnsiString, (PSTR) AnsiMsg->lParam); 1209 RtlFreeAnsiString(&AnsiString); 1210 } 1211 break; 1212 } 1213 1214 case CB_ADDSTRING: 1215 case CB_INSERTSTRING: 1216 case CB_FINDSTRING: 1217 case CB_FINDSTRINGEXACT: 1218 case CB_SELECTSTRING: 1219 { 1220 if (AnsiMsg->lParam && combobox_has_strings(AnsiMsg->hwnd)) 1221 { 1222 RtlInitAnsiString(&AnsiString, (PSTR) AnsiMsg->lParam); 1223 RtlFreeAnsiString(&AnsiString); 1224 } 1225 break; 1226 } 1227 1228 case WM_MDICREATE: 1229 { 1230 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)AnsiMsg->lParam; 1231 RtlInitAnsiString(&AnsiString, (PCSTR)cs->szTitle); 1232 RtlFreeAnsiString(&AnsiString); 1233 if (!IS_ATOM(cs->szClass)) 1234 { 1235 RtlInitAnsiString(&AnsiString, (PCSTR)cs->szClass); 1236 RtlFreeAnsiString(&AnsiString); 1237 } 1238 HeapFree(GetProcessHeap(), 0, cs); 1239 break; 1240 } 1241 1242 } 1243 1244 return TRUE; 1245 } 1246 1247 /* 1248 * callout return -> Ansi Result to Unicode Result 1249 */ 1250 static BOOL FASTCALL 1251 MsgiUnicodeToAnsiReply(LPMSG AnsiMsg, LPMSG UnicodeMsg, LRESULT *Result) 1252 { 1253 LPSTR Buffer = (LPSTR) AnsiMsg->lParam; 1254 LPWSTR UBuffer = (LPWSTR) UnicodeMsg->lParam; 1255 1256 switch (UnicodeMsg->message) 1257 { 1258 case WM_GETTEXT: 1259 case WM_ASKCBFORMATNAME: 1260 { 1261 DWORD len = AnsiMsg->wParam;// * 2; 1262 if (len) 1263 { 1264 if (*Result) 1265 { 1266 RtlMultiByteToUnicodeN( UBuffer, AnsiMsg->wParam*sizeof(WCHAR), &len, Buffer, strlen(Buffer)+1 ); 1267 *Result = len/sizeof(WCHAR) - 1; /* do not count terminating null */ 1268 //ERR("WM_GETTEXT U2A Result %d Size %d\n",*Result,AnsiMsg->wParam); 1269 } 1270 UBuffer[*Result] = 0; 1271 } 1272 break; 1273 } 1274 case LB_GETTEXT: 1275 { 1276 if (!UBuffer || !listbox_has_strings( UnicodeMsg->hwnd )) break; 1277 if (*Result >= 0) 1278 { 1279 DWORD len; 1280 RtlMultiByteToUnicodeN( UBuffer, ~0u, &len, Buffer, strlen(Buffer) + 1 ); 1281 *Result = len / sizeof(WCHAR) - 1; 1282 } 1283 break; 1284 } 1285 case CB_GETLBTEXT: 1286 { 1287 if (!UBuffer || !combobox_has_strings( UnicodeMsg->hwnd )) break; 1288 if (*Result >= 0) 1289 { 1290 DWORD len; 1291 RtlMultiByteToUnicodeN( UBuffer, ~0u, &len, Buffer, strlen(Buffer) + 1 ); 1292 *Result = len / sizeof(WCHAR) - 1; 1293 } 1294 break; 1295 } 1296 } 1297 1298 MsgiUnicodeToAnsiCleanup(AnsiMsg, UnicodeMsg); 1299 1300 return TRUE; 1301 } 1302 1303 1304 LRESULT 1305 WINAPI 1306 DesktopWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) 1307 { 1308 LRESULT Result; 1309 MSG AnsiMsg, UcMsg; 1310 1311 TRACE("Desktop A Class Atom! hWnd 0x%x, Msg %d\n", hwnd, message); 1312 1313 AnsiMsg.hwnd = hwnd; 1314 AnsiMsg.message = message; 1315 AnsiMsg.wParam = wParam; 1316 AnsiMsg.lParam = lParam; 1317 AnsiMsg.time = 0; 1318 AnsiMsg.pt.x = 0; 1319 AnsiMsg.pt.y = 0; 1320 1321 // Desktop is always Unicode so convert Ansi here. 1322 if (!MsgiAnsiToUnicodeMessage(hwnd, &UcMsg, &AnsiMsg)) 1323 { 1324 return FALSE; 1325 } 1326 1327 Result = DesktopWndProcW(hwnd, message, UcMsg.wParam, UcMsg.lParam); 1328 1329 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); 1330 1331 return Result; 1332 } 1333 1334 /* 1335 * @implemented 1336 */ 1337 LPARAM 1338 WINAPI 1339 GetMessageExtraInfo(VOID) 1340 { 1341 return NtUserxGetMessageExtraInfo(); 1342 } 1343 1344 1345 /* 1346 * @implemented 1347 */ 1348 DWORD 1349 WINAPI 1350 GetMessagePos(VOID) 1351 { 1352 return NtUserxGetMessagePos(); 1353 } 1354 1355 1356 /* 1357 * @implemented 1358 */ 1359 LONG WINAPI 1360 GetMessageTime(VOID) 1361 { 1362 return NtUserGetThreadState(THREADSTATE_GETMESSAGETIME); 1363 } 1364 1365 1366 /* 1367 * @implemented 1368 */ 1369 BOOL 1370 WINAPI 1371 InSendMessage(VOID) 1372 { 1373 PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; 1374 if ( pcti ) 1375 { 1376 if (pcti->CTI_flags & CTI_INSENDMESSAGE) 1377 { 1378 return TRUE; 1379 } 1380 } 1381 return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); 1382 } 1383 1384 1385 /* 1386 * @implemented 1387 */ 1388 DWORD 1389 WINAPI 1390 InSendMessageEx( 1391 LPVOID lpReserved) 1392 { 1393 PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; 1394 if (pcti && !(pcti->CTI_flags & CTI_INSENDMESSAGE)) 1395 return ISMEX_NOSEND; 1396 else 1397 return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); 1398 } 1399 1400 1401 /* 1402 * @implemented 1403 */ 1404 BOOL 1405 WINAPI 1406 ReplyMessage(LRESULT lResult) 1407 { 1408 return NtUserxReplyMessage(lResult); 1409 } 1410 1411 1412 /* 1413 * @implemented 1414 */ 1415 LPARAM 1416 WINAPI 1417 SetMessageExtraInfo( 1418 LPARAM lParam) 1419 { 1420 return NtUserxSetMessageExtraInfo(lParam); 1421 } 1422 1423 LRESULT FASTCALL 1424 IntCallWindowProcW(BOOL IsAnsiProc, 1425 WNDPROC WndProc, 1426 PWND pWnd, 1427 HWND hWnd, 1428 UINT Msg, 1429 WPARAM wParam, 1430 LPARAM lParam) 1431 { 1432 MSG AnsiMsg; 1433 MSG UnicodeMsg; 1434 BOOL Hook = FALSE, MsgOverride = FALSE, Dialog, DlgOverride = FALSE; 1435 LRESULT Result = 0, PreResult = 0; 1436 DWORD Data = 0; 1437 1438 if (WndProc == NULL) 1439 { 1440 WARN("IntCallWindowsProcW() called with WndProc = NULL!\n"); 1441 return FALSE; 1442 } 1443 1444 if (pWnd) 1445 Dialog = (pWnd->fnid == FNID_DIALOG); 1446 else 1447 Dialog = FALSE; 1448 1449 Hook = BeginIfHookedUserApiHook(); 1450 if (Hook) 1451 { 1452 if (Dialog) 1453 DlgOverride = IsMsgOverride( Msg, &guah.DlgProcArray); 1454 MsgOverride = IsMsgOverride( Msg, &guah.WndProcArray); 1455 } 1456 1457 if (IsAnsiProc) 1458 { 1459 UnicodeMsg.hwnd = hWnd; 1460 UnicodeMsg.message = Msg; 1461 UnicodeMsg.wParam = wParam; 1462 UnicodeMsg.lParam = lParam; 1463 UnicodeMsg.time = 0; 1464 UnicodeMsg.pt.x = 0; 1465 UnicodeMsg.pt.y = 0; 1466 if (! MsgiUnicodeToAnsiMessage(hWnd, &AnsiMsg, &UnicodeMsg)) 1467 { 1468 goto Exit; 1469 } 1470 1471 if (Hook && (MsgOverride || DlgOverride)) 1472 { 1473 _SEH2_TRY 1474 { 1475 if (!DlgOverride) 1476 PreResult = guah.PreWndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam, (ULONG_PTR)&Result, &Data ); 1477 else 1478 PreResult = guah.PreDefDlgProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam, (ULONG_PTR)&Result, &Data ); 1479 } 1480 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1481 { 1482 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride); 1483 } 1484 _SEH2_END; 1485 } 1486 1487 if (PreResult) goto Exit; 1488 1489 if (!Dialog) 1490 Result = CALL_EXTERN_WNDPROC(WndProc, AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam); 1491 else 1492 { 1493 _SEH2_TRY 1494 { 1495 Result = CALL_EXTERN_WNDPROC(WndProc, AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam); 1496 } 1497 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1498 { 1499 ERR("Exception Dialog Ansi %p Msg %d pti %p Wndpti %p\n",WndProc,Msg,GetW32ThreadInfo(),pWnd->head.pti); 1500 } 1501 _SEH2_END; 1502 } 1503 1504 if (Hook && (MsgOverride || DlgOverride)) 1505 { 1506 _SEH2_TRY 1507 { 1508 if (!DlgOverride) 1509 guah.PostWndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam, (ULONG_PTR)&Result, &Data ); 1510 else 1511 guah.PostDefDlgProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam, (ULONG_PTR)&Result, &Data ); 1512 } 1513 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1514 { 1515 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride); 1516 } 1517 _SEH2_END; 1518 } 1519 1520 if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result)) 1521 { 1522 goto Exit; 1523 } 1524 } 1525 else 1526 { 1527 if (Hook && (MsgOverride || DlgOverride)) 1528 { 1529 _SEH2_TRY 1530 { 1531 if (!DlgOverride) 1532 PreResult = guah.PreWndProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1533 else 1534 PreResult = guah.PreDefDlgProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1535 } 1536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1537 { 1538 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride); 1539 } 1540 _SEH2_END; 1541 } 1542 1543 if (PreResult) goto Exit; 1544 1545 if (!Dialog) 1546 Result = CALL_EXTERN_WNDPROC(WndProc, hWnd, Msg, wParam, lParam); 1547 else 1548 { 1549 _SEH2_TRY 1550 { 1551 Result = CALL_EXTERN_WNDPROC(WndProc, hWnd, Msg, wParam, lParam); 1552 } 1553 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1554 { 1555 ERR("Exception Dialog unicode %p Msg %d pti %p Wndpti %p\n",WndProc, Msg,GetW32ThreadInfo(),pWnd->head.pti); 1556 } 1557 _SEH2_END; 1558 } 1559 1560 if (Hook && (MsgOverride || DlgOverride)) 1561 { 1562 _SEH2_TRY 1563 { 1564 if (!DlgOverride) 1565 guah.PostWndProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1566 else 1567 guah.PostDefDlgProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1568 } 1569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1570 { 1571 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride); 1572 } 1573 _SEH2_END; 1574 } 1575 } 1576 1577 Exit: 1578 if (Hook) EndUserApiHook(); 1579 return Result; 1580 } 1581 1582 static LRESULT FASTCALL 1583 IntCallWindowProcA(BOOL IsAnsiProc, 1584 WNDPROC WndProc, 1585 PWND pWnd, 1586 HWND hWnd, 1587 UINT Msg, 1588 WPARAM wParam, 1589 LPARAM lParam) 1590 { 1591 MSG AnsiMsg; 1592 MSG UnicodeMsg; 1593 BOOL Hook = FALSE, MsgOverride = FALSE, Dialog, DlgOverride = FALSE; 1594 LRESULT Result = 0, PreResult = 0; 1595 DWORD Data = 0; 1596 1597 TRACE("IntCallWindowProcA: IsAnsiProc : %s, WndProc %p, pWnd %p, hWnd %p, Msg %u, wParam %Iu, lParam %Iu.\n", 1598 IsAnsiProc ? "TRUE" : "FALSE", WndProc, pWnd, hWnd, Msg, wParam, lParam); 1599 1600 if (WndProc == NULL) 1601 { 1602 WARN("IntCallWindowsProcA() called with WndProc = NULL!\n"); 1603 return FALSE; 1604 } 1605 1606 if (pWnd) 1607 Dialog = (pWnd->fnid == FNID_DIALOG); 1608 else 1609 Dialog = FALSE; 1610 1611 Hook = BeginIfHookedUserApiHook(); 1612 if (Hook) 1613 { 1614 if (Dialog) 1615 DlgOverride = IsMsgOverride( Msg, &guah.DlgProcArray); 1616 MsgOverride = IsMsgOverride( Msg, &guah.WndProcArray); 1617 } 1618 1619 if (IsAnsiProc) 1620 { 1621 if (Hook && (MsgOverride || DlgOverride)) 1622 { 1623 _SEH2_TRY 1624 { 1625 if (!DlgOverride) 1626 PreResult = guah.PreWndProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1627 else 1628 PreResult = guah.PreDefDlgProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1629 } 1630 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1631 { 1632 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride); 1633 } 1634 _SEH2_END; 1635 } 1636 1637 if (PreResult) goto Exit; 1638 1639 if (!Dialog) 1640 Result = CALL_EXTERN_WNDPROC(WndProc, hWnd, Msg, wParam, lParam); 1641 else 1642 { 1643 _SEH2_TRY 1644 { 1645 Result = CALL_EXTERN_WNDPROC(WndProc, hWnd, Msg, wParam, lParam); 1646 } 1647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1648 { 1649 ERR("Exception Dialog Ansi %p Msg %d pti %p Wndpti %p\n",WndProc,Msg,GetW32ThreadInfo(),pWnd->head.pti); 1650 } 1651 _SEH2_END; 1652 } 1653 1654 if (Hook && (MsgOverride || DlgOverride)) 1655 { 1656 _SEH2_TRY 1657 { 1658 if (!DlgOverride) 1659 guah.PostWndProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1660 else 1661 guah.PostDefDlgProc(hWnd, Msg, wParam, lParam, (ULONG_PTR)&Result, &Data ); 1662 } 1663 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1664 { 1665 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride); 1666 } 1667 _SEH2_END; 1668 } 1669 } 1670 else 1671 { 1672 AnsiMsg.hwnd = hWnd; 1673 AnsiMsg.message = Msg; 1674 AnsiMsg.wParam = wParam; 1675 AnsiMsg.lParam = lParam; 1676 AnsiMsg.time = 0; 1677 AnsiMsg.pt.x = 0; 1678 AnsiMsg.pt.y = 0; 1679 if (! MsgiAnsiToUnicodeMessage(hWnd, &UnicodeMsg, &AnsiMsg)) 1680 { 1681 goto Exit; 1682 } 1683 1684 if (Hook && (MsgOverride || DlgOverride)) 1685 { 1686 _SEH2_TRY 1687 { 1688 if (!DlgOverride) 1689 PreResult = guah.PreWndProc(UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam, (ULONG_PTR)&Result, &Data ); 1690 else 1691 PreResult = guah.PreDefDlgProc(UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam, (ULONG_PTR)&Result, &Data ); 1692 } 1693 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1694 { 1695 ERR("Got exception in hooked PreWndProc, dlg:%d!\n", DlgOverride); 1696 } 1697 _SEH2_END; 1698 } 1699 1700 if (PreResult) goto Exit; 1701 1702 if (!Dialog) 1703 Result = CALL_EXTERN_WNDPROC(WndProc, UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam); 1704 else 1705 { 1706 _SEH2_TRY 1707 { 1708 Result = CALL_EXTERN_WNDPROC(WndProc, UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam); 1709 } 1710 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1711 { 1712 ERR("Exception Dialog unicode %p Msg %d pti %p Wndpti %p\n",WndProc, Msg,GetW32ThreadInfo(),pWnd->head.pti); 1713 } 1714 _SEH2_END; 1715 } 1716 1717 if (Hook && (MsgOverride || DlgOverride)) 1718 { 1719 _SEH2_TRY 1720 { 1721 if (!DlgOverride) 1722 guah.PostWndProc(UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam, (ULONG_PTR)&Result, &Data ); 1723 else 1724 guah.PostDefDlgProc(UnicodeMsg.hwnd, UnicodeMsg.message, UnicodeMsg.wParam, UnicodeMsg.lParam, (ULONG_PTR)&Result, &Data ); 1725 } 1726 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1727 { 1728 ERR("Got exception in hooked PostWndProc, dlg:%d!\n", DlgOverride); 1729 } 1730 _SEH2_END; 1731 } 1732 1733 if (! MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result)) 1734 { 1735 goto Exit; 1736 } 1737 } 1738 1739 Exit: 1740 if (Hook) EndUserApiHook(); 1741 return Result; 1742 } 1743 1744 1745 static LRESULT WINAPI 1746 IntCallMessageProc(IN PWND Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN LPARAM lParam, IN BOOL Ansi) 1747 { 1748 WNDPROC WndProc; 1749 BOOL IsAnsi; 1750 PCLS Class; 1751 1752 Class = DesktopPtrToUser(Wnd->pcls); 1753 WndProc = NULL; 1754 1755 if ( Wnd->head.pti != GetW32ThreadInfo()) 1756 { // Must be inside the same thread! 1757 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 1758 return 0; 1759 } 1760 /* 1761 This is the message exchange for user32. If there's a need to monitor messages, 1762 do it here! 1763 */ 1764 TRACE("HWND %p, MSG %u, WPARAM %p, LPARAM %p, Ansi %d\n", hWnd, Msg, wParam, lParam, Ansi); 1765 // if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON ) 1766 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_FIRST ) 1767 { 1768 if (Ansi) 1769 { 1770 if (GETPFNCLIENTW(Class->fnid) == Wnd->lpfnWndProc) 1771 WndProc = GETPFNCLIENTA(Class->fnid); 1772 } 1773 else 1774 { 1775 if (GETPFNCLIENTA(Class->fnid) == Wnd->lpfnWndProc) 1776 WndProc = GETPFNCLIENTW(Class->fnid); 1777 } 1778 1779 IsAnsi = Ansi; 1780 1781 if (!WndProc) 1782 { 1783 IsAnsi = !Wnd->Unicode; 1784 WndProc = Wnd->lpfnWndProc; 1785 } 1786 } 1787 else 1788 { 1789 IsAnsi = !Wnd->Unicode; 1790 WndProc = Wnd->lpfnWndProc; 1791 } 1792 /* 1793 Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or 1794 the same. 1795 */ 1796 if (!Ansi) 1797 return IntCallWindowProcW(IsAnsi, WndProc, Wnd, hWnd, Msg, wParam, lParam); 1798 else 1799 return IntCallWindowProcA(IsAnsi, WndProc, Wnd, hWnd, Msg, wParam, lParam); 1800 } 1801 1802 1803 /* 1804 * @implemented 1805 */ 1806 LRESULT WINAPI 1807 CallWindowProcA(WNDPROC lpPrevWndFunc, 1808 HWND hWnd, 1809 UINT Msg, 1810 WPARAM wParam, 1811 LPARAM lParam) 1812 { 1813 PWND pWnd; 1814 PCALLPROCDATA CallProc; 1815 1816 if (lpPrevWndFunc == NULL) 1817 { 1818 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); 1819 return 0; 1820 } 1821 1822 pWnd = ValidateHwnd(hWnd); 1823 1824 if (!IsCallProcHandle(lpPrevWndFunc)) 1825 return IntCallWindowProcA(TRUE, lpPrevWndFunc, pWnd, hWnd, Msg, wParam, lParam); 1826 else 1827 { 1828 CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); 1829 if (CallProc != NULL) 1830 { 1831 return IntCallWindowProcA(!(CallProc->wType & UserGetCPDA2U), 1832 CallProc->pfnClientPrevious, 1833 pWnd, 1834 hWnd, 1835 Msg, 1836 wParam, 1837 lParam); 1838 } 1839 else 1840 { 1841 WARN("CallWindowProcA: can not dereference WndProcHandle\n"); 1842 return 0; 1843 } 1844 } 1845 } 1846 1847 1848 /* 1849 * @implemented 1850 */ 1851 LRESULT WINAPI 1852 CallWindowProcW(WNDPROC lpPrevWndFunc, 1853 HWND hWnd, 1854 UINT Msg, 1855 WPARAM wParam, 1856 LPARAM lParam) 1857 { 1858 PWND pWnd; 1859 PCALLPROCDATA CallProc; 1860 1861 /* FIXME - can the first parameter be NULL? */ 1862 if (lpPrevWndFunc == NULL) 1863 { 1864 WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); 1865 return 0; 1866 } 1867 1868 pWnd = ValidateHwnd(hWnd); 1869 1870 if (!IsCallProcHandle(lpPrevWndFunc)) 1871 return IntCallWindowProcW(FALSE, lpPrevWndFunc, pWnd, hWnd, Msg, wParam, lParam); 1872 else 1873 { 1874 CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); 1875 if (CallProc != NULL) 1876 { 1877 return IntCallWindowProcW(!(CallProc->wType & UserGetCPDA2U), 1878 CallProc->pfnClientPrevious, 1879 pWnd, 1880 hWnd, 1881 Msg, 1882 wParam, 1883 lParam); 1884 } 1885 else 1886 { 1887 WARN("CallWindowProcW: can not dereference WndProcHandle\n"); 1888 return 0; 1889 } 1890 } 1891 } 1892 1893 1894 /* 1895 * @implemented 1896 */ 1897 LRESULT 1898 WINAPI 1899 DECLSPEC_HOTPATCH 1900 DispatchMessageA(CONST MSG *lpmsg) 1901 { 1902 LRESULT Ret = 0; 1903 MSG UnicodeMsg; 1904 PWND Wnd; 1905 1906 if ( lpmsg->message & ~WM_MAXIMUM ) 1907 { 1908 SetLastError( ERROR_INVALID_PARAMETER ); 1909 return 0; 1910 } 1911 1912 if (lpmsg->hwnd != NULL) 1913 { 1914 Wnd = ValidateHwnd(lpmsg->hwnd); 1915 if (!Wnd) return 0; 1916 } 1917 else 1918 Wnd = NULL; 1919 1920 if (is_pointer_message(lpmsg->message)) 1921 { 1922 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 1923 return 0; 1924 } 1925 1926 if ((lpmsg->message == WM_TIMER || lpmsg->message == WM_SYSTIMER) && lpmsg->lParam != 0) 1927 { 1928 WNDPROC WndProc = (WNDPROC)lpmsg->lParam; 1929 1930 if ( lpmsg->message == WM_SYSTIMER ) 1931 return NtUserDispatchMessage( (PMSG)lpmsg ); 1932 1933 if (!NtUserValidateTimerCallback(lpmsg->lParam)) 1934 { 1935 WARN("Validating Timer Callback failed!\n"); 1936 return 0; 1937 } 1938 1939 _SEH2_TRY // wine does this. Hint: Prevents call to another thread.... 1940 { 1941 Ret = WndProc(lpmsg->hwnd, 1942 lpmsg->message, 1943 lpmsg->wParam, 1944 GetTickCount()); 1945 } 1946 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1947 { 1948 ERR("Exception in Timer Callback!\n"); 1949 } 1950 _SEH2_END; 1951 } 1952 else if (Wnd != NULL) 1953 { 1954 if ( (lpmsg->message != WM_PAINT) && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) 1955 { 1956 Ret = IntCallMessageProc(Wnd, 1957 lpmsg->hwnd, 1958 lpmsg->message, 1959 lpmsg->wParam, 1960 lpmsg->lParam, 1961 TRUE); 1962 } 1963 else 1964 { 1965 if (!MsgiAnsiToUnicodeMessage(lpmsg->hwnd, &UnicodeMsg, (LPMSG)lpmsg)) 1966 { 1967 return FALSE; 1968 } 1969 1970 Ret = NtUserDispatchMessage(&UnicodeMsg); 1971 1972 if (!MsgiAnsiToUnicodeReply(&UnicodeMsg, (LPMSG)lpmsg, &Ret)) 1973 { 1974 return FALSE; 1975 } 1976 } 1977 } 1978 1979 return Ret; 1980 } 1981 1982 1983 /* 1984 * @implemented 1985 */ 1986 LRESULT 1987 WINAPI 1988 DECLSPEC_HOTPATCH 1989 DispatchMessageW(CONST MSG *lpmsg) 1990 { 1991 LRESULT Ret = 0; 1992 PWND Wnd; 1993 BOOL Hit = FALSE; 1994 1995 if ( lpmsg->message & ~WM_MAXIMUM ) 1996 { 1997 SetLastError( ERROR_INVALID_PARAMETER ); 1998 return 0; 1999 } 2000 2001 if (lpmsg->hwnd != NULL) 2002 { 2003 Wnd = ValidateHwnd(lpmsg->hwnd); 2004 if (!Wnd) return 0; 2005 } 2006 else 2007 Wnd = NULL; 2008 2009 if (is_pointer_message(lpmsg->message)) 2010 { 2011 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 2012 return 0; 2013 } 2014 2015 if ((lpmsg->message == WM_TIMER || lpmsg->message == WM_SYSTIMER) && lpmsg->lParam != 0) 2016 { 2017 WNDPROC WndProc = (WNDPROC)lpmsg->lParam; 2018 2019 if ( lpmsg->message == WM_SYSTIMER ) 2020 return NtUserDispatchMessage( (PMSG) lpmsg ); 2021 2022 if (!NtUserValidateTimerCallback(lpmsg->lParam)) 2023 { 2024 WARN("Validating Timer Callback failed!\n"); 2025 return 0; 2026 } 2027 2028 _SEH2_TRY 2029 { 2030 Ret = WndProc(lpmsg->hwnd, 2031 lpmsg->message, 2032 lpmsg->wParam, 2033 GetTickCount()); 2034 } 2035 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2036 { 2037 Hit = TRUE; 2038 } 2039 _SEH2_END; 2040 } 2041 else if (Wnd != NULL) 2042 { 2043 if ( (lpmsg->message != WM_PAINT) && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) 2044 { 2045 Ret = IntCallMessageProc(Wnd, 2046 lpmsg->hwnd, 2047 lpmsg->message, 2048 lpmsg->wParam, 2049 lpmsg->lParam, 2050 FALSE); 2051 } 2052 else 2053 Ret = NtUserDispatchMessage( (PMSG) lpmsg ); 2054 } 2055 2056 if (Hit) 2057 { 2058 WARN("Exception in Timer Callback WndProcW!\n"); 2059 } 2060 return Ret; 2061 } 2062 2063 static VOID 2064 IntConvertMsgToAnsi(LPMSG lpMsg) 2065 { 2066 CHAR ch[2]; 2067 WCHAR wch[2]; 2068 2069 switch (lpMsg->message) 2070 { 2071 case WM_CHAR: 2072 case WM_DEADCHAR: 2073 case WM_SYSCHAR: 2074 case WM_SYSDEADCHAR: 2075 case WM_MENUCHAR: 2076 wch[0] = LOWORD(lpMsg->wParam); 2077 wch[1] = HIWORD(lpMsg->wParam); 2078 ch[0] = ch[1] = 0; 2079 WideCharToMultiByte(CP_THREAD_ACP, 0, wch, 2, ch, 2, NULL, NULL); 2080 lpMsg->wParam = MAKEWPARAM(ch[0] | (ch[1] << 8), 0); 2081 break; 2082 } 2083 } 2084 2085 /* 2086 * @implemented 2087 */ 2088 BOOL 2089 WINAPI 2090 DECLSPEC_HOTPATCH 2091 GetMessageA(LPMSG lpMsg, 2092 HWND hWnd, 2093 UINT wMsgFilterMin, 2094 UINT wMsgFilterMax) 2095 { 2096 BOOL Res; 2097 2098 if ( (wMsgFilterMin|wMsgFilterMax) & ~WM_MAXIMUM ) 2099 { 2100 SetLastError( ERROR_INVALID_PARAMETER ); 2101 return FALSE; 2102 } 2103 2104 Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); 2105 if (-1 == (int) Res) 2106 { 2107 return Res; 2108 } 2109 2110 IntConvertMsgToAnsi(lpMsg); 2111 2112 return Res; 2113 } 2114 2115 /* 2116 * @implemented 2117 */ 2118 BOOL 2119 WINAPI 2120 DECLSPEC_HOTPATCH 2121 GetMessageW(LPMSG lpMsg, 2122 HWND hWnd, 2123 UINT wMsgFilterMin, 2124 UINT wMsgFilterMax) 2125 { 2126 BOOL Res; 2127 2128 if ( (wMsgFilterMin|wMsgFilterMax) & ~WM_MAXIMUM ) 2129 { 2130 SetLastError( ERROR_INVALID_PARAMETER ); 2131 return FALSE; 2132 } 2133 2134 Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); 2135 if (-1 == (int) Res) 2136 { 2137 return Res; 2138 } 2139 2140 return Res; 2141 } 2142 2143 BOOL WINAPI 2144 PeekMessageWorker( PMSG pMsg, 2145 HWND hWnd, 2146 UINT wMsgFilterMin, 2147 UINT wMsgFilterMax, 2148 UINT wRemoveMsg) 2149 { 2150 PCLIENTINFO pci; 2151 PCLIENTTHREADINFO pcti; 2152 pci = GetWin32ClientInfo(); 2153 pcti = pci->pClientThreadInfo; 2154 2155 if (!hWnd && pci && pcti) 2156 { 2157 pci->cSpins++; 2158 2159 if ((pci->cSpins >= 100) && (pci->dwTIFlags & TIF_SPINNING)) 2160 { // Yield after 100 spin cycles and ready to swap vinyl. 2161 if (!(pci->dwTIFlags & TIF_WAITFORINPUTIDLE)) 2162 { // Not waiting for idle event. 2163 if (!pcti->fsChangeBits && !pcti->fsWakeBits) 2164 { // No messages are available. 2165 if ((GetTickCount() - pcti->timeLastRead) > 1000) 2166 { // Up the msg read count if over 1 sec. 2167 NtUserGetThreadState(THREADSTATE_UPTIMELASTREAD); 2168 } 2169 pci->cSpins = 0; 2170 ZwYieldExecution(); 2171 FIXME("seeSpins!\n"); 2172 return FALSE; 2173 } 2174 } 2175 } 2176 } 2177 return NtUserPeekMessage(pMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 2178 } 2179 2180 /* 2181 * @implemented 2182 */ 2183 BOOL 2184 WINAPI 2185 DECLSPEC_HOTPATCH 2186 PeekMessageA(LPMSG lpMsg, 2187 HWND hWnd, 2188 UINT wMsgFilterMin, 2189 UINT wMsgFilterMax, 2190 UINT wRemoveMsg) 2191 { 2192 BOOL Res; 2193 2194 Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 2195 if (-1 == (int) Res || !Res) 2196 { 2197 return FALSE; 2198 } 2199 2200 IntConvertMsgToAnsi(lpMsg); 2201 2202 return Res; 2203 } 2204 2205 2206 /* 2207 * @implemented 2208 */ 2209 BOOL 2210 WINAPI 2211 DECLSPEC_HOTPATCH 2212 PeekMessageW( 2213 LPMSG lpMsg, 2214 HWND hWnd, 2215 UINT wMsgFilterMin, 2216 UINT wMsgFilterMax, 2217 UINT wRemoveMsg) 2218 { 2219 BOOL Res; 2220 2221 Res = PeekMessageWorker(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 2222 if (-1 == (int) Res || !Res) 2223 { 2224 return FALSE; 2225 } 2226 2227 return Res; 2228 } 2229 2230 /* 2231 * @implemented 2232 */ 2233 BOOL 2234 WINAPI 2235 PostMessageA( 2236 HWND hWnd, 2237 UINT Msg, 2238 WPARAM wParam, 2239 LPARAM lParam) 2240 { 2241 LRESULT Ret; 2242 2243 /* Check for combo box or a list box to send names. */ 2244 if (Msg == CB_DIR || Msg == LB_DIR) 2245 { 2246 /* 2247 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the 2248 combo/list box. Forces a call like DlgDirListComboBox. 2249 */ 2250 //wParam |= DDL_POSTMSGS; 2251 return NtUserPostMessage(hWnd, Msg, wParam, lParam); 2252 } 2253 2254 /* No drop files or current Process, just post message. */ 2255 if ( (Msg != WM_DROPFILES) || 2256 ( NtUserQueryWindow( hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) == 2257 PtrToUint(NtCurrentTeb()->ClientId.UniqueProcess) ) ) 2258 { 2259 return NtUserPostMessage(hWnd, Msg, wParam, lParam); 2260 } 2261 2262 /* We have drop files and this is not the same process for this window. */ 2263 2264 /* Just incase, check wParam for Global memory handle and send size. */ 2265 Ret = SendMessageA( hWnd, 2266 WM_COPYGLOBALDATA, 2267 (WPARAM)GlobalSize((HGLOBAL)wParam), // Zero if not a handle. 2268 (LPARAM)wParam); // Send wParam as lParam. 2269 2270 if ( Ret ) return NtUserPostMessage(hWnd, Msg, (WPARAM)Ret, lParam); 2271 2272 return FALSE; 2273 } 2274 2275 /* 2276 * @implemented 2277 */ 2278 BOOL 2279 WINAPI 2280 PostMessageW( 2281 HWND hWnd, 2282 UINT Msg, 2283 WPARAM wParam, 2284 LPARAM lParam) 2285 { 2286 LRESULT Ret; 2287 2288 /* Check for combo box or a list box to send names. */ 2289 if (Msg == CB_DIR || Msg == LB_DIR) 2290 { 2291 /* 2292 Set DDL_POSTMSGS, so use the PostMessage function to send messages to the 2293 combo/list box. Forces a call like DlgDirListComboBox. 2294 */ 2295 //wParam |= DDL_POSTMSGS; 2296 return NtUserPostMessage(hWnd, Msg, wParam, lParam); 2297 } 2298 2299 /* No drop files or current Process, just post message. */ 2300 if ( (Msg != WM_DROPFILES) || 2301 ( NtUserQueryWindow( hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) == 2302 PtrToUint(NtCurrentTeb()->ClientId.UniqueProcess) ) ) 2303 { 2304 return NtUserPostMessage(hWnd, Msg, wParam, lParam); 2305 } 2306 2307 /* We have drop files and this is not the same process for this window. */ 2308 2309 /* Just incase, check wParam for Global memory handle and send size. */ 2310 Ret = SendMessageW( hWnd, 2311 WM_COPYGLOBALDATA, 2312 (WPARAM)GlobalSize((HGLOBAL)wParam), // Zero if not a handle. 2313 (LPARAM)wParam); // Send wParam as lParam. 2314 2315 if ( Ret ) return NtUserPostMessage(hWnd, Msg, (WPARAM)Ret, lParam); 2316 2317 return FALSE; 2318 } 2319 2320 /* 2321 * @implemented 2322 */ 2323 VOID 2324 WINAPI 2325 PostQuitMessage( 2326 int nExitCode) 2327 { 2328 NtUserxPostQuitMessage(nExitCode); 2329 } 2330 2331 2332 /* 2333 * @implemented 2334 */ 2335 BOOL 2336 WINAPI 2337 PostThreadMessageA( 2338 DWORD idThread, 2339 UINT Msg, 2340 WPARAM wParam, 2341 LPARAM lParam) 2342 { 2343 return NtUserPostThreadMessage(idThread, Msg, wParam, lParam); 2344 } 2345 2346 2347 /* 2348 * @implemented 2349 */ 2350 BOOL 2351 WINAPI 2352 PostThreadMessageW( 2353 DWORD idThread, 2354 UINT Msg, 2355 WPARAM wParam, 2356 LPARAM lParam) 2357 { 2358 return NtUserPostThreadMessage(idThread, Msg, wParam, lParam); 2359 } 2360 2361 2362 /* 2363 * @implemented 2364 */ 2365 LRESULT WINAPI 2366 SendMessageW(HWND Wnd, 2367 UINT Msg, 2368 WPARAM wParam, 2369 LPARAM lParam) 2370 { 2371 MSG UMMsg, KMMsg; 2372 LRESULT Result; 2373 BOOL Ret; 2374 PWND Window; 2375 PTHREADINFO ti = GetW32ThreadInfo(); 2376 2377 if ( Msg & ~WM_MAXIMUM ) 2378 { 2379 SetLastError( ERROR_INVALID_PARAMETER ); 2380 return 0; 2381 } 2382 2383 if (Wnd != HWND_TOPMOST && Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST)) 2384 { 2385 Window = ValidateHwnd(Wnd); 2386 2387 if ( Window != NULL && 2388 Window->head.pti == ti && 2389 !ISITHOOKED(WH_CALLWNDPROC) && 2390 !ISITHOOKED(WH_CALLWNDPROCRET) && 2391 !(Window->state & WNDS_SERVERSIDEWINDOWPROC) ) 2392 { 2393 /* NOTE: We can directly send messages to the window procedure 2394 if *all* the following conditions are met: 2395 2396 * Window belongs to calling thread 2397 * The calling thread is not being hooked for CallWndProc 2398 * Not calling a server side proc: 2399 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage 2400 */ 2401 2402 return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE); 2403 } 2404 } 2405 2406 UMMsg.hwnd = Wnd; 2407 UMMsg.message = Msg; 2408 UMMsg.wParam = wParam; 2409 UMMsg.lParam = lParam; 2410 UMMsg.time = 0; 2411 UMMsg.pt.x = 0; 2412 UMMsg.pt.y = 0; 2413 2414 if (! MsgiUMToKMMessage(&UMMsg, &KMMsg, FALSE)) 2415 { 2416 return FALSE; 2417 } 2418 2419 Ret = NtUserMessageCall( Wnd, 2420 KMMsg.message, 2421 KMMsg.wParam, 2422 KMMsg.lParam, 2423 (ULONG_PTR)&Result, 2424 FNID_SENDMESSAGE, 2425 FALSE); 2426 if (!Ret) 2427 { 2428 ERR("SendMessageW Error\n"); 2429 } 2430 2431 MsgiUMToKMCleanup(&UMMsg, &KMMsg); 2432 2433 return Result; 2434 } 2435 2436 2437 /* 2438 * @implemented 2439 */ 2440 LRESULT WINAPI 2441 SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) 2442 { 2443 MSG AnsiMsg, UcMsg, KMMsg; 2444 LRESULT Result; 2445 BOOL Ret; 2446 PWND Window; 2447 PTHREADINFO ti = GetW32ThreadInfo(); 2448 2449 if ( Msg & ~WM_MAXIMUM ) 2450 { 2451 SetLastError( ERROR_INVALID_PARAMETER ); 2452 return 0; 2453 } 2454 2455 if (Wnd != HWND_TOPMOST && Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST)) 2456 { 2457 Window = ValidateHwnd(Wnd); 2458 2459 if ( Window != NULL && 2460 Window->head.pti == ti && 2461 !ISITHOOKED(WH_CALLWNDPROC) && 2462 !ISITHOOKED(WH_CALLWNDPROCRET) && 2463 !(Window->state & WNDS_SERVERSIDEWINDOWPROC) ) 2464 { 2465 /* NOTE: We can directly send messages to the window procedure 2466 if *all* the following conditions are met: 2467 2468 * Window belongs to calling thread 2469 * The calling thread is not being hooked for CallWndProc 2470 * Not calling a server side proc: 2471 Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage 2472 */ 2473 2474 return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE); 2475 } 2476 } 2477 2478 AnsiMsg.hwnd = Wnd; 2479 AnsiMsg.message = Msg; 2480 AnsiMsg.wParam = wParam; 2481 AnsiMsg.lParam = lParam; 2482 AnsiMsg.time = 0; 2483 AnsiMsg.pt.x = 0; 2484 AnsiMsg.pt.y = 0; 2485 2486 if (!MsgiAnsiToUnicodeMessage(Wnd, &UcMsg, &AnsiMsg)) 2487 { 2488 return FALSE; 2489 } 2490 2491 if (!MsgiUMToKMMessage(&UcMsg, &KMMsg, FALSE)) 2492 { 2493 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); 2494 return FALSE; 2495 } 2496 2497 Ret = NtUserMessageCall( Wnd, 2498 KMMsg.message, 2499 KMMsg.wParam, 2500 KMMsg.lParam, 2501 (ULONG_PTR)&Result, 2502 FNID_SENDMESSAGE, 2503 TRUE); 2504 if (!Ret) 2505 { 2506 ERR("SendMessageA Error\n"); 2507 } 2508 2509 MsgiUMToKMCleanup(&UcMsg, &KMMsg); 2510 MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result); 2511 2512 return Result; 2513 } 2514 2515 /* 2516 * @implemented 2517 */ 2518 BOOL 2519 WINAPI 2520 SendMessageCallbackA( 2521 HWND hWnd, 2522 UINT Msg, 2523 WPARAM wParam, 2524 LPARAM lParam, 2525 SENDASYNCPROC lpCallBack, 2526 ULONG_PTR dwData) 2527 { 2528 BOOL Result; 2529 MSG AnsiMsg, UcMsg; 2530 CALL_BACK_INFO CallBackInfo; 2531 2532 if (is_pointer_message(Msg)) 2533 { 2534 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 2535 return FALSE; 2536 } 2537 2538 CallBackInfo.CallBack = lpCallBack; 2539 CallBackInfo.Context = dwData; 2540 2541 AnsiMsg.hwnd = hWnd; 2542 AnsiMsg.message = Msg; 2543 AnsiMsg.wParam = wParam; 2544 AnsiMsg.lParam = lParam; 2545 AnsiMsg.time = 0; 2546 AnsiMsg.pt.x = 0; 2547 AnsiMsg.pt.y = 0; 2548 2549 if (!MsgiAnsiToUnicodeMessage(hWnd, &UcMsg, &AnsiMsg)) 2550 { 2551 return FALSE; 2552 } 2553 2554 Result = NtUserMessageCall( hWnd, 2555 UcMsg.message, 2556 UcMsg.wParam, 2557 UcMsg.lParam, 2558 (ULONG_PTR)&CallBackInfo, 2559 FNID_SENDMESSAGECALLBACK, 2560 TRUE); 2561 2562 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); 2563 2564 return Result; 2565 } 2566 2567 /* 2568 * @implemented 2569 */ 2570 BOOL 2571 WINAPI 2572 SendMessageCallbackW( 2573 HWND hWnd, 2574 UINT Msg, 2575 WPARAM wParam, 2576 LPARAM lParam, 2577 SENDASYNCPROC lpCallBack, 2578 ULONG_PTR dwData) 2579 { 2580 CALL_BACK_INFO CallBackInfo; 2581 2582 if (is_pointer_message(Msg)) 2583 { 2584 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 2585 return FALSE; 2586 } 2587 2588 CallBackInfo.CallBack = lpCallBack; 2589 CallBackInfo.Context = dwData; 2590 2591 return NtUserMessageCall(hWnd, 2592 Msg, 2593 wParam, 2594 lParam, 2595 (ULONG_PTR)&CallBackInfo, 2596 FNID_SENDMESSAGECALLBACK, 2597 FALSE); 2598 } 2599 2600 /* 2601 * @implemented 2602 */ 2603 LRESULT 2604 WINAPI 2605 SendMessageTimeoutA( 2606 HWND hWnd, 2607 UINT Msg, 2608 WPARAM wParam, 2609 LPARAM lParam, 2610 UINT fuFlags, 2611 UINT uTimeout, 2612 PDWORD_PTR lpdwResult) 2613 { 2614 MSG AnsiMsg, UcMsg, KMMsg; 2615 LRESULT Result; 2616 DOSENDMESSAGE dsm; 2617 2618 if ( Msg & ~WM_MAXIMUM || fuFlags & ~(SMTO_NOTIMEOUTIFNOTHUNG|SMTO_ABORTIFHUNG|SMTO_BLOCK)) 2619 { 2620 SetLastError( ERROR_INVALID_PARAMETER ); 2621 return 0; 2622 } 2623 2624 if (lpdwResult) *lpdwResult = 0; 2625 2626 SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam); 2627 2628 dsm.uFlags = fuFlags; 2629 dsm.uTimeout = uTimeout; 2630 dsm.Result = 0; 2631 2632 AnsiMsg.hwnd = hWnd; 2633 AnsiMsg.message = Msg; 2634 AnsiMsg.wParam = wParam; 2635 AnsiMsg.lParam = lParam; 2636 AnsiMsg.time = 0; 2637 AnsiMsg.pt.x = 0; 2638 AnsiMsg.pt.y = 0; 2639 2640 if (! MsgiAnsiToUnicodeMessage(hWnd, &UcMsg, &AnsiMsg)) 2641 { 2642 return FALSE; 2643 } 2644 2645 if (!MsgiUMToKMMessage(&UcMsg, &KMMsg, FALSE)) 2646 { 2647 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); 2648 return FALSE; 2649 } 2650 2651 Result = NtUserMessageCall( hWnd, 2652 KMMsg.message, 2653 KMMsg.wParam, 2654 KMMsg.lParam, 2655 (ULONG_PTR)&dsm, 2656 FNID_SENDMESSAGEWTOOPTION, 2657 TRUE); 2658 2659 MsgiUMToKMCleanup(&UcMsg, &KMMsg); 2660 MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result); 2661 2662 if (lpdwResult) *lpdwResult = dsm.Result; 2663 2664 SPY_ExitMessage(SPY_RESULT_OK, hWnd, Msg, Result, wParam, lParam); 2665 2666 return Result; 2667 } 2668 2669 2670 /* 2671 * @implemented 2672 */ 2673 LRESULT 2674 WINAPI 2675 SendMessageTimeoutW( 2676 HWND hWnd, 2677 UINT Msg, 2678 WPARAM wParam, 2679 LPARAM lParam, 2680 UINT fuFlags, 2681 UINT uTimeout, 2682 PDWORD_PTR lpdwResult) 2683 { 2684 LRESULT Result; 2685 DOSENDMESSAGE dsm; 2686 MSG UMMsg, KMMsg; 2687 2688 if ( Msg & ~WM_MAXIMUM || fuFlags & ~(SMTO_NOTIMEOUTIFNOTHUNG|SMTO_ABORTIFHUNG|SMTO_BLOCK)) 2689 { 2690 SetLastError( ERROR_INVALID_PARAMETER ); 2691 return 0; 2692 } 2693 2694 if (lpdwResult) *lpdwResult = 0; 2695 2696 SPY_EnterMessage(SPY_SENDMESSAGE, hWnd, Msg, wParam, lParam); 2697 2698 dsm.uFlags = fuFlags; 2699 dsm.uTimeout = uTimeout; 2700 dsm.Result = 0; 2701 2702 UMMsg.hwnd = hWnd; 2703 UMMsg.message = Msg; 2704 UMMsg.wParam = wParam; 2705 UMMsg.lParam = lParam; 2706 UMMsg.time = 0; 2707 UMMsg.pt.x = 0; 2708 UMMsg.pt.y = 0; 2709 if (! MsgiUMToKMMessage(&UMMsg, &KMMsg, TRUE)) 2710 { 2711 return FALSE; 2712 } 2713 2714 Result = NtUserMessageCall( hWnd, 2715 KMMsg.message, 2716 KMMsg.wParam, 2717 KMMsg.lParam, 2718 (ULONG_PTR)&dsm, 2719 FNID_SENDMESSAGEWTOOPTION, 2720 FALSE); 2721 2722 MsgiUMToKMCleanup(&UMMsg, &KMMsg); 2723 2724 if (lpdwResult) *lpdwResult = dsm.Result; 2725 2726 SPY_ExitMessage(SPY_RESULT_OK, hWnd, Msg, Result, wParam, lParam); 2727 2728 return Result; 2729 } 2730 2731 /* 2732 * @implemented 2733 */ 2734 BOOL 2735 WINAPI 2736 SendNotifyMessageA( 2737 HWND hWnd, 2738 UINT Msg, 2739 WPARAM wParam, 2740 LPARAM lParam) 2741 { 2742 BOOL Ret; 2743 MSG AnsiMsg, UcMsg; 2744 2745 if (is_pointer_message(Msg)) 2746 { 2747 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 2748 return FALSE; 2749 } 2750 2751 AnsiMsg.hwnd = hWnd; 2752 AnsiMsg.message = Msg; 2753 AnsiMsg.wParam = wParam; 2754 AnsiMsg.lParam = lParam; 2755 AnsiMsg.time = 0; 2756 AnsiMsg.pt.x = 0; 2757 AnsiMsg.pt.y = 0; 2758 if (! MsgiAnsiToUnicodeMessage(hWnd, &UcMsg, &AnsiMsg)) 2759 { 2760 return FALSE; 2761 } 2762 Ret = SendNotifyMessageW(hWnd, UcMsg.message, UcMsg.wParam, UcMsg.lParam); 2763 2764 MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); 2765 2766 return Ret; 2767 } 2768 2769 /* 2770 * @implemented 2771 */ 2772 BOOL 2773 WINAPI 2774 SendNotifyMessageW( 2775 HWND hWnd, 2776 UINT Msg, 2777 WPARAM wParam, 2778 LPARAM lParam) 2779 { 2780 LRESULT Result; 2781 2782 if (is_pointer_message(Msg)) 2783 { 2784 SetLastError( ERROR_MESSAGE_SYNC_ONLY ); 2785 return FALSE; 2786 } 2787 2788 Result = NtUserMessageCall( hWnd, 2789 Msg, 2790 wParam, 2791 lParam, 2792 0, 2793 FNID_SENDNOTIFYMESSAGE, 2794 FALSE); 2795 2796 return Result; 2797 } 2798 2799 /* 2800 * @implemented 2801 */ 2802 BOOL WINAPI 2803 TranslateMessageEx(CONST MSG *lpMsg, UINT Flags) 2804 { 2805 switch (lpMsg->message) 2806 { 2807 case WM_KEYDOWN: 2808 case WM_KEYUP: 2809 case WM_SYSKEYDOWN: 2810 case WM_SYSKEYUP: 2811 return(NtUserTranslateMessage((LPMSG)lpMsg, Flags)); 2812 2813 default: 2814 if ( lpMsg->message & ~WM_MAXIMUM ) 2815 SetLastError(ERROR_INVALID_PARAMETER); 2816 return FALSE; 2817 } 2818 } 2819 2820 2821 /* 2822 * @implemented 2823 */ 2824 BOOL WINAPI 2825 TranslateMessage(CONST MSG *lpMsg) 2826 { 2827 BOOL Ret = FALSE; 2828 2829 // Ref: msdn ImmGetVirtualKey: 2830 // http://msdn.microsoft.com/en-us/library/aa912145.aspx 2831 /* 2832 if ( (LOWORD(lpMsg->wParam) != VK_PROCESSKEY) || 2833 !(Ret = IMM_ImmTranslateMessage( lpMsg->hwnd, 2834 lpMsg->message, 2835 lpMsg->wParam, 2836 lpMsg->lParam)) )*/ 2837 { 2838 Ret = TranslateMessageEx((LPMSG)lpMsg, 0); 2839 } 2840 return Ret; 2841 } 2842 2843 2844 /* 2845 * @implemented 2846 */ 2847 UINT WINAPI 2848 RegisterWindowMessageA(LPCSTR lpString) 2849 { 2850 UNICODE_STRING String; 2851 UINT Atom; 2852 2853 if (!RtlCreateUnicodeStringFromAsciiz(&String, (PCSZ)lpString)) 2854 { 2855 return(0); 2856 } 2857 Atom = NtUserRegisterWindowMessage(&String); 2858 RtlFreeUnicodeString(&String); 2859 return(Atom); 2860 } 2861 2862 2863 /* 2864 * @implemented 2865 */ 2866 UINT WINAPI 2867 RegisterWindowMessageW(LPCWSTR lpString) 2868 { 2869 UNICODE_STRING String; 2870 2871 RtlInitUnicodeString(&String, lpString); 2872 return(NtUserRegisterWindowMessage(&String)); 2873 } 2874 2875 /* 2876 * @implemented 2877 */ 2878 HWND WINAPI 2879 GetCapture(VOID) 2880 { 2881 return (HWND)NtUserGetThreadState(THREADSTATE_CAPTUREWINDOW); 2882 } 2883 2884 /* 2885 * @implemented 2886 */ 2887 BOOL WINAPI 2888 ReleaseCapture(VOID) 2889 { 2890 return NtUserxReleaseCapture(); 2891 } 2892 2893 2894 /* 2895 * @implemented 2896 */ 2897 DWORD 2898 WINAPI 2899 RealGetQueueStatus(UINT flags) 2900 { 2901 #define QS_TEMPALLINPUT 255 // ATM, do not support QS_RAWINPUT 2902 if (flags & ~(QS_SMRESULT|QS_ALLPOSTMESSAGE|QS_TEMPALLINPUT)) 2903 { 2904 SetLastError( ERROR_INVALID_FLAGS ); 2905 return 0; 2906 } 2907 return NtUserxGetQueueStatus(flags); 2908 } 2909 2910 2911 /* 2912 * @implemented 2913 */ 2914 BOOL WINAPI GetInputState(VOID) 2915 { 2916 PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; 2917 2918 if ((!pcti) || (pcti->fsChangeBits & (QS_KEY|QS_MOUSEBUTTON))) 2919 return (BOOL)NtUserGetThreadState(THREADSTATE_GETINPUTSTATE); 2920 2921 return FALSE; 2922 } 2923 2924 2925 NTSTATUS WINAPI 2926 User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) 2927 { 2928 PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs; 2929 MSG KMMsg, UMMsg; 2930 PWND pWnd = NULL; 2931 PCLIENTINFO pci = GetWin32ClientInfo(); 2932 2933 /* Make sure we don't try to access mem beyond what we were given */ 2934 if (ArgumentLength < sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) 2935 { 2936 return STATUS_INFO_LENGTH_MISMATCH; 2937 } 2938 2939 CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS) Arguments; 2940 KMMsg.hwnd = CallbackArgs->Wnd; 2941 KMMsg.message = CallbackArgs->Msg; 2942 KMMsg.wParam = CallbackArgs->wParam; 2943 KMMsg.time = 0; 2944 KMMsg.pt.x = 0; 2945 KMMsg.pt.y = 0; 2946 /* Check if lParam is really a pointer and adjust it if it is */ 2947 if (0 <= CallbackArgs->lParamBufferSize) 2948 { 2949 if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) 2950 + CallbackArgs->lParamBufferSize) 2951 { 2952 return STATUS_INFO_LENGTH_MISMATCH; 2953 } 2954 KMMsg.lParam = (LPARAM) ((char *) CallbackArgs + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)); 2955 switch(KMMsg.message) 2956 { 2957 case WM_CREATE: 2958 { 2959 TRACE("WM_CREATE CB %p lParam %p\n",CallbackArgs, KMMsg.lParam); 2960 break; 2961 } 2962 case WM_NCCREATE: 2963 { 2964 TRACE("WM_NCCREATE CB %p lParam %p\n",CallbackArgs, KMMsg.lParam); 2965 break; 2966 } 2967 case WM_SYSTIMER: 2968 { 2969 TRACE("WM_SYSTIMER %p\n",KMMsg.hwnd); 2970 break; 2971 } 2972 case WM_SIZING: 2973 { 2974 PRECT prect = (PRECT) KMMsg.lParam; 2975 TRACE("WM_SIZING 1 t %d l %d r %d b %d\n",prect->top,prect->left,prect->right,prect->bottom); 2976 break; 2977 } 2978 default: 2979 break; 2980 } 2981 } 2982 else 2983 { 2984 if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) 2985 { 2986 return STATUS_INFO_LENGTH_MISMATCH; 2987 } 2988 KMMsg.lParam = CallbackArgs->lParam; 2989 } 2990 2991 if (WM_NCCALCSIZE == CallbackArgs->Msg && CallbackArgs->wParam) 2992 { 2993 NCCALCSIZE_PARAMS *Params = (NCCALCSIZE_PARAMS *) KMMsg.lParam; 2994 Params->lppos = (PWINDOWPOS) (Params + 1); 2995 } 2996 2997 if (! MsgiKMToUMMessage(&KMMsg, &UMMsg)) 2998 { 2999 } 3000 3001 if (pci->CallbackWnd.hWnd == UMMsg.hwnd) 3002 pWnd = pci->CallbackWnd.pWnd; 3003 3004 CallbackArgs->Result = IntCallWindowProcW( CallbackArgs->IsAnsiProc, 3005 CallbackArgs->Proc, 3006 pWnd, 3007 UMMsg.hwnd, 3008 UMMsg.message, 3009 UMMsg.wParam, 3010 UMMsg.lParam); 3011 3012 if (! MsgiKMToUMReply(&KMMsg, &UMMsg, &CallbackArgs->Result)) 3013 { 3014 } 3015 3016 if (0 <= CallbackArgs->lParamBufferSize) 3017 { 3018 switch(KMMsg.message) 3019 { 3020 case WM_SIZING: 3021 { 3022 PRECT prect = (PRECT) KMMsg.lParam; 3023 TRACE("WM_SIZING 2 t %d l %d r %d b %d\n",prect->top,prect->left,prect->right,prect->bottom); 3024 break; 3025 } 3026 default: 3027 break; 3028 } 3029 } 3030 return ZwCallbackReturn(CallbackArgs, ArgumentLength, STATUS_SUCCESS); 3031 } 3032 3033 /* 3034 * @implemented 3035 */ 3036 BOOL WINAPI SetMessageQueue(int cMessagesMax) 3037 { 3038 /* Function does nothing on 32 bit windows */ 3039 return TRUE; 3040 } 3041 typedef DWORD (WINAPI * RealGetQueueStatusProc)(UINT flags); 3042 typedef DWORD (WINAPI * RealMsgWaitForMultipleObjectsExProc)(DWORD nCount, CONST HANDLE *lpHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags); 3043 typedef BOOL (WINAPI * RealInternalGetMessageProc)(LPMSG,HWND,UINT,UINT,UINT,BOOL); 3044 typedef BOOL (WINAPI * RealWaitMessageExProc)(DWORD,UINT); 3045 3046 typedef struct _USER_MESSAGE_PUMP_ADDRESSES { 3047 DWORD cbSize; 3048 RealInternalGetMessageProc NtUserRealInternalGetMessage; 3049 RealWaitMessageExProc NtUserRealWaitMessageEx; 3050 RealGetQueueStatusProc RealGetQueueStatus; 3051 RealMsgWaitForMultipleObjectsExProc RealMsgWaitForMultipleObjectsEx; 3052 } USER_MESSAGE_PUMP_ADDRESSES, * PUSER_MESSAGE_PUMP_ADDRESSES; 3053 3054 DWORD 3055 WINAPI 3056 RealMsgWaitForMultipleObjectsEx( 3057 DWORD nCount, 3058 CONST HANDLE *pHandles, 3059 DWORD dwMilliseconds, 3060 DWORD dwWakeMask, 3061 DWORD dwFlags); 3062 3063 typedef BOOL (WINAPI * MESSAGEPUMPHOOKPROC)(BOOL Unregistering,PUSER_MESSAGE_PUMP_ADDRESSES MessagePumpAddresses); 3064 3065 CRITICAL_SECTION gcsMPH; 3066 MESSAGEPUMPHOOKPROC gpfnInitMPH; 3067 DWORD gcLoadMPH = 0; 3068 USER_MESSAGE_PUMP_ADDRESSES gmph = {sizeof(USER_MESSAGE_PUMP_ADDRESSES), 3069 NtUserRealInternalGetMessage, 3070 NtUserRealWaitMessageEx, 3071 RealGetQueueStatus, 3072 RealMsgWaitForMultipleObjectsEx 3073 }; 3074 3075 DWORD gfMessagePumpHook = 0; 3076 3077 BOOL WINAPI IsInsideMessagePumpHook() 3078 { // FF uses this and polls it when Min/Max 3079 PCLIENTTHREADINFO pcti = GetWin32ClientInfo()->pClientThreadInfo; 3080 return (gfMessagePumpHook && pcti && (pcti->dwcPumpHook > 0)); 3081 } 3082 3083 void WINAPI ResetMessagePumpHook(PUSER_MESSAGE_PUMP_ADDRESSES Addresses) 3084 { 3085 Addresses->cbSize = sizeof(USER_MESSAGE_PUMP_ADDRESSES); 3086 Addresses->NtUserRealInternalGetMessage = NtUserRealInternalGetMessage; 3087 Addresses->NtUserRealWaitMessageEx = NtUserRealWaitMessageEx; 3088 Addresses->RealGetQueueStatus = RealGetQueueStatus; 3089 Addresses->RealMsgWaitForMultipleObjectsEx = RealMsgWaitForMultipleObjectsEx; 3090 } 3091 3092 BOOL WINAPI RegisterMessagePumpHook(MESSAGEPUMPHOOKPROC Hook) 3093 { 3094 EnterCriticalSection(&gcsMPH); 3095 if(!Hook) { 3096 SetLastError(ERROR_INVALID_PARAMETER); 3097 LeaveCriticalSection(&gcsMPH); 3098 return FALSE; 3099 } 3100 if(!gcLoadMPH) { 3101 USER_MESSAGE_PUMP_ADDRESSES Addresses; 3102 gpfnInitMPH = Hook; 3103 ResetMessagePumpHook(&Addresses); 3104 if(!Hook(FALSE, &Addresses) || !Addresses.cbSize) { 3105 LeaveCriticalSection(&gcsMPH); 3106 return FALSE; 3107 } 3108 memcpy(&gmph, &Addresses, Addresses.cbSize); 3109 } else { 3110 if(gpfnInitMPH != Hook) { 3111 LeaveCriticalSection(&gcsMPH); 3112 return FALSE; 3113 } 3114 } 3115 if(NtUserxInitMessagePump()) { 3116 LeaveCriticalSection(&gcsMPH); 3117 return FALSE; 3118 } 3119 if (!gcLoadMPH++) { 3120 InterlockedExchange((PLONG)&gfMessagePumpHook, 1); 3121 } 3122 LeaveCriticalSection(&gcsMPH); 3123 return TRUE; 3124 } 3125 3126 BOOL WINAPI UnregisterMessagePumpHook(VOID) 3127 { 3128 EnterCriticalSection(&gcsMPH); 3129 if(gcLoadMPH > 0) { 3130 if(NtUserxUnInitMessagePump()) { 3131 gcLoadMPH--; 3132 if(!gcLoadMPH) { 3133 InterlockedExchange((PLONG)&gfMessagePumpHook, 0); 3134 gpfnInitMPH(TRUE, NULL); 3135 ResetMessagePumpHook(&gmph); 3136 gpfnInitMPH = 0; 3137 } 3138 LeaveCriticalSection(&gcsMPH); 3139 return TRUE; 3140 } 3141 } 3142 LeaveCriticalSection(&gcsMPH); 3143 return FALSE; 3144 } 3145 3146 DWORD WINAPI GetQueueStatus(UINT flags) 3147 { 3148 return IsInsideMessagePumpHook() ? gmph.RealGetQueueStatus(flags) : RealGetQueueStatus(flags); 3149 } 3150 3151 /** 3152 * @name RealMsgWaitForMultipleObjectsEx 3153 * 3154 * Wait either for either message arrival or for one of the passed events 3155 * to be signalled. 3156 * 3157 * @param nCount 3158 * Number of handles in the pHandles array. 3159 * @param pHandles 3160 * Handles of events to wait for. 3161 * @param dwMilliseconds 3162 * Timeout interval. 3163 * @param dwWakeMask 3164 * Mask specifying on which message events we should wakeup. 3165 * @param dwFlags 3166 * Wait type (see MWMO_* constants). 3167 * 3168 * @implemented 3169 */ 3170 3171 DWORD WINAPI 3172 RealMsgWaitForMultipleObjectsEx( 3173 DWORD nCount, 3174 const HANDLE *pHandles, 3175 DWORD dwMilliseconds, 3176 DWORD dwWakeMask, 3177 DWORD dwFlags) 3178 { 3179 LPHANDLE RealHandles; 3180 HANDLE MessageQueueHandle; 3181 DWORD Result; 3182 PCLIENTINFO pci; 3183 PCLIENTTHREADINFO pcti; 3184 3185 if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) 3186 { 3187 SetLastError(ERROR_INVALID_PARAMETER); 3188 return WAIT_FAILED; 3189 } 3190 3191 pci = GetWin32ClientInfo(); 3192 if (!pci) return WAIT_FAILED; 3193 3194 pcti = pci->pClientThreadInfo; 3195 if (pcti && ( !nCount || !(dwFlags & MWMO_WAITALL) )) 3196 { 3197 if ( (pcti->fsChangeBits & LOWORD(dwWakeMask)) || 3198 ( (dwFlags & MWMO_INPUTAVAILABLE) && (pcti->fsWakeBits & LOWORD(dwWakeMask)) ) ) 3199 { 3200 //FIXME("Return Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount); 3201 return nCount; 3202 } 3203 } 3204 3205 MessageQueueHandle = NtUserxMsqSetWakeMask(MAKELONG(dwWakeMask, dwFlags)); 3206 if (MessageQueueHandle == NULL) 3207 { 3208 SetLastError(0); /* ? */ 3209 return WAIT_FAILED; 3210 } 3211 3212 RealHandles = HeapAlloc(GetProcessHeap(), 0, (nCount + 1) * sizeof(HANDLE)); 3213 if (RealHandles == NULL) 3214 { 3215 NtUserxMsqClearWakeMask(); 3216 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3217 return WAIT_FAILED; 3218 } 3219 3220 RtlCopyMemory(RealHandles, pHandles, nCount * sizeof(HANDLE)); 3221 RealHandles[nCount] = MessageQueueHandle; 3222 3223 //FIXME("1 Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount); 3224 3225 Result = WaitForMultipleObjectsEx( nCount + 1, 3226 RealHandles, 3227 dwFlags & MWMO_WAITALL, 3228 dwMilliseconds, 3229 dwFlags & MWMO_ALERTABLE ); 3230 3231 //FIXME("2 Chg 0x%x Wake 0x%x Mask 0x%x nCnt %d\n",pcti->fsChangeBits, pcti->fsWakeBits, dwWakeMask, nCount); 3232 3233 HeapFree(GetProcessHeap(), 0, RealHandles); 3234 NtUserxMsqClearWakeMask(); 3235 3236 // wine hack! MSDN: If dwMilliseconds is zero,,specified objects are not signaled; it always returns immediately. 3237 if (!Result && !nCount && !dwMilliseconds) Result = WAIT_TIMEOUT; 3238 3239 //FIXME("Result 0X%x\n",Result); 3240 return Result; 3241 } 3242 3243 /* 3244 * @implemented 3245 */ 3246 DWORD WINAPI 3247 MsgWaitForMultipleObjectsEx( 3248 DWORD nCount, 3249 CONST HANDLE *lpHandles, 3250 DWORD dwMilliseconds, 3251 DWORD dwWakeMask, 3252 DWORD dwFlags) 3253 { 3254 return IsInsideMessagePumpHook() ? gmph.RealMsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, dwWakeMask, dwFlags) : RealMsgWaitForMultipleObjectsEx(nCount, lpHandles,dwMilliseconds, dwWakeMask, dwFlags); 3255 } 3256 3257 /* 3258 * @implemented 3259 */ 3260 DWORD WINAPI 3261 MsgWaitForMultipleObjects( 3262 DWORD nCount, 3263 CONST HANDLE *lpHandles, 3264 BOOL fWaitAll, 3265 DWORD dwMilliseconds, 3266 DWORD dwWakeMask) 3267 { 3268 return MsgWaitForMultipleObjectsEx(nCount, lpHandles, dwMilliseconds, 3269 dwWakeMask, fWaitAll ? MWMO_WAITALL : 0); 3270 } 3271 3272 3273 BOOL FASTCALL MessageInit(VOID) 3274 { 3275 InitializeCriticalSection(&DdeCrst); 3276 InitializeCriticalSection(&gcsMPH); 3277 3278 return TRUE; 3279 } 3280 3281 VOID FASTCALL MessageCleanup(VOID) 3282 { 3283 DeleteCriticalSection(&DdeCrst); 3284 DeleteCriticalSection(&gcsMPH); 3285 } 3286 3287 /* 3288 * @implemented 3289 */ 3290 BOOL WINAPI 3291 IsDialogMessageA( HWND hwndDlg, LPMSG pmsg ) 3292 { 3293 MSG msg = *pmsg; 3294 msg.wParam = map_wparam_AtoW( msg.message, msg.wParam ); 3295 return IsDialogMessageW( hwndDlg, &msg ); 3296 } 3297 3298 LONG 3299 WINAPI 3300 IntBroadcastSystemMessage( 3301 DWORD dwflags, 3302 LPDWORD lpdwRecipients, 3303 UINT uiMessage, 3304 WPARAM wParam, 3305 LPARAM lParam, 3306 PBSMINFO pBSMInfo, 3307 BOOL Ansi) 3308 { 3309 BROADCASTPARM parm; 3310 DWORD recips = BSM_ALLCOMPONENTS; 3311 BOOL ret = -1; // Set to return fail 3312 static const DWORD all_flags = ( BSF_QUERY | BSF_IGNORECURRENTTASK | BSF_FLUSHDISK | BSF_NOHANG 3313 | BSF_POSTMESSAGE | BSF_FORCEIFHUNG | BSF_NOTIMEOUTIFNOTHUNG 3314 | BSF_ALLOWSFW | BSF_SENDNOTIFYMESSAGE | BSF_RETURNHDESK | BSF_LUID ); 3315 3316 if ((dwflags & ~all_flags) || 3317 (!pBSMInfo && (dwflags & (BSF_RETURNHDESK|BSF_LUID))) ) 3318 { 3319 SetLastError(ERROR_INVALID_PARAMETER); 3320 return 0; 3321 } 3322 3323 if(uiMessage >= WM_USER && uiMessage < 0xC000) 3324 { 3325 SetLastError(ERROR_INVALID_PARAMETER); 3326 return 0; 3327 } 3328 3329 if (dwflags & BSF_FORCEIFHUNG) dwflags |= BSF_NOHANG; 3330 3331 if (dwflags & BSF_QUERY) dwflags &= ~BSF_SENDNOTIFYMESSAGE|BSF_POSTMESSAGE; 3332 3333 if (!lpdwRecipients) 3334 lpdwRecipients = &recips; 3335 3336 if (*lpdwRecipients & ~(BSM_APPLICATIONS|BSM_ALLDESKTOPS|BSM_INSTALLABLEDRIVERS|BSM_NETDRIVER|BSM_VXDS)) 3337 { 3338 SetLastError(ERROR_INVALID_PARAMETER); 3339 return 0; 3340 } 3341 3342 if ( pBSMInfo && (dwflags & BSF_QUERY) ) 3343 { 3344 if (pBSMInfo->cbSize != sizeof(BSMINFO)) 3345 { 3346 SetLastError(ERROR_INVALID_PARAMETER); 3347 return 0; 3348 } 3349 } 3350 3351 parm.hDesk = NULL; 3352 parm.hWnd = NULL; 3353 parm.flags = dwflags; 3354 parm.recipients = *lpdwRecipients; 3355 3356 if (dwflags & BSF_LUID) parm.luid = pBSMInfo->luid; 3357 3358 ret = NtUserMessageCall(GetDesktopWindow(), 3359 uiMessage, 3360 wParam, 3361 lParam, 3362 (ULONG_PTR)&parm, 3363 FNID_BROADCASTSYSTEMMESSAGE, 3364 Ansi); 3365 3366 if (!ret) 3367 { 3368 if ( pBSMInfo && (dwflags & BSF_QUERY) ) 3369 { 3370 pBSMInfo->hdesk = parm.hDesk; 3371 pBSMInfo->hwnd = parm.hWnd; 3372 } 3373 } 3374 return ret; 3375 } 3376 3377 /* 3378 * @implemented 3379 */ 3380 LONG 3381 WINAPI 3382 BroadcastSystemMessageA( 3383 DWORD dwFlags, 3384 LPDWORD lpdwRecipients, 3385 UINT uiMessage, 3386 WPARAM wParam, 3387 LPARAM lParam) 3388 { 3389 return IntBroadcastSystemMessage( dwFlags, lpdwRecipients, uiMessage, wParam, lParam, NULL, TRUE ); 3390 } 3391 3392 /* 3393 * @implemented 3394 */ 3395 LONG 3396 WINAPI 3397 BroadcastSystemMessageW( 3398 DWORD dwFlags, 3399 LPDWORD lpdwRecipients, 3400 UINT uiMessage, 3401 WPARAM wParam, 3402 LPARAM lParam) 3403 { 3404 return IntBroadcastSystemMessage( dwFlags, lpdwRecipients, uiMessage, wParam, lParam, NULL, FALSE ); 3405 } 3406 3407 /* 3408 * @implemented 3409 */ 3410 LONG 3411 WINAPI 3412 BroadcastSystemMessageExA( 3413 DWORD dwflags, 3414 LPDWORD lpdwRecipients, 3415 UINT uiMessage, 3416 WPARAM wParam, 3417 LPARAM lParam, 3418 PBSMINFO pBSMInfo) 3419 { 3420 return IntBroadcastSystemMessage( dwflags, lpdwRecipients, uiMessage, wParam, lParam , pBSMInfo, TRUE ); 3421 } 3422 3423 /* 3424 * @implemented 3425 */ 3426 LONG 3427 WINAPI 3428 BroadcastSystemMessageExW( 3429 DWORD dwflags, 3430 LPDWORD lpdwRecipients, 3431 UINT uiMessage, 3432 WPARAM wParam, 3433 LPARAM lParam, 3434 PBSMINFO pBSMInfo) 3435 { 3436 return IntBroadcastSystemMessage( dwflags, lpdwRecipients, uiMessage, wParam, lParam , pBSMInfo, FALSE ); 3437 } 3438 3439