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 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 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 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 
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