https://git.reactos.org/?p=reactos.git;a=commitdiff;h=da264743e1f53d1bb47235...
commit da264743e1f53d1bb4723590e47132f73071cf0d Author: jimtabor james.tabor@reactos.org AuthorDate: Fri May 31 21:44:17 2019 -0500 Commit: jimtabor james.tabor@reactos.org CommitDate: Fri May 31 21:44:17 2019 -0500
[Win32SS] Support Clipboard Metafile
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 | 84 +++++++++++++++++++++++++++---- win32ss/gdi/gdi32/objects/metafile.c | 89 ++++++++++++++++++++------------- win32ss/gdi/ntgdi/gdiobj.c | 6 ++- win32ss/gdi/ntgdi/metafile.c | 29 +++-------- win32ss/include/ntgdityp.h | 5 ++ win32ss/user/ntuser/clipboard.c | 9 +++- win32ss/user/user32/windows/clipboard.c | 28 +++++++++-- 7 files changed, 173 insertions(+), 77 deletions(-)
diff --git a/win32ss/gdi/gdi32/objects/enhmfile.c b/win32ss/gdi/gdi32/objects/enhmfile.c index bf8a94a947d..a7d168dc20a 100644 --- a/win32ss/gdi/gdi32/objects/enhmfile.c +++ b/win32ss/gdi/gdi32/objects/enhmfile.c @@ -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; }
/* diff --git a/win32ss/gdi/gdi32/objects/metafile.c b/win32ss/gdi/gdi32/objects/metafile.c index 44cea8e6739..e1a51fb69f4 100644 --- a/win32ss/gdi/gdi32/objects/metafile.c +++ b/win32ss/gdi/gdi32/objects/metafile.c @@ -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 } diff --git a/win32ss/gdi/ntgdi/gdiobj.c b/win32ss/gdi/ntgdi/gdiobj.c index 2635aab4576..3a323dc2fb4 100644 --- a/win32ss/gdi/ntgdi/gdiobj.c +++ b/win32ss/gdi/ntgdi/gdiobj.c @@ -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 */ diff --git a/win32ss/gdi/ntgdi/metafile.c b/win32ss/gdi/ntgdi/metafile.c index 63d5a241d60..e1c3c72e39f 100644 --- a/win32ss/gdi/ntgdi/metafile.c +++ b/win32ss/gdi/ntgdi/metafile.c @@ -13,11 +13,8 @@ #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; }
diff --git a/win32ss/include/ntgdityp.h b/win32ss/include/ntgdityp.h index 99eed15cc92..3cce9e8afe0 100644 --- a/win32ss/include/ntgdityp.h +++ b/win32ss/include/ntgdityp.h @@ -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; diff --git a/win32ss/user/ntuser/clipboard.c b/win32ss/user/ntuser/clipboard.c index 04e5d22291a..28a1844dd6a 100644 --- a/win32ss/user/ntuser/clipboard.c +++ b/win32ss/user/ntuser/clipboard.c @@ -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); diff --git a/win32ss/user/user32/windows/clipboard.c b/win32ss/user/user32/windows/clipboard.c index 66a4217301e..95fb87811be 100644 --- a/win32ss/user/user32/windows/clipboard.c +++ b/win32ss/user/user32/windows/clipboard.c @@ -15,6 +15,12 @@
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 {