Optimize SendMessageA/W to allow certain messages be sent without calling win32k

svn path=/trunk/; revision=30514
This commit is contained in:
Thomas Bluemel
2007-11-17 00:40:22 +00:00
parent 7033c976bb
commit 232b9edcf0
9 changed files with 135 additions and 46 deletions
@@ -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;
+14
View File
@@ -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;
+28 -28
View File
@@ -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;