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