Author: tkreuzer
Date: Wed May 16 14:13:26 2012
New Revision: 56593
URL:
http://svn.reactos.org/svn/reactos?rev=56593&view=rev
Log:
[WIN32K]
- Mark bitmap as API bitmap in NtGdiCreateDIBSection
- Mark palette as DIB section palette in NtGdiCreateDIBSection
- Set biXPelsPerMeter to 0 instead of using the bitmap dimentions
- Check BITMAPINFO parameters in GreGetDIBits
- Handle case when requested bit depth doesn't match actual one in GreGetDIBits
- Use maximum BITMAPINFO size in NtGdiGetDIBitsInternal
- Verify header size in NtGdiGetDIBitsInternal
- Misc code improvements
Modified:
branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c
Modified: branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c
URL:
http://svn.reactos.org/svn/reactos/branches/dib_rewrite/win32ss/gdi/ntgdi/d…
==============================================================================
--- branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c [iso-8859-1] (original)
+++ branches/dib_rewrite/win32ss/gdi/ntgdi/dibitmap.c [iso-8859-1] Wed May 16 14:13:26
2012
@@ -530,6 +530,12 @@
/* Return the base address if requested */
if (ppvBits) *ppvBits = psurfDIBSection->SurfObj.pvBits;
+ /* Mark as API bitmap */
+ psurfDIBSection->flags |= API_BITMAP;
+
+ /* Mark the palette as a DIB section palette */
+ psurfDIBSection->ppal->flFlags |= PAL_DIBSECTION;
+
/* Save the handle and unlock the bitmap */
hbmp = psurfDIBSection->BaseObject.hHmgr;
SURFACE_UnlockSurface(psurfDIBSection);
@@ -697,7 +703,7 @@
HANDLE hSecure;
HBITMAP hbmp;
-__debugbreak();
+//__debugbreak();
if (fInit & CBM_INIT)
{
@@ -772,24 +778,16 @@
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biCompression = SURFACE_iCompression(psurf);
pbmi->bmiHeader.biSizeImage = psurf->SurfObj.cjBits;
- pbmi->bmiHeader.biXPelsPerMeter = psurf->sizlDim.cx;
- pbmi->bmiHeader.biYPelsPerMeter = psurf->sizlDim.cy;
-
- /* Check if the caller requests a color table */
- if (pbmi->bmiHeader.biBitCount != 0)
- {
- /* Synthesize a color table */
- __debugbreak();
- }
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biBitCount = gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
+
+ /* Set the number of colors */
+ if (pbmi->bmiHeader.biBitCount <= 8)
+ pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
else
- {
- /* Just return the bit depth */
- pbmi->bmiHeader.biBitCount =
- gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
- }
-
- /* Set the number of colors */
- pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
+ pbmi->bmiHeader.biClrUsed = 0;
+
pbmi->bmiHeader.biClrImportant = pbmi->bmiHeader.biClrUsed;
if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
@@ -828,12 +826,31 @@
_In_ UINT cjMaxInfo)
{
PDC pdc;
- PSURFACE psurf;
+ PSURFACE psurfBmp;
ULONG iCompression, cBitsPixel, cjLine;
LONG lDeltaDst;
PBYTE pjSrc;
INT iResult = 0;
+ /* Check bitmap info */
+ if ((pbmi->bmiHeader.biCompression >= BI_JPEG) ||
+ (pbmi->bmiHeader.biWidth <= 0) ||
+ (pbmi->bmiHeader.biHeight == 0))
+ {
+ return 0;
+ }
+
+ /* Check if we have a proper bit count value */
+ if ((pbmi->bmiHeader.biBitCount != 1) &&
+ (pbmi->bmiHeader.biBitCount != 4) &&
+ (pbmi->bmiHeader.biBitCount != 8) &&
+ (pbmi->bmiHeader.biBitCount != 16) &&
+ (pbmi->bmiHeader.biBitCount != 24) &&
+ (pbmi->bmiHeader.biBitCount != 32))
+ {
+ return 0;
+ }
+
/* Lock the DC */
pdc = DC_LockDc(hdc);
if (!pdc)
@@ -842,35 +859,56 @@
}
/* Lock the bitmap */
- psurf = SURFACE_ShareLockSurface(hbm);
- if (!psurf)
- {
-
+ psurfBmp = SURFACE_ShareLockSurface(hbm);
+ if (!psurfBmp)
+ {
+ DC_UnlockDc(pdc);
return 0;
}
+ /* Check if the bitmap is compatile with the dc */
+ if (!DC_bIsBitmapCompatible(pdc, psurfBmp))
+ {
+ /* Dereference the bitmap, unlock the DC and fail. */
+ SURFACE_ShareUnlockSurface(psurfBmp);
+ DC_UnlockDc(pdc);
+ return 0;
+ }
+
+ /* Calculate width of one dest line */
+ lDeltaDst = WIDTH_BYTES_ALIGN32(pbmi->bmiHeader.biWidth,
+ pbmi->bmiHeader.biBitCount);
+
+ /* Calculate the image size */
+ pbmi->bmiHeader.biSizeImage = lDeltaDst * abs(pbmi->bmiHeader.biHeight);
+
+ /* Set planes to 1 */
+ pbmi->bmiHeader.biPlanes = 1;
+
/* Check if there is anything to do */
- if (iStartScan < (ULONG)psurf->SurfObj.sizlBitmap.cy)
- {
+ if (pjBits == NULL)
+ {
+ /* Nothing to copy, but we had success */
+ iResult = 1;
+ }
+ else if (iStartScan < (ULONG)psurfBmp->SurfObj.sizlBitmap.cy)
+ {
+ /* Calculate the maximum number of scan lines to be copied */
+ cScans = min(cScans, psurfBmp->SurfObj.sizlBitmap.cy - iStartScan);
+ cScans = min(cScans, cjMaxBits / lDeltaDst);
+
/* Get the bit depth of the bitmap */
- cBitsPixel = gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
+ cBitsPixel = gajBitsPerFormat[psurfBmp->SurfObj.iBitmapFormat];
/* Get the compression of the bitmap */
- iCompression = SURFACE_iCompression(psurf);
+ iCompression = SURFACE_iCompression(psurfBmp);
/* Check if the requested format matches the actual one */
if ((cBitsPixel == pbmi->bmiHeader.biBitCount) &&
(iCompression == pbmi->bmiHeader.biCompression))
{
- /* Calculate width of one dest line */
- lDeltaDst = WIDTH_BYTES_ALIGN32(pbmi->bmiHeader.biWidth, cBitsPixel);
-
- /* Calculate the maximum number of scan lines to be copied */
- cScans = min(cScans, psurf->SurfObj.sizlBitmap.cy - iStartScan);
- cScans = min(cScans, cjMaxBits / lDeltaDst);
-
/* Calculate the maximum length of a line */
- cjLine = min(lDeltaDst, abs(psurf->SurfObj.lDelta));
+ cjLine = min(lDeltaDst, abs(psurfBmp->SurfObj.lDelta));
/* Check for top-down bitmaps */
if (pbmi->bmiHeader.biHeight > 0)
@@ -881,8 +919,8 @@
}
/* Calculate the start address from where to copy */
- pjSrc = psurf->SurfObj.pvScan0;
- pjSrc += iStartScan * psurf->SurfObj.lDelta;
+ pjSrc = psurfBmp->SurfObj.pvScan0;
+ pjSrc += iStartScan * psurfBmp->SurfObj.lDelta;
/* Save number of copied scans */
iResult = cScans;
@@ -894,7 +932,7 @@
RtlCopyMemory(pjBits, pjSrc, cjLine);
/* go to the next scan line */
- pjSrc += psurf->SurfObj.lDelta;
+ pjSrc += psurfBmp->SurfObj.lDelta;
pjBits += lDeltaDst;
}
@@ -904,7 +942,42 @@
}
else
{
- __debugbreak();
+ RECTL rclDest = {0, 0, pbmi->bmiHeader.biWidth - 1, cScans -1};
+ POINTL ptlSrc = {0, iStartScan};
+ EXLATEOBJ exlo;
+ PSURFACE psurfDIB;
+
+ /* Create a DIB surface */
+ psurfDIB = DibCreateDIBSurface(pbmi,
+ pdc,
+ iUsage,
+ 0,
+ pjBits,
+ cjMaxBits);
+ if (psurfDIB)
+ {
+ /* Initialize XLATEOBJ */
+ EXLATEOBJ_vInitialize(&exlo,
+ psurfDIB->ppal,
+ psurfBmp->ppal,
+ RGB(0xff, 0xff, 0xff),
+ pdc->pdcattr->crBackgroundClr,
+ pdc->pdcattr->crForegroundClr);
+
+ EngCopyBits(&psurfDIB->SurfObj,
+ &psurfBmp->SurfObj,
+ NULL,
+ &exlo.xlo,
+ &rclDest,
+ &ptlSrc);
+
+ /* Cleanup */
+ EXLATEOBJ_vCleanup(&exlo);
+ GDIOBJ_vDeleteObject(&psurfDIB->BaseObject);
+
+ /* Return the number of copied scan lnes */
+ iResult = cScans;
+ }
}
}
else
@@ -913,9 +986,8 @@
iResult = 0;
}
- /* Unlock the bitmap surface */
- SURFACE_ShareUnlockSurface(psurf);
-
+ /* Unlock the bitmap surface and the DC */
+ SURFACE_ShareUnlockSurface(psurfBmp);
DC_UnlockDc(pdc);
return iResult;
@@ -936,7 +1008,10 @@
{
PBITMAPINFO pbmi;
HANDLE hSecure;
- INT iResult;
+ INT iResult = 0;
+
+ /* Check for bad iUsage */
+ if (iUsage > 2) return 0;
/* Check if the size of the bitmap info is large enough */
if (cjMaxInfo < sizeof(BITMAPINFOHEADER))
@@ -944,37 +1019,53 @@
return 0;
}
+ /* Use maximum size */
+ cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
+
+ /* Allocate a buffer the bitmapinfo */
+ pbmi = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, GDITAG_BITMAPINFO);
+ if (!pbmi)
+ {
+ /* Fail */
+ return 0;
+ }
+
+ /* Use SEH */
+ _SEH2_TRY
+ {
+ /* Probe and copy the BITMAPINFO */
+ ProbeForWrite(pbmiUser, cjMaxInfo, 1);
+ RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(goto cleanup;)
+ }
+ _SEH2_END;
+
+ /* Check if the header size is large enough */
+ if ((pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) ||
+ (pbmi->bmiHeader.biSize > cjMaxInfo))
+ {
+ iResult = 0;
+ goto cleanup;
+ }
+
+ /* Check if the caller provided bitmap bits */
if (pjBits)
{
+ /* Secure the user mode memory */
hSecure = EngSecureMem(pjBits, cjMaxBits);
if (!hSecure)
{
- return 0;
- }
- }
-
- pbmi = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, GDITAG_BITMAPINFO);
- if (!pbmi)
- {
- __debugbreak();
- }
-
- _SEH2_TRY
- {
- ProbeForWrite(pbmiUser, cjMaxInfo, 1);
- RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- __debugbreak();
- }
- _SEH2_END;
-
- // FIXME: check pbmi size
-
- if (pjBits)
- {
- /* Call the internal functiomn */
+ goto cleanup;
+ }
+ }
+
+ /* Check if the bitcount member is initialized */
+ if (pbmi->bmiHeader.biBitCount != 0)
+ {
+ /* Call the internal function */
iResult = GreGetDIBits(hdc,
hbm,
iStartScan,
@@ -985,23 +1076,35 @@
cjMaxBits,
cjMaxInfo);
}
+ else if (pjBits == NULL)
+ {
+ /* Just get the BITMAPINFO */
+ iResult = GreGetDIBitmapInfo(hbm, pbmi, iUsage, cjMaxInfo);
+ }
else
{
- iResult = GreGetDIBitmapInfo(hbm, pbmi, iUsage, cjMaxInfo);
- }
-
- _SEH2_TRY
- {
- RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- }
- _SEH2_END;
-
-
+ /* This combination is not valid */
+ iResult = 0;
+ }
+
+ /* Check for success */
+ if (iResult)
+ {
+ /* Use SEH to copy back to user mode */
+ _SEH2_TRY
+ {
+ /* Buffer is already probed, copy the data back */
+ RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+ }
+
+cleanup:
+ if (hSecure) EngUnsecureMem(hSecure);
ExFreePoolWithTag(pbmi, GDITAG_BITMAPINFO);
-
return iResult;
}
@@ -1269,7 +1372,7 @@
BITMAPINFO*
FASTCALL
-DIB_ConvertBitmapInfo(CONST BITMAPINFO* pbmi, DWORD Usage)
+_DIB_ConvertBitmapInfo(CONST BITMAPINFO* pbmi, DWORD Usage)
{
__debugbreak();
return 0;
@@ -1277,7 +1380,7 @@
VOID
FASTCALL
-DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+_DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
{
if(converted != orig)
ExFreePoolWithTag(converted, TAG_DIB);