Author: greatlrd
Date: Sat Apr 15 14:41:58 2006
New Revision: 21596
URL:
http://svn.reactos.ru/svn/reactos?rev=21596&view=rev
Log:
Bug 1393 : Patch from w3seek Fix moving class objects between desktop heaps and the shared
heaps
Modified:
trunk/reactos/dll/win32/aclui/checklist.c
trunk/reactos/dll/win32/aclui/precomp.h
trunk/reactos/include/reactos/win32k/ntuser.h
trunk/reactos/subsystems/win32/win32k/include/class.h
trunk/reactos/subsystems/win32/win32k/include/desktop.h
trunk/reactos/subsystems/win32/win32k/main/dllmain.c
trunk/reactos/subsystems/win32/win32k/ntuser/class.c
trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/aclui/checklist.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/aclui/checklist.c…
==============================================================================
--- trunk/reactos/dll/win32/aclui/checklist.c (original)
+++ trunk/reactos/dll/win32/aclui/checklist.c Sat Apr 15 14:41:58 2006
@@ -85,10 +85,10 @@
HTHEME ThemeHandle;
#endif
- BOOL HasFocus : 1;
- BOOL FocusedPushed : 1;
- BOOL QuickSearchEnabled : 1;
- BOOL ShowingCaret : 1;
+ UINT HasFocus : 1;
+ UINT FocusedPushed : 1;
+ UINT QuickSearchEnabled : 1;
+ UINT ShowingCaret : 1;
} CHECKLISTWND, *PCHECKLISTWND;
static VOID EscapeQuickSearch(IN PCHECKLISTWND infoPtr);
Modified: trunk/reactos/dll/win32/aclui/precomp.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/aclui/precomp.h?r…
==============================================================================
--- trunk/reactos/dll/win32/aclui/precomp.h (original)
+++ trunk/reactos/dll/win32/aclui/precomp.h Sat Apr 15 14:41:58 2006
@@ -63,7 +63,7 @@
HANDLE SidCacheMgr;
LONG SidLookupsPending;
- BOOL Initializing : 1;
+ UINT Initializing : 1;
LPCWSTR ServerName;
} SECURITY_PAGE, *PSECURITY_PAGE;
Modified: trunk/reactos/include/reactos/win32k/ntuser.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/win32k/ntus…
==============================================================================
--- trunk/reactos/include/reactos/win32k/ntuser.h (original)
+++ trunk/reactos/include/reactos/win32k/ntuser.h Sat Apr 15 14:41:58 2006
@@ -33,6 +33,7 @@
WNDPROC WndProcExtra;
PCALLPROC CallProc;
};
+ PCALLPROC CallProc2;
INT ClsExtra;
INT WndExtra;
HINSTANCE hInstance;
@@ -50,6 +51,8 @@
UINT Unicode : 1;
UINT System : 1;
UINT Global : 1;
+ UINT GlobalCallProc : 1;
+ UINT GlobalCallProc2 : 1;
} WINDOWCLASS, *PWINDOWCLASS;
typedef struct _W32PROCESSINFO
Modified: trunk/reactos/subsystems/win32/win32k/include/class.h
URL:
http://svn.reactos.ru/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 Sat Apr 15 14:41:58 2006
@@ -32,7 +32,8 @@
DestroyProcessClasses(PW32PROCESS Process );
PWINDOWCLASS
-IntReferenceClass(IN PWINDOWCLASS BaseClass,
+IntReferenceClass(IN OUT PWINDOWCLASS BaseClass,
+ IN OUT PWINDOWCLASS *ClassLink,
IN PDESKTOP Desktop);
VOID
@@ -64,6 +65,10 @@
OUT PWINDOWCLASS *BaseClass OPTIONAL,
OUT PWINDOWCLASS **Link OPTIONAL);
+BOOL
+IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
+ IN BOOL FreeOnFailure);
+
#endif /* _WIN32K_CLASS_H */
/* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/include/desktop.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/desktop.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/desktop.h Sat Apr 15 14:41:58 2006
@@ -93,7 +93,8 @@
HDESK FASTCALL
IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject);
-BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject);
+BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
+ IN BOOL FreeOnFailure);
NTSTATUS FASTCALL
IntValidateDesktopHandle(
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/mai…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/main/dllmain.c (original)
+++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c Sat Apr 15 14:41:58 2006
@@ -203,6 +203,9 @@
DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n",
Thread->Cid.UniqueThread, KeGetCurrentIrql());
+ InitializeListHead(&Win32Thread->WindowListHead);
+ InitializeListHead(&Win32Thread->W32CallbackListHead);
+
/*
* inherit the thread desktop and process window station (if not yet inherited)
from the process startup
* info structure. See documentation of CreateProcess()
@@ -244,7 +247,8 @@
NtClose(hDesk);
if(NT_SUCCESS(Status))
{
- if (!IntSetThreadDesktop(DesktopObject))
+ if (!IntSetThreadDesktop(DesktopObject,
+ FALSE))
{
DPRINT1("Unable to set thread desktop\n");
}
@@ -260,8 +264,6 @@
Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
Win32Thread->MessagePumpHookValue = 0;
- InitializeListHead(&Win32Thread->WindowListHead);
- InitializeListHead(&Win32Thread->W32CallbackListHead);
}
else
{
@@ -278,14 +280,6 @@
MsqDestroyMessageQueue(Win32Thread->MessageQueue);
IntCleanupThreadCallbacks(Win32Thread);
- IntSetThreadDesktop(NULL);
-
- if (Win32Thread->ThreadInfo != NULL)
- {
- UserHeapFree(Win32Thread->ThreadInfo);
- Win32Thread->ThreadInfo = NULL;
- }
-
/* cleanup user object references stack */
e = PopEntryList(&Win32Thread->ReferencesList);
while (e)
@@ -296,6 +290,16 @@
e = PopEntryList(&Win32Thread->ReferencesList);
}
+
+ IntSetThreadDesktop(NULL,
+ TRUE);
+
+ if (Win32Thread->ThreadInfo != NULL)
+ {
+ UserHeapFree(Win32Thread->ThreadInfo);
+ Win32Thread->ThreadInfo = NULL;
+ }
+
PsSetThreadWin32Thread(Thread, NULL);
}
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c
URL:
http://svn.reactos.ru/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 Sat Apr 15 14:41:58 2006
@@ -25,9 +25,6 @@
* PROGRAMER: Thomas Weidenmueller <w3seek(a)reactos.com>
* REVISION HISTORY:
* 06-06-2001 CSH Created
- *
- * NOTE: Should classes created on a desktop heap be moved to the shared
- * heap when the desktop is destroyed, or should they be unregistered?
*/
/* INCLUDES ******************************************************************/
@@ -89,7 +86,7 @@
{
NewCallProc->pi = pi;
NewCallProc->WndProc = WndProc;
- NewCallProc->Unicode = Unicode != FALSE;
+ NewCallProc->Unicode = Unicode;
}
return NewCallProc;
@@ -154,22 +151,12 @@
IntDestroyClass(IN OUT PWINDOWCLASS Class)
{
/* there shouldn't be any clones anymore */
-
ASSERT(Class->Windows == 0);
+ ASSERT(Class->Clone == NULL);
if (Class->Desktop != NULL)
{
ASSERT(Class->Clone == NULL);
- }
- else if (Class->Clone != NULL)
- {
- /* there must not be more than one clone! This can be the case
- when the base class is on the shared heap */
- ASSERT(Class->Clone->Next == NULL);
-
- /* free the clone */
- IntDestroyClass(Class->Clone);
- Class->Clone = NULL;
}
if (Class->Base == Class)
@@ -177,8 +164,14 @@
/* destruct resources shared with clones */
if (!Class->System && Class->CallProc != NULL)
{
- DestroyCallProc(Class->Desktop,
+ DestroyCallProc(Class->GlobalCallProc ? NULL : Class->Desktop,
Class->CallProc);
+ }
+
+ if (Class->CallProc2 != NULL)
+ {
+ DestroyCallProc(Class->GlobalCallProc2 ? NULL : Class->Desktop,
+ Class->CallProc2);
}
IntFreeClassMenuName(Class);
@@ -323,7 +316,8 @@
static WNDPROC
IntGetClassWndProc(IN PWINDOWCLASS Class,
IN PW32PROCESSINFO pi,
- IN BOOL Ansi)
+ IN BOOL Ansi,
+ IN BOOL UseCallProc2)
{
/* FIXME - assert for exclusive lock! */
@@ -339,19 +333,27 @@
}
else
{
- if (Class->CallProc != NULL)
- {
- return (WNDPROC)ObmObjectToHandle(Class->CallProc);
+ PCALLPROC *CallProcPtr;
+ PWINDOWCLASS BaseClass;
+
+ /* make sure the call procedures are located on the desktop
+ of the base class! */
+ BaseClass = Class->Base;
+ Class = BaseClass;
+
+ CallProcPtr = (UseCallProc2 ? &Class->CallProc2 :
&Class->CallProc);
+
+ if (*CallProcPtr != NULL)
+ {
+ return (WNDPROC)ObmObjectToHandle(*CallProcPtr);
}
else
{
- PCALLPROC NewCallProc, CallProc;
+ PCALLPROC NewCallProc;
if (pi == NULL)
return NULL;
- /* NOTE: use the interlocked functions, as this operation may be done
even
- when only the shared lock is held! */
NewCallProc = CreateCallProc(Class->Desktop,
Class->WndProc,
Class->Unicode,
@@ -362,16 +364,35 @@
return NULL;
}
- CallProc = InterlockedCompareExchangePointer(&Class->CallProc,
- NewCallProc,
- NULL);
- if (CallProc != NULL)
+ *CallProcPtr = NewCallProc;
+
+ if (Class->Desktop == NULL)
{
- DestroyCallProc(Class->Desktop,
- NewCallProc);
+ if (UseCallProc2)
+ Class->GlobalCallProc2 = TRUE;
+ else
+ Class->GlobalCallProc = TRUE;
}
- return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc :
CallProc));
+ /* 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 = Class->Next;
+ }
+
+ return (WNDPROC)ObmObjectToHandle(NewCallProc);
}
}
}
@@ -391,17 +412,19 @@
return NULL;
}
+ /* update the base class first */
+ Class = Class->Base;
+
Ret = IntGetClassWndProc(Class,
GetW32ProcessInfo(),
- Ansi);
+ Ansi,
+ TRUE);
if (Ret == NULL)
{
return NULL;
}
- /* update the base class first */
- Class = Class->Base;
-
+ /* update the class info */
Class->Unicode = !Ansi;
Class->WndProc = WndProc;
if (Class->CallProc != NULL)
@@ -424,7 +447,8 @@
}
static PWINDOWCLASS
-IntGetClassForDesktop(IN PWINDOWCLASS BaseClass,
+IntGetClassForDesktop(IN OUT PWINDOWCLASS BaseClass,
+ IN OUT PWINDOWCLASS *ClassLink,
IN PDESKTOP Desktop)
{
SIZE_T ClassSize;
@@ -443,6 +467,9 @@
if (BaseClass->Desktop == NULL)
{
+ ASSERT(BaseClass->Windows == 0);
+ ASSERT(BaseClass->Clone == NULL);
+
/* Classes are also located in the shared heap when the class
was created before the thread attached to a desktop. As soon
as a window is created for such a class located on the shared
@@ -485,13 +512,43 @@
ClassSize);
/* update some pointers and link the class */
- Class->Next = BaseClass->Clone;
- Class->Clone = NULL;
- Class->Base = BaseClass;
Class->Desktop = Desktop;
Class->Windows = 0;
- (void)InterlockedExchangePointer(&BaseClass->Clone,
- Class);
+
+ if (BaseClass->Desktop == NULL)
+ {
+ /* we don't really need the base class on the shared
+ heap anymore, delete it so the only class left is
+ the clone we just created, which now serves as the
+ new base class */
+ ASSERT(BaseClass->Clone == NULL);
+ ASSERT(Class->Clone == NULL);
+ 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);
+
+ /* destroy the obsolete copy on the shared heap */
+ BaseClass->Base = NULL;
+ BaseClass->Clone = NULL;
+ IntDestroyClass(BaseClass);
+ }
+ else
+ {
+ /* link in the clone */
+ Class->Clone = NULL;
+ Class->Base = BaseClass;
+ Class->Next = BaseClass->Clone;
+ (void)InterlockedExchangePointer(&BaseClass->Clone,
+ Class);
+ }
}
else
{
@@ -503,12 +560,16 @@
}
PWINDOWCLASS
-IntReferenceClass(IN PWINDOWCLASS BaseClass,
+IntReferenceClass(IN OUT PWINDOWCLASS BaseClass,
+ IN OUT PWINDOWCLASS *ClassLink,
IN PDESKTOP Desktop)
{
PWINDOWCLASS Class;
+ ASSERT(BaseClass->Base == BaseClass);
+
Class = IntGetClassForDesktop(BaseClass,
+ ClassLink,
Desktop);
if (Class != NULL)
{
@@ -516,6 +577,72 @@
}
return Class;
+}
+
+static VOID
+IntMakeCloneBaseClass(IN OUT PWINDOWCLASS Class,
+ IN OUT PWINDOWCLASS *BaseClassLink,
+ IN OUT PWINDOWCLASS *CloneLink)
+{
+ PWINDOWCLASS Clone, BaseClass;
+ PCALLPROC CallProc;
+
+ ASSERT(Class->Base != Class);
+ ASSERT(Class->Base->Clone != NULL);
+ ASSERT(Class->Desktop != NULL);
+ ASSERT(Class->Windows != 0);
+ ASSERT(Class->Base->Desktop != NULL);
+ ASSERT(Class->Base->Windows == 0);
+
+ /* unlink the clone */
+ *CloneLink = Class->Next;
+ Class->Clone = Class->Base->Clone;
+
+ 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;
+
+ /* update all clones */
+ Clone = Class->Clone;
+ while (Clone != NULL)
+ {
+ ASSERT(Clone->Clone == NULL);
+ Clone->Base = Class;
+
+ if (!Class->System)
+ Clone->CallProc = Class->CallProc;
+ Clone->CallProc2 = Class->CallProc2;
+
+ Clone = Clone->Next;
+ }
+
+ /* link in the new base class */
+ (void)InterlockedExchangePointer(BaseClassLink,
+ Class);
}
VOID
@@ -535,12 +662,10 @@
/* check if there are clones of the class on other desktops,
link the first clone in if possible. If there are no clones
- then leave the class on the desktop heap... */
+ then leave the class on the desktop heap. It will get moved
+ to the shared heap when the thread detaches. */
if (BaseClass->Clone != NULL)
{
- PWINDOWCLASS NewBase = BaseClass->Clone;
-
- /* locate the base class and unlink it */
if (BaseClass->System)
PrevLink = &pi->SystemClassList;
else if (BaseClass->Global)
@@ -548,35 +673,18 @@
else
PrevLink = &pi->LocalClassList;
- CurrentClass = *PrevLink;
- while (CurrentClass != BaseClass)
+ while (*PrevLink != BaseClass)
{
- ASSERT(CurrentClass != NULL);
-
- PrevLink = &CurrentClass->Next;
- CurrentClass = CurrentClass->Next;
+ ASSERT(BaseClass != NULL);
+ PrevLink = &BaseClass->Next;
}
- ASSERT(CurrentClass == BaseClass);
-
- NewBase->Clone = NewBase->Next;
- NewBase->Next = BaseClass->Next;
- NewBase->Base = NewBase;
-
- /* update all clones */
- CurrentClass = NewBase->Clone;
- while (CurrentClass != NULL)
- {
- ASSERT(CurrentClass->Clone == NULL);
-
- CurrentClass->Base = NewBase;
-
- CurrentClass = CurrentClass->Next;
- }
-
- /* link in the new base class */
- (void)InterlockedExchangePointer(PrevLink,
- NewBase);
+ ASSERT(*PrevLink == BaseClass);
+
+ /* make the first clone become the new base class */
+ IntMakeCloneBaseClass(BaseClass->Clone,
+ PrevLink,
+ &BaseClass->Clone);
/* destroy the class, there's still another clone of the class
that now serves as a base class. Make sure we don't destruct
@@ -611,6 +719,180 @@
IntDestroyClass(Class);
}
}
+}
+
+static BOOL
+IntMoveClassToSharedHeap(IN OUT PWINDOWCLASS Class,
+ IN OUT PWINDOWCLASS **ClassLinkPtr)
+{
+ PWINDOWCLASS NewClass;
+ PCALLPROC CallProc;
+ SIZE_T ClassSize;
+
+ ASSERT(Class->Base == Class);
+ ASSERT(Class->Desktop != NULL);
+ ASSERT(Class->Windows == 0);
+ ASSERT(Class->Clone == NULL);
+
+ ClassSize = (SIZE_T)Class->ClassExtraDataOffset +
+ (SIZE_T)Class->ClsExtra;
+
+ /* allocate the new base class on the shared heap */
+ NewClass = UserHeapAlloc(ClassSize);
+ if (NewClass != NULL)
+ {
+ RtlCopyMemory(NewClass,
+ Class,
+ ClassSize);
+
+ 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,
+ NewClass);
+ *ClassLinkPtr = &NewClass->Next;
+
+ /* free the obsolete class on the desktop heap */
+ Class->Base = NULL;
+ IntDestroyClass(Class);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static VOID
+IntCheckDesktopClasses(IN PDESKTOP Desktop,
+ IN OUT PWINDOWCLASS *ClassList,
+ IN BOOL FreeOnFailure,
+ OUT BOOL *Ret)
+{
+ PWINDOWCLASS Class, NextClass, *Link;
+
+ /* NOTE: We only need to check base classes! When classes are no longer needed
+ on a desktop, the clones will be freed automatically as soon as possible.
+ However, we need to move base classes to the shared heap, as soon as
+ the last desktop heap where a class is allocated on is about to be
destroyed.
+ If we didn't move the class to the shared heap, the class would become
+ inaccessible! */
+
+ ASSERT(Desktop != NULL);
+
+ Link = ClassList;
+ Class = *Link;
+ while (Class != NULL)
+ {
+ NextClass = Class->Next;
+
+ ASSERT(Class->Base == Class);
+
+ if (Class->Desktop == Desktop &&
+ Class->Windows == 0)
+ {
+ /* there shouldn't be any clones around anymore! */
+ ASSERT(Class->Clone == NULL);
+
+ /* FIXME - If process is terminating, don't move the class but rather
destroy it! */
+ /* FIXME - We could move the class to another desktop heap if there's
still desktops
+ mapped into the process... */
+
+ /* move the class to the shared heap */
+ if (IntMoveClassToSharedHeap(Class,
+ &Link))
+ {
+ ASSERT(*Link == NextClass);
+ }
+ else
+ {
+ ASSERT(NextClass == Class->Next);
+
+ if (FreeOnFailure)
+ {
+ /* unlink the base class */
+ (void)InterlockedExchangePointer(Link,
+ Class->Next);
+
+ /* we can free the old base class now */
+ Class->Base = NULL;
+ IntDestroyClass(Class);
+ }
+ else
+ {
+ Link = &Class->Next;
+ *Ret = FALSE;
+ }
+ }
+ }
+ else
+ Link = &Class->Next;
+
+ Class = NextClass;
+ }
+}
+
+BOOL
+IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
+ IN BOOL FreeOnFailure)
+{
+ PW32PROCESSINFO pi;
+ BOOL Ret = TRUE;
+
+ pi = GetW32ProcessInfo();
+ if (pi == NULL)
+ return TRUE;
+
+ /* check all local classes */
+ IntCheckDesktopClasses(Desktop,
+ &pi->LocalClassList,
+ FreeOnFailure,
+ &Ret);
+
+ /* check all global classes */
+ IntCheckDesktopClasses(Desktop,
+ &pi->GlobalClassList,
+ FreeOnFailure,
+ &Ret);
+
+ /* check all system classes */
+ IntCheckDesktopClasses(Desktop,
+ &pi->SystemClassList,
+ FreeOnFailure,
+ &Ret);
+
+ if (!Ret)
+ {
+ DPRINT1("Failed to move process classes from desktop 0x%p to the shared
heap!\n", Desktop);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ return Ret;
}
static PWINDOWCLASS
@@ -908,24 +1190,14 @@
static PWINDOWCLASS
IntClassResizeInternal(IN OUT PWINDOWCLASS Class,
IN INT ClsExtraNew,
- IN PWINDOWCLASS *List)
-{
- PWINDOWCLASS *PrevLink, CurrentClass, NewClass;
+ IN PWINDOWCLASS *PrevLink)
+{
+ PWINDOWCLASS NewClass;
SIZE_T NewSize;
+ /* NOTE: Do *not* access Class->Base here, it may be invalid at this point! */
+
/* temporarily unlink the class, as resizing it may change it's location */
- PrevLink = List;
- CurrentClass = *PrevLink;
- while (CurrentClass != Class)
- {
- ASSERT(CurrentClass != NULL);
-
- PrevLink = &CurrentClass->Next;
- CurrentClass = CurrentClass->Next;
- }
-
- ASSERT(CurrentClass == Class);
-
(void)InterlockedExchangePointer(PrevLink,
Class->Next);
@@ -986,7 +1258,7 @@
IN PW32PROCESSINFO pi,
IN INT ClsExtraNew)
{
- PWINDOWCLASS *List, *CloneList, NewClass, Clone, FailedResize = NULL;
+ PWINDOWCLASS *Link, NewClass, Clone, FailedResize = NULL;
BOOL FailOnResize;
if (pi == NULL)
@@ -1003,18 +1275,18 @@
}
if (Class->System)
- List = &pi->SystemClassList;
+ Link = &pi->SystemClassList;
else if (Class->Global)
- List = &pi->GlobalClassList;
+ Link = &pi->GlobalClassList;
else
- List = &pi->LocalClassList;
+ Link = &pi->LocalClassList;
FailOnResize = Class->ClsExtra < ClsExtraNew;
/* resize the base class */
NewClass = IntClassResizeInternal(Class,
ClsExtraNew,
- List);
+ Link);
if (NewClass == NULL)
{
if (FailOnResize)
@@ -1027,13 +1299,13 @@
Class = NewClass;
/* resize the clones */
- CloneList = &Class->Clone;
+ Link = &Class->Clone;
Clone = Class->Clone;
while (Clone != NULL)
{
NewClass = IntClassResizeInternal(Clone,
ClsExtraNew,
- CloneList);
+ Link);
if (NewClass == NULL)
{
@@ -1050,6 +1322,7 @@
/* save the pointer to the base class in case it changed */
Clone->Base = Class;
+ Link = &Clone->Next;
Clone = Clone->Next;
}
@@ -1059,15 +1332,22 @@
other clones and to the base class */
DPRINT1("Failed to resize the cloned class 0x%p\n", FailedResize);
+ if (Class->System)
+ Link = &pi->SystemClassList;
+ else if (Class->Global)
+ Link = &pi->GlobalClassList;
+ else
+ Link = &pi->LocalClassList;
+
/* roll back the changes made to the base class */
NewClass = IntClassResizeInternal(Class,
Class->ClsExtra,
- List);
+ Link);
if (NewClass != NULL)
Class = NewClass;
/* roll back all changes made to the class clones */
- CloneList = &Class->Clone;
+ Link = &Class->Clone;
Clone = Class->Clone;
while (Clone != FailedResize)
{
@@ -1075,14 +1355,14 @@
NewClass = IntClassResizeInternal(Clone,
Class->ClsExtra,
- CloneList);
+ Link);
if (NewClass != NULL)
Clone = NewClass;
/* save the pointer to the base class in case it changed */
Clone->Base = Class;
- CloneList = &Clone->Next;
+ Link = &Clone->Next;
Clone = Clone->Next;
}
@@ -1097,6 +1377,9 @@
while (Clone != NULL)
{
Clone->ClsExtra = ClsExtraNew;
+
+ ASSERT(Clone->Base == Class);
+
Clone = Clone->Next;
}
@@ -1165,8 +1448,6 @@
}
}
}
-
- ASSERT(ti->Desktop != NULL);
Class = IntCreateClass(lpwcx,
ClassName,
@@ -1447,7 +1728,8 @@
case GCLP_WNDPROC:
Ret = (ULONG_PTR)IntGetClassWndProc(Class,
GetW32ProcessInfo(),
- Ansi);
+ Ansi,
+ FALSE);
break;
case GCW_ATOM:
@@ -1770,7 +2052,8 @@
lpwcx->lpfnWndProc = IntGetClassWndProc(Class,
GetW32ProcessInfo(),
- Ansi);
+ Ansi,
+ FALSE);
lpwcx->cbClsExtra = Class->ClsExtra;
lpwcx->cbWndExtra = Class->WndExtra;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c Sat Apr 15 14:41:58 2006
@@ -1757,7 +1757,8 @@
}
BOOL
-IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject)
+IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
+ IN BOOL FreeOnFailure)
{
PDESKTOP_OBJECT OldDesktop;
PW32THREAD W32Thread;
@@ -1770,6 +1771,13 @@
if (W32Thread->Desktop != DesktopObject)
{
OldDesktop = W32Thread->Desktop;
+
+ if (!IsListEmpty(&W32Thread->WindowListHead))
+ {
+ DPRINT1("Attempted to change thread desktop although the thread has
windows!\n");
+ SetLastWin32Error(ERROR_BUSY);
+ return FALSE;
+ }
W32Thread->Desktop = DesktopObject;
@@ -1783,6 +1791,20 @@
}
}
+ if (OldDesktop != NULL &&
+ !IntCheckProcessDesktopClasses(OldDesktop->DesktopInfo,
+ FreeOnFailure))
+ {
+ DPRINT1("Failed to move process classes to shared heap!\n");
+
+ /* failed to move desktop classes to the shared heap,
+ unmap the view and return the error */
+ if (MapHeap && DesktopObject != NULL)
+ IntUnmapDesktopView(DesktopObject);
+
+ return FALSE;
+ }
+
if (DesktopObject != NULL)
{
ObReferenceObject(DesktopObject);
@@ -1797,6 +1819,7 @@
ObDereferenceObject(OldDesktop);
+ /* update the thread info */
if (W32Thread != NULL && W32Thread->ThreadInfo != NULL &&
W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ?
DesktopObject->DesktopInfo : NULL))
{
@@ -1849,7 +1872,8 @@
/* FIXME: Should check here to see if the thread has any windows. */
- if (!IntSetThreadDesktop(DesktopObject))
+ if (!IntSetThreadDesktop(DesktopObject,
+ FALSE))
{
RETURN(FALSE);
}
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c
URL:
http://svn.reactos.ru/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 Apr 15 14:41:58 2006
@@ -442,7 +442,6 @@
if (Window->CallProc2 != NULL)
{
- DbgPrint("!!!!! Destroy call proc 0x%p\n",
ObmObjectToHandle(Window->CallProc2));
DestroyCallProc(Window->ti->Desktop,
Window->CallProc2);
}
@@ -1401,7 +1400,7 @@
BOOL bUnicodeWindow)
{
PWINSTATION_OBJECT WinSta;
- PWINDOWCLASS Class = NULL;
+ PWINDOWCLASS *ClassLink, Class = NULL;
RTL_ATOM ClassAtom;
PWINDOW_OBJECT Window = NULL;
PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow;
@@ -1482,7 +1481,7 @@
hInstance,
ti->kpi,
&Class,
- NULL);
+ &ClassLink);
if (ClassAtom == (RTL_ATOM)0)
{
@@ -1500,6 +1499,7 @@
}
Class = IntReferenceClass(Class,
+ ClassLink,
ti->Desktop);
if (Class == NULL)
{
@@ -1541,6 +1541,8 @@
*/
Window->ti = ti;
Window->Class = Class;
+ Class = NULL;
+
Window->SystemMenu = (HMENU)0;
Window->ContextHelpId = 0;
Window->IDMenu = 0;
@@ -1548,7 +1550,7 @@
Window->hSelf = hWnd;
if (!hMenu)
- hMenu = Class->hMenu;
+ hMenu = Window->Class->hMenu;
if (0 != (dwStyle & WS_CHILD))
{
@@ -1576,18 +1578,18 @@
Window->UserData = 0;
- Window->IsSystem = Class->System;
- if (Class->System)
+ Window->IsSystem = Window->Class->System;
+ if (Window->Class->System)
{
/* NOTE: Always create a unicode window for system classes! */
Window->Unicode = TRUE;
- Window->WndProc = Class->WndProc;
- Window->WndProcExtra = Class->WndProcExtra;
+ Window->WndProc = Window->Class->WndProc;
+ Window->WndProcExtra = Window->Class->WndProcExtra;
}
else
{
- Window->Unicode = Class->Unicode;
- Window->WndProc = Class->WndProc;
+ Window->Unicode = Window->Class->Unicode;
+ Window->WndProc = Window->Class->WndProc;
Window->CallProc = NULL;
}
@@ -1596,10 +1598,10 @@
Window->LastChild = NULL;
Window->PrevSibling = NULL;
Window->NextSibling = NULL;
- Window->ExtraDataSize = Class->WndExtra;
+ Window->ExtraDataSize = Window->Class->WndExtra;
/* extra window data */
- if (Class->WndExtra)
+ if (Window->Class->WndExtra)
Window->ExtraData = (PCHAR)(Window + 1);
InitializeListHead(&Window->PropListHead);
@@ -3463,7 +3465,6 @@
}
Ret = (WNDPROC)ObmObjectToHandle(Window->CallProc2);
- DbgPrint("!!!!!!!! Returning handle 0x%p\n", Ret);
}
}