1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Win32k subsystem 4 * PURPOSE: Messages 5 * FILE: win32ss/user/ntuser/message.c 6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 */ 8 9 #include <win32k.h> 10 11 #include <dde.h> 12 13 DBG_DEFAULT_CHANNEL(UserMsg); 14 15 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE) 16 17 /* FUNCTIONS *****************************************************************/ 18 19 NTSTATUS FASTCALL 20 IntInitMessageImpl(VOID) 21 { 22 return STATUS_SUCCESS; 23 } 24 25 NTSTATUS FASTCALL 26 IntCleanupMessageImpl(VOID) 27 { 28 return STATUS_SUCCESS; 29 } 30 31 /* From wine: */ 32 /* flag for messages that contain pointers */ 33 /* 32 messages per entry, messages 0..31 map to bits 0..31 */ 34 35 #define SET(msg) (1 << ((msg) & 31)) 36 37 static const unsigned int message_pointer_flags[] = 38 { 39 /* 0x00 - 0x1f */ 40 SET(WM_CREATE) | SET(WM_SETTEXT) | SET(WM_GETTEXT) | 41 SET(WM_WININICHANGE) | SET(WM_DEVMODECHANGE), 42 /* 0x20 - 0x3f */ 43 SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM) | 44 SET(WM_COMPAREITEM), 45 /* 0x40 - 0x5f */ 46 SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) | SET(WM_COPYGLOBALDATA) | SET(WM_HELP), 47 /* 0x60 - 0x7f */ 48 SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED), 49 /* 0x80 - 0x9f */ 50 SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE), 51 /* 0xa0 - 0xbf */ 52 SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP), 53 /* 0xc0 - 0xdf */ 54 SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS), 55 /* 0xe0 - 0xff */ 56 SET(SBM_GETRANGE) | SET(SBM_SETSCROLLINFO) | SET(SBM_GETSCROLLINFO) | SET(SBM_GETSCROLLBARINFO), 57 /* 0x100 - 0x11f */ 58 0, 59 /* 0x120 - 0x13f */ 60 0, 61 /* 0x140 - 0x15f */ 62 SET(CB_GETEDITSEL) | SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) | 63 SET(CB_INSERTSTRING) | SET(CB_FINDSTRING) | SET(CB_SELECTSTRING) | 64 SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT), 65 /* 0x160 - 0x17f */ 66 0, 67 /* 0x180 - 0x19f */ 68 SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) | 69 SET(LB_DIR) | SET(LB_FINDSTRING) | 70 SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT), 71 /* 0x1a0 - 0x1bf */ 72 SET(LB_FINDSTRINGEXACT), 73 /* 0x1c0 - 0x1df */ 74 0, 75 /* 0x1e0 - 0x1ff */ 76 0, 77 /* 0x200 - 0x21f */ 78 SET(WM_NEXTMENU) | SET(WM_SIZING) | SET(WM_MOVING) | SET(WM_DEVICECHANGE), 79 /* 0x220 - 0x23f */ 80 SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) | 81 SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGLOOP) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE), 82 /* 0x240 - 0x25f */ 83 0, 84 /* 0x260 - 0x27f */ 85 0, 86 /* 0x280 - 0x29f */ 87 0, 88 /* 0x2a0 - 0x2bf */ 89 0, 90 /* 0x2c0 - 0x2df */ 91 0, 92 /* 0x2e0 - 0x2ff */ 93 0, 94 /* 0x300 - 0x31f */ 95 SET(WM_ASKCBFORMATNAME) 96 }; 97 98 /* check whether a given message type includes pointers */ 99 static inline int is_pointer_message( UINT message ) 100 { 101 if (message >= 8*sizeof(message_pointer_flags)) return FALSE; 102 return (message_pointer_flags[message / 32] & SET(message)) != 0; 103 } 104 #undef SET 105 106 #define MMS_SIZE_WPARAM -1 107 #define MMS_SIZE_WPARAMWCHAR -2 108 #define MMS_SIZE_LPARAMSZ -3 109 #define MMS_SIZE_SPECIAL -4 110 #define MMS_FLAG_READ 0x01 111 #define MMS_FLAG_WRITE 0x02 112 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE) 113 typedef struct tagMSGMEMORY 114 { 115 UINT Message; 116 UINT Size; 117 INT Flags; 118 } 119 MSGMEMORY, *PMSGMEMORY; 120 121 static MSGMEMORY g_MsgMemory[] = 122 { 123 { WM_CREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, 124 { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE }, 125 { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE }, 126 { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, 127 { WM_NCCREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, 128 { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ }, 129 { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ }, 130 { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE }, 131 { WM_SETTINGCHANGE, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ }, 132 { WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ }, 133 { WM_COPYGLOBALDATA, MMS_SIZE_WPARAM, MMS_FLAG_READ }, 134 { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READWRITE }, 135 { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE }, 136 { WM_SIZING, sizeof(RECT), MMS_FLAG_READWRITE }, 137 { WM_MOVING, sizeof(RECT), MMS_FLAG_READWRITE }, 138 { WM_MEASUREITEM, sizeof(MEASUREITEMSTRUCT), MMS_FLAG_READWRITE }, 139 { WM_DRAWITEM, sizeof(DRAWITEMSTRUCT), MMS_FLAG_READWRITE }, 140 { WM_HELP, sizeof(HELPINFO), MMS_FLAG_READWRITE }, 141 { WM_NEXTMENU, sizeof(MDINEXTMENU), MMS_FLAG_READWRITE }, 142 }; 143 144 static PMSGMEMORY FASTCALL 145 FindMsgMemory(UINT Msg) 146 { 147 PMSGMEMORY MsgMemoryEntry; 148 149 /* See if this message type is present in the table */ 150 for (MsgMemoryEntry = g_MsgMemory; 151 MsgMemoryEntry < g_MsgMemory + sizeof(g_MsgMemory) / sizeof(MSGMEMORY); 152 MsgMemoryEntry++) 153 { 154 if (Msg == MsgMemoryEntry->Message) 155 { 156 return MsgMemoryEntry; 157 } 158 } 159 160 return NULL; 161 } 162 163 static UINT FASTCALL 164 MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam) 165 { 166 CREATESTRUCTW *Cs; 167 PLARGE_STRING WindowName; 168 PUNICODE_STRING ClassName; 169 UINT Size = 0; 170 171 _SEH2_TRY 172 { 173 if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size) 174 { 175 Size = (UINT)wParam; 176 } 177 else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size) 178 { 179 Size = (UINT) (wParam * sizeof(WCHAR)); 180 } 181 else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size) 182 { 183 // WM_SETTEXT and WM_SETTINGCHANGE can be null! 184 if (!lParam) 185 { 186 TRACE("lParam is NULL!\n"); 187 Size = 0; 188 } 189 else 190 Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR)); 191 } 192 else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size) 193 { 194 switch(MsgMemoryEntry->Message) 195 { 196 case WM_CREATE: 197 case WM_NCCREATE: 198 Cs = (CREATESTRUCTW *) lParam; 199 WindowName = (PLARGE_STRING) Cs->lpszName; 200 ClassName = (PUNICODE_STRING) Cs->lpszClass; 201 Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR); 202 if (IS_ATOM(ClassName->Buffer)) 203 { 204 Size += sizeof(WCHAR) + sizeof(ATOM); 205 } 206 else 207 { 208 Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR); 209 } 210 break; 211 212 case WM_NCCALCSIZE: 213 Size = wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT); 214 break; 215 216 case WM_COPYDATA: 217 { 218 COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam; 219 Size = sizeof(COPYDATASTRUCT) + cds->cbData; 220 } 221 break; 222 223 default: 224 ASSERT(FALSE); 225 Size = 0; 226 break; 227 } 228 } 229 else 230 { 231 Size = MsgMemoryEntry->Size; 232 } 233 } 234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 235 { 236 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode()); 237 Size = 0; 238 } 239 _SEH2_END; 240 return Size; 241 } 242 243 UINT lParamMemorySize(UINT Msg, WPARAM wParam, LPARAM lParam) 244 { 245 PMSGMEMORY MsgMemoryEntry = FindMsgMemory(Msg); 246 if(MsgMemoryEntry == NULL) return 0; 247 return MsgMemorySize(MsgMemoryEntry, wParam, lParam); 248 } 249 250 static NTSTATUS 251 PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded) 252 { 253 NCCALCSIZE_PARAMS *UnpackedNcCalcsize; 254 NCCALCSIZE_PARAMS *PackedNcCalcsize; 255 CREATESTRUCTW *UnpackedCs; 256 CREATESTRUCTW *PackedCs; 257 PLARGE_STRING WindowName; 258 PUNICODE_STRING ClassName; 259 POOL_TYPE PoolType; 260 UINT Size; 261 PCHAR CsData; 262 263 *lParamPacked = lParam; 264 265 if (NonPagedPoolNeeded) 266 PoolType = NonPagedPool; 267 else 268 PoolType = PagedPool; 269 270 if (WM_NCCALCSIZE == Msg && wParam) 271 { 272 273 UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam; 274 PackedNcCalcsize = ExAllocatePoolWithTag(PoolType, 275 sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS), 276 TAG_MSG); 277 278 if (NULL == PackedNcCalcsize) 279 { 280 ERR("Not enough memory to pack lParam\n"); 281 return STATUS_NO_MEMORY; 282 } 283 RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS)); 284 PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1); 285 RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS)); 286 *lParamPacked = (LPARAM) PackedNcCalcsize; 287 } 288 else if (WM_CREATE == Msg || WM_NCCREATE == Msg) 289 { 290 UnpackedCs = (CREATESTRUCTW *) lParam; 291 WindowName = (PLARGE_STRING) UnpackedCs->lpszName; 292 ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass; 293 Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR); 294 if (IS_ATOM(ClassName->Buffer)) 295 { 296 Size += sizeof(WCHAR) + sizeof(ATOM); 297 } 298 else 299 { 300 Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR); 301 } 302 PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG); 303 if (NULL == PackedCs) 304 { 305 ERR("Not enough memory to pack lParam\n"); 306 return STATUS_NO_MEMORY; 307 } 308 RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW)); 309 CsData = (PCHAR) (PackedCs + 1); 310 PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs); 311 RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length); 312 CsData += WindowName->Length; 313 *((WCHAR *) CsData) = L'\0'; 314 CsData += sizeof(WCHAR); 315 PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs); 316 if (IS_ATOM(ClassName->Buffer)) 317 { 318 *((WCHAR *) CsData) = L'A'; 319 CsData += sizeof(WCHAR); 320 *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer; 321 CsData += sizeof(ATOM); 322 } 323 else 324 { 325 NT_ASSERT(ClassName->Buffer != NULL); 326 *((WCHAR *) CsData) = L'S'; 327 CsData += sizeof(WCHAR); 328 RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length); 329 CsData += ClassName->Length; 330 *((WCHAR *) CsData) = L'\0'; 331 CsData += sizeof(WCHAR); 332 } 333 ASSERT(CsData == (PCHAR) PackedCs + Size); 334 *lParamPacked = (LPARAM) PackedCs; 335 } 336 else if (PoolType == NonPagedPool) 337 { 338 PMSGMEMORY MsgMemoryEntry; 339 PVOID PackedData; 340 SIZE_T size; 341 342 MsgMemoryEntry = FindMsgMemory(Msg); 343 344 if (!MsgMemoryEntry) 345 { 346 /* Keep previous behavior */ 347 return STATUS_SUCCESS; 348 } 349 size = MsgMemorySize(MsgMemoryEntry, wParam, lParam); 350 if (!size) 351 { 352 ERR("No size for lParamPacked\n"); 353 return STATUS_SUCCESS; 354 } 355 PackedData = ExAllocatePoolWithTag(NonPagedPool, size, TAG_MSG); 356 if (PackedData == NULL) 357 { 358 ERR("Not enough memory to pack lParam\n"); 359 return STATUS_NO_MEMORY; 360 } 361 RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam)); 362 *lParamPacked = (LPARAM)PackedData; 363 } 364 365 return STATUS_SUCCESS; 366 } 367 368 static NTSTATUS 369 UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed) 370 { 371 NCCALCSIZE_PARAMS *UnpackedParams; 372 NCCALCSIZE_PARAMS *PackedParams; 373 PWINDOWPOS UnpackedWindowPos; 374 375 if (lParamPacked == lParam) 376 { 377 return STATUS_SUCCESS; 378 } 379 380 if (WM_NCCALCSIZE == Msg && wParam) 381 { 382 PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked; 383 UnpackedParams = (NCCALCSIZE_PARAMS *) lParam; 384 UnpackedWindowPos = UnpackedParams->lppos; 385 RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS)); 386 UnpackedParams->lppos = UnpackedWindowPos; 387 RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS)); 388 ExFreePool((PVOID) lParamPacked); 389 390 return STATUS_SUCCESS; 391 } 392 else if (WM_CREATE == Msg || WM_NCCREATE == Msg) 393 { 394 ExFreePool((PVOID) lParamPacked); 395 396 return STATUS_SUCCESS; 397 } 398 else if (NonPagedPoolUsed) 399 { 400 PMSGMEMORY MsgMemoryEntry; 401 MsgMemoryEntry = FindMsgMemory(Msg); 402 ASSERT(MsgMemoryEntry); 403 404 if (MsgMemoryEntry->Flags == MMS_FLAG_READWRITE) 405 { 406 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size); 407 } 408 ExFreePool((PVOID) lParamPacked); 409 return STATUS_SUCCESS; 410 } 411 412 ASSERT(FALSE); 413 414 return STATUS_INVALID_PARAMETER; 415 } 416 417 static NTSTATUS FASTCALL 418 CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry) 419 { 420 NTSTATUS Status; 421 422 PVOID KernelMem; 423 UINT Size; 424 425 *KernelModeMsg = *UserModeMsg; 426 427 /* See if this message type is present in the table */ 428 if (NULL == MsgMemoryEntry) 429 { 430 /* Not present, no copying needed */ 431 return STATUS_SUCCESS; 432 } 433 434 /* Determine required size */ 435 Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam); 436 437 if (0 != Size) 438 { 439 /* Allocate kernel mem */ 440 KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG); 441 if (NULL == KernelMem) 442 { 443 ERR("Not enough memory to copy message to kernel mem\n"); 444 return STATUS_NO_MEMORY; 445 } 446 KernelModeMsg->lParam = (LPARAM) KernelMem; 447 448 /* Copy data if required */ 449 if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ)) 450 { 451 TRACE("Copy Message %u from usermode buffer\n", KernelModeMsg->message); 452 Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size); 453 if (! NT_SUCCESS(Status)) 454 { 455 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n"); 456 ExFreePoolWithTag(KernelMem, TAG_MSG); 457 return Status; 458 } 459 } 460 else 461 { 462 /* Make sure we don't pass any secrets to usermode */ 463 RtlZeroMemory(KernelMem, Size); 464 } 465 } 466 else 467 { 468 KernelModeMsg->lParam = 0; 469 } 470 471 return STATUS_SUCCESS; 472 } 473 474 static NTSTATUS FASTCALL 475 CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg) 476 { 477 NTSTATUS Status; 478 PMSGMEMORY MsgMemoryEntry; 479 UINT Size; 480 481 /* See if this message type is present in the table */ 482 MsgMemoryEntry = FindMsgMemory(UserModeMsg->message); 483 if (NULL == MsgMemoryEntry) 484 { 485 /* Not present, no copying needed */ 486 return STATUS_SUCCESS; 487 } 488 489 /* Determine required size */ 490 Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam); 491 492 if (0 != Size) 493 { 494 /* Copy data if required */ 495 if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE)) 496 { 497 Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size); 498 if (! NT_SUCCESS(Status)) 499 { 500 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n"); 501 ExFreePool((PVOID) KernelModeMsg->lParam); 502 return Status; 503 } 504 } 505 ExFreePool((PVOID) KernelModeMsg->lParam); 506 } 507 508 return STATUS_SUCCESS; 509 } 510 511 // 512 // Wakeup any thread/process waiting on idle input. 513 // 514 VOID FASTCALL 515 IdlePing(VOID) 516 { 517 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 518 PTHREADINFO pti; 519 520 pti = PsGetCurrentThreadWin32Thread(); 521 522 if ( pti ) 523 { 524 pti->pClientInfo->cSpins = 0; // Reset spins. 525 526 if ( pti->pDeskInfo && pti == gptiForeground ) 527 { 528 if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) || 529 pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ) 530 { 531 co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0); 532 } 533 } 534 } 535 536 TRACE("IdlePing ppi %p\n", ppi); 537 if ( ppi && ppi->InputIdleEvent ) 538 { 539 TRACE("InputIdleEvent\n"); 540 KeSetEvent( ppi->InputIdleEvent, IO_NO_INCREMENT, FALSE); 541 } 542 } 543 544 VOID FASTCALL 545 IdlePong(VOID) 546 { 547 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 548 549 TRACE("IdlePong ppi %p\n", ppi); 550 if ( ppi && ppi->InputIdleEvent ) 551 { 552 KeClearEvent(ppi->InputIdleEvent); 553 } 554 } 555 556 static BOOL is_message_broadcastable(UINT msg) 557 { 558 return msg < WM_USER || msg >= 0xc000; 559 } 560 561 UINT FASTCALL 562 GetWakeMask(UINT first, UINT last ) 563 { 564 UINT mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */ 565 566 if (first || last) 567 { 568 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY; 569 if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) || 570 ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE; 571 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER; 572 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER; 573 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT; 574 } 575 else mask = QS_ALLINPUT; 576 577 return mask; 578 } 579 580 static VOID FASTCALL 581 IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 582 { 583 BOOL SameThread = FALSE; 584 CWPSTRUCT CWP; 585 586 if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())) 587 SameThread = TRUE; 588 589 CWP.hwnd = hWnd; 590 CWP.message = Msg; 591 CWP.wParam = wParam; 592 CWP.lParam = lParam; 593 co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP ); 594 } 595 596 static VOID FASTCALL 597 IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult) 598 { 599 BOOL SameThread = FALSE; 600 CWPRETSTRUCT CWPR; 601 602 if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread())) 603 SameThread = TRUE; 604 605 CWPR.hwnd = hWnd; 606 CWPR.message = Msg; 607 CWPR.wParam = wParam; 608 CWPR.lParam = lParam; 609 CWPR.lResult = uResult ? (*uResult) : 0; 610 co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR ); 611 } 612 613 static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam ) 614 { 615 LRESULT lRes; 616 // USER_REFERENCE_ENTRY Ref; 617 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 618 619 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 620 return 0; 621 622 TRACE("Internal Event Msg 0x%x hWnd 0x%p\n", msg, pWnd->head.h); 623 624 switch(msg) 625 { 626 case WM_ASYNC_SHOWWINDOW: 627 return co_WinPosShowWindow( pWnd, wparam ); 628 case WM_ASYNC_SETWINDOWPOS: 629 { 630 PWINDOWPOS winpos = (PWINDOWPOS)lparam; 631 if (!winpos) return 0; 632 lRes = co_WinPosSetWindowPos( pWnd, 633 winpos->hwndInsertAfter, 634 winpos->x, 635 winpos->y, 636 winpos->cx, 637 winpos->cy, 638 winpos->flags); 639 ExFreePoolWithTag(winpos, USERTAG_SWP); 640 return lRes; 641 } 642 case WM_ASYNC_DESTROYWINDOW: 643 { 644 ERR("WM_ASYNC_DESTROYWINDOW\n"); 645 if (pWnd->style & WS_CHILD) 646 return co_UserFreeWindow(pWnd, PsGetCurrentProcessWin32Process(), PsGetCurrentThreadWin32Thread(), TRUE); 647 else 648 co_UserDestroyWindow(pWnd); 649 } 650 } 651 return 0; 652 } 653 654 static LRESULT handle_internal_events( PTHREADINFO pti, PWND pWnd, DWORD dwQEvent, LONG_PTR ExtraInfo, PMSG pMsg) 655 { 656 LRESULT Result = 0; 657 658 switch(dwQEvent) 659 { 660 case POSTEVENT_NWE: 661 { 662 co_EVENT_CallEvents( pMsg->message, pMsg->hwnd, pMsg->wParam, ExtraInfo); 663 } 664 break; 665 case POSTEVENT_SAW: 666 { 667 //ERR("HIE : SAW : pti 0x%p hWnd 0x%p\n",pti,pMsg->hwnd); 668 IntActivateWindow((PWND)pMsg->wParam, pti, (HANDLE)pMsg->lParam, (DWORD)ExtraInfo); 669 } 670 break; 671 case POSTEVENT_DAW: 672 { 673 //ERR("HIE : DAW : pti 0x%p tid 0x%p hWndPrev 0x%p\n",pti,ExtraInfo,pMsg->hwnd); 674 IntDeactivateWindow(pti, (HANDLE)ExtraInfo); 675 } 676 break; 677 } 678 return Result; 679 } 680 681 LRESULT FASTCALL 682 IntDispatchMessage(PMSG pMsg) 683 { 684 LONG Time; 685 LRESULT retval = 0; 686 PTHREADINFO pti; 687 PWND Window = NULL; 688 BOOL DoCallBack = TRUE; 689 690 if (pMsg->hwnd) 691 { 692 Window = UserGetWindowObject(pMsg->hwnd); 693 if (!Window) return 0; 694 } 695 696 pti = PsGetCurrentThreadWin32Thread(); 697 698 if ( Window && Window->head.pti != pti) 699 { 700 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY ); 701 return 0; 702 } 703 704 if (((pMsg->message == WM_SYSTIMER) || 705 (pMsg->message == WM_TIMER)) && 706 (pMsg->lParam) ) 707 { 708 if (pMsg->message == WM_TIMER) 709 { 710 if (ValidateTimerCallback(pti,pMsg->lParam)) 711 { 712 Time = EngGetTickCount32(); 713 retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam, 714 TRUE, 715 pMsg->hwnd, 716 WM_TIMER, 717 pMsg->wParam, 718 (LPARAM)Time, 719 -1); 720 } 721 return retval; 722 } 723 else 724 { 725 PTIMER pTimer = FindSystemTimer(pMsg); 726 if (pTimer && pTimer->pfn) 727 { 728 Time = EngGetTickCount32(); 729 pTimer->pfn(pMsg->hwnd, WM_SYSTIMER, (UINT)pMsg->wParam, Time); 730 } 731 return 0; 732 } 733 } 734 // Need a window! 735 if ( !Window ) return 0; 736 737 if (pMsg->message == WM_PAINT) Window->state |= WNDS_PAINTNOTPROCESSED; 738 739 if ( Window->state & WNDS_SERVERSIDEWINDOWPROC ) 740 { 741 TRACE("Dispatch: Server Side Window Procedure\n"); 742 switch(Window->fnid) 743 { 744 case FNID_DESKTOP: 745 DoCallBack = !DesktopWindowProc( Window, 746 pMsg->message, 747 pMsg->wParam, 748 pMsg->lParam, 749 &retval); 750 break; 751 case FNID_MESSAGEWND: 752 DoCallBack = !UserMessageWindowProc( Window, 753 pMsg->message, 754 pMsg->wParam, 755 pMsg->lParam, 756 &retval); 757 break; 758 case FNID_MENU: 759 DoCallBack = !PopupMenuWndProc( Window, 760 pMsg->message, 761 pMsg->wParam, 762 pMsg->lParam, 763 &retval); 764 break; 765 } 766 } 767 768 /* Since we are doing a callback on the same thread right away, there is 769 no need to copy the lparam to kernel mode and then back to usermode. 770 We just pretend it isn't a pointer */ 771 772 if (DoCallBack) 773 retval = co_IntCallWindowProc( Window->lpfnWndProc, 774 !Window->Unicode, 775 pMsg->hwnd, 776 pMsg->message, 777 pMsg->wParam, 778 pMsg->lParam, 779 -1); 780 781 if ( pMsg->message == WM_PAINT && 782 VerifyWnd(Window) && 783 Window->state & WNDS_PAINTNOTPROCESSED ) // <--- Cleared, paint was already processed! 784 { 785 Window->state2 &= ~WNDS2_WMPAINTSENT; 786 /* send a WM_ERASEBKGND if the non-client area is still invalid */ 787 ERR("Message WM_PAINT count %d Internal Paint Set? %s\n",Window->head.pti->cPaintsReady, Window->state & WNDS_INTERNALPAINT ? "TRUE" : "FALSE"); 788 IntPaintWindow( Window ); 789 } 790 791 return retval; 792 } 793 794 /* 795 * Internal version of PeekMessage() doing all the work 796 * 797 * MSDN: 798 * Sent messages 799 * Posted messages 800 * Input (hardware) messages and system internal events 801 * Sent messages (again) 802 * WM_PAINT messages 803 * WM_TIMER messages 804 */ 805 BOOL APIENTRY 806 co_IntPeekMessage( PMSG Msg, 807 PWND Window, 808 UINT MsgFilterMin, 809 UINT MsgFilterMax, 810 UINT RemoveMsg, 811 LONG_PTR *ExtraInfo, 812 BOOL bGMSG ) 813 { 814 PTHREADINFO pti; 815 BOOL RemoveMessages; 816 UINT ProcessMask; 817 BOOL Hit = FALSE; 818 819 pti = PsGetCurrentThreadWin32Thread(); 820 821 RemoveMessages = RemoveMsg & PM_REMOVE; 822 ProcessMask = HIWORD(RemoveMsg); 823 824 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns 825 all available messages (that is, no range filtering is performed)". */ 826 if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT); 827 828 IdlePong(); 829 830 do 831 { 832 /* Update the last message-queue access time */ 833 pti->pcti->timeLastRead = EngGetTickCount32(); 834 835 // Post mouse moves while looping through peek messages. 836 if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED) 837 { 838 IntCoalesceMouseMove(pti); 839 } 840 841 /* Dispatch sent messages here. */ 842 while ( co_MsqDispatchOneSentMessage(pti) ) 843 { 844 /* if some PM_QS* flags were specified, only handle sent messages from now on */ 845 if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; // wine does this; ProcessMask = QS_SENDMESSAGE; 846 } 847 if (Hit) return FALSE; 848 849 /* Clear changed bits so we can wait on them if we don't find a message */ 850 if (ProcessMask & QS_POSTMESSAGE) 851 { 852 pti->pcti->fsChangeBits &= ~(QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER); 853 if (MsgFilterMin == 0 && MsgFilterMax == 0) // Wine hack does this; ~0U) 854 { 855 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE; 856 } 857 } 858 859 if (ProcessMask & QS_INPUT) 860 { 861 pti->pcti->fsChangeBits &= ~QS_INPUT; 862 } 863 864 /* Now check for normal messages. */ 865 if (( (ProcessMask & QS_POSTMESSAGE) || 866 (ProcessMask & QS_HOTKEY) ) && 867 MsqPeekMessage( pti, 868 RemoveMessages, 869 Window, 870 MsgFilterMin, 871 MsgFilterMax, 872 ProcessMask, 873 ExtraInfo, 874 0, 875 Msg )) 876 { 877 goto GotMessage; 878 } 879 880 /* Only check for quit messages if not posted messages pending. */ 881 if (ProcessMask & QS_POSTMESSAGE && pti->QuitPosted) 882 { 883 /* According to the PSDK, WM_QUIT messages are always returned, regardless 884 of the filter specified */ 885 Msg->hwnd = NULL; 886 Msg->message = WM_QUIT; 887 Msg->wParam = pti->exitCode; 888 Msg->lParam = 0; 889 if (RemoveMessages) 890 { 891 pti->QuitPosted = FALSE; 892 ClearMsgBitsMask(pti, QS_POSTMESSAGE); 893 pti->pcti->fsWakeBits &= ~QS_ALLPOSTMESSAGE; 894 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE; 895 } 896 goto GotMessage; 897 } 898 899 /* Check for hardware events. */ 900 if ((ProcessMask & QS_INPUT) && 901 co_MsqPeekHardwareMessage( pti, 902 RemoveMessages, 903 Window, 904 MsgFilterMin, 905 MsgFilterMax, 906 ProcessMask, 907 Msg)) 908 { 909 goto GotMessage; 910 } 911 912 /* Now check for System Event messages. */ 913 { 914 LONG_PTR eExtraInfo; 915 MSG eMsg; 916 DWORD dwQEvent; 917 if (MsqPeekMessage( pti, 918 TRUE, 919 Window, 920 0, 921 0, 922 QS_EVENT, 923 &eExtraInfo, 924 &dwQEvent, 925 &eMsg )) 926 { 927 handle_internal_events( pti, Window, dwQEvent, eExtraInfo, &eMsg); 928 continue; 929 } 930 } 931 932 /* Check for sent messages again. */ 933 while ( co_MsqDispatchOneSentMessage(pti) ) 934 { 935 if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; 936 } 937 if (Hit) return FALSE; 938 939 /* Check for paint messages. */ 940 if ((ProcessMask & QS_PAINT) && 941 pti->cPaintsReady && 942 IntGetPaintMessage( Window, 943 MsgFilterMin, 944 MsgFilterMax, 945 pti, 946 Msg, 947 RemoveMessages)) 948 { 949 goto GotMessage; 950 } 951 952 /* This is correct, check for the current threads timers waiting to be 953 posted to this threads message queue. If any we loop again. 954 */ 955 if ((ProcessMask & QS_TIMER) && 956 PostTimerMessages(Window)) 957 { 958 continue; 959 } 960 961 return FALSE; 962 } 963 while (TRUE); 964 965 GotMessage: 966 /* Update the last message-queue access time */ 967 pti->pcti->timeLastRead = EngGetTickCount32(); 968 return TRUE; 969 } 970 971 BOOL FASTCALL 972 co_IntWaitMessage( PWND Window, 973 UINT MsgFilterMin, 974 UINT MsgFilterMax ) 975 { 976 PTHREADINFO pti; 977 NTSTATUS Status = STATUS_SUCCESS; 978 MSG Msg; 979 LONG_PTR ExtraInfo = 0; 980 981 pti = PsGetCurrentThreadWin32Thread(); 982 983 do 984 { 985 if ( co_IntPeekMessage( &Msg, // Dont reenter! 986 Window, 987 MsgFilterMin, 988 MsgFilterMax, 989 MAKELONG( PM_NOREMOVE, GetWakeMask( MsgFilterMin, MsgFilterMax)), 990 &ExtraInfo, 991 TRUE ) ) // act like GetMessage. 992 { 993 return TRUE; 994 } 995 996 /* Nothing found. Wait for new messages. */ 997 Status = co_MsqWaitForNewMessages( pti, 998 Window, 999 MsgFilterMin, 1000 MsgFilterMax); 1001 if (!NT_SUCCESS(Status)) 1002 { 1003 SetLastNtError(Status); 1004 ERR("Exit co_IntWaitMessage on error!\n"); 1005 return FALSE; 1006 } 1007 if (Status == STATUS_USER_APC || Status == STATUS_TIMEOUT) 1008 { 1009 return FALSE; 1010 } 1011 } 1012 while ( TRUE ); 1013 1014 return FALSE; 1015 } 1016 1017 BOOL APIENTRY 1018 co_IntGetPeekMessage( PMSG pMsg, 1019 HWND hWnd, 1020 UINT MsgFilterMin, 1021 UINT MsgFilterMax, 1022 UINT RemoveMsg, 1023 BOOL bGMSG ) 1024 { 1025 PWND Window; 1026 PTHREADINFO pti; 1027 BOOL Present = FALSE; 1028 NTSTATUS Status; 1029 LONG_PTR ExtraInfo = 0; 1030 1031 if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST ) 1032 hWnd = HWND_BOTTOM; 1033 1034 /* Validate input */ 1035 if (hWnd && hWnd != HWND_BOTTOM) 1036 { 1037 if (!(Window = UserGetWindowObject(hWnd))) 1038 { 1039 if (bGMSG) 1040 return -1; 1041 else 1042 return FALSE; 1043 } 1044 } 1045 else 1046 { 1047 Window = (PWND)hWnd; 1048 } 1049 1050 if (MsgFilterMax < MsgFilterMin) 1051 { 1052 MsgFilterMin = 0; 1053 MsgFilterMax = 0; 1054 } 1055 1056 if (bGMSG) 1057 { 1058 RemoveMsg |= ((GetWakeMask( MsgFilterMin, MsgFilterMax ))<< 16); 1059 } 1060 1061 pti = PsGetCurrentThreadWin32Thread(); 1062 pti->pClientInfo->cSpins++; // Bump up the spin count. 1063 1064 do 1065 { 1066 Present = co_IntPeekMessage( pMsg, 1067 Window, 1068 MsgFilterMin, 1069 MsgFilterMax, 1070 RemoveMsg, 1071 &ExtraInfo, 1072 bGMSG ); 1073 if (Present) 1074 { 1075 /* GetMessage or PostMessage must never get messages that contain pointers */ 1076 ASSERT(FindMsgMemory(pMsg->message) == NULL); 1077 1078 if ( pMsg->message >= WM_DDE_FIRST && pMsg->message <= WM_DDE_LAST ) 1079 { 1080 if (!IntDdeGetMessageHook(pMsg, ExtraInfo)) 1081 { 1082 TRACE("DDE Get return ERROR\n"); 1083 continue; 1084 } 1085 } 1086 1087 if (pMsg->message != WM_PAINT && pMsg->message != WM_QUIT) 1088 { 1089 if (!RtlEqualMemory(&pti->ptLast, &pMsg->pt, sizeof(POINT))) 1090 { 1091 pti->TIF_flags |= TIF_MSGPOSCHANGED; 1092 } 1093 pti->timeLast = pMsg->time; 1094 pti->ptLast = pMsg->pt; 1095 } 1096 1097 // The WH_GETMESSAGE hook enables an application to monitor messages about to 1098 // be returned by the GetMessage or PeekMessage function. 1099 1100 co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)pMsg); 1101 1102 if ( bGMSG || pMsg->message == WM_PAINT) break; 1103 } 1104 1105 if ( bGMSG ) 1106 { 1107 Status = co_MsqWaitForNewMessages( pti, 1108 Window, 1109 MsgFilterMin, 1110 MsgFilterMax); 1111 if ( !NT_SUCCESS(Status) || 1112 Status == STATUS_USER_APC || 1113 Status == STATUS_TIMEOUT ) 1114 { 1115 Present = -1; 1116 break; 1117 } 1118 } 1119 else 1120 { 1121 if (!(RemoveMsg & PM_NOYIELD)) 1122 { 1123 IdlePing(); 1124 // Yield this thread! 1125 UserLeave(); 1126 ZwYieldExecution(); 1127 UserEnterExclusive(); 1128 // Fall through to exit. 1129 IdlePong(); 1130 } 1131 break; 1132 } 1133 } 1134 while( bGMSG && !Present ); 1135 1136 // Been spinning, time to swap vinyl... 1137 if (pti->pClientInfo->cSpins >= 100) 1138 { 1139 // Clear the spin cycle to fix the mix. 1140 pti->pClientInfo->cSpins = 0; 1141 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl... 1142 } 1143 return Present; 1144 } 1145 1146 BOOL FASTCALL 1147 UserPostThreadMessage( PTHREADINFO pti, 1148 UINT Msg, 1149 WPARAM wParam, 1150 LPARAM lParam ) 1151 { 1152 MSG Message; 1153 1154 if (is_pointer_message(Msg)) 1155 { 1156 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY ); 1157 return FALSE; 1158 } 1159 Message.hwnd = NULL; 1160 Message.message = Msg; 1161 Message.wParam = wParam; 1162 Message.lParam = lParam; 1163 Message.pt = gpsi->ptCursor; 1164 Message.time = EngGetTickCount32(); 1165 MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0); 1166 return TRUE; 1167 } 1168 1169 PTHREADINFO FASTCALL 1170 IntSendTo(PWND Window, PTHREADINFO ptiCur, UINT Msg) 1171 { 1172 if ( ptiCur ) 1173 { 1174 if (!Window || 1175 Window->head.pti == ptiCur ) 1176 { 1177 return NULL; 1178 } 1179 } 1180 return Window ? Window->head.pti : NULL; 1181 } 1182 1183 BOOL FASTCALL 1184 UserPostMessage( HWND Wnd, 1185 UINT Msg, 1186 WPARAM wParam, 1187 LPARAM lParam ) 1188 { 1189 PTHREADINFO pti; 1190 MSG Message; 1191 LONG_PTR ExtraInfo = 0; 1192 1193 Message.hwnd = Wnd; 1194 Message.message = Msg; 1195 Message.wParam = wParam; 1196 Message.lParam = lParam; 1197 Message.pt = gpsi->ptCursor; 1198 Message.time = EngGetTickCount32(); 1199 1200 if (is_pointer_message(Message.message)) 1201 { 1202 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY ); 1203 return FALSE; 1204 } 1205 1206 if (Wnd == HWND_BROADCAST || Wnd == HWND_TOPMOST) 1207 { 1208 HWND *List; 1209 PWND DesktopWindow; 1210 ULONG i; 1211 1212 if (!is_message_broadcastable(Msg)) return TRUE; 1213 1214 DesktopWindow = UserGetDesktopWindow(); 1215 List = IntWinListChildren(DesktopWindow); 1216 1217 if (List != NULL) 1218 { 1219 UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam); 1220 for (i = 0; List[i]; i++) 1221 { 1222 PWND pwnd = UserGetWindowObject(List[i]); 1223 if (!pwnd) continue; 1224 1225 if ( pwnd->fnid == FNID_MENU || // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass 1226 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 1227 continue; 1228 1229 UserPostMessage(List[i], Msg, wParam, lParam); 1230 } 1231 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1232 } 1233 } 1234 else 1235 { 1236 PWND Window; 1237 1238 if (!Wnd) 1239 { 1240 return UserPostThreadMessage( gptiCurrent, 1241 Msg, 1242 wParam, 1243 lParam); 1244 } 1245 1246 Window = UserGetWindowObject(Wnd); 1247 if ( !Window ) 1248 { 1249 ERR("UserPostMessage: Invalid handle 0x%p Msg 0x%x!\n", Wnd, Msg); 1250 return FALSE; 1251 } 1252 1253 pti = Window->head.pti; 1254 1255 if ( pti->TIF_flags & TIF_INCLEANUP ) 1256 { 1257 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd); 1258 return FALSE; 1259 } 1260 1261 if ( Window->state & WNDS_DESTROYED ) 1262 { 1263 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd); 1264 /* FIXME: Last error code? */ 1265 return FALSE; 1266 } 1267 1268 if ( Msg >= WM_DDE_FIRST && Msg <= WM_DDE_LAST ) 1269 { 1270 if (!IntDdePostMessageHook(Window, Msg, wParam, &lParam, &ExtraInfo)) 1271 { 1272 TRACE("Posting Exit DDE 0x%x\n",Msg); 1273 return FALSE; 1274 } 1275 Message.lParam = lParam; 1276 } 1277 1278 MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, ExtraInfo); 1279 } 1280 return TRUE; 1281 } 1282 1283 LRESULT FASTCALL 1284 co_IntSendMessage( HWND hWnd, 1285 UINT Msg, 1286 WPARAM wParam, 1287 LPARAM lParam ) 1288 { 1289 ULONG_PTR Result = 0; 1290 1291 if (co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result)) 1292 { 1293 return (LRESULT)Result; 1294 } 1295 return 0; 1296 } 1297 1298 static LRESULT FASTCALL 1299 co_IntSendMessageTimeoutSingle( HWND hWnd, 1300 UINT Msg, 1301 WPARAM wParam, 1302 LPARAM lParam, 1303 UINT uFlags, 1304 UINT uTimeout, 1305 ULONG_PTR *uResult ) 1306 { 1307 NTSTATUS Status = STATUS_SUCCESS; 1308 PWND Window = NULL; 1309 PMSGMEMORY MsgMemoryEntry; 1310 INT lParamBufferSize; 1311 LPARAM lParamPacked; 1312 PTHREADINFO Win32Thread, ptiSendTo = NULL; 1313 ULONG_PTR Result = 0; 1314 DECLARE_RETURN(LRESULT); 1315 USER_REFERENCE_ENTRY Ref; 1316 BOOL DoCallBack = TRUE; 1317 1318 if (!(Window = UserGetWindowObject(hWnd))) 1319 { 1320 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd); 1321 RETURN( FALSE); 1322 } 1323 1324 UserRefObjectCo(Window, &Ref); 1325 1326 Win32Thread = PsGetCurrentThreadWin32Thread(); 1327 1328 ptiSendTo = IntSendTo(Window, Win32Thread, Msg); 1329 1330 if ( Msg >= WM_DDE_FIRST && Msg <= WM_DDE_LAST ) 1331 { 1332 if (!IntDdeSendMessageHook(Window, Msg, wParam, lParam)) 1333 { 1334 ERR("Sending Exit DDE 0x%x\n",Msg); 1335 RETURN( FALSE); 1336 } 1337 } 1338 1339 if ( !ptiSendTo ) 1340 { 1341 if (Win32Thread->TIF_flags & TIF_INCLEANUP) 1342 { 1343 /* Never send messages to exiting threads */ 1344 RETURN( FALSE); 1345 } 1346 1347 if (Msg & 0x80000000) 1348 { 1349 TRACE("SMTS: Internal Message!\n"); 1350 Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam ); 1351 if (uResult) *uResult = Result; 1352 RETURN( TRUE); 1353 } 1354 1355 // Only happens when calling the client! 1356 IntCallWndProc( Window, hWnd, Msg, wParam, lParam); 1357 1358 if ( Window->state & WNDS_SERVERSIDEWINDOWPROC ) 1359 { 1360 TRACE("SMT: Server Side Window Procedure\n"); 1361 // Handle it here. Safeguard against excessive recursions. 1362 if (IoGetRemainingStackSize() < PAGE_SIZE) 1363 { 1364 ERR("Server Callback Exceeded Stack!\n"); 1365 RETURN( FALSE); 1366 } 1367 /* Return after server side call, IntCallWndProcRet will not be called. */ 1368 switch(Window->fnid) 1369 { 1370 case FNID_DESKTOP: 1371 DoCallBack = !DesktopWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); 1372 break; 1373 case FNID_MESSAGEWND: 1374 DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); 1375 break; 1376 case FNID_MENU: 1377 DoCallBack = !PopupMenuWndProc( Window, Msg, wParam, lParam,(LRESULT*)&Result); 1378 break; 1379 } 1380 if (!DoCallBack) 1381 { 1382 if (uResult) *uResult = Result; 1383 RETURN( TRUE); 1384 } 1385 } 1386 /* See if this message type is present in the table */ 1387 MsgMemoryEntry = FindMsgMemory(Msg); 1388 if (NULL == MsgMemoryEntry) 1389 { 1390 lParamBufferSize = -1; 1391 } 1392 else 1393 { 1394 lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam); 1395 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695. 1396 if (!lParamBufferSize) lParamBufferSize = -1; 1397 } 1398 1399 if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE))) 1400 { 1401 ERR("Failed to pack message parameters\n"); 1402 RETURN( FALSE); 1403 } 1404 1405 Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc, 1406 !Window->Unicode, 1407 hWnd, 1408 Msg, 1409 wParam, 1410 lParamPacked, 1411 lParamBufferSize ); 1412 if (uResult) 1413 { 1414 *uResult = Result; 1415 } 1416 1417 if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) 1418 { 1419 ERR("Failed to unpack message parameters\n"); 1420 RETURN( TRUE); 1421 } 1422 1423 // Only happens when calling the client! 1424 IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); 1425 1426 RETURN( TRUE); 1427 } 1428 1429 if (Window->state & WNDS_DESTROYED) 1430 { 1431 /* FIXME: Last error? */ 1432 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd); 1433 RETURN( FALSE); 1434 } 1435 1436 if ((uFlags & SMTO_ABORTIFHUNG) && MsqIsHung(ptiSendTo, 4 * MSQ_HUNG)) 1437 { 1438 // FIXME: Set window hung and add to a list. 1439 /* FIXME: Set a LastError? */ 1440 ERR("Window %p (%p) (pti %p) is hung!\n", hWnd, Window, ptiSendTo); 1441 RETURN( FALSE); 1442 } 1443 1444 do 1445 { 1446 Status = co_MsqSendMessage( ptiSendTo, 1447 hWnd, 1448 Msg, 1449 wParam, 1450 lParam, 1451 uTimeout, 1452 (uFlags & SMTO_BLOCK), 1453 MSQ_NORMAL, 1454 uResult ); 1455 } 1456 while ((Status == STATUS_TIMEOUT) && 1457 (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) && 1458 !MsqIsHung(ptiSendTo, MSQ_HUNG)); // FIXME: Set window hung and add to a list. 1459 1460 if (Status == STATUS_TIMEOUT) 1461 { 1462 if (0 && MsqIsHung(ptiSendTo, MSQ_HUNG)) 1463 { 1464 TRACE("Let's go Ghost!\n"); 1465 IntMakeHungWindowGhosted(hWnd); 1466 } 1467 /* 1468 * MSDN says: 1469 * Microsoft Windows 2000: If GetLastError returns zero, then the function 1470 * timed out. 1471 * XP+ : If the function fails or times out, the return value is zero. 1472 * To get extended error information, call GetLastError. If GetLastError 1473 * returns ERROR_TIMEOUT, then the function timed out. 1474 */ 1475 EngSetLastError(ERROR_TIMEOUT); 1476 RETURN( FALSE); 1477 } 1478 else if (!NT_SUCCESS(Status)) 1479 { 1480 SetLastNtError(Status); 1481 RETURN( FALSE); 1482 } 1483 1484 RETURN( TRUE); 1485 1486 CLEANUP: 1487 if (Window) UserDerefObjectCo(Window); 1488 END_CLEANUP; 1489 } 1490 1491 LRESULT FASTCALL 1492 co_IntSendMessageTimeout( HWND hWnd, 1493 UINT Msg, 1494 WPARAM wParam, 1495 LPARAM lParam, 1496 UINT uFlags, 1497 UINT uTimeout, 1498 ULONG_PTR *uResult ) 1499 { 1500 PWND DesktopWindow; 1501 HWND *Children; 1502 HWND *Child; 1503 1504 if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST) 1505 { 1506 return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult); 1507 } 1508 1509 if (!is_message_broadcastable(Msg)) return TRUE; 1510 1511 DesktopWindow = UserGetDesktopWindow(); 1512 if (NULL == DesktopWindow) 1513 { 1514 EngSetLastError(ERROR_INTERNAL_ERROR); 1515 return 0; 1516 } 1517 1518 if (hWnd != HWND_TOPMOST) 1519 { 1520 /* Send message to the desktop window too! */ 1521 co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult); 1522 } 1523 1524 Children = IntWinListChildren(DesktopWindow); 1525 if (NULL == Children) 1526 { 1527 return 0; 1528 } 1529 1530 for (Child = Children; NULL != *Child; Child++) 1531 { 1532 PWND pwnd = UserGetWindowObject(*Child); 1533 if (!pwnd) continue; 1534 1535 if ( pwnd->fnid == FNID_MENU || 1536 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 1537 continue; 1538 1539 co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult); 1540 } 1541 1542 ExFreePoolWithTag(Children, USERTAG_WINDOWLIST); 1543 1544 return (LRESULT) TRUE; 1545 } 1546 1547 LRESULT FASTCALL 1548 co_IntSendMessageNoWait(HWND hWnd, 1549 UINT Msg, 1550 WPARAM wParam, 1551 LPARAM lParam) 1552 { 1553 ULONG_PTR Result = 0; 1554 return co_IntSendMessageWithCallBack( hWnd, 1555 Msg, 1556 wParam, 1557 lParam, 1558 NULL, 1559 0, 1560 &Result); 1561 } 1562 /* MSDN: 1563 If you send a message in the range below WM_USER to the asynchronous message 1564 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its 1565 message parameters cannot include pointers. Otherwise, the operation will fail. 1566 The functions will return before the receiving thread has had a chance to 1567 process the message and the sender will free the memory before it is used. 1568 */ 1569 LRESULT FASTCALL 1570 co_IntSendMessageWithCallBack( HWND hWnd, 1571 UINT Msg, 1572 WPARAM wParam, 1573 LPARAM lParam, 1574 SENDASYNCPROC CompletionCallback, 1575 ULONG_PTR CompletionCallbackContext, 1576 ULONG_PTR *uResult) 1577 { 1578 ULONG_PTR Result; 1579 PWND Window = NULL; 1580 PMSGMEMORY MsgMemoryEntry; 1581 INT lParamBufferSize; 1582 LPARAM lParamPacked; 1583 PTHREADINFO Win32Thread, ptiSendTo = NULL; 1584 DECLARE_RETURN(LRESULT); 1585 USER_REFERENCE_ENTRY Ref; 1586 PUSER_SENT_MESSAGE Message; 1587 BOOL DoCallBack = TRUE; 1588 1589 if (!(Window = UserGetWindowObject(hWnd))) 1590 { 1591 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd); 1592 RETURN(FALSE); 1593 } 1594 1595 UserRefObjectCo(Window, &Ref); 1596 1597 if (Window->state & WNDS_DESTROYED) 1598 { 1599 /* FIXME: last error? */ 1600 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd); 1601 RETURN(FALSE); 1602 } 1603 1604 Win32Thread = PsGetCurrentThreadWin32Thread(); 1605 1606 if (Win32Thread == NULL || 1607 Win32Thread->TIF_flags & TIF_INCLEANUP) 1608 { 1609 RETURN(FALSE); 1610 } 1611 1612 ptiSendTo = IntSendTo(Window, Win32Thread, Msg); 1613 1614 if (Msg & 0x80000000 && 1615 !ptiSendTo) 1616 { 1617 if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE); 1618 1619 TRACE("SMWCB: Internal Message!\n"); 1620 Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam ); 1621 if (uResult) *uResult = Result; 1622 RETURN( TRUE); 1623 } 1624 1625 /* See if this message type is present in the table */ 1626 MsgMemoryEntry = FindMsgMemory(Msg); 1627 if (NULL == MsgMemoryEntry) 1628 { 1629 lParamBufferSize = -1; 1630 } 1631 else 1632 { 1633 lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam); 1634 if (!lParamBufferSize) lParamBufferSize = -1; 1635 } 1636 1637 if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, !!ptiSendTo))) 1638 { 1639 ERR("Failed to pack message parameters\n"); 1640 RETURN( FALSE); 1641 } 1642 1643 /* If it can be sent now, then send it. */ 1644 if ( !ptiSendTo ) 1645 { 1646 if (Win32Thread->TIF_flags & TIF_INCLEANUP) 1647 { 1648 UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE); 1649 /* Never send messages to exiting threads */ 1650 RETURN(FALSE); 1651 } 1652 1653 IntCallWndProc( Window, hWnd, Msg, wParam, lParam); 1654 1655 if ( Window->state & WNDS_SERVERSIDEWINDOWPROC ) 1656 { 1657 TRACE("SMWCB: Server Side Window Procedure\n"); 1658 switch(Window->fnid) 1659 { 1660 case FNID_DESKTOP: 1661 DoCallBack = !DesktopWindowProc(Window, Msg, wParam, lParamPacked, (LRESULT*)&Result); 1662 break; 1663 case FNID_MESSAGEWND: 1664 DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result); 1665 break; 1666 case FNID_MENU: 1667 DoCallBack = !PopupMenuWndProc( Window, Msg, wParam, lParam,(LRESULT*)&Result); 1668 break; 1669 } 1670 } 1671 1672 if (DoCallBack) 1673 Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc, 1674 !Window->Unicode, 1675 hWnd, 1676 Msg, 1677 wParam, 1678 lParamPacked, 1679 lParamBufferSize ); 1680 if(uResult) 1681 { 1682 *uResult = Result; 1683 } 1684 1685 IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult); 1686 1687 if (CompletionCallback) 1688 { 1689 co_IntCallSentMessageCallback(CompletionCallback, 1690 hWnd, 1691 Msg, 1692 CompletionCallbackContext, 1693 Result); 1694 } 1695 } 1696 1697 if ( !ptiSendTo) 1698 { 1699 if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) 1700 { 1701 ERR("Failed to unpack message parameters\n"); 1702 } 1703 RETURN(TRUE); 1704 } 1705 1706 if(!(Message = AllocateUserMessage(FALSE))) 1707 { 1708 ERR("MsqSendMessage(): Not enough memory to allocate a message"); 1709 RETURN( FALSE); 1710 } 1711 1712 Message->Msg.hwnd = hWnd; 1713 Message->Msg.message = Msg; 1714 Message->Msg.wParam = wParam; 1715 Message->Msg.lParam = lParamPacked; 1716 Message->pkCompletionEvent = NULL; // No event needed. 1717 Message->lResult = 0; 1718 Message->QS_Flags = 0; 1719 Message->ptiReceiver = ptiSendTo; 1720 Message->ptiSender = NULL; // mjmartin, you are right! This is null. 1721 Message->ptiCallBackSender = Win32Thread; 1722 Message->CompletionCallback = CompletionCallback; 1723 Message->CompletionCallbackContext = CompletionCallbackContext; 1724 Message->HookMessage = MSQ_NORMAL; 1725 Message->HasPackedLParam = (lParamBufferSize > 0); 1726 Message->QS_Flags = QS_SENDMESSAGE; 1727 Message->flags = SMF_RECEIVERFREE; 1728 1729 if (Msg & 0x80000000) // Higher priority event message! 1730 InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry); 1731 else 1732 InsertTailList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry); 1733 MsqWakeQueue(ptiSendTo, QS_SENDMESSAGE, TRUE); 1734 1735 RETURN(TRUE); 1736 1737 CLEANUP: 1738 if (Window) UserDerefObjectCo(Window); 1739 END_CLEANUP; 1740 } 1741 1742 #if 0 1743 /* 1744 This HACK function posts a message if the destination's message queue belongs to 1745 another thread, otherwise it sends the message. It does not support broadcast 1746 messages! 1747 */ 1748 LRESULT FASTCALL 1749 co_IntPostOrSendMessage( HWND hWnd, 1750 UINT Msg, 1751 WPARAM wParam, 1752 LPARAM lParam ) 1753 { 1754 ULONG_PTR Result; 1755 PTHREADINFO pti; 1756 PWND Window; 1757 1758 if ( hWnd == HWND_BROADCAST ) 1759 { 1760 return 0; 1761 } 1762 1763 if(!(Window = UserGetWindowObject(hWnd))) 1764 { 1765 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd); 1766 return 0; 1767 } 1768 1769 pti = PsGetCurrentThreadWin32Thread(); 1770 1771 if ( IntSendTo(Window, pti, Msg) && 1772 FindMsgMemory(Msg) == 0 ) 1773 { 1774 Result = UserPostMessage(hWnd, Msg, wParam, lParam); 1775 } 1776 else 1777 { 1778 if ( !co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result) ) 1779 { 1780 Result = 0; 1781 } 1782 } 1783 1784 return (LRESULT)Result; 1785 } 1786 #endif 1787 1788 static LRESULT FASTCALL 1789 co_IntDoSendMessage( HWND hWnd, 1790 UINT Msg, 1791 WPARAM wParam, 1792 LPARAM lParam, 1793 PDOSENDMESSAGE dsm) 1794 { 1795 LRESULT Result = TRUE; 1796 NTSTATUS Status; 1797 PWND Window = NULL; 1798 MSG UserModeMsg, KernelModeMsg; 1799 PMSGMEMORY MsgMemoryEntry; 1800 PTHREADINFO ptiSendTo; 1801 1802 if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST) 1803 { 1804 Window = UserGetWindowObject(hWnd); 1805 if ( !Window ) 1806 { 1807 return 0; 1808 } 1809 } 1810 1811 /* Check for an exiting window. */ 1812 if (Window && Window->state & WNDS_DESTROYED) 1813 { 1814 ERR("co_IntDoSendMessage Window Exiting!\n"); 1815 } 1816 1817 /* See if the current thread can handle this message */ 1818 ptiSendTo = IntSendTo(Window, gptiCurrent, Msg); 1819 1820 // If broadcasting or sending to another thread, save the users data. 1821 if (!Window || ptiSendTo ) 1822 { 1823 UserModeMsg.hwnd = hWnd; 1824 UserModeMsg.message = Msg; 1825 UserModeMsg.wParam = wParam; 1826 UserModeMsg.lParam = lParam; 1827 MsgMemoryEntry = FindMsgMemory(UserModeMsg.message); 1828 Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry); 1829 if (!NT_SUCCESS(Status)) 1830 { 1831 EngSetLastError(ERROR_INVALID_PARAMETER); 1832 return (dsm ? 0 : -1); 1833 } 1834 } 1835 else 1836 { 1837 KernelModeMsg.hwnd = hWnd; 1838 KernelModeMsg.message = Msg; 1839 KernelModeMsg.wParam = wParam; 1840 KernelModeMsg.lParam = lParam; 1841 } 1842 1843 if (!dsm) 1844 { 1845 Result = co_IntSendMessage( KernelModeMsg.hwnd, 1846 KernelModeMsg.message, 1847 KernelModeMsg.wParam, 1848 KernelModeMsg.lParam ); 1849 } 1850 else 1851 { 1852 Result = co_IntSendMessageTimeout( KernelModeMsg.hwnd, 1853 KernelModeMsg.message, 1854 KernelModeMsg.wParam, 1855 KernelModeMsg.lParam, 1856 dsm->uFlags, 1857 dsm->uTimeout, 1858 &dsm->Result ); 1859 } 1860 1861 if (!Window || ptiSendTo ) 1862 { 1863 Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg); 1864 if (!NT_SUCCESS(Status)) 1865 { 1866 EngSetLastError(ERROR_INVALID_PARAMETER); 1867 return(dsm ? 0 : -1); 1868 } 1869 } 1870 1871 return (LRESULT)Result; 1872 } 1873 1874 BOOL FASTCALL 1875 UserSendNotifyMessage( HWND hWnd, 1876 UINT Msg, 1877 WPARAM wParam, 1878 LPARAM lParam ) 1879 { 1880 BOOL Ret = TRUE; 1881 1882 if (is_pointer_message(Msg)) 1883 { 1884 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY ); 1885 return FALSE; 1886 } 1887 1888 // Basicly the same as IntPostOrSendMessage 1889 if (hWnd == HWND_BROADCAST) // Handle Broadcast 1890 { 1891 HWND *List; 1892 PWND DesktopWindow; 1893 ULONG i; 1894 1895 DesktopWindow = UserGetDesktopWindow(); 1896 List = IntWinListChildren(DesktopWindow); 1897 1898 if (List != NULL) 1899 { 1900 UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam); 1901 for (i = 0; List[i]; i++) 1902 { 1903 PWND pwnd = UserGetWindowObject(List[i]); 1904 if (!pwnd) continue; 1905 1906 if ( pwnd->fnid == FNID_MENU || 1907 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 1908 continue; 1909 1910 Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam); 1911 } 1912 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1913 } 1914 } 1915 else 1916 { 1917 Ret = co_IntSendMessageNoWait( hWnd, Msg, wParam, lParam); 1918 } 1919 return Ret; 1920 } 1921 1922 1923 DWORD APIENTRY 1924 IntGetQueueStatus(DWORD Changes) 1925 { 1926 PTHREADINFO pti; 1927 DWORD Result; 1928 1929 pti = PsGetCurrentThreadWin32Thread(); 1930 // wine: 1931 Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT); 1932 1933 /* High word, types of messages currently in the queue. 1934 Low word, types of messages that have been added to the queue and that 1935 are still in the queue 1936 */ 1937 Result = MAKELONG(pti->pcti->fsChangeBits & Changes, pti->pcti->fsWakeBits & Changes); 1938 1939 pti->pcti->fsChangeBits &= ~Changes; 1940 1941 return Result; 1942 } 1943 1944 BOOL APIENTRY 1945 IntInitMessagePumpHook(VOID) 1946 { 1947 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 1948 1949 if (pti->pcti) 1950 { 1951 pti->pcti->dwcPumpHook++; 1952 return TRUE; 1953 } 1954 return FALSE; 1955 } 1956 1957 BOOL APIENTRY 1958 IntUninitMessagePumpHook(VOID) 1959 { 1960 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 1961 1962 if (pti->pcti) 1963 { 1964 if (pti->pcti->dwcPumpHook <= 0) 1965 { 1966 return FALSE; 1967 } 1968 pti->pcti->dwcPumpHook--; 1969 return TRUE; 1970 } 1971 return FALSE; 1972 } 1973 1974 BOOL FASTCALL 1975 IntCallMsgFilter( LPMSG lpmsg, INT code) 1976 { 1977 BOOL Ret = FALSE; 1978 1979 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)lpmsg)) 1980 { 1981 Ret = TRUE; 1982 } 1983 else 1984 { 1985 Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)lpmsg); 1986 } 1987 return Ret; 1988 } 1989 1990 /** Functions ******************************************************************/ 1991 1992 BOOL 1993 APIENTRY 1994 NtUserDragDetect( 1995 HWND hWnd, 1996 POINT pt) // Just like the User call. 1997 { 1998 MSG msg; 1999 RECT rect; 2000 ULONG wDragWidth, wDragHeight; 2001 DECLARE_RETURN(BOOL); 2002 2003 TRACE("Enter NtUserDragDetect(%p)\n", hWnd); 2004 UserEnterExclusive(); 2005 2006 wDragWidth = UserGetSystemMetrics(SM_CXDRAG); 2007 wDragHeight= UserGetSystemMetrics(SM_CYDRAG); 2008 2009 rect.left = pt.x - wDragWidth; 2010 rect.right = pt.x + wDragWidth; 2011 2012 rect.top = pt.y - wDragHeight; 2013 rect.bottom = pt.y + wDragHeight; 2014 2015 co_UserSetCapture(hWnd); 2016 2017 for (;;) 2018 { 2019 while (co_IntGetPeekMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE, FALSE ) || 2020 co_IntGetPeekMessage( &msg, 0, WM_QUEUESYNC, WM_QUEUESYNC, PM_REMOVE, FALSE ) || 2021 co_IntGetPeekMessage( &msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE, FALSE ) ) 2022 { 2023 if ( msg.message == WM_LBUTTONUP ) 2024 { 2025 co_UserSetCapture(NULL); 2026 RETURN( FALSE); 2027 } 2028 if ( msg.message == WM_MOUSEMOVE ) 2029 { 2030 POINT tmp; 2031 tmp.x = (short)LOWORD(msg.lParam); 2032 tmp.y = (short)HIWORD(msg.lParam); 2033 if( !RECTL_bPointInRect( &rect, tmp.x, tmp.y ) ) 2034 { 2035 co_UserSetCapture(NULL); 2036 RETURN( TRUE); 2037 } 2038 } 2039 if ( msg.message == WM_KEYDOWN ) 2040 { 2041 if ( msg.wParam == VK_ESCAPE ) 2042 { 2043 co_UserSetCapture(NULL); 2044 RETURN( TRUE); 2045 } 2046 } 2047 if ( msg.message == WM_QUEUESYNC ) 2048 { 2049 co_HOOK_CallHooks( WH_CBT, HCBT_QS, 0, 0 ); 2050 } 2051 } 2052 co_IntWaitMessage(NULL, 0, 0); 2053 } 2054 RETURN( FALSE); 2055 2056 CLEANUP: 2057 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_); 2058 UserLeave(); 2059 END_CLEANUP; 2060 } 2061 2062 BOOL APIENTRY 2063 NtUserPostMessage(HWND hWnd, 2064 UINT Msg, 2065 WPARAM wParam, 2066 LPARAM lParam) 2067 { 2068 BOOL ret; 2069 2070 UserEnterExclusive(); 2071 2072 ret = UserPostMessage(hWnd, Msg, wParam, lParam); 2073 2074 UserLeave(); 2075 2076 return ret; 2077 } 2078 2079 BOOL APIENTRY 2080 NtUserPostThreadMessage(DWORD idThread, 2081 UINT Msg, 2082 WPARAM wParam, 2083 LPARAM lParam) 2084 { 2085 BOOL ret = FALSE; 2086 PETHREAD peThread; 2087 PTHREADINFO pThread; 2088 NTSTATUS Status; 2089 2090 UserEnterExclusive(); 2091 2092 Status = PsLookupThreadByThreadId(UlongToHandle(idThread), &peThread); 2093 2094 if ( Status == STATUS_SUCCESS ) 2095 { 2096 pThread = (PTHREADINFO)peThread->Tcb.Win32Thread; 2097 if( !pThread || 2098 !pThread->MessageQueue || 2099 (pThread->TIF_flags & TIF_INCLEANUP)) 2100 { 2101 ObDereferenceObject( peThread ); 2102 goto exit; 2103 } 2104 ret = UserPostThreadMessage( pThread, Msg, wParam, lParam); 2105 ObDereferenceObject( peThread ); 2106 } 2107 else 2108 { 2109 SetLastNtError( Status ); 2110 } 2111 exit: 2112 UserLeave(); 2113 return ret; 2114 } 2115 2116 BOOL APIENTRY 2117 NtUserWaitMessage(VOID) 2118 { 2119 BOOL ret; 2120 2121 UserEnterExclusive(); 2122 TRACE("NtUserWaitMessage Enter\n"); 2123 ret = co_IntWaitMessage(NULL, 0, 0); 2124 TRACE("NtUserWaitMessage Leave\n"); 2125 UserLeave(); 2126 2127 return ret; 2128 } 2129 2130 BOOL APIENTRY 2131 NtUserGetMessage(PMSG pMsg, 2132 HWND hWnd, 2133 UINT MsgFilterMin, 2134 UINT MsgFilterMax ) 2135 { 2136 MSG Msg; 2137 BOOL Ret; 2138 2139 if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM ) 2140 { 2141 EngSetLastError(ERROR_INVALID_PARAMETER); 2142 return FALSE; 2143 } 2144 2145 UserEnterExclusive(); 2146 2147 RtlZeroMemory(&Msg, sizeof(MSG)); 2148 2149 Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE); 2150 2151 UserLeave(); 2152 2153 if (Ret) 2154 { 2155 _SEH2_TRY 2156 { 2157 ProbeForWrite(pMsg, sizeof(MSG), 1); 2158 RtlCopyMemory(pMsg, &Msg, sizeof(MSG)); 2159 } 2160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2161 { 2162 SetLastNtError(_SEH2_GetExceptionCode()); 2163 Ret = FALSE; 2164 } 2165 _SEH2_END; 2166 } 2167 2168 if ((INT)Ret != -1) 2169 Ret = Ret ? (WM_QUIT != pMsg->message) : FALSE; 2170 2171 return Ret; 2172 } 2173 2174 BOOL APIENTRY 2175 NtUserPeekMessage( PMSG pMsg, 2176 HWND hWnd, 2177 UINT MsgFilterMin, 2178 UINT MsgFilterMax, 2179 UINT RemoveMsg) 2180 { 2181 MSG Msg; 2182 BOOL Ret; 2183 2184 if ( RemoveMsg & PM_BADMSGFLAGS ) 2185 { 2186 EngSetLastError(ERROR_INVALID_FLAGS); 2187 return FALSE; 2188 } 2189 2190 UserEnterExclusive(); 2191 2192 RtlZeroMemory(&Msg, sizeof(MSG)); 2193 2194 Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE); 2195 2196 UserLeave(); 2197 2198 if (Ret) 2199 { 2200 _SEH2_TRY 2201 { 2202 ProbeForWrite(pMsg, sizeof(MSG), 1); 2203 RtlCopyMemory(pMsg, &Msg, sizeof(MSG)); 2204 } 2205 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2206 { 2207 SetLastNtError(_SEH2_GetExceptionCode()); 2208 Ret = FALSE; 2209 } 2210 _SEH2_END; 2211 } 2212 2213 return Ret; 2214 } 2215 2216 BOOL APIENTRY 2217 NtUserCallMsgFilter( LPMSG lpmsg, INT code) 2218 { 2219 BOOL Ret = FALSE; 2220 MSG Msg; 2221 2222 _SEH2_TRY 2223 { 2224 ProbeForRead(lpmsg, sizeof(MSG), 1); 2225 RtlCopyMemory( &Msg, lpmsg, sizeof(MSG)); 2226 } 2227 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2228 { 2229 _SEH2_YIELD(return FALSE); 2230 } 2231 _SEH2_END; 2232 2233 UserEnterExclusive(); 2234 2235 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg)) 2236 { 2237 Ret = TRUE; 2238 } 2239 else 2240 { 2241 Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg); 2242 } 2243 2244 UserLeave(); 2245 2246 _SEH2_TRY 2247 { 2248 ProbeForWrite(lpmsg, sizeof(MSG), 1); 2249 RtlCopyMemory(lpmsg, &Msg, sizeof(MSG)); 2250 } 2251 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2252 { 2253 Ret = FALSE; 2254 } 2255 _SEH2_END; 2256 2257 return Ret; 2258 } 2259 2260 LRESULT APIENTRY 2261 NtUserDispatchMessage(PMSG UnsafeMsgInfo) 2262 { 2263 LRESULT Res = 0; 2264 MSG SafeMsg; 2265 2266 _SEH2_TRY 2267 { 2268 ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1); 2269 RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG)); 2270 } 2271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2272 { 2273 SetLastNtError(_SEH2_GetExceptionCode()); 2274 _SEH2_YIELD(return FALSE); 2275 } 2276 _SEH2_END; 2277 2278 UserEnterExclusive(); 2279 2280 Res = IntDispatchMessage(&SafeMsg); 2281 2282 UserLeave(); 2283 return Res; 2284 } 2285 2286 BOOL APIENTRY 2287 NtUserTranslateMessage(LPMSG lpMsg, UINT flags) 2288 { 2289 MSG SafeMsg; 2290 BOOL Ret; 2291 PWND pWnd; 2292 2293 _SEH2_TRY 2294 { 2295 ProbeForRead(lpMsg, sizeof(MSG), 1); 2296 RtlCopyMemory(&SafeMsg, lpMsg, sizeof(MSG)); 2297 } 2298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2299 { 2300 SetLastNtError(_SEH2_GetExceptionCode()); 2301 _SEH2_YIELD(return FALSE); 2302 } 2303 _SEH2_END; 2304 2305 UserEnterExclusive(); 2306 pWnd = UserGetWindowObject(SafeMsg.hwnd); 2307 if (pWnd) // Must have a window! 2308 { 2309 Ret = IntTranslateKbdMessage(&SafeMsg, flags); 2310 } 2311 else 2312 { 2313 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg.hwnd, SafeMsg.message); 2314 Ret = FALSE; 2315 } 2316 UserLeave(); 2317 2318 return Ret; 2319 } 2320 2321 LRESULT APIENTRY ScrollBarWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam); 2322 2323 BOOL APIENTRY 2324 NtUserMessageCall( HWND hWnd, 2325 UINT Msg, 2326 WPARAM wParam, 2327 LPARAM lParam, 2328 ULONG_PTR ResultInfo, 2329 DWORD dwType, // fnID? 2330 BOOL Ansi) 2331 { 2332 LRESULT lResult = 0; 2333 BOOL Ret = FALSE; 2334 PWND Window = NULL; 2335 USER_REFERENCE_ENTRY Ref; 2336 2337 UserEnterExclusive(); 2338 2339 switch(dwType) 2340 { 2341 case FNID_SCROLLBAR: 2342 { 2343 lResult = ScrollBarWndProc(hWnd, Msg, wParam, lParam); 2344 break; 2345 } 2346 case FNID_DESKTOP: 2347 { 2348 Window = UserGetWindowObject(hWnd); 2349 if (Window) 2350 { 2351 //ERR("FNID_DESKTOP IN\n"); 2352 Ret = DesktopWindowProc(Window, Msg, wParam, lParam, &lResult); 2353 //ERR("FNID_DESKTOP OUT\n"); 2354 } 2355 break; 2356 } 2357 case FNID_MENU: 2358 { 2359 Window = UserGetWindowObject(hWnd); 2360 if (Window) 2361 { 2362 Ret = PopupMenuWndProc( Window, Msg, wParam, lParam, &lResult); 2363 } 2364 break; 2365 } 2366 case FNID_MESSAGEWND: 2367 { 2368 Window = UserGetWindowObject(hWnd); 2369 if (Window) 2370 { 2371 Ret = !UserMessageWindowProc(Window, Msg, wParam, lParam, &lResult); 2372 } 2373 break; 2374 } 2375 case FNID_DEFWINDOWPROC: 2376 /* Validate input */ 2377 if (hWnd) 2378 { 2379 Window = UserGetWindowObject(hWnd); 2380 if (!Window) 2381 { 2382 UserLeave(); 2383 return FALSE; 2384 } 2385 UserRefObjectCo(Window, &Ref); 2386 } 2387 lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi); 2388 Ret = TRUE; 2389 if (hWnd) 2390 UserDerefObjectCo(Window); 2391 break; 2392 case FNID_SENDNOTIFYMESSAGE: 2393 Ret = UserSendNotifyMessage(hWnd, Msg, wParam, lParam); 2394 break; 2395 case FNID_BROADCASTSYSTEMMESSAGE: 2396 { 2397 BROADCASTPARM parm, *retparam; 2398 DWORD_PTR RetVal = 0; 2399 2400 if (ResultInfo) 2401 { 2402 _SEH2_TRY 2403 { 2404 ProbeForWrite((PVOID)ResultInfo, sizeof(BROADCASTPARM), 1); 2405 RtlCopyMemory(&parm, (PVOID)ResultInfo, sizeof(BROADCASTPARM)); 2406 } 2407 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2408 { 2409 _SEH2_YIELD(break); 2410 } 2411 _SEH2_END; 2412 } 2413 else 2414 break; 2415 2416 if ( parm.recipients & BSM_ALLDESKTOPS || 2417 parm.recipients == BSM_ALLCOMPONENTS ) 2418 { 2419 PLIST_ENTRY DesktopEntry; 2420 PDESKTOP rpdesk; 2421 HWND *List, hwndDenied = NULL; 2422 HDESK hDesk = NULL; 2423 PWND pwnd, pwndDesk; 2424 ULONG i; 2425 UINT fuFlags; 2426 2427 for (DesktopEntry = InputWindowStation->DesktopListHead.Flink; 2428 DesktopEntry != &InputWindowStation->DesktopListHead; 2429 DesktopEntry = DesktopEntry->Flink) 2430 { 2431 rpdesk = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry); 2432 pwndDesk = rpdesk->pDeskInfo->spwnd; 2433 List = IntWinListChildren(pwndDesk); 2434 2435 if (parm.flags & BSF_QUERY) 2436 { 2437 if (List != NULL) 2438 { 2439 if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG) 2440 { 2441 fuFlags = SMTO_ABORTIFHUNG; 2442 } 2443 else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG) 2444 { 2445 fuFlags = SMTO_NOTIMEOUTIFNOTHUNG; 2446 } 2447 else 2448 { 2449 fuFlags = SMTO_NORMAL; 2450 } 2451 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk), 2452 Msg, 2453 wParam, 2454 lParam, 2455 fuFlags, 2456 2000, 2457 &RetVal); 2458 Ret = TRUE; 2459 for (i = 0; List[i]; i++) 2460 { 2461 pwnd = UserGetWindowObject(List[i]); 2462 if (!pwnd) continue; 2463 2464 if ( pwnd->fnid == FNID_MENU || 2465 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2466 continue; 2467 2468 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2469 { 2470 if ( pwnd->head.pti == gptiCurrent ) 2471 continue; 2472 } 2473 co_IntSendMessageTimeout( List[i], 2474 Msg, 2475 wParam, 2476 lParam, 2477 fuFlags, 2478 2000, 2479 &RetVal); 2480 2481 if (!RetVal && EngGetLastError() == ERROR_TIMEOUT) 2482 { 2483 if (!(parm.flags & BSF_FORCEIFHUNG)) 2484 Ret = FALSE; 2485 } 2486 if (RetVal == BROADCAST_QUERY_DENY) 2487 { 2488 hwndDenied = List[i]; 2489 hDesk = UserHMGetHandle(pwndDesk); 2490 Ret = FALSE; 2491 } 2492 } 2493 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2494 _SEH2_TRY 2495 { 2496 retparam = (PBROADCASTPARM) ResultInfo; 2497 retparam->hDesk = hDesk; 2498 retparam->hWnd = hwndDenied; 2499 } 2500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2501 { 2502 _SEH2_YIELD(break); 2503 } 2504 _SEH2_END; 2505 if (!Ret) break; // Have a hit! Let everyone know! 2506 } 2507 } 2508 else if (parm.flags & BSF_POSTMESSAGE) 2509 { 2510 if (List != NULL) 2511 { 2512 UserPostMessage(UserHMGetHandle(pwndDesk), Msg, wParam, lParam); 2513 2514 for (i = 0; List[i]; i++) 2515 { 2516 pwnd = UserGetWindowObject(List[i]); 2517 if (!pwnd) continue; 2518 2519 if ( pwnd->fnid == FNID_MENU || 2520 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2521 continue; 2522 2523 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2524 { 2525 if ( pwnd->head.pti == gptiCurrent ) 2526 continue; 2527 } 2528 UserPostMessage(List[i], Msg, wParam, lParam); 2529 } 2530 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2531 } 2532 Ret = TRUE; 2533 } 2534 else 2535 { 2536 if (List != NULL) 2537 { 2538 UserSendNotifyMessage(UserHMGetHandle(pwndDesk), Msg, wParam, lParam); 2539 2540 for (i = 0; List[i]; i++) 2541 { 2542 pwnd = UserGetWindowObject(List[i]); 2543 if (!pwnd) continue; 2544 2545 if ( pwnd->fnid == FNID_MENU || 2546 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2547 continue; 2548 2549 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2550 { 2551 if ( pwnd->head.pti == gptiCurrent ) 2552 continue; 2553 } 2554 UserSendNotifyMessage(List[i], Msg, wParam, lParam); 2555 } 2556 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2557 } 2558 Ret = TRUE; 2559 } 2560 } 2561 } 2562 else if (parm.recipients & BSM_APPLICATIONS) 2563 { 2564 HWND *List, hwndDenied = NULL; 2565 HDESK hDesk = NULL; 2566 PWND pwnd, pwndDesk; 2567 ULONG i; 2568 UINT fuFlags; 2569 2570 pwndDesk = UserGetDesktopWindow(); 2571 List = IntWinListChildren(pwndDesk); 2572 2573 if (parm.flags & BSF_QUERY) 2574 { 2575 if (List != NULL) 2576 { 2577 if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG) 2578 { 2579 fuFlags = SMTO_ABORTIFHUNG; 2580 } 2581 else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG) 2582 { 2583 fuFlags = SMTO_NOTIMEOUTIFNOTHUNG; 2584 } 2585 else 2586 { 2587 fuFlags = SMTO_NORMAL; 2588 } 2589 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk), 2590 Msg, 2591 wParam, 2592 lParam, 2593 fuFlags, 2594 2000, 2595 &RetVal); 2596 Ret = TRUE; 2597 for (i = 0; List[i]; i++) 2598 { 2599 pwnd = UserGetWindowObject(List[i]); 2600 if (!pwnd) continue; 2601 2602 if ( pwnd->fnid == FNID_MENU || 2603 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2604 continue; 2605 2606 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2607 { 2608 if ( pwnd->head.pti == gptiCurrent ) 2609 continue; 2610 } 2611 co_IntSendMessageTimeout( List[i], 2612 Msg, 2613 wParam, 2614 lParam, 2615 fuFlags, 2616 2000, 2617 &RetVal); 2618 2619 if (!RetVal && EngGetLastError() == ERROR_TIMEOUT) 2620 { 2621 if (!(parm.flags & BSF_FORCEIFHUNG)) 2622 Ret = FALSE; 2623 } 2624 if (RetVal == BROADCAST_QUERY_DENY) 2625 { 2626 hwndDenied = List[i]; 2627 hDesk = UserHMGetHandle(pwndDesk); 2628 Ret = FALSE; 2629 } 2630 } 2631 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2632 _SEH2_TRY 2633 { 2634 retparam = (PBROADCASTPARM) ResultInfo; 2635 retparam->hDesk = hDesk; 2636 retparam->hWnd = hwndDenied; 2637 } 2638 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2639 { 2640 _SEH2_YIELD(break); 2641 } 2642 _SEH2_END; 2643 } 2644 } 2645 else if (parm.flags & BSF_POSTMESSAGE) 2646 { 2647 if (List != NULL) 2648 { 2649 UserPostMessage(UserHMGetHandle(pwndDesk), Msg, wParam, lParam); 2650 2651 for (i = 0; List[i]; i++) 2652 { 2653 pwnd = UserGetWindowObject(List[i]); 2654 if (!pwnd) continue; 2655 2656 if ( pwnd->fnid == FNID_MENU || 2657 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2658 continue; 2659 2660 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2661 { 2662 if ( pwnd->head.pti == gptiCurrent ) 2663 continue; 2664 } 2665 UserPostMessage(List[i], Msg, wParam, lParam); 2666 } 2667 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2668 } 2669 Ret = TRUE; 2670 } 2671 else 2672 { 2673 if (List != NULL) 2674 { 2675 UserSendNotifyMessage(UserHMGetHandle(pwndDesk), Msg, wParam, lParam); 2676 2677 for (i = 0; List[i]; i++) 2678 { 2679 pwnd = UserGetWindowObject(List[i]); 2680 if (!pwnd) continue; 2681 2682 if ( pwnd->fnid == FNID_MENU || 2683 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] ) 2684 continue; 2685 2686 if ( parm.flags & BSF_IGNORECURRENTTASK ) 2687 { 2688 if ( pwnd->head.pti == gptiCurrent ) 2689 continue; 2690 } 2691 UserSendNotifyMessage(List[i], Msg, wParam, lParam); 2692 } 2693 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2694 } 2695 Ret = TRUE; 2696 } 2697 } 2698 } 2699 break; 2700 case FNID_SENDMESSAGECALLBACK: 2701 { 2702 CALL_BACK_INFO CallBackInfo; 2703 ULONG_PTR uResult; 2704 2705 _SEH2_TRY 2706 { 2707 ProbeForRead((PVOID)ResultInfo, sizeof(CALL_BACK_INFO), 1); 2708 RtlCopyMemory(&CallBackInfo, (PVOID)ResultInfo, sizeof(CALL_BACK_INFO)); 2709 } 2710 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2711 { 2712 _SEH2_YIELD(break); 2713 } 2714 _SEH2_END; 2715 2716 if (is_pointer_message(Msg)) 2717 { 2718 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY ); 2719 break; 2720 } 2721 2722 if (!(Ret = co_IntSendMessageWithCallBack(hWnd, Msg, wParam, lParam, 2723 CallBackInfo.CallBack, CallBackInfo.Context, &uResult))) 2724 { 2725 ERR("Callback failure!\n"); 2726 } 2727 } 2728 break; 2729 case FNID_SENDMESSAGE: 2730 { 2731 lResult = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0); 2732 Ret = TRUE; 2733 2734 if (ResultInfo) 2735 { 2736 _SEH2_TRY 2737 { 2738 ProbeForWrite((PVOID)ResultInfo, sizeof(ULONG_PTR), 1); 2739 RtlCopyMemory((PVOID)ResultInfo, &lResult, sizeof(ULONG_PTR)); 2740 } 2741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2742 { 2743 Ret = FALSE; 2744 _SEH2_YIELD(break); 2745 } 2746 _SEH2_END; 2747 } 2748 break; 2749 } 2750 case FNID_SENDMESSAGEFF: 2751 case FNID_SENDMESSAGEWTOOPTION: 2752 { 2753 DOSENDMESSAGE dsm, *pdsm = (PDOSENDMESSAGE)ResultInfo; 2754 if (ResultInfo) 2755 { 2756 _SEH2_TRY 2757 { 2758 ProbeForRead(pdsm, sizeof(DOSENDMESSAGE), 1); 2759 RtlCopyMemory(&dsm, pdsm, sizeof(DOSENDMESSAGE)); 2760 } 2761 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2762 { 2763 _SEH2_YIELD(break); 2764 } 2765 _SEH2_END; 2766 } 2767 2768 Ret = co_IntDoSendMessage( hWnd, Msg, wParam, lParam, pdsm ? &dsm : NULL ); 2769 2770 if (pdsm) 2771 { 2772 _SEH2_TRY 2773 { 2774 ProbeForWrite(pdsm, sizeof(DOSENDMESSAGE), 1); 2775 RtlCopyMemory(pdsm, &dsm, sizeof(DOSENDMESSAGE)); 2776 } 2777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2778 { 2779 Ret = FALSE; 2780 _SEH2_YIELD(break); 2781 } 2782 _SEH2_END; 2783 } 2784 break; 2785 } 2786 // CallNextHook bypass. 2787 case FNID_CALLWNDPROC: 2788 case FNID_CALLWNDPROCRET: 2789 { 2790 PTHREADINFO pti; 2791 PCLIENTINFO ClientInfo; 2792 PHOOK NextObj, Hook; 2793 2794 pti = GetW32ThreadInfo(); 2795 2796 Hook = pti->sphkCurrent; 2797 2798 if (!Hook) break; 2799 2800 NextObj = Hook->phkNext; 2801 ClientInfo = pti->pClientInfo; 2802 _SEH2_TRY 2803 { 2804 ClientInfo->phkCurrent = NextObj; 2805 } 2806 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2807 { 2808 ClientInfo = NULL; 2809 } 2810 _SEH2_END; 2811 2812 if (!ClientInfo || !NextObj) break; 2813 2814 NextObj->phkNext = IntGetNextHook(NextObj); 2815 2816 if ( Hook->HookId == WH_CALLWNDPROC) 2817 { 2818 CWPSTRUCT CWP; 2819 CWP.hwnd = hWnd; 2820 CWP.message = Msg; 2821 CWP.wParam = wParam; 2822 CWP.lParam = lParam; 2823 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook, NextObj); 2824 2825 lResult = co_IntCallHookProc( Hook->HookId, 2826 HC_ACTION, 2827 ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0), 2828 (LPARAM)&CWP, 2829 Hook->Proc, 2830 Hook->ihmod, 2831 Hook->offPfn, 2832 Hook->Ansi, 2833 &Hook->ModuleName); 2834 } 2835 else 2836 { 2837 CWPRETSTRUCT CWPR; 2838 CWPR.hwnd = hWnd; 2839 CWPR.message = Msg; 2840 CWPR.wParam = wParam; 2841 CWPR.lParam = lParam; 2842 CWPR.lResult = ClientInfo->dwHookData; 2843 2844 lResult = co_IntCallHookProc( Hook->HookId, 2845 HC_ACTION, 2846 ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0), 2847 (LPARAM)&CWPR, 2848 Hook->Proc, 2849 Hook->ihmod, 2850 Hook->offPfn, 2851 Hook->Ansi, 2852 &Hook->ModuleName); 2853 } 2854 } 2855 break; 2856 } 2857 2858 switch(dwType) 2859 { 2860 case FNID_DEFWINDOWPROC: 2861 case FNID_CALLWNDPROC: 2862 case FNID_CALLWNDPROCRET: 2863 case FNID_SCROLLBAR: 2864 case FNID_DESKTOP: 2865 case FNID_MENU: 2866 if (ResultInfo) 2867 { 2868 _SEH2_TRY 2869 { 2870 ProbeForWrite((PVOID)ResultInfo, sizeof(LRESULT), 1); 2871 RtlCopyMemory((PVOID)ResultInfo, &lResult, sizeof(LRESULT)); 2872 } 2873 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2874 { 2875 Ret = FALSE; 2876 } 2877 _SEH2_END; 2878 } 2879 break; 2880 default: 2881 break; 2882 } 2883 2884 UserLeave(); 2885 2886 return Ret; 2887 } 2888 2889 #define INFINITE 0xFFFFFFFF 2890 #define WAIT_FAILED ((DWORD)0xFFFFFFFF) 2891 2892 DWORD 2893 APIENTRY 2894 NtUserWaitForInputIdle( IN HANDLE hProcess, 2895 IN DWORD dwMilliseconds, 2896 IN BOOL Unknown2) 2897 { 2898 PEPROCESS Process; 2899 PPROCESSINFO W32Process; 2900 PTHREADINFO pti; 2901 NTSTATUS Status; 2902 HANDLE Handles[3]; 2903 LARGE_INTEGER Timeout; 2904 KAPC_STATE ApcState; 2905 2906 UserEnterExclusive(); 2907 2908 Status = ObReferenceObjectByHandle(hProcess, 2909 PROCESS_QUERY_INFORMATION, 2910 *PsProcessType, 2911 UserMode, 2912 (PVOID*)&Process, 2913 NULL); 2914 2915 if (!NT_SUCCESS(Status)) 2916 { 2917 UserLeave(); 2918 SetLastNtError(Status); 2919 return WAIT_FAILED; 2920 } 2921 2922 pti = PsGetCurrentThreadWin32Thread(); 2923 2924 W32Process = (PPROCESSINFO)Process->Win32Process; 2925 2926 if ( PsGetProcessExitProcessCalled(Process) || 2927 !W32Process || 2928 pti->ppi == W32Process) 2929 { 2930 ObDereferenceObject(Process); 2931 UserLeave(); 2932 EngSetLastError(ERROR_INVALID_PARAMETER); 2933 return WAIT_FAILED; 2934 } 2935 2936 Handles[0] = Process; 2937 Handles[1] = W32Process->InputIdleEvent; 2938 Handles[2] = pti->pEventQueueServer; // IntMsqSetWakeMask returns hEventQueueClient 2939 2940 if (!Handles[1]) 2941 { 2942 ObDereferenceObject(Process); 2943 UserLeave(); 2944 return STATUS_SUCCESS; /* no event to wait on */ 2945 } 2946 2947 if (dwMilliseconds != INFINITE) 2948 Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000; 2949 2950 KeStackAttachProcess(&Process->Pcb, &ApcState); 2951 2952 W32Process->W32PF_flags |= W32PF_WAITFORINPUTIDLE; 2953 for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling) 2954 { 2955 pti->TIF_flags |= TIF_WAITFORINPUTIDLE; 2956 pti->pClientInfo->dwTIFlags = pti->TIF_flags; 2957 } 2958 2959 KeUnstackDetachProcess(&ApcState); 2960 2961 TRACE("WFII: ppi %p\n", W32Process); 2962 TRACE("WFII: waiting for %p\n", Handles[1] ); 2963 2964 /* 2965 * We must add a refcount to our current PROCESSINFO, 2966 * because anything could happen (including process death) we're leaving win32k 2967 */ 2968 IntReferenceProcessInfo(W32Process); 2969 2970 do 2971 { 2972 UserLeave(); 2973 Status = KeWaitForMultipleObjects( 3, 2974 Handles, 2975 WaitAny, 2976 UserRequest, 2977 UserMode, 2978 FALSE, 2979 dwMilliseconds == INFINITE ? NULL : &Timeout, 2980 NULL); 2981 UserEnterExclusive(); 2982 2983 if (!NT_SUCCESS(Status)) 2984 { 2985 SetLastNtError(Status); 2986 Status = WAIT_FAILED; 2987 goto WaitExit; 2988 } 2989 2990 switch (Status) 2991 { 2992 case STATUS_WAIT_0: 2993 goto WaitExit; 2994 2995 case STATUS_WAIT_2: 2996 { 2997 MSG Msg; 2998 co_IntGetPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE, FALSE); 2999 ERR("WFII: WAIT 2\n"); 3000 } 3001 break; 3002 3003 case STATUS_TIMEOUT: 3004 ERR("WFII: timeout\n"); 3005 case WAIT_FAILED: 3006 goto WaitExit; 3007 3008 default: 3009 ERR("WFII: finished\n"); 3010 Status = STATUS_SUCCESS; 3011 goto WaitExit; 3012 } 3013 } 3014 while (TRUE); 3015 3016 WaitExit: 3017 for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling) 3018 { 3019 pti->TIF_flags &= ~TIF_WAITFORINPUTIDLE; 3020 pti->pClientInfo->dwTIFlags = pti->TIF_flags; 3021 } 3022 W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE; 3023 IntDereferenceProcessInfo(W32Process); 3024 ObDereferenceObject(Process); 3025 UserLeave(); 3026 return Status; 3027 } 3028 3029 /* EOF */ 3030