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

Windows Kernel

Development Platform:

Visual C++

  1. /*****************************************************************************
  2.     FILE:   isf.cpp
  3.     DESCRIPTION:
  4.         This is a base class that implements the default behavior of IShellFolder.
  5. *****************************************************************************/
  6. #include "priv.h"
  7. #include "isf.h"
  8. #include <shlobj.h>
  9. /*****************************************************************************
  10.     FUNCTION: IShellFolder::ParseDisplayName
  11.     DESCRIPTION:
  12. *****************************************************************************/
  13. HRESULT CBaseFolder::ParseDisplayName(HWND hwnd, LPBC pbcReserved, LPOLESTR pwszDisplayName,
  14.                         ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes)
  15. {
  16.     if (pdwAttributes)
  17.         *pdwAttributes = 0;
  18.     if (ppidl)
  19.         *ppidl = NULL;
  20.     return E_NOTIMPL;
  21. }
  22. /*****************************************************************************
  23.     FUNCTION: IShellFolder::EnumObjects
  24.     DESCRIPTION:
  25. *****************************************************************************/
  26. HRESULT CBaseFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags, IEnumIDList ** ppenumIDList)
  27. {
  28.     if (ppenumIDList)
  29.         *ppenumIDList = NULL;
  30.     return E_NOTIMPL;
  31. }
  32. /*****************************************************************************
  33.     FUNCTION: IShellFolder::BindToObject
  34.     DESCRIPTION:
  35. *****************************************************************************/
  36. HRESULT CBaseFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, LPVOID * ppvObj)
  37. {
  38.     if (ppvObj)
  39.         *ppvObj = NULL;
  40.     return E_NOTIMPL;
  41. }
  42. /*****************************************************************************
  43.      FUNCTION: IShellFolder::BindToStorage
  44.  
  45.     DESCRIPTION:
  46.          This should be implemented so people can use the File.Open and File.SaveAs
  47.     dialogs with this ShellFolder.
  48. *****************************************************************************/
  49. HRESULT CBaseFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, LPVOID * ppvObj)
  50. {
  51.     if (ppvObj)
  52.         *ppvObj = NULL;
  53.     return E_NOTIMPL;
  54. }
  55. /*****************************************************************************
  56.      FUNCTION: IShellFolder::CompareIDs
  57.  
  58.     DESCRIPTION:
  59.          This should be implemented so people can use the File.Open and File.SaveAs
  60.     dialogs with this ShellFolder.
  61. *****************************************************************************/
  62. HRESULT CBaseFolder::CompareIDs(LPARAM ici, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  63. {
  64.     return E_NOTIMPL;
  65. }
  66. /*****************************************************************************
  67.      FUNCTION: IShellFolder::CreateViewObject
  68.  
  69.     DESCRIPTION:
  70.          This should be implemented so people can use the File.Open and File.SaveAs
  71.     dialogs with this ShellFolder.
  72. *****************************************************************************/
  73. HRESULT CBaseFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvObj)
  74. {
  75.     HRESULT hr = E_NOINTERFACE;
  76.     *ppvObj = NULL;
  77.     if (IsEqualIID(riid, IID_IShellView))
  78.         hr = _CreateShellView(hwndOwner, ppvObj);
  79.     else if (IsEqualIID(riid, IID_IContextMenu))
  80.         hr = _GetUIObjectOf(hwndOwner, 0, NULL, riid, 0, ppvObj, TRUE);
  81.     else
  82.         hr = E_NOINTERFACE;
  83.     return hr;
  84. }
  85. BOOL IsShellIntegration(void)
  86. {
  87.     BOOL fResult = FALSE;
  88.     HINSTANCE hInst = LoadLibrary(TEXT("shell32.dll"));
  89.     if (EVAL(hInst))
  90.     {
  91.         LPVOID pv = GetProcAddress(hInst, "DllGetVersion");
  92.         if (pv)
  93.             fResult = TRUE;
  94.         FreeLibrary(hInst);
  95.     }
  96.     
  97.     return fResult;
  98. }
  99. HRESULT CBaseFolder::_CreateShellView(HWND hwndOwner, void ** ppvObj, LONG lEvents, FOLDERVIEWMODE fvm, 
  100.                                        IShellFolderViewCB * psfvCallBack, LPCITEMIDLIST pidl, LPFNVIEWCALLBACK pfnCallback)
  101. {
  102.     HRESULT hr;
  103.     IShellFolder * psf;
  104.     hr = this->QueryInterface(IID_IShellFolder, (LPVOID *) &psf);
  105.     if (EVAL(SUCCEEDED(hr)))
  106.     {
  107.         SFV_CREATE sfvCreate =      // SHCreateShellFolderView struct
  108.         {
  109.                 sizeof(SFV_CREATE),
  110.                 psf,            // psf
  111.                 NULL,           // psvOuter
  112.                 psfvCallBack    // psfvcb - (IShellFolderViewCB *)
  113.         };
  114.         // SHCreateShellFolderView isn't in the original shell.  We can't rely on the 
  115.         // the Delayload code because it's exported by ordinal and the original
  116.         // shell had a different exports by the same number.
  117.         if (IsShellIntegration())
  118.             hr = _SHCreateShellFolderView(&sfvCreate, (LPSHELLVIEW FAR*)ppvObj);
  119.         else
  120.             hr = E_FAIL;  // Force us to go into the next try.
  121.         // If we aren't running on a machine with Shell Integration, SHCreateShellFolderView will fail.
  122.         if (FAILED(hr))
  123.         {
  124.             CSFV csfv;
  125.             csfv.cbSize = sizeof(csfv);
  126.             csfv.pshf = psf;
  127.             csfv.psvOuter = (IShellView *) psfvCallBack;      // Hack but it works...
  128.             csfv.pidl = pidl;           // This is feed to SFVM_GETNOTIFY so it needs to be a pidlTarget.
  129.             csfv.lEvents = lEvents;
  130.             csfv.pfnCallback = pfnCallback;
  131.             csfv.fvm = fvm;         // vs. FVM_ICON, ...
  132.             hr = SHCreateShellFolderViewEx(&csfv, (LPSHELLVIEW FAR*)ppvObj);
  133.             if (SUCCEEDED(hr))
  134.                 psfvCallBack->AddRef();     // We gave them a ref.
  135.         }
  136.         psf->Release();
  137.     }
  138.     return hr;
  139. }
  140. /*****************************************************************************
  141.      FUNCTION: IShellFolder::GetAttributesOf
  142.  
  143.     DESCRIPTION:
  144. *****************************************************************************/
  145. HRESULT CBaseFolder::GetAttributesOf(UINT cpidl, LPCITEMIDLIST *apidl, ULONG *rgfInOut)
  146. {
  147.     return E_NOTIMPL;
  148. }
  149. /*****************************************************************************
  150.      FUNCTION: IShellFolder::GetUIObjectOf
  151.  
  152.     DESCRIPTION:
  153. *****************************************************************************/
  154. HRESULT CBaseFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST rgpidl[],
  155.                                 REFIID riid, UINT * prgfInOut, LPVOID * ppvObj)
  156. {
  157.     return E_NOTIMPL;
  158. }
  159. /*****************************************************************************
  160.     DESCRIPTION:
  161. *****************************************************************************/
  162. HRESULT CBaseFolder::_GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST rgpidl[],
  163.                                 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut, BOOL fFromCreateViewObject)
  164. {
  165.     return GetUIObjectOf(hwndOwner, cidl, rgpidl, riid, prgfInOut, ppvOut);
  166. }
  167. /*****************************************************************************
  168.      FUNCTION: IShellFolder::GetDisplayNameOf
  169.  
  170.     DESCRIPTION:
  171. *****************************************************************************/
  172. HRESULT CBaseFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD shgno, LPSTRRET pStrRet)
  173. {
  174.     return E_NOTIMPL;
  175. }
  176. /*****************************************************************************
  177.      FUNCTION: IShellFolder::SetNameOf
  178.  
  179.     DESCRIPTION:
  180. *****************************************************************************/
  181. HRESULT CBaseFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR pwszName,
  182.                                 DWORD dwReserved, LPITEMIDLIST *ppidlOut)
  183. {
  184.     return E_NOTIMPL;
  185. }
  186. //===========================
  187. // *** IShellFolder2 Interface ***
  188. //===========================
  189. //===========================
  190. // *** IPersist Interface ***
  191. //===========================
  192. /*****************************************************************************
  193.      FUNCTION: IPersist::GetClassID
  194.  
  195.     DESCRIPTION:
  196. *****************************************************************************/
  197. HRESULT CBaseFolder::GetClassID(LPCLSID pClassID)
  198. {
  199.     HRESULT hr = E_INVALIDARG;
  200.     if (EVAL(pClassID))
  201.     {
  202.         if (EVAL(m_pClassID))
  203.         {
  204.             *pClassID = *m_pClassID;
  205.             hr = S_OK;
  206.         }
  207.         else
  208.             hr = E_FAIL;
  209.     }
  210.     return hr;
  211. }
  212. //===========================
  213. // *** IPersistFolder Interface ***
  214. //===========================
  215. /*****************************************************************************
  216.     DESCRIPTION:
  217. *****************************************************************************/
  218. HRESULT CBaseFolder::Initialize(LPCITEMIDLIST pidl)
  219. {
  220.     ASSERT(!m_pidl);   // Don't reroot us.
  221.     return _Initialize(pidl, NULL, ILGetSize(pidl) - sizeof(pidl->mkid.cb));
  222. }
  223. //===========================
  224. // *** IPersistFolder2 Interface ***
  225. //===========================
  226. /***************************************************************************** 
  227.     DESCRIPTION:
  228. *****************************************************************************/
  229. HRESULT CBaseFolder::GetCurFolder(LPITEMIDLIST *ppidl)
  230. {
  231.     HRESULT hr = E_INVALIDARG;
  232.     if (EVAL(ppidl))
  233.     {
  234.         hr = E_FAIL;
  235.         if (m_pidlRoot)
  236.         {
  237.             *ppidl = ILClone(m_pidlRoot);
  238.         }
  239.         else if (EVAL(m_pidl))
  240.         {
  241.             *ppidl = GetPublicTargetPidlClone();
  242.         }
  243.         if (*ppidl)
  244.             hr = S_OK;
  245.     }
  246.     return hr;
  247. }
  248. //===========================
  249. // *** IPersistFolder3 Interface ***
  250. //===========================
  251. HRESULT GetPidlFromPersistFolderTargetInfo(const PERSIST_FOLDER_TARGET_INFO *ppfti, LPITEMIDLIST * ppidl, BOOL fFree)
  252. {
  253.     HRESULT hr = E_INVALIDARG;
  254.     if (ppidl)
  255.     {
  256.         *ppidl = NULL;
  257.         if (ppfti->pidlTargetFolder)
  258.         {
  259.             *ppidl = (fFree ? ppfti->pidlTargetFolder : ILClone(ppfti->pidlTargetFolder));
  260.             if (*ppidl)
  261.                 hr = S_OK;
  262.             else
  263.                 hr = E_OUTOFMEMORY;
  264.         }
  265.         else
  266.         {
  267.             if (ppfti->szTargetParsingName[0])
  268.             {
  269.                 hr = IEParseDisplayNameWithBCW(CP_ACP, ppfti->szTargetParsingName, NULL, ppidl);
  270.             }
  271.             if (!*ppidl && (-1 != ppfti->csidl))
  272.             {
  273.                 hr = SHGetSpecialFolderLocation(NULL, ppfti->csidl, ppidl);
  274.             }
  275.         }
  276.     }
  277.     
  278.     return hr;
  279. }
  280. /*****************************************************************************
  281.     DESCRIPTION:
  282. *****************************************************************************/
  283. HRESULT CBaseFolder::InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti)
  284. {
  285.     HRESULT hr = E_INVALIDARG;
  286.     if (EVAL(pidlRoot))
  287.     {
  288.         if (ppfti)
  289.         {
  290.             // We are a Folder Shortcut.
  291.             LPITEMIDLIST pidlTarget;
  292.             hr = GetPidlFromPersistFolderTargetInfo(ppfti, &pidlTarget, FALSE);  // Get the real root.           
  293.             TraceMsg(TF_FOLDER_SHRTCUTS, "CBaseFolder::InitializeEx() this=%#08lx, pidlTarget=%#08lx, pidlRoot=%#08lx", this, pidlTarget, pidlRoot);
  294.             AssertMsg((NULL != pidlTarget), TEXT("CBaseFolder::InitializeEx() We are useless without a pidlTarget so watch me go limp."));
  295.             if (pidlTarget)
  296.             {
  297.                 hr = _Initialize(pidlTarget, pidlRoot, m_nIDOffsetToPrivate);
  298.                 ILFree(pidlTarget);
  299.             }
  300.         }
  301.         else
  302.         {
  303.             // We aren't a folder shortcut.
  304.             hr = Initialize(pidlRoot);
  305.         }
  306.     }
  307.     return hr;
  308. }
  309. HRESULT CBaseFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti)
  310. {
  311.     HRESULT hr = E_INVALIDARG;
  312.     AssertMsg((NULL != ppfti), TEXT("CBaseFolder::GetFolderTargetInfo() Caller passed an invalid param."));
  313.     if (ppfti)
  314.     {
  315.         ZeroMemory(ppfti, sizeof(*ppfti)); 
  316.         ppfti->pidlTargetFolder = ILClone(m_pidlRoot);
  317.         ppfti->dwAttributes = -1;
  318.         ppfti->csidl = -1;
  319.         hr = S_OK;
  320.     }
  321.     return hr;
  322. }
  323. LPCITEMIDLIST CBaseFolder::GetPrivatePidlReference(void)
  324. {
  325.     return _ILSkip(m_pidl, m_nIDOffsetToPrivate);
  326. }
  327. // This function always needs the InternetExplorer pidl.
  328. LPITEMIDLIST CBaseFolder::GetPublicPidlRootIDClone(void)
  329. {
  330.     LPITEMIDLIST pidlFull = ILClone(m_pidl);
  331.     LPITEMIDLIST pidlPrivStart = _ILSkip(pidlFull, m_nIDOffsetToPrivate);
  332.     // Strip all Private ItemIDs
  333.     while (!ILIsEmpty(pidlPrivStart))
  334.         ILRemoveLastID(pidlPrivStart);
  335.     return pidlFull;
  336. }
  337. LPITEMIDLIST CBaseFolder::CreateFullPrivatePidl(LPCITEMIDLIST pidlPrivateSubPidl)
  338. {
  339.     return ILCombine(GetPrivatePidlReference(), pidlPrivateSubPidl);
  340. }
  341. LPITEMIDLIST CBaseFolder::CreateFullPublicPidlFromRelative(LPCITEMIDLIST pidlPrivateSubPidl)
  342. {
  343.     return ILCombine(GetPublicRootPidlReference(), pidlPrivateSubPidl);
  344. }
  345. LPITEMIDLIST CBaseFolder::CreateFullPublicPidl(LPCITEMIDLIST pidlPrivatePidl)
  346. {
  347.     LPITEMIDLIST pidlRoot = GetPublicPidlRootIDClone();
  348.     LPITEMIDLIST pidlResult = NULL;
  349.     
  350.     if (pidlRoot)
  351.     {
  352.         pidlResult = ILCombine(pidlRoot, pidlPrivatePidl);
  353.         ILFree(pidlRoot);
  354.     }
  355.     return pidlResult;
  356. }
  357. HRESULT CBaseFolder::_Initialize(LPCITEMIDLIST pidlTarget, LPCITEMIDLIST pidlRoot, int nBytesToPrivate)
  358. {
  359.     HRESULT hr = E_INVALIDARG;
  360.     if (pidlTarget)
  361.     {
  362.         ILFree(m_pidl);
  363.         ILFree(m_pidlRoot);    
  364.         m_pidl = ILClone(pidlTarget);
  365.         m_pidlRoot = ILClone(pidlRoot); // This is the Folder Shortcut pidl.  We don't use it outselves.
  366.         if (m_pidl)
  367.         {
  368.             m_nIDOffsetToPrivate = nBytesToPrivate;
  369.             hr = S_OK;
  370.         }
  371.         else
  372.             hr = E_OUTOFMEMORY;
  373.     }
  374.     return hr;
  375. }
  376. /****************************************************
  377.     Constructor
  378. ****************************************************/
  379. CBaseFolder::CBaseFolder(LPCLSID pClassID) : m_cRef(1)
  380. {
  381.     DllAddRef();
  382.     // This needs to be allocated in Zero Inited Memory.
  383.     // Assert that all Member Variables are inited to Zero.
  384.     ASSERT(!m_pidl);
  385.     ASSERT(!m_nIDOffsetToPrivate);
  386.     ASSERT(!m_pClassID);
  387.     m_pClassID = pClassID;
  388.     ASSERT(pClassID);
  389. }
  390. /****************************************************
  391.     Destructor
  392. ****************************************************/
  393. CBaseFolder::~CBaseFolder()
  394. {
  395.     Pidl_Set(&m_pidlRoot, NULL);    // Folder Shortcut pidl
  396.     Pidl_Set(&m_pidl, NULL);
  397.     DllRelease();
  398. }
  399. //===========================
  400. // *** IUnknown Interface ***
  401. //===========================
  402. ULONG CBaseFolder::AddRef()
  403. {
  404.     m_cRef++;
  405.     return m_cRef;
  406. }
  407. ULONG CBaseFolder::Release()
  408. {
  409.     ASSERT(m_cRef > 0);
  410.     m_cRef--;
  411.     if (m_cRef > 0)
  412.         return m_cRef;
  413.     delete this;
  414.     return 0;
  415. }
  416. HRESULT CBaseFolder::QueryInterface(REFIID riid, void **ppvObj)
  417. {
  418.     static const QITAB qit[] = {
  419.         QITABENTMULTI(CBaseFolder, IShellFolder, IShellFolder2),
  420.         QITABENTMULTI(CBaseFolder, IPersist, IPersistFolder),
  421.         QITABENTMULTI(CBaseFolder, IPersist, IPersistFolder3),
  422.         QITABENTMULTI(CBaseFolder, IPersistFolder, IPersistFolder3),
  423.         QITABENTMULTI(CBaseFolder, IPersistFolder2, IPersistFolder3),
  424.         QITABENT(CBaseFolder, IShellFolder2),
  425.         QITABENT(CBaseFolder, IPersistFolder3),
  426.         QITABENT(CBaseFolder, IObjectWithSite),
  427.         { 0 },
  428.     };
  429.     return QISearch(this, qit, riid, ppvObj);
  430. }