1 // Windows/Shell.cpp
2
3 #include "StdAfx.h"
4
5 #include "../Common/MyCom.h"
6 #ifndef _UNICODE
7 #include "../Common/StringConvert.h"
8 #endif
9
10 #include "COM.h"
11 #include "Shell.h"
12
13 #ifndef _UNICODE
14 extern bool g_IsNT;
15 #endif
16
17 namespace NWindows {
18 namespace NShell {
19
20 #ifndef UNDER_CE
21
22 // SHGetMalloc is unsupported in Windows Mobile?
23
Free()24 void CItemIDList::Free()
25 {
26 if (m_Object == NULL)
27 return;
28 CMyComPtr<IMalloc> shellMalloc;
29 if (::SHGetMalloc(&shellMalloc) != NOERROR)
30 throw 41099;
31 shellMalloc->Free(m_Object);
32 m_Object = NULL;
33 }
34
35 /*
36 CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)
37 { *this = itemIDList; }
38 CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)
39 { *this = itemIDList; }
40
41 CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)
42 {
43 Free();
44 if (object != 0)
45 {
46 UINT32 size = GetSize(object);
47 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
48 if (m_Object != NULL)
49 MoveMemory(m_Object, object, size);
50 }
51 return *this;
52 }
53
54 CItemIDList& CItemIDList::operator=(const CItemIDList &object)
55 {
56 Free();
57 if (object.m_Object != NULL)
58 {
59 UINT32 size = GetSize(object.m_Object);
60 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
61 if (m_Object != NULL)
62 MoveMemory(m_Object, object.m_Object, size);
63 }
64 return *this;
65 }
66 */
67
68 /////////////////////////////
69 // CDrop
70
Attach(HDROP object)71 void CDrop::Attach(HDROP object)
72 {
73 Free();
74 m_Object = object;
75 m_Assigned = true;
76 }
77
Free()78 void CDrop::Free()
79 {
80 if (m_MustBeFinished && m_Assigned)
81 Finish();
82 m_Assigned = false;
83 }
84
QueryCountOfFiles()85 UINT CDrop::QueryCountOfFiles()
86 {
87 return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
88 }
89
QueryFileName(UINT fileIndex)90 UString CDrop::QueryFileName(UINT fileIndex)
91 {
92 UString fileName;
93 #ifndef _UNICODE
94 if (!g_IsNT)
95 {
96 AString fileNameA;
97 UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
98 const unsigned len = bufferSize + 2;
99 QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);
100 fileNameA.ReleaseBuf_CalcLen(len);
101 fileName = GetUnicodeString(fileNameA);
102 }
103 else
104 #endif
105 {
106 UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
107 const unsigned len = bufferSize + 2;
108 QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);
109 fileName.ReleaseBuf_CalcLen(len);
110 }
111 return fileName;
112 }
113
QueryFileNames(UStringVector & fileNames)114 void CDrop::QueryFileNames(UStringVector &fileNames)
115 {
116 UINT numFiles = QueryCountOfFiles();
117 fileNames.ClearAndReserve(numFiles);
118 for (UINT i = 0; i < numFiles; i++)
119 fileNames.AddInReserved(QueryFileName(i));
120 }
121
122
GetPathFromIDList(LPCITEMIDLIST itemIDList,CSysString & path)123 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
124 {
125 const unsigned len = MAX_PATH * 2;
126 bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
127 path.ReleaseBuf_CalcLen(len);
128 return result;
129 }
130
131 #endif
132
133 #ifdef UNDER_CE
134
BrowseForFolder(LPBROWSEINFO,CSysString)135 bool BrowseForFolder(LPBROWSEINFO, CSysString)
136 {
137 return false;
138 }
139
BrowseForFolder(HWND,LPCTSTR,UINT,LPCTSTR,CSysString &)140 bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
141 {
142 return false;
143 }
144
BrowseForFolder(HWND,LPCTSTR,LPCTSTR,CSysString &)145 bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
146 LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
147 {
148 /*
149 // SHBrowseForFolder doesn't work before CE 6.0 ?
150 if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
151 MessageBoxW(0, L"no", L"", 0);
152 else
153 MessageBoxW(0, L"yes", L"", 0);
154 */
155 /*
156 UString s = L"all files";
157 s += L" (*.*)";
158 return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
159 */
160 return false;
161 }
162
163 #else
164
BrowseForFolder(LPBROWSEINFO browseInfo,CSysString & resultPath)165 bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
166 {
167 NWindows::NCOM::CComInitializer comInitializer;
168 LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
169 if (itemIDList == NULL)
170 return false;
171 CItemIDList itemIDListHolder;
172 itemIDListHolder.Attach(itemIDList);
173 return GetPathFromIDList(itemIDList, resultPath);
174 }
175
176
BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)177 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
178 {
179 #ifndef UNDER_CE
180 switch (uMsg)
181 {
182 case BFFM_INITIALIZED:
183 {
184 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
185 break;
186 }
187 /*
188 case BFFM_SELCHANGED:
189 {
190 TCHAR dir[MAX_PATH];
191 if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
192 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
193 else
194 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
195 break;
196 }
197 */
198 default:
199 break;
200 }
201 #endif
202 return 0;
203 }
204
205
BrowseForFolder(HWND owner,LPCTSTR title,UINT ulFlags,LPCTSTR initialFolder,CSysString & resultPath)206 bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
207 LPCTSTR initialFolder, CSysString &resultPath)
208 {
209 CSysString displayName;
210 BROWSEINFO browseInfo;
211 browseInfo.hwndOwner = owner;
212 browseInfo.pidlRoot = NULL;
213
214 // there are Unicode/Astring problems in some WinCE SDK ?
215 /*
216 #ifdef UNDER_CE
217 browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);
218 browseInfo.lpszTitle = (LPCSTR)title;
219 #else
220 */
221 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
222 browseInfo.lpszTitle = title;
223 // #endif
224 browseInfo.ulFlags = ulFlags;
225 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
226 browseInfo.lParam = (LPARAM)initialFolder;
227 return BrowseForFolder(&browseInfo, resultPath);
228 }
229
BrowseForFolder(HWND owner,LPCTSTR title,LPCTSTR initialFolder,CSysString & resultPath)230 bool BrowseForFolder(HWND owner, LPCTSTR title,
231 LPCTSTR initialFolder, CSysString &resultPath)
232 {
233 return BrowseForFolder(owner, title,
234 #ifndef UNDER_CE
235 BIF_NEWDIALOGSTYLE |
236 #endif
237 BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
238 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
239 }
240
241 #ifndef _UNICODE
242
243 typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
244
GetPathFromIDList(LPCITEMIDLIST itemIDList,UString & path)245 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
246 {
247 path.Empty();
248 SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
249 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
250 if (shGetPathFromIDListW == 0)
251 return false;
252 const unsigned len = MAX_PATH * 2;
253 bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
254 path.ReleaseBuf_CalcLen(len);
255 return result;
256 }
257
258 typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
259
BrowseForFolder(LPBROWSEINFOW browseInfo,UString & resultPath)260 bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
261 {
262 NWindows::NCOM::CComInitializer comInitializer;
263 SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
264 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
265 if (shBrowseForFolderW == 0)
266 return false;
267 LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
268 if (itemIDList == NULL)
269 return false;
270 CItemIDList itemIDListHolder;
271 itemIDListHolder.Attach(itemIDList);
272 return GetPathFromIDList(itemIDList, resultPath);
273 }
274
275
BrowseCallbackProc2(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)276 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
277 {
278 switch (uMsg)
279 {
280 case BFFM_INITIALIZED:
281 {
282 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
283 break;
284 }
285 /*
286 case BFFM_SELCHANGED:
287 {
288 wchar_t dir[MAX_PATH * 2];
289
290 if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
291 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
292 else
293 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
294 break;
295 }
296 */
297 default:
298 break;
299 }
300 return 0;
301 }
302
303
BrowseForFolder(HWND owner,LPCWSTR title,UINT ulFlags,LPCWSTR initialFolder,UString & resultPath)304 static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
305 LPCWSTR initialFolder, UString &resultPath)
306 {
307 UString displayName;
308 BROWSEINFOW browseInfo;
309 browseInfo.hwndOwner = owner;
310 browseInfo.pidlRoot = NULL;
311 browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
312 browseInfo.lpszTitle = title;
313 browseInfo.ulFlags = ulFlags;
314 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
315 browseInfo.lParam = (LPARAM)initialFolder;
316 return BrowseForFolder(&browseInfo, resultPath);
317 }
318
BrowseForFolder(HWND owner,LPCWSTR title,LPCWSTR initialFolder,UString & resultPath)319 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
320 {
321 if (g_IsNT)
322 return BrowseForFolder(owner, title,
323 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
324 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
325 , initialFolder, resultPath);
326 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
327 CSysString s;
328 bool res = BrowseForFolder(owner, GetSystemString(title),
329 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
330 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
331 , GetSystemString(initialFolder), s);
332 resultPath = GetUnicodeString(s);
333 return res;
334 }
335
336 #endif
337
338 #endif
339
340 }}
341