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