Fix a typo.
[reactos.git] / reactos / subsys / win32k / objects / dc.c
index 8e5ce1c..e44b5df 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: dc.c,v 1.117 2004/01/16 19:32:00 gvg Exp $
+/* $Id$
  *
  * DC.C - Device context functions
  *
  */
 
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <ddk/ntddvid.h>
-
-#include <internal/safe.h>
-#include <win32k/bitmaps.h>
-#include <win32k/brush.h>
-#include <win32k/cliprgn.h>
-#include <win32k/coord.h>
-#include <win32k/driver.h>
-#include <win32k/dc.h>
-#include <win32k/misc.h>
-#include <win32k/print.h>
-#include <win32k/region.h>
-#include <win32k/gdiobj.h>
-#include <win32k/paint.h>
-#include <win32k/pen.h>
-#include <win32k/text.h>
-#include "../eng/clip.h"
-#include "../eng/handle.h"
-#include <include/dce.h>
-#include <include/error.h>
-#include <include/inteng.h>
-#include <include/eng.h>
-#include <include/palette.h>
-#include <include/guicheck.h>
-#include <include/desktop.h>
-#include <include/intgdi.h>
-#include <include/cleanup.h>
+#include <w32k.h>
 
 #define NDEBUG
-#include <win32k/debug1.h>
+#include <debug.h>
 
-#define TAG_DC  TAG('D', 'C', 'D', 'C')
+#ifndef OBJ_COLORSPACE
+#define OBJ_COLORSPACE (14)
+#endif
 
 static GDIDEVICE PrimarySurface;
 
@@ -74,10 +47,11 @@ func_type STDCALL  func_name( HDC hdc ) \
   PDC  dc = DC_LockDc( hdc );  \
   if (!dc)                          \
   {                                 \
+    SetLastWin32Error(ERROR_INVALID_HANDLE); \
     return 0;                       \
   }                                 \
   ft = dc->dc_field;                \
-  DC_UnlockDc( hdc );                          \
+  DC_UnlockDc(dc);                             \
   return ft;                        \
 }
 
@@ -85,22 +59,49 @@ func_type STDCALL  func_name( HDC hdc ) \
  * important that the function has the right signature, for the implementation
  * we can do whatever we want.
  */
