Serge Ivanov
[wine] / windows / class.c
index 639d2da..d7a1155 100644 (file)
 /*
  * Window classes functions
  *
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1993, 1996 Alexandre Julliard
+ *           1998 Juergen Schmied (jsch)
+ *
+ * FIXME: In win32 all classes are local. They are registered at 
+ *       program start. Processes CANNOT share classes. (Source: some
+ *       win31->NT migration book)
+ *
+ * FIXME: There seems to be a general problem with hInstance in WINE
+ *   classes are getting registred with wrong hInstance.
  */
 
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
-
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
+#include "wine/winbase16.h"
+#include "winerror.h"
+#include "windef.h"
+#include "wingdi.h"
+#include "wine/winuser16.h"
+#include "wine/unicode.h"
 #include "class.h"
-#include "user.h"
+#include "heap.h"
 #include "win.h"
 #include "dce.h"
-#include "stddebug.h"
-/* #define DEBUG_CLASS /* */
-/* #undef  DEBUG_CLASS /* */
-#include "debug.h"
+#include "ldt.h"
+#include "toolhelp.h"
+#include "winproc.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(class);
 
 
-static HCLASS firstClass = 0;
+static CLASS *firstClass = NULL;
 
 
 /***********************************************************************
- *           CLASS_FindClassByName
+ *           CLASS_DumpClass
  *
- * Return a handle and a pointer to the class.
- * 'ptr' can be NULL if the pointer is not needed.
+ * Dump the content of a class structure to stderr.
  */
-HCLASS CLASS_FindClassByName( char * name, CLASS **ptr )
+void CLASS_DumpClass( CLASS *ptr )
 {
-    ATOM atom;
-    HCLASS class;
-    CLASS * classPtr;
+    char className[MAX_CLASSNAME+1];
+    int i;
+
+    if (ptr->magic != CLASS_MAGIC)
+    {
+        DPRINTF("%p is not a class\n", ptr );
+        return;
+    }
+
+    GlobalGetAtomNameA( ptr->atomName, className, sizeof(className) );
+
+    DPRINTF( "Class %p:\n", ptr );
+    DPRINTF( "next=%p  name=%04x '%s'  style=%08x  wndProc=%08x\n"
+             "inst=%04x  dce=%08x  icon=%04x  cursor=%04x  bkgnd=%04x\n"
+             "clsExtra=%d  winExtra=%d  #windows=%d\n",
+             ptr->next, ptr->atomName, className, ptr->style,
+             (UINT)ptr->winproc, ptr->hInstance, (UINT)ptr->dce,
+             ptr->hIcon, ptr->hCursor, ptr->hbrBackground,
+             ptr->cbClsExtra, ptr->cbWndExtra, ptr->cWindows );
+    if (ptr->cbClsExtra)
+    {
+        DPRINTF( "extra bytes:" );
+        for (i = 0; i < ptr->cbClsExtra; i++)
+            DPRINTF( " %02x", *((BYTE *)ptr->wExtra+i) );
+        DPRINTF( "\n" );
+    }
+    DPRINTF( "\n" );
+}
+
+
+/***********************************************************************
+ *           CLASS_WalkClasses
+ *
+ * Walk the class list and print each class on stderr.
+ */
+void CLASS_WalkClasses(void)
+{
+    CLASS *ptr;
+    char className[MAX_CLASSNAME+1];
+
+    DPRINTF( " Class   Name                  Style   WndProc\n" );
+    for (ptr = firstClass; ptr; ptr = ptr->next)
+    {
+        GlobalGetAtomNameA( ptr->atomName, className, sizeof(className) );
+        DPRINTF( "%08x %-20.20s %08x %08x\n", (UINT)ptr, className,
+                 ptr->style, (UINT)ptr->winproc );
+    }
+    DPRINTF( "\n" );
+}
+
+
+/***********************************************************************
+ *           CLASS_GetMenuNameA
+ *
+ * Get the menu name as a ASCII string.
+ */
+static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
+{
+    if (!classPtr->menuNameA && classPtr->menuNameW)
+    {
+        /* We need to copy the Unicode string */
+        classPtr->menuNameA = SEGPTR_STRDUP_WtoA( classPtr->menuNameW );
+    }
+    return classPtr->menuNameA;
+}
+
+
+/***********************************************************************
+ *           CLASS_GetMenuNameW
+ *
+ * Get the menu name as a Unicode string.
+ */
+static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
+{
+    if (!classPtr->menuNameW && classPtr->menuNameA)
+    {
+        if (!HIWORD(classPtr->menuNameA))
+            return (LPWSTR)classPtr->menuNameA;
+        /* Now we need to copy the ASCII string */
+        classPtr->menuNameW = HEAP_strdupAtoW( SystemHeap, 0,
+                                               classPtr->menuNameA );
+    }
+    return classPtr->menuNameW;
+}
+
+
+/***********************************************************************
+ *           CLASS_SetMenuNameA
+ *
+ * Set the menu name in a class structure by copying the string.
+ */
+static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
+{
+    if (HIWORD(classPtr->menuNameA)) SEGPTR_FREE( classPtr->menuNameA );
+    if (classPtr->menuNameW) HeapFree( SystemHeap, 0, classPtr->menuNameW );
+    classPtr->menuNameA = SEGPTR_STRDUP( name );
+    classPtr->menuNameW = 0;
+}
+
+
+/***********************************************************************
+ *           CLASS_SetMenuNameW
+ *
+ * Set the menu name in a class structure by copying the string.
+ */
+static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
+{
+    if (!HIWORD(name))
+    {
+        CLASS_SetMenuNameA( classPtr, (LPCSTR)name );
+        return;
+    }
+    if (HIWORD(classPtr->menuNameA)) SEGPTR_FREE( classPtr->menuNameA );
+    if (classPtr->menuNameW) HeapFree( SystemHeap, 0, classPtr->menuNameW );
+    if ((classPtr->menuNameW = HeapAlloc( SystemHeap, 0,
+                                         (strlenW(name)+1)*sizeof(WCHAR) )))
+        strcpyW( classPtr->menuNameW, name );
+    classPtr->menuNameA = 0;
+}
+
+
+/***********************************************************************
+ *           CLASS_GetClassNameA
+ *
+ * Get the clas name as a ASCII string.
+ */
+static LPSTR CLASS_GetClassNameA( CLASS *classPtr )
+{
+    if (!classPtr->classNameA && classPtr->classNameW)
+    {
+        /* We need to copy the Unicode string */
+        classPtr->classNameA = SEGPTR_STRDUP_WtoA( classPtr->classNameW );
+    }
+    return classPtr->classNameA;
+}
 
