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.

897 lines
20 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // itemmenu.cpp
  4. //
  5. // IConextMenu for folder items.
  6. //
  7. // History:
  8. //
  9. // 3/26/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "itemmenu.h"
  18. #include "dll.h"
  19. #include "resource.h"
  20. #include <mluisupp.h>
  21. // In Shdocvw: shbrowse.cpp
  22. #ifndef UNIX
  23. extern HRESULT CDDEAuto_Navigate(BSTR str, HWND *phwnd, long lLaunchNewWindow);
  24. #else
  25. extern "C" HRESULT CDDEAuto_Navigate(BSTR str, HWND *phwnd, long lLaunchNewWindow);
  26. #endif /* UNIX */
  27. //
  28. // Constructor and destructor.
  29. //
  30. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  31. //
  32. // *** CContextMenu::CContextMenu ***
  33. //
  34. // Constructor for IContextMenu.
  35. //
  36. ////////////////////////////////////////////////////////////////////////////////
  37. CContextMenu::CContextMenu (
  38. PCDFITEMIDLIST* apcdfidl,
  39. LPITEMIDLIST pidlPath,
  40. UINT nCount
  41. )
  42. : m_cRef(1)
  43. {
  44. //
  45. // Copy the pcdfidls.
  46. //
  47. ASSERT(apcdfidl || 0 == nCount);
  48. ASSERT(NULL == m_apcdfidl);
  49. ASSERT(NULL == m_pidlPath);
  50. //
  51. // In low memory situations pidlPath may be NULL.
  52. //
  53. if (pidlPath)
  54. m_pidlPath = ILClone(pidlPath);
  55. IMalloc* pIMalloc;
  56. if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
  57. {
  58. ASSERT(pIMalloc);
  59. m_apcdfidl = (PCDFITEMIDLIST*)pIMalloc->Alloc(
  60. nCount * sizeof(PCDFITEMIDLIST));
  61. if (m_apcdfidl)
  62. {
  63. for (UINT i = 0, bOutOfMem = FALSE; (i < nCount) && !bOutOfMem; i++)
  64. {
  65. ASSERT(CDFIDL_IsValid(apcdfidl[i]));
  66. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)apcdfidl[i])));
  67. m_apcdfidl[i] = (PCDFITEMIDLIST)ILClone(
  68. (LPITEMIDLIST)apcdfidl[i]);
  69. if (bOutOfMem = (NULL == m_apcdfidl[i]))
  70. {
  71. while (i--)
  72. pIMalloc->Free(m_apcdfidl[i]);
  73. pIMalloc->Free(m_apcdfidl);
  74. m_apcdfidl = NULL;
  75. }
  76. else
  77. {
  78. ASSERT(CDFIDL_IsValid(m_apcdfidl[i]));
  79. }
  80. }
  81. }
  82. pIMalloc->Release();
  83. }
  84. m_nCount = m_apcdfidl ? nCount : 0;
  85. //
  86. // Don't allow the DLL to unload.
  87. //
  88. TraceMsg(TF_OBJECTS, "+ IContextMenu");
  89. DllAddRef();
  90. return;
  91. }
  92. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  93. //
  94. // *** CContextMenu::~CContextMenu ***
  95. //
  96. // Destructor.
  97. //
  98. ////////////////////////////////////////////////////////////////////////////////
  99. CContextMenu::~CContextMenu (
  100. void
  101. )
  102. {
  103. ASSERT(0 == m_cRef);
  104. //
  105. // Free the locally stored cdfidls.
  106. //
  107. if (m_apcdfidl)
  108. {
  109. IMalloc* pIMalloc;
  110. if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
  111. {
  112. ASSERT(pIMalloc);
  113. while (m_nCount--)
  114. {
  115. ASSERT(CDFIDL_IsValid(m_apcdfidl[m_nCount]));
  116. ASSERT(pIMalloc->DidAlloc(m_apcdfidl[m_nCount]));
  117. pIMalloc->Free(m_apcdfidl[m_nCount]);
  118. }
  119. ASSERT(pIMalloc->DidAlloc(m_apcdfidl));
  120. pIMalloc->Free(m_apcdfidl);
  121. pIMalloc->Release();
  122. }
  123. }
  124. if (m_pidlPath)
  125. ILFree(m_pidlPath);
  126. //
  127. // Matching Release for the constructor Addref.
  128. //
  129. TraceMsg(TF_OBJECTS, "- IContextMenu");
  130. DllRelease();
  131. return;
  132. }
  133. //
  134. // IUnknown methods.
  135. //
  136. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  137. //
  138. // *** CContextMenu::CContextMenu ***
  139. //
  140. // CExtractIcon QI.
  141. //
  142. ////////////////////////////////////////////////////////////////////////////////
  143. STDMETHODIMP
  144. CContextMenu::QueryInterface (
  145. REFIID riid,
  146. void **ppv
  147. )
  148. {
  149. ASSERT(ppv);
  150. HRESULT hr;
  151. *ppv = NULL;
  152. if (IID_IUnknown == riid || IID_IContextMenu2 == riid)
  153. {
  154. *ppv = (IContextMenu2*)this;
  155. }
  156. else if (IID_IContextMenu == riid)
  157. {
  158. *ppv = (IContextMenu*)this;
  159. }
  160. if (*ppv)
  161. {
  162. ((IUnknown*)*ppv)->AddRef();
  163. hr = S_OK;
  164. }
  165. else
  166. {
  167. hr = E_NOINTERFACE;
  168. }
  169. ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
  170. return hr;
  171. }
  172. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  173. //
  174. // *** CContextMenu::AddRef ***
  175. //
  176. // CContextMenu AddRef.
  177. //
  178. ////////////////////////////////////////////////////////////////////////////////
  179. STDMETHODIMP_(ULONG)
  180. CContextMenu::AddRef (
  181. void
  182. )
  183. {
  184. ASSERT(m_cRef != 0);
  185. ASSERT(m_cRef < (ULONG)-1);
  186. return ++m_cRef;
  187. }
  188. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  189. //
  190. // *** CContextMenu::Release ***
  191. //
  192. // CContextMenu Release.
  193. //
  194. ////////////////////////////////////////////////////////////////////////////////
  195. STDMETHODIMP_(ULONG)
  196. CContextMenu::Release (
  197. void
  198. )
  199. {
  200. ASSERT (m_cRef != 0);
  201. ULONG cRef = --m_cRef;
  202. if (0 == cRef)
  203. delete this;
  204. return cRef;
  205. }
  206. //
  207. // IContextMenu methods.
  208. //
  209. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  210. //
  211. // *** CContextMenu::QueryContextMenu ***
  212. //
  213. //
  214. // Description:
  215. // Adds menu items to the given item's context menu.
  216. //
  217. // Parameters:
  218. // [In Out] hmenu - A handle to the menu. New items are inserted into
  219. // this menu
  220. // [In] indexMenu - Zero-based position at which to insert the first
  221. // menu item.
  222. // [In] idCmdFirst - Minimum value that can be used for a new menu item
  223. // identifier.
  224. // [In] idCmdLast - Maximum value the can be used for a menu item id.
  225. // [In] uFlags - CMF_DEFAULTONLY, CMF_EXPLORE, CMF_NORMAL or
  226. // CMF_VERBSONLY.
  227. //
  228. // Return:
  229. // On success the scode contains the the menu identifier offset of the last
  230. // menu item added plus one.
  231. //
  232. // Comments:
  233. // CMF_DEFAULTONLY flag indicates the user double-clicked on the item. In
  234. // this case no menu is displayed. The shell is simply querying for the ID
  235. // of the default action.
  236. //
  237. ////////////////////////////////////////////////////////////////////////////////
  238. STDMETHODIMP
  239. CContextMenu::QueryContextMenu(
  240. HMENU hmenu,
  241. UINT indexMenu,
  242. UINT idCmdFirst,
  243. UINT idCmdLast,
  244. UINT uFlags
  245. )
  246. {
  247. ASSERT(hmenu);
  248. ASSERT(idCmdFirst < idCmdLast);
  249. HRESULT hr;
  250. if (CMF_DEFAULTONLY & uFlags)
  251. {
  252. ASSERT(idCmdFirst + IDM_OPEN < idCmdLast);
  253. InsertMenu(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst + IDM_OPEN,
  254. TEXT(""));
  255. SetMenuDefaultItem(hmenu, idCmdFirst + IDM_OPEN, FALSE);
  256. hr = S_OK;
  257. }
  258. else
  259. {
  260. ASSERT(idCmdFirst + IDM_PROPERTIES < idCmdLast);
  261. HMENU hmenuParent = LoadMenu(MLGetHinst(),
  262. MAKEINTRESOURCE(IDM_CONTEXTMENU));
  263. if (hmenuParent)
  264. {
  265. HMENU hmenuContext = GetSubMenu(hmenuParent, 0);
  266. if (hmenuContext)
  267. {
  268. ULONG idNew = Shell_MergeMenus(hmenu, hmenuContext, indexMenu,
  269. idCmdFirst, idCmdLast,
  270. MM_ADDSEPARATOR |
  271. MM_SUBMENUSHAVEIDS);
  272. SetMenuDefaultItem(hmenu, idCmdFirst + IDM_OPEN, FALSE);
  273. hr = 0x000ffff & idNew;
  274. DestroyMenu(hmenuContext);
  275. }
  276. else
  277. {
  278. hr = E_FAIL;
  279. }
  280. DestroyMenu(hmenuParent);
  281. }
  282. else
  283. {
  284. hr = E_FAIL;
  285. }
  286. }
  287. return hr;
  288. }
  289. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  290. //
  291. // *** CContextMenu::InvokeCommand ***
  292. //
  293. //
  294. // Description:
  295. // Carries out the command for the given menu item id.
  296. //
  297. // Parameters:
  298. // [In] lpici - Structure containing the verb, hwnd, menu id, etc.
  299. //
  300. // Return:
  301. // S_OK if the command was successful.
  302. // E_FAIL otherwise.
  303. //
  304. // Comments:
  305. //
  306. //
  307. ////////////////////////////////////////////////////////////////////////////////
  308. STDMETHODIMP
  309. CContextMenu::InvokeCommand(
  310. LPCMINVOKECOMMANDINFO lpici
  311. )
  312. {
  313. ASSERT(lpici);
  314. HRESULT hr;
  315. if (HIWORD(lpici->lpVerb))
  316. {
  317. hr = E_NOTIMPL;
  318. }
  319. else
  320. {
  321. WORD wCmd = LOWORD(lpici->lpVerb);
  322. switch(wCmd)
  323. {
  324. case IDM_OPEN:
  325. hr = DoOpen(lpici->hwnd, lpici->nShow);
  326. break;
  327. case IDM_PROPERTIES:
  328. hr = DoProperties(lpici->hwnd);
  329. break;
  330. default:
  331. hr = E_NOTIMPL;
  332. break;
  333. }
  334. }
  335. return hr;
  336. }
  337. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  338. //
  339. // *** CContextMenu::GetCommandString ***
  340. //
  341. //
  342. // Description:
  343. //
  344. //
  345. // Parameters:
  346. //
  347. //
  348. // Return:
  349. //
  350. //
  351. // Comments:
  352. // note -- return an ANSI command string
  353. //
  354. ////////////////////////////////////////////////////////////////////////////////
  355. STDMETHODIMP
  356. CContextMenu::GetCommandString(
  357. UINT_PTR idCommand,
  358. UINT uFlags,
  359. UINT *pwReserved,
  360. LPSTR pszName,
  361. UINT cchMax
  362. )
  363. {
  364. HRESULT hr = E_FAIL;
  365. if ((uFlags == GCS_VERB) && (idCommand == IDM_OPEN))
  366. {
  367. StrCpyN((LPTSTR)pszName, TEXT("open"), cchMax);
  368. hr = NOERROR;
  369. }
  370. #ifdef UNICODE
  371. else if ((uFlags == GCS_VERBA) && (idCommand == IDM_OPEN))
  372. {
  373. StrCpyNA(pszName, "open", cchMax);
  374. hr = NOERROR;
  375. }
  376. #endif
  377. return hr;
  378. }
  379. //
  380. // IContextMenu2 methods.
  381. //
  382. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  383. //
  384. // *** CContextMenu::HandleMenuMsg ***
  385. //
  386. //
  387. // Description:
  388. //
  389. //
  390. // Parameters:
  391. //
  392. //
  393. // Return:
  394. //
  395. //
  396. // Comments:
  397. //
  398. //
  399. ////////////////////////////////////////////////////////////////////////////////
  400. STDMETHODIMP
  401. CContextMenu::HandleMenuMsg(
  402. UINT uMsg,
  403. WPARAM wParam,
  404. LPARAM lParam
  405. )
  406. {
  407. return S_OK;
  408. }
  409. //
  410. // Helper functions.
  411. //
  412. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  413. //
  414. // *** CContextMenu::DoOpen ***
  415. //
  416. //
  417. // Description:
  418. // Command handler for IDM_OPEN.
  419. //
  420. // Parameters:
  421. // [In] hwnd - Parent window. Used for dialogs etc.
  422. // [In] nShow - ShowFlag use in ShowWindow command.
  423. //
  424. // Return:
  425. // S_OK if the command executed.
  426. // E_FAIL if the command iddn't execute.
  427. // E_OUTOFMEMORY if there wasn't enough memory to execute the command.
  428. //
  429. // Comments:
  430. //
  431. //
  432. ////////////////////////////////////////////////////////////////////////////////
  433. HRESULT
  434. CContextMenu::DoOpen(
  435. HWND hwnd,
  436. int nShow
  437. )
  438. {
  439. HRESULT hr;
  440. if (m_apcdfidl)
  441. {
  442. ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
  443. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
  444. if (CDFIDL_IsFolder(m_apcdfidl[0]))
  445. {
  446. hr = DoOpenFolder(hwnd, nShow);
  447. }
  448. else
  449. {
  450. hr = DoOpenStory(hwnd, nShow);
  451. }
  452. }
  453. else
  454. {
  455. hr = E_OUTOFMEMORY;
  456. }
  457. return hr;
  458. }
  459. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  460. //
  461. // *** CContextMenu::DoOpenFolder ***
  462. //
  463. //
  464. // Description:
  465. // Open command for folders.
  466. //
  467. // Parameters:
  468. // [In] hwnd - Parent window. Used for dialogs etc.
  469. // [In] nShow - ShowFlag use in ShowWindow command.
  470. //
  471. // Return:
  472. // S_OK if the command executed.
  473. // E_FAIL if the command iddn't execute.
  474. // E_OUTOFMEMORY if there wasn't enough memory to execute the command.
  475. //
  476. // Comments:
  477. //
  478. //
  479. ////////////////////////////////////////////////////////////////////////////////
  480. HRESULT
  481. CContextMenu::DoOpenFolder(
  482. HWND hwnd,
  483. int nShow
  484. )
  485. {
  486. HRESULT hr;
  487. if (m_pidlPath)
  488. {
  489. ASSERT(m_apcdfidl);
  490. ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
  491. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
  492. LPITEMIDLIST pidlFull = ILCombine(m_pidlPath,
  493. (LPITEMIDLIST)m_apcdfidl[0]);
  494. if (pidlFull)
  495. {
  496. SHELLEXECUTEINFO ei = {0};
  497. ei.cbSize = sizeof(SHELLEXECUTEINFO);
  498. ei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
  499. ei.hwnd = hwnd;
  500. ei.lpVerb = TEXT("Open");
  501. ei.nShow = nShow;
  502. ei.lpIDList = (LPVOID)pidlFull;
  503. ei.lpClass = TEXT("Folder");
  504. hr = ShellExecuteEx(&ei) ? S_OK : E_FAIL;
  505. ILFree(pidlFull);
  506. }
  507. else
  508. {
  509. hr = E_OUTOFMEMORY;
  510. }
  511. }
  512. else
  513. {
  514. hr = E_OUTOFMEMORY;
  515. }
  516. return hr;
  517. }
  518. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  519. //
  520. // *** CContextMenu::DoOpenStory ***
  521. //
  522. //
  523. // Description:
  524. // Open command for stories (internet links).
  525. //
  526. // Parameters:
  527. // [In] hwnd - Parent window. Used for dialogs etc.
  528. // [In] nShow - ShowFlag use in ShowWindow command.
  529. //
  530. // Return:
  531. // S_OK if ShellExecuteEx succeeded.
  532. // E_FAIL if ShellExecuteEx didn't succeed.
  533. //
  534. // Comments:
  535. //
  536. //
  537. ////////////////////////////////////////////////////////////////////////////////
  538. HRESULT
  539. CContextMenu::DoOpenStory(
  540. HWND hwnd,
  541. int nShow
  542. )
  543. {
  544. ASSERT(m_apcdfidl);
  545. ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
  546. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
  547. HRESULT hr = E_FAIL;
  548. LPTSTR pszURL = CDFIDL_GetURL(m_apcdfidl[0]);
  549. if (PathIsURL(pszURL))
  550. {
  551. WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  552. HWND hwndTemp = (HWND)-1;
  553. BSTR bstrURL;
  554. SHTCharToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL));
  555. bstrURL = SysAllocString(wszURL);
  556. if (bstrURL)
  557. {
  558. hr = CDDEAuto_Navigate(bstrURL, &hwndTemp, 0);
  559. SysFreeString(bstrURL);
  560. }
  561. else
  562. {
  563. hr = E_OUTOFMEMORY;
  564. }
  565. }
  566. return hr;
  567. }
  568. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  569. //
  570. // *** CContextMenu::DoProperties ***
  571. //
  572. //
  573. // Description:
  574. // Command handler for IDM_PROPERTIES.
  575. //
  576. // Parameters:
  577. // [In] hwnd - Parent window. Used for dialogs etc.
  578. //
  579. // Return:
  580. // S_OK if the command executed.
  581. // E_FAIL if the command iddn't execute.
  582. // E_OUTOFMEMORY if there wasn't enough memory to execute the command.
  583. //
  584. // Comments:
  585. // Uses the property pages of the InternetShortcut object.
  586. //
  587. ////////////////////////////////////////////////////////////////////////////////
  588. HRESULT
  589. CContextMenu::DoProperties(
  590. HWND hwnd
  591. )
  592. {
  593. HRESULT hr;
  594. if (m_apcdfidl)
  595. {
  596. ASSERT(CDFIDL_IsValid(m_apcdfidl[0]));
  597. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)m_apcdfidl[0])));
  598. IShellPropSheetExt* pIShellPropSheetExt;
  599. hr = QueryInternetShortcut(m_apcdfidl[0], IID_IShellPropSheetExt,
  600. (void**)&pIShellPropSheetExt);
  601. if (SUCCEEDED(hr))
  602. {
  603. ASSERT(pIShellPropSheetExt);
  604. PROPSHEETHEADER psh = {0};
  605. HPROPSHEETPAGE ahpage[MAX_PROP_PAGES];
  606. psh.dwSize = sizeof(PROPSHEETHEADER);
  607. psh.dwFlags = PSH_NOAPPLYNOW;
  608. psh.hwndParent = hwnd;
  609. psh.hInstance = MLGetHinst();
  610. psh.pszCaption = CDFIDL_GetName(m_apcdfidl[0]);
  611. psh.phpage = ahpage;
  612. hr = pIShellPropSheetExt->AddPages(AddPages_Callback, (LPARAM)&psh);
  613. if (SUCCEEDED(hr))
  614. {
  615. //
  616. // Property sheets are currently disabled. This is the only
  617. // API called in comctl32.dll so remove it to avoid a
  618. //dependency.
  619. //hr = (-1 == PropertySheet(&psh)) ? E_FAIL : S_OK;
  620. }
  621. pIShellPropSheetExt->Release();
  622. }
  623. }
  624. else
  625. {
  626. hr = E_OUTOFMEMORY;
  627. }
  628. return hr;
  629. }
  630. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  631. //
  632. // *** AddPages_Callback ***
  633. //
  634. //
  635. // Description:
  636. //
  637. //
  638. // Parameters:
  639. //
  640. //
  641. // Return:
  642. //
  643. //
  644. // Comments:
  645. //
  646. //
  647. ////////////////////////////////////////////////////////////////////////////////
  648. BOOL CALLBACK
  649. AddPages_Callback(
  650. HPROPSHEETPAGE hpage,
  651. LPARAM lParam
  652. )
  653. {
  654. ASSERT(hpage);
  655. ASSERT(lParam);
  656. BOOL bRet;
  657. PROPSHEETHEADER* ppsh = (PROPSHEETHEADER*)lParam;
  658. if (ppsh->nPages < MAX_PROP_PAGES)
  659. {
  660. ppsh->phpage[ppsh->nPages++] = hpage;
  661. bRet = TRUE;
  662. }
  663. else
  664. {
  665. bRet = FALSE;
  666. }
  667. return bRet;
  668. }
  669. //
  670. //
  671. //
  672. HRESULT CALLBACK
  673. MenuCallBack(
  674. IShellFolder* pIShellFolder,
  675. HWND hwndOwner,
  676. LPDATAOBJECT pdtobj,
  677. UINT uMsg,
  678. WPARAM wParam,
  679. LPARAM lParam
  680. )
  681. {
  682. return S_OK;
  683. }
  684. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  685. //
  686. // *** CCdfView::QueryInternetShortcut ***
  687. //
  688. //
  689. // Description:
  690. // Sets up an internet shorcut object for the given pidl.
  691. //
  692. // Parameters:
  693. // [In] pcdfidl - The shortcut object is created for the URL stored in this
  694. // cdf item id list.
  695. // [In] riid - The requested interface on the shortcut object.
  696. // [Out] ppvOut - A pointer that receives the interface.
  697. //
  698. // Return:
  699. // S_OK if the object is created and the interface is found.
  700. // A COM error code otherwise.
  701. //
  702. // Comments:
  703. //
  704. //
  705. ////////////////////////////////////////////////////////////////////////////////
  706. HRESULT
  707. CContextMenu::QueryInternetShortcut(
  708. PCDFITEMIDLIST pcdfidl,
  709. REFIID riid,
  710. void** ppvOut
  711. )
  712. {
  713. ASSERT(CDFIDL_IsValid(pcdfidl));
  714. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  715. ASSERT(ppvOut);
  716. HRESULT hr;
  717. *ppvOut = NULL;
  718. //
  719. // Only create a shell link object if the CDF contains an URL
  720. //
  721. if (*(CDFIDL_GetURL(pcdfidl)) != 0)
  722. {
  723. IShellLinkA * pIShellLink;
  724. hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  725. IID_IShellLinkA, (void**)&pIShellLink);
  726. if (SUCCEEDED(hr))
  727. {
  728. ASSERT(pIShellLink);
  729. #ifdef UNICODE
  730. CHAR szUrlA[INTERNET_MAX_URL_LENGTH];
  731. SHTCharToAnsi(CDFIDL_GetURL(pcdfidl), szUrlA, ARRAYSIZE(szUrlA));
  732. hr = pIShellLink->SetPath(szUrlA);
  733. #else
  734. hr = pIShellLink->SetPath(CDFIDL_GetURL(pcdfidl));
  735. #endif
  736. if (SUCCEEDED(hr))
  737. {
  738. //
  739. // The description ends up being the file name created.
  740. //
  741. TCHAR szPath[MAX_PATH];
  742. #ifdef UNICODE
  743. CHAR szPathA[MAX_PATH];
  744. #endif
  745. StrCpyN(szPath, CDFIDL_GetName(pcdfidl), ARRAYSIZE(szPath) - 5);
  746. StrCatBuff(szPath, TEXT(".url"), ARRAYSIZE(szPath));
  747. #ifdef UNICODE
  748. SHTCharToAnsi(szPath, szPathA, ARRAYSIZE(szPathA));
  749. pIShellLink->SetDescription(szPathA);
  750. #else
  751. pIShellLink->SetDescription(szPath);
  752. #endif
  753. hr = pIShellLink->QueryInterface(riid, ppvOut);
  754. }
  755. pIShellLink->Release();
  756. }
  757. }
  758. else
  759. {
  760. hr = E_FAIL;
  761. }
  762. ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
  763. return hr;
  764. }