[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / dibobj.c
index 66a7766..6ab2f6c 100644 (file)
@@ -42,6 +42,26 @@ static const RGBQUAD EGAColorsQuads[16] = {
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
+static const RGBTRIPLE EGAColorsTriples[16] = {
+/* rgbBlue, rgbGreen, rgbRed */
+    { 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x80 },
+    { 0x00, 0x80, 0x00 },
+    { 0x00, 0x80, 0x80 },
+    { 0x80, 0x00, 0x00 },
+    { 0x80, 0x00, 0x80 },
+    { 0x80, 0x80, 0x00 },
+    { 0x80, 0x80, 0x80 },
+    { 0xc0, 0xc0, 0xc0 },
+    { 0x00, 0x00, 0xff },
+    { 0x00, 0xff, 0x00 },
+    { 0x00, 0xff, 0xff },
+    { 0xff, 0x00, 0x00 },
+    { 0xff, 0x00, 0xff },
+    { 0xff, 0xff, 0x00 },
+    { 0xff, 0xff, 0xff }
+};
+
 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
     { 0x00, 0x00, 0x00, 0x00 },
@@ -66,6 +86,30 @@ static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palet
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
+static const RGBQUAD DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
+/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
+    { 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x80 },
+    { 0x00, 0x80, 0x00 },
+    { 0x00, 0x80, 0x80 },
+    { 0x80, 0x00, 0x00 },
+    { 0x80, 0x00, 0x80 },
+    { 0x80, 0x80, 0x00 },
+    { 0xc0, 0xc0, 0xc0 },
+    { 0xc0, 0xdc, 0xc0 },
+    { 0xf0, 0xca, 0xa6 },
+    { 0xf0, 0xfb, 0xff },
+    { 0xa4, 0xa0, 0xa0 },
+    { 0x80, 0x80, 0x80 },
+    { 0x00, 0x00, 0xf0 },
+    { 0x00, 0xff, 0x00 },
+    { 0x00, 0xff, 0xff },
+    { 0xff, 0x00, 0x00 },
+    { 0xff, 0x00, 0xff },
+    { 0xff, 0xff, 0x00 },
+    { 0xff, 0xff, 0xff }
+};
+
 
 UINT
 APIENTRY
@@ -92,14 +136,14 @@ IntSetDIBColorTable(
     if (psurf == NULL)
     {
         DC_UnlockDc(dc);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
     if (psurf->hSecure == NULL)
     {
         DC_UnlockDc(dc);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
@@ -112,7 +156,7 @@ IntSetDIBColorTable(
         if (psurf->ppal == NULL)
         {
             DC_UnlockDc(dc);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return 0;
         }
 
@@ -164,14 +208,14 @@ IntGetDIBColorTable(
     if (psurf == NULL)
     {
         DC_UnlockDc(dc);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
     if (psurf->hSecure == NULL)
     {
         DC_UnlockDc(dc);
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
@@ -185,7 +229,7 @@ IntGetDIBColorTable(
         if (psurf->ppal == NULL)
         {
             DC_UnlockDc(dc);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return 0;
         }
 
@@ -221,112 +265,67 @@ IntSetDIBits(
     CONST BITMAPINFO  *bmi,
     UINT  ColorUse)
 {
-    SURFACE     *bitmap;
     HBITMAP     SourceBitmap;
+       PSURFACE    psurfDst, psurfSrc;
     INT         result = 0;
-    BOOL        copyBitsResult;
-    SURFOBJ     *DestSurf, *SourceSurf;
-    SIZEL       SourceSize;
-    POINTL      ZeroPoint;
-    RECTL       DestRect;
-    EXLATEOBJ   exlo;
-    PPALETTE    ppalDIB;
-    //RGBQUAD    *lpRGB;
-    HPALETTE    DIB_Palette;
-    ULONG       DIB_Palette_Type;
-    INT         DIBWidth;
-
-    // Check parameters
-    if (!(bitmap = SURFACE_LockSurface(hBitmap)))
-    {
-        return 0;
-    }
-
-    // Get RGB values
-    //if (ColorUse == DIB_PAL_COLORS)
-    //  lpRGB = DIB_MapPaletteColors(hDC, bmi);
-    //else
-    //  lpRGB = &bmi->bmiColors;
-
-    DestSurf = &bitmap->SurfObj;
-
-    // Create source surface
-    SourceSize.cx = bmi->bmiHeader.biWidth;
-    SourceSize.cy = ScanLines;
+       RECT            rcDst;
+       POINTL          ptSrc;
+       PVOID           pvBits;
+       EXLATEOBJ       exlo;
 
-    // Determine width of DIB
-    DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
-
-    SourceBitmap = EngCreateBitmap(SourceSize,
-                                   DIBWidth,
-                                   BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
-                                   bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
-                                   (PVOID) Bits);
-    if (0 == SourceBitmap)
-    {
-        SURFACE_UnlockSurface(bitmap);
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        return 0;
-    }
-
-    SourceSurf = EngLockSurface((HSURF)SourceBitmap);
-    if (NULL == SourceSurf)
-    {
-        EngDeleteSurface((HSURF)SourceBitmap);
-        SURFACE_UnlockSurface(bitmap);
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        return 0;
-    }
-
-    ASSERT(bitmap->ppal);
-
-    // Source palette obtained from the BITMAPINFO
-    DIB_Palette = BuildDIBPalette(bmi, (PINT)&DIB_Palette_Type);
-    if (NULL == DIB_Palette)
+    SourceBitmap = DIB_CreateDIBSection(DC, bmi, ColorUse, &pvBits, NULL, 0, 0);
+       if (0 == SourceBitmap)
     {
-        EngUnlockSurface(SourceSurf);
-        EngDeleteSurface((HSURF)SourceBitmap);
-        SURFACE_UnlockSurface(bitmap);
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+               DPRINT1("Error : Could not create a DIBSection.\n");
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         return 0;
     }
 
-    ppalDIB = PALETTE_LockPalette(DIB_Palette);
+       RtlCopyMemory(pvBits, Bits, DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+                                                                                                        bmi->bmiHeader.biHeight,
+                                                                                                        bmi->bmiHeader.biBitCount));
 
-    /* Initialize XLATEOBJ for color translation */
-    EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0);
+       psurfDst = SURFACE_LockSurface(hBitmap);
+       psurfSrc = SURFACE_LockSurface(SourceBitmap);
 
-    // Zero point
-    ZeroPoint.x = 0;
-    ZeroPoint.y = 0;
+       if(!(psurfSrc && psurfDst))
+       {
+               DPRINT1("Error, could not lock surfaces\n");
+               goto cleanup;
+       }
 
-    // Determine destination rectangle
-    DestRect.left      = 0;
-    DestRect.top       = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
-    DestRect.right     = SourceSize.cx;
-    DestRect.bottom    = DestRect.top + ScanLines;
+       rcDst.top = bmi->bmiHeader.biHeight < 0 ?
+               abs(bmi->bmiHeader.biHeight) - (ScanLines + StartScan) : StartScan;
+       rcDst.left = 0;
+       rcDst.bottom = rcDst.top + ScanLines;
+       rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
 
-    copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
+       ptSrc.x = 0;
+       ptSrc.y = 0;
 
-    // If it succeeded, return number of scanlines copies
-    if (copyBitsResult == TRUE)
-    {
-        result = SourceSize.cy;
-// or
-//        result = abs(bmi->bmiHeader.biHeight) - StartScan;
-    }
+       EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0, 0, 0);
 
-    // Clean up
-    EXLATEOBJ_vCleanup(&exlo);
-    PALETTE_UnlockPalette(ppalDIB);
-    PALETTE_FreePaletteByHandle(DIB_Palette);
-    EngUnlockSurface(SourceSurf);
-    EngDeleteSurface((HSURF)SourceBitmap);
+       result = IntEngCopyBits(&psurfDst->SurfObj,
+                                   &psurfSrc->SurfObj,
+                                                       NULL,
+                                                       &exlo.xlo,
+                                                       &rcDst,
+                                                       &ptSrc);
+       if(result)
+               result = ScanLines;
 
-//    if (ColorUse == DIB_PAL_COLORS)
-//        WinFree((LPSTR)lpRGB);
+       EXLATEOBJ_vCleanup(&exlo);
 
-    SURFACE_UnlockSurface(bitmap);
+cleanup:
+       if(psurfSrc)
+       {
+               SURFACE_UnlockSurface(psurfSrc);
+       }
+       if(psurfDst)
+       {
+               SURFACE_UnlockSurface(psurfDst);
+       }
+       GreDeleteObject(SourceBitmap);
 
     return result;
 }
@@ -348,13 +347,19 @@ NtGdiSetDIBits(
     PDC Dc;
     INT Ret;
     NTSTATUS Status = STATUS_SUCCESS;
-    BITMAPV5INFO bmiLocal;
 
     if (!Bits) return 0;
 
     _SEH2_TRY
     {
-        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
+        ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+               ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+               ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, ColorUse), 1);
+        ProbeForRead(Bits,
+                     DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+                                          ScanLines,
+                                          bmi->bmiHeader.biBitCount),
+                                1);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -370,7 +375,7 @@ NtGdiSetDIBits(
     Dc = DC_LockDc(hDC);
     if (NULL == Dc)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return 0;
     }
     if (Dc->dctype == DC_TYPE_INFO)
@@ -379,7 +384,7 @@ NtGdiSetDIBits(
         return 0;
     }
 
-    Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, (PBITMAPINFO)&bmiLocal, ColorUse);
+    Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
 
     DC_UnlockDc(Dc);
 
@@ -420,14 +425,13 @@ NtGdiSetDIBitsToDeviceInternal(
     EXLATEOBJ exlo;
     PPALETTE ppalDIB = NULL;
     HPALETTE hpalDIB = NULL;
-    ULONG DIBPaletteType;
-    BITMAPV5INFO bmiLocal ;
 
     if (!Bits) return 0;
 
     _SEH2_TRY
     {
-        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
+        ProbeForRead(bmi, cjMaxInfo, 1);
+        ProbeForRead(Bits, cjMaxBits, 1);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -443,7 +447,7 @@ NtGdiSetDIBitsToDeviceInternal(
     pDC = DC_LockDc(hDC);
     if (!pDC)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return 0;
     }
     if (pDC->dctype == DC_TYPE_INFO)
@@ -456,7 +460,7 @@ NtGdiSetDIBitsToDeviceInternal(
 
     pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
 
-    ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
+    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
 
     rcDest.left = XDest;
     rcDest.top = YDest;
@@ -473,20 +477,20 @@ NtGdiSetDIBitsToDeviceInternal(
     ptSource.x = XSrc;
     ptSource.y = YSrc;
 
-    SourceSize.cx = bmiLocal.bmiHeader.bV5Width;
+    SourceSize.cx = bmi->bmiHeader.biWidth;
     SourceSize.cy = ScanLines;
 
-    DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount);
+    DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
     hSourceBitmap = EngCreateBitmap(SourceSize,
                                     DIBWidth,
-                                    BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
-                                                 bmiLocal.bmiHeader.bV5Compression),
-                                    bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
+                                    BitmapFormat(bmi->bmiHeader.biBitCount,
+                                                 bmi->bmiHeader.biCompression),
+                                    bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
                                     (PVOID) Bits);
     if (!hSourceBitmap)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
@@ -501,10 +505,10 @@ NtGdiSetDIBitsToDeviceInternal(
     ASSERT(pSurf->ppal);
 
     /* Create a palette for the DIB */
-    hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType);
+    hpalDIB = BuildDIBPalette(bmi);
     if (!hpalDIB)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
@@ -513,7 +517,7 @@ NtGdiSetDIBitsToDeviceInternal(
     ppalDIB = PALETTE_LockPalette(hpalDIB);
     if (!ppalDIB)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         Status = STATUS_UNSUCCESSFUL;
         goto Exit;
     }
@@ -571,32 +575,29 @@ NtGdiGetDIBitsInternal(
     UINT MaxBits,
     UINT MaxInfo)
 {
-    PDC Dc;
-    SURFACE *psurf = NULL;
-    HBITMAP hDestBitmap = NULL;
-    HPALETTE hDestPalette = NULL;
-    BITMAPV5INFO bmiLocal ;
-    PPALETTE ppalDst = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG Result = 0;
-    BOOL bPaletteMatch = FALSE;
-    PBYTE ChkBits = Bits;
-    ULONG DestPaletteType;
-    ULONG Index;
+       BITMAPCOREINFO* pbmci = NULL;
+       PSURFACE psurf = NULL;
+       PDC pDC;
+       LONG width, height;
+       WORD planes, bpp;
+       DWORD compr, size ;
+       int i, 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;
 
-    // if ScanLines == 0, no need to copy Bits.
-    if (!ScanLines)
-        ChkBits = NULL;
-
     _SEH2_TRY
     {
-        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage);
-        if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
+               /* Probe for read and write */
+        ProbeForRead(Info, MaxInfo, 1);
+               ProbeForWrite(Info, MaxInfo, 1);
+        if (Bits) ProbeForWrite(Bits, MaxBits, 1);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -609,303 +610,397 @@ NtGdiGetDIBitsInternal(
         return 0;
     }
 
-    Dc = DC_LockDc(hDC);
-    if (Dc == NULL) return 0;
-    if (Dc->dctype == DC_TYPE_INFO)
+       colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
+       rgbTriples = colorPtr;
+       rgbQuads = colorPtr;
+
+       bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
+                                           &width,
+                                                                       &height,
+                                                                       &planes,
+                                                                       &bpp,
+                                                                       &compr,
+                                                                       &size);
+       if(bitmap_type == -1)
+       {
+               DPRINT("Wrong bitmap format\n");
+               EngSetLastError(ERROR_INVALID_PARAMETER);
+               return 0;
+       }
+       else if(bitmap_type == 0)
+       {
+               /* We need a BITMAPINFO to create a DIB, but we have to fill
+                * the BITMAPCOREINFO we're provided */
+               pbmci = (BITMAPCOREINFO*)Info;
+               Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
+               if(Info == NULL)
+               {
+                       DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
+                       return 0;
+               }
+               rgbQuads = Info->bmiColors;
+       }
+
+    pDC = DC_LockDc(hDC);
+    if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
     {
-        DC_UnlockDc(Dc);
-        return 0;
+               ScanLines = 0;
+        goto done;
     }
 
     /* Get a pointer to the source bitmap object */
     psurf = SURFACE_LockSurface(hBitmap);
     if (psurf == NULL)
     {
-        DC_UnlockDc(Dc);
-        return 0;
-    }
-
-    ASSERT(psurf->ppal);
-
-    DC_UnlockDc(Dc);
-
-    /* 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 = psurf->ppal;
-        bPaletteMatch = TRUE;
-    }
-    else
-    {
-        hDestPalette = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DestPaletteType);
-        ppalDst = PALETTE_LockPalette(hDestPalette);
-    }
-
-    DPRINT("ppalDst : %p\n", ppalDst);
-    ASSERT(ppalDst);
-
-    /* Copy palette. */
-    switch (bmiLocal.bmiHeader.bV5BitCount)
-    {
-        case 1:
-        case 4:
-        case 8:
-            bmiLocal.bmiHeader.bV5ClrUsed = 0;
-            if (psurf->hSecure &&
-                BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bmiLocal.bmiHeader.bV5BitCount)
-            {
-                if (Usage == DIB_RGB_COLORS)
-                {
-                    if (ppalDst->NumColors != 1 << bmiLocal.bmiHeader.bV5BitCount)
-                        bmiLocal.bmiHeader.bV5ClrUsed = ppalDst->NumColors;
-                    for (Index = 0;
-                         Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
-                         Index++)
-                    {
-                        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
-                {
-                    for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount);
-                         Index++)
-                    {
-                        ((WORD*)bmiLocal.bmiColors)[Index] = Index;
-                    }
-                }
-            }
-            else
-            {
-                if (Usage == DIB_PAL_COLORS)
-                {
-                    for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount);
-                         Index++)
+        ScanLines = 0;
+        goto done;
+    }
+
+       /* Fill in the structure */
+       switch(bpp)
+       {
+       case 0: /* Only info */
+               if(pbmci)
+               {
+                       pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
+                       pbmci->bmciHeader.bcHeight = (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 :
+                   psurf->SurfObj.sizlBitmap.cy;;
+               Info->bmiHeader.biPlanes = 1;
+               Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+               Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
+                                                                                                                       Info->bmiHeader.biHeight,
+                                                                                                                       Info->bmiHeader.biBitCount);
+               if(psurf->hSecure)
+               {
+                       switch(Info->bmiHeader.biBitCount)
+                       {
+                       case 16:
+                       case 32:
+                               Info->bmiHeader.biCompression = BI_BITFIELDS;
+                               break;
+                       default:
+                               Info->bmiHeader.biCompression = BI_RGB;
+                               break;
+                       }
+               }
+               else if(Info->bmiHeader.biBitCount > 8)
+               {
+                       Info->bmiHeader.biCompression = BI_BITFIELDS;
+               }
+               else
+               {
+                       Info->bmiHeader.biCompression = BI_RGB;
+               }
+               Info->bmiHeader.biXPelsPerMeter = 0;
+        Info->bmiHeader.biYPelsPerMeter = 0;
+        Info->bmiHeader.biClrUsed = 0;
+        Info->bmiHeader.biClrImportant = 0;
+               ScanLines = abs(Info->bmiHeader.biHeight);
+               goto done;
+
+       case 1:
+       case 4:
+       case 8:
+               Info->bmiHeader.biClrUsed = 0;
+
+               /* If the bitmap if a DIB section and has the same format than what
+                * we're asked, go ahead! */
+               if((psurf->hSecure) &&
+                       (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
+               {
+                       if(Usage == DIB_RGB_COLORS)
+                       {
+                               unsigned int colors = min(psurf->ppal->NumColors, 1 << bpp);
+
+                               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 != 1 << bpp) 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;
+                               }
+                       }
+                       else
+                       {
+                               for(i=0; i < 1 << bpp; i++)
+                               {
+                                       if(pbmci) ((WORD*)rgbTriples)[i] = i;
+                                       ((WORD*)rgbQuads)[i] = i;
+                               }
+                       }
+               }
+               else
+               {
+                       if(Usage == DIB_PAL_COLORS)
+                       {
+                               for(i=0; i < 1 << bpp; i++)
+                               {
+                                       if(pbmci) ((WORD*)rgbTriples)[i] = i;
+                                       ((WORD*)rgbQuads)[i] = i;
+                               }
+                       }
+                       else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat)) {
+                /* For color DDBs in native depth (mono DDBs always have
+                   a black/white palette):
+                   Generate the color map from the selected palette */
+                PPALETTE pDcPal = PALETTE_LockPalette(pDC->dclevel.hpal);
+                               if(!pDcPal)
+                               {
+                                       ScanLines = 0 ;
+                                       goto done ;
+                               }
+                for (i = 0; i < pDcPal->NumColors; i++) {
+                    if (pbmci)
                     {
-                        ((WORD*)bmiLocal.bmiColors)[Index] = (WORD)Index;
+                        rgbTriples[i].rgbtRed   = pDcPal->IndexedColors[i].peRed;
+                        rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
+                        rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
                     }
-                }
-                else if (Info->bmiHeader.biBitCount > 1  && bPaletteMatch)
-                {
-                    for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
-                         Index++)
+
+                    rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
+                    rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
+                    rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
+                    rgbQuads[i].rgbReserved = 0;
+                               }
+                               PALETTE_UnlockPalette(pDcPal);
+            } else {
+                switch (bpp) {
+                case 1:
+                    if (pbmci)
                     {
-                        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;
+                        rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
+                            rgbTriples[0].rgbtBlue = 0;
+                        rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
+                            rgbTriples[1].rgbtBlue = 0xff;
                     }
-                }
-                else
-                {
-                    switch (bmiLocal.bmiHeader.bV5BitCount)
+                    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;
+                    break;
+
+                case 4:
+                    if (pbmci)
+                        RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
+                    RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
+
+                    break;
+
+                case 8:
                     {
-                        case 1:
-                            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(bmiLocal.bmiColors, EGAColorsQuads, sizeof(EGAColorsQuads));
-                            break;
-                        case 8:
+                                               INT r, g, b;
+                        RGBQUAD *color;
+                        if (pbmci)
                         {
-                            INT r, g, b;
-                            RGBQUAD *color;
-
-                            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++)
-                                    {
-                                        color->rgbRed = (r * 0xff) / 5;
-                                        color->rgbGreen = (g * 0xff) / 5;
-                                        color->rgbBlue = (b * 0xff) / 5;
-                                        color->rgbReserved = 0;
+                            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++;
                                     }
+                                                               }
+                                                       }
                         }
-                        break;
+                                               memcpy(rgbQuads, DefLogPaletteQuads,
+                                   10 * sizeof(RGBQUAD));
+                        memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
+                               10 * sizeof(RGBQUAD));
+                        color = rgbQuads + 10;
+                        for(r = 0; r <= 5; r++) /* FIXME */
+                                               {
+                            for(g = 0; g <= 5; g++)
+                                                       {
+                                for(b = 0; b <= 5; b++)
+                                                               {
+                                    color->rgbRed =   (r * 0xff) / 5;
+                                    color->rgbGreen = (g * 0xff) / 5;
+                                    color->rgbBlue =  (b * 0xff) / 5;
+                                    color->rgbReserved = 0;
+                                    color++;
+                                }
+                                                       }
+                                               }
                     }
                 }
             }
+        }
+        break;
 
-        case 15:
-            if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
-            {
-                bmiLocal.bmiHeader.bV5RedMask = 0x7c00;
-                bmiLocal.bmiHeader.bV5GreenMask = 0x03e0;
-                bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
-            }
-            break;
+    case 15:
+        if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+        {
+            ((PDWORD)Info->bmiColors)[0] = 0x7c00;
+            ((PDWORD)Info->bmiColors)[1] = 0x03e0;
+            ((PDWORD)Info->bmiColors)[2] = 0x001f;
+        }
+        break;
 
-        case 16:
-            if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+    case 16:
+        if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+        {
+            if (psurf->hSecure)
+                       {
+                               ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+                ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+                ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+                       }
+            else
             {
-                bmiLocal.bmiHeader.bV5RedMask = 0xf800;
-                bmiLocal.bmiHeader.bV5GreenMask = 0x07e0;
-                bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
+                ((PDWORD)Info->bmiColors)[0] = 0xf800;
+                ((PDWORD)Info->bmiColors)[1] = 0x07e0;
+                ((PDWORD)Info->bmiColors)[2] = 0x001f;
             }
-            break;
+        }
+        break;
 
-        case 24:
-        case 32:
-            if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+    case 24:
+    case 32:
+        if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+        {
+            if (psurf->hSecure)
+                       {
+                               ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+                ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+                ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+                       }
+            else
             {
-                bmiLocal.bmiHeader.bV5RedMask = 0xff0000;
-                bmiLocal.bmiHeader.bV5GreenMask = 0x00ff00;
-                bmiLocal.bmiHeader.bV5BlueMask = 0x0000ff;
+                ((PDWORD)Info->bmiColors)[0] = 0xff0000;
+                ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
+                ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
             }
-            break;
-    }
-
-    /* fill out the BITMAPINFO struct */
-    if (!ChkBits)
-    {
-        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)
-        {
-                /* 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
-    {
-        SIZEL DestSize;
-        POINTL SourcePoint;
-
-//
-// If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
-//
-        /* Create the destination bitmap too for the copy operation */
-        if (StartScan > psurf->SurfObj.sizlBitmap.cy)
+        break;
+    }
+       Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
+
+       if(Bits && ScanLines)
+       {
+               /* Create a DIBSECTION, blt it, profit */
+               PVOID pDIBits ;
+               HBITMAP hBmpDest;
+               PSURFACE psurfDest;
+               EXLATEOBJ exlo;
+               RECT rcDest;
+               POINTL srcPoint;
+               BOOL ret ;
+
+               if (StartScan > psurf->SurfObj.sizlBitmap.cy)
         {
-            goto cleanup;
+                       ScanLines = 0;
+            goto done;
         }
         else
         {
             ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
-            DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
-            DestSize.cy = ScanLines;
-
-            hDestBitmap = NULL;
-
-            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);
-
-            if (hDestBitmap == NULL)
-                goto cleanup;
-        }
-
-        if (NT_SUCCESS(Status))
-        {
-            EXLATEOBJ exlo;
-            SURFOBJ *DestSurfObj;
-            RECTL DestRect;
-
-            EXLATEOBJ_vInitialize(&exlo, psurf->ppal, ppalDst, 0, 0, 0);
-
-            SourcePoint.x = 0;
-            SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
-
-            /* Determine destination rectangle */
-            DestRect.top = 0;
-            DestRect.left = 0;
-            DestRect.right = DestSize.cx;
-            DestRect.bottom = DestSize.cy;
-
-            DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
-
-            if (IntEngCopyBits(DestSurfObj,
-                               &psurf->SurfObj,
-                               NULL,
-                               &exlo.xlo,
-                               &DestRect,
-                               &SourcePoint))
-            {
-                DPRINT("GetDIBits %d \n",abs(Info->bmiHeader.biHeight) - StartScan);
-                Result = ScanLines;
-            }
-
-            EXLATEOBJ_vCleanup(&exlo);
-            EngUnlockSurface(DestSurfObj);
-        }
-    }
-    /* Now that everything is over, get back the information to caller */
-    /* Note : Info has already been probed */
-    GetBMIFromBitmapV5Info(&bmiLocal, Info, Usage);
-cleanup:
-
-    if (hDestBitmap != NULL)
-        EngDeleteSurface((HSURF)hDestBitmap);
-
-    if (hDestPalette != NULL && !bPaletteMatch)
-    {
-        PALETTE_UnlockPalette(ppalDst);
-        PALETTE_FreePaletteByHandle(hDestPalette);
-    }
-
-    SURFACE_UnlockSurface(psurf);
-
-    DPRINT("leaving NtGdiGetDIBitsInternal\n");
-
-    return Result;
+               }
+
+               /* Fixup values */
+               Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
+               Info->bmiHeader.biHeight = height < 0 ?
+                       -ScanLines : ScanLines;
+               /* Create the DIB */
+               hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
+               /* Restore them */
+               Info->bmiHeader.biWidth = width;
+               Info->bmiHeader.biHeight = height;
+
+               if(!hBmpDest)
+               {
+                       DPRINT1("Unable to create a DIB Section!\n");
+                       EngSetLastError(ERROR_INVALID_PARAMETER);
+                       ScanLines = 0;
+                       goto done ;
+               }
+
+               psurfDest = SURFACE_LockSurface(hBmpDest);
+
+               rcDest.left = 0;
+               rcDest.top = 0;
+               rcDest.bottom = ScanLines;
+               rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+
+               srcPoint.x = 0;
+               srcPoint.y = height < 0 ?
+                       psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines) : StartScan;
+
+               EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0, 0, 0);
+
+               ret = IntEngCopyBits(&psurfDest->SurfObj,
+                                                        &psurf->SurfObj,
+                                                        NULL,
+                                                        &exlo.xlo,
+                                                        &rcDest,
+                                                        &srcPoint);
+
+               if(!ret)
+                       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;
+                       }
+               }
+
+               GreDeleteObject(hBmpDest);
+               EXLATEOBJ_vCleanup(&exlo);
+       }
+       else ScanLines = abs(height);
+
+done:
+
+       if(pDC) DC_UnlockDc(pDC);
+       if(psurf) SURFACE_UnlockSurface(psurf);
+       if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+
+       return ScanLines;
 }
 
