Bug 1393 : Patch from w3seek Fix moving class objects between desktop heaps and the shared heaps

svn path=/trunk/; revision=21596
This commit is contained in:
Magnus Olsen 2006-04-15 10:41:58 +00:00
parent 88699130d7
commit 299c670648
9 changed files with 452 additions and 131 deletions

View file

@ -85,10 +85,10 @@ typedef struct _CHECKLISTWND
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);

View file

@ -63,7 +63,7 @@ typedef struct _SECURITY_PAGE
HANDLE SidCacheMgr;
LONG SidLookupsPending;
BOOL Initializing : 1;
UINT Initializing : 1;
LPCWSTR ServerName;
} SECURITY_PAGE, *PSECURITY_PAGE;

View file

@ -33,6 +33,7 @@ typedef struct _WINDOWCLASS
WNDPROC WndProcExtra;
PCALLPROC CallProc;
};
PCALLPROC CallProc2;
INT ClsExtra;
INT WndExtra;
HINSTANCE hInstance;
@ -50,6 +51,8 @@ typedef struct _WINDOWCLASS
UINT Unicode : 1;
UINT System : 1;
UINT Global : 1;
UINT GlobalCallProc : 1;
UINT GlobalCallProc2 : 1;
} WINDOWCLASS, *PWINDOWCLASS;
typedef struct _W32PROCESSINFO

View file

@ -32,7 +32,8 @@ void FASTCALL
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 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
OUT PWINDOWCLASS *BaseClass OPTIONAL,
OUT PWINDOWCLASS **Link OPTIONAL);
BOOL
IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
IN BOOL FreeOnFailure);
#endif /* _WIN32K_CLASS_H */
/* EOF */

View file

@ -93,7 +93,8 @@ IntHideDesktop(PDESKTOP_OBJECT Desktop);
HDESK FASTCALL
IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject);
BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject);
BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
IN BOOL FreeOnFailure);
NTSTATUS FASTCALL
IntValidateDesktopHandle(

View file

@ -203,6 +203,9 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
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 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
NtClose(hDesk);
if(NT_SUCCESS(Status))
{
if (!IntSetThreadDesktop(DesktopObject))
if (!IntSetThreadDesktop(DesktopObject,
FALSE))
{
DPRINT1("Unable to set thread desktop\n");
}
@ -260,8 +264,6 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
Win32Thread->MessagePumpHookValue = 0;
InitializeListHead(&Win32Thread->WindowListHead);
InitializeListHead(&Win32Thread->W32CallbackListHead);
}
else
{
@ -278,14 +280,6 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
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 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
e = PopEntryList(&Win32Thread->ReferencesList);
}
IntSetThreadDesktop(NULL,
TRUE);
if (Win32Thread->ThreadInfo != NULL)
{
UserHeapFree(Win32Thread->ThreadInfo);
Win32Thread->ThreadInfo = NULL;
}
PsSetThreadWin32Thread(Thread, NULL);
}

View file

