Fixed locking of class list.
Print ERR when accessing classes of other processes.
diff --git a/windows/class.c b/windows/class.c
index 3c32cd8..0f01e71 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -23,6 +23,7 @@
#include "wine/port.h"
#include "heap.h"
#include "win.h"
+#include "user.h"
#include "controls.h"
#include "dce.h"
#include "winproc.h"
@@ -52,6 +53,39 @@
static CLASS *firstClass;
+/***********************************************************************
+ * get_class_ptr
+ */
+static CLASS *get_class_ptr( HWND hwnd )
+{
+ CLASS *ret = NULL;
+ WND *ptr = WIN_GetWndPtr( hwnd );
+
+ if (!ptr)
+ {
+ if (IsWindow( hwnd )) /* check other processes */
+ {
+ ERR( "class of window %04x belongs to other process\n", hwnd );
+ /* DbgBreakPoint(); */
+ }
+ }
+ else
+ {
+ if (ptr != BAD_WND_PTR) ret = ptr->class;
+ else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ }
+ return ret;
+}
+
+
+/***********************************************************************
+ * release_class_ptr
+ */
+inline static void release_class_ptr( CLASS *ptr )
+{
+ USER_Unlock();
+}
+
/***********************************************************************
* CLASS_GetProc
@@ -218,14 +252,16 @@
void CLASS_FreeModuleClasses( HMODULE16 hModule )
{
CLASS *ptr, *next;
-
- TRACE("0x%08x\n", hModule);
+ TRACE("0x%08x\n", hModule);
+
+ USER_Lock();
for (ptr = firstClass; ptr; ptr = next)
{
next = ptr->next;
if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
}
+ USER_Unlock();
}
@@ -341,6 +377,30 @@
/***********************************************************************
+ * CLASS_UnregisterClass
+ *
+ * The real UnregisterClass() functionality.
+ */
+static BOOL CLASS_UnregisterClass( ATOM atom, HINSTANCE hInstance )
+{
+ CLASS *classPtr;
+ BOOL ret = FALSE;
+
+ USER_Lock();
+ if (atom &&
+ (classPtr = CLASS_FindClassByAtom( atom, hInstance )) &&
+ (classPtr->hInstance == hInstance))
+ {
+ ret = CLASS_FreeClass( classPtr );
+ }
+ else SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
+
+ USER_Unlock();
+ return ret;
+}
+
+
+/***********************************************************************
* CLASS_RegisterBuiltinClass
*
* Register a builtin control class.
@@ -647,30 +707,14 @@
return UnregisterClassA( className, GetExePtr( hInstance ) );
}
-
/***********************************************************************
* UnregisterClassA (USER32.@)
*
*/
BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
{
- CLASS *classPtr;
- ATOM atom;
-
TRACE("%s %x\n",debugres_a(className), hInstance);
-
- if (!(atom = GlobalFindAtomA( className )))
- {
- SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
- }
- if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
- (classPtr->hInstance != hInstance))
- {
- SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
- }
- return CLASS_FreeClass( classPtr );
+ return CLASS_UnregisterClass( GlobalFindAtomA( className ), hInstance );
}
/***********************************************************************
@@ -678,23 +722,8 @@
*/
BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
{
- CLASS *classPtr;
- ATOM atom;
-
TRACE("%s %x\n",debugres_w(className), hInstance);
-
- if (!(atom = GlobalFindAtomW( className )))
- {
- SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
- }
- if (!(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
- (classPtr->hInstance != hInstance))
- {
- SetLastError(ERROR_CLASS_DOES_NOT_EXIST);
- return FALSE;
- }
- return CLASS_FreeClass( classPtr );
+ return CLASS_UnregisterClass( GlobalFindAtomW( className ), hInstance );
}
@@ -703,40 +732,20 @@
*/
WORD WINAPI GetClassWord( HWND hwnd, INT offset )
{
- WND * wndPtr;
+ CLASS *class;
WORD retvalue = 0;
-
- TRACE("%x %x\n",hwnd, offset);
-
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
- if (offset >= 0)
- {
- if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
- {
- retvalue = GET_WORD((char *)(wndPtr->class + 1) + offset);
- goto END;
- }
- }
- else switch(offset)
- {
- case GCW_ATOM:
- retvalue = wndPtr->class->atomName;
- goto END;
- case GCL_HBRBACKGROUND:
- case GCL_HCURSOR:
- case GCL_HICON:
- case GCL_HICONSM:
- case GCL_STYLE:
- case GCL_CBWNDEXTRA:
- case GCL_CBCLSEXTRA:
- case GCL_HMODULE:
- retvalue = (WORD)GetClassLongA( hwnd, offset );
- goto END;
- }
- WARN("Invalid offset %d\n", offset);
- END:
- WIN_ReleaseWndPtr(wndPtr);
+ if (offset < 0) return GetClassLongA( hwnd, offset );
+
+ TRACE("%x %x\n",hwnd, offset);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
+ if (offset <= class->cbClsExtra - sizeof(WORD))
+ retvalue = GET_WORD((char *)(class + 1) + offset);
+ else
+ SetLastError( ERROR_INVALID_INDEX );
+ release_class_ptr( class );
return retvalue;
}
@@ -744,25 +753,26 @@
/***********************************************************************
* GetClassLong (USER.131)
*/
-LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
+LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
{
- WND *wndPtr;
+ CLASS *class;
LONG ret;
+ HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
- TRACE("%x %x\n",hwnd, offset);
+ TRACE("%x %d\n",hwnd, offset);
switch( offset )
{
case GCL_WNDPROC:
- if (!(wndPtr = WIN_FindWndPtr16( hwnd ))) return 0;
- ret = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_16 );
- WIN_ReleaseWndPtr(wndPtr);
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+ ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
+ release_class_ptr( class );
return ret;
case GCL_MENUNAME:
- ret = GetClassLongA( WIN_Handle32(hwnd), offset );
+ ret = GetClassLongA( hwnd, offset );
return (LONG)SEGPTR_GET( (void *)ret );
default:
- return GetClassLongA( WIN_Handle32(hwnd), offset );
+ return GetClassLongA( hwnd, offset );
}
}
@@ -772,61 +782,63 @@
*/
LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
{
- WND * wndPtr;
- LONG retvalue;
-
- TRACE("%x %x\n",hwnd, offset);
-
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+ CLASS *class;
+ LONG retvalue = 0;
+
+ TRACE("%x %d\n", hwnd, offset);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
if (offset >= 0)
{
- if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
- {
- retvalue = GET_DWORD((char *)(wndPtr->class + 1) + offset);
- goto END;
- }
+ if (offset <= class->cbClsExtra - sizeof(LONG))
+ retvalue = GET_DWORD((char *)(class + 1) + offset);
+ else
+ SetLastError( ERROR_INVALID_INDEX );
+ release_class_ptr( class );
+ return retvalue;
}
switch(offset)
{
- case GCL_HBRBACKGROUND:
- retvalue = (LONG)wndPtr->class->hbrBackground;
- goto END;
- case GCL_HCURSOR:
- retvalue = (LONG)wndPtr->class->hCursor;
- goto END;
- case GCL_HICON:
- retvalue = (LONG)wndPtr->class->hIcon;
- goto END;
- case GCL_HICONSM:
- retvalue = (LONG)wndPtr->class->hIconSm;
- goto END;
- case GCL_STYLE:
- retvalue = (LONG)wndPtr->class->style;
- goto END;
- case GCL_CBWNDEXTRA:
- retvalue = (LONG)wndPtr->class->cbWndExtra;
- goto END;
- case GCL_CBCLSEXTRA:
- retvalue = (LONG)wndPtr->class->cbClsExtra;
- goto END;
- case GCL_HMODULE:
- retvalue = (LONG)wndPtr->class->hInstance;
- goto END;
- case GCL_WNDPROC:
- retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32A );
- goto END;
- case GCL_MENUNAME:
- retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
- goto END;
- case GCW_ATOM:
- retvalue = GetClassWord( hwnd, offset );
- goto END;
+ case GCL_HBRBACKGROUND:
+ retvalue = (LONG)class->hbrBackground;
+ break;
+ case GCL_HCURSOR:
+ retvalue = (LONG)class->hCursor;
+ break;
+ case GCL_HICON:
+ retvalue = (LONG)class->hIcon;
+ break;
+ case GCL_HICONSM:
+ retvalue = (LONG)class->hIconSm;
+ break;
+ case GCL_STYLE:
+ retvalue = (LONG)class->style;
+ break;
+ case GCL_CBWNDEXTRA:
+ retvalue = (LONG)class->cbWndExtra;
+ break;
+ case GCL_CBCLSEXTRA:
+ retvalue = (LONG)class->cbClsExtra;
+ break;
+ case GCL_HMODULE:
+ retvalue = (LONG)class->hInstance;
+ break;
+ case GCL_WNDPROC:
+ retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
+ break;
+ case GCL_MENUNAME:
+ retvalue = (LONG)CLASS_GetMenuNameA( class );
+ break;
+ case GCW_ATOM:
+ retvalue = (DWORD)class->atomName;
+ break;
+ default:
+ SetLastError( ERROR_INVALID_INDEX );
+ break;
}
- WARN("Invalid offset %d\n", offset);
- retvalue = 0;
-END:
- WIN_ReleaseWndPtr(wndPtr);
+ release_class_ptr( class );
return retvalue;
}
@@ -836,26 +848,23 @@
*/
LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
{
- WND * wndPtr;
+ CLASS *class;
LONG retvalue;
- TRACE("%x %x\n",hwnd, offset);
-
- switch(offset)
- {
- case GCL_WNDPROC:
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
- retvalue = (LONG)CLASS_GetProc( wndPtr->class, WIN_PROC_32W );
- WIN_ReleaseWndPtr(wndPtr);
- return retvalue;
- case GCL_MENUNAME:
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
- retvalue = (LONG)CLASS_GetMenuNameW( wndPtr->class );
- WIN_ReleaseWndPtr(wndPtr);
- return retvalue;
- default:
+ if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
return GetClassLongA( hwnd, offset );
- }
+
+ TRACE("%x %d\n", hwnd, offset);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
+ if (offset == GCL_WNDPROC)
+ retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
+ else /* GCL_MENUNAME */
+ retvalue = (LONG)CLASS_GetMenuNameW( class );
+
+ release_class_ptr( class );
+ return retvalue;
}
@@ -864,47 +873,24 @@
*/
WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
{
- WND * wndPtr;
+ CLASS *class;
WORD retval = 0;
- void *ptr;
-
- TRACE("%x %x %x\n",hwnd, offset, newval);
-
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
- if (offset >= 0)
+
+ if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
+
+ TRACE("%x %d %x\n", hwnd, offset, newval);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
+ if (offset <= class->cbClsExtra - sizeof(WORD))
{
- if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
- ptr = (char *)(wndPtr->class + 1) + offset;
- else
- {
- WARN("Invalid offset %d\n", offset );
- WIN_ReleaseWndPtr(wndPtr);
- return 0;
- }
+ void *ptr = (char *)(class + 1) + offset;
+ retval = GET_WORD(ptr);
+ PUT_WORD( ptr, newval );
}
- else switch(offset)
- {
- case GCL_HBRBACKGROUND:
- case GCL_HCURSOR:
- case GCL_HICON:
- case GCL_HICONSM:
- case GCL_STYLE:
- case GCL_CBWNDEXTRA:
- case GCL_CBCLSEXTRA:
- case GCL_HMODULE:
- WIN_ReleaseWndPtr(wndPtr);
- return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
- case GCW_ATOM:
- ptr = &wndPtr->class->atomName;
- break;
- default:
- WARN("Invalid offset %d\n", offset);
- WIN_ReleaseWndPtr(wndPtr);
- return 0;
- }
- retval = GET_WORD(ptr);
- PUT_WORD( ptr, newval );
- WIN_ReleaseWndPtr(wndPtr);
+ else SetLastError( ERROR_INVALID_INDEX );
+
+ release_class_ptr( class );
return retval;
}
@@ -912,25 +898,26 @@
/***********************************************************************
* SetClassLong (USER.132)
*/
-LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
+LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
{
- WND *wndPtr;
+ CLASS *class;
LONG retval;
+ HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
- TRACE("%x %x %lx\n",hwnd, offset, newval);
+ TRACE("%x %d %lx\n", hwnd, offset, newval);
switch(offset)
{
case GCL_WNDPROC:
- if (!(wndPtr = WIN_FindWndPtr16(hwnd))) return 0;
- retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_16 );
- WIN_ReleaseWndPtr(wndPtr);
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+ retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
+ release_class_ptr( class );
return retval;
case GCL_MENUNAME:
newval = (LONG)MapSL( newval );
/* fall through */
default:
- return SetClassLongA( WIN_Handle32(hwnd), offset, newval );
+ return SetClassLongA( hwnd, offset, newval );
}
}
@@ -940,69 +927,73 @@
*/
LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
{
- WND * wndPtr;
+ CLASS *class;
LONG retval = 0;
- void *ptr;
-
- TRACE("%x %x %lx\n",hwnd, offset, newval);
-
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+
+ TRACE("%x %d %lx\n", hwnd, offset, newval);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
if (offset >= 0)
{
- if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
- ptr = (char *)(wndPtr->class + 1) + offset;
- else
+ if (offset <= class->cbClsExtra - sizeof(LONG))
{
- WARN("Invalid offset %d\n", offset );
- retval = 0;
- goto END;
+ void *ptr = (char *)(class + 1) + offset;
+ retval = GET_DWORD(ptr);
+ PUT_DWORD( ptr, newval );
}
+ else SetLastError( ERROR_INVALID_INDEX );
}
else switch(offset)
{
- case GCL_MENUNAME:
- CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
- retval = 0; /* Old value is now meaningless anyway */
- goto END;
- case GCL_WNDPROC:
- retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32A );
- goto END;
- case GCL_HBRBACKGROUND:
- ptr = &wndPtr->class->hbrBackground;
- break;
- case GCL_HCURSOR:
- ptr = &wndPtr->class->hCursor;
- break;
- case GCL_HICON:
- ptr = &wndPtr->class->hIcon;
- break;
- case GCL_HICONSM:
- ptr = &wndPtr->class->hIconSm;
- break;
- case GCL_STYLE:
- ptr = &wndPtr->class->style;
- break;
- case GCL_CBWNDEXTRA:
- ptr = &wndPtr->class->cbWndExtra;
- break;
- case GCL_CBCLSEXTRA:
- ptr = &wndPtr->class->cbClsExtra;
- break;
- case GCL_HMODULE:
- ptr = &wndPtr->class->hInstance;
- break;
- case GCW_ATOM:
- WIN_ReleaseWndPtr(wndPtr);
- return SetClassWord( hwnd, offset, newval );
- default:
- WARN("Invalid offset %d\n", offset );
- retval = 0;
- goto END;
+ case GCL_MENUNAME:
+ CLASS_SetMenuNameA( class, (LPCSTR)newval );
+ retval = 0; /* Old value is now meaningless anyway */
+ break;
+ case GCL_WNDPROC:
+ retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
+ break;
+ case GCL_HBRBACKGROUND:
+ retval = (LONG)class->hbrBackground;
+ class->hbrBackground = newval;
+ break;
+ case GCL_HCURSOR:
+ retval = (LONG)class->hCursor;
+ class->hCursor = newval;
+ break;
+ case GCL_HICON:
+ retval = (LONG)class->hIcon;
+ class->hIcon = newval;
+ break;
+ case GCL_HICONSM:
+ retval = (LONG)class->hIconSm;
+ class->hIconSm = newval;
+ break;
+ case GCL_STYLE:
+ retval = (LONG)class->style;
+ class->style = newval;
+ break;
+ case GCL_CBWNDEXTRA:
+ retval = (LONG)class->cbWndExtra;
+ class->cbWndExtra = newval;
+ break;
+ case GCL_CBCLSEXTRA:
+ retval = (LONG)class->cbClsExtra;
+ class->cbClsExtra = newval;
+ break;
+ case GCL_HMODULE:
+ retval = (LONG)class->hInstance;
+ class->hInstance = newval;
+ break;
+ case GCW_ATOM:
+ retval = (DWORD)class->atomName;
+ class->atomName = newval;
+ break;
+ default:
+ SetLastError( ERROR_INVALID_INDEX );
+ break;
}
- retval = GET_DWORD(ptr);
- PUT_DWORD( ptr, newval );
-END:
- WIN_ReleaseWndPtr(wndPtr);
+ release_class_ptr( class );
return retval;
}
@@ -1012,26 +1003,25 @@
*/
LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
{
- WND *wndPtr;
+ CLASS *class;
LONG retval;
- TRACE("%x %x %lx\n",hwnd, offset, newval);
-
- switch(offset)
- {
- case GCL_WNDPROC:
- if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
- retval = (LONG)CLASS_SetProc( wndPtr->class, (WNDPROC)newval, WIN_PROC_32W );
- WIN_ReleaseWndPtr(wndPtr);
- return retval;
- case GCL_MENUNAME:
- if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
- CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
- WIN_ReleaseWndPtr(wndPtr);
- return 0; /* Old value is now meaningless anyway */
- default:
+ if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
return SetClassLongA( hwnd, offset, newval );
+
+ TRACE("%x %d %lx\n", hwnd, offset, newval);
+
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+
+ if (offset == GCL_WNDPROC)
+ retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
+ else /* GCL_MENUNAME */
+ {
+ CLASS_SetMenuNameW( class, (LPCWSTR)newval );
+ retval = 0; /* Old value is now meaningless anyway */
}
+ release_class_ptr( class );
+ return retval;
}
@@ -1039,14 +1029,15 @@
* GetClassNameA (USER32.@)
*/
INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
-{ INT ret;
- WND *wndPtr;
-
- if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
- ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
+{
+ INT ret;
+ CLASS *class;
- WIN_ReleaseWndPtr(wndPtr);
- TRACE("%x %s %x\n",hwnd, buffer, count);
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+ ret = GlobalGetAtomNameA( class->atomName, buffer, count );
+ release_class_ptr( class );
+
+ TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
return ret;
}
@@ -1055,14 +1046,15 @@
* GetClassNameW (USER32.@)
*/
INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
-{ INT ret;
- WND *wndPtr;
+{
+ INT ret;
+ CLASS *class;
- if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
- ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
- WIN_ReleaseWndPtr(wndPtr);
+ if (!(class = get_class_ptr( hwnd ))) return 0;
+ ret = GlobalGetAtomNameW( class->atomName, buffer, count );
+ release_class_ptr( class );
+
TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
-
return ret;
}