-      /* First search task-specific classes */
 
-    if ((atom = FindAtom( name )) != 0)
+/***********************************************************************
+ *           CLASS_GetClassNameW
+ *
+ * Get the class name as a Unicode string.
+ */
+static LPWSTR CLASS_GetClassNameW( CLASS *classPtr )
+{
+    if (!classPtr->classNameW && classPtr->classNameA)
     {
-       for (class = firstClass; (class); class = classPtr->hNext)
-       {
-           classPtr = (CLASS *) USER_HEAP_ADDR(class);
-           if (classPtr->wc.style & CS_GLOBALCLASS) continue;
-           if (classPtr->atomName == atom)
-           {
-               if (ptr) *ptr = classPtr;
-               return class;
-           }
-       }
+        if (!HIWORD(classPtr->classNameA))
+            return (LPWSTR)classPtr->classNameA;
+        /* Now we need to copy the ASCII string */
+        classPtr->classNameW = HEAP_strdupAtoW( SystemHeap, 0,
+                                               classPtr->classNameA );
+    }
+    return classPtr->classNameW;
+}
+
+/***********************************************************************
+ *           CLASS_SetClassNameA
+ *
+ * Set the class name in a class structure by copying the string.
+ */
+static void CLASS_SetClassNameA( CLASS *classPtr, LPCSTR name )
+{
+    if (HIWORD(classPtr->classNameA)) SEGPTR_FREE( classPtr->classNameA );
+    if (classPtr->classNameW) HeapFree( SystemHeap, 0, classPtr->classNameW );
+    classPtr->classNameA = SEGPTR_STRDUP( name );
+    classPtr->classNameW = 0;
+}
+
+
+/***********************************************************************
+ *           CLASS_SetClassNameW
+ *
+ * Set the class name in a class structure by copying the string.
+ */
+static void CLASS_SetClassNameW( CLASS *classPtr, LPCWSTR name )
+{
+    if (!HIWORD(name))
+    {
+        CLASS_SetClassNameA( classPtr, (LPCSTR)name );
+        return;
+    }
+    if (HIWORD(classPtr->classNameA)) SEGPTR_FREE( classPtr->classNameA );
+    if (classPtr->classNameW) HeapFree( SystemHeap, 0, classPtr->classNameW );
+    if ((classPtr->classNameW = HeapAlloc( SystemHeap, 0,
+                                         (strlenW(name)+1)*sizeof(WCHAR) )))
+        strcpyW( classPtr->classNameW, name );
+    classPtr->classNameA = 0;
+}
+
+
+/***********************************************************************
+ *           CLASS_FreeClass
+ *
+ * Free a class structure.
+ */
+static BOOL CLASS_FreeClass( CLASS *classPtr )
+{
+    CLASS **ppClass;
+    TRACE("%p \n", classPtr);  
+
+    /* Check if we can remove this class */
+
+    if (classPtr->cWindows > 0) return FALSE;
+
+    /* Remove the class from the linked list */
+
+    for (ppClass = &firstClass; *ppClass; ppClass = &(*ppClass)->next)
+        if (*ppClass == classPtr) break;
+    if (!*ppClass)
+    {
+        ERR("Class list corrupted\n" );
+        return FALSE;
+    }
+    *ppClass = classPtr->next;
+
+    /* Delete the class */
+
+    if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
+    if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
+    GlobalDeleteAtom( classPtr->atomName );
+    CLASS_SetMenuNameA( classPtr, NULL );
+    CLASS_SetClassNameA( classPtr, NULL );
+    WINPROC_FreeProc( classPtr->winproc, WIN_PROC_CLASS );
+    HeapFree( SystemHeap, 0, classPtr );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           CLASS_FreeModuleClasses
+ */
+void CLASS_FreeModuleClasses( HMODULE16 hModule )
+{
+    CLASS *ptr, *next;
+  
+    TRACE("0x%08x \n", hModule);  
+
+    for (ptr = firstClass; ptr; ptr = next)
+    {
+        next = ptr->next;
+       if (ptr->hInstance == hModule) CLASS_FreeClass( ptr );
+    }
+}
+
+
+/***********************************************************************
+ *           CLASS_FindClassByAtom
+ *
+ * Return a pointer to the class.
+ * hinstance has been normalized by the caller.
+ *
+ * NOTES
+ *  980805 a local class will be found now if registred with hInst=0
+ *  and looed up with a hInst!=0. msmoney does it (jsch)
+ */
+CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
+{   CLASS * class, *tclass=0;
+
+    TRACE("0x%08x 0x%08x\n", atom, hinstance);
+
+    /* First search task-specific classes */
+
+    for (class = firstClass; (class); class = class->next)
+    {
+        if (class->style & CS_GLOBALCLASS) continue;
+        if (class->atomName == atom)
+        {
+            if (hinstance==class->hInstance || hinstance==0xffff )
+            {
+                TRACE("-- found local %p\n", class);
+                return class;
+            }
+            if (class->hInstance==0) tclass = class;
+        }
     }
     
       /* Then search global classes */
 
-    if ((atom = GlobalFindAtom( name )) != 0)
+    for (class = firstClass; (class); class = class->next)
     {
-       for (class = firstClass; (class); class = classPtr->hNext)
-       {
-           classPtr = (CLASS *) USER_HEAP_ADDR(class);
-           if (!(classPtr->wc.style & CS_GLOBALCLASS)) continue;
-           if (classPtr->atomName == atom)
-           {
-               if (ptr) *ptr = classPtr;
-               return class;
-           }
-       }
+        if (!(class->style & CS_GLOBALCLASS)) continue;
+        if (class->atomName == atom)
+        {
+            TRACE("-- found global %p\n", class);
+            return class;
+        }
     }
 
+    /* Then check if there was a local class with hInst=0*/
+    if ( tclass )
+    {
+        WARN("-- found local Class registred with hInst=0\n");
+        return tclass;
+    }
+    
+    TRACE("-- not found\n");
     return 0;
 }
 
 
 /***********************************************************************
- *           CLASS_FindClassPtr
+ *           CLASS_RegisterClass
  *
- * Return a pointer to the CLASS structure corresponding to a HCLASS.
+ * The real RegisterClass() functionality.
  */
-CLASS * CLASS_FindClassPtr( HCLASS hclass )
+static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance,
+                                   DWORD style, INT classExtra,
+                                   INT winExtra, WNDPROC16 wndProc,
+                                   WINDOWPROCTYPE wndProcType )
 {
-    CLASS * ptr;
+    CLASS *classPtr;
+
+    TRACE("atom=0x%x hinst=0x%x style=0x%lx clExtr=0x%x winExtr=0x%x wndProc=0x%p ProcType=0x%x\n",
+     atom, hInstance, style, classExtra, winExtra, wndProc, wndProcType);
+
+   /* Check if a class with this name already exists */
+    classPtr = CLASS_FindClassByAtom( atom, hInstance );
+    if (classPtr)
+    {
+        /* Class can be created only if it is local and */
+        /* if the class with the same name is global.   */
+
+       if (style & CS_GLOBALCLASS) return NULL;
+        if (!(classPtr->style & CS_GLOBALCLASS)) return NULL;
+    }
+
+    /* Fix the extra bytes value */
+
+    if (classExtra < 0) classExtra = 0;
+    else if (classExtra > 40)  /* Extra bytes are limited to 40 in Win32 */
+        WARN("Class extra bytes %d is > 40\n", classExtra);
+    if (winExtra < 0) winExtra = 0;
+    else if (winExtra > 40)    /* Extra bytes are limited to 40 in Win32 */
+        WARN("Win extra bytes %d is > 40\n", winExtra );
+
+    /* Create the class */
+
+    classPtr = (CLASS *)HeapAlloc( SystemHeap, 0, sizeof(CLASS) +
+                                       classExtra - sizeof(classPtr->wExtra) );
+    if (!classPtr) return NULL;
+    classPtr->next        = firstClass;
+    classPtr->magic       = CLASS_MAGIC;
+    classPtr->cWindows    = 0;  
+    classPtr->style       = style;
+    classPtr->winproc     = (HWINDOWPROC)0;
+    classPtr->cbWndExtra  = winExtra;
+    classPtr->cbClsExtra  = classExtra;
+    classPtr->hInstance   = hInstance;
+    classPtr->atomName    = atom;
+    classPtr->menuNameA   = 0;
+    classPtr->menuNameW   = 0;
+    classPtr->classNameA  = 0;
+    classPtr->classNameW  = 0;
+    classPtr->dce         = (style & CS_CLASSDC) ?
+                                 DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
+
+    WINPROC_SetProc( &classPtr->winproc, wndProc, wndProcType, WIN_PROC_CLASS);    
+
+    /* Other values must be set by caller */
+
+    if (classExtra) memset( classPtr->wExtra, 0, classExtra );
+    firstClass = classPtr;
+    return classPtr;
+}
+
+
+/***********************************************************************
+ *           RegisterClass16    (USER.57)
+ */
+ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+    int iSmIconWidth, iSmIconHeight;
+    HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
+
+    if (!(atom = GlobalAddAtomA( PTR_SEG_TO_LIN(wc->lpszClassName) ))) return 0;
+    if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
+    {
+        GlobalDeleteAtom( atom );
+        return 0;
+    }
+
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x "
+                 "bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
+                   atom, (DWORD)wc->lpfnWndProc, hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr,
+                  HIWORD(wc->lpszClassName) ?
+                       (char *)PTR_SEG_TO_LIN(wc->lpszClassName) : "" );
+
+    iSmIconWidth  = GetSystemMetrics(SM_CXSMICON);
+    iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
+
+    classPtr->hIcon         = wc->hIcon;
+    classPtr->hIconSm       = CopyImage(wc->hIcon, IMAGE_ICON,
+                                       iSmIconWidth, iSmIconHeight,
+                                       LR_COPYFROMRESOURCE);
+    classPtr->hCursor       = wc->hCursor;
+    classPtr->hbrBackground = wc->hbrBackground;
+
+    CLASS_SetMenuNameA( classPtr, HIWORD(wc->lpszMenuName) ?
+                 PTR_SEG_TO_LIN(wc->lpszMenuName) : (LPCSTR)wc->lpszMenuName );
+    CLASS_SetClassNameA( classPtr, HIWORD(wc->lpszClassName) ?
+                 PTR_SEG_TO_LIN(wc->lpszClassName) : (LPCSTR)wc->lpszClassName );
+
+    return atom;
+}
+
+
+/***********************************************************************
+ *           RegisterClassA      (USER32.427)
+ * RETURNS
+ *     >0: Unique identifier
+ *     0: Failure
+ */
+ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* Address of structure with class data */
+{
+    ATOM atom;
+    int iSmIconWidth, iSmIconHeight;
+    CLASS *classPtr;
+
+    if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
+
+    if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32A )))
+    {   GlobalDeleteAtom( atom );
+        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
+        return FALSE;
+    }
+
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n",
+                   atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr,
+                   HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
+    
+    iSmIconWidth  = GetSystemMetrics(SM_CXSMICON);
+    iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
+    
+    classPtr->hIcon         = wc->hIcon;
+    classPtr->hIconSm       = CopyImage(wc->hIcon, IMAGE_ICON,
+                                       iSmIconWidth, iSmIconHeight,
+                                       LR_COPYFROMRESOURCE);
+    classPtr->hCursor       = (HCURSOR16)wc->hCursor;
+    classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
+    
+    CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
+    CLASS_SetClassNameA( classPtr, wc->lpszClassName );
+    return atom;
+}
+
+
+/***********************************************************************
+ *           RegisterClassW      (USER32.430)
+ */
+ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
+{
+    ATOM atom;
+    int iSmIconWidth, iSmIconHeight;
+    CLASS *classPtr;
+
+    if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
+
+    if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32W )))
+    {
+        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
+        GlobalDeleteAtom( atom );
+        return 0;
+    }
+
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+                   atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr );
     
