Fix a typo.
[reactos.git] / reactos / subsys / win32k / objects / dc.c
index 360f3f6..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.135 2004/05/14 16:55:18 navaraf Exp $
+/* $Id$
  *
  * DC.C - Device context functions
  *
  */
+
 #include <w32k.h>
 
+#define NDEBUG
+#include <debug.h>
+
 #ifndef OBJ_COLORSPACE
 #define OBJ_COLORSPACE (14)
 #endif
@@ -47,7 +51,7 @@ func_type STDCALL  func_name( HDC hdc ) \
     return 0;                       \
   }                                 \
   ft = dc->dc_field;                \
-  DC_UnlockDc( hdc );                          \
+  DC_UnlockDc(dc);                             \
   return ft;                        \
 }
 
@@ -65,7 +69,7 @@ VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
 } \
 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
 { \
-  NTSTATUS Status; \
+  NTSTATUS Status = STATUS_SUCCESS; \
   type Safept; \
   PDC dc; \
   if(!pt) \
@@ -79,8 +83,19 @@ BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
     return FALSE; \
   } \
   Int##FuncName( dc, &Safept); \
-  DC_UnlockDc(hdc); \
-  Status = MmCopyToCaller(pt, &Safept, sizeof( type )); \
+  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); \
@@ -107,7 +122,7 @@ INT STDCALL  func_name( HDC hdc, INT mode ) \
   } \
   prevMode = dc->dc_field;                  \
   dc->dc_field = mode;                      \
-  DC_UnlockDc ( hdc );                    \
+  DC_UnlockDc ( dc );                    \
   return prevMode;                          \
 }
 
@@ -120,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;
@@ -158,7 +173,7 @@ NtGdiCreateCompatableDC(HDC hDC)
 
   if (NULL == hNewDC)
     {
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(OrigDC);
       if (NULL != DisplayDC)
         {
           NtGdiDeleteDC(DisplayDC);
@@ -169,9 +184,9 @@ NtGdiCreateCompatableDC(HDC hDC)
 
   /* Copy information from original DC to new DC  */
   NewDC->hSelf = hNewDC;
+  NewDC->IsIC = FALSE;
 
   NewDC->PDev = OrigDC->PDev;
-  NewDC->DMW = OrigDC->DMW;
   memcpy(NewDC->FillPatternSurfaces,
          OrigDC->FillPatternSurfaces,
          sizeof OrigDC->FillPatternSurfaces);
@@ -193,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)
         {
@@ -206,21 +221,19 @@ NtGdiCreateCompatableDC(HDC hDC)
   NewDC->w.hBitmap      = hBitmap;
   NewDC->w.hFirstBitmap = hBitmap;
   NewDC->GDIDevice      = OrigDC->GDIDevice;
-  pb = BITMAPOBJ_LockBitmap(hBitmap);
-  NewDC->Surface = (HSURF)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);
@@ -392,7 +405,7 @@ SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
   if (Valid)
     {
       ProfilePath = ExAllocatePoolWithTag(PagedPool,
-                                          (wcslen(RegistryPath.Buffer) + 
+                                          (wcslen(RegistryPath.Buffer) +
                                            wcslen(Insert) + 1) * sizeof(WCHAR),
                                           TAG_DC);
       if (NULL != ProfilePath)
@@ -456,13 +469,11 @@ SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
   return Valid;
 }
 
-BOOL FASTCALL
-IntCreatePrimarySurface()
+static BOOL FASTCALL
+IntPrepareDriver()
 {
    PGD_ENABLEDRIVER GDEnableDriver;
    DRVENABLEDATA DED;
-   SURFOBJ *SurfObj;
-   PSURFGDI SurfGDI;
    UNICODE_STRING DriverFileNames;
    PWSTR CurrentName;
    BOOL GotDriver;
@@ -474,7 +485,6 @@ IntCreatePrimarySurface()
       DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
 
       RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
-      ExInitializeFastMutex(&PrimarySurface.DriverLock);
 
       PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
 
@@ -490,7 +500,6 @@ IntCreatePrimarySurface()
       if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
       {
          DPRINT1("FindDriverFileNames failed\n");
-         /* return FALSE; */
          continue;
       }
 
@@ -501,7 +510,7 @@ IntCreatePrimarySurface()
       CurrentName = DriverFileNames.Buffer;
       GotDriver = FALSE;
       while (!GotDriver &&
-             CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+             CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
       {
          /* Get the DDI driver's entry point */
          GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
@@ -528,11 +537,11 @@ IntCreatePrimarySurface()
          {
             /* Skip to the next name but never get past the Unicode string */
             while (L'\0' != *CurrentName &&
-                   CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+                   CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
             {
                CurrentName++;
             }
-            if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
+            if (CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
             {
                CurrentName++;
             }
@@ -545,7 +554,6 @@ IntCreatePrimarySurface()
       {
          ObDereferenceObject(PrimarySurface.VideoFileObject);
          DPRINT1("No suitable DDI driver found\n");
-         /* return FALSE; */
          continue;
       }
 
@@ -562,9 +570,10 @@ IntCreatePrimarySurface()
       }
 
       /* 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.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
             &PrimarySurface.DMW,
             L"",
             HS_DDI_MAX,
@@ -590,7 +599,8 @@ IntCreatePrimarySurface()
       if (DoDefault)
       {
          RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
-         PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDev(
+         PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
+         PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
             &PrimarySurface.DMW,
             L"",
             HS_DDI_MAX,
@@ -608,7 +618,6 @@ IntCreatePrimarySurface()
             ObDereferenceObject(PrimarySurface.VideoFileObject);
             DPRINT1("DrvEnablePDEV with default parameters failed\n");
             DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
-            /* return FALSE; */
             continue;
          }
       }
@@ -624,10 +633,12 @@ IntCreatePrimarySurface()
          PrimarySurface.GDIInfo.ulLogPixelsY = 96;
       }
 
+      PrimarySurface.Pointer.Exclude.right = -1;
+
       DPRINT("calling completePDev\n");
 
       /* Complete initialization of the physical device */
-      PrimarySurface.DriverFunctions.CompletePDev(
+      PrimarySurface.DriverFunctions.CompletePDEV(
          PrimarySurface.PDev,
         (HDEV)&PrimarySurface);
 
@@ -635,29 +646,135 @@ IntCreatePrimarySurface()
 
       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)
-      {
-/*         PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
-         PrimarySurface.DriverFunctions.DisablePDev(PrimarySurface.PDev);
-         ObDereferenceObject(PrimarySurface.VideoFileObject);
-         DPRINT1("DrvEnableSurface failed\n");
-         /* return FALSE; */
-         continue;
-      }
+      return TRUE;
+   }
 
-      SurfObj = (SURFOBJ*)AccessUserObject((ULONG) PrimarySurface.Handle);
-      SurfObj->dhpdev = PrimarySurface.PDev;
-      SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
-      IntShowDesktop(
-         IntGetActiveDesktop(),
-         SurfGDI->SurfObj.sizlBitmap.cx,
-         SurfGDI->SurfObj.sizlBitmap.cy);
-      break;
+   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;
+   }
+
+   PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, 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;
@@ -666,23 +783,32 @@ IntCreatePrimarySurface()
 VOID FASTCALL
 IntDestroyPrimarySurface()
   {
-#if 0
-    SURFOBJ *SurfObj;
-    PSURFGDI SurfGDI;
-#endif
-
+    BOOL calledFromUser; 
+     
     DRIVER_UnreferenceDriver(L"DISPLAY");
 
-#if 0
-    DPRINT("Hiding mouse pointer\n" );
-    SurfObj = (SURFOBJ*)AccessUserObject((ULONG) PrimarySurface.Handle);
-    SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
-    SurfGDI->SetPointerShape(SurfObj, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0);
-#endif
+    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();
 
@@ -693,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();
+          } 
+          
         }
     }
 
@@ -717,12 +868,12 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
   if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
   {
     hDC = hNewDC;
-    return  NtGdiCreateCompatableDC(hDC);
+    return  NtGdiCreateCompatibleDC(hDC);
   }
 
   if (Driver != NULL && Driver->Buffer != NULL)
   {
-    DPRINT("NAME: %S\n", Driver->Buffer); // FIXME: Should not crash if NULL
+    DPRINT("NAME: %wZ\n", Driver); // FIXME: Should not crash if NULL
   }
 
   /*  Allocate a DC object  */
@@ -732,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 = (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;
 }
 
@@ -789,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);
@@ -801,7 +965,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
     }
     /* FIXME - InitData can have some more bytes! */
   }
