[ros-diffs] [peterw] 21460: Applied patch by: Thomas Weidenmueller - win32k window class rewrite. - http://www.reactos.org/bugzilla/show_bug.cgi?id=1366

aleksey at studiocerebral.com aleksey at studiocerebral.com
Wed Apr 5 10:06:04 CEST 2006


Author: peterw
Date: Wed Apr  5 12:05:55 2006
New Revision: 21460

URL: http://svn.reactos.ru/svn/reactos?rev=21460&view=rev
Log:
Applied patch by: Thomas Weidenmueller
- win32k window class rewrite.
- http://www.reactos.org/bugzilla/show_bug.cgi?id=1366

Added:
    trunk/reactos/subsystems/win32/win32k/misc/usrheap.c
Modified:
    trunk/reactos/dll/win32/user32/controls/regcontrol.c
    trunk/reactos/dll/win32/user32/misc/misc.c
    trunk/reactos/dll/win32/user32/windows/class.c
    trunk/reactos/dll/win32/user32/windows/message.c
    trunk/reactos/dll/win32/user32/windows/window.c
    trunk/reactos/include/ndk/pstypes.h
    trunk/reactos/include/reactos/probe.h
    trunk/reactos/include/reactos/win32k/ntuser.h
    trunk/reactos/lib/rtl/heap.c
    trunk/reactos/subsystems/win32/win32k/include/class.h
    trunk/reactos/subsystems/win32/win32k/include/desktop.h
    trunk/reactos/subsystems/win32/win32k/include/object.h
    trunk/reactos/subsystems/win32/win32k/include/userfuncs.h
    trunk/reactos/subsystems/win32/win32k/include/win32.h
    trunk/reactos/subsystems/win32/win32k/include/window.h
    trunk/reactos/subsystems/win32/win32k/main/dllmain.c
    trunk/reactos/subsystems/win32/win32k/misc/err.c
    trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c
    trunk/reactos/subsystems/win32/win32k/ntuser/class.c
    trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
    trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
    trunk/reactos/subsystems/win32/win32k/ntuser/hook.c
    trunk/reactos/subsystems/win32/win32k/ntuser/menu.c
    trunk/reactos/subsystems/win32/win32k/ntuser/message.c
    trunk/reactos/subsystems/win32/win32k/ntuser/misc.c
    trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c
    trunk/reactos/subsystems/win32/win32k/ntuser/object.c
    trunk/reactos/subsystems/win32/win32k/ntuser/windc.c
    trunk/reactos/subsystems/win32/win32k/ntuser/window.c
    trunk/reactos/subsystems/win32/win32k/w32k.h
    trunk/reactos/subsystems/win32/win32k/win32k.rbuild
    trunk/reactos/tools/nci/w32ksvc.db

Modified: trunk/reactos/dll/win32/user32/controls/regcontrol.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/controls/regcontrol.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/dll/win32/user32/controls/regcontrol.c (original)
+++ trunk/reactos/dll/win32/user32/controls/regcontrol.c Wed Apr  5 12:05:55 2006
@@ -44,15 +44,13 @@
       RtlInitUnicodeString(&ClassName, Descr->name);
    }
 
-   NtUserRegisterClassExWOW(
+   NtUserRegisterClassEx(
       &wc,
-      &ClassName,
       &ClassName,
       &MenuName,
       Descr->procA,
       REGISTERCLASS_SYSTEM,
-      0,
-      0);
+      NULL);
 }
 
 /***********************************************************************

Modified: trunk/reactos/dll/win32/user32/misc/misc.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/misc/misc.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/dll/win32/user32/misc/misc.c (original)
+++ trunk/reactos/dll/win32/user32/misc/misc.c Wed Apr  5 12:05:55 2006
@@ -113,3 +113,34 @@
 {
    return NtUserUpdatePerUserSystemParameters(dwReserved, bEnable);
 }
+
+PW32THREADINFO
+GetW32ThreadInfo(VOID)
+{
+    PW32THREADINFO ti;
+
+    ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo;
+    if (ti == NULL)
+    {
+        /* create the W32THREADINFO structure */
+        NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
+        ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo;
+    }
+
+    return ti;
+}
+
+PW32PROCESSINFO
+GetW32ProcessInfo(VOID)
+{
+    PW32THREADINFO ti;
+    PW32PROCESSINFO pi = NULL;
+
+    ti = GetW32ThreadInfo();
+    if (ti != NULL)
+    {
+        pi = ti->pi;
+    }
+
+    return pi;
+}

Modified: trunk/reactos/dll/win32/user32/windows/class.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/class.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/class.c (original)
+++ trunk/reactos/dll/win32/user32/windows/class.c Wed Apr  5 12:05:55 2006
@@ -11,117 +11,6 @@
 
 #include <user32.h>
 
-static BOOL GetClassInfoExCommon(
-    HINSTANCE hInst,
-    LPCWSTR lpszClass,
-    LPWNDCLASSEXW lpwcx,
-    BOOL unicode)
-{
-  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) );
-
-        if ( !str )
-        {
-          SetLastError (ERROR_OUTOFMEMORY);
-          return FALSE;
-        }
-    }
-
-    else
-    {
-        Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL);
-
-        if (! NT_SUCCESS(Status))
-        {
-            SetLastError(RtlNtStatusToDosError(Status));
-            return FALSE;
-        }
-    }
-
-    /* Register built-in controls if not already done */
-    if ( !ControlsInitialized )
-    {
-      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 );
-  }
-
-  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 );
-  }
-
-  HEAP_free ( str2.Buffer );
-  HEAP_free ( str3.Buffer );
-
-  return retval;
-}
-
 
 /*
  * @implemented
@@ -133,7 +22,40 @@
   LPCSTR lpszClass,
   LPWNDCLASSEXA lpwcx)
 {
-    return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE);
+    UNICODE_STRING ClassName = {0};
+    BOOL Ret;
+
+    if (lpszClass == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (IS_ATOM(lpszClass))
+    {
+        ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
+    }
+    else
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
+                                              lpszClass))
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+    }
+
+    Ret = NtUserGetClassInfo(hinst,
+                             &ClassName,
+                             (LPWNDCLASSEXW)lpwcx,
+                             TRUE);
+
+    if (!IS_ATOM(lpszClass))
+    {
+        RtlFreeUnicodeString(&ClassName);
+    }
+
+    return Ret;
 }
 
 
@@ -147,7 +69,28 @@
   LPCWSTR lpszClass,
   LPWNDCLASSEXW lpwcx)
 {
-    return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE);
+    UNICODE_STRING ClassName = {0};
+
+    if (lpszClass == NULL)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (IS_ATOM(lpszClass))
+    {
+        ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
+    }
+    else
+    {
+        RtlInitUnicodeString(&ClassName,
+                             lpszClass);
+    }
+
+    return NtUserGetClassInfo(hinst,
+                              &ClassName,
+                              lpwcx,
+                              FALSE);
 }
 
 
@@ -170,6 +113,7 @@
     return FALSE;
   }
 
+  w.cbSize = sizeof(w);
   retval = GetClassInfoExA(hInstance,lpClassName,&w);
   if (retval)
   {
@@ -197,8 +141,12 @@
     return FALSE;
   }
 
+  w.cbSize = sizeof(w);
   retval = GetClassInfoExW(hInstance,lpClassName,&w);
-  RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
+  if (retval)
+  {
+    RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
+  }
   return retval;
 }
 
@@ -275,25 +223,14 @@
   LPSTR lpClassName,
   int nMaxCount)
 {
-  int result;
-  LPWSTR ClassNameW;
-  NTSTATUS Status;
-
-  if(!lpClassName)
-    return 0;
-
-  ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) );
-
-  result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
-
-  Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result );
-
-  HEAP_free ( ClassNameW );
-
-  if ( !NT_SUCCESS(Status) )
-    return 0;
-
-  return result;
+    ANSI_STRING ClassName;
+
+    ClassName.MaximumLength = nMaxCount;
+    ClassName.Buffer = lpClassName;
+
+    return NtUserGetClassName(hWnd,
+                              (PUNICODE_STRING)&ClassName,
+                              TRUE);
 }
 
 
@@ -307,7 +244,14 @@
   LPWSTR lpClassName,
   int nMaxCount)
 {
-   return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
+    UNICODE_STRING ClassName;
+
+    ClassName.MaximumLength = nMaxCount;
+    ClassName.Buffer = lpClassName;
+
+    return NtUserGetClassName(hWnd,
+                              &ClassName,
+                              FALSE);
 }
 
 
@@ -573,8 +517,8 @@
    RTL_ATOM Atom;
    WNDCLASSEXA WndClass;
    UNICODE_STRING ClassName;
-   UNICODE_STRING MenuName;
-   HMENU hMenu;
+   UNICODE_STRING MenuName = {0};
+   HMENU hMenu = NULL;
 
    if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) ||
        lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
@@ -609,16 +553,17 @@
       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;
+   if (lpwcx->lpszMenuName != NULL)
+   {
+      if (HIWORD(lpwcx->lpszMenuName))
+      {
+         RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName);
+      }
+      else
+      {
+         MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+      }
+
       hMenu = LoadMenuA(WndClass.hInstance, lpwcx->lpszMenuName);
    }
  
@@ -627,20 +572,18 @@
       ClassName.Length =
       ClassName.MaximumLength = 0;
       ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
-   } else
+   }
+   else
    {
       RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName);
    }
 
-   Atom = NtUserRegisterClassExWOW(
-      (WNDCLASSEXW*)&WndClass,
-      &ClassName,
-      &ClassName,
-      &MenuName,
-      NULL,
-      REGISTERCLASS_ANSI,
-      0,
-      hMenu);
+   Atom = NtUserRegisterClassEx((WNDCLASSEXW*)&WndClass,
+                                &ClassName,
+                                &MenuName,
+                                NULL,
+                                REGISTERCLASS_ANSI,
+                                hMenu);
 
    if (!IS_ATOM(WndClass.lpszMenuName))
       RtlFreeUnicodeString(&MenuName);
@@ -658,8 +601,8 @@
 {
    WNDCLASSEXW WndClass;
    UNICODE_STRING ClassName;
-   UNICODE_STRING MenuName;
-   HMENU hMenu;
+   UNICODE_STRING MenuName = {0};
+   HMENU hMenu = NULL;
 
    if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
        lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
@@ -694,16 +637,16 @@
       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;
+   if (lpwcx->lpszMenuName != NULL)
+   {
+      if (HIWORD(lpwcx->lpszMenuName))
+      {
+         RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
+      }
+      else
+      {
+         MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+      }
       hMenu = LoadMenuW(WndClass.hInstance, lpwcx->lpszMenuName);
    }
 
@@ -712,20 +655,18 @@
       ClassName.Length =
       ClassName.MaximumLength = 0;
       ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
-   } else
+   }
+   else
    {
       RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
    }
 
-   return (ATOM)NtUserRegisterClassExWOW(
-      &WndClass,
-      &ClassName,
-      &ClassName,
-      &MenuName,
-      NULL,
-      0,
-      0,
-      hMenu);
+   return (ATOM)NtUserRegisterClassEx(&WndClass,
+                                      &ClassName,
+                                      &MenuName,
+                                      NULL,
+                                      0,
+                                      hMenu);
 }
 
 /*
@@ -769,42 +710,65 @@
  */
 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 );
-  }
+SetClassLongA (HWND hWnd,
+               int nIndex,
+               LONG dwNewLong)
+{
+    PSTR lpStr = (PSTR)dwNewLong;
+    UNICODE_STRING Value = {0};
+    BOOL Allocated = FALSE;
+    DWORD Ret;
+
+    /* FIXME - portability!!!! */
+
+    if (nIndex == GCL_MENUNAME && lpStr != NULL)
+    {
+        if (!IS_INTRESOURCE(lpStr))
+        {
+            if (!RtlCreateUnicodeStringFromAsciiz(&Value,
+                                                  lpStr))
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return 0;
+            }
+
+            Allocated = TRUE;
+        }
+        else
+            Value.Buffer = (PWSTR)lpStr;
+
+        dwNewLong = (LONG)&Value;
+    }
+    else if (nIndex == GCW_ATOM && lpStr != NULL)
+    {
+        if (!IS_ATOM(lpStr))
+        {
+            if (!RtlCreateUnicodeStringFromAsciiz(&Value,
+                                                  lpStr))
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return 0;
+            }
+
+            Allocated = TRUE;
+        }
+        else
+            Value.Buffer = (PWSTR)lpStr;
+
+        dwNewLong = (LONG)&Value;
+    }
+
+    Ret = (DWORD)NtUserSetClassLong(hWnd,
+                                    nIndex,
+                                    dwNewLong,
+                                    TRUE);
+
+    if (Allocated)
+    {
+        RtlFreeUnicodeString(&Value);
+    }
+
+    return Ret;
 }
 
 
@@ -813,42 +777,44 @@
  */
 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 );
-  }
+SetClassLongW(HWND hWnd,
+              int nIndex,
+              LONG dwNewLong)
+{
+    PWSTR lpStr = (PWSTR)dwNewLong;
+    UNICODE_STRING Value = {0};
+
+    /* FIXME - portability!!!! */
+
+    if (nIndex == GCL_MENUNAME && lpStr != NULL)
+    {
+        if (!IS_INTRESOURCE(lpStr))
+        {
+            RtlInitUnicodeString(&Value,
+                                 lpStr);
+        }
+        else
+            Value.Buffer = lpStr;
+
+        dwNewLong = (LONG)&Value;
+    }
+    else if (nIndex == GCW_ATOM && lpStr != NULL)
+    {
+        if (!IS_ATOM(lpStr))
+        {
+            RtlInitUnicodeString(&Value,
+                                 lpStr);
+        }
+        else
+            Value.Buffer = lpStr;
+
+        dwNewLong = (LONG)&Value;
+    }
+
+    return (DWORD)NtUserSetClassLong(hWnd,
+                                     nIndex,
+                                     dwNewLong,
+                                     FALSE);
 }
 
 
@@ -868,7 +834,7 @@
     if ((nIndex < 0) && (nIndex != GCW_ATOM))
         return 0;
 
-    return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
+    return (WORD) SetClassLongW ( hWnd, nIndex, wNewWord );
 }
 
 
@@ -909,28 +875,32 @@
   LPCSTR lpClassName,
   HINSTANCE hInstance)
 {
-  LPWSTR ClassName;
-  NTSTATUS Status;
-  BOOL Result;
-
-  if(!IS_ATOM(lpClassName))
-  {
-    Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
-    if(!NT_SUCCESS(Status))
-    {
-      SetLastError(RtlNtStatusToDosError(Status));
-      return FALSE;
-    }
-  }
-  else
-    ClassName = (LPWSTR)lpClassName;
-
-  Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
-
-  if(ClassName && !IS_ATOM(lpClassName))
-    HEAP_free(ClassName);
-
-  return Result;
+    UNICODE_STRING ClassName = {0};
+    NTSTATUS Status;
+    BOOL Ret;
+
+    if (!IS_ATOM(lpClassName))
+    {
+        Status = HEAP_strdupAtoW(&ClassName.Buffer, lpClassName, NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastError(RtlNtStatusToDosError(Status));
+            return FALSE;
+        }
+
+        RtlInitUnicodeString(&ClassName,
+                             ClassName.Buffer);
+    }
+    else
+        ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
+
+    Ret = NtUserUnregisterClass(&ClassName,
+                                hInstance);
+
+    if(!IS_ATOM(lpClassName) && ClassName.Buffer != NULL)
+        HEAP_free(ClassName.Buffer);
+
+    return Ret;
 }
 
 
@@ -943,7 +913,18 @@
   LPCWSTR lpClassName,
   HINSTANCE hInstance)
 {
-  return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
+    UNICODE_STRING ClassName = {0};
+
+    if (!IS_ATOM(lpClassName))
+    {
+        RtlInitUnicodeString(&ClassName,
+                             lpClassName);
+    }
+    else
+        ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
+
+    return NtUserUnregisterClass(&ClassName,
+                                 hInstance);
 }
 
 /* EOF */

Modified: trunk/reactos/dll/win32/user32/windows/message.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/message.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/message.c (original)
+++ trunk/reactos/dll/win32/user32/windows/message.c Wed Apr  5 12:05:55 2006
@@ -951,6 +951,7 @@
           return FALSE;
         }
       Result = WndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam);
+
       if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result))
         {
           return FALSE;
@@ -991,6 +992,7 @@
         }
       Result = WndProc(UnicodeMsg.hwnd, UnicodeMsg.message,
                        UnicodeMsg.wParam, UnicodeMsg.lParam);
+
       if (! MsgiAnsiToUnicodeReply(&UnicodeMsg, &AnsiMsg, &Result))
         {
           return FALSE;
@@ -1010,20 +1012,19 @@
 		WPARAM wParam,
 		LPARAM lParam)
 {
-  BOOL IsHandle;
-  WndProcHandle wphData;
+  WNDPROC_INFO wpInfo;
 
   if (lpPrevWndFunc == NULL)
-    lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWL_WNDPROC, FALSE);
-
-  IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
-  if (! IsHandle)
+    lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, FALSE);
+
+  if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc,
+                                      &wpInfo))
     {
       return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
     }
   else
     {
-      return IntCallWindowProcA(! wphData.IsUnicode, wphData.WindowProc,
+      return IntCallWindowProcA(!wpInfo.IsUnicode, wpInfo.WindowProc,
                                 hWnd, Msg, wParam, lParam);
     }
 }
@@ -1039,17 +1040,16 @@
 		WPARAM wParam,
 		LPARAM lParam)
 {
-  BOOL IsHandle;
-  WndProcHandle wphData;
-
-  IsHandle = NtUserDereferenceWndProcHandle(lpPrevWndFunc,&wphData);
-  if (! IsHandle)
+  WNDPROC_INFO wpInfo;
+
+  if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc,
+                                      &wpInfo))
     {
       return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
     }
   else
     {
-      return IntCallWindowProcW(! wphData.IsUnicode, wphData.WindowProc,
+      return IntCallWindowProcW(!wpInfo.IsUnicode, wpInfo.WindowProc,
                                 hWnd, Msg, wParam, lParam);
     }
 }

Modified: trunk/reactos/dll/win32/user32/windows/window.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/window.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/window.c (original)
+++ trunk/reactos/dll/win32/user32/windows/window.c Wed Apr  5 12:05:55 2006
@@ -289,8 +289,8 @@
   {
     wce.cbSize = sizeof(WNDCLASSEXW);
     if(GetClassInfoExW(hInstance, lpClassName, &wce) && wce.lpszMenuName)
-    {
-      hMenu = LoadMenuW(hInstance, wce.lpszMenuName);
+    {DbgPrint("LoadingMenu 0x%p %d\n", wce.lpszMenuName, IS_INTRESOURCE(wce.lpszMenuName));
+    hMenu = LoadMenuW(hInstance, wce.lpszMenuName);DbgPrint("Loaded menu: 0x%p\n", hMenu);
     }
   }
 
@@ -1449,7 +1449,7 @@
 STDCALL
 GetFocus(VOID)
 {
-  return (HWND)NtUserGetThreadState(0);
+  return (HWND)NtUserGetThreadState(THREADSTATE_FOCUSWINDOW);
 }
 
 /*

Modified: trunk/reactos/include/ndk/pstypes.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/ndk/pstypes.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/include/ndk/pstypes.h (original)
+++ trunk/reactos/include/ndk/pstypes.h Wed Apr  5 12:05:55 2006
@@ -424,7 +424,7 @@
     ULONG LastErrorValue;                   /* 34h */
     ULONG CountOfOwnedCriticalSections;     /* 38h */
     PVOID CsrClientThread;                  /* 3Ch */
-    struct _W32THREAD* Win32ThreadInfo;     /* 40h */
+    PVOID Win32ThreadInfo;                  /* 40h */
     ULONG User32Reserved[0x1A];             /* 44h */
     ULONG UserReserved[5];                  /* ACh */
     PVOID WOW32Reserved;                    /* C0h */

Modified: trunk/reactos/include/reactos/probe.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/probe.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/include/reactos/probe.h (original)
+++ trunk/reactos/include/reactos/probe.h Wed Apr  5 12:05:55 2006
@@ -8,6 +8,14 @@
 static const UNICODE_STRING __emptyUnicodeString = {0};
 static const LARGE_INTEGER __emptyLargeInteger = {{0, 0}};
 static const ULARGE_INTEGER __emptyULargeInteger = {{0, 0}};
+
+#if defined(_WIN32K_)
+/*
+ * NOTE: NTOSKRNL unfortunately doesn't export RtlRaiseStatus!
+ */
+VOID NTAPI W32kRaiseStatus(NTSTATUS Status);
+#define RtlRaiseStatus W32kRaiseStatus
+#endif
 
 /*
  * NOTE: Alignment of the pointers is not verified!

Modified: trunk/reactos/include/reactos/win32k/ntuser.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/win32k/ntuser.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/include/reactos/win32k/ntuser.h (original)
+++ trunk/reactos/include/reactos/win32k/ntuser.h Wed Apr  5 12:05:55 2006
@@ -1,6 +1,75 @@
 #ifndef __WIN32K_NTUSER_H
 #define __WIN32K_NTUSER_H
 
+struct _W32PROCESSINFO;
+struct _W32THREADINFO;
+
+typedef struct _DESKTOP
+{
+    HANDLE hKernelHeap;
+    WCHAR szDesktopName[1];
+} DESKTOP, *PDESKTOP;
+
+typedef struct _CALLPROC
+{
+    struct _W32PROCESSINFO *pi;
+    WNDPROC WndProc;
+    BOOL Unicode : 1;
+} CALLPROC, *PCALLPROC;
+
+typedef struct _WINDOWCLASS
+{
+    struct _WINDOWCLASS *Next;
+    struct _WINDOWCLASS *Clone;
+    struct _WINDOWCLASS *Base;
+    PDESKTOP Desktop;
+    RTL_ATOM Atom;
+    ULONG Windows;
+
+    UINT Style;
+    WNDPROC WndProc;
+    union
+    {
+        WNDPROC WndProcExtra;
+        PCALLPROC CallProc;
+    };
+    INT ClsExtra;
+    INT WndExtra;
+    HINSTANCE hInstance;
+    HANDLE hIcon; /* FIXME - Use pointer! */
+    HANDLE hIconSm; /* FIXME - Use pointer! */
+    HANDLE hCursor; /* FIXME - Use pointer! */
+    HBRUSH hbrBackground;
+    HANDLE hMenu; /* FIXME - Use pointer! */
+    PWSTR MenuName;
+    PSTR AnsiMenuName;
+
+    ULONG_PTR ClassExtraDataOffset;
+
+    BOOL Destroying : 1;
+    BOOL Unicode : 1;
+    BOOL System : 1;
+    BOOL Global : 1;
+} WINDOWCLASS, *PWINDOWCLASS;
+
+typedef struct _W32PROCESSINFO
+{
+    PVOID UserHandleTable;
+    PWINDOWCLASS LocalClassList;
+    PWINDOWCLASS GlobalClassList;
+    PWINDOWCLASS SystemClassList;
+} W32PROCESSINFO, *PW32PROCESSINFO;
+
+typedef struct _W32THREADINFO
+{
+    PW32PROCESSINFO pi; /* [USER] */
+    PW32PROCESSINFO kpi; /* [KERNEL] */
+    PDESKTOP Desktop;
+    ULONG_PTR DesktopHeapDelta;
+} W32THREADINFO, *PW32THREADINFO;
+
+PW32THREADINFO GetW32ThreadInfo(VOID);
+PW32PROCESSINFO GetW32ProcessInfo(VOID);
 
 DWORD
 NTAPI
@@ -196,8 +265,8 @@
 ULONG NTAPI
 NtUserGetSystemMetrics(ULONG Index);
 
-DWORD NTAPI
-NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi);
+ULONG_PTR NTAPI
+NtUserGetClassLong(HWND hWnd, INT Offset, BOOL Ansi);
 
 LONG NTAPI
 NtUserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi);
@@ -785,18 +854,17 @@
 NtUserGetCaretPos(
   LPPOINT lpPoint);
 
-DWORD NTAPI
-NtUserGetClassInfo(HINSTANCE hInst,
-		   LPCWSTR str,
+BOOL NTAPI
+NtUserGetClassInfo(HINSTANCE hInstance,
+		   PUNICODE_STRING ClassName,
 		   LPWNDCLASSEXW wcex,
-		   BOOL Ansi,
-		   DWORD unknown3);
-
-DWORD
+		   BOOL Ansi);
+
+INT
 NTAPI
 NtUserGetClassName(HWND hWnd,
-		   LPWSTR lpClassName,
-		   ULONG nMaxCount);
+		   PUNICODE_STRING ClassName,
+                   BOOL Ansi);
 
 HANDLE
 NTAPI
@@ -1041,6 +1109,7 @@
   DWORD dwThreadId,
   DWORD Unknown1);
 
+#define THREADSTATE_GETTHREADINFO   (0)
 #define THREADSTATE_FOCUSWINDOW (1)
 #define THREADSTATE_INSENDMESSAGE       (2)
 DWORD
@@ -1355,14 +1424,12 @@
 #define REGISTERCLASS_ALL	(REGISTERCLASS_ANSI | REGISTERCLASS_SYSTEM)
 
 RTL_ATOM NTAPI
-NtUserRegisterClassExWOW(
+NtUserRegisterClassEx(
    CONST WNDCLASSEXW* lpwcx,
    PUNICODE_STRING ClassName,
-   PUNICODE_STRING ClassNameCopy,
    PUNICODE_STRING MenuName,
    WNDPROC wpExtra,
    DWORD Flags,
-   DWORD Unknown7,
    HMENU hMenu);
 
 BOOL
@@ -1470,11 +1537,11 @@
 HWND NTAPI
 NtUserGetCapture(VOID);
 
-DWORD NTAPI
+ULONG_PTR NTAPI
 NtUserSetClassLong(
   HWND  hWnd,
-  DWORD Offset,
-  LONG  dwNewLong,
+  INT Offset,
+  ULONG_PTR  dwNewLong,
   BOOL  Ansi );
 
 
@@ -1840,9 +1907,8 @@
 BOOL
 NTAPI
 NtUserUnregisterClass(
-  LPCWSTR ClassNameOrAtom,
-  HINSTANCE hInstance,
-  DWORD Unknown);
+  PUNICODE_STRING ClassNameOrAtom,
+  HINSTANCE hInstance);
 
 BOOL
 NTAPI
@@ -1951,15 +2017,15 @@
 
 HWND NTAPI
 NtUserGetLastActivePopup(HWND hWnd);
-typedef struct _WndProcHandle
+
+typedef struct _WNDPROC_INFO
 {
-  WNDPROC WindowProc;
-  BOOL IsUnicode;
-  HANDLE ProcessID;
-} WndProcHandle;
+    WNDPROC WindowProc;
+    BOOL IsUnicode;
+} WNDPROC_INFO, *PWNDPROC_INFO;
                                     
-DWORD NTAPI
-NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data);
+BOOL NTAPI
+NtUserDereferenceWndProcHandle(IN HANDLE wpHandle, OUT PWNDPROC_INFO wpInfo);
 
 VOID NTAPI
 NtUserManualGuiCheck(LONG Check);

Modified: trunk/reactos/lib/rtl/heap.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/lib/rtl/heap.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/lib/rtl/heap.c (original)
+++ trunk/reactos/lib/rtl/heap.c Wed Apr  5 12:05:55 2006
@@ -311,7 +311,7 @@
    }
    else
    {
-      Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+      Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
                                        &address,
                                        0,
                                        &commitsize,
@@ -570,13 +570,24 @@
 
       /* Initialize critical section */
 
-      RtlInitializeHeapLock( &heap->critSection );
+      if (RtlpGetMode() == UserMode)
+      {
+         RtlInitializeHeapLock( &heap->critSection );
+      }
    }
 
    /* Commit memory */
    if (heap->commitRoutine)
    {
-      Status = heap->commitRoutine(heap, &address, &commitSize);
+      if (subheap != (SUBHEAP *)heap)
+      {
+         Status = heap->commitRoutine(heap, &address, &commitSize);
+      }
+      else
+      {
+         /* the caller is responsible for committing the first page! */
+         Status = STATUS_SUCCESS;
+      }
    }
    else
    {

Modified: trunk/reactos/subsystems/win32/win32k/include/class.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/class.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/class.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/class.h Wed Apr  5 12:05:55 2006
@@ -4,28 +4,19 @@
 #define IS_ATOM(x) \
   (((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000))
 
-typedef struct _WNDCLASS_OBJECT
-{
-  UINT    cbSize;
-  LONG    refs;                  /* windows using this class (is 0 after class creation) */
-  UINT    style;
-  WNDPROC lpfnWndProcA;
-  WNDPROC lpfnWndProcW;
-  int     cbClsExtra;
-  int     cbWndExtra;
-  HANDLE  hInstance;
-  HICON   hIcon;
-  HCURSOR hCursor;
-  HBRUSH  hbrBackground;
-  HMENU   hMenu;
-  UNICODE_STRING lpszMenuName;
-  RTL_ATOM Atom;
-  HICON   hIconSm;
-  BOOL Unicode;
-  BOOL Global;
-  LIST_ENTRY ListEntry;          /* linked into owning process */
-  PCHAR   ExtraData;
-} WNDCLASS_OBJECT, *PWNDCLASS_OBJECT;
+VOID
+DestroyCallProc(IN PDESKTOP Desktop,
+                IN OUT PCALLPROC CallProc);
+
+PCALLPROC
+CloneCallProc(IN PDESKTOP Desktop,
+              IN PCALLPROC CallProc);
+
+PCALLPROC
+CreateCallProc(IN PDESKTOP Desktop,
+               IN WNDPROC WndProc,
+               IN BOOL Unicode,
+               IN PW32PROCESSINFO pi);
 
 NTSTATUS FASTCALL
 InitClassImpl(VOID);
@@ -33,32 +24,45 @@
 NTSTATUS FASTCALL
 CleanupClassImpl(VOID);
 
-void FASTCALL DestroyProcessClasses(PW32PROCESS Process );
+BOOL
+UserGetCallProcInfo(IN HANDLE hCallProc,
+                    OUT PWNDPROC_INFO wpInfo);
 
-__inline VOID FASTCALL 
-ClassDerefObject(PWNDCLASS_OBJECT Class);
+void FASTCALL
+DestroyProcessClasses(PW32PROCESS Process );
 
-__inline VOID FASTCALL 
-ClassRefObject(PWNDCLASS_OBJECT Class);
+PWINDOWCLASS
+IntReferenceClass(IN PWINDOWCLASS BaseClass,
+                  IN PDESKTOP Desktop);
 
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByAtom(
-   RTL_ATOM Atom,
-   HINSTANCE hInstance);
+VOID
+IntDereferenceClass(IN OUT PWINDOWCLASS Class,
+                    IN PDESKTOP Desktop,
+                    IN PW32PROCESSINFO pi);
 
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByName(
-   LPCWSTR ClassName,
-   HINSTANCE hInstance);
+RTL_ATOM
+UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
+                  IN PUNICODE_STRING ClassName,
+                  IN PUNICODE_STRING MenuName,
+                  IN HANDLE hMenu,
+                  IN WNDPROC wpExtra,
+                  IN DWORD dwFlags);
 
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByNameOrAtom(
-   LPCWSTR ClassNameOrAtom,
-   HINSTANCE hInstance);
+BOOL
+UserUnregisterClass(IN PUNICODE_STRING ClassName,
+                    IN HINSTANCE hInstance);
 
-struct _WINDOW_OBJECT;
-ULONG FASTCALL
-IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi);
+ULONG_PTR
+UserGetClassLongPtr(IN PWINDOWCLASS Class,
+                    IN INT Index,
+                    IN BOOL Ansi);
+
+RTL_ATOM
+IntGetClassAtom(IN PUNICODE_STRING ClassName,
+                IN HINSTANCE hInstance  OPTIONAL,
+                IN PW32PROCESSINFO pi  OPTIONAL,
+                OUT PWINDOWCLASS *BaseClass  OPTIONAL,
+                OUT PWINDOWCLASS **Link  OPTIONAL);
 
 #endif /* _WIN32K_CLASS_H */
 

Modified: trunk/reactos/subsystems/win32/win32k/include/desktop.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/desktop.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/desktop.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/desktop.h Wed Apr  5 12:05:55 2006
@@ -6,8 +6,6 @@
 
 typedef struct _DESKTOP_OBJECT
 {
-    PVOID DesktopHeap; /* points to kmode memory! */
-
     CSHORT Type;
     CSHORT Size;
     LIST_ENTRY ListEntry;
@@ -26,11 +24,15 @@
     PVOID BlockInputThread;
 
     LIST_ENTRY ShellHookWindows;
+
+    HANDLE hDesktopHeap;
+    PSECTION_OBJECT DesktopHeapSection;
+    PDESKTOP DesktopInfo;
 } DESKTOP_OBJECT, *PDESKTOP_OBJECT;
 
 extern PDESKTOP_OBJECT InputDesktop;
 extern HDESK InputDesktopHandle;
-extern PWNDCLASS_OBJECT DesktopWindowClass;
+extern PWINDOWCLASS DesktopWindowClass;
 extern HDC ScreenDeviceContext;
 extern BOOL g_PaintDesktopVersion;
 
@@ -91,6 +93,8 @@
 HDESK FASTCALL
 IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject);
 
+BOOL IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject);
+
 NTSTATUS FASTCALL
 IntValidateDesktopHandle(
    HDESK Desktop,
@@ -115,6 +119,113 @@
 #define IntIsActiveDesktop(Desktop) \
   ((Desktop)->WindowStation->ActiveDesktop == (Desktop))
 
+static __inline PVOID
+DesktopHeapAlloc(IN PDESKTOP Desktop,
+                 IN SIZE_T Bytes)
+{
+    return RtlAllocateHeap(Desktop->hKernelHeap,
+                           HEAP_NO_SERIALIZE,
+                           Bytes);
+}
+
+static __inline BOOL
+DesktopHeapFree(IN PDESKTOP Desktop,
+                IN PVOID lpMem)
+{
+    return RtlFreeHeap(Desktop->hKernelHeap,
+                       HEAP_NO_SERIALIZE,
+                       lpMem);
+}
+
+static __inline PVOID
+DesktopHeapReAlloc(IN PDESKTOP Desktop,
+                   IN PVOID lpMem,
+                   IN SIZE_T Bytes)
+{
+#if 0
+    /* NOTE: ntoskrnl doesn't export RtlReAllocateHeap... */
+    return RtlReAllocateHeap(Desktop->hKernelHeap,
+                             HEAP_NO_SERIALIZE,
+                             lpMem,
+                             Bytes);
+#else
+    SIZE_T PrevSize;
+    PVOID pNew;
+
+    PrevSize = RtlSizeHeap(Desktop->hKernelHeap,
+                           HEAP_NO_SERIALIZE,
+                           lpMem);
+
+    if (PrevSize == Bytes)
+        return lpMem;
+
+    pNew = RtlAllocateHeap(Desktop->hKernelHeap,
+                           HEAP_NO_SERIALIZE,
+                           Bytes);
+    if (pNew != NULL)
+    {
+        if (PrevSize < Bytes)
+            Bytes = PrevSize;
+
+        RtlCopyMemory(pNew,
+                      lpMem,
+                      Bytes);
+
+        RtlFreeHeap(Desktop->hKernelHeap,
+                    HEAP_NO_SERIALIZE,
+                    lpMem);
+    }
+
+    return pNew;
+#endif
+}
+
+static __inline ULONG_PTR
+DesktopHeapGetUserDelta(VOID)
+{
+    PW32HEAP_USER_MAPPING Mapping;
+    HANDLE hDesktopHeap;
+    ULONG_PTR Delta = 0;
+
+    ASSERT(PsGetWin32Thread()->Desktop != NULL);
+    hDesktopHeap = PsGetWin32Thread()->Desktop->hDesktopHeap;
+
+    Mapping = PsGetWin32Process()->HeapMappings.Next;
+    while (Mapping != NULL)
+    {
+        if (Mapping->UserMapping == (PVOID)hDesktopHeap)
+        {
+            Delta = (ULONG_PTR)Mapping->KernelMapping - (ULONG_PTR)Mapping->UserMapping;
+            break;
+        }
+
+        Mapping = Mapping->Next;
+    }
+
+    return Delta;
+}
+
+static __inline PVOID
+DesktopHeapAddressToUser(IN PDESKTOP Desktop,
+                         PVOID lpMem)
+{
+    PW32HEAP_USER_MAPPING Mapping;
+
+    Mapping = PsGetWin32Process()->HeapMappings.Next;
+    while (Mapping != NULL)
+    {
+        if (Mapping->KernelMapping == (PVOID)Desktop->hKernelHeap)
+        {
+            return (PVOID)(((ULONG_PTR)lpMem - (ULONG_PTR)Desktop->hKernelHeap) +
+                           (ULONG_PTR)Mapping->UserMapping);
+        }
+
+        Mapping = Mapping->Next;
+    }
+
+    return NULL;
+}
+
 #endif /* _WIN32K_DESKTOP_H */
 
 /* EOF */

Modified: trunk/reactos/subsystems/win32/win32k/include/object.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/object.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/object.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/object.h Wed Apr  5 12:05:55 2006
@@ -45,7 +45,7 @@
   otCursorIcon,
   otHook,
   otMonitor,
-  otClass //fixme: remove
+  otCallProc
   
 } USER_OBJECT_TYPE;
 
@@ -125,6 +125,8 @@
    \
 }
 
+HANDLE FASTCALL ObmObjectToHandle(PVOID obj);
+
 VOID  FASTCALL CreateStockObjects (VOID);
 VOID  FASTCALL CreateSysColorObjects (VOID);
 

Modified: trunk/reactos/subsystems/win32/win32k/include/userfuncs.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/userfuncs.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/userfuncs.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/userfuncs.h Wed Apr  5 12:05:55 2006
@@ -75,7 +75,7 @@
 
 /******************** HANDLE.C ***************/
 
-extern USER_HANDLE_TABLE gHandleTable;
+extern PUSER_HANDLE_TABLE gHandleTable;
 
 PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle );
 VOID UserInitHandleTable(PUSER_HANDLE_TABLE ht, PVOID mem, ULONG bytes);

Modified: trunk/reactos/subsystems/win32/win32k/include/win32.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/win32.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/win32.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/win32.h Wed Apr  5 12:05:55 2006
@@ -15,10 +15,18 @@
   BOOLEAN IsExiting;
   SINGLE_LIST_ENTRY  ReferencesList;
 
+  PW32THREADINFO ThreadInfo;
 } W32THREAD, *PW32THREAD;
 
 #include <poppack.h>
 
+typedef struct _W32HEAP_USER_MAPPING
+{
+    struct _W32HEAP_USER_MAPPING *Next;
+    PVOID KernelMapping;
+    PVOID UserMapping;
+    ULONG Count;
+} W32HEAP_USER_MAPPING, *PW32HEAP_USER_MAPPING;
 
 typedef struct _W32PROCESS
 {
@@ -32,6 +40,9 @@
   ULONG Flags;
   LONG GDIObjects;
   LONG UserObjects;
+
+  W32HEAP_USER_MAPPING HeapMappings;
+  PW32PROCESSINFO ProcessInfo;
 } W32PROCESS, *PW32PROCESS;
 
 

Modified: trunk/reactos/subsystems/win32/win32k/include/window.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/window.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/window.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/window.h Wed Apr  5 12:05:55 2006
@@ -26,8 +26,21 @@
 
 typedef struct _WINDOW_OBJECT
 {
+  /* Pointer to the thread information */
+  PW32THREADINFO ti;
+  /* Pointer to the desktop */
+  PDESKTOP Desktop;
+  union
+  {
+    /* Pointer to a call procedure handle */
+    PCALLPROC CallProc;
+    /* Extra Wnd proc (windows of system classes) */
+    WNDPROC WndProcExtra;
+  };
+  /* Indicates whether the window is derived from a system class */
+  BOOL IsSystem;
   /* Pointer to the window class. */
-  PWNDCLASS_OBJECT Class;
+  PWINDOWCLASS Class;
   /* Extended style. */
   DWORD ExStyle;
   /* Window name. */
@@ -81,8 +94,7 @@
   PWINDOW_SCROLLINFO Scroll;
   LONG UserData;
   BOOL Unicode;
-  WNDPROC WndProcA;
-  WNDPROC WndProcW;
+  WNDPROC WndProc;
   PETHREAD OwnerThread;
   HWND hWndLastPopup; /* handle to last active popup window (wine doesn't use pointer, for unk. reason)*/
   PINTERNALPOS InternalPos;
@@ -190,10 +202,6 @@
 BOOL FASTCALL
 IntIsWindowInDestroy(PWINDOW_OBJECT Window);
 
-DWORD IntRemoveWndProcHandle(WNDPROC Handle);
-DWORD IntRemoveProcessWndProcHandles(HANDLE ProcessID);
-DWORD IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode);
-
 BOOL FASTCALL
 IntShowOwnedPopups( PWINDOW_OBJECT owner, BOOL fShow );
 

Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/main/dllmain.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/main/dllmain.c (original)
+++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c Wed Apr  5 12:05:55 2006
@@ -33,6 +33,9 @@
 PGDI_HANDLE_TABLE GdiHandleTable = NULL;
 PSECTION_OBJECT GdiTableSection = NULL;
 
+HANDLE GlobalUserHeap = NULL;
+PSECTION_OBJECT GlobalUserHeapSection = NULL;
+
 extern ULONG_PTR Win32kSSDT[];
 extern UCHAR Win32kSSPT[];
 extern ULONG Win32kNumberOfSysCalls;
@@ -69,7 +72,34 @@
 
   if (Create)
     {
+      ULONG ViewSize = 0;
+      LARGE_INTEGER Offset;
+      PVOID UserBase = NULL;
+      NTSTATUS Status;
+      extern PSECTION_OBJECT GlobalUserHeapSection;
       DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
+
+      /* map the global heap into the process */
+      Offset.QuadPart = 0;
+      Status = MmMapViewOfSection(GlobalUserHeapSection,
+                                  PsGetCurrentProcess(),
+                                  &UserBase,
+                                  0,
+                                  0,
+                                  &Offset,
+                                  &ViewSize,
+                                  ViewUnmap,
+                                  SEC_NO_CHANGE,
+                                  PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+      if (!NT_SUCCESS(Status))
+      {
+          DPRINT1("Failed to map the global heap! 0x%x\n", Status);
+          RETURN(Status);
+      }
+      Win32Process->HeapMappings.Next = NULL;
+      Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
+      Win32Process->HeapMappings.UserMapping = UserBase;
+      Win32Process->HeapMappings.Count = 1;
 
       InitializeListHead(&Win32Process->ClassList);
 
@@ -95,7 +125,6 @@
   else
     {
       DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
-      IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId);
       IntCleanupMenus(Process, Win32Process);
       IntCleanupCurIcons(Process, Win32Process);
       IntEngCleanupDriverObjs(Process, Win32Process);
@@ -114,6 +143,12 @@
       if(LogonProcess == Win32Process)
       {
         LogonProcess = NULL;
+      }
+
+      if (Win32Process->ProcessInfo != NULL)
+      {
+          UserHeapFree(Win32Process->ProcessInfo);
+          Win32Process->ProcessInfo = NULL;
       }
     }
 
@@ -198,17 +233,25 @@
 
         if (hDesk != NULL)
         {
+          PDESKTOP_OBJECT DesktopObject;
+          Win32Thread->Desktop = NULL;
           Status = ObReferenceObjectByHandle(hDesk,
                                              0,
                                              ExDesktopObjectType,
                                              KernelMode,
-                                             (PVOID*)&Win32Thread->Desktop,
+                                             (PVOID*)&DesktopObject,
                                              NULL);
           NtClose(hDesk);
-          if(!NT_SUCCESS(Status))
+          if(NT_SUCCESS(Status))
+          {
+            if (!IntSetThreadDesktop(DesktopObject))
+            {
+              DPRINT1("Unable to set thread desktop\n");
+            }
+          }
+          else
           {
             DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
-            Win32Thread->Desktop = NULL;
           }
         }
       }
