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