+
 INT
 APIENTRY
 NtGdiStretchDIBitsInternal(
@@ -926,15 +1021,32 @@ NtGdiStretchDIBitsInternal(
     UINT cjMaxBits,
     HANDLE hcmXform)
 {
-    HBITMAP hBitmap, hOldBitmap = NULL;
+    PDC pdc;
+    INT ret = 0;
+    LONG height;
+    LONG width;
+    WORD planes, bpp;
+    DWORD compr, size;
+    HBITMAP hBitmap;
+    HBITMAP hOldBitmap;
     HDC hdcMem;
-    HPALETTE hPal = NULL;
-    PDC pDC;
-    BOOL Hit = FALSE;
+    PVOID pvBits;
+    PBYTE safeBits;
 
     if (!Bits || !BitsInfo)
+        return 0;
+
+    safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+    if(!safeBits)
+    {
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+    }
+
+    if (!(pdc = DC_LockDc(hDC)))
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        ExFreePoolWithTag(safeBits, TAG_DIB);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return 0;
     }
 
@@ -942,97 +1054,77 @@ NtGdiStretchDIBitsInternal(
     {
         ProbeForRead(BitsInfo, cjMaxInfo, 1);
         ProbeForRead(Bits, cjMaxBits, 1);
+        if (DIB_GetBitmapInfo(&BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size) == -1)
+        {
+            DPRINT1("Invalid bitmap\n");
+            _SEH2_YIELD(goto cleanup;)
+        }
+        RtlCopyMemory(safeBits, Bits, cjMaxBits);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        Hit = TRUE;
+        DPRINT1("Error, failed to read the DIB bits\n");
+        _SEH2_YIELD(goto cleanup;)
     }
     _SEH2_END
 
-    if (Hit)
+    if (width < 0)
     {
-        DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
+        DPRINT1("Bitmap has a negative width\n");
         return 0;
     }
 
-    hdcMem = NtGdiCreateCompatibleDC(hDC);
-    if (hdcMem == NULL)
-    {
-        DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
-        return 0;
-    }
+    hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
 
-    hBitmap = NtGdiCreateCompatibleBitmap(hDC,
-                                          abs(BitsInfo->bmiHeader.biWidth),
-                                          abs(BitsInfo->bmiHeader.biHeight));
-    if (hBitmap == NULL)
+    if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
+        DestWidth == SrcWidth && DestHeight == SrcHeight &&
+        compr == BI_RGB &&
+        ROP == SRCCOPY)
     {
-        DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
-        DPRINT1("hDC : 0x%08x \n", hDC);
-        DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
-        DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
-        return 0;
-    }
-
-    /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
-    hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
-
-    if (Usage == DIB_PAL_COLORS)
-    {
-        hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
-        hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
+        BITMAP bmp;
+        ret = IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp);
+        if (ret &&
+            bmp.bmBitsPixel == bpp &&
+            bmp.bmWidth == SrcWidth &&
+            bmp.bmHeight == SrcHeight &&
+            bmp.bmPlanes == planes)
+        {
+            /* fast path */
+            ret = IntSetDIBits(pdc, hBitmap, 0, height, safeBits, BitsInfo, Usage);
+            goto cleanup;
+        }
     }
 