-    if (!hclass) return NULL;
-    ptr = (CLASS *) USER_HEAP_ADDR( hclass );
-    if (ptr->wMagic != CLASS_MAGIC) return NULL;
-    return ptr;
+    iSmIconWidth  = GetSystemMetrics(SM_CXSMICON);
+    iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
+
+    classPtr->hIcon         = wc->hIcon;
+    classPtr->hIconSm       = CopyImage(wc->hIcon, IMAGE_ICON,
+                                       iSmIconWidth, iSmIconHeight,
+                                       LR_COPYFROMRESOURCE);
+    classPtr->hCursor       = (HCURSOR16)wc->hCursor;
+    classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
+    
+    CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
+    CLASS_SetClassNameW( classPtr, wc->lpszClassName );
+    return atom;
 }
 
 
 /***********************************************************************
- *           RegisterClass    (USER.57)
+ *           RegisterClassEx16    (USER.397)
  */
-ATOM RegisterClass( LPWNDCLASS class )
+ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
 {
-    CLASS * newClass, * prevClassPtr;
-    HCLASS handle, prevClass;
-    int classExtra;
+    ATOM atom;
+    CLASS *classPtr;
+    HINSTANCE16 hInstance = GetExePtr( wc->hInstance );
+
+    if (!(atom = GlobalAddAtomA( PTR_SEG_TO_LIN(wc->lpszClassName) ))) return 0;
+    if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
+    {
+        GlobalDeleteAtom( atom );
+        return 0;
+    }
 
-    dprintf_class(stddeb, "RegisterClass: wndproc=%08x hinst=%d name='%s' background %x\n", 
-           class->lpfnWndProc, class->hInstance, class->lpszClassName,
-           class->hbrBackground );
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+                   atom, (DWORD)wc->lpfnWndProc, hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr );
+    
+    classPtr->hIcon         = wc->hIcon;
+    classPtr->hIconSm       = wc->hIconSm;
+    classPtr->hCursor       = wc->hCursor;
+    classPtr->hbrBackground = wc->hbrBackground;
 
