BUGFIX: Missing error handling in IntSetDIBits()
[reactos.git] / reactos / subsys / win32k / objects / dib.c
index 0b196b7..d3d1a7f 100644 (file)
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <stdlib.h>
-#include <win32k/bitmaps.h>
-#include <win32k/debug.h>
-#include "../eng/handle.h"
-#include <ntos/minmax.h>
-#include <include/inteng.h>
-
-#define NDEBUG
-#include <win32k/debug1.h>
-
-UINT STDCALL W32kSetDIBColorTable(HDC  hDC,
-                           UINT  StartIndex,
-                           UINT  Entries,
-                           CONST RGBQUAD  *Colors)
+/*
+ * $Id: dib.c,v 1.58 2004/12/18 17:15:10 royce Exp $
+ *
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <w32k.h>
+
+UINT STDCALL
+NtGdiSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
 {
-  PDC dc;
-  PALETTEENTRY * palEntry;
-  PPALOBJ palette;
-  RGBQUAD *end;
+   PDC dc;
+   PBITMAPOBJ BitmapObj;
 
-  if (!(dc = (PDC)AccessUserObject(hDC))) return 0;
+   if (!(dc = DC_LockDc(hDC))) return 0;
 
-  if (!(palette = (PPALOBJ)AccessUserObject(dc->DevInfo->hpalDefault)))
-  {
-//    GDI_ReleaseObj( hdc );
-    return 0;
-  }
+   BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+   if (BitmapObj == NULL)
+   {
+      DC_UnlockDc(hDC);
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
 
-  // Transfer color info
+   if (BitmapObj->dib == NULL)
+   {
+      BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+      DC_UnlockDc(hDC);
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
 
-  if (dc->w.bitsPerPixel <= 8) {
-    palEntry = palette->logpalette->palPalEntry + StartIndex;
-    if (StartIndex + Entries > (1 << dc->w.bitsPerPixel))
-      Entries = (1 << dc->w.bitsPerPixel) - StartIndex;
+   if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
+       StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
+   {
+      if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
+         Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
 
-    if (StartIndex + Entries > palette->logpalette->palNumEntries)
-      Entries = palette->logpalette->palNumEntries - StartIndex;
+      MmCopyFromCaller(BitmapObj->ColorMap + StartIndex, Colors, Entries * sizeof(RGBQUAD));
 
-    for (end = Colors + Entries; Colors < end; palEntry++, Colors++)
-    {
-      palEntry->peRed   = Colors->rgbRed;
-      palEntry->peGreen = Colors->rgbGreen;
-      palEntry->peBlue  = Colors->rgbBlue;
-    }
-  } else {
-    Entries = 0;
-  }
+      /* Rebuild the palette. */
+      NtGdiDeleteObject(dc->w.hPalette);
+      dc->w.hPalette = PALETTE_AllocPaletteIndexedRGB(1 << BitmapObj->dib->dsBmih.biBitCount,
+                                                      BitmapObj->ColorMap);
+   }
+   else
+      Entries = 0;
 
-//  GDI_ReleaseObj(dc->DevInfo->hpalDefault);
-//  GDI_ReleaseObj(hdc);
+   BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+   DC_UnlockDc(hDC);
 