-    if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
-            BitsInfo->bmiHeader.biCompression == BI_RLE8)
-    {
-        /* copy existing bitmap from destination dc */
-        if (SrcWidth == DestWidth && SrcHeight == DestHeight)
-            NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                        SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
-        else
-            NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                            SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
-                            ROP, 0);
-    }
+    /* slow path - need to use StretchBlt */
 
-    pDC = DC_LockDc(hdcMem);
-    if (pDC != NULL)
+    hdcMem = NtGdiCreateCompatibleDC(hDC);
+    hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
+    if(!hBitmap)
     {
-        /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
-         * if it negitve we getting to many scanline for scanline is UINT not
-         * a INT, so we need make the negtive value to positve and that make the
-         * count correct for negtive bitmap, TODO : we need testcase for this api */
-        IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
-                     BitsInfo, Usage);
-
-        DC_UnlockDc(pDC);
+        DPRINT1("Error, failed to create a DIB section\n");
+        NtGdiDeleteObjectApp(hdcMem);
+        goto cleanup;
     }
 
+    RtlCopyMemory(pvBits, safeBits, cjMaxBits);
+    hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
 
     /* Origin for DIBitmap may be bottom left (positive biHeight) or top
        left (negative biHeight) */
-    if (SrcWidth == DestWidth && SrcHeight == DestHeight)
-        NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
-                    hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                    ROP, 0, 0);
-    else
-        NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
-                        hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                        SrcWidth, SrcHeight, ROP, 0);
-
-    /* cleanup */
-    if (hPal)
-        GdiSelectPalette(hdcMem, hPal, FALSE);
-
-    if (hOldBitmap)
-        NtGdiSelectBitmap(hdcMem, hOldBitmap);
+    ret = NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
+                         hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
+                         SrcWidth, SrcHeight, ROP, 0);
 
