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.

790 lines
20 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // Chanmenu.cpp
  4. //
  5. // IConextMenu for folder items.
  6. //
  7. // History:
  8. //
  9. // 6/12/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "xmlutil.h"
  18. #include "chanmenu.h"
  19. #include "dll.h"
  20. #include "persist.h"
  21. #include "resource.h"
  22. #include "chanapi.h"
  23. #include "chanmgrp.h"
  24. #include "chanmgri.h"
  25. #define _SHDOCVW_
  26. #include <shdocvw.h>
  27. #include <mluisupp.h>
  28. #ifdef UNIX
  29. EXTERN_C char *MwGetXDisplayString( void );
  30. #ifdef UNICODE
  31. #define unixInvokeEditor unixInvokeEditorW
  32. #else
  33. #define unixInvokeEditor unixInvokeEditorA
  34. #endif /* UNICODE */
  35. static void unixInvokeEditorA(LPCSTR lpszPath)
  36. {
  37. HKEY hkeyUnix;
  38. CHAR szCommand [2*MAX_PATH];
  39. CHAR szCmdTempl[MAX_PATH+1];
  40. CHAR szName [MAX_PATH+1];
  41. CHAR hKeyName [MAX_PATH+1];
  42. STARTUPINFOA st;
  43. PROCESS_INFORMATION pi;
  44. BOOL bIsKnownEdit = FALSE;
  45. char displayString [2*MAX_PATH];
  46. DWORD editors = 0;
  47. DWORD type = REG_SZ;
  48. DWORD dwLength = sizeof(szCmdTempl);
  49. if( MwGetXDisplayString() )
  50. sprintf( displayString, "-display %s", MwGetXDisplayString() );
  51. else
  52. sprintf( displayString, " ");
  53. // Get user preferred editor.
  54. if( getenv("EDITOR" ) )
  55. strcpy(szName, getenv("EDITOR") );
  56. else
  57. strcpy(szName, "vi");
  58. // Check editor against the list of known editors in
  59. // registry.
  60. sprintf( hKeyName,
  61. "Software\\Microsoft\\Internet Explorer\\Unix\\Editors\\%s",
  62. szName );
  63. LONG lResult = RegOpenKeyExA(
  64. HKEY_CURRENT_USER,
  65. hKeyName,
  66. 0,
  67. KEY_QUERY_VALUE,
  68. &hkeyUnix);
  69. // Create proper command and append dissplay string to make the
  70. // editor appear on the same XServer as the Iexplorer.
  71. if( !bIsKnownEdit )
  72. {
  73. // Default use vi
  74. sprintf( szCommand, "xterm %s -e vi %s ", displayString, lpszPath );
  75. }
  76. else
  77. {
  78. // Use template command from registry to create actual command.
  79. sprintf( szCommand, szCmdTempl, displayString, lpszPath );
  80. }
  81. // Initialize startup info struct.
  82. st.cb = sizeof(STARTUPINFO);
  83. st.lpReserved = NULL;
  84. st.lpDesktop = NULL;
  85. st.lpTitle = NULL;
  86. st.dwFlags = 0;
  87. st.wShowWindow= SW_SHOWNORMAL;
  88. st.cbReserved2= 0;
  89. st.lpReserved2= NULL;
  90. // Launch the command
  91. if ( CreateProcessA( NULL, szCommand, NULL, NULL, TRUE,
  92. CREATE_NEW_CONSOLE, NULL, NULL, &st, &pi ))
  93. {
  94. return;
  95. }
  96. return;
  97. }
  98. static void unixInvokeEditorW(LPCWSTR lpwszPath)
  99. {
  100. char szFileName[MAX_PATH+2]; /* same as in ViewSource */
  101. SHUnicodeToAnsi(lpwszPath,szFileName, ARRAYSIZE(szFileName));
  102. unixInvokeEditorA(szFileName);
  103. return;
  104. }
  105. #endif /* UNIX */
  106. //
  107. // Constructor and destructor.
  108. //
  109. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  110. //
  111. // *** CContextMenu::CContextMenu ***
  112. //
  113. // Constructor for IContextMenu.
  114. //
  115. ////////////////////////////////////////////////////////////////////////////////
  116. CChannelMenu::CChannelMenu (
  117. void
  118. )
  119. : m_cRef(1)
  120. {
  121. TraceMsg(TF_OBJECTS, "+ IContextMenu (root)");
  122. DllAddRef();
  123. ASSERT(NULL == m_pSubscriptionMgr);
  124. ASSERT(NULL == m_bstrURL);
  125. ASSERT(NULL == m_bstrName);
  126. return;
  127. }
  128. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  129. //
  130. // *** CContextMenu::~CContextMenu ***
  131. //
  132. // Destructor.
  133. //
  134. ////////////////////////////////////////////////////////////////////////////////
  135. CChannelMenu::~CChannelMenu (
  136. void
  137. )
  138. {
  139. ASSERT(0 == m_cRef);
  140. if (NULL != m_bstrURL)
  141. SysFreeString(m_bstrURL);
  142. if (NULL != m_bstrName)
  143. SysFreeString(m_bstrName);
  144. if (NULL != m_pSubscriptionMgr)
  145. m_pSubscriptionMgr->Release();
  146. //
  147. // Matching Release for the constructor Addref.
  148. //
  149. TraceMsg(TF_OBJECTS, "- IContextMenu (root)");
  150. DllRelease();
  151. return;
  152. }
  153. //
  154. // IUnknown methods.
  155. //
  156. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  157. //
  158. // *** CContextMenu::CContextMenu ***
  159. //
  160. // CExtractIcon QI.
  161. //
  162. ////////////////////////////////////////////////////////////////////////////////
  163. STDMETHODIMP
  164. CChannelMenu::QueryInterface (
  165. REFIID riid,
  166. void **ppv
  167. )
  168. {
  169. ASSERT(ppv);
  170. HRESULT hr;
  171. *ppv = NULL;
  172. if (IID_IUnknown == riid || IID_IContextMenu == riid)
  173. {
  174. *ppv = (IContextMenu*)this;
  175. }
  176. else if (IID_IShellExtInit == riid)
  177. {
  178. *ppv = (IShellExtInit*)this;
  179. }
  180. if (*ppv)
  181. {
  182. ((IUnknown*)*ppv)->AddRef();
  183. hr = S_OK;
  184. }
  185. else
  186. {
  187. hr = E_NOINTERFACE;
  188. }
  189. ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
  190. return hr;
  191. }
  192. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  193. //
  194. // *** CContextMenu::AddRef ***
  195. //
  196. // CContextMenu AddRef.
  197. //
  198. ////////////////////////////////////////////////////////////////////////////////
  199. STDMETHODIMP_(ULONG)
  200. CChannelMenu::AddRef (
  201. void
  202. )
  203. {
  204. ASSERT(m_cRef != 0);
  205. ASSERT(m_cRef < (ULONG)-1);
  206. return ++m_cRef;
  207. }
  208. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  209. //
  210. // *** CContextMenu::Release ***
  211. //
  212. // CContextMenu Release.
  213. //
  214. ////////////////////////////////////////////////////////////////////////////////
  215. STDMETHODIMP_(ULONG)
  216. CChannelMenu::Release (
  217. void
  218. )
  219. {
  220. ASSERT (m_cRef != 0);
  221. ULONG cRef = --m_cRef;
  222. if (0 == cRef)
  223. delete this;
  224. return cRef;
  225. }
  226. //
  227. // IContextMenu methods.
  228. //
  229. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  230. //
  231. // *** CContextMenu::QueryContextMenu ***
  232. //
  233. //
  234. // Description:
  235. // Adds menu items to the given item's context menu.
  236. //
  237. // Parameters:
  238. // [In Out] hmenu - A handle to the menu. New items are inserted into
  239. // this menu
  240. // [In] indexMenu - Zero-based position at which to insert the first
  241. // menu item.
  242. // [In] idCmdFirst - Minimum value that can be used for a new menu item
  243. // identifier.
  244. // [In] idCmdLast - Maximum value the can be used for a menu item id.
  245. // [In] uFlags - CMF_DEFAULTONLY, CMF_EXPLORE, CMF_NORMAL or
  246. // CMF_VERBSONLY.
  247. //
  248. // Return:
  249. // On success the scode contains the the menu identifier offset of the last
  250. // menu item added plus one.
  251. //
  252. // Comments:
  253. // CMF_DEFAULTONLY flag indicates the user double-clicked on the item. In
  254. // this case no menu is displayed. The shell is simply querying for the ID
  255. // of the default action.
  256. //
  257. ////////////////////////////////////////////////////////////////////////////////
  258. STDMETHODIMP
  259. CChannelMenu::QueryContextMenu(
  260. HMENU hmenu,
  261. UINT indexMenu,
  262. UINT idCmdFirst,
  263. UINT idCmdLast,
  264. UINT uFlags
  265. )
  266. {
  267. HRESULT hr = S_OK;
  268. BOOL fSubscribed;
  269. HMENU hChannelMenu, hChannelSubMenu;
  270. ASSERT(hmenu);
  271. ASSERT(idCmdFirst < idCmdLast);
  272. if (!(CMF_DEFAULTONLY & uFlags))
  273. {
  274. if (NULL != m_pSubscriptionMgr)
  275. {
  276. ASSERT(idCmdFirst + IDM_SUBSCRIBE < idCmdLast);
  277. #ifndef UNIX
  278. if (CanSubscribe(m_bstrURL))
  279. {
  280. m_pSubscriptionMgr->IsSubscribed(m_bstrURL, &fSubscribed);
  281. if (fSubscribed)
  282. {
  283. hChannelMenu = LoadMenu(MLGetHinst(),
  284. MAKEINTRESOURCE(IDM_SUBSCRIBEDMENU));
  285. if (SHRestricted2W(REST_NoRemovingSubscriptions, m_bstrURL, 0))
  286. {
  287. EnableMenuItem(hChannelMenu, IDM_SUBSCRIBE,
  288. MF_BYCOMMAND | MF_GRAYED);
  289. }
  290. if (SHRestricted2W(REST_NoManualUpdates, m_bstrURL, 0))
  291. {
  292. EnableMenuItem(hChannelMenu, IDM_UPDATESUBSCRIPTION,
  293. MF_BYCOMMAND | MF_GRAYED);
  294. }
  295. }
  296. else
  297. {
  298. int idMenu = !SHRestricted2W(REST_NoAddingSubscriptions,
  299. m_bstrURL, 0)
  300. ? IDM_UNSUBSCRIBEDMENU : IDM_NOSUBSCRIBEMENU;
  301. hChannelMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(idMenu));
  302. }
  303. }
  304. else
  305. #endif /* !UNIX */
  306. {
  307. hChannelMenu = LoadMenu(MLGetHinst(),
  308. MAKEINTRESOURCE(IDM_NOSUBSCRIBEMENU));
  309. }
  310. if (NULL != hChannelMenu)
  311. {
  312. hChannelSubMenu = GetSubMenu(hChannelMenu, 0);
  313. if (NULL != hChannelSubMenu)
  314. {
  315. hr = Shell_MergeMenus(hmenu, hChannelSubMenu, indexMenu,
  316. idCmdFirst, idCmdLast, MM_ADDSEPARATOR)
  317. - idCmdFirst;
  318. }
  319. else
  320. {
  321. hr = E_FAIL;
  322. }
  323. DestroyMenu(hChannelMenu);
  324. }
  325. else
  326. {
  327. hr = E_FAIL;
  328. }
  329. }
  330. RemoveMenuItems(hmenu);
  331. }
  332. return hr;
  333. }
  334. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  335. //
  336. // *** CContextMenu::InvokeCommand ***
  337. //
  338. //
  339. // Description:
  340. // Carries out the command for the given menu item id.
  341. //
  342. // Parameters:
  343. // [In] lpici - Structure containing the verb, hwnd, menu id, etc.
  344. //
  345. // Return:
  346. // S_OK if the command was successful.
  347. // E_FAIL otherwise.
  348. //
  349. // Comments:
  350. //
  351. //
  352. ////////////////////////////////////////////////////////////////////////////////
  353. STDMETHODIMP
  354. CChannelMenu::InvokeCommand(
  355. LPCMINVOKECOMMANDINFO lpici
  356. )
  357. {
  358. HRESULT hr = S_OK;
  359. ASSERT(lpici);
  360. if (HIWORD(lpici->lpVerb) == 0)
  361. {
  362. switch (LOWORD(lpici->lpVerb))
  363. {
  364. case IDM_UPDATESUBSCRIPTION:
  365. ASSERT(NULL != m_pSubscriptionMgr);
  366. m_pSubscriptionMgr->UpdateSubscription(m_bstrURL);
  367. break;
  368. case IDM_SUBSCRIBE:
  369. ASSERT(NULL != m_pSubscriptionMgr);
  370. ASSERT( sizeof(SUBSCRIPTIONINFO) == m_si.cbSize);
  371. hr = Subscribe(lpici->hwnd);
  372. break;
  373. case IDM_UNSUBSCRIBE:
  374. ASSERT(NULL != m_pSubscriptionMgr);
  375. m_pSubscriptionMgr->DeleteSubscription(m_bstrURL, lpici->hwnd);
  376. break;
  377. case IDM_EDITSUBSCRIPTION:
  378. ASSERT(NULL != m_pSubscriptionMgr);
  379. m_pSubscriptionMgr->ShowSubscriptionProperties(m_bstrURL,
  380. lpici->hwnd);
  381. break;
  382. case IDM_REFRESHCHANNEL:
  383. Refresh(lpici->hwnd);
  384. break;
  385. case IDM_VIEWSOURCE:
  386. ViewSource(lpici->hwnd);
  387. break;
  388. }
  389. }
  390. return hr;
  391. }
  392. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  393. //
  394. // *** CContextMenu::GetCommandString ***
  395. //
  396. //
  397. // Description:
  398. //
  399. //
  400. // Parameters:
  401. //
  402. //
  403. // Return:
  404. //
  405. //
  406. // Comments:
  407. //
  408. //
  409. ////////////////////////////////////////////////////////////////////////////////
  410. STDMETHODIMP
  411. CChannelMenu::GetCommandString(
  412. UINT_PTR idCommand,
  413. UINT uFLags,
  414. UINT *pwReserved,
  415. LPSTR pszName,
  416. UINT cchMax
  417. )
  418. {
  419. return E_NOTIMPL;
  420. }
  421. //
  422. //
  423. //
  424. STDMETHODIMP
  425. CChannelMenu::Initialize(
  426. LPCITEMIDLIST pidl,
  427. LPDATAOBJECT pdobj,
  428. HKEY hkey
  429. )
  430. {
  431. HRESULT hr;
  432. STGMEDIUM stgmed;
  433. FORMATETC fmtetc = {CF_HDROP, NULL, DVASPECT_CONTENT, -1,
  434. TYMED_HGLOBAL};
  435. ASSERT(pdobj);
  436. hr = pdobj->GetData(&fmtetc, &stgmed);
  437. if (SUCCEEDED(hr))
  438. {
  439. if (DragQueryFile((HDROP)stgmed.hGlobal, 0, m_szPath,
  440. ARRAYSIZE(m_szPath)))
  441. {
  442. m_tt.cbTriggerSize = sizeof(TASK_TRIGGER);
  443. m_si.cbSize = sizeof(SUBSCRIPTIONINFO);
  444. m_si.fUpdateFlags |= SUBSINFO_SCHEDULE;
  445. m_si.schedule = SUBSSCHED_AUTO;
  446. m_si.pTrigger = &m_tt;
  447. hr = GetNameAndURLAndSubscriptionInfo(m_szPath, &m_bstrName, &m_bstrURL,
  448. &m_si);
  449. ASSERT((SUCCEEDED(hr) && m_bstrName && m_bstrURL) || FAILED(hr));
  450. }
  451. else
  452. {
  453. hr = E_FAIL;
  454. }
  455. ReleaseStgMedium(&stgmed);
  456. if (SUCCEEDED(hr))
  457. {
  458. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  459. CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr,
  460. (void**)&m_pSubscriptionMgr);
  461. }
  462. }
  463. // Return S_OK even if things didn't go as planned so that
  464. // RemoveMenus will get called.
  465. return S_OK;
  466. }
  467. //
  468. // Helper functions
  469. //
  470. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  471. //
  472. // *** Name ***
  473. //
  474. //
  475. // Description:
  476. //
  477. //
  478. // Parameters:
  479. //
  480. //
  481. // Return:
  482. //
  483. //
  484. // Comments:
  485. //
  486. //
  487. ////////////////////////////////////////////////////////////////////////////////
  488. void
  489. CChannelMenu::RemoveMenuItems(
  490. HMENU hmenu
  491. )
  492. {
  493. TCHAR aszRemove[4][62] = {{0}, {0}, {0}, {0}};
  494. MLLoadString(IDS_SHARING, aszRemove[0], ARRAYSIZE(aszRemove[0]));
  495. MLLoadString(IDS_RENAME, aszRemove[1], ARRAYSIZE(aszRemove[1]));
  496. MLLoadString(IDS_SENDTO, aszRemove[2], ARRAYSIZE(aszRemove[2]));
  497. if (SHRestricted2W(REST_NoEditingChannels, NULL, 0))
  498. MLLoadString(IDS_PROPERTIES, aszRemove[3], ARRAYSIZE(aszRemove[3]));
  499. TCHAR szBuffer[62];
  500. MENUITEMINFO mii;
  501. mii.cbSize = sizeof(MENUITEMINFO);
  502. mii.fMask = MIIM_TYPE;
  503. for (int i = GetMenuItemCount(hmenu) - 1; i >= 0; i--)
  504. {
  505. mii.dwTypeData = szBuffer;
  506. mii.cch = ARRAYSIZE(szBuffer);
  507. if (GetMenuItemInfo(hmenu, i, TRUE, &mii) && mii.cch)
  508. {
  509. for (int j = 0; j < ARRAYSIZE(aszRemove); j++)
  510. {
  511. if (StrEql(aszRemove[j], mii.dwTypeData))
  512. {
  513. DeleteMenu(hmenu, i, MF_BYPOSITION);
  514. break;
  515. }
  516. }
  517. }
  518. }
  519. return;
  520. }
  521. void CChannelMenu::Refresh(HWND hwnd)
  522. {
  523. IXMLDocument* pIXMLDocument;
  524. DLL_ForcePreloadDlls(PRELOAD_MSXML);
  525. HRESULT hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  526. IID_IXMLDocument, (void**)&pIXMLDocument);
  527. if (SUCCEEDED(hr))
  528. {
  529. ASSERT(pIXMLDocument);
  530. if (DownloadCdfUI(hwnd, m_bstrURL, pIXMLDocument))
  531. {
  532. UpdateImage(m_szPath);
  533. SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSH,
  534. (void*)m_szPath, NULL);
  535. }
  536. pIXMLDocument->Release();
  537. }
  538. }
  539. static TCHAR c_szFileProtocol[] = TEXT("file:");
  540. static TCHAR c_szCDFExtension[] = TEXT(".cdf");
  541. static TCHAR c_szShellEdit[] = TEXT("\\shell\\edit\\command");
  542. static TCHAR c_szEditVerb[] = TEXT("edit");
  543. static TCHAR c_szChannelFile[] = TEXT("ChannelFile");
  544. static TCHAR c_szChannelFileEdit[] = TEXT("ChannelFile\\shell\\edit\\command");
  545. static TCHAR c_szNotepad[] = TEXT("notepad.exe");
  546. void CChannelMenu::ViewSource(HWND hwnd)
  547. {
  548. TCHAR szProgId[64] = TEXT("");
  549. TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  550. TCHAR szFile[MAX_PATH + 2]; // Leave room for quotes
  551. DWORD cch, dwType;
  552. SHELLEXECUTEINFO sei;
  553. BOOL fFoundProg = FALSE;
  554. HRESULT hr = S_OK;
  555. TraceMsg(TF_OBJECTS, "+ IContextMenu ViewSource %ls", m_bstrURL);
  556. if (SHUnicodeToTChar(m_bstrURL, szBuf, ARRAYSIZE(szBuf)))
  557. {
  558. if (SUCCEEDED(URLGetLocalFileName(szBuf, szFile, ARRAYSIZE(szFile),
  559. NULL)))
  560. {
  561. if (StrCmpNI(szFile, c_szFileProtocol, 5) == 0)
  562. {
  563. ASSERT(ARRAYSIZE(szFile) < ARRAYSIZE(szBuf));
  564. StrCpy(szBuf, szFile);
  565. cch = ARRAYSIZE(szFile) - 2;
  566. hr = PathCreateFromUrl(szBuf, szFile, &cch, 0);
  567. }
  568. if (SUCCEEDED(hr))
  569. {
  570. PathQuoteSpaces(szFile);
  571. //
  572. // We don't just call ShellExec with edit verb since
  573. // who knows what the file extension will be.
  574. //
  575. cch = ARRAYSIZE(szProgId);
  576. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT,
  577. c_szCDFExtension,
  578. NULL, &dwType,
  579. szProgId, &cch)
  580. )
  581. {
  582. ASSERT(ARRAYSIZE(szProgId) < ARRAYSIZE(szBuf));
  583. StrCpy(szBuf, szProgId);
  584. ASSERT(ARRAYSIZE(szProgId) + ARRAYSIZE(c_szShellEdit) <
  585. ARRAYSIZE(szBuf));
  586. StrCat(szBuf, c_szShellEdit);
  587. cch = ARRAYSIZE(szBuf);
  588. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, szBuf,
  589. NULL, &dwType, szBuf, &cch)
  590. )
  591. {
  592. //
  593. // Getting here means they have an edit verb for CDF files
  594. //
  595. fFoundProg = TRUE;
  596. }
  597. }
  598. //
  599. // If we haven't found a class key yet and the CDF ProgID
  600. // isn't ours, then fall back to our edit verb.
  601. //
  602. if (!fFoundProg && StrCmpI(szProgId, c_szChannelFile))
  603. {
  604. cch = ARRAYSIZE(szBuf);
  605. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT,
  606. c_szChannelFileEdit,
  607. NULL, &dwType,
  608. szBuf, &cch)
  609. )
  610. {
  611. fFoundProg = TRUE;
  612. ASSERT(ARRAYSIZE(c_szChannelFile) < ARRAYSIZE(szProgId));
  613. StrCpy(szProgId, c_szChannelFile);
  614. }
  615. }
  616. memset(&sei, 0, sizeof(sei));
  617. sei.cbSize = sizeof(sei);
  618. sei.hwnd = hwnd;
  619. sei.nShow = SW_SHOW;
  620. if (fFoundProg)
  621. {
  622. sei.fMask = SEE_MASK_CLASSNAME;
  623. sei.lpVerb = c_szEditVerb;
  624. sei.lpFile = szFile;
  625. sei.lpClass = szProgId;
  626. TraceMsg(TF_OBJECTS, "IContextMenu ViewSource progid=%s file=%s", szProgId, szFile);
  627. }
  628. else
  629. {
  630. sei.lpFile = c_szNotepad;
  631. sei.lpParameters = szFile;
  632. TraceMsg(TF_OBJECTS, "IContextMenu ViewSource Notepad file=%s", szFile);
  633. }
  634. #ifndef UNIX
  635. ShellExecuteEx(&sei);
  636. #else
  637. unixInvokeEditor(szFile);
  638. #endif /* UNIX */
  639. }
  640. }
  641. else
  642. {
  643. CDFMessageBox(hwnd, IDS_ERROR_NO_CACHE_ENTRY, IDS_ERROR_DLG_TITLE,
  644. MB_OK | MB_ICONEXCLAMATION, szBuf);
  645. }
  646. }
  647. else
  648. {
  649. TraceMsg(TF_OBJECTS, "IContextMenu ViewSource couldn't convert to TSTR");
  650. }
  651. TraceMsg(TF_OBJECTS, "- IContextMenu ViewSource");
  652. }
  653. HRESULT CChannelMenu::Subscribe(HWND hwnd)
  654. {
  655. HRESULT hr = S_OK;
  656. CChannelMgr *pChannelMgr = new CChannelMgr;
  657. if (pChannelMgr)
  658. {
  659. hr = pChannelMgr->AddAndSubscribeEx2(hwnd, m_bstrURL, m_pSubscriptionMgr, TRUE);
  660. pChannelMgr->Release();
  661. if (SUCCEEDED(hr) && (NULL != m_pSubscriptionMgr))
  662. {
  663. hr = m_pSubscriptionMgr->UpdateSubscription(m_bstrURL);
  664. }
  665. }
  666. else
  667. {
  668. hr = E_OUTOFMEMORY;
  669. }
  670. return hr;
  671. }