-      /* Check if a class with this name already exists */
+    CLASS_SetMenuNameA( classPtr, HIWORD(wc->lpszMenuName) ?
+                 PTR_SEG_TO_LIN(wc->lpszMenuName) : (LPCSTR)wc->lpszMenuName );
+    CLASS_SetClassNameA( classPtr, HIWORD(wc->lpszClassName) ?
+                 PTR_SEG_TO_LIN(wc->lpszClassName) : (LPCSTR)wc->lpszClassName );
+    return atom;
+}
 
-    prevClass = CLASS_FindClassByName( class->lpszClassName, &prevClassPtr );
-    if (prevClass)
+
+/***********************************************************************
+ *           RegisterClassExA      (USER32.428)
+ */
+ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
+
+    if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32A )))
     {
-         /* Class can be created only if it is local and */
-         /* if the class with the same name is global.   */
+        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
+        GlobalDeleteAtom( atom );
+        return FALSE;
+    }
+
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+                   atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr );
+    
+    classPtr->hIcon         = (HICON16)wc->hIcon;
+    classPtr->hIconSm       = (HICON16)wc->hIconSm;
+    classPtr->hCursor       = (HCURSOR16)wc->hCursor;
+    classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
+    CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
+    CLASS_SetClassNameA( classPtr, wc->lpszClassName );
+    return atom;
+}
 
-       if (class->style & CS_GLOBALCLASS) return 0;
-       if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0;
+
+/***********************************************************************
+ *           RegisterClassExW      (USER32.429)
+ */
+ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
+
+    if (!(classPtr = CLASS_RegisterClass( atom, wc->hInstance, wc->style,
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32W )))
+    {
+        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
+        GlobalDeleteAtom( atom );
+        return 0;
     }
 
-      /* Create class */
+    TRACE("atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n",
+                   atom, (DWORD)wc->lpfnWndProc, wc->hInstance,
+                   wc->hbrBackground, wc->style, wc->cbClsExtra,
+                   wc->cbWndExtra, classPtr );
+    
+    classPtr->hIcon         = (HICON16)wc->hIcon;
+    classPtr->hIconSm       = (HICON16)wc->hIconSm;
+    classPtr->hCursor       = (HCURSOR16)wc->hCursor;
+    classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
+    CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
+    CLASS_SetClassNameW( classPtr, wc->lpszClassName );
+    return atom;
+}
+
 
-    classExtra = (class->cbClsExtra < 0) ? 0 : class->cbClsExtra;
-    handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS) + classExtra );
-    if (!handle) return 0;
-    newClass = (CLASS *) USER_HEAP_ADDR( handle );
-    newClass->hNext         = firstClass;
-    newClass->wMagic        = CLASS_MAGIC;
-    newClass->cWindows      = 0;  
-    newClass->wc            = *class;
-    newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra;
-    newClass->wc.cbClsExtra = classExtra;
+/***********************************************************************
+ *           UnregisterClass16    (USER.403)
+ */
+BOOL16 WINAPI UnregisterClass16( LPCSTR className, HINSTANCE16 hInstance )
+{
+    return UnregisterClassA( className, GetExePtr( hInstance ) );
+}
 
-    if (newClass->wc.style & CS_GLOBALCLASS)
-       newClass->atomName = GlobalAddAtom( class->lpszClassName );
-    else newClass->atomName = AddAtom( class->lpszClassName );
-    newClass->wc.lpszClassName = NULL; 
 
