mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 12:23:25 +00:00
Optimize SendMessageA/W to allow certain messages be sent without calling win32k
svn path=/trunk/; revision=30514
This commit is contained in:
@@ -85,6 +85,12 @@ SharedPtrToKernel(PVOID Ptr)
|
||||
return (PVOID)((ULONG_PTR)Ptr + g_pi->UserHeapDelta);
|
||||
}
|
||||
|
||||
static __inline BOOL
|
||||
IsThreadHooked(PW32THREADINFO ti)
|
||||
{
|
||||
return ti->Hooks != 0;
|
||||
}
|
||||
|
||||
PCALLPROC FASTCALL ValidateCallProc(HANDLE hCallProc);
|
||||
PWINDOW FASTCALL ValidateHwnd(HWND hwnd);
|
||||
PWINDOW FASTCALL ValidateHwndOrDesk(HWND hwnd);
|
||||
|
||||
@@ -1298,6 +1298,30 @@ CallWindowProcW(WNDPROC lpPrevWndFunc,
|
||||
}
|
||||
|
||||
|
||||
static LRESULT WINAPI
|
||||
IntCallMessageProc(IN PWINDOW Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN LPARAM lParam, IN BOOL Ansi)
|
||||
{
|
||||
WNDPROC WndProc;
|
||||
BOOL IsAnsi;
|
||||
|
||||
if (Wnd->IsSystem)
|
||||
{
|
||||
WndProc = (Ansi ? Wnd->WndProcExtra : Wnd->WndProc);
|
||||
IsAnsi = Ansi;
|
||||
}
|
||||
else
|
||||
{
|
||||
WndProc = Wnd->WndProc;
|
||||
IsAnsi = !Wnd->Unicode;
|
||||
}
|
||||
|
||||
if (!Ansi)
|
||||
return IntCallWindowProcW(IsAnsi, WndProc, hWnd, Msg, wParam, lParam);
|
||||
else
|
||||
return IntCallWindowProcA(IsAnsi, WndProc, hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
@@ -1651,6 +1675,25 @@ SendMessageW(HWND Wnd,
|
||||
NTUSERSENDMESSAGEINFO Info;
|
||||
LRESULT Result;
|
||||
|
||||
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
|
||||
{
|
||||
PWINDOW Window;
|
||||
PW32THREADINFO ti = GetW32ThreadInfo();
|
||||
|
||||
Window = ValidateHwnd(Wnd);
|
||||
if (Window != NULL && SharedPtrToUser(Window->ti) == ti && !IsThreadHooked(ti))
|
||||
{
|
||||
/* NOTE: We can directly send messages to the window procedure
|
||||
if *all* the following conditions are met:
|
||||
|
||||
* Window belongs to calling thread
|
||||
* The calling thread is not being hooked
|
||||
*/
|
||||
|
||||
return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
UMMsg.hwnd = Wnd;
|
||||
UMMsg.message = Msg;
|
||||
UMMsg.wParam = wParam;
|
||||
@@ -1689,6 +1732,25 @@ SendMessageA(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
LRESULT Result;
|
||||
NTUSERSENDMESSAGEINFO Info;
|
||||
|
||||
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
|
||||
{
|
||||
PWINDOW Window;
|
||||
PW32THREADINFO ti = GetW32ThreadInfo();
|
||||
|
||||
Window = ValidateHwnd(Wnd);
|
||||
if (Window != NULL && SharedPtrToUser(Window->ti) == ti && !IsThreadHooked(ti))
|
||||
{
|
||||
/* NOTE: We can directly send messages to the window procedure
|
||||
if *all* the following conditions are met:
|
||||
|
||||
* Window belongs to calling thread
|
||||
* The calling thread is not being hooked
|
||||
*/
|
||||
|
||||
return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
AnsiMsg.hwnd = Wnd;
|
||||
AnsiMsg.message = Msg;
|
||||
AnsiMsg.wParam = wParam;
|
||||
|
||||
@@ -100,6 +100,16 @@ typedef struct _WINDOW
|
||||
struct _W32THREADINFO *ti;
|
||||
RECT WindowRect;
|
||||
RECT ClientRect;
|
||||
|
||||
WNDPROC WndProc;
|
||||
union
|
||||
{
|
||||
/* Pointer to a call procedure handle */
|
||||
PCALLPROC CallProc;
|
||||
/* Extra Wnd proc (windows of system classes) */
|
||||
WNDPROC WndProcExtra;
|
||||
};
|
||||
|
||||
/* Size of the extra data associated with the window. */
|
||||
ULONG ExtraDataSize;
|
||||
/* Style. */
|
||||
@@ -117,6 +127,8 @@ typedef struct _WINDOW
|
||||
UNICODE_STRING WindowName;
|
||||
|
||||
UINT Unicode : 1;
|
||||
/* Indicates whether the window is derived from a system class */
|
||||
UINT IsSystem : 1;
|
||||
} WINDOW, *PWINDOW;
|
||||
|
||||
typedef struct _W32PROCESSINFO
|
||||
@@ -141,6 +153,8 @@ typedef struct _W32THREADINFO
|
||||
PVOID DesktopHeapBase;
|
||||
ULONG_PTR DesktopHeapLimit;
|
||||
ULONG_PTR DesktopHeapDelta;
|
||||
/* A mask of what hooks are currently active */
|
||||
ULONG Hooks;
|
||||
} W32THREADINFO, *PW32THREADINFO;
|
||||
|
||||
/* Window Client Information structure */
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef struct _W32THREAD
|
||||
DWORD MessagePumpHookValue;
|
||||
BOOLEAN IsExiting;
|
||||
SINGLE_LIST_ENTRY ReferencesList;
|
||||
|
||||
ULONG Hooks;
|
||||
PW32THREADINFO ThreadInfo;
|
||||
} W32THREAD, *PW32THREAD;
|
||||
|
||||
|
||||
@@ -36,15 +36,6 @@ typedef struct _WINDOW_OBJECT
|
||||
PW32THREADINFO ti;
|
||||
/* Pointer to the desktop */
|
||||
PDESKTOP Desktop;
|
||||
union
|
||||
{
|
||||
/* Pointer to a call procedure handle */
|
||||
PCALLPROC CallProc;
|
||||
/* Extra Wnd proc (windows of system classes) */
|
||||
WNDPROC WndProcExtra;
|
||||
};
|
||||
/* Indicates whether the window is derived from a system class */
|
||||
BOOL IsSystem;
|
||||
/* Context help id */
|
||||
DWORD ContextHelpId;
|
||||
/* system menu handle. */
|
||||
@@ -78,7 +69,6 @@ typedef struct _WINDOW_OBJECT
|
||||
ULONG PropListItems;
|
||||
/* Scrollbar info */
|
||||
PWINDOW_SCROLLINFO Scroll;
|
||||
WNDPROC WndProc;
|
||||
PETHREAD OwnerThread;
|
||||
HWND hWndLastPopup; /* handle to last active popup window (wine doesn't use pointer, for unk. reason)*/
|
||||
PINTERNALPOS InternalPos;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <debug.h>
|
||||
|
||||
#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
|
||||
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
|
||||
|
||||
static PHOOKTABLE GlobalHooks;
|
||||
|
||||
@@ -89,6 +90,7 @@ PHOOK FASTCALL IntGetHookObject(HHOOK hHook)
|
||||
static PHOOK
|
||||
IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
|
||||
{
|
||||
PW32THREAD W32Thread;
|
||||
PHOOK Hook;
|
||||
PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PW32THREAD)Thread->Tcb.Win32Thread)->MessageQueue);
|
||||
HANDLE Handle;
|
||||
@@ -119,6 +121,13 @@ IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinSt
|
||||
Hook->Self = Handle;
|
||||
Hook->Thread = Thread;
|
||||
Hook->HookId = HookId;
|
||||
|
||||
W32Thread = ((PW32THREAD)Thread->Tcb.Win32Thread);
|
||||
ASSERT(W32Thread != NULL);
|
||||
W32Thread->Hooks |= HOOKID_TO_FLAG(HookId);
|
||||
if (W32Thread->ThreadInfo != NULL)
|
||||
W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
|
||||
|
||||
RtlInitUnicodeString(&Hook->ModuleName, NULL);
|
||||
|
||||
InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
|
||||
@@ -213,6 +222,7 @@ IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
|
||||
static VOID
|
||||
IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
|
||||
{
|
||||
PW32THREAD W32Thread;
|
||||
PHOOKTABLE Table = IntGetTable(Hook);
|
||||
|
||||
ASSERT(NULL != Table);
|
||||
@@ -221,6 +231,12 @@ IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
|
||||
return;
|
||||
}
|
||||
|
||||
W32Thread = ((PW32THREAD)Hook->Thread->Tcb.Win32Thread);
|
||||
ASSERT(W32Thread != NULL);
|
||||
W32Thread->Hooks &= ~HOOKID_TO_FLAG(Hook->HookId);
|
||||
if (W32Thread->ThreadInfo != NULL)
|
||||
W32Thread->ThreadInfo->Hooks = W32Thread->Hooks;
|
||||
|
||||
if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
|
||||
{
|
||||
Hook->Proc = NULL; /* chain is in use, just mark it and return */
|
||||
|
||||
@@ -379,14 +379,14 @@ NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo)
|
||||
MsgInfo.HandledByKernel = FALSE;
|
||||
Result = 0;
|
||||
|
||||
if (Window->IsSystem)
|
||||
if (Window->Wnd->IsSystem)
|
||||
{
|
||||
MsgInfo.Proc = (!MsgInfo.Ansi ? Window->WndProc : Window->WndProcExtra);
|
||||
MsgInfo.Proc = (!MsgInfo.Ansi ? Window->Wnd->WndProc : Window->Wnd->WndProcExtra);
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgInfo.Ansi = !Window->Wnd->Unicode;
|
||||
MsgInfo.Proc = Window->WndProc;
|
||||
MsgInfo.Proc = Window->Wnd->WndProc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1390,7 +1390,7 @@ co_IntSendMessageTimeoutSingle(HWND hWnd,
|
||||
RETURN( FALSE);
|
||||
}
|
||||
|
||||
Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Wnd->Unicode, hWnd, Msg, wParam,
|
||||
Result = (ULONG_PTR)co_IntCallWindowProc(Window->Wnd->WndProc, !Window->Wnd->Unicode, hWnd, Msg, wParam,
|
||||
lParamPacked,lParamBufferSize);
|
||||
|
||||
if(uResult)
|
||||
@@ -1569,14 +1569,14 @@ co_IntDoSendMessage(HWND hWnd,
|
||||
Info.Ansi = ! Window->Wnd->Unicode;
|
||||
}
|
||||
|
||||
if (Window->IsSystem)
|
||||
if (Window->Wnd->IsSystem)
|
||||
{
|
||||
Info.Proc = (!Info.Ansi ? Window->WndProc : Window->WndProcExtra);
|
||||
Info.Proc = (!Info.Ansi ? Window->Wnd->WndProc : Window->Wnd->WndProcExtra);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info.Ansi = !Window->Wnd->Unicode;
|
||||
Info.Proc = Window->WndProc;
|
||||
Info.Proc = Window->Wnd->WndProc;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2585,6 +2585,7 @@ GetW32ThreadInfo(VOID)
|
||||
/* initialize it */
|
||||
ti->kpi = GetW32ProcessInfo();
|
||||
ti->pi = UserHeapAddressToUser(ti->kpi);
|
||||
ti->Hooks = W32Thread->Hooks;
|
||||
if (W32Thread->Desktop != NULL)
|
||||
{
|
||||
ti->Desktop = W32Thread->Desktop->DesktopInfo;
|
||||
|
||||
@@ -519,33 +519,33 @@ IntGetWindowProc(IN PWINDOW_OBJECT Window,
|
||||
|
||||
ASSERT(UserIsEnteredExclusive() == TRUE);
|
||||
|
||||
if (Window->IsSystem)
|
||||
if (Wnd->IsSystem)
|
||||
{
|
||||
return (Ansi ? Window->WndProcExtra : Window->WndProc);
|
||||
return (Ansi ? Wnd->WndProcExtra : Wnd->WndProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Ansi == Wnd->Unicode)
|
||||
{
|
||||
return Window->WndProc;
|
||||
return Wnd->WndProc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Window->CallProc != NULL)
|
||||
if (Wnd->CallProc != NULL)
|
||||
{
|
||||
return GetCallProcHandle(Window->CallProc);
|
||||
return GetCallProcHandle(Wnd->CallProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
PCALLPROC NewCallProc, CallProc;
|
||||
|
||||
NewCallProc = UserFindCallProc(Wnd->Class,
|
||||
Window->WndProc,
|
||||
Wnd->WndProc,
|
||||
Wnd->Unicode);
|
||||
if (NewCallProc == NULL)
|
||||
{
|
||||
NewCallProc = CreateCallProc(Wnd->ti->Desktop,
|
||||
Window->WndProc,
|
||||
Wnd->WndProc,
|
||||
Wnd->Unicode,
|
||||
Wnd->ti->kpi);
|
||||
if (NewCallProc == NULL)
|
||||
@@ -558,8 +558,8 @@ IntGetWindowProc(IN PWINDOW_OBJECT Window,
|
||||
NewCallProc);
|
||||
}
|
||||
|
||||
CallProc = Window->CallProc;
|
||||
Window->CallProc = NewCallProc;
|
||||
CallProc = Wnd->CallProc;
|
||||
Wnd->CallProc = NewCallProc;
|
||||
|
||||
return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc));
|
||||
}
|
||||
@@ -1645,19 +1645,19 @@ AllocErr:
|
||||
|
||||
Wnd->UserData = 0;
|
||||
|
||||
Window->IsSystem = Wnd->Class->System;
|
||||
Wnd->IsSystem = Wnd->Class->System;
|
||||
if (Wnd->Class->System)
|
||||
{
|
||||
/* NOTE: Always create a unicode window for system classes! */
|
||||
Wnd->Unicode = TRUE;
|
||||
Window->WndProc = Wnd->Class->WndProc;
|
||||
Window->WndProcExtra = Wnd->Class->WndProcExtra;
|
||||
Wnd->WndProc = Wnd->Class->WndProc;
|
||||
Wnd->WndProcExtra = Wnd->Class->WndProcExtra;
|
||||
}
|
||||
else
|
||||
{
|
||||
Wnd->Unicode = Wnd->Class->Unicode;
|
||||
Window->WndProc = Wnd->Class->WndProc;
|
||||
Window->CallProc = NULL;
|
||||
Wnd->WndProc = Wnd->Class->WndProc;
|
||||
Wnd->CallProc = NULL;
|
||||
}
|
||||
|
||||
Window->OwnerThread = PsGetCurrentThread();
|
||||
@@ -3608,25 +3608,25 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
|
||||
}
|
||||
|
||||
/* attempt to get the previous window proc */
|
||||
if (Window->IsSystem)
|
||||
if (Wnd->IsSystem)
|
||||
{
|
||||
Ret = (Ansi ? Window->WndProcExtra : Window->WndProc);
|
||||
Ret = (Ansi ? Wnd->WndProcExtra : Wnd->WndProc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Ansi == Wnd->Unicode)
|
||||
{
|
||||
Ret = Window->WndProc;
|
||||
Ret = Wnd->WndProc;
|
||||
}
|
||||
else
|
||||
{
|
||||
CallProc = UserFindCallProc(Wnd->Class,
|
||||
Window->WndProc,
|
||||
Wnd->WndProc,
|
||||
Wnd->Unicode);
|
||||
if (CallProc == NULL)
|
||||
{
|
||||
CallProc = CreateCallProc(NULL,
|
||||
Window->WndProc,
|
||||
Wnd->WndProc,
|
||||
Wnd->Unicode,
|
||||
Wnd->ti->kpi);
|
||||
if (CallProc == NULL)
|
||||
@@ -3639,9 +3639,9 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
|
||||
CallProc);
|
||||
}
|
||||
|
||||
Window->CallProc = CallProc;
|
||||
Wnd->CallProc = CallProc;
|
||||
|
||||
Ret = GetCallProcHandle(Window->CallProc);
|
||||
Ret = GetCallProcHandle(Wnd->CallProc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3649,22 +3649,22 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
|
||||
{
|
||||
/* check if the new procedure matches with the one in the
|
||||
window class. If so, we need to restore both procedures! */
|
||||
Window->IsSystem = (NewWndProc == Wnd->Class->WndProc ||
|
||||
NewWndProc == Wnd->Class->WndProcExtra);
|
||||
Wnd->IsSystem = (NewWndProc == Wnd->Class->WndProc ||
|
||||
NewWndProc == Wnd->Class->WndProcExtra);
|
||||
|
||||
if (Window->IsSystem)
|
||||
if (Wnd->IsSystem)
|
||||
{
|
||||
Window->WndProc = Wnd->Class->WndProc;
|
||||
Window->WndProcExtra = Wnd->Class->WndProcExtra;
|
||||
Wnd->WndProc = Wnd->Class->WndProc;
|
||||
Wnd->WndProcExtra = Wnd->Class->WndProcExtra;
|
||||
Wnd->Unicode = !Ansi;
|
||||
return Ret;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(!Window->IsSystem);
|
||||
ASSERT(!Wnd->IsSystem);
|
||||
|
||||
/* update the window procedure */
|
||||
Window->WndProc = NewWndProc;
|
||||
Wnd->WndProc = NewWndProc;
|
||||
Wnd->Unicode = !Ansi;
|
||||
|
||||
return Ret;
|
||||
|
||||
Reference in New Issue
Block a user