diff --git a/reactos/subsys/win32k/include/class.h b/reactos/subsys/win32k/include/class.h index b8a752b6005..527b50fc2d7 100644 --- a/reactos/subsys/win32k/include/class.h +++ b/reactos/subsys/win32k/include/class.h @@ -28,6 +28,9 @@ typedef struct _WNDCLASS_OBJECT BOOL Global; LIST_ENTRY ListEntry; PCHAR ExtraData; + /* list of windows */ + FAST_MUTEX ClassWindowsListLock; + LIST_ENTRY ClassWindowsListHead; } WNDCLASS_OBJECT, *PWNDCLASS_OBJECT; NTSTATUS FASTCALL @@ -37,10 +40,19 @@ NTSTATUS FASTCALL CleanupClassImpl(VOID); #define IntLockProcessClasses(W32Process) \ - ExAcquireFastMutex(&W32Process->ClassListLock) + ExAcquireFastMutex(&(W32Process)->ClassListLock) #define IntUnLockProcessClasses(W32Process) \ - ExReleaseFastMutex(&W32Process->ClassListLock) + ExReleaseFastMutex(&(W32Process)->ClassListLock) + +#define IntLockClassWindows(ClassObj) \ + ExAcquireFastMutex(&(ClassObj)->ClassWindowsListLock) + +#define IntUnLockClassWindows(ClassObj) \ + ExReleaseFastMutex(&(ClassObj)->ClassWindowsListLock) + +#define ClassDereferenceObject(ClassObj) \ + ObmDereferenceObject(ClassObj) BOOL FASTCALL ClassReferenceClassByAtom( diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index 77a280a0b63..03da203bd3a 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -30,6 +30,8 @@ typedef struct _WINDOW_OBJECT { /* Pointer to the window class. */ PWNDCLASS_OBJECT Class; + /* entry in the window list of the class object */ + LIST_ENTRY ClassListEntry; /* Extended style. */ DWORD ExStyle; /* Window name. */ diff --git a/reactos/subsys/win32k/ntuser/class.c b/reactos/subsys/win32k/ntuser/class.c index 4cab09725ff..c38f3f6fa06 100644 --- a/reactos/subsys/win32k/ntuser/class.c +++ b/reactos/subsys/win32k/ntuser/class.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: class.c,v 1.56 2004/05/23 14:04:58 weiden Exp $ +/* $Id: class.c,v 1.57 2004/05/27 11:47:42 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -366,6 +366,9 @@ IntCreateClass( ClassObject->ExtraData = NULL; } + InitializeListHead(&ClassObject->ClassWindowsListHead); + ExInitializeFastMutex(&ClassObject->ClassWindowsListLock); + return(ClassObject); } @@ -690,34 +693,42 @@ NtUserUnregisterClass( if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance)) { + ObDereferenceObject(WinStaObject); SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); return FALSE; } if (Class->hInstance && Class->hInstance != hInstance) { - ObmDereferenceObject(Class); + ClassDereferenceObject(Class); + ObDereferenceObject(WinStaObject); SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); return FALSE; } - if (ObmGetReferenceCount(Class) > 2) + IntLockClassWindows(Class); + if (!IsListEmpty(&Class->ClassWindowsListHead)) { + IntUnLockClassWindows(Class); + /* Dereference the ClassReferenceClassByNameOrAtom() call */ ObmDereferenceObject(Class); + ObDereferenceObject(WinStaObject); SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS); return FALSE; } + IntUnLockClassWindows(Class); /* Dereference the ClassReferenceClassByNameOrAtom() call */ - ObmDereferenceObject(Class); + ClassDereferenceObject(Class); RemoveEntryList(&Class->ListEntry); RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Class->Atom); - ObDereferenceObject(WinStaObject); /* Free the object */ - ObmDereferenceObject(Class); + ClassDereferenceObject(Class); + + ObDereferenceObject(WinStaObject); return TRUE; } diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index eef3351487d..5af359c5efd 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: window.c,v 1.235 2004/05/19 19:16:47 weiden Exp $ +/* $Id: window.c,v 1.236 2004/05/27 11:47:42 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -387,7 +387,13 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window, /* don't remove the WINDOWSTATUS_DESTROYING bit */ IntUnLockThreadWindows(Window->OwnerThread->Win32Thread); - ObmDereferenceObject(Window->Class); + /* remove the window from the class object */ + IntLockClassWindows(Window->Class); + RemoveEntryList(&Window->ClassListEntry); + IntUnLockClassWindows(Window->Class); + + /* dereference the class */ + ClassDereferenceObject(Window->Class); Window->Class = NULL; if(Window->WindowRegion) @@ -1509,7 +1515,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, &WinStaObject); if (!NT_SUCCESS(Status)) { - ObmDereferenceObject(ClassObject); + ClassDereferenceObject(ClassObject); RtlFreeUnicodeString(&WindowName); if (NULL != ParentWindow) { @@ -1530,7 +1536,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, if (!WindowObject) { ObDereferenceObject(WinStaObject); - ObmDereferenceObject(ClassObject); + ClassDereferenceObject(ClassObject); RtlFreeUnicodeString(&WindowName); if (NULL != ParentWindow) { @@ -1551,6 +1557,10 @@ NtUserCreateWindowEx(DWORD dwExStyle, * Fill out the structure describing it. */ WindowObject->Class = ClassObject; + IntLockClassWindows(ClassObject); + InsertTailList(&ClassObject->ClassWindowsListHead, &WindowObject->ClassListEntry); + IntUnLockClassWindows(ClassObject); + WindowObject->ExStyle = dwExStyle; WindowObject->Style = dwStyle & ~WS_VISIBLE; DPRINT("1: Style is now %lx\n", WindowObject->Style); @@ -1690,6 +1700,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, /* FIXME - Delete window object and remove it from the thread windows list */ /* FIXME - delete allocated DCE */ + ClassDereferenceObject(ClassObject); DPRINT1("CBT-hook returned !0\n"); return (HWND) NULL; } @@ -1907,6 +1918,7 @@ NtUserCreateWindowEx(DWORD dwExStyle, { IntReleaseWindowObject(ParentWindow); } + ClassDereferenceObject(ClassObject); DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n"); return((HWND)0); } @@ -2463,6 +2475,8 @@ NtUserFindWindowEx(HWND hwndParent, } #endif + ClassDereferenceObject(ClassObject); + Cleanup: if(ClassName.Length > 0 && ClassName.Buffer) ExFreePool(ClassName.Buffer);