1*f6dc9357SAndroid Build Coastguard Worker // Windows/Shell.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MyCom.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StringConvert.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "COM.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "FileName.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "MemoryGlobal.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "Shell.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
14*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
15*f6dc9357SAndroid Build Coastguard Worker #endif
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker // MSVC6 and old SDK don't support this function:
18*f6dc9357SAndroid Build Coastguard Worker // #define LWSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
19*f6dc9357SAndroid Build Coastguard Worker // LWSTDAPI StrRetToStrW(STRRET *pstr, LPCITEMIDLIST pidl, LPWSTR *ppsz);
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_SHELL
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_SHELL
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker #include "../Common/IntToString.h"
26*f6dc9357SAndroid Build Coastguard Worker
Print_Number(UInt32 number,const char * s)27*f6dc9357SAndroid Build Coastguard Worker static void Print_Number(UInt32 number, const char *s)
28*f6dc9357SAndroid Build Coastguard Worker {
29*f6dc9357SAndroid Build Coastguard Worker AString s2;
30*f6dc9357SAndroid Build Coastguard Worker s2.Add_UInt32(number);
31*f6dc9357SAndroid Build Coastguard Worker s2.Add_Space();
32*f6dc9357SAndroid Build Coastguard Worker s2 += s;
33*f6dc9357SAndroid Build Coastguard Worker OutputDebugStringA(s2);
34*f6dc9357SAndroid Build Coastguard Worker }
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker #define ODS(sz) { OutputDebugStringA(sz); }
37*f6dc9357SAndroid Build Coastguard Worker #define ODS_U(s) { OutputDebugStringW(s); }
38*f6dc9357SAndroid Build Coastguard Worker #define ODS_(op) { op; }
39*f6dc9357SAndroid Build Coastguard Worker
40*f6dc9357SAndroid Build Coastguard Worker #else
41*f6dc9357SAndroid Build Coastguard Worker
42*f6dc9357SAndroid Build Coastguard Worker #define ODS(sz)
43*f6dc9357SAndroid Build Coastguard Worker #define ODS_U(s)
44*f6dc9357SAndroid Build Coastguard Worker #define ODS_(op)
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker #endif
47*f6dc9357SAndroid Build Coastguard Worker
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
50*f6dc9357SAndroid Build Coastguard Worker namespace NShell {
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker // SHGetMalloc is unsupported in Windows Mobile?
55*f6dc9357SAndroid Build Coastguard Worker
Free()56*f6dc9357SAndroid Build Coastguard Worker void CItemIDList::Free()
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker if (!m_Object)
59*f6dc9357SAndroid Build Coastguard Worker return;
60*f6dc9357SAndroid Build Coastguard Worker /* DOCs:
61*f6dc9357SAndroid Build Coastguard Worker SHGetMalloc was introduced in Windows 95 and Microsoft Windows NT 4.0,
62*f6dc9357SAndroid Build Coastguard Worker but as of Windows 2000 it is no longer necessary.
63*f6dc9357SAndroid Build Coastguard Worker In its place, programs can call the equivalent (and easier to use) CoTaskMemAlloc and CoTaskMemFree.
64*f6dc9357SAndroid Build Coastguard Worker Description from oldnewthings:
65*f6dc9357SAndroid Build Coastguard Worker shell functions could work without COM (if OLE32.DLL is not loaded),
66*f6dc9357SAndroid Build Coastguard Worker but now if OLE32.DLL is loaded, then shell functions and com functions do same things.
67*f6dc9357SAndroid Build Coastguard Worker 22.02: so we use OLE32.DLL function to free memory:
68*f6dc9357SAndroid Build Coastguard Worker */
69*f6dc9357SAndroid Build Coastguard Worker /*
70*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IMalloc> shellMalloc;
71*f6dc9357SAndroid Build Coastguard Worker if (::SHGetMalloc(&shellMalloc) != NOERROR)
72*f6dc9357SAndroid Build Coastguard Worker throw 41099;
73*f6dc9357SAndroid Build Coastguard Worker shellMalloc->Free(m_Object);
74*f6dc9357SAndroid Build Coastguard Worker */
75*f6dc9357SAndroid Build Coastguard Worker CoTaskMemFree(m_Object);
76*f6dc9357SAndroid Build Coastguard Worker m_Object = NULL;
77*f6dc9357SAndroid Build Coastguard Worker }
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker /*
80*f6dc9357SAndroid Build Coastguard Worker CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)
81*f6dc9357SAndroid Build Coastguard Worker { *this = itemIDList; }
82*f6dc9357SAndroid Build Coastguard Worker CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)
83*f6dc9357SAndroid Build Coastguard Worker { *this = itemIDList; }
84*f6dc9357SAndroid Build Coastguard Worker
85*f6dc9357SAndroid Build Coastguard Worker CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker Free();
88*f6dc9357SAndroid Build Coastguard Worker if (object != 0)
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker UINT32 size = GetSize(object);
91*f6dc9357SAndroid Build Coastguard Worker m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
92*f6dc9357SAndroid Build Coastguard Worker if (m_Object != NULL)
93*f6dc9357SAndroid Build Coastguard Worker MoveMemory(m_Object, object, size);
94*f6dc9357SAndroid Build Coastguard Worker }
95*f6dc9357SAndroid Build Coastguard Worker return *this;
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker
98*f6dc9357SAndroid Build Coastguard Worker CItemIDList& CItemIDList::operator=(const CItemIDList &object)
99*f6dc9357SAndroid Build Coastguard Worker {
100*f6dc9357SAndroid Build Coastguard Worker Free();
101*f6dc9357SAndroid Build Coastguard Worker if (object.m_Object != NULL)
102*f6dc9357SAndroid Build Coastguard Worker {
103*f6dc9357SAndroid Build Coastguard Worker UINT32 size = GetSize(object.m_Object);
104*f6dc9357SAndroid Build Coastguard Worker m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
105*f6dc9357SAndroid Build Coastguard Worker if (m_Object != NULL)
106*f6dc9357SAndroid Build Coastguard Worker MoveMemory(m_Object, object.m_Object, size);
107*f6dc9357SAndroid Build Coastguard Worker }
108*f6dc9357SAndroid Build Coastguard Worker return *this;
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker */
111*f6dc9357SAndroid Build Coastguard Worker
112*f6dc9357SAndroid Build Coastguard Worker
ReadUnicodeStrings(const wchar_t * p,size_t size,UStringVector & names)113*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names)
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker names.Clear();
116*f6dc9357SAndroid Build Coastguard Worker const wchar_t *lim = p + size;
117*f6dc9357SAndroid Build Coastguard Worker UString s;
118*f6dc9357SAndroid Build Coastguard Worker /*
119*f6dc9357SAndroid Build Coastguard Worker if (size == 0 || p[size - 1] != 0)
120*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
121*f6dc9357SAndroid Build Coastguard Worker if (size == 1)
122*f6dc9357SAndroid Build Coastguard Worker return S_OK;
123*f6dc9357SAndroid Build Coastguard Worker if (p[size - 2] != 0)
124*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
125*f6dc9357SAndroid Build Coastguard Worker */
126*f6dc9357SAndroid Build Coastguard Worker for (;;)
127*f6dc9357SAndroid Build Coastguard Worker {
128*f6dc9357SAndroid Build Coastguard Worker const wchar_t *start = p;
129*f6dc9357SAndroid Build Coastguard Worker for (;;)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker if (p == lim) return E_INVALIDARG; // S_FALSE
132*f6dc9357SAndroid Build Coastguard Worker if (*p++ == 0)
133*f6dc9357SAndroid Build Coastguard Worker break;
134*f6dc9357SAndroid Build Coastguard Worker }
135*f6dc9357SAndroid Build Coastguard Worker const size_t num = (size_t)(p - start);
136*f6dc9357SAndroid Build Coastguard Worker if (num == 1)
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker if (p != lim) return E_INVALIDARG; // S_FALSE
139*f6dc9357SAndroid Build Coastguard Worker return S_OK;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker s.SetFrom(start, (unsigned)(num - 1));
142*f6dc9357SAndroid Build Coastguard Worker ODS_U(s)
143*f6dc9357SAndroid Build Coastguard Worker names.Add(s);
144*f6dc9357SAndroid Build Coastguard Worker // names.ReserveOnePosition();
145*f6dc9357SAndroid Build Coastguard Worker // names.AddInReserved_Ptr_of_new(new UString((unsigned)num - 1, start));
146*f6dc9357SAndroid Build Coastguard Worker }
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker
149*f6dc9357SAndroid Build Coastguard Worker
ReadAnsiStrings(const char * p,size_t size,UStringVector & names)150*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names)
151*f6dc9357SAndroid Build Coastguard Worker {
152*f6dc9357SAndroid Build Coastguard Worker names.Clear();
153*f6dc9357SAndroid Build Coastguard Worker AString name;
154*f6dc9357SAndroid Build Coastguard Worker for (; size != 0; size--)
155*f6dc9357SAndroid Build Coastguard Worker {
156*f6dc9357SAndroid Build Coastguard Worker const char c = *p++;
157*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
160*f6dc9357SAndroid Build Coastguard Worker return S_OK;
161*f6dc9357SAndroid Build Coastguard Worker names.Add(GetUnicodeString(name));
162*f6dc9357SAndroid Build Coastguard Worker name.Empty();
163*f6dc9357SAndroid Build Coastguard Worker }
164*f6dc9357SAndroid Build Coastguard Worker else
165*f6dc9357SAndroid Build Coastguard Worker name.Add_Char(c);
166*f6dc9357SAndroid Build Coastguard Worker }
167*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker #define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
172*f6dc9357SAndroid Build Coastguard Worker
DataObject_GetData_HGLOBAL(IDataObject * dataObject,CLIPFORMAT cf,NCOM::CStgMedium & medium)173*f6dc9357SAndroid Build Coastguard Worker static HRESULT DataObject_GetData_HGLOBAL(IDataObject *dataObject, CLIPFORMAT cf, NCOM::CStgMedium &medium)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker FORMATETC etc = INIT_FORMATETC_HGLOBAL(cf);
176*f6dc9357SAndroid Build Coastguard Worker RINOK(dataObject->GetData(&etc, &medium))
177*f6dc9357SAndroid Build Coastguard Worker if (medium.tymed != TYMED_HGLOBAL)
178*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
179*f6dc9357SAndroid Build Coastguard Worker return S_OK;
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker
DataObject_GetData_HDROP_Names(IDataObject * dataObject,UStringVector & names)182*f6dc9357SAndroid Build Coastguard Worker static HRESULT DataObject_GetData_HDROP_Names(IDataObject *dataObject, UStringVector &names)
183*f6dc9357SAndroid Build Coastguard Worker {
184*f6dc9357SAndroid Build Coastguard Worker names.Clear();
185*f6dc9357SAndroid Build Coastguard Worker NCOM::CStgMedium medium;
186*f6dc9357SAndroid Build Coastguard Worker
187*f6dc9357SAndroid Build Coastguard Worker /* Win10 : if (dataObject) is from IContextMenu::Initialize() and
188*f6dc9357SAndroid Build Coastguard Worker if (len_of_path >= MAX_PATH (260) for some file in data object)
189*f6dc9357SAndroid Build Coastguard Worker {
190*f6dc9357SAndroid Build Coastguard Worker GetData() returns HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
191*f6dc9357SAndroid Build Coastguard Worker "The data area passed to a system call is too small",
192*f6dc9357SAndroid Build Coastguard Worker Is there a way to fix this code for long paths?
193*f6dc9357SAndroid Build Coastguard Worker } */
194*f6dc9357SAndroid Build Coastguard Worker
195*f6dc9357SAndroid Build Coastguard Worker RINOK(DataObject_GetData_HGLOBAL(dataObject, CF_HDROP, medium))
196*f6dc9357SAndroid Build Coastguard Worker const size_t blockSize = GlobalSize(medium.hGlobal);
197*f6dc9357SAndroid Build Coastguard Worker if (blockSize < sizeof(DROPFILES))
198*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
199*f6dc9357SAndroid Build Coastguard Worker NMemory::CGlobalLock dropLock(medium.hGlobal);
200*f6dc9357SAndroid Build Coastguard Worker const DROPFILES *dropFiles = (const DROPFILES *)dropLock.GetPointer();
201*f6dc9357SAndroid Build Coastguard Worker if (!dropFiles)
202*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
203*f6dc9357SAndroid Build Coastguard Worker if (blockSize < dropFiles->pFiles
204*f6dc9357SAndroid Build Coastguard Worker || dropFiles->pFiles < sizeof(DROPFILES)
205*f6dc9357SAndroid Build Coastguard Worker // || dropFiles->pFiles != sizeof(DROPFILES)
206*f6dc9357SAndroid Build Coastguard Worker )
207*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
208*f6dc9357SAndroid Build Coastguard Worker const size_t size = blockSize - dropFiles->pFiles;
209*f6dc9357SAndroid Build Coastguard Worker const void *namesData = (const Byte *)(const void *)dropFiles + dropFiles->pFiles;
210*f6dc9357SAndroid Build Coastguard Worker HRESULT hres;
211*f6dc9357SAndroid Build Coastguard Worker if (dropFiles->fWide)
212*f6dc9357SAndroid Build Coastguard Worker {
213*f6dc9357SAndroid Build Coastguard Worker if (size % sizeof(wchar_t) != 0)
214*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
215*f6dc9357SAndroid Build Coastguard Worker hres = ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names);
216*f6dc9357SAndroid Build Coastguard Worker }
217*f6dc9357SAndroid Build Coastguard Worker else
218*f6dc9357SAndroid Build Coastguard Worker hres = ReadAnsiStrings((const char *)namesData, size, names);
219*f6dc9357SAndroid Build Coastguard Worker
220*f6dc9357SAndroid Build Coastguard Worker ODS_(Print_Number(names.Size(), "DataObject_GetData_HDROP_Names"))
221*f6dc9357SAndroid Build Coastguard Worker return hres;
222*f6dc9357SAndroid Build Coastguard Worker }
223*f6dc9357SAndroid Build Coastguard Worker
224*f6dc9357SAndroid Build Coastguard Worker
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker // CF_IDLIST:
227*f6dc9357SAndroid Build Coastguard Worker #define MYWIN_CFSTR_SHELLIDLIST TEXT("Shell IDList Array")
228*f6dc9357SAndroid Build Coastguard Worker
229*f6dc9357SAndroid Build Coastguard Worker typedef struct
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker UINT cidl;
232*f6dc9357SAndroid Build Coastguard Worker UINT aoffset[1];
233*f6dc9357SAndroid Build Coastguard Worker } MYWIN_CIDA;
234*f6dc9357SAndroid Build Coastguard Worker /*
235*f6dc9357SAndroid Build Coastguard Worker cidl : number of PIDLs that are being transferred, not including the parent folder.
236*f6dc9357SAndroid Build Coastguard Worker aoffset : An array of offsets, relative to the beginning of this structure.
237*f6dc9357SAndroid Build Coastguard Worker aoffset[0] - fully qualified PIDL of a parent folder.
238*f6dc9357SAndroid Build Coastguard Worker If this PIDL is empty, the parent folder is the desktop.
239*f6dc9357SAndroid Build Coastguard Worker aoffset[1] ... aoffset[cidl] : offset to one of the PIDLs to be transferred.
240*f6dc9357SAndroid Build Coastguard Worker All of these PIDLs are relative to the PIDL of the parent folder.
241*f6dc9357SAndroid Build Coastguard Worker */
242*f6dc9357SAndroid Build Coastguard Worker
DataObject_GetData_IDLIST(IDataObject * dataObject,UStringVector & names)243*f6dc9357SAndroid Build Coastguard Worker static HRESULT DataObject_GetData_IDLIST(IDataObject *dataObject, UStringVector &names)
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker names.Clear();
246*f6dc9357SAndroid Build Coastguard Worker NCOM::CStgMedium medium;
247*f6dc9357SAndroid Build Coastguard Worker RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)
248*f6dc9357SAndroid Build Coastguard Worker RegisterClipboardFormat(MYWIN_CFSTR_SHELLIDLIST), medium))
249*f6dc9357SAndroid Build Coastguard Worker const size_t blockSize = GlobalSize(medium.hGlobal);
250*f6dc9357SAndroid Build Coastguard Worker if (blockSize < sizeof(MYWIN_CIDA) || blockSize >= (UInt32)((UInt32)0 - 1))
251*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
252*f6dc9357SAndroid Build Coastguard Worker NMemory::CGlobalLock dropLock(medium.hGlobal);
253*f6dc9357SAndroid Build Coastguard Worker const MYWIN_CIDA *cida = (const MYWIN_CIDA *)dropLock.GetPointer();
254*f6dc9357SAndroid Build Coastguard Worker if (!cida)
255*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
256*f6dc9357SAndroid Build Coastguard Worker if (cida->cidl == 0)
257*f6dc9357SAndroid Build Coastguard Worker {
258*f6dc9357SAndroid Build Coastguard Worker // is it posssible to have no selected items?
259*f6dc9357SAndroid Build Coastguard Worker // it's unexpected case.
260*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
261*f6dc9357SAndroid Build Coastguard Worker }
262*f6dc9357SAndroid Build Coastguard Worker if (cida->cidl >= (blockSize - (UInt32)sizeof(MYWIN_CIDA)) / sizeof(UINT))
263*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
264*f6dc9357SAndroid Build Coastguard Worker const UInt32 start = cida->cidl * (UInt32)sizeof(UINT) + (UInt32)sizeof(MYWIN_CIDA);
265*f6dc9357SAndroid Build Coastguard Worker
266*f6dc9357SAndroid Build Coastguard Worker STRRET strret;
267*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IShellFolder> parentFolder;
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker const UINT offset = cida->aoffset[0];
270*f6dc9357SAndroid Build Coastguard Worker if (offset < start || offset >= blockSize
271*f6dc9357SAndroid Build Coastguard Worker // || offset != start
272*f6dc9357SAndroid Build Coastguard Worker )
273*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
274*f6dc9357SAndroid Build Coastguard Worker
275*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IShellFolder> desktopFolder;
276*f6dc9357SAndroid Build Coastguard Worker RINOK(::SHGetDesktopFolder(&desktopFolder))
277*f6dc9357SAndroid Build Coastguard Worker if (!desktopFolder)
278*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
279*f6dc9357SAndroid Build Coastguard Worker
280*f6dc9357SAndroid Build Coastguard Worker LPCITEMIDLIST const lpcItem = (LPCITEMIDLIST)(const void *)((const Byte *)cida + offset);
281*f6dc9357SAndroid Build Coastguard Worker
282*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_SHELL
283*f6dc9357SAndroid Build Coastguard Worker {
284*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = desktopFolder->GetDisplayNameOf(
285*f6dc9357SAndroid Build Coastguard Worker lpcItem, SHGDN_FORPARSING, &strret);
286*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && strret.uType == STRRET_WSTR)
287*f6dc9357SAndroid Build Coastguard Worker {
288*f6dc9357SAndroid Build Coastguard Worker ODS_U(strret.pOleStr)
289*f6dc9357SAndroid Build Coastguard Worker /* if lpcItem is empty, the path will be
290*f6dc9357SAndroid Build Coastguard Worker "C:\Users\user_name\Desktop"
291*f6dc9357SAndroid Build Coastguard Worker if lpcItem is "My Computer" folder, the path will be
292*f6dc9357SAndroid Build Coastguard Worker "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" */
293*f6dc9357SAndroid Build Coastguard Worker CoTaskMemFree(strret.pOleStr);
294*f6dc9357SAndroid Build Coastguard Worker }
295*f6dc9357SAndroid Build Coastguard Worker }
296*f6dc9357SAndroid Build Coastguard Worker #endif
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker RINOK(desktopFolder->BindToObject(lpcItem,
299*f6dc9357SAndroid Build Coastguard Worker NULL, IID_IShellFolder, (void **)&parentFolder))
300*f6dc9357SAndroid Build Coastguard Worker if (!parentFolder)
301*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
302*f6dc9357SAndroid Build Coastguard Worker }
303*f6dc9357SAndroid Build Coastguard Worker
304*f6dc9357SAndroid Build Coastguard Worker names.ClearAndReserve(cida->cidl);
305*f6dc9357SAndroid Build Coastguard Worker UString path;
306*f6dc9357SAndroid Build Coastguard Worker
307*f6dc9357SAndroid Build Coastguard Worker // for (int y = 0; y < 1; y++) // for debug
308*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 1; i <= cida->cidl; i++)
309*f6dc9357SAndroid Build Coastguard Worker {
310*f6dc9357SAndroid Build Coastguard Worker const UINT offset = cida->aoffset[i];
311*f6dc9357SAndroid Build Coastguard Worker if (offset < start || offset >= blockSize)
312*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
313*f6dc9357SAndroid Build Coastguard Worker const void *p = (const Byte *)(const void *)cida + offset;
314*f6dc9357SAndroid Build Coastguard Worker /* ITEMIDLIST of file can contain more than one SHITEMID item.
315*f6dc9357SAndroid Build Coastguard Worker In win10 only SHGDN_FORPARSING returns path that contains
316*f6dc9357SAndroid Build Coastguard Worker all path parts related to parts of ITEMIDLIST.
317*f6dc9357SAndroid Build Coastguard Worker So we can use only SHGDN_FORPARSING here.
318*f6dc9357SAndroid Build Coastguard Worker Don't use (SHGDN_INFOLDER)
319*f6dc9357SAndroid Build Coastguard Worker Don't use (SHGDN_INFOLDER | SHGDN_FORPARSING)
320*f6dc9357SAndroid Build Coastguard Worker */
321*f6dc9357SAndroid Build Coastguard Worker RINOK(parentFolder->GetDisplayNameOf((LPCITEMIDLIST)p, SHGDN_FORPARSING, &strret))
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker /*
324*f6dc9357SAndroid Build Coastguard Worker // MSVC6 and old SDK do not support StrRetToStrW().
325*f6dc9357SAndroid Build Coastguard Worker LPWSTR lpstr;
326*f6dc9357SAndroid Build Coastguard Worker RINOK (StrRetToStrW(&strret, NULL, &lpstr))
327*f6dc9357SAndroid Build Coastguard Worker ODS_U(lpstr)
328*f6dc9357SAndroid Build Coastguard Worker path = lpstr;
329*f6dc9357SAndroid Build Coastguard Worker CoTaskMemFree(lpstr);
330*f6dc9357SAndroid Build Coastguard Worker */
331*f6dc9357SAndroid Build Coastguard Worker if (strret.uType != STRRET_WSTR)
332*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
333*f6dc9357SAndroid Build Coastguard Worker ODS_U(strret.pOleStr)
334*f6dc9357SAndroid Build Coastguard Worker path = strret.pOleStr;
335*f6dc9357SAndroid Build Coastguard Worker // the path could have super path prefix "\\\\?\\"
336*f6dc9357SAndroid Build Coastguard Worker // we can remove super path prefix here, if we don't need that prefix
337*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LONG_PATH
338*f6dc9357SAndroid Build Coastguard Worker // we remove super prefix, if we can work without that prefix
339*f6dc9357SAndroid Build Coastguard Worker NFile::NName::If_IsSuperPath_RemoveSuperPrefix(path);
340*f6dc9357SAndroid Build Coastguard Worker #endif
341*f6dc9357SAndroid Build Coastguard Worker names.AddInReserved(path);
342*f6dc9357SAndroid Build Coastguard Worker CoTaskMemFree(strret.pOleStr);
343*f6dc9357SAndroid Build Coastguard Worker }
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker ODS_(Print_Number(cida->cidl, "CFSTR_SHELLIDLIST END"))
346*f6dc9357SAndroid Build Coastguard Worker return S_OK;
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker
DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject * dataObject,UStringVector & paths)350*f6dc9357SAndroid Build Coastguard Worker HRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &paths)
351*f6dc9357SAndroid Build Coastguard Worker {
352*f6dc9357SAndroid Build Coastguard Worker ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names START")
353*f6dc9357SAndroid Build Coastguard Worker HRESULT hres = NShell::DataObject_GetData_HDROP_Names(dataObject, paths);
354*f6dc9357SAndroid Build Coastguard Worker // if (hres == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
355*f6dc9357SAndroid Build Coastguard Worker if (hres != S_OK)
356*f6dc9357SAndroid Build Coastguard Worker {
357*f6dc9357SAndroid Build Coastguard Worker ODS("-- DataObject_GetData_IDLIST START")
358*f6dc9357SAndroid Build Coastguard Worker // for (int y = 0; y < 10000; y++) // for debug
359*f6dc9357SAndroid Build Coastguard Worker hres = NShell::DataObject_GetData_IDLIST(dataObject, paths);
360*f6dc9357SAndroid Build Coastguard Worker }
361*f6dc9357SAndroid Build Coastguard Worker ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names END")
362*f6dc9357SAndroid Build Coastguard Worker return hres;
363*f6dc9357SAndroid Build Coastguard Worker }
364*f6dc9357SAndroid Build Coastguard Worker
365*f6dc9357SAndroid Build Coastguard Worker
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker // #if (NTDDI_VERSION >= NTDDI_VISTA)
368*f6dc9357SAndroid Build Coastguard Worker typedef struct
369*f6dc9357SAndroid Build Coastguard Worker {
370*f6dc9357SAndroid Build Coastguard Worker UINT cItems; // number of items in rgdwFileAttributes array
371*f6dc9357SAndroid Build Coastguard Worker DWORD dwSumFileAttributes; // all of the attributes ORed together
372*f6dc9357SAndroid Build Coastguard Worker DWORD dwProductFileAttributes; // all of the attributes ANDed together
373*f6dc9357SAndroid Build Coastguard Worker DWORD rgdwFileAttributes[1]; // array
374*f6dc9357SAndroid Build Coastguard Worker } MYWIN_FILE_ATTRIBUTES_ARRAY;
375*f6dc9357SAndroid Build Coastguard Worker
376*f6dc9357SAndroid Build Coastguard Worker #define MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY TEXT("File Attributes Array")
377*f6dc9357SAndroid Build Coastguard Worker
DataObject_GetData_FILE_ATTRS(IDataObject * dataObject,CFileAttribs & attribs)378*f6dc9357SAndroid Build Coastguard Worker HRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs)
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker attribs.Clear();
381*f6dc9357SAndroid Build Coastguard Worker NCOM::CStgMedium medium;
382*f6dc9357SAndroid Build Coastguard Worker RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)
383*f6dc9357SAndroid Build Coastguard Worker RegisterClipboardFormat(MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY), medium))
384*f6dc9357SAndroid Build Coastguard Worker const size_t blockSize = GlobalSize(medium.hGlobal);
385*f6dc9357SAndroid Build Coastguard Worker if (blockSize < sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY))
386*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
387*f6dc9357SAndroid Build Coastguard Worker NMemory::CGlobalLock dropLock(medium.hGlobal);
388*f6dc9357SAndroid Build Coastguard Worker const MYWIN_FILE_ATTRIBUTES_ARRAY *faa = (const MYWIN_FILE_ATTRIBUTES_ARRAY *)dropLock.GetPointer();
389*f6dc9357SAndroid Build Coastguard Worker if (!faa)
390*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
391*f6dc9357SAndroid Build Coastguard Worker const unsigned numFiles = faa->cItems;
392*f6dc9357SAndroid Build Coastguard Worker if (numFiles == 0)
393*f6dc9357SAndroid Build Coastguard Worker {
394*f6dc9357SAndroid Build Coastguard Worker // is it posssible to have empty array here?
395*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker if ((blockSize - (sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY) - sizeof(DWORD)))
398*f6dc9357SAndroid Build Coastguard Worker / sizeof(DWORD) != numFiles)
399*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
400*f6dc9357SAndroid Build Coastguard Worker // attribs.Sum = faa->dwSumFileAttributes;
401*f6dc9357SAndroid Build Coastguard Worker // attribs.Product = faa->dwProductFileAttributes;
402*f6dc9357SAndroid Build Coastguard Worker // attribs.Vals.SetFromArray(faa->rgdwFileAttributes, numFiles);
403*f6dc9357SAndroid Build Coastguard Worker // attribs.IsDirVector.ClearAndSetSize(numFiles);
404*f6dc9357SAndroid Build Coastguard Worker
405*f6dc9357SAndroid Build Coastguard Worker if ((faa->dwSumFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
406*f6dc9357SAndroid Build Coastguard Worker {
407*f6dc9357SAndroid Build Coastguard Worker /* in win10: if selected items are volumes (c:\, d:\ ..) in My Compter,
408*f6dc9357SAndroid Build Coastguard Worker all items have FILE_ATTRIBUTE_DIRECTORY attribute
409*f6dc9357SAndroid Build Coastguard Worker ntfs volume also have FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM
410*f6dc9357SAndroid Build Coastguard Worker udf volume: FILE_ATTRIBUTE_READONLY
411*f6dc9357SAndroid Build Coastguard Worker dvd-rom device: (-1) : all bits are set
412*f6dc9357SAndroid Build Coastguard Worker */
413*f6dc9357SAndroid Build Coastguard Worker const DWORD *attr = faa->rgdwFileAttributes;
414*f6dc9357SAndroid Build Coastguard Worker // DWORD product = (UInt32)0 - 1, sum = 0;
415*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numFiles; i++)
416*f6dc9357SAndroid Build Coastguard Worker {
417*f6dc9357SAndroid Build Coastguard Worker if (attr[i] & FILE_ATTRIBUTE_DIRECTORY)
418*f6dc9357SAndroid Build Coastguard Worker {
419*f6dc9357SAndroid Build Coastguard Worker // attribs.ThereAreDirs = true;
420*f6dc9357SAndroid Build Coastguard Worker attribs.FirstDirIndex = (int)i;
421*f6dc9357SAndroid Build Coastguard Worker break;
422*f6dc9357SAndroid Build Coastguard Worker }
423*f6dc9357SAndroid Build Coastguard Worker // attribs.IsDirVector[i] = (attr[i] & FILE_ATTRIBUTE_DIRECTORY) != 0;
424*f6dc9357SAndroid Build Coastguard Worker // product &= v;
425*f6dc9357SAndroid Build Coastguard Worker // sum |= v;
426*f6dc9357SAndroid Build Coastguard Worker }
427*f6dc9357SAndroid Build Coastguard Worker // ODS_(Print_Number(product, "Product calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
428*f6dc9357SAndroid Build Coastguard Worker // ODS_(Print_Number(sum, "Sum calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
429*f6dc9357SAndroid Build Coastguard Worker }
430*f6dc9357SAndroid Build Coastguard Worker // ODS_(Print_Number(attribs.Product, "Product FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
431*f6dc9357SAndroid Build Coastguard Worker // ODS_(Print_Number(attribs.Sum, "Sum FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
432*f6dc9357SAndroid Build Coastguard Worker ODS_(Print_Number(numFiles, "FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names"))
433*f6dc9357SAndroid Build Coastguard Worker return S_OK;
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker
436*f6dc9357SAndroid Build Coastguard Worker
437*f6dc9357SAndroid Build Coastguard Worker /////////////////////////////
438*f6dc9357SAndroid Build Coastguard Worker // CDrop
439*f6dc9357SAndroid Build Coastguard Worker
440*f6dc9357SAndroid Build Coastguard Worker /*
441*f6dc9357SAndroid Build Coastguard Worker win10:
442*f6dc9357SAndroid Build Coastguard Worker DragQueryFile() implementation code is not effective because
443*f6dc9357SAndroid Build Coastguard Worker there is no pointer inside DROP internal file list, so
444*f6dc9357SAndroid Build Coastguard Worker DragQueryFile(fileIndex) runs all names in range [0, fileIndex].
445*f6dc9357SAndroid Build Coastguard Worker DragQueryFile(,, buf, bufSize)
446*f6dc9357SAndroid Build Coastguard Worker if (buf == NULL) by spec
447*f6dc9357SAndroid Build Coastguard Worker {
448*f6dc9357SAndroid Build Coastguard Worker returns value is the required size
449*f6dc9357SAndroid Build Coastguard Worker in characters, of the buffer, not including the terminating null character
450*f6dc9357SAndroid Build Coastguard Worker tests show that if (bufSize == 0), then it also returns required size.
451*f6dc9357SAndroid Build Coastguard Worker }
452*f6dc9357SAndroid Build Coastguard Worker if (bufSize != NULL)
453*f6dc9357SAndroid Build Coastguard Worker {
454*f6dc9357SAndroid Build Coastguard Worker returns: the count of the characters copied, not including null character.
455*f6dc9357SAndroid Build Coastguard Worker win10: null character is also copied at position buf[ret_count];
456*f6dc9357SAndroid Build Coastguard Worker }
457*f6dc9357SAndroid Build Coastguard Worker */
458*f6dc9357SAndroid Build Coastguard Worker
459*f6dc9357SAndroid Build Coastguard Worker /*
460*f6dc9357SAndroid Build Coastguard Worker void CDrop::Attach(HDROP object)
461*f6dc9357SAndroid Build Coastguard Worker {
462*f6dc9357SAndroid Build Coastguard Worker Free();
463*f6dc9357SAndroid Build Coastguard Worker m_Object = object;
464*f6dc9357SAndroid Build Coastguard Worker m_Assigned = true;
465*f6dc9357SAndroid Build Coastguard Worker }
466*f6dc9357SAndroid Build Coastguard Worker
467*f6dc9357SAndroid Build Coastguard Worker void CDrop::Free()
468*f6dc9357SAndroid Build Coastguard Worker {
469*f6dc9357SAndroid Build Coastguard Worker if (m_MustBeFinished && m_Assigned)
470*f6dc9357SAndroid Build Coastguard Worker Finish();
471*f6dc9357SAndroid Build Coastguard Worker m_Assigned = false;
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker
474*f6dc9357SAndroid Build Coastguard Worker UINT CDrop::QueryCountOfFiles()
475*f6dc9357SAndroid Build Coastguard Worker {
476*f6dc9357SAndroid Build Coastguard Worker return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
477*f6dc9357SAndroid Build Coastguard Worker }
478*f6dc9357SAndroid Build Coastguard Worker
479*f6dc9357SAndroid Build Coastguard Worker void CDrop::QueryFileName(UINT fileIndex, UString &fileName)
480*f6dc9357SAndroid Build Coastguard Worker {
481*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
482*f6dc9357SAndroid Build Coastguard Worker if (!g_IsNT)
483*f6dc9357SAndroid Build Coastguard Worker {
484*f6dc9357SAndroid Build Coastguard Worker AString fileNameA;
485*f6dc9357SAndroid Build Coastguard Worker const UINT len = QueryFile(fileIndex, (LPTSTR)NULL, 0);
486*f6dc9357SAndroid Build Coastguard Worker const UINT numCopied = QueryFile(fileIndex, fileNameA.GetBuf(len + 2), len + 2);
487*f6dc9357SAndroid Build Coastguard Worker fileNameA.ReleaseBuf_CalcLen(len);
488*f6dc9357SAndroid Build Coastguard Worker if (numCopied != len)
489*f6dc9357SAndroid Build Coastguard Worker throw 20221223;
490*f6dc9357SAndroid Build Coastguard Worker fileName = GetUnicodeString(fileNameA);
491*f6dc9357SAndroid Build Coastguard Worker }
492*f6dc9357SAndroid Build Coastguard Worker else
493*f6dc9357SAndroid Build Coastguard Worker #endif
494*f6dc9357SAndroid Build Coastguard Worker {
495*f6dc9357SAndroid Build Coastguard Worker // kReserve must be >= 3 for additional buffer size
496*f6dc9357SAndroid Build Coastguard Worker // safety and for optimal performance
497*f6dc9357SAndroid Build Coastguard Worker const unsigned kReserve = 3;
498*f6dc9357SAndroid Build Coastguard Worker {
499*f6dc9357SAndroid Build Coastguard Worker unsigned len = 0;
500*f6dc9357SAndroid Build Coastguard Worker wchar_t *buf = fileName.GetBuf_GetMaxAvail(len);
501*f6dc9357SAndroid Build Coastguard Worker if (len >= kReserve)
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker const UINT numCopied = QueryFile(fileIndex, buf, len);
504*f6dc9357SAndroid Build Coastguard Worker if (numCopied < len - 1)
505*f6dc9357SAndroid Build Coastguard Worker {
506*f6dc9357SAndroid Build Coastguard Worker // (numCopied < len - 1) case means that it have copied full string.
507*f6dc9357SAndroid Build Coastguard Worker fileName.ReleaseBuf_CalcLen(numCopied);
508*f6dc9357SAndroid Build Coastguard Worker return;
509*f6dc9357SAndroid Build Coastguard Worker }
510*f6dc9357SAndroid Build Coastguard Worker }
511*f6dc9357SAndroid Build Coastguard Worker }
512*f6dc9357SAndroid Build Coastguard Worker const UINT len = QueryFile(fileIndex, (LPWSTR)NULL, 0);
513*f6dc9357SAndroid Build Coastguard Worker const UINT numCopied = QueryFile(fileIndex,
514*f6dc9357SAndroid Build Coastguard Worker fileName.GetBuf(len + kReserve), len + kReserve);
515*f6dc9357SAndroid Build Coastguard Worker fileName.ReleaseBuf_CalcLen(len);
516*f6dc9357SAndroid Build Coastguard Worker if (numCopied != len)
517*f6dc9357SAndroid Build Coastguard Worker throw 20221223;
518*f6dc9357SAndroid Build Coastguard Worker }
519*f6dc9357SAndroid Build Coastguard Worker }
520*f6dc9357SAndroid Build Coastguard Worker
521*f6dc9357SAndroid Build Coastguard Worker
522*f6dc9357SAndroid Build Coastguard Worker void CDrop::QueryFileNames(UStringVector &fileNames)
523*f6dc9357SAndroid Build Coastguard Worker {
524*f6dc9357SAndroid Build Coastguard Worker UINT numFiles = QueryCountOfFiles();
525*f6dc9357SAndroid Build Coastguard Worker
526*f6dc9357SAndroid Build Coastguard Worker Print_Number(numFiles, "\n====== CDrop::QueryFileNames START ===== \n");
527*f6dc9357SAndroid Build Coastguard Worker
528*f6dc9357SAndroid Build Coastguard Worker fileNames.ClearAndReserve(numFiles);
529*f6dc9357SAndroid Build Coastguard Worker UString s;
530*f6dc9357SAndroid Build Coastguard Worker for (UINT i = 0; i < numFiles; i++)
531*f6dc9357SAndroid Build Coastguard Worker {
532*f6dc9357SAndroid Build Coastguard Worker QueryFileName(i, s);
533*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
534*f6dc9357SAndroid Build Coastguard Worker fileNames.AddInReserved(s);
535*f6dc9357SAndroid Build Coastguard Worker }
536*f6dc9357SAndroid Build Coastguard Worker Print_Number(numFiles, "\n====== CDrop::QueryFileNames END ===== \n");
537*f6dc9357SAndroid Build Coastguard Worker }
538*f6dc9357SAndroid Build Coastguard Worker */
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker
541*f6dc9357SAndroid Build Coastguard Worker // #if (NTDDI_VERSION >= NTDDI_VISTA)
542*f6dc9357SAndroid Build Coastguard Worker // SHGetPathFromIDListEx returns a win32 file system path for the item in the name space.
543*f6dc9357SAndroid Build Coastguard Worker typedef int Z7_WIN_GPFIDL_FLAGS;
544*f6dc9357SAndroid Build Coastguard Worker
545*f6dc9357SAndroid Build Coastguard Worker extern "C" {
546*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
547*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); // nt4
548*f6dc9357SAndroid Build Coastguard Worker #endif
549*f6dc9357SAndroid Build Coastguard Worker
550*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0600 // Vista
551*f6dc9357SAndroid Build Coastguard Worker #define Z7_USE_DYN_SHGetPathFromIDListEx
552*f6dc9357SAndroid Build Coastguard Worker #endif
553*f6dc9357SAndroid Build Coastguard Worker
554*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_SHGetPathFromIDListEx
555*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
556*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); // vista
557*f6dc9357SAndroid Build Coastguard Worker #endif
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker
560*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
561*f6dc9357SAndroid Build Coastguard Worker
GetPathFromIDList(LPCITEMIDLIST itemIDList,AString & path)562*f6dc9357SAndroid Build Coastguard Worker bool GetPathFromIDList(LPCITEMIDLIST itemIDList, AString &path)
563*f6dc9357SAndroid Build Coastguard Worker {
564*f6dc9357SAndroid Build Coastguard Worker path.Empty();
565*f6dc9357SAndroid Build Coastguard Worker const unsigned len = MAX_PATH + 16;
566*f6dc9357SAndroid Build Coastguard Worker const bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
567*f6dc9357SAndroid Build Coastguard Worker path.ReleaseBuf_CalcLen(len);
568*f6dc9357SAndroid Build Coastguard Worker return result;
569*f6dc9357SAndroid Build Coastguard Worker }
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker #endif
572*f6dc9357SAndroid Build Coastguard Worker
GetPathFromIDList(LPCITEMIDLIST itemIDList,UString & path)573*f6dc9357SAndroid Build Coastguard Worker bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
574*f6dc9357SAndroid Build Coastguard Worker {
575*f6dc9357SAndroid Build Coastguard Worker path.Empty();
576*f6dc9357SAndroid Build Coastguard Worker unsigned len = MAX_PATH + 16;
577*f6dc9357SAndroid Build Coastguard Worker
578*f6dc9357SAndroid Build Coastguard Worker #ifdef _UNICODE
579*f6dc9357SAndroid Build Coastguard Worker bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
580*f6dc9357SAndroid Build Coastguard Worker #else
581*f6dc9357SAndroid Build Coastguard Worker const
582*f6dc9357SAndroid Build Coastguard Worker Func_SHGetPathFromIDListW
583*f6dc9357SAndroid Build Coastguard Worker shGetPathFromIDListW = Z7_GET_PROC_ADDRESS(
584*f6dc9357SAndroid Build Coastguard Worker Func_SHGetPathFromIDListW, ::GetModuleHandleW(L"shell32.dll"),
585*f6dc9357SAndroid Build Coastguard Worker "SHGetPathFromIDListW");
586*f6dc9357SAndroid Build Coastguard Worker if (!shGetPathFromIDListW)
587*f6dc9357SAndroid Build Coastguard Worker return false;
588*f6dc9357SAndroid Build Coastguard Worker bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
589*f6dc9357SAndroid Build Coastguard Worker #endif
590*f6dc9357SAndroid Build Coastguard Worker
591*f6dc9357SAndroid Build Coastguard Worker if (!result)
592*f6dc9357SAndroid Build Coastguard Worker {
593*f6dc9357SAndroid Build Coastguard Worker ODS("==== GetPathFromIDList() SHGetPathFromIDList() returned false")
594*f6dc9357SAndroid Build Coastguard Worker /* for long path we need SHGetPathFromIDListEx().
595*f6dc9357SAndroid Build Coastguard Worker win10: SHGetPathFromIDListEx() for long path returns path with
596*f6dc9357SAndroid Build Coastguard Worker with super path prefix "\\\\?\\". */
597*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_SHGetPathFromIDListEx
598*f6dc9357SAndroid Build Coastguard Worker const
599*f6dc9357SAndroid Build Coastguard Worker Func_SHGetPathFromIDListEx
600*f6dc9357SAndroid Build Coastguard Worker func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS(
601*f6dc9357SAndroid Build Coastguard Worker Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"),
602*f6dc9357SAndroid Build Coastguard Worker "SHGetPathFromIDListEx");
603*f6dc9357SAndroid Build Coastguard Worker if (func_SHGetPathFromIDListEx)
604*f6dc9357SAndroid Build Coastguard Worker #endif
605*f6dc9357SAndroid Build Coastguard Worker {
606*f6dc9357SAndroid Build Coastguard Worker ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)")
607*f6dc9357SAndroid Build Coastguard Worker do
608*f6dc9357SAndroid Build Coastguard Worker {
609*f6dc9357SAndroid Build Coastguard Worker len *= 4;
610*f6dc9357SAndroid Build Coastguard Worker result = BOOLToBool(
611*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_SHGetPathFromIDListEx
612*f6dc9357SAndroid Build Coastguard Worker func_SHGetPathFromIDListEx
613*f6dc9357SAndroid Build Coastguard Worker #else
614*f6dc9357SAndroid Build Coastguard Worker SHGetPathFromIDListEx
615*f6dc9357SAndroid Build Coastguard Worker #endif
616*f6dc9357SAndroid Build Coastguard Worker (itemIDList, path.GetBuf(len), len, 0));
617*f6dc9357SAndroid Build Coastguard Worker if (result)
618*f6dc9357SAndroid Build Coastguard Worker break;
619*f6dc9357SAndroid Build Coastguard Worker }
620*f6dc9357SAndroid Build Coastguard Worker while (len <= (1 << 16));
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker }
623*f6dc9357SAndroid Build Coastguard Worker
624*f6dc9357SAndroid Build Coastguard Worker path.ReleaseBuf_CalcLen(len);
625*f6dc9357SAndroid Build Coastguard Worker return result;
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker
628*f6dc9357SAndroid Build Coastguard Worker #endif
629*f6dc9357SAndroid Build Coastguard Worker
630*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
631*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(LPBROWSEINFO,CSysString)632*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(LPBROWSEINFO, CSysString)
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker return false;
635*f6dc9357SAndroid Build Coastguard Worker }
636*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND,LPCTSTR,UINT,LPCTSTR,CSysString &)637*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
638*f6dc9357SAndroid Build Coastguard Worker {
639*f6dc9357SAndroid Build Coastguard Worker return false;
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND,LPCTSTR,LPCTSTR,CSysString &)642*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
643*f6dc9357SAndroid Build Coastguard Worker LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
644*f6dc9357SAndroid Build Coastguard Worker {
645*f6dc9357SAndroid Build Coastguard Worker /*
646*f6dc9357SAndroid Build Coastguard Worker // SHBrowseForFolder doesn't work before CE 6.0 ?
647*f6dc9357SAndroid Build Coastguard Worker if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
648*f6dc9357SAndroid Build Coastguard Worker MessageBoxW(0, L"no", L"", 0);
649*f6dc9357SAndroid Build Coastguard Worker else
650*f6dc9357SAndroid Build Coastguard Worker MessageBoxW(0, L"yes", L"", 0);
651*f6dc9357SAndroid Build Coastguard Worker */
652*f6dc9357SAndroid Build Coastguard Worker /*
653*f6dc9357SAndroid Build Coastguard Worker UString s = "all files";
654*f6dc9357SAndroid Build Coastguard Worker s += " (*.*)";
655*f6dc9357SAndroid Build Coastguard Worker return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
656*f6dc9357SAndroid Build Coastguard Worker */
657*f6dc9357SAndroid Build Coastguard Worker return false;
658*f6dc9357SAndroid Build Coastguard Worker }
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker #else
661*f6dc9357SAndroid Build Coastguard Worker
662*f6dc9357SAndroid Build Coastguard Worker /* win10: SHBrowseForFolder() doesn't support long paths,
663*f6dc9357SAndroid Build Coastguard Worker even if long path suppport is enabled in registry and in manifest.
664*f6dc9357SAndroid Build Coastguard Worker and SHBrowseForFolder() doesn't support super path prefix "\\\\?\\". */
665*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(LPBROWSEINFO browseInfo,CSysString & resultPath)666*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker resultPath.Empty();
669*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CComInitializer comInitializer;
670*f6dc9357SAndroid Build Coastguard Worker LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
671*f6dc9357SAndroid Build Coastguard Worker if (!itemIDList)
672*f6dc9357SAndroid Build Coastguard Worker return false;
673*f6dc9357SAndroid Build Coastguard Worker CItemIDList itemIDListHolder;
674*f6dc9357SAndroid Build Coastguard Worker itemIDListHolder.Attach(itemIDList);
675*f6dc9357SAndroid Build Coastguard Worker return GetPathFromIDList(itemIDList, resultPath);
676*f6dc9357SAndroid Build Coastguard Worker }
677*f6dc9357SAndroid Build Coastguard Worker
678*f6dc9357SAndroid Build Coastguard Worker
BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)679*f6dc9357SAndroid Build Coastguard Worker static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
680*f6dc9357SAndroid Build Coastguard Worker {
681*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
682*f6dc9357SAndroid Build Coastguard Worker switch (uMsg)
683*f6dc9357SAndroid Build Coastguard Worker {
684*f6dc9357SAndroid Build Coastguard Worker case BFFM_INITIALIZED:
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
687*f6dc9357SAndroid Build Coastguard Worker break;
688*f6dc9357SAndroid Build Coastguard Worker }
689*f6dc9357SAndroid Build Coastguard Worker /*
690*f6dc9357SAndroid Build Coastguard Worker case BFFM_SELCHANGED:
691*f6dc9357SAndroid Build Coastguard Worker {
692*f6dc9357SAndroid Build Coastguard Worker TCHAR dir[MAX_PATH];
693*f6dc9357SAndroid Build Coastguard Worker if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
694*f6dc9357SAndroid Build Coastguard Worker SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
695*f6dc9357SAndroid Build Coastguard Worker else
696*f6dc9357SAndroid Build Coastguard Worker SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
697*f6dc9357SAndroid Build Coastguard Worker break;
698*f6dc9357SAndroid Build Coastguard Worker }
699*f6dc9357SAndroid Build Coastguard Worker */
700*f6dc9357SAndroid Build Coastguard Worker default:
701*f6dc9357SAndroid Build Coastguard Worker break;
702*f6dc9357SAndroid Build Coastguard Worker }
703*f6dc9357SAndroid Build Coastguard Worker #endif
704*f6dc9357SAndroid Build Coastguard Worker return 0;
705*f6dc9357SAndroid Build Coastguard Worker }
706*f6dc9357SAndroid Build Coastguard Worker
707*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND owner,LPCTSTR title,UINT ulFlags,LPCTSTR initialFolder,CSysString & resultPath)708*f6dc9357SAndroid Build Coastguard Worker static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
709*f6dc9357SAndroid Build Coastguard Worker LPCTSTR initialFolder, CSysString &resultPath)
710*f6dc9357SAndroid Build Coastguard Worker {
711*f6dc9357SAndroid Build Coastguard Worker CSysString displayName;
712*f6dc9357SAndroid Build Coastguard Worker BROWSEINFO browseInfo;
713*f6dc9357SAndroid Build Coastguard Worker browseInfo.hwndOwner = owner;
714*f6dc9357SAndroid Build Coastguard Worker browseInfo.pidlRoot = NULL;
715*f6dc9357SAndroid Build Coastguard Worker
716*f6dc9357SAndroid Build Coastguard Worker // there are Unicode/Astring problems in some WinCE SDK ?
717*f6dc9357SAndroid Build Coastguard Worker /*
718*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
719*f6dc9357SAndroid Build Coastguard Worker browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);
720*f6dc9357SAndroid Build Coastguard Worker browseInfo.lpszTitle = (LPCSTR)title;
721*f6dc9357SAndroid Build Coastguard Worker #else
722*f6dc9357SAndroid Build Coastguard Worker */
723*f6dc9357SAndroid Build Coastguard Worker browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
724*f6dc9357SAndroid Build Coastguard Worker browseInfo.lpszTitle = title;
725*f6dc9357SAndroid Build Coastguard Worker // #endif
726*f6dc9357SAndroid Build Coastguard Worker browseInfo.ulFlags = ulFlags;
727*f6dc9357SAndroid Build Coastguard Worker browseInfo.lpfn = initialFolder ? BrowseCallbackProc : NULL;
728*f6dc9357SAndroid Build Coastguard Worker browseInfo.lParam = (LPARAM)initialFolder;
729*f6dc9357SAndroid Build Coastguard Worker return BrowseForFolder(&browseInfo, resultPath);
730*f6dc9357SAndroid Build Coastguard Worker }
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_OLD_WIN_SDK
733*f6dc9357SAndroid Build Coastguard Worker // ShlObj.h:
734*f6dc9357SAndroid Build Coastguard Worker #ifndef BIF_NEWDIALOGSTYLE
735*f6dc9357SAndroid Build Coastguard Worker #define BIF_NEWDIALOGSTYLE 0x0040
736*f6dc9357SAndroid Build Coastguard Worker #endif
737*f6dc9357SAndroid Build Coastguard Worker #endif
738*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND owner,LPCTSTR title,LPCTSTR initialFolder,CSysString & resultPath)739*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(HWND owner, LPCTSTR title,
740*f6dc9357SAndroid Build Coastguard Worker LPCTSTR initialFolder, CSysString &resultPath)
741*f6dc9357SAndroid Build Coastguard Worker {
742*f6dc9357SAndroid Build Coastguard Worker return BrowseForFolder(owner, title,
743*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
744*f6dc9357SAndroid Build Coastguard Worker BIF_NEWDIALOGSTYLE |
745*f6dc9357SAndroid Build Coastguard Worker #endif
746*f6dc9357SAndroid Build Coastguard Worker BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
747*f6dc9357SAndroid Build Coastguard Worker // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
748*f6dc9357SAndroid Build Coastguard Worker }
749*f6dc9357SAndroid Build Coastguard Worker
750*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker extern "C" {
753*f6dc9357SAndroid Build Coastguard Worker typedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi);
754*f6dc9357SAndroid Build Coastguard Worker }
755*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(LPBROWSEINFOW browseInfo,UString & resultPath)756*f6dc9357SAndroid Build Coastguard Worker static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
757*f6dc9357SAndroid Build Coastguard Worker {
758*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CComInitializer comInitializer;
759*f6dc9357SAndroid Build Coastguard Worker const
760*f6dc9357SAndroid Build Coastguard Worker Func_SHBrowseForFolderW
761*f6dc9357SAndroid Build Coastguard Worker f_SHBrowseForFolderW = Z7_GET_PROC_ADDRESS(
762*f6dc9357SAndroid Build Coastguard Worker Func_SHBrowseForFolderW, ::GetModuleHandleW(L"shell32.dll"),
763*f6dc9357SAndroid Build Coastguard Worker "SHBrowseForFolderW");
764*f6dc9357SAndroid Build Coastguard Worker if (!f_SHBrowseForFolderW)
765*f6dc9357SAndroid Build Coastguard Worker return false;
766*f6dc9357SAndroid Build Coastguard Worker LPITEMIDLIST itemIDList = f_SHBrowseForFolderW(browseInfo);
767*f6dc9357SAndroid Build Coastguard Worker if (!itemIDList)
768*f6dc9357SAndroid Build Coastguard Worker return false;
769*f6dc9357SAndroid Build Coastguard Worker CItemIDList itemIDListHolder;
770*f6dc9357SAndroid Build Coastguard Worker itemIDListHolder.Attach(itemIDList);
771*f6dc9357SAndroid Build Coastguard Worker return GetPathFromIDList(itemIDList, resultPath);
772*f6dc9357SAndroid Build Coastguard Worker }
773*f6dc9357SAndroid Build Coastguard Worker
774*f6dc9357SAndroid Build Coastguard Worker static
BrowseCallbackProc2(HWND hwnd,UINT uMsg,LPARAM,LPARAM data)775*f6dc9357SAndroid Build Coastguard Worker int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
776*f6dc9357SAndroid Build Coastguard Worker {
777*f6dc9357SAndroid Build Coastguard Worker switch (uMsg)
778*f6dc9357SAndroid Build Coastguard Worker {
779*f6dc9357SAndroid Build Coastguard Worker case BFFM_INITIALIZED:
780*f6dc9357SAndroid Build Coastguard Worker {
781*f6dc9357SAndroid Build Coastguard Worker SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
782*f6dc9357SAndroid Build Coastguard Worker break;
783*f6dc9357SAndroid Build Coastguard Worker }
784*f6dc9357SAndroid Build Coastguard Worker /*
785*f6dc9357SAndroid Build Coastguard Worker case BFFM_SELCHANGED:
786*f6dc9357SAndroid Build Coastguard Worker {
787*f6dc9357SAndroid Build Coastguard Worker wchar_t dir[MAX_PATH * 2];
788*f6dc9357SAndroid Build Coastguard Worker
789*f6dc9357SAndroid Build Coastguard Worker if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
790*f6dc9357SAndroid Build Coastguard Worker SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
791*f6dc9357SAndroid Build Coastguard Worker else
792*f6dc9357SAndroid Build Coastguard Worker SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
793*f6dc9357SAndroid Build Coastguard Worker break;
794*f6dc9357SAndroid Build Coastguard Worker }
795*f6dc9357SAndroid Build Coastguard Worker */
796*f6dc9357SAndroid Build Coastguard Worker default:
797*f6dc9357SAndroid Build Coastguard Worker break;
798*f6dc9357SAndroid Build Coastguard Worker }
799*f6dc9357SAndroid Build Coastguard Worker return 0;
800*f6dc9357SAndroid Build Coastguard Worker }
801*f6dc9357SAndroid Build Coastguard Worker
802*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND owner,LPCWSTR title,UINT ulFlags,LPCWSTR initialFolder,UString & resultPath)803*f6dc9357SAndroid Build Coastguard Worker static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
804*f6dc9357SAndroid Build Coastguard Worker LPCWSTR initialFolder, UString &resultPath)
805*f6dc9357SAndroid Build Coastguard Worker {
806*f6dc9357SAndroid Build Coastguard Worker UString displayName;
807*f6dc9357SAndroid Build Coastguard Worker BROWSEINFOW browseInfo;
808*f6dc9357SAndroid Build Coastguard Worker browseInfo.hwndOwner = owner;
809*f6dc9357SAndroid Build Coastguard Worker browseInfo.pidlRoot = NULL;
810*f6dc9357SAndroid Build Coastguard Worker browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
811*f6dc9357SAndroid Build Coastguard Worker browseInfo.lpszTitle = title;
812*f6dc9357SAndroid Build Coastguard Worker browseInfo.ulFlags = ulFlags;
813*f6dc9357SAndroid Build Coastguard Worker browseInfo.lpfn = initialFolder ? BrowseCallbackProc2 : NULL;
814*f6dc9357SAndroid Build Coastguard Worker browseInfo.lParam = (LPARAM)initialFolder;
815*f6dc9357SAndroid Build Coastguard Worker return BrowseForFolder(&browseInfo, resultPath);
816*f6dc9357SAndroid Build Coastguard Worker }
817*f6dc9357SAndroid Build Coastguard Worker
BrowseForFolder(HWND owner,LPCWSTR title,LPCWSTR initialFolder,UString & resultPath)818*f6dc9357SAndroid Build Coastguard Worker bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
819*f6dc9357SAndroid Build Coastguard Worker {
820*f6dc9357SAndroid Build Coastguard Worker if (g_IsNT)
821*f6dc9357SAndroid Build Coastguard Worker return BrowseForFolder(owner, title,
822*f6dc9357SAndroid Build Coastguard Worker BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
823*f6dc9357SAndroid Build Coastguard Worker // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
824*f6dc9357SAndroid Build Coastguard Worker , initialFolder, resultPath);
825*f6dc9357SAndroid Build Coastguard Worker // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
826*f6dc9357SAndroid Build Coastguard Worker CSysString s;
827*f6dc9357SAndroid Build Coastguard Worker bool res = BrowseForFolder(owner, GetSystemString(title),
828*f6dc9357SAndroid Build Coastguard Worker BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
829*f6dc9357SAndroid Build Coastguard Worker // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
830*f6dc9357SAndroid Build Coastguard Worker , GetSystemString(initialFolder), s);
831*f6dc9357SAndroid Build Coastguard Worker resultPath = GetUnicodeString(s);
832*f6dc9357SAndroid Build Coastguard Worker return res;
833*f6dc9357SAndroid Build Coastguard Worker }
834*f6dc9357SAndroid Build Coastguard Worker
835*f6dc9357SAndroid Build Coastguard Worker #endif
836*f6dc9357SAndroid Build Coastguard Worker
837*f6dc9357SAndroid Build Coastguard Worker #endif
838*f6dc9357SAndroid Build Coastguard Worker
839*f6dc9357SAndroid Build Coastguard Worker }}
840