xref: /aosp_15_r20/external/lzma/CPP/Windows/Shell.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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