-  
+
   if(Driver)
   {
     Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
@@ -811,7 +975,7 @@ NtGdiCreateDC(PUNICODE_STRING Driver,
       return NULL;
     }
   }
-  
+
   if(Device)
   {
     Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
@@ -822,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;
 }
 
@@ -832,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
@@ -843,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)
   {
@@ -864,7 +1089,7 @@ NtGdiDeleteDC(HDC  DCHandle)
     }
     DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
     DCToDelete->saveLevel--;
-       DC_UnlockDc( savedHDC );
+    DC_UnlockDc( savedDC );
     NtGdiDeleteDC (savedHDC);
   }
 
@@ -878,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)
   {
@@ -901,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;
@@ -914,6 +1142,7 @@ NtGdiDrawEscape(HDC  hDC,
                LPCSTR  lpszInData)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 INT STDCALL
@@ -923,6 +1152,7 @@ NtGdiEnumObjects(HDC  hDC,
                 LPARAM  lParam)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
@@ -935,13 +1165,13 @@ NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
 {
   HGDIOBJ SelObject;
   DC *dc;
-  
+
   if(!(dc = DC_LockDc(hDC)))
   {
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return NULL;
   }
-  
+
   switch(ObjectType)
   {
     case OBJ_PEN:
@@ -952,6 +1182,7 @@ NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
       break;
     case OBJ_PAL:
       DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
+      SelObject = NULL;
       break;
     case OBJ_FONT:
       SelObject = dc->w.hFont;
@@ -961,14 +1192,15 @@ NtGdiGetCurrentObject(HDC  hDC, UINT  ObjectType)
       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(hDC);
+
+  DC_UnlockDc(dc);
   return SelObject;
 }
 
@@ -979,7 +1211,7 @@ IntGdiGetDCOrgEx(DC *dc, LPPOINT  Point)
 {
   Point->x = dc->w.DCOrgX;
   Point->y = dc->w.DCOrgY;
-  
+
   return  TRUE;
 }
 
@@ -989,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;
 }
 
@@ -1034,7 +1278,7 @@ NtGdiSetBkColor(HDC hDC, COLORREF color)
   oldColor = dc->w.backgroundColor;
   dc->w.backgroundColor = color;
   hBrush = dc->w.hBrush;
-  DC_UnlockDc ( hDC );
+  DC_UnlockDc(dc);
   NtGdiSelectObject(hDC, hBrush);
   return oldColor;
 }
@@ -1055,10 +1299,11 @@ NtGdiGetDCState(HDC  hDC)
   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;
@@ -1113,6 +1358,7 @@ NtGdiGetDCState(HDC  hDC)
 
   newdc->hSelf = hnewdc;
   newdc->saveLevel = 0;
+  newdc->IsIC = dc->IsIC;
 
 #if 0
   PATH_InitGdiPath( &newdc->w.path );
@@ -1126,8 +1372,8 @@ NtGdiGetDCState(HDC  hDC)
     newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
     NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
   }
-  DC_UnlockDc( hnewdc );
-  DC_UnlockDc( hDC );
+  DC_UnlockDc( newdc );
+  DC_UnlockDc( dc );
   return  hnewdc;
 }
 
@@ -1218,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
 
@@ -1238,11 +1488,11 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
        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);
     }
   }
@@ -1250,21 +1500,12 @@ NtGdiSetDCState ( HDC hDC, HDC hDCSave )
     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)
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return 0;
-  }
-
   /* Retrieve capability */
   switch (Index)
   {
@@ -1357,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;
       }
@@ -1368,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;
       }
@@ -1379,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;
       }
@@ -1390,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;
       }
@@ -1405,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;
       }
@@ -1416,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;
       }
@@ -1451,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;
 }
 
@@ -1463,7 +1723,7 @@ DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
 INT FASTCALL
 IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
 {
-  PGDIOBJHDR GdiObject;
+  PVOID GdiObject;
   INT Result = 0;
   DWORD ObjectType;
 
@@ -1473,7 +1733,7 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
       SetLastWin32Error(ERROR_INVALID_HANDLE);
       return 0;
     }
-  
+
   ObjectType = GDIOBJ_GetObjectType(Handle);
   switch (ObjectType)
     {
@@ -1508,7 +1768,7 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
         break;
     }
 
-  GDIOBJ_UnlockObj(Handle, GDI_OBJECT_TYPE_DONTCARE);
+  GDIOBJ_UnlockObjByPtr(GdiObject);
 
   return Result;
 }
@@ -1518,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 = ExAllocatePoolWithTag(NonPagedPool, count, TAG_GDIOBJ);
+  _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))
   {
@@ -1549,7 +1839,7 @@ DWORD STDCALL
 NtGdiGetObjectType(HANDLE handle)
 {
   GDIOBJHDR * ptr;
-  INT result = 0;
+  INT result;
   DWORD objectType;
 
   ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
@@ -1601,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;
 }
 
@@ -1623,6 +1915,7 @@ HDC STDCALL
 NtGdiResetDC(HDC  hDC, CONST DEVMODEW *InitData)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
 BOOL STDCALL
@@ -1644,7 +1937,10 @@ NtGdiRestoreDC(HDC  hDC, INT  SaveLevel)
     SaveLevel = dc->saveLevel;
 
   if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
+  {
+    DC_UnlockDc(dc);
     return FALSE;
+  }
 
   success = TRUE;
   while (dc->saveLevel >= SaveLevel)
@@ -1654,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 ))
@@ -1678,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;
 }
 
@@ -1709,7 +2006,7 @@ NtGdiSaveDC(HDC  hDC)
   dc = DC_LockDc (hDC);
   if (dc == NULL)
   {
-    DC_UnlockDc(dc);
+    DC_UnlockDc(dcs);
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return 0;
   }
@@ -1731,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;
 }
@@ -1747,13 +2044,9 @@ NtGdiSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
   PGDIBRUSHOBJ pen;
   PGDIBRUSHOBJ brush;
   XLATEOBJ *XlateObj;
-  PPALGDI PalGDI;
   DWORD objectType;
-  COLORREF *ColorMap;
-  COLORREF MonoColorMap[2];
-  ULONG NumColors, Index;
   HRGN hVisRgn;
-  USHORT Mode;
+  BOOLEAN Failed;
 
   if(!hDC || !hGDIObj) return NULL;
 
