Replace RtlNtStatusToDosError(STATUS_NO_MEMORY) with ERROR_OUTOFMEMORY.
[reactos.git] / reactos / lib / user32 / windows / class.c
index c61787a..423b74c 100644 (file)
-
-#include <windows.h>
-#include <user32/class.h>
-#include <user32/win.h>
-#include <user32/heapdup.h>
-
-CLASS *rootClass;
-
-ATOM STDCALL RegisterClassA(const WNDCLASS* wc) 
-{
-       WNDCLASSEX wcex;
-       wcex.cbSize = sizeof(WNDCLASSEX);
-       wcex.style = wc->style; 
-       wcex.lpfnWndProc = wc->lpfnWndProc; 
-       wcex.cbClsExtra = wc->cbClsExtra; 
-       wcex.cbWndExtra = wc->cbWndExtra;
-       wcex.hInstance = wc->hInstance;
-       wcex.hIcon = wc->hIcon;
-       wcex.hCursor = wc->hCursor;
-       wcex.hbrBackground = wc->hbrBackground;
-       wcex.lpszMenuName = wc->lpszMenuName; 
-       wcex.lpszClassName =    wc->lpszClassName;
-       wcex.hIconSm = NULL;
-       return RegisterClassExA(&wcex);
-}
-
-ATOM STDCALL RegisterClassW(const WNDCLASS* wc) 
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS user32.dll
+ * FILE:            lib/user32/windows/class.c
+ * PURPOSE:         Window classes
+ * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *      09-05-2001  CSH  Created
+ */
+
+#include <user32.h>
+
+static BOOL GetClassInfoExCommon(
+    HINSTANCE hInst,
+    LPCWSTR lpszClass,
+    LPWNDCLASSEXW lpwcx,
+    BOOL unicode)
 {
-       WNDCLASSEX wcex;
-       wcex.cbSize = sizeof(WNDCLASSEX);
-       wcex.style = wc->style; 
-       wcex.lpfnWndProc = wc->lpfnWndProc; 
-       wcex.cbClsExtra = wc->cbClsExtra; 
-       wcex.cbWndExtra = wc->cbWndExtra;
-       wcex.hInstance = wc->hInstance;
-       wcex.hIcon = wc->hIcon;
-       wcex.hCursor = wc->hCursor;
-       wcex.hbrBackground = wc->hbrBackground;
-       wcex.lpszMenuName = wc->lpszMenuName; 
-       wcex.lpszClassName =    wc->lpszClassName;
-       wcex.hIconSm = NULL;
-       return RegisterClassExW(&wcex);
-}
+  LPWSTR str;
+  UNICODE_STRING str2, str3;
+  WNDCLASSEXW w;
+  BOOL retval;
+  NTSTATUS Status;
+
+  if ( !lpszClass || !lpwcx )
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  if(IS_ATOM(lpszClass))
+    str = (LPWSTR)lpszClass;
+  else
+  {
+    extern BOOL ControlsInitialized;
+
+    if (unicode)
+    {
+        str = HEAP_strdupW ( lpszClass, wcslen(lpszClass) );
 
-ATOM STDCALL RegisterClassExA(const WNDCLASSEX* wc) 
-{
-    ATOM atom;
-    CLASS *classPtr;
-    INT classExtra, winExtra;
-    int len;
+        if ( !str )
+        {
+          SetLastError (ERROR_OUTOFMEMORY);
+          return FALSE;
+        }
+    }
 
+    else
+    {
+        Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL);
 
-    if ( wc == NULL || wc->cbSize != sizeof(WNDCLASSEX)) {
-       SetLastError(ERROR_INVALID_DATA);
-       return FALSE;
+        if (! NT_SUCCESS(Status))
+        {
+            SetLastError(RtlNtStatusToDosError(Status));
+            return FALSE;
+        }
     }
 
-    atom = GlobalAddAtomA( wc->lpszClassName );
-    if (!atom)
+    /* Register built-in controls if not already done */
+    if ( !ControlsInitialized )
     {
-        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
-        return FALSE;
+      ControlsInitialized = ControlsInit(str);
     }
+  }
+
+  str2.Length = str3.Length = 0;
+  str2.MaximumLength = str3.MaximumLength = 255;
+  str2.Buffer = (PWSTR)HEAP_alloc ( str2.MaximumLength * sizeof(WCHAR) );
+  if ( !str2.Buffer )
+  {
+    SetLastError (ERROR_OUTOFMEMORY);
+    if ( !IS_ATOM(str) )
+      HEAP_free ( str );
+    return FALSE;
+  }
+
+  str3.Buffer = (PWSTR)HEAP_alloc ( str3.MaximumLength * sizeof(WCHAR) );
+  if ( !str3.Buffer )
+  {
+    SetLastError (ERROR_OUTOFMEMORY);
+    HEAP_free ( str2.Buffer );
+    if ( !IS_ATOM(str) )
+      HEAP_free ( str );
+    return FALSE;
+  }
+
+  w.lpszMenuName = (LPCWSTR)&str2;
+  w.lpszClassName = (LPCWSTR)&str3;
+  
+  /* get info about system classes? */
+  if (!hInst) hInst = User32Instance;
+  
+  retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0);
+  
+  w.hInstance = (hInst == User32Instance) ? 0 : hInst;
+  
+  if ( !IS_ATOM(str) )
+    HEAP_free(str);
+
+  RtlCopyMemory ( lpwcx, &w, sizeof(WNDCLASSEXW) );
+
+  if ( !IS_INTRESOURCE(w.lpszMenuName) && w.lpszMenuName )
+  {
+    if (unicode)
+        lpwcx->lpszMenuName = heap_string_poolW ( str2.Buffer, str2.Length );
+    else
+        ((LPWNDCLASSEXA) lpwcx)->lpszMenuName = heap_string_poolA ( str2.Buffer, str2.Length );
+  }
 
-    classExtra = wc->cbClsExtra;
-    if (classExtra < 0) 
-       classExtra = 0;
-    else if (classExtra > 40)  
-       classExtra = 40;
+  if ( !IS_ATOM(w.lpszClassName) && w.lpszClassName )
+  {
+    if (unicode)
+        lpwcx->lpszClassName = heap_string_poolW ( str3.Buffer, str3.Length );
+    else
+        ((LPWNDCLASSEXA) lpwcx)->lpszClassName = heap_string_poolA ( str3.Buffer, str3.Length );
+  }
 
-    winExtra = wc->cbClsExtra;
-    if (winExtra < 0) 
-       winExtra = 0;
-    else if (winExtra > 40)    
-       winExtra = 40;
+  HEAP_free ( str2.Buffer );
+  HEAP_free ( str3.Buffer );
 
-    classPtr = (CLASS *)HeapAlloc( GetProcessHeap(), 0, sizeof(CLASS) +
-                                       classExtra - sizeof(classPtr->wExtra) );
+  return retval;
+}
 
 
-    if (classExtra) 
-       memset( classPtr->wExtra, 0, classExtra );
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetClassInfoExA(
+  HINSTANCE hinst,
+  LPCSTR lpszClass,
+  LPWNDCLASSEXA lpwcx)
+{
+    return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE);
+}
 
-    if (!classPtr) {
-       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       GlobalDeleteAtom( atom );
-       return FALSE;
-    }
-    classPtr->magic       = CLASS_MAGIC;
-    classPtr->cWindows    = 0;  
-    classPtr->style       = wc->style;
-    classPtr->winproc     = wc->lpfnWndProc; 
-    classPtr->cbWndExtra  = winExtra;
-    classPtr->cbClsExtra  = classExtra;
-    classPtr->hInstance   = wc->hInstance;
-    classPtr->atomName   = atom;
-    classPtr->hIcon         = (HICON)wc->hIcon;
-    classPtr->hIconSm       = (HICON)wc->hIconSm;
-    classPtr->hCursor       = (HCURSOR)wc->hCursor;
-    classPtr->hbrBackground = (HBRUSH)wc->hbrBackground;
-    classPtr->bUnicode = FALSE;
-
-    classPtr->dce         = (wc->style & CS_CLASSDC) ?
-                                 CreateDC( "DISPLAY", NULL,NULL,NULL ) : NULL;
-    
-
-    if ( wc->lpszMenuName != NULL ) {
-       len = lstrlenA(wc->lpszMenuName);
-       classPtr->menuName = HeapAlloc(GetProcessHeap(),0,len+1);
-       lstrcpyA(classPtr->menuName,wc->lpszMenuName);
-    }
-    else
-       classPtr->menuName = NULL;
 
-    
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetClassInfoExW(
+  HINSTANCE hinst,
+  LPCWSTR lpszClass,
+  LPWNDCLASSEXW lpwcx)
+{
+    return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE);
+}
 
-    len = lstrlenA(wc->lpszClassName);
-    classPtr->className = HeapAlloc(GetProcessHeap(),0,len+1);
-    lstrcpyA(classPtr->className,wc->lpszClassName);
-    
-    
 
-    classPtr->next        = rootClass;
-    rootClass = classPtr;
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetClassInfoA(
+  HINSTANCE hInstance,
+  LPCSTR lpClassName,
+  LPWNDCLASSA lpWndClass)
+{
+  WNDCLASSEXA w;
+  BOOL retval;
+
+  if ( !lpClassName || !lpWndClass )
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  retval = GetClassInfoExA(hInstance,lpClassName,&w);
+  if (retval)
+  {
+    RtlCopyMemory ( lpWndClass, &w.style, sizeof(WNDCLASSA) );
+  }
+  return retval;
+}
 
