[WIN32K]
authorJérôme Gardou <jerome.gardou@reactos.org>
Tue, 8 Jun 2010 00:40:42 +0000 (00:40 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Tue, 8 Jun 2010 00:40:42 +0000 (00:40 +0000)
  - remove duplicate prototypes.
  - Add missing trail to debug print
  - replace some now superfluous checks on bitmap palette with sanity ASSERTS
  - begin using BITMAPV5HEADER as a default bitmap format, and introduce conversion to and from everything prior that.
Congratulations to BITMAPCOREHEADER, for its backward compatibility personal failure.

svn path=/branches/reactos-yarotows/; revision=47690

subsystems/win32/win32k/include/bitmaps.h
subsystems/win32/win32k/misc/file.c
subsystems/win32/win32k/objects/bitblt.c
subsystems/win32/win32k/objects/dibobj.c

index 11b0585..cc3b47b 100644 (file)
@@ -2,14 +2,19 @@
 
 #include "surface.h"
 
-INT     FASTCALL DIB_GetDIBWidthBytes (INT  width, INT  depth);
-int     APIENTRY  DIB_GetDIBImageBytes (INT  width, INT  height, INT  depth);
-INT     FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse);
+typedef struct tagBITMAPV5INFO
+{
+    BITMAPV5HEADER bmiHeader;
+    RGBQUAD        bmiColors[256];
+} BITMAPV5INFO, *PBITMAPV5INFO;
+
 INT     APIENTRY  BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer);
 HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits);
 HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP  hBitmap);
 UINT    FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
 INT     FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp);
+NTSTATUS FASTCALL ProbeAndConvertToBitmapV5Info( OUT PBITMAPV5INFO pbmiDst, IN CONST BITMAPINFO* pbmiUnsafe, IN DWORD dwUse);
+VOID FASTCALL GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc, OUT PBITMAPINFO pbmiDst, IN DWORD dwUse);
 
 HBITMAP
 APIENTRY
index d6de6c8..f8b9325 100644 (file)
@@ -149,144 +149,8 @@ W32kMapViewOfSection(
     return pvBase;
 }
 
-typedef struct tagBITMAPV5INFO
-{
-    BITMAPV5HEADER bmiHeader;
-    RGBQUAD        bmiColors[256];
-} BITMAPV5INFO, *PBITMAPV5INFO;
-
 // FIXME: this should go to dibobj.c