-#define DC_GET_VAL_EX( NtGdiFuncName, IntFuncName, ret_x, ret_y, type ) \
-VOID FASTCALL IntFuncName ( PDC dc, LP##type pt )  \
-{                                                  \
-  ASSERT ( dc );                                   \
-  ASSERT ( pt );                                   \
-  ((LPPOINT)pt)->x = dc->ret_x;                    \
-  ((LPPOINT)pt)->y = dc->ret_y;                    \
-}                                                  \
-BOOL STDCALL NtGdiFuncName ( HDC hdc, LP##type pt ) \
-{                                                  \
-  PDC dc = DC_LockDc ( hdc );                 \
-  if ( !dc )                                       \
-    return FALSE;                                  \
-  IntFuncName ( dc, pt );                          \
-  DC_UnlockDc ( hdc );                           \
-  return TRUE;                                     \
+#define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
+VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
+{ \
+  ASSERT(dc); \
+  ASSERT(pt); \
+  pt->ax = dc->ret_x; \
+  pt->ay = dc->ret_y; \
+} \
+BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
+{ \
+  NTSTATUS Status = STATUS_SUCCESS; \
+  type Safept; \
+  PDC dc; \
+  if(!pt) \
+  { \
+    SetLastWin32Error(ERROR_INVALID_PARAMETER); \
+    return FALSE; \
+  } \
+  if(!(dc = DC_LockDc(hdc))) \
+  { \
+    SetLastWin32Error(ERROR_INVALID_HANDLE); \
+    return FALSE; \
+  } \
+  Int##FuncName( dc, &Safept); \
+  DC_UnlockDc(dc); \
+  _SEH_TRY \
+  { \
+    ProbeForWrite(pt, \
+                  sizeof( type ), \
+                  1); \
+    *pt = Safept; \
+  } \
+  _SEH_HANDLE \
+  { \
+    Status = _SEH_GetExceptionCode(); \
+  } \
+  _SEH_END; \
+  if(!NT_SUCCESS(Status)) \
+  { \
+    SetLastNtError(Status); \
+    return FALSE; \
+  } \
+  return TRUE; \
 }
 
 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
@@ -109,13 +110,19 @@ INT STDCALL  func_name( HDC hdc, INT mode ) \
   INT  prevMode;                            \
   PDC  dc;                                  \
   if ((mode < min_val) || (mode > max_val)) \
+  { \
+    SetLastWin32Error(ERROR_INVALID_PARAMETER); \
     return 0;                               \
+  } \
   dc = DC_LockDc ( hdc );              \
   if ( !dc )                                \
+  { \
+    SetLastWin32Error(ERROR_INVALID_HANDLE); \
     return 0;                               \
+  } \
   prevMode = dc->dc_field;                  \
   dc->dc_field = mode;                      \
-  DC_UnlockDc ( hdc );                    \
+  DC_UnlockDc ( dc );                    \
   return prevMode;                          \
 }
 
@@ -128,23 +135,23 @@ BOOL STDCALL
 NtGdiCancelDC(HDC  hDC)
 {
   UNIMPLEMENTED;
+  return FALSE;
 }
 
 HDC STDCALL
-NtGdiCreateCompatableDC(HDC hDC)
+NtGdiCreateCompatibleDC(HDC hDC)
 {
   PDC  NewDC, OrigDC;
   HBITMAP  hBitmap;
   HDC hNewDC, DisplayDC;
   HRGN hVisRgn;
-  BITMAPOBJ *pb;
   UNICODE_STRING DriverName;
 
   DisplayDC = NULL;
   if (hDC == NULL)
     {
       RtlInitUnicodeString(&DriverName, L"DISPLAY");
-      DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL);
+      DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
       if (NULL == DisplayDC)
         {
           return NULL;
@@ -166,7 +173,7 @@ NtGdiCreateCompatableDC(HDC hDC)
 
   if (NULL == hNewDC)
     {
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(OrigDC);
       if (NULL != DisplayDC)
         {
           NtGdiDeleteDC(DisplayDC);
@@ -176,10 +183,10 @@ NtGdiCreateCompatableDC(HDC hDC)
   NewDC = DC_LockDc( hNewDC );
 
   /* Copy information from original DC to new DC  */
-  NewDC->hSelf = NewDC;
+  NewDC->hSelf = hNewDC;
+  NewDC->IsIC = FALSE;
 
   NewDC->PDev = OrigDC->PDev;
-  NewDC->DMW = OrigDC->DMW;
   memcpy(NewDC->FillPatternSurfaces,
          OrigDC->FillPatternSurfaces,
          sizeof OrigDC->FillPatternSurfaces);
@@ -201,8 +208,8 @@ NtGdiCreateCompatableDC(HDC hDC)
   /* Create default bitmap */
   if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
     {
-      DC_UnlockDc( hDC );
-      DC_UnlockDc( hNewDC );
+      DC_UnlockDc( OrigDC );
+      DC_UnlockDc( NewDC );
       DC_FreeDC( hNewDC );
       if (NULL != DisplayDC)
         {
@@ -214,21 +221,19 @@ NtGdiCreateCompatableDC(HDC hDC)
   NewDC->w.hBitmap      = hBitmap;
   NewDC->w.hFirstBitmap = hBitmap;
   NewDC->GDIDevice      = OrigDC->GDIDevice;
-  pb = BITMAPOBJ_LockBitmap(hBitmap);
-  NewDC->Surface = BitmapToSurf(pb, NewDC->GDIDevice);
-  BITMAPOBJ_UnlockBitmap(hBitmap);
 
   NewDC->w.hPalette = OrigDC->w.hPalette;
   NewDC->w.textColor = OrigDC->w.textColor;
   NewDC->w.textAlign = OrigDC->w.textAlign;
   NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
   NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
-  DC_UnlockDc( hDC );
+  NewDC->w.ROPmode = OrigDC->w.ROPmode;
+  DC_UnlockDc(NewDC);
+  DC_UnlockDc(OrigDC);
   if (NULL != DisplayDC)
     {
       NtGdiDeleteDC(DisplayDC);
     }
-  DC_UnlockDc(hNewDC);
 
   hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
   NtGdiSelectVisRgn(hNewDC, hVisRgn);
@@ -240,15 +245,17 @@ NtGdiCreateCompatableDC(HDC hDC)
 }
 
 static BOOL FASTCALL
-GetRegistryPath(PUNICODE_STRING RegistryPath)
+GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
 {
   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  WCHAR DeviceNameBuffer[20];
   NTSTATUS Status;
 
+  swprintf(DeviceNameBuffer, L"\\Device\\Video%d", DisplayNumber);
   RtlInitUnicodeString(RegistryPath, NULL);
   RtlZeroMemory(QueryTable, sizeof(QueryTable));
   QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
-  QueryTable[0].Name = L"\\Device\\Video0";
+  QueryTable[0].Name = DeviceNameBuffer;
   QueryTable[0].EntryContext = RegistryPath;
 
   Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
@@ -258,7 +265,7 @@ GetRegistryPath(PUNICODE_STRING RegistryPath)
                                   NULL);
   if (! NT_SUCCESS(Status))
     {
-      DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
+      DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
       return FALSE;
     }
 
@@ -268,13 +275,13 @@ GetRegistryPath(PUNICODE_STRING RegistryPath)
 }
 
 static BOOL FASTCALL
-FindDriverFileNames(PUNICODE_STRING DriverFileNames)
+FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
 {
   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
   UNICODE_STRING RegistryPath;
   NTSTATUS Status;
 
-  if (! GetRegistryPath(&RegistryPath))
+  if (! GetRegistryPath(&RegistryPath, DisplayNumber))
     {
       DPRINT("GetRegistryPath failed\n");
       return FALSE;
@@ -351,7 +358,7 @@ DevModeCallback(IN PWSTR ValueName,
 }
 
 static BOOL FASTCALL
-SetupDevMode(PDEVMODEW DevMode)
+SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
 {
   static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
   static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
@@ -364,7 +371,7 @@ SetupDevMode(PDEVMODEW DevMode)
   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
   NTSTATUS Status;
 
-  if (! GetRegistryPath(&RegistryPath))
+  if (! GetRegistryPath(&RegistryPath, DisplayNumber))
     {
       DPRINT("GetRegistryPath failed\n");
       return FALSE;
@@ -398,7 +405,7 @@ SetupDevMode(PDEVMODEW DevMode)
   if (Valid)
     {
       ProfilePath = ExAllocatePoolWithTag(PagedPool,
-                                          (wcslen(RegistryPath.Buffer) + 
+                                          (wcslen(RegistryPath.Buffer) +
                                            wcslen(Insert) + 1) * sizeof(WCHAR),
                                           TAG_DC);
       if (NULL != ProfilePath)
@@ -462,202 +469,346 @@ SetupDevMode(PDEVMODEW DevMode)
   return Valid;
 }
 
-BOOL FASTCALL
-IntCreatePrimarySurface()
+static BOOL FASTCALL
+IntPrepareDriver()
 {
-  PGD_ENABLEDRIVER GDEnableDriver;
-  DRVENABLEDATA DED;
-  PSURFOBJ SurfObj;
-  PSURFGDI SurfGDI;
-  UNICODE_STRING DriverFileNames;
-  PWSTR CurrentName;
-  BOOL GotDriver;
-  BOOL DoDefault;
-
-  ExInitializeFastMutex(&PrimarySurface.DriverLock);
-
-  /*  Open the miniport driver  */
-  if ((PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(L"DISPLAY")) == NULL)
-    {
-      DPRINT1("FindMPDriver failed\n");
-      return FALSE;
-    }
+   PGD_ENABLEDRIVER GDEnableDriver;
+   DRVENABLEDATA DED;
+   UNICODE_STRING DriverFileNames;
+   PWSTR CurrentName;
+   BOOL GotDriver;
+   BOOL DoDefault;
+   ULONG DisplayNumber;
 
-  /*  Retrieve DDI driver names from registry */
-  RtlInitUnicodeString(&DriverFileNames, NULL);
-  if (! FindDriverFileNames(&DriverFileNames))
-    {
-      DPRINT1("FindDriverFileNames failed\n");
-      return FALSE;
-    }
+   for (DisplayNumber = 0; ; DisplayNumber++)
+   {
+      DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
 
-  /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
-     them until a good one found */
-  CurrentName = DriverFileNames.Buffer;
-  GotDriver = FALSE;
-  while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
-    {
-      /*  Get the DDI driver's entry point  */
-      GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
-      if (NULL == GDEnableDriver)
-        {
-          DPRINT("FindDDIDriver failed for %S\n", CurrentName);
-        }
-      else
-        {
-          /*  Call DDI driver's EnableDriver function  */
-          RtlZeroMemory(&DED, sizeof(DED));
+      RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
+
+      PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
+
+      /* Open the miniport driver  */
+      if (PrimarySurface.VideoFileObject == NULL)
+      {
+         DPRINT1("FindMPDriver failed\n");
+         return FALSE;
+      }
+
+      /* Retrieve DDI driver names from registry */
+      RtlInitUnicodeString(&DriverFileNames, NULL);
+      if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
+      {
+         DPRINT1("FindDriverFileNames failed\n");
+         continue;
+      }
 
-          if (! GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
+      /*
+       * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
+       * scan all of them until a good one found.
+       */
+      CurrentName = DriverFileNames.Buffer;
+      GotDriver = FALSE;
+      while (!GotDriver &&
+             CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
+      {
+         /* Get the DDI driver's entry point */
+         GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
+         if (NULL == GDEnableDriver)
+         {
+            DPRINT("FindDDIDriver failed for %S\n", CurrentName);
+         }
+         else
+         {
+            /*  Call DDI driver's EnableDriver function  */
+            RtlZeroMemory(&DED, sizeof(DED));
+
+            if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof(DED), &DED))
             {
-              DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
+               DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
             }
-          else
+            else
             {
-              GotDriver = TRUE;
+               GotDriver = TRUE;
             }
-        }
+         }
 
-      if (! GotDriver)
-        {
-          /* Skip to the next name but never get past the Unicode string */
-          while (L'\0' != *CurrentName &&
-                 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+         if (! GotDriver)
+         {
+            /* Skip to the next name but never get past the Unicode string */
+            while (L'\0' != *CurrentName &&
+                   CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
             {
-              CurrentName++;
+               CurrentName++;
             }
-          if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+            if (CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
             {
-              CurrentName++;
+               CurrentName++;
             }
-        }
-    }
-  RtlFreeUnicodeString(&DriverFileNames);
-  if (! GotDriver)
-    {
-      ObDereferenceObject(PrimarySurface.VideoFileObject);
-      DPRINT1("No suitable DDI driver found\n");
-      return FALSE;
-    }
+         }
+      }
 
-  DPRINT("Display driver %S loaded\n", CurrentName);
+      RtlFreeUnicodeString(&DriverFileNames);
 
-  DPRINT("Building DDI Functions\n");
+      if (!GotDriver)
+      {
+         ObDereferenceObject(PrimarySurface.VideoFileObject);
+         DPRINT1("No suitable DDI driver found\n");
+         continue;
+      }
 
-  /*  Make sure the non existant functions are NULL  */
-  RtlZeroMemory(&PrimarySurface.DriverFunctions, sizeof(PrimarySurface.DriverFunctions));
+      DPRINT("Display driver %S loaded\n", CurrentName);
 
-  /*  Construct DDI driver function dispatch table  */
-  if (! DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
-    {
-      ObDereferenceObject(PrimarySurface.VideoFileObject);
-      DPRINT1("BuildDDIFunctions failed\n");
-      return FALSE;
-    }
+      DPRINT("Building DDI Functions\n");
+
+      /* Construct DDI driver function dispatch table */
+      if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
+      {
+         ObDereferenceObject(PrimarySurface.VideoFileObject);
+         DPRINT1("BuildDDIFunctions failed\n");
+         return FALSE;
+      }
+
+      /* Allocate a phyical device handle from the driver */
+      PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
+      if (SetupDevMode(&PrimarySurface.DMW, DisplayNumber))
+      {
+         PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
+            &PrimarySurface.DMW,
+            L"",
+            HS_DDI_MAX,
+            PrimarySurface.FillPatterns,
+            sizeof(PrimarySurface.GDIInfo),
+            (ULONG *) &PrimarySurface.GDIInfo,
+            sizeof(PrimarySurface.DevInfo),
+            &PrimarySurface.DevInfo,
+            NULL,
+            L"",
+            (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
+         DoDefault = (NULL == PrimarySurface.PDev);
+         if (DoDefault)
+         {
+            DPRINT1("DrvEnablePDev with registry parameters failed\n");
+         }
+      }
+      else
+      {
+         DoDefault = TRUE;
+      }
 
-  /*  Allocate a phyical device handle from the driver  */
-  if (SetupDevMode(&PrimarySurface.DMW))
-    {
-      PrimarySurface.PDev =
-        PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
-                                                  L"",
-                                                  HS_DDI_MAX,
-                                                  PrimarySurface.FillPatterns,
-                                                  sizeof(PrimarySurface.GDIInfo),
-                                                  (ULONG *) &PrimarySurface.GDIInfo,
-                                                  sizeof(PrimarySurface.DevInfo),
-                                                  &PrimarySurface.DevInfo,
-                                                  NULL,
-                                                  L"",
-                                                  (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
-      DoDefault = (NULL == PrimarySurface.PDev);
       if (DoDefault)
-        {
-          DPRINT1("DrvEnablePDev with registry parameters failed\n");
-        }
-    }
-  else
-    {
-      DoDefault = TRUE;
-    }
+      {
+         RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
+         PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
+         PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
+            &PrimarySurface.DMW,
+            L"",
+            HS_DDI_MAX,
+            PrimarySurface.FillPatterns,
+            sizeof(PrimarySurface.GDIInfo),
+            (ULONG *) &PrimarySurface.GDIInfo,
+            sizeof(PrimarySurface.DevInfo),
+            &PrimarySurface.DevInfo,
+            NULL,
+            L"",
+            (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
+
+         if (NULL == PrimarySurface.PDev)
+         {
+            ObDereferenceObject(PrimarySurface.VideoFileObject);
+            DPRINT1("DrvEnablePDEV with default parameters failed\n");
+            DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
+            continue;
+         }
+      }
 
-  if (DoDefault)
-    {
-      RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
-      PrimarySurface.PDev =
-        PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
-                                                  L"",
-                                                  HS_DDI_MAX,
-                                                  PrimarySurface.FillPatterns,
-                                                  sizeof(PrimarySurface.GDIInfo),
-                                                  (ULONG *) &PrimarySurface.GDIInfo,
-                                                  sizeof(PrimarySurface.DevInfo),
-                                                  &PrimarySurface.DevInfo,
-                                                  NULL,
-                                                  L"",
-                                                  (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
-
-      if (NULL == PrimarySurface.PDev)
-        {
-          ObDereferenceObject(PrimarySurface.VideoFileObject);
-          DPRINT1("DrvEnablePDEV with default parameters failed\n");
-          DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
-          return FALSE;
-        }
-    }
+      if (0 == PrimarySurface.GDIInfo.ulLogPixelsX)
+      {
+         DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
+         PrimarySurface.GDIInfo.ulLogPixelsX = 96;
+      }
+      if (0 == PrimarySurface.GDIInfo.ulLogPixelsY)
+      {
+         DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
+         PrimarySurface.GDIInfo.ulLogPixelsY = 96;
+      }
 
-  if (0 == PrimarySurface.GDIInfo.ulLogPixelsX)
-    {
-      DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
-      PrimarySurface.GDIInfo.ulLogPixelsX = 96;
-    }
-  if (0 == PrimarySurface.GDIInfo.ulLogPixelsY)
-    {
-      DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
-      PrimarySurface.GDIInfo.ulLogPixelsY = 96;
-    }
+      PrimarySurface.Pointer.Exclude.right = -1;
 
-  DPRINT("calling completePDev\n");
+      DPRINT("calling completePDev\n");
 
-  /*  Complete initialization of the physical device  */
-  PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
-                                             &PrimarySurface);
+      /* Complete initialization of the physical device */
+      PrimarySurface.DriverFunctions.CompletePDEV(
+         PrimarySurface.PDev,
+        (HDEV)&PrimarySurface);
 
-  DPRINT("calling DRIVER_ReferenceDriver\n");
+      DPRINT("calling DRIVER_ReferenceDriver\n");
 
-  DRIVER_ReferenceDriver(L"DISPLAY");
+      DRIVER_ReferenceDriver(L"DISPLAY");
 
-  DPRINT("calling EnableSurface\n");
+      PrimarySurface.PreparedDriver = TRUE;
+      PrimarySurface.DisplayNumber = DisplayNumber;
 
-  /*  Enable the drawing surface  */
-  PrimarySurface.Handle =
-    PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
-  if (NULL == PrimarySurface.Handle)
-    {
+      return TRUE;
+   }
+
+   return FALSE;
+}
+
+static BOOL FASTCALL
+IntPrepareDriverIfNeeded()
+{
+   return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
+}
+
+static BOOL FASTCALL
+PrepareVideoPrt()
+{
+   PIRP Irp;
+   NTSTATUS Status;
+   IO_STATUS_BLOCK Iosb;
+   BOOL Prepare = TRUE;
+   ULONG Length = sizeof(BOOL);
+   PIO_STACK_LOCATION StackPtr;
+   LARGE_INTEGER StartOffset;
+   PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject;
+   PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
+
+   DPRINT("PrepareVideoPrt() called\n");
+
+   KeClearEvent(&PrimarySurface.VideoFileObject->Event);
+
+   ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode);
+
+   StartOffset.QuadPart = 0;
+   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+                                      DeviceObject,
+                                      (PVOID) &Prepare,
+                                      Length,
+                                      &StartOffset,
+                                      NULL,
+                                      &Iosb);
+   if (NULL == Irp)
+   {
+      return FALSE;
+   }
+
+   /* Set up IRP Data */
+   Irp->Tail.Overlay.OriginalFileObject = FileObject;
+   Irp->RequestorMode = KernelMode;
+   Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+   Irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
+   Irp->Flags |= IRP_WRITE_OPERATION;
+
+   /* Setup Stack Data */
+   StackPtr = IoGetNextIrpStackLocation(Irp);
+   StackPtr->FileObject = PrimarySurface.VideoFileObject;
+   StackPtr->Parameters.Write.Key = 0;
+
+   Status = IoCallDriver(DeviceObject, Irp);
+
+   if (STATUS_PENDING == Status)
+   {
+      KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0);
+      Status = Iosb.Status;
+   }
+
+   return NT_SUCCESS(Status);
+}
+
+BOOL FASTCALL
+IntCreatePrimarySurface()
+{
+   SIZEL SurfSize;
+   RECTL SurfaceRect;
+   SURFOBJ *SurfObj;
+   BOOL calledFromUser;
+   
+   if (! IntPrepareDriverIfNeeded())
+   {
+      return FALSE;
+   }
+
+   if (! PrepareVideoPrt())
+   {
+      return FALSE;
+   }
+
+   DPRINT("calling EnableSurface\n");
+   /* Enable the drawing surface */
+   PrimarySurface.Handle =
+      PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
+   if (NULL == PrimarySurface.Handle)
+   {
+/*      PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
+      PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.PDev);
       ObDereferenceObject(PrimarySurface.VideoFileObject);
       DPRINT1("DrvEnableSurface failed\n");
       return FALSE;
-    }
+   }
 
-  SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
-  SurfObj->dhpdev = PrimarySurface.PDev;
-  SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
-  IntShowDesktop(IntGetActiveDesktop(),
-                 SurfGDI->SurfObj.sizlBitmap.cx,
-                 SurfGDI->SurfObj.sizlBitmap.cy);
+   PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, TRUE);
 
-  return TRUE;
+   calledFromUser = UserIsEntered(); //fixme: possibly upgrade a shared lock
+   if (!calledFromUser){
+      UserEnterExclusive();
+   }
+
+   /* attach monitor */
+   IntAttachMonitor(&PrimarySurface, PrimarySurface.DisplayNumber);
+
+   SurfObj = EngLockSurface((HSURF)PrimarySurface.Handle);
+   SurfObj->dhpdev = PrimarySurface.PDev;
+   SurfSize = SurfObj->sizlBitmap;
+   SurfaceRect.left = SurfaceRect.top = 0;
+   SurfaceRect.right = SurfObj->sizlBitmap.cx;
+   SurfaceRect.bottom = SurfObj->sizlBitmap.cy;
+   /* FIXME - why does EngEraseSurface() sometimes crash?
+     EngEraseSurface(SurfObj, &SurfaceRect, 0); */
+
+   /* Put the pointer in the center of the screen */
+   GDIDEV(SurfObj)->Pointer.Pos.x = (SurfaceRect.right - SurfaceRect.left) / 2;
+   GDIDEV(SurfObj)->Pointer.Pos.y = (SurfaceRect.bottom - SurfaceRect.top) / 2;
+
+   EngUnlockSurface(SurfObj);
+   co_IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
+
+   if (!calledFromUser){
+      UserLeave();
+   }
+
+   return TRUE;
 }
 
 VOID FASTCALL
 IntDestroyPrimarySurface()
   {
+    BOOL calledFromUser; 
+     
     DRIVER_UnreferenceDriver(L"DISPLAY");
 
+    calledFromUser = UserIsEntered();
+    if (!calledFromUser){
+       UserEnterExclusive();
+    }
+
+    /* detach monitor */
+    IntDetachMonitor(&PrimarySurface);
+
+    if (!calledFromUser){
+       UserLeave();
+    }
+
+    /*
+     * FIXME: Hide a mouse pointer there. Also because we have to prevent
+     * memory leaks with the Eng* mouse routines.
+     */
+
     DPRINT("Reseting display\n" );
     PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);
     PrimarySurface.DriverFunctions.DisableSurface(PrimarySurface.PDev);
-    PrimarySurface.DriverFunctions.DisablePDev(PrimarySurface.PDev);
+    PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.PDev);
+    PrimarySurface.PreparedDriver = FALSE;
 
     DceEmptyCache();
 
@@ -668,23 +819,48 @@ HDC FASTCALL
 IntGdiCreateDC(PUNICODE_STRING Driver,
                PUNICODE_STRING Device,
                PUNICODE_STRING Output,
-               CONST PDEVMODEW InitData)
+               CONST PDEVMODEW InitData,
+               BOOL CreateAsIC)
 {
   HDC      hNewDC;
   PDC      NewDC;
   HDC      hDC = NULL;
-  PSURFGDI SurfGDI;
   HRGN     hVisRgn;
   UNICODE_STRING StdDriver;
+  BOOL calledFromUser;
   
   RtlInitUnicodeString(&StdDriver, L"DISPLAY");
-  
+
   if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
     {
-      if (! IntGraphicsCheck(TRUE))
+      if (CreateAsIC)
         {
-          DPRINT1("Unable to initialize graphics, returning NULL dc\n");
-          return NULL;
+          if (! IntPrepareDriverIfNeeded())
+            {
+              DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
+              return NULL;
+            }
+        }
+      else
+        {
+          calledFromUser = UserIsEntered();
+          if (!calledFromUser){
+             UserEnterExclusive();
+          }
+          
+          if (! co_IntGraphicsCheck(TRUE))
+          {
+            if (!calledFromUser){
+               UserLeave();
+            } 
+            DPRINT1("Unable to initialize graphics, returning NULL dc\n");
+            return NULL;
+          }
+          
+          if (!calledFromUser){
+            UserLeave();
+          } 
+          
         }
     }
 
@@ -692,10 +868,13 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
   if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
   {
     hDC = hNewDC;
-    return  NtGdiCreateCompatableDC(hDC);
+    return  NtGdiCreateCompatibleDC(hDC);
   }
 
-  DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
+  if (Driver != NULL && Driver->Buffer != NULL)
+  {
+    DPRINT("NAME: %wZ\n", Driver); // FIXME: Should not crash if NULL
+  }
 
   /*  Allocate a DC object  */
   if ((hNewDC = DC_AllocDC(Driver)) == NULL)
@@ -704,51 +883,50 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
   }
 
   NewDC = DC_LockDc( hNewDC );
-  ASSERT( NewDC );
+  /* FIXME - NewDC can be NULL!!! Don't assert here! */
+  if ( !NewDC )
+  {
+    DC_FreeDC( hNewDC );
+    return NULL;
+  }
 
-  NewDC->DMW = PrimarySurface.DMW;
+  NewDC->IsIC = CreateAsIC;
   NewDC->DevInfo = &PrimarySurface.DevInfo;
   NewDC->GDIInfo = &PrimarySurface.GDIInfo;
   memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
         sizeof(NewDC->FillPatternSurfaces));
   NewDC->PDev = PrimarySurface.PDev;
-  NewDC->Surface = PrimarySurface.Handle;
-  NewDC->GDIDevice = &PrimarySurface;
+  NewDC->GDIDevice = (HDEV)&PrimarySurface;
   NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
+  NewDC->w.hBitmap = PrimarySurface.Handle;
 
-  NewDC->DMW.dmSize = sizeof(NewDC->DMW);
-  NewDC->DMW.dmFields = 0x000fc000;
-
-  /* FIXME: get mode selection information from somewhere  */
-
-  NewDC->DMW.dmLogPixels = 96;
-  SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
-  NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
-  NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
-  NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
-  NewDC->DMW.dmDisplayFlags = 0;
-  NewDC->DMW.dmDisplayFrequency = 0;
-
-  NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
-
-  NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
-
+  NewDC->w.bitsPerPixel = NewDC->GDIInfo->cBitsPixel * NewDC->GDIInfo->cPlanes;
   DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
-  
-  DC_UnlockDc( hNewDC );
 
-  hVisRgn = NtGdiCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
-                              SurfGDI->SurfObj.sizlBitmap.cy);
-  NtGdiSelectVisRgn(hNewDC, hVisRgn);
-  NtGdiDeleteObject(hVisRgn);
+  if (! CreateAsIC)
+  {
+    NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
+    NewDC->w.ROPmode = R2_COPYPEN;
+
+    DC_UnlockDc( NewDC );
+
+    hVisRgn = NtGdiCreateRectRgn(0, 0, NewDC->GDIInfo->ulHorzRes,
+                                 NewDC->GDIInfo->ulVertRes);
+    NtGdiSelectVisRgn(hNewDC, hVisRgn);
+    NtGdiDeleteObject(hVisRgn);
+
+    /*  Initialize the DC state  */
+    DC_InitDC(hNewDC);
+    NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
+    NtGdiSetTextAlign(hNewDC, TA_TOP);
+    NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
+    NtGdiSetBkMode(hNewDC, OPAQUE);
+  }
+  else
+  {
+    DC_UnlockDc( NewDC );
+  }
 
-  /*  Initialize the DC state  */
-  DC_InitDC(hNewDC);
-  NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
-  NtGdiSetTextAlign(hNewDC, TA_TOP);
-  NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
-  NtGdiSetBkMode(hNewDC, OPAQUE);
-  
   return hNewDC;
 }
 
@@ -761,11 +939,25 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
   UNICODE_STRING SafeDriver, SafeDevice;
   DEVMODEW SafeInitData;
   HDC Ret;
-  NTSTATUS Status;
-  
+  NTSTATUS Status = STATUS_SUCCESS;
+
   if(InitData)
   {
-    Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
+    _SEH_TRY
+    {
+      ProbeForRead(InitData,
+                   sizeof(DEVMODEW),
+                   1);
+      RtlCopyMemory(&SafeInitData,
+                    InitData,
+                    sizeof(DEVMODEW));
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
     if(!NT_SUCCESS(Status))
     {
       SetLastNtError(Status);
@@ -773,7 +965,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
     }
     /* FIXME - InitData can have some more bytes! */
   }
-  
+
   if(Driver)
   {
     Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
@@ -783,7 +975,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
+
   if(Device)
   {
     Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
@@ -794,9 +986,11 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
-  Ret = IntGdiCreateDC(&SafeDriver, &SafeDevice, NULL, &SafeInitData);
-  
+
+  Ret = IntGdiCreateDC(NULL == Driver ? NULL : &SafeDriver,
+                       NULL == Device ? NULL : &SafeDevice, NULL,
+                       NULL == InitData ? NULL : &SafeInitData, FALSE);
+
   return Ret;
 }
 
@@ -804,10 +998,63 @@ HDC STDCALL
 NtGdiCreateIC(PUNICODE_STRING Driver,
               PUNICODE_STRING Device,
               PUNICODE_STRING Output,
-              CONST PDEVMODEW DevMode)
+              CONST PDEVMODEW InitData)
 {
-  /* FIXME: this should probably do something else...  */
-  return  NtGdiCreateDC(Driver, Device, Output, DevMode);
+  UNICODE_STRING SafeDriver, SafeDevice;
+  DEVMODEW SafeInitData;
+  HDC Ret;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  if(InitData)
+  {
+    _SEH_TRY
+    {
+      ProbeForRead(InitData,
+                   sizeof(DEVMODEW),
+                   1);
+      RtlCopyMemory(&SafeInitData,
+                    InitData,
+                    sizeof(DEVMODEW));
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      return NULL;
+    }
+    /* FIXME - InitData can have some more bytes! */
+  }
+
+  if(Driver)
+  {
+    Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      return NULL;
+    }
+  }
+
+  if(Device)
+  {
+    Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
+    if(!NT_SUCCESS(Status))
+    {
+      RtlFreeUnicodeString(&SafeDriver);
+      SetLastNtError(Status);
+      return NULL;
+    }
+  }
+
+  Ret = IntGdiCreateDC(NULL == Driver ? NULL : &SafeDriver,
+                       NULL == Device ? NULL : &SafeDevice, NULL,
+                       NULL == InitData ? NULL : &SafeInitData, TRUE);
+
+  return Ret;
 }
 
 BOOL STDCALL
@@ -815,13 +1062,19 @@ NtGdiDeleteDC(HDC  DCHandle)
 {
   PDC  DCToDelete;
 
+  if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
+    {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
+    }
+  
   DCToDelete = DC_LockDc(DCHandle);
   if (DCToDelete == NULL)
     {
-      return  FALSE;
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return FALSE;
     }
-  DPRINT( "Deleting DC\n" );
-  CHECKPOINT;
+
   /*  First delete all saved DCs  */
   while (DCToDelete->saveLevel)
   {
@@ -836,7 +1089,7 @@ NtGdiDeleteDC(HDC  DCHandle)
     }
     DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
     DCToDelete->saveLevel--;
-       DC_UnlockDc( savedHDC );
+    DC_UnlockDc( savedDC );
     NtGdiDeleteDC (savedHDC);
   }
 
@@ -850,9 +1103,12 @@ NtGdiDeleteDC(HDC  DCHandle)
     DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet  */
     if (DCToDelete->w.flags & DC_MEMORY)
     {
-      EngDeleteSurface (DCToDelete->Surface);
       NtGdiDeleteObject (DCToDelete->w.hFirstBitmap);
     }
+    if (DCToDelete->XlateBrush != NULL)
+      EngDeleteXlate(DCToDelete->XlateBrush);
+    if (DCToDelete->XlatePen != NULL)
+      EngDeleteXlate(DCToDelete->XlatePen);
   }
   if (DCToDelete->w.hClipRgn)
   {
@@ -873,7 +1129,7 @@ NtGdiDeleteDC(HDC  DCHandle)
 #if 0 /* FIXME */
   PATH_DestroyGdiPath (&DCToDelete->w.path);
 #endif
-  DC_UnlockDc( DCHandle );
+  DC_UnlockDc( DCToDelete );
   DC_FreeDC ( DCHandle );
 
   return TRUE;
@@ -886,6 +1142,7 @@ NtGdiDrawEscape(HDC  hDC,
                LPCSTR  lpszInData)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 INT STDCALL
@@ -895,27 +1152,66 @@ NtGdiEnumObjects(HDC  hDC,
                 LPARAM  lParam)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
 DC_GET_VAL( INT, NtGdiGetBkMode, w.backgroundMode )
-DC_GET_VAL_EX( NtGdiGetBrushOrgEx, IntGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
+DC_GET_VAL_EX( GetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT, x, y )
 DC_GET_VAL( HRGN, NtGdiGetClipRgn, w.hClipRgn )
 
 HGDIOBJ STDCALL
 NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
 {
-  UNIMPLEMENTED;
+  HGDIOBJ SelObject;
+  DC *dc;
+
+  if(!(dc = DC_LockDc(hDC)))
+  {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
+    return NULL;
+  }
+
+  switch(ObjectType)
+  {
+    case OBJ_PEN:
+      SelObject = dc->w.hPen;
+      break;
+    case OBJ_BRUSH:
+      SelObject = dc->w.hBrush;
+      break;
+    case OBJ_PAL:
+      DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
+      SelObject = NULL;
+      break;
+    case OBJ_FONT:
+      SelObject = dc->w.hFont;
+      break;
+    case OBJ_BITMAP:
+      SelObject = dc->w.hBitmap;
+      break;
+    case OBJ_COLORSPACE:
+      DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
+      SelObject = NULL;
+      break;
+    default:
+      SelObject = NULL;
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      break;
+  }
+
+  DC_UnlockDc(dc);
+  return SelObject;
 }
 
-DC_GET_VAL_EX ( NtGdiGetCurrentPositionEx, IntGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
+DC_GET_VAL_EX ( GetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT, x, y )
 
 BOOL FASTCALL
 IntGdiGetDCOrgEx(DC *dc, LPPOINT  Point)
 {
   Point->x = dc->w.DCOrgX;
   Point->y = dc->w.DCOrgY;
-  
+
   return  TRUE;
 }
 
@@ -925,32 +1221,44 @@ NtGdiGetDCOrgEx(HDC  hDC, LPPOINT  Point)
   BOOL Ret;
   DC *dc;
   POINT SafePoint;
-  NTSTATUS Status;
-  
+  NTSTATUS Status = STATUS_SUCCESS;
+
   if(!Point)
   {
     SetLastWin32Error(ERROR_INVALID_PARAMETER);
     return FALSE;
   }
-  
+
   dc = DC_LockDc(hDC);
   if(!dc)
   {
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return FALSE;
   }
-  
+
   Ret = IntGdiGetDCOrgEx(dc, &SafePoint);
-  
-  Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
+
+  _SEH_TRY
+  {
+    ProbeForWrite(Point,
+                  sizeof(POINT),
+                  1);
+    *Point = SafePoint;
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+
   if(!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
-    DC_UnlockDc(hDC);
+    DC_UnlockDc(dc);
     return FALSE;
   }
-  
-  DC_UnlockDc(hDC);
+
+  DC_UnlockDc(dc);
   return Ret;
 }
 
@@ -958,14 +1266,20 @@ COLORREF STDCALL
 NtGdiSetBkColor(HDC hDC, COLORREF color)
 {
   COLORREF oldColor;
-  PDC  dc = DC_LockDc(hDC);
+  PDC dc;
+  HBRUSH hBrush;
 
-  if ( !dc )
-    return 0x80000000;
+  if (!(dc = DC_LockDc(hDC)))
+  {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
+    return CLR_INVALID;
+  }
 
   oldColor = dc->w.backgroundColor;
   dc->w.backgroundColor = color;
-  DC_UnlockDc ( hDC );
+  hBrush = dc->w.hBrush;
+  DC_UnlockDc(dc);
+  NtGdiSelectObject(hDC, hBrush);
   return oldColor;
 }
 
@@ -978,16 +1292,18 @@ NtGdiGetDCState(HDC  hDC)
   dc = DC_LockDc(hDC);
   if (dc == NULL)
   {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
   }
 
   hnewdc = DC_AllocDC(NULL);
   if (hnewdc == NULL)
   {
-    DC_UnlockDc( hDC );
+    DC_UnlockDc(dc);
     return 0;
   }
   newdc = DC_LockDc( hnewdc );
+  /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
   ASSERT( newdc );
 
   newdc->w.flags            = dc->w.flags | DC_SAVED;
@@ -998,8 +1314,8 @@ NtGdiGetDCState(HDC  hDC)
   newdc->w.hFirstBitmap     = dc->w.hFirstBitmap;
 #if 0
   newdc->w.hDevice          = dc->w.hDevice;
-  newdc->w.hPalette         = dc->w.hPalette;
 #endif
+  newdc->w.hPalette         = dc->w.hPalette;
   newdc->w.totalExtent      = dc->w.totalExtent;
   newdc->w.bitsPerPixel     = dc->w.bitsPerPixel;
   newdc->w.ROPmode          = dc->w.ROPmode;
@@ -1027,12 +1343,10 @@ NtGdiGetDCState(HDC  hDC)
   newdc->w.CursPosX         = dc->w.CursPosX;
   newdc->w.CursPosY         = dc->w.CursPosY;
   newdc->w.ArcDirection     = dc->w.ArcDirection;
-#if 0
   newdc->w.xformWorld2Wnd   = dc->w.xformWorld2Wnd;
   newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
   newdc->w.xformVport2World = dc->w.xformVport2World;
   newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
-#endif
   newdc->wndOrgX            = dc->wndOrgX;
   newdc->wndOrgY            = dc->wndOrgY;
   newdc->wndExtX            = dc->wndExtX;
@@ -1044,6 +1358,7 @@ NtGdiGetDCState(HDC  hDC)
 
   newdc->hSelf = hnewdc;
   newdc->saveLevel = 0;
+  newdc->IsIC = dc->IsIC;
 
 #if 0
   PATH_InitGdiPath( &newdc->w.path );
@@ -1051,20 +1366,14 @@ NtGdiGetDCState(HDC  hDC)
 
   /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
 
-#if 0
   newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
-#endif
   if (dc->w.hClipRgn)
   {
     newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
     NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
   }
-  else
-  {
-    newdc->w.hClipRgn = 0;
-  }
-  DC_UnlockDc( hnewdc );
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( newdc );
+  DC_UnlockDc( dc );
   return  hnewdc;
 }
 
@@ -1118,12 +1427,10 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
        dc->w.CursPosY         = dcs->w.CursPosY;
        dc->w.ArcDirection     = dcs->w.ArcDirection;
 
-#if 0
        dc->w.xformWorld2Wnd   = dcs->w.xformWorld2Wnd;
        dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
        dc->w.xformVport2World = dcs->w.xformVport2World;
        dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
-#endif
 
        dc->wndOrgX            = dcs->wndOrgX;
        dc->wndOrgY            = dcs->wndOrgY;
@@ -1157,10 +1464,14 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
 
          dc->w.hClipRgn = 0;
        }
-       CLIPPING_UpdateGCRegion( dc );
-       DC_UnlockDc ( hDC );
+       {
+               int res;
+               res = CLIPPING_UpdateGCRegion( dc );
+               ASSERT ( res != ERROR );
+       }
+       DC_UnlockDc ( dc );
 #else
-       DC_UnlockDc ( hDC );
+       DC_UnlockDc ( dc );
        NtGdiSelectClipRgn(hDC, dcs->w.hClipRgn);
 #endif
 
@@ -1171,33 +1482,30 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
        NtGdiSetBkColor( hDC, dcs->w.backgroundColor);
        NtGdiSetTextColor( hDC, dcs->w.textColor);
 
+       NtGdiSelectPalette( hDC, dcs->w.hPalette, FALSE );
+
 #if 0
        GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
 #endif
       } else {
-       DC_UnlockDc(hDC);      
+       DC_UnlockDc(dc);
       }
-      DC_UnlockDc ( hDCSave );
+      DC_UnlockDc ( dcs );
     } else {
-      DC_UnlockDc ( hDC );
+      DC_UnlockDc ( dc );
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
     }
   }
+  else
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
 }
 
-INT STDCALL
-NtGdiGetDeviceCaps(HDC  hDC,
-                  INT  Index)
+INT FASTCALL
+IntGdiGetDeviceCaps(PDC dc, INT Index)
 {
-  PDC  dc;
-  INT  ret;
+  INT ret = 0;
   POINT  pt;
 
-  dc = DC_LockDc(hDC);
-  if (dc == NULL)
-  {
-    return 0;
-  }
-
   /* Retrieve capability */
   switch (Index)
   {
@@ -1290,7 +1598,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case PHYSICALWIDTH:
-      if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.x;
       }
@@ -1301,7 +1609,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case PHYSICALHEIGHT:
-      if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.y;
       }
@@ -1312,7 +1620,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case PHYSICALOFFSETX:
-      if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.x;
       }
@@ -1323,7 +1631,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case PHYSICALOFFSETY:
-      if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.y;
       }
@@ -1338,7 +1646,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case SCALINGFACTORX:
-      if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.x;
       }
@@ -1349,7 +1657,7 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
 
     case SCALINGFACTORY:
-      if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
+      if(IntGdiEscape(dc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
       {
         ret = pt.y;
       }
@@ -1384,9 +1692,28 @@ NtGdiGetDeviceCaps(HDC  hDC,
       break;
   }
 
+  return ret;
+}
+
+INT STDCALL
+NtGdiGetDeviceCaps(HDC  hDC,
+                  INT  Index)
+{
+  PDC  dc;
+  INT  ret;
+
+  dc = DC_LockDc(hDC);
+  if (dc == NULL)
+  {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
+    return 0;
+  }
+
+  ret = IntGdiGetDeviceCaps(dc, Index);
+
   DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
 
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return ret;
 }
 
@@ -1394,47 +1721,56 @@ DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
 DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
 
 INT FASTCALL
-IntGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
+IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
 {
-  PGDIOBJHDR  gdiObject;
-  INT  result = 0;
-  DWORD objectType;
+  PVOID GdiObject;
+  INT Result = 0;
+  DWORD ObjectType;
 
-  gdiObject = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
-  if (gdiObject == 0)
-    return 0;
-  
-  objectType = GDIOBJ_GetObjectType(handle);
-  switch(objectType)
-  {
-/*    case GDI_OBJECT_TYPE_PEN:
-      result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
-      break;
-    case GDI_OBJECT_TYPE_BRUSH:
-      result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
-       break; */
-    case GDI_OBJECT_TYPE_BITMAP:
-      result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
-      break;
-/*    case GDI_OBJECT_TYPE_FONT:
-      result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
-
-      // Fix the LOGFONT structure for the stock fonts
+  GdiObject = GDIOBJ_LockObj(Handle, GDI_OBJECT_TYPE_DONTCARE);
+  if (NULL == GdiObject)
+    {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+    }
 
-      if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
-      FixStockFontSizeW(handle, count, buffer);
-    break;
-    case GDI_OBJECT_TYPE_PALETTE:
-      result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
-      break; */
-    default:
-      DPRINT1("GDI object type 0x%08x not implemented\n", objectType);
-      break;
-  }
+  ObjectType = GDIOBJ_GetObjectType(Handle);
+  switch (ObjectType)
+    {
+#if 0
+      case GDI_OBJECT_TYPE_PEN:
+        Result = PEN_GetObject((PENOBJ *) GdiObject, Count, Buffer);
+        break;
+      case GDI_OBJECT_TYPE_BRUSH:
+        Result = BRUSH_GetObject((BRUSHOBJ *) GdiObject, Count, Buffer);
+        break;
+#endif
+      case GDI_OBJECT_TYPE_BITMAP:
+        Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer);
+        break;
+      case GDI_OBJECT_TYPE_FONT:
+        Result = FontGetObject((PTEXTOBJ) GdiObject, Count, Buffer);
+#if 0
+        // Fix the LOGFONT structure for the stock fonts
+        if (FIRST_STOCK_HANDLE <= Handle && Handle <= LAST_STOCK_HANDLE)
+          {
+            FixStockFontSizeW(Handle, Count, Buffer);
+          }
+#endif
+        break;
+#if 0
+      case GDI_OBJECT_TYPE_PALETTE:
+        Result = PALETTE_GetObject((PALETTEOBJ *) GdiObject, Count, Buffer);
+        break;
+#endif
+      default:
+        DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType);
+        break;
+    }
 
-  GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
+  GDIOBJ_UnlockObjByPtr(GdiObject);
 
-  return result;
+  return Result;
 }
 
 INT STDCALL
@@ -1442,23 +1778,53 @@ NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
 {
   INT Ret;
   LPVOID SafeBuf;
-  NTSTATUS Status;
+  NTSTATUS Status = STATUS_SUCCESS;
 
   if (count <= 0)
   {
     return 0;
   }
   
-  SafeBuf = ExAllocatePool(NonPagedPool, count);
+  _SEH_TRY
+  {
+    ProbeForWrite(buffer,
+                  count,
+                  1);
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+  
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    return 0;
+  }
+
+  SafeBuf = ExAllocatePoolWithTag(PagedPool, count, TAG_GDIOBJ);
   if(!SafeBuf)
   {
     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
     return 0;
   }
-  
+
   Ret = IntGdiGetObject(handle, count, SafeBuf);
-  
-  Status = MmCopyToCaller(buffer, SafeBuf, count);
+
+  _SEH_TRY
+  {
+    /* pointer already probed! */
+    RtlCopyMemory(buffer,
+                  SafeBuf,
+                  count);
+  }
+  _SEH_HANDLE
+  {
+    Status = _SEH_GetExceptionCode();
+  }
+  _SEH_END;
+
   ExFreePool(SafeBuf);
   if(!NT_SUCCESS(Status))
   {
@@ -1473,12 +1839,15 @@ DWORD STDCALL
 NtGdiGetObjectType(HANDLE handle)
 {
   GDIOBJHDR * ptr;
-  INT result = 0;
+  INT result;
   DWORD objectType;
 
   ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
   if (ptr == 0)
+  {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
+  }
 
   objectType = GDIOBJ_GetObjectType(handle);
   switch(objectType)
@@ -1522,11 +1891,13 @@ NtGdiGetObjectType(HANDLE handle)
     case GDI_OBJECT_TYPE_MEMDC:
       result = OBJ_MEMDC;
       break;
+
     default:
       DPRINT1("Magic 0x%08x not implemented\n", objectType);
+      result = 0;
       break;
   }
-  GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
+  GDIOBJ_UnlockObjByPtr(ptr);
   return result;
 }
 
@@ -1535,36 +1906,39 @@ DC_GET_VAL( INT, NtGdiGetROP2, w.ROPmode )
 DC_GET_VAL( INT, NtGdiGetStretchBltMode, w.stretchBltMode )
 DC_GET_VAL( UINT, NtGdiGetTextAlign, w.textAlign )
 DC_GET_VAL( COLORREF, NtGdiGetTextColor, w.textColor )
-DC_GET_VAL_EX( NtGdiGetViewportExtEx, IntGetViewportExtEx, vportExtX, vportExtY, SIZE )
-DC_GET_VAL_EX( NtGdiGetViewportOrgEx, IntGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
-DC_GET_VAL_EX( NtGdiGetWindowExtEx, IntGetWindowExtEx, wndExtX, wndExtY, SIZE )
-DC_GET_VAL_EX( NtGdiGetWindowOrgEx, IntGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
+DC_GET_VAL_EX( GetViewportExtEx, vportExtX, vportExtY, SIZE, cx, cy )
+DC_GET_VAL_EX( GetViewportOrgEx, vportOrgX, vportOrgY, POINT, x, y )
+DC_GET_VAL_EX( GetWindowExtEx, wndExtX, wndExtY, SIZE, cx, cy )
+DC_GET_VAL_EX( GetWindowOrgEx, wndOrgX, wndOrgY, POINT, x, y )
 
 HDC STDCALL
 NtGdiResetDC(HDC  hDC, CONST DEVMODEW *InitData)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 BOOL STDCALL
 NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
 {
-  PDC  dc, dcs;
-  BOOL  success;
+  PDC dc, dcs;
+  BOOL success;
+
+  DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC, SaveLevel);
 
   dc = DC_LockDc(hDC);
-  if(!dc)
+  if (!dc)
   {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
     return FALSE;
   }
 
   if (SaveLevel == -1)
-  {
     SaveLevel = dc->saveLevel;
-  }
 
   if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
   {
+    DC_UnlockDc(dc);
     return FALSE;
   }
 
@@ -1576,13 +1950,14 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
     dcs = DC_LockDc (hdcs);
     if (dcs == NULL)
     {
+      DC_UnlockDc(dc);
       return FALSE;
     }
     DC_SetNextDC (dcs, DC_GetNextDC (dcs));
     if (--dc->saveLevel < SaveLevel)
       {
-       DC_UnlockDc( hDC );
-        DC_UnlockDc( hdcs );
+       DC_UnlockDc( dc );
+        DC_UnlockDc( dcs );
         NtGdiSetDCState(hDC, hdcs);
 #if 0
         if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
@@ -1600,11 +1975,11 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
       }
     else
       {
-      DC_UnlockDc( hdcs );
+      DC_UnlockDc( dcs );
       }
     NtGdiDeleteDC (hdcs);
   }
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return  success;
 }
 
@@ -1615,6 +1990,8 @@ NtGdiSaveDC(HDC  hDC)
   PDC  dc, dcs;
   INT  ret;
 
+  DPRINT("NtGdiSaveDC(%lx)\n", hDC);
+
   if (!(hdcs = NtGdiGetDCState(hDC)))
   {
     return 0;
@@ -1623,12 +2000,14 @@ NtGdiSaveDC(HDC  hDC)
   dcs = DC_LockDc (hdcs);
   if (dcs == NULL)
   {
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
   }
   dc = DC_LockDc (hDC);
   if (dc == NULL)
   {
-    DC_UnlockDc(dc);
+    DC_UnlockDc(dcs);
+    SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
   }
 
@@ -1649,8 +2028,8 @@ NtGdiSaveDC(HDC  hDC)
   DC_SetNextDC (dcs, DC_GetNextDC (dc));
   DC_SetNextDC (dc, hdcs);
   ret = ++dc->saveLevel;
-  DC_UnlockDc( hdcs );
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dcs );
+  DC_UnlockDc( dc );
 
   return  ret;
 }
@@ -1662,16 +2041,12 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
   HGDIOBJ objOrg = NULL; // default to failure
   BITMAPOBJ *pb;
   PDC dc;
-  PPENOBJ pen;
-  PBRUSHOBJ brush;
-  PXLATEOBJ XlateObj;
-  PPALGDI PalGDI;
+  PGDIBRUSHOBJ pen;
+  PGDIBRUSHOBJ brush;
+  XLATEOBJ *XlateObj;
   DWORD objectType;
-  COLORREF *ColorMap;
-  COLORREF MonoColorMap[2];
-  ULONG NumColors, Index;
   HRGN hVisRgn;
-  USHORT Mode;
+  BOOLEAN Failed;
 
   if(!hDC || !hGDIObj) return NULL;
 
@@ -1687,168 +2062,116 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
   switch (objectType)
   {
     case GDI_OBJECT_TYPE_PEN:
-      objOrg = NULL;
-      /* Convert the color of the pen to the format of the DC */
-      PalGDI = PALETTE_LockPalette(dc->w.hPalette);
-      if (NULL != PalGDI)
-        {
-          Mode = PalGDI->Mode;
-          PALETTE_UnlockPalette(dc->w.hPalette);
-          XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
-          if (NULL != XlateObj)
-            {
-              pen = PENOBJ_LockPen((HPEN) hGDIObj);
-              if (NULL != pen)
-                {
-                  pen->iSolidColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
-                  PENOBJ_UnlockPen((HPEN) hGDIObj);
-                  objOrg = (HGDIOBJ)dc->w.hPen;
-                  dc->w.hPen = hGDIObj;
-                }
-              else
-                {
-                  SetLastWin32Error(ERROR_INVALID_HANDLE);
-                }
-              EngDeleteXlate(XlateObj);
-           }
-          else
-            {
-              SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-            }
-        }
-      else
-        {
-          SetLastWin32Error(ERROR_INVALID_HANDLE);
-        }
+      pen = PENOBJ_LockPen((HPEN) hGDIObj);
+      if (pen == NULL)
+      {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        break;
+      }
+
+      XlateObj = IntGdiCreateBrushXlate(dc, pen, &Failed);
+      PENOBJ_UnlockPen(pen);
+      if (Failed)
+      {
+        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        break;
+      }
+
+      objOrg = (HGDIOBJ)dc->w.hPen;
+      dc->w.hPen = hGDIObj;
+      if (dc->XlatePen != NULL)
+        EngDeleteXlate(dc->XlatePen);
+      dc->XlatePen = XlateObj;
       break;
 
     case GDI_OBJECT_TYPE_BRUSH:
-      objOrg = NULL;
-      /* Convert the color of the brush to the format of the DC */
-      PalGDI = PALETTE_LockPalette(dc->w.hPalette);
-      if (NULL != PalGDI)
-        {
-         Mode = PalGDI->Mode;
-          PALETTE_UnlockPalette(dc->w.hPalette);
-          XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
-          if (NULL != XlateObj)
-            {
-              brush = BRUSHOBJ_LockBrush((HBRUSH) hGDIObj);
-              if (NULL != brush)
-                {
-                  brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
-                  BRUSHOBJ_UnlockBrush((HBRUSH) hGDIObj);
-                  objOrg = (HGDIOBJ)dc->w.hBrush;
-                  dc->w.hBrush = (HBRUSH) hGDIObj;
-                }
-              else
-                {
-                  SetLastWin32Error(ERROR_INVALID_HANDLE);
-                }
-              EngDeleteXlate(XlateObj);
-            }
-          else
-            {
-              SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-            }
-        }
-      else
-        {
-          SetLastWin32Error(ERROR_INVALID_HANDLE);
-        }
+      brush = BRUSHOBJ_LockBrush((HPEN) hGDIObj);
+      if (brush == NULL)
+      {
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        break;
+      }
+
+      XlateObj = IntGdiCreateBrushXlate(dc, brush, &Failed);
+      BRUSHOBJ_UnlockBrush(brush);
+      if (Failed)
+      {
+        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        break;
+      }
+
+      objOrg = (HGDIOBJ)dc->w.hBrush;
+      dc->w.hBrush = hGDIObj;
+      if (dc->XlateBrush != NULL)
+        EngDeleteXlate(dc->XlateBrush);
+      dc->XlateBrush = XlateObj;
       break;
 
     case GDI_OBJECT_TYPE_FONT:
-      objOrg = (HGDIOBJ)dc->w.hFont;
-      dc->w.hFont = (HFONT) hGDIObj;
-      TextIntRealizeFont(dc->w.hFont);
+      if(NT_SUCCESS(TextIntRealizeFont((HFONT)hGDIObj)))
+      {
+        objOrg = (HGDIOBJ)dc->w.hFont;
+        dc->w.hFont = (HFONT) hGDIObj;
+      }
       break;
 
     case GDI_OBJECT_TYPE_BITMAP:
       // must be memory dc to select bitmap
       if (!(dc->w.flags & DC_MEMORY))
         {
-          DC_UnlockDc(hDC);
+          DC_UnlockDc(dc);
           return NULL;
         }
       pb = BITMAPOBJ_LockBitmap(hGDIObj);
       if (NULL == pb)
        {
          SetLastWin32Error(ERROR_INVALID_HANDLE);
-          DC_UnlockDc(hDC);
+          DC_UnlockDc(dc);
          return NULL;
        }
       objOrg = (HGDIOBJ)dc->w.hBitmap;
 
       /* Release the old bitmap, lock the new one and convert it to a SURF */
-      EngDeleteSurface(dc->Surface);
       dc->w.hBitmap = hGDIObj;
-      dc->Surface = BitmapToSurf(pb, dc->GDIDevice);
 
       // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
       if(pb->dib)
       {
         dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
-
-        if(pb->dib->dsBmih.biBitCount <= 8)
-        {
-          if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
-          if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
-          if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
-
-          ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(COLORREF) * NumColors, TAG_DC);
-          ASSERT(ColorMap);
-          for (Index = 0; Index < NumColors; Index++)
-          {
-            ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
-                                  pb->ColorMap[Index].rgbGreen,
-                                  pb->ColorMap[Index].rgbBlue);
-          }
-          dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
-          ExFreePool(ColorMap);
-        }
-        else if ( 16 == pb->dib->dsBmih.biBitCount )
-        {
-          dc->w.hPalette = PALETTE_AllocPalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
-        }
-        else if(pb->dib->dsBmih.biBitCount >= 24)
-        {
-          dc->w.hPalette = PALETTE_AllocPalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
-        }
+        dc->w.hPalette = pb->hDIBPalette;
       }
       else
       {
-        dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
-        if (1 == dc->w.bitsPerPixel)
-          {
-            MonoColorMap[0] = RGB(0, 0, 0);
-            MonoColorMap[1] = RGB(255, 255, 255);
-            dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, 2, MonoColorMap, 0, 0, 0);
-          }
-        else
-          {
-            dc->w.hPalette = dc->DevInfo->hpalDefault;
-          }
+        dc->w.bitsPerPixel = BitsPerFormat(pb->SurfObj.iBitmapFormat);
+        dc->w.hPalette = dc->DevInfo->hpalDefault;
       }
 
-      DC_UnlockDc ( hDC );
-      hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->size.cx, pb->size.cy );
+      /* Reselect brush and pen to regenerate the XLATEOBJs. */
+      NtGdiSelectObject ( hDC, dc->w.hBrush );
+      NtGdiSelectObject ( hDC, dc->w.hPen );
+
+      DC_UnlockDc ( dc );
+      hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->SurfObj.sizlBitmap.cx, pb->SurfObj.sizlBitmap.cy );
+      BITMAPOBJ_UnlockBitmap( pb );
       NtGdiSelectVisRgn ( hDC, hVisRgn );
       NtGdiDeleteObject ( hVisRgn );
-      BITMAPOBJ_UnlockBitmap(hGDIObj);
 
       return objOrg;
 
-#if UPDATEREGIONS
     case GDI_OBJECT_TYPE_REGION:
-      DC_UnlockDc ( hDC );
-      SelectClipRgn(hDC, (HRGN)hGDIObj);
-      return NULL;
-#endif
+      DC_UnlockDc (dc);
+      /*
+       * The return value is one of the following values:
+       *  SIMPLEREGION
+       *  COMPLEXREGION
+       *  NULLREGION
+       */
+      return (HGDIOBJ) NtGdiSelectClipRgn(hDC, (HRGN) hGDIObj);
+
     default:
       break;
   }
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( dc );
   return objOrg;
 }
 
@@ -1860,6 +2183,7 @@ NtGdiSetHookFlags(HDC hDC, WORD Flags)
 
   if (NULL == dc)
     {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
       return 0;
     }
 
@@ -1879,7 +2203,7 @@ NtGdiSetHookFlags(HDC hDC, WORD Flags)
       dc->w.flags &= ~DC_DIRTY;
     }
 
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(dc);
 
   return wRet;
 }
@@ -1898,7 +2222,7 @@ DC_AllocDC(PUNICODE_STRING Driver)
   PDC  NewDC;
   HDC  hDC;
   PWSTR Buf = NULL;