-    return atom;
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetClassInfoW(
+  HINSTANCE hInstance,
+  LPCWSTR lpClassName,
+  LPWNDCLASSW lpWndClass)
+{
+  WNDCLASSEXW w;
+  BOOL retval;
+
+  if(!lpClassName || !lpWndClass)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  retval = GetClassInfoExW(hInstance,lpClassName,&w);
+  RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
+  return retval;
 }
 
 
-ATOM STDCALL RegisterClassExW( const WNDCLASSEX* wc )
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetClassLongA(HWND hWnd, int nIndex)
 {
-    ATOM atom;
-    CLASS *classPtr;
-    INT classExtra, winExtra;
-
-    int i, len;
-    if ( wc == NULL || wc->cbSize != sizeof(WNDCLASSEX)) {
-       SetLastError(ERROR_INVALID_DATA);
-       return FALSE;
-    }
+   switch (nIndex)
+   {
+      case GCL_HBRBACKGROUND:
+         {
+            DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
+            if (hBrush != 0 && hBrush < 0x4000)
+               hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
+            return hBrush;
+         }
+
+      case GCL_MENUNAME:
+         {
+            PUNICODE_STRING Name;
+            Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, TRUE);
+            if (IS_INTRESOURCE(Name))
+               return (DWORD)Name;
+            else
+               return (DWORD)heap_string_poolA(Name->Buffer, Name->Length);
+         }
+
+      default:
+         return NtUserGetClassLong(hWnd, nIndex, TRUE);
+   }
+}
 
-    if (!(atom = GlobalAddAtomW( (LPWSTR)wc->lpszClassName )))
-    {
-        SetLastError(ERROR_CLASS_ALREADY_EXISTS);
-        return FALSE;
-    }
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetClassLongW ( HWND hWnd, int nIndex )
+{
+   switch (nIndex)
+   {
+      case GCL_HBRBACKGROUND:
+         {
+            DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
+            if (hBrush != 0 && hBrush < 0x4000)
+               hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
+            return hBrush;
+         }
+
+      case GCL_MENUNAME:
+         {
+            PUNICODE_STRING Name;
+            Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, FALSE);
+            if (IS_INTRESOURCE(Name))
+               return (DWORD)Name;
+            else
+               return (DWORD)heap_string_poolW(Name->Buffer, Name->Length);
+         }
+
+      default:
+         return NtUserGetClassLong(hWnd, nIndex, FALSE);
+   }
+}
 
-    classExtra = wc->cbClsExtra;
-    if (classExtra < 0) 
-       classExtra = 0;
-    else if (classExtra > 40)  
-       classExtra = 40;
 
-    winExtra = wc->cbClsExtra;
-    if (winExtra < 0) 
-       winExtra = 0;
-    else if (winExtra > 40)    
-       winExtra = 40;
+/*
+ * @implemented
+ */
+int STDCALL
+GetClassNameA(
+  HWND hWnd,
+  LPSTR lpClassName,
+  int nMaxCount)
+{
+  int result;
+  LPWSTR ClassNameW;
+  NTSTATUS Status;
 
-    classPtr = (CLASS *)HeapAlloc( GetProcessHeap(), 0, sizeof(CLASS) +
-                                       classExtra - sizeof(classPtr->wExtra) );
+  if(!lpClassName)
+    return 0;
 
+  ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) );
 
-    if (classExtra) 
-       memset( classPtr->wExtra, 0, classExtra );
+  result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
 
-    if (!classPtr) {
-       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       GlobalDeleteAtom( atom );
-       return FALSE;
-    }
-    classPtr->magic       = CLASS_MAGIC;
-    classPtr->cWindows    = 0;  
-    classPtr->style       = wc->style;
-    classPtr->winproc     = wc->lpfnWndProc; 
-    classPtr->cbWndExtra  = winExtra;
-    classPtr->cbClsExtra  = classExtra;
-    classPtr->hInstance   = wc->hInstance;
-    classPtr->atomName   = atom;
-    classPtr->hIcon         = (HICON)wc->hIcon;
-    classPtr->hIconSm       = (HICON)wc->hIconSm;
-    classPtr->hCursor       = (HCURSOR)wc->hCursor;
-    classPtr->hbrBackground = (HBRUSH)wc->hbrBackground;
-    classPtr->bUnicode = FALSE;
-
-    classPtr->dce         = (wc->style & CS_CLASSDC) ?
-                                 CreateDC( "DISPLAY", NULL,NULL,NULL ) : NULL;
-
-    len = lstrlenW((LPWSTR)wc->lpszMenuName);
-    classPtr->menuName = HeapAlloc(GetProcessHeap(),0,(len+1)*2);
-    lstrcpyW((LPWSTR)classPtr->menuName, (LPWSTR)wc->lpszMenuName);
-
-
-    len = lstrlenW((LPWSTR)wc->lpszClassName);
-    classPtr->className = HeapAlloc(GetProcessHeap(),0,(len+1)*2);
-    lstrcpyW((LPWSTR)classPtr->className,(LPWSTR) wc->lpszClassName );
-
-    classPtr->next        = rootClass;
-    rootClass = classPtr;
-
-    return atom;
-}
+  Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result );
 
