[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dibobj.c
index deedecd..83252a9 100644 (file)
@@ -103,134 +103,186 @@ static const RGBQUAD DefLogPaletteTriples[20] =   /* Copy of Default Logical Pal
     { 0xff, 0xff, 0xff }
 };
 
-
-UINT
-APIENTRY
-IntSetDIBColorTable(
-    HDC hDC,
-    UINT StartIndex,
-    UINT Entries,
-    CONST RGBQUAD *Colors)
+PPALETTE
+NTAPI
+CreateDIBPalette(
+    _In_ const BITMAPINFO *pbmi,
+    _In_ PDC pdc,
+    _In_ ULONG iUsage)
 {
-    PDC dc;
-    PSURFACE psurf;
-    PPALETTE PalGDI;
-    UINT Index;
-    ULONG biBitCount;
+    PPALETTE ppal;
+    ULONG i, cBitsPixel, cColors;
 
-    if (!(dc = DC_LockDc(hDC))) return 0;
-    if (dc->dctype == DC_TYPE_INFO)
+    if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
     {
-        DC_UnlockDc(dc);
-        return 0;
+        PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
+        cBitsPixel = pbci->bmciHeader.bcBitCount;
     }
-
-    psurf = dc->dclevel.pSurface;
-    if (psurf == NULL)
+    else
     {
-        DC_UnlockDc(dc);
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
+        cBitsPixel = pbmi->bmiHeader.biBitCount;
     }
 
-    if (psurf->hSecure == NULL)
+    /* Check if the colors are indexed */
+    if (cBitsPixel <= 8)
     {
-        DC_UnlockDc(dc);
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
+        /* We create a "full" palette */
+        cColors = 1 << cBitsPixel;
 
-    biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-    if ((biBitCount <= 8) && (StartIndex < (1UL << biBitCount)))
-    {
-        if (StartIndex + Entries > (1UL << biBitCount))
-            Entries = (1 << biBitCount) - StartIndex;
+        /* Allocate the palette */
+        ppal = PALETTE_AllocPalette(PAL_INDEXED,
+                                    cColors,
+                                    NULL,
+                                    0,
+                                    0,
+                                    0);
 
-        if (psurf->ppal == NULL)
+        /* Check if the BITMAPINFO specifies how many colors to use */
+        if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
+            (pbmi->bmiHeader.biClrUsed != 0))
         {
-            DC_UnlockDc(dc);
-            EngSetLastError(ERROR_INVALID_HANDLE);
-            return 0;
+            /* This is how many colors we can actually process */
+            cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
         }
 
-        PalGDI = psurf->ppal;
-
-        for (Index = StartIndex;
-                Index < StartIndex + Entries && Index < PalGDI->NumColors;
-                Index++)
+        /* Check how to use the colors */
+        if (iUsage == DIB_PAL_COLORS)
         {
-            PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
-            PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
-            PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
-        }
-    }
-    else
-        Entries = 0;
+            COLORREF crColor;
 
-    /* Mark the brushes invalid */
-    dc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|DIRTY_BACKGROUND|DIRTY_TEXT;
+            /* The colors are an array of WORD indices into the DC palette */
+            PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
 
-    DC_UnlockDc(dc);
+            /* Use the DCs palette or, if no DC is given, the default one */
+            PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
 
-    return Entries;
-}
+            /* Loop all color indices in the DIB */
+            for (i = 0; i < cColors; i++)
+            {
+                /* Get the palette index and handle wraparound when exceeding
+                   the number of colors in the DC palette */
+                WORD wIndex = pwColors[i] % ppalDC->NumColors;
 
-UINT
-APIENTRY
-IntGetDIBColorTable(
-    HDC hDC,
-    UINT StartIndex,
-    UINT Entries,
-    RGBQUAD *Colors)
-{
-    PDC dc;
-    PSURFACE psurf;
-    PPALETTE ppal;
-    UINT Index, Count = 0;
+                /* USe the RGB value from the DC palette */
+                crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
+                PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+            }
+        }
+        else if (iUsage == DIB_PAL_BRUSHHACK)
+        {
+            /* The colors are an array of WORD indices into the DC palette */
+            PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
 
-    if (!(dc = DC_LockDc(hDC))) return 0;
-    if (dc->dctype == DC_TYPE_INFO)
-    {
-        DC_UnlockDc(dc);
-        return 0;
-    }
+            /* Loop all color indices in the DIB */
+            for (i = 0; i < cColors; i++)
+            {
+                /* Set the index directly as the RGB color, the real palette
+                   containing RGB values will be calculated when the brush is
+                   realized */
+                PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
+            }
 
-    psurf = dc->dclevel.pSurface;
-    if (psurf == NULL)
-    {
-        DC_UnlockDc(dc);
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
+            /* Mark the palette as a brush hack palette */
+            ppal->flFlags |= PAL_BRUSHHACK;
+        }
+//        else if (iUsage == 2)
+//        {
+            // FIXME: this one is undocumented
+//            ASSERT(FALSE);
+//        }
+        else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
+        {
+            /* The colors are an array of RGBQUAD values */
+            RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
 
-    if (psurf->hSecure == NULL)
-    {
-        DC_UnlockDc(dc);
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
+            // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
 
-    ppal = psurf->ppal;
-    ASSERT(ppal);
+            /* Loop all color indices in the DIB */
+            for (i = 0; i < cColors; i++)
+            {
+                /* Get the color value and translate it to a COLORREF */
+                RGBQUAD rgb = prgb[i];
+                COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
+
+                /* Set the RGB value in the palette */
+                PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+            }
+        }
+        else
+        {
+            /* The colors are an array of RGBTRIPLE values */
+            RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
 
-    if (ppal->flFlags & PAL_INDEXED)
+            /* Loop all color indices in the DIB */
+            for (i = 0; i < cColors; i++)
+            {
+                /* Get the color value and translate it to a COLORREF */
+                RGBTRIPLE rgb = prgb[i];
+                COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
+
+                /* Set the RGB value in the palette */
+                PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+            }
+        }
+    }
+    else
     {
+        /* This is a bitfield / RGB palette */
+        ULONG flRedMask, flGreenMask, flBlueMask;
 
-        for (Index = StartIndex;
-                Index < StartIndex + Entries && Index < ppal->NumColors;
-                Index++)
+        /* Check if the DIB contains bitfield values */
+        if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
+            (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
+        {
+            /* Check if we have a v4/v5 header */
+            if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
+            {
+                /* The masks are dedicated fields in the header */
+                PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
+                flRedMask = pbmV4Header->bV4RedMask;
+                flGreenMask = pbmV4Header->bV4GreenMask;
+                flBlueMask = pbmV4Header->bV4BlueMask;
+            }
+            else
+            {
+                /* The masks are the first 3 values in the DIB color table */
+                PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
+                flRedMask = pdwColors[0];
+                flGreenMask = pdwColors[1];
+                flBlueMask = pdwColors[2];
+            }
+        }
+        else
         {
-            Colors[Index - StartIndex].rgbRed = ppal->IndexedColors[Index].peRed;
-            Colors[Index - StartIndex].rgbGreen = ppal->IndexedColors[Index].peGreen;
-            Colors[Index - StartIndex].rgbBlue = ppal->IndexedColors[Index].peBlue;
-            Colors[Index - StartIndex].rgbReserved = 0;
-            Count++;
+            /* Check what bit depth we have. Note: optimization flags are
+               calculated in PALETTE_AllocPalette()  */
+            if (cBitsPixel == 16)
+            {
+                /* This is an RGB 555 palette */
+                flRedMask = 0x7C00;
+                flGreenMask = 0x03E0;
+                flBlueMask = 0x001F;
+            }
+            else
+            {
+                /* This is an RGB 888 palette */
+                flRedMask = 0xFF0000;
+                flGreenMask = 0x00FF00;
+                flBlueMask = 0x0000FF;
+            }
         }
-    }
 
-    DC_UnlockDc(dc);
+        /* Allocate the bitfield palette */
+        ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
+                                    0,
+                                    NULL,
+                                    flRedMask,
+                                    flGreenMask,
+                                    flBlueMask);
+    }
 