+    if(ret)
+        ret = SrcHeight;
+    NtGdiSelectBitmap(hdcMem, hOldBitmap);
     NtGdiDeleteObjectApp(hdcMem);
-
     GreDeleteObject(hBitmap);
 
-    return SrcHeight;
+cleanup:
+    ExFreePoolWithTag(safeBits, TAG_DIB);
+    DC_UnlockDc(pdc);
+    return ret;
 }
 
 
@@ -1058,40 +1150,19 @@ IntCreateDIBitmap(
     else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
     else
     {
-        if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-        {
-            const RGBQUAD *rgb = data->bmiColors;
-            DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
+        const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
+        DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
 
-            // Check if the first color of the colormap is black
-            if ((col == RGB(0, 0, 0)))
-            {
-                rgb++;
-                col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
-
-                // If the second color is white, create a monochrome bitmap
-                fColor = (col != RGB(0xff,0xff,0xff));
-            }
-            else fColor = TRUE;
-        }
-        else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+        // Check if the first color of the colormap is black
+        if ((col == RGB(0, 0, 0)))
         {
-            RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
-            DWORD col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
+            rgb++;
+            col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
 
-            if ((col == RGB(0,0,0)))
-            {
-                rgb++;
-                col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
-                fColor = (col != RGB(0xff,0xff,0xff));
-            }
-            else fColor = TRUE;
-        }
-        else
-        {
-            DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize);
-            return 0;
+            // If the second color is white, create a monochrome bitmap
+            fColor = (col != RGB(0xff,0xff,0xff));
         }
+        else fColor = TRUE;
     }
 
     // Now create the bitmap
