1 /*
2  *    Virtual Desktop Folder
3  *
4  *    Copyright 1997                Marcus Meissner
5  *    Copyright 1998, 1999, 2002    Juergen Schmied
6  *    Copyright 2009                Andrew Hill
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #ifndef _CDESKTOPFOLDER_H_
24 #define _CDESKTOPFOLDER_H_
25 
26 class CStubFolderBase : public IShellFolder
27 {
28 public:
29     CStubFolderBase() { }
30 
31     STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override { return E_NOTIMPL; }
32     STDMETHODIMP_(ULONG) AddRef()  override { return 3; }
33     STDMETHODIMP_(ULONG) Release() override { return 2; }
34 
35     // IShellFolder methods
36     STDMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
37                                   DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override
38     { return E_NOTIMPL; }
39     STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override
40     { return E_NOTIMPL; }
41     STDMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override
42     { return E_NOTIMPL; }
43     STDMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override
44     { return E_NOTIMPL; }
45     STDMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) override
46     { return E_NOTIMPL; }
47     STDMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) override
48     { return E_NOTIMPL; }
49     STDMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) override
50     { return E_NOTIMPL; }
51     STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
52                                REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) override
53     { return E_NOTIMPL; }
54     STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) override
55     { return E_NOTIMPL; }
56     STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName,
57                            DWORD dwFlags, PITEMID_CHILD *pPidlOut) override
58     { return E_NOTIMPL; }
59 };
60 
61 class CShellUrlStub : public CStubFolderBase
62 {
63 public:
64     STDMETHODIMP
65     ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
66                      PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
67 };
68 
69 class CFileUrlStub : public CStubFolderBase
70 {
71 public:
72     STDMETHODIMP
73     ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
74                      PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
75 };
76 
77 class CIDListUrlStub : public CStubFolderBase
78 {
79 public:
80     STDMETHODIMP
81     ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
82                      PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
83 };
84 
85 class CHttpUrlStub : public CStubFolderBase
86 {
87 public:
88     STDMETHODIMP
89     ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
90                      PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
91 };
92 
93 class CDesktopFolder :
94     public CComCoClass<CDesktopFolder, &CLSID_ShellDesktop>,
95     public CComObjectRootEx<CComMultiThreadModelNoCS>,
96     public IShellFolder2,
97     public IPersistFolder2,
98     public IContextMenuCB,
99     public IItemNameLimits
100 {
101     private:
102         /* both paths are parsible from the desktop */
103         CComPtr<IShellFolder2> m_DesktopFSFolder;
104         CComPtr<IShellFolder2> m_SharedDesktopFSFolder;
105         CComPtr<IShellFolder2> m_regFolder;
106 
107         // Stub URL objects
108         CShellUrlStub   m_ShellUrlStub;
109         CFileUrlStub    m_FileUrlStub;
110         CIDListUrlStub  m_IDListUrlStub;
111         CHttpUrlStub    m_HttpUrlStub;
112 
113         LPWSTR sPathTarget;     /* complete path to target used for enumeration and ChangeNotify */
114         LPITEMIDLIST pidlRoot;  /* absolute pidl */
115 
116         HRESULT _GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf);
117 
118         BOOL _TryUrlJunctions(
119             LPCWSTR pcszURL,
120             IBindCtx *pBindCtx,
121             IShellFolder **ppShellFolder,
122             LPITEMIDLIST *ppidl);
123         BOOL _GetParentForParsing(
124             LPCWSTR pszPath,
125             IBindCtx *pbc,
126             IShellFolder **ppParentFolder,
127             LPITEMIDLIST *ppidlParent);
128         HRESULT _ChildParseDisplayName(
129             IShellFolder *pParentFolder,
130             LPCITEMIDLIST pidlParent,
131             HWND hwndOwner,
132             IBindCtx *pBindCtx,
133             LPWSTR lpszDisplayName,
134             DWORD *pchEaten,
135             LPITEMIDLIST *ppidl,
136             DWORD *pdwAttributes);
137 
138     public:
139         CDesktopFolder();
140         ~CDesktopFolder();
141         HRESULT WINAPI FinalConstruct();
142 
143         // *** IShellFolder methods ***
144         STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
145         STDMETHOD(EnumObjects)(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override;
146         STDMETHOD(BindToObject)(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override;
147         STDMETHOD(BindToStorage)(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override;
148         STDMETHOD(CompareIDs)(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) override;
149         STDMETHOD(CreateViewObject)(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) override;
150         STDMETHOD(GetAttributesOf)(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) override;
151         STDMETHOD(GetUIObjectOf)(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) override;
152         STDMETHOD(GetDisplayNameOf)(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) override;
153         STDMETHOD(SetNameOf)(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) override;
154 
155         // *** IShellFolder2 methods ***
156         STDMETHOD(GetDefaultSearchGUID)(GUID *pguid) override;
157         STDMETHOD(EnumSearches)(IEnumExtraSearch **ppenum) override;
158         STDMETHOD(GetDefaultColumn)(DWORD dwRes, ULONG *pSort, ULONG *pDisplay) override;
159         STDMETHOD(GetDefaultColumnState)(UINT iColumn, DWORD *pcsFlags) override;
160         STDMETHOD(GetDetailsEx)(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) override;
161         STDMETHOD(GetDetailsOf)(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd) override;
162         STDMETHOD(MapColumnToSCID)(UINT column, SHCOLUMNID *pscid) override;
163 
164         // *** IPersist methods ***
165         STDMETHOD(GetClassID)(CLSID *lpClassId) override;
166 
167         // *** IPersistFolder methods ***
168         STDMETHOD(Initialize)(PCIDLIST_ABSOLUTE pidl) override;
169 
170         // *** IPersistFolder2 methods ***
171         STDMETHOD(GetCurFolder)(PIDLIST_ABSOLUTE * pidl) override;
172 
173         // IContextMenuCB
174         STDMETHOD(CallBack)(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
175 
176         /*** IItemNameLimits methods ***/
177 
178         STDMETHODIMP
179         GetMaxLength(LPCWSTR pszName, int *piMaxNameLen) override
180         {
181             return E_NOTIMPL;
182         }
183 
184         STDMETHODIMP
185         GetValidCharacters(LPWSTR *ppwszValidChars, LPWSTR *ppwszInvalidChars) override
186         {
187             if (ppwszValidChars)
188             {
189                 *ppwszValidChars = NULL;
190             }
191             if (ppwszInvalidChars)
192             {
193                 SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars);
194             }
195             return S_OK;
196         }
197 
198         DECLARE_REGISTRY_RESOURCEID(IDR_SHELLDESKTOP)
199         DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(CDesktopFolder)
200 
201         DECLARE_PROTECT_FINAL_CONSTRUCT()
202 
203         BEGIN_COM_MAP(CDesktopFolder)
204         COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
205         COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
206         COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
207         COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
208         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
209         COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
210         END_COM_MAP()
211 };
212 
213 #endif /* _CDESKTOPFOLDER_H_ */
214