Leaked source code of windows server 2003
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

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