aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/Shell.cpp
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Windows/Shell.cpp
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-21.07.tar.gz
7zip-21.07.tar.bz2
7zip-21.07.zip
'21.07'21.07
Diffstat (limited to 'CPP/Windows/Shell.cpp')
-rw-r--r--CPP/Windows/Shell.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
new file mode 100644
index 0000000..d0f9032
--- /dev/null
+++ b/CPP/Windows/Shell.cpp
@@ -0,0 +1,358 @@
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
19extern bool g_IsNT;
20#endif
21
22namespace NWindows {
23namespace NShell {
24
25#ifndef UNDER_CE
26
27// SHGetMalloc is unsupported in Windows Mobile?
28
29void 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/*
41CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)
42 { *this = itemIDList; }
43CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)
44 { *this = itemIDList; }
45
46CItemIDList& 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
59CItemIDList& 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
76void CDrop::Attach(HDROP object)
77{
78 Free();
79 m_Object = object;
80 m_Assigned = true;
81}
82
83void CDrop::Free()
84{
85 if (m_MustBeFinished && m_Assigned)
86 Finish();
87 m_Assigned = false;
88}
89
90UINT CDrop::QueryCountOfFiles()
91{
92 return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
93}
94
95UString 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
119void 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
141bool 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
153bool BrowseForFolder(LPBROWSEINFO, CSysString)
154{
155 return false;
156}
157
158bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
159{
160 return false;
161}
162
163bool 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
183bool 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
195static 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
224static 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
248bool 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
261typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
262
263bool 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
276typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
277
278static 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
293static
294int 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
322static 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
337bool 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}}