@@ -1135,72 +1206,106 @@ NtGdiCreateDIBitmapInternal(
     IN UINT cjMaxBits,
     IN FLONG fl,
     IN HANDLE hcmXform)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+       PBYTE safeBits = NULL;
+       HBITMAP hbmResult = NULL;
+
+       if(pjInit && (fInit == CBM_INIT))
+       {
+               safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+               if(!safeBits)
+               {
+                       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                       return NULL;
+               }
+       }
+
+    _SEH2_TRY
+    {
+        if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
+        if(pjInit && (fInit == CBM_INIT))
+               {
+                       ProbeForRead(pjInit, cjMaxBits, 1);
+                       RtlCopyMemory(safeBits, pjInit, cjMaxBits);
+               }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END
+
+    if(!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+               goto cleanup;
+    }
+
+    hbmResult =  GreCreateDIBitmapInternal(hDc,
+                                                              cx,
+                                                                  cy,
+                                                                              fInit,
+                                           safeBits,
+                                           pbmi,
+                                           iUsage,
+                                           fl,
+                                           hcmXform);
+
+cleanup:
+       if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
+       return hbmResult;
+}
+
+HBITMAP
+FASTCALL
+GreCreateDIBitmapInternal(
+    IN HDC hDc,
+    IN INT cx,
+    IN INT cy,
+    IN DWORD fInit,
+    IN OPTIONAL LPBYTE pjInit,
+    IN OPTIONAL PBITMAPINFO pbmi,
+    IN DWORD iUsage,
+    IN FLONG fl,
+    IN HANDLE hcmXform)
 {
     PDC Dc;
     HBITMAP Bmp;
-    UINT bpp;
+    WORD bpp;
+    HDC hdcDest;
 
-    if (!hDc) // CreateBitmap
+    if (!hDc) /* 1bpp monochrome bitmap */
     {  // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
-        hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
-        if (!hDc)
-        {
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
-            return NULL;
-        }
-
-        Dc = DC_LockDc(hDc);
-        if (!Dc)
+        hdcDest = NtGdiCreateCompatibleDC(0);
+        if(!hdcDest)
         {
-            NtGdiDeleteObjectApp(hDc);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
             return NULL;
         }
-        bpp = 1;
-        Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+    }
+    else
+    {
+        hdcDest = hDc;
+    }
 
-        DC_UnlockDc(Dc);
-        NtGdiDeleteObjectApp(hDc);
+    Dc = DC_LockDc(hdcDest);
+    if (!Dc)
+    {
+        EngSetLastError(ERROR_INVALID_HANDLE);
+        return NULL;
     }
-    else // CreateCompatibleBitmap
+    /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
+     * if bpp != 1 and ignore the real value that was passed */
+    if (pbmi)
+        bpp = pbmi->bmiHeader.biBitCount;
+    else
+        bpp = 0;
+    Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+    DC_UnlockDc(Dc);
+
+    if(!hDc)
     {
-        Dc = DC_LockDc(hDc);
-        if (!Dc)
-        {
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
-            return NULL;
-        }
-        /* pbmi == null
-           First create an un-initialised bitmap.  The depth of the bitmap
-           should match that of the hdc and not that supplied in bmih.
-         */
-        if (pbmi)
-            bpp = pbmi->bmiHeader.biBitCount;
-        else
-        {
-            if (Dc->dctype != DC_TYPE_MEMORY)
-                bpp = Dc->ppdev->gdiinfo.cBitsPixel;
-            else
-            {
-                DIBSECTION dibs;
-                INT Count;
-                SURFACE *psurf = Dc->dclevel.pSurface;
-                Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
-                if (!Count)
-                    bpp = 1;
-                else
-                {
-                    if (Count == sizeof(BITMAP))
-                        /* A device-dependent bitmap is selected in the DC */
-                        bpp = dibs.dsBm.bmBitsPixel;
-                    else
-                        /* A DIB section is selected in the DC */
-                        bpp = dibs.dsBmih.biBitCount;
-                }
-            }
-        }
-        Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
-        DC_UnlockDc(Dc);
+        NtGdiDeleteObjectApp(hdcDest);
     }
     return Bmp;
 }
