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 = "all files";
157   s += " (*.*)";
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