-WINBOOL UnregisterClassA(LPCSTR  lpClassName,   HINSTANCE  hInstance )
-{
-    CLASS *classPtr;
-    classPtr = CLASS_FindClassByAtom( STRING2ATOMA(lpClassName), hInstance );
-    if ( classPtr == NULL )
-               return FALSE;
+  HEAP_free ( ClassNameW );
 
+  if ( !NT_SUCCESS(Status) )
+    return 0;
 
-    if ( CLASS_FreeClass(classPtr) == TRUE )
-           GlobalDeleteAtom( classPtr->atomName );     
-    return TRUE;
+  return result;
 }
 
 
+/*
+ * @implemented
+ */
+int
+STDCALL
+GetClassNameW(
+  HWND hWnd,
+  LPWSTR lpClassName,
+  int nMaxCount)
+{
+   return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
+}
 
 
-WINBOOL UnregisterClassW(LPCWSTR  lpClassName,  HINSTANCE  hInstance )
+/*
+ * @implemented
+ */
+WORD
+STDCALL
+GetClassWord(
+  HWND hWnd,
+  int nIndex)
+/*
+ * NOTE: Obsoleted in 32-bit windows
+ */
 {
-    CLASS *classPtr;
-    classPtr = CLASS_FindClassByAtom( STRING2ATOMW(lpClassName), hInstance );
-    if ( classPtr == NULL )
-               return FALSE;
+    if ((nIndex < 0) && (nIndex != GCW_ATOM))
+        return 0;
 
+    return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
+}
 
-    if ( CLASS_FreeClass(classPtr) == TRUE )
-           GlobalDeleteAtom( classPtr->atomName );     
-    return TRUE;
+
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+GetWindowLongA ( HWND hWnd, int nIndex )
+{
+  return NtUserGetWindowLong(hWnd, nIndex, TRUE);
 }
 
 
-WINBOOL GetClassInfoA( HINSTANCE  hInstance, LPCSTR  lpClassName, LPWNDCLASS  lpWndClass )
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+GetWindowLongW(HWND hWnd, int nIndex)
 {
+  return NtUserGetWindowLong(hWnd, nIndex, FALSE);
+}
 
-       return FALSE;
+/*
+ * @implemented
+ */
+WORD
+STDCALL
+GetWindowWord(HWND hWnd, int nIndex)
+{
+  return (WORD)NtUserGetWindowLong(hWnd, nIndex,  TRUE);
 }
 
+/*
+ * @implemented
+ */
+WORD
+STDCALL
+SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
+{
+  return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
+}
 
-WINBOOL GetClassInfoW( HINSTANCE  hInstance, LPCWSTR  lpClassName, LPWNDCLASS  lpWndClass )
+/*
+ * @implemented
+ */
+UINT
+STDCALL
+RealGetWindowClassW(
+  HWND  hwnd,
+  LPWSTR pszType,
+  UINT  cchType)
 {
-       CLASS *classPtr;
-       ATOM a;
-
-       if ( HIWORD(lpClassName) != 0 )
-               a = FindAtomW(lpClassName);
-       else
-               a = lpClassName;
-
-       classPtr = CLASS_FindClassByAtom(  a,  hInstance );
-       if ( classPtr == NULL )
-               return FALSE;
-
-               
-       lpWndClass->style = classPtr->style;
-       lpWndClass->lpfnWndProc = classPtr->winproc;
-       lpWndClass->cbClsExtra =   classPtr->cbWndExtra;
-       lpWndClass->cbClsExtra = classPtr->cbClsExtra;
-       lpWndClass->hInstance = classPtr->hInstance;
-       lpWndClass->hIcon = classPtr->hIcon;
-       lpWndClass->hCursor = classPtr->hCursor;
-       lpWndClass->hbrBackground = classPtr->hbrBackground;
-       return TRUE;
-       
+       /* FIXME: Implement correct functionality of RealGetWindowClass */
+       return GetClassNameW(hwnd,pszType,cchType);
 }
 
-WINBOOL GetClassInfoExA( HINSTANCE  hInstance, LPCSTR  lpClassName, LPWNDCLASSEX  lpWndClass )
+
+/*
+ * @implemented
+ */
+UINT
+STDCALL
+RealGetWindowClassA(
+  HWND  hwnd,
+  LPSTR pszType,
+  UINT  cchType)
 {
+       /* FIXME: Implement correct functionality of RealGetWindowClass */
+       return GetClassNameA(hwnd,pszType,cchType);
+}
 
