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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "stdenum.h"
  4. #define DM_SDFOLDER 0
  5. // in DVOC.CPP
  6. extern DWORD GetViewOptionsForDispatch(void);
  7. //=====================================================================
  8. // ShellFolderView Class Definition...
  9. //=====================================================================
  10. class CShellFolderView :  public IShellFolderViewDual,
  11.                             public IShellService,
  12.                             public CObjectSafety,
  13.                             public CObjectWithSite, 
  14.                             protected CImpIConnectionPointContainer,
  15.                             protected CImpIExpDispSupport,
  16.                             protected CImpIDispatch
  17. {
  18. public:
  19.     CShellFolderView(void);
  20.     // IUnknown
  21.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  22.     STDMETHODIMP_(ULONG) AddRef(void);
  23.     STDMETHODIMP_(ULONG) Release(void);
  24.     // IDispatch
  25.     virtual STDMETHODIMP GetTypeInfoCount(UINT * pctinfo)
  26.         { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
  27.     virtual STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  28.         { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
  29.     virtual STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
  30.         { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
  31.     virtual STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr);
  32.     // ShellWindow
  33.     STDMETHODIMP get_Application(IDispatch **ppid);
  34.     STDMETHODIMP get_Parent(IDispatch **ppid);
  35.     STDMETHODIMP get_Folder(Folder **ppid);
  36.     STDMETHODIMP SelectedItems(FolderItems **ppid);
  37.     STDMETHODIMP get_FocusedItem(FolderItem **ppid);
  38.     STDMETHODIMP SelectItem(VARIANT *pvfi, int dwFlags);
  39.     STDMETHODIMP PopupItemMenu(FolderItem * pfi, VARIANT vx, VARIANT vy, BSTR * pbs);
  40.     STDMETHODIMP get_Script(IDispatch **ppid);
  41.     STDMETHODIMP get_ViewOptions(long *plSetting);
  42.     // IShellService methods.
  43.     STDMETHODIMP SetOwner(IUnknown* punkOwner);
  44.     // CImpIConnectionPoint
  45.     STDMETHODIMP EnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum);
  46.     // CObjectWithSite overriding
  47.     virtual STDMETHODIMP SetSite(IUnknown *punkSite);
  48. private:
  49.     ~CShellFolderView(void);
  50.     HRESULT _GetFolder();
  51.     // CImpIExpDispSupport
  52.     virtual CConnectionPoint* _FindCConnectionPointNoRef(BOOL fdisp, REFIID iid);
  53.     LONG m_cRef;
  54.     CFolder *m_psdf;        // The shell folder we talk to ...
  55.     IUnknown *m_punkOwner;   // The owner object of us...
  56.     IShellFolderView *m_psfvOwner;  // The owners Shell folder view...
  57.     HWND m_hwnd;         // the hwnd for the window...
  58.     // Embed our Connection Point object - implmentation in cnctnpt.cpp
  59.     CConnectionPoint m_cpEvents;
  60. };
  61. STDAPI CShellFolderView_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppvOut)
  62. {
  63.     *ppvOut = NULL;
  64.     HRESULT hr = E_OUTOFMEMORY;
  65.     CShellFolderView* psfv = new CShellFolderView();
  66.     if (psfv) 
  67.     {
  68.         hr = psfv->QueryInterface(riid, ppvOut);
  69.         psfv->Release();
  70.     }
  71.     return hr;
  72. }
  73. CShellFolderView::CShellFolderView(void) :
  74.         CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_IShellFolderViewDual), m_cRef(1), m_psdf(NULL)
  75. {
  76.     DllAddRef();
  77.     m_cpEvents.SetOwner((IUnknown*)SAFECAST(this, IShellFolderViewDual*), &DIID_DShellFolderViewEvents);
  78. }
  79. CShellFolderView::~CShellFolderView(void)
  80. {
  81.     TraceMsg(DM_SDFOLDER, "CShellFolderView::~CShellFolderView called");
  82.     // if we ever grabbed a shell folder for this window release it also
  83.     if (m_psdf)
  84.     {
  85.         m_psdf->SetSite(NULL);
  86.         m_psdf->Release();
  87.     }
  88.     ASSERT(m_punkOwner == NULL);
  89.     ASSERT(m_psfvOwner == NULL);
  90.     DllRelease();
  91. }
  92. STDMETHODIMP CShellFolderView::QueryInterface(REFIID riid, void **ppv)
  93. {
  94.     static const QITAB qit[] = {
  95.         QITABENT(CShellFolderView, IShellFolderViewDual),
  96.         QITABENTMULTI(CShellFolderView, IDispatch, IShellFolderViewDual),
  97.         QITABENT(CShellFolderView, IShellService),
  98.         QITABENT(CShellFolderView, IConnectionPointContainer),
  99.         QITABENT(CShellFolderView, IExpDispSupport),
  100.         QITABENT(CShellFolderView, IObjectSafety),
  101.         QITABENT(CShellFolderView, IObjectWithSite),
  102.         { 0 },
  103.     };
  104.     return QISearch(this, qit, riid, ppv);
  105. }
  106. STDMETHODIMP_(ULONG) CShellFolderView::AddRef(void)
  107. {
  108.     return ++m_cRef;
  109. }
  110. STDMETHODIMP_(ULONG) CShellFolderView::Release(void)
  111. {
  112.     //CCosmoClient deletes this object during shutdown
  113.     if (0 != --m_cRef)
  114.         return m_cRef;
  115.     delete this;
  116.     return 0L;
  117. }
  118. //The ShellWindow implementation
  119. // let folder we have handle this.  Probably won't work for webviews as this object
  120. // is not secure...
  121. STDMETHODIMP CShellFolderView::get_Application(IDispatch **ppid)
  122. {
  123.     HRESULT hres = _GetFolder();
  124.     if (SUCCEEDED(hres))
  125.         hres = m_psdf->get_Application(ppid);
  126.     return hres;
  127. }
  128. STDMETHODIMP CShellFolderView::get_Parent(IDispatch **ppid)
  129. {
  130.     *ppid = NULL;
  131.     return E_FAIL;
  132. }
  133. HRESULT CShellFolderView::_GetFolder()
  134. {
  135.     if (m_psdf)
  136.         return NOERROR;
  137.     HRESULT hres;
  138.     LPITEMIDLIST pidl = NULL;
  139.     IShellFolder *psf = NULL;
  140.     if (m_psfvOwner)
  141.     {
  142.         IDefViewFrame *pdvf;
  143.         if (SUCCEEDED(m_psfvOwner->QueryInterface(IID_IDefViewFrame, (void**)&pdvf)))
  144.         {
  145.             if (SUCCEEDED(pdvf->GetShellFolder(&psf)))
  146.             {
  147.                 if (SHGetIDListFromUnk(psf, &pidl) != S_OK)
  148.                 {
  149.                     psf->Release();
  150.                     psf = NULL;
  151.                 }
  152.             }
  153.             pdvf->Release();
  154.         }
  155.         if (!pidl)
  156.         {
  157.             LPCITEMIDLIST pidlT;
  158.             hres = GetObjectSafely(m_psfvOwner, &pidlT, (UINT)-42);
  159.             if (SUCCEEDED(hres))
  160.             {
  161.                 pidl = ILClone(pidlT);
  162.             }
  163.         }
  164.     }
  165.     if (pidl)
  166.     {
  167.         hres = CFolder_Create2(m_hwnd, pidl, psf, &m_psdf);
  168.         if (_dwSafetyOptions && _punkSite && SUCCEEDED(hres))
  169.         {
  170.             m_psdf->SetSite(_punkSite);
  171.             hres = MakeSafeForScripting((IUnknown**)&m_psdf);
  172.         }
  173.         if (psf)
  174.             psf->Release();
  175.         ILFree(pidl);
  176.     }
  177.     else
  178.         hres = E_FAIL;
  179.     return hres;
  180. }
  181. STDMETHODIMP CShellFolderView::SetSite(IUnknown *punkSite)
  182. {
  183.     if (m_psdf)
  184.         m_psdf->SetSite(punkSite);
  185.     return CObjectWithSite::SetSite(punkSite);
  186. }
  187. STDMETHODIMP CShellFolderView::get_Folder(Folder **ppid)
  188. {
  189.     *ppid = NULL;
  190.     HRESULT hres = _GetFolder();
  191.     if (SUCCEEDED(hres))
  192.         hres = m_psdf->QueryInterface(IID_Folder, (void **)ppid);
  193.     return hres;
  194. }
  195. STDMETHODIMP CShellFolderView::SelectedItems(FolderItems **ppid)
  196. {
  197.     // We need to talk to the actual window under us
  198.     HRESULT hres = _GetFolder();
  199.     if (FAILED(hres))
  200.         return hres;
  201.     hres = CFolderItems_Create(m_psdf, TRUE, ppid);
  202.     if (_dwSafetyOptions && SUCCEEDED(hres))
  203.         hres = MakeSafeForScripting((IUnknown**)ppid);
  204.     return hres;
  205. }
  206. // NOTE: this returns an alias pointer, it is not allocated
  207. HRESULT GetObjectSafely(IShellFolderView *psfv, LPCITEMIDLIST *ppidl, UINT iType)
  208. {
  209. // cast needed because GetObject() is declared wrong, it returns a const ptr
  210.     HRESULT hr = psfv->GetObject((LPITEMIDLIST *)ppidl, iType);
  211.     if (SUCCEEDED(hr))
  212.     {
  213.         // On the off chance this is coppied across process boundries...
  214.         __try
  215.         {
  216.             // force a full deref this PIDL to generate a fault if cross process
  217.             if (ILGetSize(*ppidl) > 0)
  218.                 hr = S_OK;
  219.             // Don't free it as it was not cloned...
  220.         }
  221.         __except(SetErrorMode(SEM_NOGPFAULTERRORBOX), UnhandledExceptionFilter(GetExceptionInformation()))
  222.         {
  223.             *ppidl = NULL;
  224.             hr = E_FAIL;
  225.         }
  226.     }
  227.     return hr;
  228. }
  229. STDMETHODIMP CShellFolderView::get_FocusedItem(FolderItem **ppid)
  230. {
  231.     // We need to talk to the actual window under us
  232.     HRESULT hr = _GetFolder();
  233.     if (FAILED(hr))
  234.         return hr;
  235.     *ppid = NULL;
  236.     hr = S_FALSE;
  237.     if (m_psfvOwner)
  238.     {
  239.         // Warning:
  240.         //   It is common for the following function to fail (which means no item has the focus).
  241.         // So, do not save the return code from GetObjectSafely() into "hr" that will ruin the
  242.         // S_FALSE value already stored there and result in script errors. (Bug #301306)
  243.         //
  244.         LPCITEMIDLIST pidl;
  245.         if (SUCCEEDED(GetObjectSafely(m_psfvOwner, &pidl, (UINT)-2)))
  246.         {
  247.             hr = CFolderItem_Create(m_psdf, pidl, ppid);
  248.             if (_dwSafetyOptions && SUCCEEDED(hr))
  249.                 hr = MakeSafeForScripting((IUnknown**)ppid);
  250.         }
  251.     }
  252.     else
  253.         hr = E_FAIL;
  254.     return hr;
  255. }
  256. // pvfi should be a "FolderItem" IDispatch
  257. STDMETHODIMP CShellFolderView::SelectItem(VARIANT *pvfi, int dwFlags)
  258. {
  259.     HRESULT hr = E_FAIL;
  260.     LPITEMIDLIST pidl = VariantToIDList(pvfi);
  261.     if (pidl)
  262.     {
  263.         IShellView *psv;    // use this to select the item...
  264.         if (m_punkOwner && SUCCEEDED(m_punkOwner->QueryInterface(IID_IShellView, (void **)&psv)))
  265.         {
  266.             hr = psv->SelectItem(ILFindLastID(pidl), dwFlags);
  267.             psv->Release();
  268.         }
  269.         ILFree(pidl);
  270.     }
  271.     return hr;
  272. }
  273. STDMETHODIMP CShellFolderView::PopupItemMenu(FolderItem *pfi, VARIANT vx, VARIANT vy, BSTR * pbs)
  274. {
  275.     return E_NOTIMPL;
  276. }
  277. STDMETHODIMP CShellFolderView::get_Script(IDispatch **ppid)
  278. {
  279.     // Say that we got nothing...
  280.     *ppid = NULL;
  281.     // Assume we don't have one...
  282.     if (!m_punkOwner)
  283.         return S_FALSE;
  284.     IShellView *psv;
  285.     HRESULT hres = m_punkOwner->QueryInterface(IID_IShellView, (void **)&psv);
  286.     if (SUCCEEDED(hres))
  287.     {
  288.         // lets see if there is a IHTMLDocument that is below us now...
  289.         IHTMLDocument *phtmld;
  290.         hres = psv->GetItemObject(SVGIO_BACKGROUND, IID_IHTMLDocument, (void **)&phtmld);
  291.         if (SUCCEEDED(hres))
  292.         {
  293.             if (_dwSafetyOptions)
  294.                 hres = MakeSafeForScripting((IUnknown **)&phtmld);
  295.             if (SUCCEEDED(hres))
  296.             {
  297.                 hres = phtmld->get_Script(ppid);
  298.                 phtmld->Release();
  299.             }
  300.         }
  301.         psv->Release();
  302.     }
  303.     return hres;
  304. }
  305. STDMETHODIMP CShellFolderView::get_ViewOptions(long *plSetting)
  306. {
  307.     *plSetting = (LONG)GetViewOptionsForDispatch();
  308.     return S_OK;
  309. }
  310. STDMETHODIMP CShellFolderView::SetOwner(IUnknown* punkOwner)
  311. {
  312.     // Release any previous owners. (ATOMICRELEASE takes care of the null check)
  313.     ATOMICRELEASE(m_psfvOwner);
  314.     ATOMICRELEASE(m_punkOwner);
  315.     // Set the new owner if any set then increment reference count...
  316.     m_punkOwner = punkOwner;
  317.     if (m_punkOwner)
  318.     {
  319.         m_punkOwner->AddRef();
  320.         m_punkOwner->QueryInterface(IID_IShellFolderView, (void **)&m_psfvOwner);
  321.         if (!m_hwnd)
  322.         {
  323.             IShellView *psv;
  324.             // this is gross, until we can merge the two models, create one of our
  325.             // Window objects.
  326.             if (SUCCEEDED(m_punkOwner->QueryInterface(IID_IShellView, (void **)&psv)))
  327.             {
  328.                 HWND hwndFldr;
  329.                 psv->GetWindow(&hwndFldr);
  330.                 // Really gross, but assume parent HWND is the HWND we are after...
  331.                 m_hwnd = GetParent(hwndFldr);
  332.                 psv->Release();
  333.             }
  334.         }
  335.     }
  336.     return NOERROR;
  337. }
  338. STDMETHODIMP CShellFolderView::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
  339. {
  340.     return CreateInstance_IEnumConnectionPoints(ppEnum, 1, m_cpEvents.CastToIConnectionPoint());
  341. }
  342. CConnectionPoint* CShellFolderView::_FindCConnectionPointNoRef(BOOL fdisp, REFIID iid)
  343. {
  344.     if (IsEqualIID(iid, DIID_DShellFolderViewEvents) || (fdisp && IsEqualIID(iid, IID_IDispatch)))
  345.         return &m_cpEvents;
  346.     return NULL;
  347. }
  348. HRESULT CShellFolderView::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  349. {
  350.     HRESULT hr;
  351.     if (dispidMember == DISPID_READYSTATE)
  352.         return DISP_E_MEMBERNOTFOUND;   // perf: what typeinfo would return.
  353.     if (dispidMember == DISPID_WINDOWOBJECT) 
  354.     {
  355.         IDispatch *pdisp;
  356.         if (SUCCEEDED(get_Script(&pdisp))) 
  357.         {
  358.             hr = pdisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  359.             pdisp->Release();
  360.         } 
  361.         else 
  362.         {
  363.             hr = DISP_E_MEMBERNOTFOUND;
  364.         }
  365.     }
  366.     else
  367.         hr = CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  368.     return hr;
  369. }