- Silence some debug messages
[reactos.git] / reactos / subsys / win32k / ntuser / misc.c
index c2195cc..4bc6d4e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.69 2004/05/02 17:25:21 weiden Exp $
+/* $Id$
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -8,30 +8,8 @@
  * REVISION HISTORY:
  *       2003/05/22  Created
  */
-#define __WIN32K__
-#include <ddk/ntddk.h>
-#include <ddk/ntddmou.h>
-#include <win32k/win32k.h>
-#include <win32k/dc.h>
-#include <internal/safe.h>
-#include <include/error.h>
-#include <include/window.h>
-#include <include/menu.h>
-#include <include/painting.h>
-#include <include/dce.h>
-#include <include/inteng.h>
-#include <include/input.h>
-#include <include/intgdi.h>
-#include <include/mouse.h>
-#include <include/winsta.h>
-#include <include/caret.h>
-#include <include/object.h>
-#include <include/focus.h>
-#include <include/clipboard.h>
-#include <include/msgqueue.h>
-#include <include/desktop.h>
-#include <include/text.h>
-#include <include/tags.h>
+
+#include <w32k.h>
 
 #define NDEBUG
 #include <debug.h>
 /* registered Logon process */
 PW32PROCESS LogonProcess = NULL;
 
-/* FIXME - not yet defined in w32api :( */
-#define SPI_GETFOCUSBORDERWIDTH        (8206)
-#define SPI_SETFOCUSBORDERWIDTH        (8207)
-#define SPI_GETFOCUSBORDERHEIGHT       (8208)
-#define SPI_SETFOCUSBORDERHEIGHT       (8209)
-
-void W32kRegisterPrimitiveMessageQueue() {
+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" );
   }
 }
 
-PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue() {
+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
-IntRegisterLogonProcess(HANDLE hProcess, BOOL x)
+IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
 {
   PEPROCESS Process;
   NTSTATUS Status;
-  
-  if(LogonProcess != NULL && LogonProcess != PsGetWin32Process())
+  CSR_API_MESSAGE Request;
+
+  Status = PsLookupProcessByProcessId(ProcessId,
+                                     &Process);
+  if (!NT_SUCCESS(Status))
   {
-    SetLastWin32Error(ERROR_ACCESS_DENIED);
+    SetLastWin32Error(RtlNtStatusToDosError(Status));
     return FALSE;
   }
-  
-  if(hProcess)
+
+  if (Register)
   {
-    Status = ObReferenceObjectByHandle(hProcess,
-                                       PROCESS_QUERY_INFORMATION,
-                                       PsProcessType,
-                                       ExGetPreviousMode(),
-                                       (PVOID*)&Process,
-                                       NULL);
-    if(!NT_SUCCESS(Status))
+    /* Register the logon process */
+    if (LogonProcess != NULL)
     {
-      SetLastNtError(Status);
-      return 0;
+      ObDereferenceObject(Process);
+      return FALSE;
     }
-  
-    LogonProcess = Process->Win32Process;
-    ObDereferenceObject(Process);
+
+    LogonProcess = (PW32PROCESS)Process->Win32Process;
   }
   else
   {
-    /* deregister the logon process */
+    /* Deregister the logon process */
+    if (LogonProcess != (PW32PROCESS)Process->Win32Process)
+    {
+      ObDereferenceObject(Process);
+      return FALSE;
+    }
+
     LogonProcess = NULL;
   }
+
+  ObDereferenceObject(Process);
+
+  Request.Type = MAKE_CSR_API(REGISTER_LOGON_PROCESS, CSR_GUI);
+  Request.Data.RegisterLogonProcessRequest.ProcessId = ProcessId;
+  Request.Data.RegisterLogonProcessRequest.Register = Register;
+
+  Status = CsrNotify(&Request);
+  if (! NT_SUCCESS(Status))
+  {
+    DPRINT1("Failed to register logon process with CSRSS\n");
+    return FALSE;
+  }
+
   return TRUE;
 }
 
@@ -116,11 +115,11 @@ NtUserCallNoParam(DWORD Routine)
       W32kRegisterPrimitiveMessageQueue();
       Result = (DWORD)TRUE;
       break;
-    
+
     case NOPARAM_ROUTINE_DESTROY_CARET:
-      Result = (DWORD)IntDestroyCaret(PsGetCurrentThread()->Win32Thread);
+      Result = (DWORD)IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
       break;
-    
+
     case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
       Result = (DWORD)IntInitMessagePumpHook();
       break;
@@ -128,17 +127,24 @@ NtUserCallNoParam(DWORD Routine)
     case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
       Result = (DWORD)IntUninitMessagePumpHook();
       break;
-    
+
     case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO:
       Result = (DWORD)MsqGetMessageExtraInfo();
       break;
-    
+
     case NOPARAM_ROUTINE_ANYPOPUP:
       Result = (DWORD)IntAnyPopup();
       break;
-    
+
+    case NOPARAM_ROUTINE_CSRSS_INITIALIZED:
+      Result = (DWORD)CsrInit();
+      break;
+
+    case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
+      return (DWORD)IntMsqClearWakeMask();
+
     default:
-      DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n");
+      DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
       break;
   }
@@ -160,25 +166,25 @@ NtUserCallOneParam(
     {
       PWINDOW_OBJECT WindowObject;
       DWORD Result;
-      
+
       WindowObject = IntGetWindowObject((HWND)Param);
       if(!WindowObject)
       {
         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
         return FALSE;
       }
-      
+
       Result = (DWORD)WindowObject->IDMenu;
-      
+
       IntReleaseWindowObject(WindowObject);
       return Result;
     }
-      
+
     case ONEPARAM_ROUTINE_ISWINDOWUNICODE:
     {
       PWINDOW_OBJECT WindowObject;
       DWORD Result;
-      
+
       WindowObject = IntGetWindowObject((HWND)Param);
       if(!WindowObject)
       {
@@ -189,94 +195,95 @@ NtUserCallOneParam(
       IntReleaseWindowObject(WindowObject);
       return Result;
     }
-      
+
     case ONEPARAM_ROUTINE_WINDOWFROMDC:
       return (DWORD)IntWindowFromDC((HDC)Param);
-      
+
     case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID:
     {
       PWINDOW_OBJECT WindowObject;
       DWORD Result;
-      
+
       WindowObject = IntGetWindowObject((HWND)Param);
       if(!WindowObject)
       {
         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
         return FALSE;
       }
-      
+
       Result = WindowObject->ContextHelpId;
-      
+
       IntReleaseWindowObject(WindowObject);
       return Result;
     }
-    
+
     case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
     {
       PWINSTATION_OBJECT WinStaObject;
       NTSTATUS Status;
       DWORD Result;
-      
-      Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
+
+      Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
                                               KernelMode,
                                               0,
                                               &WinStaObject);
       if (!NT_SUCCESS(Status))
         return (DWORD)FALSE;
 
-      Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param);
+      /* FIXME
+      Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param); */
+      Result = 0;
 
       ObDereferenceObject(WinStaObject);
       return Result;
     }
-    
+
     case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
       return (DWORD)IntSwitchCaretShowing((PVOID)Param);
-    
+
     case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
       return (DWORD)IntSetCaretBlinkTime((UINT)Param);
 
     case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
       return (DWORD)IntEnumClipboardFormats((UINT)Param);
-    
+
     case ONEPARAM_ROUTINE_GETWINDOWINSTANCE:
     {
       PWINDOW_OBJECT WindowObject;
       DWORD Result;
-      
+
       if(!(WindowObject = IntGetWindowObject((HWND)Param)))
       {
         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
         return FALSE;
       }
-      
+
       Result = (DWORD)WindowObject->Instance;
       IntReleaseWindowObject(WindowObject);
       return Result;
     }
-    
+
     case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
       return (DWORD)MsqSetMessageExtraInfo((LPARAM)Param);
-    
+
     case ONEPARAM_ROUTINE_GETCURSORPOSITION:
     {
       PWINSTATION_OBJECT WinStaObject;
       NTSTATUS Status;
       POINT Pos;
-      
+
       if(!Param)
         return (DWORD)FALSE;
-      Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
+      Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
                                               KernelMode,
                                               0,
                                               &WinStaObject);
       if (!NT_SUCCESS(Status))
         return (DWORD)FALSE;
-      
+
       /* FIXME - check if process has WINSTA_READATTRIBUTES */
-      Pos.x = WinStaObject->SystemCursor.x;
-      Pos.y = WinStaObject->SystemCursor.y;
-      
+      IntGetCursorLocation(WinStaObject, &Pos);
+
       Status = MmCopyToCaller((PPOINT)Param, &Pos, sizeof(POINT));
       if(!NT_SUCCESS(Status))
       {
@@ -284,31 +291,64 @@ NtUserCallOneParam(
         SetLastNtError(Status);
         return FALSE;
       }
-      
+
       ObDereferenceObject(WinStaObject);
-      
+
       return (DWORD)TRUE;
     }
-    
+
     case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
     {
       PWINDOW_OBJECT WindowObject;
       DWORD Result;
-      
+
       WindowObject = IntGetWindowObject((HWND)Param);
       if(!WindowObject)
       {
         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
         return FALSE;
       }
-      
+
       Result = (DWORD)IntIsWindowInDestroy(WindowObject);
-      
+
       IntReleaseWindowObject(WindowObject);
       return Result;
     }
+
+    case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
+    {
+      BOOL Enable;
+      PW32PROCESS Process = PsGetWin32Process();
+
+      if(Process != NULL)
+      {
+        Enable = (BOOL)(Param != 0);
+
+        if(Enable)
+        {
+          Process->Flags &= ~W32PF_NOWINDOWGHOSTING;
+        }
+        else
+        {
+          Process->Flags |= W32PF_NOWINDOWGHOSTING;
+        }
+
+        return TRUE;
+      }
+
+      return FALSE;
+    }
+
+    case ONEPARAM_ROUTINE_MSQSETWAKEMASK:
+      return (DWORD)IntMsqSetWakeMask(Param);
+
+    case ONEPARAM_ROUTINE_GETKEYBOARDTYPE:
+      return NtUserGetKeyboardType(Param);
+      
+    case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT:
+      return (DWORD)NtUserGetKeyboardLayout(Param);
   }
