1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Win32k subsystem 4 * PURPOSE: Callback to usermode support 5 * FILE: win32ss/user/ntuser/callback.c 6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * Thomas Weidenmueller (w3seek@users.sourceforge.net) 8 * NOTES: Please use the Callback Memory Management functions for 9 * callbacks to make sure, the memory is freed on thread 10 * termination! 11 */ 12 13 #include <win32k.h> 14 DBG_DEFAULT_CHANNEL(UserCallback); 15 16 17 /* CALLBACK MEMORY MANAGEMENT ************************************************/ 18 19 typedef struct _INT_CALLBACK_HEADER 20 { 21 /* List entry in the THREADINFO structure */ 22 LIST_ENTRY ListEntry; 23 } 24 INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER; 25 26 PVOID FASTCALL 27 IntCbAllocateMemory(ULONG Size) 28 { 29 PINT_CALLBACK_HEADER Mem; 30 PTHREADINFO W32Thread; 31 32 if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER), 33 USERTAG_CALLBACK))) 34 { 35 return NULL; 36 } 37 38 RtlZeroMemory(Mem, Size + sizeof(INT_CALLBACK_HEADER)); 39 W32Thread = PsGetCurrentThreadWin32Thread(); 40 ASSERT(W32Thread); 41 42 /* Insert the callback memory into the thread's callback list */ 43 44 InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry); 45 46 return (Mem + 1); 47 } 48 49 VOID FASTCALL 50 IntCbFreeMemory(PVOID Data) 51 { 52 PINT_CALLBACK_HEADER Mem; 53 PTHREADINFO W32Thread; 54 55 W32Thread = PsGetCurrentThreadWin32Thread(); 56 ASSERT(W32Thread); 57 58 if (W32Thread->TIF_flags & TIF_INCLEANUP) 59 { 60 ERR("CbFM Thread is already in cleanup\n"); 61 return; 62 } 63 64 ASSERT(Data); 65 66 Mem = ((PINT_CALLBACK_HEADER)Data - 1); 67 68 /* Remove the memory block from the thread's callback list */ 69 RemoveEntryList(&Mem->ListEntry); 70 71 /* Free memory */ 72 ExFreePoolWithTag(Mem, USERTAG_CALLBACK); 73 } 74 75 VOID FASTCALL 76 IntCleanupThreadCallbacks(PTHREADINFO W32Thread) 77 { 78 PLIST_ENTRY CurrentEntry; 79 PINT_CALLBACK_HEADER Mem; 80 81 while (!IsListEmpty(&W32Thread->W32CallbackListHead)) 82 { 83 CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead); 84 Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER, 85 ListEntry); 86 87 /* Free memory */ 88 ExFreePoolWithTag(Mem, USERTAG_CALLBACK); 89 } 90 } 91 92 // 93 // Pass the Current Window handle and pointer to the Client Callback. 94 // This will help user space programs speed up read access with the window object. 95 // 96 static VOID 97 IntSetTebWndCallback (HWND * hWnd, PWND * pWnd, PVOID * pActCtx) 98 { 99 HWND hWndS = *hWnd; 100 PWND Window = UserGetWindowObject(*hWnd); 101 PCLIENTINFO ClientInfo = GetWin32ClientInfo(); 102 103 *hWnd = ClientInfo->CallbackWnd.hWnd; 104 *pWnd = ClientInfo->CallbackWnd.pWnd; 105 *pActCtx = ClientInfo->CallbackWnd.pActCtx; 106 107 if (Window) 108 { 109 ClientInfo->CallbackWnd.hWnd = hWndS; 110 ClientInfo->CallbackWnd.pWnd = DesktopHeapAddressToUser(Window); 111 ClientInfo->CallbackWnd.pActCtx = Window->pActCtx; 112 } 113 else //// What if Dispatching WM_SYS/TIMER with NULL window? Fix AbiWord Crash when sizing. 114 { 115 ClientInfo->CallbackWnd.hWnd = hWndS; 116 ClientInfo->CallbackWnd.pWnd = Window; 117 ClientInfo->CallbackWnd.pActCtx = 0; 118 } 119 } 120 121 static VOID 122 IntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx) 123 { 124 PCLIENTINFO ClientInfo = GetWin32ClientInfo(); 125 126 ClientInfo->CallbackWnd.hWnd = hWnd; 127 ClientInfo->CallbackWnd.pWnd = pWnd; 128 ClientInfo->CallbackWnd.pActCtx = pActCtx; 129 } 130 131 /* FUNCTIONS *****************************************************************/ 132 133 /* Calls ClientLoadLibrary in user32 */ 134 BOOL 135 NTAPI 136 co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, 137 PUNICODE_STRING pstrInitFunc, 138 BOOL Unload, 139 BOOL ApiHook) 140 { 141 PVOID ResultPointer; 142 ULONG ResultLength; 143 ULONG ArgumentLength; 144 PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments; 145 NTSTATUS Status; 146 BOOL bResult; 147 ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0; 148 149 /* Do not allow the desktop thread to do callback to user mode */ 150 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 151 152 TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook); 153 154 /* Calculate the size of the argument */ 155 ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS); 156 if(pstrLibName) 157 { 158 pLibNameBuffer = ArgumentLength; 159 ArgumentLength += pstrLibName->Length + sizeof(WCHAR); 160 } 161 if(pstrInitFunc) 162 { 163 pInitFuncBuffer = ArgumentLength; 164 ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR); 165 } 166 167 /* Allocate the argument */ 168 pArguments = IntCbAllocateMemory(ArgumentLength); 169 if(pArguments == NULL) 170 { 171 return FALSE; 172 } 173 174 /* Fill the argument */ 175 pArguments->Unload = Unload; 176 pArguments->ApiHook = ApiHook; 177 if(pstrLibName) 178 { 179 /* Copy the string to the callback memory */ 180 pLibNameBuffer += (ULONG_PTR)pArguments; 181 pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer; 182 pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR); 183 RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName); 184 185 /* Fix argument pointer to be relative to the argument */ 186 pLibNameBuffer -= (ULONG_PTR)pArguments; 187 pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer); 188 } 189 190 if(pstrInitFunc) 191 { 192 /* Copy the strings to the callback memory */ 193 pInitFuncBuffer += (ULONG_PTR)pArguments; 194 pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer; 195 pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR); 196 RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc); 197 198 /* Fix argument pointers to be relative to the argument */ 199 pInitFuncBuffer -= (ULONG_PTR)pArguments; 200 pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer); 201 } 202 203 /* Do the callback */ 204 UserLeaveCo(); 205 206 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY, 207 pArguments, 208 ArgumentLength, 209 &ResultPointer, 210 &ResultLength); 211 212 UserEnterCo(); 213 214 /* Free the argument */ 215 IntCbFreeMemory(pArguments); 216 217 if(!NT_SUCCESS(Status)) 218 { 219 return FALSE; 220 } 221 222 _SEH2_TRY 223 { 224 /* Probe and copy the usermode result data */ 225 ProbeForRead(ResultPointer, sizeof(HMODULE), 1); 226 bResult = *(BOOL*)ResultPointer; 227 } 228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 229 { 230 bResult = FALSE; 231 } 232 _SEH2_END; 233 234 return bResult; 235 } 236 237 VOID APIENTRY 238 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback, 239 HWND hWnd, 240 UINT Msg, 241 ULONG_PTR CompletionCallbackContext, 242 LRESULT Result) 243 { 244 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments; 245 PVOID ResultPointer, pActCtx; 246 PWND pWnd; 247 ULONG ResultLength; 248 NTSTATUS Status; 249 250 /* Do not allow the desktop thread to do callback to user mode */ 251 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 252 253 Arguments.Callback = CompletionCallback; 254 Arguments.Wnd = hWnd; 255 Arguments.Msg = Msg; 256 Arguments.Context = CompletionCallbackContext; 257 Arguments.Result = Result; 258 259 IntSetTebWndCallback (&hWnd, &pWnd, &pActCtx); 260 261 UserLeaveCo(); 262 263 Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC, 264 &Arguments, 265 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS), 266 &ResultPointer, 267 &ResultLength); 268 269 UserEnterCo(); 270 271 IntRestoreTebWndCallback (hWnd, pWnd, pActCtx); 272 273 if (!NT_SUCCESS(Status)) 274 { 275 ERR("KeUserModeCallback failed with %lx\n", Status); 276 return; 277 } 278 return; 279 } 280 281 LRESULT APIENTRY 282 co_IntCallWindowProc(WNDPROC Proc, 283 BOOLEAN IsAnsiProc, 284 HWND Wnd, 285 UINT Message, 286 WPARAM wParam, 287 LPARAM lParam, 288 INT lParamBufferSize) 289 { 290 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments = { 0 }; 291 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments; 292 NTSTATUS Status; 293 PVOID ResultPointer, pActCtx; 294 PWND pWnd; 295 ULONG ResultLength; 296 ULONG ArgumentLength; 297 LRESULT Result; 298 299 TRACE("co_IntCallWindowProc(Proc %p, IsAnsiProc: %s, Wnd %p, Message %u, wParam %Iu, lParam %Id, lParamBufferSize %d)\n", 300 Proc, IsAnsiProc ? "TRUE" : "FALSE", Wnd, Message, wParam, lParam, lParamBufferSize); 301 302 /* Do not allow the desktop thread to do callback to user mode */ 303 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 304 305 if (lParamBufferSize != -1) 306 { 307 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; 308 Arguments = IntCbAllocateMemory(ArgumentLength); 309 if (NULL == Arguments) 310 { 311 ERR("Unable to allocate buffer for window proc callback\n"); 312 return -1; 313 } 314 RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), 315 (PVOID) lParam, lParamBufferSize); 316 } 317 else 318 { 319 Arguments = &StackArguments; 320 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS); 321 } 322 Arguments->Proc = Proc; 323 Arguments->IsAnsiProc = IsAnsiProc; 324 Arguments->Wnd = Wnd; 325 Arguments->Msg = Message; 326 Arguments->wParam = wParam; 327 Arguments->lParam = lParam; 328 Arguments->lParamBufferSize = lParamBufferSize; 329 ResultPointer = NULL; 330 ResultLength = ArgumentLength; 331 332 IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx); 333 334 UserLeaveCo(); 335 336 Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC, 337 Arguments, 338 ArgumentLength, 339 &ResultPointer, 340 &ResultLength); 341 if (!NT_SUCCESS(Status)) 342 { 343 ERR("Error Callback to User space Status %lx Message %d\n",Status,Message); 344 UserEnterCo(); 345 return 0; 346 } 347 348 _SEH2_TRY 349 { 350 /* Simulate old behaviour: copy into our local buffer */ 351 RtlMoveMemory(Arguments, ResultPointer, ArgumentLength); 352 } 353 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 354 { 355 ERR("Failed to copy result from user mode, Message %u lParam size %d!\n", Message, lParamBufferSize); 356 Status = _SEH2_GetExceptionCode(); 357 } 358 _SEH2_END; 359 360 UserEnterCo(); 361 362 IntRestoreTebWndCallback (Wnd, pWnd, pActCtx); 363 364 if (!NT_SUCCESS(Status)) 365 { 366 ERR("Call to user mode failed! 0x%08lx\n",Status); 367 if (lParamBufferSize != -1) 368 { 369 IntCbFreeMemory(Arguments); 370 } 371 return -1; 372 } 373 Result = Arguments->Result; 374 375 if (lParamBufferSize != -1) 376 { 377 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 378 // Is this message being processed from inside kernel space? 379 BOOL InSendMessage = (pti->pcti->CTI_flags & CTI_INSENDMESSAGE); 380 381 TRACE("Copy lParam Message %u lParam %d!\n", Message, lParam); 382 switch (Message) 383 { 384 default: 385 TRACE("Don't copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam); 386 break; 387 // Write back to user/kernel space. Also see g_MsgMemory. 388 case WM_CREATE: 389 case WM_GETMINMAXINFO: 390 case WM_GETTEXT: 391 case WM_NCCALCSIZE: 392 case WM_NCCREATE: 393 case WM_STYLECHANGING: 394 case WM_WINDOWPOSCHANGING: 395 case WM_SIZING: 396 case WM_MOVING: 397 case WM_MEASUREITEM: 398 case WM_NEXTMENU: 399 TRACE("Copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam); 400 if (InSendMessage) 401 // Copy into kernel space. 402 RtlMoveMemory((PVOID) lParam, 403 (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), 404 lParamBufferSize); 405 else 406 { 407 _SEH2_TRY 408 { // Copy into user space. 409 RtlMoveMemory((PVOID) lParam, 410 (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), 411 lParamBufferSize); 412 } 413 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 414 { 415 ERR("Failed to copy lParam to user space, Message %u!\n", Message); 416 } 417 _SEH2_END; 418 } 419 break; 420 } 421 IntCbFreeMemory(Arguments); 422 } 423 424 return Result; 425 } 426 427 HMENU APIENTRY 428 co_IntLoadSysMenuTemplate(VOID) 429 { 430 LRESULT Result = 0; 431 NTSTATUS Status; 432 PVOID ResultPointer; 433 ULONG ResultLength; 434 435 /* Do not allow the desktop thread to do callback to user mode */ 436 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 437 438 ResultPointer = NULL; 439 ResultLength = sizeof(LRESULT); 440 441 UserLeaveCo(); 442 443 Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE, 444 &ResultPointer, 445 0, 446 &ResultPointer, 447 &ResultLength); 448 if (NT_SUCCESS(Status)) 449 { 450 /* Simulate old behaviour: copy into our local buffer */ 451 _SEH2_TRY 452 { 453 ProbeForRead(ResultPointer, sizeof(LRESULT), 1); 454 Result = *(LRESULT*)ResultPointer; 455 } 456 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 457 { 458 Result = 0; 459 } 460 _SEH2_END; 461 } 462 463 UserEnterCo(); 464 465 return (HMENU)Result; 466 } 467 468 extern HCURSOR gDesktopCursor; 469 470 BOOL APIENTRY 471 co_IntLoadDefaultCursors(VOID) 472 { 473 NTSTATUS Status; 474 PVOID ResultPointer; 475 ULONG ResultLength; 476 BOOL DefaultCursor = TRUE; 477 478 /* Do not allow the desktop thread to do callback to user mode */ 479 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 480 481 ResultPointer = NULL; 482 ResultLength = sizeof(HCURSOR); 483 484 UserLeaveCo(); 485 486 Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS, 487 &DefaultCursor, 488 sizeof(BOOL), 489 &ResultPointer, 490 &ResultLength); 491 492 UserEnterCo(); 493 494 if (!NT_SUCCESS(Status)) 495 { 496 return FALSE; 497 } 498 499 /* HACK: The desktop class doen't have a proper cursor yet, so set it here */ 500 gDesktopCursor = *((HCURSOR*)ResultPointer); 501 502 return TRUE; 503 } 504 505 static INT iTheId = -2; // Set it out of range. 506 507 LRESULT APIENTRY 508 co_IntCallHookProc(INT HookId, 509 INT Code, 510 WPARAM wParam, 511 LPARAM lParam, 512 HOOKPROC Proc, 513 INT Mod, 514 ULONG_PTR offPfn, 515 BOOLEAN Ansi, 516 PUNICODE_STRING ModuleName) 517 { 518 ULONG ArgumentLength; 519 PVOID Argument = NULL; 520 LRESULT Result = 0; 521 NTSTATUS Status; 522 PVOID ResultPointer; 523 ULONG ResultLength; 524 PHOOKPROC_CALLBACK_ARGUMENTS Common; 525 CBT_CREATEWNDW *CbtCreateWnd = NULL; 526 PCHAR Extra; 527 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; 528 PTHREADINFO pti; 529 PWND pWnd; 530 PMSG pMsg = NULL; 531 BOOL Hit = FALSE; 532 UINT lParamSize = 0; 533 CWPSTRUCT* pCWP = NULL; 534 CWPRETSTRUCT* pCWPR = NULL; 535 536 ASSERT(Proc); 537 /* Do not allow the desktop thread to do callback to user mode */ 538 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 539 540 pti = PsGetCurrentThreadWin32Thread(); 541 if (pti->TIF_flags & TIF_INCLEANUP) 542 { 543 ERR("Thread is in cleanup and trying to call hook %d\n", Code); 544 return 0; 545 } 546 547 ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS); 548 549 switch(HookId) 550 { 551 case WH_CBT: 552 TRACE("WH_CBT: Code %d\n", Code); 553 switch(Code) 554 { 555 case HCBT_CREATEWND: 556 pWnd = UserGetWindowObject((HWND) wParam); 557 if (!pWnd) 558 { 559 ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); 560 goto Fault_Exit; 561 } 562 TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False"); 563 // Due to KsStudio.exe, just pass the callers original pointers 564 // except class which point to kernel space if not an atom. 565 // Found by, Olaf Siejka 566 CbtCreateWnd = (CBT_CREATEWNDW *) lParam; 567 ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); 568 break; 569 570 case HCBT_MOVESIZE: 571 ArgumentLength += sizeof(RECTL); 572 break; 573 case HCBT_ACTIVATE: 574 ArgumentLength += sizeof(CBTACTIVATESTRUCT); 575 break; 576 case HCBT_CLICKSKIPPED: 577 ArgumentLength += sizeof(MOUSEHOOKSTRUCT); 578 break; 579 /* ATM pass on */ 580 case HCBT_KEYSKIPPED: 581 case HCBT_MINMAX: 582 case HCBT_SETFOCUS: 583 case HCBT_SYSCOMMAND: 584 /* These types pass through. */ 585 case HCBT_DESTROYWND: 586 case HCBT_QS: 587 break; 588 default: 589 ERR("Trying to call unsupported CBT hook %d\n", Code); 590 goto Fault_Exit; 591 } 592 break; 593 case WH_KEYBOARD_LL: 594 ArgumentLength += sizeof(KBDLLHOOKSTRUCT); 595 break; 596 case WH_MOUSE_LL: 597 ArgumentLength += sizeof(MSLLHOOKSTRUCT); 598 break; 599 case WH_MOUSE: 600 ArgumentLength += sizeof(MOUSEHOOKSTRUCT); 601 break; 602 case WH_CALLWNDPROC: 603 { 604 pCWP = (CWPSTRUCT*) lParam; 605 ArgumentLength = sizeof(CWP_Struct); 606 if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE ) 607 { 608 lParamSize = sizeof(CREATESTRUCTW); 609 } 610 else 611 lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); 612 ArgumentLength += lParamSize; 613 break; 614 } 615 case WH_CALLWNDPROCRET: 616 { 617 pCWPR = (CWPRETSTRUCT*) lParam; 618 ArgumentLength = sizeof(CWPR_Struct); 619 if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE ) 620 { 621 lParamSize = sizeof(CREATESTRUCTW); 622 } 623 else 624 lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); 625 ArgumentLength += lParamSize; 626 break; 627 } 628 case WH_MSGFILTER: 629 case WH_SYSMSGFILTER: 630 case WH_GETMESSAGE: 631 ArgumentLength += sizeof(MSG); 632 break; 633 case WH_FOREGROUNDIDLE: 634 case WH_KEYBOARD: 635 case WH_SHELL: 636 break; 637 default: 638 ERR("Trying to call unsupported window hook %d\n", HookId); 639 goto Fault_Exit; 640 } 641 642 Argument = IntCbAllocateMemory(ArgumentLength); 643 if (NULL == Argument) 644 { 645 ERR("HookProc callback %d failed: out of memory %d\n",HookId,ArgumentLength); 646 goto Fault_Exit; 647 } 648 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument; 649 Common->HookId = HookId; 650 Common->Code = Code; 651 Common->wParam = wParam; 652 Common->lParam = lParam; 653 Common->Proc = Proc; 654 Common->Mod = Mod; 655 Common->offPfn = offPfn; 656 Common->Ansi = Ansi; 657 Common->lParamSize = lParamSize; 658 if (ModuleName->Buffer && ModuleName->Length) 659 { 660 RtlCopyMemory(&Common->ModuleName, ModuleName->Buffer, ModuleName->Length); 661 // If ModuleName->Buffer NULL while in destroy, 662 // this will make User32:Hook.c complain about not loading the library module. 663 // Fix symptom for CORE-10549. 664 } 665 Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS); 666 667 switch(HookId) 668 { 669 case WH_CBT: 670 switch(Code) 671 { // Need to remember this is not the first time through! Call Next Hook? 672 case HCBT_CREATEWND: 673 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; 674 RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); 675 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; 676 CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; 677 CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; 678 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 679 //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, CbtCreateWnd->lpcs, CbtCreateWnd->lpcs->lpszName, CbtCreateWnd->lpcs->lpszClass); 680 break; 681 case HCBT_CLICKSKIPPED: 682 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); 683 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 684 break; 685 case HCBT_MOVESIZE: 686 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL)); 687 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 688 break; 689 case HCBT_ACTIVATE: 690 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT)); 691 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 692 break; 693 } 694 break; 695 case WH_KEYBOARD_LL: 696 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT)); 697 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 698 break; 699 case WH_MOUSE_LL: 700 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT)); 701 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 702 break; 703 case WH_MOUSE: 704 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); 705 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 706 break; 707 case WH_CALLWNDPROC: 708 { 709 PCWP_Struct pcwps = (PCWP_Struct)Common; 710 RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT)); 711 /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that 712 * lParam could be a pointer to a buffer. This buffer must be exported 713 * to user space too */ 714 if ( lParamSize ) 715 { 716 RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize ); 717 } 718 } 719 break; 720 case WH_CALLWNDPROCRET: 721 { 722 PCWPR_Struct pcwprs = (PCWPR_Struct)Common; 723 RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT)); 724 if ( lParamSize ) 725 { 726 RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize ); 727 } 728 } 729 break; 730 case WH_MSGFILTER: 731 case WH_SYSMSGFILTER: 732 case WH_GETMESSAGE: 733 pMsg = (PMSG)lParam; 734 RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG)); 735 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 736 break; 737 case WH_FOREGROUNDIDLE: 738 case WH_KEYBOARD: 739 case WH_SHELL: 740 break; 741 } 742 743 ResultPointer = NULL; 744 ResultLength = ArgumentLength; 745 746 UserLeaveCo(); 747 748 Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC, 749 Argument, 750 ArgumentLength, 751 &ResultPointer, 752 &ResultLength); 753 754 UserEnterCo(); 755 756 if (!NT_SUCCESS(Status)) 757 { 758 if ( iTheId != HookId ) // Hook ID can change. 759 { 760 ERR("Failure to make Callback %d! Status 0x%x ArgumentLength %d\n",HookId,Status,ArgumentLength); 761 iTheId = HookId; 762 } 763 goto Fault_Exit; 764 } 765 766 if (ResultPointer) 767 { 768 _SEH2_TRY 769 { 770 /* Simulate old behaviour: copy into our local buffer */ 771 RtlMoveMemory(Argument, ResultPointer, ArgumentLength); 772 Result = Common->Result; 773 } 774 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 775 { 776 Result = 0; 777 Hit = TRUE; 778 } 779 _SEH2_END; 780 } 781 else 782 { 783 ERR("ERROR: Hook %d Code %d ResultPointer 0x%p ResultLength %u\n",HookId,Code,ResultPointer,ResultLength); 784 } 785 786 /* Support write backs... SEH is in UserCallNextHookEx. */ 787 switch (HookId) 788 { 789 case WH_CBT: 790 { 791 switch (Code) 792 { 793 case HCBT_CREATEWND: 794 if (CbtCreatewndExtra) 795 {/* 796 The parameters could have been changed, include the coordinates 797 and dimensions of the window. We copy it back. 798 */ 799 CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; 800 CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x; 801 CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y; 802 CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx; 803 CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy; 804 } 805 break; 806 case HCBT_MOVESIZE: 807 if (Extra && lParam) 808 { 809 RtlCopyMemory((PVOID) lParam, Extra, sizeof(RECTL)); 810 } 811 break; 812 } 813 } 814 // "The GetMsgProc hook procedure can examine or modify the message." 815 case WH_GETMESSAGE: 816 if (pMsg) 817 { 818 RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG)); 819 } 820 break; 821 } 822 823 Fault_Exit: 824 if (Hit) 825 { 826 ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code); 827 } 828 if (Argument) IntCbFreeMemory(Argument); 829 830 return Result; 831 } 832 833 // 834 // Events are notifications w/o results. 835 // 836 LRESULT 837 APIENTRY 838 co_IntCallEventProc(HWINEVENTHOOK hook, 839 DWORD event, 840 HWND hWnd, 841 LONG idObject, 842 LONG idChild, 843 DWORD dwEventThread, 844 DWORD dwmsEventTime, 845 WINEVENTPROC Proc, 846 INT Mod, 847 ULONG_PTR offPfn) 848 { 849 LRESULT Result = 0; 850 NTSTATUS Status; 851 PEVENTPROC_CALLBACK_ARGUMENTS Common; 852 ULONG ArgumentLength, ResultLength; 853 PVOID Argument, ResultPointer; 854 855 ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS); 856 857 Argument = IntCbAllocateMemory(ArgumentLength); 858 if (NULL == Argument) 859 { 860 ERR("EventProc callback failed: out of memory\n"); 861 return 0; 862 } 863 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument; 864 Common->hook = hook; 865 Common->event = event; 866 Common->hwnd = hWnd; 867 Common->idObject = idObject; 868 Common->idChild = idChild; 869 Common->dwEventThread = dwEventThread; 870 Common->dwmsEventTime = dwmsEventTime; 871 Common->Proc = Proc; 872 Common->Mod = Mod; 873 Common->offPfn = offPfn; 874 875 ResultPointer = NULL; 876 ResultLength = sizeof(LRESULT); 877 878 UserLeaveCo(); 879 880 Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC, 881 Argument, 882 ArgumentLength, 883 &ResultPointer, 884 &ResultLength); 885 886 UserEnterCo(); 887 888 IntCbFreeMemory(Argument); 889 890 if (!NT_SUCCESS(Status)) 891 { 892 return 0; 893 } 894 895 return Result; 896 } 897 898 // 899 // Callback Load Menu and results. 900 // 901 HMENU 902 APIENTRY 903 co_IntCallLoadMenu( HINSTANCE hModule, 904 PUNICODE_STRING pMenuName ) 905 { 906 LRESULT Result = 0; 907 NTSTATUS Status; 908 PLOADMENU_CALLBACK_ARGUMENTS Common; 909 ULONG ArgumentLength, ResultLength; 910 PVOID Argument, ResultPointer; 911 912 ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS); 913 914 ArgumentLength += pMenuName->Length + sizeof(WCHAR); 915 916 Argument = IntCbAllocateMemory(ArgumentLength); 917 if (NULL == Argument) 918 { 919 ERR("LoadMenu callback failed: out of memory\n"); 920 return 0; 921 } 922 Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument; 923 924 Common->hModule = hModule; 925 if (pMenuName->Length) 926 RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length); 927 else 928 Common->InterSource = pMenuName->Buffer; 929 930 ResultPointer = NULL; 931 ResultLength = sizeof(LRESULT); 932 933 UserLeaveCo(); 934 935 Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU, 936 Argument, 937 ArgumentLength, 938 &ResultPointer, 939 &ResultLength); 940 941 UserEnterCo(); 942 943 if (NT_SUCCESS(Status)) 944 { 945 Result = *(LRESULT*)ResultPointer; 946 } 947 else 948 { 949 Result = 0; 950 } 951 952 IntCbFreeMemory(Argument); 953 954 return (HMENU)Result; 955 } 956 957 NTSTATUS 958 APIENTRY 959 co_IntClientThreadSetup(VOID) 960 { 961 NTSTATUS Status; 962 ULONG ArgumentLength, ResultLength; 963 PVOID Argument, ResultPointer; 964 965 /* Do not allow the desktop thread to do callback to user mode */ 966 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 967 968 ArgumentLength = ResultLength = 0; 969 Argument = ResultPointer = NULL; 970 971 UserLeaveCo(); 972 973 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP, 974 Argument, 975 ArgumentLength, 976 &ResultPointer, 977 &ResultLength); 978 979 UserEnterCo(); 980 981 return Status; 982 } 983 984 HANDLE FASTCALL 985 co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags) 986 { 987 HANDLE Handle; 988 NTSTATUS Status; 989 ULONG ArgumentLength, ResultLength; 990 PVOID Argument, ResultPointer; 991 PCOPYIMAGE_CALLBACK_ARGUMENTS Common; 992 993 ArgumentLength = ResultLength = 0; 994 Argument = ResultPointer = NULL; 995 996 ArgumentLength = sizeof(COPYIMAGE_CALLBACK_ARGUMENTS); 997 998 Argument = IntCbAllocateMemory(ArgumentLength); 999 if (NULL == Argument) 1000 { 1001 ERR("CopyImage callback failed: out of memory\n"); 1002 return 0; 1003 } 1004 Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Argument; 1005 1006 Common->hImage = hnd; 1007 Common->uType = type; 1008 Common->cxDesired = desiredx; 1009 Common->cyDesired = desiredy; 1010 Common->fuFlags = flags; 1011 1012 UserLeaveCo(); 1013 1014 Status = KeUserModeCallback(USER32_CALLBACK_COPYIMAGE, 1015 Argument, 1016 ArgumentLength, 1017 &ResultPointer, 1018 &ResultLength); 1019 1020 1021 UserEnterCo(); 1022 1023 if (NT_SUCCESS(Status)) 1024 { 1025 Handle = *(HANDLE*)ResultPointer; 1026 } 1027 else 1028 { 1029 ERR("CopyImage callback failed!\n"); 1030 Handle = NULL; 1031 } 1032 1033 IntCbFreeMemory(Argument); 1034 1035 return Handle; 1036 } 1037 1038 BOOL 1039 APIENTRY 1040 co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs) 1041 { 1042 NTSTATUS Status; 1043 ULONG ArgumentLength, ResultLength; 1044 PVOID Argument, ResultPointer; 1045 PGET_CHARSET_INFO Common; 1046 1047 ArgumentLength = sizeof(GET_CHARSET_INFO); 1048 1049 Argument = IntCbAllocateMemory(ArgumentLength); 1050 if (NULL == Argument) 1051 { 1052 ERR("GetCharsetInfo callback failed: out of memory\n"); 1053 return 0; 1054 } 1055 Common = (PGET_CHARSET_INFO) Argument; 1056 1057 Common->Locale = Locale; 1058 1059 ResultPointer = NULL; 1060 ResultLength = ArgumentLength; 1061 1062 UserLeaveCo(); 1063 1064 Status = KeUserModeCallback(USER32_CALLBACK_GETCHARSETINFO, 1065 Argument, 1066 ArgumentLength, 1067 &ResultPointer, 1068 &ResultLength); 1069 1070 if (NT_SUCCESS(Status)) 1071 { 1072 _SEH2_TRY 1073 { 1074 /* Need to copy into our local buffer */ 1075 RtlMoveMemory(Argument, ResultPointer, ArgumentLength); 1076 } 1077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1078 { 1079 ERR("Failed to copy result from user mode!\n"); 1080 Status = _SEH2_GetExceptionCode(); 1081 } 1082 _SEH2_END; 1083 } 1084 1085 UserEnterCo(); 1086 1087 RtlCopyMemory(pCs, &Common->Cs, sizeof(CHARSETINFO)); 1088 1089 IntCbFreeMemory(Argument); 1090 1091 if (!NT_SUCCESS(Status)) 1092 { 1093 ERR("GetCharsetInfo Failed!!\n"); 1094 return FALSE; 1095 } 1096 1097 return TRUE; 1098 } 1099 1100 BOOL FASTCALL 1101 co_IntSetWndIcons(VOID) 1102 { 1103 NTSTATUS Status; 1104 ULONG ArgumentLength, ResultLength; 1105 PVOID Argument, ResultPointer; 1106 PSETWNDICONS_CALLBACK_ARGUMENTS Common; 1107 1108 ResultPointer = NULL; 1109 ResultLength = ArgumentLength = sizeof(SETWNDICONS_CALLBACK_ARGUMENTS); 1110 1111 Argument = IntCbAllocateMemory(ArgumentLength); 1112 if (NULL == Argument) 1113 { 1114 ERR("Set Window Icons callback failed: out of memory\n"); 1115 return FALSE; 1116 } 1117 Common = (PSETWNDICONS_CALLBACK_ARGUMENTS) Argument; 1118 1119 UserLeaveCo(); 1120 1121 Status = KeUserModeCallback(USER32_CALLBACK_SETWNDICONS, 1122 Argument, 1123 ArgumentLength, 1124 &ResultPointer, 1125 &ResultLength); 1126 1127 1128 UserEnterCo(); 1129 1130 if (!NT_SUCCESS(Status)) 1131 { 1132 ERR("Set Window Icons callback failed!\n"); 1133 IntCbFreeMemory(Argument); 1134 return FALSE; 1135 } 1136 1137 RtlMoveMemory(Common, ResultPointer, ArgumentLength); 1138 gpsi->hIconSmWindows = Common->hIconSmWindows; 1139 gpsi->hIconWindows = Common->hIconWindows; 1140 1141 IntLoadSystenIcons(Common->hIconSample, OIC_SAMPLE); 1142 IntLoadSystenIcons(Common->hIconHand, OIC_HAND); 1143 IntLoadSystenIcons(Common->hIconQuestion, OIC_QUES); 1144 IntLoadSystenIcons(Common->hIconBang, OIC_BANG); 1145 IntLoadSystenIcons(Common->hIconNote, OIC_NOTE); 1146 IntLoadSystenIcons(gpsi->hIconWindows, OIC_WINLOGO); 1147 IntLoadSystenIcons(gpsi->hIconSmWindows, OIC_WINLOGO+1); 1148 1149 ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows); 1150 1151 IntCbFreeMemory(Argument); 1152 1153 return TRUE; 1154 } 1155 1156 VOID FASTCALL 1157 co_IntDeliverUserAPC(VOID) 1158 { 1159 ULONG ResultLength; 1160 PVOID ResultPointer; 1161 NTSTATUS Status; 1162 UserLeaveCo(); 1163 1164 Status = KeUserModeCallback(USER32_CALLBACK_DELIVERUSERAPC, 1165 0, 1166 0, 1167 &ResultPointer, 1168 &ResultLength); 1169 1170 1171 UserEnterCo(); 1172 1173 if (!NT_SUCCESS(Status)) 1174 { 1175 ERR("Delivering User APC callback failed!\n"); 1176 } 1177 } 1178 1179 VOID FASTCALL 1180 co_IntSetupOBM(VOID) 1181 { 1182 NTSTATUS Status; 1183 ULONG ArgumentLength, ResultLength; 1184 PVOID Argument, ResultPointer; 1185 PSETOBM_CALLBACK_ARGUMENTS Common; 1186 1187 ResultPointer = NULL; 1188 ResultLength = ArgumentLength = sizeof(SETOBM_CALLBACK_ARGUMENTS); 1189 1190 Argument = IntCbAllocateMemory(ArgumentLength); 1191 if (NULL == Argument) 1192 { 1193 ERR("Set Window Icons callback failed: out of memory\n"); 1194 return; 1195 } 1196 Common = (PSETOBM_CALLBACK_ARGUMENTS) Argument; 1197 1198 UserLeaveCo(); 1199 1200 Status = KeUserModeCallback(USER32_CALLBACK_SETOBM, 1201 Argument, 1202 ArgumentLength, 1203 &ResultPointer, 1204 &ResultLength); 1205 1206 1207 UserEnterCo(); 1208 1209 if (!NT_SUCCESS(Status)) 1210 { 1211 ERR("Set Window Icons callback failed!\n"); 1212 IntCbFreeMemory(Argument); 1213 return; 1214 } 1215 1216 RtlMoveMemory(Common, ResultPointer, ArgumentLength); 1217 RtlCopyMemory(gpsi->oembmi, Common->oembmi, sizeof(gpsi->oembmi)); 1218 1219 IntCbFreeMemory(Argument); 1220 } 1221 1222 // 1223 // Called from Kernel GDI sides, no UserLeave/EnterCo required. 1224 // 1225 LRESULT 1226 APIENTRY 1227 co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize ) 1228 { 1229 NTSTATUS Status; 1230 PVOID ResultPointer; 1231 1232 Status = KeUserModeCallback( USER32_CALLBACK_UMPD, 1233 pkt, 1234 InSize, 1235 &ResultPointer, 1236 (PULONG)&OutSize ); 1237 1238 1239 if (!NT_SUCCESS(Status)) 1240 { 1241 ERR("User UMPD callback failed!\n"); 1242 return 1; 1243 } 1244 1245 if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize ); 1246 1247 return 0; 1248 } 1249 1250 // Win: ClientImmProcessKey 1251 DWORD 1252 APIENTRY 1253 co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) 1254 { 1255 DWORD ret = 0; 1256 NTSTATUS Status; 1257 ULONG ResultLength = sizeof(DWORD); 1258 PVOID ResultPointer = NULL; 1259 IMMPROCESSKEY_CALLBACK_ARGUMENTS Common = { hWnd, hKL, vKey, lParam, dwHotKeyID }; 1260 1261 UserLeaveCo(); 1262 Status = KeUserModeCallback(USER32_CALLBACK_IMMPROCESSKEY, 1263 &Common, 1264 sizeof(Common), 1265 &ResultPointer, 1266 &ResultLength); 1267 UserEnterCo(); 1268 1269 if (NT_SUCCESS(Status)) 1270 ret = *(LPDWORD)ResultPointer; 1271 1272 return ret; 1273 } 1274 1275 /* EOF */ 1276