@@ -1212,7 +1317,7 @@ NtGdiCreateDIBSection(
     IN HDC hDC,
     IN OPTIONAL HANDLE hSection,
     IN DWORD dwOffset,
-    IN LPBITMAPINFO bmi,
+    IN BITMAPINFO* bmi,
     IN DWORD Usage,
     IN UINT cjHeader,
     IN FLONG fl,
@@ -1222,9 +1327,28 @@ NtGdiCreateDIBSection(
     HBITMAP hbitmap = 0;
     DC *dc;
     BOOL bDesktopDC = FALSE;
+       NTSTATUS Status = STATUS_SUCCESS;
 
     if (!bmi) return hbitmap; // Make sure.
 
+       _SEH2_TRY
+    {
+        ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+               ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+               ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END
+
+    if(!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        return NULL;
+    }
+
     // If the reference hdc is null, take the desktop dc
     if (hDC == 0)
     {
@@ -1235,7 +1359,7 @@ NtGdiCreateDIBSection(
     if ((dc = DC_LockDc(hDC)))
     {
         hbitmap = DIB_CreateDIBSection(dc,
-                                       (BITMAPINFO*)bmi,
+                                       bmi,
                                        Usage,
                                        Bits,
                                        hSection,
@@ -1245,7 +1369,7 @@ NtGdiCreateDIBSection(
     }
     else
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
     }
 
     if (bDesktopDC)
@@ -1258,7 +1382,7 @@ HBITMAP
 APIENTRY
 DIB_CreateDIBSection(
     PDC dc,
-    BITMAPINFO *bmi,
+    CONST BITMAPINFO *bmi,
     UINT usage,
     LPVOID *bits,
     HANDLE section,
@@ -1268,19 +1392,15 @@ DIB_CreateDIBSection(
     HBITMAP res = 0;
     SURFACE *bmp = NULL;
     void *mapBits = NULL;
-    PDC_ATTR pdcattr;
     HPALETTE hpal ;
 
     // Fill BITMAP32 structure with DIB data
-    BITMAPINFOHEADER *bi = &bmi->bmiHeader;
+    CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
     INT effHeight;
     ULONG totalSize;
     BITMAP bm;
     SIZEL Size;
-    RGBQUAD *lpRGB;
     HANDLE hSecure;
-    DWORD dsBitfields[3] = {0};
-    ULONG ColorCount;
 
     DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
            bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
@@ -1292,13 +1412,11 @@ DIB_CreateDIBSection(
         return (HBITMAP)NULL;
     }
 
-    pdcattr = dc->pdcattr;
-
     effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
     bm.bmType = 0;
     bm.bmWidth = bi->biWidth;
     bm.bmHeight = effHeight;
-    bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
+    bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
 
     bm.bmPlanes = bi->biPlanes;
     bm.bmBitsPixel = bi->biBitCount;
@@ -1306,7 +1424,7 @@ DIB_CreateDIBSection(
 
     // Get storage location for DIB bits.  Only use biSizeImage if it's valid and
     // we're dealing with a compressed bitmap.  Otherwise, use width * height.
-    totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
+    totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
                 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
 
     if (section)
@@ -1344,7 +1462,7 @@ DIB_CreateDIBSection(
                                     PAGE_READWRITE);
         if (!NT_SUCCESS(Status))
         {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return NULL;
         }
 
@@ -1356,6 +1474,7 @@ DIB_CreateDIBSection(
     {
         offset = 0;
         bm.bmBits = EngAllocUserMem(totalSize, 0);
+               if(!bm.bmBits) goto cleanup;
     }
 
 //  hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
@@ -1363,54 +1482,31 @@ DIB_CreateDIBSection(
 
     if (usage == DIB_PAL_COLORS)
     {
-        lpRGB = DIB_MapPaletteColors(dc, bmi);
-        ColorCount = bi->biClrUsed;
-        if (ColorCount == 0)
-        {
-            ColorCount = 1 << bi->biBitCount;
-        }
+               if(dc)
+               {
+                       PPALETTE pdcPal ;
+                       pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
+                       hpal = DIB_MapPaletteColors(pdcPal, bmi);
+                       PALETTE_UnlockPalette(pdcPal);
+               }
+               else
+               {
+                       /* For DIB Brushes */
+                       DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
+                       /* HACK */
+                       hpal = (HPALETTE) 0xFFFFFFFF;
+               }
     }
     else
-    {
-        lpRGB = bmi->bmiColors;
-        ColorCount = 1 << bi->biBitCount;
-    }
+       {
+        hpal = BuildDIBPalette(bmi);
+       }
 
-    /* Set dsBitfields values */
-    if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
-    {
-        dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
-    }
-    else if (bi->biCompression == BI_RGB)
-    {
-        switch (bi->biBitCount)
-        {
-            case 15:
-                dsBitfields[0] = 0x7c00;
-                dsBitfields[1] = 0x03e0;
-                dsBitfields[2] = 0x001f;
-                break;
-
-            case 16:
-                dsBitfields[0] = 0xF800;
-                dsBitfields[1] = 0x07e0;
-                dsBitfields[2] = 0x001f;
-                break;
-
-            case 24:
-            case 32:
-                dsBitfields[0] = 0xff0000;
-                dsBitfields[1] = 0x00ff00;
-                dsBitfields[2] = 0x0000ff;
-                break;
-        }
-    }
-    else
-    {
-        dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
-        dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
-        dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
-    }
+       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;
@@ -1422,68 +1518,41 @@ DIB_CreateDIBSection(
                             BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
                               (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
                             bi->biSizeImage,
-                            bm.bmBits);
+                            bm.bmBits,
+                                                       0);
     if (!res)
     {
-        if (lpRGB != bmi->bmiColors)
-        {
-            ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-        }
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        return NULL;
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
+        goto cleanup;
     }
     bmp = SURFACE_LockSurface(res);
     if (NULL == bmp)
     {
-        if (lpRGB != bmi->bmiColors)
-        {
-            ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-        }
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
-        GreDeleteObject(res);
-        return NULL;
+               EngSetLastError(ERROR_INVALID_HANDLE);
+        goto cleanup;
     }
 
     /* WINE NOTE: WINE makes use of a colormap, which is a color translation
                   table between the DIB and the X physical device. Obviously,
                   this is left out of the ReactOS implementation. Instead,
                   we call NtGdiSetDIBColorTable. */
-    if (bi->biBitCount <= 8)
-    {
-        bi->biClrUsed = 1 << bi->biBitCount;
-    }
-    else
-    {
-        bi->biClrUsed = 0;
-    }
-
     bmp->hDIBSection = section;
     bmp->hSecure = hSecure;
     bmp->dwOffset = offset;
     bmp->flags = API_BITMAP;
-    bmp->dsBitfields[0] = dsBitfields[0];
-    bmp->dsBitfields[1] = dsBitfields[1];
-    bmp->dsBitfields[2] = dsBitfields[2];
-    bmp->biClrUsed = bi->biClrUsed;
     bmp->biClrImportant = bi->biClrImportant;
+    bmp->SurfObj.fjBitmap &= ~BMF_DONT_FREE;
 
-    if (bi->biClrUsed != 0)
-    {
-        hpal = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
-    }
-    else
-    {
-        hpal = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
-                                                dsBitfields[0],
-                                                dsBitfields[1],
-                                                dsBitfields[2]);
-    }
-
-    bmp->ppal = PALETTE_ShareLockPalette(hpal);
-    /* Lazy delete hpal, it will be freed at surface release */
-    GreDeleteObject(hpal);
+       /* HACK */
+       if(hpal != (HPALETTE)0xFFFFFFFF)
+       {
+               bmp->ppal = PALETTE_ShareLockPalette(hpal);
+               /* Lazy delete hpal, it will be freed at surface release */
+               GreDeleteObject(hpal);
+       }
 
     // Clean up in case of errors
+cleanup:
     if (!res || !bmp || !bm.bmBits)
     {
         DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
@@ -1510,11 +1579,6 @@ DIB_CreateDIBSection(
         }
     }
 
-    if (lpRGB != bmi->bmiColors)
-    {
-        ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-    }
-
     if (bmp)
     {
         SURFACE_UnlockSurface(bmp);
@@ -1526,21 +1590,43 @@ DIB_CreateDIBSection(
         *bits = bm.bmBits;
     }
 
-    if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
-
     return res;
 }
 
 /***********************************************************************
- *           DIB_GetDIBWidthBytes
+ *           DIB_GetBitmapInfo
  *
- * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
- * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
- * 11/16/1999 (RJJ) lifted from wine
+ * Get the info from a bitmap header.
+ * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
  */
-INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
+int
+FASTCALL
+DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+                       LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
 {
-    return ((width * depth + 31) & ~31) >> 3;
+    if (header->biSize == sizeof(BITMAPCOREHEADER))
+    {
+        const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
+        *width  = core->bcWidth;
+        *height = core->bcHeight;
+        *planes = core->bcPlanes;
+        *bpp    = core->bcBitCount;
+        *compr  = BI_RGB;
+        *size   = 0;
+        return 0;
+    }
+    if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
+    {
+        *width  = header->biWidth;
+        *height = header->biHeight;
+        *planes = header->biPlanes;
+        *bpp    = header->biBitCount;
+        *compr  = header->biCompression;
+        *size   = header->biSizeImage;
+        return 1;
+    }
+    DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
+    return -1;
 }
 
 /***********************************************************************
@@ -1552,7 +1638,7 @@ INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
 
 INT APIENTRY DIB_GetDIBImageBytes(INT  width, INT height, INT depth)
 {
-    return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
+    return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
 }
 
 /***********************************************************************
@@ -1564,90 +1650,93 @@ INT APIENTRY DIB_GetDIBImageBytes(INT  width, INT height, INT depth)
 
 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
 {
-    int colors;
+    unsigned int colors, size, masks = 0;
 
     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
     {
-        BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
+        const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
-        return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
+        return sizeof(BITMAPCOREHEADER) + colors *
+             ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
     }
     else  /* assume BITMAPINFOHEADER */
     {
         colors = info->bmiHeader.biClrUsed;
-        if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
-        return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+        if (colors > 256) colors = 256;
+        if (!colors && (info->bmiHeader.biBitCount <= 8))
+            colors = 1 << info->bmiHeader.biBitCount;
+        if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
+        size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
+        return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
     }
 }
 
-RGBQUAD *
+HPALETTE
 FASTCALL
-DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
+DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
 {
-    RGBQUAD *lpRGB;
+    PALETTEENTRY* ppalEntries;
     ULONG nNumColors,i;
     USHORT *lpIndex;
-    PPALETTE palGDI;
-
-    palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
+       HPALETTE hpal;
 
-    if (NULL == palGDI)
+    if (!(ppal->flFlags & PAL_INDEXED))
     {
         return NULL;
     }
 
-    if (palGDI->Mode != PAL_INDEXED)
-    {
-        PALETTE_UnlockPalette(palGDI);
-        return NULL;
-    }
-
     nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
     if (lpbmi->bmiHeader.biClrUsed)
     {
         nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
     }
 
-    lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
-    if (lpRGB == NULL)
+       /* Don't have more colors than we need */
+       nNumColors = min(ppal->NumColors, nNumColors);
+
+    ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
+    if (ppalEntries == NULL)
     {
-        PALETTE_UnlockPalette(palGDI);
+        DPRINT1("Could not allocate palette entries\n");
         return NULL;
     }
 
-    lpIndex = (USHORT *)&lpbmi->bmiColors[0];
+    lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
 
     for (i = 0; i < nNumColors; i++)
     {
-        if (*lpIndex < palGDI->NumColors)
+        if (*lpIndex < ppal->NumColors)
         {
-            lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
-            lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
-            lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+            ppalEntries[i] = ppal->IndexedColors[*lpIndex];
         }
         else
         {
-            lpRGB[i].rgbRed = 0;
-            lpRGB[i].rgbGreen = 0;
-            lpRGB[i].rgbBlue = 0;
+            ppalEntries[i].peRed = 0;
+                       ppalEntries[i].peGreen = 0;
+                       ppalEntries[i].peBlue = 0;
+                       ppalEntries[i].peFlags = 0;
         }
-        lpRGB[i].rgbReserved = 0;
+
         lpIndex++;
     }
-    PALETTE_UnlockPalette(palGDI);
 
-    return lpRGB;
+       hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
+
+       ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
+
+       return hpal;
 }
 
 HPALETTE
 FASTCALL
-BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
+BuildDIBPalette(CONST BITMAPINFO *bmi)
 {
     BYTE bits;
     ULONG ColorCount;
     HPALETTE hPal;
-    ULONG RedMask, GreenMask, BlueMask;
+    ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
     PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
+       INT paletteType;
 
     // Determine Bits Per Pixel
     bits = bmi->bmiHeader.biBitCount;
@@ -1655,36 +1744,43 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
     // Determine paletteType from Bits Per Pixel
     if (bits <= 8)
     {
-        *paletteType = PAL_INDEXED;
+        paletteType = PAL_INDEXED;
         RedMask = GreenMask = BlueMask = 0;
     }
     else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
     {
-        *paletteType = PAL_BITFIELDS;
+        paletteType = PAL_BITFIELDS;
         RedMask = pdwColors[0];
         GreenMask = pdwColors[1];
         BlueMask = pdwColors[2];
     }
-    else if (bits == 15)
-    {
-        *paletteType = PAL_BITFIELDS;
-        RedMask = 0x7c00;
-        GreenMask = 0x03e0;
-        BlueMask = 0x001f;
-    }
-    else if (bits == 16)
-    {
-        *paletteType = PAL_BITFIELDS;
-        RedMask = 0xF800;
-        GreenMask = 0x07e0;
-        BlueMask = 0x001f;
-    }
     else
     {
-        *paletteType = PAL_BGR;
-        RedMask = 0xff0000;
-        GreenMask = 0x00ff00;
-        BlueMask = 0x0000ff;
+        paletteType = PAL_BITFIELDS;
+        switch (bits)
+        {
+            case 15:
+                paletteType |= PAL_RGB16_555;
+                RedMask = 0x7C00;
+                GreenMask = 0x03E0;
+                BlueMask = 0x001F;
+                break;
+
+            case 16:
+                paletteType |= PAL_RGB16_565;
+                RedMask = 0xF800;
+                GreenMask = 0x07E0;
+                BlueMask = 0x001F;
+                break;
+
+            case 24:
+            case 32:
+                paletteType |= PAL_BGR;
+                RedMask = 0xFF0000;
+                GreenMask = 0x00FF00;
+                BlueMask = 0x0000FF;
+                break;
+        }
     }
 
     if (bmi->bmiHeader.biClrUsed == 0)
@@ -1696,13 +1792,13 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
         ColorCount = bmi->bmiHeader.biClrUsed;
     }
 
-    if (PAL_INDEXED == *paletteType)
+    if (PAL_INDEXED == paletteType)
     {
         hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
     }
     else
     {
-        hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
+        hPal = PALETTE_AllocPalette(paletteType, 0,
                                     NULL,
                                     RedMask, GreenMask, BlueMask);
     }
@@ -1710,244 +1806,82 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
     return hPal;
 }
 
-FORCEINLINE
-DWORD
-GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
+/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
+ * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
+BITMAPINFO*
+FASTCALL
+DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
 {
-    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;
+       CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
+       BITMAPINFO* pNewBmi ;
+       UINT numColors = 0, ColorsSize = 0;
+
+       if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
+       if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
+
+       if(pbmci->bmciHeader.bcBitCount <= 8)
+       {
+               numColors = 1 << pbmci->bmciHeader.bcBitCount;
+               if(Usage == DIB_PAL_COLORS)
+               {
+                       ColorsSize = numColors * sizeof(WORD);
+               }
+               else
+               {
+                       ColorsSize = numColors * sizeof(RGBQUAD);
+               }
+       }
+       else if (Usage == DIB_PAL_COLORS)
+       {
+               /* Invalid at high Res */
+               return NULL;
+       }
+
+       pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
+       if(!pNewBmi) return NULL;
+
+       RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
+
+       pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+       pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
+       pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
+       pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
+       pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
+       pNewBmi->bmiHeader.biCompression = BI_RGB ;
+       pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
+                                                                                               pNewBmi->bmiHeader.biHeight,
+                                                                                               pNewBmi->bmiHeader.biBitCount);
+
+       if(Usage == DIB_PAL_COLORS)
+       {
+               RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
+       }
+       else
+       {
+               UINT i;
+               for(i=0; i<numColors; i++)
+               {
+                       pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
+                       pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
+                       pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
+               }
+       }
+
+       return pNewBmi ;
 }
 
-FORCEINLINE
+/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
 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)
+DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
 {
-    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(converted != orig)
+               ExFreePoolWithTag(converted, TAG_DIB);
+}
 
-    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 */