[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dibobj.c
index a8e26cf..2dc749e 100644 (file)
@@ -32,27 +32,6 @@ static const RGBQUAD EGAColorsQuads[16] =
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
-static const RGBTRIPLE EGAColorsTriples[16] =
-{
-    /* rgbBlue, rgbGreen, rgbRed */
-    { 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x80 },
-    { 0x00, 0x80, 0x00 },
-    { 0x00, 0x80, 0x80 },
-    { 0x80, 0x00, 0x00 },
-    { 0x80, 0x00, 0x80 },
-    { 0x80, 0x80, 0x00 },
-    { 0x80, 0x80, 0x80 },
-    { 0xc0, 0xc0, 0xc0 },
-    { 0x00, 0x00, 0xff },
-    { 0x00, 0xff, 0x00 },
-    { 0x00, 0xff, 0xff },
-    { 0xff, 0x00, 0x00 },
-    { 0xff, 0x00, 0xff },
-    { 0xff, 0xff, 0x00 },
-    { 0xff, 0xff, 0xff }
-};
-
 static const RGBQUAD DefLogPaletteQuads[20] =   /* Copy of Default Logical Palette */
 {
     /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
@@ -78,31 +57,6 @@ static const RGBQUAD DefLogPaletteQuads[20] =   /* Copy of Default Logical Palet
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
-static const RGBQUAD DefLogPaletteTriples[20] =   /* Copy of Default Logical Palette */
-{
-    /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
-    { 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x80 },
-    { 0x00, 0x80, 0x00 },
-    { 0x00, 0x80, 0x80 },
-    { 0x80, 0x00, 0x00 },
-    { 0x80, 0x00, 0x80 },
-    { 0x80, 0x80, 0x00 },
-    { 0xc0, 0xc0, 0xc0 },
-    { 0xc0, 0xdc, 0xc0 },
-    { 0xf0, 0xca, 0xa6 },
-    { 0xf0, 0xfb, 0xff },
-    { 0xa4, 0xa0, 0xa0 },
-    { 0x80, 0x80, 0x80 },
-    { 0x00, 0x00, 0xf0 },
-    { 0x00, 0xff, 0x00 },
-    { 0x00, 0xff, 0xff },
-    { 0xff, 0x00, 0x00 },
-    { 0xff, 0x00, 0xff },
-    { 0xff, 0xff, 0x00 },
-    { 0xff, 0xff, 0xff }
-};
-
 PPALETTE
 NTAPI
 CreateDIBPalette(
@@ -375,6 +329,115 @@ cleanup:
     return result;
 }
 
+static
+HBITMAP
+IntGdiCreateMaskFromRLE(
+    DWORD Width,
+    DWORD Height,
+    ULONG Compression,
+    const BYTE* Bits,
+    DWORD BitsSize)
+{
+    HBITMAP Mask;
+    DWORD x, y;
+    SURFOBJ* SurfObj;
+    UINT i = 0;
+    BYTE Data, NumPixels, ToSkip;
+
+    ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
+
+    /* Create the bitmap */
+    Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
+    if (!Mask)
+        return NULL;
+
+    SurfObj = EngLockSurface((HSURF)Mask);
+    if (!SurfObj)
+    {
+        GreDeleteObject(Mask);
+        return NULL;
+    }
+    ASSERT(SurfObj->pvBits != NULL);
+
+    x = y = 0;
+
+    while (i < BitsSize)
+    {
+        NumPixels = Bits[i];
+        Data = Bits[i + 1];
+        i += 2;
+
+        if (NumPixels != 0)
+        {
+            if ((x + NumPixels) > Width)
+                NumPixels = Width - x;
+
+            if (NumPixels == 0)
+                continue;
+
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+            continue;
+        }
+
+        if (Data < 3)
+        {
+            switch (Data)
+            {
+                case 0:
+                    /* End of line */
+                    y++;
+                    if (y == Height)
+                        goto done;
+                    x = 0;
+                    break;
+                case 1:
+                    /* End of file */
+                    goto done;
+                case 2:
+                    /* Jump */
+                    if (i >= (BitsSize - 1))
+                        goto done;
+                    x += Bits[i];
+                    if (x > Width)
+                        x = Width;
+                    y += Bits[i + 1];
+                    if (y >= Height)
+                        goto done;
+                    i += 2;
+                    break;
+            }
+            /* Done for this run */
+            continue;
+        }
+
+        /* Embedded data into the RLE */
+        NumPixels = Data;
+        if (Compression == BI_RLE8)
+            ToSkip = NumPixels;
+        else
+            ToSkip = (NumPixels / 2) + (NumPixels & 1);
+
+        if ((i + ToSkip) > BitsSize)
+            goto done;
+        ToSkip = (ToSkip + 1) & ~1;
+
+        if ((x + NumPixels) > Width)
+            NumPixels = Width - x;
+
+        if (NumPixels != 0)
+        {
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+        }
+        i += ToSkip;
+    }
+
+done:
+    EngUnlockSurface(SurfObj);
+    return Mask;
+}
+
 W32KAPI
 INT
 APIENTRY
@@ -399,8 +462,8 @@ NtGdiSetDIBitsToDeviceInternal(
     INT ret = 0;
     NTSTATUS Status = STATUS_SUCCESS;
     PDC pDC;
-    HBITMAP hSourceBitmap = NULL;
-    SURFOBJ *pDestSurf, *pSourceSurf = NULL;
+    HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
+    SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
     SURFACE *pSurf;
     RECTL rcDest;
     POINTL ptSource;
@@ -465,7 +528,7 @@ NtGdiSetDIBitsToDeviceInternal(
 
     SourceSize.cx = bmi->bmiHeader.biWidth;
     SourceSize.cy = ScanLines;
-    
+
     //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
     hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
@@ -492,6 +555,28 @@ NtGdiSetDIBitsToDeviceInternal(
         goto Exit;
     }
 
+    /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
+    if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
+    {
+        hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
+            ScanLines,
+            bmi->bmiHeader.biCompression,
+            Bits,
+            cjMaxBits);
+        if (!hMaskBitmap)
+        {
+            EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
+            Status = STATUS_NO_MEMORY;
+            goto Exit;
+        }
+        pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
+        if (!pMaskSurf)
+        {
+            Status = STATUS_UNSUCCESSFUL;
+            goto Exit;
+        }
+    }
+
     /* Create a palette for the DIB */
     ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
     if (!ppalDIB)
@@ -500,9 +585,9 @@ NtGdiSetDIBitsToDeviceInternal(
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
-    
+
     /* This is actually a blit */
-    DC_vPrepareDCsForBlit(pDC, rcDest, NULL, rcDest);
+    DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
     pSurf = pDC->dclevel.pSurface;
     if (!pSurf)
     {
@@ -510,7 +595,7 @@ NtGdiSetDIBitsToDeviceInternal(
         ret = ScanLines;
         goto Exit;
     }
-    
+
     ASSERT(pSurf->ppal);
 
     /* Initialize EXLATEOBJ */
@@ -520,7 +605,7 @@ NtGdiSetDIBitsToDeviceInternal(
                           RGB(0xff, 0xff, 0xff),
                           pDC->pdcattr->crBackgroundClr,
                           pDC->pdcattr->crForegroundClr);
-                          
+
     pDestSurf = &pSurf->SurfObj;
 
     /* Copy the bits */
@@ -529,19 +614,19 @@ NtGdiSetDIBitsToDeviceInternal(
            ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
     Status = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
-                          NULL,
-                          pDC->rosdc.CombinedClip,
+                          pMaskSurf,
+                          &pDC->co.ClipObj,
                           &exlo.xlo,
                           &rcDest,
                           &ptSource,
+                          pMaskSurf ? &ptSource : NULL,
                           NULL,
                           NULL,
-                          NULL,
-                          ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+                          pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
 
     /* Cleanup EXLATEOBJ */
     EXLATEOBJ_vCleanup(&exlo);
-    
+
     /* We're done */
     DC_vFinishBlit(pDC, NULL);
 
@@ -555,9 +640,11 @@ Exit:
 
     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
+    if (pMaskSurf) EngUnlockSurface(pMaskSurf);
+    if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
     DC_UnlockDc(pDC);
 Exit2:
-    ExFreePool(pbmiSafe);
+    ExFreePoolWithTag(pbmiSafe, 'pmTG');
     return ret;
 }
 
@@ -565,7 +652,7 @@ Exit2:
 /* Converts a device-dependent bitmap to a DIB */
 INT
 APIENTRY
-NtGdiGetDIBitsInternal(
+GreGetDIBitsInternal(
     HDC hDC,
     HBITMAP hBitmap,
     UINT StartScan,
@@ -584,36 +671,15 @@ NtGdiGetDIBitsInternal(
     DWORD compr, size ;
     USHORT i;
     int bitmap_type;
-    RGBTRIPLE* rgbTriples;
     RGBQUAD* rgbQuads;
     VOID* colorPtr;
-    NTSTATUS Status = STATUS_SUCCESS;
 
     DPRINT("Entered NtGdiGetDIBitsInternal()\n");
 
     if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
         return 0;
 
-    _SEH2_TRY
-    {
-        /* Probe for read and write */
-        ProbeForRead(Info, MaxInfo, 1);
-        ProbeForWrite(Info, MaxInfo, 1);
-        if (Bits) ProbeForWrite(Bits, MaxBits, 1);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END
-
-    if (!NT_SUCCESS(Status))
-    {
-        return 0;
-    }
-
     colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
-    rgbTriples = colorPtr;
     rgbQuads = colorPtr;
 
     bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
@@ -662,15 +728,6 @@ NtGdiGetDIBitsInternal(
     switch(bpp)
     {
     case 0: /* Only info */
-        if(pbmci)
-        {
-            pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
-            pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
-                                         -psurf->SurfObj.sizlBitmap.cy :
-                                         psurf->SurfObj.sizlBitmap.cy);
-            pbmci->bmciHeader.bcPlanes = 1;
-            pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-        }
         Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
         Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
                                    -psurf->SurfObj.sizlBitmap.cy :
@@ -721,31 +778,19 @@ NtGdiGetDIBitsInternal(
             if(Usage == DIB_RGB_COLORS)
             {
                 ULONG colors = min(psurf->ppal->NumColors, 256);
-
-                if(pbmci)
-                {
-                    for(i = 0; i < colors; i++)
-                    {
-                        rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
-                        rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
-                        rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
-                    }
-                }
                 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
                 for(i = 0; i < colors; i++)
                 {
                     rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
                     rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
                     rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
+                    rgbQuads[i].rgbReserved = 0;
                 }
             }
             else
             {
                 for(i = 0; i < 256; i++)
-                {
-                    if(pbmci) ((WORD*)rgbTriples)[i] = i;
                     ((WORD*)rgbQuads)[i] = i;
-                }
             }
         }
         else
@@ -754,7 +799,6 @@ NtGdiGetDIBitsInternal(
             {
                 for(i = 0; i < 256; i++)
                 {
-                    if(pbmci) ((WORD*)rgbTriples)[i] = i;
                     ((WORD*)rgbQuads)[i] = i;
                 }
             }
@@ -771,13 +815,6 @@ NtGdiGetDIBitsInternal(
                 }
                 for (i = 0; i < pDcPal->NumColors; i++)
                 {
-                    if (pbmci)
-                    {
-                        rgbTriples[i].rgbtRed   = pDcPal->IndexedColors[i].peRed;
-                        rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
-                        rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
-                    }
-
                     rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
                     rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
                     rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
@@ -790,55 +827,20 @@ NtGdiGetDIBitsInternal(
                 switch (bpp)
                 {
                 case 1:
-                    if (pbmci)
-                    {
-                        rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
-                                                    rgbTriples[0].rgbtBlue = 0;
-                        rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
-                                                    rgbTriples[1].rgbtBlue = 0xff;
-                    }
-                    rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
-                                             rgbQuads[0].rgbBlue = 0;
+                    rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
                     rgbQuads[0].rgbReserved = 0;
-                    rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
-                                             rgbQuads[1].rgbBlue = 0xff;
+                    rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
                     rgbQuads[1].rgbReserved = 0;
                     break;
 
                 case 4:
-                    if (pbmci)
-                        RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
                     RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
-
                     break;
 
                 case 8:
                 {
                     INT r, g, b;
                     RGBQUAD *color;
-                    if (pbmci)
-                    {
-                        RGBTRIPLE *colorTriple;
-
-                        RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
-                                      10 * sizeof(RGBTRIPLE));
-                        RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
-                                      10 * sizeof(RGBTRIPLE));
-                        colorTriple = rgbTriples + 10;
-                        for(r = 0; r <= 5; r++) /* FIXME */
-                        {
-                            for(g = 0; g <= 5; g++)
-                            {
-                                for(b = 0; b <= 5; b++)
-                                {
-                                    colorTriple->rgbtRed =   (r * 0xff) / 5;
-                                    colorTriple->rgbtGreen = (g * 0xff) / 5;
-                                    colorTriple->rgbtBlue =  (b * 0xff) / 5;
-                                    color++;
-                                }
-                            }
-                        }
-                    }
                     memcpy(rgbQuads, DefLogPaletteQuads,
                            10 * sizeof(RGBQUAD));
                     memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
@@ -953,10 +955,7 @@ NtGdiGetDIBitsInternal(
 
         psurfDest = SURFACE_ShareLockSurface(hBmpDest);
 
-        rcDest.left = 0;
-        rcDest.top = 0;
-        rcDest.bottom = ScanLines;
-        rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+        RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
 
         srcPoint.x = 0;
 
@@ -994,22 +993,7 @@ NtGdiGetDIBitsInternal(
             ScanLines = 0;
         else
         {
-            Status = STATUS_SUCCESS;
-            _SEH2_TRY
-            {
-                RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
-            }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-            {
-                Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END
-
-            if(!NT_SUCCESS(Status))
-            {
-                DPRINT1("Unable to copy bits to the user provided pointer\n");
-                ScanLines = 0;
-            }
+            RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
         }
 
         GreDeleteObject(hBmpDest);
@@ -1021,11 +1005,120 @@ done:
 
     if(pDC) DC_UnlockDc(pDC);
     if(psurf) SURFACE_ShareUnlockSurface(psurf);
-    if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+    if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
 
     return ScanLines;
 }
 
+INT
+APIENTRY
+NtGdiGetDIBitsInternal(
+    _In_ HDC hdc,
+    _In_ HBITMAP hbm,
+    _In_ UINT iStartScan,
+    _In_ UINT cScans,
+    _Out_opt_ LPBYTE pjBits,
+    _Inout_ LPBITMAPINFO pbmiUser,
+    _In_ UINT iUsage,
+    _In_ UINT cjMaxBits,
+    _In_ UINT cjMaxInfo)
+{
+    PBITMAPINFO pbmi;
+    HANDLE hSecure = NULL;
+    INT iResult = 0;
+    UINT cjAlloc;
+
+    /* Check for bad iUsage */
+    if (iUsage > 2) return 0;
+
+    /* Check if the size of the bitmap info is large enough */
+    if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
+    {
+        return 0;
+    }
+
+    /* Use maximum size */
+    cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
+
+    // HACK: the underlying code sucks and doesn't care for the size, so we
+    // give it the maximum ever needed
+    cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
+
+    /* Allocate a buffer the bitmapinfo */
+    pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
+    if (!pbmi)
+    {
+        /* Fail */
+        return 0;
+    }
+
+    /* Use SEH */
+    _SEH2_TRY
+    {
+        /* Probe and copy the BITMAPINFO */
+        ProbeForRead(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(BITMAPCOREHEADER)) ||
+        (pbmi->bmiHeader.biSize > cjMaxInfo))
+    {
+        goto cleanup;
+    }
+
+    /* Check if the caller provided bitmap bits */
+    if (pjBits)
+    {
+        /* Secure the user mode memory */
+        hSecure = EngSecureMem(pjBits, cjMaxBits);
+        if (!hSecure)
+        {
+            goto cleanup;
+        }
+    }
+
+    /* Now call the internal function */
+    iResult = GreGetDIBitsInternal(hdc,
+                                   hbm,
+                                   iStartScan,
+                                   cScans,
+                                   pjBits,
+                                   pbmi,
+                                   iUsage,
+                                   cjMaxBits,
+                                   cjMaxInfo);
+
+    /* Check for success */
+    if (iResult)
+    {
+        /* Use SEH to copy back to user mode */
+        _SEH2_TRY
+        {
+            /* Copy the data back */
+            ProbeForWrite(pbmiUser, cjMaxInfo, 1);
+            RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Ignore */
+        }
+        _SEH2_END;
+    }
+
+cleanup:
+    if (hSecure) EngUnsecureMem(hSecure);
+    ExFreePoolWithTag(pbmi, 'imBG');
+
+    return iResult;
+}
+
+
 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
 
 W32KAPI
@@ -1065,6 +1158,14 @@ NtGdiStretchDIBitsInternal(
         return 0;
     }
 
+    /* Check for info / mem DC without surface */
+    if (!pdc->dclevel.pSurface)
+    {
+        DC_UnlockDc(pdc);
+        // CHECKME
+        return TRUE;
+    }
+
     /* Transform dest size */
     sizel.cx = cxDst;
     sizel.cy = cyDst;
@@ -1093,22 +1194,30 @@ NtGdiStretchDIBitsInternal(
                                               hcmXform);
     }
 
-    pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
-    if (!pvBits)
+    if (pjInit && (cjMaxBits > 0))
     {
-        return 0;
-    }
+        pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
+        if (!pvBits)
+        {
+            return 0;
+        }
 
-    _SEH2_TRY
-    {
-        ProbeForRead(pjInit, cjMaxBits, 1);
-        RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+        _SEH2_TRY
+        {
+            ProbeForRead(pjInit, cjMaxBits, 1);
+            RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            ExFreePoolWithTag(pvBits, 'pmeT');
+            _SEH2_YIELD(return 0);
+        }
+        _SEH2_END
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    else
     {
-        _SEH2_YIELD(return 0);
+        pvBits = NULL;
     }
-    _SEH2_END
 
     /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
     if (!(pdc = DC_LockDc(hdc)))
@@ -1129,7 +1238,7 @@ NtGdiStretchDIBitsInternal(
     rcDst.bottom = rcDst.top + cyDst;
     IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
     RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
-    
+
     hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
                                pbmi->bmiHeader.biHeight,
                                0,
@@ -1162,17 +1271,10 @@ NtGdiStretchDIBitsInternal(
     }
 
     /* Prepare DC for blit */
-    DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
-    
+    DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
+
     psurfDst = pdc->dclevel.pSurface;
-    if (!psurfDst)
-    {
-        DC_vFinishBlit(pdc, NULL);
-        // CHECKME
-        bResult = TRUE;
-        goto cleanup;
-    }
-    
+
     /* Initialize XLATEOBJ */
     EXLATEOBJ_vInitialize(&exlo,
                           ppalDIB,
@@ -1185,7 +1287,7 @@ NtGdiStretchDIBitsInternal(
     bResult = IntEngStretchBlt(&psurfDst->SurfObj,
                                &psurfTmp->SurfObj,
                                NULL,
-                               pdc->rosdc.CombinedClip,
+                               &pdc->co.ClipObj,
                                &exlo.xlo,
                                &pdc->dclevel.ca,
                                &rcDst,
@@ -1203,7 +1305,7 @@ cleanup:
     if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
     if (hbmTmp) GreDeleteObject(hbmTmp);
     if (pdc) DC_UnlockDc(pdc);
-    ExFreePoolWithTag(pvBits, 'pmeT');
+    if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
 
     return bResult;
 }
@@ -1235,7 +1337,7 @@ IntCreateDIBitmap(
         DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
 
         // Check if the first color of the colormap is black
-        if ((col == RGB(0, 0, 0)))
+        if (col == RGB(0, 0, 0))
         {
             rgb++;
             col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
@@ -1477,7 +1579,7 @@ DIB_CreateDIBSection(
     HBITMAP res = 0;
     SURFACE *bmp = NULL;
     void *mapBits = NULL;
-    PPALETTE ppalDIB;
+    PPALETTE ppalDIB = NULL;
 
     // Fill BITMAP32 structure with DIB data
     CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
@@ -1611,15 +1713,10 @@ DIB_CreateDIBSection(
 
     /* Create a palette for the DIB */
     ppalDIB = CreateDIBPalette(bmi, dc, usage);
-    if (ppalDIB)
-    {
-        SURFACE_vSetPalette(bmp, ppalDIB);
-        PALETTE_ShareUnlockPalette(ppalDIB);
-    }
 
     // Clean up in case of errors
 cleanup:
-    if (!res || !bmp || !bm.bmBits)
+    if (!res || !bmp || !bm.bmBits || !ppalDIB)
     {
         DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
         if (bm.bmBits)
@@ -1635,17 +1732,28 @@ cleanup:
         }
 
         if (bmp)
+        {
+            SURFACE_ShareUnlockSurface(bmp);
             bmp = NULL;
+        }
 
         if (res)
         {
             GreDeleteObject(res);
             res = 0;
         }
+
+        if(ppalDIB)
+        {
+            PALETTE_ShareUnlockPalette(ppalDIB);
+        }
     }
 
     if (bmp)
     {
+        /* If we're here, everything went fine */
+        SURFACE_vSetPalette(bmp, ppalDIB);
+        PALETTE_ShareUnlockPalette(ppalDIB);
         SURFACE_ShareUnlockSurface(bmp);
     }
 
@@ -1845,10 +1953,51 @@ DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
 VOID
 FASTCALL
-DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
 {
-    if(converted != orig)
+    BITMAPCOREINFO* pbmci;
+    if(converted == orig)
+        return;
+
+    if(usage == -1)
+    {
+        /* Caller don't want any conversion */
         ExFreePoolWithTag(converted, TAG_DIB);
+        return;
+    }
+
+    /* Perform inverse conversion */
+    pbmci = (BITMAPCOREINFO*)orig;
+
+    ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
+    pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
+    pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
+    pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
+    pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
+
+    if(pbmci->bmciHeader.bcBitCount <= 8)
+    {
+        UINT numColors = converted->bmiHeader.biClrUsed;
+        if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
+        if(usage == DIB_PAL_COLORS)
+        {
+            RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
+            RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
+        }
+        else
+        {
+            UINT i;
+            RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
+            for(i=0; i<numColors; i++)
+            {
+                pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
+                pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
+                pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
+            }
+        }
+    }
+    /* Now free it, it's not needed anymore */
+    ExFreePoolWithTag(converted, TAG_DIB);
 }
 
 /* EOF */