-  DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n", 
+  DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
           Routine, Param);
   SetLastWin32Error(ERROR_INVALID_PARAMETER);
   return 0;
@@ -327,7 +367,7 @@ NtUserCallTwoParam(
 {
   NTSTATUS Status;
   PWINDOW_OBJECT WindowObject;
-  
+
   switch(Routine)
   {
     case TWOPARAM_ROUTINE_SETDCPENCOLOR:
@@ -365,7 +405,7 @@ NtUserCallTwoParam(
       PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
       if(!MenuObject)
         return 0;
-      
+
       if(Param2 > 0)
       {
         Ret = (MenuObject->MenuInfo.Height == (int)Param2);
@@ -383,27 +423,27 @@ NtUserCallTwoParam(
       PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
       if(!MenuObject)
         return 0;
-      
+
       if(!NT_SUCCESS(MmCopyFromCaller(&smir, (PVOID)Param2, sizeof(SETMENUITEMRECT))))
       {
         IntReleaseMenuObject(MenuObject);
         return 0;
       }
-      
+
       Ret = IntSetMenuItemRect(MenuObject, smir.uItem, smir.fByPosition, &smir.rcRect);
-      
+
       IntReleaseMenuObject(MenuObject);
       return (DWORD)Ret;
     }
-    
+
     case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
     {
-      PUSER_MESSAGE_QUEUE MsgQueue = PsGetCurrentThread()->Win32Thread->MessageQueue;
-      
+      PUSER_MESSAGE_QUEUE MsgQueue = PsGetCurrentThread()->Tcb.Win32Thread->MessageQueue;
+
       ASSERT(MsgQueue);
       return (DWORD)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2);
     }
-    
+
     case TWOPARAM_ROUTINE_ENABLEWINDOW:
          UNIMPLEMENTED
       return 0;
@@ -413,16 +453,39 @@ NtUserCallTwoParam(
          return 0;
 
     case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
-         UNIMPLEMENTED
-         return 0;
+         return (DWORD)IntShowOwnedPopups((HWND) Param1, (BOOL) Param2);
 
+    case TWOPARAM_ROUTINE_ROS_SHOWWINDOW:
+    {
+#define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
+          PWINDOW_OBJECT Window = IntGetWindowObject((HWND)Param1);
+         DPRINT1("ROS_SHOWWINDOW\n");
+          if (Window == 0)
+           {
+                 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+                 return FALSE;
+           }
+          if (Param2)
+           {
+               if (!(Window->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP))
+                {
+                    IntReleaseWindowObject(Window);
+                    return TRUE;
+                }
+                Window->Flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
+           }
+          else Window->Flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
+          DPRINT1("ROS_SHOWWINDOW ---> 0x%x\n",Window->Flags);
+          IntReleaseWindowObject(Window);
+          return TRUE;
+    }
     case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
          UNIMPLEMENTED
          return 0;
 
     case TWOPARAM_ROUTINE_VALIDATERGN:
       return (DWORD)NtUserValidateRgn((HWND) Param1, (HRGN) Param2);
-      
+
     case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
       WindowObject = IntGetWindowObject((HWND)Param1);
       if(!WindowObject)
@@ -430,26 +493,31 @@ NtUserCallTwoParam(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return (DWORD)FALSE;
       }
-      
+
       WindowObject->ContextHelpId = Param2;
-      
+
       IntReleaseWindowObject(WindowObject);
       return (DWORD)TRUE;
-    
+
     case TWOPARAM_ROUTINE_SETCARETPOS:
       return (DWORD)IntSetCaretPos((int)Param1, (int)Param2);
-    
+
     case TWOPARAM_ROUTINE_GETWINDOWINFO:
     {
       WINDOWINFO wi;
       DWORD Ret;
-      
+
       if(!(WindowObject = IntGetWindowObject((HWND)Param1)))
       {
         SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
         return FALSE;
       }
-      
+
+#if 0
+      /*
+       * According to WINE, Windows' doesn't check the cbSize field
+       */
+
       Status = MmCopyFromCaller(&wi.cbSize, (PVOID)Param2, sizeof(wi.cbSize));
       if(!NT_SUCCESS(Status))
       {
@@ -457,14 +525,15 @@ NtUserCallTwoParam(
         SetLastNtError(Status);
         return FALSE;
       }
-      
+
       if(wi.cbSize != sizeof(WINDOWINFO))
       {
         IntReleaseWindowObject(WindowObject);
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return FALSE;
       }
-      
+#endif
+
       if((Ret = (DWORD)IntGetWindowInfo(WindowObject, &wi)))
       {
         Status = MmCopyToCaller((PVOID)Param2, &wi, sizeof(WINDOWINFO));
@@ -475,14 +544,109 @@ NtUserCallTwoParam(
           return FALSE;
         }
       }
-      
+
       IntReleaseWindowObject(WindowObject);
       return Ret;
     }
-    
+
     case TWOPARAM_ROUTINE_REGISTERLOGONPROC:
       return (DWORD)IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2);
-    
+
+    case TWOPARAM_ROUTINE_SETSYSCOLORS:
+    {
+      DWORD Ret = 0;
+      PVOID Buffer;
+      struct
+      {
+        INT *Elements;
+        COLORREF *Colors;
+      } ChangeSysColors;
+
+      /* FIXME - we should make use of SEH here... */
+
+      Status = MmCopyFromCaller(&ChangeSysColors, (PVOID)Param1, sizeof(ChangeSysColors));
+      if(!NT_SUCCESS(Status))
+      {
+        SetLastNtError(Status);
+        return 0;
+      }
+
+      Buffer = ExAllocatePool(PagedPool, (Param2 * sizeof(INT)) + (Param2 * sizeof(COLORREF)));
+      if(Buffer != NULL)
+      {
+        INT *Elements = (INT*)Buffer;
+        COLORREF *Colors = (COLORREF*)Buffer + Param2;
+
+        Status = MmCopyFromCaller(Elements, ChangeSysColors.Elements, Param2 * sizeof(INT));
+        if(NT_SUCCESS(Status))
+        {
+          Status = MmCopyFromCaller(Colors, ChangeSysColors.Colors, Param2 * sizeof(COLORREF));
+          if(NT_SUCCESS(Status))
+          {
+            Ret = (DWORD)IntSetSysColors((UINT)Param2, Elements, Colors);
+          }
+          else
+            SetLastNtError(Status);
+        }
+        else
+          SetLastNtError(Status);
+
+        ExFreePool(Buffer);
+      }
+
+
+      return Ret;
+    }
+
+    case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
+    case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
+    case TWOPARAM_ROUTINE_GETSYSCOLORS:
+    {
+      DWORD Ret = 0;
+      union
+      {
+        PVOID Pointer;
+        HBRUSH *Brushes;
+        HPEN *Pens;
+        COLORREF *Colors;
+      } Buffer;
+
+      /* FIXME - we should make use of SEH here... */
+
+      Buffer.Pointer = ExAllocatePool(PagedPool, Param2 * sizeof(HANDLE));
+      if(Buffer.Pointer != NULL)
+      {
+        switch(Routine)
+        {
+          case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
+            Ret = (DWORD)IntGetSysColorBrushes(Buffer.Brushes, (UINT)Param2);
+            break;
+          case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
+            Ret = (DWORD)IntGetSysColorPens(Buffer.Pens, (UINT)Param2);
+            break;
+          case TWOPARAM_ROUTINE_GETSYSCOLORS:
+            Ret = (DWORD)IntGetSysColors(Buffer.Colors, (UINT)Param2);
+            break;
+          default:
+            Ret = 0;
+            break;
+        }
+
+        if(Ret > 0)
+        {
+          Status = MmCopyToCaller((PVOID)Param1, Buffer.Pointer, Param2 * sizeof(HANDLE));
+          if(!NT_SUCCESS(Status))
+          {
+            SetLastNtError(Status);
+            Ret = 0;
+          }
+        }
+
+        ExFreePool(Buffer.Pointer);
+      }
+      return Ret;
+    }
+
   }
   DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
           Routine, Param1, Param2);
@@ -490,6 +654,7 @@ NtUserCallTwoParam(
   return 0;
 }
 
+
 /*
  * @unimplemented
  */
@@ -513,18 +678,31 @@ NtUserCallHwndLock(
    switch (Routine)
    {
       case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
-         /* FIXME */
+         WinPosArrangeIconicWindows(Window);
          break;
 
       case HWNDLOCK_ROUTINE_DRAWMENUBAR:
-         /* FIXME */
-         break;
+           {
+              PMENU_OBJECT MenuObject;
+              DPRINT("HWNDLOCK_ROUTINE_DRAWMENUBAR\n");
+              Ret = FALSE;
+              if (!((Window->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD)) break;
+              MenuObject = IntGetMenuObject((HMENU) Window->IDMenu);
+              if(MenuObject == NULL) break;
+              MenuObject->MenuInfo.WndOwner = hWnd;
+              MenuObject->MenuInfo.Height = 0;
+              IntReleaseMenuObject(MenuObject);
+              WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                           SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+              Ret = TRUE;
+              break;
+            }
 
       case HWNDLOCK_ROUTINE_REDRAWFRAME:
          /* FIXME */
          break;
 
-      case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:         
+      case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
          Ret = IntSetForegroundWindow(Window);
          break;
 
@@ -538,6 +716,9 @@ NtUserCallHwndLock(
    return Ret;
 }
 
+/*
+ * @unimplemented
+ */
 HWND
 STDCALL
 NtUserCallHwndOpt(
@@ -547,15 +728,23 @@ NtUserCallHwndOpt(
    switch (Routine)
    {
       case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
-         /* FIXME */
+         /* 
+          * FIXME 
+          * Nothing too hard...validate the hWnd and save it in the Desktop Info
+          */
+         DPRINT1("HWNDOPT_ROUTINE_SETPROGMANWINDOW UNIMPLEMENTED\n");
          break;
 
       case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
-         /* FIXME */
+         /* 
+          * FIXME 
+          * Nothing too hard...validate the hWnd and save it in the Desktop Info
+          */
+         DPRINT1("HWNDOPT_ROUTINE_SETTASKMANWINDOW UNIMPLEMENTED\n");
          break;
    }
 
-   return 0;
+   return Param;
 }
 
 /*
@@ -574,8 +763,8 @@ NtUserGetThreadState(
 }
 
 VOID FASTCALL
-IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font) 
-{ 
+IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
+{
    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
    NTSTATUS Status;
    static LOGFONTW DefaultFont = {
@@ -619,19 +808,19 @@ IntSystemParametersInfo(
   static BOOL GradientCaptions = TRUE;
   static UINT FocusBorderHeight = 1;
   static UINT FocusBorderWidth = 1;
-  
+
   if (!bInitialized)
   {
-    ZeroMemory(&IconFont, sizeof(LOGFONTW)); 
-    ZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
-    
+    RtlZeroMemory(&IconFont, sizeof(LOGFONTW));
+    RtlZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
+
     IntGetFontMetricSetting(L"CaptionFont", &pMetrics.lfCaptionFont);
     IntGetFontMetricSetting(L"SmCaptionFont", &pMetrics.lfSmCaptionFont);
     IntGetFontMetricSetting(L"MenuFont", &pMetrics.lfMenuFont);
     IntGetFontMetricSetting(L"StatusFont", &pMetrics.lfStatusFont);
     IntGetFontMetricSetting(L"MessageFont", &pMetrics.lfMessageFont);
     IntGetFontMetricSetting(L"IconFont", &IconFont);
-    
+
     pMetrics.iBorderWidth = 1;
     pMetrics.iScrollWidth = NtUserGetSystemMetrics(SM_CXVSCROLL);
     pMetrics.iScrollHeight = NtUserGetSystemMetrics(SM_CYHSCROLL);
@@ -641,18 +830,22 @@ IntSystemParametersInfo(
     pMetrics.iSmCaptionHeight = NtUserGetSystemMetrics(SM_CYSMSIZE);
     pMetrics.iMenuWidth = NtUserGetSystemMetrics(SM_CXMENUSIZE);
     pMetrics.iMenuHeight = NtUserGetSystemMetrics(SM_CYMENUSIZE);
-    pMetrics.cbSize = sizeof(LPNONCLIENTMETRICSW);
-    
+    pMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
+
     bInitialized = TRUE;
   }
-  
+
   switch(uiAction)
   {
     case SPI_SETDOUBLECLKWIDTH:
     case SPI_SETDOUBLECLKHEIGHT:
     case SPI_SETDOUBLECLICKTIME:
+    case SPI_SETDESKWALLPAPER:
+    case SPI_GETDESKWALLPAPER:
     {
-      Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
+      PSYSTEM_CURSORINFO CurInfo;
+
+      Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
                                               KernelMode,
                                               0,
                                               &WinStaObject);
@@ -661,25 +854,73 @@ IntSystemParametersInfo(
         SetLastNtError(Status);
         return (DWORD)FALSE;
       }
-      
+
       switch(uiAction)
       {
         case SPI_SETDOUBLECLKWIDTH:
+          CurInfo = IntGetSysCursorInfo(WinStaObject);
           /* FIXME limit the maximum value? */
-          WinStaObject->SystemCursor.DblClickWidth = uiParam;
+          CurInfo->DblClickWidth = uiParam;
           break;
         case SPI_SETDOUBLECLKHEIGHT:
+          CurInfo = IntGetSysCursorInfo(WinStaObject);
           /* FIXME limit the maximum value? */
-          WinStaObject->SystemCursor.DblClickHeight = uiParam;
+          CurInfo->DblClickHeight = uiParam;
           break;
         case SPI_SETDOUBLECLICKTIME:
+          CurInfo = IntGetSysCursorInfo(WinStaObject);
           /* FIXME limit the maximum time to 1000 ms? */
-          WinStaObject->SystemCursor.DblClickSpeed = uiParam;
+          CurInfo->DblClickSpeed = uiParam;
+          break;
+        case SPI_SETDESKWALLPAPER:
+        {
+          /* This function expects different parameters than the user mode version!
+
+             We let the user mode code load the bitmap, it passed the handle to
+             the bitmap. We'll change it's ownership to system and replace it with
+             the current wallpaper bitmap */
+          HBITMAP hOldBitmap, hNewBitmap;
+          ASSERT(pvParam);
+
+          hNewBitmap = *(HBITMAP*)pvParam;
+          if(hNewBitmap != NULL)
+          {
+            BITMAPOBJ *bmp;
+            /* try to get the size of the wallpaper */
+            if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap)))
+            {
+              ObDereferenceObject(WinStaObject);
+              return FALSE;
+            }
+            WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx;
+            WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy;
+
+            BITMAPOBJ_UnlockBitmap(bmp);
+
+            /* change the bitmap's ownership */
+            GDIOBJ_SetOwnership(hNewBitmap, NULL);
+          }
+          hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
+          if(hOldBitmap != NULL)
+          {
+            /* delete the old wallpaper */
+            NtGdiDeleteObject(hOldBitmap);
+          }
+          break;
+        }
+        case SPI_GETDESKWALLPAPER:
+          /* This function expects different parameters than the user mode version!
+
+             We basically return the current wallpaper handle - if any. The user
+             mode version should load the string from the registry and return it
+             without calling this function */
+          ASSERT(pvParam);
+          *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper;
           break;
       }
-      
+
       /* FIXME save the value to the registry */
-      
+
       ObDereferenceObject(WinStaObject);
       return TRUE;
     }
@@ -687,32 +928,32 @@ IntSystemParametersInfo(
     {
       RECT *rc;
       PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
-      
+
       if(!Desktop)
       {
         /* FIXME - Set last error */
         return FALSE;
       }
-      
+
       ASSERT(pvParam);
       rc = (RECT*)pvParam;
       Desktop->WorkArea = *rc;
-      
+
       return TRUE;
     }
     case SPI_GETWORKAREA:
     {
       PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
-      
+
       if(!Desktop)
       {
         /* FIXME - Set last error */
         return FALSE;
       }
-      
+
       ASSERT(pvParam);
-      *((PRECT)pvParam) = *(IntGetDesktopWorkArea(Desktop));
-      
+      IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
+
       return TRUE;
     }
     case SPI_SETGRADIENTCAPTIONS:
@@ -724,19 +965,13 @@ IntSystemParametersInfo(
     case SPI_GETGRADIENTCAPTIONS:
     {
       HDC hDC;
-      PDC dc;
-      SURFOBJ *SurfObj;
       BOOL Ret = GradientCaptions;
-      
+
       hDC = IntGetScreenDC();
       if(hDC)
       {
-        dc = DC_LockDc(hDC);
-        SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
-        if(SurfObj)
-          Ret = (SurfObj->iBitmapFormat > BMF_8BPP) && Ret;
-        DC_UnlockDc(hDC);
-        
+        Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
+
         ASSERT(pvParam);
         *((PBOOL)pvParam) = Ret;
         return TRUE;
@@ -788,7 +1023,7 @@ IntSystemParametersInfo(
       FocusBorderWidth = (UINT)pvParam;
       return TRUE;
     }
-    
+
     default:
     {
       DPRINT1("SystemParametersInfo: Unsupported Action 0x%x (uiParam: 0x%x, pvParam: 0x%x, fWinIni: 0x%x)\n",
@@ -802,7 +1037,7 @@ IntSystemParametersInfo(
 /*
  * @implemented
  */
-DWORD
+BOOL
 STDCALL
 NtUserSystemParametersInfo(
   UINT uiAction,
@@ -838,12 +1073,12 @@ NtUserSystemParametersInfo(
     case SPI_GETWORKAREA:
     {
       RECT rc;
-      
+
       if(!IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni))
       {
         return FALSE;
       }
-      
+
       Status = MmCopyToCaller((PRECT)pvParam, &rc, sizeof(RECT));
       if(!NT_SUCCESS(Status))
       {
@@ -858,12 +1093,12 @@ NtUserSystemParametersInfo(
     case SPI_GETFOCUSBORDERWIDTH:
     {
       BOOL Ret;
-      
+
       if(!IntSystemParametersInfo(uiAction, uiParam, &Ret, fWinIni))
       {
         return FALSE;
       }
-      
+
       Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
       if(!NT_SUCCESS(Status))
       {
@@ -872,15 +1107,46 @@ NtUserSystemParametersInfo(
       }
       return TRUE;
     }
+    case SPI_SETDESKWALLPAPER:
+    {
+      /* !!! As opposed to the user mode version this version accepts a handle
+             to the bitmap! */
+      HBITMAP hbmWallpaper;
+
+      Status = MmCopyFromCaller(&hbmWallpaper, pvParam, sizeof(HBITMAP));
+      if(!NT_SUCCESS(Status))
+      {
+        SetLastNtError(Status);
+        return FALSE;
+      }
+      return IntSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni);
+    }
+    case SPI_GETDESKWALLPAPER:
+    {
+      /* !!! As opposed to the user mode version this version returns a handle
+             to the bitmap! */
+      HBITMAP hbmWallpaper;
+      BOOL Ret;
+
+      Ret = IntSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni);
+
+      Status = MmCopyToCaller(pvParam, &hbmWallpaper, sizeof(HBITMAP));
+      if(!NT_SUCCESS(Status))
+      {
+        SetLastNtError(Status);
+        return FALSE;
+      }
+      return Ret;
+    }
     case SPI_GETICONTITLELOGFONT:
     {
       LOGFONTW IconFont;
-      
+
       if(!IntSystemParametersInfo(uiAction, uiParam, &IconFont, fWinIni))
       {
         return FALSE;
       }
-      
+
       Status = MmCopyToCaller(pvParam, &IconFont, sizeof(LOGFONTW));
       if(!NT_SUCCESS(Status))
       {
@@ -892,25 +1158,24 @@ NtUserSystemParametersInfo(
     case SPI_GETNONCLIENTMETRICS:
     {
       NONCLIENTMETRICSW metrics;
-      
+
       Status = MmCopyFromCaller(&metrics.cbSize, pvParam, sizeof(UINT));
       if(!NT_SUCCESS(Status))
       {
         SetLastNtError(Status);
         return FALSE;
       }
-      if((metrics.cbSize != sizeof(NONCLIENTMETRICSW)) ||
-         (uiParam != sizeof(NONCLIENTMETRICSW)))
+      if(metrics.cbSize != sizeof(NONCLIENTMETRICSW))
       {
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return FALSE;
       }
-      
+
       if(!IntSystemParametersInfo(uiAction, uiParam, &metrics, fWinIni))
       {
         return FALSE;
       }
-      
+
       Status = MmCopyToCaller(pvParam, &metrics.cbSize, sizeof(NONCLIENTMETRICSW));
       if(!NT_SUCCESS(Status))
       {
@@ -930,16 +1195,18 @@ NtUserGetDoubleClickTime(VOID)
   UINT Result;
   NTSTATUS Status;
   PWINSTATION_OBJECT WinStaObject;
-  
-  Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
+  PSYSTEM_CURSORINFO CurInfo;
+
+  Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
                                           KernelMode,
                                           0,
                                           &WinStaObject);
   if (!NT_SUCCESS(Status))
     return (DWORD)FALSE;
 
-  Result = WinStaObject->SystemCursor.DblClickSpeed;
-      
+  CurInfo = IntGetSysCursorInfo(WinStaObject);
+  Result = CurInfo->DblClickSpeed;
+
   ObDereferenceObject(WinStaObject);
   return Result;
 }
@@ -956,34 +1223,34 @@ NtUserGetGUIThreadInfo(
   PDESKTOP_OBJECT Desktop;
   PUSER_MESSAGE_QUEUE MsgQueue;
   PETHREAD Thread = NULL;
-  
+
   Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
     return FALSE;
   }
-  
+
   if(SafeGui.cbSize != sizeof(GUITHREADINFO))
   {
     SetLastWin32Error(ERROR_INVALID_PARAMETER);
     return FALSE;
   }
-  
+
   if(idThread)
   {
-    Status = PsLookupThreadByThreadId((PVOID)idThread, &Thread);
+    Status = PsLookupThreadByThreadId((HANDLE)idThread, &Thread);
     if(!NT_SUCCESS(Status))
     {
       SetLastWin32Error(ERROR_ACCESS_DENIED);
       return FALSE;
     }
-    Desktop = Thread->Win32Thread->Desktop;
+    Desktop = Thread->Tcb.Win32Thread->Desktop;
   }
   else
   {
     /* get the foreground thread */
-    PW32THREAD W32Thread = PsGetCurrentThread()->Win32Thread;
+    PW32THREAD W32Thread = PsGetCurrentThread()->Tcb.Win32Thread;
     Desktop = W32Thread->Desktop;
     if(Desktop)
     {
@@ -994,7 +1261,7 @@ NtUserGetGUIThreadInfo(
       }
     }
   }
-  
+
   if(!Thread || !Desktop)
   {
     if(idThread && Thread)
@@ -1002,33 +1269,33 @@ NtUserGetGUIThreadInfo(
     SetLastWin32Error(ERROR_ACCESS_DENIED);
     return FALSE;
   }
-  
+
   MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
   CaretInfo = MsgQueue->CaretInfo;
-  
+
   SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
   if(MsgQueue->MenuOwner)
     SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
   if(MsgQueue->MoveSize)
     SafeGui.flags |= GUI_INMOVESIZE;
-  
+
   /* FIXME add flag GUI_16BITTASK */
-  
+
   SafeGui.hwndActive = MsgQueue->ActiveWindow;
   SafeGui.hwndFocus = MsgQueue->FocusWindow;
   SafeGui.hwndCapture = MsgQueue->CaptureWindow;
   SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
   SafeGui.hwndMoveSize = MsgQueue->MoveSize;
   SafeGui.hwndCaret = CaretInfo->hWnd;
-  
+
   SafeGui.rcCaret.left = CaretInfo->Pos.x;
   SafeGui.rcCaret.top = CaretInfo->Pos.y;
   SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
   SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
-  
+
   if(idThread)
     ObDereferenceObject(Thread);
-  
+
   Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
   if(!NT_SUCCESS(Status))
   {
@@ -1050,28 +1317,28 @@ NtUserGetGuiResources(
   PW32PROCESS W32Process;
   NTSTATUS Status;
   DWORD Ret = 0;
-  
+
   Status = ObReferenceObjectByHandle(hProcess,
                                      PROCESS_QUERY_INFORMATION,
                                      PsProcessType,
                                      ExGetPreviousMode(),
                                      (PVOID*)&Process,
                                      NULL);
-  
+
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
     return 0;
   }
-  
-  W32Process = Process->Win32Process;
+
+  W32Process = (PW32PROCESS)Process->Win32Process;
   if(!W32Process)
   {
     ObDereferenceObject(Process);
     SetLastWin32Error(ERROR_INVALID_PARAMETER);
     return 0;
   }
-  
+
   switch(uiFlags)
   {
     case GR_GDIOBJECTS:
@@ -1090,7 +1357,7 @@ NtUserGetGuiResources(
       break;
     }
   }
-  
+
   ObDereferenceObject(Process);
 
   return Ret;
@@ -1102,29 +1369,30 @@ IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
 {
   NTSTATUS Status;
   PWSTR Src;
-  
+
   Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
   if(!NT_SUCCESS(Status))
   {
     return Status;
   }
-  
+
   if(Dest->Length > 0x4000)
   {
     return STATUS_UNSUCCESSFUL;
   }
-  
+
   Src = Dest->Buffer;
   Dest->Buffer = NULL;
-  
+
   if(Dest->Length > 0 && Src)
   {
-    Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->Length, TAG_STRING);
+    Dest->MaximumLength = Dest->Length;
+    Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
     if(!Dest->Buffer)
     {
       return STATUS_NO_MEMORY;
     }
-    
+
     Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
     if(!NT_SUCCESS(Status))
     {
@@ -1132,12 +1400,103 @@ IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
       Dest->Buffer = NULL;
       return Status;
     }
-    
-    
+
+
     return STATUS_SUCCESS;
   }
-  
+
   /* string is empty */
   return STATUS_SUCCESS;
 }
 
+NTSTATUS FASTCALL
+IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
+                                      PUNICODE_STRING Source)
+{
+  NTSTATUS Status;
+  PWSTR Src;
+
+  Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
+  if(!NT_SUCCESS(Status))
+  {
+    return Status;
+  }
+
+  if(Dest->Length > 0x4000)
+  {
+    return STATUS_UNSUCCESSFUL;
+  }
+
+  Src = Dest->Buffer;
+  Dest->Buffer = NULL;
+
+  if(Dest->Length > 0 && Src)
+  {
+    Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
+    Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
+    if(!Dest->Buffer)
+    {
+      return STATUS_NO_MEMORY;
+    }
+
+    Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
+    if(!NT_SUCCESS(Status))
+    {
+      ExFreePool(Dest->Buffer);
+      Dest->Buffer = NULL;
+      return Status;
+    }
+
+    /* make sure the string is null-terminated */
+    Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
+    *Src = L'\0';
+
+    return STATUS_SUCCESS;
+  }
+
+  /* string is empty */
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS FASTCALL
+IntUnicodeStringToNULLTerminated(PWSTR *Dest, PUNICODE_STRING Src)
+{
+  if (Src->Length + sizeof(WCHAR) <= Src->MaximumLength
+      && L'\0' == Src->Buffer[Src->Length / sizeof(WCHAR)])
+    {
+      /* The unicode_string is already nul terminated. Just reuse it. */
+      *Dest = Src->Buffer;
+      return STATUS_SUCCESS;
+    }
+
+  *Dest = ExAllocatePoolWithTag(PagedPool, Src->Length + sizeof(WCHAR), TAG_STRING);
+  if (NULL == *Dest)
+    {
+      return STATUS_NO_MEMORY;
+    }
+  RtlCopyMemory(*Dest, Src->Buffer, Src->Length);
+  (*Dest)[Src->Length / 2] = L'\0';
+
+  return STATUS_SUCCESS;
+}
+
+void FASTCALL
+IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated, PUNICODE_STRING UnicodeString)
+{
+  if (NullTerminated != UnicodeString->Buffer)
+    {
+      ExFreePool(NullTerminated);
+    }
+}
+
+BOOL STDCALL
+NtUserUpdatePerUserSystemParameters(
+   DWORD dwReserved,
+   BOOL bEnable)
+{
+   BOOL Result = TRUE;
+   Result &= IntDesktopUpdatePerUserSettings(bEnable);
+   return Result;
+}
+
+/* EOF */