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 QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);
99 fileNameA.ReleaseBuffer();
100 fileName = GetUnicodeString(fileNameA);
101 }
102 else
103 #endif
104 {
105 UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
106 QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);
107 fileName.ReleaseBuffer();
108 }
109 return fileName;
110 }
111
QueryFileNames(UStringVector & fileNames)112 void CDrop::QueryFileNames(UStringVector &fileNames)
113 {
114 UINT numFiles = QueryCountOfFiles();
115 fileNames.ClearAndReserve(numFiles);
116 for (UINT i = 0; i < numFiles; i++)
117 fileNames.AddInReserved(QueryFileName(i));
118 }
119
120
GetPathFromIDList(LPCITEMIDLIST itemIDList,CSysString & path)121 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
122 {
123 bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));
124 path.ReleaseBuffer();
125 return result;
126 }
127
128 #endif
129
130 #ifdef UNDER_CE
131
BrowseForFolder(LPBROWSEINFO,CSysString)132 bool BrowseForFolder(LPBROWSEINFO, CSysString)
133 {
134 return false;
135 }
136
BrowseForFolder(HWND,LPCTSTR,UINT,LPCTSTR,CSysString &)137 bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
138 {
139 return false;
140 }
141
BrowseForFolder(HWND,LPCTSTR,LPCTSTR,CSysString &)142 bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
143 LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
144 {
145 /*
146 // SHBrowseForFolder doesn't work before CE 6.0 ?
147 if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
148 MessageBoxW(0, L"no", L"", 0);
149 else
150 MessageBoxW(0, L"yes", L"", 0);
151 */
152 /*
153 UString s = L"all files";
154 s += L" (*.*)";
155 return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
156 */
157 return false;
158 }
159
160 #else
161
BrowseForFolder(LPBROWSEINFO browseInfo,CSysString & resultPath)162 bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
163 {
164 NWindows::NCOM::CComInitializer comInitializer;
165 LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
166 if (itemIDList == NULL)
167 return false;
168 CItemIDList itemIDListHolder;
169 itemIDListHolder.Attach(itemIDList);
170 return GetPathFromIDList(itemIDList, resultPath);
171 }
172
173
BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)174 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
175 {
176 #ifndef UNDER_CE
177 switch(uMsg)
178 {
179 case BFFM_INITIALIZED:
180 {
181 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
182 break;
183 }
184 /*
185 case BFFM_SELCHANGED:
186 {
187 TCHAR dir[MAX_PATH];
188 if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
189 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
190 else
191 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
192 break;
193 }
194 */
195 default:
196 break;
197 }
198 #endif
199 return 0;
200 }
201
202
BrowseForFolder(HWND owner,LPCTSTR title,UINT ulFlags,LPCTSTR initialFolder,CSysString & resultPath)203 bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
204 LPCTSTR initialFolder, CSysString &resultPath)
205 {
206 CSysString displayName;
207 BROWSEINFO browseInfo;
208 browseInfo.hwndOwner = owner;
209 browseInfo.pidlRoot = NULL;
210
211 // there are Unicode/astring problems in WinCE SDK!!!
212 #ifdef UNDER_CE
213 browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);
214 browseInfo.lpszTitle = (LPCSTR)title;
215 #else
216 browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
217 browseInfo.lpszTitle = title;
218 #endif
219 browseInfo.ulFlags = ulFlags;
220 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
221 browseInfo.lParam = (LPARAM)initialFolder;
222 return BrowseForFolder(&browseInfo, resultPath);
223 }
224
BrowseForFolder(HWND owner,LPCTSTR title,LPCTSTR initialFolder,CSysString & resultPath)225 bool BrowseForFolder(HWND owner, LPCTSTR title,
226 LPCTSTR initialFolder, CSysString &resultPath)
227 {
228 return BrowseForFolder(owner, title,
229 #ifndef UNDER_CE
230 BIF_NEWDIALOGSTYLE |
231 #endif
232 BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
233 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
234 }
235
236 #ifndef _UNICODE
237
238 typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
239
GetPathFromIDList(LPCITEMIDLIST itemIDList,UString & path)240 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
241 {
242 path.Empty();
243 SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
244 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
245 if (shGetPathFromIDListW == 0)
246 return false;
247 bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));
248 path.ReleaseBuffer();
249 return result;
250 }
251
252 typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
253
BrowseForFolder(LPBROWSEINFOW browseInfo,UString & resultPath)254 bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
255 {
256 NWindows::NCOM::CComInitializer comInitializer;
257 SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
258 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
259 if (shBrowseForFolderW == 0)
260 return false;
261 LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
262 if (itemIDList == NULL)
263 return false;
264 CItemIDList itemIDListHolder;
265 itemIDListHolder.Attach(itemIDList);
266 return GetPathFromIDList(itemIDList, resultPath);
267 }
268
269
BrowseCallbackProc2(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)270 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
271 {
272 switch(uMsg)
273 {
274 case BFFM_INITIALIZED:
275 {
276 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
277 break;
278 }
279 /*
280 case BFFM_SELCHANGED:
281 {
282 wchar_t dir[MAX_PATH * 2];
283
284 if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
285 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
286 else
287 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
288 break;
289 }
290 */
291 default:
292 break;
293 }
294 return 0;
295 }
296
297
BrowseForFolder(HWND owner,LPCWSTR title,UINT ulFlags,LPCWSTR initialFolder,UString & resultPath)298 static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
299 LPCWSTR initialFolder, UString &resultPath)
300 {
301 UString displayName;
302 BROWSEINFOW browseInfo;
303 browseInfo.hwndOwner = owner;
304 browseInfo.pidlRoot = NULL;
305 browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
306 browseInfo.lpszTitle = title;
307 browseInfo.ulFlags = ulFlags;
308 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
309 browseInfo.lParam = (LPARAM)initialFolder;
310 return BrowseForFolder(&browseInfo, resultPath);
311 }
312
BrowseForFolder(HWND owner,LPCWSTR title,LPCWSTR initialFolder,UString & resultPath)313 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
314 {
315 if (g_IsNT)
316 return BrowseForFolder(owner, title,
317 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
318 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
319 , initialFolder, resultPath);
320 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
321 CSysString s;
322 bool res = BrowseForFolder(owner, GetSystemString(title),
323 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
324 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
325 , GetSystemString(initialFolder), s);
326 resultPath = GetUnicodeString(s);
327 return res;
328 }
329
330 #endif
331
332 #endif
333
334 }}
335