@@ -234,11 +277,15 @@
       IntBlockInput(Win32Thread, FALSE);
       MsqDestroyMessageQueue(Win32Thread->MessageQueue);
       IntCleanupThreadCallbacks(Win32Thread);
-      if(Win32Thread->Desktop != NULL)
-      {
-        ObDereferenceObject(Win32Thread->Desktop);
-      }
-      
+
+      IntSetThreadDesktop(NULL);
+
+      if (Win32Thread->ThreadInfo != NULL)
+      {
+          UserHeapFree(Win32Thread->ThreadInfo);
+          Win32Thread->ThreadInfo = NULL;
+      }
+
       /* cleanup user object references stack */
       e = PopEntryList(&Win32Thread->ReferencesList);
       while (e)
@@ -309,6 +356,7 @@
   NTSTATUS Status;
   BOOLEAN Result;
   W32_CALLOUT_DATA CalloutData;
+  PVOID GlobalUserHeapBase = NULL;
 
   /*
    * Register user mode call interface
@@ -342,6 +390,16 @@
      */
     PsEstablishWin32Callouts(&CalloutData);
 
+    GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
+                                    &GlobalUserHeapBase,
+                                    1 * 1024 * 1024); /* FIXME - 1 MB for now... */
+    if (GlobalUserHeap == NULL)
+    {
+        DPRINT1("Failed to initialize the global heap!\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+
   Status = InitUserImpl();
   if (!NT_SUCCESS(Status))
   {

Modified: trunk/reactos/subsystems/win32/win32k/misc/err.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/misc/err.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/misc/err.c (original)
+++ trunk/reactos/subsystems/win32/win32k/misc/err.c Wed Apr  5 12:05:55 2006
@@ -61,4 +61,22 @@
   return 0;
 }
 
+VOID
+NTAPI
+W32kRaiseStatus(NTSTATUS Status)
+{
+    EXCEPTION_RECORD ExceptionRecord;
+
+    /* Create an exception record */
+    ExceptionRecord.ExceptionCode  = Status;
+    ExceptionRecord.ExceptionRecord = NULL;
+    ExceptionRecord.NumberParameters = 0;
+    ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+
+    RtlRaiseException(&ExceptionRecord);
+
+    /* If we returned, raise a status */
+    W32kRaiseStatus(Status);
+}
+
 /* EOF */

Added: trunk/reactos/subsystems/win32/win32k/misc/usrheap.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/misc/usrheap.c?rev=21460&view=auto
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/misc/usrheap.c (added)
+++ trunk/reactos/subsystems/win32/win32k/misc/usrheap.c Wed Apr  5 12:05:55 2006
@@ -1,0 +1,216 @@
+/*
+ *  ReactOS W32 Subsystem
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <w32k.h>
+
+#define NDEBUG
+#include <debug.h>
+
+
+static NTSTATUS NTAPI
+IntUserHeapCommitRoutine(IN PVOID Base,
+                         IN OUT PVOID *CommitAddress,
+                         IN OUT PSIZE_T CommitSize)
+{
+    PW32PROCESS W32Process;
+    PW32HEAP_USER_MAPPING Mapping;
+    PVOID UserBase = NULL;
+    NTSTATUS Status;
+    SIZE_T Delta = (SIZE_T)((ULONG_PTR)(*CommitAddress) - (ULONG_PTR)Base);
+
+    W32Process = PsGetWin32Process();
+
+    if (W32Process != NULL)
+    {
+        /* search for the mapping */
+        Mapping = &W32Process->HeapMappings;
+        while (Mapping != NULL)
+        {
+            if (Mapping->KernelMapping == Base)
+            {
+                UserBase = Mapping->UserMapping;
+                break;
+            }
+
+            Mapping = Mapping->Next;
+        }
+
+        ASSERT(UserBase != NULL);
+    }
+    else
+    {
+        ULONG ViewSize = 0;
+        LARGE_INTEGER Offset;
+        extern PSECTION_OBJECT GlobalUserHeapSection;
+
+        /* HACK: This needs to be handled during startup only... */
+        ASSERT(Base == (PVOID)GlobalUserHeap);
+
+        /* temporarily map it into user space */
+        Offset.QuadPart = 0;
+        Status = MmMapViewOfSection(GlobalUserHeapSection,
+                                    PsGetCurrentProcess(),
+                                    &UserBase,
+                                    0,
+                                    0,
+                                    &Offset,
+                                    &ViewSize,
+                                    ViewUnmap,
+                                    SEC_NO_CHANGE,
+                                    PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+
+        if (!NT_SUCCESS(Status))
+            return Status;
+    }
+
+    /* commit! */
+    UserBase = (PVOID)((ULONG_PTR)UserBase + Delta);
+
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     &UserBase,
+                                     0,
+                                     CommitSize,
+                                     MEM_COMMIT,
+                                     PAGE_EXECUTE_READ);
+    if (NT_SUCCESS(Status))
+    {
+        *CommitAddress = (PVOID)((ULONG_PTR)UserBase + Delta);
+    }
+
+    if (W32Process == NULL)
+    {
+        MmUnmapViewOfSection(PsGetCurrentProcess(),
+                             UserBase);
+    }
+
+    return Status;
+}
+
+static HANDLE
+IntUserHeapCreate(IN PSECTION_OBJECT SectionObject,
+                  IN PVOID *SystemMappedBase,
+                  IN ULONG HeapSize)
+{
+    PVOID MappedView = NULL;
+    LARGE_INTEGER Offset;
+    ULONG ViewSize = PAGE_SIZE;
+    RTL_HEAP_PARAMETERS Parameters = {0};
+    HANDLE hHeap;
+    NTSTATUS Status;
+
+    Offset.QuadPart = 0;
+
+    /* Commit the first page before creating the heap! */
+    Status = MmMapViewOfSection(SectionObject,
+                                PsGetCurrentProcess(),
+                                &MappedView,
+                                0,
+                                0,
+                                &Offset,
+                                &ViewSize,
+                                ViewUnmap,
+                                SEC_NO_CHANGE,
+                                PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+    if (!NT_SUCCESS(Status))
+        return NULL;
+
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     &MappedView,
+                                     0,
+                                     &ViewSize,
+                                     MEM_COMMIT,
+                                     PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+
+    MmUnmapViewOfSection(PsGetCurrentProcess(),
+                         MappedView);
+
+    if (!NT_SUCCESS(Status))
+        return NULL;
+
+    /* Create the heap, don't serialize in kmode! The caller is responsible
+       to synchronize the heap! */
+    Parameters.Length = sizeof(Parameters);
+    Parameters.InitialCommit = PAGE_SIZE;
+    Parameters.InitialReserve = (SIZE_T)HeapSize;
+    Parameters.CommitRoutine = IntUserHeapCommitRoutine;
+
+    hHeap = RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE,
+                          *SystemMappedBase,
+                          (SIZE_T)HeapSize,
+                          PAGE_SIZE,
+                          NULL,
+                          &Parameters);
+
+    return hHeap;
+}
+
+HANDLE
+UserCreateHeap(OUT PSECTION_OBJECT *SectionObject,
+               IN OUT PVOID *SystemBase,
+               IN ULONG HeapSize)
+{
+    LARGE_INTEGER SizeHeap;
+    HANDLE hHeap = NULL;
+    NTSTATUS Status;
+
+    SizeHeap.QuadPart = HeapSize;
+
+    /* create the section and map it into session space */
+    Status = MmCreateSection((PVOID*)SectionObject,
+                             SECTION_ALL_ACCESS,
+                             NULL,
+                             &SizeHeap,
+                             PAGE_EXECUTE_READWRITE, /* would prefer PAGE_READWRITE, but thanks to RTL heaps... */
+                             SEC_RESERVE,
+                             NULL,
+                             NULL);
+
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        return FALSE;
+    }
+
+    Status = MmMapViewInSystemSpace(*SectionObject,
+                                    SystemBase,
+                                    &HeapSize);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(*SectionObject);
+        *SectionObject = NULL;
+
+        SetLastNtError(Status);
+        return FALSE;
+    }
+
+    /* create the heap */
+    hHeap = IntUserHeapCreate(*SectionObject,
+                              SystemBase,
+                              HeapSize);
+
+    if (hHeap == NULL)
+    {
+        ObDereferenceObject(*SectionObject);
+        *SectionObject = NULL;
+
+        SetLastNtError(STATUS_UNSUCCESSFUL);
+    }
+
+    return hHeap;
+}

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/accelerator.c Wed Apr  5 12:05:55 2006
@@ -80,7 +80,7 @@
       return NULL;
    }
    
-   Accel= UserGetObject(&gHandleTable, hAccel,  otAccel);
+   Accel= UserGetObject(gHandleTable, hAccel,  otAccel);
    if (!Accel)
    {
       SetLastWin32Error(ERROR_INVALID_ACCEL_HANDLE);
@@ -344,7 +344,7 @@
           Entries, EntriesCount);
    UserEnterExclusive();
 