-       return FALSE;
+/*
+ * Create a small icon based on a standard icon
+ */
+static HICON
+CreateSmallIcon(HICON StdIcon)
+{
+   HICON SmallIcon = NULL;
+   ICONINFO StdInfo;
+   int SmallIconWidth;
+   int SmallIconHeight;
+   BITMAP StdBitmapInfo;
+   HDC hInfoDc = NULL;
+   HDC hSourceDc = NULL;
+   HDC hDestDc = NULL;
+   ICONINFO SmallInfo;
+   HBITMAP OldSourceBitmap = NULL;
+   HBITMAP OldDestBitmap = NULL;
+
+   SmallInfo.hbmColor = NULL;
+   SmallInfo.hbmMask = NULL;
+
+   /* We need something to work with... */
+   if (NULL == StdIcon)
+   {
+      goto cleanup;
+   }
+
+   SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
+   SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
+   if (! GetIconInfo(StdIcon, &StdInfo))
+   {
+      DPRINT1("Failed to get icon info for icon 0x%x\n", StdIcon);
+      goto cleanup;
+   }
+   if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
+   {
+      DPRINT1("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
+              StdIcon, StdInfo.hbmColor);
+      goto cleanup;
+   }
+   if (StdBitmapInfo.bmWidth == SmallIconWidth &&
+       StdBitmapInfo.bmHeight == SmallIconHeight)
+   {
+      /* Icon already has the correct dimensions */
+      return StdIcon;
+   }
+
+   /* Get a handle to a info DC and handles to DCs which can be used to
+      select a bitmap into. This is done to avoid triggering a switch to
+      graphics mode (if we're currently in text/blue screen mode) */
+   hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
+   if (NULL == hInfoDc)
+   {
+      DPRINT1("Failed to create info DC\n");
+      goto cleanup;
+   }
+   hSourceDc = CreateCompatibleDC(NULL);
+   if (NULL == hSourceDc)
+   {
+      DPRINT1("Failed to create source DC\n");
+      goto cleanup;
+   }
+   hDestDc = CreateCompatibleDC(NULL);
+   if (NULL == hDestDc)
+   {
+      DPRINT1("Failed to create dest DC\n");
+      goto cleanup;
+   }
+
+   OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
+   if (NULL == OldSourceBitmap)
+   {
+      DPRINT1("Failed to select source color bitmap\n");
+      goto cleanup;
+   }
+   SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
+                                              SmallIconHeight);
+   if (NULL == SmallInfo.hbmColor)
+   {
+      DPRINT1("Failed to create color bitmap\n");
+      goto cleanup;
+   }
+   OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
+   if (NULL == OldDestBitmap)
+   {
+      DPRINT1("Failed to select dest color bitmap\n");
+      goto cleanup;
+   }
+   if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+                    hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+                    StdBitmapInfo.bmHeight, SRCCOPY))
+   {
+     DPRINT1("Failed to stretch color bitmap\n");
+     goto cleanup;
+   }
+
+   if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
+   {
+      DPRINT1("Failed to select source mask bitmap\n");
+      goto cleanup;
+   }
+   SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
+                                    NULL);
+   if (NULL == SmallInfo.hbmMask)
+   {
+      DPRINT1("Failed to create mask bitmap\n");
+      goto cleanup;
+   }
+   if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
+   {
+      DPRINT1("Failed to select dest mask bitmap\n");
+      goto cleanup;
+   }
+   if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+                    hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+                    StdBitmapInfo.bmHeight, SRCCOPY))
+   {
+      DPRINT1("Failed to stretch mask bitmap\n");
+      goto cleanup;
+   }
+
+   SmallInfo.fIcon = TRUE;
+   SmallInfo.xHotspot = SmallIconWidth / 2;
+   SmallInfo.yHotspot = SmallIconHeight / 2;
+   SmallIcon = CreateIconIndirect(&SmallInfo);
+   if (NULL == SmallIcon)
+   {
+      DPRINT1("Failed to create icon\n");
+      goto cleanup;
+   }
+
+cleanup:
+   if (NULL != SmallInfo.hbmMask)
+   {
+      DeleteObject(SmallInfo.hbmMask);
+   }
+   if (NULL != OldDestBitmap)
+   {
+      SelectObject(hDestDc, OldDestBitmap);
+   }
+   if (NULL != SmallInfo.hbmColor)
+   {
+      DeleteObject(SmallInfo.hbmColor);
+   }
+   if (NULL != hDestDc)
+   {
+      DeleteDC(hDestDc);
+   }
+   if (NULL != OldSourceBitmap)
+   {
+      SelectObject(hSourceDc, OldSourceBitmap);
+   }
+   if (NULL != hSourceDc)
+   {
+      DeleteDC(hSourceDc);
+   }
+   if (NULL != hInfoDc)
+   {
+      DeleteDC(hInfoDc);
+   }
+
+   return SmallIcon;
 }
 
-WINBOOL GetClassInfoExW( HINSTANCE  hInstance, LPCWSTR  lpClassName, LPWNDCLASSEX  lpWndClassEx )
+/*
+ * @implemented
+ */
+ATOM STDCALL
+RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
 {
+   RTL_ATOM Atom;
+   WNDCLASSEXA WndClass;
+   UNICODE_STRING ClassName;
+   UNICODE_STRING MenuName;
+   HMENU hMenu;
+
+   if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) ||
+       lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
+       lpwcx->lpszClassName == NULL)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   /*
+    * On real Windows this looks more like:
+    *    if (lpwcx->hInstance == User32Instance &&
+    *        *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
+    * But since I have no idea what the magic field in the
+    * TEB structure means, I rather decided to omit that.
+    * -- Filip Navara
+    */
+   if (lpwcx->hInstance == User32Instance)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   /* Yes, this is correct. We should modify the passed structure. */
+   if (lpwcx->hInstance == NULL)
+      ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
+
+   RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
+
+   if (NULL == WndClass.hIconSm)
+   {
+      WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
+   }
+
+   if HIWORD(lpwcx->lpszMenuName)
+   {
+      hMenu = 0;
+      RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName);
+    }
+   else
+   {
+      MenuName.Length =
+      MenuName.MaximumLength = 0;
+      MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+      hMenu = LoadMenuA(WndClass.hInstance, lpwcx->lpszMenuName);
+   }
+   if (IS_ATOM(WndClass.lpszClassName))
+   {
+      ClassName.Length =
+      ClassName.MaximumLength = 0;
+      ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
+   } else
+   {
+      RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName);
+   }
+
+   Atom = NtUserRegisterClassExWOW(
+      (WNDCLASSEXW*)&WndClass,
+      &ClassName,
+      &ClassName,
+      &MenuName,
+      NULL,
+      REGISTERCLASS_ANSI,
+      0,
+      hMenu);
+
+   if (!IS_ATOM(WndClass.lpszMenuName))
+      RtlFreeUnicodeString(&MenuName);
+   if (!IS_ATOM(WndClass.lpszClassName))
+      RtlFreeUnicodeString(&ClassName);
+
+   return (ATOM)Atom;
+}
 