-  
+
   if (Driver != NULL)
   {
     Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
@@ -1909,7 +2233,7 @@ DC_AllocDC(PUNICODE_STRING Driver)
     RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
   }
 
-  hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GDI_OBJECT_TYPE_DC, (GDICLEANUPPROC) DC_InternalDeleteDC);
+  hDC = (HDC) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_DC);
   if (hDC == NULL)
   {
     if(Buf)
@@ -1920,7 +2244,8 @@ DC_AllocDC(PUNICODE_STRING Driver)
   }
 
   NewDC = DC_LockDc(hDC);
-  
+  /* FIXME - Handle NewDC == NULL! */
+
   if (Driver != NULL)
   {
     RtlCopyMemory(&NewDC->DriverName, Driver, sizeof(UNICODE_STRING));
@@ -1937,11 +2262,19 @@ DC_AllocDC(PUNICODE_STRING Driver)
   NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
   NewDC->w.vport2WorldValid = TRUE;
   NewDC->w.MapMode = MM_TEXT;
+  NewDC->wndExtX = 1.0f;
+  NewDC->wndExtY = 1.0f;
+  NewDC->vportExtX = 1.0f;
+  NewDC->vportExtY = 1.0f;
+  NewDC->w.textColor = 0;
+  NewDC->w.backgroundColor = 0xffffff;
 
   NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
   TextIntRealizeFont(NewDC->w.hFont);
 
-  DC_UnlockDc(hDC);
+  NewDC->w.hPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
+
+  DC_UnlockDc(NewDC);
 
   return  hDC;
 }
