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