- rewrite UserLoadImage so that it uses information from the BITMAPFILEHEADER and probes the right buffer.

svn path=/branches/reactos-yarotows/; revision=48364
This commit is contained in:
Jérôme Gardou 2010-07-29 18:01:14 +00:00
parent fa93ac8293
commit b011aff53b
3 changed files with 125 additions and 34 deletions

View file

@ -18,3 +18,6 @@ DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi);
HPALETTE FASTCALL
BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType);
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);

View file

@ -157,14 +157,12 @@ HBITMAP
NTAPI
UserLoadImage(PCWSTR pwszName)
{
NTSTATUS Status;
NTSTATUS Status = STATUS_SUCCESS;
HANDLE hFile, hSection;
BITMAPFILEHEADER *pbmfh;
LPBITMAPINFO pbmi;
ULONG cjInfoSize;
PVOID pvBits;
HBITMAP hbmp = 0;
BITMAPV5INFO bmiLocal;
DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
@ -194,40 +192,58 @@ UserLoadImage(PCWSTR pwszName)
/* Get a pointer to the BITMAPINFO */
pbmi = (LPBITMAPINFO)(pbmfh + 1);
/* Create a normalized local BITMAPINFO */
_SEH2_TRY
{
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal,
pbmi,
DIB_RGB_COLORS,
0);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
_SEH2_TRY
{
ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
ProbeForRead(pbmfh, pbmfh->bfSize, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (NT_SUCCESS(Status))
if(!NT_SUCCESS(Status))
{
DPRINT1("Bad File?\n");
goto leave;
}
if (pbmfh->bfType == 0x4D42 /* 'BM' */)
{
cjInfoSize = bmiLocal.bmiHeader.bV5Size +
bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD);
pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
/* Could be BITMAPCOREINFO */
BITMAPINFO* pConvertedInfo;
pvBits = (PVOID)((PCHAR)pbmi + pbmfh->bfOffBits);
pConvertedInfo = DIB_ConvertBitmapInfo(pbmi, DIB_RGB_COLORS);
if(!pConvertedInfo)
{
DPRINT1("Unable to convert the bitmap Info\n");
goto leave;
}
// FIXME: use Gre... so that the BITMAPINFO doesn't get probed
hbmp = NtGdiCreateDIBitmapInternal(NULL,
bmiLocal.bmiHeader.bV5Width,
bmiLocal.bmiHeader.bV5Height,
pConvertedInfo->bmiHeader.biWidth,
pConvertedInfo->bmiHeader.biHeight,
CBM_INIT,
pvBits,
pbmi,
DIB_RGB_COLORS,
bmiLocal.bmiHeader.bV5Size,
bmiLocal.bmiHeader.bV5SizeImage,
pConvertedInfo->bmiHeader.biSize,
pConvertedInfo->bmiHeader.biSizeImage,
0,
0);
}
DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi);
}
else
{
DPRINT1("Unknown file type!\n");
}
leave:
/* Unmap our section, we don't need it anymore */
ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);

View file

@ -674,18 +674,12 @@ NtGdiGetDIBitsInternal(
/* We need a BITMAPINFO to create a DIB, but we have to fill
* the BITMAPCOREINFO we're provided */
pbmci = (BITMAPCOREINFO*)Info;
Info = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD), TAG_DIB);
Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
if(Info == NULL)
{
DPRINT1("Error, could not allocate another BITMAPINFO!\n");
DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
return 0;
}
RtlZeroMemory(Info, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
Info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Info->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
Info->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
Info->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
Info->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
rgbQuads = Info->bmiColors;
}
@ -1050,7 +1044,7 @@ done:
if(pDC) DC_UnlockDc(pDC);
if(psurf) SURFACE_UnlockSurface(psurf);
if(pbmci) ExFreePoolWithTag(Info, TAG_DIB);
if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
return ScanLines;
}
@ -2077,4 +2071,82 @@ ProbeAndConvertToBitmapV5Info(
return STATUS_SUCCESS;
}
/* 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)
{
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 ;
}
/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
VOID
FASTCALL
DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
{
if(converted != orig)
ExFreePoolWithTag(converted, TAG_DIB);
}
/* EOF */