-       CLASS *classPtr;
-       ATOM a;
-
-       if ( HIWORD(lpClassName) != 0 )
-               a = FindAtomW(lpClassName);
-       else
-               a = lpClassName;
-
-       classPtr = CLASS_FindClassByAtom(  a, hInstance );
-       if ( classPtr == NULL )
-               return FALSE;
-
-       
-       if ( lpWndClassEx ->cbSize != sizeof(WNDCLASSEX) ) 
-               return FALSE;
-               
-       
-       lpWndClassEx->style = classPtr->style;
-       lpWndClassEx->lpfnWndProc = classPtr->winproc;
-       lpWndClassEx->cbClsExtra =   classPtr->cbWndExtra;
-       lpWndClassEx->cbClsExtra = classPtr->cbClsExtra;
-       lpWndClassEx->hInstance = classPtr->hInstance;
-       lpWndClassEx->hIcon = classPtr->hIcon;
-       lpWndClassEx->hCursor = classPtr->hCursor;
-       lpWndClassEx->hbrBackground = classPtr->hbrBackground;
-               
-       
-       return TRUE;
+/*
+ * @implemented
+ */
+ATOM STDCALL
+RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
+{
+   WNDCLASSEXW WndClass;
+   UNICODE_STRING ClassName;
+   UNICODE_STRING MenuName;
+   HMENU hMenu;
+
+   if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
+       lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
+       lpwcx->lpszClassName == NULL)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   /*
+    * On real Windows this looks more like:
+    *    if (lpwcx->hInstance == User32Instance &&
+    *        *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
+    * But since I have no idea what the magic field in the
+    * TEB structure means, I rather decided to omit that.
+    * -- Filip Navara
+    */
+   if (lpwcx->hInstance == User32Instance)
+   {
+      SetLastError(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   /* Yes, this is correct. We should modify the passed structure. */
+   if (lpwcx->hInstance == NULL)
+      ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
+
+   RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
+
+   if (NULL == WndClass.hIconSm)
+   {
+      WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
+   }
+
+   if HIWORD(lpwcx->lpszMenuName)
+   {
+      hMenu = 0;
+      RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
+    }
+   else
+   {
+      MenuName.Length =
+      MenuName.MaximumLength = 0;
+      MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+      hMenu = LoadMenuW(WndClass.hInstance, lpwcx->lpszMenuName);
+   }
+
+   if (IS_ATOM(WndClass.lpszClassName))
+   {
+      ClassName.Length =
+      ClassName.MaximumLength = 0;
+      ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
+   } else
+   {
+      RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
+   }
+
+   return (ATOM)NtUserRegisterClassExWOW(
+      &WndClass,
+      &ClassName,
+      &ClassName,
+      &MenuName,
+      NULL,
+      0,
+      0,
+      hMenu);
 }
 
-int GetClassNameA(HWND  hWnd, LPSTR  lpClassName, int  nMaxCount )
+/*
+ * @implemented
+ */
+ATOM STDCALL
+RegisterClassA(CONST WNDCLASSA *lpWndClass)
 {
-       WND *wndPtr = WIN_FindWndPtr(hWnd);
+   WNDCLASSEXA Class;
 
-       if ( wndPtr == NULL )
-               return 0;
+   if (lpWndClass == NULL)
+      return 0;
 
-       if ( wndPtr->class->bUnicode == TRUE )
-               return 0;
+   RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
+   Class.cbSize = sizeof(WNDCLASSEXA);
+   Class.hIconSm = NULL;
 
-       return lpstrncpyA(lpClassName,wndPtr->class->className, nMaxCount);
-       
+   return RegisterClassExA(&Class);
 }
 
-int GetClassNameW(HWND  hWnd, LPWSTR  lpClassName, int  nMaxCount )
+/*
+ * @implemented
+ */
+ATOM STDCALL
+RegisterClassW(CONST WNDCLASSW *lpWndClass)
 {
-       WND *wndPtr = WIN_FindWndPtr(hWnd);
+   WNDCLASSEXW Class;
+
+   if (lpWndClass == NULL)
+      return 0;
 
-       if ( wndPtr == NULL )
-               return 0;
+   RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
+   Class.cbSize = sizeof(WNDCLASSEXW);
+   Class.hIconSm = NULL;
 
-       if ( wndPtr->class->bUnicode == FALSE )
-               return 0;
+   return RegisterClassExW(&Class);
+}
 
-       return lpstrncpyW(lpClassName,wndPtr->class->className, nMaxCount);
+/*
+ * @implemented
+ */
+DWORD
+STDCALL
+SetClassLongA (
+  HWND hWnd,
+  int nIndex,
+  LONG dwNewLong)
+{
+  UNICODE_STRING str2buf;
+  PUNICODE_STRING str;
+  PUNICODE_STRING str2 = &str2buf;
+
+  if ( nIndex != GCL_MENUNAME )
+  {
+    return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
+  }
+  if ( IS_INTRESOURCE(dwNewLong) )
+  {
+    str2 = (PUNICODE_STRING)dwNewLong;
+  }
+  else
+  {
+    RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong );
+  }
+
+  str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
+
+  if ( !IS_INTRESOURCE(dwNewLong) )
+  {
+    RtlFreeUnicodeString ( str2 );
+  }
+  if ( IS_INTRESOURCE(str) )
+  {
+    return (DWORD)str;
+  }
+  else
+  {
+    return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
+  }
+}
 
 
+/*
+ * @implemented
+ */
+DWORD
+STDCALL
+SetClassLongW(
+  HWND hWnd,
+  int nIndex,
+  LONG dwNewLong)
+{
+  UNICODE_STRING str2buf;
+  PUNICODE_STRING str;
+  PUNICODE_STRING str2 = &str2buf;
+
+  if (nIndex != GCL_MENUNAME )
+  {
+    return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
+  }
+  if ( IS_INTRESOURCE(dwNewLong) )
+  {
+    str2 = (PUNICODE_STRING)dwNewLong;
+  }
+  else
+  {
+    RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong );
+  }
+
+  str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
+
+  if ( !IS_INTRESOURCE(dwNewLong) )
+  {
+    RtlFreeUnicodeString(str2);
+  }
+  if ( IS_INTRESOURCE(str) )
+  {
+    return (DWORD)str;
+  }
+  else
+  {
+    return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
+  }
 }
 
-DWORD GetClassLongA(HWND  hWnd,        int  nIndex )
+
+/*
+ * @implemented
+ */
+WORD
+STDCALL
+SetClassWord(
+  HWND hWnd,
+  int nIndex,
+  WORD wNewWord)
+/*
+ * NOTE: Obsoleted in 32-bit windows
+ */
 {
-    WND * wndPtr;
-    
-    if (!(wndPtr = WIN_FindWndPtr( hWnd ))) return 0;
-    if (nIndex >= 0)
-    {
-        if (nIndex <= wndPtr->class->cbClsExtra - sizeof(LONG))
-            return (DWORD)((char *)wndPtr->class->wExtra) + nIndex;
-    }
-    switch(nIndex)
-    {
-        case GCL_STYLE:      return (LONG)wndPtr->class->style;
-        case GCL_CBWNDEXTRA: return (LONG)wndPtr->class->cbWndExtra;
-        case GCL_CBCLSEXTRA: return (LONG)wndPtr->class->cbClsExtra;
-        case GCL_HMODULE:    return (LONG)wndPtr->class->hInstance;
-        case GCL_WNDPROC:    return (LONG)wndPtr->class->winproc;
-        case GCL_MENUNAME:   return (LONG)wndPtr->class->menuName;
-        case GCW_ATOM:
-        case GCL_HBRBACKGROUND:
-        case GCL_HCURSOR:
-        case GCL_HICON:
-        case GCL_HICONSM:
-            return GetClassWord( hWnd, nIndex );
-       default:
-           return -1;
-    }
-    
-    return 0;
+    if ((nIndex < 0) && (nIndex != GCW_ATOM))
+        return 0;
+
+    return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
 }
 
