Author: weiden Date: Sat Nov 17 03:40:22 2007 New Revision: 30514
URL: http://svn.reactos.org/svn/reactos?rev=30514&view=rev Log: Optimize SendMessageA/W to allow certain messages be sent without calling win32k
Modified: trunk/reactos/dll/win32/user32/include/user32.h trunk/reactos/dll/win32/user32/windows/message.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/win32.h trunk/reactos/subsystems/win32/win32k/include/window.h trunk/reactos/subsystems/win32/win32k/ntuser/hook.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/misc.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/user32/include/user32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/us... ============================================================================== --- trunk/reactos/dll/win32/user32/include/user32.h (original) +++ trunk/reactos/dll/win32/user32/include/user32.h Sat Nov 17 03:40:22 2007 @@ -85,6 +85,12 @@ 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);
Modified: trunk/reactos/dll/win32/user32/windows/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/me... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/message.c (original) +++ trunk/reactos/dll/win32/user32/windows/message.c Sat Nov 17 03:40:22 2007 @@ -1298,6 +1298,30 @@ }
+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 @@ 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; @@ -1688,6 +1731,25 @@ MSG KMMsg; 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;
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Sat Nov 17 03:40:22 2007 @@ -100,6 +100,16 @@ 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 @@ 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 @@ PVOID DesktopHeapBase; ULONG_PTR DesktopHeapLimit; ULONG_PTR DesktopHeapDelta; + /* A mask of what hooks are currently active */ + ULONG Hooks; } W32THREADINFO, *PW32THREADINFO;
/* Window Client Information structure */
Modified: trunk/reactos/subsystems/win32/win32k/include/win32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/win32.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/win32.h Sat Nov 17 03:40:22 2007 @@ -14,7 +14,7 @@ DWORD MessagePumpHookValue; BOOLEAN IsExiting; SINGLE_LIST_ENTRY ReferencesList; - + ULONG Hooks; PW32THREADINFO ThreadInfo; } W32THREAD, *PW32THREAD;
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/window.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/window.h Sat Nov 17 03:40:22 2007 @@ -36,15 +36,6 @@ 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 @@ 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;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/hook.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/hook.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/hook.c Sat Nov 17 03:40:22 2007 @@ -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 @@ 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 @@ 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 @@ static VOID IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked) { + PW32THREAD W32Thread; PHOOKTABLE Table = IntGetTable(Hook);
ASSERT(NULL != Table); @@ -220,6 +230,12 @@ { 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)]) {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c Sat Nov 17 03:40:22 2007 @@ -379,14 +379,14 @@ 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 @@ 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 @@ Info.Ansi = ! Window->Wnd->Unicode; }
- if (Window->IsSystem) - { - Info.Proc = (!Info.Ansi ? Window->WndProc : Window->WndProcExtra); + if (Window->Wnd->IsSystem) + { + 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
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/misc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/misc.c Sat Nov 17 03:40:22 2007 @@ -2585,6 +2585,7 @@ /* initialize it */ ti->kpi = GetW32ProcessInfo(); ti->pi = UserHeapAddressToUser(ti->kpi); + ti->Hooks = W32Thread->Hooks; if (W32Thread->Desktop != NULL) { ti->Desktop = W32Thread->Desktop->DesktopInfo;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Sat Nov 17 03:40:22 2007 @@ -519,33 +519,33 @@
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 @@ NewCallProc); }
- CallProc = Window->CallProc; - Window->CallProc = NewCallProc; + CallProc = Wnd->CallProc; + Wnd->CallProc = NewCallProc;
return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc)); } @@ -1645,19 +1645,19 @@
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 @@ }
/* 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 @@ CallProc); }
- Window->CallProc = CallProc; - - Ret = GetCallProcHandle(Window->CallProc); + Wnd->CallProc = CallProc; + + Ret = GetCallProcHandle(Wnd->CallProc); } }
@@ -3649,22 +3649,22 @@ { /* 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); - - if (Window->IsSystem) + Wnd->IsSystem = (NewWndProc == Wnd->Class->WndProc || + NewWndProc == Wnd->Class->WndProcExtra); + + 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;