-  return Entries;
+   return Entries;
+}
+
+UINT STDCALL
+NtGdiGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors)
+{
+   PDC dc;
+   PBITMAPOBJ BitmapObj;
+
+   if (!(dc = DC_LockDc(hDC))) return 0;
+
+   BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+   if (BitmapObj == NULL)
+   {
+      DC_UnlockDc(hDC);
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   if (BitmapObj->dib == NULL)
+   {
+      BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+      DC_UnlockDc(hDC);
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+   }
+
+   if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
+       StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
+   {
+      if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
+         Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
+
+      MmCopyToCaller(Colors, BitmapObj->ColorMap + StartIndex, Entries * sizeof(RGBQUAD));
+   }
+   else
+      Entries = 0;
+
+   BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
+   DC_UnlockDc(hDC);
+
+   return Entries;
 }
 
 // Converts a DIB to a device-dependent bitmap
-INT STDCALL W32kSetDIBits(HDC  hDC,
-                   HBITMAP  hBitmap,
-                   UINT  StartScan,
-                   UINT  ScanLines,
-                   CONST VOID  *Bits,
-                   CONST BITMAPINFO  *bmi,
-                   UINT  ColorUse)
+static INT FASTCALL
+IntSetDIBits(
+       PDC   DC,
+       HBITMAP  hBitmap,
+       UINT  StartScan,
+       UINT  ScanLines,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *bmi,
+       UINT  ColorUse)
 {
-  DC *dc;
-  BITMAPOBJ *bitmap;
-  HBITMAP SourceBitmap, DestBitmap;
-  INT result = 0;
-  BOOL copyBitsResult;
-  PSURFOBJ DestSurf, SourceSurf;
-  PSURFGDI DestGDI;
-  SIZEL        SourceSize;
-  POINTL ZeroPoint;
-  RECTL        DestRect;
-  PXLATEOBJ XlateObj;
-  PPALGDI hDCPalette;
-  RGBQUAD *lpRGB;
-  HPALETTE DDB_Palette, DIB_Palette;
-  ULONG DDB_Palette_Type, DIB_Palette_Type;
-  PBYTE vBits = Bits;
-  INT scanDirection = 1, DIBWidth;
+  BITMAPOBJ  *bitmap;
+  HBITMAP     SourceBitmap;
+  INT         result = 0;
+  BOOL        copyBitsResult;
+  SURFOBJ    *DestSurf, *SourceSurf;
+  SIZEL       SourceSize;
+  POINTL      ZeroPoint;
+  RECTL       DestRect;
+  XLATEOBJ   *XlateObj;
+  PPALGDI     hDCPalette;
+  //RGBQUAD  *lpRGB;
+  HPALETTE    DDB_Palette, DIB_Palette;
+  ULONG       DDB_Palette_Type, DIB_Palette_Type;
+  INT         DIBWidth;
 
   // Check parameters
-  if (!(dc = DC_HandleToPtr(hDC)))
-     return 0;
-
-  if (!(bitmap = (BITMAPOBJ *)GDIOBJ_LockObj(hBitmap, GO_BITMAP_MAGIC)))
+  if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
   {
-    DC_ReleasePtr(hDC);
     return 0;
   }
 
   // Get RGB values
-  if (ColorUse == DIB_PAL_COLORS)
-    lpRGB = DIB_MapPaletteColors(hDC, bmi);
-  else
-    lpRGB = &bmi->bmiColors[0];
-
-  // Create a temporary surface for the destination bitmap
-  DestBitmap = BitmapToSurf(bitmap);
+  //if (ColorUse == DIB_PAL_COLORS)
+  //  lpRGB = DIB_MapPaletteColors(hDC, bmi);
+  //else
+  //  lpRGB = &bmi->bmiColors[0];
 
-  DestSurf   = (PSURFOBJ) AccessUserObject( DestBitmap );
-  DestGDI    = (PSURFGDI) AccessInternalObject( DestBitmap );
+  DestSurf = &bitmap->SurfObj;
 
   // Create source surface
   SourceSize.cx = bmi->bmiHeader.biWidth;
@@ -110,30 +154,63 @@ INT STDCALL W32kSetDIBits(HDC  hDC,
   // Determine width of DIB
   DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
-  // Determine DIB Vertical Orientation
-  if(bmi->bmiHeader.biHeight > 0)
+  SourceBitmap = EngCreateBitmap(SourceSize,
+                                 DIBWidth,
+                                 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
+                                 0 < bmi->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
+                                 (PVOID) Bits);
+  if (0 == SourceBitmap)
   {
-    scanDirection = -1;
-    vBits += DIBWidth * bmi->bmiHeader.biHeight - DIBWidth;
+      BITMAPOBJ_UnlockBitmap(hBitmap);
+      SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+      return 0;
   }
 
-  SourceBitmap = EngCreateBitmap(SourceSize,
-                                 DIBWidth * scanDirection,
-                                 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
-                                 0,
-                                 vBits);
-  SourceSurf = (PSURFOBJ)AccessUserObject(SourceBitmap);
+  SourceSurf = EngLockSurface((HSURF)SourceBitmap);
+  if (NULL == SourceSurf)
+  {
+         EngDeleteSurface((HSURF)SourceBitmap);
+      BITMAPOBJ_UnlockBitmap(hBitmap);
+      SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+      return 0;
+  }
 
   // Destination palette obtained from the hDC
-  hDCPalette = (PPALGDI)AccessInternalObject(dc->DevInfo->hpalDefault);
+  hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
+  if (NULL == hDCPalette)
+    {
+      EngUnlockSurface(SourceSurf);
+      EngDeleteSurface((HSURF)SourceBitmap);
+      BITMAPOBJ_UnlockBitmap(hBitmap);
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+    }
   DDB_Palette_Type = hDCPalette->Mode;
-  DDB_Palette = dc->DevInfo->hpalDefault;
+  DDB_Palette = DC->DevInfo->hpalDefault;
+  PALETTE_UnlockPalette(DC->DevInfo->hpalDefault);
 
   // Source palette obtained from the BITMAPINFO
-  DIB_Palette = BuildDIBPalette(bmi, &DIB_Palette_Type);
+  DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
+  if (NULL == DIB_Palette)
+    {
+      EngUnlockSurface(SourceSurf);
+      EngDeleteSurface((HSURF)SourceBitmap);
+      BITMAPOBJ_UnlockBitmap(hBitmap);
+      SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+      return 0;
+    }
 
   // Determine XLATEOBJ for color translation
   XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
+  if (NULL == XlateObj)
+    {
+      PALETTE_FreePalette(DIB_Palette);
+      EngUnlockSurface(SourceSurf);
+      EngDeleteSurface((HSURF)SourceBitmap);
+      BITMAPOBJ_UnlockBitmap(hBitmap);
+      SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+      return 0;
+    }
 
   // Zero point
   ZeroPoint.x = 0;
@@ -155,57 +232,239 @@ INT STDCALL W32kSetDIBits(HDC  hDC,
 
   // Clean up
   EngDeleteXlate(XlateObj);
-  EngDeletePalette(DIB_Palette);
-  EngDeleteSurface(SourceBitmap);
-  EngDeleteSurface(DestBitmap);
+  PALETTE_FreePalette(DIB_Palette);
+  EngUnlockSurface(SourceSurf);
+  EngDeleteSurface((HSURF)SourceBitmap);
 
 //  if (ColorUse == DIB_PAL_COLORS)
 //    WinFree((LPSTR)lpRGB);
 
-//  GDI_ReleaseObj(hBitmap); unlock?
-  GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC);
-  DC_ReleasePtr(hDC);
+  BITMAPOBJ_UnlockBitmap(hBitmap);
 
   return result;
 }
 
-INT STDCALL W32kSetDIBitsToDevice(HDC  hDC,
-                           INT  XDest,
-                           INT  YDest,
-                           DWORD  Width,
-                           DWORD  Height,
-                           INT  XSrc,
-                           INT  YSrc,
-                           UINT  StartScan,
-                           UINT  ScanLines,
-                           CONST VOID  *Bits,
-                           CONST BITMAPINFO  *bmi,
-                           UINT  ColorUse)
+// Converts a DIB to a device-dependent bitmap
+INT STDCALL
+NtGdiSetDIBits(
+       HDC  hDC,
+       HBITMAP  hBitmap,
+       UINT  StartScan,
+       UINT  ScanLines,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *bmi,
+       UINT  ColorUse)
 {
+  PDC Dc;
+  INT Ret;
 
+  Dc = DC_LockDc(hDC);
+  if (NULL == Dc)
+    {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+    }
+
+  Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
+
+  DC_UnlockDc(hDC);
+
+  return Ret;
 }
 
-UINT STDCALL W32kGetDIBColorTable(HDC  hDC,
-                           UINT  StartIndex,
-                           UINT  Entries,
-                           RGBQUAD  *Colors)
+INT STDCALL
+NtGdiSetDIBitsToDevice(
+       HDC  hDC,
+       INT  XDest,
+       INT  YDest,
+       DWORD  Width,
+       DWORD  Height,
+       INT  XSrc,
+       INT  YSrc,
+       UINT  StartScan,
+       UINT  ScanLines,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *bmi,
+       UINT  ColorUse)
 {
   UNIMPLEMENTED;
+  return 0;
 }
 
-// Converts a device-dependent bitmap to a DIB
-INT STDCALL W32kGetDIBits(HDC  hDC,
-                   HBITMAP hBitmap,
-                   UINT  StartScan,
-                   UINT  ScanLines,
-                   LPVOID  Bits,
-                   LPBITMAPINFO   bi,
-                   UINT  Usage)
+/* Converts a device-dependent bitmap to a DIB */
+INT STDCALL
+NtGdiGetDIBits(HDC hDC,
+               HBITMAP hBitmap,
+               UINT StartScan,
+               UINT ScanLines,
+               LPVOID Bits,
+               LPBITMAPINFO Info,
+               UINT Usage)
 {
-  UNIMPLEMENTED;
+   BITMAPOBJ *BitmapObj;
+   SURFOBJ *DestSurfObj;
+   XLATEOBJ *XlateObj;
+   HBITMAP DestBitmap;
+   SIZEL DestSize;
+   HPALETTE hSourcePalette;
+   HPALETTE hDestPalette;
+   PPALGDI SourcePalette;
+   PPALGDI DestPalette;
+   ULONG SourcePaletteType;
+   ULONG DestPaletteType;
+   PDC Dc;
+   POINTL SourcePoint;
+   RECTL DestRect;
+   ULONG Result = 0;
+   ULONG Index;
+
+   /* Get handle for the palette in DC. */
+   Dc = DC_LockDc(hDC);
+   if (Dc == NULL)
+   {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+   }
+   hSourcePalette = Dc->w.hPalette;
+   /* FIXME: This is incorrect. hDestPalette should be something other. */
+   hDestPalette = Dc->DevInfo->hpalDefault;
+   DC_UnlockDc(hDC);
+
+   /* Get pointer to the source bitmap object. */
+   BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
+   if (BitmapObj == NULL)
+   {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return 0;
+   }
+
+   if (Bits == NULL)
+   {
+      if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) ||
+          Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+      {
+         Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
+         Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
+         /* Report negtive height for top-down bitmaps. */
+         if (BitmapObj->SurfObj.lDelta > 0)
+            Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
+         Info->bmiHeader.biPlanes = 1;
+         Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
+         if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+         {
+            switch (BitmapObj->SurfObj.iBitmapFormat)
+            {
+               case BMF_1BPP: case BMF_4BPP: case BMF_8BPP:
+               case BMF_16BPP: case BMF_24BPP: case BMF_32BPP:
+                  Info->bmiHeader.biCompression = BI_RGB;
+                  break;
+               case BMF_4RLE:
+                  Info->bmiHeader.biCompression = BI_RLE4;
+                  break;
+               case BMF_8RLE:
+                  Info->bmiHeader.biCompression = BI_RLE8;
+                  break;
+               case BMF_JPEG: 
+                  Info->bmiHeader.biCompression = BI_JPEG;
+                  break;
+               case BMF_PNG:
+                  Info->bmiHeader.biCompression = BI_PNG;
+                  break;
+            }
+            Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
+            Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
+            Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */ 
+            Info->bmiHeader.biClrUsed = 
+            Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
+            Result = BitmapObj->SurfObj.sizlBitmap.cy;
+         }
+      }
+   }
+   else
+   {
+      if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
+      {
+         Result = 0;
+      }
+      else
+      {
+         ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
+         DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
+         DestSize.cy = ScanLines;
+         DestBitmap = EngCreateBitmap(
+            DestSize, BitmapObj->SurfObj.lDelta,
+            BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
+            0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
+            Bits);
+         DestSurfObj = EngLockSurface((HSURF)DestBitmap);
+
+         SourcePalette = PALETTE_LockPalette(hSourcePalette);
+         /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
+         ASSERT(SourcePalette);
+         SourcePaletteType = SourcePalette->Mode;
+         PALETTE_UnlockPalette(hSourcePalette);
+
+         DestPalette = PALETTE_LockPalette(hDestPalette);
+         /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
+         ASSERT(DestPalette);
+         DestPaletteType = DestPalette->Mode;
+         
+         /* Copy palette. */
+         /* FIXME: This is largely incomplete. */
+         if (Info->bmiHeader.biBitCount <= 8)
+         {
+            if (Usage == DIB_RGB_COLORS)
+            {
+               for (Index = 0;
+                    Index < (1 << Info->bmiHeader.biBitCount) &&
+                    Index < DestPalette->NumColors;
+                    Index++)
+               {
+                  Info->bmiColors[Index].rgbRed =
+                     DestPalette->IndexedColors[Index].peRed;
+                  Info->bmiColors[Index].rgbGreen =
+                     DestPalette->IndexedColors[Index].peGreen;
+                  Info->bmiColors[Index].rgbBlue =
+                     DestPalette->IndexedColors[Index].peBlue;
+               }
+            }
+            if (Usage == DIB_PAL_COLORS)
+            {
+               DbgPrint("GetDIBits with DIB_PAL_COLORS isn't implemented yet.");
+            }
+         }
+
+         PALETTE_UnlockPalette(hDestPalette);
+
+         XlateObj = IntEngCreateXlate(
+            DestPaletteType, SourcePaletteType, hDestPalette, hSourcePalette);
+         
+         SourcePoint.x = 0;
+         SourcePoint.y = StartScan;
+
+         /* Determine destination rectangle */
+         DestRect.top = 0;
+         DestRect.left = 0;
+         DestRect.right = DestSize.cx;
+         DestRect.bottom = DestSize.cy;
+
+         if (EngCopyBits(DestSurfObj, &BitmapObj->SurfObj,
+                         NULL, XlateObj, &DestRect, &SourcePoint))
+         {
+            Result = ScanLines;
+         }
+         
+         EngDeleteXlate(XlateObj);
+         EngUnlockSurface(DestSurfObj);
+      }
+   }
+
+   BITMAPOBJ_UnlockBitmap(hBitmap);
+
+   return Result;
 }
 
-INT STDCALL W32kStretchDIBits(HDC  hDC,
+INT STDCALL NtGdiStretchDIBits(HDC  hDC,
                        INT  XDest,
                        INT  YDest,
                        INT  DestWidth,
@@ -219,17 +478,62 @@ INT STDCALL W32kStretchDIBits(HDC  hDC,
                        UINT  Usage,
                        DWORD  ROP)
 {
-  UNIMPLEMENTED;
+   HBITMAP hBitmap, hOldBitmap;
+   HDC hdcMem;
+
+   if (!Bits || !BitsInfo)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return 0;
+   }   
+
+   hdcMem = NtGdiCreateCompatableDC(hDC);
+   hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
+                                         BitsInfo->bmiHeader.biHeight);
+   hOldBitmap = NtGdiSelectObject(hdcMem, hBitmap);
+
+   if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
+       BitsInfo->bmiHeader.biCompression == BI_RLE8)
+   {
+      /* copy existing bitmap from destination dc */
+      if (SrcWidth == DestWidth && SrcHeight == DestHeight)
+         NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
+                     SrcWidth, SrcHeight, hDC, XDest, YDest, ROP);
+      else
+         NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
+                         SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
+                         ROP);
+   }
+
+   NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
+                  BitsInfo, Usage);
+
+   /* Origin for DIBitmap may be bottom left (positive biHeight) or top
+      left (negative biHeight) */
+   if (SrcWidth == DestWidth && SrcHeight == DestHeight)
+      NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
+                  hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
+                  ROP);
+   else
+      NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
+                      hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
+                      SrcWidth, SrcHeight, ROP);
+
+   NtGdiSelectObject(hdcMem, hOldBitmap);
+   NtGdiDeleteDC(hdcMem);
+   NtGdiDeleteObject(hBitmap);
+
+   return SrcHeight;
 }
 
