windows-nt/Source/XPSP1/NT/shell/browseui/bandobj.cpp
2020-09-26 16:20:57 +08:00

221 lines
5 KiB
C++

#include "priv.h"
#include "bandobj.h"
UINT g_cfDeskBand = 0;
UINT g_cfDeskBandState = 0;
void InitCFDeskBand()
{
if (!g_cfDeskBand)
g_cfDeskBand = RegisterClipboardFormat(TEXT("DeskBand"));
if (!g_cfDeskBandState)
g_cfDeskBandState = RegisterClipboardFormat(TEXT("DeskBandState"));
}
CBandDataObject::CBandDataObject()
: _cRef(1)
{
InitCFDeskBand();
}
HRESULT CBandDataObject::Init(IUnknown* punkBand, IBandSite *pbs, DWORD dwBandID)
{
HRESULT hres = E_FAIL;
_pstm = SHCreateMemStream(NULL, 0);
if (_pstm) {
IPersistStream *ppstm;
punkBand->QueryInterface(IID_IPersistStream, (LPVOID*)&ppstm);
if (ppstm) {
LARGE_INTEGER li = {0};
OleSaveToStream(ppstm, _pstm);
_pstm->Seek(li, STREAM_SEEK_SET, NULL);
ppstm->Release();
// bandsite state flags
_dwState = 0; // (if we fail just do w/o the state flags)
if (pbs)
pbs->QueryBand(dwBandID, NULL, &_dwState, NULL, 0);
hres = S_OK;
}
}
return hres;
}
CBandDataObject::~CBandDataObject()
{
if (_pstm)
_pstm->Release();
}
ULONG CBandDataObject::AddRef()
{
_cRef++;
return _cRef;
}
ULONG CBandDataObject::Release()
{
ASSERT(_cRef > 0);
_cRef--;
if (_cRef > 0)
return _cRef;
delete this;
return 0;
}
HRESULT CBandDataObject::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_IDataObject))
{
*ppvObj = SAFECAST(this, IDataObject*);
AddRef();
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
// *** IDataObject ***
HRESULT CBandDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
HRESULT hres = E_FAIL;
if (pformatetcIn->cfFormat == g_cfDeskBand)
{
if (pformatetcIn->tymed & TYMED_ISTREAM && EVAL(_pstm))
{
ASSERT(_pstm);
pmedium->tymed = TYMED_ISTREAM;
pmedium->pstm = _pstm; // no AddRef since we xfer ownership
_pstm = NULL; // can only use it 1x (read causes seek)
pmedium->pUnkForRelease = NULL;
hres = S_OK;
}
}
else if (pformatetcIn->cfFormat == g_cfDeskBandState)
{
if (pformatetcIn->tymed & TYMED_HGLOBAL)
{
pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = GlobalAlloc(GPTR, sizeof (DWORD));
if (pmedium->hGlobal)
{
DWORD *pdw = (DWORD*)(pmedium->hGlobal);
*pdw = _dwState;
pmedium->pUnkForRelease = NULL;
hres = S_OK;
}
else
{
hres = E_OUTOFMEMORY;
}
}
}
return hres;
}
HRESULT CBandDataObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
return E_NOTIMPL;
}
HRESULT CBandDataObject::QueryGetData(FORMATETC *pformatetc)
{
HRESULT hres = S_FALSE;
// TODO: (reuse, perf) use rgfmtetc table lookup
if ((pformatetc->cfFormat == g_cfDeskBand) &&
(pformatetc->tymed & TYMED_ISTREAM) ||
(pformatetc->cfFormat == g_cfDeskBandState) &&
(pformatetc->tymed & TYMED_HGLOBAL))
{
hres = S_OK;
}
return hres;
}
HRESULT CBandDataObject::GetCanonicalFormatEtc(FORMATETC *pformatetcIn, FORMATETC *pformatetcOut)
{
*pformatetcOut = *pformatetcIn;
return DATA_S_SAMEFORMATETC;
}
HRESULT CBandDataObject::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
{
return E_NOTIMPL;
}
HRESULT CBandDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
{
HRESULT hr = E_FAIL;
if (dwDirection == DATADIR_GET)
{
FORMATETC rgfmtetc[] =
{
{ g_cfDeskBand, NULL, 0, -1, TYMED_ISTREAM },
{ g_cfDeskBandState, NULL, 0, -1, TYMED_HGLOBAL },
};
hr = SHCreateStdEnumFmtEtc(ARRAYSIZE(rgfmtetc), rgfmtetc, ppenumFormatEtc);
}
return hr;
}
HRESULT CBandDataObject::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
return E_NOTIMPL;
}
HRESULT CBandDataObject::DUnadvise(DWORD dwConnection)
{
return E_NOTIMPL;
}
HRESULT CBandDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
{
return E_NOTIMPL;
}
//*** IDataObject_GetDeskBandState -- get band's bandsite state flags from BandDataObject
// NOTES
// 'paired' w/ DragBandState (inline in CBandDataObject::Init)
DWORD IDataObject_GetDeskBandState(IDataObject *pdtobj)
{
DWORD dwState = 0; // (if we fail just do w/o the state flags)
FORMATETC fmte = {g_cfDeskBandState, NULL, 0, -1, TYMED_HGLOBAL};
STGMEDIUM stg;
HRESULT hrTmp;
hrTmp = pdtobj->GetData(&fmte, &stg);
if (SUCCEEDED(hrTmp))
{
DWORD *p = (DWORD *)(stg.hGlobal);
dwState = *p;
ReleaseStgMedium(&stg);
}
return dwState;
}