-   Accel = ObmCreateObject(&gHandleTable, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE));
+   Accel = ObmCreateObject(gHandleTable, (PHANDLE)&hAccel, otAccel, sizeof(ACCELERATOR_TABLE));
 
    if (Accel == NULL)
    {

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/class.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Wed Apr  5 12:05:55 2006
@@ -1,6 +1,6 @@
 /*
  *  ReactOS W32 Subsystem
- *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *  Copyright (C) 1998 - 2006 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -22,9 +22,12 @@
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window classes
  * FILE:             subsys/win32k/ntuser/class.c
- * PROGRAMER:        Casper S. Hornstrup (chorns at users.sourceforge.net)
+ * PROGRAMER:        Thomas Weidenmueller <w3seek at reactos.com>
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
+ *
+ * NOTE: Should classes created on a desktop heap be moved to the shared
+ *       heap when the desktop is destroyed, or should they be unregistered?
  */
 /* INCLUDES ******************************************************************/
 
@@ -33,7 +36,96 @@
 #define NDEBUG
 #include <debug.h>
 
-/* FUNCTIONS *****************************************************************/
+/* CALLPROC ******************************************************************/
+
+VOID
+DestroyCallProc(IN PDESKTOP Desktop,
+                IN OUT PCALLPROC CallProc)
+{
+    /* FIXME - use new object manager! */
+    HANDLE Handle = ObmObjectToHandle(CallProc);
+
+    ObmDeleteObject(Handle,
+                    otCallProc);
+}
+
+PCALLPROC
+CloneCallProc(IN PDESKTOP Desktop,
+              IN PCALLPROC CallProc)
+{
+    PCALLPROC NewCallProc;
+    HANDLE Handle;
+
+    /* FIXME - use new object manager! */
+    NewCallProc = (PCALLPROC)ObmCreateObject(gHandleTable,
+                                             &Handle,
+                                             otCallProc,
+                                             sizeof(CALLPROC));
+    if (NewCallProc != NULL)
+    {
+        NewCallProc->pi = CallProc->pi;
+        NewCallProc->WndProc = CallProc->WndProc;
+        NewCallProc->Unicode = CallProc->Unicode;
+    }
+
+    return NewCallProc;
+}
+
+PCALLPROC
+CreateCallProc(IN PDESKTOP Desktop,
+               IN WNDPROC WndProc,
+               IN BOOL Unicode,
+               IN PW32PROCESSINFO pi)
+{
+    PCALLPROC NewCallProc;
+    HANDLE Handle;
+
+    /* FIXME - use new object manager! */
+    NewCallProc = (PCALLPROC)ObmCreateObject(gHandleTable,
+                                             &Handle,
+                                             otCallProc,
+                                             sizeof(CALLPROC));
+    if (NewCallProc != NULL)
+    {
+        NewCallProc->pi = pi;
+        NewCallProc->WndProc = WndProc;
+        NewCallProc->Unicode = Unicode;
+    }
+
+    return NewCallProc;
+}
+
+BOOL
+UserGetCallProcInfo(IN HANDLE hCallProc,
+                    OUT PWNDPROC_INFO wpInfo)
+{
+    PCALLPROC CallProc;
+
+    /* NOTE: Accessing the WNDPROC_INFO structure may raise an exception! */
+
+    /* FIXME - use new object manager! */
+    CallProc = UserGetObject(gHandleTable,
+                             hCallProc,
+                             otCallProc);
+    if (CallProc == NULL)
+    {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (CallProc->pi != GetW32ProcessInfo())
+    {
+        SetLastWin32Error(ERROR_ACCESS_DENIED);
+        return FALSE;
+    }
+
+    wpInfo->WindowProc = CallProc->WndProc;
+    wpInfo->IsUnicode = CallProc->Unicode;
+
+    return TRUE;
+}
+
+/* WINDOWCLASS ***************************************************************/
 
 NTSTATUS FASTCALL
 InitClassImpl(VOID)
@@ -47,398 +139,1673 @@
    return(STATUS_SUCCESS);
 }
 
-
-__inline VOID FASTCALL 
-ClassDerefObject(PWNDCLASS_OBJECT Class)
-{
-   ASSERT(Class->refs >= 1);
-   Class->refs--;   
-}
-
-
-__inline VOID FASTCALL 
-ClassRefObject(PWNDCLASS_OBJECT Class)
-{
-   ASSERT(Class->refs >= 0);
-   Class->refs++;
-}
-
-
-VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
-{
-#if defined(DBG) || defined(KDBG)
-   if ( Class->refs != 0 )
-   {
-      WCHAR AtomName[256];
-      ULONG AtomNameLen = sizeof(AtomName);
-      RtlQueryAtomInAtomTable ( gAtomTable, Class->Atom,
-         NULL, NULL, AtomName, &AtomNameLen );
-      DPRINT1("DestroyClass(): can't delete class = '%ws', b/c refs = %lu\n", AtomName, Class->refs );
-   }
-#endif
-   ASSERT(Class->refs == 0);
-   
-   RemoveEntryList(&Class->ListEntry);
-   if (Class->hMenu)
-      UserDestroyMenu(Class->hMenu);
-   RtlDeleteAtomFromAtomTable(gAtomTable, Class->Atom);
-   ExFreePool(Class);
+static VOID
+IntFreeClassMenuName(IN OUT PWINDOWCLASS Class)
+{
+    /* free the menu name, if it was changed and allocated */
+    if (Class->MenuName != NULL && !IS_INTRESOURCE(Class->MenuName) &&
+        Class->MenuName != (PWSTR)(Class + 1))
+    {
+        UserHeapFree(Class->MenuName);
+        Class->MenuName = NULL;
+        Class->AnsiMenuName = NULL;
+    }
+}
+
+static VOID
+IntDestroyClass(IN OUT PWINDOWCLASS Class)
+{
+    /* there shouldn't be any clones anymore */
+
+    ASSERT(Class->Windows == 0);
+
+    if (Class->Desktop != NULL)
+    {
+        ASSERT(Class->Clone == NULL);
+    }
+    else if (Class->Clone != NULL)
+    {
+        /* there must not be more than one clone! This can be the case
+           when the base class is on the shared heap */
+        ASSERT(Class->Clone->Next == NULL);
+
+        /* free the clone */
+        IntDestroyClass(Class->Clone);
+        Class->Clone = NULL;
+    }
+
+    if (Class->Base == Class)
+    {
+        /* destruct resources shared with clones */
+        if (!Class->System && Class->CallProc != NULL)
+        {
+            DestroyCallProc(Class->Desktop,
+                            Class->CallProc);
+        }
+
+        IntFreeClassMenuName(Class);
+    }
+
+    /* free the structure */
+    if (Class->Desktop != NULL)
+    {
+        DesktopHeapFree(Class->Desktop,
+                        Class);
+    }
+    else
+    {
+        UserHeapFree(Class);
+    }
 }
 
 
 /* clean all process classes. all process windows must cleaned first!! */
 void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
 {
-   PWNDCLASS_OBJECT Class;
-
-   while (!IsListEmpty(&Process->ClassList))
-   {
-      Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
-      DestroyClass(Class);
-   }
-}
-
-
-
-
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
-{
-   PWNDCLASS_OBJECT Class;
-   PW32PROCESS Process = PsGetWin32Process();
-
-   LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
-   {
-      if (Class->Atom != Atom) continue;
-
-      if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
-   }
-   
-   return NULL;
-}
-
-
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
-{
-   NTSTATUS Status;
-   RTL_ATOM Atom;
-
-   if (!ClassName || !PsGetWin32Thread()->Desktop)
-      return FALSE;
-
-   Status = RtlLookupAtomInAtomTable(
-               gAtomTable,
-               (LPWSTR)ClassName,
-               &Atom);
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT1("Failed to lookup class atom (ClassName '%S')!\n", ClassName);
-      return FALSE;
-   }
-
-   return ClassGetClassByAtom(Atom, hInstance);
-}
-
-
-PWNDCLASS_OBJECT FASTCALL
-ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
-{
-   if (!ClassNameOrAtom) return NULL;
-   
-   if (IS_ATOM(ClassNameOrAtom))
-      return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
-   else
-      return ClassGetClassByName(ClassNameOrAtom, hInstance);
-}
-
-
-static
-BOOL FASTCALL
-IntRegisterClass(
-   CONST WNDCLASSEXW *lpwcx,
-   DWORD Flags,
-   WNDPROC wpExtra,
-   PUNICODE_STRING MenuName,
-   RTL_ATOM Atom,
-   HMENU hMenu)
-{
-   PWNDCLASS_OBJECT Class;
-   ULONG  objectSize;
-   BOOL Global;
-
-   ASSERT(lpwcx);
-   ASSERT(Atom);
-   ASSERT(lpwcx->hInstance);
-
-   Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS);
-
-   /* Check for double registration of the class. */
-   Class = ClassGetClassByAtom(Atom, lpwcx->hInstance);
-   if (Class && Global == Class->Global)
-   {
-      /* can max have one class of each type (global/local) */
-      SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
-      return(FALSE);
-   }
-
-   objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
-   
-   //FIXME: allocate in session heap (or possibly desktop heap)
-   Class = ExAllocatePool(PagedPool, objectSize);
-   if (!Class)
-   {
-      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-      return(FALSE);
-   }
-   RtlZeroMemory(Class, objectSize);
-
-   Class->cbSize = lpwcx->cbSize;
-   Class->style = lpwcx->style;
-   Class->cbClsExtra = lpwcx->cbClsExtra;
-   Class->cbWndExtra = lpwcx->cbWndExtra;
-   Class->hInstance = lpwcx->hInstance;
-   Class->hIcon = lpwcx->hIcon;
-   Class->hCursor = lpwcx->hCursor;
-   Class->hMenu = hMenu;
-   Class->hbrBackground = lpwcx->hbrBackground;
-   Class->Unicode = !(Flags & REGISTERCLASS_ANSI);
-   Class->Global = Global;
-   Class->hIconSm = lpwcx->hIconSm;
-   Class->Atom = Atom;
-   
-   if (MenuName->Length == 0)
-   {
-      Class->lpszMenuName.Length =
-         Class->lpszMenuName.MaximumLength = 0;
-      Class->lpszMenuName.Buffer = MenuName->Buffer;
-   }
-   else
-   {
-      Class->lpszMenuName.Length =
-         Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
-      Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
-      
-      if (Class->lpszMenuName.Buffer == NULL) 
-      {
-         SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-         return(FALSE);
-      }
-      
-      RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
-   }
-   
-   if (wpExtra == NULL)
-   {
-      if (Flags & REGISTERCLASS_ANSI)
-      {
-         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
-         Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
-      }
-      else
-      {
-         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
-         Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
-      }
-   }
-   else
-   {
-      if (Flags & REGISTERCLASS_ANSI)
-      {
-         Class->lpfnWndProcA = lpwcx->lpfnWndProc;
-         Class->lpfnWndProcW = wpExtra;
-      }
-      else
-      {
-         Class->lpfnWndProcW = lpwcx->lpfnWndProc;
-         Class->lpfnWndProcA = wpExtra;
-      }
-   }
-   
-  
-   
-   /* Extra class data */
-   if (Class->cbClsExtra)
-      Class->ExtraData = (PCHAR)(Class + 1);
-
-   if (Global)
-   {
-      /* global classes go last (incl. system classes) */
-      InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
-   }
-   else
-   {
-      /* local classes have priority so we put them first */
-      InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
-   }
-   
-   return TRUE;
-}
-
-
-ULONG FASTCALL
-IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
-{
-   LONG Ret;
-
-   if ((int)Offset >= 0)
-   {
-      DPRINT("GetClassLong(%x, %d)\n", Window->hSelf, Offset);
-      if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
-      {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return 0;
-      }
-      Ret = *((LONG *)(Window->Class->ExtraData + Offset));
-      DPRINT("Result: %x\n", Ret);
-      return Ret;
-   }
-
-   switch (Offset)
-   {
-      case GCL_CBWNDEXTRA:
-         Ret = Window->Class->cbWndExtra;
-         break;
-      case GCL_CBCLSEXTRA:
-         Ret = Window->Class->cbClsExtra;
-         break;
-      case GCL_HBRBACKGROUND:
-         Ret = (ULONG)Window->Class->hbrBackground;
-         break;
-      case GCL_HCURSOR:
-         Ret = (ULONG)Window->Class->hCursor;
-         break;
-      case GCL_HICON:
-         Ret = (ULONG)Window->Class->hIcon;
-         break;
-      case GCL_HICONSM:
-         Ret = (ULONG)Window->Class->hIconSm;
-         break;
-      case GCL_HMODULE:
-         Ret = (ULONG)Window->Class->hInstance;
-         break;
-      case GCL_MENUNAME:
-         Ret = (ULONG)Window->Class->lpszMenuName.Buffer;
-         break;
-      case GCL_STYLE:
-         Ret = Window->Class->style;
-         break;
-      case GCL_WNDPROC:
-         if (Ansi)
-         {
-            Ret = (ULONG)Window->Class->lpfnWndProcA;
-         }
-         else
-         {
-            Ret = (ULONG)Window->Class->lpfnWndProcW;
-         }
-         break;
-      case GCW_ATOM:
-         Ret = Window->Class->Atom;
-         break;
-      default:
-         Ret = 0;
-         break;
-   }
-   return(Ret);
-}
-
-static
-void FASTCALL
-co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
-{
-   ASSERT_REFS_CO(Window);
-
-   if ((int)Offset >= 0)
-   {
-      DPRINT("SetClassLong(%x, %d, %x)\n", Window->hSelf, Offset, dwNewLong);
-      if ((Offset + sizeof(LONG)) > Window->Class->cbClsExtra)
-      {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return;
-      }
-      *((LONG *)(Window->Class->ExtraData + Offset)) = dwNewLong;
-      return;
-   }
-
-   switch (Offset)
-   {
-      case GCL_CBWNDEXTRA:
-         Window->Class->cbWndExtra = dwNewLong;
-         break;
-      case GCL_CBCLSEXTRA:
-         Window->Class->cbClsExtra = dwNewLong;
-         break;
-      case GCL_HBRBACKGROUND:
-         Window->Class->hbrBackground = (HBRUSH)dwNewLong;
-         break;
-      case GCL_HCURSOR:
-         Window->Class->hCursor = (HCURSOR)dwNewLong;
-         break;
-      case GCL_HICON:
-         Window->Class->hIcon = (HICON)dwNewLong;
-
-         if (!IntGetOwner(Window) && !IntGetParent(Window))
-         {
-            co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) Window->hSelf);
-         }
-         break;
-      case GCL_HICONSM:
-         Window->Class->hIconSm = (HICON)dwNewLong;
-         break;
-      case GCL_HMODULE:
-         Window->Class->hInstance = (HINSTANCE)dwNewLong;
-         break;
-      case GCL_MENUNAME:
-         if (Window->Class->lpszMenuName.MaximumLength)
-            RtlFreeUnicodeString(&Window->Class->lpszMenuName);
-         if (!IS_INTRESOURCE(dwNewLong))
-         {
-            Window->Class->lpszMenuName.Length =
-               Window->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
-            Window->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Window->Class->lpszMenuName.MaximumLength, TAG_STRING);
-            RtlCopyUnicodeString(&Window->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
-         }
-         else
-         {
-            Window->Class->lpszMenuName.Length =
-               Window->Class->lpszMenuName.MaximumLength = 0;
-            Window->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
-         }
-         break;
-      case GCL_STYLE:
-         Window->Class->style = dwNewLong;
-         break;
-      case GCL_WNDPROC:
-         if (Ansi)
-         {
-            Window->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
-            Window->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
-            Window->Class->Unicode = FALSE;
-         }
-         else
-         {
-            Window->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
-            Window->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
-            Window->Class->Unicode = TRUE;
-         }
-         break;
-   }
-}
+    PWINDOWCLASS Class;
+    PW32PROCESSINFO pi = Process->ProcessInfo;
+
+    if (pi != NULL)
+    {
+        /* free all local classes */
+        Class = pi->LocalClassList;
+        while (Class != NULL)
+        {
+            pi->LocalClassList = Class->Next;
+
+            ASSERT(Class->Base == Class);
+            IntDestroyClass(Class);
+
+            Class = pi->LocalClassList;
+        }
+
+        /* free all global classes */
+        Class = pi->GlobalClassList;
+        while (Class != NULL)
+        {
+            pi->GlobalClassList = Class->Next;
+
+            ASSERT(Class->Base == Class);
+            IntDestroyClass(Class);
+
+            Class = pi->GlobalClassList;
+        }
+
+        /* free all system classes */
+        Class = pi->SystemClassList;
+        while (Class != NULL)
+        {
+            pi->SystemClassList = Class->Next;
+
+            ASSERT(Class->Base == Class);
+            IntDestroyClass(Class);
+
+            Class = pi->SystemClassList;
+        }
+    }
+}
+
+static BOOL
+IntRegisterClassAtom(IN PUNICODE_STRING ClassName,
+                     OUT RTL_ATOM *pAtom)
+{
+    WCHAR szBuf[65];
+    PWSTR AtomName;
+    NTSTATUS Status;
+
+    if (ClassName->Length != 0)
+    {
+        /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */
+        if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0]))
+        {
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            return (RTL_ATOM)0;
+        }
+
+        RtlCopyMemory(szBuf,
+                      ClassName->Buffer,
+                      ClassName->Length);
+        szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
+        AtomName = szBuf;
+    }
+    else
+        AtomName = ClassName->Buffer;
+
+    Status = RtlAddAtomToAtomTable(gAtomTable,
+                                   AtomName,
+                                   pAtom);
+
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static VOID
+IntDeregisterClassAtom(IN RTL_ATOM Atom)
+{
+    RtlDeleteAtomFromAtomTable(gAtomTable,
+                               Atom);
+}
+
+static BOOL
+IntSetClassAtom(IN OUT PWINDOWCLASS Class,
+                IN PUNICODE_STRING ClassName)
+{
+    RTL_ATOM Atom = (RTL_ATOM)0;
+
+    /* update the base class first */
+    Class = Class->Base;
+
+    if (!IntRegisterClassAtom(ClassName,
+                              &Atom))
+    {
+        return FALSE;
+    }
+
+    IntDeregisterClassAtom(Class->Atom);
+
+    Class->Atom = Atom;
+
+    /* update the clones */
+    Class = Class->Clone;
+    while (Class != NULL)
+    {
+        Class->Atom = Atom;
+
+        Class = Class->Next;
+    }
+
+    return TRUE;
+}
+
+static WNDPROC
+IntSetClassWndProc(IN OUT PWINDOWCLASS Class,
+                   IN WNDPROC WndProc,
+                   IN BOOL Ansi)
+{
+    WNDPROC Ret = Class->WndProc;
+
+    if (Class->System)
+    {
+        DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->Atom);
+        SetLastWin32Error(ERROR_ACCESS_DENIED);
+        return NULL;
+    }
+
+    /* update the base class first */
+    Class = Class->Base;
+
+    Class->Unicode = !Ansi;
+    Class->WndProc = WndProc;
+    if (Class->CallProc != NULL)
+    {
+        Class->CallProc->WndProc = WndProc;
+        Class->CallProc->Unicode = !Ansi;
+    }
+
+    /* update the clones */
+    Class = Class->Clone;
+    while (Class != NULL)
+    {
+        Class->Unicode = !Ansi;
+        Class->WndProc = WndProc;
+
+        Class = Class->Next;
+    }
+
+    return Ret;
+}
+
+static PWINDOWCLASS
+IntGetClassForDesktop(IN PWINDOWCLASS BaseClass,
+                      IN PDESKTOP Desktop)
+{
+    SIZE_T ClassSize;
+    PWINDOWCLASS Class;
+
+    ASSERT(Desktop != NULL);
+    ASSERT(BaseClass->Base == BaseClass);
+
+    if (BaseClass->Desktop == Desktop)
+    {
+        /* it is most likely that a window is created on the same
+           desktop as the window class. */
+
+        return BaseClass;
+    }
+
+    if (BaseClass->Desktop == NULL)
+    {
+        /* Classes are also located in the shared heap when the class
+           was created before the thread attached to a desktop. As soon
+           as a window is created for such a class located on the shared
+           heap, the class is cloned into the desktop heap on which the
+           window is created. */
+        Class = NULL;
+    }
+    else
+    {
+        /* The user is asking for a class object on a different desktop,
+           try to find one! */
+        Class = BaseClass->Clone;
+        while (Class != NULL)
+        {
+            if (Class->Desktop == Desktop)
+            {
+                ASSERT(Class->Base == BaseClass);
+                ASSERT(Class->Clone == NULL);
+                break;
+            }
+
+            Class = Class->Next;
+        }
+    }
+
+    if (Class == NULL)
+    {
+        /* The window is created on a different desktop, we need to
+           clone the class object to the desktop heap of the window! */
+        ClassSize = (SIZE_T)BaseClass->ClassExtraDataOffset +
+                    (SIZE_T)BaseClass->ClsExtra;
+
+        Class = DesktopHeapAlloc(Desktop,
+                                 ClassSize);
+        if (Class != NULL)
+        {
+            /* simply clone the class */
+            RtlCopyMemory(Class,
+                          BaseClass,
+                          ClassSize);
+
+            /* update some pointers and link the class */
+            Class->Next = BaseClass->Clone;
+            Class->Clone = NULL;
+            Class->Base = BaseClass;
+            Class->Desktop = Desktop;
+            Class->Windows = 0;
+            (void)InterlockedExchangePointer(&BaseClass->Clone,
+                                             Class);
+        }
+        else
+        {
+            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        }
+    }
+
+    return Class;
+}
+
+PWINDOWCLASS
+IntReferenceClass(IN PWINDOWCLASS BaseClass,
+                  IN PDESKTOP Desktop)
+{
+    PWINDOWCLASS Class;
+
+    Class = IntGetClassForDesktop(BaseClass,
+                                  Desktop);
+    if (Class != NULL)
+    {
+        Class->Windows++;
+    }
+
+    return Class;
+}
+
+VOID
+IntDereferenceClass(IN OUT PWINDOWCLASS Class,
+                    IN PDESKTOP Desktop,
+                    IN PW32PROCESSINFO pi)
+{
+    PWINDOWCLASS *PrevLink, BaseClass, CurrentClass;
+
+    BaseClass = Class->Base;
+
+    if (--Class->Windows == 0)
+    {
+        if (BaseClass == Class)
+        {
+            ASSERT(Class->Base == Class);
+
+            /* check if there are clones of the class on other desktops,
+               link the first clone in if possible. If there are no clones
+               then leave the class on the desktop heap... */
+            if (BaseClass->Clone != NULL)
+            {
+                PWINDOWCLASS NewBase = BaseClass->Clone;
+
+                /* locate the base class and unlink it */
+                if (BaseClass->System)
+                    PrevLink = &pi->SystemClassList;
+                else if (BaseClass->Global)
+                    PrevLink = &pi->GlobalClassList;
+                else
+                    PrevLink = &pi->LocalClassList;
+
+                CurrentClass = *PrevLink;
+                while (CurrentClass != BaseClass)
+                {
+                    ASSERT(CurrentClass != NULL);
+
+                    PrevLink = &CurrentClass->Next;
+                    CurrentClass = CurrentClass->Next;
+                }
+
+                ASSERT(CurrentClass == BaseClass);
+
+                NewBase->Clone = NewBase->Next;
+                NewBase->Next = BaseClass->Next;
+                NewBase->Base = NewBase;
+
+                /* update all clones */
+                CurrentClass = NewBase->Clone;
+                while (CurrentClass != NULL)
+                {
+                    ASSERT(CurrentClass->Clone == NULL);
+
+                    CurrentClass->Base = NewBase;
+
+                    CurrentClass = CurrentClass->Next;
+                }
+
+                /* link in the new base class */
+                (void)InterlockedExchangePointer(PrevLink,
+                                                 NewBase);
+
+                /* destroy the class, there's still another clone of the class
+                   that now serves as a base class. Make sure we don't destruct
+                   resources shared by all classes (Base = NULL)! */
+                BaseClass->Base = NULL;
+                BaseClass->Clone = NULL;
+                IntDestroyClass(BaseClass);
+            }
+        }
+        else
+        {
+            /* locate the cloned class and unlink it */
+            PrevLink = &BaseClass->Clone;
+            CurrentClass = BaseClass->Clone;
+            while (CurrentClass != Class)
+            {
+                ASSERT(CurrentClass != NULL);
+
+                PrevLink = &CurrentClass->Next;
+                CurrentClass = CurrentClass->Next;
+            }
+
+            ASSERT(CurrentClass == Class);
+
+            (void)InterlockedExchangePointer(PrevLink,
+                                             Class->Next);
+
+            ASSERT(Class->Base == BaseClass);
+            ASSERT(Class->Clone == NULL);
+
+            /* the class was just a clone, we don't need it anymore */
+            IntDestroyClass(Class);
+        }
+    }
+}
+
+static PWINDOWCLASS
+IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
+               IN PUNICODE_STRING ClassName,
+               IN PUNICODE_STRING MenuName,
+               IN WNDPROC wpExtra,
+               IN DWORD dwFlags,
+               IN PDESKTOP Desktop,
+               IN PW32PROCESSINFO pi)
+{
+    SIZE_T ClassSize;
+    PWINDOWCLASS Class = NULL;
+    RTL_ATOM Atom;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (!IntRegisterClassAtom(ClassName,
+                              &Atom))
+    {
+        DPRINT1("Failed to register class atom!\n");
+        return NULL;
+    }
+
+    ClassSize = sizeof(WINDOWCLASS) + lpwcx->cbClsExtra;
+    ClassSize += ClassName->Length + sizeof(UNICODE_NULL);
+    ClassSize += MenuName->Length + sizeof(UNICODE_NULL);
+    if (ClassName->Length != 0)
+        ClassSize += RtlUnicodeStringToAnsiSize(ClassName);
+    if (MenuName->Length != 0)
+        ClassSize += RtlUnicodeStringToAnsiSize(MenuName);
+
+    if (Desktop != NULL)
+    {
+        Class = DesktopHeapAlloc(Desktop,
+                                 ClassSize);
+    }
+    else
+    {
+        /* FIXME - the class was created before being connected
+                   to a desktop. It is possible for the desktop window,
+                   but should it be allowed for any other case? */
+        Class = UserHeapAlloc(ClassSize);
+    }
+
+    if (Class != NULL)
+    {
+        RtlZeroMemory(Class,
+                      sizeof(ClassSize));
+
+        Class->Desktop = Desktop;
+        Class->Base = Class;
+        Class->Atom = Atom;
+
+        if (dwFlags & REGISTERCLASS_SYSTEM)
+        {
+            dwFlags &= ~REGISTERCLASS_ANSI;
+            Class->WndProcExtra = wpExtra;
+            Class->System = TRUE;
+        }
+
+        _SEH_TRY
+        {
+            PWSTR strBuf;
+            PSTR strBufA;
+            ANSI_STRING AnsiString;
+
+            /* need to protect with SEH since accessing the WNDCLASSEX structure
+               and string buffers might raise an exception! We don't want to
+               leak memory... */
+            Class->WndProc = lpwcx->lpfnWndProc;
+            Class->Style = lpwcx->style;
+            Class->ClsExtra = lpwcx->cbClsExtra;
+            Class->WndExtra = lpwcx->cbWndExtra;
+            Class->hInstance = lpwcx->hInstance;
+            Class->hIcon = lpwcx->hIcon; /* FIXME */
+            Class->hIconSm = lpwcx->hIconSm; /* FIXME */
+            Class->hCursor = lpwcx->hCursor; /* FIXME */
+            Class->hbrBackground = lpwcx->hbrBackground;
+
+            /* make a copy of the string */
+            strBuf = (PWSTR)(Class + 1);
+            if (MenuName->Length != 0)
+            {
+                Class->MenuName = strBuf;
+                RtlCopyMemory(Class->MenuName,
+                              MenuName->Buffer,
+                              MenuName->Length);
+
+                strBuf += (MenuName->Length / sizeof(WCHAR)) + 1;
+            }
+            else
+                Class->MenuName = MenuName->Buffer;
+
+            /* save an ansi copy of the string */
+            strBufA = (PSTR)strBuf;
+            if (MenuName->Length != 0)
+            {
+                Class->AnsiMenuName = strBufA;
+                AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName);
+                AnsiString.Buffer = strBufA;
+                Status = RtlUnicodeStringToAnsiString(&AnsiString,
+                                                      MenuName,
+                                                      FALSE);
+                if (!NT_SUCCESS(Status))
+                {
+                    DPRINT1("Failed to convert unicode menu name to ansi!\n");
+
+                    /* life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
+                    _SEH_LEAVE;
+                }
+
+                strBufA += AnsiString.Length + 1;
+            }
+            else
+                Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+
+            /* calculate the offset of the extra data */
+            Class->ClassExtraDataOffset = (ULONG_PTR)strBufA - (ULONG_PTR)Class;
+
+            if (!(dwFlags & REGISTERCLASS_ANSI))
+                Class->Unicode = TRUE;
+
+            if (Class->Style & CS_GLOBALCLASS)
+                Class->Global = TRUE;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed creating the class: 0x%x\n", Status);
+
+            SetLastNtError(Status);
+
+            DesktopHeapFree(Desktop,
+                            Class);
+            Class = NULL;
+
+            IntDeregisterClassAtom(Atom);
+        }
+    }
+    else
+    {
+        DPRINT1("Failed to allocate class on Desktop 0x%p\n", Desktop);
+
+        IntDeregisterClassAtom(Atom);
+
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    return Class;
+}
+
+static PWINDOWCLASS
+IntFindClass(IN RTL_ATOM Atom,
+             IN HINSTANCE hInstance,
+             IN PWINDOWCLASS *ClassList,
+             OUT PWINDOWCLASS **Link  OPTIONAL)
+{
+    PWINDOWCLASS Class, *PrevLink = ClassList;
+
+    Class = *PrevLink;
+    while (Class != NULL)
+    {
+        if (Class->Atom == Atom &&
+            (hInstance == NULL || Class->hInstance == hInstance) &&
+            !Class->Destroying)
+        {
+            ASSERT(Class->Base == Class);
+
+            if (Link != NULL)
+                *Link = PrevLink;
+            break;
+        }
+
+        PrevLink = &Class->Next;
+        Class = Class->Next;
+    }
+
+    return Class;
+}
+
+static WNDPROC
+IntGetClassWndProc(IN PWINDOWCLASS Class,
+                   IN PW32PROCESSINFO pi,
+                   IN BOOL Ansi)
+{
+    if (Class->System)
+    {
+        return (Ansi ? Class->WndProcExtra : Class->WndProc);
+    }
+    else
+    {
+        if (!Ansi == Class->Unicode)
+        {
+            return Class->WndProc;
+        }
+        else
+        {
+            if (Class->CallProc != NULL)
+            {
+                return (WNDPROC)ObmObjectToHandle(Class->CallProc);
+            }
+            else
+            {
+                PCALLPROC NewCallProc, CallProc;
+
+                if (pi == NULL)
+                    return NULL;
+
+                /* NOTE: use the interlocked functions, as this operation may be done even
+                         when only the shared lock is held! */
+                NewCallProc = CreateCallProc(Class->Desktop,
+                                             Class->WndProc,
+                                             Class->Unicode,
+                                             pi);
+                if (NewCallProc == NULL)
+                {
+                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                    return NULL;
+                }
+
+                CallProc = InterlockedCompareExchangePointer(&Class->CallProc,
+                                                             NewCallProc,
+                                                             NULL);
+                if (CallProc != NULL)
+                {
+                    DestroyCallProc(Class->Desktop,
+                                    NewCallProc);
+                }
+
+                return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc));
+            }
+        }
+    }
+}
+
+RTL_ATOM
+IntGetClassAtom(IN PUNICODE_STRING ClassName,
+                IN HINSTANCE hInstance  OPTIONAL,
+                IN PW32PROCESSINFO pi  OPTIONAL,
+                OUT PWINDOWCLASS *BaseClass  OPTIONAL,
+                OUT PWINDOWCLASS **Link  OPTIONAL)
+{
+    RTL_ATOM Atom = (RTL_ATOM)0;
+
+    if (ClassName->Length != 0)
+    {
+        WCHAR szBuf[65];
+        PWSTR AtomName;
+        NTSTATUS Status;
+
+        /* NOTE: Caller has to protect the call with SEH! */
+
+        if (ClassName->Length != 0)
+        {
+            /* FIXME - Don't limit to 64 characters! use SEH when allocating memory! */
+            if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / sizeof(szBuf[0]))
+            {
+                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                return (RTL_ATOM)0;
+            }
+
+            /* We need to make a local copy of the class name! The caller could
+               modify the buffer and we could overflow in RtlLookupAtomInAtomTable.
+               We're protected by SEH, but the ranges that might be accessed were
+               not probed... */
+            RtlCopyMemory(szBuf,
+                          ClassName->Buffer,
+                          ClassName->Length);
+            szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
+            AtomName = szBuf;
+        }
+        else
+            AtomName = ClassName->Buffer;
+
+        /* lookup the atom */
+        Status = RtlLookupAtomInAtomTable(gAtomTable,
+                                          AtomName,
+                                          &Atom);
+        if (!NT_SUCCESS(Status))
+        {
+            if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+            {
+                SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
+            }
+            else
+            {
+                SetLastNtError(Status);
+            }
+        }
+    }
+    else
+    {
+        ASSERT(IS_ATOM(ClassName->Buffer));
+        Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
+    }
+
+    if (BaseClass != NULL && Atom != (RTL_ATOM)0)
+    {
+        PWINDOWCLASS Class;
+
+        /* attempt to locate the class object */
+
+        ASSERT(pi != NULL);
+
+        /* Step 1: try to find an exact match of locally registered classes */
+        Class = IntFindClass(Atom,
+                             hInstance,
+                             &pi->LocalClassList,
+                             Link);
+        if (Class != NULL)
+        {
+            goto FoundClass;
+        }
+
+        /* Step 2: try to find any globally registered class. The hInstance
+                   is not relevant for global classes */
+        Class = IntFindClass(Atom,
+                             NULL,
+                             &pi->GlobalClassList,
+                             Link);
+        if (Class != NULL)
+        {
+            goto FoundClass;
+        }
+
+        /* Step 3: try to find a system class */
+        Class = IntFindClass(Atom,
+                             NULL,
+                             &pi->SystemClassList,
+                             Link);
+
+        if (Class == NULL)
+        {
+            SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+            return (RTL_ATOM)0;
+        }
+
+FoundClass:
+        *BaseClass = Class;
+    }
+
+    return Atom;
+}
+
+static PWINDOWCLASS
+IntClassResizeInternal(IN OUT PWINDOWCLASS Class,
+                       IN INT ClsExtraNew,
+                       IN PWINDOWCLASS *List)
+{
+    PWINDOWCLASS *PrevLink, CurrentClass, NewClass;
+    SIZE_T NewSize;
+
+    /* temporarily unlink the class, as resizing it may change it's location */
+    PrevLink = List;
+    CurrentClass = *PrevLink;
+    while (CurrentClass != Class)
+    {
+        ASSERT(CurrentClass != NULL);
+
+        PrevLink = &CurrentClass->Next;
+        CurrentClass = CurrentClass->Next;
+    }
+
+    ASSERT(CurrentClass == Class);
+
+    (void)InterlockedExchangePointer(PrevLink,
+                                     Class->Next);
+
+    NewSize = (SIZE_T)ClsExtraNew + Class->ClassExtraDataOffset;
+    if (Class->Desktop != NULL)
+    {
+        NewClass = DesktopHeapReAlloc(Class->Desktop,
+                                      Class,
+                                      NewSize);
+    }
+    else
+    {
+        NewClass = UserHeapReAlloc(Class,
+                                   NewSize);
+    }
+
+    if (NewClass == NULL)
+    {
+        /* link in the class again */
+        (void)InterlockedExchangePointer(PrevLink,
+                                         Class);
+
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    if (Class != NewClass)
+    {
+        /* adjust the menu name pointers, if neccessary */
+        if (NewClass->MenuName != NULL && !IS_INTRESOURCE(NewClass->MenuName) &&
+            NewClass->MenuName == (PWSTR)(NewClass + 1))
+        {
+            ULONG_PTR PtrDelta = (ULONG_PTR)NewClass - (ULONG_PTR)Class;
+
+            NewClass->MenuName = (PWSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta);
+            NewClass->AnsiMenuName = (PSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta);
+        }
+
+        Class = NewClass;
+    }
+
+    if (Class->ClsExtra < ClsExtraNew)
+    {
+        /* zero the memory allocated */
+        RtlZeroMemory((PVOID)((ULONG_PTR)Class + Class->ClassExtraDataOffset + Class->ClsExtra),
+                      ClsExtraNew - Class->ClsExtra);
+    }
+
+    /* link in the class again */
+    (void)InterlockedExchangePointer(PrevLink,
+                                     Class);
+
+    return Class;
+}
+
+static BOOL
+IntClassResize(IN OUT PWINDOWCLASS Class,
+               IN PW32PROCESSINFO pi,
+               IN INT ClsExtraNew)
+{
+    PWINDOWCLASS *List, *CloneList, NewClass, Clone, FailedResize = NULL;
+    BOOL FailOnResize;
+
+    if (pi == NULL)
+        return FALSE;
+
+    /* first modify the base class, then the clones */
+    Class = Class->Base;
+
+    if (ClsExtraNew < 0 ||
+        (ULONG_PTR)ClsExtraNew + Class->ClassExtraDataOffset < Class->ClassExtraDataOffset)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (Class->System)
+        List = &pi->SystemClassList;
+    else if (Class->Global)
+        List = &pi->GlobalClassList;
+    else
+        List = &pi->LocalClassList;
+
+    FailOnResize = Class->ClsExtra < ClsExtraNew;
+
+    /* resize the base class */
+    NewClass = IntClassResizeInternal(Class,
+                                      ClsExtraNew,
+                                      List);
+    if (NewClass == NULL)
+    {
+        if (FailOnResize)
+        {
+            DPRINT1("Failed to resize the base class\n");
+            return FALSE;
+        }
+    }
+    else
+        Class = NewClass;
+
+    /* resize the clones */
+    CloneList = &Class->Clone;
+    Clone = Class->Clone;
+    while (Clone != NULL)
+    {
+        NewClass = IntClassResizeInternal(Clone,
+                                          ClsExtraNew,
+                                          CloneList);
+
+        if (NewClass == NULL)
+        {
+            if (FailOnResize)
+            {
+                /* roll back all changes */
+                FailedResize = Clone;
+                break;
+            }
+        }
+        else
+            Clone = NewClass;
+
+        /* save the pointer to the base class in case it changed */
+        Clone->Base = Class;
+
+        Clone = Clone->Next;
+    }
+
+    if (FailedResize != NULL)
+    {
+        /* failed to resize one clone, roll back the changes to all
+           other clones and to the base class */
+        DPRINT1("Failed to resize the cloned class 0x%p\n", FailedResize);
+
+        /* roll back the changes made to the base class */
+        NewClass = IntClassResizeInternal(Class,
+                                          Class->ClsExtra,
+                                          List);
+        if (NewClass != NULL)
+            Class = NewClass;
+
+        /* roll back all changes made to the class clones */
+        CloneList = &Class->Clone;
+        Clone = Class->Clone;
+        while (Clone != FailedResize)
+        {
+            ASSERT(Clone != NULL);
+
+            NewClass = IntClassResizeInternal(Clone,
+                                              Class->ClsExtra,
+                                              CloneList);
+            if (NewClass != NULL)
+                Clone = NewClass;
+
+            /* save the pointer to the base class in case it changed */
+            Clone->Base = Class;
+
+            CloneList = &Clone->Next;
+            Clone = Clone->Next;
+        }
+
+        return FALSE;
+    }
+    else
+    {
+        /* all classes were successfully resized,
+           save the new extra data size */
+        Class->ClsExtra = ClsExtraNew;
+        Clone = Class->Clone;
+        while (Clone != NULL)
+        {
+            Clone->ClsExtra = ClsExtraNew;
+            Clone = Clone->Next;
+        }
+
+        return TRUE;
+    }
+}
+
+RTL_ATOM
+UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
+                  IN PUNICODE_STRING ClassName,
+                  IN PUNICODE_STRING MenuName,
+                  IN HANDLE hMenu, /* FIXME */
+                  IN WNDPROC wpExtra,
+                  IN DWORD dwFlags)
+{
+    PW32THREADINFO ti;
+    PW32PROCESSINFO pi;
+    PWINDOWCLASS Class;
+    RTL_ATOM ClassAtom;
+    RTL_ATOM Ret = (RTL_ATOM)0;
+
+    /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
+
+    ti = GetW32ThreadInfo();
+    if (ti == NULL)
+    {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return (RTL_ATOM)0;
+    }
+
+    pi = ti->kpi;
+
+    /* try to find a previously registered class */
+    ClassAtom = IntGetClassAtom(ClassName,
+                                NULL,
+                                NULL,
+                                NULL,
+                                NULL);
+    if (ClassAtom != (RTL_ATOM)0)
+    {
+        Class = IntFindClass(ClassAtom,
+                             lpwcx->hInstance,
+                             &pi->LocalClassList,
+                             NULL);
+        if (Class != NULL)
+        {
+            goto ClassAlreadyExists;
+        }
+
+        /* if CS_GLOBALCLASS is set, try to find a previously registered global class.
+           Re-registering system classes as global classes seems to be allowed,
+           so we don't fail */
+        if (lpwcx->style & CS_GLOBALCLASS)
+        {
+            Class = IntFindClass(ClassAtom,
+                                 NULL,
+                                 ((dwFlags & REGISTERCLASS_SYSTEM) ?
+                                     &pi->SystemClassList : &pi->GlobalClassList),
+                                 NULL);
+            if (Class != NULL)
+            {
+ClassAlreadyExists:
+                DPRINT1("Class 0x%p does already exist!\n", ClassAtom);
+                SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+                return (RTL_ATOM)0;
+            }
+        }
+    }
+
+    ASSERT(ti->Desktop != NULL);
+
+    Class = IntCreateClass(lpwcx,
+                           ClassName,
+                           MenuName,
+                           wpExtra,
+                           dwFlags,
+                           ti->Desktop,
+                           pi);
+
+    if (Class != NULL)
+    {
+        PWINDOWCLASS *List;
+
+        /* FIXME - pass the PMENU pointer to IntCreateClass instead! */
+        Class->hMenu = hMenu;
+
+        /* Register the class */
+        if (Class->System)
+            List = &pi->SystemClassList;
+        else if (Class->Global)
+            List = &pi->GlobalClassList;
+        else
+            List = &pi->LocalClassList;
+
+        Class->Next = *List;
+        (void)InterlockedExchangePointer(List,
+                                         Class);
+
+        Ret = Class->Atom;
+    }
+
+    return Ret;
+}
+
+BOOL
+UserUnregisterClass(IN PUNICODE_STRING ClassName,
+                    IN HINSTANCE hInstance)
+{
+    PWINDOWCLASS *Link;
+    PW32PROCESSINFO pi;
+    RTL_ATOM ClassAtom;
+    PWINDOWCLASS Class;
+
+    pi = GetW32ProcessInfo();
+    if (pi == NULL)
+    {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    /* NOTE: Accessing the buffer in ClassName may raise an exception! */
+    ClassAtom = IntGetClassAtom(ClassName,
+                                hInstance,
+                                pi,
+                                &Class,
+                                &Link);
+    if (ClassAtom == (RTL_ATOM)0)
+    {
+        return FALSE;
+    }
+
+    ASSERT(Class != NULL);
+
+    if (Class->System)
+    {
+        DPRINT1("Attempted to unregister system class 0x%p!\n", ClassAtom);
+        SetLastWin32Error(ERROR_ACCESS_DENIED);
+        return FALSE;
+    }
+
+    if (Class->Windows != 0 ||
+        Class->Clone != NULL)
+    {
+        SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
+        return FALSE;
+    }
+
+    /* must be a base class! */
+    ASSERT(Class->Base == Class);
+
+    /* unlink the class */
+    *Link = Class->Next;
+
+    /* finally free the resources */
+    IntDestroyClass(Class);
+    return TRUE;
+}
+
+INT
+UserGetClassName(IN PWINDOWCLASS Class,
+                 IN OUT PUNICODE_STRING ClassName,
+                 IN BOOL Ansi)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    WCHAR szStaticTemp[32];
+    PWSTR szTemp = NULL;
+    ULONG BufLen = sizeof(szStaticTemp);
+    INT Ret = 0;
+
+    /* Note: Accessing the buffer in ClassName may raise an exception! */
+
+    _SEH_TRY
+    {
+        if (Ansi)
+        {
+            PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
+            UNICODE_STRING UnicodeClassName;
+
+            /* limit the size of the static buffer on the stack to the
+               size of the buffer provided by the caller */
+            if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
+            {
+                BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
+            }
+
+            /* find out how big the buffer needs to be */
+            Status = RtlQueryAtomInAtomTable(gAtomTable,
+                                             Class->Atom,
+                                             NULL,
+                                             NULL,
+                                             szStaticTemp,
+                                             &BufLen);
+            if (Status == STATUS_BUFFER_TOO_SMALL)
+            {
+                if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
+                {
+                    /* the buffer required exceeds the ansi buffer provided,
+                       pretend like we're using the ansi buffer and limit the
+                       size to the buffer size provided */
+                    BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
+                }
+
+                /* allocate a temporary buffer that can hold the unicode class name */
+                szTemp = ExAllocatePool(PagedPool,
+                                        BufLen);
+                if (szTemp == NULL)
+                {
+                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                    _SEH_LEAVE;
+                }
+
+                /* query the class name */
+                Status = RtlQueryAtomInAtomTable(gAtomTable,
+                                                 Class->Atom,
+                                                 NULL,
+                                                 NULL,
+                                                 szTemp,
+                                                 &BufLen);
+            }
+            else
+                szTemp = szStaticTemp;
+
+            if (NT_SUCCESS(Status))
+            {
+                /* convert the atom name to ansi */
+
+                RtlInitUnicodeString(&UnicodeClassName,
+                                     szTemp);
+
+                Status = RtlUnicodeStringToAnsiString(AnsiClassName,
+                                                      &UnicodeClassName,
+                                                      FALSE);
+                if (!NT_SUCCESS(Status))
+                {
+                    SetLastNtError(Status);
+                    _SEH_LEAVE;
+                }
+            }
+
+            Ret = BufLen / sizeof(WCHAR);
+        }
+        else /* !Ansi */
+        {
+            BufLen = ClassName->MaximumLength;
+
+            /* query the atom name */
+            Status = RtlQueryAtomInAtomTable(gAtomTable,
+                                             Class->Atom,
+                                             NULL,
+                                             NULL,
+                                             ClassName->Buffer,
+                                             &BufLen);
+
+            if (NT_SUCCESS(Status))
+            {
+                SetLastNtError(Status);
+                _SEH_LEAVE;
+            }
+
+            Ret = BufLen / sizeof(WCHAR);
+        }
+    }
+    _SEH_HANDLE
+    {
+        SetLastNtError(_SEH_GetExceptionCode());
+    }
+    _SEH_END;
+
+    if (Ansi && szTemp != NULL && szTemp != szStaticTemp)
+    {
+        ExFreePool(szTemp);
+    }
+
+    return Ret;
+}
+
+ULONG_PTR
+UserGetClassLongPtr(IN PWINDOWCLASS Class,
+                    IN INT Index,
+                    IN BOOL Ansi)
+{
+    ULONG_PTR Ret = 0;
+
+    if (Index > 0)
+    {
+        PULONG_PTR Data;
+
+        if (Index + sizeof(ULONG_PTR) < Index ||
+            Index + sizeof(ULONG_PTR) > Class->ClsExtra)
+        {
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            return 0;
+        }
+
+        Data = (PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset);
+
+        /* FIXME - Data might be a unaligned pointer! Might be a problem on
+                   certain architectures, maybe using RtlCopyMemory is a
+                   better choice for those architectures! */
+        return *Data;
+    }
+
+    switch (Index)
+    {
+        case GCL_CBWNDEXTRA:
+            Ret = (ULONG_PTR)Class->WndExtra;
+            break;
+
+        case GCL_CBCLSEXTRA:
+            Ret = (ULONG_PTR)Class->ClsExtra;
+            break;
+
+        case GCLP_HBRBACKGROUND:
+            Ret = (ULONG_PTR)Class->hbrBackground;
+            break;
+
+        case GCLP_HCURSOR:
+            /* FIXME - get handle from pointer to CURSOR object */
+            Ret = (ULONG_PTR)Class->hCursor;
+            break;
+
+        case GCLP_HICON:
+            /* FIXME - get handle from pointer to ICON object */
+            Ret = (ULONG_PTR)Class->hIcon;
+            break;
+
+        case GCLP_HICONSM:
+            /* FIXME - get handle from pointer to ICON object */
+            Ret = (ULONG_PTR)Class->hIconSm;
+            break;
+
+        case GCLP_HMODULE:
+            Ret = (ULONG_PTR)Class->hInstance;
+            break;
+
+        case GCLP_MENUNAME:
+            /* NOTE: Returns pointer in kernel heap! */
+            if (Ansi)
+                Ret = (ULONG_PTR)Class->AnsiMenuName;
+            else
+                Ret = (ULONG_PTR)Class->MenuName;
+            break;
+
+        case GCL_STYLE:
+            Ret = (ULONG_PTR)Class->Style;
+            break;
+
+        case GCLP_WNDPROC:
+            Ret = (ULONG_PTR)IntGetClassWndProc(Class,
+                                                GetW32ProcessInfo(),
+                                                Ansi);
+            break;
+
+        case GCW_ATOM:
+            Ret = (ULONG_PTR)Class->Atom;
+            break;
+
+        default:
+            SetLastWin32Error(ERROR_INVALID_INDEX);
+            break;
+    }
+
+    return Ret;
+}
+
+static BOOL
+IntSetClassMenuName(IN PWINDOWCLASS Class,
+                    IN PUNICODE_STRING MenuName)
+{
+    BOOL Ret = FALSE;
+
+    /* change the base class first */
+    Class = Class->Base;
+
+    if (MenuName->Length != 0)
+    {
+        ANSI_STRING AnsiString;
+        PWSTR strBufW;
+
+        AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName);
+
+        strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
+                                AnsiString.MaximumLength);
+        if (strBufW != NULL)
+        {
+            _SEH_TRY
+            {
+                NTSTATUS Status;
+
+                /* copy the unicode string */
+                RtlCopyMemory(strBufW,
+                              MenuName->Buffer,
+                              MenuName->Length);
+                strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+                /* create an ansi copy of the string */
+                AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1);
+                Status = RtlUnicodeStringToAnsiString(&AnsiString,
+                                                      MenuName,
+                                                      FALSE);
+                if (!NT_SUCCESS(Status))
+                {
+                    SetLastNtError(Status);
+                    _SEH_LEAVE;
+                }
+
+                Ret = TRUE;
+            }
+            _SEH_HANDLE
+            {
+                SetLastNtError(_SEH_GetExceptionCode());
+            }
+            _SEH_END;
+
+            if (Ret)
+            {
+                /* update the base class */
+                IntFreeClassMenuName(Class);
+                Class->MenuName = strBufW;
+                Class->AnsiMenuName = AnsiString.Buffer;
+
+                /* update the clones */
+                Class = Class->Clone;
+                while (Class != NULL)
+                {
+                    Class->MenuName = strBufW;
+                    Class->AnsiMenuName = AnsiString.Buffer;
+
+                    Class = Class->Next;
+                }
+            }
+            else
+            {
+                DPRINT1("Failed to copy class menu name!\n");
+                UserHeapFree(strBufW);
+            }
+        }
+        else
+            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+    }
+    else
+    {
+        ASSERT(IS_INTRESOURCE(MenuName->Buffer));
+
+        /* update the base class */
+        IntFreeClassMenuName(Class);
+        Class->MenuName = MenuName->Buffer;
+        Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+
+        /* update the clones */
+        Class = Class->Clone;
+        while (Class != NULL)
+        {
+            Class->MenuName = MenuName->Buffer;
+            Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+
+            Class = Class->Next;
+        }
+
+        Ret = TRUE;
+    }
+
+    return Ret;
+}
+
+ULONG_PTR
+UserSetClassLongPtr(IN PWINDOWCLASS Class,
+                    IN INT Index,
+                    IN ULONG_PTR NewLong,
+                    IN BOOL Ansi)
+{
+    ULONG_PTR Ret = 0;
+
+    /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
+
+    /* change the information in the base class first, then update the clones */
+    Class = Class->Base;
+
+    if (Index > 0)
+    {
+        PULONG_PTR Data;
+
+        if (Index + sizeof(ULONG_PTR) < Index ||
+            Index + sizeof(ULONG_PTR) > Class->ClsExtra)
+        {
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            return 0;
+        }
+
+        Data = (PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset);
+
+        /* FIXME - Data might be a unaligned pointer! Might be a problem on
+                   certain architectures, maybe using RtlCopyMemory is a
+                   better choice for those architectures! */
+        Ret = *Data;
+        *Data = NewLong;
+
+        /* update the clones */
+        Class = Class->Clone;
+        while (Class != NULL)
+        {
+            *(PULONG_PTR)((ULONG_PTR)Class + Class->ClassExtraDataOffset) = NewLong;
+            Class = Class->Next;
+        }
+
+        return Ret;
+    }
+
+    switch (Index)
+    {
+        case GCL_CBWNDEXTRA:
+            Ret = (ULONG_PTR)Class->WndExtra;
+            Class->WndExtra = (INT)NewLong;
+
+            /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->WndExtra = (INT)NewLong;
+                Class = Class->Next;
+            }
+
+            break;
+
+        case GCL_CBCLSEXTRA:
+            Ret = (ULONG_PTR)Class->ClsExtra;
+            if (Class->ClsExtra != (INT)NewLong)
+            {
+                if (!IntClassResize(Class,
+                                    GetW32ProcessInfo(),
+                                    (INT)NewLong))
+                {
+                    Ret = 0;
+                }
+            }
+            break;
+
+        case GCLP_HBRBACKGROUND:
+            Ret = (ULONG_PTR)Class->hbrBackground;
+            Class->hbrBackground = (HBRUSH)NewLong;
+
+            /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->hbrBackground = (HBRUSH)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_HCURSOR:
+            /* FIXME - get handle from pointer to CURSOR object */
+            Ret = (ULONG_PTR)Class->hCursor;
+            Class->hCursor = (HANDLE)NewLong;
+
+            /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->hCursor = (HANDLE)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_HICON:
+            /* FIXME - get handle from pointer to ICON object */
+            Ret = (ULONG_PTR)Class->hIcon;
+            Class->hIcon = (HANDLE)NewLong;
+
+            /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->hIcon = (HANDLE)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_HICONSM:
+            /* FIXME - get handle from pointer to ICON object */
+            Ret = (ULONG_PTR)Class->hIconSm;
+            Class->hIconSm = (HANDLE)NewLong;
+
+            /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->hIconSm = (HANDLE)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_HMODULE:
+            Ret = (ULONG_PTR)Class->hInstance;
+            Class->hInstance = (HINSTANCE)NewLong;
+
+           /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->hInstance = (HINSTANCE)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_MENUNAME:
+        {
+            PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
+
+            if (!IntSetClassMenuName(Class,
+                                     Value))
+            {
+                DPRINT("Setting the class menu name failed!\n");
+            }
+
+            /* FIXME - really return NULL? Wine does so... */
+            break;
+        }
+
+        case GCL_STYLE:
+            Ret = (ULONG_PTR)Class->Style;
+            Class->Style = (UINT)NewLong;
+
+            /* FIXME - what if the CS_GLOBALCLASS style is changed? should we
+                       move the class to the appropriate list? For now, we save
+                       the original value in Class->Global, so we can always
+                       locate the appropriate list */
+
+           /* update the clones */
+            Class = Class->Clone;
+            while (Class != NULL)
+            {
+                Class->Style = (UINT)NewLong;
+                Class = Class->Next;
+            }
+            break;
+
+        case GCLP_WNDPROC:
+            Ret = (ULONG_PTR)IntSetClassWndProc(Class,
+                                                (WNDPROC)NewLong,
+                                                Ansi);
+            break;
+
+        case GCW_ATOM:
+        {
+            PUNICODE_STRING Value = (PUNICODE_STRING)NewLong;
+
+            Ret = (ULONG_PTR)Class->Atom;
+            if (!IntSetClassAtom(Class,
+                                 Value))
+            {
+                Ret = 0;
+            }
+            break;
+        }
+
+        default:
+            SetLastWin32Error(ERROR_INVALID_INDEX);
+            break;
+    }
+
+    return Ret;
+}
+
+static BOOL
+UserGetClassInfo(IN PWINDOWCLASS Class,
+                 OUT PWNDCLASSEXW lpwcx,
+                 IN BOOL Ansi)
+{
+    lpwcx->style = Class->Style;
+
+    if (Class->System)
+    {
+        lpwcx->lpfnWndProc = (!Ansi ? Class->WndProc : Class->WndProcExtra);
+    }
+    else
+    {
+        if (!Ansi == Class->Unicode)
+        {
+            lpwcx->lpfnWndProc = Class->WndProc;
+        }
+        else
+        {
+            /* FIXME - return callproc handle or function pointer? */
+            lpwcx->lpfnWndProc = Class->CallProc->WndProc;
+        }
+    }
+
+    lpwcx->cbClsExtra = Class->ClsExtra;
+    lpwcx->cbWndExtra = Class->WndExtra;
+    lpwcx->hInstance = Class->hInstance;
+    lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */
+    lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */
+    lpwcx->hbrBackground = Class->hbrBackground;
+
+    if (Ansi)
+        ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->AnsiMenuName;
+    else
+        lpwcx->lpszMenuName = Class->MenuName;
+
+    lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->Atom); /* FIXME - return the string? */
+
+    lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */
+
+    return TRUE;
+}
+
 /* SYSCALLS *****************************************************************/
 
 