-    if (newClass->wc.style & CS_CLASSDC)
-       newClass->hdce = DCE_AllocDCE( DCE_CLASS_DC );
-    else newClass->hdce = 0;
+/***********************************************************************
+ *           UnregisterClassA    (USER32.563)
+ *
+ */
+BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
+{   CLASS *classPtr;
+    ATOM atom;
+    BOOL ret;
 
-      /* Make a copy of the menu name (only if it is a string) */
+    TRACE("%s %x\n",debugres_a(className), hInstance);
 
-    if ((int)class->lpszMenuName & 0xffff0000)
+    if (!(atom = GlobalFindAtomA( className )))
     {
-       HANDLE hname;
-       hname = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(class->lpszMenuName)+1);
-       if (hname)
-       {
-           newClass->wc.lpszMenuName = (char *)USER_HEAP_ADDR( hname );
-           strcpy( newClass->wc.lpszMenuName, class->lpszMenuName );
-       }
+        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;
+    }
+    if (!(ret = CLASS_FreeClass( classPtr )))
+        SetLastError(ERROR_CLASS_HAS_WINDOWS);
+    return ret;
+}
 
-    if (classExtra) memset( newClass->wExtra, 0, classExtra );
-    firstClass = handle;
-    return newClass->atomName;
+/***********************************************************************
+ *           UnregisterClassW    (USER32.564)
+ */
+BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
+{   CLASS *classPtr;
+    ATOM atom;
+    BOOL ret;
+
+    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;
+    }
+    if (!(ret = CLASS_FreeClass( classPtr )))
+        SetLastError(ERROR_CLASS_HAS_WINDOWS);
+    return ret;
+}
+
+/***********************************************************************
+ *           GetClassWord16    (USER.129)
+ */
+WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset )
+{
+    return GetClassWord( hwnd, offset );
 }
 
 
 /***********************************************************************
- *           UnregisterClass    (USER.403)
+ *           GetClassWord    (USER32.219)
  */
-BOOL UnregisterClass( LPSTR className, HANDLE instance )
+WORD WINAPI GetClassWord( HWND hwnd, INT offset )
 {
-    HANDLE class, prevClass;
-    CLASS * classPtr, * prevClassPtr;
+    WND * wndPtr;
+    WORD retvalue = 0;
     
-      /* Check if we can remove this class */
-    class = CLASS_FindClassByName( className, &classPtr );
-    if (!class) return FALSE;
-    if ((classPtr->wc.hInstance != instance) || (classPtr->cWindows > 0))
-       return FALSE;
+    TRACE("%x %x\n",hwnd, offset);
     
-      /* Remove the class from the linked list */
-    if (firstClass == class) firstClass = classPtr->hNext;
-    else
-    {
-       for (prevClass = firstClass; prevClass; prevClass=prevClassPtr->hNext)
-       {
-           prevClassPtr = (CLASS *) USER_HEAP_ADDR(prevClass);
-           if (prevClassPtr->hNext == class) break;
-       }
-       if (!prevClass)
-       {
-           fprintf(stderr, "ERROR: Class list corrupted\n" );
-           return FALSE;
-       }
-       prevClassPtr->hNext = classPtr->hNext;
-    }
-
-      /* Delete the class */
-    if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
-    if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
-    if (classPtr->wc.style & CS_GLOBALCLASS) GlobalDeleteAtom( classPtr->atomName );
-    else DeleteAtom( classPtr->atomName );
-    if ((int)classPtr->wc.lpszMenuName & 0xffff0000)
-       USER_HEAP_FREE( (int)classPtr->wc.lpszMenuName & 0xffff );
-    USER_HEAP_FREE( class );
-    return TRUE;
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    if (offset >= 0)
+    {
+        if (offset <= wndPtr->class->cbClsExtra - sizeof(WORD))
+        {
+            retvalue = GET_WORD(((char *)wndPtr->class->wExtra) + offset);
+            goto END;
+        }
+    }
+    else switch(offset)
+    {
+        case GCW_HBRBACKGROUND: retvalue =  wndPtr->class->hbrBackground;
+                                goto END;
+        case GCW_HCURSOR:       retvalue =  wndPtr->class->hCursor;
+                                goto END;
+        case GCW_HICON:         retvalue = wndPtr->class->hIcon;
+                                goto END;
+        case GCW_HICONSM:       retvalue = wndPtr->class->hIconSm;
+                                goto END;
+        case GCW_ATOM:          retvalue =  wndPtr->class->atomName;
+                                goto END;
+        case GCW_STYLE:
+        case GCW_CBWNDEXTRA:
+        case GCW_CBCLSEXTRA:
+        case GCW_HMODULE:
+            retvalue = (WORD)GetClassLongA( hwnd, offset );
+            goto END;
+    }
+
+    WARN("Invalid offset %d\n", offset);
+ END:
+    WIN_ReleaseWndPtr(wndPtr);
+    return retvalue;
 }
 
 
 /***********************************************************************
- *           GetClassWord    (USER.129)
+ *           GetClassLong16    (USER.131)
  */
-WORD GetClassWord( HWND hwnd, short offset )
+LONG WINAPI GetClassLong16( HWND16 hwnd, INT16 offset )
 {
-    return (WORD)GetClassLong( hwnd, offset );
+    WND *wndPtr;
+    LONG ret;
+
+    TRACE("%x %x\n",hwnd, offset);
+
+    switch( offset )
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+        ret = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
+        WIN_ReleaseWndPtr(wndPtr);
+        return ret;
+    case GCL_MENUNAME:
+        ret = GetClassLongA( hwnd, offset );
+        return (LONG)SEGPTR_GET( (void *)ret );
+    default:
+        return GetClassLongA( hwnd, offset );
+    }
 }
 
 
 /***********************************************************************
- *           SetClassWord    (USER.130)
+ *           GetClassLongA    (USER32.215)
  */
