1 // NetFolder.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Windows/PropVariant.h"
6
7 #include "../../PropID.h"
8
9 #include "FSFolder.h"
10 #include "NetFolder.h"
11 #include "SysIconUtils.h"
12
13 using namespace NWindows;
14 using namespace NNet;
15
16 static const Byte kProps[] =
17 {
18 kpidName,
19 kpidLocalName,
20 kpidComment,
21 kpidProvider
22 };
23
Init(const UString & path)24 void CNetFolder::Init(const UString &path)
25 {
26 /*
27 if (path.Len() > 2)
28 {
29 if (path[0] == L'\\' && path[1] == L'\\')
30 {
31 CResource netResource;
32 netResource.RemoteName = GetSystemString(path.Left(path.Len() - 1));
33 netResource.Scope = RESOURCE_GLOBALNET;
34 netResource.Type = RESOURCETYPE_DISK;
35 netResource.DisplayType = RESOURCEDISPLAYTYPE_SERVER;
36 netResource.Usage = RESOURCEUSAGE_CONTAINER;
37 Init(&netResource, 0, path);
38 return;
39 }
40 }
41 Init(0, 0 , L"");
42 */
43 CResourceW resource;
44 resource.RemoteNameIsDefined = true;
45 if (!path.IsEmpty())
46 resource.RemoteName.SetFrom(path, path.Len() - 1);
47 resource.ProviderIsDefined = false;
48 resource.LocalNameIsDefined = false;
49 resource.CommentIsDefined = false;
50 resource.Type = RESOURCETYPE_DISK;
51 resource.Scope = RESOURCE_GLOBALNET;
52 resource.Usage = 0;
53 resource.DisplayType = 0;
54 CResourceW destResource;
55 UString systemPathPart;
56 DWORD result = GetResourceInformation(resource, destResource, systemPathPart);
57 if (result == NO_ERROR)
58 Init(&destResource, 0, path);
59 else
60 Init(0, 0 , L"");
61 return;
62 }
63
Init(const NWindows::NNet::CResourceW * netResource,IFolderFolder * parentFolder,const UString & path)64 void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource,
65 IFolderFolder *parentFolder, const UString &path)
66 {
67 _path = path;
68 if (netResource == 0)
69 _netResourcePointer = 0;
70 else
71 {
72 _netResource = *netResource;
73 _netResourcePointer = &_netResource;
74
75 // if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
76 _path = _netResource.RemoteName;
77
78 /* WinXP-64: When we move UP from Network share without _parentFolder chain,
79 we can get empty _netResource.RemoteName. Do we need to use Provider there ? */
80 if (_path.IsEmpty())
81 _path = _netResource.Provider;
82
83 if (!_path.IsEmpty())
84 _path.Add_PathSepar();
85 }
86 _parentFolder = parentFolder;
87 }
88
LoadItems()89 STDMETHODIMP CNetFolder::LoadItems()
90 {
91 _items.Clear();
92 CEnum enumerator;
93
94 for (;;)
95 {
96 DWORD result = enumerator.Open(
97 RESOURCE_GLOBALNET,
98 RESOURCETYPE_DISK,
99 0, // enumerate all resources
100 _netResourcePointer
101 );
102 if (result == NO_ERROR)
103 break;
104 if (result != ERROR_ACCESS_DENIED)
105 return result;
106 if (_netResourcePointer != 0)
107 result = AddConnection2(_netResource,
108 0, 0, CONNECT_INTERACTIVE);
109 if (result != NO_ERROR)
110 return result;
111 }
112
113 for (;;)
114 {
115 CResourceEx resource;
116 DWORD result = enumerator.Next(resource);
117 if (result == NO_ERROR)
118 {
119 if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong
120 resource.RemoteName = resource.Comment;
121 resource.Name = resource.RemoteName;
122 int pos = resource.Name.ReverseFind_PathSepar();
123 if (pos >= 0)
124 {
125 // _path = resource.Name.Left(pos + 1);
126 resource.Name.DeleteFrontal(pos + 1);
127 }
128 _items.Add(resource);
129 }
130 else if (result == ERROR_NO_MORE_ITEMS)
131 break;
132 else
133 return result;
134 }
135
136 /*
137 It's too slow for some systems.
138 if (_netResourcePointer && _netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
139 {
140 for (char c = 'a'; c <= 'z'; c++)
141 {
142 CResourceEx resource;
143 resource.Name = UString(wchar_t(c)) + L'$';
144 resource.RemoteNameIsDefined = true;
145 resource.RemoteName = _path + resource.Name;
146
147 NFile::NFind::CFindFile findFile;
148 NFile::NFind::CFileInfo fileInfo;
149 if (!findFile.FindFirst(us2fs(resource.RemoteName) + FString(FCHAR_PATH_SEPARATOR) + FCHAR_ANY_MASK, fileInfo))
150 continue;
151 resource.Usage = RESOURCEUSAGE_CONNECTABLE;
152 resource.LocalNameIsDefined = false;
153 resource.CommentIsDefined = false;
154 resource.ProviderIsDefined = false;
155 _items.Add(resource);
156 }
157 }
158 */
159 return S_OK;
160 }
161
162
GetNumberOfItems(UInt32 * numItems)163 STDMETHODIMP CNetFolder::GetNumberOfItems(UInt32 *numItems)
164 {
165 *numItems = _items.Size();
166 return S_OK;
167 }
168
GetProperty(UInt32 itemIndex,PROPID propID,PROPVARIANT * value)169 STDMETHODIMP CNetFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
170 {
171 NCOM::CPropVariant prop;
172 const CResourceEx &item = _items[itemIndex];
173 switch (propID)
174 {
175 case kpidIsDir: prop = true; break;
176 case kpidName:
177 // if (item.RemoteNameIsDefined)
178 prop = item.Name;
179 break;
180 case kpidLocalName: if (item.LocalNameIsDefined) prop = item.LocalName; break;
181 case kpidComment: if (item.CommentIsDefined) prop = item.Comment; break;
182 case kpidProvider: if (item.ProviderIsDefined) prop = item.Provider; break;
183 }
184 prop.Detach(value);
185 return S_OK;
186 }
187
BindToFolder(UInt32 index,IFolderFolder ** resultFolder)188 STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
189 {
190 *resultFolder = 0;
191 const CResourceEx &resource = _items[index];
192 if (resource.Usage == RESOURCEUSAGE_CONNECTABLE ||
193 resource.DisplayType == RESOURCEDISPLAYTYPE_SHARE)
194 {
195 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
196 CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
197 RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR))); // , this
198 *resultFolder = subFolder.Detach();
199 }
200 else
201 {
202 CNetFolder *netFolder = new CNetFolder;
203 CMyComPtr<IFolderFolder> subFolder = netFolder;
204 netFolder->Init(&resource, this, resource.Name + WCHAR_PATH_SEPARATOR);
205 *resultFolder = subFolder.Detach();
206 }
207 return S_OK;
208 }
209
BindToFolder(const wchar_t *,IFolderFolder **)210 STDMETHODIMP CNetFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder ** /* resultFolder */)
211 {
212 return E_NOTIMPL;
213 }
214
BindToParentFolder(IFolderFolder ** resultFolder)215 STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder)
216 {
217 *resultFolder = 0;
218 if (_parentFolder)
219 {
220 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
221 *resultFolder = parentFolder.Detach();
222 return S_OK;
223 }
224 if (_netResourcePointer != 0)
225 {
226 CResourceW resourceParent;
227 DWORD result = GetResourceParent(_netResource, resourceParent);
228 if (result != NO_ERROR)
229 return result;
230 if (!_netResource.RemoteNameIsDefined)
231 return S_OK;
232
233 CNetFolder *netFolder = new CNetFolder;
234 CMyComPtr<IFolderFolder> subFolder = netFolder;
235 netFolder->Init(&resourceParent, 0, WSTRING_PATH_SEPARATOR);
236 *resultFolder = subFolder.Detach();
237 }
238 return S_OK;
239 }
240
IMP_IFolderFolder_Props(CNetFolder)241 IMP_IFolderFolder_Props(CNetFolder)
242
243 STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
244 {
245 NWindows::NCOM::CPropVariant prop;
246 switch (propID)
247 {
248 case kpidType: prop = "NetFolder"; break;
249 case kpidPath: prop = _path; break;
250 }
251 prop.Detach(value);
252 return S_OK;
253 }
254
GetSystemIconIndex(UInt32 index,Int32 * iconIndex)255 STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
256 {
257 if (index >= (UInt32)_items.Size())
258 return E_INVALIDARG;
259 *iconIndex = 0;
260 const CResourceW &resource = _items[index];
261 int iconIndexTemp;
262 if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
263 resource.Usage == RESOURCEUSAGE_CONNECTABLE)
264 {
265 if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp))
266 {
267 *iconIndex = iconIndexTemp;
268 return S_OK;
269 }
270 }
271 else
272 {
273 if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp))
274 {
275 *iconIndex = iconIndexTemp;
276 return S_OK;
277 }
278 // *anIconIndex = GetRealIconIndex(0, L"\\\\HOME");
279 }
280 return GetLastError();
281 }
282