Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Win32k subsystem * PURPOSE: Callback to usermode support * FILE: win32ss/user/ntuser/callback.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * Thomas Weidenmueller (w3seek@users.sourceforge.net) * NOTES: Please use the Callback Memory Management functions for * callbacks to make sure, the memory is freed on thread * termination! */
#include <win32k.h>DBG_DEFAULT_CHANNEL(UserCallback);
/* CALLBACK MEMORY MANAGEMENT ************************************************/
typedef struct _INT_CALLBACK_HEADER{ /* List entry in the THREADINFO structure */ LIST_ENTRY ListEntry;}INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
PVOID FASTCALLIntCbAllocateMemory(ULONG Size){ PINT_CALLBACK_HEADER Mem; PTHREADINFO W32Thread;
if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER), USERTAG_CALLBACK))) { return NULL; }
RtlZeroMemory(Mem, Size + sizeof(INT_CALLBACK_HEADER)); W32Thread = PsGetCurrentThreadWin32Thread(); ASSERT(W32Thread);
/* Insert the callback memory into the thread's callback list */
InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
return (Mem + 1);}
VOID FASTCALLIntCbFreeMemory(PVOID Data){ PINT_CALLBACK_HEADER Mem; PTHREADINFO W32Thread;
W32Thread = PsGetCurrentThreadWin32Thread(); ASSERT(W32Thread);
if (W32Thread->TIF_flags & TIF_INCLEANUP) { ERR("CbFM Thread is already in cleanup\n"); return; }
ASSERT(Data);
Mem = ((PINT_CALLBACK_HEADER)Data - 1);
/* Remove the memory block from the thread's callback list */ RemoveEntryList(&Mem->ListEntry);
/* Free memory */ ExFreePoolWithTag(Mem, USERTAG_CALLBACK);}
VOID FASTCALLIntCleanupThreadCallbacks(PTHREADINFO W32Thread){ PLIST_ENTRY CurrentEntry; PINT_CALLBACK_HEADER Mem;
while (!IsListEmpty(&W32Thread->W32CallbackListHead)) { CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead); Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER, ListEntry);
/* Free memory */ ExFreePoolWithTag(Mem, USERTAG_CALLBACK); }}
//// Pass the Current Window handle and pointer to the Client Callback.// This will help user space programs speed up read access with the window object.//static VOIDIntSetTebWndCallback (HWND * hWnd, PWND * pWnd, PVOID * pActCtx){ HWND hWndS = *hWnd; PWND Window = UserGetWindowObject(*hWnd); PCLIENTINFO ClientInfo = GetWin32ClientInfo();
*hWnd = ClientInfo->CallbackWnd.hWnd; *pWnd = ClientInfo->CallbackWnd.pWnd; *pActCtx = ClientInfo->CallbackWnd.pActCtx;
if (Window) { ClientInfo->CallbackWnd.hWnd = hWndS; ClientInfo->CallbackWnd.pWnd = DesktopHeapAddressToUser(Window); ClientInfo->CallbackWnd.pActCtx = Window->pActCtx; } else //// What if Dispatching WM_SYS/TIMER with NULL window? Fix AbiWord Crash when sizing. { ClientInfo->CallbackWnd.hWnd = hWndS; ClientInfo->CallbackWnd.pWnd = Window; ClientInfo->CallbackWnd.pActCtx = 0; }}
static VOIDIntRestoreTebWndCallback (HWND hWnd, PWND pWnd, PVOID pActCtx){ PCLIENTINFO ClientInfo = GetWin32ClientInfo();
ClientInfo->CallbackWnd.hWnd = hWnd; ClientInfo->CallbackWnd.pWnd = pWnd; ClientInfo->CallbackWnd.pActCtx = pActCtx;}
/* FUNCTIONS *****************************************************************/
/* Calls ClientLoadLibrary in user32 */BOOLNTAPIco_IntClientLoadLibrary(PUNICODE_STRING pstrLibName, PUNICODE_STRING pstrInitFunc, BOOL Unload, BOOL ApiHook){ PVOID ResultPointer; ULONG ResultLength; ULONG ArgumentLength; PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments; NTSTATUS Status; BOOL bResult; ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);
/* Calculate the size of the argument */ ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS); if(pstrLibName) { pLibNameBuffer = ArgumentLength; ArgumentLength += pstrLibName->Length + sizeof(WCHAR); } if(pstrInitFunc) { pInitFuncBuffer = ArgumentLength; ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR); }
/* Allocate the argument */ pArguments = IntCbAllocateMemory(ArgumentLength); if(pArguments == NULL) { return FALSE; }
/* Fill the argument */ pArguments->Unload = Unload; pArguments->ApiHook = ApiHook; if(pstrLibName) { /* Copy the string to the callback memory */ pLibNameBuffer += (ULONG_PTR)pArguments; pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer; pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR); RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName);
/* Fix argument pointer to be relative to the argument */ pLibNameBuffer -= (ULONG_PTR)pArguments; pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer); }
if(pstrInitFunc) { /* Copy the strings to the callback memory */ pInitFuncBuffer += (ULONG_PTR)pArguments; pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer; pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR); RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc);
/* Fix argument pointers to be relative to the argument */ pInitFuncBuffer -= (ULONG_PTR)pArguments; pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer); }
/* Do the callback */ UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY, pArguments, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
/* Free the argument */ IntCbFreeMemory(pArguments);
if(!NT_SUCCESS(Status)) { return FALSE; }
_SEH2_TRY { /* Probe and copy the usermode result data */ ProbeForRead(ResultPointer, sizeof(HMODULE), 1); bResult = *(BOOL*)ResultPointer; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { bResult = FALSE; } _SEH2_END;
return bResult;}
VOID APIENTRYco_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback, HWND hWnd, UINT Msg, ULONG_PTR CompletionCallbackContext, LRESULT Result){ SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments; PVOID ResultPointer, pActCtx; PWND pWnd; ULONG ResultLength; NTSTATUS Status;
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
Arguments.Callback = CompletionCallback; Arguments.Wnd = hWnd; Arguments.Msg = Msg; Arguments.Context = CompletionCallbackContext; Arguments.Result = Result;
IntSetTebWndCallback (&hWnd, &pWnd, &pActCtx);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_SENDASYNCPROC, &Arguments, sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS), &ResultPointer, &ResultLength);
UserEnterCo();
IntRestoreTebWndCallback (hWnd, pWnd, pActCtx);
if (!NT_SUCCESS(Status)) { ERR("KeUserModeCallback failed with %lx\n", Status); return; } return;}
LRESULT APIENTRYco_IntCallWindowProc(WNDPROC Proc, BOOLEAN IsAnsiProc, HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam, INT lParamBufferSize){ WINDOWPROC_CALLBACK_ARGUMENTS StackArguments = { 0 }; PWINDOWPROC_CALLBACK_ARGUMENTS Arguments; NTSTATUS Status; PVOID ResultPointer, pActCtx; PWND pWnd; ULONG ResultLength; ULONG ArgumentLength; LRESULT Result;
TRACE("co_IntCallWindowProc(Proc %p, IsAnsiProc: %s, Wnd %p, Message %u, wParam %Iu, lParam %Id, lParamBufferSize %d)\n", Proc, IsAnsiProc ? "TRUE" : "FALSE", Wnd, Message, wParam, lParam, lParamBufferSize);
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
if (lParamBufferSize != -1) { ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; Arguments = IntCbAllocateMemory(ArgumentLength); if (NULL == Arguments) { ERR("Unable to allocate buffer for window proc callback\n"); return -1; } RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), (PVOID) lParam, lParamBufferSize); } else { Arguments = &StackArguments; ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS); } Arguments->Proc = Proc; Arguments->IsAnsiProc = IsAnsiProc; Arguments->Wnd = Wnd; Arguments->Msg = Message; Arguments->wParam = wParam; Arguments->lParam = lParam; Arguments->lParamBufferSize = lParamBufferSize; ResultPointer = NULL; ResultLength = ArgumentLength;
IntSetTebWndCallback (&Wnd, &pWnd, &pActCtx);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_WINDOWPROC, Arguments, ArgumentLength, &ResultPointer, &ResultLength); if (!NT_SUCCESS(Status)) { ERR("Error Callback to User space Status %lx Message %d\n",Status,Message); UserEnterCo(); return 0; }
_SEH2_TRY { /* Simulate old behaviour: copy into our local buffer */ RtlMoveMemory(Arguments, ResultPointer, ArgumentLength); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy result from user mode, Message %u lParam size %d!\n", Message, lParamBufferSize); Status = _SEH2_GetExceptionCode(); } _SEH2_END;
UserEnterCo();
IntRestoreTebWndCallback (Wnd, pWnd, pActCtx);
if (!NT_SUCCESS(Status)) { ERR("Call to user mode failed! 0x%08lx\n",Status); if (lParamBufferSize != -1) { IntCbFreeMemory(Arguments); } return -1; } Result = Arguments->Result;
if (lParamBufferSize != -1) { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); // Is this message being processed from inside kernel space? BOOL InSendMessage = (pti->pcti->CTI_flags & CTI_INSENDMESSAGE);
TRACE("Copy lParam Message %u lParam %d!\n", Message, lParam); switch (Message) { default: TRACE("Don't copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam); break; // Write back to user/kernel space. Also see g_MsgMemory. case WM_CREATE: case WM_GETMINMAXINFO: case WM_GETTEXT: case WM_NCCALCSIZE: case WM_NCCREATE: case WM_STYLECHANGING: case WM_WINDOWPOSCHANGING: case WM_SIZING: case WM_MOVING: case WM_MEASUREITEM: case WM_NEXTMENU: TRACE("Copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam); if (InSendMessage) // Copy into kernel space. RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); else { _SEH2_TRY { // Copy into user space. RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy lParam to user space, Message %u!\n", Message); } _SEH2_END; } break; } IntCbFreeMemory(Arguments); }
return Result;}
HMENU APIENTRYco_IntLoadSysMenuTemplate(VOID){ LRESULT Result = 0; NTSTATUS Status; PVOID ResultPointer; ULONG ResultLength;
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
ResultPointer = NULL; ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LOADSYSMENUTEMPLATE, &ResultPointer, 0, &ResultPointer, &ResultLength); if (NT_SUCCESS(Status)) { /* Simulate old behaviour: copy into our local buffer */ _SEH2_TRY { ProbeForRead(ResultPointer, sizeof(LRESULT), 1); Result = *(LRESULT*)ResultPointer; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Result = 0; } _SEH2_END; }
UserEnterCo();
return (HMENU)Result;}
extern HCURSOR gDesktopCursor;
BOOL APIENTRYco_IntLoadDefaultCursors(VOID){ NTSTATUS Status; PVOID ResultPointer; ULONG ResultLength; BOOL DefaultCursor = TRUE;
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
ResultPointer = NULL; ResultLength = sizeof(HCURSOR);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LOADDEFAULTCURSORS, &DefaultCursor, sizeof(BOOL), &ResultPointer, &ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status)) { return FALSE; }
/* HACK: The desktop class doen't have a proper cursor yet, so set it here */ gDesktopCursor = *((HCURSOR*)ResultPointer);
return TRUE;}
static INT iTheId = -2; // Set it out of range.
LRESULT APIENTRYco_IntCallHookProc(INT HookId, INT Code, WPARAM wParam, LPARAM lParam, HOOKPROC Proc, INT Mod, ULONG_PTR offPfn, BOOLEAN Ansi, PUNICODE_STRING ModuleName){ ULONG ArgumentLength; PVOID Argument = NULL; LRESULT Result = 0; NTSTATUS Status; PVOID ResultPointer; ULONG ResultLength; PHOOKPROC_CALLBACK_ARGUMENTS Common; CBT_CREATEWNDW *CbtCreateWnd = NULL; PCHAR Extra; PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; PTHREADINFO pti; PWND pWnd; PMSG pMsg = NULL; BOOL Hit = FALSE; UINT lParamSize = 0; CWPSTRUCT* pCWP = NULL; CWPRETSTRUCT* pCWPR = NULL;
ASSERT(Proc); /* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
pti = PsGetCurrentThreadWin32Thread(); if (pti->TIF_flags & TIF_INCLEANUP) { ERR("Thread is in cleanup and trying to call hook %d\n", Code); return 0; }
ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
switch(HookId) { case WH_CBT: TRACE("WH_CBT: Code %d\n", Code); switch(Code) { case HCBT_CREATEWND: pWnd = UserGetWindowObject((HWND) wParam); if (!pWnd) { ERR("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); goto Fault_Exit; } TRACE("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False"); // Due to KsStudio.exe, just pass the callers original pointers // except class which point to kernel space if not an atom. // Found by, Olaf Siejka CbtCreateWnd = (CBT_CREATEWNDW *) lParam; ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS); break;
case HCBT_MOVESIZE: ArgumentLength += sizeof(RECTL); break; case HCBT_ACTIVATE: ArgumentLength += sizeof(CBTACTIVATESTRUCT); break; case HCBT_CLICKSKIPPED: ArgumentLength += sizeof(MOUSEHOOKSTRUCT); break;/* ATM pass on */ case HCBT_KEYSKIPPED: case HCBT_MINMAX: case HCBT_SETFOCUS: case HCBT_SYSCOMMAND:/* These types pass through. */ case HCBT_DESTROYWND: case HCBT_QS: break; default: ERR("Trying to call unsupported CBT hook %d\n", Code); goto Fault_Exit; } break; case WH_KEYBOARD_LL: ArgumentLength += sizeof(KBDLLHOOKSTRUCT); break; case WH_MOUSE_LL: ArgumentLength += sizeof(MSLLHOOKSTRUCT); break; case WH_MOUSE: ArgumentLength += sizeof(MOUSEHOOKSTRUCT); break; case WH_CALLWNDPROC: { pCWP = (CWPSTRUCT*) lParam; ArgumentLength = sizeof(CWP_Struct); if ( pCWP->message == WM_CREATE || pCWP->message == WM_NCCREATE ) { lParamSize = sizeof(CREATESTRUCTW); } else lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam); ArgumentLength += lParamSize; break; } case WH_CALLWNDPROCRET: { pCWPR = (CWPRETSTRUCT*) lParam; ArgumentLength = sizeof(CWPR_Struct); if ( pCWPR->message == WM_CREATE || pCWPR->message == WM_NCCREATE ) { lParamSize = sizeof(CREATESTRUCTW); } else lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam); ArgumentLength += lParamSize; break; } case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: ArgumentLength += sizeof(MSG); break; case WH_FOREGROUNDIDLE: case WH_KEYBOARD: case WH_SHELL: break; default: ERR("Trying to call unsupported window hook %d\n", HookId); goto Fault_Exit; }
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("HookProc callback %d failed: out of memory %d\n",HookId,ArgumentLength); goto Fault_Exit; } Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument; Common->HookId = HookId; Common->Code = Code; Common->wParam = wParam; Common->lParam = lParam; Common->Proc = Proc; Common->Mod = Mod; Common->offPfn = offPfn; Common->Ansi = Ansi; Common->lParamSize = lParamSize; if (ModuleName->Buffer && ModuleName->Length) { RtlCopyMemory(&Common->ModuleName, ModuleName->Buffer, ModuleName->Length); // If ModuleName->Buffer NULL while in destroy, // this will make User32:Hook.c complain about not loading the library module. // Fix symptom for CORE-10549. } Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS);
switch(HookId) { case WH_CBT: switch(Code) { // Need to remember this is not the first time through! Call Next Hook? case HCBT_CREATEWND: CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; Common->lParam = (LPARAM) (Extra - (PCHAR) Common); //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, CbtCreateWnd->lpcs, CbtCreateWnd->lpcs->lpszName, CbtCreateWnd->lpcs->lpszClass); break; case HCBT_CLICKSKIPPED: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case HCBT_MOVESIZE: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(RECTL)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case HCBT_ACTIVATE: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CBTACTIVATESTRUCT)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; } break; case WH_KEYBOARD_LL: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_MOUSE_LL: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_MOUSE: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_CALLWNDPROC: { PCWP_Struct pcwps = (PCWP_Struct)Common; RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT)); /* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that * lParam could be a pointer to a buffer. This buffer must be exported * to user space too */ if ( lParamSize ) { RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize ); } } break; case WH_CALLWNDPROCRET: { PCWPR_Struct pcwprs = (PCWPR_Struct)Common; RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT)); if ( lParamSize ) { RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize ); } } break; case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: pMsg = (PMSG)lParam; RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_FOREGROUNDIDLE: case WH_KEYBOARD: case WH_SHELL: break; }
ResultPointer = NULL; ResultLength = ArgumentLength;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_HOOKPROC, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status)) { if ( iTheId != HookId ) // Hook ID can change. { ERR("Failure to make Callback %d! Status 0x%x ArgumentLength %d\n",HookId,Status,ArgumentLength); iTheId = HookId; } goto Fault_Exit; }
if (ResultPointer) { _SEH2_TRY { /* Simulate old behaviour: copy into our local buffer */ RtlMoveMemory(Argument, ResultPointer, ArgumentLength); Result = Common->Result; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Result = 0; Hit = TRUE; } _SEH2_END; } else { ERR("ERROR: Hook %d Code %d ResultPointer 0x%p ResultLength %u\n",HookId,Code,ResultPointer,ResultLength); }
/* Support write backs... SEH is in UserCallNextHookEx. */ switch (HookId) { case WH_CBT: { switch (Code) { case HCBT_CREATEWND: if (CbtCreatewndExtra) {/* The parameters could have been changed, include the coordinates and dimensions of the window. We copy it back. */ CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x; CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y; CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx; CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy; } break; case HCBT_MOVESIZE: if (Extra && lParam) { RtlCopyMemory((PVOID) lParam, Extra, sizeof(RECTL)); } break; } } // "The GetMsgProc hook procedure can examine or modify the message." case WH_GETMESSAGE: if (pMsg) { RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG)); } break; }
Fault_Exit: if (Hit) { ERR("Exception CallHookProc HookId %d Code %d\n",HookId,Code); } if (Argument) IntCbFreeMemory(Argument);
return Result;}
//// Events are notifications w/o results.//LRESULTAPIENTRYco_IntCallEventProc(HWINEVENTHOOK hook, DWORD event, HWND hWnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime, WINEVENTPROC Proc, INT Mod, ULONG_PTR offPfn){ LRESULT Result = 0; NTSTATUS Status; PEVENTPROC_CALLBACK_ARGUMENTS Common; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer;
ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("EventProc callback failed: out of memory\n"); return 0; } Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument; Common->hook = hook; Common->event = event; Common->hwnd = hWnd; Common->idObject = idObject; Common->idChild = idChild; Common->dwEventThread = dwEventThread; Common->dwmsEventTime = dwmsEventTime; Common->Proc = Proc; Common->Mod = Mod; Common->offPfn = offPfn;
ResultPointer = NULL; ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
IntCbFreeMemory(Argument);
if (!NT_SUCCESS(Status)) { return 0; }
return Result;}
//// Callback Load Menu and results.//HMENUAPIENTRYco_IntCallLoadMenu( HINSTANCE hModule, PUNICODE_STRING pMenuName ){ LRESULT Result = 0; NTSTATUS Status; PLOADMENU_CALLBACK_ARGUMENTS Common; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer;
ArgumentLength = sizeof(LOADMENU_CALLBACK_ARGUMENTS);
ArgumentLength += pMenuName->Length + sizeof(WCHAR);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("LoadMenu callback failed: out of memory\n"); return 0; } Common = (PLOADMENU_CALLBACK_ARGUMENTS) Argument;
Common->hModule = hModule; if (pMenuName->Length) RtlCopyMemory(&Common->MenuName, pMenuName->Buffer, pMenuName->Length); else Common->InterSource = pMenuName->Buffer;
ResultPointer = NULL; ResultLength = sizeof(LRESULT);
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LOADMENU, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
if (NT_SUCCESS(Status)) { Result = *(LRESULT*)ResultPointer; } else { Result = 0; }
IntCbFreeMemory(Argument);
return (HMENU)Result;}
NTSTATUSAPIENTRYco_IntClientThreadSetup(VOID){ NTSTATUS Status; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer;
/* Do not allow the desktop thread to do callback to user mode */ ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);
ArgumentLength = ResultLength = 0; Argument = ResultPointer = NULL;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_CLIENTTHREADSTARTUP, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
return Status;}
HANDLE FASTCALLco_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags){ HANDLE Handle; NTSTATUS Status; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer; PCOPYIMAGE_CALLBACK_ARGUMENTS Common;
ArgumentLength = ResultLength = 0; Argument = ResultPointer = NULL;
ArgumentLength = sizeof(COPYIMAGE_CALLBACK_ARGUMENTS);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("CopyImage callback failed: out of memory\n"); return 0; } Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Argument;
Common->hImage = hnd; Common->uType = type; Common->cxDesired = desiredx; Common->cyDesired = desiredy; Common->fuFlags = flags;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_COPYIMAGE, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
if (NT_SUCCESS(Status)) { Handle = *(HANDLE*)ResultPointer; } else { ERR("CopyImage callback failed!\n"); Handle = NULL; }
IntCbFreeMemory(Argument);
return Handle;}
BOOLAPIENTRYco_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs){ NTSTATUS Status; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer; PGET_CHARSET_INFO Common;
ArgumentLength = sizeof(GET_CHARSET_INFO);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("GetCharsetInfo callback failed: out of memory\n"); return 0; } Common = (PGET_CHARSET_INFO) Argument;
Common->Locale = Locale;
ResultPointer = NULL; ResultLength = ArgumentLength;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_GETCHARSETINFO, Argument, ArgumentLength, &ResultPointer, &ResultLength);
if (NT_SUCCESS(Status)) { _SEH2_TRY { /* Need to copy into our local buffer */ RtlMoveMemory(Argument, ResultPointer, ArgumentLength); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ERR("Failed to copy result from user mode!\n"); Status = _SEH2_GetExceptionCode(); } _SEH2_END; }
UserEnterCo();
RtlCopyMemory(pCs, &Common->Cs, sizeof(CHARSETINFO));
IntCbFreeMemory(Argument);
if (!NT_SUCCESS(Status)) { ERR("GetCharsetInfo Failed!!\n"); return FALSE; }
return TRUE;}
BOOL FASTCALLco_IntSetWndIcons(VOID){ NTSTATUS Status; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer; PSETWNDICONS_CALLBACK_ARGUMENTS Common;
ResultPointer = NULL; ResultLength = ArgumentLength = sizeof(SETWNDICONS_CALLBACK_ARGUMENTS);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("Set Window Icons callback failed: out of memory\n"); return FALSE; } Common = (PSETWNDICONS_CALLBACK_ARGUMENTS) Argument;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_SETWNDICONS, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status)) { ERR("Set Window Icons callback failed!\n"); IntCbFreeMemory(Argument); return FALSE; }
RtlMoveMemory(Common, ResultPointer, ArgumentLength); gpsi->hIconSmWindows = Common->hIconSmWindows; gpsi->hIconWindows = Common->hIconWindows;
IntLoadSystenIcons(Common->hIconSample, OIC_SAMPLE); IntLoadSystenIcons(Common->hIconHand, OIC_HAND); IntLoadSystenIcons(Common->hIconQuestion, OIC_QUES); IntLoadSystenIcons(Common->hIconBang, OIC_BANG); IntLoadSystenIcons(Common->hIconNote, OIC_NOTE); IntLoadSystenIcons(gpsi->hIconWindows, OIC_WINLOGO); IntLoadSystenIcons(gpsi->hIconSmWindows, OIC_INTERNAL_WINSMALL);
ERR("hIconSmWindows %p hIconWindows %p \n",gpsi->hIconSmWindows,gpsi->hIconWindows);
IntCbFreeMemory(Argument);
return TRUE;}
VOID FASTCALLco_IntDeliverUserAPC(VOID){ ULONG ResultLength; PVOID ResultPointer; NTSTATUS Status; UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_DELIVERUSERAPC, 0, 0, &ResultPointer, &ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status)) { ERR("Delivering User APC callback failed!\n"); }}
VOID FASTCALLco_IntSetupOBM(VOID){ NTSTATUS Status; ULONG ArgumentLength, ResultLength; PVOID Argument, ResultPointer; PSETOBM_CALLBACK_ARGUMENTS Common;
ResultPointer = NULL; ResultLength = ArgumentLength = sizeof(SETOBM_CALLBACK_ARGUMENTS);
Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { ERR("Set Window Icons callback failed: out of memory\n"); return; } Common = (PSETOBM_CALLBACK_ARGUMENTS) Argument;
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_SETOBM, Argument, ArgumentLength, &ResultPointer, &ResultLength);
UserEnterCo();
if (!NT_SUCCESS(Status)) { ERR("Set Window Icons callback failed!\n"); IntCbFreeMemory(Argument); return; }
RtlMoveMemory(Common, ResultPointer, ArgumentLength); RtlCopyMemory(gpsi->oembmi, Common->oembmi, sizeof(gpsi->oembmi));
IntCbFreeMemory(Argument);}
//// Called from Kernel GDI sides, no UserLeave/EnterCo required.//LRESULTAPIENTRYco_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize ){ NTSTATUS Status; PVOID ResultPointer;
Status = KeUserModeCallback( USER32_CALLBACK_UMPD, pkt, InSize, &ResultPointer, (PULONG)&OutSize );
if (!NT_SUCCESS(Status)) { ERR("User UMPD callback failed!\n"); return 1; }
if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize );
return 0;}
// Win: ClientImmProcessKeyDWORDAPIENTRYco_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID){ DWORD ret = 0; NTSTATUS Status; ULONG ResultLength = sizeof(DWORD); PVOID ResultPointer = NULL; IMMPROCESSKEY_CALLBACK_ARGUMENTS Common = { hWnd, hKL, vKey, lParam, dwHotKeyID };
UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_IMMPROCESSKEY, &Common, sizeof(Common), &ResultPointer, &ResultLength); UserEnterCo();
if (NT_SUCCESS(Status)) ret = *(LPDWORD)ResultPointer;
return ret;}
/* Win: ClientImmLoadLayout */BOOLAPIENTRYco_ClientImmLoadLayout( _In_ HKL hKL, _Inout_ PIMEINFOEX pImeInfoEx){ BOOL ret; NTSTATUS Status; IMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = { hKL }; ULONG ResultLength = sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT); PIMMLOADLAYOUT_CALLBACK_OUTPUT ResultPointer = NULL;
RtlZeroMemory(pImeInfoEx, sizeof(IMEINFOEX));
UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_IMMLOADLAYOUT, &Common, sizeof(Common), (PVOID*)&ResultPointer, &ResultLength); UserEnterCo();
if (!NT_SUCCESS(Status) || !ResultPointer || ResultLength != sizeof(IMMLOADLAYOUT_CALLBACK_OUTPUT)) { ERR("0x%lX, %p, %lu\n", Status, ResultPointer, ResultLength); return FALSE; }
_SEH2_TRY { ProbeForRead(ResultPointer, ResultLength, 1); ret = ResultPointer->ret; if (ret) RtlCopyMemory(pImeInfoEx, &ResultPointer->iiex, sizeof(IMEINFOEX)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ret = FALSE; } _SEH2_END;
return ret;}
/* EOF */