-LONG STDCALL W32kGetBitmapBits(HBITMAP  hBitmap,
+LONG STDCALL NtGdiGetBitmapBits(HBITMAP  hBitmap,
                         LONG  Count,
                         LPVOID  Bits)
 {
   PBITMAPOBJ  bmp;
   LONG  height, ret;
 
-  bmp = BITMAPOBJ_HandleToPtr (hBitmap);
+  bmp = BITMAPOBJ_LockBitmap (hBitmap);
   if (!bmp)
   {
     return 0;
@@ -238,7 +542,9 @@ LONG STDCALL W32kGetBitmapBits(HBITMAP  hBitmap,
   /* If the bits vector is null, the function should return the read size */
   if (Bits == NULL)
   {
-    return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
+    ret = bmp->SurfObj.cjBits;
+    BITMAPOBJ_UnlockBitmap (hBitmap);
+    return ret;
   }
 
   if (Count < 0)
@@ -248,21 +554,23 @@ LONG STDCALL W32kGetBitmapBits(HBITMAP  hBitmap,
   }
 
   /* Only get entire lines */
-  height = Count / bmp->bitmap.bmWidthBytes;
-  if (height > bmp->bitmap.bmHeight)
+  height = Count / abs(bmp->SurfObj.lDelta);
+  if (height > bmp->SurfObj.sizlBitmap.cy)
   {
-    height = bmp->bitmap.bmHeight;
+    height = bmp->SurfObj.sizlBitmap.cy;
   }
-  Count = height * bmp->bitmap.bmWidthBytes;
+  Count = height * abs(bmp->SurfObj.lDelta);
   if (Count == 0)
   {
     DPRINT("Less then one entire line requested\n");
+    BITMAPOBJ_UnlockBitmap (hBitmap);
     return  0;
   }
 
   DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
-         hBitmap, Count, Bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
-         1 << bmp->bitmap.bmBitsPixel, height );
+         hBitmap, Count, Bits, bmp->SurfObj.sizlBitmap.cx,
+         bmp->SurfObj.sizlBitmap.cy,
+         1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat), height );
 #if 0
   /* FIXME: Call DDI CopyBits here if available  */
   if(bmp->DDBitmap)
@@ -282,26 +590,19 @@ LONG STDCALL W32kGetBitmapBits(HBITMAP  hBitmap,
   else
 #endif
   {
-    if(!bmp->bitmap.bmBits)
-    {
-      DPRINT ("Bitmap is empty\n");
-      ret = 0;
-    }
-    else
-    {
-      memcpy(Bits, bmp->bitmap.bmBits, Count);
-      ret = Count;
-    }
+    memcpy(Bits, bmp->SurfObj.pvBits, Count);
+    ret = Count;
   }
 
+  BITMAPOBJ_UnlockBitmap (hBitmap);
+
   return  ret;
 }
 
-// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
-// The DDB that is created will be whatever bit depth your reference DC is
-HBITMAP STDCALL W32kCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header,
-                               DWORD init, LPCVOID bits, const BITMAPINFO *data,
-                               UINT coloruse)
+static HBITMAP FASTCALL
+IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
+                  DWORD init, LPCVOID bits, const BITMAPINFO *data,
+                  UINT coloruse)
 {
   HBITMAP handle;
   BOOL fColor;
@@ -311,7 +612,6 @@ HBITMAP STDCALL W32kCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header,
   WORD compr;
 
   if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
-  if (height < 0) height = -height;
 
   // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
   // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
@@ -358,31 +658,50 @@ HBITMAP STDCALL W32kCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header,
   }
 
   // Now create the bitmap