-NTSTATUS
-ProbeAndConvertBitmapInfo(
-    OUT BITMAPV5HEADER *pbmhDst,
-    OUT RGBQUAD *pbmiColorsDst,
-    ULONG cColors,
-    IN  PBITMAPINFO pbmiUnsafe)
-{
-    DWORD dwSize;
-    RGBQUAD *pbmiColors;
-    ULONG ulWidthBytes;
-
-    /* Get the size and probe */
-    ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
-    dwSize = pbmiUnsafe->bmiHeader.biSize;
-    ProbeForRead(pbmiUnsafe, dwSize, 1);
-
-    /* Check the size */
-    // FIXME: are intermediate sizes allowed? As what are they interpreted?
-    //        make sure we don't use a too big dwSize later
-    if (dwSize != sizeof(BITMAPCOREHEADER) &&
-        dwSize != sizeof(BITMAPINFOHEADER) &&
-        dwSize != sizeof(BITMAPV4HEADER) &&
-        dwSize != sizeof(BITMAPV5HEADER))
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
 
-    pbmiColors = (RGBQUAD*)((PCHAR)pbmiUnsafe + dwSize);
-
-    pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
-
-    if (dwSize == sizeof(BITMAPCOREHEADER))
-    {
-        PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
-
-        /* Manually copy the fields that are present */
-        pbmhDst->bV5Width = pbch->bcWidth;
-        pbmhDst->bV5Height = pbch->bcHeight;
-        pbmhDst->bV5Planes = pbch->bcPlanes;
-        pbmhDst->bV5BitCount = pbch->bcBitCount;
-
-        /* Set some default values */
-        pbmhDst->bV5Compression = BI_RGB;
-        pbmhDst->bV5SizeImage = 0;
-        pbmhDst->bV5XPelsPerMeter = 72;
-        pbmhDst->bV5YPelsPerMeter = 72;
-        pbmhDst->bV5ClrUsed = 0;
-        pbmhDst->bV5ClrImportant = 0;
-    }
-    else
-    {
-        /* Copy valid fields */
-        memcpy(pbmhDst, pbmiUnsafe, dwSize);
-
-        /* Zero out the rest of the V5 header */
-        memset((char*)pbmhDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
-    }
-
-
-    if (dwSize < sizeof(BITMAPV4HEADER))
-    {
-        if (pbmhDst->bV5Compression == BI_BITFIELDS)
-        {
-            DWORD *pMasks = (DWORD*)pbmiColors;
-            pbmhDst->bV5RedMask = pMasks[0];
-            pbmhDst->bV5GreenMask = pMasks[1];
-            pbmhDst->bV5BlueMask = pMasks[2];
-            pbmhDst->bV5AlphaMask = 0;
-            pbmhDst->bV5ClrUsed = 0;
-        }
-
-//        pbmhDst->bV5CSType;
-//        pbmhDst->bV5Endpoints;
-//        pbmhDst->bV5GammaRed;
-//        pbmhDst->bV5GammaGreen;
-//        pbmhDst->bV5GammaBlue;
-    }
-
-    if (dwSize < sizeof(BITMAPV5HEADER))
-    {
-//        pbmhDst->bV5Intent;
-//        pbmhDst->bV5ProfileData;
-//        pbmhDst->bV5ProfileSize;
-//        pbmhDst->bV5Reserved;
-    }
-
-    ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
-                     pbmhDst->bV5BitCount + 31) & ~31) / 8;
-
-    if (pbmhDst->bV5SizeImage == 0)
-        pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
-
-    if (pbmhDst->bV5ClrUsed == 0)
-        pbmhDst->bV5ClrUsed = pbmhDst->bV5BitCount == 1 ? 2 :
-                              (pbmhDst->bV5BitCount == 4 ? 16 :
-                              (pbmhDst->bV5BitCount == 8 ? 256 : 0));
-
-    if (pbmhDst->bV5Planes != 1)
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
-        pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
-        pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
-        pbmhDst->bV5BitCount != 32)
-    {
-        DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if ((pbmhDst->bV5BitCount == 0 &&
-         pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
-    {
-        DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    if (pbmhDst->bV5Compression == BI_BITFIELDS &&
-        pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
-    {
-        DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Copy Colors */
-    cColors = min(cColors, pbmhDst->bV5ClrUsed);
-    memcpy(pbmiColorsDst, pbmiColors, cColors * sizeof(RGBQUAD));
-
-    return STATUS_SUCCESS;
-}
 
 
 HBITMAP
@@ -333,10 +197,9 @@ UserLoadImage(PCWSTR pwszName)
     /* Create a normalized local BITMAPINFO */
     _SEH2_TRY
     {
-        Status = ProbeAndConvertBitmapInfo(&bmiLocal.bmiHeader,
-                                           bmiLocal.bmiColors,
-                                           256,
-                                           pbmi);
+        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal,
+                                               pbmi,
+                                               DIB_RGB_COLORS);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
index d1fb797..5b59a59 100644 (file)
@@ -757,7 +757,7 @@ GreStretchBltMask(
     }
     else if(DCSrc)
     {
-        DPRINT1("Getting a valid Source handle without using source!!!");
+        DPRINT1("Getting a valid Source handle without using source!!!\n");
         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
         DCSrc = NULL ;
     }
index f5816da..66a7766 100644 (file)
@@ -221,16 +221,16 @@ IntSetDIBits(
     CONST BITMAPINFO  *bmi,
     UINT  ColorUse)
 {
-    SURFACE  *bitmap;
+    SURFACE     *bitmap;
     HBITMAP     SourceBitmap;
     INT         result = 0;
     BOOL        copyBitsResult;
-    SURFOBJ    *DestSurf, *SourceSurf;
+    SURFOBJ     *DestSurf, *SourceSurf;
     SIZEL       SourceSize;
     POINTL      ZeroPoint;
     RECTL       DestRect;
     EXLATEOBJ   exlo;
-    PPALETTE    ppalDDB, ppalDIB;
+    PPALETTE    ppalDIB;
     //RGBQUAD    *lpRGB;
     HPALETTE    DIB_Palette;
     ULONG       DIB_Palette_Type;
@@ -278,32 +278,15 @@ IntSetDIBits(
         return 0;
     }
 
-    if (bitmap->ppal)
-    {
-        ppalDDB = bitmap->ppal;
-        GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject);
-    }
-    else
-        // Destination palette obtained from the hDC
-        ppalDDB = PALETTE_ShareLockPalette(DC->ppdev->devinfo.hpalDefault);
-
-    if (NULL == ppalDDB)
-    {
-        EngUnlockSurface(SourceSurf);
-        EngDeleteSurface((HSURF)SourceBitmap);
-        SURFACE_UnlockSurface(bitmap);
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
-        return 0;
-    }
+    ASSERT(bitmap->ppal);
 
     // Source palette obtained from the BITMAPINFO
-    DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type);
+    DIB_Palette = BuildDIBPalette(bmi, (PINT)&DIB_Palette_Type);
     if (NULL == DIB_Palette)
     {
         EngUnlockSurface(SourceSurf);
         EngDeleteSurface((HSURF)SourceBitmap);
         SURFACE_UnlockSurface(bitmap);
-        PALETTE_ShareUnlockPalette(ppalDDB);
         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
         return 0;
     }
@@ -311,7 +294,7 @@ IntSetDIBits(
     ppalDIB = PALETTE_LockPalette(DIB_Palette);
 
     /* Initialize XLATEOBJ for color translation */
-    EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+    EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0);
 
     // Zero point
     ZeroPoint.x = 0;
@@ -336,7 +319,6 @@ IntSetDIBits(
     // Clean up
     EXLATEOBJ_vCleanup(&exlo);
     PALETTE_UnlockPalette(ppalDIB);
-    PALETTE_ShareUnlockPalette(ppalDDB);
     PALETTE_FreePaletteByHandle(DIB_Palette);
     EngUnlockSurface(SourceSurf);
     EngDeleteSurface((HSURF)SourceBitmap);
@@ -366,17 +348,13 @@ NtGdiSetDIBits(
     PDC Dc;
     INT Ret;
     NTSTATUS Status = STATUS_SUCCESS;
-    UINT cjBits;
+    BITMAPV5INFO bmiLocal;
 
     if (!Bits) return 0;
 
     _SEH2_TRY
-    {  // FYI: We converted from CORE in gdi.
-        ProbeForRead(bmi, sizeof(BITMAPINFO), 1);
-        cjBits = bmi->bmiHeader.biBitCount * bmi->bmiHeader.biPlanes * bmi->bmiHeader.biWidth;
-        cjBits = ((cjBits + 31) & ~31) / 8;
-        cjBits *= ScanLines;
-        ProbeForRead(Bits, cjBits, 1);
+    {
+        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -401,7 +379,7 @@ NtGdiSetDIBits(
         return 0;
     }
 
-    Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
+    Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, (PBITMAPINFO)&bmiLocal, ColorUse);
 
     DC_UnlockDc(Dc);
 
@@ -440,16 +418,16 @@ NtGdiSetDIBitsToDeviceInternal(
     INT DIBWidth;
     SIZEL SourceSize;
     EXLATEOBJ exlo;
-    PPALETTE ppalDDB = NULL, ppalDIB = NULL;
+    PPALETTE ppalDIB = NULL;
     HPALETTE hpalDIB = NULL;
     ULONG DIBPaletteType;
+    BITMAPV5INFO bmiLocal ;
 
     if (!Bits) return 0;
 
     _SEH2_TRY
     {
-        ProbeForRead(bmi, cjMaxInfo , 1);
-        ProbeForRead(Bits, cjMaxBits, 1);
+        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -478,7 +456,7 @@ NtGdiSetDIBitsToDeviceInternal(
 
     pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
 
-    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
+    ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
 
     rcDest.left = XDest;
     rcDest.top = YDest;
@@ -495,15 +473,16 @@ NtGdiSetDIBitsToDeviceInternal(
     ptSource.x = XSrc;
     ptSource.y = YSrc;
 
-    SourceSize.cx = bmi->bmiHeader.biWidth;
+    SourceSize.cx = bmiLocal.bmiHeader.bV5Width;
     SourceSize.cy = ScanLines;
 
-    DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
+    DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount);
 
     hSourceBitmap = EngCreateBitmap(SourceSize,
                                     DIBWidth,
-                                    BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
-                                    bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
+                                    BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
+                                                 bmiLocal.bmiHeader.bV5Compression),
+                                    bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
                                     (PVOID) Bits);
     if (!hSourceBitmap)
     {
@@ -519,24 +498,10 @@ NtGdiSetDIBitsToDeviceInternal(
         goto Exit;
     }
 
-    /* Obtain destination palette */
-    if (pSurf && pSurf->ppal)
-    {
-        ppalDDB = pSurf->ppal;
-        GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject);
-    }
-    else
-        ppalDDB = PALETTE_ShareLockPalette(pDC->ppdev->devinfo.hpalDefault);
-
-    if (!ppalDDB)
-    {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
-        Status = STATUS_UNSUCCESSFUL;
-        goto Exit;
-    }
+    ASSERT(pSurf->ppal);
 
     /* Create a palette for the DIB */
-    hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
+    hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType);
     if (!hpalDIB)
     {
         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
@@ -554,7 +519,7 @@ NtGdiSetDIBitsToDeviceInternal(
     }
 
     /* Initialize EXLATEOBJ */
-    EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+    EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0);
 
     /* Copy the bits */
     DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
@@ -582,7 +547,6 @@ Exit:
     }
 
     if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
-    if (ppalDDB) PALETTE_ShareUnlockPalette(ppalDDB);
 
     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
@@ -611,14 +575,12 @@ NtGdiGetDIBitsInternal(
     SURFACE *psurf = NULL;
     HBITMAP hDestBitmap = NULL;
     HPALETTE hDestPalette = NULL;
-    PPALETTE ppalSrc = NULL;
+    BITMAPV5INFO bmiLocal ;
     PPALETTE ppalDst = NULL;
     NTSTATUS Status = STATUS_SUCCESS;
     ULONG Result = 0;
     BOOL bPaletteMatch = FALSE;
     PBYTE ChkBits = Bits;
-    PVOID ColorPtr;
-    RGBQUAD *rgbQuads;
     ULONG DestPaletteType;
     ULONG Index;
 
@@ -633,9 +595,7 @@ NtGdiGetDIBitsInternal(
 
     _SEH2_TRY
     {
-        ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1);
-
-        ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core.
+        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage);
         if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -665,74 +625,59 @@ NtGdiGetDIBitsInternal(
         return 0;
     }
 
-    if (psurf->ppal)
-    {
-        ppalSrc = psurf->ppal;
-        GDIOBJ_IncrementShareCount(&ppalSrc->BaseObject);
-    }
-    else
-        ppalSrc = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+    ASSERT(psurf->ppal);
 
     DC_UnlockDc(Dc);
 
-    ASSERT(ppalSrc != NULL);
-
-    ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize);
-    rgbQuads = (RGBQUAD *)ColorPtr;
-
     /* Copy palette information
      * Always create a palette for 15 & 16 bit. */
     if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
          Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) ||
          !ChkBits)
     {
-        ppalDst = ppalSrc;
+        ppalDst = psurf->ppal;
         bPaletteMatch = TRUE;
     }
     else
-        hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
-
-    if (!bPaletteMatch)
     {
+        hDestPalette = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DestPaletteType);
         ppalDst = PALETTE_LockPalette(hDestPalette);
-        /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */
-        DPRINT("ppalDst : %p\n", ppalDst);
-        ASSERT(ppalDst);
     }
 
+    DPRINT("ppalDst : %p\n", ppalDst);
+    ASSERT(ppalDst);
+
     /* Copy palette. */
-    /* FIXME: This is largely incomplete. ATM no Core!*/
-    switch (Info->bmiHeader.biBitCount)
+    switch (bmiLocal.bmiHeader.bV5BitCount)
     {
         case 1:
         case 4:
         case 8:
-            Info->bmiHeader.biClrUsed = 0;
+            bmiLocal.bmiHeader.bV5ClrUsed = 0;
             if (psurf->hSecure &&
-                BitsPerFormat(psurf->SurfObj.iBitmapFormat) == Info->bmiHeader.biBitCount)
+                BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bmiLocal.bmiHeader.bV5BitCount)
             {
                 if (Usage == DIB_RGB_COLORS)
                 {
-                    if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount)
-                        Info->bmiHeader.biClrUsed = ppalDst->NumColors;
+                    if (ppalDst->NumColors != 1 << bmiLocal.bmiHeader.bV5BitCount)
+                        bmiLocal.bmiHeader.bV5ClrUsed = ppalDst->NumColors;
                     for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
+                         Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
                          Index++)
                     {
-                        rgbQuads[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
-                        rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
-                        rgbQuads[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
-                        rgbQuads[Index].rgbReserved = 0;
+                        bmiLocal.bmiColors[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
+                        bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
+                        bmiLocal.bmiColors[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
+                        bmiLocal.bmiColors[Index].rgbReserved = 0;
                     }
                 }
                 else
                 {
-                    PWORD Ptr = ColorPtr;
                     for (Index = 0;
                          Index < (1 << Info->bmiHeader.biBitCount);
                          Index++)
                     {
-                        Ptr[Index] = (WORD)Index;
+                        ((WORD*)bmiLocal.bmiColors)[Index] = Index;
                     }
                 }
             }
@@ -740,12 +685,11 @@ NtGdiGetDIBitsInternal(
             {
                 if (Usage == DIB_PAL_COLORS)
                 {
-                    PWORD Ptr = ColorPtr;
                     for (Index = 0;
                          Index < (1 << Info->bmiHeader.biBitCount);
                          Index++)
                     {
-                        Ptr[Index] = (WORD)Index;
+                        ((WORD*)bmiLocal.bmiColors)[Index] = (WORD)Index;
                     }
                 }
                 else if (Info->bmiHeader.biBitCount > 1  && bPaletteMatch)
@@ -754,33 +698,37 @@ NtGdiGetDIBitsInternal(
                          Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
                          Index++)
                     {
-                        Info->bmiColors[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
-                        Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
-                        Info->bmiColors[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
-                        Info->bmiColors[Index].rgbReserved = 0;
+                        bmiLocal.bmiColors[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
+                        bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
+                        bmiLocal.bmiColors[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
+                        bmiLocal.bmiColors[Index].rgbReserved = 0;
                     }
                 }
                 else
                 {
-                    switch (Info->bmiHeader.biBitCount)
+                    switch (bmiLocal.bmiHeader.bV5BitCount)
                     {
                         case 1:
-                            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].rgbReserved = 0;
+                            bmiLocal.bmiColors[0].rgbRed =0 ;
+                            bmiLocal.bmiColors[0].rgbGreen = 0;
+                            bmiLocal.bmiColors[0].rgbBlue = 0;
+                            bmiLocal.bmiColors[0].rgbReserved = 0;
+                            bmiLocal.bmiColors[1].rgbRed =0xFF ;
+                            bmiLocal.bmiColors[1].rgbGreen = 0xFF;
+                            bmiLocal.bmiColors[1].rgbBlue = 0xFF;
+                            bmiLocal.bmiColors[1].rgbReserved = 0;
                             break;
                         case 4:
-                            RtlCopyMemory(ColorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
+                            RtlCopyMemory(bmiLocal.bmiColors, EGAColorsQuads, sizeof(EGAColorsQuads));
                             break;
                         case 8:
                         {
                             INT r, g, b;
                             RGBQUAD *color;
 
-                            RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
-                            RtlCopyMemory(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
-                            color = rgbQuads + 10;
+                            RtlCopyMemory(bmiLocal.bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
+                            RtlCopyMemory(bmiLocal.bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
+                            color = bmiLocal.bmiColors + 10;
                             for (r = 0; r <= 5; r++) /* FIXME */
                                 for (g = 0; g <= 5; g++)
                                     for (b = 0; b <= 5; b++)
@@ -798,20 +746,20 @@ NtGdiGetDIBitsInternal(
             }
 
         case 15:
-            if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+            if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
             {
-                ((PDWORD)Info->bmiColors)[0] = 0x7c00;
-                ((PDWORD)Info->bmiColors)[1] = 0x03e0;
-                ((PDWORD)Info->bmiColors)[2] = 0x001f;
+                bmiLocal.bmiHeader.bV5RedMask = 0x7c00;
+                bmiLocal.bmiHeader.bV5GreenMask = 0x03e0;
+                bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
             }
             break;
 
         case 16:
             if (Info->bmiHeader.biCompression == BI_BITFIELDS)
             {
-                ((PDWORD)Info->bmiColors)[0] = 0xf800;
-                ((PDWORD)Info->bmiColors)[1] = 0x07e0;
-                ((PDWORD)Info->bmiColors)[2] = 0x001f;
+                bmiLocal.bmiHeader.bV5RedMask = 0xf800;
+                bmiLocal.bmiHeader.bV5GreenMask = 0x07e0;
+                bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
             }
             break;
 
@@ -819,71 +767,54 @@ NtGdiGetDIBitsInternal(
         case 32:
             if (Info->bmiHeader.biCompression == BI_BITFIELDS)
             {
-                ((PDWORD)Info->bmiColors)[0] = 0xff0000;
-                ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
-                ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
+                bmiLocal.bmiHeader.bV5RedMask = 0xff0000;
+                bmiLocal.bmiHeader.bV5GreenMask = 0x00ff00;
+                bmiLocal.bmiHeader.bV5BlueMask = 0x0000ff;
             }
             break;
     }
 
-    if (!bPaletteMatch)
-        PALETTE_UnlockPalette(ppalDst);
-
     /* fill out the BITMAPINFO struct */
     if (!ChkBits)
-    {  // Core or not to Core? We have converted from Core in Gdi~ so?
-        if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-        {
-            BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
-            coreheader->bcWidth = psurf->SurfObj.sizlBitmap.cx;
-            coreheader->bcPlanes = 1;
-            coreheader->bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-            coreheader->bcHeight = psurf->SurfObj.sizlBitmap.cy;
-            if (psurf->SurfObj.lDelta > 0)
-                coreheader->bcHeight = -coreheader->bcHeight;
-        }
-
-        if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
+    {
+        bmiLocal.bmiHeader.bV5Width = psurf->SurfObj.sizlBitmap.cx;
+        bmiLocal.bmiHeader.bV5Height = psurf->SurfObj.sizlBitmap.cy;
+        bmiLocal.bmiHeader.bV5Planes = 1;
+        bmiLocal.bmiHeader.bV5BitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+        switch (psurf->SurfObj.iBitmapFormat)
         {
-            Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
-            Info->bmiHeader.biHeight = psurf->SurfObj.sizlBitmap.cy;
-            Info->bmiHeader.biPlanes = 1;
-            Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-            switch (psurf->SurfObj.iBitmapFormat)
-            {
-                    /* FIXME: What about BI_BITFIELDS? */
-                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;
-            }
-            /* Image size has to be calculated */
-            Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
-                                          Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
-            Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
-            Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
-            Info->bmiHeader.biClrUsed = 0;
-            Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
-            /* Report negtive height for top-down bitmaps. */
-            if (psurf->SurfObj.lDelta > 0)
-                Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
+                /* FIXME: What about BI_BITFIELDS? */
+            case BMF_1BPP:
+            case BMF_4BPP:
+            case BMF_8BPP:
+            case BMF_16BPP:
+            case BMF_24BPP:
+            case BMF_32BPP:
+                bmiLocal.bmiHeader.bV5Compression = BI_RGB;
+                break;
+            case BMF_4RLE:
+                bmiLocal.bmiHeader.bV5Compression = BI_RLE4;
+                break;
+            case BMF_8RLE:
+                bmiLocal.bmiHeader.bV5Compression = BI_RLE8;
+                break;
+            case BMF_JPEG:
+                bmiLocal.bmiHeader.bV5Compression = BI_JPEG;
+                break;
+            case BMF_PNG:
+                bmiLocal.bmiHeader.bV5Compression = BI_PNG;
+                break;
         }
+        /* Image size has to be calculated */
+        bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
+                                      Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
+        bmiLocal.bmiHeader.bV5XPelsPerMeter = 0; /* FIXME */
+        bmiLocal.bmiHeader.bV5YPelsPerMeter = 0; /* FIXME */
+        bmiLocal.bmiHeader.bV5ClrUsed = 0;
+        bmiLocal.bmiHeader.bV5ClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
+        /* Report negative height for top-down bitmaps. */
+        if (psurf->SurfObj.lDelta > 0)
+            bmiLocal.bmiHeader.bV5Height *= -1;
         Result = psurf->SurfObj.sizlBitmap.cy;
     }
     else
@@ -907,27 +838,14 @@ NtGdiGetDIBitsInternal(
 
             hDestBitmap = NULL;
 
-            if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-            {
-                BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
-                hDestBitmap = EngCreateBitmap(DestSize,
-                                              DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
-                                              BitmapFormat(coreheader->bcBitCount, BI_RGB),
-                                              0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
-                                              Bits);
-            }
-
-            if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
-            {
-                Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
+            bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
                                               Info->bmiHeader.biBitCount) * DestSize.cy;
 
-                hDestBitmap = EngCreateBitmap(DestSize,
-                                              DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
-                                              BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
-                                              0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
-                                              Bits);
-            }
+            hDestBitmap = EngCreateBitmap(DestSize,
+                                          DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
+                                          BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
+                                          0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
+                                          Bits);
 
             if (hDestBitmap == NULL)
                 goto cleanup;
@@ -939,7 +857,7 @@ NtGdiGetDIBitsInternal(
             SURFOBJ *DestSurfObj;
             RECTL DestRect;
 
-            EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0);
+            EXLATEOBJ_vInitialize(&exlo, psurf->ppal, ppalDst, 0, 0, 0);
 
             SourcePoint.x = 0;
             SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
@@ -967,14 +885,19 @@ NtGdiGetDIBitsInternal(
             EngUnlockSurface(DestSurfObj);
         }
     }
+    /* Now that everything is over, get back the information to caller */
+    /* Note : Info has already been probed */
+    GetBMIFromBitmapV5Info(&bmiLocal, Info, Usage);
 cleanup:
-    PALETTE_ShareUnlockPalette(ppalSrc);
 
     if (hDestBitmap != NULL)
         EngDeleteSurface((HSURF)hDestBitmap);
 
-    if (hDestPalette != NULL && bPaletteMatch == FALSE)
+    if (hDestPalette != NULL && !bPaletteMatch)
+    {
+        PALETTE_UnlockPalette(ppalDst);
         PALETTE_FreePaletteByHandle(hDestPalette);
+    }
 
     SURFACE_UnlockSurface(psurf);
 
@@ -1653,7 +1576,7 @@ INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
     {
         colors = info->bmiHeader.biClrUsed;
         if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
-        return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+        return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
     }
 }
 
@@ -1722,9 +1645,9 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
 {
     BYTE bits;
     ULONG ColorCount;
-    PALETTEENTRY *palEntries = NULL;
     HPALETTE hPal;
     ULONG RedMask, GreenMask, BlueMask;
+    PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
 
     // Determine Bits Per Pixel
     bits = bmi->bmiHeader.biBitCount;
@@ -1738,9 +1661,9 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
     else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
     {
         *paletteType = PAL_BITFIELDS;
-        RedMask = ((ULONG *)bmi->bmiColors)[0];
-        GreenMask = ((ULONG *)bmi->bmiColors)[1];
-        BlueMask = ((ULONG *)bmi->bmiColors)[2];
+        RedMask = pdwColors[0];
+        GreenMask = pdwColors[1];
+        BlueMask = pdwColors[2];
     }
     else if (bits == 15)
     {
@@ -1775,16 +1698,256 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
 
     if (PAL_INDEXED == *paletteType)
     {
-        hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
+        hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
     }
     else
     {
         hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
-                                    (ULONG*) palEntries,
+                                    NULL,
                                     RedMask, GreenMask, BlueMask);
     }
 
     return hPal;
 }
 
+FORCEINLINE
+DWORD
+GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
+{
+    DWORD dwRet = 0;
+    INT size;
+    if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        /* BITMAPCOREINFO holds RGBTRIPLE values */
+        size = sizeof(RGBTRIPLE);
+    }
+    else
+    {
+        size = sizeof(RGBQUAD);
+    }
+    memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
+    return dwRet;
+}
+
+FORCEINLINE
+VOID
+SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i)
+{
+    if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        *(RGBTRIPLE*)((PBYTE)pbmi + pbmi->bmiHeader.biSize + i*sizeof(RGBTRIPLE)) = *(RGBTRIPLE*)color;
+    }
+    else
+    {
+        *(RGBQUAD*)((PBYTE)pbmi + pbmi->bmiHeader.biSize + i*sizeof(RGBQUAD)) = *(RGBQUAD*)color;
+    }
+}
+
+NTSTATUS
+FASTCALL
+ProbeAndConvertToBitmapV5Info(
+    OUT PBITMAPV5INFO pbmiDst,
+    IN CONST BITMAPINFO* pbmiUnsafe,
+    IN DWORD dwColorUse)
+{
+    DWORD dwSize;
+    ULONG ulWidthBytes;
+    PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
+
+    /* Get the size and probe */
+    ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
+    dwSize = pbmiUnsafe->bmiHeader.biSize;
+    ProbeForRead(pbmiUnsafe, dwSize, 1);
+
+    /* Check the size */
+    // FIXME: are intermediate sizes allowed? As what are they interpreted?
+    //        make sure we don't use a too big dwSize later
+    if (dwSize != sizeof(BITMAPCOREHEADER) &&
+        dwSize != sizeof(BITMAPINFOHEADER) &&
+        dwSize != sizeof(BITMAPV4HEADER) &&
+        dwSize != sizeof(BITMAPV5HEADER))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (dwSize == sizeof(BITMAPCOREHEADER))
+    {
+        PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
+
+        /* Manually copy the fields that are present */
+        pbmhDst->bV5Width = pbch->bcWidth;
+        pbmhDst->bV5Height = pbch->bcHeight;
+        pbmhDst->bV5Planes = pbch->bcPlanes;
+        pbmhDst->bV5BitCount = pbch->bcBitCount;
+
+        /* Set some default values */
+        pbmhDst->bV5Compression = BI_RGB;
+        pbmhDst->bV5SizeImage = 0;
+        pbmhDst->bV5XPelsPerMeter = 72;
+        pbmhDst->bV5YPelsPerMeter = 72;
+        pbmhDst->bV5ClrUsed = 0;
+        pbmhDst->bV5ClrImportant = 0;
+    }
+    else
+    {
+        /* Copy valid fields */
+        memcpy(pbmiDst, pbmiUnsafe, dwSize);
+
+        if(dwSize < sizeof(BITMAPV5HEADER))
+        {
+            /* Zero out the rest of the V5 header */
+            memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
+        }
+    }
+    pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
+
+
+    if (dwSize < sizeof(BITMAPV4HEADER))
+    {
+        if (pbmhDst->bV5Compression == BI_BITFIELDS)
+        {
+            pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
+            pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
+            pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
+            pbmhDst->bV5AlphaMask = 0;
+            pbmhDst->bV5ClrUsed = 0;
+        }
+
+//        pbmhDst->bV5CSType;
+//        pbmhDst->bV5Endpoints;
+//        pbmhDst->bV5GammaRed;
+//        pbmhDst->bV5GammaGreen;
+//        pbmhDst->bV5GammaBlue;
+    }
+
+    if (dwSize < sizeof(BITMAPV5HEADER))
+    {
+//        pbmhDst->bV5Intent;
+//        pbmhDst->bV5ProfileData;
+//        pbmhDst->bV5ProfileSize;
+//        pbmhDst->bV5Reserved;
+    }
+
+    ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
+                     pbmhDst->bV5BitCount + 31) & ~31) / 8;
+
+    if (pbmhDst->bV5SizeImage == 0)
+        pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
+
+    if (pbmhDst->bV5ClrUsed == 0)
+    {
+        switch(pbmhDst->bV5BitCount)
+        {
+            case 1:
+                pbmhDst->bV5ClrUsed = 2;
+                break;
+            case 4:
+                pbmhDst->bV5ClrUsed = 16;
+                break;
+            case 8:
+                pbmhDst->bV5ClrUsed = 256;
+                break;
+            default:
+                pbmhDst->bV5ClrUsed = 0;
+                break;
+        }
+    }
+
+    if (pbmhDst->bV5Planes != 1)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
+        pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
+        pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
+        pbmhDst->bV5BitCount != 32)
+    {
+        DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if ((pbmhDst->bV5BitCount == 0 &&
+         pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
+    {
+        DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if (pbmhDst->bV5Compression == BI_BITFIELDS &&
+        pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
+    {
+        DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Copy Colors */
+    if(pbmhDst->bV5ClrUsed)
+    {
+        INT i;
+        if(dwColorUse == DIB_PAL_COLORS)
+        {
+            RtlCopyMemory(pbmiDst->bmiColors,
+                          pbmiUnsafe->bmiColors,
+                          pbmhDst->bV5ClrUsed * sizeof(WORD));
+        }
+        else
+        {
+            for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
+            {
+                ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
+            }
+        }
+    }
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+FASTCALL
+GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc,
+                       OUT PBITMAPINFO pbmiDst,
+                       IN DWORD dwColorUse)
+{
+    if(pbmiDst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        /* Manually set value */
+        BITMAPCOREHEADER* pbmhCore = (BITMAPCOREHEADER*)&pbmiDst->bmiHeader;
+        pbmhCore->bcWidth = pbmiSrc->bmiHeader.bV5Width;
+        pbmhCore->bcHeight = pbmiSrc->bmiHeader.bV5Height;
+        pbmhCore->bcPlanes = pbmiSrc->bmiHeader.bV5Planes;
+        pbmhCore->bcBitCount = pbmiSrc->bmiHeader.bV5BitCount;
+    }
+    else
+    {
+        /* Copy valid Fields, keep bmiHeader.biSize safe */
+        RtlCopyMemory((PBYTE)pbmiDst + sizeof(DWORD), pbmiSrc, pbmiDst->bmiHeader.biSize - sizeof(DWORD));
+    }
+    if((pbmiDst->bmiHeader.biSize < sizeof(BITMAPV4HEADER)) &&
+        (pbmiSrc->bmiHeader.bV5Compression == BI_BITFIELDS))
+    {
+        /* Masks are already set in V4 and V5 headers */
+        SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5RedMask, 0);
+        SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5GreenMask, 1);
+        SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5BlueMask, 2);
+    }
+    else
+    {
+        INT i;
+        if(dwColorUse == DIB_PAL_COLORS)
+        {
+            RtlCopyMemory(pbmiDst->bmiColors,
+                          pbmiSrc->bmiColors,
+                          pbmiSrc->bmiHeader.bV5ClrUsed * sizeof(WORD));
+        }
+        else
+        {
+            for(i = 0; i < pbmiSrc->bmiHeader.bV5ClrUsed; i++)
+            {
+                SetBMIColor(pbmiDst, (DWORD*)pbmiSrc->bmiColors + i, i);
+            }
+        }
+    }
+}
+
 /* EOF */