[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / bitmaps.c
index 658b53d..e604957 100644 (file)
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
-HBITMAP APIENTRY
-IntGdiCreateBitmap(
-    INT Width,
-    INT Height,
-    UINT Planes,
-    UINT BitsPixel,
-    IN OPTIONAL LPBYTE pBits)
+LONG APIENTRY
+IntSetBitmapBits(
+    PSURFACE psurf,
+    DWORD Bytes,
+    IN PBYTE Bits)
 {
-    HBITMAP hBitmap;
-    SIZEL Size;
-    LONG WidthBytes;
-    PSURFACE psurfBmp;
+    /* Don't copy more bytes than the buffer has */
+    Bytes = min(Bytes, psurf->SurfObj.cjBits);
 
-    /* NOTE: Windows also doesn't store nr. of planes separately! */
-    BitsPixel = BITMAP_GetRealBitsPixel(BitsPixel * Planes);
+    RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
 
-    /* Check parameters */
-    if (BitsPixel == 0 || Width <= 0 || Width >= 0x8000000 || Height == 0)
-    {
-        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
-                Width, Height, BitsPixel);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
+    return Bytes;
+}
 
-    WidthBytes = BITMAP_GetWidthBytes(Width, BitsPixel);
+void
+NTAPI
+UnsafeSetBitmapBits(
+    PSURFACE psurf,
+    IN ULONG cjBits,
+    IN PVOID pvBits)
+{
+    PUCHAR pjDst, pjSrc;
+    LONG lDeltaDst, lDeltaSrc;
+    ULONG nWidth, nHeight, cBitsPixel;
 
-    Size.cx = Width;
-    Size.cy = abs(Height);
+    nWidth = psurf->SurfObj.sizlBitmap.cx;
+    nHeight = psurf->SurfObj.sizlBitmap.cy;
+    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
 
-    /* Make sure that cjBits will not overflow */
-    if ((ULONGLONG)WidthBytes * Size.cy >= 0x100000000ULL)
-    {
-        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
-                Width, Height, BitsPixel);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
+    /* Get pointers */
+    pjDst = psurf->SurfObj.pvScan0;
+    pjSrc = pvBits;
+    lDeltaDst = psurf->SurfObj.lDelta;
+    lDeltaSrc = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
 
-    /* Create the bitmap object. */
-    hBitmap = IntCreateBitmap(Size, WidthBytes,
-                              BitmapFormat(BitsPixel, BI_RGB),
-                              (Height < 0 ? BMF_TOPDOWN : 0) |
-                              (NULL == pBits ? 0 : BMF_NOZEROINIT), NULL);
-    if (!hBitmap)
+    while (nHeight--)
     {
-        DPRINT("IntGdiCreateBitmap: returned 0\n");
-        return 0;
+        /* Copy one line */
+        memcpy(pjDst, pjSrc, lDeltaSrc);
+        pjSrc += lDeltaSrc;
+        pjDst += lDeltaDst;
     }
 
-    psurfBmp = SURFACE_LockSurface(hBitmap);
-    if (psurfBmp == NULL)
+}
+
+HBITMAP
+APIENTRY
+GreCreateBitmapEx(
+    IN INT nWidth,
+    IN INT nHeight,
+    IN ULONG cjWidthBytes,
+    IN ULONG iFormat,
+    IN USHORT fjBitmap,
+    IN ULONG cjSizeImage,
+    IN OPTIONAL PVOID pvBits)
+{
+    PSURFACE psurf;
+    SURFOBJ *pso;
+    HBITMAP hbmp;
+    PVOID pvCompressedBits;
+    SIZEL sizl;
+    FLONG fl = 0;
+
+    /* Verify format */
+    if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
+
+    /* Allocate a surface */
+    psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
+    if (!psurf)
     {
-        GreDeleteObject(hBitmap);
+        DPRINT1("SURFACE_AllocSurface failed.\n");
         return NULL;
     }
 
-    psurfBmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
-    psurfBmp->hDC = NULL; // Fixme
+    /* Get the handle for the bitmap and the surfobj */
+    hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+    pso = &psurf->SurfObj;
 
-    if (NULL != pBits)
+    /* The infamous RLE hack */
+    if (iFormat == BMF_4RLE)
+    {
+        sizl.cx = nWidth; sizl.cy = nHeight;
+        pvCompressedBits = pvBits;
+        pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+        Decompress4bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
+        fl |= BMF_RLE_HACK;
+    }
+    else if (iFormat == BMF_8RLE)
     {
-        IntSetBitmapBits(psurfBmp, psurfBmp->SurfObj.cjBits, pBits);
+        sizl.cx = nWidth; sizl.cy = nHeight;
+        pvCompressedBits = pvBits;
+        pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+        Decompress8bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
+        fl |= BMF_RLE_HACK;
     }
 
-    SURFACE_UnlockSurface(psurfBmp);
+    /* Set the bitmap bits */
+    if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
+    {
+        /* Bail out if that failed */
+        DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+        SURFACE_FreeSurfaceByHandle(hbmp);
+        return NULL;
+    }
 
-    DPRINT("IntGdiCreateBitmap : %dx%d, %d BPP colors, topdown %d, returning %08x\n",
-           Size.cx, Size.cy, BitsPixel, (Height < 0 ? 1 : 0), hBitmap);
+    /* Mark as API bitmap */
+    psurf->flags |= API_BITMAP;
 
-    return hBitmap;
+    /* Unlock the surface and return */
+    SURFACE_UnlockSurface(psurf);
+    return hbmp;
 }
 
+HBITMAP
+APIENTRY
+GreCreateBitmap(
+    IN INT nWidth,
+    IN INT nHeight,
+    IN UINT cPlanes,
+    IN UINT cBitsPixel,
+    IN OPTIONAL PVOID pvBits)
+{
+    /* Call the extended function */
+    return GreCreateBitmapEx(nWidth,
+                             nHeight,
+                             0, /* auto width */
+                             BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
+                             0, /* no bitmap flags */
+                             0, /* auto size */
+                             pvBits);
+}
 
-HBITMAP APIENTRY
+HBITMAP
+APIENTRY
 NtGdiCreateBitmap(
-    INWidth,
-    INHeight,
-    UINT Planes,
-    UINT BitsPixel,
+    IN INT nWidth,
+    IN INT nHeight,
+    IN UINT cPlanes,
+    IN UINT cBitsPixel,
     IN OPTIONAL LPBYTE pUnsafeBits)
 {
-    if (pUnsafeBits)
+    PSURFACE psurf;
+    SURFOBJ *pso;
+    HBITMAP hbmp;
+    FLONG fl = 0;
+    ULONG cjWidthBytes, iFormat;
+
+    /* NOTE: Windows also doesn't store nr. of planes separately! */
+    cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes);
+
+    /* Calculate bitmap format */
+    iFormat = BitmapFormat(cBitsPixel, BI_RGB);
+
+    /* Check parameters */
+    if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0)
     {
-        BOOL Hit = FALSE;
-        UINT cjBits = BITMAP_GetWidthBytes(Width, BitsPixel) * abs(Height);
+        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+                nWidth, nHeight, cBitsPixel);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
 
