Author: weiden Date: Tue Oct 30 04:24:47 2007 New Revision: 29967
URL: http://svn.reactos.org/svn/reactos?rev=29967&view=rev Log: Keep callproc handles valid as long as a window classes exists. Abiword should work again.
Modified: trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/class.h trunk/reactos/subsystems/win32/win32k/include/window.h trunk/reactos/subsystems/win32/win32k/ntuser/callproc.c trunk/reactos/subsystems/win32/win32k/ntuser/class.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
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 Tue Oct 30 04:24:47 2007 @@ -16,6 +16,7 @@ { struct _W32PROCESSINFO *pi; WNDPROC WndProc; + struct _CALLPROC *Next; UINT Unicode : 1; } CALLPROC, *PCALLPROC;
@@ -36,6 +37,7 @@ PCALLPROC CallProc; }; PCALLPROC CallProc2; + PCALLPROC CallProcList; INT ClsExtra; INT WndExtra; HINSTANCE hInstance; @@ -51,8 +53,6 @@ UINT Unicode : 1; UINT System : 1; UINT Global : 1; - UINT GlobalCallProc : 1; - UINT GlobalCallProc2 : 1; UINT MenuNameIsString : 1; } WINDOWCLASS, *PWINDOWCLASS;
Modified: trunk/reactos/subsystems/win32/win32k/include/class.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/class.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/class.h Tue Oct 30 04:24:47 2007 @@ -69,6 +69,15 @@ OUT PWINDOWCLASS *BaseClass OPTIONAL, OUT PWINDOWCLASS **Link OPTIONAL);
+PCALLPROC +UserFindCallProc(IN PWINDOWCLASS Class, + IN WNDPROC WndProc, + IN BOOL bUnicode); + +VOID +UserAddCallProcToClass(IN OUT PWINDOWCLASS Class, + IN PCALLPROC CallProc); + BOOL IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *Atom);
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 Tue Oct 30 04:24:47 2007 @@ -37,9 +37,6 @@ /* Extra Wnd proc (windows of system classes) */ WNDPROC WndProcExtra; }; - /* Pointer to another call procedure handle (used for returning the previous - window proc in SetWindowLongPtr) */ - PCALLPROC CallProc2; /* Indicates whether the window is derived from a system class */ BOOL IsSystem; /* Pointer to the window class. */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/callproc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/callproc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/callproc.c Tue Oct 30 04:24:47 2007 @@ -70,6 +70,7 @@ NewCallProc->pi = CallProc->pi; NewCallProc->WndProc = CallProc->WndProc; NewCallProc->Unicode = CallProc->Unicode; + NewCallProc->Next = NULL; }
return NewCallProc; @@ -94,6 +95,7 @@ NewCallProc->pi = pi; NewCallProc->WndProc = WndProc; NewCallProc->Unicode = Unicode; + NewCallProc->Next = NULL; }
return NewCallProc;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Tue Oct 30 04:24:47 2007 @@ -59,17 +59,19 @@
if (Class->Base == Class) { - /* destruct resources shared with clones */ - if (!Class->System && Class->CallProc != NULL) - { - DestroyCallProc(Class->GlobalCallProc ? NULL : Class->Desktop, + PCALLPROC CallProc, NextCallProc; + + /* Destroy allocated callproc handles */ + CallProc = Class->CallProcList; + while (CallProc != NULL) + { + NextCallProc = CallProc->Next; + + CallProc->Next = NULL; + DestroyCallProc(NULL, Class->CallProc); - } - - if (Class->CallProc2 != NULL) - { - DestroyCallProc(Class->GlobalCallProc2 ? NULL : Class->Desktop, - Class->CallProc2); + + CallProc = NextCallProc; }
IntFreeClassMenuName(Class); @@ -180,6 +182,50 @@ Atom); }
+PCALLPROC +UserFindCallProc(IN PWINDOWCLASS Class, + IN WNDPROC WndProc, + IN BOOL bUnicode) +{ + PCALLPROC CallProc; + + CallProc = Class->CallProcList; + while (CallProc != NULL) + { + if (CallProc->WndProc == WndProc && + CallProc->Unicode == (UINT)bUnicode) + { + return CallProc; + } + + CallProc = CallProc->Next; + } + + return NULL; +} + +VOID +UserAddCallProcToClass(IN OUT PWINDOWCLASS Class, + IN PCALLPROC CallProc) +{ + PWINDOWCLASS BaseClass; + + ASSERT(CallProc->Next == NULL); + + BaseClass = Class->Base; + ASSERT(CallProc->Next == NULL); + CallProc->Next = BaseClass->CallProcList; + BaseClass->CallProcList = CallProc; + + /* Update all clones */ + Class = Class->Clone; + while (Class != NULL) + { + Class->CallProcList = BaseClass->CallProcList; + Class = Class->Next; + } +} + static BOOL IntSetClassAtom(IN OUT PWINDOWCLASS Class, IN PUNICODE_STRING ClassName) @@ -214,8 +260,7 @@ static WNDPROC IntGetClassWndProc(IN PWINDOWCLASS Class, IN PW32PROCESSINFO pi, - IN BOOL Ansi, - IN BOOL UseCallProc2) + IN BOOL Ansi) { ASSERT(UserIsEnteredExclusive() == TRUE);
@@ -231,7 +276,6 @@ } else { - PCALLPROC *CallProcPtr; PWINDOWCLASS BaseClass;
/* make sure the call procedures are located on the desktop @@ -239,11 +283,9 @@ BaseClass = Class->Base; Class = BaseClass;
- CallProcPtr = (UseCallProc2 ? &Class->CallProc2 : &Class->CallProc); - - if (*CallProcPtr != NULL) - { - return GetCallProcHandle(*CallProcPtr); + if (Class->CallProc != NULL) + { + return GetCallProcHandle(Class->CallProc); } else { @@ -252,40 +294,32 @@ if (pi == NULL) return NULL;
- NewCallProc = CreateCallProc(Class->Desktop, - Class->WndProc, - Class->Unicode, - pi); + NewCallProc = UserFindCallProc(Class, + Class->WndProc, + Class->Unicode); if (NewCallProc == NULL) { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; + NewCallProc = CreateCallProc(NULL, + Class->WndProc, + Class->Unicode, + pi); + if (NewCallProc == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + UserAddCallProcToClass(Class, + NewCallProc); }
- *CallProcPtr = NewCallProc; - - if (Class->Desktop == NULL) - { - if (UseCallProc2) - Class->GlobalCallProc2 = TRUE; - else - Class->GlobalCallProc = TRUE; - } + Class->CallProc = NewCallProc;
/* update the clones */ Class = Class->Clone; while (Class != NULL) { - if (UseCallProc2) - { - Class->CallProc2 = NewCallProc; - Class->GlobalCallProc2 = BaseClass->GlobalCallProc2; - } - else - { - Class->CallProc = NewCallProc; - Class->GlobalCallProc = BaseClass->GlobalCallProc; - } + Class->CallProc = NewCallProc;
Class = Class->Next; } @@ -328,8 +362,7 @@
Ret = IntGetClassWndProc(Class, GetW32ProcessInfo(), - Ansi, - TRUE); + Ansi); if (Ret == NULL) { return NULL; @@ -338,11 +371,6 @@ /* update the class info */ Class->Unicode = !Ansi; Class->WndProc = WndProc; - if (Class->CallProc != NULL) - { - Class->CallProc->WndProc = WndProc; - Class->CallProc->Unicode = !Ansi; - }
/* update the clones */ Class = Class->Clone; @@ -436,11 +464,6 @@ Class->Base = Class; Class->Next = BaseClass->Next;
- if (!BaseClass->System && BaseClass->CallProc != NULL) - Class->GlobalCallProc = TRUE; - if (BaseClass->CallProc2 != NULL) - Class->GlobalCallProc2 = TRUE; - /* replace the base class */ (void)InterlockedExchangePointer(ClassLink, Class); @@ -495,7 +518,6 @@ IN OUT PWINDOWCLASS *CloneLink) { PWINDOWCLASS Clone, BaseClass; - PCALLPROC CallProc;
ASSERT(Class->Base != Class); ASSERT(Class->Base->Clone != NULL); @@ -510,28 +532,6 @@
BaseClass = Class->Base;
- if (!BaseClass->System && BaseClass->CallProc != NULL && - !BaseClass->GlobalCallProc) - { - /* we need to move the allocated call procedure */ - CallProc = BaseClass->CallProc; - Class->CallProc = CloneCallProc(Class->Desktop, - CallProc); - DestroyCallProc(BaseClass->Desktop, - CallProc); - } - - if (BaseClass->CallProc2 != NULL && - !BaseClass->GlobalCallProc2) - { - /* we need to move the allocated call procedure */ - CallProc = BaseClass->CallProc2; - Class->CallProc2 = CloneCallProc(Class->Desktop, - CallProc); - DestroyCallProc(BaseClass->Desktop, - CallProc); - } - /* update the class information to make it a base class */ Class->Base = Class; Class->Next = (*BaseClassLink)->Next; @@ -636,7 +636,6 @@ IN OUT PWINDOWCLASS **ClassLinkPtr) { PWINDOWCLASS NewClass; - PCALLPROC CallProc; SIZE_T ClassSize;
ASSERT(Class->Base == Class); @@ -656,32 +655,6 @@
NewClass->Desktop = NULL; NewClass->Base = NewClass; - - if (!NewClass->System && NewClass->CallProc != NULL && - !NewClass->GlobalCallProc) - { - /* we need to move the allocated call procedure to the shared heap */ - CallProc = NewClass->CallProc; - NewClass->CallProc = CloneCallProc(NULL, - CallProc); - DestroyCallProc(Class->Desktop, - CallProc); - - NewClass->GlobalCallProc = TRUE; - } - - if (NewClass->CallProc2 != NULL && - !NewClass->GlobalCallProc2) - { - /* we need to move the allocated call procedure to the shared heap */ - CallProc = NewClass->CallProc2; - NewClass->CallProc2 = CloneCallProc(NULL, - CallProc); - DestroyCallProc(Class->Desktop, - CallProc); - - NewClass->GlobalCallProc2 = TRUE; - }
/* replace the class in the list */ (void)InterlockedExchangePointer(*ClassLinkPtr, @@ -1473,8 +1446,7 @@ case GCLP_WNDPROC: Ret = (ULONG_PTR)IntGetClassWndProc(Class, GetW32ProcessInfo(), - Ansi, - FALSE); + Ansi); break;
case GCW_ATOM: @@ -1798,8 +1770,7 @@ pi = GetW32ProcessInfo(); lpwcx->lpfnWndProc = IntGetClassWndProc(Class, pi, - Ansi, - FALSE); + Ansi);
lpwcx->cbClsExtra = Class->ClsExtra; lpwcx->cbWndExtra = Class->WndExtra;
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 Tue Oct 30 04:24:47 2007 @@ -434,18 +434,6 @@
IntDestroyScrollBars(Window);
- if (!Window->Class->System && Window->CallProc != NULL) - { - DestroyCallProc(Window->ti->Desktop, - Window->CallProc); - } - - if (Window->CallProc2 != NULL) - { - DestroyCallProc(Window->ti->Desktop, - Window->CallProc2); - } - /* dereference the class */ IntDereferenceClass(Window->Class, Window->ti->Desktop, @@ -497,6 +485,8 @@ IntGetWindowProc(IN PWINDOW_OBJECT Window, IN BOOL Ansi) { + ASSERT(UserIsEnteredExclusive() == TRUE); + if (Window->IsSystem) { return (Ansi ? Window->WndProcExtra : Window->WndProc); @@ -517,26 +507,27 @@ { PCALLPROC NewCallProc, CallProc;
- /* NOTE: use the interlocked functions, as this operation may be done even - when only the shared lock is held! */ - NewCallProc = CreateCallProc(Window->ti->Desktop, - Window->WndProc, - Window->Unicode, - Window->ti->kpi); + NewCallProc = UserFindCallProc(Window->Class, + Window->WndProc, + Window->Unicode); if (NewCallProc == NULL) { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; + NewCallProc = CreateCallProc(Window->ti->Desktop, + Window->WndProc, + Window->Unicode, + Window->ti->kpi); + if (NewCallProc == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + UserAddCallProcToClass(Window->Class, + NewCallProc); }
- CallProc = InterlockedCompareExchangePointer(&Window->CallProc, - NewCallProc, - NULL); - if (CallProc != NULL) - { - DestroyCallProc(Window->ti->Desktop, - NewCallProc); - } + CallProc = Window->CallProc; + Window->CallProc = NewCallProc;
return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc)); } @@ -3533,6 +3524,7 @@ BOOL Ansi) { WNDPROC Ret; + PCALLPROC CallProc;
/* resolve any callproc handle if possible */ if (IsCallProcHandle(NewWndProc)) @@ -3560,49 +3552,37 @@ } else { - /* allocate or update an existing call procedure handle to return - the old window proc */ - if (Window->CallProc2 != NULL) + CallProc = UserFindCallProc(Window->Class, + Window->WndProc, + Window->Unicode); + if (CallProc == NULL) { - Window->CallProc2->WndProc = Window->WndProc; - Window->CallProc2->Unicode = Window->Unicode; - } - else - { - Window->CallProc2 = CreateCallProc(Window->ti->Desktop, - Window->WndProc, - Window->Unicode, - Window->ti->kpi); - if (Window->CallProc2 == NULL) + CallProc = CreateCallProc(NULL, + Window->WndProc, + Window->Unicode, + Window->ti->kpi); + if (CallProc == NULL) { SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); return NULL; } + + UserAddCallProcToClass(Window->Class, + CallProc); }
- Ret = GetCallProcHandle(Window->CallProc2); + Window->CallProc = CallProc; + + Ret = GetCallProcHandle(Window->CallProc); } }
if (Window->Class->System) { - BOOL SysWnd = Window->IsSystem; - /* check if the new procedure matches with the one in the window class. If so, we need to restore both procedures! */ Window->IsSystem = (NewWndProc == Window->Class->WndProc || NewWndProc == Window->Class->WndProcExtra); - - if (Window->IsSystem != SysWnd) - { - if (!Window->IsSystem && Window->CallProc != NULL) - { - /* destroy the callproc, we don't need it anymore */ - DestroyCallProc(Window->ti->Desktop, - Window->CallProc); - Window->CallProc = NULL; - } - }
if (Window->IsSystem) { @@ -3617,11 +3597,6 @@
/* update the window procedure */ Window->WndProc = NewWndProc; - if (Window->CallProc != NULL) - { - Window->CallProc->WndProc = NewWndProc; - Window->CallProc->Unicode = !Ansi; - } Window->Unicode = !Ansi;
return Ret;