[WIN32SS][NTGDI] Improve UnsafeGetBitmapBits and NtGdiGetBitmapBits (#1308)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sun, 27 Jan 2019 06:51:33 +0000 (15:51 +0900)
committerGitHub <noreply@github.com>
Sun, 27 Jan 2019 06:51:33 +0000 (15:51 +0900)
CORE-15657

win32ss/gdi/ntgdi/bitmaps.c

index c0c5874..e003640 100644 (file)
@@ -496,7 +496,7 @@ NtGdiGetBitmapDimension(
 }
 
 
-VOID
+LONG
 FASTCALL
 UnsafeGetBitmapBits(
     PSURFACE psurf,
@@ -505,10 +505,10 @@ UnsafeGetBitmapBits(
 {
     PUCHAR pjDst, pjSrc;
     LONG lDeltaDst, lDeltaSrc;
-    ULONG nWidth, nHeight, cBitsPixel;
+    ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel;
 
     nWidth = psurf->SurfObj.sizlBitmap.cx;
-    nHeight = psurf->SurfObj.sizlBitmap.cy;
+    nHeight = labs(psurf->SurfObj.sizlBitmap.cy);
     cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
 
     /* Get pointers */
@@ -516,14 +516,33 @@ UnsafeGetBitmapBits(
     pjDst = pvBits;
     lDeltaSrc = psurf->SurfObj.lDelta;
     lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+    NT_ASSERT(labs(lDeltaSrc) >= lDeltaDst);
+
+    cbSrc = nHeight * labs(lDeltaSrc);
+    cbDst = nHeight * lDeltaDst;
+    Bytes = min(Bytes, cbDst);
 
-    while (nHeight--)
+    iSrc = iDst = 0;
+    for (Y = 0; Y < nHeight; Y++)
     {
+        if (iSrc + labs(lDeltaSrc) > cbSrc || iDst + lDeltaDst > Bytes)
+        {
+            LONG lDelta = min(cbSrc - iSrc, Bytes - iDst);
+            NT_ASSERT(lDelta >= 0);
+            RtlCopyMemory(pjDst, pjSrc, lDelta);
+            iDst += lDelta;
+            break;
+        }
+
         /* Copy one line */
         RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
         pjSrc += lDeltaSrc;
         pjDst += lDeltaDst;
+        iSrc += labs(lDeltaSrc);
+        iDst += lDeltaDst;
     }
+
+    return iDst;
 }
 
 LONG
@@ -570,8 +589,7 @@ NtGdiGetBitmapBits(
     _SEH2_TRY
     {
         ProbeForWrite(pUnsafeBits, cjBuffer, 1);
-        UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
-        ret = cjBuffer;
+        ret = UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {