https://git.reactos.org/?p=reactos.git;a=commitdiff;h=da264743e1f53d1bb4723…
commit da264743e1f53d1bb4723590e47132f73071cf0d
Author: jimtabor <james.tabor(a)reactos.org>
AuthorDate: Fri May 31 21:44:17 2019 -0500
Commit: jimtabor <james.tabor(a)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(a)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
{