@@ -1769,192 +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 = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
-          if (NULL != XlateObj)
-            {
-              pen = PENOBJ_LockPen((HPEN) hGDIObj);
-              if (NULL != pen)
-                {
-                  if (pen->flAttrs & GDIBRUSH_IS_SOLID)
-                    {
-                      pen->BrushObject.iSolidColor = 
-                        XLATEOBJ_iXlate(XlateObj, pen->BrushAttr.lbColor);
-                    }
-                  else
-                    {
-                      pen->BrushObject.iSolidColor = 0xFFFFFFFF;
-                    }
-                  pen->crBack = XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor);
-                  pen->crFore = XLATEOBJ_iXlate(XlateObj, dc->w.textColor);
-                  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 = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
-          if (NULL != XlateObj)
-            {
-              brush = BRUSHOBJ_LockBrush((HBRUSH) hGDIObj);
-              if (NULL != brush)
-                {
-                  if (brush->flAttrs & GDIBRUSH_IS_SOLID)
-                    {
-                      brush->BrushObject.iSolidColor = 
-                        XLATEOBJ_iXlate(XlateObj, brush->BrushAttr.lbColor);
-                    }
-                  else
-                    {
-                      brush->BrushObject.iSolidColor = 0xFFFFFFFF;
-                    }
-                  brush->crBack = XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor);
-                  brush->crFore = XLATEOBJ_iXlate(XlateObj, ((brush->flAttrs & GDIBRUSH_IS_HATCH) ? 
-                                                             brush->BrushAttr.lbColor : dc->w.textColor));
-                  /* according to the documentation of SetBrushOrgEx(), the origin is assigned to the
-                     next brush selected into the DC, so we should set it here */
-                  brush->ptOrigin.x = dc->w.brushOrgX;
-                  brush->ptOrigin.y = dc->w.brushOrgY;
-                  
-                  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 = (HSURF)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->bitmap.bmWidth, pb->bitmap.bmHeight );
+      /* 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;
 
     case GDI_OBJECT_TYPE_REGION:
-      DC_UnlockDc (hDC);
+      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;
 }
 
@@ -1986,7 +2203,7 @@ NtGdiSetHookFlags(HDC hDC, WORD Flags)
       dc->w.flags &= ~DC_DIRTY;
     }
 
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(dc);
 
   return wRet;
 }
@@ -2005,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);
@@ -2016,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)
@@ -2027,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));
@@ -2044,13 +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);
 
   NewDC->w.hPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
 
-  DC_UnlockDc(hDC);
+  DC_UnlockDc(NewDC);
 
   return  hDC;
 }
@@ -2073,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;
 }
 
@@ -2113,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;
@@ -2172,18 +2401,18 @@ DC_SetOwnership(HDC hDC, PEPROCESS Owner)
         {
           GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
         }
-      DC_UnlockDc(hDC);
+      DC_UnlockDc(DC);
     }
 }
 
 BOOL FASTCALL
-IntIsPrimarySurface(PSURFGDI SurfGDI)
+IntIsPrimarySurface(SURFOBJ *SurfObj)
 {
    if (PrimarySurface.Handle == NULL)
      {
        return FALSE;
      }
-   return SurfGDI == (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle) ? TRUE : FALSE;
+   return SurfObj->hsurf == PrimarySurface.Handle;
 }
 
 /*
@@ -2193,89 +2422,20 @@ IntIsPrimarySurface(PSURFGDI SurfGDI)
 COLORREF FASTCALL
 IntGetDCColor(HDC hDC, ULONG Object)
 {
-  COLORREF Result;
-  DC *dc;
-  PPALGDI PalGDI;
-  PGDIBRUSHOBJ pen;
-  PGDIBRUSHOBJ brush;
-  XLATEOBJ *XlateObj;
-  HPALETTE Pal;
-  USHORT Mode;
-  ULONG iColor;
-  
-  if(!(dc = DC_LockDc(hDC)))
-  {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return CLR_INVALID;
-  }
-  
-  switch(Object)
-  {
-    case OBJ_PEN:
-    {
-      if(!(pen = PENOBJ_LockPen(dc->w.hPen)))
-      {
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      if(!(pen->flAttrs & GDIBRUSH_IS_SOLID))
-      {
-        /* FIXME - just bail here? */
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      iColor = pen->BrushObject.iSolidColor;
-      PENOBJ_UnlockPen(dc->w.hPen);
-      break;
-    }
-    case OBJ_BRUSH:
-    {
-      if(!(brush = BRUSHOBJ_LockBrush(dc->w.hBrush)))
-      {
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      if(!(brush->flAttrs & GDIBRUSH_IS_SOLID))
-      {
-        /* FIXME - just bail here? */
-        BRUSHOBJ_UnlockBrush(dc->w.hBrush);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      iColor = brush->BrushObject.iSolidColor;
-      BRUSHOBJ_UnlockBrush(dc->w.hBrush);
-      break;
-    }
-    default:
-    {
-      DC_UnlockDc(hDC);
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return CLR_INVALID;
-    }
-  }
-  
-  /* translate the color into RGB */
-  
-  if(dc->w.hPalette)
-    Pal = dc->w.hPalette;
-  
-  Result = CLR_INVALID;
-  
-  if((PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
-  {
-    Mode = PalGDI->Mode;
-    PALETTE_UnlockPalette(dc->w.hPalette);
-    XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, Pal);
-    if(XlateObj)
-    {
-      Result = XLATEOBJ_iXlate(XlateObj, iColor);
-      EngDeleteXlate(XlateObj);
-    }
-  }
-  
-  DC_UnlockDc(hDC);
-  return Result;
+   /*
+    * 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. */
 }
 
 /*
@@ -2285,133 +2445,446 @@ IntGetDCColor(HDC hDC, ULONG Object)
 COLORREF FASTCALL
 IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color)
 {
-  COLORREF Result;
-  DC *dc;
-  PPALGDI PalGDI;
-  PGDIBRUSHOBJ pen;
-  PGDIBRUSHOBJ brush;
-  XLATEOBJ *XlateObj;
-  HPALETTE Pal;
-  USHORT Mode;
-  ULONG iColor;
-  
-  if(Color == CLR_INVALID)
+   /* 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(ERROR_INVALID_PARAMETER);
-    return CLR_INVALID;
+    SetLastWin32Error(STATUS_INVALID_PARAMETER);
+    return FALSE;
   }
-  
-  if(!(dc = DC_LockDc(hDC)))
+
+  if (iModeNum == ENUM_CURRENT_SETTINGS)
   {
-    SetLastWin32Error(ERROR_INVALID_HANDLE);
-    return CLR_INVALID;
+    CachedMode = &PrimarySurface.DMW;
+    ASSERT(CachedMode->dmSize > 0);
   }
-  
-  switch(Object)
+  else if (iModeNum == ENUM_REGISTRY_SETTINGS)
   {
-    case OBJ_PEN:
+    RtlZeroMemory(&DevMode, sizeof (DevMode));
+    DevMode.dmSize = sizeof (DevMode);
+    DevMode.dmDriverExtra = 0;
+    if (SetupDevMode(&DevMode, DisplayNumber))
+      CachedMode = &DevMode;
+    else
     {
-      if(!(pen = PENOBJ_LockPen(dc->w.hPen)))
-      {
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      if(!(pen->flAttrs & GDIBRUSH_IS_SOLID))
-      {
-        /* FIXME - just bail here? */
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      
-      /* save old color index, translate it to RGB later */
-      iColor = pen->BrushObject.iSolidColor;
-      
-      if(!(PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
-      {
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      Mode = PalGDI->Mode;
-      PALETTE_UnlockPalette(dc->w.hPalette);
-      if(!(XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL)))
-      {
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
-      }
-      pen->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, (ULONG)Color);
-      EngDeleteXlate(XlateObj);
-      PENOBJ_UnlockPen(dc->w.hPen);
-      break;
+      SetLastWin32Error(0); /* FIXME: use error code */
+      return FALSE;
     }
-    case OBJ_BRUSH:
+    /* 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 */
     {
-      if(!(brush = BRUSHOBJ_LockBrush(dc->w.hBrush)))
+      BOOL PrimarySurfaceCreated = FALSE;
+      UNICODE_STRING DriverFileNames;
+      LPWSTR CurrentName;
+      DRVENABLEDATA DrvEnableData;
+
+      /* Retrieve DDI driver names from registry */
+      RtlInitUnicodeString(&DriverFileNames, NULL);
+      if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
       {
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
+        DPRINT1("FindDriverFileNames failed\n");
+        return FALSE;
       }
-      if(!(brush->flAttrs & GDIBRUSH_IS_SOLID))
+
+      if (!HalQueryDisplayOwnership())
       {
-        /* FIXME - just bail here? */
-        BRUSHOBJ_UnlockBrush(dc->w.hBrush);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
+        IntCreatePrimarySurface();
+        PrimarySurfaceCreated = TRUE;
       }
-      
-      /* save old color index, translate it to RGB later */
-      iColor = brush->BrushObject.iSolidColor;
-      
-      if(!(PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
+
+      /*
+       * 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)
       {
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
+        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;
+        }
       }
-      Mode = PalGDI->Mode;
-      PALETTE_UnlockPalette(dc->w.hPalette);
-      if(!(XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL)))
+
+      if (PrimarySurfaceCreated)
       {
-        PENOBJ_UnlockPen(dc->w.hPen);
-        DC_UnlockDc(hDC);
-        return CLR_INVALID;
+        IntDestroyPrimarySurface();
       }
-      brush->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, (ULONG)Color);
-      EngDeleteXlate(XlateObj);
-      BRUSHOBJ_UnlockBrush(dc->w.hBrush);
-      break;
+
+      RtlFreeUnicodeString(&DriverFileNames);
     }
-    default:
+
+    /* return cached info */
+    CachedMode = CachedDevModes;
+    if (CachedMode >= CachedDevModesEnd)
     {
-      DC_UnlockDc(hDC);
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return CLR_INVALID;
+      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;
+  }
   
-  /* translate the old color into RGB */
-  
-  if(dc->w.hPalette)
-    Pal = dc->w.hPalette;
-  
-  Result = CLR_INVALID;
-  
-  if((PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
+  if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
   {
-    Mode = PalGDI->Mode;
-    PALETTE_UnlockPalette(dc->w.hPalette);
-    XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, Pal);
-    if(XlateObj)
-    {
-      Result = XLATEOBJ_iXlate(XlateObj, iColor);
-      EngDeleteXlate(XlateObj);
-    }
+   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)
+  {  
   
-  DC_UnlockDc(hDC);
-  return Result;
+               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 */