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