- 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 HPALETTE FASTCALL
BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType); 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 NTAPI
UserLoadImage(PCWSTR pwszName) UserLoadImage(PCWSTR pwszName)
{ {
NTSTATUS Status; NTSTATUS Status = STATUS_SUCCESS;
HANDLE hFile, hSection; HANDLE hFile, hSection;
BITMAPFILEHEADER *pbmfh; BITMAPFILEHEADER *pbmfh;
LPBITMAPINFO pbmi; LPBITMAPINFO pbmi;
ULONG cjInfoSize;
PVOID pvBits; PVOID pvBits;
HBITMAP hbmp = 0; HBITMAP hbmp = 0;
BITMAPV5INFO bmiLocal;
DPRINT("Enter UserLoadImage(%ls)\n", pwszName); DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
@ -194,40 +192,58 @@ UserLoadImage(PCWSTR pwszName)
/* Get a pointer to the BITMAPINFO */ /* Get a pointer to the BITMAPINFO */
pbmi = (LPBITMAPINFO)(pbmfh + 1); pbmi = (LPBITMAPINFO)(pbmfh + 1);
/* Create a normalized local BITMAPINFO */ _SEH2_TRY
_SEH2_TRY {
{ ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, ProbeForRead(pbmfh, pbmfh->bfSize, 1);
pbmi, }
DIB_RGB_COLORS, _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
0); {
} Status = _SEH2_GetExceptionCode();
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) }
{ _SEH2_END
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 + /* Could be BITMAPCOREINFO */
bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD); BITMAPINFO* pConvertedInfo;
pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
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 // FIXME: use Gre... so that the BITMAPINFO doesn't get probed
hbmp = NtGdiCreateDIBitmapInternal(NULL, hbmp = NtGdiCreateDIBitmapInternal(NULL,
bmiLocal.bmiHeader.bV5Width, pConvertedInfo->bmiHeader.biWidth,
bmiLocal.bmiHeader.bV5Height, pConvertedInfo->bmiHeader.biHeight,
CBM_INIT, CBM_INIT,
pvBits, pvBits,
pbmi, pbmi,
DIB_RGB_COLORS, DIB_RGB_COLORS,
bmiLocal.bmiHeader.bV5Size, pConvertedInfo->bmiHeader.biSize,
bmiLocal.bmiHeader.bV5SizeImage, pConvertedInfo->bmiHeader.biSizeImage,
0, 0,
0); 0);
}
DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi);
}
else
{
DPRINT1("Unknown file type!\n");
}
leave:
/* Unmap our section, we don't need it anymore */ /* Unmap our section, we don't need it anymore */
ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh); ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);

View file

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