-RTL_ATOM STDCALL
-NtUserRegisterClassExWOW(
-   CONST WNDCLASSEXW* lpwcx,
-   PUNICODE_STRING ClassName,
-   PUNICODE_STRING ClassNameCopy,//huhuhuhu???
-   PUNICODE_STRING MenuName,
-   WNDPROC wpExtra,
-   DWORD Flags,
-   DWORD Unknown7,
-   HMENU hMenu)
+RTL_ATOM NTAPI
+NtUserRegisterClassEx(IN CONST WNDCLASSEXW* lpwcx,
+                      IN PUNICODE_STRING ClassName,
+                      IN PUNICODE_STRING MenuName,
+                      IN WNDPROC wpExtra,
+                      IN DWORD Flags,
+                      IN HMENU hMenu)
 
 /*
  * FUNCTION:
@@ -452,149 +1819,204 @@
  *   Atom identifying the new class
  */
 {
-   WNDCLASSEXW SafeClass;
-   NTSTATUS Status;
-   RTL_ATOM Atom;
-   DECLARE_RETURN(RTL_ATOM);
-
-   DPRINT("Enter NtUserRegisterClassExWOW\n");
-   UserEnterExclusive();
-
-   if (!lpwcx)
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN( (RTL_ATOM)0);
-   }
-
-   if (Flags & ~REGISTERCLASS_ALL)
-   {
-      SetLastWin32Error(ERROR_INVALID_FLAGS);
-      RETURN( (RTL_ATOM)0);
-   }
-
-   Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( (RTL_ATOM)0);
-   }
-
-   /* Deny negative sizes */
-   if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN( (RTL_ATOM)0);
-   }
-
-   if (!lpwcx->hInstance)
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN( (RTL_ATOM)0);
-   }
-
-   //FIXME: make ClassName ptr the atom, not buffer
-   if (ClassName->Length > 0)
-   {
-      DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
-      /* FIXME - Safely copy/verify the buffer first!!! */
-      Status = RtlAddAtomToAtomTable(gAtomTable,
-                                     ClassName->Buffer,
-                                     &Atom);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT1("Failed adding class name (%S) to atom table\n",
-                 ClassName->Buffer);
-         SetLastNtError(Status);
-         RETURN((RTL_ATOM)0);
-      }
-   }
-   else
-   {
-      Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
-   }
-
-   if (!Atom)
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN(0);
-   }
-
-   if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom, hMenu))
-   {
-      if (ClassName->Length)
-      {
-         RtlDeleteAtomFromAtomTable(gAtomTable, Atom);
-      }
-      DPRINT("Failed creating window class object\n");
-      RETURN((RTL_ATOM)0);
-   }
-
-   RETURN(Atom);
-
-CLEANUP:
-   DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-
-
-DWORD STDCALL
-NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
-{
-   PWINDOW_OBJECT Window;
-   DECLARE_RETURN(DWORD);
-
-   DPRINT("Enter NtUserGetClassLong\n");
-   UserEnterExclusive();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(0);
-   }
-
-   RETURN(IntGetClassLong(Window, Offset, Ansi));
-
-CLEANUP:
-   DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-
-
-DWORD STDCALL
+    WNDCLASSEXW CapturedClassInfo = {0};
+    UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
+    RTL_ATOM Ret = (RTL_ATOM)0;
+
+    if (Flags & ~REGISTERCLASS_ALL)
+    {
+        SetLastWin32Error(ERROR_INVALID_FLAGS);
+        return Ret;
+    }
+
+    UserEnterExclusive();
+
+    _SEH_TRY
+    {
+        /* Probe the parameters and basic parameter checks */
+        if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
+        {
+            goto InvalidParameter;
+        }
+
+        ProbeForRead(lpwcx,
+                     sizeof(WNDCLASSEXW),
+                     sizeof(ULONG));
+        RtlCopyMemory(&CapturedClassInfo,
+                      lpwcx,
+                      sizeof(WNDCLASSEXW));
+
+        CapturedName = ProbeForReadUnicodeString(ClassName);
+        CapturedMenuName = ProbeForReadUnicodeString(MenuName);
+
+        if (CapturedName.Length & 1 || CapturedMenuName.Length & 1 ||
+            CapturedClassInfo.cbClsExtra < 0 ||
+            CapturedClassInfo.cbClsExtra + CapturedName.Length +
+                CapturedMenuName.Length + sizeof(WINDOWCLASS) < CapturedClassInfo.cbClsExtra ||
+            CapturedClassInfo.cbWndExtra < 0 ||
+            CapturedClassInfo.hInstance == NULL)
+        {
+            goto InvalidParameter;
+        }
+
+        if (CapturedName.Length != 0)
+        {
+            ProbeForRead(CapturedName.Buffer,
+                         CapturedName.Length,
+                         sizeof(WCHAR));
+        }
+        else
+        {
+            if (!IS_ATOM(CapturedName.Buffer))
+            {
+                goto InvalidParameter;
+            }
+        }
+
+        if (CapturedMenuName.Length != 0)
+        {
+            ProbeForRead(CapturedMenuName.Buffer,
+                         CapturedMenuName.Length,
+                         sizeof(WCHAR));
+        }
+        else if (CapturedMenuName.Buffer != NULL &&
+                 !IS_INTRESOURCE(CapturedMenuName.Buffer))
+        {
+InvalidParameter:
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            _SEH_LEAVE;
+        }
+
+        /* Register the class */
+        Ret = UserRegisterClass(&CapturedClassInfo,
+                                &CapturedName,
+                                &CapturedMenuName,
+                                hMenu, /* FIXME - pass pointer */
+                                wpExtra,
+                                Flags);
+
+    }
+    _SEH_HANDLE
+    {
+        SetLastNtError(_SEH_GetExceptionCode());
+    }
+    _SEH_END;
+
+    UserLeave();
+
+    return Ret;
+}
+
+
+
+ULONG_PTR NTAPI
+NtUserGetClassLong(IN HWND hWnd,
+                   IN INT Offset,
+                   IN BOOL Ansi)
+{
+    PWINDOW_OBJECT Window;
+    ULONG_PTR Ret = 0;
+
+    UserEnterShared();
+
+    Window = UserGetWindowObject(hWnd);
+    if (Window != NULL)
+    {
+        Ret = UserGetClassLongPtr(Window->Class,
+                                  Offset,
+                                  Ansi);
+
+        if (Ret != 0 && Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Ret))
+        {
+            Ret = (ULONG_PTR)DesktopHeapAddressToUser(Window->Class->Desktop,
+                                                      (PVOID)Ret);
+        }
+    }
+
+    UserLeave();
+
+    return Ret;
+}
+
+
+
+ULONG_PTR STDCALL
 NtUserSetClassLong(HWND hWnd,
-                   DWORD Offset,
-                   LONG dwNewLong,
+                   INT Offset,
+                   ULONG_PTR dwNewLong,
                    BOOL Ansi)
 {
-   PWINDOW_OBJECT Window;
-   LONG Ret;
-   USER_REFERENCE_ENTRY Ref;
-   DECLARE_RETURN(DWORD);
-
-   DPRINT("Enter NtUserSetClassLong\n");
-   UserEnterExclusive();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(0);
-   }
-
-   UserRefObjectCo(Window, &Ref);
-
-   Ret = IntGetClassLong(Window, Offset, Ansi);
-   co_IntSetClassLong(Window, Offset, dwNewLong, Ansi);
-
-   UserDerefObjectCo(Window);
-
-   RETURN(Ret);
-
-CLEANUP:
-   DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    PW32PROCESSINFO pi;
+    PWINDOW_OBJECT Window;
+    ULONG_PTR Ret = 0;
+
+    UserEnterExclusive();
+
+    pi = GetW32ProcessInfo();
+    if (pi == NULL)
+        goto Cleanup;
+
+    Window = UserGetWindowObject(hWnd);
+    if (Window != NULL)
+    {
+        if (Window->ti->kpi != pi)
+        {
+            SetLastWin32Error(ERROR_ACCESS_DENIED);
+            goto Cleanup;
+        }
+
+        _SEH_TRY
+        {
+            UNICODE_STRING Value;
+
+            /* probe the parameters */
+            if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
+            {
+                Value = ProbeForReadUnicodeString((PUNICODE_STRING)dwNewLong);
+                if (Value.Length & 1)
+                {
+                    goto InvalidParameter;
+                }
+
+                if (Value.Length != 0)
+                {
+                    ProbeForRead(Value.Buffer,
+                                 Value.Length,
+                                 sizeof(WCHAR));
+                }
+                else
+                {
+                    if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer))
+                    {
+                        goto InvalidParameter;
+                    }
+                    else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
+                    {
+InvalidParameter:
+                        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                        _SEH_LEAVE;
+                    }
+                }
+
+                dwNewLong = (ULONG_PTR)&Value;
+            }
+
+            Ret = UserSetClassLongPtr(Window->Class,
+                                      Offset,
+                                      dwNewLong,
+                                      Ansi);
+        }
+        _SEH_HANDLE
+        {
+            SetLastNtError(_SEH_GetExceptionCode());
+        }
+        _SEH_END;
+    }
+
+Cleanup:
+    UserLeave();
+
+    return Ret;
 }
 
 DWORD STDCALL
