Source code of Windows XP (NT5)
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.

828 lines
23 KiB

  1. #include "private.h"
  2. #include "offl_cpp.h"
  3. #include <mluisupp.h>
  4. // registered clipboard formats
  5. UINT g_cfFileDescriptor = 0;
  6. UINT g_cfFileContents = 0;
  7. UINT g_cfPrefDropEffect = 0;
  8. UINT g_cfURL = 0;
  9. HICON g_webCrawlerIcon = NULL;
  10. HICON g_channelIcon = NULL;
  11. HICON g_desktopIcon = NULL;
  12. #define MAX_ITEM_OPEN 10
  13. //////////////////////////////////////////////////////////////////////////////
  14. // COfflineObjectItem Object
  15. //////////////////////////////////////////////////////////////////////////////
  16. void LoadDefaultIcons()
  17. {
  18. if (g_webCrawlerIcon == NULL)
  19. {
  20. g_webCrawlerIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SUBSCRIBE));
  21. g_channelIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_CHANNEL));
  22. g_desktopIcon = LoadIcon(MLGetHinst(), MAKEINTRESOURCE(IDI_DESKTOPITEM));
  23. }
  24. }
  25. COfflineObjectItem::COfflineObjectItem()
  26. {
  27. TraceMsg(TF_SUBSFOLDER, "hci - COfflineObjectItem() called.");
  28. DllAddRef();
  29. _cRef = 1;
  30. }
  31. COfflineObjectItem::~COfflineObjectItem()
  32. {
  33. Assert(_cRef == 0); // we should have zero ref count here
  34. TraceMsg(TF_SUBSFOLDER, "hci - ~COfflineObjectItem() called.");
  35. SAFERELEASE(m_pUIHelper);
  36. SAFERELEASE(_pOOFolder);
  37. if (_ppooi)
  38. {
  39. for (UINT i = 0; i < _cItems; i++)
  40. {
  41. if (_ppooi[i])
  42. ILFree((LPITEMIDLIST)_ppooi[i]);
  43. }
  44. MemFree((HLOCAL)_ppooi);
  45. }
  46. DllRelease();
  47. }
  48. HRESULT COfflineObjectItem::Initialize(COfflineFolder *pOOFolder, UINT cidl, LPCITEMIDLIST *ppidl)
  49. {
  50. _ppooi = (LPMYPIDL *)MemAlloc(LPTR, cidl * sizeof(LPMYPIDL));
  51. if (!_ppooi)
  52. return E_OUTOFMEMORY;
  53. _cItems = cidl;
  54. for (UINT i = 0; i < cidl; i++)
  55. {
  56. // we need to clone the whole array, so if one of them fails, we'll
  57. // destroy the ones we've already created
  58. _ppooi[i] = (LPMYPIDL)ILClone(ppidl[i]);
  59. if (!_ppooi[i]) {
  60. UINT j = 0;
  61. for (; j < i; j++) {
  62. ILFree((LPITEMIDLIST)_ppooi[j]);
  63. _ppooi[j] = NULL;
  64. }
  65. MemFree((HLOCAL)_ppooi);
  66. return E_OUTOFMEMORY;
  67. }
  68. }
  69. _pOOFolder = pOOFolder;
  70. _pOOFolder->AddRef(); // we're going to hold onto this pointer, so
  71. // we need to AddRef it.
  72. // If there is only one item here, we initialize UI helper.
  73. if (_cItems == 1)
  74. {
  75. ASSERT(!m_pUIHelper);
  76. POOEntry pooe = &(_ppooi[0]->ooe);
  77. HRESULT hr = CoInitialize(NULL);
  78. ASSERT(SUCCEEDED(hr));
  79. if (SUCCEEDED(hr))
  80. {
  81. hr = CoCreateInstance(*(&(pooe->clsidDest)), NULL, CLSCTX_INPROC_SERVER,
  82. IID_IUnknown, (void **)&m_pUIHelper);
  83. ASSERT(SUCCEEDED(hr));
  84. ASSERT(m_pUIHelper);
  85. if (SUCCEEDED(hr))
  86. {
  87. ISubscriptionAgentShellExt *psase;
  88. hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase);
  89. if (SUCCEEDED(hr))
  90. {
  91. WCHAR wszURL[MAX_URL + 1];
  92. WCHAR wszName[MAX_NAME + 1];
  93. SUBSCRIPTIONCOOKIE alignedCookie;
  94. MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), URL(pooe));
  95. MyStrToOleStrN(wszName, ARRAYSIZE(wszName), NAME(pooe));
  96. alignedCookie = pooe->m_Cookie;
  97. psase->Initialize(&alignedCookie, wszURL, wszName, (SUBSCRIPTIONTYPE)-1);
  98. pooe->m_Cookie = alignedCookie;
  99. psase->Release();
  100. }
  101. }
  102. CoUninitialize();
  103. }
  104. }
  105. return S_OK;
  106. }
  107. HRESULT COfflineObjectItem_CreateInstance
  108. (
  109. COfflineFolder *pOOFolder,
  110. UINT cidl,
  111. LPCITEMIDLIST *ppidl,
  112. REFIID riid,
  113. void **ppvOut
  114. )
  115. {
  116. COfflineObjectItem *pOOItem;
  117. HRESULT hr;
  118. *ppvOut = NULL; // null the out param
  119. if (!_ValidateIDListArray(cidl, ppidl))
  120. return E_FAIL;
  121. #ifdef UNICODE
  122. if (((riid == IID_IExtractIconA) || (riid == IID_IExtractIconW)) && (cidl != 1))
  123. #else
  124. if ((riid == IID_IExtractIcon) && (cidl != 1))
  125. #endif
  126. return E_FAIL; // What do you need this icon for?
  127. pOOItem = new COfflineObjectItem;
  128. if (!pOOItem)
  129. return E_OUTOFMEMORY;
  130. hr = pOOItem->Initialize(pOOFolder, cidl, ppidl);
  131. if (SUCCEEDED(hr))
  132. {
  133. hr = pOOItem->QueryInterface(riid, ppvOut);
  134. }
  135. pOOItem->Release();
  136. if (g_cfPrefDropEffect == 0)
  137. {
  138. g_cfFileDescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); // "FileContents"
  139. g_cfFileContents = RegisterClipboardFormat(CFSTR_FILECONTENTS); // "FileDescriptor"
  140. g_cfPrefDropEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
  141. g_cfURL = RegisterClipboardFormat(CFSTR_SHELLURL);
  142. }
  143. return hr;
  144. }
  145. // IUnknown Methods...
  146. HRESULT COfflineObjectItem::QueryInterface(REFIID iid, LPVOID *ppvObj)
  147. {
  148. // TraceMsg(TF_ALWAYS, TEXT("hci - QueryInterface() called."));
  149. *ppvObj = NULL; // null the out param
  150. if (iid == IID_IUnknown) {
  151. TraceMsg(TF_SUBSFOLDER, " getting IUnknown");
  152. *ppvObj = (LPVOID)this;
  153. }
  154. else if (iid == IID_IContextMenu) {
  155. TraceMsg(TF_SUBSFOLDER, " getting IContextMenu");
  156. *ppvObj = (LPVOID)(IContextMenu *)this;
  157. }
  158. else if (iid == IID_IQueryInfo) {
  159. TraceMsg(TF_SUBSFOLDER, " getting IQueryInfo");
  160. *ppvObj = (LPVOID)(IQueryInfo *)this;
  161. }
  162. else if (iid == IID_IDataObject) {
  163. TraceMsg(TF_SUBSFOLDER, " getting IDataObject");
  164. *ppvObj = (LPVOID)(IDataObject *)this;
  165. }
  166. #ifdef UNICODE
  167. else if ((iid == IID_IExtractIconA) || (iid == IID_IExtractIconW)) {
  168. #else
  169. else if (iid == IID_IExtractIcon) {
  170. #endif
  171. if (m_pUIHelper) {
  172. TraceMsg(TF_SUBSFOLDER, " getting IExtractIcon from UIHelper");
  173. if (S_OK == m_pUIHelper->QueryInterface(iid, ppvObj))
  174. return S_OK;
  175. else
  176. TraceMsg(TF_SUBSFOLDER, " failed to get IExtractIcon from UIHelper");
  177. }
  178. TraceMsg(TF_SUBSFOLDER, " getting default IExtractIcon");
  179. #ifdef UNICODE
  180. *ppvObj = iid == IID_IExtractIconA ?
  181. (LPVOID)(IExtractIconA *)this :
  182. (LPVOID)(IExtractIconW *)this;
  183. #else
  184. *ppvObj = (LPVOID)(IExtractIcon*)this;
  185. #endif
  186. }
  187. else if (iid == IID_IOfflineObject) {
  188. TraceMsg(TF_SUBSFOLDER, " getting IOfflineObject");
  189. *ppvObj = (LPVOID)this;
  190. }
  191. if (*ppvObj)
  192. {
  193. ((LPUNKNOWN)*ppvObj)->AddRef();
  194. return S_OK;
  195. }
  196. DBGIID("COfflineObjectItem::QueryInterface() failed", iid);
  197. return E_NOINTERFACE;
  198. }
  199. ULONG COfflineObjectItem::AddRef()
  200. {
  201. return ++_cRef;
  202. }
  203. ULONG COfflineObjectItem::Release()
  204. {
  205. if (0L != --_cRef)
  206. return _cRef;
  207. delete this;
  208. return 0;
  209. }
  210. // IContextMenu Methods
  211. HRESULT COfflineObjectItem::QueryContextMenu
  212. (
  213. HMENU hmenu,
  214. UINT indexMenu,
  215. UINT idCmdFirst,
  216. UINT idCmdLast,
  217. UINT uFlags
  218. )
  219. {
  220. UINT cItems;
  221. TraceMsg(TF_SUBSFOLDER, "Item::QueryContextMenu() called.");
  222. ///////////////////////////////////////////////////////////
  223. // FEATURE: May also need some category specific code here.
  224. #ifdef DEBUG
  225. int imi = GetMenuItemCount(hmenu);
  226. while (--imi >= 0)
  227. {
  228. MENUITEMINFO mii = {
  229. sizeof(MENUITEMINFO), MIIM_ID | MIIM_SUBMENU | MIIM_TYPE,
  230. 0, 0, 0, 0, 0, 0, 0, 0, 0};
  231. if (GetMenuItemInfo(hmenu, imi, TRUE, &mii)) {
  232. ;
  233. }
  234. }
  235. #endif
  236. if ((uFlags & CMF_VERBSONLY) || (uFlags & CMF_DVFILE))
  237. cItems = MergePopupMenu(&hmenu, POPUP_CONTEXT_VERBSONLY, 0, indexMenu,
  238. idCmdFirst - RSVIDM_FIRST, idCmdLast);
  239. else
  240. {
  241. if (_ppooi[0]->ooe.bChannel &&
  242. SHRestricted2(REST_NoEditingChannels, URL(&(_ppooi[0]->ooe)), 0))
  243. {
  244. cItems = MergePopupMenu(&hmenu, POPUP_RESTRICTED_CONTEXT, 0, indexMenu,
  245. idCmdFirst - RSVIDM_FIRST, idCmdLast);
  246. }
  247. else
  248. {
  249. cItems = MergePopupMenu(&hmenu, POPUP_OFFLINE_CONTEXT, 0, indexMenu,
  250. idCmdFirst - RSVIDM_FIRST, idCmdLast);
  251. }
  252. if (_cItems > 1)
  253. EnableMenuItem(hmenu, RSVIDM_PROPERTIES + idCmdFirst - RSVIDM_FIRST, MF_BYCOMMAND | MF_GRAYED);
  254. }
  255. if (SHRestricted2(REST_NoManualUpdates, URL(&(_ppooi[0]->ooe)), 0))
  256. EnableMenuItem(hmenu, RSVIDM_UPDATE + idCmdFirst - RSVIDM_FIRST, MF_BYCOMMAND | MF_GRAYED);
  257. SetMenuDefaultItem(hmenu, indexMenu, MF_BYPOSITION);
  258. return ResultFromShort(cItems); // number of menu items
  259. }
  260. STDMETHODIMP COfflineObjectItem::InvokeCommand
  261. (
  262. LPCMINVOKECOMMANDINFO pici
  263. )
  264. {
  265. UINT i;
  266. int idCmd = _GetCmdID(pici->lpVerb);
  267. HRESULT hres = S_OK;
  268. CLSID * pClsid = NULL;
  269. int updateCount = 0;
  270. TraceMsg(TF_SUBSFOLDER, "hci - cm - InvokeCommand() called.");
  271. if (idCmd == RSVIDM_DELETE)
  272. {
  273. BOOL fRet = ConfirmDelete(pici->hwnd, _cItems, _ppooi);
  274. if (!fRet)
  275. return S_FALSE;
  276. } else if (idCmd == RSVIDM_UPDATE) {
  277. pClsid = (CLSID *)MemAlloc(LPTR, sizeof(CLSID) * _cItems);
  278. if (!pClsid)
  279. return E_OUTOFMEMORY;
  280. }
  281. for (i = 0; i < _cItems; i++)
  282. {
  283. if (_ppooi[i])
  284. {
  285. SUBSCRIPTIONTYPE subType;
  286. switch (idCmd)
  287. {
  288. case RSVIDM_OPEN:
  289. if (i >= MAX_ITEM_OPEN)
  290. {
  291. hres = S_FALSE;
  292. goto Done;
  293. }
  294. subType = GetItemCategory(&(_ppooi[i]->ooe));
  295. switch (subType) {
  296. case SUBSTYPE_URL:
  297. case SUBSTYPE_CHANNEL:
  298. case SUBSTYPE_DESKTOPURL:
  299. case SUBSTYPE_DESKTOPCHANNEL:
  300. hres = _LaunchApp(pici->hwnd,URL(&(_ppooi[i]->ooe)));
  301. break;
  302. default:
  303. break;
  304. }
  305. break;
  306. case RSVIDM_COPY:
  307. OleSetClipboard((IDataObject *)this);
  308. goto Done;
  309. case RSVIDM_DELETE:
  310. hres = DoDeleteSubscription(&(_ppooi[i]->ooe));
  311. if (SUCCEEDED(hres))
  312. _GenerateEvent(SHCNE_DELETE,(LPITEMIDLIST)(_ppooi[i]),NULL);
  313. break;
  314. case RSVIDM_PROPERTIES:
  315. {
  316. POOEntry pooe = &(_ppooi[i]->ooe);
  317. OOEBuf ooeBuf;
  318. int iRet;
  319. pooe->dwFlags = 0;
  320. CopyToOOEBuf(pooe, &ooeBuf);
  321. subType = GetItemCategory(&(_ppooi[i]->ooe));
  322. switch (subType) {
  323. case SUBSTYPE_URL:
  324. case SUBSTYPE_CHANNEL:
  325. case SUBSTYPE_DESKTOPCHANNEL:
  326. case SUBSTYPE_DESKTOPURL:
  327. case SUBSTYPE_EXTERNAL:
  328. iRet = _CreatePropSheet(pici->hwnd,&ooeBuf);
  329. break;
  330. default:
  331. goto Done;
  332. }
  333. if (iRet <= 0)
  334. goto Done;
  335. LPMYPIDL newPidl = NULL;
  336. hres = LoadSubscription(ooeBuf.m_URL, &newPidl);
  337. if (FAILED(hres)) {
  338. ASSERT(0);
  339. } else {
  340. ILFree((LPITEMIDLIST)_ppooi[i]);
  341. _ppooi[i] = newPidl;
  342. }
  343. }
  344. goto Done;
  345. case RSVIDM_UPDATE:
  346. {
  347. POOEntry pooe = &(_ppooi[i]->ooe);
  348. pClsid[updateCount] = pooe->m_Cookie;
  349. updateCount ++;
  350. }
  351. break;
  352. default:
  353. hres = E_FAIL;
  354. break;
  355. }
  356. }
  357. }
  358. if (idCmd == RSVIDM_UPDATE) {
  359. hres = SendUpdateRequests(pici->hwnd, pClsid, updateCount);
  360. MemFree(pClsid);
  361. }
  362. Done:
  363. return hres;
  364. }
  365. STDMETHODIMP COfflineObjectItem::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved,
  366. LPSTR pszName, UINT cchMax)
  367. {
  368. HRESULT hres = E_FAIL;
  369. // TraceMsg(TF_ALWAYS, TEXT("OOI/IContextMenu - GetCommandString() called."));
  370. if (uFlags == GCS_VERBA)
  371. {
  372. LPCSTR pszSrc = NULL;
  373. switch(idCmd)
  374. {
  375. case RSVIDM_OPEN:
  376. pszSrc = c_szOpen;
  377. break;
  378. case RSVIDM_COPY:
  379. pszSrc = c_szCopy;
  380. break;
  381. case RSVIDM_DELETE:
  382. pszSrc = c_szDelete;
  383. break;
  384. case RSVIDM_PROPERTIES:
  385. pszSrc = c_szProperties;
  386. break;
  387. }
  388. if (pszSrc)
  389. {
  390. lstrcpynA(pszName, pszSrc, cchMax);
  391. hres = NOERROR;
  392. }
  393. }
  394. else if (uFlags == GCS_HELPTEXTA)
  395. {
  396. switch(idCmd)
  397. {
  398. case RSVIDM_OPEN:
  399. case RSVIDM_RENAME:
  400. case RSVIDM_UPDATE:
  401. case RSVIDM_COPY:
  402. case RSVIDM_DELETE:
  403. case RSVIDM_PROPERTIES:
  404. MLLoadStringA((UINT)(IDS_SB_FIRST+idCmd), pszName, cchMax);
  405. hres = NOERROR;
  406. break;
  407. default:
  408. break;
  409. }
  410. }
  411. return hres;
  412. }
  413. // IQueryInfo Method
  414. HRESULT COfflineObjectItem::GetInfoTip(DWORD dwFlags, WCHAR ** ppwsz)
  415. {
  416. *ppwsz = NULL;
  417. int clen = lstrlen(STATUS(&(_ppooi[0]->ooe)))+1;
  418. *ppwsz = (LPOLESTR)SHAlloc(clen*sizeof(WCHAR)) ;
  419. if (!(*ppwsz)) {
  420. return E_OUTOFMEMORY;
  421. }
  422. MyStrToOleStrN(*ppwsz, clen, STATUS(&(_ppooi[0]->ooe)));
  423. return S_OK;
  424. }
  425. HRESULT COfflineObjectItem::GetInfoFlags(DWORD *pdwFlags)
  426. {
  427. return E_NOTIMPL;
  428. }
  429. // IDataObject Methods...
  430. HRESULT COfflineObjectItem::GetData(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM)
  431. {
  432. HRESULT hres;
  433. #ifdef DEBUG
  434. TCHAR szName[64];
  435. if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
  436. wsprintf(szName, TEXT("#%d"), pFEIn->cfFormat);
  437. TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - GetData(%s)", szName);
  438. #endif
  439. pSTM->hGlobal = NULL;
  440. pSTM->pUnkForRelease = NULL;
  441. if ((pFEIn->cfFormat == g_cfPrefDropEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
  442. hres = _CreatePrefDropEffect(pSTM);
  443. else if ((pFEIn->cfFormat == g_cfFileDescriptor) && (pFEIn->tymed & TYMED_HGLOBAL))
  444. hres = _CreateFileDescriptor(pSTM);
  445. else if ((pFEIn->cfFormat == g_cfFileContents) && (pFEIn->tymed & TYMED_ISTREAM))
  446. hres = _CreateFileContents(pSTM, pFEIn->lindex);
  447. else if ((pFEIn->cfFormat == g_cfURL || pFEIn->cfFormat == CF_TEXT) && (pFEIn->tymed & TYMED_HGLOBAL))
  448. hres = _CreateURL(pSTM);
  449. else
  450. hres = DATA_E_FORMATETC;
  451. return hres;
  452. }
  453. HRESULT COfflineObjectItem::GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  454. {
  455. // TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - GetDataHere() called."));
  456. return E_NOTIMPL;
  457. }
  458. HRESULT COfflineObjectItem::QueryGetData(LPFORMATETC pFEIn)
  459. {
  460. #ifdef DEBUG
  461. TCHAR szName[64];
  462. if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
  463. wsprintf(szName, TEXT("#%d"), pFEIn->cfFormat);
  464. #endif
  465. if (pFEIn->cfFormat == g_cfPrefDropEffect ||
  466. pFEIn->cfFormat == g_cfFileDescriptor ||
  467. pFEIn->cfFormat == g_cfFileContents ||
  468. pFEIn->cfFormat == g_cfURL ||
  469. pFEIn->cfFormat == CF_TEXT
  470. ) {
  471. #ifdef DEBUG
  472. TraceMsg(TF_ALWAYS, "\t%s format supported.", szName);
  473. #endif
  474. return NOERROR;
  475. }
  476. return S_FALSE;
  477. }
  478. HRESULT COfflineObjectItem::GetCanonicalFormatEtc(LPFORMATETC pFEIn, LPFORMATETC pFEOut)
  479. {
  480. // TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - GetCanonicalFormatEtc() called."));
  481. return DATA_S_SAMEFORMATETC;
  482. }
  483. HRESULT COfflineObjectItem::SetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM, BOOL fRelease)
  484. {
  485. TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - SetData() called.");
  486. return E_NOTIMPL;
  487. }
  488. HRESULT COfflineObjectItem::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC *ppEnum)
  489. {
  490. FORMATETC objectfmte[5] = {
  491. {(CLIPFORMAT) g_cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  492. {(CLIPFORMAT) g_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM },
  493. {(CLIPFORMAT) g_cfPrefDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  494. {(CLIPFORMAT) g_cfURL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  495. {(CLIPFORMAT) CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
  496. };
  497. HRESULT hres;
  498. TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - EnumFormatEtc() called.");
  499. hres = SHCreateStdEnumFmtEtc(ARRAYSIZE(objectfmte), objectfmte, ppEnum);
  500. TraceMsg(TF_SUBSFOLDER, "\t- EnumFormatEtc() return %d.", hres);
  501. return hres;
  502. }
  503. HRESULT COfflineObjectItem::DAdvise(LPFORMATETC pFE, DWORD grfAdv, LPADVISESINK pAdvSink,
  504. LPDWORD pdwConnection)
  505. {
  506. TraceMsg(TF_SUBSFOLDER, "COfflineObjectItem - DAdvise() called.");
  507. return OLE_E_ADVISENOTSUPPORTED;
  508. }
  509. HRESULT COfflineObjectItem::DUnadvise(DWORD dwConnection)
  510. {
  511. // TraceMsg(TF_SUBSFOLDER, TEXT("COfflineObjectItem - DUnAdvise() called."));
  512. return OLE_E_ADVISENOTSUPPORTED;
  513. }
  514. HRESULT COfflineObjectItem::EnumDAdvise(LPENUMSTATDATA *ppEnum)
  515. {
  516. // TraceMsg(TF_ALWAYS, TEXT("COfflineObjectItem - EnumAdvise() called."));
  517. return OLE_E_ADVISENOTSUPPORTED;
  518. }
  519. //////////////////////////////////////////////////////////////////////////////
  520. //
  521. // Helper Routines
  522. //
  523. //////////////////////////////////////////////////////////////////////////////
  524. HRESULT COfflineObjectItem::_CreatePrefDropEffect(LPSTGMEDIUM pSTM)
  525. {
  526. pSTM->tymed = TYMED_HGLOBAL;
  527. pSTM->pUnkForRelease = NULL;
  528. TraceMsg(TF_SUBSFOLDER, "OOI/CreatePrefDropEffect");
  529. pSTM->hGlobal = MemAlloc(LPTR, sizeof(DWORD));
  530. // FEATURE: Need category specific code.
  531. DWORD prefEffect = DROPEFFECT_COPY;
  532. if (pSTM->hGlobal)
  533. {
  534. *((LPDWORD)pSTM->hGlobal) = prefEffect;
  535. return S_OK;
  536. }
  537. return E_OUTOFMEMORY;
  538. }
  539. HRESULT COfflineObjectItem::_CreateURL(LPSTGMEDIUM pSTM)
  540. {
  541. LPTSTR pszURL = URL(&(((LPMYPIDL)_ppooi[0])->ooe));
  542. int cchAlloc = (lstrlen(pszURL) + 1) * 2;
  543. pSTM->tymed = TYMED_HGLOBAL;
  544. pSTM->pUnkForRelease = NULL;
  545. pSTM->hGlobal = MemAlloc(LPTR, cchAlloc);
  546. if (pSTM->hGlobal)
  547. {
  548. SHTCharToAnsi(pszURL, (LPSTR)pSTM->hGlobal, cchAlloc);
  549. return S_OK;
  550. }
  551. return E_OUTOFMEMORY;
  552. }
  553. HRESULT COfflineObjectItem::_CreateFileContents(LPSTGMEDIUM pSTM, LONG lindex)
  554. {
  555. HRESULT hr;
  556. LONG iIndex;
  557. // make sure the index is in a valid range.
  558. if (lindex == -1)
  559. {
  560. if (_cItems == 1)
  561. lindex = 0;
  562. else
  563. return E_FAIL;
  564. }
  565. Assert((unsigned)lindex < _cItems);
  566. Assert(lindex >= 0);
  567. iIndex = lindex;
  568. pSTM->tymed = TYMED_ISTREAM;
  569. pSTM->pUnkForRelease = NULL;
  570. hr = CreateStreamOnHGlobal(NULL, TRUE, &pSTM->pstm);
  571. if (SUCCEEDED(hr))
  572. {
  573. LARGE_INTEGER li = {0L, 0L};
  574. IUniformResourceLocator *purl;
  575. hr = SHCoCreateInstance(NULL, &CLSID_InternetShortcut, NULL,
  576. IID_IUniformResourceLocator, (void **)&purl);
  577. if (SUCCEEDED(hr))
  578. {
  579. hr = purl->SetURL(URL(&(_ppooi[iIndex]->ooe)), TRUE);
  580. if (SUCCEEDED(hr))
  581. {
  582. IPersistStream *pps;
  583. hr = purl->QueryInterface(IID_IPersistStream, (LPVOID *)&pps);
  584. if (SUCCEEDED(hr))
  585. {
  586. hr = pps->Save(pSTM->pstm, TRUE);
  587. pps->Release();
  588. }
  589. }
  590. purl->Release();
  591. }
  592. pSTM->pstm->Seek(li, STREAM_SEEK_SET, NULL);
  593. }
  594. return hr;
  595. }
  596. HRESULT COfflineObjectItem::_CreateFileDescriptor(LPSTGMEDIUM pSTM)
  597. {
  598. FILEGROUPDESCRIPTOR *pfgd;
  599. // render the file descriptor
  600. // we only allocate for _cItems-1 file descriptors because the filegroup
  601. // descriptor has already allocated space for 1.
  602. pSTM->tymed = TYMED_HGLOBAL;
  603. pSTM->pUnkForRelease = NULL;
  604. pfgd = (FILEGROUPDESCRIPTOR *)MemAlloc(LPTR, sizeof(FILEGROUPDESCRIPTOR) + (_cItems-1) * sizeof(FILEDESCRIPTOR));
  605. if (pfgd == NULL)
  606. {
  607. TraceMsg(TF_ALWAYS, "ooi - Couldn't alloc file descriptor");
  608. return E_OUTOFMEMORY;
  609. }
  610. pfgd->cItems = _cItems;
  611. for (UINT i = 0; i < _cItems; i++)
  612. {
  613. FILEDESCRIPTOR *pfd = &(pfgd->fgd[i]);
  614. StrCpyN(pfd->cFileName, NAME(&(_ppooi[i]->ooe)), ARRAYSIZE(pfd->cFileName));
  615. int len = lstrlen(pfd->cFileName);
  616. StrCpyN(pfd->cFileName + len, TEXT(".URL"), ARRAYSIZE(pfd->cFileName) - len);
  617. }
  618. pSTM->hGlobal = pfgd;
  619. return S_OK;
  620. }
  621. #ifdef UNICODE
  622. // IExtractIconA members
  623. HRESULT COfflineObjectItem::GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
  624. {
  625. return IExtractIcon_GetIconLocationThunk((IExtractIconW *)this, uFlags, szIconFile, cchMax, piIndex, pwFlags);
  626. }
  627. HRESULT COfflineObjectItem::Extract(LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
  628. {
  629. return IExtractIcon_ExtractThunk((IExtractIconW *)this, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
  630. }
  631. #endif
  632. HRESULT COfflineObjectItem::GetIconLocation(UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
  633. {
  634. ASSERT (piIndex && pwFlags);
  635. StrCpyN(szIconFile, TEXT("not used"), cchMax);
  636. SUBSCRIPTIONTYPE subType = GetItemCategory(&(_ppooi[0]->ooe));
  637. switch (subType) {
  638. case SUBSTYPE_URL:
  639. *piIndex = 10;
  640. break;
  641. case SUBSTYPE_CHANNEL:
  642. *piIndex = 11;
  643. break;
  644. case SUBSTYPE_DESKTOPCHANNEL:
  645. case SUBSTYPE_DESKTOPURL:
  646. *piIndex = 12;
  647. break;
  648. default:
  649. *piIndex = 13; // Unknown!
  650. break;
  651. }
  652. *pwFlags |= GIL_NOTFILENAME | GIL_PERINSTANCE | GIL_DONTCACHE;
  653. return NOERROR;
  654. }
  655. HRESULT COfflineObjectItem::Extract(LPCTSTR szIconFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
  656. {
  657. * phiconLarge = * phiconSmall = NULL;
  658. LoadDefaultIcons();
  659. SUBSCRIPTIONTYPE subType = GetItemCategory(&(_ppooi[0]->ooe));
  660. switch (subType) {
  661. case SUBSTYPE_URL:
  662. * phiconLarge = * phiconSmall = g_webCrawlerIcon;
  663. break;
  664. case SUBSTYPE_CHANNEL:
  665. * phiconLarge = * phiconSmall = g_channelIcon;
  666. break;
  667. case SUBSTYPE_DESKTOPURL:
  668. case SUBSTYPE_DESKTOPCHANNEL:
  669. * phiconLarge = * phiconSmall = g_desktopIcon;
  670. break;
  671. default:
  672. break;
  673. }
  674. if (!(*phiconLarge)) {
  675. if (_ppooi[0]->ooe.bDesktop)
  676. * phiconLarge = * phiconSmall = g_desktopIcon;
  677. else if (_ppooi[0]->ooe.bChannel)
  678. * phiconLarge = * phiconSmall = g_channelIcon;
  679. }
  680. return NOERROR;
  681. }