-
-  if(fColor)
+  if (fColor)
   {
-    // If we are using indexed colors, then we need to create a bitmap that is compatible with the palette
-    if(coloruse == DIB_PAL_COLORS)
-    {
-      handle = W32kCreateCompatibleBitmap(hdc, width, height);
-    }
-    else if(coloruse == DIB_RGB_COLORS) {
-      handle = W32kCreateBitmap(width, height, 1, 24, NULL);
-    }
+    handle = IntCreateCompatibleBitmap(Dc, width, height);
+  }
+  else
+  {
+    handle = NtGdiCreateBitmap( width, height, 1, 1, NULL);
   }
-  else handle = W32kCreateBitmap(width, height, 1, 1, NULL);
 
-  if (!handle) return 0;
+  if (height < 0)
+    height = -height;
 
-  if (init == CBM_INIT)
+  if (NULL != handle && CBM_INIT == init)
   {
-    W32kSetDIBits(hdc, handle, 0, height, bits, data, coloruse);
+    IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
   }
 
   return handle;
 }
 
-HBITMAP STDCALL W32kCreateDIBSection(HDC hDC,
+// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
+// The DDB that is created will be whatever bit depth your reference DC is
+HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
+                                    DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
+                                    UINT ColorUse)
+{
+  PDC Dc;
+  HBITMAP Bmp;
+
+  Dc = DC_LockDc(hDc);
+  if (NULL == Dc)
+    {
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return NULL;
+    }
+
+  Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
+
+  DC_UnlockDc(hDc);
+
+  return Bmp;
+}
+
+HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
                               CONST BITMAPINFO  *bmi,
                               UINT  Usage,
                               VOID  *Bits,