@@ -602,164 +2024,232 @@
                    DWORD Unknown1,
                    DWORD Unknown2)
 {
-   UNIMPLEMENTED;
    return(0);
 }
 
+BOOL NTAPI
+NtUserUnregisterClass(IN PUNICODE_STRING ClassNameOrAtom,
+                      IN HINSTANCE hInstance)
+{
+    UNICODE_STRING CapturedClassName;
+    BOOL Ret = FALSE;
+
+    UserEnterExclusive();
+
+    _SEH_TRY
+    {
+        /* probe the paramters */
+        CapturedClassName = ProbeForReadUnicodeString(ClassNameOrAtom);
+        if (CapturedClassName.Length & 1)
+        {
+            goto InvalidParameter;
+        }
+
+        if (CapturedClassName.Length != 0)
+        {
+            ProbeForRead(CapturedClassName.Buffer,
+                         CapturedClassName.Length,
+                         sizeof(WCHAR));
+        }
+        else
+        {
+            if (!IS_ATOM(CapturedClassName.Buffer))
+            {
+InvalidParameter:
+                SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                _SEH_LEAVE;
+            }
+        }
+
+        /* unregister the class */
+        Ret = UserUnregisterClass(&CapturedClassName,
+                                  hInstance);
+    }
+    _SEH_HANDLE
+    {
+        SetLastNtError(_SEH_GetExceptionCode());
+    }
+    _SEH_END;
+
+    UserLeave();
+
+    return Ret;
+}
+
+/* NOTE: for system classes hInstance is not NULL here, but User32Instance */
 BOOL STDCALL
-NtUserUnregisterClass(
-   LPCWSTR ClassNameOrAtom,
-   HINSTANCE hInstance, /* can be 0 */
-   DWORD Unknown)
-{
-   PWNDCLASS_OBJECT Class;
-   DECLARE_RETURN(BOOL);
-
-   DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
-   UserEnterExclusive();
-
-   if (!ClassNameOrAtom)
-   {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      RETURN(FALSE);
-   }
-
-   if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
-   {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      RETURN(FALSE);
-   }
-
-   if (Class->refs)
-   {
-      /* NOTE: the class will not be freed when its refs become 0 ie. no more
-       * windows are using it. I dunno why that is but its how Windows does it (and Wine).
-       * The class will hang around until the process exit. -Gunnar
-       */
-      SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
-      RETURN(FALSE);
-   }
-
-   DestroyClass(Class);
-   
-   RETURN(TRUE);
-
-CLEANUP:
-   DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/* NOTE: for system classes hInstance is not NULL here, but User32Instance */
-DWORD STDCALL
 NtUserGetClassInfo(
    HINSTANCE hInstance,
-   LPCWSTR lpClassName,
+   PUNICODE_STRING ClassName,
    LPWNDCLASSEXW lpWndClassEx,
-   BOOL Ansi,
-   DWORD unknown3)
-{
-   PWNDCLASS_OBJECT Class;
-   RTL_ATOM Atom;
-   DECLARE_RETURN(DWORD);
-
-   if (IS_ATOM(lpClassName))
-      DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
-   else
-      DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
-
-   UserEnterExclusive();
-
-   if (!hInstance)
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN(0);
-   }
-
-   if (!(Class = ClassGetClassByNameOrAtom(lpClassName, hInstance)))
-   {
-      SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
-      RETURN(0);
-   }
-
-   lpWndClassEx->cbSize = sizeof(WNDCLASSEXW);
-   lpWndClassEx->style = Class->style;
-   if (Ansi)
-      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
-   else
-      lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
-   lpWndClassEx->cbClsExtra = Class->cbClsExtra;
-   lpWndClassEx->cbWndExtra = Class->cbWndExtra;
-   /* This is not typo, we're really not going to use Class->hInstance here. */
-   /* Well, i think its wrong so i changed it -Gunnar */
-   lpWndClassEx->hInstance = Class->hInstance;
-   lpWndClassEx->hIcon = Class->hIcon;
-   lpWndClassEx->hCursor = Class->hCursor;
-   lpWndClassEx->hbrBackground = Class->hbrBackground;
-   if (Class->lpszMenuName.MaximumLength)
-      RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName);
-   else
-      lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer;
-   lpWndClassEx->lpszClassName = lpClassName;
-   lpWndClassEx->hIconSm = Class->hIconSm;
-   Atom = Class->Atom;
-
-   RETURN(Atom);
-
-CLEANUP:
-   DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-
-
-DWORD STDCALL
-NtUserGetClassName (
-   HWND hWnd,
-   LPWSTR lpClassName,
-   ULONG nMaxCount /* in TCHARS */
-   )
-{
-   PWINDOW_OBJECT Window;
-   DECLARE_RETURN(DWORD);
-   NTSTATUS Status;
-
-   UserEnterShared();
-   DPRINT("Enter NtUserGetClassName\n");   
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(0);
-   }
-
-   nMaxCount *= sizeof(WCHAR);
-   
-   //FIXME: wrap in SEH to protect lpClassName access
-   Status = RtlQueryAtomInAtomTable(gAtomTable,
-                                    Window->Class->Atom, NULL, NULL,
-                                    lpClassName, &nMaxCount);
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN(0);
-   }
-
-   RETURN(nMaxCount / sizeof(WCHAR));
-
-CLEANUP:
-   DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+   BOOL Ansi)
+{
+    UNICODE_STRING CapturedClassName;
+    PWINDOWCLASS Class;
+    RTL_ATOM ClassAtom;
+    PW32PROCESSINFO pi;
+    BOOL Ret = FALSE;
+
+    UserEnterShared();
+
+    pi = GetW32ProcessInfo();
+    if (pi == NULL)
+    {
+        goto Cleanup;
+    }
+
+    _SEH_TRY
+    {
+        /* probe the paramters */
+        CapturedClassName = ProbeForReadUnicodeString(ClassName);
+        if (CapturedClassName.Length & 1)
+        {
+            goto InvalidParameter;
+        }
+
+        if (CapturedClassName.Length != 0)
+        {
+            ProbeForRead(CapturedClassName.Buffer,
+                         CapturedClassName.Length,
+                         sizeof(WCHAR));
+        }
+        else
+        {
+            if (!IS_ATOM(CapturedClassName.Buffer))
+            {
+                goto InvalidParameter;
+            }
+        }
+
+        if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
+        {
+InvalidParameter:
+            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            _SEH_LEAVE;
+        }
+
+        ProbeForWrite(lpWndClassEx,
+                      sizeof(WNDCLASSEXW),
+                      sizeof(ULONG));
+
+        ClassAtom = IntGetClassAtom(&CapturedClassName,
+                                    hInstance,
+                                    pi,
+                                    &Class,
+                                    NULL);
+        if (ClassAtom != (RTL_ATOM)0)
+        {
+            Ret = UserGetClassInfo(Class,
+                                   lpWndClassEx,
+                                   Ansi);
+
+            if (Ret)
+            {
+                lpWndClassEx->lpszClassName = CapturedClassName.Buffer;
+
+                /* FIXME - handle Class->Desktop == NULL!!!!! */
+
+                if (Class->MenuName != NULL &&
+                    !IS_INTRESOURCE(Class->MenuName))
+                {
+                    lpWndClassEx->lpszMenuName = DesktopHeapAddressToUser(Class->Desktop,
+                                                                          (Ansi ?
+                                                                              (PVOID)Class->AnsiMenuName :
+                                                                              (PVOID)Class->MenuName));
+                }
+            }
+        }
+    }
+    _SEH_HANDLE
+    {
+        SetLastNtError(_SEH_GetExceptionCode());
+    }
+    _SEH_END;
+
+Cleanup:
+    UserLeave();
+
+    return Ret;
+}
+
+
+
+INT NTAPI
+NtUserGetClassName (IN HWND hWnd,
+                    OUT PUNICODE_STRING ClassName,
+                    IN BOOL Ansi)
+{
+    PWINDOW_OBJECT Window;
+    UNICODE_STRING CapturedClassName;
+    INT Ret = 0;
+
+    UserEnterShared();
+
+    Window = UserGetWindowObject(hWnd);
+    if (Window != NULL)
+    {
+        _SEH_TRY
+        {
+            ProbeForWriteUnicodeString(ClassName);
+            CapturedClassName = *ClassName;
+
+            /* get the class name */
+            Ret = UserGetClassName(Window->Class,
+                                   &CapturedClassName,
+                                   Ansi);
+
+            if (Ret != 0)
+            {
+                /* update the Length field */
+                ClassName->Length = CapturedClassName.Length;
+            }
+        }
+        _SEH_HANDLE
+        {
+            SetLastNtError(_SEH_GetExceptionCode());
+        }
+        _SEH_END;
+    }
+
+    UserLeave();
+
+    return Ret;
 }
 
 DWORD STDCALL
 NtUserGetWOWClass(DWORD Unknown0,
                   DWORD Unknown1)
 {
-   UNIMPLEMENTED;
    return(0);
 }
 
 
+BOOL NTAPI
+NtUserDereferenceWndProcHandle(IN HANDLE wpHandle,
+                               OUT PWNDPROC_INFO wpInfo)
+{
+    BOOL Ret = FALSE;
+
+    UserEnterShared();
+
+    _SEH_TRY
+    {
+        ProbeForWrite(wpInfo,
+                      sizeof(WNDPROC_INFO),
+                      sizeof(ULONG));
+
+        Ret = UserGetCallProcInfo(wpHandle,
+                                  wpInfo);
+    }
+    _SEH_HANDLE
+    {
+        SetLastWin32Error(_SEH_GetExceptionCode());
+    }
+    _SEH_END;
+
+    UserLeave();
+
+    return Ret;
+}
+
 /* EOF */

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c Wed Apr  5 12:05:55 2006
@@ -83,7 +83,7 @@
       return NULL;
    }
    
-   CurIcon = (PCURICON_OBJECT)UserGetObject(&gHandleTable, hCurIcon, otCursorIcon);
+   CurIcon = (PCURICON_OBJECT)UserGetObject(gHandleTable, hCurIcon, otCursorIcon);
    if (!CurIcon)
    {
       /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
@@ -397,7 +397,7 @@
    PCURICON_OBJECT CurIcon;
    HANDLE hCurIcon;
 
-   CurIcon = ObmCreateObject(&gHandleTable, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
+   CurIcon = ObmCreateObject(gHandleTable, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
 
    if(!CurIcon)
    {

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c Wed Apr  5 12:05:55 2006
@@ -43,6 +43,8 @@
 
 BOOL g_PaintDesktopVersion = FALSE;
 
+static VOID IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop);
+
 /* INITALIZATION FUNCTIONS ****************************************************/
 
 static GENERIC_MAPPING IntDesktopMapping =
@@ -121,6 +123,8 @@
    RemoveEntryList(&Desktop->ListEntry);
 
    RtlFreeUnicodeString(&Desktop->Name);
+
+   IntFreeDesktopHeap(Desktop);
 }
 
 /* PRIVATE FUNCTIONS **********************************************************/
@@ -723,7 +727,15 @@
    return FALSE;
 }
 
-
+static VOID
+IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop)
+{
+    if (Desktop->DesktopHeapSection != NULL)
+    {
+        ObDereferenceObject(Desktop->DesktopHeapSection);
+        Desktop->DesktopHeapSection = NULL;
+    }
+}
 
 
 /* SYSCALLS *******************************************************************/
