mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[NTGDI][GDI32] Icon fixes for Office 2000, VB6, and Hoyle Cards (#5227)
Many thanks for Simone Lombardo for pointing to the code needing attention and providing a working proof-of-concept solution. CORE-12377 CORE-18084 CORE-13889
This commit is contained in:
parent
38560761ce
commit
12e1919e5e
|
@ -5,6 +5,52 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* Copied from win32ss/gdi/eng/surface.c */
|
||||||
|
ULONG
|
||||||
|
FASTCALL
|
||||||
|
BitmapFormat(ULONG cBits, ULONG iCompression)
|
||||||
|
{
|
||||||
|
switch (iCompression)
|
||||||
|
{
|
||||||
|
case BI_RGB:
|
||||||
|
/* Fall through */
|
||||||
|
case BI_BITFIELDS:
|
||||||
|
if (cBits <= 1) return BMF_1BPP;
|
||||||
|
if (cBits <= 4) return BMF_4BPP;
|
||||||
|
if (cBits <= 8) return BMF_8BPP;
|
||||||
|
if (cBits <= 16) return BMF_16BPP;
|
||||||
|
if (cBits <= 24) return BMF_24BPP;
|
||||||
|
if (cBits <= 32) return BMF_32BPP;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case BI_RLE4:
|
||||||
|
return BMF_4RLE;
|
||||||
|
|
||||||
|
case BI_RLE8:
|
||||||
|
return BMF_8RLE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copied from win32ss/gdi/eng/surface.c */
|
||||||
|
UCHAR
|
||||||
|
gajBitsPerFormat[11] =
|
||||||
|
{
|
||||||
|
0, /* 0: unused */
|
||||||
|
1, /* 1: BMF_1BPP */
|
||||||
|
4, /* 2: BMF_4BPP */
|
||||||
|
8, /* 3: BMF_8BPP */
|
||||||
|
16, /* 4: BMF_16BPP */
|
||||||
|
24, /* 5: BMF_24BPP */
|
||||||
|
32, /* 6: BMF_32BPP */
|
||||||
|
4, /* 7: BMF_4RLE */
|
||||||
|
8, /* 8: BMF_8RLE */
|
||||||
|
0, /* 9: BMF_JPEG */
|
||||||
|
0, /* 10: BMF_PNG */
|
||||||
|
};
|
||||||
|
|
||||||
// From Yuan, ScanLineSize = (Width * bitcount + 31)/32
|
// From Yuan, ScanLineSize = (Width * bitcount + 31)/32
|
||||||
#define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
|
#define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
|
||||||
|
|
||||||
|
@ -577,6 +623,9 @@ SetDIBits(
|
||||||
INT LinesCopied = 0;
|
INT LinesCopied = 0;
|
||||||
BOOL newDC = FALSE;
|
BOOL newDC = FALSE;
|
||||||
|
|
||||||
|
if (fuColorUse != DIB_RGB_COLORS && fuColorUse != DIB_PAL_COLORS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP))
|
if (!lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -590,6 +639,16 @@ SetDIBits(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpbmi->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
|
{
|
||||||
|
DWORD *masks = (DWORD *)lpbmi->bmiColors;
|
||||||
|
if (!masks[0] || !masks[1] || !masks[2])
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap.
|
hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap.
|
||||||
SavehDC = hDCc;
|
SavehDC = hDCc;
|
||||||
if (!hDCc) // No DC associated with bitmap, Clone or Create one.
|
if (!hDCc) // No DC associated with bitmap, Clone or Create one.
|
||||||
|
@ -666,10 +725,31 @@ SetDIBitsToDevice(
|
||||||
UINT cjBmpScanSize = 0;
|
UINT cjBmpScanSize = 0;
|
||||||
BOOL Hit = FALSE;
|
BOOL Hit = FALSE;
|
||||||
PVOID pvSafeBits = (PVOID) Bits;
|
PVOID pvSafeBits = (PVOID) Bits;
|
||||||
|
UINT bmiHeight;
|
||||||
|
BOOL top_down;
|
||||||
|
INT src_y = 0;
|
||||||
|
ULONG iFormat, cBitsPixel, cjBits, cjWidth;
|
||||||
|
|
||||||
|
#define MaxScanLines 1000
|
||||||
|
#define MaxHeight 2000
|
||||||
|
#define MaxSourceHeight 2000
|
||||||
|
#define IS_ALIGNED(Pointer, Alignment) \
|
||||||
|
(((ULONG_PTR)(void *)(Pointer)) % (Alignment) == 0)
|
||||||
|
|
||||||
if (!ScanLines || !lpbmi || !Bits)
|
if (!ScanLines || !lpbmi || !Bits)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
DPRINT("ScanLines %d Height %d Width %d biHeight %d biWidth %d\n"
|
||||||
|
" lpbmi '%p' ColorUse '%d' SizeImage '%d' StartScan %d\n"
|
||||||
|
" biCompression '%d' biBitCount '%d'\n",
|
||||||
|
ScanLines, Height, Width, lpbmi->bmiHeader.biHeight,
|
||||||
|
lpbmi->bmiHeader.biWidth, lpbmi, ColorUse,
|
||||||
|
lpbmi->bmiHeader.biSizeImage, StartScan,
|
||||||
|
lpbmi->bmiHeader.biCompression, lpbmi->bmiHeader.biBitCount);
|
||||||
|
|
||||||
|
if (lpbmi->bmiHeader.biWidth < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
|
if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -677,6 +757,91 @@ SetDIBitsToDevice(
|
||||||
if (!pConvertedInfo)
|
if (!pConvertedInfo)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (ScanLines > MaxScanLines)
|
||||||
|
{
|
||||||
|
LinesCopied = 0;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bmiHeight = abs(pConvertedInfo->bmiHeader.biHeight);
|
||||||
|
top_down = (pConvertedInfo->bmiHeader.biHeight < 0);
|
||||||
|
if ((StartScan > bmiHeight) && (ScanLines > bmiHeight))
|
||||||
|
{
|
||||||
|
DPRINT("Returning ScanLines of '%d'\n", ScanLines);
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pConvertedInfo->bmiHeader.biHeight == 0)
|
||||||
|
{
|
||||||
|
LinesCopied = 0;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_ALIGNED(Bits, 2) && (ScanLines > Height))
|
||||||
|
{
|
||||||
|
LinesCopied = 0;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Below code modeled after Wine's nulldrv_SetDIBitsToDevice */
|
||||||
|
if (StartScan <= YSrc + bmiHeight)
|
||||||
|
{
|
||||||
|
if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) ||
|
||||||
|
(pConvertedInfo->bmiHeader.biCompression == BI_RLE4))
|
||||||
|
{
|
||||||
|
StartScan = 0;
|
||||||
|
ScanLines = bmiHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (StartScan >= bmiHeight)
|
||||||
|
{
|
||||||
|
LinesCopied = 0;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
if (!top_down && ScanLines > bmiHeight - StartScan)
|
||||||
|
{
|
||||||
|
ScanLines = bmiHeight - StartScan;
|
||||||
|
}
|
||||||
|
src_y = StartScan + ScanLines - (YSrc + Height);
|
||||||
|
if (!top_down)
|
||||||
|
{
|
||||||
|
/* get rid of unnecessary lines */
|
||||||
|
if ((src_y < 0 || src_y >= (INT)ScanLines) &&
|
||||||
|
pConvertedInfo->bmiHeader.biCompression != BI_BITFIELDS)
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
if (YDest >= 0)
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines + StartScan;
|
||||||
|
ScanLines -= src_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines - src_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (src_y < 0 || src_y >= (INT)ScanLines)
|
||||||
|
{
|
||||||
|
if (lpbmi->bmiHeader.biHeight < 0 &&
|
||||||
|
StartScan > MaxScanLines)
|
||||||
|
{
|
||||||
|
ScanLines = lpbmi->bmiHeader.biHeight - StartScan;
|
||||||
|
}
|
||||||
|
DPRINT("Returning ScanLines of '%d'\n", ScanLines);
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE_METADC(INT,
|
HANDLE_METADC(INT,
|
||||||
SetDIBitsToDevice,
|
SetDIBitsToDevice,
|
||||||
0,
|
0,
|
||||||
|
@ -742,12 +907,19 @@ SetDIBitsToDevice(
|
||||||
{
|
{
|
||||||
Hit = TRUE;
|
Hit = TRUE;
|
||||||
}
|
}
|
||||||
_SEH2_END
|
_SEH2_END;
|
||||||
|
|
||||||
if (Hit)
|
if (Hit)
|
||||||
{
|
{
|
||||||
// We don't die, we continue on with a allocated safe pointer to kernel
|
// We don't die, we continue on with a allocated safe pointer to kernel
|
||||||
// space.....
|
// space.....
|
||||||
|
|
||||||
|
if (!IS_ALIGNED(Bits, 2)) // If both Read Exception and mis-aligned
|
||||||
|
{
|
||||||
|
LinesCopied = 0;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
|
DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
|
||||||
pConvertedInfo, Bits, cjBmpScanSize);
|
pConvertedInfo, Bits, cjBmpScanSize);
|
||||||
}
|
}
|
||||||
|
@ -761,6 +933,53 @@ SetDIBitsToDevice(
|
||||||
LinesCopied = 0;
|
LinesCopied = 0;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculation of ScanLines for NtGdiSetDIBitsToDeviceInternal */
|
||||||
|
if (YDest >= 0)
|
||||||
|
{
|
||||||
|
ScanLines = min(abs(Height), ScanLines);
|
||||||
|
if (YSrc > 0)
|
||||||
|
ScanLines += YSrc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScanLines = min(ScanLines,
|
||||||
|
abs(pConvertedInfo->bmiHeader.biHeight) - StartScan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (YDest >= 0 && YSrc > 0 && bmiHeight <= MaxHeight)
|
||||||
|
{
|
||||||
|
ScanLines += YSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find Format from lpbmi which is now pConvertedInfo */
|
||||||
|
iFormat = BitmapFormat(pConvertedInfo->bmiHeader.biBitCount,
|
||||||
|
pConvertedInfo->bmiHeader.biCompression);
|
||||||
|
|
||||||
|
/* Get bits per pixel from the format */
|
||||||
|
cBitsPixel = gajBitsPerFormat[iFormat];
|
||||||
|
|
||||||
|
cjWidth = WIDTH_BYTES_ALIGN32(pConvertedInfo->bmiHeader.biWidth, cBitsPixel);
|
||||||
|
|
||||||
|
/* Calculate the correct bitmap size in bytes */
|
||||||
|
if (!NT_SUCCESS(RtlULongMult(cjWidth, max(ScanLines, LinesCopied), &cjBits)))
|
||||||
|
{
|
||||||
|
DPRINT1("Overflow calculating size: cjWidth %lu, ScanLines %lu\n",
|
||||||
|
cjWidth, max(ScanLines, LinesCopied));
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the buffer is large enough */
|
||||||
|
if (pConvertedInfo->bmiHeader.biSizeImage < cjBits)
|
||||||
|
{
|
||||||
|
DPRINT("Buffer is too small, required: %lu, got %lu\n",
|
||||||
|
cjBits, pConvertedInfo->bmiHeader.biSizeImage);
|
||||||
|
if (pConvertedInfo->bmiHeader.biCompression == BI_RGB)
|
||||||
|
{
|
||||||
|
pConvertedInfo->bmiHeader.biSizeImage = cjBits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ( !pDc_Attr || // DC is Public
|
if ( !pDc_Attr || // DC is Public
|
||||||
ColorUse == DIB_PAL_COLORS ||
|
ColorUse == DIB_PAL_COLORS ||
|
||||||
|
@ -768,12 +987,47 @@ SetDIBitsToDevice(
|
||||||
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
|
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
|
||||||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
|
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
|
||||||
{
|
{
|
||||||
LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc,
|
LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest,
|
||||||
StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
|
Width, Height, XSrc, YSrc,
|
||||||
|
StartScan, ScanLines, (LPBYTE) pvSafeBits,
|
||||||
|
(LPBITMAPINFO) pConvertedInfo, ColorUse,
|
||||||
cjBmpScanSize, ConvertedInfoSize,
|
cjBmpScanSize, ConvertedInfoSize,
|
||||||
TRUE,
|
TRUE,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bmiHeight > MaxScanLines)
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (YDest < 0)
|
||||||
|
{
|
||||||
|
if (top_down)
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
else
|
||||||
|
LinesCopied = ScanLines - src_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pConvertedInfo->bmiHeader.biCompression == BI_RLE8 ||
|
||||||
|
pConvertedInfo->bmiHeader.biCompression == BI_RLE4)
|
||||||
|
{
|
||||||
|
LinesCopied = bmiHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pConvertedInfo->bmiHeader.biHeight < 0)
|
||||||
|
{
|
||||||
|
if (pConvertedInfo->bmiHeader.biHeight < -MaxSourceHeight ||
|
||||||
|
(YDest >= 0 && src_y < -ScanLines))
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines + src_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LinesCopied = ScanLines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
if (Bits != pvSafeBits)
|
if (Bits != pvSafeBits)
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
|
||||||
|
|
|
@ -518,7 +518,27 @@ NtGdiSetDIBitsToDeviceInternal(
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
|
DPRINT("StartScan %d ScanLines %d Bits %p bmi %p ColorUse %d\n"
|
||||||
|
" Height %d Width %d SizeImage %d\n"
|
||||||
|
" biHeight %d biWidth %d biBitCount %d\n"
|
||||||
|
" XSrc %d YSrc %d xDext %d yDest %d\n",
|
||||||
|
StartScan, ScanLines, Bits, bmi, ColorUse,
|
||||||
|
Height, Width, bmi->bmiHeader.biSizeImage,
|
||||||
|
bmi->bmiHeader.biHeight, bmi->bmiHeader.biWidth,
|
||||||
|
bmi->bmiHeader.biBitCount,
|
||||||
|
XSrc, YSrc, XDest, YDest);
|
||||||
|
|
||||||
|
if (YDest >= 0)
|
||||||
|
{
|
||||||
|
ScanLines = min(abs(Height), ScanLines);
|
||||||
|
if (YSrc > 0)
|
||||||
|
ScanLines += YSrc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
|
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
|
||||||
|
}
|
||||||
|
|
||||||
if (ScanLines == 0)
|
if (ScanLines == 0)
|
||||||
{
|
{
|
||||||
DPRINT1("ScanLines == 0\n");
|
DPRINT1("ScanLines == 0\n");
|
||||||
|
@ -562,6 +582,10 @@ NtGdiSetDIBitsToDeviceInternal(
|
||||||
|
|
||||||
SourceSize.cx = bmi->bmiHeader.biWidth;
|
SourceSize.cx = bmi->bmiHeader.biWidth;
|
||||||
SourceSize.cy = ScanLines;
|
SourceSize.cy = ScanLines;
|
||||||
|
if (YDest >= 0 && YSrc > 0)
|
||||||
|
{
|
||||||
|
ScanLines += YSrc;
|
||||||
|
}
|
||||||
|
|
||||||
//DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
|
//DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue