From b011aff53bc4b6276aa55bc004677ff03cf0bce4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Thu, 29 Jul 2010 18:01:14 +0000 Subject: [PATCH] [WIN32K] - rewrite UserLoadImage so that it uses information from the BITMAPFILEHEADER and probes the right buffer. svn path=/branches/reactos-yarotows/; revision=48364 --- subsystems/win32/win32k/include/dib.h | 3 + subsystems/win32/win32k/misc/file.c | 64 ++++++++++------- subsystems/win32/win32k/objects/dibobj.c | 90 +++++++++++++++++++++--- 3 files changed, 124 insertions(+), 33 deletions(-) diff --git a/subsystems/win32/win32k/include/dib.h b/subsystems/win32/win32k/include/dib.h index 16d17f44b4a..9a2554168cc 100644 --- a/subsystems/win32/win32k/include/dib.h +++ b/subsystems/win32/win32k/include/dib.h @@ -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); \ No newline at end of file diff --git a/subsystems/win32/win32k/misc/file.c b/subsystems/win32/win32k/misc/file.c index 365b09933c7..87df7d3915e 100644 --- a/subsystems/win32/win32k/misc/file.c +++ b/subsystems/win32/win32k/misc/file.c @@ -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) + _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)) + { + DPRINT1("Bad File?\n"); + goto leave; + } + + if (pbmfh->bfType == 0x4D42 /* 'BM' */) { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END + /* Could be BITMAPCOREINFO */ + BITMAPINFO* pConvertedInfo; - if (NT_SUCCESS(Status)) - { - cjInfoSize = bmiLocal.bmiHeader.bV5Size + - bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD); - 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 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); diff --git a/subsystems/win32/win32k/objects/dibobj.c b/subsystems/win32/win32k/objects/dibobj.c index d61b36f7598..5741113544e 100644 --- a/subsystems/win32/win32k/objects/dibobj.c +++ b/subsystems/win32/win32k/objects/dibobj.c @@ -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; ibmiColors[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 */ -- 2.17.1