@@ -776,6 +788,8 @@
    NTSTATUS Status;
    HDESK Desktop;
    CSR_API_MESSAGE Request;
+   PVOID DesktopHeapSystemBase = NULL;
+   SIZE_T DesktopInfoSize;
    DECLARE_RETURN(HDESK);
 
    DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
@@ -857,6 +871,39 @@
       SetLastNtError(STATUS_UNSUCCESSFUL);
       RETURN( NULL);
    }
+
+   DesktopObject->DesktopHeapSection = NULL;
+   DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection,
+                                                &DesktopHeapSystemBase,
+                                                4 * 1024 * 1024); /* FIXME */
+   if (DesktopObject->hDesktopHeap == NULL)
+   {
+       ObDereferenceObject(DesktopObject);
+       DPRINT1("Failed to create desktop heap!\n");
+       RETURN(NULL);
+   }
+
+   DesktopInfoSize = FIELD_OFFSET(DESKTOP,
+                                  szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);
+
+   DesktopObject->DesktopInfo = RtlAllocateHeap(DesktopObject->hDesktopHeap,
+                                                HEAP_NO_SERIALIZE,
+                                                DesktopInfoSize);
+
+   if (DesktopObject->DesktopInfo == NULL)
+   {
+       ObDereferenceObject(DesktopObject);
+       DPRINT1("Failed to create the DESKTOP structure!\n");
+       RETURN(NULL);
+   }
+
+   RtlZeroMemory(DesktopObject->DesktopInfo,
+                 DesktopInfoSize);
+
+   DesktopObject->DesktopInfo->hKernelHeap = DesktopObject->hDesktopHeap;
+   RtlCopyMemory(DesktopObject->DesktopInfo->szDesktopName,
+                 lpszDesktopName->Buffer,
+                 lpszDesktopName->Length);
 
    // init desktop area
    DesktopObject->WorkArea.left = 0;
@@ -1216,7 +1263,7 @@
       RETURN(FALSE);
    }
 
-   DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
+   DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE);
 
 
    /*
@@ -1560,6 +1607,183 @@
    END_CLEANUP;
 }
 
+static NTSTATUS
+IntUnmapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
+{
+    PW32THREADINFO ti;
+    PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetWin32Process()->HeapMappings.Next;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* unmap if we're the last thread using the desktop */
+    HeapMapping = *PrevLink;
+    while (HeapMapping != NULL)
+    {
+        if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
+        {
+            if (--HeapMapping->Count == 0)
+            {
+                *PrevLink = HeapMapping->Next;
+
+                Status = MmUnmapViewOfSection(PsGetCurrentProcess(),
+                                              HeapMapping->UserMapping);
+
+                ObDereferenceObject(DesktopObject);
+
+                UserHeapFree(HeapMapping);
+                break;
+            }
+        }
+
+        PrevLink = &HeapMapping->Next;
+        HeapMapping = HeapMapping->Next;
+    }
+
+    ti = GetW32ThreadInfo();
+    if (ti != NULL)
+    {
+        if (ti->Desktop == DesktopObject->DesktopInfo)
+        {
+            ti->Desktop = NULL;
+            ti->DesktopHeapDelta = 0;
+        }
+    }
+
+    return Status;
+}
+
+static NTSTATUS
+IntMapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
+{
+    PW32THREADINFO ti;
+    PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetWin32Process()->HeapMappings.Next;
+    PVOID UserBase = NULL;
+    ULONG ViewSize = 0;
+    LARGE_INTEGER Offset;
+    NTSTATUS Status;
+
+    /* find out if another thread already mapped the desktop heap */
+    HeapMapping = *PrevLink;
+    while (HeapMapping != NULL)
+    {
+        if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
+        {
+            HeapMapping->Count++;
+            return STATUS_SUCCESS;
+        }
+
+        PrevLink = &HeapMapping->Next;
+        HeapMapping = HeapMapping->Next;
+    }
+
+    /* we're the first, map the heap */
+    Offset.QuadPart = 0;
+    Status = MmMapViewOfSection(DesktopObject->DesktopHeapSection,
+                                PsGetCurrentProcess(),
+                                &UserBase,
+                                0,
+                                0,
+                                &Offset,
+                                &ViewSize,
+                                ViewUnmap,
+                                SEC_NO_CHANGE,
+                                PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+    if (!NT_SUCCESS(Status))
+    {
+        DbgPrint("Failed to map desktop\n");
+        return Status;
+    }
+
+    /* add the mapping */
+    HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING));
+    if (HeapMapping == NULL)
+    {
+        MmUnmapViewOfSection(PsGetCurrentProcess(),
+                             UserBase);
+        return STATUS_NO_MEMORY;
+    }
+
+    HeapMapping->Next = NULL;
+    HeapMapping->KernelMapping = (PVOID)DesktopObject->hDesktopHeap;
+    HeapMapping->UserMapping = UserBase;
+    HeapMapping->Count = 1;
+
+    ObReferenceObject(DesktopObject);
+
+    /* create a W32THREADINFO structure if not already done, or update it */
+    ti = GetW32ThreadInfo();
+    if (ti != NULL)
+    {
+        if (ti->Desktop == NULL)
+        {
+            ti->Desktop = DesktopObject->DesktopInfo;
+            ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
+        }
+    }
+
+    return STATUS_SUCCESS;
+}
+
+BOOL
+IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject)
+{
+    PDESKTOP_OBJECT OldDesktop;
+    PW32THREAD W32Thread;
+    NTSTATUS Status;
+    BOOL MapHeap;
+
+    MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
+    W32Thread = PsGetWin32Thread();
+
+    if (W32Thread->Desktop != DesktopObject)
+    {
+        OldDesktop = W32Thread->Desktop;
+
+        W32Thread->Desktop = DesktopObject;
+
+        if (MapHeap && DesktopObject != NULL)
+        {
+            Status = IntMapDesktopView(DesktopObject);
+            if (!NT_SUCCESS(Status))
+            {
+                SetLastNtError(Status);
+                return FALSE;
+            }
+        }
+
+        if (DesktopObject != NULL)
+        {
+            ObReferenceObject(DesktopObject);
+        }
+
+        if (OldDesktop != NULL)
+        {
+            if (MapHeap)
+            {
+                IntUnmapDesktopView(OldDesktop);
+            }
+
+            ObDereferenceObject(OldDesktop);
+
+            if (W32Thread != NULL && W32Thread->ThreadInfo != NULL &&
+                W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ? DesktopObject->DesktopInfo : NULL))
+            {
+                if (DesktopObject != NULL)
+                {
+                    W32Thread->ThreadInfo->Desktop = DesktopObject->DesktopInfo;
+                    W32Thread->ThreadInfo->DesktopHeapDelta = DesktopHeapGetUserDelta();
+                }
+                else
+                {
+                    W32Thread->ThreadInfo->Desktop = NULL;
+                    W32Thread->ThreadInfo->DesktopHeapDelta = 0;
+                }
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 /*
  * NtUserSetThreadDesktop
  *
@@ -1570,7 +1794,6 @@
 BOOL STDCALL
 NtUserSetThreadDesktop(HDESK hDesktop)
 {
-   PW32THREAD W32Thread;
    PDESKTOP_OBJECT DesktopObject;
    NTSTATUS Status;
    DECLARE_RETURN(BOOL);
@@ -1591,17 +1814,12 @@
       RETURN(FALSE);
    }
 
-   W32Thread = PsGetWin32Thread();
-
    /* FIXME: Should check here to see if the thread has any windows. */
 
-   if (W32Thread->Desktop != NULL)
-   {
-      ObDereferenceObject(W32Thread->Desktop);
-   }
-
-   W32Thread->Desktop = DesktopObject;
-   W32Thread->hDesktop = hDesktop;
+   if (!IntSetThreadDesktop(DesktopObject))
+   {
+       RETURN(FALSE);
+   }
 
    RETURN(TRUE);
    

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/hook.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/hook.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/hook.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/hook.c Wed Apr  5 12:05:55 2006
@@ -69,7 +69,7 @@
       return NULL;
    }
    
-   Hook = (PHOOK)UserGetObject(&gHandleTable, hHook, otHook);
+   Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
    if (!Hook)
    {
       SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
@@ -110,7 +110,7 @@
       }
    }
 
-   Hook = ObmCreateObject(&gHandleTable, &Handle, otHook, sizeof(HOOK));
+   Hook = ObmCreateObject(gHandleTable, &Handle, otHook, sizeof(HOOK));
    if (NULL == Hook)
    {
       return NULL;

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/menu.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/menu.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/menu.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/menu.c Wed Apr  5 12:05:55 2006
@@ -127,7 +127,7 @@
       return NULL;
    }
    
-   Menu = (PMENU_OBJECT)UserGetObject(&gHandleTable, hMenu, otMenu);
+   Menu = (PMENU_OBJECT)UserGetObject(gHandleTable, hMenu, otMenu);
    if (!Menu)
    {
       SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
@@ -310,7 +310,7 @@
    PMENU_OBJECT Menu;
 
    Menu = (PMENU_OBJECT)ObmCreateObject(
-             &gHandleTable, Handle,
+             gHandleTable, Handle,
              otMenu, sizeof(MENU_OBJECT));
 
    if(!Menu)
@@ -419,7 +419,7 @@
       return NULL;
 
    Menu = (PMENU_OBJECT)ObmCreateObject(
-             &gHandleTable, &hMenu,
+             gHandleTable, &hMenu,
              otMenu, sizeof(MENU_OBJECT));
 
    if(!Menu)

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/message.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/message.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c Wed Apr  5 12:05:55 2006
@@ -378,28 +378,9 @@
 
             MsgInfo.HandledByKernel = FALSE;
             Result = 0;
-            if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
-            {
-               if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
-               {
-                  /* Both Unicode and Ansi winprocs are real, use whatever
-                     usermode prefers */
-                  MsgInfo.Proc = (MsgInfo.Ansi ? Window->WndProcA
-                                  : Window->WndProcW);
-               }
-               else
-               {
-                  /* Real Unicode winproc */
-                  MsgInfo.Ansi = FALSE;
-                  MsgInfo.Proc = Window->WndProcW;
-               }
-            }
-            else
-            {
-               /* Must have real Ansi winproc */
-               MsgInfo.Ansi = TRUE;
-               MsgInfo.Proc = Window->WndProcA;
-            }
+
+            MsgInfo.Ansi = !Window->Unicode;
+            MsgInfo.Proc = Window->WndProc;
          }
       }
    }
@@ -615,7 +596,7 @@
    {
       /* generate double click messages, if necessary */
       if ((((*HitTest) != HTCLIENT) ||
-            (IntGetClassLong(Window, GCL_STYLE, FALSE) & CS_DBLCLKS)) &&
+            (Window->Class->Style & CS_DBLCLKS)) &&
             MsqIsDblClk(Msg, Remove))
       {
          Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
@@ -1401,16 +1382,9 @@
          DPRINT1("Failed to pack message parameters\n");
           RETURN( FALSE);
       }
-      if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
-      {
-         Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcW, FALSE, hWnd, Msg, wParam,
-                  lParamPacked,lParamBufferSize);
-      }
-      else
-      {
-         Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcA, TRUE, hWnd, Msg, wParam,
-                  lParamPacked,lParamBufferSize);
-      }
+
+      Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Unicode, hWnd, Msg, wParam,
+               lParamPacked,lParamBufferSize);
 
       if(uResult)
       {
@@ -1580,32 +1554,16 @@
    {
       /* Gather the information usermode needs to call the window proc directly */
       Info.HandledByKernel = FALSE;
-      if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
-      {
-         if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
-         {
-            /* Both Unicode and Ansi winprocs are real, see what usermode prefers */
-            Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
-                                      sizeof(BOOL));
-            if (! NT_SUCCESS(Status))
-            {
-               Info.Ansi = ! Window->Unicode;
-            }
-            Info.Proc = (Info.Ansi ? Window->WndProcA : Window->WndProcW);
-         }
-         else
-         {
-            /* Real Unicode winproc */
-            Info.Ansi = FALSE;
-            Info.Proc = Window->WndProcW;
-         }
-      }
-      else
-      {
-         /* Must have real Ansi winproc */
-         Info.Ansi = TRUE;
-         Info.Proc = Window->WndProcA;
-      }
+
+      Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
+                                sizeof(BOOL));
+      if (! NT_SUCCESS(Status))
+      {
+         Info.Ansi = ! Window->Unicode;
+      }
+
+      Info.Ansi = !Window->Unicode;
+      Info.Proc = Window->WndProc;
    }
    else
    {

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/misc.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/misc.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/misc.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/misc.c Wed Apr  5 12:05:55 2006
@@ -886,11 +886,22 @@
    DECLARE_RETURN(DWORD);
 
    DPRINT("Enter NtUserGetThreadState\n");
-   UserEnterShared();
+   if (Routine != THREADSTATE_GETTHREADINFO)
+   {
+       UserEnterShared();
+   }
+   else
+   {
+       UserEnterExclusive();
+   }
 
    switch (Routine)
    {
-      case 0:
+      case THREADSTATE_GETTHREADINFO:
+         GetW32ThreadInfo();
+         RETURN(0);
+
+      case THREADSTATE_FOCUSWINDOW:
          RETURN( (DWORD)IntGetThreadFocusWindow());
    }
    RETURN( 0);
@@ -1829,4 +1840,106 @@
    END_CLEANUP;
 }
 
+PW32PROCESSINFO
+GetW32ProcessInfo(VOID)
+{
+    PW32PROCESSINFO pi;
+    PW32PROCESS W32Process = PsGetWin32Process();
+
+    if (W32Process == NULL)
+    {
+        /* FIXME - temporary hack for system threads... */
+        return NULL;
+    }
+
+    if (W32Process->ProcessInfo == NULL)
+    {
+        pi = UserHeapAlloc(sizeof(W32PROCESSINFO));
+        if (pi != NULL)
+        {
+            RtlZeroMemory(pi,
+                          sizeof(W32PROCESSINFO));
+
+            /* initialize it */
+            pi->UserHandleTable = gHandleTable;
+
+            if (InterlockedCompareExchangePointer(&W32Process->ProcessInfo,
+                                                  pi,
+                                                  NULL) != NULL)
+            {
+                UserHeapFree(pi);
+            }
+        }
+        else
+        {
+            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        }
+    }
+
+    return W32Process->ProcessInfo;
+}
+
+PW32THREADINFO
+GetW32ThreadInfo(VOID)
+{
+    PTEB Teb;
+    PW32THREADINFO ti;
+    PW32THREAD W32Thread = PsGetWin32Thread();
+
+    if (W32Thread == NULL)
+    {
+        /* FIXME - temporary hack for system threads... */
+        return NULL;
+    }
+
+    /* allocate a W32THREAD structure if neccessary */
+    if (W32Thread->ThreadInfo == NULL)
+    {
+        ti = UserHeapAlloc(sizeof(W32THREADINFO));
+        if (ti != NULL)
+        {
+            RtlZeroMemory(ti,
+                          sizeof(W32THREADINFO));
+
+            /* initialize it */
+            ti->kpi = GetW32ProcessInfo();
+            ti->pi = UserHeapAddressToUser(ti->kpi);
+            if (W32Thread->Desktop != NULL)
+            {
+                ti->Desktop = W32Thread->Desktop->DesktopInfo;
+                ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
+            }
+            else
+            {
+                ti->Desktop = NULL;
+                ti->DesktopHeapDelta = 0;
+            }
+
+            W32Thread->ThreadInfo = ti;
+            /* update the TEB */
+            Teb = NtCurrentTeb();
+            _SEH_TRY
+            {
+                ProbeForWrite(Teb,
+                              sizeof(TEB),
+                              sizeof(ULONG));
+
+                Teb->Win32ThreadInfo = UserHeapAddressToUser(W32Thread->ThreadInfo);
+            }
+            _SEH_HANDLE
+            {
+                SetLastNtError(_SEH_GetExceptionCode());
+            }
+            _SEH_END;
+        }
+        else
+        {
+            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        }
+    }
+
+    return W32Thread->ThreadInfo;
+}
+
+
 /* EOF */

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c Wed Apr  5 12:05:55 2006
@@ -89,7 +89,7 @@
    HANDLE Handle;
    PMONITOR_OBJECT Monitor;
 
-   Monitor = ObmCreateObject(&gHandleTable, &Handle, otMonitor, sizeof (MONITOR_OBJECT));
+   Monitor = ObmCreateObject(gHandleTable, &Handle, otMonitor, sizeof (MONITOR_OBJECT));
    if (Monitor == NULL)
    {
       return NULL;
@@ -133,7 +133,7 @@
    }
    
    
-   Monitor = (PMONITOR_OBJECT)UserGetObject(&gHandleTable, hMonitor, otMonitor);
+   Monitor = (PMONITOR_OBJECT)UserGetObject(gHandleTable, hMonitor, otMonitor);
    if (!Monitor)
    {
       SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE);

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/object.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/object.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/object.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/object.c Wed Apr  5 12:05:55 2006
@@ -28,7 +28,7 @@
 #include <debug.h>
 
 int usedHandles=0;
-USER_HANDLE_TABLE gHandleTable;
+PUSER_HANDLE_TABLE gHandleTable = NULL;
 
 
 PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle )
@@ -71,19 +71,17 @@
       DPRINT1("Out of user handles!\n");
       return NULL;
 #if 0
-
-      struct user_handle *new_handles;
+      PUSER_HANDLE_ENTRY new_handles;
       /* grow array by 50% (but at minimum 32 entries) */
-      int growth = max( 32, allocated_handles / 2 );
-      int new_size = min( allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 );
-      if (new_size <= allocated_handles)
+      int growth = max( 32, ht->allocated_handles / 2 );
+      int new_size = min( ht->allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 );
+      if (new_size <= ht->allocated_handles)
          return NULL;
-      if (!(new_handles = realloc( handles, new_size * sizeof(*handles) )))
+      if (!(new_handles = UserHeapReAlloc( ht->handles, new_size * sizeof(*ht->handles) )))
          return NULL;
-      handles = new_handles;
-      allocated_handles = new_size;
+      ht->handles = new_handles;
+      ht->allocated_handles = new_size;
 #endif
-
    }
 
    entry = &ht->handles[ht->nb_handles++];
@@ -217,7 +215,7 @@
 {
 
    HANDLE hi;
-   PUSER_OBJECT_HEADER hdr = ExAllocatePool(PagedPool, size + sizeof(USER_OBJECT_HEADER));
+   PUSER_OBJECT_HEADER hdr = UserHeapAlloc(size + sizeof(USER_OBJECT_HEADER));//ExAllocatePool(PagedPool, size + sizeof(USER_OBJECT_HEADER));
    if (!hdr)
       return NULL;
 
@@ -225,7 +223,8 @@
    hi = UserAllocHandle(ht, USER_HEADER_TO_BODY(hdr), type );
    if (!hi)
    {
-      ExFreePool(hdr);
+      //ExFreePool(hdr);
+       UserHeapFree(hdr);
       return NULL;
    }
 
@@ -242,7 +241,7 @@
 ObmDeleteObject(HANDLE h, USER_OBJECT_TYPE type )
 {
    PUSER_OBJECT_HEADER hdr;
-   PVOID body = UserGetObject(&gHandleTable, h, type);
+   PVOID body = UserGetObject(gHandleTable, h, type);
    if (!body)
       return FALSE;
 
@@ -252,11 +251,12 @@
    hdr->destroyed = TRUE;
    if (hdr->RefCount == 0)
    {
-      UserFreeHandle(&gHandleTable, h);
+      UserFreeHandle(gHandleTable, h);
 
       memset(hdr, 0x55, sizeof(USER_OBJECT_HEADER));
 
-      ExFreePool(hdr);
+      UserHeapFree(hdr);
+      //ExFreePool(hdr);
       return TRUE;
    }
 
@@ -274,6 +274,12 @@
    hdr->RefCount++;
 }
 
+HANDLE FASTCALL ObmObjectToHandle(PVOID obj)
+{
+    PUSER_OBJECT_HEADER hdr = USER_BODY_TO_HEADER(obj);
+    return hdr->hSelf;
+}
+
 
 BOOL FASTCALL ObmDereferenceObject2(PVOID obj)
 {
@@ -287,11 +293,12 @@
    {
 //      DPRINT1("info: something destroyed bcaise of deref, in use=%i\n",usedHandles);
 
-      UserFreeHandle(&gHandleTable, hdr->hSelf);
+      UserFreeHandle(gHandleTable, hdr->hSelf);
 
       memset(hdr, 0x55, sizeof(USER_OBJECT_HEADER));
 
-      ExFreePool(hdr);
+      UserHeapFree(hdr);
+      //ExFreePool(hdr);
 
       return TRUE;
    }
@@ -307,15 +314,24 @@
    PVOID mem;
 
    //FIXME: dont alloc all at once! must be mapped into umode also...
-   mem = ExAllocatePool(PagedPool, sizeof(USER_HANDLE_ENTRY) * 1024*2);
+   //mem = ExAllocatePool(PagedPool, sizeof(USER_HANDLE_ENTRY) * 1024*2);
+   mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * 1024*2);
    if (!mem)
    {
       DPRINT1("Failed creating handle table\n");
       return FALSE;
    }
 
+   gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE));
+   if (gHandleTable == NULL)
+   {
+       UserHeapFree(mem);
+       DPRINT1("Failed creating handle table\n");
+       return FALSE;
+   }
+
    //FIXME: make auto growable
-   UserInitHandleTable(&gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
+   UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
 
    return TRUE;
 }

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/windc.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/windc.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/windc.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/windc.c Wed Apr  5 12:05:55 2006
@@ -353,7 +353,7 @@
 
       if (!(Flags & DCX_WINDOW))
       {
-         if (Window->Class->style & CS_PARENTDC)
+         if (Window->Class->Style & CS_PARENTDC)
          {
             Flags |= DCX_PARENTCLIP;
          }
@@ -676,7 +676,7 @@
       {
          if (pDCE == Window->Dce) /* owned or Class DCE*/
          {
-            if (Window->Class->style & CS_OWNDC) /* owned DCE*/
+            if (Window->Class->Style & CS_OWNDC) /* owned DCE*/
             {
                pDCE = DceFreeDCE(pDCE, FALSE);
                Window->Dce = NULL;

Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/window.c?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Wed Apr  5 12:05:55 2006
@@ -33,10 +33,6 @@
 #define NDEBUG
 #include <debug.h>
 
-static WndProcHandle *WndProcHandlesArray = 0;
-static WORD WndProcHandlesArraySize = 0;
-#define WPH_SIZE 0x40 /* the size to add to the WndProcHandle array each time */
-
 /* dialog resources appear to pass this in 16 bits, handle them properly */
 #define CW_USEDEFAULT16 (0x8000)
 
@@ -53,8 +49,6 @@
 NTSTATUS FASTCALL
 InitWindowImpl(VOID)
 {
-   WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,WPH_SIZE * sizeof(WndProcHandle), TAG_WINPROCLST);
-   WndProcHandlesArraySize = WPH_SIZE;
    return STATUS_SUCCESS;
 }
 
@@ -67,9 +61,6 @@
 NTSTATUS FASTCALL
 CleanupWindowImpl(VOID)
 {
-   ExFreePool(WndProcHandlesArray);
-   WndProcHandlesArray = 0;
-   WndProcHandlesArraySize = 0;
    return STATUS_SUCCESS;
 }
 
@@ -95,15 +86,26 @@
 /* temp hack */
 PWINDOW_OBJECT FASTCALL UserGetWindowObject(HWND hWnd)
 {
+   PW32THREADINFO ti;
    PWINDOW_OBJECT Window;
-   
+
+   if (PsGetCurrentProcess() != PsInitialSystemProcess)
+   {
+       ti = GetW32ThreadInfo();
+       if (ti == NULL)
+       {
+          SetLastWin32Error(ERROR_ACCESS_DENIED);
+          return NULL;
+       }
+   }
+
    if (!hWnd)
    { 
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
       return NULL;
    }
    
-   Window = (PWINDOW_OBJECT)UserGetObject(&gHandleTable, hWnd, otWindow);
+   Window = (PWINDOW_OBJECT)UserGetObject(gHandleTable, hWnd, otWindow);
    if (!Window || 0 != (Window->Status & WINDOWSTATUS_DESTROYED))
    {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
@@ -432,8 +434,16 @@
 
    IntDestroyScrollBars(Window);
 
+   if (!Window->Class->System && Window->CallProc != NULL)
+   {
+       DestroyCallProc(Window->ti->Desktop,
+                       Window->CallProc);
+   }
+
    /* dereference the class */
-   ClassDerefObject(Window->Class);
+   IntDereferenceClass(Window->Class,
+                       Window->ti->Desktop,
+                       Window->ti->kpi);
    Window->Class = NULL;
 
    if(Window->WindowRegion)
@@ -473,6 +483,57 @@
          *cx = *cy = 0;
       }
    }
+}
+
+static WNDPROC
+IntGetWindowProc(IN PWINDOW_OBJECT Window,
+                 IN BOOL Ansi)
+{
+    if (Window->IsSystem)
+    {
+        return (Ansi ? Window->WndProcExtra : Window->WndProc);
+    }
+    else
+    {
+        if (!Ansi == Window->Unicode)
+        {
+            return Window->WndProc;
+        }
+        else
+        {
+            if (Window->CallProc != NULL)
+            {
+                return (WNDPROC)ObmObjectToHandle(Window->CallProc);
+            }
+            else
+            {
+                PCALLPROC NewCallProc, CallProc;
+
+                /* NOTE: use the interlocked functions, as this operation may be done even
+                         when only the shared lock is held! */
+                NewCallProc = CreateCallProc(Window->ti->Desktop,
+                                             Window->WndProc,
+                                             Window->Unicode,
+                                             Window->ti->kpi);
+                if (NewCallProc == NULL)
+                {
+                    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                    return NULL;
+                }
+
+                CallProc = InterlockedCompareExchangePointer(&Window->CallProc,
+                                                             NewCallProc,
+                                                             NULL);
+                if (CallProc != NULL)
+                {
+                    DestroyCallProc(Window->ti->Desktop,
+                                    NewCallProc);
+                }
+
+                return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc));
+            }
+        }
+    }
 }
 
 BOOL FASTCALL
@@ -1333,7 +1394,8 @@
                      BOOL bUnicodeWindow)
 {
    PWINSTATION_OBJECT WinSta;
-   PWNDCLASS_OBJECT Class = NULL;
+   PWINDOWCLASS Class = NULL;
+   RTL_ATOM ClassAtom;
    PWINDOW_OBJECT Window = NULL;
    PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow;
    HWND ParentWindowHandle;
@@ -1342,6 +1404,7 @@
    HWND hWnd;
    POINT Pos;
    SIZE Size;
+   PW32THREADINFO ti = NULL;
 #if 0
 
    POINT MaxSize, MaxPos, MinTrack, MaxTrack;
@@ -1349,7 +1412,6 @@
 
    POINT MaxPos;
 #endif
-
    CREATESTRUCTW Cs;
    CBT_CREATEWNDW CbtCreate;
    LRESULT Result;
@@ -1399,13 +1461,27 @@
 
    /* FIXME: parent must belong to the current process */
 
+   /* Check the window station. */
+   ti = GetW32ThreadInfo();
+   if (ti == NULL || PsGetWin32Thread()->Desktop == NULL)
+   {
+      DPRINT1("Thread is not attached to a desktop! Cannot create window!\n");
+      RETURN( (HWND)0);
+   }
+
    /* Check the class. */
-   Class = ClassGetClassByNameOrAtom(ClassName->Buffer, hInstance);
-   if (!Class)
+
+   ClassAtom = IntGetClassAtom(ClassName,
+                               hInstance,
+                               ti->kpi,
+                               &Class,
+                               NULL);
+
+   if (ClassAtom == (RTL_ATOM)0)
    {
       if (IS_ATOM(ClassName->Buffer))
       {
-         DPRINT1("Class 0x%x not found\n", (DWORD_PTR) ClassName->Buffer);
+         DPRINT1("Class 0x%p not found\n", (DWORD_PTR) ClassName->Buffer);
       }
       else
       {
@@ -1416,14 +1492,14 @@
       RETURN((HWND)0);
    }
 
-   ClassRefObject(Class);
-
-   /* Check the window station. */
-   if (PsGetWin32Thread()->Desktop == NULL)
-   {
-      DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
-      RETURN( (HWND)0);
-   }
+   Class = IntReferenceClass(Class,
+                             ti->Desktop);
+   if (Class == NULL)
+   {
+       DPRINT1("Failed to reference window class!\n");
+       RETURN(NULL);
+   }
+
    WinSta = PsGetWin32Thread()->Desktop->WindowStation;
 
    //FIXME: Reference thread/desktop instead
@@ -1431,8 +1507,8 @@
 
    /* Create the window object. */
    Window = (PWINDOW_OBJECT)
-            ObmCreateObject(&gHandleTable, (PHANDLE)&hWnd,
-                            otWindow, sizeof(WINDOW_OBJECT) + Class->cbWndExtra
+            ObmCreateObject(gHandleTable, (PHANDLE)&hWnd,
+                            otWindow, sizeof(WINDOW_OBJECT) + Class->WndExtra
                            );
 
    DPRINT("Created object with handle %X\n", hWnd);
@@ -1456,6 +1532,7 @@
    /*
     * Fill out the structure describing it.
     */
+   Window->ti = ti;
    Window->Class = Class;
    Window->SystemMenu = (HMENU)0;
    Window->ContextHelpId = 0;
@@ -1474,7 +1551,7 @@
    {
       IntSetMenu(Window, hMenu, &MenuChanged);
    }
-   
+
    Window->MessageQueue = PsGetWin32Thread()->MessageQueue;
    IntReferenceMessageQueue(Window->MessageQueue);
    Window->Parent = ParentWindow;
@@ -1491,27 +1568,38 @@
    }
    
    Window->UserData = 0;
-   
-   if ((((DWORD)Class->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000)
-         && (((DWORD)Class->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000))
-   {
-      Window->Unicode = bUnicodeWindow;
+
+   Window->IsSystem = Class->System;
+   if (Class->System)
+   {
+       Window->Unicode = bUnicodeWindow;
+       if (bUnicodeWindow)
+       {
+           Window->WndProc = Class->WndProc;
+           Window->WndProcExtra = Class->WndProcExtra;
+       }
+       else
+       {
+           Window->WndProc = Class->WndProcExtra;
+           Window->WndProcExtra = Class->WndProc;
+       }
    }
    else
    {
-      Window->Unicode = Class->Unicode;
-   }
-   Window->WndProcA = Class->lpfnWndProcA;
-   Window->WndProcW = Class->lpfnWndProcW;
+       Window->Unicode = Class->Unicode;
+       Window->WndProc = Class->WndProc;
+       Window->CallProc = NULL;
+   }
+
    Window->OwnerThread = PsGetCurrentThread();
    Window->FirstChild = NULL;
    Window->LastChild = NULL;
    Window->PrevSibling = NULL;
    Window->NextSibling = NULL;
-   Window->ExtraDataSize = Class->cbWndExtra;
+   Window->ExtraDataSize = Class->WndExtra;
 
    /* extra window data */
-   if (Class->cbWndExtra)
+   if (Class->WndExtra)
       Window->ExtraData = (PCHAR)(Window + 1);
 
    InitializeListHead(&Window->PropListHead);
@@ -1535,7 +1623,6 @@
    {
       RtlInitUnicodeString(&Window->WindowName, NULL);
    }
-
 
    /*
     * This has been tested for WS_CHILD | WS_VISIBLE.  It has not been
@@ -1931,7 +2018,15 @@
 CLEANUP:
    if (Window) UserDerefObjectCo(Window);
    if (ParentWindow) UserDerefObjectCo(ParentWindow);
-   if (!_ret_ && Class) ClassDerefObject(Class); /* only deref if failure (return 0) */
+   if (!_ret_ && ti != NULL)
+   {
+       if (Class != NULL)
+       {
+           IntDereferenceClass(Class,
+                               ti->Desktop,
+                               ti->kpi);
+       }
+   }
    END_CLEANUP;
 }
 
@@ -1967,7 +2062,7 @@
       SetLastNtError(Status);
       RETURN( NULL);
    }
-   if (! IS_ATOM(ClassName.Buffer))
+   if (ClassName.Length != 0)
    {
       Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
       if (! NT_SUCCESS(Status))
@@ -1975,6 +2070,11 @@
          SetLastNtError(Status);
          RETURN( NULL);
       }
+   }
+   else if (! IS_INTRESOURCE(ClassName.Buffer))
+   {
+       SetLastWin32Error(ERROR_INVALID_PARAMETER);
+       return NULL;
    }
 
    /* safely copy the window name */
@@ -3254,10 +3354,8 @@
             break;
 
          case GWL_WNDPROC:
-            if (Ansi)
-               Result = (LONG) Window->WndProcA;
-            else
-               Result = (LONG) Window->WndProcW;
+            Result = (LONG)IntGetWindowProc(Window,
+                                            Ansi);
             break;
 
          case GWL_HINSTANCE:
@@ -3390,22 +3488,28 @@
             break;
 
          case GWL_WNDPROC:
+         {
             /* FIXME: should check if window belongs to current process */
-            if (Ansi)
+            if (Window->IsSystem)
             {
-               OldValue = (LONG) Window->WndProcA;
-               Window->WndProcA = (WNDPROC) NewValue;
-               Window->WndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,FALSE);
-               Window->Unicode = FALSE;
+               /* the user changes the window procedure, the window is no longer
+                  directly derived from the system class, because it no longer
+                  uses independent window procedures for ansi and unicode */
+               Window->IsSystem = FALSE;
+               Window->CallProc = NULL;
             }
-            else
+
+            /* update the window procedure */
+            OldValue = (LONG)Window->WndProc;
+            Window->WndProc = (WNDPROC)NewValue;
+            if (Window->CallProc != NULL)
             {
-               OldValue = (LONG) Window->WndProcW;
-               Window->WndProcW = (WNDPROC) NewValue;
-               Window->WndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)NewValue,TRUE);
-               Window->Unicode = TRUE;
+                Window->CallProc->WndProc = (WNDPROC)NewValue;
+                Window->CallProc->Unicode = !Ansi;
             }
+            Window->Unicode = !Ansi;
             break;
+         }
 
          case GWL_HINSTANCE:
             OldValue = (LONG) Window->Instance;
@@ -4404,99 +4508,6 @@
    END_CLEANUP;
 }
 
-DWORD STDCALL
-NtUserDereferenceWndProcHandle(WNDPROC wpHandle, WndProcHandle *Data)
-{
-   DECLARE_RETURN(DWORD);
-   WndProcHandle Entry;
-
-   DPRINT("Enter NtUserDereferenceWndProcHandle\n");
-   UserEnterShared();
-
-   if (((DWORD)wpHandle & 0xFFFF0000) == 0xFFFF0000)
-   {
-      Entry = WndProcHandlesArray[(DWORD)wpHandle & 0x0000FFFF];
-      Data->WindowProc = Entry.WindowProc;
-      Data->IsUnicode = Entry.IsUnicode;
-      Data->ProcessID = Entry.ProcessID;
-      RETURN(  TRUE);
-   }
-   else
-   {
-      RETURN(  FALSE);
-   }
-   RETURN( FALSE);
-
-CLEANUP:
-   DPRINT("Leave NtUserDereferenceWndProcHandle, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-DWORD
-IntAddWndProcHandle(WNDPROC WindowProc, BOOL IsUnicode)
-{
-   WORD i;
-   WORD FreeSpot = 0;
-   BOOL found;
-   WndProcHandle *OldArray;
-   WORD OldArraySize;
-   found = FALSE;
-   for (i = 0;i < WndProcHandlesArraySize;i++)
-   {
-      if (WndProcHandlesArray[i].WindowProc == NULL)
-      {
-         FreeSpot = i;
-         found = TRUE;
-      }
-   }
-   if (!found)
-   {
-      OldArray = WndProcHandlesArray;
-      OldArraySize = WndProcHandlesArraySize;
-      WndProcHandlesArray = ExAllocatePoolWithTag(PagedPool,(OldArraySize + WPH_SIZE) * sizeof(WndProcHandle), TAG_WINPROCLST);
-      WndProcHandlesArraySize = OldArraySize + WPH_SIZE;
-      RtlCopyMemory(WndProcHandlesArray,OldArray,OldArraySize * sizeof(WndProcHandle));
-      ExFreePool(OldArray);
-      FreeSpot = OldArraySize + 1;
-   }
-   WndProcHandlesArray[FreeSpot].WindowProc = WindowProc;
-   WndProcHandlesArray[FreeSpot].IsUnicode = IsUnicode;
-   WndProcHandlesArray[FreeSpot].ProcessID = PsGetCurrentProcessId();
-   return FreeSpot + 0xFFFF0000;
-}
-
-DWORD
-IntRemoveWndProcHandle(WNDPROC Handle)
-{
-   WORD position;
-   position = (DWORD)Handle & 0x0000FFFF;
-   if (position > WndProcHandlesArraySize)
-   {
-      return FALSE;
-   }
-   WndProcHandlesArray[position].WindowProc = NULL;
-   WndProcHandlesArray[position].IsUnicode = FALSE;
-   WndProcHandlesArray[position].ProcessID = NULL;
-   return TRUE;
-}
-
-DWORD
-IntRemoveProcessWndProcHandles(HANDLE ProcessID)
-{
-   WORD i;
-   for (i = 0;i < WndProcHandlesArraySize;i++)
-   {
-      if (WndProcHandlesArray[i].ProcessID == ProcessID)
-      {
-         WndProcHandlesArray[i].WindowProc = NULL;
-         WndProcHandlesArray[i].IsUnicode = FALSE;
-         WndProcHandlesArray[i].ProcessID = NULL;
-      }
-   }
-   return TRUE;
-}
-
 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
 
 BOOL

Modified: trunk/reactos/subsystems/win32/win32k/w32k.h
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/w32k.h?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/w32k.h (original)
+++ trunk/reactos/subsystems/win32/win32k/w32k.h Wed Apr  5 12:05:55 2006
@@ -1,3 +1,5 @@
+#ifndef __W32K_H
+#define __W32K_H
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Graphics Subsystem
@@ -68,3 +70,77 @@
 #define M_PI_2 1.57079632679489661923
 #endif
 
+/* User heap */
+extern HANDLE GlobalUserHeap;
+
+HANDLE
+UserCreateHeap(OUT PSECTION_OBJECT *SectionObject,
+               IN OUT PVOID *SystemBase,
+               IN ULONG HeapSize);
+
+static __inline PVOID
+UserHeapAlloc(SIZE_T Bytes)
+{
+    return RtlAllocateHeap(GlobalUserHeap,
+                           HEAP_NO_SERIALIZE,
+                           Bytes);
+}
+
+static __inline BOOL
+UserHeapFree(PVOID lpMem)
+{
+    return RtlFreeHeap(GlobalUserHeap,
+                       HEAP_NO_SERIALIZE,
+                       lpMem);
+}
+
+static __inline PVOID
+UserHeapReAlloc(PVOID lpMem,
+                SIZE_T Bytes)
+{
+#if 0
+    /* NOTE: ntoskrnl doesn't export RtlReAllocateHeap... */
+    return RtlReAllocateHeap(GlobalUserHeap,
+                             HEAP_NO_SERIALIZE,
+                             lpMem,
+                             Bytes);
+#else
+    SIZE_T PrevSize;
+    PVOID pNew;
+
+    PrevSize = RtlSizeHeap(GlobalUserHeap,
+                           HEAP_NO_SERIALIZE,
+                           lpMem);
+
+    if (PrevSize == Bytes)
+        return lpMem;
+
+    pNew = RtlAllocateHeap(GlobalUserHeap,
+                           HEAP_NO_SERIALIZE,
+                           Bytes);
+    if (pNew != NULL)
+    {
+        if (PrevSize < Bytes)
+            Bytes = PrevSize;
+
+        RtlCopyMemory(pNew,
+                      lpMem,
+                      Bytes);
+
+        RtlFreeHeap(GlobalUserHeap,
+                    HEAP_NO_SERIALIZE,
+                    lpMem);
+    }
+
+    return pNew;
+#endif
+}
+
+static __inline PVOID
+UserHeapAddressToUser(PVOID lpMem)
+{
+    return (PVOID)(((ULONG_PTR)lpMem - (ULONG_PTR)GlobalUserHeap) +
+                   (ULONG_PTR)PsGetWin32Process()->HeapMappings.UserMapping);
+}
+
+#endif /* __W32K_H */

Modified: trunk/reactos/subsystems/win32/win32k/win32k.rbuild
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/win32k.rbuild?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/win32k.rbuild (original)
+++ trunk/reactos/subsystems/win32/win32k/win32k.rbuild Wed Apr  5 12:05:55 2006
@@ -64,14 +64,15 @@
 			<file>err.c</file>
 			<file>math.c</file>
 			<file>copy.c</file>
+			<file>usrheap.c</file>
 		</compilationunit>
 		<directory name="i386">
-		<file>cos_asm.s</file>
-		<file>sin_asm.s</file>
-		<file>atan2_asm.s</file>
-		<file>floor_asm.s</file>
-		<file>ceil_asm.s</file>
-        </directory>
+			<file>cos_asm.s</file>
+			<file>sin_asm.s</file>
+			<file>atan2_asm.s</file>
+			<file>floor_asm.s</file>
+			<file>ceil_asm.s</file>
+	        </directory>
 	</directory>
 	<directory name="ntddraw">
 		<compilationunit name="ntddraw.c">

Modified: trunk/reactos/tools/nci/w32ksvc.db
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/tools/nci/w32ksvc.db?rev=21460&r1=21459&r2=21460&view=diff
==============================================================================
--- trunk/reactos/tools/nci/w32ksvc.db (original)
+++ trunk/reactos/tools/nci/w32ksvc.db Wed Apr  5 12:05:55 2006
@@ -356,7 +356,7 @@
 NtUserGetCapture			0
 NtUserGetCaretBlinkTime                 0
 NtUserGetCaretPos                       1
-NtUserGetClassInfo                      5
+NtUserGetClassInfo                      4
 NtUserGetClassLong			3
 NtUserGetClassName                      3
 NtUserGetClientOrigin			2
@@ -457,7 +457,7 @@
 NtUserReleaseDC				2
 NtUserRealChildWindowFromPoint          3
 NtUserRedrawWindow                      4
-NtUserRegisterClassExWOW                8
+NtUserRegisterClassEx                   6
 NtUserRegisterHotKey                    4
 NtUserRegisterTasklist                  1
 NtUserRegisterWindowMessage             1
@@ -536,7 +536,7 @@
 NtUserUnhookWinEvent                    1
 NtUserUnloadKeyboardLayout              1
 NtUserUnlockWindowStation               1
-NtUserUnregisterClass                   3
+NtUserUnregisterClass                   2
 NtUserUnregisterHotKey                  2
 NtUserUpdateInputContext                3
 NtUserUpdateInstance                    3





More information about the Ros-diffs mailing list