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?re... ============================================================================== --- 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/ntuse... ============================================================================== --- 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/incl... ============================================================================== --- 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/incl... ============================================================================== --- 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/main... ============================================================================== --- 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/ntus... ============================================================================== --- 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@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/ntus... ============================================================================== --- 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/ntus... ============================================================================== --- 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); } }