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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. //#include "sdspatch.h"
  4. //#include "security.h"
  5. //#include "dutil.h"
  6. //#include <oleauto.h>    // For OLEAUT32.DLL
  7. #define TF_SHELLAUTO TF_CUSTOM1
  8. EXTERN_C const GUID IID_ISDGetPidl       = {0xc066d4e0, 0x6400, 0x11d0, 0x95, 0x25, 0x0, 0xa0, 0xc9, 0x1f, 0x38, 0x80};
  9. EXTERN_C const GUID IID_ICSDFolderItem   = {0xaae84a70, 0x40db, 0x11d0, 0x94, 0xeb, 0x0, 0xa0, 0xc9, 0x1f, 0x38, 0x80};
  10. #define CMD_ID_FIRST    1
  11. #define CMD_ID_LAST     0x7fff
  12. #define DEFINE_FLOAT_STUFF  // Do this because DATE is being used below
  13. //==========================================================================
  14. class CSDFolderItemVerbs;
  15. class CSDEnumFolderItemVerbs;
  16. class CSDFolderItemVerb;
  17. HRESULT CSDFolderItemVerbs_Create(CSDFldrItem *psdfi, FolderItemVerbs ** ppid);
  18. //==========================================================================
  19. // Folder item Verbs class definition
  20. class CSDFolderItemVerbs : public FolderItemVerbs,
  21.                             protected CImpIDispatch
  22. {
  23.     friend class CSDEnumFolderItemVerbs;
  24.     friend class CSDFolderItemVerb;
  25.     public:
  26.         ULONG           m_cRef; //Public for debug checks
  27.     protected:
  28.         CSDFldrItem  *m_psdfi;
  29.         HMENU           m_hmenu;
  30.         IContextMenu    *m_pcm;
  31.     public:
  32.         CSDFolderItemVerbs(CSDFldrItem *psdfi);
  33.         ~CSDFolderItemVerbs(void);
  34.         BOOL         Init(void);
  35.         //IUnknown methods
  36.         STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  37.         STDMETHODIMP_(ULONG) AddRef(void);
  38.         STDMETHODIMP_(ULONG) Release(void);
  39.         //IDispatch members
  40.         virtual STDMETHODIMP GetTypeInfoCount(UINT * pctinfo)
  41.             { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
  42.         virtual STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  43.             { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
  44.         virtual STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
  45.             { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
  46.         virtual STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  47.             { return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
  48.         //FolderItemVerbs methods
  49.         STDMETHODIMP        get_Application(IDispatch **ppid);
  50.         STDMETHODIMP        get_Parent(IDispatch **ppid);
  51.         STDMETHODIMP        get_Count(long *plCount);
  52.         STDMETHODIMP        Item(VARIANT, FolderItemVerb**);
  53.         STDMETHODIMP        _NewEnum(IUnknown **);
  54. };
  55. class CSDEnumFolderItemVerbs : public IEnumVARIANT
  56. {
  57.     protected:
  58.         ULONG           m_cRef;
  59.         int             m_iCur;
  60.         CSDFolderItemVerbs   *m_psdfiv;
  61.     public:
  62.         CSDEnumFolderItemVerbs(CSDFolderItemVerbs *psdfiv);
  63.         ~CSDEnumFolderItemVerbs();
  64.         BOOL        Init();
  65.         //IUnknown members
  66.         STDMETHODIMP         QueryInterface(REFIID, LPVOID *);
  67.         STDMETHODIMP_(ULONG) AddRef(void);
  68.         STDMETHODIMP_(ULONG) Release(void);
  69.         //IEnumFORMATETC members
  70.         STDMETHODIMP Next(ULONG, VARIANT *, ULONG *);
  71.         STDMETHODIMP Skip(ULONG);
  72.         STDMETHODIMP Reset(void);
  73.         STDMETHODIMP Clone(IEnumVARIANT **);
  74. };
  75. HRESULT CSDFolderItemVerb_Create(CSDFolderItemVerbs *psdfivs, UINT id, FolderItemVerb **pfiv);
  76. class CSDFolderItemVerb : public FolderItemVerb,
  77.         protected CImpIDispatch
  78. {
  79.     public:
  80.         ULONG           m_cRef; //Public for debug checks
  81.     protected:
  82.         friend class CSDFolderItemVerbs;
  83.         CSDFolderItemVerbs  *m_psdfivs;
  84.         UINT                m_id;
  85.     public:
  86.         CSDFolderItemVerb(CSDFolderItemVerbs *psdfivs, UINT id);
  87.         ~CSDFolderItemVerb(void);
  88.         //IUnknown methods
  89.         STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  90.         STDMETHODIMP_(ULONG) AddRef(void);
  91.         STDMETHODIMP_(ULONG) Release(void);
  92.         //IDispatch members
  93.         virtual STDMETHODIMP GetTypeInfoCount(UINT * pctinfo)
  94.             { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
  95.         virtual STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  96.             { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
  97.         virtual STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
  98.             { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
  99.         virtual STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  100.             { return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
  101.         //FolderItem methods
  102.         STDMETHODIMP get_Application(IDispatch **ppid);
  103.         STDMETHODIMP get_Parent(IDispatch **ppid);
  104.         STDMETHODIMP get_Name(BSTR *pbs);
  105.         STDMETHODIMP DoIt();
  106.     protected:
  107. };
  108. //==========================================================================
  109. HRESULT CSDFldrItem_Create(CSDFolder *psdf, LPITEMIDLIST pidl, FolderItem **ppid)
  110. {
  111.     *ppid = NULL;
  112.     HRESULT hres = E_OUTOFMEMORY;
  113.     CSDFldrItem* psdfi = new CSDFldrItem(psdf);
  114.     if (psdfi)
  115.     {
  116.         if (psdfi->Init(pidl))
  117.         {
  118.             hres = psdfi->QueryInterface(IID_FolderItem, (void **)ppid);
  119.             if (SUCCEEDED(hres))
  120.                 psdf->_GetShellFolder();
  121.         }
  122.         psdfi->Release();
  123.     }
  124.     return hres;
  125. }
  126. CSDFldrItem::CSDFldrItem(CSDFolder *psdf) :
  127.     m_cRef(1), m_psdf(psdf), m_pidl(NULL),
  128.     CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_FolderItem)
  129. {
  130.     m_psdf->AddRef();
  131.     DllAddRef();
  132. }
  133. CSDFldrItem::~CSDFldrItem(void)
  134. {
  135.     if (m_pidl)
  136.         ILFree(m_pidl);
  137.     m_psdf->Release();
  138.     DllRelease();
  139. }
  140. BOOL CSDFldrItem::Init(LPITEMIDLIST pidl)
  141. {
  142.     TraceMsg(TF_SHELLAUTO, "CSDFldrItem::Init called");
  143.     m_pidl = ILClone(pidl);
  144.     if (!m_pidl)
  145.         return FALSE;
  146.     return TRUE;
  147. }
  148. STDMETHODIMP CSDFldrItem::QueryInterface(REFIID riid, void **ppv)
  149. {
  150.     static const QITAB qit[] = {
  151.         QITABENT(CSDFldrItem, FolderItem),
  152.         QITABENTMULTI(CSDFldrItem, IDispatch, FolderItem),
  153.         QITABENTMULTI(CSDFldrItem, ICSDFolderItem, FolderItem),
  154.         QITABENT(CSDFldrItem, ISDGetPidl),
  155.         QITABENT(CSDFldrItem, IObjectSafety),
  156.         { 0 },
  157.     };
  158.     return QISearch(this, qit, riid, ppv);
  159. }
  160. STDMETHODIMP_(ULONG) CSDFldrItem::AddRef(void)
  161. {
  162.     return ++m_cRef;
  163. }
  164. STDMETHODIMP_(ULONG) CSDFldrItem::Release(void)
  165. {
  166.     if (0!=--m_cRef)
  167.         return m_cRef;
  168.     delete this;
  169.     return 0L;
  170. }
  171. //The FolderItem implementation
  172. STDMETHODIMP CSDFldrItem::get_Application(IDispatch **ppid)
  173. {
  174.     // Let the folder object handle security and reference counting of site, etc
  175.     return m_psdf->get_Application(ppid);
  176. }
  177. STDMETHODIMP CSDFldrItem::get_Parent(IDispatch **ppid)
  178. {
  179.     // Assume that the Folder object is the parent of this object...
  180.     HRESULT hres = m_psdf->QueryInterface(IID_IDispatch, (LPVOID*)ppid);
  181.     if (SUCCEEDED(hres) && _dwSafetyOptions)
  182.         hres = MakeSafeForScripting((IUnknown**)ppid);
  183.     return hres;
  184. }
  185. STDMETHODIMP CSDFldrItem::get_Name(BSTR *pbs)
  186. {
  187.     TraceMsg(TF_SHELLAUTO, "CSDFldrItem::Get_Name called");
  188.     *pbs = NULL;
  189.     STRRET strret;
  190.     if (SUCCEEDED(m_psdf->m_psf->GetDisplayNameOf(m_pidl, SHGDN_NORMAL, &strret)))
  191.     {
  192.         *pbs = StrRetToBStr(m_pidl, &strret);
  193.     }
  194.     return NOERROR;
  195. }
  196. STDMETHODIMP CSDFldrItem::put_Name(BSTR bs)
  197. {
  198.     HRESULT hres;
  199.     LPITEMIDLIST pidlOut;
  200.     if (_dwSafetyOptions && (!m_psdf || LocalZoneCheck(m_psdf->_punkSite) != S_OK))
  201.         return E_ACCESSDENIED;
  202.     hres = m_psdf->m_psf->SetNameOf(m_psdf->m_hwnd, m_pidl, bs, SHGDN_INFOLDER, &pidlOut);
  203.     if (SUCCEEDED(hres))
  204.     {
  205.         ILFree(m_pidl);
  206.         m_pidl = pidlOut;
  207.     }
  208.     return hres;
  209. }
  210. STDMETHODIMP CSDFldrItem::get_Path(BSTR *pbs)
  211. {
  212.     TraceMsg(TF_SHELLAUTO, "CSDFolderItem::Get_Path called");
  213.     *pbs = NULL;
  214.     STRRET strret;
  215.     if (SUCCEEDED(m_psdf->m_psf->GetDisplayNameOf(m_pidl, SHGDN_FORPARSING, &strret)))
  216.     {
  217.         *pbs = StrRetToBStr(m_pidl, &strret);
  218.     }
  219.     return NOERROR;
  220. }
  221. STDMETHODIMP CSDFldrItem::get_GetLink(IDispatch **ppid)
  222. {
  223.     TraceMsg(TF_SHELLAUTO, "CSDFldrItem::Get_GetLink called");
  224.     HRESULT hres = CSDShellLink_CreateIDispatch(m_psdf->m_hwnd, m_psdf->m_psf, m_pidl,  ppid);
  225.     if (SUCCEEDED(hres) && _dwSafetyOptions)
  226.         hres = MakeSafeForScripting((IUnknown**)ppid);
  227.     return hres;
  228. }
  229. STDMETHODIMP CSDFldrItem::get_GetFolder(IDispatch **ppid)
  230. {
  231.     // BUGBUG:: this should return Folder...
  232.     *ppid = NULL;
  233.     // If in Safe mode we fail this one...
  234.     if (_dwSafetyOptions && (!m_psdf || LocalZoneCheck(m_psdf->_punkSite) != S_OK))
  235.         return E_ACCESSDENIED;
  236.     CSDFolder *psf;
  237.     LPITEMIDLIST pidl = ILCombine(m_psdf->m_pidl, m_pidl);
  238.     if (pidl)
  239.     {
  240.         HRESULT hres = CSDFolder_Create(NULL, pidl, NULL, &psf);
  241.         if (SUCCEEDED(hres) && psf)
  242.         {
  243.             hres = psf->QueryInterface(IID_IDispatch, (LPVOID*)ppid);
  244.             psf->Release();
  245.             if (SUCCEEDED(hres) && _dwSafetyOptions)
  246.                 hres = MakeSafeForScripting((IUnknown**)ppid);
  247.         }
  248.         ILFree(pidl);
  249.         return hres;
  250.     }
  251.     return E_OUTOFMEMORY;
  252. }
  253. HRESULT CSDFldrItem::_CheckAttribute( ULONG ulAttrIn, VARIANT_BOOL * pb)
  254. {
  255.     ULONG ulAttr = ulAttrIn;
  256.     HRESULT hres;
  257.     *pb = FALSE;
  258.     if (SUCCEEDED(hres = m_psdf->m_psf->GetAttributesOf(1, (LPCITEMIDLIST*)&m_pidl, &ulAttr))
  259.             && (ulAttr & ulAttrIn))
  260.         *pb = TRUE;
  261.     return hres;
  262. }
  263. HRESULT CSDFldrItem::_GetUIObjectOf(REFIID riid, void **ppvOut)
  264. {
  265.     return m_psdf->m_psf->GetUIObjectOf(m_psdf->m_hwnd, 1, (LPCITEMIDLIST*)&m_pidl, riid, NULL, ppvOut);
  266. }
  267. STDMETHODIMP CSDFldrItem::get_IsLink(VARIANT_BOOL * pb)
  268. {
  269.     return _CheckAttribute(SFGAO_LINK, pb);
  270. }
  271. STDMETHODIMP CSDFldrItem::get_IsFolder(VARIANT_BOOL * pb)
  272. {
  273.     return _CheckAttribute(SFGAO_FOLDER, pb);
  274. }
  275. STDMETHODIMP CSDFldrItem::get_IsFileSystem(VARIANT_BOOL * pb)
  276. {
  277.     return _CheckAttribute(SFGAO_FILESYSTEM, pb);
  278. }
  279. STDMETHODIMP CSDFldrItem::get_IsBrowsable(VARIANT_BOOL * pb)
  280. {
  281.     return _CheckAttribute(SFGAO_BROWSABLE, pb);
  282. }
  283. STDMETHODIMP CSDFldrItem::get_ModifyDate(DATE *pdt)
  284. {
  285.     WIN32_FIND_DATA finddata;
  286.     if (SUCCEEDED(SHGetDataFromIDList(m_psdf->m_psf, m_pidl, SHGDFIL_FINDDATA, &finddata, sizeof(finddata))))
  287.     {
  288.         WORD wDosDate, wDosTime;
  289.         FILETIME filetime;
  290.         FileTimeToLocalFileTime(&finddata.ftLastWriteTime, &filetime);
  291.         FileTimeToDosDateTime(&filetime, &wDosDate, &wDosTime);
  292.         DosDateTimeToVariantTime(wDosDate, wDosTime, pdt);
  293.     }
  294.     return NOERROR;
  295. }
  296. STDMETHODIMP CSDFldrItem::put_ModifyDate(DATE dt)
  297. {
  298.     return E_NOTIMPL;
  299. }
  300. // BUGBUG:: Should see about getting larger numbers through
  301. STDMETHODIMP CSDFldrItem::get_Size(LONG *pul)
  302. {
  303.     WIN32_FIND_DATA finddata;
  304.     if (SUCCEEDED(SHGetDataFromIDList(m_psdf->m_psf, m_pidl, SHGDFIL_FINDDATA, &finddata, sizeof(finddata))))
  305.     {
  306.          *pul = (LONG)finddata.nFileSizeLow;
  307.     }
  308.     return NOERROR;
  309. }
  310. STDMETHODIMP CSDFldrItem::get_Type(BSTR *pbs)
  311. {
  312.     HRESULT hres;
  313.     *pbs = NULL;    // in case of error.
  314.     IShellDetails *psd = m_psdf->_GetShellDetails();
  315.     if (!psd)
  316.         return E_FAIL;
  317.     SHELLDETAILS sd;
  318.     if (SUCCEEDED(hres = psd->GetDetailsOf(m_pidl, 2, &sd)))
  319.     {
  320.         *pbs = StrRetToBStr(m_pidl, &sd.str);
  321.     }
  322.     return hres;
  323. }
  324. STDMETHODIMP CSDFldrItem::Verbs (FolderItemVerbs **ppfic)
  325. {
  326.     HRESULT hres = CSDFolderItemVerbs_Create(SAFECAST(this, CSDFldrItem*), ppfic);
  327.     if (SUCCEEDED(hres) && _dwSafetyOptions)
  328.         hres = MakeSafeForScripting((IUnknown**)ppfic);
  329.     return hres;
  330. }
  331. STDMETHODIMP CSDFldrItem::InvokeVerb(VARIANT vVerb)
  332. {
  333.     IContextMenu *pcm;
  334.     BOOL fDefaultVerb = TRUE;
  335.     TCHAR szCmd[128];
  336.     TCHAR   szURL[MAX_URL_STRING];
  337.     DWORD dwPolicy = 0, dwContext = 0;
  338.     BOOL  bSafeZone;
  339.     
  340.     bSafeZone = !_dwSafetyOptions || (m_psdf && LocalZoneCheck(m_psdf->_punkSite) == S_OK);
  341.     switch (vVerb.vt)
  342.     {
  343.     case VT_BSTR:
  344.         if (!bSafeZone)
  345.             return E_ACCESSDENIED;  // not allowed in safe mode
  346.         fDefaultVerb = FALSE;
  347.         SHUnicodeToTChar(vVerb.bstrVal, szCmd, ARRAYSIZE(szCmd));
  348.         break;
  349.     }
  350.     // Do a zones check 
  351.    if (!bSafeZone)
  352.    {
  353.        LPITEMIDLIST pidl = ILCombine(m_psdf->m_pidl, m_pidl);
  354.        if (pidl)
  355.        {
  356.            ILGetDisplayNameEx(NULL, pidl, szURL, SHGDN_FORPARSING);
  357.            ILFree(pidl);
  358.            ZoneCheckUrlEx(szURL, &dwPolicy, SIZEOF(dwPolicy), &dwContext, SIZEOF(dwContext), 
  359.                             URLACTION_SHELL_VERB, PUAF_NOUI, NULL);
  360.             dwPolicy = GetUrlPolicyPermissions(dwPolicy);
  361.             if (dwPolicy != URLPOLICY_ALLOW) 
  362.                 return E_ACCESSDENIED;  
  363.         }    
  364.     }
  365.     
  366.     // Start of only doing default verb...
  367.     if (SUCCEEDED(m_psdf->m_psf->GetUIObjectOf(m_psdf->m_hwnd, 1, (LPCITEMIDLIST*)&m_pidl, IID_IContextMenu, NULL, (LPVOID*)&pcm)) && pcm)
  368.     {
  369.         HMENU hmenu = CreatePopupMenu();
  370.         pcm->QueryContextMenu(hmenu, 0, CMD_ID_FIRST, CMD_ID_LAST, fDefaultVerb? CMF_DEFAULTONLY : CMF_CANRENAME);
  371.         int idCmd = 0;
  372.         if (fDefaultVerb)
  373.             idCmd = GetMenuDefaultItem(hmenu, MF_BYCOMMAND, 0);
  374.         else
  375.         {
  376.             // Lets try to find a verb that matches name:
  377.             // BUGBUG:: Right now must match & in verbs...
  378.             int i;
  379.             MENUITEMINFO mii;
  380.             TCHAR szText[128];    // should be big enough for this
  381.             for (i = GetMenuItemCount(hmenu)-1; i >= 0; i--)
  382.             {
  383.                 mii.cbSize = sizeof(MENUITEMINFO);
  384.                 mii.dwTypeData = szText;
  385.                 mii.fMask = MIIM_ID | MIIM_TYPE;
  386.                 mii.cch = ARRAYSIZE(szText);
  387.                 mii.fType = MFT_SEPARATOR;                // to avoid ramdom result.
  388.                 mii.dwItemData = 0;
  389.                 GetMenuItemInfo(hmenu, i, TRUE, &mii);
  390.                 if (lstrcmpi(szText, szCmd) == 0)
  391.                 {
  392.                     idCmd = mii.wID;
  393.                     break;
  394.                 }
  395.             }
  396.         }
  397.         if (idCmd)
  398.         {
  399.             CMINVOKECOMMANDINFO ici = {
  400.                 sizeof(CMINVOKECOMMANDINFO),
  401.                 0L,
  402.                 m_psdf->m_hwnd,
  403.                 NULL,
  404.                 NULL, NULL,
  405.                 SW_SHOWNORMAL,
  406.             };
  407.             ici.lpVerb = (LPSTR)MAKEINTRESOURCE(idCmd - CMD_ID_FIRST);
  408.             // Finally invoke the command
  409.             pcm->InvokeCommand(&ici);
  410.         }
  411.         DestroyMenu(hmenu);
  412.         pcm->Release();
  413.     }
  414.     return NOERROR;
  415. }
  416. STDMETHODIMP CSDFldrItem::GetPidl (LPITEMIDLIST *ppidl)
  417. {
  418.     *ppidl = ILClone(m_pidl);
  419.     if (*ppidl)
  420.         return NOERROR;
  421.     else
  422.     {
  423.         return E_OUTOFMEMORY;
  424.     }
  425. }
  426. //==========================================================================
  427. // Folder item verbs
  428. HRESULT CSDFolderItemVerbs_Create(CSDFldrItem *psdfi, FolderItemVerbs ** ppid)
  429. {
  430.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerbs_CreateIDispatch called");
  431.     *ppid = NULL;
  432.     CSDFolderItemVerbs* psdfiv = new CSDFolderItemVerbs(psdfi);
  433.     if (psdfiv)
  434.     {
  435.         if (!psdfiv->Init())
  436.         {
  437.             psdfiv->Release();
  438.             return E_OUTOFMEMORY;
  439.         }
  440.         HRESULT hres = psdfiv->QueryInterface(IID_FolderItemVerbs, (LPVOID *)ppid);
  441.         psdfiv->Release();
  442.         if (FAILED(hres))
  443.         {
  444.             *ppid = NULL;
  445.             return hres;
  446.         }
  447. return S_OK;
  448.     }
  449.     return E_OUTOFMEMORY;
  450. }
  451. /*
  452.  * CSDFolderItemVerbs::CSDFolderItemVerbs
  453.  * CSDFolderItemVerbs::~CSDFolderItemVerbs
  454.  *
  455.  * Constructor Parameters:
  456.  *  pCL             PCCosmoClient to the client object that we use
  457.  *                  to implement much of this interface.
  458.  */
  459. CSDFolderItemVerbs::CSDFolderItemVerbs(CSDFldrItem *psdfi) :
  460.     m_cRef(1), m_hmenu(NULL), m_pcm(NULL),
  461.     m_psdfi(psdfi), CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_FolderItemVerbs)
  462. {
  463.     DllAddRef();
  464.     m_psdfi->AddRef();
  465. }
  466. CSDFolderItemVerbs::~CSDFolderItemVerbs(void)
  467. {
  468.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerbs::~CSDFolderItemVerbs called");
  469.     DllRelease();
  470.     if (m_pcm)
  471.         m_pcm->Release();
  472.     if (m_hmenu)
  473.         DestroyMenu(m_hmenu);
  474.     m_psdfi->Release();
  475. }
  476. /*
  477.  * CSDFolderItemVerbs::Init
  478.  *
  479.  * Purpose:
  480.  *  Performs any intiailization of a CSDFolderItemVerbs that's prone to failure
  481.  *  that we also use internally before exposing the object outside.
  482.  *
  483.  * Parameters:
  484.  *  None
  485.  *
  486.  * Return Value:
  487.  *  BOOL            TRUE if the function is successful,
  488.  *                  FALSE otherwise.
  489.  */
  490. BOOL CSDFolderItemVerbs::Init()
  491. {
  492.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerbs::Init called");
  493.     // Start of only doing default verb...
  494.     if (SUCCEEDED(m_psdfi->_GetUIObjectOf(IID_IContextMenu, (LPVOID*)&m_pcm)) && m_pcm)
  495.     {
  496.         m_hmenu = CreatePopupMenu();
  497.         if (FAILED(m_pcm->QueryContextMenu(m_hmenu, 0, CMD_ID_FIRST, CMD_ID_LAST, 0)))
  498.             return FALSE;
  499.     }
  500.     else
  501.         return FALSE;
  502.     // Just for the heck of it, remove junk like sepearators from the menu...
  503.     int i;
  504.     MENUITEMINFO mii;
  505.     TCHAR szText[80];    // should be big enough for this
  506.     for (i = GetMenuItemCount(m_hmenu)-1; i >= 0; i--)
  507.     {
  508.         mii.cbSize = sizeof(MENUITEMINFO);
  509.         mii.dwTypeData = szText;
  510.         mii.fMask = MIIM_TYPE | MIIM_ID;
  511.         mii.cch = ARRAYSIZE(szText);
  512.         mii.fType = MFT_SEPARATOR;                // to avoid ramdom result.
  513.         mii.dwItemData = 0;
  514.         GetMenuItemInfo(m_hmenu, i, TRUE, &mii);
  515.         if (mii.fType & MFT_SEPARATOR)
  516.             DeleteMenu(m_hmenu, i, MF_BYPOSITION);
  517.     }
  518.     return TRUE;
  519. }
  520. STDMETHODIMP CSDFolderItemVerbs::QueryInterface(REFIID riid, void **ppv)
  521. {
  522.     static const QITAB qit[] = {
  523.         QITABENT(CSDFolderItemVerbs, FolderItemVerbs),
  524.         QITABENTMULTI(CSDFolderItemVerbs, IDispatch, FolderItemVerbs),
  525.         { 0 },
  526.     };
  527.     return QISearch(this, qit, riid, ppv);
  528. }
  529. STDMETHODIMP_(ULONG) CSDFolderItemVerbs::AddRef(void)
  530. {
  531.     return ++m_cRef;
  532. }
  533. STDMETHODIMP_(ULONG) CSDFolderItemVerbs::Release(void)
  534. {
  535.     if (0!=--m_cRef)
  536.         return m_cRef;
  537.     delete this;
  538.     return 0;
  539. }
  540. STDMETHODIMP CSDFolderItemVerbs::get_Application(IDispatch **ppid)
  541. {
  542.     // Walk it up the tree, it will get up to folder object that will cache the application object...
  543.     return m_psdfi->get_Application(ppid);
  544. }
  545. STDMETHODIMP CSDFolderItemVerbs::get_Parent(IDispatch **ppid)
  546. {
  547.     *ppid = NULL;
  548.     return E_NOTIMPL;
  549. }
  550. STDMETHODIMP CSDFolderItemVerbs::get_Count(long *plCount)
  551. {
  552.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerbs::Get_Count called");
  553.     *plCount = GetMenuItemCount(m_hmenu);
  554.     return NOERROR;
  555. }
  556. /*
  557.  * This is essentially an array lookup operator for the collection.
  558.  * Collection.Item by itself the same as the collection itself.
  559.  * Otherwise you can refer to the item by index or by path, which
  560.  * shows up in the VARIANT parameter.  We have to check the type
  561.  * of the variant to see if it's VT_I4 (an index) or VT_BSTR (a
  562.  * path) and do the right thing.
  563.  */
  564. STDMETHODIMP CSDFolderItemVerbs::Item(VARIANT index, FolderItemVerb **ppid)
  565. {
  566.     *ppid= NULL;
  567.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerbs::Get_Item called");
  568.     // This is sortof gross, but if we are passed a pointer to another variant, simply
  569.     // update our copy here...
  570.     if (index.vt == (VT_BYREF|VT_VARIANT) && index.pvarVal)
  571.         index = *index.pvarVal;
  572.     switch (index.vt)
  573.     {
  574.     case VT_ERROR:
  575.             /*
  576.              * No parameters, get the "Figures" collection
  577.              * IDispatch, which we can easily retrieve with
  578.              * our own QueryInterface.
  579.              */
  580.         QueryInterface(IID_IDispatch, (void **)ppid);
  581.         break;
  582.     case VT_I2:
  583.         index.lVal = (long)index.iVal;
  584.         // And fall through...
  585.     case VT_I4:
  586.         if ((index.lVal >= 0) && (index.lVal <= GetMenuItemCount(m_hmenu)))
  587.         {
  588.             if (FAILED(CSDFolderItemVerb_Create(this, GetMenuItemID(m_hmenu, index.lVal),
  589.                         ppid)))
  590.                 *ppid = NULL;
  591.         }
  592.         break;
  593. #ifdef LATER    // Should match strings in menu...
  594.     case VT_BSTR:
  595.         {
  596.             HRESULT hres;
  597.             ULONG ulEaten;
  598.             LPITEMIDLIST pidl;
  599.             hres = m_psdf->m_psf->ParseDisplayName(m_psdf->m_hwnd, NULL,
  600.                     (LPOLESTR)index.bstrVal, &ulEaten, &pidl, NULL);
  601.             if (SUCCEEDED(hres))
  602.             {
  603.                 hres = CSDFolderItemVerb_Create(this, GetMenuItemID(index.lVal), ppid);
  604.                 if (FAILED(hres))
  605.                     *ppid = NULL;
  606.             }
  607.             return hres;
  608.         }
  609.         break;
  610. #endif  // Later
  611.     default:
  612.         return E_NOTIMPL;
  613.     }
  614.     return NOERROR;
  615. }
  616. STDMETHODIMP CSDFolderItemVerbs::_NewEnum(IUnknown **ppunk)
  617. {
  618.     CSDEnumFolderItemVerbs *pNew = new CSDEnumFolderItemVerbs(SAFECAST(this, CSDFolderItemVerbs*));
  619.     if (NULL!=pNew)
  620.     {
  621.         if (!pNew->Init())
  622.         {
  623.             delete pNew;
  624.             pNew=NULL;
  625.         }
  626.     }
  627.     *ppunk = pNew;
  628.     return NOERROR;
  629. }
  630. CSDEnumFolderItemVerbs::CSDEnumFolderItemVerbs(CSDFolderItemVerbs *psdfiv) :
  631.     m_cRef(1), m_iCur(0), m_psdfiv(psdfiv)
  632. {
  633.     m_psdfiv->AddRef();
  634.     DllAddRef();
  635. }
  636. CSDEnumFolderItemVerbs::~CSDEnumFolderItemVerbs(void)
  637. {
  638.     DllRelease();
  639.     m_psdfiv->Release();
  640. }
  641. BOOL CSDEnumFolderItemVerbs::Init()
  642. {
  643.     // Currently no initialization needed
  644.     return TRUE;
  645. }
  646. STDMETHODIMP CSDEnumFolderItemVerbs::QueryInterface(REFIID riid, void **ppv)
  647. {
  648.     static const QITAB qit[] = {
  649.         QITABENT(CSDEnumFolderItemVerbs, IEnumVARIANT),
  650.         { 0 },
  651.     };
  652.     return QISearch(this, qit, riid, ppv);
  653. }
  654. STDMETHODIMP_(ULONG) CSDEnumFolderItemVerbs::AddRef(void)
  655. {
  656.     ++m_cRef;
  657.     return m_cRef;
  658. }
  659. STDMETHODIMP_(ULONG) CSDEnumFolderItemVerbs::Release(void)
  660. {
  661.     ULONG       cRefT;
  662.     cRefT=--m_cRef;
  663.     if (0L==m_cRef)
  664.         delete this;
  665.     return cRefT;
  666. }
  667. STDMETHODIMP CSDEnumFolderItemVerbs::Next(ULONG cVar, VARIANT *pVar, ULONG *pulVar)
  668. {
  669.     ULONG       cReturn=0L;
  670.     HRESULT     hr;
  671.     FolderItemVerb *pidv;
  672.     TraceMsg(TF_SHELLAUTO, "CSDEnumFolderItemVerbs::Next called");
  673.     if (!pulVar)
  674.     {
  675.         if (cVar != 1)
  676.             return E_POINTER;
  677.     }
  678.     else
  679.         *pulVar=0L;
  680.     if (!pVar || m_iCur >= GetMenuItemCount(m_psdfiv->m_hmenu))
  681.         return S_FALSE;
  682.     while (m_iCur < GetMenuItemCount(m_psdfiv->m_hmenu) && cVar > 0)
  683.     {
  684.         hr=CSDFolderItemVerb_Create(m_psdfiv, GetMenuItemID(m_psdfiv->m_hmenu, m_iCur), &pidv);
  685.         m_iCur++;
  686.         if (SUCCEEDED(hr))
  687.         {
  688.             pVar->pdispVal=pidv;
  689.             pVar->vt = VT_DISPATCH;
  690.             pVar++;
  691.             cReturn++;
  692.             cVar--;
  693.         }
  694.     }
  695.     if (NULL!=pulVar)
  696.         *pulVar=cReturn;
  697.     return NOERROR;
  698. }
  699. STDMETHODIMP CSDEnumFolderItemVerbs::Skip(ULONG cSkip)
  700. {
  701.     if ((int)(m_iCur+cSkip) >= GetMenuItemCount(m_psdfiv->m_hmenu))
  702.         return S_FALSE;
  703.     m_iCur+=cSkip;
  704.     return NOERROR;
  705. }
  706. STDMETHODIMP CSDEnumFolderItemVerbs::Reset(void)
  707. {
  708.     m_iCur=0;
  709.     return NOERROR;
  710. }
  711. STDMETHODIMP CSDEnumFolderItemVerbs::Clone(LPENUMVARIANT *ppEnum)
  712. {
  713.     *ppEnum = NULL;
  714.     HRESULT hres = E_OUTOFMEMORY;
  715.     CSDEnumFolderItemVerbs *pNew = new CSDEnumFolderItemVerbs(m_psdfiv);
  716.     if (pNew)
  717.     {
  718.         if (pNew->Init())
  719.         {
  720.             hres = pNew->QueryInterface(IID_IEnumVARIANT, (void **)ppEnum);
  721.         }
  722.         pNew->Release();
  723.     }
  724.     return hres;
  725. }
  726. //==========================================================================
  727. // Implemention of the FolderItemVerb...
  728. HRESULT CSDFolderItemVerb_Create( CSDFolderItemVerbs *psdfivs, UINT id, FolderItemVerb ** ppid)
  729. {
  730.     *ppid = NULL;
  731.     HRESULT hres = E_OUTOFMEMORY;
  732.     CSDFolderItemVerb* psdfiv = new CSDFolderItemVerb(psdfivs, id);
  733.     if (psdfiv)
  734.     {
  735.         hres = psdfiv->QueryInterface(IID_FolderItemVerb, (void **)ppid);
  736.         psdfiv->Release();
  737.     }
  738.     return hres;
  739. }
  740. CSDFolderItemVerb::CSDFolderItemVerb(CSDFolderItemVerbs *psdfivs, UINT id) :
  741.     m_cRef(1), m_psdfivs(psdfivs), m_id(id),
  742.     CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_FolderItemVerbs)
  743. {
  744.     m_psdfivs->AddRef();
  745.     DllAddRef();
  746. }
  747. CSDFolderItemVerb::~CSDFolderItemVerb(void)
  748. {
  749.     DllRelease();
  750.     TraceMsg(TF_SHELLAUTO, "CSDFolderItemVerb::~CSDFolderItemVerb called");
  751.     m_psdfivs->Release();
  752. }
  753. STDMETHODIMP CSDFolderItemVerb::QueryInterface(REFIID riid, void **ppv)
  754. {
  755.     static const QITAB qit[] = {
  756.         QITABENT(CSDFolderItemVerb, FolderItemVerb),
  757.         QITABENTMULTI(CSDFolderItemVerb, IDispatch, FolderItemVerb),
  758.         { 0 },
  759.     };
  760.     return QISearch(this, qit, riid, ppv);
  761. }
  762. STDMETHODIMP_(ULONG) CSDFolderItemVerb::AddRef(void)
  763. {
  764.     return ++m_cRef;
  765. }
  766. STDMETHODIMP_(ULONG) CSDFolderItemVerb::Release(void)
  767. {
  768.     //CCosmoClient deletes this object during shutdown
  769.     if (0!=--m_cRef)
  770.         return m_cRef;
  771.     delete this;
  772.     return 0L;
  773. }
  774. STDMETHODIMP CSDFolderItemVerb::get_Application(IDispatch **ppid)
  775. {
  776.     // walk this up the chain to get to FOLDER
  777.     return m_psdfivs->get_Application(ppid);
  778. }
  779. STDMETHODIMP CSDFolderItemVerb::get_Parent(IDispatch **ppid)
  780. {
  781.     *ppid = NULL;
  782.     return E_NOTIMPL;
  783. }
  784. STDMETHODIMP CSDFolderItemVerb::get_Name(BSTR *pbs)
  785. {
  786.     TCHAR szMenuText[MAX_PATH];
  787.     GetMenuString(m_psdfivs->m_hmenu, m_id, szMenuText, ARRAYSIZE(szMenuText), MF_BYCOMMAND);
  788.     *pbs = AllocBStrFromString(szMenuText);
  789.     return NOERROR;
  790. }
  791. STDMETHODIMP CSDFolderItemVerb::DoIt()
  792. {
  793.     CMINVOKECOMMANDINFO ici = {
  794.         sizeof(CMINVOKECOMMANDINFO),
  795.         0L,
  796.         NULL/* m_psdf->m_hwnd */,
  797.         NULL,
  798.         NULL, NULL,
  799.         SW_SHOWNORMAL,
  800.     };
  801.     ici.lpVerb = (LPSTR)MAKEINTRESOURCE(m_id - CMD_ID_FIRST);
  802.     return m_psdfivs->m_pcm->InvokeCommand(&ici);
  803. }