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/ntu…
==============================================================================
--- 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/in…
==============================================================================
--- 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/in…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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;