-WORD SetClassWord( HWND hwnd, short offset, WORD newval )
+LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
 {
-    CLASS * classPtr;
     WND * wndPtr;
-    WORD *ptr, retval = 0;
+    LONG retvalue;
+    
+    TRACE("%x %x\n",hwnd, offset);
     
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-    ptr = (WORD *)(((char *)classPtr->wExtra) + offset);
-    retval = *ptr;
-    *ptr = newval;
-    return retval;
+    if (offset >= 0)
+    {
+        if (offset <= wndPtr->class->cbClsExtra - sizeof(LONG))
+        {
+            retvalue = GET_DWORD(((char *)wndPtr->class->wExtra) + offset);
+            goto END;
+        }
+    }
+        
+    switch(offset)
+    {
+        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)WINPROC_GetProc(wndPtr->class->winproc, WIN_PROC_32A);
+            goto END;
+        case GCL_MENUNAME:
+            retvalue = (LONG)CLASS_GetMenuNameA( wndPtr->class );
+            goto END;
+        case GCW_ATOM:
+        case GCL_HBRBACKGROUND:
+        case GCL_HCURSOR:
+        case GCL_HICON:
+        case GCL_HICONSM:
+            retvalue = GetClassWord( hwnd, offset );
+            goto END;
+    }
+    WARN("Invalid offset %d\n", offset);
+    retvalue = 0;
+END:
+    WIN_ReleaseWndPtr(wndPtr);
+    return retvalue;
+}
+
+
+/***********************************************************************
+ *           GetClassLongW    (USER32.216)
+ */
+LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
+{
+    WND * wndPtr;
+    LONG retvalue;
+
+    TRACE("%x %x\n",hwnd, offset);
+
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+        retvalue = (LONG)WINPROC_GetProc( wndPtr->class->winproc, 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:
+        return GetClassLongA( hwnd, offset );
+    }
 }
 
 
 /***********************************************************************
- *           GetClassLong    (USER.131)
+ *           SetClassWord16    (USER.130)
  */
-LONG GetClassLong( HWND hwnd, short offset )
+WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval )
+{
+    return SetClassWord( hwnd, offset, newval );
+}
+
+
+/***********************************************************************
+ *           SetClassWord    (USER32.469)
+ */
+WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
 {
-    CLASS * classPtr;
     WND * wndPtr;
+    WORD retval = 0;
+    void *ptr;
+    
+    TRACE("%x %x %x\n",hwnd, offset, newval);
     
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-    return *(LONG *)(((char *)classPtr->wExtra) + offset);
+    if (offset >= 0)
+    {
+        if (offset + sizeof(WORD) <= wndPtr->class->cbClsExtra)
+            ptr = ((char *)wndPtr->class->wExtra) + offset;
+        else
+        {
+            WARN("Invalid offset %d\n", offset );
+            WIN_ReleaseWndPtr(wndPtr);
+            return 0;
+        }
+    }
+    else switch(offset)
+    {
+        case GCW_STYLE:
+        case GCW_CBWNDEXTRA:
+        case GCW_CBCLSEXTRA:
+        case GCW_HMODULE:
+            WIN_ReleaseWndPtr(wndPtr);
+            return (WORD)SetClassLongA( hwnd, offset, (LONG)newval );
+        case GCW_HBRBACKGROUND: ptr = &wndPtr->class->hbrBackground; break;
+        case GCW_HCURSOR:       ptr = &wndPtr->class->hCursor; break;
+        case GCW_HICON:         ptr = &wndPtr->class->hIcon; break;
+        case GCW_HICONSM:       ptr = &wndPtr->class->hIconSm; break;
+        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 );
+    
+    /* Note: If the GCW_ATOM was changed, this means that the WNDCLASS className fields
+    need to be updated as well.  Problem is that we can't tell whether the atom is 
+    using wide or narrow characters.  For now, we'll just NULL out the className 
+    fields, and emit a FIXME. */
+    if (offset == GCW_ATOM)
+    {
+        CLASS_SetClassNameA( wndPtr->class, NULL );
+        FIXME("GCW_ATOM changed for a class.  Not updating className, so GetClassInfoEx may not return correct className!\n");
+    }
+    WIN_ReleaseWndPtr(wndPtr);
+    return retval;
 }
 
 
 /***********************************************************************
- *           SetClassLong    (USER.132)
+ *           SetClassLong16    (USER.132)
  */
-LONG SetClassLong( HWND hwnd, short offset, LONG newval )
+LONG WINAPI SetClassLong16( HWND16 hwnd, INT16 offset, LONG newval )
+{
+    WND *wndPtr;
+    LONG retval;
+
+    TRACE("%x %x %lx\n",hwnd, offset, newval);
+
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+        retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_16 );
+        WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                         WIN_PROC_16, WIN_PROC_CLASS );
+        WIN_ReleaseWndPtr(wndPtr);
+        return retval;
+    case GCL_MENUNAME:
+        return SetClassLongA( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
+    default:
+        return SetClassLongA( hwnd, offset, newval );
+    }
+}
+
+
+/***********************************************************************
+ *           SetClassLongA    (USER32.467)
+ */
+LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
 {
-    CLASS * classPtr;
     WND * wndPtr;
-    LONG *ptr, retval = 0;
+    LONG retval = 0;
+    void *ptr;
     
+    TRACE("%x %x %lx\n",hwnd, offset, newval);
+        
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-    ptr = (LONG *)(((char *)classPtr->wExtra) + offset);
-    retval = *ptr;
-    *ptr = newval;
+    if (offset >= 0)
+    {
+        if (offset + sizeof(LONG) <= wndPtr->class->cbClsExtra)
+            ptr = ((char *)wndPtr->class->wExtra) + offset;
+        else
+        {
+            WARN("Invalid offset %d\n", offset );
+            retval = 0;
+            goto END;
+        }
+    }
+    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)WINPROC_GetProc( wndPtr->class->winproc,
+                                            WIN_PROC_32A );
+            WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                             WIN_PROC_32A, WIN_PROC_CLASS );
+            goto END;
+        case GCL_HBRBACKGROUND:
+        case GCL_HCURSOR:
+        case GCL_HICON:
+        case GCL_HICONSM:
+            retval = SetClassWord( hwnd, offset, (WORD)newval );
+            goto END;
+        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;
+        default:
+            WARN("Invalid offset %d\n", offset );
+            retval = 0;
+            goto END;
+    }
+    retval = GET_DWORD(ptr);
+    PUT_DWORD( ptr, newval );
+END:
+    WIN_ReleaseWndPtr(wndPtr);
     return retval;
 }
 
 
 /***********************************************************************
- *           GetClassName      (USER.58)
+ *           SetClassLongW    (USER32.468)
  */
-int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
+LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
 {
     WND *wndPtr;
-    CLASS *classPtr;
+    LONG retval;
 
+    TRACE("%x %x %lx\n",hwnd, offset, newval);
+    
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+        retval = (LONG)WINPROC_GetProc( wndPtr->class->winproc, WIN_PROC_32W );
+        WINPROC_SetProc( &wndPtr->class->winproc, (WNDPROC16)newval,
+                         WIN_PROC_32W, WIN_PROC_CLASS );
+        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:
+        return SetClassLongA( hwnd, offset, newval );
+    }
+}
+
+
+/***********************************************************************
+ *           GetClassName16      (USER.58)
+ */
+INT16 WINAPI GetClassName16( HWND16 hwnd, LPSTR buffer, INT16 count )
+{
+    return GetClassNameA( hwnd, buffer, count );
+}
+
+
+/***********************************************************************
+ *           GetClassNameA      (USER32.217)
+ */
+INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
+{   INT ret;
+    WND *wndPtr;
+            
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-    if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
+    ret = GlobalGetAtomNameA( wndPtr->class->atomName, buffer, count );
+
+    WIN_ReleaseWndPtr(wndPtr);
+    TRACE("%x %s %x\n",hwnd, buffer, count);
+    return ret;
+}
 
-    return (GetAtomName(classPtr->atomName, lpClassName, maxCount));
+
+/***********************************************************************
+ *           GetClassNameW      (USER32.218)
+ */
+INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
+{   INT ret;
+    WND *wndPtr;
+
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    ret = GlobalGetAtomNameW( wndPtr->class->atomName, buffer, count );
+    WIN_ReleaseWndPtr(wndPtr);
+    TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
+    
+    return ret;
 }
 
 
 /***********************************************************************
- *           GetClassInfo      (USER.404)
+ *           GetClassInfo16      (USER.404)
  */
-BOOL GetClassInfo(HANDLE hInstance, LPSTR lpClassName, 
-                                   LPWNDCLASS lpWndClass)
+BOOL16 WINAPI GetClassInfo16( HINSTANCE16 hInstance, LPCSTR name, WNDCLASS16 *wc )
 {
+    ATOM atom;
     CLASS *classPtr;
 
-    if (!(CLASS_FindClassByName(lpClassName, &classPtr))) return FALSE;
-    if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
+    TRACE("%x %s %p\n",hInstance, debugres_a(name), wc);
+    
+    hInstance = GetExePtr( hInstance );
+    if (!(atom = GlobalFindAtomA( name )) ||
+        !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
+        return FALSE;
+    if ((hInstance != classPtr->hInstance) &&
+        !(classPtr->style & CS_GLOBALCLASS)) /*BWCC likes to pass hInstance=0*/
+        return FALSE;
+    wc->style         = (UINT16)classPtr->style;
+    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
+    wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
+    wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
+    wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
+    wc->hIcon         = classPtr->hIcon;
+    wc->hCursor       = classPtr->hCursor;
+    wc->hbrBackground = classPtr->hbrBackground;
+    wc->lpszClassName = (SEGPTR)CLASS_GetClassNameA( classPtr );;
+    if (HIWORD(wc->lpszClassName))  /* Make it a SEGPTR */
+        wc->lpszClassName = SEGPTR_GET( (LPSTR)wc->lpszClassName );
+    wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
+    if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
+        wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
+    return TRUE;
+}
+
 
-    memcpy(lpWndClass, &(classPtr->wc), sizeof(WNDCLASS));
+/***********************************************************************
+ *           GetClassInfoA      (USER32.211)
+ */
+BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name,
+                               WNDCLASSA *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    TRACE("%x %p %p\n",hInstance, name, wc);
+
+    /* workaround: if hInstance=NULL you expect to get the system classes
+    but this classes (as example from comctl32.dll SysListView) won't be
+    registered with hInstance=NULL in WINE because of the late loading
+    of this dll. fixes file dialogs in WinWord95 (jsch)*/
+
+    if (!(atom=GlobalFindAtomA(name)) || !(classPtr=CLASS_FindClassByAtom(atom,hInstance)))
+        return FALSE;
+
+    if (!(classPtr->style & CS_GLOBALCLASS) &&
+        classPtr->hInstance &&
+        (hInstance != classPtr->hInstance))
+    {
+        if (hInstance) return FALSE;
+        WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",name);
+    }
+
+    wc->style         = classPtr->style;
+    wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32A );
+    wc->cbClsExtra    = classPtr->cbClsExtra;
+    wc->cbWndExtra    = classPtr->cbWndExtra;
+    wc->hInstance     = hInstance;
+    wc->hIcon         = (HICON)classPtr->hIcon;
+    wc->hCursor       = (HCURSOR)classPtr->hCursor;
+    wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
+    wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
+    wc->lpszClassName = CLASS_GetClassNameA( classPtr );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetClassInfoW      (USER32.214)
+ */
+BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name,
+                               WNDCLASSW *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    TRACE("%x %p %p\n",hInstance, name, wc);
+
+    if (       !(atom=GlobalFindAtomW(name)) ||
+               !(classPtr=CLASS_FindClassByAtom(atom,hInstance))
+    )
+        return FALSE;
+
+    if (!(classPtr->style & CS_GLOBALCLASS) &&
+        classPtr->hInstance &&
+        (hInstance != classPtr->hInstance))
+    {
+        if (hInstance) return FALSE;
+        WARN("systemclass %s (hInst=0) demanded but only class with hInst!=0 found\n",debugstr_w(name));
+    }
+    wc->style         = classPtr->style;
+    wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32W );
+    wc->cbClsExtra    = classPtr->cbClsExtra;
+    wc->cbWndExtra    = classPtr->cbWndExtra;
+    wc->hInstance     = hInstance;
+    wc->hIcon         = (HICON)classPtr->hIcon;
+    wc->hCursor       = (HCURSOR)classPtr->hCursor;
+    wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
+    wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
+    wc->lpszClassName = CLASS_GetClassNameW( classPtr );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetClassInfoEx16      (USER.398)
+ *
+ * FIXME: this is just a guess, I have no idea if GetClassInfoEx() is the
+ * same in Win16 as in Win32. --AJ
+ */
+BOOL16 WINAPI GetClassInfoEx16( HINSTANCE16 hInstance, LPCSTR name, WNDCLASSEX16 *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    TRACE("%x %s %p\n",hInstance,debugres_a( name ), wc);
+    
+    hInstance = GetExePtr( hInstance );
+    if (!(atom = GlobalFindAtomA( name )) ||
+        !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
+        (hInstance != classPtr->hInstance)) return FALSE;
+    wc->style         = classPtr->style;
+    wc->lpfnWndProc   = WINPROC_GetProc( classPtr->winproc, WIN_PROC_16 );
+    wc->cbClsExtra    = (INT16)classPtr->cbClsExtra;
+    wc->cbWndExtra    = (INT16)classPtr->cbWndExtra;
+    wc->hInstance     = (HINSTANCE16)classPtr->hInstance;
+    wc->hIcon         = classPtr->hIcon;
+    wc->hIconSm       = classPtr->hIconSm;
+    wc->hCursor       = classPtr->hCursor;
+    wc->hbrBackground = classPtr->hbrBackground;
+    wc->lpszClassName = (SEGPTR)0;
+    wc->lpszMenuName  = (SEGPTR)CLASS_GetMenuNameA( classPtr );
+    if (HIWORD(wc->lpszMenuName))  /* Make it a SEGPTR */
+        wc->lpszMenuName = SEGPTR_GET( (LPSTR)wc->lpszMenuName );
+    wc->lpszClassName  = (SEGPTR)CLASS_GetClassNameA( classPtr );
+    if (HIWORD(wc->lpszClassName))  /* Make it a SEGPTR */
+        wc->lpszClassName = SEGPTR_GET( (LPSTR)wc->lpszClassName );
+
+    /* We must return the atom of the class here instead of just TRUE. */
+    return atom;
+}
+
+
+/***********************************************************************
+ *           GetClassInfoExA      (USER32.212)
+ */
+BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name,
+                                 WNDCLASSEXA *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    TRACE("%x %p %p\n",hInstance, name, wc);
+    
+    if (!(atom = GlobalFindAtomA( name )) ||
+        !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) 
+       /*|| (hInstance != classPtr->hInstance) */ ) return FALSE;
+    wc->style         = classPtr->style;
+    wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32A );
+    wc->cbClsExtra    = classPtr->cbClsExtra;
+    wc->cbWndExtra    = classPtr->cbWndExtra;
+    wc->hInstance     = classPtr->hInstance;
+    wc->hIcon         = (HICON)classPtr->hIcon;
+    wc->hIconSm       = (HICON)classPtr->hIconSm;
+    wc->hCursor       = (HCURSOR)classPtr->hCursor;
+    wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
+    wc->lpszMenuName  = CLASS_GetMenuNameA( classPtr );
+    wc->lpszClassName  = CLASS_GetClassNameA( classPtr );
+    
+    /* We must return the atom of the class here instead of just TRUE. */
+    return atom;
+}
+
+
+/***********************************************************************
+ *           GetClassInfoExW      (USER32.213)
+ */
+BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name,
+                                 WNDCLASSEXW *wc )
+{
+    ATOM atom;
+    CLASS *classPtr;
+
+    TRACE("%x %p %p\n",hInstance, name, wc);
+    
+    if (!(atom = GlobalFindAtomW( name )) ||
+        !(classPtr = CLASS_FindClassByAtom( atom, hInstance )) ||
+        (hInstance != classPtr->hInstance)) return FALSE;
+    wc->style         = classPtr->style;
+    wc->lpfnWndProc   = (WNDPROC)WINPROC_GetProc( classPtr->winproc,
+                                                    WIN_PROC_32W );
+    wc->cbClsExtra    = classPtr->cbClsExtra;
+    wc->cbWndExtra    = classPtr->cbWndExtra;
+    wc->hInstance     = classPtr->hInstance;
+    wc->hIcon         = (HICON)classPtr->hIcon;
+    wc->hIconSm       = (HICON)classPtr->hIconSm;
+    wc->hCursor       = (HCURSOR)classPtr->hCursor;
+    wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
+    wc->lpszMenuName  = CLASS_GetMenuNameW( classPtr );
+    wc->lpszClassName = CLASS_GetClassNameW( classPtr );;
+    
+    /* We must return the atom of the class here instead of just TRUE. */
+    return atom;
+}
+
+
+/***********************************************************************
+ *           ClassFirst      (TOOLHELP.69)
+ */
+BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
+{
+    TRACE("%p\n",pClassEntry);
+    pClassEntry->wNext = 1;
+    return ClassNext16( pClassEntry );
+}
+
+
+/***********************************************************************
+ *           ClassNext      (TOOLHELP.70)
+ */
+BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
+{
+    int i;
+    CLASS *class = firstClass;
+
+    TRACE("%p\n",pClassEntry);
+   
+    if (!pClassEntry->wNext) return FALSE;
+    for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
+    if (!class)
+    {
+        pClassEntry->wNext = 0;
+        return FALSE;
+    }
+    pClassEntry->hInst = class->hInstance;
+    pClassEntry->wNext++;
+    GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
+                          sizeof(pClassEntry->szClassName) );
     return TRUE;
 }