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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. //#include "security.h"
  4. //#include "dspsprt.h"
  5. //#include "sdspatch.h"
  6. //#include "dutil.h"
  7. #define TF_SHELLAUTO            TF_CUSTOM1
  8. #undef TF_SHDLIFE
  9. #define TF_SHDLIFE              TF_CUSTOM2
  10. HRESULT CSDFolder_Create(HWND hwnd, LPITEMIDLIST pidl, IShellFolder *psf, CSDFolder **ppsdf)
  11. {
  12.     *ppsdf = new CSDFolder(hwnd, psf);
  13.     if (*ppsdf)
  14.     {
  15.         if (!(*ppsdf)->Init(pidl))
  16.         {
  17.             (*ppsdf)->Release();
  18.             return E_OUTOFMEMORY;
  19.         }
  20.      return S_OK;
  21.     }
  22.     return E_OUTOFMEMORY;
  23. }
  24. CSDFolder::CSDFolder(HWND hwnd, IShellFolder *psf) :
  25.     m_cRef (1), m_hwnd(hwnd), m_pidl(NULL), m_psf(psf),
  26.     CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_Folder)
  27. {
  28.     TraceMsg(TF_SHDLIFE, "ctor CSDFolder");
  29.     if (m_psf)
  30.         m_psf->AddRef();
  31.     DllAddRef();
  32. }
  33. CSDFolder::~CSDFolder(void)
  34. {
  35.     TraceMsg(TF_SHDLIFE, "dtor CSDFolder");
  36.     DllRelease();
  37.     ATOMICRELEASE(m_psd);
  38.     ATOMICRELEASE(m_psf);
  39.     if (m_pidl)
  40.         ILFree(m_pidl);
  41.     // If we created an Application object release its site object...
  42.     if (m_pidApp)
  43.     {
  44.         IUnknown_SetSite(SAFECAST(m_pidApp, IUnknown*), NULL);
  45.         ATOMICRELEASE(m_pidApp);
  46.     }
  47.     return;
  48. }
  49. STDMETHODIMP CSDFolder::SetSite(IUnknown *punkSite)
  50. {
  51.     IUnknown_SetSite(SAFECAST(m_pidApp, IUnknown*), punkSite);
  52.     return CObjectWithSite::SetSite(punkSite);
  53. }
  54. BOOL CSDFolder::Init(LPITEMIDLIST pidl)
  55. {
  56.     m_pidl = ILClone(pidl);
  57.     if (m_pidl == NULL)
  58.         return FALSE;
  59.     return TRUE;
  60. }
  61. STDMETHODIMP CSDFolder::QueryInterface(REFIID riid, void **ppv)
  62. {
  63.     static const QITAB qit[] = {
  64.         QITABENT(CSDFolder, Folder),
  65.         QITABENTMULTI(CSDFolder, IDispatch, Folder),
  66.         QITABENT(CSDFolder, ISDGetPidl),
  67.         QITABENT(CSDFolder, IObjectSafety),
  68.         QITABENT(CSDFolder, IObjectWithSite),
  69.         { 0 },
  70.     };
  71.     return QISearch(this, qit, riid, ppv);
  72. }
  73. STDMETHODIMP_(ULONG) CSDFolder::AddRef(void)
  74. {
  75.     return ++m_cRef;
  76. }
  77. STDMETHODIMP_(ULONG) CSDFolder::Release(void)
  78. {
  79.     if (0!=--m_cRef)
  80.         return m_cRef;
  81.     delete this;
  82.     return 0L;
  83. }
  84. //The Folder implementation
  85. STDMETHODIMP CSDFolder::get_Application(IDispatch **ppid)
  86. {
  87.     // The Get application object takes care of security...
  88.     HRESULT hres = S_OK;
  89.     if (!m_pidApp)
  90.         HRESULT hres = ::GetApplicationObject(_dwSafetyOptions, _punkSite, &m_pidApp);
  91.     if (m_pidApp)
  92.     {    
  93.         *ppid = m_pidApp;
  94.         m_pidApp->AddRef();
  95.     }
  96.     return hres;
  97. }
  98. STDMETHODIMP CSDFolder::get_Parent(IDispatch **ppid)
  99. {
  100.     *ppid = NULL;
  101.     return E_NOTIMPL;
  102. }
  103. STDMETHODIMP CSDFolder::get_ParentFolder (Folder **ppdf)
  104. {
  105.     *ppdf = NULL;   // assume error
  106.     if (m_pidl->mkid.cb == 0)
  107.         return S_FALSE;
  108.     if (_dwSafetyOptions && LocalZoneCheck(_punkSite) != S_OK)
  109.         return E_ACCESSDENIED;
  110.     LPITEMIDLIST pidl = ILClone(m_pidl);
  111.     if (pidl)
  112.     {
  113.         ILRemoveLastID(pidl);
  114.         CSDFolder *psdf;
  115.         HRESULT hres = CSDFolder_Create(m_hwnd, pidl, NULL, &psdf);
  116.         if (SUCCEEDED(hres))
  117.         {
  118.             hres = psdf->QueryInterface(IID_Folder, (void **)ppdf);
  119.             psdf->Release();
  120.         }
  121.         ILFree(pidl);
  122.         return hres;
  123.     }
  124.     return E_OUTOFMEMORY;
  125. }
  126. STDMETHODIMP CSDFolder::get_Title(BSTR *pbs)
  127. {
  128.     *pbs = NULL;
  129.     SHFILEINFO sfi;
  130.     if (SHGetFileInfo((LPCTSTR)m_pidl, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_PIDL))
  131.         *pbs = AllocBStrFromString(sfi.szDisplayName);
  132.     return NOERROR;
  133. }
  134. LPSHELLFOLDER CSDFolder::_GetShellFolder(void)
  135. {
  136.     if (!m_psf)
  137.     {
  138.         IShellFolder *psfRoot;
  139.         if (FAILED(CoCreateInstance(CLSID_ShellDesktop, NULL, CLSCTX_INPROC_SERVER,
  140.             IID_IShellFolder, (void **)&psfRoot)))
  141.             return FALSE;
  142.         if (!m_pidl || (m_pidl->mkid.cb == 0))
  143.         {
  144.             m_psf = psfRoot;
  145.             return m_psf;
  146.         }
  147.         if (FAILED(psfRoot->BindToObject(m_pidl, NULL, IID_IShellFolder, (void **)&m_psf)))
  148.             m_psf = NULL;   // incase some does not set it right..
  149.         psfRoot->Release();
  150.     }
  151.     return m_psf;
  152. }
  153. IShellDetails * CSDFolder::_GetShellDetails(void)
  154. {
  155.     if (!m_psd)
  156.     {
  157.         LPSHELLFOLDER psf = _GetShellFolder();
  158.         if (psf)
  159.         {   
  160.             psf->CreateViewObject(m_hwnd, IID_IShellDetails, (void **)&m_psd);
  161.         }
  162.     }
  163.     return m_psd;
  164. }
  165. STDMETHODIMP CSDFolder::Items(FolderItems **ppid)
  166. {
  167.     *ppid = NULL;
  168.     HRESULT hres = NOERROR;
  169.     if (_GetShellFolder())
  170.     {
  171.         // For now don't allow enumeration in Safe mode...
  172.         if (_dwSafetyOptions && LocalZoneCheck(_punkSite) != S_OK)
  173.             return E_ACCESSDENIED;
  174.         hres = CSDFldrItems_Create(this, FALSE, ppid);
  175.     }
  176.     return hres;
  177. }
  178. STDMETHODIMP CSDFolder::ParseName(BSTR bName, FolderItem **ppid)
  179. {
  180.     *ppid = NULL;
  181.     HRESULT hres = E_FAIL;
  182.     // Aargh, lets be anal here and not allow them to do much...
  183.     if (_dwSafetyOptions && LocalZoneCheck(_punkSite) != S_OK)
  184.         return E_ACCESSDENIED;
  185.     LPSHELLFOLDER psf = _GetShellFolder();
  186.     if (psf)
  187.     {   
  188.         ULONG chEaten;
  189.         LPITEMIDLIST pidl;
  190.         hres = psf->ParseDisplayName(m_hwnd, NULL, bName, &chEaten, &pidl, NULL);
  191.         if (SUCCEEDED(hres))
  192.         {
  193.             LPITEMIDLIST pidlLast = ILFindLastID(pidl);
  194.             if (pidlLast == pidl)
  195.             {
  196.                 if (FAILED(hres = CSDFldrItem_Create(this, pidl, ppid)))
  197.                     *ppid = NULL;
  198.             }
  199.             else
  200.             {
  201.                 CSDFolder *psdf;
  202.                 LPITEMIDLIST pidlParent = ILCombine(m_pidl, pidl);
  203.                 ILRemoveLastID(pidlParent);
  204.                 hres = CSDFolder_Create(m_hwnd, pidlParent, NULL, &psdf);
  205.                 if (SUCCEEDED(hres))
  206.                 {
  207.                     if (FAILED(hres = CSDFldrItem_Create(psdf, pidlLast, ppid)))
  208.                         *ppid = NULL;
  209.                     psdf->Release();
  210.                 }
  211.                 ILFree(pidlParent);
  212.             }
  213.             ILFree(pidl);
  214.         }
  215.     }
  216.     return hres;
  217. }
  218. STDMETHODIMP CSDFolder::NewFolder(BSTR bName, VARIANT vOptions)
  219. {
  220.     return E_NOTIMPL;
  221. }
  222. STDMETHODIMP CSDFolder::MoveHere(VARIANT vItem, VARIANT vOptions)
  223. {
  224.     return _FileOperation(FO_MOVE, vItem, vOptions);
  225. }
  226. STDMETHODIMP CSDFolder::CopyHere(VARIANT vItem, VARIANT vOptions)
  227. {
  228.     return _FileOperation(FO_COPY, vItem, vOptions);
  229. }
  230. STDMETHODIMP CSDFolder::GetDetailsOf(VARIANT vItem, int iColumn, BSTR * pbs)
  231. {
  232.     HRESULT hres = E_FAIL;
  233.     *pbs = NULL;    // assume emtpy
  234.     if (iColumn == -1)
  235.     {
  236.         // They want the info tip for the item if any...
  237.         LPCITEMIDLIST pidl = VariantToConstIDList(&vItem);
  238.         if (pidl)
  239.         {
  240.             LPSHELLFOLDER psf = _GetShellFolder();
  241.             if (psf)
  242.             {
  243.                 TCHAR szInfoTip[1024];
  244.                 GetInfoTip(psf, pidl, szInfoTip, ARRAYSIZE(szInfoTip));
  245.                 *pbs = AllocBStrFromString(szInfoTip);
  246.                 hres = *pbs ? S_OK : E_OUTOFMEMORY;
  247.             }
  248.         }
  249.         else
  250.             hres = S_OK;    // NULL pidl for multiple selection, don't fail
  251.     }
  252.     else
  253.     {
  254.         IShellDetails* psd = _GetShellDetails();
  255.         if (psd)
  256.         {
  257.             LPCITEMIDLIST pidl = VariantToConstIDList(&vItem);
  258.             // NULL pidl is valid it implies get the header text
  259.             SHELLDETAILS sd;
  260.             hres = psd->GetDetailsOf(pidl, iColumn, &sd);
  261.             if (SUCCEEDED(hres))
  262.             {
  263.                 *pbs = StrRetToBStr(pidl, &sd.str);
  264.                 if (!*pbs)
  265.                     hres = E_OUTOFMEMORY;
  266.             }
  267.             else
  268.             {
  269.                 // BUGBUG: (kinda)  Current, ISD:GDO returns E_NOTIMPL if you ask for a column
  270.                 //  that doesn't exist.  WebView doesn't like this error, so we hide all errors
  271.                 goto RetNulStr;
  272.             }
  273.         }
  274.         else
  275.         {
  276. RetNulStr:
  277.             // failure case, return empty string (no details)
  278.             *pbs = AllocBStrFromString(TEXT(""));
  279.             hres = *pbs ? S_OK : E_OUTOFMEMORY;
  280.         }
  281.     }
  282.     return hres;
  283. }
  284. // Main function to do Move or Copy
  285. HRESULT CSDFolder::_FileOperation(UINT wFunc, VARIANT vItem, VARIANT vOptions)
  286. {
  287.     // If in Safe mode we fail this one...
  288.     if (_dwSafetyOptions  && LocalZoneCheck(_punkSite) != S_OK)
  289.         return E_ACCESSDENIED;
  290.     // BUGBUG:: Not using options yet...
  291.     SHFILEOPSTRUCT fileop = {m_hwnd, wFunc};
  292.     int cch;
  293.     if (vItem.vt == (VT_BYREF | VT_VARIANT) && vItem.pvarVal)
  294.          vItem = *vItem.pvarVal;
  295.      // We need to get the source files out of the variant.
  296.      // Currently support string, or IDispatch (Either FolderItem or FolderItems)
  297.     switch (vItem.vt)
  298.     {
  299.     case VT_BSTR:
  300.         fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, cch = (lstrlenW(vItem.bstrVal)+2) * sizeof(TCHAR));   // +2 for double null
  301.         if (fileop.pFrom)
  302.             SHUnicodeToTChar(vItem.bstrVal, (LPTSTR)fileop.pFrom, cch);
  303.         break;
  304.     case VT_DISPATCH:
  305.         {
  306.             BSTR bs;
  307.             FolderItem *pfi;
  308.             FolderItems *pfis;
  309.             if (!vItem.pdispVal)
  310.                 break;
  311.             if (SUCCEEDED(vItem.pdispVal->QueryInterface(IID_FolderItems, (void **)&pfis)))
  312.             {
  313.                 // This is gross, but allocate N times MAX_PATH for buffer as to keep from
  314.                 // looping through the items twice.
  315.                 long cItems;
  316.                 pfis->get_Count(&cItems);
  317.                 fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, ((cItems * MAX_PATH) + 1) * sizeof(TCHAR));
  318.                 if (fileop.pFrom)
  319.                 {
  320.                     long i; 
  321.                     VARIANT v = {VT_I4};
  322.                     LPTSTR pszT = (LPTSTR)fileop.pFrom;
  323.                     for (i = 0; i < cItems; i++)
  324.                     {
  325.                         v.lVal = i;
  326.                         if (SUCCEEDED(pfis->Item(v, &pfi)))
  327.                         {
  328.                             if (SUCCEEDED(pfi->get_Path(&bs)))
  329.                             {
  330.                                 cch = lstrlenW(bs);
  331.                                 SHUnicodeToTCharCP(CP_ACP, bs, pszT, MAX_PATH);
  332.                                 SysFreeString(bs);
  333.                                 pszT += cch + 1;
  334.                             }
  335.             
  336.                             pfi->Release();
  337.                         }
  338.                     }
  339.                 }
  340.                 pfis->Release();
  341.                 break;
  342.             }
  343.             else if (SUCCEEDED(vItem.pdispVal->QueryInterface(IID_FolderItem, (void **)&pfi)))
  344.             {
  345.                 if (SUCCEEDED(pfi->get_Path(&bs)))
  346.                 {
  347.                     fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, cch = (lstrlenW(bs)+2) * sizeof(TCHAR));
  348.                     if (fileop.pFrom)
  349.                         SHUnicodeToTCharCP(CP_ACP, bs, (LPTSTR)fileop.pFrom, cch);
  350.                     SysFreeString(bs);
  351.                 }
  352.                 pfi->Release();
  353.                 break;
  354.             }
  355.         }
  356.         break;
  357.     default:
  358.         return E_INVALIDARG;   // don't support that type of variable.
  359.     }
  360.     if (!fileop.pFrom)
  361.          return E_OUTOFMEMORY;
  362.     // Now setup the Destination...
  363.     TCHAR szDest[MAX_PATH];
  364.     fileop.pTo = szDest;
  365.     SHGetPathFromIDList(m_pidl, szDest);
  366.     // Allow flags to pass through...
  367.     if (vOptions.vt == (VT_BYREF | VT_VARIANT) && vOptions.pvarVal)
  368.          vOptions = *vOptions.pvarVal;
  369.      // We need to get the source files out of the variant.
  370.      // Currently support string, or IDispatch (Either FolderItem or FolderItems)
  371.     switch (vOptions.vt)
  372.     {
  373.     case VT_I2:
  374.         fileop.fFlags = (FILEOP_FLAGS)vOptions.iVal;
  375.         break;
  376.         // And fall through...
  377.     case VT_I4:
  378.         fileop.fFlags = (FILEOP_FLAGS)vOptions.lVal;
  379.         break;
  380.     }
  381.     // Finally lets try to do the operation.
  382.     int ret = SHFileOperation(&fileop);
  383.     LocalFree((HLOCAL)fileop.pFrom);
  384.     return ret ? HRESULT_FROM_WIN32(ret) : NOERROR;
  385. }
  386. STDMETHODIMP CSDFolder::GetPidl(LPITEMIDLIST *ppidl)
  387. {
  388.     *ppidl = ILClone(m_pidl);
  389.     return *ppidl ? NOERROR : E_OUTOFMEMORY;
  390. }