diff --git a/reactos/win32ss/gdi/gdi32/objects/bitmap.c b/reactos/win32ss/gdi/gdi32/objects/bitmap.c index d5b81dc69cd..a2d6c2b20f4 100644 --- a/reactos/win32ss/gdi/gdi32/objects/bitmap.c +++ b/reactos/win32ss/gdi/gdi32/objects/bitmap.c @@ -408,23 +408,30 @@ CreateDIBitmap( // PDC_ATTR pDc_Attr; UINT InfoSize = 0; UINT cjBmpScanSize = 0; - HBITMAP hBmp; + HBITMAP hBmp = NULL; NTSTATUS Status = STATUS_SUCCESS; + PBITMAPINFO pbmiConverted; + UINT cjInfoSize; + + /* Convert the BITMAPINFO if it is a COREINFO */ + pbmiConverted = ConvertBitmapInfo(Data, ColorUse, &cjInfoSize, FALSE); /* Check for CBM_CREATDIB */ if (Init & CBM_CREATDIB) { /* CBM_CREATDIB needs Data. */ - if (!Data) + if (pbmiConverted == NULL) { - return 0; + DPRINT1("CBM_CREATDIB needs a BITMAINFO!\n"); + goto Exit; } /* It only works with PAL or RGB */ if (ColorUse > DIB_PAL_COLORS) { + DPRINT1("Invalid ColorUse: %lu\n", ColorUse); GdiSetLastError(ERROR_INVALID_PARAMETER); - return 0; + goto Exit; } /* Use the header from the data */ @@ -434,38 +441,48 @@ CreateDIBitmap( /* Header is required */ if (!Header) { + DPRINT1("Header is NULL\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); - return 0; + goto Exit; } /* Get the bitmap format and dimensions */ if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1) { + DPRINT1("DIB_GetBitmapInfo failed!\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); - return NULL; + goto Exit; } /* Check if the Compr is incompatible */ if ((compr == BI_JPEG) || (compr == BI_PNG) || (compr == BI_BITFIELDS)) - return 0; + { + DPRINT1("invalid compr: %lu!\n", compr); + goto Exit; + } /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */ if (ColorUse > DIB_PAL_COLORS + 1) { + DPRINT1("invalid compr: %lu!\n", compr); GdiSetLastError(ERROR_INVALID_PARAMETER); - return 0; + goto Exit; } /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */ if (Bits && (ColorUse > DIB_PAL_COLORS)) { + DPRINT1("Invalid ColorUse: %lu\n", ColorUse); GdiSetLastError(ERROR_INVALID_PARAMETER); - return 0; + goto Exit; } /* Negative width is not allowed */ if (width < 0) - return 0; + { + DPRINT1("Negative width: %li\n", width); + goto Exit; + } /* Top-down DIBs have a negative height. */ height = abs(height); @@ -473,13 +490,13 @@ CreateDIBitmap( // For Icm support. // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) - if (Data) + if (pbmiConverted) { _SEH2_TRY { - cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) Data); - CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize); - InfoSize += Data->bmiHeader.biSize; + cjBmpScanSize = GdiGetBitmapBitsSize(pbmiConverted); + CalculateColorTableSize(&pbmiConverted->bmiHeader, &ColorUse, &InfoSize); + InfoSize += pbmiConverted->bmiHeader.biSize; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -490,8 +507,9 @@ CreateDIBitmap( if (!NT_SUCCESS(Status)) { + DPRINT1("Got an exception!\n"); GdiSetLastError(ERROR_INVALID_PARAMETER); - return NULL; + goto Exit; } DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data, bpp, dibsize, InfoSize, @@ -501,9 +519,18 @@ CreateDIBitmap( hBmp = GetStockObject(DEFAULT_BITMAP); else { - hBmp = NtGdiCreateDIBitmapInternal(hDC, width, height, Init, (LPBYTE) Bits, - (LPBITMAPINFO) Data, ColorUse, InfoSize, cjBmpScanSize, 0, 0); + hBmp = NtGdiCreateDIBitmapInternal(hDC, width, height, Init, (LPBYTE)Bits, + (LPBITMAPINFO)pbmiConverted, ColorUse, InfoSize, cjBmpScanSize, 0, 0); } + +Exit: + + /* Cleanup converted BITMAPINFO */ + if ((pbmiConverted != NULL) && (pbmiConverted != Data)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted); + } + return hBmp; } diff --git a/reactos/win32ss/gdi/ntgdi/dibobj.c b/reactos/win32ss/gdi/ntgdi/dibobj.c index 819962303a4..36bfa4dfbfe 100644 --- a/reactos/win32ss/gdi/ntgdi/dibobj.c +++ b/reactos/win32ss/gdi/ntgdi/dibobj.c @@ -259,11 +259,37 @@ IntSetDIBits( POINTL ptSrc; EXLATEOBJ exlo; PPALETTE ppalDIB = 0; + ULONG cjSizeImage; if (!bmi) return 0; - if (bmi->bmiHeader.biSizeImage > cjMaxBits) + /* Check if the header provided an image size */ + if (bmi->bmiHeader.biSizeImage != 0) { + /* Use the given size */ + cjSizeImage = bmi->bmiHeader.biSizeImage; + } + /* Otherwise check for uncompressed formats */ + else if ((bmi->bmiHeader.biCompression == BI_RGB) || + (bmi->bmiHeader.biCompression == BI_BITFIELDS)) + { + /* Calculate the image size */ + cjSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, + ScanLines, + bmi->bmiHeader.biBitCount); + } + else + { + /* Compressed format without a size. This is invalid. */ + DPRINT1("Compressed format without a size!"); + return 0; + } + + /* Check if the size that we have is ok */ + if (cjSizeImage > cjMaxBits) + { + DPRINT1("Size too large! cjSizeImage = %lu, cjMaxBits = %lu\n", + cjSizeImage, cjMaxBits); return 0; } @@ -273,7 +299,7 @@ IntSetDIBits( BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression), bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0, - bmi->bmiHeader.biSizeImage, + cjSizeImage, (PVOID)Bits, 0); if (!SourceBitmap) @@ -315,6 +341,8 @@ IntSetDIBits( ptSrc.x = 0; ptSrc.y = 0; + NT_ASSERT(psurfSrc->SurfObj.cjBits <= cjMaxBits); + result = IntEngCopyBits(&psurfDst->SurfObj, &psurfSrc->SurfObj, NULL, @@ -1366,7 +1394,11 @@ IntCreateDIBitmap( /* Undocumented flag which creates a DDB of the format specified by the bitmap info. */ handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp); if (!handle) + { + DPRINT1("IntCreateCompatibleBitmap() failed!\n"); return NULL; + } + /* The palette must also match the given data */ Surface = SURFACE_ShareLockSurface(handle); ASSERT(Surface); @@ -1430,6 +1462,7 @@ NtGdiCreateDIBitmapInternal( safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB); if(!safeBits) { + DPRINT1("Failed to allocate %lu bytes\n", cjMaxBits); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } @@ -1452,6 +1485,7 @@ NtGdiCreateDIBitmapInternal( if(!NT_SUCCESS(Status)) { + DPRINT1("Got an exception! pjInit = %p\n", pjInit); SetLastNtError(Status); goto cleanup; } @@ -1498,6 +1532,7 @@ GreCreateDIBitmapInternal( hdcDest = NtGdiCreateCompatibleDC(0); if(!hdcDest) { + DPRINT1("NtGdiCreateCompatibleDC failed\n"); return NULL; } } @@ -1509,6 +1544,7 @@ GreCreateDIBitmapInternal( Dc = DC_LockDc(hdcDest); if (!Dc) { + DPRINT1("Failed to lock hdcDest %p\n", hdcDest); EngSetLastError(ERROR_INVALID_HANDLE); return NULL; }