-        // FIXME: Use MmSecureVirtualMemory
+    /* Make sure that cjBits will not overflow */
+    cjWidthBytes = DIB_GetDIBWidthBytes(nWidth, cBitsPixel);
+    if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
+    {
+        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+                nWidth, nHeight, cBitsPixel);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Allocate a surface */
+    psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
+    if (!psurf)
+    {
+        DPRINT1("SURFACE_AllocSurface failed.\n");
+        EngSetLastError(ERROR_OUTOFMEMORY);
+        return NULL;
+    }
+
+    /* Get the handle for the bitmap and the surfobj */
+    hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+    pso = &psurf->SurfObj;
+
+    /* Allocate the bitmap bits */
+    if (!SURFACE_bSetBitmapBits(psurf, fl, 0, NULL))
+    {
+        /* Bail out if that failed */
+        DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+        SURFACE_FreeSurfaceByHandle(hbmp);
+        return NULL;
+    }
+    
+    if (pUnsafeBits)
+    {
         _SEH2_TRY
         {
-            ProbeForRead(pUnsafeBits, cjBits, 1);
+            ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
+            UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Hit = TRUE;
+            SURFACE_FreeSurfaceByHandle(hbmp);
+            _SEH2_YIELD(return NULL;)
         }
         _SEH2_END
-
-        if (Hit) return 0;
     }
 
-    return IntGdiCreateBitmap(Width, Height, Planes, BitsPixel, pUnsafeBits);
+    /* Mark as API bitmap */
+    psurf->flags |= API_BITMAP;
+
+    /* Unlock the surface and return */
+    SURFACE_UnlockSurface(psurf);
+    return hbmp;
 }
 
+
 HBITMAP FASTCALL
 IntCreateCompatibleBitmap(
     PDC Dc,
@@ -143,11 +257,24 @@ IntCreateCompatibleBitmap(
     {
         if (Dc->dctype != DC_TYPE_MEMORY)
         {
-            Bmp = IntGdiCreateBitmap(abs(Width),
-                                     abs(Height),
-                                     IntGdiGetDeviceCaps(Dc,PLANES),
-                                     IntGdiGetDeviceCaps(Dc,BITSPIXEL),
-                                     NULL);
+            PSURFACE psurf;
+            SIZEL size;
+
+            size.cx = abs(Width);
+            size.cy = abs(Height);
+            Bmp = GreCreateBitmap(abs(Width),
+                                  abs(Height),
+                                  1,
+                                  Dc->ppdev->gdiinfo.cBitsPixel,
+                                  NULL);
+            psurf = SURFACE_LockSurface(Bmp);
+            ASSERT(psurf);
+            /* Set palette */
+            psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+            /* Set flags */
+            psurf->flags = API_BITMAP;
+            psurf->hdc = NULL; // Fixme
+            SURFACE_UnlockSurface(psurf);
         }
         else
         {
@@ -160,83 +287,73 @@ IntCreateCompatibleBitmap(
             {
                 if (Count == sizeof(BITMAP))
                 {
-                    /* We have a bitmap bug!!! W/O the HACK, we have white icons.
-
-                       MSDN Note: When a memory device context is created, it initially
-                       has a 1-by-1 monochrome bitmap selected into it. If this memory
-                       device context is used in CreateCompatibleBitmap, the bitmap that
-                       is created is a monochrome bitmap. To create a color bitmap, use
-                       the hDC that was used to create the memory device context, as
-                       shown in the following code:
-
-                           HDC memDC = CreateCompatibleDC(hDC);
-                           HBITMAP memBM = CreateCompatibleBitmap(hDC, nWidth, nHeight);
-                           SelectObject(memDC, memBM);
-                     */
-                    Bmp = IntGdiCreateBitmap(abs(Width),
-                                             abs(Height),
-                                             dibs.dsBm.bmPlanes,
-                                             IntGdiGetDeviceCaps(Dc,BITSPIXEL),//<-- HACK! dibs.dsBm.bmBitsPixel, // <-- Correct!
-                                             NULL);
+                    SIZEL size;
+                    PSURFACE psurfBmp;
+                    size.cx = abs(Width);
+                    size.cy = abs(Height);
+                                       Bmp = GreCreateBitmap(abs(Width),
+                                  abs(Height),
+                                  1,
+                                  dibs.dsBm.bmBitsPixel,
+                                  NULL);
+                    psurfBmp = SURFACE_LockSurface(Bmp);
+                    ASSERT(psurfBmp);
+                    /* Assign palette */
+                    psurfBmp->ppal = psurf->ppal;
+                    GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
+                    /* Set flags */
+                    psurfBmp->flags = API_BITMAP;
+                    psurfBmp->hdc = NULL; // Fixme
+                    SURFACE_UnlockSurface(psurfBmp);
                 }
                 else
                 {
                     /* A DIB section is selected in the DC */
-                    BITMAPINFO *bi;
+                                       BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
                     PVOID Bits;
-
-                    /* Allocate memory for a BITMAPINFOHEADER structure and a
-                       color table. The maximum number of colors in a color table
-                       is 256 which corresponds to a bitmap with depth 8.
-                       Bitmaps with higher depths don't have color tables. */
-                    bi = ExAllocatePoolWithTag(PagedPool,
-                                               sizeof(BITMAPINFOHEADER) +
-                                                   256 * sizeof(RGBQUAD),
-                                               TAG_TEMP);
-
-                    if (bi)
+                                       BITMAPINFO* bi = (BITMAPINFO*)buf;
+
+                    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+                    bi->bmiHeader.biWidth         = Width;
+                    bi->bmiHeader.biHeight        = Height;
+                    bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
+                    bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
+                    bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
+                    bi->bmiHeader.biSizeImage     = 0;
+                    bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
+                    bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
+                    bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
+                    bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
+
+                    if (bi->bmiHeader.biCompression == BI_BITFIELDS)
                     {
-                        bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
-                        bi->bmiHeader.biWidth         = Width;
-                        bi->bmiHeader.biHeight        = Height;
-                        bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
-                        bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
-                        bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
-                        bi->bmiHeader.biSizeImage     = 0;
-                        bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
-                        bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
-                        bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
-                        bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
-
-                        if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                        /* Copy the color masks */
+                        RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
+                    }
+                    else if (bi->bmiHeader.biBitCount <= 8)
+                    {
+                        /* Copy the color table */
+                        UINT Index;
+                        PPALETTE PalGDI;
+
+                        if (!psurf->ppal)
                         {
-                            /* Copy the color masks */
-                            RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3 * sizeof(DWORD));
+                            SetLastWin32Error(ERROR_INVALID_HANDLE);
+                            return 0;
                         }
-                        else if (bi->bmiHeader.biBitCount <= 8)
+
+                        PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
+                        for (Index = 0;
+                                Index < 256 && Index < PalGDI->NumColors;
+                                Index++)
                         {
-                            /* Copy the color table */
-                            UINT Index;
-                            PPALETTE PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
-
-                            if (!PalGDI)
-                            {
-                                ExFreePoolWithTag(bi, TAG_TEMP);
-                                SetLastWin32Error(ERROR_INVALID_HANDLE);
-                                return 0;
-                            }
-
-                            for (Index = 0;
-                                    Index < 256 && Index < PalGDI->NumColors;
-                                    Index++)
-                            {
-                                bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
-                                bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
-                                bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
-                                bi->bmiColors[Index].rgbReserved = 0;
-                            }
-                            PALETTE_UnlockPalette(PalGDI);
+                            bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
+                            bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
+                            bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
+                            bi->bmiColors[Index].rgbReserved = 0;
                         }
+                        PALETTE_UnlockPalette(PalGDI);
 
                         Bmp = DIB_CreateDIBSection(Dc,
                                                    bi,
@@ -245,8 +362,6 @@ IntCreateCompatibleBitmap(
                                                    NULL,
                                                    0,
                                                    0);
-
-                        ExFreePoolWithTag(bi, TAG_TEMP);
                         return Bmp;
                     }
                 }
@@ -272,7 +387,7 @@ NtGdiCreateCompatibleBitmap(
     }
 
     if (!hDC)
-        return IntGdiCreateBitmap(Width, Height, 1, 1, 0);
+        return GreCreateBitmap(Width, Height, 1, 1, 0);
 
     Dc = DC_LockDc(hDC);
 
@@ -313,7 +428,7 @@ NtGdiGetBitmapDimension(
     _SEH2_TRY
     {
         ProbeForWrite(Dimension, sizeof(SIZE), 1);
-        *Dimension = psurfBmp->dimension;
+        *Dimension = psurfBmp->sizlDim;
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -334,7 +449,6 @@ NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
     BOOL bInRect = FALSE;
     SURFACE *psurf;
     SURFOBJ *pso;
-    HPALETTE hpal = 0;
     PPALETTE ppal;
     EXLATEOBJ exlo;
     HBITMAP hBmpTmp;
@@ -362,9 +476,13 @@ NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
         if (psurf)
         {
             pso = &psurf->SurfObj;
-            hpal = psurf->hDIBPalette;
-            if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
-            ppal = PALETTE_ShareLockPalette(hpal);
+            if (psurf->ppal)
+            {
+                ppal = psurf->ppal;
+                GDIOBJ_IncrementShareCount(&ppal->BaseObject);
+            }
+            else
+                ppal = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault);
 
             if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
             {
@@ -412,7 +530,7 @@ NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
                                                   0,
                                                   0);
 
-            //HBITMAP hBmpTmp = IntGdiCreateBitmap(1, 1, 1, 32, NULL);
+            //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL);
             if (hBmpTmp)
             {
                 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
@@ -535,46 +653,6 @@ NtGdiGetBitmapBits(
 }
 
 
-LONG APIENTRY
-IntSetBitmapBits(
-    PSURFACE psurf,
-    DWORD Bytes,
-    IN PBYTE Bits)
-{
-    LONG ret;
-
-    /* Don't copy more bytes than the buffer has */
-    Bytes = min(Bytes, psurf->SurfObj.cjBits);
-
-#if 0
-    /* FIXME: call DDI specific function here if available  */
-    if (psurf->DDBitmap)
-    {
-        DPRINT("Calling device specific BitmapBits\n");
-        if (psurf->DDBitmap->funcs->pBitmapBits)
-        {
-            ret = psurf->DDBitmap->funcs->pBitmapBits(hBitmap,
-                                                      (void *)Bits,
-                                                      Bytes,
-                                                      DDB_SET);
-        }
-        else
-        {
-            DPRINT("BitmapBits == NULL??\n");
-            ret = 0;
-        }
-    }
-    else
-#endif
-    {
-        RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
-        ret = Bytes;
-    }
-
-    return ret;
-}
-
-
 LONG APIENTRY
 NtGdiSetBitmapBits(
     HBITMAP hBitmap,
@@ -599,7 +677,8 @@ NtGdiSetBitmapBits(
     _SEH2_TRY
     {
         ProbeForRead(pUnsafeBits, Bytes, 1);
-        ret = IntSetBitmapBits(psurf, Bytes, pUnsafeBits);
+        UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
+        ret = 1;
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -637,7 +716,7 @@ NtGdiSetBitmapDimension(
         _SEH2_TRY
         {
             ProbeForWrite(Size, sizeof(SIZE), 1);
-            *Size = psurf->dimension;
+            *Size = psurf->sizlDim;
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
@@ -647,8 +726,8 @@ NtGdiSetBitmapDimension(
     }
 
     /* The dimension is changed even if writing the old value failed */
-    psurf->dimension.cx = Width;
-    psurf->dimension.cy = Height;
+    psurf->sizlDim.cx = Width;
+    psurf->sizlDim.cy = Height;
 
     SURFACE_UnlockSurface(psurf);
 
@@ -665,7 +744,7 @@ VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color)
     switch (*Color >> 24)
     {
         case 0x10: /* DIBINDEX */
-            if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1) 
+            if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
             {
                 *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
             }
@@ -707,7 +786,7 @@ VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color)
         default:
             DPRINT("Unsupported color type %d passed\n", *Color >> 24);
             break;
-    }   
+    }
 }
 
 BOOL APIENTRY
@@ -846,11 +925,11 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
 
     Size.cx = abs(bm.bmWidth);
     Size.cy = abs(bm.bmHeight);
-    res = IntCreateBitmap(Size,
-                          bm.bmWidthBytes,
-                          BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
-                          (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
-                          NULL);
+            res = GreCreateBitmap(abs(bm.bmWidth),
+                                  abs(bm.bmHeight),
+                                  1,
+                                  bm.bmBitsPixel,
+                                  NULL);
 
     if (res)
     {
@@ -872,7 +951,13 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
             IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
             IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
             ExFreePoolWithTag(buf,TAG_BITMAP);
-            resBitmap->flFlags = Bitmap->flFlags;
+            resBitmap->flags = Bitmap->flags;
+            /* Copy palette */
+            if (Bitmap->ppal)
+            {
+                resBitmap->ppal = Bitmap->ppal ;
+                GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject);
+            }
             GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
         }
         else
@@ -975,14 +1060,14 @@ APIENTRY
 NtGdiGetDCforBitmap(
     IN HBITMAP hsurf)
 {
-    HDC hDC = NULL;
+    HDC hdc = NULL;
     PSURFACE psurf = SURFACE_LockSurface(hsurf);
     if (psurf)
     {
-        hDC = psurf->hDC;
+        hdc = psurf->hdc;
         SURFACE_UnlockSurface(psurf);
     }
-    return hDC;
+    return hdc;
 }
 
 /* EOF */