[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 WINAPI
GdiConvertEnhMetaFile(HENHMETAFILE hmf) GdiConvertEnhMetaFile(HENHMETAFILE hemf)
{ {
UNIMPLEMENTED; HANDLE hmo = NULL;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); BYTE * Buffer = NULL;
return 0; 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 HENHMETAFILE
WINAPI WINAPI
GdiCreateLocalEnhMetaFile(HENHMETAFILE hmo) GdiCreateLocalEnhMetaFile(HANDLE hmo)
{ {
UNIMPLEMENTED; HENHMETAFILE hEMF;
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); BYTE * Buffer = NULL;
return 0; 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) * PROGRAMMERS: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/ */
#include <precomp.h> #include <precomp.h>
#define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -101,14 +103,16 @@ GdiIsMetaPrintDC(HDC hDC)
*/ */
HGLOBAL HGLOBAL
WINAPI WINAPI
GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF) GdiCreateLocalMetaFilePict(HANDLE hmo)
{ {
HGLOBAL hMetaFilePict; HGLOBAL hMetaFilePict;
METAFILEPICT * pInfo; METAFILEPICT * pInfo;
HMETAFILE hMF = NULL; HMETAFILE hMF = NULL;
BYTE * Buffer = NULL; BYTE * Buffer = NULL;
BYTE * BufNew = NULL;
HDC hDC = NULL; HDC hDC = NULL;
UINT nSize; UINT nSize, cSize;
DWORD iType;
// NOTE: On Win32, there is no difference between the local heap and // NOTE: On Win32, there is no difference between the local heap and
// the global heap. GlobalAlloc and LocalAlloc have same effect. // the global heap. GlobalAlloc and LocalAlloc have same effect.
@ -119,15 +123,7 @@ GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF)
if (pInfo == NULL) if (pInfo == NULL)
goto Exit; goto Exit;
// create DC nSize = NtGdiGetServerMetaFileBits( hmo, 0, NULL, NULL, NULL, NULL, NULL );
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;
// allocate buffer // allocate buffer
Buffer = (BYTE *)LocalAlloc(LPTR, nSize); Buffer = (BYTE *)LocalAlloc(LPTR, nSize);
@ -135,20 +131,54 @@ GdiCreateLocalMetaFilePict(HENHMETAFILE hEMF)
goto Exit; goto Exit;
// store to buffer // 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) if (nSize == 0)
goto Exit; 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 // create metafile from buffer
hMF = SetMetaFileBitsEx(nSize, Buffer); hMF = SetMetaFileBitsEx(nSize, Buffer);
if (hMF == NULL) if (hMF == NULL)
goto Exit; goto Exit;
// no suggested size is supplied
pInfo->mm = MM_ANISOTROPIC;
pInfo->xExt = 0;
pInfo->yExt = 0;
// set metafile handle // set metafile handle
pInfo->hMF = hMF; pInfo->hMF = hMF;
@ -156,8 +186,6 @@ Exit:
// clean up // clean up
if (Buffer) if (Buffer)
LocalFree(Buffer); LocalFree(Buffer);
if (hDC)
DeleteDC(hDC);
if (pInfo) if (pInfo)
GlobalUnlock(hMetaFilePict); GlobalUnlock(hMetaFilePict);
if (hMF == NULL) if (hMF == NULL)
@ -173,16 +201,15 @@ Exit:
/* /*
* @implemented * @implemented
*/ */
HENHMETAFILE HANDLE
WINAPI WINAPI
GdiConvertMetaFilePict(HGLOBAL hMetaFilePict) GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
{ {
HMETAFILE hMF; HMETAFILE hMF;
UINT nSize; UINT nSize;
HENHMETAFILE hEMF = NULL; HANDLE hmo = NULL;
BYTE * Buffer = NULL; BYTE * Buffer = NULL;
HDC hDC = NULL; METAFILEPICT * pInfo = NULL;
METAFILEPICT * pInfo = NULL;
// get METAFILEPICT pointer // get METAFILEPICT pointer
pInfo = (METAFILEPICT *)GlobalLock(hMetaFilePict); pInfo = (METAFILEPICT *)GlobalLock(hMetaFilePict);
@ -192,8 +219,6 @@ GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
// get metafile handle // get metafile handle
hMF = pInfo->hMF; hMF = pInfo->hMF;
// Missing test for GDILoObjType_LO_METADC16_TYPE (hMF)
// get size of buffer // get size of buffer
nSize = GetMetaFileBitsEx(hMF, 0, NULL); nSize = GetMetaFileBitsEx(hMF, 0, NULL);
if (nSize == 0) if (nSize == 0)
@ -209,21 +234,13 @@ GdiConvertMetaFilePict(HGLOBAL hMetaFilePict)
if (nSize == 0) if (nSize == 0)
goto Exit; goto Exit;
// create DC hmo = NtGdiCreateServerMetaFile( GDITAG_TYPE_MFP, nSize, Buffer, pInfo->mm, pInfo->xExt, pInfo->yExt);
hDC = CreateCompatibleDC(NULL);
if (hDC == NULL)
goto Exit;
// create enhanced metafile from buffer
hEMF = SetWinMetaFileBits(nSize, Buffer, hDC, pInfo);
Exit: Exit:
// clean up // clean up
if (pInfo) if (pInfo)
GlobalUnlock(hMetaFilePict); GlobalUnlock(hMetaFilePict);
if (hDC)
DeleteDC(hDC);
if (Buffer) if (Buffer)
LocalFree(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) (objt) == GDIObjType_BRUSH_TYPE)
#define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \ #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \
ASSERT((objt) == GDIObjType_DC_TYPE || \ 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) \ #define ASSERT_TRYLOCK_OBJECT_TYPE(objt) \
ASSERT((objt) == GDIObjType_DRVOBJ_TYPE) ASSERT((objt) == GDIObjType_DRVOBJ_TYPE)
#else #else
@ -177,7 +179,7 @@ apfnCleanup[] =
NULL, /* 12 GDIObjType_UNUSED4_TYPE */ NULL, /* 12 GDIObjType_UNUSED4_TYPE */
NULL, /* 13 GDIObjType_SPACE_TYPE, unused */ NULL, /* 13 GDIObjType_SPACE_TYPE, unused */
NULL, /* 14 GDIObjType_UNUSED5_TYPE */ NULL, /* 14 GDIObjType_UNUSED5_TYPE */
NULL, /* 15 GDIObjType_META_TYPE, unused */ GDIOBJ_vCleanup, /* 15 GDIObjType_META_TYPE */
NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */ NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */
NULL, /* 17 GDIObjType_BMFD_TYPE, unused */ NULL, /* 17 GDIObjType_BMFD_TYPE, unused */
NULL, /* 18 GDIObjType_VTFD_TYPE, unused */ NULL, /* 18 GDIObjType_VTFD_TYPE, unused */

View file

@ -13,11 +13,8 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #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 typedef struct _METATYPEOBJ
{ {
BASEOBJECT BaseObject; BASEOBJECT BaseObject;
@ -30,18 +27,6 @@ typedef struct _METATYPEOBJ
} METATYPEOBJ, *PMETATYPEOBJ; } 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 ******************************************************/ /* System Service Calls ******************************************************/
/* /*
@ -79,7 +64,7 @@ NtGdiCreateServerMetaFile(
cjData && cjData &&
pjData ) pjData )
{ {
pmto = (PMETATYPEOBJ)GDIOBJ_AllocObjWithHandle(GDIObjType_META_TYPE, sizeof(METATYPEOBJ) + cjData); pmto = (PMETATYPEOBJ)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_META_TYPE, sizeof(METATYPEOBJ) + cjData);
if ( pmto ) if ( pmto )
{ {
pmto->iType = iType; pmto->iType = iType;
@ -90,8 +75,8 @@ NtGdiCreateServerMetaFile(
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead( pjData, cjData, 1 ); ProbeForRead( pjData, cjData, 1 );
RtlCopyMemory( pmto->pjData, pjData, cjData) ; RtlCopyMemory( pmto->pjData, pjData, cjData) ;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -102,7 +87,7 @@ NtGdiCreateServerMetaFile(
if (Pass) if (Pass)
{ {
GDIOBJ_vSetObjectOwner(&pmto->BaseObject, GDI_OBJ_HMGR_PUBLIC); GDIOBJ_vSetObjectOwner(&pmto->BaseObject, GDI_OBJ_HMGR_PUBLIC);
GDIOBJ_vDereferenceObject ((POBJ)pmto); GDIOBJ_vUnlockObject(&pmto->BaseObject);
return pmto->BaseObject.hHmgr; return pmto->BaseObject.hHmgr;
} }
else else
@ -132,7 +117,7 @@ NtGdiGetServerMetaFileBits(
ULONG cjRet = 0; ULONG cjRet = 0;
PMETATYPEOBJ pmto; PMETATYPEOBJ pmto;
pmto = (PMETATYPEOBJ) GDIOBJ_ShareLockObj ((HGDIOBJ) hmo, GDIObjType_META_TYPE); pmto = (PMETATYPEOBJ) GDIOBJ_LockObject( hmo, GDIObjType_META_TYPE);
if (!pmto) if (!pmto)
return 0; return 0;
@ -175,7 +160,7 @@ NtGdiGetServerMetaFileBits(
} }
} }
GDIOBJ_vDereferenceObject ((POBJ)pmto); GDIOBJ_vUnlockObject(&pmto->BaseObject);
return cjRet; return cjRet;
} }

View file

@ -161,6 +161,8 @@ typedef enum GDILoObjType
GDILoObjType_LO_REGION_TYPE = 0x40000, GDILoObjType_LO_REGION_TYPE = 0x40000,
GDILoObjType_LO_ICMLCS_TYPE = 0x90000, GDILoObjType_LO_ICMLCS_TYPE = 0x90000,
GDILoObjType_LO_CLIENTOBJ_TYPE = 0x60000, GDILoObjType_LO_CLIENTOBJ_TYPE = 0x60000,
GDILoObjType_LO_UMPD_TYPE = 0x110000,
GDILoObjType_LO_META_TYPE = 0x150000,
GDILoObjType_LO_ALTDC_TYPE = 0x210000, GDILoObjType_LO_ALTDC_TYPE = 0x210000,
GDILoObjType_LO_PEN_TYPE = 0x300000, GDILoObjType_LO_PEN_TYPE = 0x300000,
GDILoObjType_LO_EXTPEN_TYPE = 0x500000, GDILoObjType_LO_EXTPEN_TYPE = 0x500000,
@ -240,6 +242,9 @@ typedef DWORD LFTYPE;
/* Get/SetBounds/Rect support. */ /* Get/SetBounds/Rect support. */
#define DCB_WINDOWMGR 0x8000 /* Queries the Windows bounding rectangle instead of the application's */ #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 *********************************************************************/ /* TYPES *********************************************************************/
typedef PVOID KERNEL_PVOID; typedef PVOID KERNEL_PVOID;

View file

@ -65,8 +65,13 @@ IntFreeElementData(PCLIP pElement)
{ {
if (pElement->fGlobalHandle) if (pElement->fGlobalHandle)
UserDeleteObject(pElement->hData, TYPE_CLIPDATA); UserDeleteObject(pElement->hData, TYPE_CLIPDATA);
else if (pElement->fmt == CF_BITMAP || pElement->fmt == CF_PALETTE || else if (pElement->fmt == CF_BITMAP ||
pElement->fmt == CF_DSPBITMAP) 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); GreSetObjectOwner(pElement->hData, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(pElement->hData); GreDeleteObject(pElement->hData);

View file

@ -15,6 +15,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(user32); WINE_DEFAULT_DEBUG_CHANNEL(user32);
HANDLE WINAPI GdiConvertMetaFilePict(HANDLE);
HANDLE WINAPI GdiConvertEnhMetaFile(HANDLE);
HANDLE WINAPI GdiCreateLocalEnhMetaFile(HANDLE);
HANDLE WINAPI GdiCreateLocalMetaFilePict(HANDLE);
/* /*
* @implemented * @implemented
*/ */
@ -202,6 +208,16 @@ GetClipboardData(UINT uFormat)
if (!hData) if (!hData)
return NULL; 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) if (gcd.fGlobalHandle)
{ {
HANDLE hGlobal; HANDLE hGlobal;
@ -300,11 +316,15 @@ SetClipboardData(UINT uFormat, HANDLE hMem)
else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE) else if (uFormat == CF_BITMAP || uFormat == CF_DSPBITMAP || uFormat == CF_PALETTE)
hRet = NtUserSetClipboardData(uFormat, hMem, &scd); hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
/* Meta files are probably checked for validity */ /* Meta files are probably checked for validity */
else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT || else if (uFormat == CF_DSPMETAFILEPICT || uFormat == CF_METAFILEPICT )
uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
{ {
UNIMPLEMENTED; hMem = GdiConvertMetaFilePict( hMem );
hRet = NULL; // not supported yet hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
}
else if (uFormat == CF_DSPENHMETAFILE || uFormat == CF_ENHMETAFILE)
{
hMem = GdiConvertEnhMetaFile( hMem );
hRet = NtUserSetClipboardData(uFormat, hMem, &scd);
} }
else else
{ {