You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
815 lines
24 KiB
815 lines
24 KiB
#include "private.h"
|
|
#include "offl_cpp.h"
|
|
|
|
#include <mluisupp.h>
|
|
|
|
// registered clipboard formats
|
|
UINT g_cfFileDescriptor = 0;
|
|
UINT g_cfFileContents = 0;
|
|
UINT g_cfPrefDropEffect = 0;
|
|
UINT g_cfURL = 0;
|
|
|
|
HICON g_webCrawlerIcon = NULL;
|
|
HICON g_channelIcon = NULL;
|
|
HICON g_desktopIcon = NULL;
|
|
|
|
#define MAX_ITEM_OPEN 10
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// COfflineObjectItem Object
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void LoadDefaultIcons()
|
|
{
|
|
if (g_webCrawlerIcon == NULL)
|
|
{
|
|
g_webCrawlerIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SUBSCRIBE));
|
|
g_channelIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_CHANNEL));
|
|
g_desktopIcon = LoadIcon(MLGetHinst(), MAKEINTRESOURCE(IDI_DESKTOPITEM));
|
|
}
|
|
}
|
|
|
|
COfflineObjectItem::COfflineObjectItem()
|
|
{
|
|
TraceMsg(TF_SUBSFOLDER, "hci - COfflineObjectItem() called.");
|
|
DllAddRef();
|
|
_cRef = 1;
|
|
}
|
|
|
|
COfflineObjectItem::~COfflineObjectItem()
|
|
{
|
|
Assert(_cRef == 0); // we should have zero ref count here
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "hci - ~COfflineObjectItem() called.");
|
|
|
|
SAFERELEASE(m_pUIHelper);
|
|
SAFERELEASE(_pOOFolder);
|
|
|
|
if (_ppooi)
|
|
{
|
|
for (UINT i = 0; i < _cItems; i++)
|
|
{
|
|
if (_ppooi[i])
|
|
ILFree((LPITEMIDLIST)_ppooi[i]);
|
|
}
|
|
MemFree((HLOCAL)_ppooi);
|
|
}
|
|
|
|
DllRelease();
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::Initialize(COfflineFolder *pOOFolder, UINT cidl, LPCITEMIDLIST *ppidl)
|
|
{
|
|
_ppooi = (LPMYPIDL *)MemAlloc(LPTR, cidl * sizeof(LPMYPIDL));
|
|
if (!_ppooi)
|
|
return E_OUTOFMEMORY;
|
|
|
|
_cItems = cidl;
|
|
|
|
for (UINT i = 0; i < cidl; i++)
|
|
{
|
|
// we need to clone the whole array, so if one of them fails, we'll
|
|
// destroy the ones we've already created
|
|
_ppooi[i] = (LPMYPIDL)ILClone(ppidl[i]);
|
|
if (!_ppooi[i]) {
|
|
UINT j = 0;
|
|
|
|
for (; j < i; j++) {
|
|
ILFree((LPITEMIDLIST)_ppooi[j]);
|
|
_ppooi[j] = NULL;
|
|
}
|
|
|
|
MemFree((HLOCAL)_ppooi);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
_pOOFolder = pOOFolder;
|
|
_pOOFolder->AddRef(); // we're going to hold onto this pointer, so
|
|
// we need to AddRef it.
|
|
|
|
// If there is only one item here, we initialize UI helper.
|
|
if (_cItems == 1)
|
|
{
|
|
ASSERT(!m_pUIHelper);
|
|
POOEntry pooe = &(_ppooi[0]->ooe);
|
|
|
|
HRESULT hr = CoInitialize(NULL);
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CoCreateInstance(*(&(pooe->clsidDest)), NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IUnknown, (void **)&m_pUIHelper);
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(m_pUIHelper);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ISubscriptionAgentShellExt *psase;
|
|
|
|
hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR wszURL[MAX_URL + 1];
|
|
WCHAR wszName[MAX_NAME + 1];
|
|
SUBSCRIPTIONCOOKIE alignedCookie;
|
|
|
|
MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), URL(pooe));
|
|
MyStrToOleStrN(wszName, ARRAYSIZE(wszName), NAME(pooe));
|
|
|
|
alignedCookie = pooe->m_Cookie;
|
|
psase->Initialize(&alignedCookie, wszURL, wszName, (SUBSCRIPTIONTYPE)-1);
|
|
pooe->m_Cookie = alignedCookie;
|
|
|
|
psase->Release();
|
|
}
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem_CreateInstance
|
|
(
|
|
COfflineFolder *pOOFolder,
|
|
UINT cidl,
|
|
LPCITEMIDLIST *ppidl,
|
|
REFIID riid,
|
|
void **ppvOut
|
|
)
|
|
{
|
|
COfflineObjectItem *pOOItem;
|
|
HRESULT hr;
|
|
|
|
*ppvOut = NULL; // null the out param
|
|
|
|
if (!_ValidateIDListArray(cidl, ppidl))
|
|
return E_FAIL;
|
|
|
|
if (((riid == IID_IExtractIconA) || (riid == IID_IExtractIconW)) && (cidl != 1))
|
|
return E_FAIL; // What do you need this icon for?
|
|
|
|
pOOItem = new COfflineObjectItem;
|
|
if (!pOOItem)
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = pOOItem->Initialize(pOOFolder, cidl, ppidl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pOOItem->QueryInterface(riid, ppvOut);
|
|
}
|
|
pOOItem->Release();
|
|
|
|
if (g_cfPrefDropEffect == 0)
|
|
{
|
|
g_cfFileDescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); // "FileContents"
|
|
g_cfFileContents = RegisterClipboardFormat(CFSTR_FILECONTENTS); // "FileDescriptor"
|
|
g_cfPrefDropEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
|
|
g_cfURL = RegisterClipboardFormat(CFSTR_SHELLURL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IUnknown Methods...
|
|
|
|
HRESULT COfflineObjectItem::QueryInterface(REFIID iid, LPVOID *ppvObj)
|
|
{
|
|
// TraceMsg(TF_ALWAYS, TEXT("hci - QueryInterface() called."));
|
|
|
|
*ppvObj = NULL; // null the out param
|
|
|
|
if (iid == IID_IUnknown) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IUnknown");
|
|
*ppvObj = (LPVOID)this;
|
|
}
|
|
else if (iid == IID_IContextMenu) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IContextMenu");
|
|
*ppvObj = (LPVOID)(IContextMenu *)this;
|
|
}
|
|
else if (iid == IID_IQueryInfo) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IQueryInfo");
|
|
*ppvObj = (LPVOID)(IQueryInfo *)this;
|
|
}
|
|
else if (iid == IID_IDataObject) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IDataObject");
|
|
*ppvObj = (LPVOID)(IDataObject *)this;
|
|
}
|
|
|
|
else if ((iid == IID_IExtractIconA) || (iid == IID_IExtractIconW)) {
|
|
if (m_pUIHelper) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IExtractIcon from UIHelper");
|
|
if (S_OK == m_pUIHelper->QueryInterface(iid, ppvObj))
|
|
return S_OK;
|
|
else
|
|
TraceMsg(TF_SUBSFOLDER, " failed to get IExtractIcon from UIHelper");
|
|
}
|
|
TraceMsg(TF_SUBSFOLDER, " getting default IExtractIcon");
|
|
|
|
*ppvObj = iid == IID_IExtractIconA ?
|
|
(LPVOID)(IExtractIconA *)this :
|
|
(LPVOID)(IExtractIconW *)this;
|
|
}
|
|
else if (iid == IID_IOfflineObject) {
|
|
TraceMsg(TF_SUBSFOLDER, " getting IOfflineObject");
|
|
*ppvObj = (LPVOID)this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
((LPUNKNOWN)*ppvObj)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
DBGIID("COfflineObjectItem::QueryInterface() failed", iid);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG COfflineObjectItem::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
ULONG COfflineObjectItem::Release()
|
|
{
|
|
if (0L != --_cRef)
|
|
return _cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
|
|
// IContextMenu Methods
|
|
|
|
HRESULT COfflineObjectItem::QueryContextMenu
|
|
(
|
|
HMENU hmenu,
|
|
UINT indexMenu,
|
|
UINT idCmdFirst,
|
|
UINT idCmdLast,
|
|
UINT uFlags
|
|
)
|
|
{
|
|
UINT cItems;
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "Item::QueryContextMenu() called.");
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// FEATURE: May also need some category specific code here.
|
|
|
|
#ifdef DEBUG
|
|
int imi = GetMenuItemCount(hmenu);
|
|
while (--imi >= 0)
|
|
{
|
|
MENUITEMINFO mii = {
|
|
sizeof(MENUITEMINFO), MIIM_ID | MIIM_SUBMENU | MIIM_TYPE,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
if (GetMenuItemInfo(hmenu, imi, TRUE, &mii)) {
|
|
;
|
|
}
|
|
}
|
|
#endif
|
|
if ((uFlags & CMF_VERBSONLY) || (uFlags & CMF_DVFILE))
|
|
cItems = MergePopupMenu(&hmenu, POPUP_CONTEXT_VERBSONLY, 0, indexMenu,
|
|
idCmdFirst - RSVIDM_FIRST, idCmdLast);
|
|
else
|
|
{
|
|
if (_ppooi[0]->ooe.bChannel &&
|
|
SHRestricted2(REST_NoEditingChannels, URL(&(_ppooi[0]->ooe)), 0))
|
|
{
|
|
cItems = MergePopupMenu(&hmenu, POPUP_RESTRICTED_CONTEXT, 0, indexMenu,
|
|
idCmdFirst - RSVIDM_FIRST, idCmdLast);
|
|
}
|
|
else
|
|
{
|
|
cItems = MergePopupMenu(&hmenu, POPUP_OFFLINE_CONTEXT, 0, indexMenu,
|
|
idCmdFirst - RSVIDM_FIRST, idCmdLast);
|
|
}
|
|
if (_cItems > 1)
|
|
EnableMenuItem(hmenu, RSVIDM_PROPERTIES + idCmdFirst - RSVIDM_FIRST, MF_BYCOMMAND | MF_GRAYED);
|
|
}
|
|
|
|
if (SHRestricted2(REST_NoManualUpdates, URL(&(_ppooi[0]->ooe)), 0))
|
|
EnableMenuItem(hmenu, RSVIDM_UPDATE + idCmdFirst - RSVIDM_FIRST, MF_BYCOMMAND | MF_GRAYED);
|
|
|
|
SetMenuDefaultItem(hmenu, indexMenu, MF_BYPOSITION);
|
|
|
|
return ResultFromShort(cItems); // number of menu items
|
|
}
|
|
|
|
|
|
STDMETHODIMP COfflineObjectItem::InvokeCommand
|
|
(
|
|
LPCMINVOKECOMMANDINFO pici
|
|
)
|
|
{
|
|
UINT i;
|
|
int idCmd = _GetCmdID(pici->lpVerb);
|
|
HRESULT hres = S_OK;
|
|
CLSID * pClsid = NULL;
|
|
int updateCount = 0;
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "hci - cm - InvokeCommand() called.");
|
|
|
|
if (idCmd == RSVIDM_DELETE)
|
|
{
|
|
BOOL fRet = ConfirmDelete(pici->hwnd, _cItems, _ppooi);
|
|
if (!fRet)
|
|
return S_FALSE;
|
|
} else if (idCmd == RSVIDM_UPDATE) {
|
|
pClsid = (CLSID *)MemAlloc(LPTR, sizeof(CLSID) * _cItems);
|
|
if (!pClsid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
for (i = 0; i < _cItems; i++)
|
|
{
|
|
if (_ppooi[i])
|
|
{
|
|
SUBSCRIPTIONTYPE subType;
|
|
switch (idCmd)
|
|
{
|
|
case RSVIDM_OPEN:
|
|
if (i >= MAX_ITEM_OPEN)
|
|
{
|
|
hres = S_FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
subType = GetItemCategory(&(_ppooi[i]->ooe));
|
|
switch (subType) {
|
|
case SUBSTYPE_URL:
|
|
case SUBSTYPE_CHANNEL:
|
|
case SUBSTYPE_DESKTOPURL:
|
|
case SUBSTYPE_DESKTOPCHANNEL:
|
|
hres = _LaunchApp(pici->hwnd,URL(&(_ppooi[i]->ooe)));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case RSVIDM_COPY:
|
|
OleSetClipboard((IDataObject *)this);
|
|
goto Done;
|
|
|
|
case RSVIDM_DELETE:
|
|
hres = DoDeleteSubscription(&(_ppooi[i]->ooe));
|
|
if (SUCCEEDED(hres))
|
|
_GenerateEvent(SHCNE_DELETE,(LPITEMIDLIST)(_ppooi[i]),NULL);
|
|
break;
|
|
|
|
case RSVIDM_PROPERTIES:
|
|
{
|
|
POOEntry pooe = &(_ppooi[i]->ooe);
|
|
OOEBuf ooeBuf;
|
|
int iRet;
|
|
|
|
pooe->dwFlags = 0;
|
|
CopyToOOEBuf(pooe, &ooeBuf);
|
|
|
|
subType = GetItemCategory(&(_ppooi[i]->ooe));
|
|
switch (subType) {
|
|
case SUBSTYPE_URL:
|
|
case SUBSTYPE_CHANNEL:
|
|
case SUBSTYPE_DESKTOPCHANNEL:
|
|
case SUBSTYPE_DESKTOPURL:
|
|
case SUBSTYPE_EXTERNAL:
|
|
iRet = _CreatePropSheet(pici->hwnd,&ooeBuf);
|
|
break;
|
|
default:
|
|
goto Done;
|
|
}
|
|
|
|
if (iRet <= 0)
|
|
goto Done;
|
|
|
|
LPMYPIDL newPidl = NULL;
|
|
hres = LoadSubscription(ooeBuf.m_URL, &newPidl);
|
|
|
|
if (FAILED(hres)) {
|
|
ASSERT(0);
|
|
} else {
|
|
ILFree((LPITEMIDLIST)_ppooi[i]);
|
|
_ppooi[i] = newPidl;
|
|
}
|
|
}
|
|
goto Done;
|
|
|
|
case RSVIDM_UPDATE:
|
|
{
|
|
POOEntry pooe = &(_ppooi[i]->ooe);
|
|
pClsid[updateCount] = pooe->m_Cookie;
|
|
updateCount ++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idCmd == RSVIDM_UPDATE) {
|
|
hres = SendUpdateRequests(pici->hwnd, pClsid, updateCount);
|
|
MemFree(pClsid);
|
|
}
|
|
Done:
|
|
return hres;
|
|
}
|
|
|
|
|
|
STDMETHODIMP COfflineObjectItem::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved,
|
|
LPSTR pszName, UINT cchMax)
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
|
|
// TraceMsg(TF_ALWAYS, TEXT("OOI/IContextMenu - GetCommandString() called."));
|
|
|
|
if (uFlags == GCS_VERBA)
|
|
{
|
|
LPCSTR pszSrc = NULL;
|
|
|
|
switch(idCmd)
|
|
{
|
|
case RSVIDM_OPEN:
|
|
pszSrc = c_szOpen;
|
|
break;
|
|
|
|
case RSVIDM_COPY:
|
|
pszSrc = c_szCopy;
|
|
break;
|
|
|
|
case RSVIDM_DELETE:
|
|
pszSrc = c_szDelete;
|
|
break;
|
|
|
|
case RSVIDM_PROPERTIES:
|
|
pszSrc = c_szProperties;
|
|
break;
|
|
}
|
|
|
|
if (pszSrc)
|
|
{
|
|
lstrcpynA(pszName, pszSrc, cchMax);
|
|
hres = NOERROR;
|
|
}
|
|
}
|
|
|
|
else if (uFlags == GCS_HELPTEXTA)
|
|
{
|
|
switch(idCmd)
|
|
{
|
|
case RSVIDM_OPEN:
|
|
case RSVIDM_RENAME:
|
|
case RSVIDM_UPDATE:
|
|
case RSVIDM_COPY:
|
|
case RSVIDM_DELETE:
|
|
case RSVIDM_PROPERTIES:
|
|
MLLoadStringA((UINT)(IDS_SB_FIRST+idCmd), pszName, cchMax);
|
|
hres = NOERROR;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
// IQueryInfo Method
|
|
HRESULT COfflineObjectItem::GetInfoTip(DWORD dwFlags, WCHAR ** ppwsz)
|
|
{
|
|
*ppwsz = NULL;
|
|
int clen = lstrlen(STATUS(&(_ppooi[0]->ooe)))+1;
|
|
*ppwsz = (LPOLESTR)SHAlloc(clen*sizeof(WCHAR)) ;
|
|
if (!(*ppwsz)) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
MyStrToOleStrN(*ppwsz, clen, STATUS(&(_ppooi[0]->ooe)));
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::GetInfoFlags(DWORD *pdwFlags)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IDataObject Methods...
|
|
|
|
HRESULT COfflineObjectItem::GetData(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM)
|
|
{
|
|
HRESULT hres;
|
|
|
|
#ifdef DEBUG
|
|
TCHAR szName[64];
|
|
if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
|
|
wnsprintf(szName, ARRAYSIZE(szName), TEXT("#%d"), pFEIn->cfFormat);
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - GetData(%s)", szName);
|
|
#endif
|
|
|
|
pSTM->hGlobal = NULL;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
if ((pFEIn->cfFormat == g_cfPrefDropEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
|
|
hres = _CreatePrefDropEffect(pSTM);
|
|
|
|
else if ((pFEIn->cfFormat == g_cfFileDescriptor) && (pFEIn->tymed & TYMED_HGLOBAL))
|
|
hres = _CreateFileDescriptor(pSTM);
|
|
|
|
else if ((pFEIn->cfFormat == g_cfFileContents) && (pFEIn->tymed & TYMED_ISTREAM))
|
|
hres = _CreateFileContents(pSTM, pFEIn->lindex);
|
|
|
|
else if ((pFEIn->cfFormat == g_cfURL || pFEIn->cfFormat == CF_TEXT) && (pFEIn->tymed & TYMED_HGLOBAL))
|
|
hres = _CreateURL(pSTM);
|
|
|
|
else
|
|
hres = DATA_E_FORMATETC;
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
|
|
{
|
|
// TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - GetDataHere() called."));
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::QueryGetData(LPFORMATETC pFEIn)
|
|
{
|
|
#ifdef DEBUG
|
|
TCHAR szName[64];
|
|
if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
|
|
wnsprintf(szName, ARRAYSIZE(szName), TEXT("#%d"), pFEIn->cfFormat);
|
|
|
|
#endif
|
|
|
|
if (pFEIn->cfFormat == g_cfPrefDropEffect ||
|
|
pFEIn->cfFormat == g_cfFileDescriptor ||
|
|
pFEIn->cfFormat == g_cfFileContents ||
|
|
pFEIn->cfFormat == g_cfURL ||
|
|
pFEIn->cfFormat == CF_TEXT
|
|
) {
|
|
#ifdef DEBUG
|
|
TraceMsg(TF_ALWAYS, "\t%s format supported.", szName);
|
|
#endif
|
|
return NOERROR;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::GetCanonicalFormatEtc(LPFORMATETC pFEIn, LPFORMATETC pFEOut)
|
|
{
|
|
// TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - GetCanonicalFormatEtc() called."));
|
|
return DATA_S_SAMEFORMATETC;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::SetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM, BOOL fRelease)
|
|
{
|
|
TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - SetData() called.");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC *ppEnum)
|
|
{
|
|
FORMATETC objectfmte[5] = {
|
|
{(CLIPFORMAT) g_cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
|
|
{(CLIPFORMAT) g_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM },
|
|
{(CLIPFORMAT) g_cfPrefDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
|
|
{(CLIPFORMAT) g_cfURL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
|
|
{(CLIPFORMAT) CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
|
|
};
|
|
HRESULT hres;
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - EnumFormatEtc() called.");
|
|
|
|
hres = SHCreateStdEnumFmtEtc(ARRAYSIZE(objectfmte), objectfmte, ppEnum);
|
|
TraceMsg(TF_SUBSFOLDER, "\t- EnumFormatEtc() return %d.", hres);
|
|
return hres;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::DAdvise(LPFORMATETC pFE, DWORD grfAdv, LPADVISESINK pAdvSink,
|
|
LPDWORD pdwConnection)
|
|
{
|
|
TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - DAdvise() called.");
|
|
return OLE_E_ADVISENOTSUPPORTED;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::DUnadvise(DWORD dwConnection)
|
|
{
|
|
// TraceMsg(TF_SUBSFOLDER, TEXT("COfflineObjectItem - DUnAdvise() called."));
|
|
return OLE_E_ADVISENOTSUPPORTED;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::EnumDAdvise(LPENUMSTATDATA *ppEnum)
|
|
{
|
|
// TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - EnumAdvise() called."));
|
|
return OLE_E_ADVISENOTSUPPORTED;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Helper Routines
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
HRESULT COfflineObjectItem::_CreatePrefDropEffect(LPSTGMEDIUM pSTM)
|
|
{
|
|
pSTM->tymed = TYMED_HGLOBAL;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
TraceMsg(TF_SUBSFOLDER, "OOI/CreatePrefDropEffect");
|
|
pSTM->hGlobal = MemAlloc(LPTR, sizeof(DWORD));
|
|
|
|
// FEATURE: Need category specific code.
|
|
|
|
DWORD prefEffect = DROPEFFECT_COPY;
|
|
|
|
if (pSTM->hGlobal)
|
|
{
|
|
*((LPDWORD)pSTM->hGlobal) = prefEffect;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::_CreateURL(LPSTGMEDIUM pSTM)
|
|
{
|
|
LPTSTR pszURL = URL(&(((LPMYPIDL)_ppooi[0])->ooe));
|
|
int cchAlloc = (lstrlen(pszURL) + 1) * 2;
|
|
|
|
pSTM->tymed = TYMED_HGLOBAL;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
pSTM->hGlobal = MemAlloc(LPTR, cchAlloc);
|
|
|
|
if (pSTM->hGlobal)
|
|
{
|
|
SHTCharToAnsi(pszURL, (LPSTR)pSTM->hGlobal, cchAlloc);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::_CreateFileContents(LPSTGMEDIUM pSTM, LONG lindex)
|
|
{
|
|
HRESULT hr;
|
|
LONG iIndex;
|
|
|
|
// make sure the index is in a valid range.
|
|
if (lindex == -1)
|
|
{
|
|
if (_cItems == 1)
|
|
lindex = 0;
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
Assert((unsigned)lindex < _cItems);
|
|
Assert(lindex >= 0);
|
|
|
|
iIndex = lindex;
|
|
|
|
pSTM->tymed = TYMED_ISTREAM;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &pSTM->pstm);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LARGE_INTEGER li = {0L, 0L};
|
|
IUniformResourceLocator *purl;
|
|
|
|
hr = SHCoCreateInstance(NULL, &CLSID_InternetShortcut, NULL,
|
|
IID_IUniformResourceLocator, (void **)&purl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = purl->SetURL(URL(&(_ppooi[iIndex]->ooe)), TRUE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPersistStream *pps;
|
|
hr = purl->QueryInterface(IID_IPersistStream, (LPVOID *)&pps);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pps->Save(pSTM->pstm, TRUE);
|
|
pps->Release();
|
|
}
|
|
}
|
|
purl->Release();
|
|
}
|
|
pSTM->pstm->Seek(li, STREAM_SEEK_SET, NULL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::_CreateFileDescriptor(LPSTGMEDIUM pSTM)
|
|
{
|
|
FILEGROUPDESCRIPTOR *pfgd;
|
|
|
|
// render the file descriptor
|
|
// we only allocate for _cItems-1 file descriptors because the filegroup
|
|
// descriptor has already allocated space for 1.
|
|
|
|
pSTM->tymed = TYMED_HGLOBAL;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
pfgd = (FILEGROUPDESCRIPTOR *)MemAlloc(LPTR, sizeof(FILEGROUPDESCRIPTOR) + (_cItems-1) * sizeof(FILEDESCRIPTOR));
|
|
if (pfgd == NULL)
|
|
{
|
|
TraceMsg(TF_ALWAYS, "ooi - Couldn't alloc file descriptor");
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
pfgd->cItems = _cItems;
|
|
|
|
for (UINT i = 0; i < _cItems; i++)
|
|
{
|
|
FILEDESCRIPTOR *pfd = &(pfgd->fgd[i]);
|
|
StrCpyN(pfd->cFileName, NAME(&(_ppooi[i]->ooe)), ARRAYSIZE(pfd->cFileName));
|
|
int len = lstrlen(pfd->cFileName);
|
|
StrCpyN(pfd->cFileName + len, TEXT(".URL"), ARRAYSIZE(pfd->cFileName) - len);
|
|
}
|
|
|
|
pSTM->hGlobal = pfgd;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// IExtractIconA members
|
|
HRESULT COfflineObjectItem::GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
|
|
{
|
|
return IExtractIcon_GetIconLocationThunk((IExtractIconW *)this, uFlags, szIconFile, cchMax, piIndex, pwFlags);
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::Extract(LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
|
|
{
|
|
return IExtractIcon_ExtractThunk((IExtractIconW *)this, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::GetIconLocation(UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
|
|
{
|
|
ASSERT (piIndex && pwFlags);
|
|
|
|
StrCpyN(szIconFile, TEXT("not used"), cchMax);
|
|
|
|
SUBSCRIPTIONTYPE subType = GetItemCategory(&(_ppooi[0]->ooe));
|
|
switch (subType) {
|
|
case SUBSTYPE_URL:
|
|
*piIndex = 10;
|
|
break;
|
|
case SUBSTYPE_CHANNEL:
|
|
*piIndex = 11;
|
|
break;
|
|
case SUBSTYPE_DESKTOPCHANNEL:
|
|
case SUBSTYPE_DESKTOPURL:
|
|
*piIndex = 12;
|
|
break;
|
|
default:
|
|
*piIndex = 13; // Unknown!
|
|
break;
|
|
}
|
|
*pwFlags |= GIL_NOTFILENAME | GIL_PERINSTANCE | GIL_DONTCACHE;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT COfflineObjectItem::Extract(LPCTSTR szIconFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
|
|
{
|
|
* phiconLarge = * phiconSmall = NULL;
|
|
|
|
LoadDefaultIcons();
|
|
|
|
SUBSCRIPTIONTYPE subType = GetItemCategory(&(_ppooi[0]->ooe));
|
|
switch (subType) {
|
|
case SUBSTYPE_URL:
|
|
* phiconLarge = * phiconSmall = g_webCrawlerIcon;
|
|
break;
|
|
case SUBSTYPE_CHANNEL:
|
|
* phiconLarge = * phiconSmall = g_channelIcon;
|
|
break;
|
|
case SUBSTYPE_DESKTOPURL:
|
|
case SUBSTYPE_DESKTOPCHANNEL:
|
|
* phiconLarge = * phiconSmall = g_desktopIcon;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (!(*phiconLarge)) {
|
|
if (_ppooi[0]->ooe.bDesktop)
|
|
* phiconLarge = * phiconSmall = g_desktopIcon;
|
|
else if (_ppooi[0]->ooe.bChannel)
|
|
* phiconLarge = * phiconSmall = g_channelIcon;
|
|
}
|
|
return NOERROR;
|
|
}
|