1 // RootFolder.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/MyWindows.h"
6
7 #include <ShlObj.h>
8
9 #include "../../../Common/StringConvert.h"
10
11 #include "../../../Windows/DLL.h"
12 #include "../../../Windows/FileName.h"
13 #include "../../../Windows/PropVariant.h"
14
15 #include "../../PropID.h"
16
17 #if defined(_WIN32) && !defined(UNDER_CE)
18 #define USE_WIN_PATHS
19 #endif
20
21 static const unsigned kNumRootFolderItems =
22 #ifdef USE_WIN_PATHS
23 4
24 #else
25 1
26 #endif
27 ;
28
29
30 #include "FSFolder.h"
31 #include "LangUtils.h"
32 #ifdef USE_WIN_PATHS
33 #include "NetFolder.h"
34 #include "FSDrives.h"
35 #include "AltStreamsFolder.h"
36 #endif
37 #include "RootFolder.h"
38 #include "SysIconUtils.h"
39
40 #include "resource.h"
41
42 using namespace NWindows;
43
44 static const Byte kProps[] =
45 {
46 kpidName
47 };
48
49 UString RootFolder_GetName_Computer(int &iconIndex);
RootFolder_GetName_Computer(int & iconIndex)50 UString RootFolder_GetName_Computer(int &iconIndex)
51 {
52 #ifdef USE_WIN_PATHS
53 iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
54 #else
55 GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
56 #endif
57 return LangString(IDS_COMPUTER);
58 }
59
60 UString RootFolder_GetName_Network(int &iconIndex);
RootFolder_GetName_Network(int & iconIndex)61 UString RootFolder_GetName_Network(int &iconIndex)
62 {
63 iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK);
64 return LangString(IDS_NETWORK);
65 }
66
67 UString RootFolder_GetName_Documents(int &iconIndex);
RootFolder_GetName_Documents(int & iconIndex)68 UString RootFolder_GetName_Documents(int &iconIndex)
69 {
70 iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL);
71 return LangString(IDS_DOCUMENTS);
72 }
73
74 enum
75 {
76 ROOT_INDEX_COMPUTER = 0
77 #ifdef USE_WIN_PATHS
78 , ROOT_INDEX_DOCUMENTS
79 , ROOT_INDEX_NETWORK
80 , ROOT_INDEX_VOLUMES
81 #endif
82 };
83
84 #ifdef USE_WIN_PATHS
85 static const char * const kVolPrefix = "\\\\.";
86 #endif
87
Init()88 void CRootFolder::Init()
89 {
90 _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]);
91 #ifdef USE_WIN_PATHS
92 _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
93 _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
94 _names[ROOT_INDEX_VOLUMES] = kVolPrefix;
95 _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES);
96 #endif
97 }
98
LoadItems()99 STDMETHODIMP CRootFolder::LoadItems()
100 {
101 Init();
102 return S_OK;
103 }
104
GetNumberOfItems(UInt32 * numItems)105 STDMETHODIMP CRootFolder::GetNumberOfItems(UInt32 *numItems)
106 {
107 *numItems = kNumRootFolderItems;
108 return S_OK;
109 }
110
GetProperty(UInt32 itemIndex,PROPID propID,PROPVARIANT * value)111 STDMETHODIMP CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
112 {
113 NCOM::CPropVariant prop;
114 switch (propID)
115 {
116 case kpidIsDir: prop = true; break;
117 case kpidName: prop = _names[itemIndex]; break;
118 }
119 prop.Detach(value);
120 return S_OK;
121 }
122
123 typedef BOOL (WINAPI *SHGetSpecialFolderPathWp)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
124 typedef BOOL (WINAPI *SHGetSpecialFolderPathAp)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate);
125
GetMyDocsPath()126 static UString GetMyDocsPath()
127 {
128 UString us;
129 WCHAR s[MAX_PATH + 1];
130 SHGetSpecialFolderPathWp getW = (SHGetSpecialFolderPathWp)
131 #ifdef UNDER_CE
132 My_GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), "SHGetSpecialFolderPath");
133 #else
134 My_GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetSpecialFolderPathW");
135 #endif
136 if (getW && getW(0, s, CSIDL_PERSONAL, FALSE))
137 us = s;
138 #ifndef _UNICODE
139 else
140 {
141 SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp)
142 (void *)::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA");
143 CHAR s2[MAX_PATH + 1];
144 if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE))
145 us = GetUnicodeString(s2);
146 }
147 #endif
148 NFile::NName::NormalizeDirPathPrefix(us);
149 return us;
150 }
151
BindToFolder(UInt32 index,IFolderFolder ** resultFolder)152 STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
153 {
154 *resultFolder = NULL;
155 CMyComPtr<IFolderFolder> subFolder;
156
157 #ifdef USE_WIN_PATHS
158 if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES)
159 {
160 CFSDrives *fsDrivesSpec = new CFSDrives;
161 subFolder = fsDrivesSpec;
162 fsDrivesSpec->Init(index == ROOT_INDEX_VOLUMES);
163 }
164 else if (index == ROOT_INDEX_NETWORK)
165 {
166 CNetFolder *netFolderSpec = new CNetFolder;
167 subFolder = netFolderSpec;
168 netFolderSpec->Init(0, 0, _names[ROOT_INDEX_NETWORK] + WCHAR_PATH_SEPARATOR);
169 }
170 else if (index == ROOT_INDEX_DOCUMENTS)
171 {
172 UString s = GetMyDocsPath();
173 if (!s.IsEmpty())
174 {
175 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
176 subFolder = fsFolderSpec;
177 RINOK(fsFolderSpec->Init(us2fs(s)));
178 }
179 }
180 #else
181 if (index == ROOT_INDEX_COMPUTER)
182 {
183 NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
184 subFolder = fsFolder;
185 fsFolder->InitToRoot();
186 }
187 #endif
188 else
189 return E_INVALIDARG;
190
191 *resultFolder = subFolder.Detach();
192 return S_OK;
193 }
194
AreEqualNames(const UString & path,const wchar_t * name)195 static bool AreEqualNames(const UString &path, const wchar_t *name)
196 {
197 unsigned len = MyStringLen(name);
198 if (len > path.Len() || len + 1 < path.Len())
199 return false;
200 if (len + 1 == path.Len() && !IS_PATH_SEPAR(path[len]))
201 return false;
202 return path.IsPrefixedBy(name);
203 }
204
BindToFolder(const wchar_t * name,IFolderFolder ** resultFolder)205 STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
206 {
207 *resultFolder = 0;
208 UString name2 = name;
209 name2.Trim();
210
211 if (name2.IsEmpty())
212 {
213 CRootFolder *rootFolderSpec = new CRootFolder;
214 CMyComPtr<IFolderFolder> rootFolder = rootFolderSpec;
215 rootFolderSpec->Init();
216 *resultFolder = rootFolder.Detach();
217 return S_OK;
218 }
219
220 for (unsigned i = 0; i < kNumRootFolderItems; i++)
221 if (AreEqualNames(name2, _names[i]))
222 return BindToFolder((UInt32)i, resultFolder);
223
224 #ifdef USE_WIN_PATHS
225 if (AreEqualNames(name2, L"My Documents") ||
226 AreEqualNames(name2, L"Documents"))
227 return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder);
228 #else
229 if (name2 == WSTRING_PATH_SEPARATOR)
230 return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
231 #endif
232
233 if (AreEqualNames(name2, L"My Computer") ||
234 AreEqualNames(name2, L"Computer"))
235 return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
236
237 if (name2 == WSTRING_PATH_SEPARATOR)
238 {
239 CMyComPtr<IFolderFolder> subFolder = this;
240 *resultFolder = subFolder.Detach();
241 return S_OK;
242 }
243
244 if (name2.Len() < 2)
245 return E_INVALIDARG;
246
247 CMyComPtr<IFolderFolder> subFolder;
248
249 #ifdef USE_WIN_PATHS
250 if (name2.IsPrefixedBy_Ascii_NoCase(kVolPrefix))
251 {
252 CFSDrives *folderSpec = new CFSDrives;
253 subFolder = folderSpec;
254 folderSpec->Init(true);
255 }
256 else if (name2.IsEqualTo(NFile::NName::kSuperPathPrefix))
257 {
258 CFSDrives *folderSpec = new CFSDrives;
259 subFolder = folderSpec;
260 folderSpec->Init(false, true);
261 }
262 else if (name2.Back() == ':')
263 {
264 NAltStreamsFolder::CAltStreamsFolder *folderSpec = new NAltStreamsFolder::CAltStreamsFolder;
265 subFolder = folderSpec;
266 if (folderSpec->Init(us2fs(name2)) != S_OK)
267 return E_INVALIDARG;
268 }
269 else
270 #endif
271 {
272 NFile::NName::NormalizeDirPathPrefix(name2);
273 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
274 subFolder = fsFolderSpec;
275 if (fsFolderSpec->Init(us2fs(name2)) != S_OK)
276 {
277 #ifdef USE_WIN_PATHS
278 if (IS_PATH_SEPAR(name2[0]))
279 {
280 CNetFolder *netFolderSpec = new CNetFolder;
281 subFolder = netFolderSpec;
282 netFolderSpec->Init(name2);
283 }
284 else
285 #endif
286 return E_INVALIDARG;
287 }
288 }
289
290 *resultFolder = subFolder.Detach();
291 return S_OK;
292 }
293
BindToParentFolder(IFolderFolder ** resultFolder)294 STDMETHODIMP CRootFolder::BindToParentFolder(IFolderFolder **resultFolder)
295 {
296 *resultFolder = 0;
297 return S_OK;
298 }
299
IMP_IFolderFolder_Props(CRootFolder)300 IMP_IFolderFolder_Props(CRootFolder)
301
302 STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
303 {
304 NCOM::CPropVariant prop;
305 switch (propID)
306 {
307 case kpidType: prop = "RootFolder"; break;
308 case kpidPath: prop = ""; break;
309 }
310 prop.Detach(value);
311 return S_OK;
312 }
313
GetSystemIconIndex(UInt32 index,Int32 * iconIndex)314 STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
315 {
316 *iconIndex = _iconIndices[index];
317 return S_OK;
318 }
319