[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / dibobj.c
index 8accc41..6ab2f6c 100644 (file)
@@ -136,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;
     }
 
@@ -156,7 +156,7 @@ IntSetDIBColorTable(
         if (psurf->ppal == NULL)
         {
             DC_UnlockDc(dc);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return 0;
         }
 
@@ -208,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;
     }
 
@@ -229,7 +229,7 @@ IntGetDIBColorTable(
         if (psurf->ppal == NULL)
         {
             DC_UnlockDc(dc);
-            SetLastWin32Error(ERROR_INVALID_HANDLE);
+            EngSetLastError(ERROR_INVALID_HANDLE);
             return 0;
         }
 
@@ -277,7 +277,7 @@ IntSetDIBits(
        if (0 == SourceBitmap)
     {
                DPRINT1("Error : Could not create a DIBSection.\n");
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         return 0;
     }
 
@@ -290,7 +290,7 @@ IntSetDIBits(
 
        if(!(psurfSrc && psurfDst))
        {
-               DPRINT1("Error, could not lock surfaces.\n");
+               DPRINT1("Error, could not lock surfaces\n");
                goto cleanup;
        }
 
@@ -375,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)
@@ -447,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)
@@ -480,7 +480,7 @@ NtGdiSetDIBitsToDeviceInternal(
     SourceSize.cx = bmi->bmiHeader.biWidth;
     SourceSize.cy = ScanLines;
 
-    DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
+    DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
     hSourceBitmap = EngCreateBitmap(SourceSize,
                                     DIBWidth,
@@ -490,7 +490,7 @@ NtGdiSetDIBitsToDeviceInternal(
                                     (PVOID) Bits);
     if (!hSourceBitmap)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
@@ -508,7 +508,7 @@ NtGdiSetDIBitsToDeviceInternal(
     hpalDIB = BuildDIBPalette(bmi);
     if (!hpalDIB)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
@@ -517,7 +517,7 @@ NtGdiSetDIBitsToDeviceInternal(
     ppalDIB = PALETTE_LockPalette(hpalDIB);
     if (!ppalDIB)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         Status = STATUS_UNSUCCESSFUL;
         goto Exit;
     }
@@ -624,7 +624,7 @@ NtGdiGetDIBitsInternal(
        if(bitmap_type == -1)
        {
                DPRINT("Wrong bitmap format\n");
-               SetLastWin32Error(ERROR_INVALID_PARAMETER);
+               EngSetLastError(ERROR_INVALID_PARAMETER);
                return 0;
        }
        else if(bitmap_type == 0)
@@ -663,15 +663,15 @@ NtGdiGetDIBitsInternal(
                if(pbmci)
                {
                        pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
-                       pbmci->bmciHeader.bcHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ? 
-                               -psurf->SurfObj.sizlBitmap.cy : 
+                       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 : 
+               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);
@@ -711,15 +711,15 @@ NtGdiGetDIBitsInternal(
        case 8:
                Info->bmiHeader.biClrUsed = 0;
 
-               /* If the bitmap if a DIB section and has the same format than what 
+               /* If the bitmap if a DIB section and has the same format than what
                 * we're asked, go ahead! */
-               if((psurf->hSecure) && 
+               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++)
@@ -773,7 +773,7 @@ NtGdiGetDIBitsInternal(
                         rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
                         rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
                     }
-                
+
                     rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
                     rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
                     rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
@@ -822,7 +822,7 @@ NtGdiGetDIBitsInternal(
                                                        {
                                 for(g = 0; g <= 5; g++)
                                                                {
-                                    for(b = 0; b <= 5; b++) 
+                                    for(b = 0; b <= 5; b++)
                                                                        {
                                         colorTriple->rgbtRed =   (r * 0xff) / 5;
                                         colorTriple->rgbtGreen = (g * 0xff) / 5;
@@ -935,11 +935,11 @@ NtGdiGetDIBitsInternal(
                /* Restore them */
                Info->bmiHeader.biWidth = width;
                Info->bmiHeader.biHeight = height;
-               
+
                if(!hBmpDest)
                {
                        DPRINT1("Unable to create a DIB Section!\n");
-                       SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                       EngSetLastError(ERROR_INVALID_PARAMETER);
                        ScanLines = 0;
                        goto done ;
                }
@@ -971,8 +971,8 @@ NtGdiGetDIBitsInternal(
                        Status = STATUS_SUCCESS;
                        _SEH2_TRY
                        {
-                               RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, height, bpp));
-                       } 
+                               RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
+                       }
                        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                        {
                                Status = _SEH2_GetExceptionCode();
@@ -1021,95 +1021,110 @@ NtGdiStretchDIBitsInternal(
     UINT cjMaxBits,
     HANDLE hcmXform)
 {
-    HBITMAP hBitmap, hOldBitmap = NULL;
-    HDC hdcMem = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-       PVOID pvDIBits;
-       INT Ret = 0;
+    PDC pdc;
+    INT ret = 0;
+    LONG height;
+    LONG width;
+    WORD planes, bpp;
+    DWORD compr, size;
+    HBITMAP hBitmap;
+    HBITMAP hOldBitmap;
+    HDC hdcMem;
+    PVOID pvBits;
+    PBYTE safeBits;
 
     if (!Bits || !BitsInfo)
+        return 0;
+
+    safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+    if(!safeBits)
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return 0;
     }
 
-    /* Create a DIB Section, data will be probed there */
-       hBitmap = NtGdiCreateDIBSection(hDC,
-                                                                 NULL,
-                                                                 0,
-                                                                 BitsInfo,
-                                                                 Usage,
-                                                                 0,
-                                                                 0,
-                                                                 0,
-                                                                 &pvDIBits);
+    if (!(pdc = DC_LockDc(hDC)))
+    {
+        ExFreePoolWithTag(safeBits, TAG_DIB);
+        EngSetLastError(ERROR_INVALID_HANDLE);
+        return 0;
+    }
 
-       if(!hBitmap)
-       {
-               DPRINT1("Failed to create a DIB.\n");
-               return 0;
-       }
+    _SEH2_TRY
+    {
+        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)
+    {
+        DPRINT1("Error, failed to read the DIB bits\n");
+        _SEH2_YIELD(goto cleanup;)
+    }
+    _SEH2_END
 
-       /* Set bits */
-       _SEH2_TRY
-       {
-               ProbeForRead(Bits, cjMaxBits, 1);
-               RtlCopyMemory(pvDIBits, Bits, DIB_GetDIBImageBytes(BitsInfo->bmiHeader.biWidth,
-                                                                                                                  BitsInfo->bmiHeader.biHeight,
-                                                                                                                  BitsInfo->bmiHeader.biBitCount));
-       }
-       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-       {
-               Status = _SEH2_GetExceptionCode();
-       }
-       _SEH2_END
+    if (width < 0)
+    {
+        DPRINT1("Bitmap has a negative width\n");
+        return 0;
+    }
 
-       if(!NT_SUCCESS(Status))
-       {
-               DPRINT1("Error : Could not read DIB bits\n");
-               SetLastNtError(Status);
-               goto cleanup;
-       }
+    hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
 
-       hdcMem = NtGdiCreateCompatibleDC(0);
-       if(!hdcMem)
-       {
-               DPRINT1("Failed to create a memory DC!");
-               goto cleanup;
-       }
+    if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
+        DestWidth == SrcWidth && DestHeight == SrcHeight &&
+        compr == BI_RGB &&
+        ROP == SRCCOPY)
+    {
+        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;
+        }
+    }
 
-       hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
-       if(!hOldBitmap)
-       {
-               DPRINT1("Could not select the DIB into the memory DC\n");
-               goto cleanup;
-       }
+    /* slow path - need to use StretchBlt */
 
-       /* Do we want to stretch ? */
-       if((SrcWidth == DestWidth) && (SrcHeight == DestHeight))
-       {
-               Ret = NtGdiBitBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight, 
-                                                 hdcMem, XSrc, YSrc, ROP, 0, 0);
-       }
-       else
-       {
-               Ret = NtGdiStretchBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight,
-                                                       hdcMem, XSrc, YSrc, XSrc + SrcWidth, YSrc + SrcHeight,
-                                                       ROP, 0);
-       }
+    hdcMem = NtGdiCreateCompatibleDC(hDC);
+    hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
+    if(!hBitmap)
+    {
+        DPRINT1("Error, failed to create a DIB section\n");
+        NtGdiDeleteObjectApp(hdcMem);
+        goto cleanup;
+    }
 
-       if(Ret)
-               Ret = SrcHeight ;
+    RtlCopyMemory(pvBits, safeBits, cjMaxBits);
+    hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
 
-cleanup:
-       if(hdcMem)
-       {
-               if(hOldBitmap) NtGdiSelectBitmap(hdcMem, hOldBitmap);
-               NtGdiDeleteObjectApp(hdcMem);
-       }
-       GreDeleteObject(hBitmap);
+    /* Origin for DIBitmap may be bottom left (positive biHeight) or top
+       left (negative biHeight) */
+    ret = NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
+                         hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
+                         SrcWidth, SrcHeight, ROP, 0);
 
-    return Ret;
+    if(ret)
+        ret = SrcHeight;
+    NtGdiSelectBitmap(hdcMem, hOldBitmap);
+    NtGdiDeleteObjectApp(hdcMem);
+    GreDeleteObject(hBitmap);
+
+cleanup:
+    ExFreePoolWithTag(safeBits, TAG_DIB);
+    DC_UnlockDc(pdc);
+    return ret;
 }
 
 
@@ -1193,11 +1208,27 @@ NtGdiCreateDIBitmapInternal(
     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);
+        if(pjInit && (fInit == CBM_INIT))
+               {
+                       ProbeForRead(pjInit, cjMaxBits, 1);
+                       RtlCopyMemory(safeBits, pjInit, cjMaxBits);
+               }
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -1208,18 +1239,22 @@ NtGdiCreateDIBitmapInternal(
     if(!NT_SUCCESS(Status))
     {
         SetLastNtError(Status);
-        return NULL;
+               goto cleanup;
     }
 
-    return GreCreateDIBitmapInternal(hDc,
-                                     cx,
-                                     cy,
-                                     fInit,
-                                     pjInit,
-                                     pbmi,
-                                     iUsage,
-                                     fl,
-                                     hcmXform);
+    hbmResult =  GreCreateDIBitmapInternal(hDc,
+                                                              cx,
+                                                                  cy,
+                                                                              fInit,
+                                           safeBits,
+                                           pbmi,
+                                           iUsage,
+                                           fl,
+                                           hcmXform);
+
+cleanup:
+       if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
+       return hbmResult;
 }
 
 HBITMAP
@@ -1256,7 +1291,7 @@ GreCreateDIBitmapInternal(
     Dc = DC_LockDc(hdcDest);
     if (!Dc)
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return NULL;
     }
     /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
@@ -1334,7 +1369,7 @@ NtGdiCreateDIBSection(
     }
     else
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
     }
 
     if (bDesktopDC)
@@ -1381,7 +1416,7 @@ DIB_CreateDIBSection(
     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;
@@ -1389,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)
@@ -1427,7 +1462,7 @@ DIB_CreateDIBSection(
                                     PAGE_READWRITE);
         if (!NT_SUCCESS(Status))
         {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return NULL;
         }
 
@@ -1462,7 +1497,7 @@ DIB_CreateDIBSection(
                        hpal = (HPALETTE) 0xFFFFFFFF;
                }
     }
-    else 
+    else
        {
         hpal = BuildDIBPalette(bmi);
        }
@@ -1487,13 +1522,13 @@ DIB_CreateDIBSection(
                                                        0);
     if (!res)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+        EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
         goto cleanup;
     }
     bmp = SURFACE_LockSurface(res);
     if (NULL == bmp)
     {
-               SetLastWin32Error(ERROR_INVALID_HANDLE);
+               EngSetLastError(ERROR_INVALID_HANDLE);
         goto cleanup;
     }
 
@@ -1506,6 +1541,7 @@ DIB_CreateDIBSection(
     bmp->dwOffset = offset;
     bmp->flags = API_BITMAP;
     bmp->biClrImportant = bi->biClrImportant;
+    bmp->SurfObj.fjBitmap &= ~BMF_DONT_FREE;
 
        /* HACK */
        if(hpal != (HPALETTE)0xFFFFFFFF)
@@ -1563,7 +1599,7 @@ cleanup:
  * Get the info from a bitmap header.
  * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
  */
-int 
+int
 FASTCALL
 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
                        LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
@@ -1575,7 +1611,7 @@ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
         *height = core->bcHeight;
         *planes = core->bcPlanes;
         *bpp    = core->bcBitCount;
-        *compr  = 0;
+        *compr  = BI_RGB;
         *size   = 0;
         return 0;
     }
@@ -1593,18 +1629,6 @@ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
     return -1;
 }
 
-/***********************************************************************
- *           DIB_GetDIBWidthBytes
- *
- * 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
- */
-INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
-{
-    return ((width * depth + 31) & ~31) >> 3;
-}
-
 /***********************************************************************
  *           DIB_GetDIBImageBytes
  *
@@ -1614,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);
 }
 
 /***********************************************************************
@@ -1656,7 +1680,7 @@ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
     USHORT *lpIndex;
        HPALETTE hpal;
 
-    if (ppal->Mode != PAL_INDEXED)
+    if (!(ppal->flFlags & PAL_INDEXED))
     {
         return NULL;
     }
@@ -1692,10 +1716,10 @@ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
                        ppalEntries[i].peBlue = 0;
                        ppalEntries[i].peFlags = 0;
         }
-        
+
         lpIndex++;
     }
-    
+
        hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
 
        ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
@@ -1730,17 +1754,33 @@ BuildDIBPalette(CONST BITMAPINFO *bmi)
         GreenMask = pdwColors[1];
         BlueMask = pdwColors[2];
     }
-    else if (bits == 15)
-    {
-        paletteType = PAL_RGB16_555;
-    }
-    else if (bits == 16)
-    {
-        paletteType = PAL_RGB16_565;
-    }
     else
     {
-               paletteType = PAL_BGR;
+        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)