📄 clipboard.c
字号:
case WM_PAINTCLIPBOARD:
*/
default:
return DefWindowProcA(hWnd, message, wParam, lParam);
}
return 0;
}
#define MAX_CLIPFORMAT_NAME 80
/***********************************************************************
* OLEClipbrd_RenderFormat(LPFORMATETC)
* Render the clipboard data. Note that this call will delegate to the
* source data object.
* Note: This function assumes it is passed an HGLOBAL format to render.
*/
static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
{
STGMEDIUM std;
HGLOBAL hDup;
HRESULT hr = S_OK;
char szFmtName[MAX_CLIPFORMAT_NAME];
ILockBytes *ptrILockBytes = 0;
HGLOBAL hStorage = 0;
if (!GetClipboardFormatNameA(pFormatetc->cfFormat, szFmtName, MAX_CLIPFORMAT_NAME))
szFmtName[0] = '\0';
/* If embed source */
if (!strcmp(szFmtName, CF_EMBEDSOURCE))
{
memset(&std, 0, sizeof(STGMEDIUM));
std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;
hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);
if (hStorage == NULL)
HANDLE_ERROR( E_OUTOFMEMORY );
hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);
hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);
if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))
{
WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%x)\n", hr);
GlobalFree(hStorage);
return hr;
}
if (1) /* check whether the presentation data is already -not- present */
{
FORMATETC fmt2;
STGMEDIUM std2;
METAFILEPICT *mfp = 0;
fmt2.cfFormat = CF_METAFILEPICT;
fmt2.ptd = 0;
fmt2.dwAspect = DVASPECT_CONTENT;
fmt2.lindex = -1;
fmt2.tymed = TYMED_MFPICT;
memset(&std2, 0, sizeof(STGMEDIUM));
std2.tymed = TYMED_MFPICT;
/* Get the metafile picture out of it */
if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
{
mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
}
if (mfp)
{
OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
IStream *pStream = 0;
void *mfBits;
PresentationDataHeader pdh;
INT nSize;
CLSID clsID;
LPOLESTR strProgID;
CHAR strOleTypeName[51];
BYTE OlePresStreamHeader [] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
nSize = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
memset(&pdh, 0, sizeof(PresentationDataHeader));
memcpy(&pdh, OlePresStreamHeader, sizeof(OlePresStreamHeader));
pdh.dwObjectExtentX = mfp->xExt;
pdh.dwObjectExtentY = mfp->yExt;
pdh.dwSize = nSize;
hr = IStorage_CreateStream(std.u.pstg, name, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &pStream);
hr = IStream_Write(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
mfBits = HeapAlloc(GetProcessHeap(), 0, nSize);
nSize = GetMetaFileBitsEx(mfp->hMF, nSize, mfBits);
hr = IStream_Write(pStream, mfBits, nSize, NULL);
IStream_Release(pStream);
HeapFree(GetProcessHeap(), 0, mfBits);
GlobalUnlock(std2.u.hGlobal);
ReadClassStg(std.u.pstg, &clsID);
ProgIDFromCLSID(&clsID, &strProgID);
WideCharToMultiByte( CP_ACP, 0, strProgID, -1, strOleTypeName, sizeof(strOleTypeName), NULL, NULL );
OLECONVERT_CreateOleStream(std.u.pstg);
OLECONVERT_CreateCompObjStream(std.u.pstg, strOleTypeName);
}
}
}
else
{
if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))
{
WARN("() : IDataObject_GetData failed to render clipboard data! (%x)\n", hr);
GlobalFree(hStorage);
return hr;
}
/* To put a copy back on the clipboard */
hStorage = std.u.hGlobal;
}
/*
* Put a copy of the rendered data back on the clipboard
*/
if ( !(hDup = OLEClipbrd_GlobalDupMem(hStorage)) )
HANDLE_ERROR( E_OUTOFMEMORY );
if ( !SetClipboardData( pFormatetc->cfFormat, hDup ) )
{
GlobalFree(hDup);
WARN("() : Failed to set rendered clipboard data into clipboard!\n");
}
CLEANUP:
ReleaseStgMedium(&std);
return hr;
}
/***********************************************************************
* OLEClipbrd_GlobalDupMem( HGLOBAL )
* Helper method to duplicate an HGLOBAL chunk of memory
*/
static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc )
{
HGLOBAL hGlobalDest;
PVOID pGlobalSrc, pGlobalDest;
DWORD cBytes;
if ( !hGlobalSrc )
return 0;
cBytes = GlobalSize(hGlobalSrc);
if ( 0 == cBytes )
return 0;
hGlobalDest = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE,
cBytes );
if ( !hGlobalDest )
return 0;
pGlobalSrc = GlobalLock(hGlobalSrc);
pGlobalDest = GlobalLock(hGlobalDest);
if ( !pGlobalSrc || !pGlobalDest )
{
GlobalFree(hGlobalDest);
return 0;
}
memcpy(pGlobalDest, pGlobalSrc, cBytes);
GlobalUnlock(hGlobalSrc);
GlobalUnlock(hGlobalDest);
return hGlobalDest;
}
/*---------------------------------------------------------------------*
* Implementation of the internal IDataObject interface exposed by
* the OLE clipboard.
*---------------------------------------------------------------------*/
/************************************************************************
* OLEClipbrd_IDataObject_QueryInterface (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryInterface(
IDataObject* iface,
REFIID riid,
void** ppvObject)
{
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObject);
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (ppvObject==0) )
return E_INVALIDARG;
/*
* Initialize the return parameter.
*/
*ppvObject = 0;
/*
* Compare the riid with the interface IDs implemented by this object.
*/
if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
{
*ppvObject = iface;
}
else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
{
*ppvObject = (IDataObject*)&(This->lpvtbl1);
}
else /* We only support IUnknown and IDataObject */
{
WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
/*
* Query Interface always increases the reference count by one when it is
* successful.
*/
IUnknown_AddRef((IUnknown*)*ppvObject);
return S_OK;
}
/************************************************************************
* OLEClipbrd_IDataObject_AddRef (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI OLEClipbrd_IDataObject_AddRef(
IDataObject* iface)
{
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
TRACE("(%p)->(count=%u)\n",This, This->ref);
return InterlockedIncrement(&This->ref);
}
/************************************************************************
* OLEClipbrd_IDataObject_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI OLEClipbrd_IDataObject_Release(
IDataObject* iface)
{
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
ULONG ref;
TRACE("(%p)->(count=%u)\n",This, This->ref);
/*
* Decrease the reference count on this object.
*/
ref = InterlockedDecrement(&This->ref);
/*
* If the reference count goes down to 0, perform suicide.
*/
if (ref == 0)
{
OLEClipbrd_Destroy(This);
}
return ref;
}
/************************************************************************
* OLEClipbrd_IDataObject_GetData (IDataObject)
*
* The OLE Clipboard's implementation of this method delegates to
* a data source if there is one or wraps around the windows clipboard
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
IDataObject* iface,
LPFORMATETC pformatetcIn,
STGMEDIUM* pmedium)
{
HANDLE hData = 0;
BOOL bClipboardOpen = FALSE;
HRESULT hr = S_OK;
LPVOID src;
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
TRACE("(%p,%p,%p)\n", iface, pformatetcIn, pmedium);
if ( !pformatetcIn || !pmedium )
return E_INVALIDARG;
/*
* If we have a data source placed on the clipboard (via OleSetClipboard)
* simply delegate to the source object's QueryGetData
* NOTE: This code assumes that the IDataObject is in the same address space!
* We will need to add marshalling support when Wine handles multiple processes.
*/
if ( This->pIDataObjectSrc )
{
return IDataObject_GetData(This->pIDataObjectSrc, pformatetcIn, pmedium);
}
if ( pformatetcIn->lindex != -1 )
return DV_E_LINDEX;
if ( (pformatetcIn->tymed & TYMED_HGLOBAL) != TYMED_HGLOBAL )
return DV_E_TYMED;
/*
if ( pformatetcIn->dwAspect != DVASPECT_CONTENT )
return DV_E_DVASPECT;
*/
/*
* Otherwise, get the data from the windows clipboard using GetClipboardData
*/
if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
hData = GetClipboardData(pformatetcIn->cfFormat);
/* Must make a copy of global handle returned by GetClipboardData; it
* is not valid after we call CloseClipboard
* Application is responsible for freeing the memory (Forte Agent does this)
*/
src = GlobalLock(hData);
if(src) {
LPVOID dest;
ULONG size;
HANDLE hDest;
size = GlobalSize(hData);
hDest = GlobalAlloc(GHND, size);
dest = GlobalLock(hDest);
memcpy(dest, src, size);
GlobalUnlock(hDest);
GlobalUnlock(hData);
hData = hDest;
}
/*
* Return the clipboard data in the storage medium structure
*/
pmedium->tymed = (hData == 0) ? TYMED_NULL : TYMED_HGLOBAL;
pmedium->u.hGlobal = (HGLOBAL)hData;
pmedium->pUnkForRelease = NULL;
hr = S_OK;
CLEANUP:
/*
* Close Windows clipboard
*/
if ( bClipboardOpen && !CloseClipboard() )
hr = CLIPBRD_E_CANT_CLOSE;
if ( FAILED(hr) )
return hr;
return (hData == 0) ? DV_E_FORMATETC : S_OK;
}
static HRESULT WINAPI OLEClipbrd_IDataObject_GetDataHere(
IDataObject* iface,
LPFORMATETC pformatetc,
STGMEDIUM* pmedium)
{
FIXME(": Stub\n");
return E_NOTIMPL;
}
/************************************************************************
* OLEClipbrd_IDataObject_QueryGetData (IDataObject)
*
* The OLE Clipboard's implementation of this method delegates to
* a data source if there is one or wraps around the windows clipboard
* function IsClipboardFormatAvailable() otherwise.
*
* See Windows documentation for more details on IDataObject methods.
*/
static HRESULT WINAPI OLEClipbrd_IDataObject_QueryGetData(
IDataObject* iface,
LPFORMATETC pformatetc)
{
/*
* Declare "This" pointer
*/
OLEClipbrd *This = (OLEClipbrd *)iface;
TRACE("(%p, %p)\n", iface, pformatetc);
/*
* If we have a data source placed on the clipboard (via OleSetClipboard)
* simply delegate to the source object's QueryGetData
*/
if ( This->pIDataObjectSrc )
{
return IDataObject_QueryGetData(This->pIDataObjectSrc, pformatetc);
}
if (!pformatetc)
return E_INVALIDARG;
/*
if ( pformatetc->dwAspect != DVASPECT_CONTENT )
return DV_E_DVASPECT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -