mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[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:
parent
07fa6fc38c
commit
da264743e1
7 changed files with 173 additions and 77 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue