|
|
#include "shole.h"
#include "ids.h"
#define INITGUID
#ifndef WINNT
#pragma data_seg(".text", "CODE")
#endif
#include <initguid.h>
#include "scguid.h"
#ifndef WINNT
#pragma data_seg()
#endif
// #define SAVE_OBJECTDESCRIPTOR
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
extern "C" const WCHAR c_wszDescriptor[];
UINT _GetClipboardFormat(UINT id) { static UINT s_acf[CFID_MAX] = { 0, 0, 0, 0, 0 }; static const TCHAR * const c_aszFormat[CFID_MAX] = { TEXT("Embedded Object"), TEXT("Object Descriptor"), TEXT("Link Source Descriptor"), TEXT("Rich Text Format"), TEXT("Shell Scrap Object") }; if (!s_acf[id]) { s_acf[id] = RegisterClipboardFormat(c_aszFormat[id]); } return s_acf[id]; }
//===========================================================================
// CScrapData : Class definition
//===========================================================================
class CScrapData : public IDataObject, public IPersistFile { public: CScrapData(); ~CScrapData();
// IUnKnown
virtual HRESULT __stdcall QueryInterface(REFIID,void **); virtual ULONG __stdcall AddRef(void); virtual ULONG __stdcall Release(void);
// IDataObject
virtual HRESULT __stdcall GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium); virtual HRESULT __stdcall GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium); virtual HRESULT __stdcall QueryGetData(FORMATETC *pformatetc); virtual HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut); virtual HRESULT __stdcall SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease); virtual HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc); virtual HRESULT __stdcall DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); virtual HRESULT __stdcall DUnadvise(DWORD dwConnection); virtual HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppenumAdvise); virtual HRESULT __stdcall IsDirty(void);
// IPersistFile
virtual HRESULT __stdcall GetClassID(CLSID *pClassID); virtual HRESULT __stdcall Load(LPCOLESTR pszFileName, DWORD dwMode); virtual HRESULT __stdcall Save(LPCOLESTR pszFileName, BOOL fRemember); virtual HRESULT __stdcall SaveCompleted(LPCOLESTR pszFileName); virtual HRESULT __stdcall GetCurFile(LPOLESTR *ppszFileName);
protected: HRESULT _OpenStorage(void); void _CloseStorage(BOOL fResetFlags); INT _GetFormatIndex(UINT cf); void _FillCFArray(void); #ifdef FIX_ROUNDTRIP
HRESULT _RunObject(void); #endif // FIX_ROUNDTRIP
#ifdef SAVE_OBJECTDESCRIPTOR
HRESULT _GetObjectDescriptor(LPSTGMEDIUM pmedium, BOOL fGetHere); #endif // SAVE_OBJECTDESCRIPTOR
UINT _cRef; BOOL _fDoc:1; BOOL _fItem:1; BOOL _fObjDesc:1; #ifdef FIX_ROUNDTRIP
BOOL _fRunObjectAlreadyCalled:1; LPDATAOBJECT _pdtobjItem; #endif // FIX_ROUNDTRIP
LPSTORAGE _pstgDoc; LPSTORAGE _pstgItem; LPSTREAM _pstmObjDesc; TCHAR _szPath[MAX_PATH]; INT _ccf; // number of clipboard format.
INT _icfCacheMax; // Max cache format index
DWORD _acf[64]; // 64 must be enough!
};
//===========================================================================
// CScrapData : Constructor
//===========================================================================
CScrapData::CScrapData(void) : _cRef(1), _pstgDoc(NULL), _pstgItem(NULL), _fDoc(FALSE), _fItem(FALSE), _fObjDesc(FALSE), _ccf(0), #ifdef FIX_ROUNDTRIP
_pdtobjItem(NULL), _fRunObjectAlreadyCalled(FALSE), #endif // FIX_ROUNDTRIP
_pstmObjDesc(NULL) { _szPath[0] = TEXT('\0'); g_cRefThisDll++; }
CScrapData::~CScrapData() { #ifdef FIX_ROUNDTRIP
if (_pdtobjItem) { _pdtobjItem->Release(); } #endif // FIX_ROUNDTRIP
_CloseStorage(FALSE); g_cRefThisDll--; } //===========================================================================
// CScrapData : Member functions (private)
//===========================================================================
//
// private member CScrapData::_OpenStorage
//
HRESULT CScrapData::_OpenStorage(void) { if (_pstgItem) { return S_OK; }
HRESULT hres; WCHAR wszFile[MAX_PATH];
#ifdef UNICODE
lstrcpyn(wszFile, _szPath, ARRAYSIZE(wszFile)); #ifdef DEBUG
DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetStorage is called (%s)"), wszFile); #endif
#else
MultiByteToWideChar(CP_ACP, 0, _szPath, -1, wszFile, ARRAYSIZE(wszFile));
#ifdef DEBUG
TCHAR szFile[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, wszFile, -1, szFile, ARRAYSIZE(szFile), NULL, NULL); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetStorage is called (%s)"), szFile); #endif
#endif
hres = StgOpenStorage(wszFile, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &_pstgDoc); if (SUCCEEDED(hres)) { _fDoc = TRUE; hres = _pstgDoc->OpenStorage(c_wszContents, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &_pstgItem); if (SUCCEEDED(hres)) { HRESULT hresT; _fItem = TRUE; #ifdef SAVE_OBJECTDESCRIPTOR
hresT = _pstgDoc->OpenStream(c_wszDescriptor, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &_pstmObjDesc); _fObjDesc = SUCCEEDED(hresT); #endif // SAVE_OBJECTDESCRIPTOR
} else { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_OpenStorage _pstgDoc->OpenStorage failed (%x)"), hres); _pstgDoc->Release(); _pstgDoc = NULL; } } else { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_OpenStorage StgOpenStorage failed (%x)"), hres); }
DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_OpenStorage _pstgDoc->OpenStorage returning (%x) %x"), hres, _pstmObjDesc); return hres; }
void CScrapData::_CloseStorage(BOOL fResetFlags) { if (_pstgItem) { _pstgItem->Release(); _pstgItem = NULL; } if (_pstmObjDesc) { _pstmObjDesc->Release(); _pstmObjDesc = NULL; } if (_pstgDoc) { _pstgDoc->Release(); _pstgDoc = NULL; }
if (fResetFlags) { _fItem = FALSE; _fObjDesc = FALSE; _fDoc = FALSE; } }
INT CScrapData::_GetFormatIndex(UINT cf) { for (INT i=0; i<_ccf; i++) { if (_acf[i] == cf) { return i; } } return -1; }
#ifdef FIX_ROUNDTRIP
extern "C" const TCHAR c_szRenderFMT[] = TEXT("DataFormats\\DelayRenderFormats"); #endif // FIX_ROUNDTRIP
extern "C" const WCHAR c_wszFormatNames[];
//
// This function filles the clipboard format array (_acf). Following
// clipboard format may be added.
//
// Step 1. CF_EMBEEDEDOBJECT
// Step 2. CF_OBJECTDESCRIPTOR
// Step 3. CF_SCRAPOBJECT
// Step 4. Cached clipboard formats (from a stream).
// Step 5. Delay Rendered clipbaord formats (from registry).
//
void CScrapData::_FillCFArray(void) { _ccf=0; //
// Step 1.
//
if (_fItem) { _acf[_ccf++] = CF_EMBEDDEDOBJECT; }
//
// Step 2.
//
if (_fObjDesc) { _acf[_ccf++] = CF_OBJECTDESCRIPTOR; }
//
// Step 3.
//
if (_fDoc) { _acf[_ccf++] = CF_SCRAPOBJECT; }
#ifdef FIX_ROUNDTRIP
if (_pstgItem) { //
// Step 3. Cached clipboard formats
//
//
// Open the stream which contains the names of cached formats.
//
LPSTREAM pstm; HRESULT hres = _pstgDoc->OpenStream(c_wszFormatNames, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, &pstm);
if (SUCCEEDED(hres)) { //
// For each cached format...
//
USHORT cb; DWORD cbRead; while(SUCCEEDED(pstm->Read(&cb, sizeof(cb), &cbRead)) && cbRead==sizeof(cb) && cb && cb<128) { UINT cf = 0;
//
// Get the cached clipboard format name
//
CHAR szFormat[128]; szFormat[cb] = '\0'; hres = pstm->Read(szFormat, cb, &cbRead); if (SUCCEEDED(hres) && cbRead==cb && lstrlenA(szFormat)==cb) { //
// Append it to the array.
//
#ifdef UNICODE
TCHAR wszFormat[128]; MultiByteToWideChar(CP_ACP, 0, szFormat, -1, wszFormat, ARRAYSIZE(wszFormat)); DebugMsg(DM_TRACE, TEXT("sc TR _FillCFA Found Cached Format %s"), wszFormat); #else
DebugMsg(DM_TRACE, TEXT("sc TR _FillCFA Found Cached Format %s"), szFormat); #endif
cf = RegisterClipboardFormatA(szFormat);
if (cf) { _acf[_ccf++] = cf; } } else { break; } } pstm->Release(); }
_icfCacheMax = _ccf;
//
// Step 4. Get the list of delay-rendered clipboard formats
//
LPPERSISTSTORAGE pps; hres = OleLoad(_pstgItem, IID_IPersistStorage, NULL, (LPVOID *)&pps); if (SUCCEEDED(hres)) { //
// Get the CLSID of embedding.
//
CLSID clsid; hres = pps->GetClassID(&clsid); if (SUCCEEDED(hres)) { //
// Open the key for delay-rendered format names.
//
extern HKEY _OpenCLSIDKey(REFCLSID rclsid, LPCTSTR pszSubKey); HKEY hkey = _OpenCLSIDKey(clsid, c_szRenderFMT); if (hkey) { TCHAR szValueName[128]; //
// For each delay-rendered clipboard format...
//
for(int iValue=0; ;iValue++) { //
// Get the value name, which is the format name.
//
DWORD cchValueName = ARRAYSIZE(szValueName); DWORD dwType; if (RegEnumValue(hkey, iValue, szValueName, &cchValueName, NULL, &dwType, NULL, NULL)==ERROR_SUCCESS) { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_FillCFA RegEnumValue found %s, %x"), szValueName, dwType); UINT cf = RegisterClipboardFormat(szValueName);
if (cf) { _acf[_ccf++] = cf; } } else { break; } }
//
// HACK: NT 3.5's regedit does not support named value...
//
for(iValue=0; ;iValue++) { TCHAR szKeyName[128]; //
// Get the value name, which is the format name.
//
if (RegEnumKey(hkey, iValue, szKeyName, ARRAYSIZE(szKeyName))==ERROR_SUCCESS) { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_FillCFA RegEnumValue found %s"), szValueName); LONG cbValue = ARRAYSIZE(szValueName); if ((RegQueryValue(hkey, szKeyName, szValueName, &cbValue)==ERROR_SUCCESS) && cbValue) { UINT cf = RegisterClipboardFormat(szValueName);
if (cf) { _acf[_ccf++] = cf; } } } else { break; } } RegCloseKey(hkey); } } pps->Release(); } } #endif // FIX_ROUNDTRIP
}
#ifdef FIX_ROUNDTRIP
//
// private member CScrapData::_RunObject
//
HRESULT CScrapData::_RunObject(void) { if (_pdtobjItem) { return S_OK; }
if (_fRunObjectAlreadyCalled) { DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject returning E_FAIL")); return E_FAIL; } _fRunObjectAlreadyCalled = TRUE;
HRESULT hres = _OpenStorage();
DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject _OpenStorage returned %x"), hres);
if (SUCCEEDED(hres) && _pstgItem) { LPOLEOBJECT pole; hres = OleLoad(_pstgItem, IID_IOleObject, NULL, (LPVOID *)&pole); DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject OleLoad returned %x"), hres); if (SUCCEEDED(hres)) { DWORD dw=GetCurrentTime(); hres = OleRun(pole); dw = GetCurrentTime()-dw; DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject OleRun returned %x (%d msec)"), hres, dw); if (SUCCEEDED(hres)) { hres = pole->GetClipboardData(0, &_pdtobjItem); DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject GetClipboardData returned %x"), hres); if (FAILED(hres)) { hres = pole->QueryInterface(IID_IDataObject, (LPVOID*)&_pdtobjItem); DebugMsg(DM_TRACE, TEXT("sc TR CSD::_RunObject QI(IID_IDataIbject) returned %x"), hres); } } pole->Release(); } }
return hres; } #endif // FIX_ROUNDTRIP
//===========================================================================
// CScrapData : Member functions (virtual IDataObject)
//===========================================================================
HRESULT CScrapData::QueryInterface(REFIID riid, LPVOID * ppvObj) { if (IsEqualIID(riid, IID_IDataObject) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (LPDATAOBJECT)this; _cRef++; return S_OK; } else if (IsEqualIID(riid, IID_IPersistFile)) { *ppvObj = (LPPERSISTFILE)this; _cRef++; return S_OK; } *ppvObj = NULL;
return E_NOINTERFACE; }
ULONG CScrapData::AddRef() { _cRef++; return _cRef; }
ULONG CScrapData::Release() { _cRef--; if (_cRef > 0) return _cRef;
DebugMsg(DM_TRACE, TEXT("sc TR - CSD::Release deleting this object")); delete this; return 0; }
#ifdef SAVE_OBJECTDESCRIPTOR
HRESULT CScrapData::_GetObjectDescriptor(LPSTGMEDIUM pmedium, BOOL fGetHere) { if (!_pstmObjDesc) return DATA_E_FORMATETC;
LARGE_INTEGER dlib = { 0, 0 }; HRESULT hres = _pstmObjDesc->Seek(dlib, STREAM_SEEK_SET, NULL); if (FAILED(hres)) return hres;
OBJECTDESCRIPTOR ods; ULONG cbRead; hres = _pstmObjDesc->Read(&ods.cbSize, sizeof(ods.cbSize), &cbRead); if (SUCCEEDED(hres) && cbRead == sizeof(ods.cbSize)) { if (fGetHere) { if (GlobalSize(pmedium->hGlobal)<ods.cbSize) { hres = STG_E_MEDIUMFULL; } } else { pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = GlobalAlloc(GMEM_MOVEABLE, ods.cbSize); hres = pmedium->hGlobal ? S_OK : E_OUTOFMEMORY; }
if (SUCCEEDED(hres)) { LPOBJECTDESCRIPTOR pods = (LPOBJECTDESCRIPTOR)GlobalLock(pmedium->hGlobal); if (pods) { pods->cbSize = ods.cbSize; hres = _pstmObjDesc->Read(&pods->clsid, ods.cbSize-sizeof(ods.cbSize), NULL); GlobalUnlock(pmedium->hGlobal); } else { if (!fGetHere) { GlobalFree(pmedium->hGlobal); pmedium->hGlobal = NULL; } hres = E_OUTOFMEMORY; } } }
DebugMsg(DM_TRACE, TEXT("sc TR - CSD::_GetObjectDescriptor returning (%x)"), hres); return hres; } #endif // SAVE_OBJECTDESCRIPTOR
HRESULT CScrapData::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) { #ifdef DEBUG
if (pformatetcIn->cfFormat<CF_MAX) { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData called with %x,%x,%x"), pformatetcIn->cfFormat, pformatetcIn->tymed, pmedium->tymed); } else { TCHAR szName[256]; GetClipboardFormatName(pformatetcIn->cfFormat, szName, ARRAYSIZE(szName)); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData called with %s,%x,%x"), szName, pformatetcIn->tymed, pmedium->tymed); } #endif
HRESULT hres;
pmedium->pUnkForRelease = NULL; pmedium->pstg = NULL;
//
// NOTES: We should avoid calling _OpenStorage if we don't support
// the format.
//
if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE && _fItem) { hres = _OpenStorage(); if (SUCCEEDED(hres)) { pmedium->tymed = TYMED_ISTORAGE; _pstgItem->AddRef(); pmedium->pstg = _pstgItem; } } else if (pformatetcIn->cfFormat == CF_SCRAPOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE && _fItem) { hres = _OpenStorage(); if (SUCCEEDED(hres)) { pmedium->tymed = TYMED_ISTORAGE; _pstgDoc->AddRef(); pmedium->pstg = _pstgDoc; } } #ifdef SAVE_OBJECTDESCRIPTOR
else if (pformatetcIn->cfFormat == CF_OBJECTDESCRIPTOR && pformatetcIn->tymed == TYMED_HGLOBAL && _fObjDesc) { hres = _OpenStorage(); if (SUCCEEDED(hres)) { hres = _GetObjectDescriptor(pmedium, FALSE); } } #endif // SAVE_OBJECTDESCRIPTOR
else { #ifdef FIX_ROUNDTRIP
INT iFmt = _GetFormatIndex(pformatetcIn->cfFormat);
if (iFmt != -1) { hres = _OpenStorage(); if (FAILED(hres)) { goto exit; } }
if (iFmt>=_icfCacheMax) { //
// Delayed Rendered format
//
if (SUCCEEDED(_RunObject())) { hres = _pdtobjItem->GetData(pformatetcIn, pmedium); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData called _pdtobjItem->GetData %x"), hres); return hres; } } else if (iFmt >= 0) { //
// Cached Format
//
extern void _GetCacheStreamName(LPCTSTR pszFormat, LPWSTR wszStreamName, UINT cchMax); TCHAR szFormat[128]; if (pformatetcIn->cfFormat<CF_MAX) { wsprintf(szFormat, TEXT("#%d"), pformatetcIn->cfFormat); } else { GetClipboardFormatName(pformatetcIn->cfFormat, szFormat, ARRAYSIZE(szFormat)); }
WCHAR wszStreamName[256]; _GetCacheStreamName(szFormat, wszStreamName, ARRAYSIZE(wszStreamName));
if (pformatetcIn->cfFormat==CF_METAFILEPICT || pformatetcIn->cfFormat==CF_ENHMETAFILE || pformatetcIn->cfFormat==CF_BITMAP || pformatetcIn->cfFormat==CF_PALETTE ) { LPSTORAGE pstg; hres = _pstgDoc->OpenStorage(wszStreamName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstg); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData OpenStorage returned (%x)"), hres); if (SUCCEEDED(hres)) { LPDATAOBJECT pdtobj; #if 0
hres = OleLoad(pstg, IID_IDataObject, NULL, (LPVOID*)&pdtobj); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData OleLoad returned (%x)"), hres); #else
const CLSID* pclsid = NULL; switch(pformatetcIn->cfFormat) { case CF_METAFILEPICT: pclsid = &CLSID_Picture_Metafile; break; case CF_ENHMETAFILE: pclsid = &CLSID_Picture_EnhMetafile; break; case CF_PALETTE: case CF_BITMAP: pclsid = &CLSID_Picture_Dib; break; }
LPPERSISTSTORAGE ppstg; hres = OleCreateDefaultHandler(*pclsid, NULL, IID_IPersistStorage, (LPVOID *)&ppstg); DebugMsg(DM_TRACE, TEXT("sc TR Scrap_CacheOPF OleCreteDefHandler returned %x"), hres); if (SUCCEEDED(hres)) { hres = ppstg->Load(pstg); DebugMsg(DM_TRACE, TEXT("sc TR Scrap_CacheOPF ppstg->Load returned %x"), hres); if (SUCCEEDED(hres)) { hres = ppstg->QueryInterface(IID_IDataObject, (LPVOID*)&pdtobj); } ppstg->HandsOffStorage(); ppstg->Release(); } #endif
if (SUCCEEDED(hres)) { hres = pdtobj->GetData(pformatetcIn, pmedium); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData pobj->GetData returned (%x)"), hres); pdtobj->Release(); } pstg->Release(); return hres; } // fall through
} else // if (pformatetcIn->cfFormat==CF_...)
{ LPSTREAM pstm; hres = _pstgDoc->OpenStream(wszStreamName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pstm); if (SUCCEEDED(hres)) { UINT cbData; DWORD cbRead; hres = pstm->Read(&cbData, sizeof(cbData), &cbRead); if (SUCCEEDED(hres) && cbRead==sizeof(cbData)) { LPBYTE pData = (LPBYTE)GlobalAlloc(GPTR, cbData); if (pData) { hres = pstm->Read(pData, cbData, &cbRead); if (SUCCEEDED(hres) && cbData==cbRead) { pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = (HGLOBAL)pData; } else { hres = E_UNEXPECTED; GlobalFree((HGLOBAL)pData); } } else { hres = E_OUTOFMEMORY; } } pstm->Release();
DebugMsg(DM_TRACE, TEXT("CSD::GetData(%s) returning %x"), szFormat, hres); return hres; } } } // if (iFmt >= 0)
#endif // FIX_ROUNDTRIP
hres = DATA_E_FORMATETC; }
exit:
#ifdef DEBUG
TCHAR szFormat[256]; GetClipboardFormatName(pformatetcIn->cfFormat, szFormat, ARRAYSIZE(szFormat));
DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetData called with %x,%x,%s and returning %x"), pformatetcIn->cfFormat, pformatetcIn->tymed, szFormat, hres); #endif
return hres; }
HRESULT CScrapData::GetDataHere(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium ) { HRESULT hres;
#ifdef DEBUG
if (pformatetcIn->cfFormat<CF_MAX) { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetDataHere called with %x,%x,%x"), pformatetcIn->cfFormat, pformatetcIn->tymed, pmedium->tymed); } else { TCHAR szName[256]; GetClipboardFormatName(pformatetcIn->cfFormat, szName, ARRAYSIZE(szName)); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetDataHere called with %s,%x,%x"), szName, pformatetcIn->tymed, pmedium->tymed); } #endif
hres = _OpenStorage(); if (FAILED(hres)) { return hres; }
if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE && pmedium->tymed == TYMED_ISTORAGE) { hres = _pstgItem->CopyTo(0, NULL, NULL, pmedium->pstg); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetDataHere _pstgItem->CopyTo returned %x"), hres); } else if (pformatetcIn->cfFormat == CF_SCRAPOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE && pmedium->tymed == TYMED_ISTORAGE) { hres = _pstgDoc->CopyTo(0, NULL, NULL, pmedium->pstg); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetDataHere _pstgItem->CopyTo returned %x"), hres); } #ifdef SAVE_OBJECTDESCRIPTOR
else if ((pformatetcIn->cfFormat == CF_OBJECTDESCRIPTOR) && (pformatetcIn->tymed == TYMED_HGLOBAL) && _pstmObjDesc) { hres = _GetObjectDescriptor(pmedium, TRUE); } #endif // SAVE_OBJECTDESCRIPTOR
else { #ifdef FIX_ROUNDTRIP
if (_GetFormatIndex(pformatetcIn->cfFormat) >= 0 && SUCCEEDED(_RunObject())) { DebugMsg(DM_TRACE, TEXT("sc TR - CSD::GetDataHere calling _pdtobjItem->GetDataHere")); return _pdtobjItem->GetDataHere(pformatetcIn, pmedium); } #endif // FIX_ROUNDTRIP
hres = DATA_E_FORMATETC; }
return hres; }
HRESULT CScrapData::QueryGetData(LPFORMATETC pformatetcIn) { HRESULT hres; if (_GetFormatIndex(pformatetcIn->cfFormat) >= 0) { hres = S_OK; } else { hres = DATA_E_FORMATETC; }
#ifdef DEBUG
TCHAR szFormat[256] = TEXT(""); GetClipboardFormatName(pformatetcIn->cfFormat, szFormat, ARRAYSIZE(szFormat)); DebugMsg(DM_TRACE, TEXT("sc TR - CSD::QueryGetData(%x,%s,%x) returning %x"), pformatetcIn->cfFormat, szFormat, pformatetcIn->tymed, hres); #endif
return hres; }
HRESULT CScrapData::GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) { //
// This is the simplest implemtation. It means we always return
// the data in the format requested.
//
return ResultFromScode(DATA_S_SAMEFORMATETC); }
HRESULT CScrapData::SetData(LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease) { return E_FAIL; }
HRESULT CScrapData::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc) { if (dwDirection!=DATADIR_GET) { return E_NOTIMPL; // Not supported (as documented)
}
if (_ccf==0) { return E_UNEXPECTED; }
FORMATETC * pfmt = (FORMATETC*)LocalAlloc(LPTR, sizeof(FORMATETC)*_ccf); if (!pfmt) { return E_OUTOFMEMORY; }
static const FORMATETC s_fmteInit = { 0, (DVTARGETDEVICE __RPC_FAR *)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL // HGLOBAL except CF_EMBEDDEDOBJECT/SCRAPOBJECT
};
//
// Fills FORMATETC for each clipboard format.
//
for (INT i=0; i<_ccf; i++) { pfmt[i] = s_fmteInit; pfmt[i].cfFormat = (CLIPFORMAT)_acf[i];
if (_acf[i]==CF_EMBEDDEDOBJECT || _acf[i]==CF_SCRAPOBJECT) { pfmt[i].tymed = TYMED_ISTORAGE; } else { switch(_acf[i]) { case CF_METAFILEPICT: pfmt[i].tymed = TYMED_MFPICT; break;
case CF_ENHMETAFILE: pfmt[i].tymed = TYMED_ENHMF; break;
case CF_BITMAP: case CF_PALETTE: pfmt[i].tymed = TYMED_GDI; break; } } }
HRESULT hres = SHCreateStdEnumFmtEtc(_ccf, pfmt, ppenumFormatEtc); LocalFree((HLOCAL)pfmt);
return hres; }
HRESULT CScrapData::DAdvise(FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
HRESULT CScrapData::DUnadvise(DWORD dwConnection) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
HRESULT CScrapData::EnumDAdvise(LPENUMSTATDATA * ppenumAdvise) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
//===========================================================================
// CScrapData : Member functions (virtual IPersistFile)
//===========================================================================
HRESULT CScrapData::GetClassID(LPCLSID lpClassID) { *lpClassID = CLSID_CScrapData; return S_OK; }
HRESULT CScrapData::IsDirty(void) { return S_FALSE; // meaningless (read only)
}
HRESULT CScrapData::Load(LPCOLESTR pwszFile, DWORD grfMode) { //
// Close all the storage (if there is any) and reset flags.
//
_CloseStorage(TRUE);
//
// Copy the new file name and open storage to update the flags.
//
#ifdef UNICODE
lstrcpyn(_szPath, pwszFile, ARRAYSIZE(_szPath)); #else
WideCharToMultiByte(CP_ACP, 0, pwszFile, -1, _szPath, ARRAYSIZE(_szPath), NULL, NULL); #endif
HRESULT hres = _OpenStorage(); _FillCFArray();
//
// Close all the storage, so that we can move/delete.
//
_CloseStorage(FALSE);
return hres; }
HRESULT CScrapData::Save(LPCOLESTR pwszFile, BOOL fRemember) { return E_FAIL; // read only
}
HRESULT CScrapData::SaveCompleted(LPCOLESTR pwszFile) { return S_OK; }
HRESULT CScrapData::GetCurFile(LPOLESTR *lplpszFileName) { return E_NOTIMPL; // nobody needs it
}
HRESULT CScrapData_CreateInstance(LPUNKNOWN * ppunk) { //
// This test code is unrelated to the scrap itself. It just verifies that
// CLSID_ShellLink is correctly registered.
//
#ifdef DEBUG
LPUNKNOWN punk = NULL; HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC, IID_IShellLink, (LPVOID*)&punk); DebugMsg(DM_TRACE, TEXT("###############################################")); DebugMsg(DM_TRACE, TEXT("CoCreateInstance returned %x"), hres); DebugMsg(DM_TRACE, TEXT("###############################################")); if (SUCCEEDED(hres)) { punk->Release(); } #endif
CScrapData* pscd = new CScrapData(); if (pscd) { *ppunk = (LPDATAOBJECT)pscd; return S_OK; } return E_OUTOFMEMORY; }
|