[Win32SS] Support Clipboard Metafile
authorjimtabor <james.tabor@reactos.org>
Sat, 1 Jun 2019 02:44:17 +0000 (21:44 -0500)
committerjimtabor <james.tabor@reactos.org>
Sat, 1 Jun 2019 02:44:17 +0000 (21:44 -0500)
Major fix ups and plugging in missing code changes. Handle code is from
another project currently being developed for ReactOS.
See CORE-12143

win32ss/gdi/gdi32/objects/enhmfile.c
win32ss/gdi/gdi32/objects/metafile.c
win32ss/gdi/ntgdi/gdiobj.c
win32ss/gdi/ntgdi/metafile.c
win32ss/include/ntgdityp.h
win32ss/user/ntuser/clipboard.c
win32ss/user/user32/windows/clipboard.c

index bf8a94a..a7d168d 100644 (file)
@@ -38,27 +38,89 @@ IsValidEnhMetaRecordOffExt(
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
-HENHMETAFILE
+HANDLE
 WINAPI
-GdiConvertEnhMetaFile(HENHMETAFILE hmf)
+GdiConvertEnhMetaFile(HENHMETAFILE hemf)
 {
-    UNIMPLEMENTED;
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    HANDLE hmo = NULL;
+    BYTE * Buffer = NULL;
+    UINT nSize;
+
+    nSize = GetEnhMetaFileBits( hemf, 0, NULL );
+    if (nSize == 0)
+        goto Exit;
+
+    // allocate buffer
+    Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
+    if (Buffer == NULL)
+        goto Exit;
+
+    nSize = GetEnhMetaFileBits( hemf, nSize, Buffer );
+    if (nSize == 0)
+        goto Exit;
+
+    hmo = NtGdiCreateServerMetaFile( GDITAG_TYPE_EMF, nSize, Buffer, 0, 0, 0 );
+
+Exit:
+    // clean up
+    if (Buffer)
+        LocalFree(Buffer);
+    return hmo;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 HENHMETAFILE
 WINAPI
-GdiCreateLocalEnhMetaFile(HENHMETAFILE hmo)
+GdiCreateLocalEnhMetaFile(HANDLE hmo)
 {
-    UNIMPLEMENTED;
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
+    HENHMETAFILE hEMF;
+    BYTE *       Buffer = NULL;
+    UINT         nSize;
+    DWORD        iType, mm, xExt, yExt;
+
+    nSize = NtGdiGetServerMetaFileBits( hmo, 0, NULL, NULL, NULL, NULL, NULL);
+    if (nSize == 0)
+        goto Exit;
+
+    // allocate buffer
+    Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
+    if (Buffer == NULL)
+        goto Exit;
+
+    // store to buffer
+    nSize = NtGdiGetServerMetaFileBits( hmo, nSize, Buffer, &iType, &mm, &xExt, &yExt);
+    if (nSize == 0)
+        goto Exit;
+
+    if ( iType == GDITAG_TYPE_MFP ) // handle conversion to EMF
+    {
+        METAFILEPICT Info;
+
+        Info.hMF  = NULL;
+        Info.mm   = mm;
+        Info.xExt = xExt;
+        Info.yExt = yExt;
+
+        hEMF = SetWinMetaFileBits( nSize, Buffer, NULL, &Info ); // Translate from old style to new style.
+        if (hEMF == NULL)
+            goto Exit;
+    }
+    else
+    {
+        hEMF = SetEnhMetaFileBits(nSize, Buffer);
+        if (hEMF == NULL)
+            goto Exit;
+    }
+
+Exit:
+    // clean up
+    if (Buffer)
+        LocalFree(Buffer);
+    return hEMF;
 }
 
 /*
index 44cea8e..e1a51fb 100644 (file)
@@ -6,6 +6,8 @@
  * PROGRAMMERS:     Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
  */
 #include <precomp.h>
+
+#define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
@@ -101,14 +103,16 @@ GdiIsMetaPrintDC(HDC hDC)
  */
 HGLOBAL
 WINAPI
-GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF)
+GdiCreateLocalMetaFilePict(HANDLE hmo)
 {
     HGLOBAL         hMetaFilePict;
     METAFILEPICT *  pInfo;
     HMETAFILE       hMF = NULL;
     BYTE *          Buffer = NULL;
+    BYTE *          BufNew = NULL;
     HDC             hDC = NULL;
-    UINT            nSize;
+    UINT            nSize, cSize;
+    DWORD           iType;
 
     // NOTE: On Win32, there is no difference between the local heap and
     //       the global heap. GlobalAlloc and LocalAlloc have same effect.
@@ -119,15 +123,7 @@ GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF)
     if (pInfo == NULL)
         goto Exit;
 
-    // create DC
-    hDC = CreateCompatibleDC(NULL);
-    if (hDC == NULL)
-        goto Exit;
-
-    // get size of dest buffer
-    nSize = GetWinMetaFileBits(hEMF, 0, NULL, MM_ANISOTROPIC, hDC);
-    if (nSize == 0)
-        goto Exit;
+    nSize = NtGdiGetServerMetaFileBits( hmo, 0, NULL, NULL, NULL, NULL, NULL );
 
     // allocate buffer
     Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
@@ -135,20 +131,54 @@ GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF)
         goto Exit;
 
     // store to buffer
-    nSize = GetWinMetaFileBits(hEMF, nSize, Buffer, MM_ANISOTROPIC, hDC);
+    nSize = NtGdiGetServerMetaFileBits( hmo, nSize, Buffer, &iType, (PDWORD)&pInfo->mm, (PDWORD)&pInfo->xExt, (PDWORD)&pInfo->yExt );
     if (nSize == 0)
         goto Exit;
 
+    if ( iType == GDITAG_TYPE_EMF ) // handle conversion to MFP
+    {
+        static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' };
+        HENHMETAFILE hEMF;
+        PENHMETAHEADER pemh = (PENHMETAHEADER)Buffer;
+
+        pInfo->mm   = MM_ANISOTROPIC;
+        pInfo->xExt = pemh->rclFrame.right   - pemh->rclFrame.left; // Width
+        pInfo->yExt = pemh->rclFrame.bottom  - pemh->rclFrame.top;  // Height
+
+        hEMF = SetEnhMetaFileBits(nSize, Buffer);
+        if (hEMF == NULL)
+            goto Exit;
+
+        hDC = CreateDCW(szDisplayW, NULL, NULL, NULL);
+        if (hDC)
+        {
+            cSize = GetWinMetaFileBits( hEMF, 0, NULL, MM_ANISOTROPIC, hDC );
+            if (cSize)
+            {
+                BufNew = (BYTE *)LocalAlloc(LPTR, cSize);
+                if (BufNew)
+                {
+                    nSize = GetWinMetaFileBits( hEMF, cSize, (LPBYTE)BufNew, MM_ANISOTROPIC, hDC );
+                    if (nSize == cSize)
+                    {
+                        if (Buffer) LocalFree(Buffer);
+                        Buffer = BufNew;
+                    }
+                }
+            }
+            DeleteDC(hDC);
+        }
+        DeleteEnhMetaFile(hEMF);
+
+        if (Buffer != BufNew)
+            goto Exit;
+    }
+
     // create metafile from buffer
     hMF = SetMetaFileBitsEx(nSize, Buffer);
     if (hMF == NULL)
         goto Exit;
 
-    // no suggested size is supplied
-    pInfo->mm = MM_ANISOTROPIC;
-    pInfo->xExt = 0;
-    pInfo->yExt = 0;
-
     // set metafile handle
     pInfo->hMF = hMF;
 
@@ -156,8 +186,6 @@ Exit:
     // clean up
     if (Buffer)
         LocalFree(Buffer);
-    if (hDC)
-        DeleteDC(hDC);
     if (pInfo)
         GlobalUnlock(hMetaFilePict);
     if (hMF == NULL)
@@ -173,16 +201,15 @@ Exit:
 /*
  * @implemented
  */
-HENHMETAFILE
+HANDLE
 WINAPI
 GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
 {
     HMETAFILE       hMF;
     UINT            nSize;
-    HENHMETAFILE    hEMF    = NULL;
-    BYTE *          Buffer  = NULL;
-    HDC             hDC     = NULL;
-    METAFILEPICT *  pInfo   = NULL;
+    HANDLE          hmo    = NULL;
+    BYTE *          Buffer = NULL;
+    METAFILEPICT *  pInfo  = NULL;
 
     // get METAFILEPICT pointer
     pInfo = (METAFILEPICT *)GlobalLock(hMetaFilePict);
@@ -192,8 +219,6 @@ GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
     // get metafile handle
     hMF = pInfo->hMF;
 
-    // Missing test for GDILoObjType_LO_METADC16_TYPE (hMF)
-
     // get size of buffer
     nSize = GetMetaFileBitsEx(hMF, 0, NULL);
     if (nSize == 0)
@@ -209,21 +234,13 @@ GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
     if (nSize == 0)
         goto Exit;
 
-    // create DC
-    hDC = CreateCompatibleDC(NULL);
-    if (hDC == NULL)
-        goto Exit;
-
-    // create enhanced metafile from buffer
-    hEMF = SetWinMetaFileBits(nSize, Buffer, hDC, pInfo);
+    hmo = NtGdiCreateServerMetaFile( GDITAG_TYPE_MFP, nSize, Buffer, pInfo->mm, pInfo->xExt, pInfo->yExt);
 
 Exit:
     // clean up
     if (pInfo)
         GlobalUnlock(hMetaFilePict);
-    if (hDC)
-        DeleteDC(hDC);
     if (Buffer)
         LocalFree(Buffer);
-    return hEMF;    // success if non-NULL
+    return hmo;    // success if non-NULL
 }
index 2635aab..3a323dc 100644 (file)
@@ -115,7 +115,9 @@ ASSERT_LOCK_ORDER(
            (objt) == GDIObjType_BRUSH_TYPE)
 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \
     ASSERT((objt) == GDIObjType_DC_TYPE || \
-           (objt) == GDIObjType_RGN_TYPE)
+           (objt) == GDIObjType_RGN_TYPE || \
+           (objt) == GDIObjType_UMPD_TYPE || \
+           (objt) == GDIObjType_META_TYPE)
 #define ASSERT_TRYLOCK_OBJECT_TYPE(objt) \
     ASSERT((objt) == GDIObjType_DRVOBJ_TYPE)
 #else
@@ -177,7 +179,7 @@ apfnCleanup[] =
     NULL,              /* 12 GDIObjType_UNUSED4_TYPE */
     NULL,              /* 13 GDIObjType_SPACE_TYPE, unused */
     NULL,              /* 14 GDIObjType_UNUSED5_TYPE */
-    NULL,              /* 15 GDIObjType_META_TYPE, unused */
+    GDIOBJ_vCleanup,   /* 15 GDIObjType_META_TYPE */
     NULL,              /* 16 GDIObjType_EFSTATE_TYPE, unused */
     NULL,              /* 17 GDIObjType_BMFD_TYPE, unused */
     NULL,              /* 18 GDIObjType_VTFD_TYPE, unused */
index 63d5a24..e1c3c72 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-// Need to move this to NtGdiTyp.h
-#define GDITAG_TYPE_EMF 'XEFM' // EnhMetaFile
-#define GDITAG_TYPE_MFP '_PFM' // MetaFile Picture
 
-// Internal Use
+// Internal Use Only
 typedef struct _METATYPEOBJ
 {
     BASEOBJECT  BaseObject;
@@ -30,18 +27,6 @@ typedef struct _METATYPEOBJ
 } METATYPEOBJ, *PMETATYPEOBJ;
 
 
-//
-//  Plug Me in Somewhere? Clipboard cleanup?
-//
-VOID
-FASTCALL
-METATYPEOBJ__vCleanup(PVOID ObjectBody)
-{
-    PMETATYPEOBJ pmto = (PMETATYPEOBJ)ObjectBody;
-    GDIOBJ_hInsertObject(&pmto->BaseObject, GDI_OBJ_HMGR_POWNED);
-    GDIOBJ_vDeleteObject(&pmto->BaseObject);
-}
-
 /* System Service Calls ******************************************************/
 
 /*
@@ -79,7 +64,7 @@ NtGdiCreateServerMetaFile(
         cjData &&
         pjData )
     {
-        pmto = (PMETATYPEOBJ)GDIOBJ_AllocObjWithHandle(GDIObjType_META_TYPE, sizeof(METATYPEOBJ) + cjData);
+        pmto = (PMETATYPEOBJ)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_META_TYPE, sizeof(METATYPEOBJ) + cjData);
         if ( pmto )
         {
             pmto->iType  = iType;
@@ -90,8 +75,8 @@ NtGdiCreateServerMetaFile(
 
             _SEH2_TRY
             {
-                 ProbeForRead( pjData, cjData, 1 );
-                 RtlCopyMemory( pmto->pjData, pjData, cjData) ;
+                ProbeForRead( pjData, cjData, 1 );
+                RtlCopyMemory( pmto->pjData, pjData, cjData) ;
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
@@ -102,7 +87,7 @@ NtGdiCreateServerMetaFile(
             if (Pass)
             {
                GDIOBJ_vSetObjectOwner(&pmto->BaseObject, GDI_OBJ_HMGR_PUBLIC);
-               GDIOBJ_vDereferenceObject ((POBJ)pmto);
+               GDIOBJ_vUnlockObject(&pmto->BaseObject);
                return pmto->BaseObject.hHmgr;
             }
             else
@@ -132,7 +117,7 @@ NtGdiGetServerMetaFileBits(
     ULONG cjRet = 0;
     PMETATYPEOBJ pmto;
 
-    pmto = (PMETATYPEOBJ) GDIOBJ_ShareLockObj ((HGDIOBJ) hmo, GDIObjType_META_TYPE);
+    pmto = (PMETATYPEOBJ) GDIOBJ_LockObject( hmo, GDIObjType_META_TYPE);
 
     if (!pmto)
         return 0;
@@ -175,7 +160,7 @@ NtGdiGetServerMetaFileBits(
         }
     }
 
-    GDIOBJ_vDereferenceObject ((POBJ)pmto);
+    GDIOBJ_vUnlockObject(&pmto->BaseObject);
     return cjRet;
 }
 
index 99eed15..3cce9e8 100644 (file)
@@ -161,6 +161,8 @@ typedef enum GDILoObjType
     GDILoObjType_LO_REGION_TYPE = 0x40000,
     GDILoObjType_LO_ICMLCS_TYPE = 0x90000,
     GDILoObjType_LO_CLIENTOBJ_TYPE = 0x60000,
+    GDILoObjType_LO_UMPD_TYPE = 0x110000,
+    GDILoObjType_LO_META_TYPE = 0x150000,
     GDILoObjType_LO_ALTDC_TYPE = 0x210000,
     GDILoObjType_LO_PEN_TYPE = 0x300000,
     GDILoObjType_LO_EXTPEN_TYPE = 0x500000,
@@ -240,6 +242,9 @@ typedef DWORD LFTYPE;
 /* Get/SetBounds/Rect support. */
 #define DCB_WINDOWMGR 0x8000 /* Queries the Windows bounding rectangle instead of the application's */
 
+#define GDITAG_TYPE_EMF 'XEFM' // EnhMetaFile
+#define GDITAG_TYPE_MFP '_PFM' // MetaFile Picture
+
 /* TYPES *********************************************************************/
 
 typedef PVOID KERNEL_PVOID;
index 04e5d22..28a1844 100644 (file)
@@ -65,8 +65,13 @@ IntFreeElementData(PCLIP pElement)
     {
         if (pElement->fGlobalHandle)
             UserDeleteObject(pElement->hData, TYPE_CLIPDATA);
-        else if (pElement->fmt == CF_BITMAP || pElement->fmt == CF_PALETTE ||
-                 pElement->fmt == CF_DSPBITMAP)
+        else if (pElement->fmt == CF_BITMAP          ||
+                 pElement->fmt == CF_PALETTE         ||
+                 pElement->fmt == CF_DSPBITMAP       ||
+                 pElement->fmt == CF_METAFILEPICT    ||
+                 pElement->fmt == CF_DSPMETAFILEPICT ||
+                 pElement->fmt == CF_DSPENHMETAFILE  ||
+                 pElement->fmt == CF_ENHMETAFILE )
         {
             GreSetObjectOwner(pElement->hData, GDI_OBJ_HMGR_POWNED);
             GreDeleteObject(pElement->hData);
index 66a4217..95fb878 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
+HANDLE WINAPI GdiConvertMetaFilePict(HANDLE);
+HANDLE WINAPI GdiConvertEnhMetaFile(HANDLE);
+HANDLE WINAPI GdiCreateLocalEnhMetaFile(HANDLE);
+HANDLE WINAPI GdiCreateLocalMetaFilePict(HANDLE);
+
+
 /*
  * @implemented
  */
@@ -202,6 +208,16 @@ GetClipboardData(UINT uFormat)
     if (!hData)
         return NULL;
 
+    switch (uFormat)
+    {
+        case CF_DSPMETAFILEPICT:
+        case CF_METAFILEPICT:
+            return GdiCreateLocalMetaFilePict(hData);
+        case CF_DSPENHMETAFILE:
+        case CF_ENHMETAFILE:
+            return GdiCreateLocalEnhMetaFile(hData);
+    }
+
     if (gcd.fGlobalHandle)
     {
         HANDLE hGlobal;
@@ -300,11 +316,15 @@ SetClipboardData(UINT uFormat, HANDLE hMem)
     else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE)
         hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
     /* Meta files are probably checked for validity */
-    else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT ||
-             uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
+    else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT )
     {
-        UNIMPLEMENTED;
-        hRet = NULL; // not supported yet
+        hMem = GdiConvertMetaFilePict( hMem );
+        hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
+    }
+    else if (uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
+    {
+        hMem = GdiConvertEnhMetaFile( hMem );
+        hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
     }
     else
     {