@@ -396,23 +715,25 @@ HBITMAP STDCALL W32kCreateDIBSection(HDC hDC,
   // If the reference hdc is null, take the desktop dc
   if (hDC == 0)
   {
-    hDC = W32kCreateCompatableDC(0);
+    hDC = NtGdiCreateCompatableDC(0);
     bDesktopDC = TRUE;
   }
 
-  if ((dc = DC_HandleToPtr(hDC)))
+  if ((dc = DC_LockDc(hDC)))
   {
-    hbitmap = DIB_CreateDIBSection(dc, bmi, Usage, Bits, hSection, dwOffset, 0);
-       DC_ReleasePtr(hDC);
+    hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
+      hSection, dwOffset, 0);
+    DC_UnlockDc(hDC);
   }
 
   if (bDesktopDC)
-    W32kDeleteDC(hDC);
+    NtGdiDeleteDC(hDC);
 
   return hbitmap;
 }
 
-HBITMAP DIB_CreateDIBSection(
+HBITMAP STDCALL
+DIB_CreateDIBSection(
   PDC dc, BITMAPINFO *bmi, UINT usage,
   LPVOID *bits, HANDLE section,
   DWORD offset, DWORD ovr_pitch)
@@ -423,9 +744,11 @@ HBITMAP DIB_CreateDIBSection(
 
   // Fill BITMAP32 structure with DIB data
   BITMAPINFOHEADER *bi = &bmi->bmiHeader;
-  INT effHeight, totalSize;
+  INT effHeight;
+  ULONG totalSize;
   UINT Entries = 0;
   BITMAP bm;
+  SIZEL Size;
 
   DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
        bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
@@ -435,7 +758,7 @@ HBITMAP DIB_CreateDIBSection(
   bm.bmType = 0;
   bm.bmWidth = bi->biWidth;
   bm.bmHeight = effHeight;
-  bm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
+  bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
 
   bm.bmPlanes = bi->biPlanes;
   bm.bmBitsPixel = bi->biBitCount;
@@ -444,12 +767,15 @@ HBITMAP DIB_CreateDIBSection(
   // Get storage location for DIB bits.  Only use biSizeImage if it's valid and
   // we're dealing with a compressed bitmap.  Otherwise, use width * height.
   totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
-    ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
+    ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
 
   if (section)
+  {
 /*    bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
                              0L, offset, totalSize); */
-    DPRINT("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
+    DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
+    return 0;
+  }
   else if (ovr_pitch && offset)
     bm.bmBits = (LPVOID) offset;
   else {
@@ -457,14 +783,13 @@ HBITMAP DIB_CreateDIBSection(
     bm.bmBits = EngAllocUserMem(totalSize, 0);
   }
 
-/*  bm.bmBits = ExAllocatePool(NonPagedPool, totalSize); */
-
-  if(usage == DIB_PAL_COLORS) memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
+  if(usage == DIB_PAL_COLORS)
+    memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
 
   // Allocate Memory for DIB and fill structure
   if (bm.bmBits)
   {
-    dib = ExAllocatePool(PagedPool, sizeof(DIBSECTION));
+    dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
     RtlZeroMemory(dib, sizeof(DIBSECTION));
   }
 
@@ -484,19 +809,18 @@ HBITMAP DIB_CreateDIBSection(
       case 16:
         dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
         dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
-        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
-        break;
+        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;        break;
 
       case 24:
-        dib->dsBitfields[0] = 0xff;
-        dib->dsBitfields[1] = 0xff00;
-        dib->dsBitfields[2] = 0xff0000;
+        dib->dsBitfields[0] = 0xff0000;
+        dib->dsBitfields[1] = 0x00ff00;
+        dib->dsBitfields[2] = 0x0000ff;
         break;
 
       case 32:
-        dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
-        dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
-        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
+        dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
+        dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
+        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
         break;
     }
     dib->dshSection = section;
@@ -506,24 +830,33 @@ HBITMAP DIB_CreateDIBSection(
   // Create Device Dependent Bitmap and add DIB pointer
   if (dib)
   {
-    res = W32kCreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
-    if (res)
-    {
-      bmp = BITMAPOBJ_HandleToPtr (res);
-      if (bmp)
+    Size.cx = bm.bmWidth;
+    Size.cy = bm.bmHeight;
+    res = IntCreateBitmap(Size, bm.bmWidthBytes,
+                          BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
+                          BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
+                          (bi->biHeight > 0 ? 0 : BMF_TOPDOWN),
+                          bm.bmBits);
+    if (! res)
       {
-        bmp->dib = (DIBSECTION *) dib;
+       return NULL;
+      } 
+    bmp = BITMAPOBJ_LockBitmap(res);
+    if (NULL == bmp)
+      {
+       NtGdiDeleteObject(bmp);
+       return NULL;
       }
-    }
+    bmp->dib = (DIBSECTION *) dib;
 
     /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
                   device. Obviously, this is left out of the ReactOS implementation. Instead, we call
-                  W32kSetDIBColorTable. */
+                  NtGdiSetDIBColorTable. */
     if(bi->biBitCount == 1) { Entries = 2; } else
     if(bi->biBitCount == 4) { Entries = 16; } else
     if(bi->biBitCount == 8) { Entries = 256; }
 
-    bmp->ColorMap = ExAllocatePool(NonPagedPool, sizeof(RGBQUAD)*Entries);
+    bmp->ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD)*Entries, TAG_COLORMAP);
     RtlCopyMemory(bmp->ColorMap, bmi->bmiColors, sizeof(RGBQUAD)*Entries);
   }
 
@@ -541,32 +874,19 @@ HBITMAP DIB_CreateDIBSection(
 
     if (dib) { ExFreePool(dib); dib = NULL; }
     if (bmp) { bmp = NULL; }
-    if (res) { GDIOBJ_FreeObj(res, GO_BITMAP_MAGIC, GDIOBJFLAG_DEFAULT); res = 0; }
+    if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
   }
 
-  // Install fault handler, if possible
-/*  if (bm.bmBits)
-  {
-    if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res))
+  if (bmp)
     {
-      if (section || offset)
-      {
-        DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
-        if (dib) dib->status = DIB_AppMod;
-      }
-      else
-      {
-        DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
-        if (dib) dib->status = DIB_InSync;
-      }
+      BITMAPOBJ_UnlockBitmap(res);
     }
-  } */
-
-  if( bmp )
-       BITMAPOBJ_ReleasePtr(res);
 
   // Return BITMAP handle and storage location
-  if (bm.bmBits && bits) *bits = bm.bmBits;
+  if (NULL != bm.bmBits && NULL != bits)
+    {
+      *bits = bm.bmBits;
+    }
 
   return res;
 }
@@ -578,18 +898,18 @@ HBITMAP DIB_CreateDIBSection(
  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
  * 11/16/1999 (RJJ) lifted from wine
  */
-int DIB_GetDIBWidthBytes(int  width, int  depth)
+INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
 {
   int words;
 
   switch(depth)
   {
-    case 1:  words = (width + 31) / 32; break;
-    case 4:  words = (width + 7) / 8; break;
-    case 8:  words = (width + 3) / 4; break;
+    case 1:  words = (width + 31) >> 5; break;
+    case 4:  words = (width + 7) >> 3; break;
+    case 8:  words = (width + 3) >> 2; break;
     case 15:
-    case 16: words = (width + 1) / 2; break;
-    case 24: words = (width * 3 + 3)/4; break;
+    case 16: words = (width + 1) >> 1; break;
+    case 24: words = (width * 3 + 3) >> 2; break;
 
     default:
       DPRINT("(%d): Unsupported depth\n", depth );
@@ -597,7 +917,7 @@ int DIB_GetDIBWidthBytes(int  width, int  depth)
     case 32:
       words = width;
   }
-  return 4 * words;
+  return words << 2;
 }
 
 /***********************************************************************
@@ -607,7 +927,7 @@ int DIB_GetDIBWidthBytes(int  width, int  depth)
  * 11/16/1999 (RJJ) lifted from wine
  */
 
-int DIB_GetDIBImageBytes (int  width, int  height, int  depth)
+INT STDCALL DIB_GetDIBImageBytes (INT  width, INT height, INT depth)
 {
   return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
 }
@@ -619,7 +939,7 @@ int DIB_GetDIBImageBytes (int  width, int  height, int  depth)
  * 11/16/1999 (RJJ) lifted from wine
  */
 
-int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
+INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
 {
   int colors;
 
@@ -637,8 +957,11 @@ int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
   }
 }
 
-int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
-                              int *height, WORD *bpp, WORD *compr )
+INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
+                              PDWORD width,
+                              PINT height,
+                              PWORD bpp,
+                              PWORD compr)
 {
   if (header->biSize == sizeof(BITMAPINFOHEADER))
   {
@@ -663,8 +986,8 @@ int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
 
 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
 // The specified Device Context (DC) defines what the DIB should be converted to
-PBITMAPOBJ DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
-                                                // change to W32kSetDIBits
+PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
+                                                // change to NtGdiSetDIBits
 {
   HBITMAP hBmp = 0;
   PBITMAPOBJ pBmp = NULL;
@@ -675,89 +998,84 @@ PBITMAPOBJ DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be remove
   // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
   dib = hPackedDIB;
 
-  pbits = (dib + DIB_BitmapInfoSize(&dib->dsBmih, DIB_RGB_COLORS));
+  pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
 
   // Create a DDB from the DIB
-  hBmp = W32kCreateDIBitmap(hdc, &dib->dsBmih, CBM_INIT, (LPVOID)pbits, &dib->dsBmih, DIB_RGB_COLORS);
+  hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
+    (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
 
   // GlobalUnlock(hPackedDIB);
 
   // Retrieve the internal Pixmap from the DDB
-  pBmp = (BITMAPOBJ *)GDIOBJ_LockObj(hBmp, GO_BITMAP_MAGIC);
+  pBmp = BITMAPOBJ_LockBitmap(hBmp);
 
   return pBmp;
 }
 
-RGBQUAD *DIB_MapPaletteColors(PDC dc, LPBITMAPINFO lpbmi)
+RGBQUAD * FASTCALL
+DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
 {
   RGBQUAD *lpRGB;
-  int nNumColors,i;
-  DWORD *lpIndex;
-  PPALOBJ palObj;
+  ULONG nNumColors,i;
+  USHORT *lpIndex;
+  PPALGDI palGDI;
 
-  palObj = AccessUserObject(dc->DevInfo->hpalDefault);
+  palGDI = PALETTE_LockPalette(dc->w.hPalette);
 
-  if (palObj == NULL) {
+  if (NULL == palGDI)
+    {
 //      RELEASEDCINFO(hDC);
-    return NULL;
-  }
+      return NULL;
+    }
 
   nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
   if (lpbmi->bmiHeader.biClrUsed)
-    nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
+    {
+      nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
+    }
 
-  lpRGB = (RGBQUAD *)ExAllocatePool(NonPagedPool, sizeof(RGBQUAD) * nNumColors);
-  lpIndex = (DWORD *)&lpbmi->bmiColors[0];
+  lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
+  lpIndex = (USHORT *)&lpbmi->bmiColors[0];
 
-  for (i=0; i<nNumColors; i++) {
-    lpRGB[i].rgbRed = palObj->logpalette->palPalEntry[*lpIndex].peRed;
-    lpRGB[i].rgbGreen = palObj->logpalette->palPalEntry[*lpIndex].peGreen;
-    lpRGB[i].rgbBlue = palObj->logpalette->palPalEntry[*lpIndex].peBlue;
-    lpIndex++;
-  }
+  for (i = 0; i < nNumColors; i++)
+    {
+      lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
+      lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
+      lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+      lpIndex++;
+    }
 //    RELEASEDCINFO(hDC);
-//    RELEASEPALETTEINFO(hPalette);
-  return lpRGB;
-}
-
-PALETTEENTRY *DIBColorTableToPaletteEntries(PALETTEENTRY *palEntries, const RGBQUAD *DIBColorTable, ULONG ColorCount)
-{
-  ULONG i;
+  PALETTE_UnlockPalette(dc->w.hPalette);
 
-  for(i=0; i<ColorCount; i++)
-  {
-    palEntries->peRed   = DIBColorTable->rgbRed;
-    palEntries->peGreen = DIBColorTable->rgbGreen;
-    palEntries->peBlue  = DIBColorTable->rgbBlue;
-    palEntries++;
-    DIBColorTable++;
-  }
+  return lpRGB;
 }
 
-HPALETTE BuildDIBPalette(BITMAPINFO *bmi, PINT paletteType)
+HPALETTE FASTCALL
+BuildDIBPalette (PBITMAPINFO bmi, PINT paletteType)
 {
   BYTE bits;
   ULONG ColorCount;
-  PALETTEENTRY *palEntries;
+  PALETTEENTRY *palEntries = NULL;
   HPALETTE hPal;
 
   // Determine Bits Per Pixel
   bits = bmi->bmiHeader.biBitCount;
 
   // Determine paletteType from Bits Per Pixel
-  if(bits <= 8)
-  {
-    *paletteType = PAL_INDEXED;
-  } else
-  if(bits < 24)
-  {
-    *paletteType = PAL_BITFIELDS;
-  } else {
-    *paletteType = PAL_RGB; // Would it be BGR, considering the BGR nature of the DIB color table?
-  }
+  if (bits <= 8)
+    {
+      *paletteType = PAL_INDEXED;
+    }
+  else if(bits < 24)
+    {
+      *paletteType = PAL_BITFIELDS;
+    }
+  else
+    {
+      *paletteType = PAL_BGR;
+    }
 
-  if (bmi->bmiHeader.biClrUsed == 0 &&
-      bmi->bmiHeader.biBitCount <= 8)
+  if (bmi->bmiHeader.biClrUsed == 0)
     {
       ColorCount = 1 << bmi->bmiHeader.biBitCount;
     }
@@ -766,10 +1084,16 @@ HPALETTE BuildDIBPalette(BITMAPINFO *bmi, PINT paletteType)
       ColorCount = bmi->bmiHeader.biClrUsed;
     }
 
-  palEntries = ExAllocatePool(NonPagedPool, sizeof(PALETTEENTRY)*ColorCount);
-  DIBColorTableToPaletteEntries(palEntries, bmi->bmiColors, ColorCount);
-  hPal = EngCreatePalette(*paletteType, ColorCount, palEntries, 0, 0, 0);
-  ExFreePool(palEntries);
+  if (PAL_INDEXED == *paletteType)
+    {
+      hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
+    }
+  else
+    {
+      hPal = PALETTE_AllocPalette( *paletteType, ColorCount, (ULONG*)palEntries, 0, 0, 0 );
+    }
 
   return hPal;
 }
+
+/* EOF */