@ -25,9 +25,6 @@
* PROGRAMER: Thomas Weidenmueller <w3seek@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 @@ CreateCallProc(IN PDESKTOP Desktop,
{
NewCallProc->pi = pi;
NewCallProc->WndProc = WndProc;
NewCallProc->Unicode = Unicode != FALSE;
NewCallProc->Unicode = Unicode;
}
return NewCallProc;
@ -154,33 +151,29 @@ static VOID
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)
{
/* 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 @@ IntSetClassAtom(IN OUT PWINDOWCLASS Class,
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 @@ IntGetClassWndProc(IN PWINDOWCLASS Class,
}
else
{
if (Class->CallProc != NULL)
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(Class->CallProc);
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 @@ IntGetClassWndProc(IN PWINDOWCLASS Class,
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 @@ IntSetClassWndProc(IN OUT PWINDOWCLASS Class,
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 @@ IntSetClassWndProc(IN OUT PWINDOWCLASS Class,
}
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 @@ IntGetClassForDesktop(IN PWINDOWCLASS BaseClass,
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,14 +512,44 @@ IntGetClassForDesktop(IN PWINDOWCLASS BaseClass,
ClassSize);
/* update some pointers and link the class */
Class->Next = BaseClass->Clone;
Class->Clone = NULL;
Class->Base = BaseClass;
Class->Desktop = Desktop;
Class->Windows = 0;
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
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
@ -503,12 +560,16 @@ IntGetClassForDesktop(IN PWINDOWCLASS BaseClass,
}
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)
{
@ -518,6 +579,72 @@ IntReferenceClass(IN PWINDOWCLASS BaseClass,
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
IntDereferenceClass(IN OUT PWINDOWCLASS Class,
IN PDESKTOP Desktop,
@ -535,12 +662,10 @@ IntDereferenceClass(IN OUT PWINDOWCLASS Class,
/* 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 @@ IntDereferenceClass(IN OUT PWINDOWCLASS Class,
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);
ASSERT(*PrevLink == 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);
/* 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
@ -613,6 +721,180 @@ IntDereferenceClass(IN OUT PWINDOWCLASS 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
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
@ -908,24 +1190,14 @@ FoundClass:
static PWINDOWCLASS
IntClassResizeInternal(IN OUT PWINDOWCLASS Class,
IN INT ClsExtraNew,
IN PWINDOWCLASS *List)
IN PWINDOWCLASS *PrevLink)
{
PWINDOWCLASS *PrevLink, CurrentClass, NewClass;
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
}
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
/* save the pointer to the base class in case it changed */
Clone->Base = Class;
Link = &Clone->Next;
Clone = Clone->Next;
}
@ -1059,15 +1332,22 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
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 @@ IntClassResize(IN OUT PWINDOWCLASS Class,
while (Clone != NULL)
{
Clone->ClsExtra = ClsExtraNew;
ASSERT(Clone->Base == Class);
Clone = Clone->Next;
}
@ -1166,8 +1449,6 @@ ClassAlreadyExists:
}
}
ASSERT(ti->Desktop != NULL);
Class = IntCreateClass(lpwcx,
ClassName,
MenuName,
@ -1447,7 +1728,8 @@ UserGetClassLongPtr(IN PWINDOWCLASS Class,
case GCLP_WNDPROC:
Ret = (ULONG_PTR)IntGetClassWndProc(Class,
GetW32ProcessInfo(),
Ansi);
Ansi,
FALSE);
break;
case GCW_ATOM:
@ -1770,7 +2052,8 @@ UserGetClassInfo(IN PWINDOWCLASS Class,
lpwcx->lpfnWndProc = IntGetClassWndProc(Class,
GetW32ProcessInfo(),
Ansi);
Ansi,
FALSE);
lpwcx->cbClsExtra = Class->ClsExtra;
lpwcx->cbWndExtra = Class->WndExtra;

View file

@ -1757,7 +1757,8 @@ IntMapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
}
BOOL
IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject)
IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
IN BOOL FreeOnFailure)
{
PDESKTOP_OBJECT OldDesktop;
PW32THREAD W32Thread;
@ -1771,6 +1772,13 @@ IntSetThreadDesktop(IN PDESKTOP_OBJECT 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;
if (MapHeap && DesktopObject != NULL)
@ -1783,6 +1791,20 @@ IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject)
}
}
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 @@ IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject)
ObDereferenceObject(OldDesktop);
/* update the thread info */
if (W32Thread != NULL && W32Thread->ThreadInfo != NULL &&
W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ? DesktopObject->DesktopInfo : NULL))
{
@ -1849,7 +1872,8 @@ NtUserSetThreadDesktop(HDESK hDesktop)
/* FIXME: Should check here to see if the thread has any windows. */
if (!IntSetThreadDesktop(DesktopObject))
if (!IntSetThreadDesktop(DesktopObject,
FALSE))
{
RETURN(FALSE);
}

View file

@ -442,7 +442,6 @@ static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window,
if (Window->CallProc2 != NULL)
{
DbgPrint("!!!!! Destroy call proc 0x%p\n", ObmObjectToHandle(Window->CallProc2));
DestroyCallProc(Window->ti->Desktop,
Window->CallProc2);
}
@ -1401,7 +1400,7 @@ co_IntCreateWindowEx(DWORD dwExStyle,
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 @@ co_IntCreateWindowEx(DWORD dwExStyle,
hInstance,
ti->kpi,
&Class,
NULL);
&ClassLink);
if (ClassAtom == (RTL_ATOM)0)
{
@ -1500,6 +1499,7 @@ co_IntCreateWindowEx(DWORD dwExStyle,
}
Class = IntReferenceClass(Class,
ClassLink,
ti->Desktop);
if (Class == NULL)
{
@ -1541,6 +1541,8 @@ co_IntCreateWindowEx(DWORD dwExStyle,
*/
Window->ti = ti;
Window->Class = Class;
Class = NULL;
Window->SystemMenu = (HMENU)0;
Window->ContextHelpId = 0;
Window->IDMenu = 0;
@ -1548,7 +1550,7 @@ co_IntCreateWindowEx(DWORD dwExStyle,
Window->hSelf = hWnd;
if (!hMenu)
hMenu = Class->hMenu;
hMenu = Window->Class->hMenu;
if (0 != (dwStyle & WS_CHILD))
{
@ -1576,18 +1578,18 @@ co_IntCreateWindowEx(DWORD dwExStyle,
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 @@ co_IntCreateWindowEx(DWORD dwExStyle,
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 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
}
Ret = (WNDPROC)ObmObjectToHandle(Window->CallProc2);
DbgPrint("!!!!!!!! Returning handle 0x%p\n", Ret);
}
}