- Merge 25404-25406, very small part of 25407, 25409, 25410, 25412+25414, 25422-25426.
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / misc.c
index 7fbed7e..ec20f50 100644 (file)
 
 #include <w32k.h>
 
-//#define NDEBUG
-#undef NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 /* registered Logon process */
 PW32PROCESS LogonProcess = NULL;
 
-VOID W32kRegisterPrimitiveMessageQueue(VOID)
-{
-   extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
-   if( !pmPrimitiveMessageQueue )
-   {
-      PW32THREAD pThread;
-      pThread = PsGetWin32Thread();
-      if( pThread && pThread->MessageQueue )
-      {
-         pmPrimitiveMessageQueue = pThread->MessageQueue;
-         IntReferenceMessageQueue(pmPrimitiveMessageQueue);
-         DPRINT( "Installed primitive input queue.\n" );
-      }
-   }
-   else
-   {
-      DPRINT1( "Alert! Someone is trying to steal the primitive queue.\n" );
-   }
-}
-
-VOID W32kUnregisterPrimitiveMessageQueue(VOID)
-{
-   extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
-   IntDereferenceMessageQueue(pmPrimitiveMessageQueue);
-   pmPrimitiveMessageQueue = NULL;
-}
-
-PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue()
-{
-   extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
-   return pmPrimitiveMessageQueue;
-}
-
 BOOL FASTCALL
 co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
 {
@@ -120,11 +86,6 @@ NtUserCallNoParam(DWORD Routine)
 
    switch(Routine)
    {
-      case NOPARAM_ROUTINE_REGISTER_PRIMITIVE:
-         W32kRegisterPrimitiveMessageQueue();
-         Result = (DWORD)TRUE;
-         break;
-
       case NOPARAM_ROUTINE_DESTROY_CARET:
          Result = (DWORD)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
          break;
@@ -183,7 +144,7 @@ NtUserCallOneParam(
 
    if (Routine == ONEPARAM_ROUTINE_SHOWCURSOR)
    {
-      PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
+      PWINSTATION_OBJECT WinSta = PsGetCurrentThreadWin32Thread()->Desktop->WindowStation;
       PSYSTEM_CURSORINFO CurInfo;
                  
       HDC Screen;
@@ -417,7 +378,7 @@ NtUserCallOneParam(
       case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
          {
             BOOL Enable;
-            PW32PROCESS Process = PsGetWin32Process();
+            PW32PROCESS Process = PsGetCurrentProcessWin32Process();
 
             if(Process != NULL)
             {
@@ -494,7 +455,7 @@ NtUserCallTwoParam(
          {
             DWORD Ret;
             RECT rcRect;
-            PWINDOW_OBJECT Window = UserGetWindowObject((HWND)Param1);
+            Window = UserGetWindowObject((HWND)Param1);
             if (!Window) RETURN(ERROR);
             
             Ret = (DWORD)IntGetWindowRgnBox(Window, &rcRect);
@@ -508,7 +469,7 @@ NtUserCallTwoParam(
          }
       case TWOPARAM_ROUTINE_GETWINDOWRGN:
          {
-            PWINDOW_OBJECT Window = UserGetWindowObject((HWND)Param1);
+            Window = UserGetWindowObject((HWND)Param1);
             if (!Window) RETURN(ERROR);
 
             RETURN( (DWORD)IntGetWindowRgn(Window, (HRGN)Param2));
@@ -568,7 +529,7 @@ NtUserCallTwoParam(
 
       case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
       {
-         PWINDOW_OBJECT Window = UserGetWindowObject((HWND)Param1);
+         Window = UserGetWindowObject((HWND)Param1);
          if (!Window) RETURN(0);
          
          RETURN( (DWORD)IntShowOwnedPopups(Window, (BOOL) Param2));
@@ -577,19 +538,18 @@ NtUserCallTwoParam(
       case TWOPARAM_ROUTINE_ROS_SHOWWINDOW:
          {
 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
-            PWINDOW_OBJECT Window;
             DPRINT1("ROS_SHOWWINDOW\n");
             
             if (!(Window = UserGetWindowObject((HWND)Param1)))
             {
-               RETURN( FALSE);
+               RETURN( );
             }
             
             if (Param2)
             {
                if (!(Window->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP))
                {
-                  RETURN( TRUE);
+                  RETURN( -1 );
                }
                Window->Flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
             }
@@ -597,8 +557,9 @@ NtUserCallTwoParam(
                Window->Flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
 
             DPRINT1("ROS_SHOWWINDOW ---> 0x%x\n",Window->Flags);
-            RETURN( TRUE);
+            RETURN( );
          }
+
       case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
          UNIMPLEMENTED
          RETURN( 0);
@@ -857,19 +818,11 @@ NtUserCallHwndOpt(
    switch (Routine)
    {
       case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
-         /*
-          * FIXME 
-          * Nothing too hard...validate the hWnd and save it in the Desktop Info
-          */
-         DPRINT1("HWNDOPT_ROUTINE_SETPROGMANWINDOW UNIMPLEMENTED\n");
+         GetW32ThreadInfo()->Desktop->hProgmanWindow = Param;
          break;
 
       case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
-         /*
-          * FIXME 
-          * Nothing too hard...validate the hWnd and save it in the Desktop Info
-          */
-         DPRINT1("HWNDOPT_ROUTINE_SETTASKMANWINDOW UNIMPLEMENTED\n");
+         GetW32ThreadInfo()->Desktop->hTaskManWindow = Param;
          break;
    }
 
@@ -886,12 +839,27 @@ NtUserGetThreadState(
    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());
+      case THREADSTATE_PROGMANWINDOW:
+         RETURN( (DWORD)GetW32ThreadInfo()->Desktop->hProgmanWindow);
+      case THREADSTATE_TASKMANWINDOW:
+         RETURN( (DWORD)GetW32ThreadInfo()->Desktop->hTaskManWindow);
    }
    RETURN( 0);
 
@@ -910,7 +878,7 @@ IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
    static LOGFONTW DefaultFont = {
                                     -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
                                     0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
-                                    L"Bitstream Vera Sans"
+                                    L"MS Sans Serif"
                                  };
 
    RtlZeroMemory(&QueryTable, sizeof(QueryTable));
@@ -941,10 +909,12 @@ IntSystemParametersInfo(
 {
    PWINSTATION_OBJECT WinStaObject;
    NTSTATUS Status;
+   BOOL bChanged = FALSE;
 
    static BOOL bInitialized = FALSE;
    static LOGFONTW IconFont;
    static NONCLIENTMETRICSW pMetrics;
+   static MINIMIZEDMETRICS MinimizedMetrics;
    static BOOL GradientCaptions = TRUE;
    static UINT FocusBorderHeight = 1;
    static UINT FocusBorderWidth = 1;
@@ -972,6 +942,12 @@ IntSystemParametersInfo(
       pMetrics.iMenuHeight = UserGetSystemMetrics(SM_CYMENUSIZE);
       pMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
 
+      MinimizedMetrics.cbSize = sizeof(MINIMIZEDMETRICS);
+      MinimizedMetrics.iWidth = UserGetSystemMetrics(SM_CXMINIMIZED);
+      MinimizedMetrics.iHorzGap = UserGetSystemMetrics(SM_CXMINSPACING);
+      MinimizedMetrics.iVertGap = UserGetSystemMetrics(SM_CYMINSPACING);
+      MinimizedMetrics.iArrange = ARW_HIDE;
+
       bInitialized = TRUE;
    }
 
@@ -981,7 +957,18 @@ IntSystemParametersInfo(
       case SPI_SETDOUBLECLKHEIGHT:
       case SPI_SETDOUBLECLICKTIME:
       case SPI_SETDESKWALLPAPER:
+      case SPI_SETSCREENSAVERRUNNING: 
+      case SPI_SETSCREENSAVETIMEOUT:
+      case SPI_SETFLATMENU:
+         /* We will change something, so set the flag here */
+         bChanged = TRUE;
       case SPI_GETDESKWALLPAPER:
+         case SPI_GETWHEELSCROLLLINES:
+         case SPI_GETWHEELSCROLLCHARS:
+         case SPI_GETSCREENSAVERRUNNING:
+         case SPI_GETSCREENSAVETIMEOUT:
+         case SPI_GETSCREENSAVEACTIVE:
+         case SPI_GETFLATMENU:
          {
             PSYSTEM_CURSORINFO CurInfo;
 
@@ -997,6 +984,44 @@ IntSystemParametersInfo(
 
             switch(uiAction)
             {
+                          case SPI_GETFLATMENU:
+                  ASSERT(pvParam);
+                  *((UINT*)pvParam) = WinStaObject->FlatMenu;
+                             break;
+               case SPI_SETFLATMENU:                              
+                  WinStaObject->FlatMenu = uiParam;
+                             break;
+                          case SPI_GETSCREENSAVETIMEOUT:
+                   ASSERT(pvParam);
+                   *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut;
+               break;
+               case SPI_SETSCREENSAVETIMEOUT:
+                  WinStaObject->ScreenSaverTimeOut = uiParam;
+                                 break;
+                          case SPI_GETSCREENSAVERRUNNING:
+                     if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
+                                 break;
+               case SPI_SETSCREENSAVERRUNNING:
+                                  if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
+                  WinStaObject->ScreenSaverRunning = uiParam;
+                                 break;
+                          case SPI_GETSCREENSAVEACTIVE:
+                                       /* FIXME: how to disable the screensaver? */
+                  ASSERT(pvParam);
+                  *((BOOL*)pvParam) = TRUE;
+                                 break;
+                          case SPI_GETWHEELSCROLLLINES:
+                  ASSERT(pvParam);
+                                   CurInfo = IntGetSysCursorInfo(WinStaObject);
+                  *((UINT*)pvParam) = CurInfo->WheelScroLines;
+                                       /* FIXME add this value to scroll list as scroll value ?? */
+                  break;
+               case SPI_GETWHEELSCROLLCHARS:
+                  ASSERT(pvParam);
+                                   CurInfo = IntGetSysCursorInfo(WinStaObject);
+                  *((UINT*)pvParam) = CurInfo->WheelScroChars;
+                                       // FIXME add this value to scroll list as scroll value ?? 
+                  break;
                case SPI_SETDOUBLECLKWIDTH:
                   CurInfo = IntGetSysCursorInfo(WinStaObject);
                   /* FIXME limit the maximum value? */
@@ -1052,7 +1077,7 @@ IntSystemParametersInfo(
                         BITMAPOBJ_UnlockBitmap(bmp);
 
                         /* change the bitmap's ownership */
-                        GDIOBJ_SetOwnership(hNewBitmap, NULL);
+                        GDIOBJ_SetOwnership(GdiHandleTable, hNewBitmap, NULL);
                      }
                      hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
                      if(hOldBitmap != NULL)
@@ -1102,7 +1127,7 @@ IntSystemParametersInfo(
                      if(!KeyValuePartialInfo)
                      {
                         NtClose(KeyHandle);
-                        return 0;
+                        return FALSE;
                      }
 
                      Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
@@ -1111,7 +1136,7 @@ IntSystemParametersInfo(
                      {
                         ZwClose(KeyHandle);
                         ExFreePool(KeyValuePartialInfo);
-                        return 0;
+                        return FALSE;
                      }
                 
                      Tile.Length = KeyValuePartialInfo->DataLength;
@@ -1137,7 +1162,7 @@ IntSystemParametersInfo(
                      if(!KeyValuePartialInfo)
                      {
                         ZwClose(KeyHandle);
-                        return 0;
+                        return FALSE;
                      }
 
                      Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
@@ -1146,7 +1171,7 @@ IntSystemParametersInfo(
                      {
                         ZwClose(KeyHandle);
                         ExFreePool(KeyValuePartialInfo);
-                        return 0;
+                        return FALSE;
                      }
                 
                      Style.Length = KeyValuePartialInfo->DataLength;
@@ -1187,12 +1212,12 @@ IntSystemParametersInfo(
             /* FIXME save the value to the registry */
 
             ObDereferenceObject(WinStaObject);
-            return TRUE;
+            break;
          }
       case SPI_SETWORKAREA:
          {
             RECT *rc;
-            PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+            PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
 
             if(!Desktop)
             {
@@ -1203,12 +1228,13 @@ IntSystemParametersInfo(
             ASSERT(pvParam);
             rc = (RECT*)pvParam;
             Desktop->WorkArea = *rc;
+            bChanged = TRUE;
 
-            return TRUE;
+            break;
          }
       case SPI_GETWORKAREA:
          {
-            PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+            PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
 
             if(!Desktop)
             {
@@ -1219,13 +1245,14 @@ IntSystemParametersInfo(
             ASSERT(pvParam);
             IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
 
-            return TRUE;
+            break;
          }
       case SPI_SETGRADIENTCAPTIONS:
          {
             GradientCaptions = (pvParam != NULL);
             /* FIXME - should be checked if the color depth is higher than 8bpp? */
-            return TRUE;
+            bChanged = TRUE;
+            break;
          }
       case SPI_GETGRADIENTCAPTIONS:
          {
@@ -1233,60 +1260,83 @@ IntSystemParametersInfo(
             BOOL Ret = GradientCaptions;
 
             hDC = IntGetScreenDC();
-            if(hDC)
+            if(!hDC)
             {
+               return FALSE;
+            }
                Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
 
                ASSERT(pvParam);
                *((PBOOL)pvParam) = Ret;
-               return TRUE;
+            break;
             }
-            return FALSE;
-         }
       case SPI_SETFONTSMOOTHING:
          {
             IntEnableFontRendering(uiParam != 0);
-            return TRUE;
+            bChanged = TRUE;
+            break;
          }
       case SPI_GETFONTSMOOTHING:
          {
             ASSERT(pvParam);
             *((BOOL*)pvParam) = IntIsFontRenderingEnabled();
-            return TRUE;
+            break;
          }
       case SPI_GETICONTITLELOGFONT:
          {
             ASSERT(pvParam);
             *((LOGFONTW*)pvParam) = IconFont;
-            return TRUE;
+            break;
          }
       case SPI_GETNONCLIENTMETRICS:
          {
             ASSERT(pvParam);
             *((NONCLIENTMETRICSW*)pvParam) = pMetrics;
-            return TRUE;
+            break;
+         }
+      case SPI_SETNONCLIENTMETRICS:
+         {
+            ASSERT(pvParam);
+            pMetrics = *((NONCLIENTMETRICSW*)pvParam);
+            bChanged = TRUE;
+            break;
+         }
+      case SPI_GETMINIMIZEDMETRICS:
+         {
+            ASSERT(pvParam);
+            *((MINIMIZEDMETRICS*)pvParam) = MinimizedMetrics;
+            break;
+         }
+      case SPI_SETMINIMIZEDMETRICS:
+         {
+            ASSERT(pvParam);
+            MinimizedMetrics = *((MINIMIZEDMETRICS*)pvParam);
+            bChanged = TRUE;
+            break;
          }
       case SPI_GETFOCUSBORDERHEIGHT:
          {
             ASSERT(pvParam);
             *((UINT*)pvParam) = FocusBorderHeight;
-            return TRUE;
+            break;
          }
       case SPI_GETFOCUSBORDERWIDTH:
          {
             ASSERT(pvParam);
             *((UINT*)pvParam) = FocusBorderWidth;
-            return TRUE;
+            break;
          }
       case SPI_SETFOCUSBORDERHEIGHT:
          {
             FocusBorderHeight = (UINT)pvParam;
-            return TRUE;
+            bChanged = TRUE;
+            break;
          }
       case SPI_SETFOCUSBORDERWIDTH:
          {
             FocusBorderWidth = (UINT)pvParam;
-            return TRUE;
+            bChanged = TRUE;
+            break;
          }
 
       default:
@@ -1296,7 +1346,18 @@ IntSystemParametersInfo(
             return FALSE;
          }
    }
-   return FALSE;
+   /* Did we change something ? */
+   if (bChanged)
+   {
+      /* Shall we send a WM_SETTINGCHANGE message ? */
+      if (fWinIni & (SPIF_UPDATEINIFILE | SPIF_SENDCHANGE))
+      {
+         /* Broadcast WM_SETTINGCHANGE to all toplevel windows */
+         /* FIXME: lParam should be pointer to a string containing the reg key */
+         UserPostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)uiAction, 0);
+}
+   }
+   return TRUE;
 }
 
 /*
@@ -1355,6 +1416,15 @@ UserSystemParametersInfo(
       case SPI_GETGRADIENTCAPTIONS:
       case SPI_GETFOCUSBORDERHEIGHT:
       case SPI_GETFOCUSBORDERWIDTH:
+         case SPI_GETWHEELSCROLLLINES:
+      case SPI_GETWHEELSCROLLCHARS:
+         case SPI_GETSCREENSAVERRUNNING:
+         case SPI_SETSCREENSAVERRUNNING:
+         case SPI_GETSCREENSAVETIMEOUT:
+         case SPI_SETSCREENSAVETIMEOUT:
+         case SPI_GETSCREENSAVEACTIVE:
+         case SPI_GETFLATMENU:
+      case SPI_SETFLATMENU:
          {
             BOOL Ret;
 
@@ -1420,10 +1490,11 @@ UserSystemParametersInfo(
             return( TRUE);
          }
       case SPI_GETNONCLIENTMETRICS:
+      case SPI_SETNONCLIENTMETRICS:
          {
             NONCLIENTMETRICSW metrics;
 
-            Status = MmCopyFromCaller(&metrics.cbSize, pvParam, sizeof(UINT));
+            Status = MmCopyFromCaller(&metrics, pvParam, sizeof(NONCLIENTMETRICSW));
             if(!NT_SUCCESS(Status))
             {
                SetLastNtError(Status);
@@ -1440,7 +1511,36 @@ UserSystemParametersInfo(
                return( FALSE);
             }
 
-            Status = MmCopyToCaller(pvParam, &metrics.cbSize, sizeof(NONCLIENTMETRICSW));
+            Status = MmCopyToCaller(pvParam, &metrics, sizeof(NONCLIENTMETRICSW));
+            if(!NT_SUCCESS(Status))
+            {
+               SetLastNtError(Status);
+               return( FALSE);
+            }
+            return( TRUE);
+         }
+      case SPI_GETMINIMIZEDMETRICS:
+      case SPI_SETMINIMIZEDMETRICS:
+         {
+            MINIMIZEDMETRICS minimetrics;
+
+            Status = MmCopyFromCaller(&minimetrics, pvParam, sizeof(MINIMIZEDMETRICS));
+            if(!NT_SUCCESS(Status))
+            {
+               SetLastNtError(Status);
+               return( FALSE);
+            }
+            if(minimetrics.cbSize != sizeof(MINIMIZEDMETRICS))
+            {
+               SetLastWin32Error(ERROR_INVALID_PARAMETER);
+               return( FALSE);
+            }
+            if(!IntSystemParametersInfo(uiAction, uiParam, &minimetrics, fWinIni))
+            {
+               return( FALSE);
+            }
+
+            Status = MmCopyToCaller(pvParam, &minimetrics, sizeof(MINIMIZEDMETRICS));
             if(!NT_SUCCESS(Status))
             {
                SetLastNtError(Status);
@@ -1448,6 +1548,11 @@ UserSystemParametersInfo(
             }
             return( TRUE);
          }
+      default :
+                 {
+              DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction );
+                         break;
+                 }
    }
    return( FALSE);
 }
@@ -1829,4 +1934,106 @@ CLEANUP:
    END_CLEANUP;
 }
 
+PW32PROCESSINFO
+GetW32ProcessInfo(VOID)
+{
+    PW32PROCESSINFO pi;
+    PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
+
+    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 = PsGetCurrentThreadWin32Thread();
+
+    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 */