diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c
index 438521f69e9..5acd50e7dbb 100644
--- a/win32ss/gdi/gdi32/objects/bitmap.c
+++ b/win32ss/gdi/gdi32/objects/bitmap.c
@@ -669,6 +669,9 @@ SetDIBitsToDevice(
 
     if (!ScanLines || !lpbmi || !Bits)
         return 0;
+     
+     if (StartScan > ScanLines)
+        return 0;
 
     if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
         return 0;
@@ -729,29 +732,33 @@ SetDIBitsToDevice(
         ScanLines = pConvertedInfo->bmiHeader.biHeight;
     }
 
-    cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);
+    cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, YSrc + min(ScanLines, abs(Height)));
 
     pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
     if (pvSafeBits)
     {
         _SEH2_TRY
         {
-            RtlCopyMemory(pvSafeBits, Bits, cjBmpScanSize);
+            RtlCopyMemory(pvSafeBits, (LPBYTE)Bits, cjBmpScanSize);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
             Hit = TRUE;
         }
-        _SEH2_END
+            _SEH2_END
 
         if (Hit)
         {
             // We don't die, we continue on with a allocated safe pointer to kernel
             // space.....
-            DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
-                pConvertedInfo, Bits, cjBmpScanSize);
+            DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u Height: %u ScanLines: %u.\n",
+                pConvertedInfo, pvSafeBits, cjBmpScanSize, Height, ScanLines);
+
+            LinesCopied = 0;
+            goto Exit;
         }
-        DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize);
+        else
+            DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize);
     }
 
     if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
@@ -767,7 +774,7 @@ SetDIBitsToDevice(
      pConvertedInfo->bmiHeader.biCompression  == BI_PNG )) )*/
     {
         LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc,
-            StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
+            StartScan, ScanLines, (LPBYTE) Bits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
             cjBmpScanSize, ConvertedInfoSize,
             TRUE,
             NULL);
diff --git a/win32ss/gdi/ntgdi/dibobj.c b/win32ss/gdi/ntgdi/dibobj.c
index 6c6dd53e941..3f64a969aa3 100644
--- a/win32ss/gdi/ntgdi/dibobj.c
+++ b/win32ss/gdi/ntgdi/dibobj.c
@@ -495,7 +495,16 @@ NtGdiSetDIBitsToDeviceInternal(
     BOOL bResult;
 
     if (!Bits) return 0;
+    
+    ScanLines = min(abs(Height),ScanLines) + YSrc;
 
+    if (ScanLines == 0)
+    {
+        DPRINT1("ScanLines == 0\n");
+        ret = 0;
+        goto Exit;
+    }
+    
     pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
     if (!pbmiSafe) return 0;
 
@@ -513,14 +522,6 @@ NtGdiSetDIBitsToDeviceInternal(
     }
     _SEH2_END;
 
-    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
-    if (ScanLines == 0)
-    {
-        DPRINT1("ScanLines == 0\n");
-        ret = 0;
-        goto Exit;
-    }
-
     pDC = DC_LockDc(hDC);
     if (!pDC)
     {
@@ -561,7 +562,7 @@ NtGdiSetDIBitsToDeviceInternal(
     //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
     hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
-                                      ScanLines,
+                                      ScanLines + YSrc,
                                       0,
                                       BitmapFormat(bmi->bmiHeader.biBitCount,
                                                    bmi->bmiHeader.biCompression),
@@ -638,9 +639,9 @@ NtGdiSetDIBitsToDeviceInternal(
     pDestSurf = &pSurf->SurfObj;
 
     /* Copy the bits */
-    DPRINT("BitsToDev with rcDest=(%d|%d) (%d|%d), ptSource=(%d|%d) w=%d h=%d\n",
+    DPRINT1("BitsToDev with rcDest=(%d|%d) (%d|%d), ptSource=(%d|%d) w=%d h=%d ScanLines=%lu Height=%lu Width=%lu pDC->ptlDCOrig.x=%lu pDC->ptlDCOrig.y=%lu  bmi->bmiHeader.biCompression=%lu XSrc=%d YSrc=%d Width=%lu Height=%lu StartScan=%lu XDest=%d YDest=%d\n",
            rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
-           ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
+           ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy,ScanLines,Height,Width,pDC->ptlDCOrig.x,pDC->ptlDCOrig.y, bmi->bmiHeader.biCompression,XSrc,YSrc,Width,Height,StartScan,XDest,YDest);
 
     /* This fixes the large Google text on Google.com from being upside down */
     if (rcDest.top > rcDest.bottom)
@@ -649,6 +650,17 @@ NtGdiSetDIBitsToDeviceInternal(
         ptSource.y -= SourceSize.cy;
     }
 
+    DWORD ROP4 = ROP4_NOOP;
+
+    if(pMaskSurf)
+        ROP4 = ROP4_MASK;
+    else {
+        if(rcDest.top == ptSource.y && rcDest.bottom == SourceSize.cy)
+            ROP4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCAND);
+        else
+            ROP4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY);
+    }
+
     bResult = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
                           pMaskSurf,
@@ -659,7 +671,7 @@ NtGdiSetDIBitsToDeviceInternal(
                           pMaskSurf ? &ptSource : NULL,
                           NULL,
                           NULL,
-                          pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+                          ROP4);
 
     /* Cleanup EXLATEOBJ */
     EXLATEOBJ_vCleanup(&exlo);
@@ -1910,6 +1922,7 @@ DIB_CreateDIBSection(
         return (HBITMAP)NULL;
     }
 
+
     effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
     bm.bmType = 0;
     bm.bmWidth = bi->biWidth;