@@ -1964,24 +2297,29 @@ DC_InitDC(HDC  DCHandle)
   NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
   //NtGdiSelectObject(DCHandle, hFont);
 
-//  CLIPPING_UpdateGCRegion(DCToInit);
-
+/*
+  {
+    int res;
+    res = CLIPPING_UpdateGCRegion(DCToInit);
+    ASSERT ( res != ERROR );
+  }
+*/
 }
 
 VOID FASTCALL
 DC_FreeDC(HDC  DCToFree)
 {
-  if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC, GDIOBJFLAG_DEFAULT))
+  if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC))
   {
     DPRINT("DC_FreeDC failed\n");
   }
 }
 
-BOOL FASTCALL
-DC_InternalDeleteDC( PDC DCToDelete )
+BOOL INTERNAL_CALL
+DC_Cleanup(PVOID ObjectBody)
 {
-
-  RtlFreeUnicodeString(&DCToDelete->DriverName);
+  PDC pDC = (PDC)ObjectBody;
+  RtlFreeUnicodeString(&pDC->DriverName);
   return TRUE;
 }
 
@@ -2004,8 +2342,8 @@ DC_UpdateXforms(PDC  dc)
   FLOAT  scaleX, scaleY;
 
   /* Construct a transformation to do the window-to-viewport conversion */
-  scaleX = (dc->wndExtX ? (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX : 0.0);
-  scaleY = (dc->wndExtY ? (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY : 0.0);
+  scaleX = (dc->wndExtX ? (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX : 0.0f);
+  scaleY = (dc->wndExtY ? (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY : 0.0f);
   xformWnd2Vport.eM11 = scaleX;
   xformWnd2Vport.eM12 = 0.0;
   xformWnd2Vport.eM21 = 0.0;
@@ -2063,8 +2401,490 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
         {
           GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
         }
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(DC);
     }
 }
 
+BOOL FASTCALL
+IntIsPrimarySurface(SURFOBJ *SurfObj)
+{
+   if (PrimarySurface.Handle == NULL)
+     {
+       return FALSE;
+     }
+   return SurfObj->hsurf == PrimarySurface.Handle;
+}
+
+/*
+ * Returns the color of the brush or pen that is currently selected into the DC.
+ * This function is called from GetDCBrushColor() and GetDCPenColor()
+ */
+COLORREF FASTCALL
+IntGetDCColor(HDC hDC, ULONG Object)
+{
+   /*
+    * The previous implementation was completly incorrect. It modified the
+    * brush that was currently selected into the device context, but in fact
+    * the DC pen/brush color should be stored directly in the device context
+    * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
+    * The actual color is then used when DC_BRUSH/DC_PEN object is selected
+    * into the device context and BRUSHOBJ for drawing is composed (belongs
+    * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
+    * the implementation should be moved to user mode GDI32.dll when UM
+    * mapped GDI objects will be implemented.
+    */
+
+   DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
+   return 0xFFFFFF; /* The default DC color. */
+}
+
+/*
+ * Changes the color of the brush or pen that is currently selected into the DC.
+ * This function is called from SetDCBrushColor() and SetDCPenColor()
+ */
+COLORREF FASTCALL
+IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color)
+{
+   /* See the comment in IntGetDCColor. */
+
+   DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
+   return CLR_INVALID;
+}
+
+#define SIZEOF_DEVMODEW_300 188
+#define SIZEOF_DEVMODEW_400 212
+#define SIZEOF_DEVMODEW_500 220
+
+/*! \brief Enumerate possible display settings for the given display...
+ *
+ * \todo Make thread safe!?
+ * \todo Don't ignore pDeviceName
+ * \todo Implement non-raw mode (only return settings valid for driver and monitor)
+ */
+BOOL FASTCALL
+IntEnumDisplaySettings(
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN DWORD iModeNum,
+  IN OUT LPDEVMODEW pDevMode,
+  IN DWORD dwFlags)
+{
+  static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
+  static DWORD SizeOfCachedDevModes = 0;
+  PDEVMODEW CachedMode = NULL;
+  DEVMODEW DevMode;
+  INT Size, OldSize;
+  ULONG DisplayNumber = 0; /* only default display supported */
+
+  DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
+  DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
+  if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
+      pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
+      pDevMode->dmSize != SIZEOF_DEVMODEW_500)
+  {
+    SetLastWin32Error(STATUS_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  if (iModeNum == ENUM_CURRENT_SETTINGS)
+  {
+    CachedMode = &PrimarySurface.DMW;
+    ASSERT(CachedMode->dmSize > 0);
+  }
+  else if (iModeNum == ENUM_REGISTRY_SETTINGS)
+  {
+    RtlZeroMemory(&DevMode, sizeof (DevMode));
+    DevMode.dmSize = sizeof (DevMode);
+    DevMode.dmDriverExtra = 0;
+    if (SetupDevMode(&DevMode, DisplayNumber))
+      CachedMode = &DevMode;
+    else
+    {
+      SetLastWin32Error(0); /* FIXME: use error code */
+      return FALSE;
+    }
+    /* FIXME: Maybe look for the matching devmode supplied by the
+     *        driver so we can provide driver private/extra data?
+     */
+  }
+  else
+  {
+    if (iModeNum == 0 || CachedDevModes == NULL) /* query modes from drivers */
+    {
+      BOOL PrimarySurfaceCreated = FALSE;
+      UNICODE_STRING DriverFileNames;
+      LPWSTR CurrentName;
+      DRVENABLEDATA DrvEnableData;
+
+      /* Retrieve DDI driver names from registry */
+      RtlInitUnicodeString(&DriverFileNames, NULL);
+      if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
+      {
+        DPRINT1("FindDriverFileNames failed\n");
+        return FALSE;
+      }
+
+      if (!HalQueryDisplayOwnership())
+      {
+        IntCreatePrimarySurface();
+        PrimarySurfaceCreated = TRUE;
+      }
+
+      /*
+       * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
+       * scan all of them until a good one found.
+       */
+      CurrentName = DriverFileNames.Buffer;
+      for (;CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR));
+           CurrentName += wcslen(CurrentName) + 1)
+      {
+        INT i;
+        PGD_ENABLEDRIVER GDEnableDriver;
+
+        /* Get the DDI driver's entry point */
+        GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
+        if (NULL == GDEnableDriver)
+        {
+          DPRINT("FindDDIDriver failed for %S\n", CurrentName);
+          continue;
+        }
+
+        /*  Call DDI driver's EnableDriver function  */
+        RtlZeroMemory(&DrvEnableData, sizeof (DrvEnableData));
+
+        if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData), &DrvEnableData))
+        {
+          DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
+          continue;
+        }
+
+        CachedDevModesEnd = CachedDevModes;
+
+        /* find DrvGetModes function */
+        for (i = 0; i < DrvEnableData.c; i++)
+        {
+          PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
+          PGD_GETMODES GetModes;
+          INT SizeNeeded, SizeUsed;
+
+          if (DrvFn->iFunc != INDEX_DrvGetModes)
+            continue;
+
+          GetModes = (PGD_GETMODES)DrvFn->pfn;
+
+          /* make sure we have enough memory to hold the modes */
+          SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
+          if (SizeNeeded <= 0)
+          {
+            DPRINT("DrvGetModes failed for %S\n", CurrentName);
+            break;
+          }
+
+          SizeUsed = CachedDevModesEnd - CachedDevModes;
+          if (SizeOfCachedDevModes - SizeUsed < SizeNeeded)
+          {
+            PVOID NewBuffer;
+
+            SizeOfCachedDevModes += SizeNeeded;
+            NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes);
+            if (NewBuffer == NULL)
+            {
+              /* clean up */
+              ExFreePool(CachedDevModes);
+              SizeOfCachedDevModes = 0;
+              CachedDevModes = NULL;
+              CachedDevModesEnd = NULL;
+              if (PrimarySurfaceCreated)
+              {
+                IntDestroyPrimarySurface();
+              }
+              SetLastWin32Error(STATUS_NO_MEMORY);
+              return FALSE;
+            }
+            if (CachedDevModes != NULL)
+            {
+              RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed);
+              ExFreePool(CachedDevModes);
+            }
+            CachedDevModes = NewBuffer;
+            CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
+          }
+
+          /* query modes */
+          SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
+                                SizeOfCachedDevModes - SizeUsed,
+                                CachedDevModesEnd);
+          if (SizeNeeded <= 0)
+          {
+            DPRINT("DrvGetModes failed for %S\n", CurrentName);
+          }
+          else
+          {
+            CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded);
+          }
+          break;
+        }
+      }
+
+      if (PrimarySurfaceCreated)
+      {
+        IntDestroyPrimarySurface();
+      }
+
+      RtlFreeUnicodeString(&DriverFileNames);
+    }
+
+    /* return cached info */
+    CachedMode = CachedDevModes;
+    if (CachedMode >= CachedDevModesEnd)
+    {
+      SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
+      return FALSE;
+    }
+    while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
+    {
+      assert(CachedMode->dmSize > 0);
+      CachedMode = (DEVMODEW *)((PCHAR)CachedMode + CachedMode->dmSize + CachedMode->dmDriverExtra);
+    }
+    if (CachedMode >= CachedDevModesEnd)
+    {
+      SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
+      return FALSE;
+    }
+  }
+
+  ASSERT(CachedMode != NULL);
+
+  Size = OldSize = pDevMode->dmSize;
+  if (Size > CachedMode->dmSize)
+    Size = CachedMode->dmSize;
+  RtlCopyMemory(pDevMode, CachedMode, Size);
+  RtlZeroMemory((PCHAR)pDevMode + Size, OldSize - Size);
+  pDevMode->dmSize = OldSize;
+
+  Size = OldSize = pDevMode->dmDriverExtra;
+  if (Size > CachedMode->dmDriverExtra)
+    Size = CachedMode->dmDriverExtra;
+  RtlCopyMemory((PCHAR)pDevMode + pDevMode->dmSize,
+                (PCHAR)CachedMode + CachedMode->dmSize, Size);
+  RtlZeroMemory((PCHAR)pDevMode + pDevMode->dmSize + Size, OldSize - Size);
+  pDevMode->dmDriverExtra = OldSize;
+
+  return TRUE;
+}
+LONG
+FASTCALL
+IntChangeDisplaySettings(
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN LPDEVMODEW DevMode,
+  IN DWORD dwflags,
+  IN PVOID lParam  OPTIONAL)
+{
+  BOOLEAN Global = FALSE;
+  BOOLEAN NoReset = FALSE;
+  BOOLEAN Reset = FALSE;
+  BOOLEAN SetPrimary = FALSE;
+  LONG Ret=0;
+  NTSTATUS Status ;
+
+  DPRINT1("display flag : %x\n",dwflags);
+
+  if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+  {
+    /* Check global, reset and noreset flags */
+    if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
+      Global = TRUE;
+    if ((dwflags & CDS_NORESET) == CDS_NORESET)
+      NoReset = TRUE;
+    dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
+  }
+  if ((dwflags & CDS_RESET) == CDS_RESET)
+    Reset = TRUE;
+  if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
+    SetPrimary = TRUE;
+  dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
+
+  if (Reset && NoReset)
+    return DISP_CHANGE_BADFLAGS;
+
+  if (dwflags == 0)
+  {
+   /* Dynamically change graphics mode */
+   DPRINT1("flag 0 UNIMPLEMENT \n");
+   return DISP_CHANGE_FAILED;
+  }
+
+  if ((dwflags & CDS_TEST) == CDS_TEST)
+  {
+   /* Test reslution */
+   dwflags &= ~CDS_TEST;
+   DPRINT1("flag CDS_TEST UNIMPLEMENT");
+   Ret = DISP_CHANGE_FAILED;
+  }
+  
+  if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
+  {
+   DEVMODE lpDevMode;
+   /* Full Screen */
+   dwflags &= ~CDS_FULLSCREEN;
+   DPRINT1("flag CDS_FULLSCREEN partially implemented");
+   Ret = DISP_CHANGE_FAILED;
+
+   lpDevMode.dmBitsPerPel =0;
+   lpDevMode.dmPelsWidth  =0;
+   lpDevMode.dmPelsHeight =0;
+   lpDevMode.dmDriverExtra =0;
+
+   lpDevMode.dmSize = sizeof(DEVMODE);
+   Status = IntEnumDisplaySettings(pDeviceName,  ENUM_CURRENT_SETTINGS, &lpDevMode, 0);
+   if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+
+   DPRINT1("Req Mode     : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel);
+   DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel);
+
+
+   if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) &&
+       (lpDevMode.dmPelsWidth  == DevMode->dmPelsWidth) &&
+       (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight))
+          Ret = DISP_CHANGE_SUCCESSFUL; 
+  }
+
+  if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
+  {  
+    dwflags &= ~CDS_VIDEOPARAMETERS;
+    if (lParam == NULL) Ret=DISP_CHANGE_BADPARAM;
+       else
+       {
+               DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
+               Ret = DISP_CHANGE_FAILED;
+       }
+
+  }    
+
+  if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+  {  
+  
+               UNICODE_STRING ObjectName;
+               UNICODE_STRING KernelModeName;
+               WCHAR KernelModeNameBuffer[256];
+               UNICODE_STRING RegistryKey;
+               WCHAR RegistryKeyBuffer[512];
+               PDEVICE_OBJECT DeviceObject;            
+               ULONG LastSlash;
+               OBJECT_ATTRIBUTES ObjectAttributes;
+               HANDLE DevInstRegKey;
+               ULONG NewValue;
+               
+
+               DPRINT1("set CDS_UPDATEREGISTRY \n");
+               
+               dwflags &= ~CDS_UPDATEREGISTRY; 
+
+               /* Get device name (pDeviceName is "\.\xxx") */
+               for (LastSlash = pDeviceName->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
+               {
+                       if (pDeviceName->Buffer[LastSlash - 1] == L'\\')
+                               break;
+               }
+               
+               if (LastSlash == 0) return DISP_CHANGE_RESTART;
+               ObjectName = *pDeviceName;
+               ObjectName.Length -= LastSlash * sizeof(WCHAR);
+               ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
+               ObjectName.Buffer += LastSlash;
+
+               KernelModeName.Length = 0;
+               KernelModeName.MaximumLength = sizeof(KernelModeNameBuffer);
+               KernelModeName.Buffer = KernelModeNameBuffer;
+
+               /* Open \??\xxx (ex: "\??\DISPLAY1") */
+               Status = RtlAppendUnicodeToString(&KernelModeName, L"\\??\\");
+               
+               if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+               Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
+               
+               if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+               Status = ObReferenceObjectByName(
+                       &KernelModeName,
+                       OBJ_CASE_INSENSITIVE,
+                       NULL,
+                       0,
+                       IoDeviceObjectType,
+                       KernelMode,
+                       NULL,
+                       (PVOID*)&DeviceObject);
+
+               if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+               /* Get associated driver name (ex: "VBE") */
+               for (LastSlash = DeviceObject->DriverObject->DriverName.Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
+               {
+                       if (DeviceObject->DriverObject->DriverName.Buffer[LastSlash - 1] == L'\\')
+                               break;
+               }
+
+               if (LastSlash == 0) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
+               ObjectName = DeviceObject->DriverObject->DriverName;
+               ObjectName.Length -= LastSlash * sizeof(WCHAR);
+               ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
+               ObjectName.Buffer += LastSlash;
+
+               RegistryKey.Length = 0;
+               RegistryKey.MaximumLength = sizeof(RegistryKeyBuffer);
+               RegistryKey.Buffer = RegistryKeyBuffer;
+
+               /* Open registry key */
+               Status = RtlAppendUnicodeToString(&RegistryKey,
+                       L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
+               
+               if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
+               Status = RtlAppendUnicodeStringToString(&RegistryKey, &ObjectName);
+
+               if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
+               Status = RtlAppendUnicodeToString(&RegistryKey,
+                       L"\\Device0");
+
+               if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
+
+               InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
+                       OBJ_CASE_INSENSITIVE, NULL, NULL);
+               Status = ZwOpenKey(&DevInstRegKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes);
+               ObDereferenceObject(DeviceObject);
+               if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
+
+               /* Update needed fields */
+               if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
+               {
+                       RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel");
+                       NewValue = DevMode->dmBitsPerPel;
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
+               }
+
+               if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
+               {
+                       RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution");
+                       NewValue = DevMode->dmPelsWidth;                        
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
+               }
+
+               if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
+               {
+                       RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution");
+                       NewValue = DevMode->dmPelsHeight;
+                       Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));                 
+               }
+
+               ZwClose(DevInstRegKey);
+               if (NT_SUCCESS(Status))
+                       Ret = DISP_CHANGE_RESTART;
+               else
+                       /* return DISP_CHANGE_NOTUPDATED when we can save to reg only vaild for NT */ 
+                       Ret = DISP_CHANGE_NOTUPDATED;
+               
+    }
+ if (dwflags != 0)  
+    Ret = DISP_CHANGE_BADFLAGS;
+
+  return Ret;
+}
+
 /* EOF */