itemmenu.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 20k
Category:

Windows Kernel

Development Platform:

Visual C++

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