Index: subsystems/win32/csrss/csrsrv/api/wapi.c
===================================================================
--- subsystems/win32/csrss/csrsrv/api/wapi.c	(revision 48973)
+++ subsystems/win32/csrss/csrsrv/api/wapi.c	(working copy)
@@ -195,14 +195,18 @@
     return Status;
 }
 
+FARPROC CsrClientThreadSetup = NULL;
+
 PCSR_THREAD
 NTAPI
 CsrConnectToUser(VOID)
 {
     PTEB Teb = NtCurrentTeb();
     PCSR_THREAD CsrThread;
-#if 0
-    NTSTATUS Status;
+
+    DPRINT("CsrConnectToUser\n");
+
+    NTSTATUS Status = STATUS_SUCCESS;
     ANSI_STRING DllName;
     UNICODE_STRING TempName;
     HANDLE hUser32;
@@ -212,7 +216,7 @@
     if (!CsrClientThreadSetup)
     {
         /* Get the DLL Handle for user32.dll */
-        RtlInitAnsiString(&DllName, "user32");
+        RtlInitAnsiString(&DllName, "user32.dll");
         RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
         Status = LdrGetDllHandle(NULL,
                                  NULL,
@@ -220,7 +224,7 @@
                                  &hUser32);
         RtlFreeUnicodeString(&TempName);
 
-        /* If we got teh handle, get the Client Thread Startup Entrypoint */
+        /* If we got the handle, get the Client Thread Startup Entrypoint */
         if (NT_SUCCESS(Status))
         {
             RtlInitAnsiString(&StartupName,"ClientThreadSetup");
@@ -232,8 +236,16 @@
     }
 
     /* Connect to user32 */
-    CsrClientThreadSetup();
-#endif
+    if (NT_SUCCESS(Status))
+    {
+       DPRINT("User32.DLL loaded!\n");
+       CsrClientThreadSetup();
+    }
+    else
+    {
+       DPRINT("User32.DLL did not load!\n");
+    }
+
     /* Save pointer to this thread in TEB */
     CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
     if (CsrThread) Teb->CsrClientThread = CsrThread;
Index: subsystems/win32/csrss/win32csr/dllmain.c
===================================================================
--- subsystems/win32/csrss/win32csr/dllmain.c	(revision 48964)
+++ subsystems/win32/csrss/win32csr/dllmain.c	(working copy)
@@ -162,6 +162,8 @@
     CsrExports = *Exports;
     Win32CsrApiHeap = CsrssApiHeap;
 
+    DPRINT("Win32CsrInitialization\n");
+
     Status = NtUserInitialize(0, NULL, NULL);
 
     PrivateCsrssManualGuiCheck(0);
Index: subsystems/win32/win32k/ntuser/ntstubs.c
===================================================================
--- subsystems/win32/win32k/ntuser/ntstubs.c	(revision 48970)
+++ subsystems/win32/win32k/ntuser/ntstubs.c	(working copy)
@@ -881,6 +881,16 @@
      UserEnterShared();
      GetW32ThreadInfo();
      W32Process = PsGetCurrentProcessWin32Process();
+
+     /* This needs to be called from CsrProcess. */
+     if (CsrProcess == PsGetCurrentProcess())
+     {
+       DPRINT("Same CsrProcess! CsrProcess: 0x%x\n", CsrProcess);
+     }
+     else
+     {
+       DPRINT("Not CsrProcess! CsrProcess: 0x%x CurProc: 0x%x\n",CsrProcess, PsGetCurrentProcess());
+     }
      _SEH2_TRY
      {
         pUserConnect->siClient.psi = gpsi;
Index: subsystems/win32/win32k/ntuser/ntuser.c
===================================================================
--- subsystems/win32/win32k/ntuser/ntuser.c	(revision 48964)
+++ subsystems/win32/win32k/ntuser/ntuser.c	(working copy)
@@ -18,9 +18,11 @@
 
 /* GLOBALS *******************************************************************/
 
+PTHREADINFO gptiCurrent = NULL;
 ERESOURCE UserLock;
 ATOM AtomMessage; // Window Message atom.
 ATOM AtomWndObj;  // Window Object atom.
+ATOM AtomLayer;   // Window Layer atom.
 BOOL gbInitialized;
 HINSTANCE hModClient = NULL;
 BOOL ClientPfnInit = FALSE;
@@ -47,6 +49,7 @@
   gpsi->atomContextHelpIdProp = IntAddGlobalAtom(L"SysCH", TRUE);
 
   AtomWndObj = IntAddGlobalAtom(L"SysWNDO", TRUE);
+  AtomLayer = IntAddGlobalAtom(L"SysLayer", TRUE);
 
   return STATUS_SUCCESS;
 }
@@ -97,7 +100,16 @@
   HANDLE  hPowerRequestEvent,
   HANDLE  hMediaRequestEvent)
 {
+    PPROCESSINFO ppi;
+
+    CsrInit(); // 1
+
 // Set W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)
+
+    ppi = PsGetProcessWin32Process(CsrProcess);
+    /* TODO: DPI aware is not supported. */
+    ppi->W32PF_flags |= (W32PF_DPIAWARE|W32PF_READSCREENACCESSGRANTED|W32PF_IOWINSTA);
+
 // Create Object Directory,,, Looks like create workstation. "\\Windows\\WindowStations"
 // Create Event for Diconnect Desktop.
 // Initialize Video.
@@ -110,25 +122,26 @@
 // Create ThreadInfo for this Thread!
 // {
 
-    GetW32ThreadInfo();
-   
+    GetW32ThreadInfo(); // 2
+
+    NtUserUpdatePerUserSystemParameters(0, TRUE); // 3
+
 //    Callback to User32 Client Thread Setup
 
-    co_IntClientThreadSetup();
+    if (!NT_SUCCESS(co_IntClientThreadSetup())) // 4
+    {
+       DPRINT1("Error Client Thread Setup.\n");
+    }
 
 // }
 // Set Global SERVERINFO Error flags.
 // Load Resources.
 
-    NtUserUpdatePerUserSystemParameters(0, TRUE);
-
-    CsrInit();
-
     return STATUS_SUCCESS;
 }
 
 /*
-    Called from win32csr.
+    Called from win32csr:Win32CsrInitialization.
  */
 NTSTATUS
 APIENTRY
@@ -209,6 +222,7 @@
 {
    KeEnterCriticalRegion();
    ExAcquireResourceExclusiveLite(&UserLock, TRUE);
+   gptiCurrent = PsGetCurrentThreadWin32Thread();
 }
 
 VOID FASTCALL UserLeave(VOID)
Index: subsystems/win32/win32k/include/ntuser.h
===================================================================
--- subsystems/win32/win32k/include/ntuser.h	(revision 48964)
+++ subsystems/win32/win32k/include/ntuser.h	(working copy)
@@ -10,6 +10,7 @@
 #define UserLeaveCo UserLeave
 
 extern PSERVERINFO gpsi;
+extern PTHREADINFO gptiCurrent;
 
 NTSTATUS FASTCALL InitUserImpl(VOID);
 VOID FASTCALL CleanupUserImpl(VOID);
Index: dll/win32/user32/misc/stubs.c
===================================================================
--- dll/win32/user32/misc/stubs.c	(revision 48964)
+++ dll/win32/user32/misc/stubs.c	(working copy)
@@ -244,17 +244,6 @@
 /*
  * @unimplemented
  */
-BOOL
-WINAPI
-ClientThreadSetup ( VOID )
-{
-  UNIMPLEMENTED;
-  return FALSE;
-}
-
-/*
- * @unimplemented
- */
 UINT
 WINAPI
 GetRawInputDeviceInfoW(
Index: dll/win32/user32/misc/dllmain.c
===================================================================
--- dll/win32/user32/misc/dllmain.c	(revision 48964)
+++ dll/win32/user32/misc/dllmain.c	(working copy)
@@ -238,6 +238,11 @@
    KernelCallbackTable[USER32_CALLBACK_CLIENTTHREADSTARTUP] =
       (PVOID)User32CallClientThreadSetupFromKernel;
 
+   if (!gpsi && !g_ppi)
+   { 
+//      ERR("User DllMain Running!\n");
+  // Never called from CsrProcess or it seems not called!
+ 
    NtUserProcessConnect( NtCurrentProcess(),
                          &UserCon,
                          sizeof(USERCONNECT));
@@ -252,6 +257,7 @@
    gfServerProcess = TRUE; // FIXME HAX! Used in CsrClientConnectToServer(,,,,&gfServerProcess);
 
    //ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", UserCon.siClient.psi, UserCon.siClient.aheList,  g_ulSharedDelta);
+   }
 
    /* Allocate an index for user32 thread local data. */
    User32TlsIndex = TlsAlloc();
@@ -340,33 +346,38 @@
 FASTCALL
 GetConnected(VOID)
 {
-  USERCONNECT UserCon;
 //  ERR("GetConnected\n");
 
   if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo == NULL)
      NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
+  return;  
+}
 
-  if (gpsi && g_ppi) return;
-// FIXME HAX: Due to the "Dll Initialization Bug" we have to call this too.
-  GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+ClientThreadSetup ( VOID )
+{
+  // Always called from CsrProcess server!
+  // DllMain is called before ClientThreadSetup or the win32k callback.
+//  ERR("ClientThreadSetup\n");
 
-  NtUserProcessConnect( NtCurrentProcess(),
-                         &UserCon,
-                         sizeof(USERCONNECT));
-
-  g_ppi = GetWin32ClientInfo()->ppi;
-  g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
-  gpsi = SharedPtrToUser(UserCon.siClient.psi);
-  gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
-  gHandleEntries = SharedPtrToUser(gHandleTable->handles);  
-  
+  if (gpsi && g_ppi)
+  {
+//     ERR("Already Setup!\n");
+     return TRUE;
+  }
+  return TRUE;
 }
 
 NTSTATUS
 WINAPI
 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength)
 {
-  ERR("GetConnected\n");
+//  ERR("Win32k Call GetConnected\n");
+  ClientThreadSetup();
   return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);  
 }
 