-    return Count;
+    /* We're done, return the palette */
+    return ppal;
 }
 
 // Converts a DIB to a device-dependent bitmap
@@ -251,9 +303,10 @@ IntSetDIBits(
     RECT               rcDst;
     POINTL             ptSrc;
     EXLATEOBJ  exlo;
-    HPALETTE    hpalDIB = 0;
     PPALETTE    ppalDIB = 0;
 
+    if (!bmi) return 0;
+
     SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
                                      ScanLines,
                                      0,
@@ -280,18 +333,10 @@ IntSetDIBits(
     }
 
     /* Create a palette for the DIB */
-    hpalDIB = BuildDIBPalette(bmi);
-    if (!hpalDIB)
-    {
-        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
-        goto cleanup;
-    }
-
-    /* Lock the DIB palette */
-    ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
+    ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
     if (!ppalDIB)
     {
-        EngSetLastError(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         goto cleanup;
     }
 
@@ -323,7 +368,6 @@ IntSetDIBits(
 
 cleanup:
     if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
-    if (hpalDIB) GreDeleteObject(hpalDIB);
     if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
     if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
     GreDeleteObject(SourceBitmap);
@@ -331,6 +375,115 @@ cleanup:
     return result;
 }
 
+static
+HBITMAP
+IntGdiCreateMaskFromRLE(
+    DWORD Width,
+    DWORD Height,
+    ULONG Compression,
+    const BYTE* Bits,
+    DWORD BitsSize)
+{
+    HBITMAP Mask;
+    DWORD x, y;
+    SURFOBJ* SurfObj;
+    UINT i = 0;
+    BYTE Data, NumPixels, ToSkip;
+
+    ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
+
+    /* Create the bitmap */
+    Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
+    if (!Mask)
+        return NULL;
+
+    SurfObj = EngLockSurface((HSURF)Mask);
+    if (!SurfObj)
+    {
+        GreDeleteObject(Mask);
+        return NULL;
+    }
+    ASSERT(SurfObj->pvBits != NULL);
+
+    x = y = 0;
+
+    while (i < BitsSize)
+    {
+        NumPixels = Bits[i];
+        Data = Bits[i + 1];
+        i += 2;
+
+        if (NumPixels != 0)
+        {
+            if ((x + NumPixels) > Width)
+                NumPixels = Width - x;
+
+            if (NumPixels == 0)
+                continue;
+
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+            continue;
+        }
+
+        if (Data < 3)
+        {
+            switch (Data)
+            {
+                case 0:
+                    /* End of line */
+                    y++;
+                    if (y == Height)
+                        goto done;
+                    x = 0;
+                    break;
+                case 1:
+                    /* End of file */
+                    goto done;
+                case 2:
+                    /* Jump */
+                    if (i >= (BitsSize - 1))
+                        goto done;
+                    x += Bits[i];
+                    if (x > Width)
+                        x = Width;
+                    y += Bits[i + 1];
+                    if (y >= Height)
+                        goto done;
+                    i += 2;
+                    break;
+            }
+            /* Done for this run */
+            continue;
+        }
+
+        /* Embedded data into the RLE */
+        NumPixels = Data;
+        if (Compression == BI_RLE8)
+            ToSkip = NumPixels;
+        else
+            ToSkip = (NumPixels / 2) + (NumPixels & 1);
+
+        if ((i + ToSkip) > BitsSize)
+            goto done;
+        ToSkip = (ToSkip + 1) & ~1;
+
+        if ((x + NumPixels) > Width)
+            NumPixels = Width - x;
+
+        if (NumPixels != 0)
+        {
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+        }
+        i += ToSkip;
+    }
+
+done:
+    EngUnlockSurface(SurfObj);
+    return Mask;
+}
+
 W32KAPI
 INT
 APIENTRY
@@ -355,8 +508,8 @@ NtGdiSetDIBitsToDeviceInternal(
     INT ret = 0;
     NTSTATUS Status = STATUS_SUCCESS;
     PDC pDC;
-    HBITMAP hSourceBitmap = NULL;
-    SURFOBJ *pDestSurf, *pSourceSurf = NULL;
+    HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
+    SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
     SURFACE *pSurf;
     RECTL rcDest;
     POINTL ptSource;
@@ -364,7 +517,6 @@ NtGdiSetDIBitsToDeviceInternal(
     SIZEL SourceSize;
     EXLATEOBJ exlo;
     PPALETTE ppalDIB = NULL;
-    HPALETTE hpalDIB = NULL;
     LPBITMAPINFO pbmiSafe;
 
     if (!Bits) return 0;
@@ -390,24 +542,21 @@ NtGdiSetDIBitsToDeviceInternal(
         goto Exit2;
     }
 
+    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
+
     pDC = DC_LockDc(hDC);
     if (!pDC)
     {
         EngSetLastError(ERROR_INVALID_HANDLE);
         goto Exit2;
     }
+
     if (pDC->dctype == DC_TYPE_INFO)
     {
         DC_UnlockDc(pDC);
-        goto Exit2;
+        goto Exit;
     }
 
-    pSurf = pDC->dclevel.pSurface;
-
-    pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
-
-    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
-
     rcDest.left = XDest;
     rcDest.top = YDest;
     if (bTransformCoordinates)
@@ -452,26 +601,49 @@ NtGdiSetDIBitsToDeviceInternal(
         goto Exit;
     }
 
-    ASSERT(pSurf->ppal);
+    /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
+    if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
+    {
+        hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
+            ScanLines,
+            bmi->bmiHeader.biCompression,
+            Bits,
+            cjMaxBits);
+        if (!hMaskBitmap)
+        {
+            EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
+            Status = STATUS_NO_MEMORY;
+            goto Exit;
+        }
+        pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
+        if (!pMaskSurf)
+        {
+            Status = STATUS_UNSUCCESSFUL;
+            goto Exit;
+        }
+    }
 
     /* Create a palette for the DIB */
-    hpalDIB = BuildDIBPalette(bmi);
-    if (!hpalDIB)
+    ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
+    if (!ppalDIB)
     {
         EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
 
-    /* Lock the DIB palette */
-    ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
-    if (!ppalDIB)
+    /* This is actually a blit */
+    DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
+    pSurf = pDC->dclevel.pSurface;
+    if (!pSurf)
     {
-        EngSetLastError(ERROR_INVALID_HANDLE);
-        Status = STATUS_UNSUCCESSFUL;
+        DC_vFinishBlit(pDC, NULL);
+        ret = ScanLines;
         goto Exit;
     }
 
+    ASSERT(pSurf->ppal);
+
     /* Initialize EXLATEOBJ */
     EXLATEOBJ_vInitialize(&exlo,
                           ppalDIB,
@@ -480,25 +652,30 @@ NtGdiSetDIBitsToDeviceInternal(
                           pDC->pdcattr->crBackgroundClr,
                           pDC->pdcattr->crForegroundClr);
 
+    pDestSurf = &pSurf->SurfObj;
+
     /* Copy the bits */
     DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
            rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
            ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
     Status = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
-                          NULL,
-                          pDC->rosdc.CombinedClip,
+                          pMaskSurf,
+                          &pDC->co.ClipObj,
                           &exlo.xlo,
                           &rcDest,
                           &ptSource,
+                          pMaskSurf ? &ptSource : NULL,
                           NULL,
                           NULL,
-                          NULL,
-                          ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+                          pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
 
     /* Cleanup EXLATEOBJ */
     EXLATEOBJ_vCleanup(&exlo);
 
+    /* We're done */
+    DC_vFinishBlit(pDC, NULL);
+
 Exit:
     if (NT_SUCCESS(Status))
     {
@@ -509,10 +686,11 @@ Exit:
 
     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
-    if (hpalDIB) GreDeleteObject(hpalDIB);
+    if (pMaskSurf) EngUnlockSurface(pMaskSurf);
+    if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
     DC_UnlockDc(pDC);
 Exit2:
-    ExFreePool(pbmiSafe);
+    ExFreePoolWithTag(pbmiSafe, 'pmTG');
     return ret;
 }
 
@@ -520,7 +698,7 @@ Exit2:
 /* Converts a device-dependent bitmap to a DIB */
 INT
 APIENTRY
-NtGdiGetDIBitsInternal(
+GreGetDIBitsInternal(
     HDC hDC,
     HBITMAP hBitmap,
     UINT StartScan,
@@ -539,36 +717,15 @@ NtGdiGetDIBitsInternal(
     DWORD compr, size ;
     USHORT i;
     int bitmap_type;
-    RGBTRIPLE* rgbTriples;
     RGBQUAD* rgbQuads;
     VOID* colorPtr;
-    NTSTATUS Status = STATUS_SUCCESS;
 
     DPRINT("Entered NtGdiGetDIBitsInternal()\n");
 
     if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
         return 0;
 
-    _SEH2_TRY
-    {
-        /* Probe for read and write */
-        ProbeForRead(Info, MaxInfo, 1);
-        ProbeForWrite(Info, MaxInfo, 1);
-        if (Bits) ProbeForWrite(Bits, MaxBits, 1);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END
-
-    if (!NT_SUCCESS(Status))
-    {
-        return 0;
-    }
-
     colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
-    rgbTriples = colorPtr;
     rgbQuads = colorPtr;
 
     bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
@@ -617,15 +774,6 @@ NtGdiGetDIBitsInternal(
     switch(bpp)
     {
     case 0: /* Only info */
-        if(pbmci)
-        {
-            pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
-            pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
-                                         -psurf->SurfObj.sizlBitmap.cy :
-                                         psurf->SurfObj.sizlBitmap.cy);
-            pbmci->bmciHeader.bcPlanes = 1;
-            pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-        }
         Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
         Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
                                    -psurf->SurfObj.sizlBitmap.cy :
@@ -676,31 +824,19 @@ NtGdiGetDIBitsInternal(
             if(Usage == DIB_RGB_COLORS)
             {
                 ULONG colors = min(psurf->ppal->NumColors, 256);
-
-                if(pbmci)
-                {
-                    for(i = 0; i < colors; i++)
-                    {
-                        rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
-                        rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
-                        rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
-                    }
-                }
                 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
                 for(i = 0; i < colors; i++)
                 {
                     rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
                     rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
                     rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
+                    rgbQuads[i].rgbReserved = 0;
                 }
             }
             else
             {
                 for(i = 0; i < 256; i++)
-                {
-                    if(pbmci) ((WORD*)rgbTriples)[i] = i;
                     ((WORD*)rgbQuads)[i] = i;
-                }
             }
         }
         else
@@ -709,7 +845,6 @@ NtGdiGetDIBitsInternal(
             {
                 for(i = 0; i < 256; i++)
                 {
-                    if(pbmci) ((WORD*)rgbTriples)[i] = i;
                     ((WORD*)rgbQuads)[i] = i;
                 }
             }
@@ -726,13 +861,6 @@ NtGdiGetDIBitsInternal(
                 }
                 for (i = 0; i < pDcPal->NumColors; i++)
                 {
-                    if (pbmci)
-                    {
-                        rgbTriples[i].rgbtRed   = pDcPal->IndexedColors[i].peRed;
-                        rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
-                        rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
-                    }
-
                     rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
                     rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
                     rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
@@ -745,55 +873,20 @@ NtGdiGetDIBitsInternal(
                 switch (bpp)
                 {
                 case 1:
-                    if (pbmci)
-                    {
-                        rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
-                                                    rgbTriples[0].rgbtBlue = 0;
-                        rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
-                                                    rgbTriples[1].rgbtBlue = 0xff;
-                    }
-                    rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
-                                             rgbQuads[0].rgbBlue = 0;
+                    rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
                     rgbQuads[0].rgbReserved = 0;
-                    rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
-                                             rgbQuads[1].rgbBlue = 0xff;
+                    rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
                     rgbQuads[1].rgbReserved = 0;
                     break;
 
                 case 4:
-                    if (pbmci)
-                        RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
                     RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
-
                     break;
 
                 case 8:
                 {
                     INT r, g, b;
                     RGBQUAD *color;
-                    if (pbmci)
-                    {
-                        RGBTRIPLE *colorTriple;
-
-                        RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
-                                      10 * sizeof(RGBTRIPLE));
-                        RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
-                                      10 * sizeof(RGBTRIPLE));
-                        colorTriple = rgbTriples + 10;
-                        for(r = 0; r <= 5; r++) /* FIXME */
-                        {
-                            for(g = 0; g <= 5; g++)
-                            {
-                                for(b = 0; b <= 5; b++)
-                                {
-                                    colorTriple->rgbtRed =   (r * 0xff) / 5;
-                                    colorTriple->rgbtGreen = (g * 0xff) / 5;
-                                    colorTriple->rgbtBlue =  (b * 0xff) / 5;
-                                    color++;
-                                }
-                            }
-                        }
-                    }
                     memcpy(rgbQuads, DefLogPaletteQuads,
                            10 * sizeof(RGBQUAD));
                     memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
@@ -908,10 +1001,7 @@ NtGdiGetDIBitsInternal(
 
         psurfDest = SURFACE_ShareLockSurface(hBmpDest);
 
-        rcDest.left = 0;
-        rcDest.top = 0;
-        rcDest.bottom = ScanLines;
-        rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+        RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
 
         srcPoint.x = 0;
 
@@ -949,22 +1039,7 @@ NtGdiGetDIBitsInternal(
             ScanLines = 0;
         else
         {
-            Status = STATUS_SUCCESS;
-            _SEH2_TRY
-            {
-                RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
-            }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-            {
-                Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END
-
-            if(!NT_SUCCESS(Status))
-            {
-                DPRINT1("Unable to copy bits to the user provided pointer\n");
-                ScanLines = 0;
-            }
+            RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
         }
 
         GreDeleteObject(hBmpDest);
@@ -976,11 +1051,120 @@ done:
 
     if(pDC) DC_UnlockDc(pDC);
     if(psurf) SURFACE_ShareUnlockSurface(psurf);
-    if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+    if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
 
     return ScanLines;
 }
 
+INT
+APIENTRY
+NtGdiGetDIBitsInternal(
+    _In_ HDC hdc,
+    _In_ HBITMAP hbm,
+    _In_ UINT iStartScan,
+    _In_ UINT cScans,
+    _Out_opt_ LPBYTE pjBits,
+    _Inout_ LPBITMAPINFO pbmiUser,
+    _In_ UINT iUsage,
+    _In_ UINT cjMaxBits,
+    _In_ UINT cjMaxInfo)
+{
+    PBITMAPINFO pbmi;
+    HANDLE hSecure = NULL;
+    INT iResult = 0;
+    UINT cjAlloc;
+
+    /* Check for bad iUsage */
+    if (iUsage > 2) return 0;
+
+    /* Check if the size of the bitmap info is large enough */
+    if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
+    {
+        return 0;
+    }
+
+    /* Use maximum size */
+    cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
+
+    // HACK: the underlying code sucks and doesn't care for the size, so we
+    // give it the maximum ever needed
+    cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
+
+    /* Allocate a buffer the bitmapinfo */
+    pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
+    if (!pbmi)
+    {
+        /* Fail */
+        return 0;
+    }
+
+    /* Use SEH */
+    _SEH2_TRY
+    {
+        /* Probe and copy the BITMAPINFO */
+        ProbeForRead(pbmiUser, cjMaxInfo, 1);
+        RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        _SEH2_YIELD(goto cleanup;)
+    }
+    _SEH2_END;
+
+    /* Check if the header size is large enough */
+    if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
+        (pbmi->bmiHeader.biSize > cjMaxInfo))
+    {
+        goto cleanup;
+    }
+
+    /* Check if the caller provided bitmap bits */
+    if (pjBits)
+    {
+        /* Secure the user mode memory */
+        hSecure = EngSecureMem(pjBits, cjMaxBits);
+        if (!hSecure)
+        {
+            goto cleanup;
+        }
+    }
+
+    /* Now call the internal function */
+    iResult = GreGetDIBitsInternal(hdc,
+                                   hbm,
+                                   iStartScan,
+                                   cScans,
+                                   pjBits,
+                                   pbmi,
+                                   iUsage,
+                                   cjMaxBits,
+                                   cjMaxInfo);
+
+    /* Check for success */
+    if (iResult)
+    {
+        /* Use SEH to copy back to user mode */
+        _SEH2_TRY
+        {
+            /* Copy the data back */
+            ProbeForWrite(pbmiUser, cjMaxInfo, 1);
+            RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Ignore */
+        }
+        _SEH2_END;
+    }
+
+cleanup:
+    if (hSecure) EngUnsecureMem(hSecure);
+    ExFreePoolWithTag(pbmi, 'imBG');
+
+    return iResult;
+}
+
+
 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
 
 W32KAPI
@@ -1010,7 +1194,6 @@ NtGdiStretchDIBitsInternal(
     PDC pdc;
     HBITMAP hbmTmp = 0;
     PSURFACE psurfTmp = 0, psurfDst = 0;
-    HPALETTE hpalDIB = 0;
     PPALETTE ppalDIB = 0;
     EXLATEOBJ exlo;
     PVOID pvBits;
@@ -1021,6 +1204,14 @@ NtGdiStretchDIBitsInternal(
         return 0;
     }
 
+    /* Check for info / mem DC without surface */
+    if (!pdc->dclevel.pSurface)
+    {
+        DC_UnlockDc(pdc);
+        // CHECKME
+        return TRUE;
+    }
+
     /* Transform dest size */
     sizel.cx = cxDst;
     sizel.cy = cyDst;
@@ -1049,22 +1240,30 @@ NtGdiStretchDIBitsInternal(
                                               hcmXform);
     }
 
-    pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
-    if (!pvBits)
+    if (pjInit && (cjMaxBits > 0))
     {
-        return 0;
-    }
+        pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
+        if (!pvBits)
+        {
+            return 0;
+        }
 
-    _SEH2_TRY
-    {
-        ProbeForRead(pjInit, cjMaxBits, 1);
-        RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+        _SEH2_TRY
+        {
+            ProbeForRead(pjInit, cjMaxBits, 1);
+            RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            ExFreePoolWithTag(pvBits, 'pmeT');
+            _SEH2_YIELD(return 0);
+        }
+        _SEH2_END
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    else
     {
-        _SEH2_YIELD(return 0);
+        pvBits = NULL;
     }
-    _SEH2_END
 
     /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
     if (!(pdc = DC_LockDc(hdc)))
@@ -1074,14 +1273,6 @@ NtGdiStretchDIBitsInternal(
         goto cleanup;
     }
 
-    psurfDst = pdc->dclevel.pSurface;
-    if (!psurfDst)
-    {
-        // CHECKME
-        bResult = TRUE;
-        goto cleanup;
-    }
-
     /* Calculate source and destination rect */
     rcSrc.left = xSrc;
     rcSrc.top = ySrc;
@@ -1118,21 +1309,18 @@ NtGdiStretchDIBitsInternal(
     }
 
     /* Create a palette for the DIB */
-    hpalDIB = BuildDIBPalette(pbmi);
-    if (!hpalDIB)
-    {
-        bResult = FALSE;
-        goto cleanup;
-    }
-
-    /* Lock the DIB palette */
-    ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
+    ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
     if (!ppalDIB)
     {
         bResult = FALSE;
         goto cleanup;
     }
 
+    /* Prepare DC for blit */
+    DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
+
+    psurfDst = pdc->dclevel.pSurface;
+
     /* Initialize XLATEOBJ */
     EXLATEOBJ_vInitialize(&exlo,
                           ppalDIB,
@@ -1141,15 +1329,13 @@ NtGdiStretchDIBitsInternal(
                           pdc->pdcattr->crBackgroundClr,
                           pdc->pdcattr->crForegroundClr);
 
-    /* Prepare DC for blit */
-    DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
-
     /* Perform the stretch operation */
     bResult = IntEngStretchBlt(&psurfDst->SurfObj,
                                &psurfTmp->SurfObj,
                                NULL,
-                               pdc->rosdc.CombinedClip,
+                               &pdc->co.ClipObj,
                                &exlo.xlo,
+                               &pdc->dclevel.ca,
                                &rcDst,
                                &rcSrc,
                                NULL,
@@ -1162,11 +1348,10 @@ NtGdiStretchDIBitsInternal(
     EXLATEOBJ_vCleanup(&exlo);
 cleanup:
     if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
-    if (hpalDIB) GreDeleteObject(hpalDIB);
     if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
     if (hbmTmp) GreDeleteObject(hbmTmp);
     if (pdc) DC_UnlockDc(pdc);
-    ExFreePoolWithTag(pvBits, 'pmeT');
+    if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
 
     return bResult;
 }
@@ -1257,6 +1442,7 @@ NtGdiCreateDIBitmapInternal(
 
     if(pjInit && (fInit == CBM_INIT))
     {
+        if (cjMaxBits == 0) return NULL;
         safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
         if(!safeBits)
         {
@@ -1439,7 +1625,7 @@ DIB_CreateDIBSection(
     HBITMAP res = 0;
     SURFACE *bmp = NULL;
     void *mapBits = NULL;
-    HPALETTE hpal ;
+    PPALETTE ppalDIB = NULL;
 
     // Fill BITMAP32 structure with DIB data
     CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
@@ -1449,7 +1635,7 @@ DIB_CreateDIBSection(
     //SIZEL Size;
     HANDLE hSecure;
 
-    DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
+    DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
            bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
            bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
 
@@ -1534,33 +1720,6 @@ DIB_CreateDIBSection(
 //  hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
     hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
 
-    if (usage == DIB_PAL_COLORS)
-    {
-        if(dc)
-        {
-            PPALETTE ppalDc;
-            ppalDc = PALETTE_ShareLockPalette(dc->dclevel.hpal);
-            hpal = DIB_MapPaletteColors(ppalDc, bmi);
-            PALETTE_ShareUnlockPalette(ppalDc);
-        }
-        else
-        {
-            /* For DIB Brushes */
-            DPRINT1("FIXME: Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
-            /* HACK */
-            hpal = (HPALETTE) 0xFFFFFFFF;
-        }
-    }
-    else
-    {
-        hpal = BuildDIBPalette(bmi);
-    }
-
-    if(!hpal)
-    {
-        DPRINT1("Error: Could not create a palette for the DIB.\n");
-        goto cleanup;
-    }
 
     // Create Device Dependent Bitmap and add DIB pointer
     //Size.cx = bm.bmWidth;
@@ -1598,26 +1757,14 @@ DIB_CreateDIBSection(
     bmp->flags = API_BITMAP;
     bmp->biClrImportant = bi->biClrImportant;
 
-    /* HACK */
-    if(hpal != (HPALETTE)0xFFFFFFFF)
-    {
-        PPALETTE ppal = PALETTE_ShareLockPalette(hpal);
-
-        if (ppal)
-        {
-            if (bmp->ppal) PALETTE_ShareUnlockPalette(bmp->ppal);
-            bmp->ppal = ppal;
-        }
-
-        /* Lazy delete hpal, it will be freed at surface release */
-        GreDeleteObject(hpal);
-    }
+    /* Create a palette for the DIB */
+    ppalDIB = CreateDIBPalette(bmi, dc, usage);
 
     // Clean up in case of errors
 cleanup:
-    if (!res || !bmp || !bm.bmBits)
+    if (!res || !bmp || !bm.bmBits || !ppalDIB)
     {
-        DPRINT("Got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
+        DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
         if (bm.bmBits)
         {
             // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
@@ -1631,17 +1778,28 @@ cleanup:
         }
 
         if (bmp)
+        {
+            SURFACE_ShareUnlockSurface(bmp);
             bmp = NULL;
+        }
 
         if (res)
         {
             GreDeleteObject(res);
             res = 0;
         }
+
+        if(ppalDIB)
+        {
+            PALETTE_ShareUnlockPalette(ppalDIB);
+        }
     }
 
     if (bmp)
     {
+        /* If we're here, everything went fine */
+        SURFACE_vSetPalette(bmp, ppalDIB);
+        PALETTE_ShareUnlockPalette(ppalDIB);
         SURFACE_ShareUnlockSurface(bmp);
     }
 
@@ -1686,7 +1844,7 @@ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
         *size   = header->biSizeImage;
         return 1;
     }
-    DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
+    DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
     return -1;
 }
 
@@ -1774,112 +1932,6 @@ DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
     return hpal;
 }
 
-HPALETTE
-FASTCALL
-BuildDIBPalette(CONST BITMAPINFO *bmi)
-{
-    WORD bits;
-    ULONG ColorCount;
-    HPALETTE hpal;
-    PPALETTE ppal;
-    ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
-    PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
-    ULONG paletteType, i;
-
-    // Determine Bits Per Pixel
-    bits = bmi->bmiHeader.biBitCount;
-
-    // Determine paletteType from Bits Per Pixel
-    if (bits <= 8)
-    {
-        paletteType = PAL_INDEXED;
-        RedMask = GreenMask = BlueMask = 0;
-    }
-    else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
-    {
-        paletteType = PAL_BITFIELDS;
-        if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
-        {
-            PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
-            RedMask = pV4Header->bV4RedMask;
-            GreenMask = pV4Header->bV4GreenMask;
-            BlueMask = pV4Header->bV4BlueMask;
-        }
-        else
-        {
-            RedMask = pdwColors[0];
-            GreenMask = pdwColors[1];
-            BlueMask = pdwColors[2];
-        }
-    }
-    else
-    {
-        paletteType = PAL_BITFIELDS;
-        switch (bits)
-        {
-        case 16:
-            paletteType |= PAL_RGB16_555;
-            RedMask = 0x7C00;
-            GreenMask = 0x03E0;
-            BlueMask = 0x001F;
-            break;
-
-        case 24:
-        case 32:
-            paletteType |= PAL_BGR;
-            RedMask = 0xFF0000;
-            GreenMask = 0x00FF00;
-            BlueMask = 0x0000FF;
-            break;
-        }
-    }
-
-    if (bmi->bmiHeader.biClrUsed == 0)
-    {
-        ColorCount = 1 << bmi->bmiHeader.biBitCount;
-    }
-    else
-    {
-        ColorCount = bmi->bmiHeader.biClrUsed;
-    }
-
-    if (paletteType == PAL_INDEXED)
-    {
-        RGBQUAD* pColors = (RGBQUAD*)((PBYTE)bmi + bmi->bmiHeader.biSize);
-
-        /* Allocate a palette */
-        ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED,
-                                          ColorCount,
-                                          NULL,
-                                          0, 0, 0);
-        if (!ppal) return NULL;
-
-        /* Copy all colors */
-        for (i = 0; i < ColorCount; i++)
-        {
-            ppal->IndexedColors[i].peRed = pColors[i].rgbRed;
-            ppal->IndexedColors[i].peGreen = pColors[i].rgbGreen;
-            ppal->IndexedColors[i].peBlue = pColors[i].rgbBlue;
-            ppal->IndexedColors[i].peFlags = 0;
-        }
-
-        /* Get palette handle and unlock the palette */
-        hpal = ppal->BaseObject.hHmgr;
-        PALETTE_UnlockPalette(ppal);
-    }
-    else
-    {
-        ppal = PALETTE_AllocPalWithHandle(paletteType, 0,
-                                          NULL,
-                                          RedMask, GreenMask, BlueMask);
-
-        hpal = ppal->BaseObject.hHmgr;
-        PALETTE_UnlockPalette(ppal);
-    }
-
-    return hpal;
-}
-
 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
  * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
 BITMAPINFO*
@@ -1947,10 +1999,51 @@ DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
 VOID
 FASTCALL
-DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
 {
-    if(converted != orig)
+    BITMAPCOREINFO* pbmci;
+    if(converted == orig)
+        return;
+
+    if(usage == -1)
+    {
+        /* Caller don't want any conversion */
         ExFreePoolWithTag(converted, TAG_DIB);
+        return;
+    }
+
+    /* Perform inverse conversion */
+    pbmci = (BITMAPCOREINFO*)orig;
+
+    ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
+    pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
+    pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
+    pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
+    pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
+
+    if(pbmci->bmciHeader.bcBitCount <= 8)
+    {
+        UINT numColors = converted->bmiHeader.biClrUsed;
+        if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
+        if(usage == DIB_PAL_COLORS)
+        {
+            RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
+            RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
+        }
+        else
+        {
+            UINT i;
+            RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
+            for(i=0; i<numColors; i++)
+            {
+                pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
+                pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
+                pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
+            }
+        }
+    }
+    /* Now free it, it's not needed anymore */
+    ExFreePoolWithTag(converted, TAG_DIB);
 }
 
 /* EOF */