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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. HRESULT CFolder_Create2(HWND hwnd, LPCITEMIDLIST pidl, IShellFolder *psf, CFolder **ppsdf)
  4. {
  5.     HRESULT hr;
  6.     CFolder *psdf = new CFolder();
  7.     if (psdf)
  8.     {
  9.         hr = psdf->Init(hwnd, pidl, psf);
  10.         if (SUCCEEDED(hr))
  11.             *ppsdf = psdf;
  12.         else
  13.             psdf->Release();
  14.     }
  15.     else
  16.         hr = E_OUTOFMEMORY;
  17.     return hr;
  18. }
  19. HRESULT CFolder_Create(HWND hwnd, LPCITEMIDLIST pidl, IShellFolder *psf, REFIID riid, void **ppv)
  20. {
  21.     *ppv = NULL;
  22.     CFolder *psdf;
  23.     HRESULT hr = CFolder_Create2(hwnd, pidl, psf, &psdf);
  24.     if (SUCCEEDED(hr))
  25.     {
  26.         hr = psdf->QueryInterface(riid, ppv);
  27.         psdf->Release();
  28.     }
  29.     return hr;
  30. }
  31. // HRESULT CFolder_Create(HWND hwnd, LPITEMIDLIST pidl, IShellFolder *psf, CFolder **ppsdf)
  32. CFolder::CFolder() :
  33.     m_cRef (1), m_pidl(NULL), m_psf(NULL), m_psf2(NULL),
  34.     CImpIDispatch(&LIBID_Shell32, 1, 0, &IID_Folder2)
  35. {
  36.     DWORD dwExStyle;
  37.     _fmt = 0;
  38.     // Be sure that the OS is supporting the flags DATE_LTRREADING and DATE_RTLREADING
  39.     if (g_bBiDiPlatform)
  40.     {
  41.         // Get the date format reading order
  42.         LCID locale = GetUserDefaultLCID();
  43.         if (   (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC)
  44.             || (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW))
  45.         {
  46.             //Get the real list view windows ExStyle.
  47.             // [msadek]; we shouldn't check for either WS_EX_RTLREADING OR RTL_MIRRORED_WINDOW
  48.             // on localized builds we have both of them to display dirve letters,..etc correctly
  49.             // on enabled builds we have none of them. let's check on RTL_MIRRORED_WINDOW only
  50.             
  51.             dwExStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE);
  52.             if (dwExStyle & RTL_MIRRORED_WINDOW)
  53.                 _fmt = LVCFMT_RIGHT_TO_LEFT;
  54.             else
  55.                 _fmt = LVCFMT_LEFT_TO_RIGHT;
  56.         }
  57.     }
  58.     DllAddRef();
  59. }
  60. CFolder::~CFolder(void)
  61. {
  62.     ATOMICRELEASE(m_psd);
  63.     ATOMICRELEASE(m_psf2);
  64.     ATOMICRELEASE(m_psf);
  65.     if (m_pidl)
  66.         ILFree(m_pidl);
  67.     // If we created an Application object release its site object...
  68.     if (m_pidApp)
  69.     {
  70.         IUnknown_SetSite(SAFECAST(m_pidApp, IUnknown*), NULL);
  71.         ATOMICRELEASE(m_pidApp);
  72.     }
  73.     DllRelease();
  74. }
  75. STDMETHODIMP CFolder::SetSite(IUnknown *punkSite)
  76. {
  77.     IUnknown_SetSite(SAFECAST(m_pidApp, IUnknown*), punkSite);
  78.     return CObjectWithSite::SetSite(punkSite);
  79. }
  80. HRESULT CFolder::Init(HWND hwnd, LPCITEMIDLIST pidl, IShellFolder *psf)
  81. {
  82.     m_hwnd = hwnd;
  83.     HRESULT hr = SHILClone(pidl, &m_pidl);
  84.     if (SUCCEEDED(hr))
  85.     {
  86.         m_psf = psf;
  87.         if (m_psf)
  88.             m_psf->AddRef();
  89.         else
  90.             hr = SHBindToObject(NULL, IID_IShellFolder, m_pidl, (void**)&m_psf);
  91.         if (m_psf)
  92.             m_psf->QueryInterface(IID_IShellFolder2, (void **)&m_psf2);
  93.     }
  94.     return hr;
  95. }
  96. STDMETHODIMP CFolder::QueryInterface(REFIID riid, void **ppv)
  97. {
  98.     static const QITAB qit[] = {
  99.         QITABENT(CFolder, Folder2),
  100.         QITABENTMULTI(CFolder, Folder, Folder2),
  101.         QITABENTMULTI(CFolder, IDispatch, Folder2),
  102.         QITABENTMULTI(CFolder, IPersist, IPersistFolder2),
  103.         QITABENTMULTI(CFolder, IPersistFolder, IPersistFolder2),
  104.         QITABENT(CFolder, IPersistFolder2),
  105.         QITABENT(CFolder, IObjectSafety),
  106.         QITABENT(CFolder, IObjectWithSite),
  107.         { 0 },
  108.     };
  109.     return QISearch(this, qit, riid, ppv);
  110. }
  111. STDMETHODIMP_(ULONG) CFolder::AddRef(void)
  112. {
  113.     return ++m_cRef;
  114. }
  115. STDMETHODIMP_(ULONG) CFolder::Release(void)
  116. {
  117.     if (0 != --m_cRef)
  118.         return m_cRef;
  119.     delete this;
  120.     return 0;
  121. }
  122. //The Folder implementation
  123. STDMETHODIMP CFolder::get_Application(IDispatch **ppid)
  124. {
  125.     // The Get application object takes care of security...
  126.     HRESULT hres = S_OK;
  127.     if (!m_pidApp)
  128.         hres = ::GetApplicationObject(_dwSafetyOptions, _punkSite, &m_pidApp);
  129.     if (m_pidApp)
  130.     {    
  131.         *ppid = m_pidApp;
  132.         m_pidApp->AddRef();
  133.     }
  134.     return hres;
  135. }
  136. STDMETHODIMP CFolder::get_Parent(IDispatch **ppid)
  137. {
  138.     *ppid = NULL;
  139.     return E_NOTIMPL;
  140. }
  141. // returns:
  142. //      S_OK    - success
  143. //      S_FALSE - failure, but not a script error
  144.     
  145. STDMETHODIMP CFolder::_ParentFolder(Folder **ppdf)
  146. {
  147.     *ppdf = NULL;   // assume error
  148.     if (ILIsEmpty(m_pidl))
  149.         return S_FALSE;     // automation compat, let script check error
  150.     LPITEMIDLIST pidl;
  151.     HRESULT hres = SHILClone(m_pidl, &pidl);
  152.     if (SUCCEEDED(hres))
  153.     {
  154.         ILRemoveLastID(pidl);
  155.         hres = CFolder_Create(m_hwnd, pidl, NULL, IID_Folder, (void **)ppdf);
  156.         ILFree(pidl);
  157.     }
  158.     return hres;
  159. }
  160. STDMETHODIMP CFolder::get_ParentFolder(Folder **ppdf)
  161. {
  162.     *ppdf = NULL;   // assume error
  163.     if (_dwSafetyOptions && IsSafePage(_punkSite) != S_OK)
  164.         return E_ACCESSDENIED;
  165.     return _ParentFolder(ppdf);
  166. }
  167. STDMETHODIMP CFolder::get_Title(BSTR *pbs)
  168. {
  169.     *pbs = NULL;
  170.     SHFILEINFO sfi;
  171.     if (SHGetFileInfo((LPCTSTR)m_pidl, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_PIDL))
  172.         *pbs = SysAllocStringT(sfi.szDisplayName);
  173.     return NOERROR;
  174. }
  175. IShellDetails * CFolder::_GetShellDetails(void)
  176. {
  177.     if (!m_psd)
  178.     {
  179.         if (m_psf)
  180.             m_psf->CreateViewObject(m_hwnd, IID_IShellDetails, (void **)&m_psd);
  181.     }
  182.     return m_psd;
  183. }
  184. STDMETHODIMP CFolder::Items(FolderItems **ppid)
  185. {
  186.     HRESULT hres;
  187.     hres = CFolderItems_Create(this, FALSE, ppid);
  188.     if (_dwSafetyOptions && SUCCEEDED(hres))
  189.         hres = MakeSafeForScripting((IUnknown**)ppid);
  190.     return hres;
  191. }
  192. STDMETHODIMP CFolder::ParseName(BSTR bName, FolderItem **ppfi)
  193. {
  194.     *ppfi = NULL;
  195.     HRESULT hres = E_FAIL;
  196.     // Aargh, lets be anal here and not allow them to do much...
  197.     if (_dwSafetyOptions && IsSafePage(_punkSite) != S_OK)
  198.         return E_ACCESSDENIED;
  199.     ULONG chEaten;
  200.     LPITEMIDLIST pidl;
  201.     hres = m_psf->ParseDisplayName(m_hwnd, NULL, bName, &chEaten, &pidl, NULL);
  202.     if (SUCCEEDED(hres))
  203.     {
  204.         LPITEMIDLIST pidlLast = ILFindLastID(pidl);
  205.         if (pidlLast == pidl)
  206.         {
  207.             hres = CFolderItem_Create(this, pidl, ppfi);
  208.         }
  209.         else
  210.         {
  211.             LPITEMIDLIST pidlFull = ILCombine(m_pidl, pidl);
  212.             if (pidlFull)
  213.             {
  214.                 CFolderItem_CreateFromIDList(m_hwnd, pidlFull, ppfi);
  215.                 ILFree(pidlFull);
  216.             }
  217.             else
  218.                 hres = E_OUTOFMEMORY;
  219.         }
  220.         ILFree(pidl);
  221.     }
  222.     return hres;
  223. }
  224. STDMETHODIMP CFolder::NewFolder(BSTR bName, VARIANT vOptions)
  225. {
  226.     return E_NOTIMPL;
  227. }
  228. STDMETHODIMP CFolder::MoveHere(VARIANT vItem, VARIANT vOptions)
  229. {
  230.     return _FileOperation(FO_MOVE, vItem, vOptions);
  231. }
  232. STDMETHODIMP CFolder::CopyHere(VARIANT vItem, VARIANT vOptions)
  233. {
  234.     return _FileOperation(FO_COPY, vItem, vOptions);
  235. }
  236. // get the IDList for an item from a VARIANT that is a FolderItem dispatch object
  237. STDMETHODIMP CFolder::GetDetailsOf(VARIANT vItem, int iColumn, BSTR *pbs)
  238. {
  239.     TCHAR szBuf[INFOTIPSIZE];
  240.     szBuf[0] = 0;
  241.     LPCITEMIDLIST pidl = CFolderItem::_GetIDListFromVariant(&vItem); // returns an ALIAS
  242.     if (iColumn == -1)  // infotip for the item
  243.     {
  244.         if (pidl)
  245.             GetInfoTip(m_psf, pidl, szBuf, ARRAYSIZE(szBuf));
  246.     }
  247.     else
  248.     {
  249.         BOOL bUseDetails;
  250.         SHELLDETAILS sd;
  251.         sd.fmt = _fmt;
  252.         sd.str.uType = STRRET_CSTR;
  253.         sd.str.cStr[0] = 0;
  254.         if (m_psf2)
  255.             bUseDetails = (E_NOTIMPL == m_psf2->GetDetailsOf(pidl, iColumn, &sd));
  256.         else
  257.             bUseDetails = TRUE;
  258.         if (bUseDetails)
  259.         {
  260.             IShellDetails* psd = _GetShellDetails();
  261.             if (psd)
  262.                 psd->GetDetailsOf(pidl, iColumn, &sd);
  263.         }
  264.         StrRetToBuf(&sd.str, pidl, szBuf, ARRAYSIZE(szBuf));
  265.     }
  266.     *pbs = SysAllocStringT(szBuf);
  267.     return *pbs ? NOERROR : E_OUTOFMEMORY;
  268. }
  269. HRESULT CFolder::get_Self(FolderItem **ppfi)
  270. {
  271.     Folder *psdf;
  272.     HRESULT hres;
  273.     
  274.     if (ILIsEmpty(m_pidl))
  275.     {
  276.         psdf = this;
  277.         psdf->AddRef();
  278.         hres = S_OK;
  279.     }
  280.     else
  281.         hres = _ParentFolder(&psdf);
  282.         
  283.     if (SUCCEEDED(hres))
  284.     {
  285.         hres = CFolderItem_Create((CFolder*)psdf, ILFindLastID(m_pidl), ppfi);
  286.         if (SUCCEEDED(hres) && _dwSafetyOptions)
  287.             hres = MakeSafeForScripting((IUnknown**)ppfi);
  288.         psdf->Release();
  289.     }
  290.     else
  291.         *ppfi = NULL;
  292.     return hres;
  293. }
  294. BOOL _VerifyUNC(LPTSTR psz, ULONG cch)
  295. {
  296.     if (PathIsUNC(psz))
  297.     {
  298.         return TRUE;
  299.     }
  300.     else if (psz[1] == TEXT(':'))
  301.     {
  302.         TCHAR szLocalName[3] = { psz[0], psz[1], TEXT('') };
  303.         // Call GetDriveType before WNetGetConnection, to avoid loading
  304.         // MPR.DLL unless absolutely necessary.
  305.         if (DRIVE_REMOTE == GetDriveType(szLocalName) &&
  306.             NOERROR == WNetGetConnection(szLocalName, psz, &cch))
  307.         {
  308.             return TRUE;
  309.         }
  310.     }
  311.     return FALSE;
  312. }
  313. HRESULT GetSharePath(LPCITEMIDLIST pidl, LPTSTR psz, ULONG cch)
  314. {
  315.     HRESULT hres = E_FAIL;
  316.     
  317.     if (SHGetPathFromIDList(pidl, psz))
  318.     {
  319.         if (_VerifyUNC(psz, cch))
  320.             hres = S_OK;
  321.         else 
  322.         {
  323.             //  check for folder shortcuts.
  324.             IShellFolder *psf;
  325.             if (SUCCEEDED(SHBindToObject(NULL, IID_IShellFolder, pidl, (void **)&psf)))
  326.             {
  327.                 IShellLink *psl;
  328.                 if (SUCCEEDED(psf->QueryInterface(IID_IShellLink, (void **)&psl)))
  329.                 {
  330.                     if (SUCCEEDED(psl->GetPath(psz, cch, NULL, 0))
  331.                     &&  _VerifyUNC(psz, cch))
  332.                         hres = S_OK;
  333.                     psl->Release();
  334.                 }
  335.                 psf->Release();
  336.             }
  337.         }
  338.         if (SUCCEEDED(hres))
  339.             PathStripToRoot(psz);
  340.     }       
  341.     return hres;
  342. }
  343. #include <cscuiext.h>
  344. STDMETHODIMP CFolder::get_OfflineStatus(LONG *pul)
  345. {
  346.     TCHAR szShare[MAX_PATH];
  347.     *pul = OFS_INACTIVE;  // default
  348.     // Make sure we have a UNC \servershare path.  Do this before
  349.     // checking whether CSC is enabled, to avoid loading CSCDLL.DLL
  350.     // unless absolutely necessary.
  351.     if (SUCCEEDED(GetSharePath(m_pidl, szShare, ARRAYSIZE(szShare))))
  352.     {
  353.         *pul = GetOfflineShareStatus(szShare);
  354.     }
  355.     return S_OK;
  356. }
  357. STDMETHODIMP CFolder::Synchronize(void)
  358. {
  359.     HWND hwndCSCUI = FindWindow(STR_CSCHIDDENWND_CLASSNAME, STR_CSCHIDDENWND_TITLE);
  360.     if (hwndCSCUI)
  361.         PostMessage(hwndCSCUI, CSCWM_SYNCHRONIZE, 0, 0);
  362.     return S_OK;
  363. }
  364. struct
  365. {
  366.     int csidlFolder;
  367.     BOOL bHaveToShowWebViewBarricade;
  368. } g_WebViewBarricadeFolderStatus[] = {  {CSIDL_WINDOWS, true},
  369.                                         {CSIDL_SYSTEM, true},
  370.                                         {CSIDL_SYSTEMX86, true},
  371.                                         {CSIDL_PROGRAM_FILES, true},
  372.                                         {CSIDL_PROGRAM_FILESX86, true}
  373.                                      };
  374. STDMETHODIMP CFolder::get_HaveToShowWebViewBarricade(VARIANT_BOOL *pbHaveToShowWebViewBarricade)
  375. {
  376.     if (pbHaveToShowWebViewBarricade)
  377.     {
  378.         *pbHaveToShowWebViewBarricade = VARIANT_FALSE;
  379.         BOOL bExitLoop = false;
  380.         for (int i = 0; (i < ARRAYSIZE(g_WebViewBarricadeFolderStatus)) && !bExitLoop; i++)
  381.         {
  382.             LPITEMIDLIST pidlTemp = NULL;
  383.             if (SUCCEEDED(SHGetFolderLocation(NULL, g_WebViewBarricadeFolderStatus[i].csidlFolder, NULL, 0, &pidlTemp)))
  384.             {
  385.                 if (ILIsEqual(m_pidl, pidlTemp))
  386.                 {
  387.                     // Careful!  VARIANT_TRUE != TRUE
  388.                     *pbHaveToShowWebViewBarricade = g_WebViewBarricadeFolderStatus[i].bHaveToShowWebViewBarricade ? VARIANT_TRUE : VARIANT_FALSE;
  389.                     bExitLoop = true;
  390.                 }
  391.                 ILFree(pidlTemp);
  392.             }
  393.         }
  394.     }
  395.     return S_OK;
  396. }
  397. STDMETHODIMP CFolder::DismissedWebViewBarricade()
  398. {
  399.     BOOL bExitLoop = false;
  400.     for (int i = 0; (i < ARRAYSIZE(g_WebViewBarricadeFolderStatus)) && !bExitLoop; i++)
  401.     {
  402.         LPITEMIDLIST pidlTemp = NULL;
  403.         if (SUCCEEDED(SHGetFolderLocation(NULL, g_WebViewBarricadeFolderStatus[i].csidlFolder, NULL, 0, &pidlTemp)))
  404.         {
  405.             if (ILIsEqual(m_pidl, pidlTemp))
  406.             {
  407.                 g_WebViewBarricadeFolderStatus[i].bHaveToShowWebViewBarricade = false;
  408.                 bExitLoop = true;
  409.             }
  410.             ILFree(pidlTemp);
  411.         }
  412.     }
  413.     return S_OK;
  414. }
  415. // Main function to do Move or Copy
  416. HRESULT CFolder::_FileOperation(UINT wFunc, VARIANT vItem, VARIANT vOptions)
  417. {
  418.     // If in Safe mode we fail this one...
  419.     if (_dwSafetyOptions  && IsSafePage(_punkSite) != S_OK)
  420.         return E_ACCESSDENIED;
  421.     // BUGBUG:: Not using options yet...
  422.     SHFILEOPSTRUCT fileop = {m_hwnd, wFunc};
  423.     int cch;
  424.     if (vItem.vt == (VT_BYREF | VT_VARIANT) && vItem.pvarVal)
  425.          vItem = *vItem.pvarVal;
  426.      // We need to get the source files out of the variant.
  427.      // Currently support string, or IDispatch (Either FolderItem or FolderItems)
  428.     switch (vItem.vt)
  429.     {
  430.     case VT_BSTR:
  431.         fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, cch = (lstrlenW(vItem.bstrVal)+2) * sizeof(TCHAR));   // +2 for double null
  432.         if (fileop.pFrom)
  433.             SHUnicodeToTChar(vItem.bstrVal, (LPTSTR)fileop.pFrom, cch);
  434.         break;
  435.     case VT_DISPATCH:
  436.         {
  437.             BSTR bs;
  438.             FolderItem *pfi;
  439.             FolderItems *pfis;
  440.             if (!vItem.pdispVal)
  441.                 break;
  442.             if (SUCCEEDED(vItem.pdispVal->QueryInterface(IID_FolderItems, (void **)&pfis)))
  443.             {
  444.                 // This is gross, but allocate N times MAX_PATH for buffer as to keep from
  445.                 // looping through the items twice.
  446.                 long cItems;
  447.                 pfis->get_Count(&cItems);
  448.                 fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, ((cItems * MAX_PATH) + 1) * sizeof(TCHAR));
  449.                 if (fileop.pFrom)
  450.                 {
  451.                     long i; 
  452.                     VARIANT v = {VT_I4};
  453.                     LPTSTR pszT = (LPTSTR)fileop.pFrom;
  454.                     for (i = 0; i < cItems; i++)
  455.                     {
  456.                         v.lVal = i;
  457.                         if (SUCCEEDED(pfis->Item(v, &pfi)))
  458.                         {
  459.                             if (SUCCEEDED(pfi->get_Path(&bs)))
  460.                             {
  461.                                 cch = lstrlenW(bs);
  462.                                 SHUnicodeToTChar(bs, pszT, MAX_PATH);
  463.                                 SysFreeString(bs);
  464.                                 pszT += cch + 1;
  465.                             }
  466.             
  467.                             pfi->Release();
  468.                         }
  469.                     }
  470.                 }
  471.                 pfis->Release();
  472.                 break;
  473.             }
  474.             else if (SUCCEEDED(vItem.pdispVal->QueryInterface(IID_FolderItem, (void **)&pfi)))
  475.             {
  476.                 if (SUCCEEDED(pfi->get_Path(&bs)))
  477.                 {
  478.                     fileop.pFrom = (LPTSTR)LocalAlloc(LPTR, cch = (lstrlenW(bs)+2) * sizeof(TCHAR));
  479.                     if (fileop.pFrom)
  480.                         SHUnicodeToTChar(bs, (LPTSTR)fileop.pFrom, cch);
  481.                     SysFreeString(bs);
  482.                 }
  483.                 pfi->Release();
  484.                 break;
  485.             }
  486.         }
  487.         break;
  488.     default:
  489.         return E_INVALIDARG;   // don't support that type of variable.
  490.     }
  491.     if (!fileop.pFrom)
  492.          return E_OUTOFMEMORY;
  493.     // Now setup the Destination...
  494.     TCHAR szDest[MAX_PATH];
  495.     fileop.pTo = szDest;
  496.     SHGetPathFromIDList(m_pidl, szDest);
  497.     // Allow flags to pass through...
  498.     if (vOptions.vt == (VT_BYREF | VT_VARIANT) && vOptions.pvarVal)
  499.          vOptions = *vOptions.pvarVal;
  500.      // We need to get the source files out of the variant.
  501.      // Currently support string, or IDispatch (Either FolderItem or FolderItems)
  502.     switch (vOptions.vt)
  503.     {
  504.     case VT_I2:
  505.         fileop.fFlags = (FILEOP_FLAGS)vOptions.iVal;
  506.         break;
  507.         // And fall through...
  508.     case VT_I4:
  509.         fileop.fFlags = (FILEOP_FLAGS)vOptions.lVal;
  510.         break;
  511.     }
  512.     // Finally lets try to do the operation.
  513.     int ret = SHFileOperation(&fileop);
  514.     LocalFree((HLOCAL)fileop.pFrom);
  515.     return ret ? HRESULT_FROM_WIN32(ret) : NOERROR;
  516. }
  517. STDMETHODIMP CFolder::GetClassID(CLSID *pClassID)
  518. {
  519.     return E_NOTIMPL;
  520. }
  521. STDMETHODIMP CFolder::Initialize(LPCITEMIDLIST pidl)
  522. {
  523.     return E_NOTIMPL;
  524. }
  525. STDMETHODIMP CFolder::GetCurFolder(LPITEMIDLIST *ppidl)
  526. {
  527.     return SHILClone(m_pidl, ppidl);
  528. }