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 static INT iTheId = -2; // Set it out of range. 513 514 LRESULT APIENTRY 515 co_IntCallHookProc(INT HookId, 516 INT Code, 517 WPARAM wParam, 518 LPARAM lParam, 519 HOOKPROC Proc, 520 INT Mod, 521 ULONG_PTR offPfn, 522 BOOLEAN Ansi, 523 PUNICODE_STRING ModuleName) 524 { 525 ULONG ArgumentLength; 526 PVOID Argument = NULL; 527 LRESULT Result = 0; 528 NTSTATUS Status; 529 PVOID ResultPointer; 530 ULONG ResultLength; 531 PHOOKPROC_CALLBACK_ARGUMENTS Common; 532 CBT_CREATEWNDW *CbtCreateWnd = NULL; 533 PCHAR Extra; 534 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; 535 PTHREADINFO pti; 536 PWND pWnd; 537 PMSG pMsg = NULL; 538 BOOL Hit = FALSE; 539 UINT lParamSize = 0; 540 CWPSTRUCT* pCWP = NULL; 541 CWPRETSTRUCT* pCWPR = NULL; 542 543 ASSERT(Proc); 544 /* Do not allow the desktop thread to do callback to user mode */ 545 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 546 547 pti = PsGetCurrentThreadWin32Thread(); 548 if (pti->TIF_flags & TIF_INCLEANUP) 549 { 550 ERR("Thread is in cleanup and trying to call hook %d\n", Code); 551 return 0; 552 } 553 554 ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS); 555 556 switch(HookId) 557 { 558 case WH_CBT: 559 TRACE("WH_CBT: Code %d\n", Code); 560 switch(Code) 561 { 562 case HCBT_CREATEWND: 563 pWnd = UserGetWindowObject((HWND) wParam); 564 if (!pWnd) 565 { 566 ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); 567 goto Fault_Exit; 568 } 569 TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False"); 570 // Due to KsStudio.exe, just pass the callers original pointers 571 // except class which point to kernel space if not an atom. 572 // Found by, Olaf Siejka 573 CbtCreateWnd = (CBT_CREATEWNDW *) lParam; 574 ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); 575 break; 576 577 case HCBT_MOVESIZE: 578 ArgumentLength += sizeof(RECTL); 579 break; 580 case HCBT_ACTIVATE: 581 ArgumentLength += sizeof(CBTACTIVATESTRUCT); 582 break; 583 case HCBT_CLICKSKIPPED: 584 ArgumentLength += sizeof(MOUSEHOOKSTRUCT); 585 break; 586 /* ATM pass on */ 587 case HCBT_KEYSKIPPED: 588 case HCBT_MINMAX: 589 case HCBT_SETFOCUS: 590 case HCBT_SYSCOMMAND: 591 /* These types pass through. */ 592 case HCBT_DESTROYWND: 593 case HCBT_QS: 594 break; 595 default: 596 ERR("Trying to call unsupported CBT hook %d\n", Code); 597 goto Fault_Exit; 598 } 599 break; 600 case WH_KEYBOARD_LL: 601 ArgumentLength += sizeof(KBDLLHOOKSTRUCT); 602 break; 603 case WH_MOUSE_LL: 604 ArgumentLength += sizeof(MSLLHOOKSTRUCT); 605 break; 606 case WH_MOUSE: 607 ArgumentLength += sizeof(MOUSEHOOKSTRUCT); 608 break; 609 case WH_CALLWNDPROC: 610 { 611 pCWP = (CWPSTRUCT*) lParam; 612 ArgumentLength = sizeof(CWP_Struct); 613 if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE ) 614 { 615 lParamSize = sizeof(CREATESTRUCTW); 616 } 617 else 618 lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); 619 ArgumentLength += lParamSize; 620 break; 621 } 622 case WH_CALLWNDPROCRET: 623 { 624 pCWPR = (CWPRETSTRUCT*) lParam; 625 ArgumentLength = sizeof(CWPR_Struct); 626 if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE ) 627 { 628 lParamSize = sizeof(CREATESTRUCTW); 629 } 630 else 631 lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); 632 ArgumentLength += lParamSize; 633 break; 634 } 635 case WH_MSGFILTER: 636 case WH_SYSMSGFILTER: 637 case WH_GETMESSAGE: 638 ArgumentLength += sizeof(MSG); 639 break; 640 case WH_FOREGROUNDIDLE: 641 case WH_KEYBOARD: 642 case WH_SHELL: 643 break; 644 default: 645 ERR("Trying to call unsupported window hook %d\n", HookId); 646 goto Fault_Exit; 647 } 648 649 Argument = IntCbAllocateMemory(ArgumentLength); 650 if (NULL == Argument) 651 { 652 ERR("HookProc callback %d failed: out of memory %d\n",HookId,ArgumentLength); 653 goto Fault_Exit; 654 } 655 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument; 656 Common->HookId = HookId; 657 Common->Code = Code; 658 Common->wParam = wParam; 659 Common->lParam = lParam; 660 Common->Proc = Proc; 661 Common->Mod = Mod; 662 Common->offPfn = offPfn; 663 Common->Ansi = Ansi; 664 Common->lParamSize = lParamSize; 665 RtlZeroMemory(&Common->ModuleName, sizeof(Common->ModuleName)); 666 if (ModuleName->Buffer && ModuleName->Length) 667 { 668 RtlCopyMemory(&Common->ModuleName, ModuleName->Buffer, ModuleName->Length); 669 // If ModuleName->Buffer NULL while in destroy, 670 // this will make User32:Hook.c complain about not loading the library module. 671 // Fix symptom for CORE-10549. 672 } 673 Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS); 674 675 switch(HookId) 676 { 677 case WH_CBT: 678 switch(Code) 679 { // Need to remember this is not the first time through! Call Next Hook? 680 case HCBT_CREATEWND: 681 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; 682 RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); 683 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; 684 CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; 685 CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; 686 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 687 //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, CbtCreateWnd->lpcs, CbtCreateWnd->lpcs->lpszName, CbtCreateWnd->lpcs->lpszClass); 688 break; 689 case HCBT_CLICKSKIPPED: 690 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); 691 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 692 break; 693 case HCBT_MOVESIZE: 694 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL)); 695 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 696 break; 697 case HCBT_ACTIVATE: 698 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT)); 699 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 700 break; 701 } 702 break; 703 case WH_KEYBOARD_LL: 704 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT)); 705 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 706 break; 707 case WH_MOUSE_LL: 708 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT)); 709 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 710 break; 711 case WH_MOUSE: 712 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); 713 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 714 break; 715 case WH_CALLWNDPROC: 716 { 717 PCWP_Struct pcwps = (PCWP_Struct)Common; 718 RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT)); 719 /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that 720 * lParam could be a pointer to a buffer. This buffer must be exported 721 * to user space too */ 722 if ( lParamSize ) 723 { 724 RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize ); 725 } 726 } 727 break; 728 case WH_CALLWNDPROCRET: 729 { 730 PCWPR_Struct pcwprs = (PCWPR_Struct)Common; 731 RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT)); 732 if ( lParamSize ) 733 { 734 RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize ); 735 } 736 } 737 break; 738 case WH_MSGFILTER: 739 case WH_SYSMSGFILTER: 740 case WH_GETMESSAGE: 741 pMsg = (PMSG)lParam; 742 RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG)); 743 Common->lParam = (LPARAM) (Extra - (PCHAR) Common); 744 break; 745 case WH_FOREGROUNDIDLE: 746 case WH_KEYBOARD: 747 case WH_SHELL: 748 break; 749 } 750 751 ResultPointer = NULL; 752 ResultLength = ArgumentLength; 753 754 UserLeaveCo(); 755 756 Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC, 757 Argument, 758 ArgumentLength, 759 &ResultPointer, 760 &ResultLength); 761 762 UserEnterCo(); 763 764 if (!NT_SUCCESS(Status)) 765 { 766 if ( iTheId != HookId ) // Hook ID can change. 767 { 768 ERR("Failure to make Callback %d! Status 0x%x ArgumentLength %d\n",HookId,Status,ArgumentLength); 769 iTheId = HookId; 770 } 771 goto Fault_Exit; 772 } 773 774 if (ResultPointer) 775 { 776 _SEH2_TRY 777 { 778 /* Simulate old behaviour: copy into our local buffer */ 779 RtlMoveMemory(Argument, ResultPointer, ArgumentLength); 780 Result = Common->Result; 781 } 782 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 783 { 784 Result = 0; 785 Hit = TRUE; 786 } 787 _SEH2_END; 788 } 789 else 790 { 791 ERR("ERROR: Hook %d Code %d ResultPointer 0x%p ResultLength %u\n",HookId,Code,ResultPointer,ResultLength); 792 } 793 794 /* Support write backs... SEH is in UserCallNextHookEx. */ 795 switch (HookId) 796 { 797 case WH_CBT: 798 { 799 switch (Code) 800 { 801 case HCBT_CREATEWND: 802 if (CbtCreatewndExtra) 803 {/* 804 The parameters could have been changed, include the coordinates 805 and dimensions of the window. We copy it back. 806 */ 807 CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; 808 CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x; 809 CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y; 810 CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx; 811 CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy; 812 } 813 break; 814 case HCBT_MOVESIZE: 815 if (Extra && lParam) 816 { 817 RtlCopyMemory((PVOID) lParam, Extra, sizeof(RECTL)); 818 } 819 break; 820 } 821 } 822 // "The GetMsgProc hook procedure can examine or modify the message." 823 case WH_GETMESSAGE: 824 if (pMsg) 825 { 826 RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG)); 827 } 828 break; 829 } 830 831 Fault_Exit: 832 if (Hit) 833 { 834 ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code); 835 } 836 if (Argument) IntCbFreeMemory(Argument); 837 838 return Result; 839 } 840 841 // 842 // Events are notifications w/o results. 843 // 844 LRESULT 845 APIENTRY 846 co_IntCallEventProc(HWINEVENTHOOK hook, 847 DWORD event, 848 HWND hWnd, 849 LONG idObject, 850 LONG idChild, 851 DWORD dwEventThread, 852 DWORD dwmsEventTime, 853 WINEVENTPROC Proc, 854 INT Mod, 855 ULONG_PTR offPfn) 856 { 857 LRESULT Result = 0; 858 NTSTATUS Status; 859 PEVENTPROC_CALLBACK_ARGUMENTS Common; 860 ULONG ArgumentLength, ResultLength; 861 PVOID Argument, ResultPointer; 862 863 ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS); 864 865 Argument = IntCbAllocateMemory(ArgumentLength); 866 if (NULL == Argument) 867 { 868 ERR("EventProc callback failed: out of memory\n"); 869 return 0; 870 } 871 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument; 872 Common->hook = hook; 873 Common->event = event; 874 Common->hwnd = hWnd; 875 Common->idObject = idObject; 876 Common->idChild = idChild; 877 Common->dwEventThread = dwEventThread; 878 Common->dwmsEventTime = dwmsEventTime; 879 Common->Proc = Proc; 880 Common->Mod = Mod; 881 Common->offPfn = offPfn; 882 883 ResultPointer = NULL; 884 ResultLength = sizeof(LRESULT); 885 886 UserLeaveCo(); 887 888 Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC, 889 Argument, 890 ArgumentLength, 891 &ResultPointer, 892 &ResultLength); 893 894 UserEnterCo(); 895 896 IntCbFreeMemory(Argument); 897 898 if (!NT_SUCCESS(Status)) 899 { 900 return 0; 901 } 902 903 return Result; 904 } 905 906 // 907 // Callback Load Menu and results. 908 // 909 HMENU 910 APIENTRY 911 co_IntCallLoadMenu( HINSTANCE hModule, 912 PUNICODE_STRING pMenuName ) 913 { 914 LRESULT Result = 0; 915 NTSTATUS Status; 916 PLOADMENU_CALLBACK_ARGUMENTS Common; 917 ULONG ArgumentLength, ResultLength; 918 PVOID Argument, ResultPointer; 919 920 ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS); 921 922 ArgumentLength += pMenuName->Length + sizeof(WCHAR); 923 924 Argument = IntCbAllocateMemory(ArgumentLength); 925 if (NULL == Argument) 926 { 927 ERR("LoadMenu callback failed: out of memory\n"); 928 return 0; 929 } 930 Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument; 931 932 // Help Intersource check and MenuName is now 4 bytes + so zero it. 933 RtlZeroMemory(Common, ArgumentLength); 934 935 Common->hModule = hModule; 936 if (pMenuName->Length) 937 RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length); 938 else 939 Common->InterSource = pMenuName->Buffer; 940 941 ResultPointer = NULL; 942 ResultLength = sizeof(LRESULT); 943 944 UserLeaveCo(); 945 946 Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU, 947 Argument, 948 ArgumentLength, 949 &ResultPointer, 950 &ResultLength); 951 952 UserEnterCo(); 953 954 if (NT_SUCCESS(Status)) 955 { 956 Result = *(LRESULT*)ResultPointer; 957 } 958 else 959 { 960 Result = 0; 961 } 962 963 IntCbFreeMemory(Argument); 964 965 return (HMENU)Result; 966 } 967 968 NTSTATUS 969 APIENTRY 970 co_IntClientThreadSetup(VOID) 971 { 972 NTSTATUS Status; 973 ULONG ArgumentLength, ResultLength; 974 PVOID Argument, ResultPointer; 975 976 /* Do not allow the desktop thread to do callback to user mode */ 977 ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread); 978 979 ArgumentLength = ResultLength = 0; 980 Argument = ResultPointer = NULL; 981 982 UserLeaveCo(); 983 984 Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP, 985 Argument, 986 ArgumentLength, 987 &ResultPointer, 988 &ResultLength); 989 990 UserEnterCo(); 991 992 return Status; 993 } 994 995 HANDLE FASTCALL 996 co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags) 997 { 998 HANDLE Handle; 999 NTSTATUS Status; 1000 ULONG ArgumentLength, ResultLength; 1001 PVOID Argument, ResultPointer; 1002 PCOPYIMAGE_CALLBACK_ARGUMENTS Common; 1003 1004 ArgumentLength = ResultLength = 0; 1005 Argument = ResultPointer = NULL; 1006 1007 ArgumentLength = sizeof(COPYIMAGE_CALLBACK_ARGUMENTS); 1008 1009 Argument = IntCbAllocateMemory(ArgumentLength); 1010 if (NULL == Argument) 1011 { 1012 ERR("CopyImage callback failed: out of memory\n"); 1013 return 0; 1014 } 1015 Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Argument; 1016 1017 Common->hImage = hnd; 1018 Common->uType = type; 1019 Common->cxDesired = desiredx; 1020 Common->cyDesired = desiredy; 1021 Common->fuFlags = flags; 1022 1023 UserLeaveCo(); 1024 1025 Status = KeUserModeCallback(USER32_CALLBACK_COPYIMAGE, 1026 Argument, 1027 ArgumentLength, 1028 &ResultPointer, 1029 &ResultLength); 1030 1031 1032 UserEnterCo(); 1033 1034 if (NT_SUCCESS(Status)) 1035 { 1036 Handle = *(HANDLE*)ResultPointer; 1037 } 1038 else 1039 { 1040 ERR("CopyImage callback failed!\n"); 1041 Handle = NULL; 1042 } 1043 1044 IntCbFreeMemory(Argument); 1045 1046 return Handle; 1047 } 1048 1049 BOOL 1050 APIENTRY 1051 co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs) 1052 { 1053 NTSTATUS Status; 1054 ULONG ArgumentLength, ResultLength; 1055 PVOID Argument, ResultPointer; 1056 PGET_CHARSET_INFO Common; 1057 1058 ArgumentLength = sizeof(GET_CHARSET_INFO); 1059 1060 Argument = IntCbAllocateMemory(ArgumentLength); 1061 if (NULL == Argument) 1062 { 1063 ERR("GetCharsetInfo callback failed: out of memory\n"); 1064 return 0; 1065 } 1066 Common = (PGET_CHARSET_INFO) Argument; 1067 1068 Common->Locale = Locale; 1069 1070 ResultPointer = NULL; 1071 ResultLength = ArgumentLength; 1072 1073 UserLeaveCo(); 1074 1075 Status = KeUserModeCallback(USER32_CALLBACK_GETCHARSETINFO, 1076 Argument, 1077 ArgumentLength, 1078 &ResultPointer, 1079 &ResultLength); 1080 1081 if (NT_SUCCESS(Status)) 1082 { 1083 _SEH2_TRY 1084 { 1085 /* Need to copy into our local buffer */ 1086 RtlMoveMemory(Argument, ResultPointer, ArgumentLength); 1087 } 1088 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1089 { 1090 ERR("Failed to copy result from user mode!\n"); 1091 Status = _SEH2_GetExceptionCode(); 1092 } 1093 _SEH2_END; 1094 } 1095 1096 UserEnterCo(); 1097 1098 RtlCopyMemory(pCs, &Common->Cs, sizeof(CHARSETINFO)); 1099 1100 IntCbFreeMemory(Argument); 1101 1102 if (!NT_SUCCESS(Status)) 1103 { 1104 ERR("GetCharsetInfo Failed!!\n"); 1105 return FALSE; 1106 } 1107 1108 return TRUE; 1109 } 1110 1111 BOOL FASTCALL 1112 co_IntSetWndIcons(VOID) 1113 { 1114 NTSTATUS Status; 1115 ULONG ArgumentLength, ResultLength; 1116 PVOID Argument, ResultPointer; 1117 PSETWNDICONS_CALLBACK_ARGUMENTS Common; 1118 1119 ResultPointer = NULL; 1120 ResultLength = ArgumentLength = sizeof(SETWNDICONS_CALLBACK_ARGUMENTS); 1121 1122 Argument = IntCbAllocateMemory(ArgumentLength); 1123 if (NULL == Argument) 1124 { 1125 ERR("Set Window Icons callback failed: out of memory\n"); 1126 return FALSE; 1127 } 1128 Common = (PSETWNDICONS_CALLBACK_ARGUMENTS) Argument; 1129 1130 UserLeaveCo(); 1131 1132 Status = KeUserModeCallback(USER32_CALLBACK_SETWNDICONS, 1133 Argument, 1134 ArgumentLength, 1135 &ResultPointer, 1136 &ResultLength); 1137 1138 1139 UserEnterCo(); 1140 1141 if (!NT_SUCCESS(Status)) 1142 { 1143 ERR("Set Window Icons callback failed!\n"); 1144 IntCbFreeMemory(Argument); 1145 return FALSE; 1146 } 1147 1148 RtlMoveMemory(Common, ResultPointer, ArgumentLength); 1149 gpsi->hIconSmWindows = Common->hIconSmWindows; 1150 gpsi->hIconWindows = Common->hIconWindows; 1151 1152 IntLoadSystenIcons(Common->hIconSample, OIC_SAMPLE); 1153 IntLoadSystenIcons(Common->hIconHand, OIC_HAND); 1154 IntLoadSystenIcons(Common->hIconQuestion, OIC_QUES); 1155 IntLoadSystenIcons(Common->hIconBang, OIC_BANG); 1156 IntLoadSystenIcons(Common->hIconNote, OIC_NOTE); 1157 IntLoadSystenIcons(gpsi->hIconWindows, OIC_WINLOGO); 1158 IntLoadSystenIcons(gpsi->hIconSmWindows, OIC_WINLOGO+1); 1159 1160 ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows); 1161 1162 IntCbFreeMemory(Argument); 1163 1164 return TRUE; 1165 } 1166 1167 VOID FASTCALL 1168 co_IntDeliverUserAPC(VOID) 1169 { 1170 ULONG ResultLength; 1171 PVOID ResultPointer; 1172 NTSTATUS Status; 1173 UserLeaveCo(); 1174 1175 Status = KeUserModeCallback(USER32_CALLBACK_DELIVERUSERAPC, 1176 0, 1177 0, 1178 &ResultPointer, 1179 &ResultLength); 1180 1181 1182 UserEnterCo(); 1183 1184 if (!NT_SUCCESS(Status)) 1185 { 1186 ERR("Delivering User APC callback failed!\n"); 1187 } 1188 } 1189 1190 VOID FASTCALL 1191 co_IntSetupOBM(VOID) 1192 { 1193 NTSTATUS Status; 1194 ULONG ArgumentLength, ResultLength; 1195 PVOID Argument, ResultPointer; 1196 PSETOBM_CALLBACK_ARGUMENTS Common; 1197 1198 ResultPointer = NULL; 1199 ResultLength = ArgumentLength = sizeof(SETOBM_CALLBACK_ARGUMENTS); 1200 1201 Argument = IntCbAllocateMemory(ArgumentLength); 1202 if (NULL == Argument) 1203 { 1204 ERR("Set Window Icons callback failed: out of memory\n"); 1205 return; 1206 } 1207 Common = (PSETOBM_CALLBACK_ARGUMENTS) Argument; 1208 1209 UserLeaveCo(); 1210 1211 Status = KeUserModeCallback(USER32_CALLBACK_SETOBM, 1212 Argument, 1213 ArgumentLength, 1214 &ResultPointer, 1215 &ResultLength); 1216 1217 1218 UserEnterCo(); 1219 1220 if (!NT_SUCCESS(Status)) 1221 { 1222 ERR("Set Window Icons callback failed!\n"); 1223 IntCbFreeMemory(Argument); 1224 return; 1225 } 1226 1227 RtlMoveMemory(Common, ResultPointer, ArgumentLength); 1228 RtlCopyMemory(gpsi->oembmi, Common->oembmi, sizeof(gpsi->oembmi)); 1229 1230 IntCbFreeMemory(Argument); 1231 } 1232 1233 // 1234 // Called from Kernel GDI sides, no UserLeave/EnterCo required. 1235 // 1236 LRESULT 1237 APIENTRY 1238 co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize ) 1239 { 1240 NTSTATUS Status; 1241 PVOID ResultPointer; 1242 1243 Status = KeUserModeCallback( USER32_CALLBACK_UMPD, 1244 pkt, 1245 InSize, 1246 &ResultPointer, 1247 (PULONG)&OutSize ); 1248 1249 1250 if (!NT_SUCCESS(Status)) 1251 { 1252 ERR("User UMPD callback failed!\n"); 1253 return 1; 1254 } 1255 1256 if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize ); 1257 1258 return 0; 1259 } 1260 1261 /* EOF */ 1262