[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
This commit is contained in:
jimtabor 2019-05-31 21:44:17 -05:00
parent 07fa6fc38c
commit da264743e1
7 changed files with 173 additions and 77 deletions

View 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;
}
/*

View 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
}

View 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 */

View file

@ -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;
}

View 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;

View 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);

View file

@ -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
{