-DWORD GetClassLongW(HWND  hWnd,        int  nIndex )
+
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+SetWindowLongA(
+  HWND hWnd,
+  int nIndex,
+  LONG dwNewLong)
 {
-    WND * wndPtr;
-    
-    if (!(wndPtr = WIN_FindWndPtr( hWnd ))) return 0;
-    if (nIndex >= 0)
-    {
-        if (nIndex <= wndPtr->class->cbClsExtra - sizeof(LONG))
-            return (DWORD)((char *)wndPtr->class->wExtra) + nIndex;
-    }
-    switch(nIndex)
-    {
-        case GCL_STYLE:      return (LONG)wndPtr->class->style;
-        case GCL_CBWNDEXTRA: return (LONG)wndPtr->class->cbWndExtra;
-        case GCL_CBCLSEXTRA: return (LONG)wndPtr->class->cbClsExtra;
-        case GCL_HMODULE:    return (LONG)wndPtr->class->hInstance;
-        case GCL_WNDPROC:    return (LONG)wndPtr->class->winproc;
-        case GCL_MENUNAME:   return (LONG)wndPtr->class->menuName;
-        case GCW_ATOM:
-        case GCL_HBRBACKGROUND:
-        case GCL_HCURSOR:
-        case GCL_HICON:
-        case GCL_HICONSM:
-            return GetClassWord( hWnd, nIndex );
-       default:
-           return -1;
-    }
-    
-    return 0;
+  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
 }
 
 
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+SetWindowLongW(
+  HWND hWnd,
+  int nIndex,
+  LONG dwNewLong)
+{
+  return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
+}
+
 
-WORD STDCALL GetClassWord( HWND hWnd, INT nIndex )
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+UnregisterClassA(
+  LPCSTR lpClassName,
+  HINSTANCE hInstance)
 {
-    WND * wndPtr;
-    
-    if (!(wndPtr = WIN_FindWndPtr( hWnd ))) return 0;
-    if (nIndex >= 0)
+  LPWSTR ClassName;
+  NTSTATUS Status;
+  BOOL Result;
+
+  if(!IS_ATOM(lpClassName))
+  {
+    Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
+    if(!NT_SUCCESS(Status))
     {
-        if (nIndex <= wndPtr->class->cbClsExtra - sizeof(WORD))
-            return (WORD)((char *)wndPtr->class->wExtra) + nIndex;
-    }
-    else switch(nIndex)
-    {
-        //case GCW_HBRBACKGROUND: return wndPtr->class->hbrBackground;
-        //case GCW_HCURSOR:       return wndPtr->class->hCursor;
-        //case GCW_HICON:         return wndPtr->class->hIcon;
-    //    case GCW_HICONSM:       return wndPtr->class->hIconSm;
-        case GCW_ATOM:          return wndPtr->class->atomName;
-        //case GCW_STYLE:
-        //case GCW_CBWNDEXTRA:
-        //case GCW_CBCLSEXTRA:
-        //case GCW_HMODULE:
-            return (WORD)GetClassLongA( hWnd, nIndex );
-       default:
-           return -1;
+      SetLastError(RtlNtStatusToDosError(Status));
+      return FALSE;
     }
+  }
+  else
+    ClassName = (LPWSTR)lpClassName;
 
-    
-    return 0;
-}
+  Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
 
+  if(ClassName && !IS_ATOM(lpClassName))
+    HEAP_free(ClassName);
 
-CLASS *CLASS_FindClassByAtom( ATOM classAtom, HINSTANCE hInstance )
-{
-       CLASS *p = rootClass;
-       while(p != NULL ) {
-               if ( p->atomName == classAtom )
-                       return p;
-               p = p->next;
-       }
-       return NULL;
+  return Result;
 }
 
 
-WINBOOL CLASS_FreeClass(CLASS *classPtr)
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+UnregisterClassW(
+  LPCWSTR lpClassName,
+  HINSTANCE hInstance)
 {
-    CLASS *p = rootClass;
-    if( classPtr->cWindows > 0 )
-       return FALSE;
-
-    if (classPtr->dce) 
-       DeleteDC( classPtr->dce );
-    if (classPtr->hbrBackground) 
-       DeleteObject( classPtr->hbrBackground );
-    
-
-    classPtr->atomName = 0;
-    HeapFree(GetProcessHeap(),0,classPtr->className);
-       
-    while(p != NULL && p->next != classPtr ) 
-       p = p->next;
-    if ( p != NULL )
-       p->next = classPtr->next;
-
-    HeapFree(GetProcessHeap(),0,classPtr);
-    return TRUE;
+  return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
 }
-               
\ No newline at end of file
+
+/* EOF */