xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/PanelMenu.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
4*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/COM.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/Clipboard.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/Menu.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantConv.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../PropID.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../Common/PropIDUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../Explorer/ContextMenu.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #include "App.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "FormatUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "LangUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "ListViewDialog.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "MyLoadMenu.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "PropertyName.h"
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker #include "PropertyNameRes.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "resource.h"
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_PANEL_MENU
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker extern
31*f6dc9357SAndroid Build Coastguard Worker LONG g_DllRefCount;
32*f6dc9357SAndroid Build Coastguard Worker LONG g_DllRefCount = 0;
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start;
35*f6dc9357SAndroid Build Coastguard Worker static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 400;
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_PANEL_MENU
Print_Ptr(void * p,const char * s)39*f6dc9357SAndroid Build Coastguard Worker static void Print_Ptr(void *p, const char *s)
40*f6dc9357SAndroid Build Coastguard Worker {
41*f6dc9357SAndroid Build Coastguard Worker   char temp[32];
42*f6dc9357SAndroid Build Coastguard Worker   ConvertUInt64ToHex((UInt64)(void *)p, temp);
43*f6dc9357SAndroid Build Coastguard Worker   AString m;
44*f6dc9357SAndroid Build Coastguard Worker   m += temp;
45*f6dc9357SAndroid Build Coastguard Worker   m.Add_Space();
46*f6dc9357SAndroid Build Coastguard Worker   m += s;
47*f6dc9357SAndroid Build Coastguard Worker   OutputDebugStringA(m);
48*f6dc9357SAndroid Build Coastguard Worker }
49*f6dc9357SAndroid Build Coastguard Worker #define ODS(sz) { Print_Ptr(this, sz); }
50*f6dc9357SAndroid Build Coastguard Worker #define ODS_U(s) { OutputDebugStringW(s); }
51*f6dc9357SAndroid Build Coastguard Worker #else
52*f6dc9357SAndroid Build Coastguard Worker #define ODS(sz)
53*f6dc9357SAndroid Build Coastguard Worker #define ODS_U(s)
54*f6dc9357SAndroid Build Coastguard Worker #endif
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker 
InvokeSystemCommand(const char * command)57*f6dc9357SAndroid Build Coastguard Worker void CPanel::InvokeSystemCommand(const char *command)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker   NCOM::CComInitializer comInitializer;
60*f6dc9357SAndroid Build Coastguard Worker   if (!IsFsOrPureDrivesFolder())
61*f6dc9357SAndroid Build Coastguard Worker     return;
62*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> operatedIndices;
63*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Operated(operatedIndices);
64*f6dc9357SAndroid Build Coastguard Worker   if (operatedIndices.IsEmpty())
65*f6dc9357SAndroid Build Coastguard Worker     return;
66*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IContextMenu> contextMenu;
67*f6dc9357SAndroid Build Coastguard Worker   if (CreateShellContextMenu(operatedIndices, contextMenu) != S_OK)
68*f6dc9357SAndroid Build Coastguard Worker     return;
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker   CMINVOKECOMMANDINFO ci;
71*f6dc9357SAndroid Build Coastguard Worker   ZeroMemory(&ci, sizeof(ci));
72*f6dc9357SAndroid Build Coastguard Worker   ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
73*f6dc9357SAndroid Build Coastguard Worker   ci.hwnd = GetParent();
74*f6dc9357SAndroid Build Coastguard Worker   ci.lpVerb = command;
75*f6dc9357SAndroid Build Coastguard Worker   contextMenu->InvokeCommand(&ci);
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker static const char * const kSeparator = "------------------------";
79*f6dc9357SAndroid Build Coastguard Worker static const char * const kSeparatorSmall = "----------------";
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker extern UString ConvertSizeToString(UInt64 value) throw();
82*f6dc9357SAndroid Build Coastguard Worker bool IsSizeProp(UINT propID) throw();
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker UString GetOpenArcErrorMessage(UInt32 errorFlags);
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker 
AddListAscii(CListViewDialog & dialog,const char * s)87*f6dc9357SAndroid Build Coastguard Worker static void AddListAscii(CListViewDialog &dialog, const char *s)
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker   dialog.Strings.Add((UString)s);
90*f6dc9357SAndroid Build Coastguard Worker   dialog.Values.AddNew();
91*f6dc9357SAndroid Build Coastguard Worker }
92*f6dc9357SAndroid Build Coastguard Worker 
AddSeparator(CListViewDialog & dialog)93*f6dc9357SAndroid Build Coastguard Worker static void AddSeparator(CListViewDialog &dialog)
94*f6dc9357SAndroid Build Coastguard Worker {
95*f6dc9357SAndroid Build Coastguard Worker   AddListAscii(dialog, kSeparator);
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker 
AddSeparatorSmall(CListViewDialog & dialog)98*f6dc9357SAndroid Build Coastguard Worker static void AddSeparatorSmall(CListViewDialog &dialog)
99*f6dc9357SAndroid Build Coastguard Worker {
100*f6dc9357SAndroid Build Coastguard Worker   AddListAscii(dialog, kSeparatorSmall);
101*f6dc9357SAndroid Build Coastguard Worker }
102*f6dc9357SAndroid Build Coastguard Worker 
AddPropertyPair(const UString & name,const UString & val,CListViewDialog & dialog)103*f6dc9357SAndroid Build Coastguard Worker static void AddPropertyPair(const UString &name, const UString &val, CListViewDialog &dialog)
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker   dialog.Strings.Add(name);
106*f6dc9357SAndroid Build Coastguard Worker   dialog.Values.Add(val);
107*f6dc9357SAndroid Build Coastguard Worker }
108*f6dc9357SAndroid Build Coastguard Worker 
109*f6dc9357SAndroid Build Coastguard Worker 
AddPropertyString(PROPID propID,const wchar_t * nameBSTR,const NCOM::CPropVariant & prop,CListViewDialog & dialog)110*f6dc9357SAndroid Build Coastguard Worker static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
111*f6dc9357SAndroid Build Coastguard Worker     const NCOM::CPropVariant &prop, CListViewDialog &dialog)
112*f6dc9357SAndroid Build Coastguard Worker {
113*f6dc9357SAndroid Build Coastguard Worker   if (prop.vt != VT_EMPTY)
114*f6dc9357SAndroid Build Coastguard Worker   {
115*f6dc9357SAndroid Build Coastguard Worker     UString val;
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker     if (propID == kpidErrorFlags ||
118*f6dc9357SAndroid Build Coastguard Worker         propID == kpidWarningFlags)
119*f6dc9357SAndroid Build Coastguard Worker     {
120*f6dc9357SAndroid Build Coastguard Worker       UInt32 flags = GetOpenArcErrorFlags(prop);
121*f6dc9357SAndroid Build Coastguard Worker       if (flags == 0)
122*f6dc9357SAndroid Build Coastguard Worker         return;
123*f6dc9357SAndroid Build Coastguard Worker       if (flags != 0)
124*f6dc9357SAndroid Build Coastguard Worker         val = GetOpenArcErrorMessage(flags);
125*f6dc9357SAndroid Build Coastguard Worker     }
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker     if (val.IsEmpty())
128*f6dc9357SAndroid Build Coastguard Worker     {
129*f6dc9357SAndroid Build Coastguard Worker       if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
130*f6dc9357SAndroid Build Coastguard Worker       {
131*f6dc9357SAndroid Build Coastguard Worker         UInt64 v = 0;
132*f6dc9357SAndroid Build Coastguard Worker         ConvertPropVariantToUInt64(prop, v);
133*f6dc9357SAndroid Build Coastguard Worker         val = ConvertSizeToString(v);
134*f6dc9357SAndroid Build Coastguard Worker       }
135*f6dc9357SAndroid Build Coastguard Worker       else
136*f6dc9357SAndroid Build Coastguard Worker         ConvertPropertyToString2(val, prop, propID, 9); // we send 9 - is ns precision
137*f6dc9357SAndroid Build Coastguard Worker     }
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker     if (!val.IsEmpty())
140*f6dc9357SAndroid Build Coastguard Worker     {
141*f6dc9357SAndroid Build Coastguard Worker       if (propID == kpidErrorType)
142*f6dc9357SAndroid Build Coastguard Worker       {
143*f6dc9357SAndroid Build Coastguard Worker         AddPropertyPair(L"Open WARNING:", L"Cannot open the file as expected archive type", dialog);
144*f6dc9357SAndroid Build Coastguard Worker       }
145*f6dc9357SAndroid Build Coastguard Worker       AddPropertyPair(GetNameOfProperty(propID, nameBSTR), val, dialog);
146*f6dc9357SAndroid Build Coastguard Worker     }
147*f6dc9357SAndroid Build Coastguard Worker   }
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker 
150*f6dc9357SAndroid Build Coastguard Worker 
AddPropertyString(PROPID propID,UInt64 val,CListViewDialog & dialog)151*f6dc9357SAndroid Build Coastguard Worker static void AddPropertyString(PROPID propID, UInt64 val, CListViewDialog &dialog)
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop = val;
154*f6dc9357SAndroid Build Coastguard Worker   AddPropertyString(propID, NULL, prop, dialog);
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker 
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker static const Byte kSpecProps[] =
159*f6dc9357SAndroid Build Coastguard Worker {
160*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
161*f6dc9357SAndroid Build Coastguard Worker   kpidType,
162*f6dc9357SAndroid Build Coastguard Worker   kpidErrorType,
163*f6dc9357SAndroid Build Coastguard Worker   kpidError,
164*f6dc9357SAndroid Build Coastguard Worker   kpidErrorFlags,
165*f6dc9357SAndroid Build Coastguard Worker   kpidWarning,
166*f6dc9357SAndroid Build Coastguard Worker   kpidWarningFlags,
167*f6dc9357SAndroid Build Coastguard Worker   kpidOffset,
168*f6dc9357SAndroid Build Coastguard Worker   kpidPhySize,
169*f6dc9357SAndroid Build Coastguard Worker   kpidTailSize
170*f6dc9357SAndroid Build Coastguard Worker };
171*f6dc9357SAndroid Build Coastguard Worker 
Properties()172*f6dc9357SAndroid Build Coastguard Worker void CPanel::Properties()
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IGetFolderArcProps> getFolderArcProps;
175*f6dc9357SAndroid Build Coastguard Worker   _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
176*f6dc9357SAndroid Build Coastguard Worker   if (!getFolderArcProps)
177*f6dc9357SAndroid Build Coastguard Worker   {
178*f6dc9357SAndroid Build Coastguard Worker     InvokeSystemCommand("properties");
179*f6dc9357SAndroid Build Coastguard Worker     return;
180*f6dc9357SAndroid Build Coastguard Worker   }
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker   {
183*f6dc9357SAndroid Build Coastguard Worker     CListViewDialog message;
184*f6dc9357SAndroid Build Coastguard Worker     // message.DeleteIsAllowed = false;
185*f6dc9357SAndroid Build Coastguard Worker     // message.SelectFirst = false;
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<UInt32> operatedIndices;
188*f6dc9357SAndroid Build Coastguard Worker     Get_ItemIndices_Operated(operatedIndices);
189*f6dc9357SAndroid Build Coastguard Worker 
190*f6dc9357SAndroid Build Coastguard Worker     if (operatedIndices.Size() == 1)
191*f6dc9357SAndroid Build Coastguard Worker     {
192*f6dc9357SAndroid Build Coastguard Worker       UInt32 index = operatedIndices[0];
193*f6dc9357SAndroid Build Coastguard Worker       // message += "Item:\n");
194*f6dc9357SAndroid Build Coastguard Worker       UInt32 numProps;
195*f6dc9357SAndroid Build Coastguard Worker       if (_folder->GetNumberOfProperties(&numProps) == S_OK)
196*f6dc9357SAndroid Build Coastguard Worker       {
197*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 i = 0; i < numProps; i++)
198*f6dc9357SAndroid Build Coastguard Worker         {
199*f6dc9357SAndroid Build Coastguard Worker           CMyComBSTR name;
200*f6dc9357SAndroid Build Coastguard Worker           PROPID propID;
201*f6dc9357SAndroid Build Coastguard Worker           VARTYPE varType;
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker           if (_folder->GetPropertyInfo(i, &name, &propID, &varType) != S_OK)
204*f6dc9357SAndroid Build Coastguard Worker             continue;
205*f6dc9357SAndroid Build Coastguard Worker 
206*f6dc9357SAndroid Build Coastguard Worker           NCOM::CPropVariant prop;
207*f6dc9357SAndroid Build Coastguard Worker           if (_folder->GetProperty(index, propID, &prop) != S_OK)
208*f6dc9357SAndroid Build Coastguard Worker             continue;
209*f6dc9357SAndroid Build Coastguard Worker           AddPropertyString(propID, name, prop, message);
210*f6dc9357SAndroid Build Coastguard Worker         }
211*f6dc9357SAndroid Build Coastguard Worker       }
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker 
214*f6dc9357SAndroid Build Coastguard Worker       if (_folderRawProps)
215*f6dc9357SAndroid Build Coastguard Worker       {
216*f6dc9357SAndroid Build Coastguard Worker         _folderRawProps->GetNumRawProps(&numProps);
217*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 i = 0; i < numProps; i++)
218*f6dc9357SAndroid Build Coastguard Worker         {
219*f6dc9357SAndroid Build Coastguard Worker           CMyComBSTR name;
220*f6dc9357SAndroid Build Coastguard Worker           PROPID propID;
221*f6dc9357SAndroid Build Coastguard Worker           if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK)
222*f6dc9357SAndroid Build Coastguard Worker             continue;
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker           const void *data;
225*f6dc9357SAndroid Build Coastguard Worker           UInt32 dataSize;
226*f6dc9357SAndroid Build Coastguard Worker           UInt32 propType;
227*f6dc9357SAndroid Build Coastguard Worker           if (_folderRawProps->GetRawProp(index, propID, &data, &dataSize, &propType) != S_OK)
228*f6dc9357SAndroid Build Coastguard Worker             continue;
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker           if (dataSize != 0)
231*f6dc9357SAndroid Build Coastguard Worker           {
232*f6dc9357SAndroid Build Coastguard Worker             AString s;
233*f6dc9357SAndroid Build Coastguard Worker             if (propID == kpidNtSecure)
234*f6dc9357SAndroid Build Coastguard Worker               ConvertNtSecureToString((const Byte *)data, dataSize, s);
235*f6dc9357SAndroid Build Coastguard Worker             else
236*f6dc9357SAndroid Build Coastguard Worker             {
237*f6dc9357SAndroid Build Coastguard Worker               const unsigned kMaxDataSize = 1 << 8;
238*f6dc9357SAndroid Build Coastguard Worker               if (dataSize > kMaxDataSize)
239*f6dc9357SAndroid Build Coastguard Worker               {
240*f6dc9357SAndroid Build Coastguard Worker                 s += "data:";
241*f6dc9357SAndroid Build Coastguard Worker                 s.Add_UInt32(dataSize);
242*f6dc9357SAndroid Build Coastguard Worker               }
243*f6dc9357SAndroid Build Coastguard Worker               else
244*f6dc9357SAndroid Build Coastguard Worker               {
245*f6dc9357SAndroid Build Coastguard Worker                 char temp[kMaxDataSize * 2 + 2];
246*f6dc9357SAndroid Build Coastguard Worker                 if (dataSize <= 8 && (propID == kpidCRC || propID == kpidChecksum))
247*f6dc9357SAndroid Build Coastguard Worker                   ConvertDataToHex_Upper(temp, (const Byte *)data, dataSize);
248*f6dc9357SAndroid Build Coastguard Worker                 else
249*f6dc9357SAndroid Build Coastguard Worker                   ConvertDataToHex_Lower(temp, (const Byte *)data, dataSize);
250*f6dc9357SAndroid Build Coastguard Worker                 s += temp;
251*f6dc9357SAndroid Build Coastguard Worker               }
252*f6dc9357SAndroid Build Coastguard Worker             }
253*f6dc9357SAndroid Build Coastguard Worker             AddPropertyPair(GetNameOfProperty(propID, name), (UString)s.Ptr(), message);
254*f6dc9357SAndroid Build Coastguard Worker           }
255*f6dc9357SAndroid Build Coastguard Worker         }
256*f6dc9357SAndroid Build Coastguard Worker       }
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker       AddSeparator(message);
259*f6dc9357SAndroid Build Coastguard Worker     }
260*f6dc9357SAndroid Build Coastguard Worker     else if (operatedIndices.Size() >= 1)
261*f6dc9357SAndroid Build Coastguard Worker     {
262*f6dc9357SAndroid Build Coastguard Worker       UInt64 packSize = 0;
263*f6dc9357SAndroid Build Coastguard Worker       UInt64 unpackSize = 0;
264*f6dc9357SAndroid Build Coastguard Worker       UInt64 numFiles = 0;
265*f6dc9357SAndroid Build Coastguard Worker       UInt64 numDirs = 0;
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, operatedIndices)
268*f6dc9357SAndroid Build Coastguard Worker       {
269*f6dc9357SAndroid Build Coastguard Worker         const UInt32 index = operatedIndices[i];
270*f6dc9357SAndroid Build Coastguard Worker         unpackSize += GetItemSize(index);
271*f6dc9357SAndroid Build Coastguard Worker         packSize += GetItem_UInt64Prop(index, kpidPackSize);
272*f6dc9357SAndroid Build Coastguard Worker         if (IsItem_Folder(index))
273*f6dc9357SAndroid Build Coastguard Worker         {
274*f6dc9357SAndroid Build Coastguard Worker           numDirs++;
275*f6dc9357SAndroid Build Coastguard Worker           numDirs += GetItem_UInt64Prop(index, kpidNumSubDirs);
276*f6dc9357SAndroid Build Coastguard Worker           numFiles += GetItem_UInt64Prop(index, kpidNumSubFiles);
277*f6dc9357SAndroid Build Coastguard Worker         }
278*f6dc9357SAndroid Build Coastguard Worker         else
279*f6dc9357SAndroid Build Coastguard Worker           numFiles++;
280*f6dc9357SAndroid Build Coastguard Worker       }
281*f6dc9357SAndroid Build Coastguard Worker       {
282*f6dc9357SAndroid Build Coastguard Worker         wchar_t temp[32];
283*f6dc9357SAndroid Build Coastguard Worker         ConvertUInt32ToString(operatedIndices.Size(), temp);
284*f6dc9357SAndroid Build Coastguard Worker         AddPropertyPair(L"", MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp), message);
285*f6dc9357SAndroid Build Coastguard Worker       }
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker       if (numDirs != 0)
288*f6dc9357SAndroid Build Coastguard Worker         AddPropertyString(kpidNumSubDirs, numDirs, message);
289*f6dc9357SAndroid Build Coastguard Worker       if (numFiles != 0)
290*f6dc9357SAndroid Build Coastguard Worker         AddPropertyString(kpidNumSubFiles, numFiles, message);
291*f6dc9357SAndroid Build Coastguard Worker       AddPropertyString(kpidSize, unpackSize, message);
292*f6dc9357SAndroid Build Coastguard Worker       AddPropertyString(kpidPackSize, packSize, message);
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker       AddSeparator(message);
295*f6dc9357SAndroid Build Coastguard Worker     }
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker 
298*f6dc9357SAndroid Build Coastguard Worker     /*
299*f6dc9357SAndroid Build Coastguard Worker     AddLangString(message, IDS_PROP_FILE_TYPE);
300*f6dc9357SAndroid Build Coastguard Worker     message += kPropValueSeparator;
301*f6dc9357SAndroid Build Coastguard Worker     message += GetFolderTypeID();
302*f6dc9357SAndroid Build Coastguard Worker     message.Add_LF();
303*f6dc9357SAndroid Build Coastguard Worker     */
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker     {
306*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
307*f6dc9357SAndroid Build Coastguard Worker       if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK)
308*f6dc9357SAndroid Build Coastguard Worker       {
309*f6dc9357SAndroid Build Coastguard Worker         AddPropertyString(kpidName, L"Path", prop, message);
310*f6dc9357SAndroid Build Coastguard Worker       }
311*f6dc9357SAndroid Build Coastguard Worker     }
312*f6dc9357SAndroid Build Coastguard Worker 
313*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IFolderProperties> folderProperties;
314*f6dc9357SAndroid Build Coastguard Worker     _folder.QueryInterface(IID_IFolderProperties, &folderProperties);
315*f6dc9357SAndroid Build Coastguard Worker     if (folderProperties)
316*f6dc9357SAndroid Build Coastguard Worker     {
317*f6dc9357SAndroid Build Coastguard Worker       UInt32 numProps;
318*f6dc9357SAndroid Build Coastguard Worker       if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK)
319*f6dc9357SAndroid Build Coastguard Worker       {
320*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 i = 0; i < numProps; i++)
321*f6dc9357SAndroid Build Coastguard Worker         {
322*f6dc9357SAndroid Build Coastguard Worker           CMyComBSTR name;
323*f6dc9357SAndroid Build Coastguard Worker           PROPID propID;
324*f6dc9357SAndroid Build Coastguard Worker           VARTYPE vt;
325*f6dc9357SAndroid Build Coastguard Worker           if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK)
326*f6dc9357SAndroid Build Coastguard Worker             continue;
327*f6dc9357SAndroid Build Coastguard Worker           NCOM::CPropVariant prop;
328*f6dc9357SAndroid Build Coastguard Worker           if (_folder->GetFolderProperty(propID, &prop) != S_OK)
329*f6dc9357SAndroid Build Coastguard Worker             continue;
330*f6dc9357SAndroid Build Coastguard Worker           AddPropertyString(propID, name, prop, message);
331*f6dc9357SAndroid Build Coastguard Worker         }
332*f6dc9357SAndroid Build Coastguard Worker       }
333*f6dc9357SAndroid Build Coastguard Worker     }
334*f6dc9357SAndroid Build Coastguard Worker 
335*f6dc9357SAndroid Build Coastguard Worker     if (getFolderArcProps)
336*f6dc9357SAndroid Build Coastguard Worker     {
337*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<IFolderArcProps> getProps;
338*f6dc9357SAndroid Build Coastguard Worker       getFolderArcProps->GetFolderArcProps(&getProps);
339*f6dc9357SAndroid Build Coastguard Worker       if (getProps)
340*f6dc9357SAndroid Build Coastguard Worker       {
341*f6dc9357SAndroid Build Coastguard Worker         UInt32 numLevels;
342*f6dc9357SAndroid Build Coastguard Worker         if (getProps->GetArcNumLevels(&numLevels) != S_OK)
343*f6dc9357SAndroid Build Coastguard Worker           numLevels = 0;
344*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 level2 = 0; level2 < numLevels; level2++)
345*f6dc9357SAndroid Build Coastguard Worker         {
346*f6dc9357SAndroid Build Coastguard Worker           {
347*f6dc9357SAndroid Build Coastguard Worker             UInt32 level = numLevels - 1 - level2;
348*f6dc9357SAndroid Build Coastguard Worker             UInt32 numProps;
349*f6dc9357SAndroid Build Coastguard Worker             if (getProps->GetArcNumProps(level, &numProps) == S_OK)
350*f6dc9357SAndroid Build Coastguard Worker             {
351*f6dc9357SAndroid Build Coastguard Worker               const int kNumSpecProps = Z7_ARRAY_SIZE(kSpecProps);
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker               AddSeparator(message);
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker               for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++)
356*f6dc9357SAndroid Build Coastguard Worker               {
357*f6dc9357SAndroid Build Coastguard Worker                 CMyComBSTR name;
358*f6dc9357SAndroid Build Coastguard Worker                 PROPID propID;
359*f6dc9357SAndroid Build Coastguard Worker                 VARTYPE vt;
360*f6dc9357SAndroid Build Coastguard Worker                 if (i < 0)
361*f6dc9357SAndroid Build Coastguard Worker                   propID = kSpecProps[i + kNumSpecProps];
362*f6dc9357SAndroid Build Coastguard Worker                 else if (getProps->GetArcPropInfo(level, (UInt32)i, &name, &propID, &vt) != S_OK)
363*f6dc9357SAndroid Build Coastguard Worker                   continue;
364*f6dc9357SAndroid Build Coastguard Worker                 NCOM::CPropVariant prop;
365*f6dc9357SAndroid Build Coastguard Worker                 if (getProps->GetArcProp(level, propID, &prop) != S_OK)
366*f6dc9357SAndroid Build Coastguard Worker                   continue;
367*f6dc9357SAndroid Build Coastguard Worker                 AddPropertyString(propID, name, prop, message);
368*f6dc9357SAndroid Build Coastguard Worker               }
369*f6dc9357SAndroid Build Coastguard Worker             }
370*f6dc9357SAndroid Build Coastguard Worker           }
371*f6dc9357SAndroid Build Coastguard Worker 
372*f6dc9357SAndroid Build Coastguard Worker           if (level2 < numLevels - 1)
373*f6dc9357SAndroid Build Coastguard Worker           {
374*f6dc9357SAndroid Build Coastguard Worker             const UInt32 level = numLevels - 1 - level2;
375*f6dc9357SAndroid Build Coastguard Worker             UInt32 numProps;
376*f6dc9357SAndroid Build Coastguard Worker             if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
377*f6dc9357SAndroid Build Coastguard Worker             {
378*f6dc9357SAndroid Build Coastguard Worker               AddSeparatorSmall(message);
379*f6dc9357SAndroid Build Coastguard Worker               for (UInt32 i = 0; i < numProps; i++)
380*f6dc9357SAndroid Build Coastguard Worker               {
381*f6dc9357SAndroid Build Coastguard Worker                 CMyComBSTR name;
382*f6dc9357SAndroid Build Coastguard Worker                 PROPID propID;
383*f6dc9357SAndroid Build Coastguard Worker                 VARTYPE vt;
384*f6dc9357SAndroid Build Coastguard Worker                 if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK)
385*f6dc9357SAndroid Build Coastguard Worker                   continue;
386*f6dc9357SAndroid Build Coastguard Worker                 NCOM::CPropVariant prop;
387*f6dc9357SAndroid Build Coastguard Worker                 if (getProps->GetArcProp2(level, propID, &prop) != S_OK)
388*f6dc9357SAndroid Build Coastguard Worker                   continue;
389*f6dc9357SAndroid Build Coastguard Worker                 AddPropertyString(propID, name, prop, message);
390*f6dc9357SAndroid Build Coastguard Worker               }
391*f6dc9357SAndroid Build Coastguard Worker             }
392*f6dc9357SAndroid Build Coastguard Worker           }
393*f6dc9357SAndroid Build Coastguard Worker         }
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker         {
396*f6dc9357SAndroid Build Coastguard Worker           // we ERROR message for NonOpen level
397*f6dc9357SAndroid Build Coastguard Worker               bool needSep = true;
398*f6dc9357SAndroid Build Coastguard Worker               const int kNumSpecProps = Z7_ARRAY_SIZE(kSpecProps);
399*f6dc9357SAndroid Build Coastguard Worker               for (Int32 i = -(int)kNumSpecProps; i < 0; i++)
400*f6dc9357SAndroid Build Coastguard Worker               {
401*f6dc9357SAndroid Build Coastguard Worker                 CMyComBSTR name;
402*f6dc9357SAndroid Build Coastguard Worker                 const PROPID propID = kSpecProps[i + kNumSpecProps];
403*f6dc9357SAndroid Build Coastguard Worker                 NCOM::CPropVariant prop;
404*f6dc9357SAndroid Build Coastguard Worker                 if (getProps->GetArcProp(numLevels, propID, &prop) != S_OK)
405*f6dc9357SAndroid Build Coastguard Worker                   continue;
406*f6dc9357SAndroid Build Coastguard Worker                 if (needSep)
407*f6dc9357SAndroid Build Coastguard Worker                 {
408*f6dc9357SAndroid Build Coastguard Worker                   AddSeparator(message);
409*f6dc9357SAndroid Build Coastguard Worker                   AddSeparator(message);
410*f6dc9357SAndroid Build Coastguard Worker                   needSep = false;
411*f6dc9357SAndroid Build Coastguard Worker                 }
412*f6dc9357SAndroid Build Coastguard Worker                 AddPropertyString(propID, name, prop, message);
413*f6dc9357SAndroid Build Coastguard Worker               }
414*f6dc9357SAndroid Build Coastguard Worker         }
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker       }
417*f6dc9357SAndroid Build Coastguard Worker     }
418*f6dc9357SAndroid Build Coastguard Worker 
419*f6dc9357SAndroid Build Coastguard Worker     message.Title = LangString(IDS_PROPERTIES);
420*f6dc9357SAndroid Build Coastguard Worker     message.NumColumns = 2;
421*f6dc9357SAndroid Build Coastguard Worker     message.Create(GetParent());
422*f6dc9357SAndroid Build Coastguard Worker   }
423*f6dc9357SAndroid Build Coastguard Worker }
424*f6dc9357SAndroid Build Coastguard Worker 
425*f6dc9357SAndroid Build Coastguard Worker 
426*f6dc9357SAndroid Build Coastguard Worker 
EditCut()427*f6dc9357SAndroid Build Coastguard Worker void CPanel::EditCut()
428*f6dc9357SAndroid Build Coastguard Worker {
429*f6dc9357SAndroid Build Coastguard Worker   // InvokeSystemCommand("cut");
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker 
EditCopy()432*f6dc9357SAndroid Build Coastguard Worker void CPanel::EditCopy()
433*f6dc9357SAndroid Build Coastguard Worker {
434*f6dc9357SAndroid Build Coastguard Worker   /*
435*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IGetFolderArcProps> getFolderArcProps;
436*f6dc9357SAndroid Build Coastguard Worker   _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
437*f6dc9357SAndroid Build Coastguard Worker   if (!getFolderArcProps)
438*f6dc9357SAndroid Build Coastguard Worker   {
439*f6dc9357SAndroid Build Coastguard Worker     InvokeSystemCommand("copy");
440*f6dc9357SAndroid Build Coastguard Worker     return;
441*f6dc9357SAndroid Build Coastguard Worker   }
442*f6dc9357SAndroid Build Coastguard Worker   */
443*f6dc9357SAndroid Build Coastguard Worker   UString s;
444*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> indices;
445*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Selected(indices);
446*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, indices)
447*f6dc9357SAndroid Build Coastguard Worker   {
448*f6dc9357SAndroid Build Coastguard Worker     if (i != 0)
449*f6dc9357SAndroid Build Coastguard Worker       s += "\xD\n";
450*f6dc9357SAndroid Build Coastguard Worker     s += GetItemName(indices[i]);
451*f6dc9357SAndroid Build Coastguard Worker   }
452*f6dc9357SAndroid Build Coastguard Worker   ClipboardSetText(_mainWindow, s);
453*f6dc9357SAndroid Build Coastguard Worker }
454*f6dc9357SAndroid Build Coastguard Worker 
EditPaste()455*f6dc9357SAndroid Build Coastguard Worker void CPanel::EditPaste()
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker   /*
458*f6dc9357SAndroid Build Coastguard Worker   UStringVector names;
459*f6dc9357SAndroid Build Coastguard Worker   ClipboardGetFileNames(names);
460*f6dc9357SAndroid Build Coastguard Worker   CopyFromNoAsk(names);
461*f6dc9357SAndroid Build Coastguard Worker   UString s;
462*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < names.Size(); i++)
463*f6dc9357SAndroid Build Coastguard Worker   {
464*f6dc9357SAndroid Build Coastguard Worker     s += L' ';
465*f6dc9357SAndroid Build Coastguard Worker     s += names[i];
466*f6dc9357SAndroid Build Coastguard Worker   }
467*f6dc9357SAndroid Build Coastguard Worker 
468*f6dc9357SAndroid Build Coastguard Worker   MessageBoxW(0, s, L"", 0);
469*f6dc9357SAndroid Build Coastguard Worker   */
470*f6dc9357SAndroid Build Coastguard Worker 
471*f6dc9357SAndroid Build Coastguard Worker   // InvokeSystemCommand("paste");
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker 
474*f6dc9357SAndroid Build Coastguard Worker 
475*f6dc9357SAndroid Build Coastguard Worker 
476*f6dc9357SAndroid Build Coastguard Worker struct CFolderPidls
477*f6dc9357SAndroid Build Coastguard Worker {
478*f6dc9357SAndroid Build Coastguard Worker   LPITEMIDLIST parent;
479*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<LPITEMIDLIST> items;
480*f6dc9357SAndroid Build Coastguard Worker 
CFolderPidlsCFolderPidls481*f6dc9357SAndroid Build Coastguard Worker   CFolderPidls(): parent(NULL) {}
~CFolderPidlsCFolderPidls482*f6dc9357SAndroid Build Coastguard Worker   ~CFolderPidls()
483*f6dc9357SAndroid Build Coastguard Worker   {
484*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, items)
485*f6dc9357SAndroid Build Coastguard Worker       CoTaskMemFree(items[i]);
486*f6dc9357SAndroid Build Coastguard Worker     CoTaskMemFree(parent);
487*f6dc9357SAndroid Build Coastguard Worker   }
488*f6dc9357SAndroid Build Coastguard Worker };
489*f6dc9357SAndroid Build Coastguard Worker 
490*f6dc9357SAndroid Build Coastguard Worker 
ShellFolder_ParseDisplayName(IShellFolder * shellFolder,HWND hwnd,const UString & path,LPITEMIDLIST * ppidl)491*f6dc9357SAndroid Build Coastguard Worker static HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder,
492*f6dc9357SAndroid Build Coastguard Worker     HWND hwnd, const UString &path, LPITEMIDLIST *ppidl)
493*f6dc9357SAndroid Build Coastguard Worker {
494*f6dc9357SAndroid Build Coastguard Worker   ULONG eaten = 0;
495*f6dc9357SAndroid Build Coastguard Worker   return shellFolder->ParseDisplayName(hwnd, NULL,
496*f6dc9357SAndroid Build Coastguard Worker       path.Ptr_non_const(), &eaten, ppidl, NULL);
497*f6dc9357SAndroid Build Coastguard Worker }
498*f6dc9357SAndroid Build Coastguard Worker 
499*f6dc9357SAndroid Build Coastguard Worker 
CreateShellContextMenu(const CRecordVector<UInt32> & operatedIndices,CMyComPtr<IContextMenu> & systemContextMenu)500*f6dc9357SAndroid Build Coastguard Worker HRESULT CPanel::CreateShellContextMenu(
501*f6dc9357SAndroid Build Coastguard Worker     const CRecordVector<UInt32> &operatedIndices,
502*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IContextMenu> &systemContextMenu)
503*f6dc9357SAndroid Build Coastguard Worker {
504*f6dc9357SAndroid Build Coastguard Worker   ODS("==== CPanel::CreateShellContextMenu");
505*f6dc9357SAndroid Build Coastguard Worker   systemContextMenu.Release();
506*f6dc9357SAndroid Build Coastguard Worker   UString folderPath = GetFsPath();
507*f6dc9357SAndroid Build Coastguard Worker 
508*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IShellFolder> desktopFolder;
509*f6dc9357SAndroid Build Coastguard Worker   RINOK(::SHGetDesktopFolder(&desktopFolder))
510*f6dc9357SAndroid Build Coastguard Worker   if (!desktopFolder)
511*f6dc9357SAndroid Build Coastguard Worker   {
512*f6dc9357SAndroid Build Coastguard Worker     // ShowMessage("Failed to get Desktop folder");
513*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
514*f6dc9357SAndroid Build Coastguard Worker   }
515*f6dc9357SAndroid Build Coastguard Worker 
516*f6dc9357SAndroid Build Coastguard Worker   CFolderPidls pidls;
517*f6dc9357SAndroid Build Coastguard Worker   // NULL is allowed for parentHWND in ParseDisplayName()
518*f6dc9357SAndroid Build Coastguard Worker   const HWND parentHWND_for_ParseDisplayName = GetParent();
519*f6dc9357SAndroid Build Coastguard Worker   // if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer"
520*f6dc9357SAndroid Build Coastguard Worker   /* win10: ParseDisplayName() supports folder path with tail slash
521*f6dc9357SAndroid Build Coastguard Worker     ParseDisplayName() returns {
522*f6dc9357SAndroid Build Coastguard Worker       E_INVALIDARG         : path with super path prefix "\\\\?\\"
523*f6dc9357SAndroid Build Coastguard Worker       ERROR_FILE_NOT_FOUND : path for network share (\\server\path1\long path2") larger than MAX_PATH
524*f6dc9357SAndroid Build Coastguard Worker     } */
525*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = ShellFolder_ParseDisplayName(desktopFolder,
526*f6dc9357SAndroid Build Coastguard Worker       parentHWND_for_ParseDisplayName,
527*f6dc9357SAndroid Build Coastguard Worker       folderPath, &pidls.parent);
528*f6dc9357SAndroid Build Coastguard Worker   if (res != S_OK)
529*f6dc9357SAndroid Build Coastguard Worker   {
530*f6dc9357SAndroid Build Coastguard Worker     ODS_U(folderPath);
531*f6dc9357SAndroid Build Coastguard Worker     if (res != E_INVALIDARG)
532*f6dc9357SAndroid Build Coastguard Worker       return res;
533*f6dc9357SAndroid Build Coastguard Worker     if (!NFile::NName::If_IsSuperPath_RemoveSuperPrefix(folderPath))
534*f6dc9357SAndroid Build Coastguard Worker       return res;
535*f6dc9357SAndroid Build Coastguard Worker     RINOK(ShellFolder_ParseDisplayName(desktopFolder,
536*f6dc9357SAndroid Build Coastguard Worker         parentHWND_for_ParseDisplayName,
537*f6dc9357SAndroid Build Coastguard Worker         folderPath, &pidls.parent))
538*f6dc9357SAndroid Build Coastguard Worker   }
539*f6dc9357SAndroid Build Coastguard Worker   if (!pidls.parent)
540*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
541*f6dc9357SAndroid Build Coastguard Worker 
542*f6dc9357SAndroid Build Coastguard Worker   /*
543*f6dc9357SAndroid Build Coastguard Worker   UString path2;
544*f6dc9357SAndroid Build Coastguard Worker   NShell::GetPathFromIDList(pidls.parent, path2);
545*f6dc9357SAndroid Build Coastguard Worker   ODS_U(path2);
546*f6dc9357SAndroid Build Coastguard Worker   */
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker   if (operatedIndices.IsEmpty())
549*f6dc9357SAndroid Build Coastguard Worker   {
550*f6dc9357SAndroid Build Coastguard Worker     // how to get IContextMenu, if there are no selected files?
551*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
552*f6dc9357SAndroid Build Coastguard Worker 
553*f6dc9357SAndroid Build Coastguard Worker     /*
554*f6dc9357SAndroid Build Coastguard Worker     xp64 :
555*f6dc9357SAndroid Build Coastguard Worker     1) we can't use GetUIObjectOf() with (numItems == 0), it throws exception
556*f6dc9357SAndroid Build Coastguard Worker     2) we can't use desktopFolder->GetUIObjectOf() with absolute pidls of folder
557*f6dc9357SAndroid Build Coastguard Worker         context menu items are different in that case:
558*f6dc9357SAndroid Build Coastguard Worker           "Open / Explorer" for folder
559*f6dc9357SAndroid Build Coastguard Worker           "Delete" for "My Computer" icon
560*f6dc9357SAndroid Build Coastguard Worker           "Preperties" for "System"
561*f6dc9357SAndroid Build Coastguard Worker     */
562*f6dc9357SAndroid Build Coastguard Worker     /*
563*f6dc9357SAndroid Build Coastguard Worker     parentFolder = desktopFolder;
564*f6dc9357SAndroid Build Coastguard Worker     pidls.items.AddInReserved(pidls.parent);
565*f6dc9357SAndroid Build Coastguard Worker     pidls.parent = NULL;
566*f6dc9357SAndroid Build Coastguard Worker     */
567*f6dc9357SAndroid Build Coastguard Worker 
568*f6dc9357SAndroid Build Coastguard Worker     // CreateViewObject() doesn't show all context menu items
569*f6dc9357SAndroid Build Coastguard Worker     /*
570*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = parentFolder->CreateViewObject(
571*f6dc9357SAndroid Build Coastguard Worker         GetParent(), IID_IContextMenu, (void**)&systemContextMenu);
572*f6dc9357SAndroid Build Coastguard Worker     */
573*f6dc9357SAndroid Build Coastguard Worker   }
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IShellFolder> parentFolder;
576*f6dc9357SAndroid Build Coastguard Worker   RINOK(desktopFolder->BindToObject(pidls.parent,
577*f6dc9357SAndroid Build Coastguard Worker       NULL, IID_IShellFolder, (void**)&parentFolder))
578*f6dc9357SAndroid Build Coastguard Worker   if (!parentFolder)
579*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
580*f6dc9357SAndroid Build Coastguard Worker 
581*f6dc9357SAndroid Build Coastguard Worker   ODS("==== CPanel::CreateShellContextMenu pidls START");
582*f6dc9357SAndroid Build Coastguard Worker 
583*f6dc9357SAndroid Build Coastguard Worker   pidls.items.ClearAndReserve(operatedIndices.Size());
584*f6dc9357SAndroid Build Coastguard Worker   UString fileName;
585*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, operatedIndices)
586*f6dc9357SAndroid Build Coastguard Worker   {
587*f6dc9357SAndroid Build Coastguard Worker     fileName.Empty();
588*f6dc9357SAndroid Build Coastguard Worker     Add_ItemRelPath2_To_String(operatedIndices[i], fileName);
589*f6dc9357SAndroid Build Coastguard Worker     /* ParseDisplayName() in win10 returns:
590*f6dc9357SAndroid Build Coastguard Worker          E_INVALIDARG : if empty name, or path with dots only: "." , ".."
591*f6dc9357SAndroid Build Coastguard Worker          HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) : if there is no such file
592*f6dc9357SAndroid Build Coastguard Worker     */
593*f6dc9357SAndroid Build Coastguard Worker     LPITEMIDLIST pidl = NULL;
594*f6dc9357SAndroid Build Coastguard Worker     RINOK(ShellFolder_ParseDisplayName(parentFolder,
595*f6dc9357SAndroid Build Coastguard Worker         parentHWND_for_ParseDisplayName,
596*f6dc9357SAndroid Build Coastguard Worker         fileName, &pidl))
597*f6dc9357SAndroid Build Coastguard Worker     if (!pidl)
598*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
599*f6dc9357SAndroid Build Coastguard Worker     pidls.items.AddInReserved(pidl);
600*f6dc9357SAndroid Build Coastguard Worker   }
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker   ODS("==== CPanel::CreateShellContextMenu pidls END");
603*f6dc9357SAndroid Build Coastguard Worker   // Get IContextMenu for items
604*f6dc9357SAndroid Build Coastguard Worker   RINOK(parentFolder->GetUIObjectOf(GetParent(),
605*f6dc9357SAndroid Build Coastguard Worker       pidls.items.Size(), (LPCITEMIDLIST *)(void *)pidls.items.ConstData(),
606*f6dc9357SAndroid Build Coastguard Worker       IID_IContextMenu, NULL, (void**)&systemContextMenu))
607*f6dc9357SAndroid Build Coastguard Worker   ODS("==== CPanel::CreateShellContextMenu GetUIObjectOf finished");
608*f6dc9357SAndroid Build Coastguard Worker   if (!systemContextMenu)
609*f6dc9357SAndroid Build Coastguard Worker   {
610*f6dc9357SAndroid Build Coastguard Worker     // ShowMessage("Unable to get context menu interface");
611*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
612*f6dc9357SAndroid Build Coastguard Worker   }
613*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
614*f6dc9357SAndroid Build Coastguard Worker }
615*f6dc9357SAndroid Build Coastguard Worker 
616*f6dc9357SAndroid Build Coastguard Worker 
617*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_FM_CTX_MENU
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_FM_CTX_MENU
620*f6dc9357SAndroid Build Coastguard Worker 
PrintHex(UString & s,UInt32 v)621*f6dc9357SAndroid Build Coastguard Worker static void PrintHex(UString &s, UInt32 v)
622*f6dc9357SAndroid Build Coastguard Worker {
623*f6dc9357SAndroid Build Coastguard Worker   char sz[32];
624*f6dc9357SAndroid Build Coastguard Worker   ConvertUInt32ToHex(v, sz);
625*f6dc9357SAndroid Build Coastguard Worker   s += sz;
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker 
PrintContextStr(UString & s,IContextMenu * ctxm,unsigned i,unsigned id,const char * name)628*f6dc9357SAndroid Build Coastguard Worker static void PrintContextStr(UString &s, IContextMenu *ctxm, unsigned i, unsigned id, const char *name)
629*f6dc9357SAndroid Build Coastguard Worker {
630*f6dc9357SAndroid Build Coastguard Worker   s += " | ";
631*f6dc9357SAndroid Build Coastguard Worker   s += name;
632*f6dc9357SAndroid Build Coastguard Worker   s += ": ";
633*f6dc9357SAndroid Build Coastguard Worker   UString s1;
634*f6dc9357SAndroid Build Coastguard Worker   {
635*f6dc9357SAndroid Build Coastguard Worker     char buf[256];
636*f6dc9357SAndroid Build Coastguard Worker     buf[0] = 0;
637*f6dc9357SAndroid Build Coastguard Worker     const HRESULT res = ctxm->GetCommandString(i, id,
638*f6dc9357SAndroid Build Coastguard Worker         NULL, buf, Z7_ARRAY_SIZE(buf) - 1);
639*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
640*f6dc9357SAndroid Build Coastguard Worker     {
641*f6dc9357SAndroid Build Coastguard Worker       PrintHex(s1, res);
642*f6dc9357SAndroid Build Coastguard Worker       s1.Add_Space();
643*f6dc9357SAndroid Build Coastguard Worker     }
644*f6dc9357SAndroid Build Coastguard Worker     s1 += GetUnicodeString(buf);
645*f6dc9357SAndroid Build Coastguard Worker   }
646*f6dc9357SAndroid Build Coastguard Worker   UString s2;
647*f6dc9357SAndroid Build Coastguard Worker   {
648*f6dc9357SAndroid Build Coastguard Worker     wchar_t buf2[256];
649*f6dc9357SAndroid Build Coastguard Worker     buf2[0] = 0;
650*f6dc9357SAndroid Build Coastguard Worker     const HRESULT res = ctxm->GetCommandString(i, id | GCS_UNICODE,
651*f6dc9357SAndroid Build Coastguard Worker         NULL, (char *)buf2, Z7_ARRAY_SIZE(buf2) - sizeof(wchar_t));
652*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
653*f6dc9357SAndroid Build Coastguard Worker     {
654*f6dc9357SAndroid Build Coastguard Worker       PrintHex(s2, res);
655*f6dc9357SAndroid Build Coastguard Worker       s2.Add_Space();
656*f6dc9357SAndroid Build Coastguard Worker     }
657*f6dc9357SAndroid Build Coastguard Worker     s2 += buf2;
658*f6dc9357SAndroid Build Coastguard Worker   }
659*f6dc9357SAndroid Build Coastguard Worker   s += s1;
660*f6dc9357SAndroid Build Coastguard Worker   if (s2.Compare(s1) != 0)
661*f6dc9357SAndroid Build Coastguard Worker   {
662*f6dc9357SAndroid Build Coastguard Worker     s += " Unicode: ";
663*f6dc9357SAndroid Build Coastguard Worker     s += s2;
664*f6dc9357SAndroid Build Coastguard Worker   }
665*f6dc9357SAndroid Build Coastguard Worker }
666*f6dc9357SAndroid Build Coastguard Worker 
PrintAllContextItems(IContextMenu * ctxm,unsigned num)667*f6dc9357SAndroid Build Coastguard Worker static void PrintAllContextItems(IContextMenu *ctxm, unsigned num)
668*f6dc9357SAndroid Build Coastguard Worker {
669*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < num; i++)
670*f6dc9357SAndroid Build Coastguard Worker   {
671*f6dc9357SAndroid Build Coastguard Worker     UString s;
672*f6dc9357SAndroid Build Coastguard Worker     s.Add_UInt32(i);
673*f6dc9357SAndroid Build Coastguard Worker     s += ": ";
674*f6dc9357SAndroid Build Coastguard Worker     PrintContextStr(s, ctxm, i, GCS_VALIDATEA, "valid");
675*f6dc9357SAndroid Build Coastguard Worker     PrintContextStr(s, ctxm, i, GCS_VERBA, "verb");
676*f6dc9357SAndroid Build Coastguard Worker     PrintContextStr(s, ctxm, i, GCS_HELPTEXTA, "helptext");
677*f6dc9357SAndroid Build Coastguard Worker     OutputDebugStringW(s);
678*f6dc9357SAndroid Build Coastguard Worker   }
679*f6dc9357SAndroid Build Coastguard Worker }
680*f6dc9357SAndroid Build Coastguard Worker 
681*f6dc9357SAndroid Build Coastguard Worker #endif
682*f6dc9357SAndroid Build Coastguard Worker 
683*f6dc9357SAndroid Build Coastguard Worker 
CreateSystemMenu(HMENU menuSpec,bool showExtendedVerbs,const CRecordVector<UInt32> & operatedIndices,CMyComPtr<IContextMenu> & systemContextMenu)684*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateSystemMenu(HMENU menuSpec,
685*f6dc9357SAndroid Build Coastguard Worker     bool showExtendedVerbs,
686*f6dc9357SAndroid Build Coastguard Worker     const CRecordVector<UInt32> &operatedIndices,
687*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IContextMenu> &systemContextMenu)
688*f6dc9357SAndroid Build Coastguard Worker {
689*f6dc9357SAndroid Build Coastguard Worker   systemContextMenu.Release();
690*f6dc9357SAndroid Build Coastguard Worker 
691*f6dc9357SAndroid Build Coastguard Worker   CreateShellContextMenu(operatedIndices, systemContextMenu);
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker   if (!systemContextMenu)
694*f6dc9357SAndroid Build Coastguard Worker     return;
695*f6dc9357SAndroid Build Coastguard Worker 
696*f6dc9357SAndroid Build Coastguard Worker   /*
697*f6dc9357SAndroid Build Coastguard Worker   // Set up a CMINVOKECOMMANDINFO structure.
698*f6dc9357SAndroid Build Coastguard Worker   CMINVOKECOMMANDINFO ci;
699*f6dc9357SAndroid Build Coastguard Worker   ZeroMemory(&ci, sizeof(ci));
700*f6dc9357SAndroid Build Coastguard Worker   ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
701*f6dc9357SAndroid Build Coastguard Worker   ci.hwnd = GetParent();
702*f6dc9357SAndroid Build Coastguard Worker   */
703*f6dc9357SAndroid Build Coastguard Worker 
704*f6dc9357SAndroid Build Coastguard Worker   /*
705*f6dc9357SAndroid Build Coastguard Worker   if (Sender == GoBtn)
706*f6dc9357SAndroid Build Coastguard Worker   {
707*f6dc9357SAndroid Build Coastguard Worker     // Verbs that can be used are cut, paste,
708*f6dc9357SAndroid Build Coastguard Worker     // properties, delete, and so on.
709*f6dc9357SAndroid Build Coastguard Worker     String action;
710*f6dc9357SAndroid Build Coastguard Worker     if (CutRb->Checked)
711*f6dc9357SAndroid Build Coastguard Worker       action = "cut";
712*f6dc9357SAndroid Build Coastguard Worker     else if (CopyRb->Checked)
713*f6dc9357SAndroid Build Coastguard Worker       action = "copy";
714*f6dc9357SAndroid Build Coastguard Worker     else if (DeleteRb->Checked)
715*f6dc9357SAndroid Build Coastguard Worker       action = "delete";
716*f6dc9357SAndroid Build Coastguard Worker     else if (PropertiesRb->Checked)
717*f6dc9357SAndroid Build Coastguard Worker       action = "properties";
718*f6dc9357SAndroid Build Coastguard Worker 
719*f6dc9357SAndroid Build Coastguard Worker     ci.lpVerb = action.c_str();
720*f6dc9357SAndroid Build Coastguard Worker     result = cm->InvokeCommand(&ci);
721*f6dc9357SAndroid Build Coastguard Worker     if (result)
722*f6dc9357SAndroid Build Coastguard Worker       ShowMessage(
723*f6dc9357SAndroid Build Coastguard Worker       "Error copying file to clipboard.");
724*f6dc9357SAndroid Build Coastguard Worker 
725*f6dc9357SAndroid Build Coastguard Worker   }
726*f6dc9357SAndroid Build Coastguard Worker   else
727*f6dc9357SAndroid Build Coastguard Worker   */
728*f6dc9357SAndroid Build Coastguard Worker   {
729*f6dc9357SAndroid Build Coastguard Worker     // HMENU hMenu = CreatePopupMenu();
730*f6dc9357SAndroid Build Coastguard Worker     CMenu popupMenu;
731*f6dc9357SAndroid Build Coastguard Worker     CMenuDestroyer menuDestroyer(popupMenu);
732*f6dc9357SAndroid Build Coastguard Worker     if (!popupMenu.CreatePopup())
733*f6dc9357SAndroid Build Coastguard Worker       throw 210503;
734*f6dc9357SAndroid Build Coastguard Worker     const HMENU hMenu = popupMenu;
735*f6dc9357SAndroid Build Coastguard Worker     DWORD flags = CMF_EXPLORE;
736*f6dc9357SAndroid Build Coastguard Worker     if (showExtendedVerbs)
737*f6dc9357SAndroid Build Coastguard Worker       flags |= Z7_WIN_CMF_EXTENDEDVERBS;
738*f6dc9357SAndroid Build Coastguard Worker     ODS("=== systemContextMenu->QueryContextMenu START");
739*f6dc9357SAndroid Build Coastguard Worker     const HRESULT res = systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, flags);
740*f6dc9357SAndroid Build Coastguard Worker     ODS("=== systemContextMenu->QueryContextMenu END");
741*f6dc9357SAndroid Build Coastguard Worker     if (SUCCEEDED(res))
742*f6dc9357SAndroid Build Coastguard Worker     {
743*f6dc9357SAndroid Build Coastguard Worker       #ifdef SHOW_DEBUG_FM_CTX_MENU
744*f6dc9357SAndroid Build Coastguard Worker       PrintAllContextItems(systemContextMenu, (unsigned)res);
745*f6dc9357SAndroid Build Coastguard Worker       #endif
746*f6dc9357SAndroid Build Coastguard Worker 
747*f6dc9357SAndroid Build Coastguard Worker       CMenu menu;
748*f6dc9357SAndroid Build Coastguard Worker       menu.Attach(menuSpec);
749*f6dc9357SAndroid Build Coastguard Worker       CMenuItem menuItem;
750*f6dc9357SAndroid Build Coastguard Worker       menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
751*f6dc9357SAndroid Build Coastguard Worker       menuItem.fType = MFT_STRING;
752*f6dc9357SAndroid Build Coastguard Worker       menuItem.hSubMenu = popupMenu.Detach();
753*f6dc9357SAndroid Build Coastguard Worker       menuDestroyer.Disable();
754*f6dc9357SAndroid Build Coastguard Worker       LangString(IDS_SYSTEM, menuItem.StringValue);
755*f6dc9357SAndroid Build Coastguard Worker       menu.InsertItem(0, true, menuItem);
756*f6dc9357SAndroid Build Coastguard Worker     }
757*f6dc9357SAndroid Build Coastguard Worker     /*
758*f6dc9357SAndroid Build Coastguard Worker     if (Cmd < 100 && Cmd != 0)
759*f6dc9357SAndroid Build Coastguard Worker     {
760*f6dc9357SAndroid Build Coastguard Worker       ci.lpVerb = MAKEINTRESOURCE(Cmd - 1);
761*f6dc9357SAndroid Build Coastguard Worker       ci.lpParameters = "";
762*f6dc9357SAndroid Build Coastguard Worker       ci.lpDirectory = "";
763*f6dc9357SAndroid Build Coastguard Worker       ci.nShow = SW_SHOWNORMAL;
764*f6dc9357SAndroid Build Coastguard Worker       cm->InvokeCommand(&ci);
765*f6dc9357SAndroid Build Coastguard Worker     }
766*f6dc9357SAndroid Build Coastguard Worker     // If Cmd is > 100 then it's one of our
767*f6dc9357SAndroid Build Coastguard Worker     // inserted menu items.
768*f6dc9357SAndroid Build Coastguard Worker     else
769*f6dc9357SAndroid Build Coastguard Worker       // Find the menu item.
770*f6dc9357SAndroid Build Coastguard Worker       for (int i = 0; i < popupMenu1->Items->Count; i++)
771*f6dc9357SAndroid Build Coastguard Worker       {
772*f6dc9357SAndroid Build Coastguard Worker         TMenuItem* menu = popupMenu1->Items->Items[i];
773*f6dc9357SAndroid Build Coastguard Worker         // Call its OnClick handler.
774*f6dc9357SAndroid Build Coastguard Worker         if (menu->Command == Cmd - 100)
775*f6dc9357SAndroid Build Coastguard Worker           menu->OnClick(this);
776*f6dc9357SAndroid Build Coastguard Worker       }
777*f6dc9357SAndroid Build Coastguard Worker       // Release the memory allocated for the menu.
778*f6dc9357SAndroid Build Coastguard Worker       DestroyMenu(hMenu);
779*f6dc9357SAndroid Build Coastguard Worker     */
780*f6dc9357SAndroid Build Coastguard Worker   }
781*f6dc9357SAndroid Build Coastguard Worker }
782*f6dc9357SAndroid Build Coastguard Worker 
CreateFileMenu(HMENU menuSpec)783*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateFileMenu(HMENU menuSpec)
784*f6dc9357SAndroid Build Coastguard Worker {
785*f6dc9357SAndroid Build Coastguard Worker   CreateFileMenu(menuSpec, _sevenZipContextMenu, _systemContextMenu, true); // programMenu
786*f6dc9357SAndroid Build Coastguard Worker }
787*f6dc9357SAndroid Build Coastguard Worker 
CreateSevenZipMenu(HMENU menuSpec,bool showExtendedVerbs,const CRecordVector<UInt32> & operatedIndices,int firstDirIndex,CMyComPtr<IContextMenu> & sevenZipContextMenu)788*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateSevenZipMenu(HMENU menuSpec,
789*f6dc9357SAndroid Build Coastguard Worker     bool showExtendedVerbs,
790*f6dc9357SAndroid Build Coastguard Worker     const CRecordVector<UInt32> &operatedIndices,
791*f6dc9357SAndroid Build Coastguard Worker     int firstDirIndex,
792*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IContextMenu> &sevenZipContextMenu)
793*f6dc9357SAndroid Build Coastguard Worker {
794*f6dc9357SAndroid Build Coastguard Worker   sevenZipContextMenu.Release();
795*f6dc9357SAndroid Build Coastguard Worker 
796*f6dc9357SAndroid Build Coastguard Worker   CMenu menu;
797*f6dc9357SAndroid Build Coastguard Worker   menu.Attach(menuSpec);
798*f6dc9357SAndroid Build Coastguard Worker   // CMenuDestroyer menuDestroyer(menu);
799*f6dc9357SAndroid Build Coastguard Worker   // menu.CreatePopup();
800*f6dc9357SAndroid Build Coastguard Worker 
801*f6dc9357SAndroid Build Coastguard Worker   CZipContextMenu *contextMenuSpec = new CZipContextMenu;
802*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IContextMenu> contextMenu = contextMenuSpec;
803*f6dc9357SAndroid Build Coastguard Worker   // if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK)
804*f6dc9357SAndroid Build Coastguard Worker   {
805*f6dc9357SAndroid Build Coastguard Worker     /*
806*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IInitContextMenu> initContextMenu;
807*f6dc9357SAndroid Build Coastguard Worker     if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK)
808*f6dc9357SAndroid Build Coastguard Worker       return;
809*f6dc9357SAndroid Build Coastguard Worker     */
810*f6dc9357SAndroid Build Coastguard Worker     ODS("=== FileName List Add START")
811*f6dc9357SAndroid Build Coastguard Worker     // for (unsigned y = 0; y < 10000; y++, contextMenuSpec->_fileNames.Clear())
812*f6dc9357SAndroid Build Coastguard Worker     GetFilePaths(operatedIndices, contextMenuSpec->_fileNames);
813*f6dc9357SAndroid Build Coastguard Worker     ODS("=== FileName List Add END")
814*f6dc9357SAndroid Build Coastguard Worker     contextMenuSpec->Init_For_7zFM();
815*f6dc9357SAndroid Build Coastguard Worker     contextMenuSpec->_attribs.FirstDirIndex = firstDirIndex;
816*f6dc9357SAndroid Build Coastguard Worker     {
817*f6dc9357SAndroid Build Coastguard Worker       DWORD flags = CMF_EXPLORE;
818*f6dc9357SAndroid Build Coastguard Worker       if (showExtendedVerbs)
819*f6dc9357SAndroid Build Coastguard Worker         flags |= Z7_WIN_CMF_EXTENDEDVERBS;
820*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res = contextMenu->QueryContextMenu(menu,
821*f6dc9357SAndroid Build Coastguard Worker           0, // indexMenu
822*f6dc9357SAndroid Build Coastguard Worker           kSevenZipStartMenuID, // first
823*f6dc9357SAndroid Build Coastguard Worker           kSystemStartMenuID - 1, // last
824*f6dc9357SAndroid Build Coastguard Worker           flags);
825*f6dc9357SAndroid Build Coastguard Worker       ODS("=== contextMenu->QueryContextMenu END")
826*f6dc9357SAndroid Build Coastguard Worker       const bool sevenZipMenuCreated = SUCCEEDED(res);
827*f6dc9357SAndroid Build Coastguard Worker       if (sevenZipMenuCreated)
828*f6dc9357SAndroid Build Coastguard Worker       {
829*f6dc9357SAndroid Build Coastguard Worker         // if (res != 0)
830*f6dc9357SAndroid Build Coastguard Worker         {
831*f6dc9357SAndroid Build Coastguard Worker           // some "non-good" implementation of QueryContextMenu() could add some items to menu, but it return 0.
832*f6dc9357SAndroid Build Coastguard Worker           // so we still allow these items
833*f6dc9357SAndroid Build Coastguard Worker           sevenZipContextMenu = contextMenu;
834*f6dc9357SAndroid Build Coastguard Worker           #ifdef SHOW_DEBUG_FM_CTX_MENU
835*f6dc9357SAndroid Build Coastguard Worker           PrintAllContextItems(contextMenu, (unsigned)res);
836*f6dc9357SAndroid Build Coastguard Worker           #endif
837*f6dc9357SAndroid Build Coastguard Worker         }
838*f6dc9357SAndroid Build Coastguard Worker       }
839*f6dc9357SAndroid Build Coastguard Worker       else
840*f6dc9357SAndroid Build Coastguard Worker       {
841*f6dc9357SAndroid Build Coastguard Worker         // MessageBox_Error_HRESULT_Caption(res, L"QueryContextMenu");
842*f6dc9357SAndroid Build Coastguard Worker       }
843*f6dc9357SAndroid Build Coastguard Worker       // int code = HRESULT_CODE(res);
844*f6dc9357SAndroid Build Coastguard Worker       // int nextItemID = code;
845*f6dc9357SAndroid Build Coastguard Worker     }
846*f6dc9357SAndroid Build Coastguard Worker   }
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker 
IsReadOnlyFolder(IFolderFolder * folder)849*f6dc9357SAndroid Build Coastguard Worker static bool IsReadOnlyFolder(IFolderFolder *folder)
850*f6dc9357SAndroid Build Coastguard Worker {
851*f6dc9357SAndroid Build Coastguard Worker   if (!folder)
852*f6dc9357SAndroid Build Coastguard Worker     return false;
853*f6dc9357SAndroid Build Coastguard Worker 
854*f6dc9357SAndroid Build Coastguard Worker   bool res = false;
855*f6dc9357SAndroid Build Coastguard Worker   {
856*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop;
857*f6dc9357SAndroid Build Coastguard Worker     if (folder->GetFolderProperty(kpidReadOnly, &prop) == S_OK)
858*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt == VT_BOOL)
859*f6dc9357SAndroid Build Coastguard Worker         res = VARIANT_BOOLToBool(prop.boolVal);
860*f6dc9357SAndroid Build Coastguard Worker   }
861*f6dc9357SAndroid Build Coastguard Worker   return res;
862*f6dc9357SAndroid Build Coastguard Worker }
863*f6dc9357SAndroid Build Coastguard Worker 
IsThereReadOnlyFolder() const864*f6dc9357SAndroid Build Coastguard Worker bool CPanel::IsThereReadOnlyFolder() const
865*f6dc9357SAndroid Build Coastguard Worker {
866*f6dc9357SAndroid Build Coastguard Worker   if (!_folderOperations)
867*f6dc9357SAndroid Build Coastguard Worker     return true;
868*f6dc9357SAndroid Build Coastguard Worker   if (IsReadOnlyFolder(_folder))
869*f6dc9357SAndroid Build Coastguard Worker     return true;
870*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, _parentFolders)
871*f6dc9357SAndroid Build Coastguard Worker   {
872*f6dc9357SAndroid Build Coastguard Worker     if (IsReadOnlyFolder(_parentFolders[i].ParentFolder))
873*f6dc9357SAndroid Build Coastguard Worker       return true;
874*f6dc9357SAndroid Build Coastguard Worker   }
875*f6dc9357SAndroid Build Coastguard Worker   return false;
876*f6dc9357SAndroid Build Coastguard Worker }
877*f6dc9357SAndroid Build Coastguard Worker 
CheckBeforeUpdate(UINT resourceID)878*f6dc9357SAndroid Build Coastguard Worker bool CPanel::CheckBeforeUpdate(UINT resourceID)
879*f6dc9357SAndroid Build Coastguard Worker {
880*f6dc9357SAndroid Build Coastguard Worker   if (!_folderOperations)
881*f6dc9357SAndroid Build Coastguard Worker   {
882*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_UnsupportOperation();
883*f6dc9357SAndroid Build Coastguard Worker     // resourceID = resourceID;
884*f6dc9357SAndroid Build Coastguard Worker     // MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID);
885*f6dc9357SAndroid Build Coastguard Worker     return false;
886*f6dc9357SAndroid Build Coastguard Worker   }
887*f6dc9357SAndroid Build Coastguard Worker 
888*f6dc9357SAndroid Build Coastguard Worker   for (int i = (int)_parentFolders.Size(); i >= 0; i--)
889*f6dc9357SAndroid Build Coastguard Worker   {
890*f6dc9357SAndroid Build Coastguard Worker     IFolderFolder *folder;
891*f6dc9357SAndroid Build Coastguard Worker     if (i == (int)_parentFolders.Size())
892*f6dc9357SAndroid Build Coastguard Worker       folder = _folder;
893*f6dc9357SAndroid Build Coastguard Worker     else
894*f6dc9357SAndroid Build Coastguard Worker       folder = _parentFolders[i].ParentFolder;
895*f6dc9357SAndroid Build Coastguard Worker 
896*f6dc9357SAndroid Build Coastguard Worker     if (!IsReadOnlyFolder(folder))
897*f6dc9357SAndroid Build Coastguard Worker       continue;
898*f6dc9357SAndroid Build Coastguard Worker 
899*f6dc9357SAndroid Build Coastguard Worker     UString s;
900*f6dc9357SAndroid Build Coastguard Worker     AddLangString(s, resourceID);
901*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
902*f6dc9357SAndroid Build Coastguard Worker     AddLangString(s, IDS_OPERATION_IS_NOT_SUPPORTED);
903*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
904*f6dc9357SAndroid Build Coastguard Worker     if (i == 0)
905*f6dc9357SAndroid Build Coastguard Worker       s += GetFolderPath(folder);
906*f6dc9357SAndroid Build Coastguard Worker     else
907*f6dc9357SAndroid Build Coastguard Worker       s += _parentFolders[i - 1].VirtualPath;
908*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
909*f6dc9357SAndroid Build Coastguard Worker     AddLangString(s, IDS_PROP_READ_ONLY);
910*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error(s);
911*f6dc9357SAndroid Build Coastguard Worker     return false;
912*f6dc9357SAndroid Build Coastguard Worker   }
913*f6dc9357SAndroid Build Coastguard Worker 
914*f6dc9357SAndroid Build Coastguard Worker   return true;
915*f6dc9357SAndroid Build Coastguard Worker }
916*f6dc9357SAndroid Build Coastguard Worker 
CreateFileMenu(HMENU menuSpec,CMyComPtr<IContextMenu> & sevenZipContextMenu,CMyComPtr<IContextMenu> & systemContextMenu,bool programMenu)917*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateFileMenu(HMENU menuSpec,
918*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IContextMenu> &sevenZipContextMenu,
919*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IContextMenu> &systemContextMenu,
920*f6dc9357SAndroid Build Coastguard Worker     bool programMenu)
921*f6dc9357SAndroid Build Coastguard Worker {
922*f6dc9357SAndroid Build Coastguard Worker   sevenZipContextMenu.Release();
923*f6dc9357SAndroid Build Coastguard Worker   systemContextMenu.Release();
924*f6dc9357SAndroid Build Coastguard Worker 
925*f6dc9357SAndroid Build Coastguard Worker   const bool showExtendedVerbs = IsKeyDown(VK_SHIFT);
926*f6dc9357SAndroid Build Coastguard Worker 
927*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> operatedIndices;
928*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Operated(operatedIndices);
929*f6dc9357SAndroid Build Coastguard Worker   const int firstDirIndex = FindDir_InOperatedList(operatedIndices);
930*f6dc9357SAndroid Build Coastguard Worker 
931*f6dc9357SAndroid Build Coastguard Worker   CMenu menu;
932*f6dc9357SAndroid Build Coastguard Worker   menu.Attach(menuSpec);
933*f6dc9357SAndroid Build Coastguard Worker 
934*f6dc9357SAndroid Build Coastguard Worker   if (!IsArcFolder())
935*f6dc9357SAndroid Build Coastguard Worker   {
936*f6dc9357SAndroid Build Coastguard Worker     CreateSevenZipMenu(menu, showExtendedVerbs, operatedIndices, firstDirIndex, sevenZipContextMenu);
937*f6dc9357SAndroid Build Coastguard Worker     // CreateSystemMenu is very slow if you call it inside ZIP archive with big number of files
938*f6dc9357SAndroid Build Coastguard Worker     // Windows probably can parse items inside ZIP archive.
939*f6dc9357SAndroid Build Coastguard Worker     if (g_App.ShowSystemMenu)
940*f6dc9357SAndroid Build Coastguard Worker       CreateSystemMenu(menu, showExtendedVerbs, operatedIndices, systemContextMenu);
941*f6dc9357SAndroid Build Coastguard Worker   }
942*f6dc9357SAndroid Build Coastguard Worker 
943*f6dc9357SAndroid Build Coastguard Worker   /*
944*f6dc9357SAndroid Build Coastguard Worker   if (menu.GetItemCount() > 0)
945*f6dc9357SAndroid Build Coastguard Worker     menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)0);
946*f6dc9357SAndroid Build Coastguard Worker   */
947*f6dc9357SAndroid Build Coastguard Worker 
948*f6dc9357SAndroid Build Coastguard Worker   CFileMenu fm;
949*f6dc9357SAndroid Build Coastguard Worker 
950*f6dc9357SAndroid Build Coastguard Worker   fm.readOnly = IsThereReadOnlyFolder();
951*f6dc9357SAndroid Build Coastguard Worker   fm.isHashFolder = IsHashFolder();
952*f6dc9357SAndroid Build Coastguard Worker   fm.isFsFolder = Is_IO_FS_Folder();
953*f6dc9357SAndroid Build Coastguard Worker   fm.programMenu = programMenu;
954*f6dc9357SAndroid Build Coastguard Worker   fm.allAreFiles = (firstDirIndex == -1);
955*f6dc9357SAndroid Build Coastguard Worker   fm.numItems = operatedIndices.Size();
956*f6dc9357SAndroid Build Coastguard Worker 
957*f6dc9357SAndroid Build Coastguard Worker   fm.isAltStreamsSupported = false;
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker   if (fm.numItems == 1)
960*f6dc9357SAndroid Build Coastguard Worker     fm.FilePath = us2fs(GetItemFullPath(operatedIndices[0]));
961*f6dc9357SAndroid Build Coastguard Worker 
962*f6dc9357SAndroid Build Coastguard Worker   if (_folderAltStreams)
963*f6dc9357SAndroid Build Coastguard Worker   {
964*f6dc9357SAndroid Build Coastguard Worker     if (operatedIndices.Size() <= 1)
965*f6dc9357SAndroid Build Coastguard Worker     {
966*f6dc9357SAndroid Build Coastguard Worker       UInt32 realIndex = (UInt32)(Int32)-1;
967*f6dc9357SAndroid Build Coastguard Worker       if (operatedIndices.Size() == 1)
968*f6dc9357SAndroid Build Coastguard Worker         realIndex = operatedIndices[0];
969*f6dc9357SAndroid Build Coastguard Worker       Int32 val = 0;
970*f6dc9357SAndroid Build Coastguard Worker       if (_folderAltStreams->AreAltStreamsSupported(realIndex, &val) == S_OK)
971*f6dc9357SAndroid Build Coastguard Worker         fm.isAltStreamsSupported = IntToBool(val);
972*f6dc9357SAndroid Build Coastguard Worker     }
973*f6dc9357SAndroid Build Coastguard Worker   }
974*f6dc9357SAndroid Build Coastguard Worker   else
975*f6dc9357SAndroid Build Coastguard Worker   {
976*f6dc9357SAndroid Build Coastguard Worker     if (fm.numItems == 0)
977*f6dc9357SAndroid Build Coastguard Worker       fm.isAltStreamsSupported = IsFSFolder();
978*f6dc9357SAndroid Build Coastguard Worker     else
979*f6dc9357SAndroid Build Coastguard Worker       fm.isAltStreamsSupported = IsFolder_with_FsItems();
980*f6dc9357SAndroid Build Coastguard Worker   }
981*f6dc9357SAndroid Build Coastguard Worker 
982*f6dc9357SAndroid Build Coastguard Worker   fm.Load(menu, (unsigned)menu.GetItemCount());
983*f6dc9357SAndroid Build Coastguard Worker }
984*f6dc9357SAndroid Build Coastguard Worker 
InvokePluginCommand(unsigned id)985*f6dc9357SAndroid Build Coastguard Worker bool CPanel::InvokePluginCommand(unsigned id)
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker   return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu);
988*f6dc9357SAndroid Build Coastguard Worker }
989*f6dc9357SAndroid Build Coastguard Worker 
990*f6dc9357SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(UNDER_CE)
991*f6dc9357SAndroid Build Coastguard Worker #define use_CMINVOKECOMMANDINFOEX
992*f6dc9357SAndroid Build Coastguard Worker /* CMINVOKECOMMANDINFOEX depends from (_WIN32_IE >= 0x0400) */
993*f6dc9357SAndroid Build Coastguard Worker #endif
994*f6dc9357SAndroid Build Coastguard Worker 
InvokePluginCommand(unsigned id,IContextMenu * sevenZipContextMenu,IContextMenu * systemContextMenu)995*f6dc9357SAndroid Build Coastguard Worker bool CPanel::InvokePluginCommand(unsigned id,
996*f6dc9357SAndroid Build Coastguard Worker     IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu)
997*f6dc9357SAndroid Build Coastguard Worker {
998*f6dc9357SAndroid Build Coastguard Worker   UInt32 offset;
999*f6dc9357SAndroid Build Coastguard Worker   const bool isSystemMenu = (id >= kSystemStartMenuID);
1000*f6dc9357SAndroid Build Coastguard Worker   if (isSystemMenu)
1001*f6dc9357SAndroid Build Coastguard Worker   {
1002*f6dc9357SAndroid Build Coastguard Worker     if (!systemContextMenu)
1003*f6dc9357SAndroid Build Coastguard Worker       return false;
1004*f6dc9357SAndroid Build Coastguard Worker     offset = id - kSystemStartMenuID;
1005*f6dc9357SAndroid Build Coastguard Worker   }
1006*f6dc9357SAndroid Build Coastguard Worker   else
1007*f6dc9357SAndroid Build Coastguard Worker   {
1008*f6dc9357SAndroid Build Coastguard Worker     if (!sevenZipContextMenu)
1009*f6dc9357SAndroid Build Coastguard Worker       return false;
1010*f6dc9357SAndroid Build Coastguard Worker     offset = id - kSevenZipStartMenuID;
1011*f6dc9357SAndroid Build Coastguard Worker   }
1012*f6dc9357SAndroid Build Coastguard Worker 
1013*f6dc9357SAndroid Build Coastguard Worker   #ifdef use_CMINVOKECOMMANDINFOEX
1014*f6dc9357SAndroid Build Coastguard Worker     CMINVOKECOMMANDINFOEX
1015*f6dc9357SAndroid Build Coastguard Worker   #else
1016*f6dc9357SAndroid Build Coastguard Worker     CMINVOKECOMMANDINFO
1017*f6dc9357SAndroid Build Coastguard Worker   #endif
1018*f6dc9357SAndroid Build Coastguard Worker       commandInfo;
1019*f6dc9357SAndroid Build Coastguard Worker 
1020*f6dc9357SAndroid Build Coastguard Worker   memset(&commandInfo, 0, sizeof(commandInfo));
1021*f6dc9357SAndroid Build Coastguard Worker   commandInfo.cbSize = sizeof(commandInfo);
1022*f6dc9357SAndroid Build Coastguard Worker 
1023*f6dc9357SAndroid Build Coastguard Worker   commandInfo.fMask = 0
1024*f6dc9357SAndroid Build Coastguard Worker   #ifdef use_CMINVOKECOMMANDINFOEX
1025*f6dc9357SAndroid Build Coastguard Worker     | CMIC_MASK_UNICODE
1026*f6dc9357SAndroid Build Coastguard Worker   #endif
1027*f6dc9357SAndroid Build Coastguard Worker     ;
1028*f6dc9357SAndroid Build Coastguard Worker 
1029*f6dc9357SAndroid Build Coastguard Worker   commandInfo.hwnd = GetParent();
1030*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));
1031*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpParameters = NULL;
1032*f6dc9357SAndroid Build Coastguard Worker   // 19.01: fixed CSysString to AString
1033*f6dc9357SAndroid Build Coastguard Worker   // MSDN suggest to send NULL: lpDirectory: This member is always NULL for menu items inserted by a Shell extension.
1034*f6dc9357SAndroid Build Coastguard Worker   const AString currentFolderA (GetAnsiString(_currentFolderPrefix));
1035*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpDirectory = (LPCSTR)(currentFolderA);
1036*f6dc9357SAndroid Build Coastguard Worker   commandInfo.nShow = SW_SHOW;
1037*f6dc9357SAndroid Build Coastguard Worker 
1038*f6dc9357SAndroid Build Coastguard Worker   #ifdef use_CMINVOKECOMMANDINFOEX
1039*f6dc9357SAndroid Build Coastguard Worker 
1040*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpParametersW = NULL;
1041*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpTitle = "";
1042*f6dc9357SAndroid Build Coastguard Worker 
1043*f6dc9357SAndroid Build Coastguard Worker   /*
1044*f6dc9357SAndroid Build Coastguard Worker   system ContextMenu handler supports ContextMenu subhandlers.
1045*f6dc9357SAndroid Build Coastguard Worker   so InvokeCommand() converts (command_offset) from global number to subhandler number.
1046*f6dc9357SAndroid Build Coastguard Worker   XP-64 / win10:
1047*f6dc9357SAndroid Build Coastguard Worker       system ContextMenu converts (command_offset) in lpVerb only,
1048*f6dc9357SAndroid Build Coastguard Worker       and it keeps lpVerbW unchanged.
1049*f6dc9357SAndroid Build Coastguard Worker       also explorer.exe sends 0 in lpVerbW.
1050*f6dc9357SAndroid Build Coastguard Worker   We try to keep compatibility with Windows Explorer here.
1051*f6dc9357SAndroid Build Coastguard Worker   */
1052*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpVerbW = NULL;
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker   const UString currentFolderUnicode = _currentFolderPrefix;
1055*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpDirectoryW = currentFolderUnicode;
1056*f6dc9357SAndroid Build Coastguard Worker   commandInfo.lpTitleW = L"";
1057*f6dc9357SAndroid Build Coastguard Worker   // commandInfo.ptInvoke.x = xPos;
1058*f6dc9357SAndroid Build Coastguard Worker   // commandInfo.ptInvoke.y = yPos;
1059*f6dc9357SAndroid Build Coastguard Worker   commandInfo.ptInvoke.x = 0;
1060*f6dc9357SAndroid Build Coastguard Worker   commandInfo.ptInvoke.y = 0;
1061*f6dc9357SAndroid Build Coastguard Worker 
1062*f6dc9357SAndroid Build Coastguard Worker   #endif
1063*f6dc9357SAndroid Build Coastguard Worker 
1064*f6dc9357SAndroid Build Coastguard Worker   HRESULT result;
1065*f6dc9357SAndroid Build Coastguard Worker   if (isSystemMenu)
1066*f6dc9357SAndroid Build Coastguard Worker     result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
1067*f6dc9357SAndroid Build Coastguard Worker   else
1068*f6dc9357SAndroid Build Coastguard Worker     result = sevenZipContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
1069*f6dc9357SAndroid Build Coastguard Worker   if (result == NOERROR)
1070*f6dc9357SAndroid Build Coastguard Worker   {
1071*f6dc9357SAndroid Build Coastguard Worker     KillSelection();
1072*f6dc9357SAndroid Build Coastguard Worker     return true;
1073*f6dc9357SAndroid Build Coastguard Worker   }
1074*f6dc9357SAndroid Build Coastguard Worker   else
1075*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT_Caption(result, L"InvokeCommand");
1076*f6dc9357SAndroid Build Coastguard Worker   return false;
1077*f6dc9357SAndroid Build Coastguard Worker }
1078*f6dc9357SAndroid Build Coastguard Worker 
OnContextMenu(HANDLE windowHandle,int xPos,int yPos)1079*f6dc9357SAndroid Build Coastguard Worker bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos)
1080*f6dc9357SAndroid Build Coastguard Worker {
1081*f6dc9357SAndroid Build Coastguard Worker   if (::GetParent((HWND)windowHandle) == _listView)
1082*f6dc9357SAndroid Build Coastguard Worker   {
1083*f6dc9357SAndroid Build Coastguard Worker     ShowColumnsContextMenu(xPos, yPos);
1084*f6dc9357SAndroid Build Coastguard Worker     return true;
1085*f6dc9357SAndroid Build Coastguard Worker   }
1086*f6dc9357SAndroid Build Coastguard Worker 
1087*f6dc9357SAndroid Build Coastguard Worker   if (windowHandle != _listView)
1088*f6dc9357SAndroid Build Coastguard Worker     return false;
1089*f6dc9357SAndroid Build Coastguard Worker   /*
1090*f6dc9357SAndroid Build Coastguard Worker   POINT point;
1091*f6dc9357SAndroid Build Coastguard Worker   point.x = xPos;
1092*f6dc9357SAndroid Build Coastguard Worker   point.y = yPos;
1093*f6dc9357SAndroid Build Coastguard Worker   if (!_listView.ScreenToClient(&point))
1094*f6dc9357SAndroid Build Coastguard Worker     return false;
1095*f6dc9357SAndroid Build Coastguard Worker 
1096*f6dc9357SAndroid Build Coastguard Worker   LVHITTESTINFO info;
1097*f6dc9357SAndroid Build Coastguard Worker   info.pt = point;
1098*f6dc9357SAndroid Build Coastguard Worker   int index = _listView.HitTest(&info);
1099*f6dc9357SAndroid Build Coastguard Worker   */
1100*f6dc9357SAndroid Build Coastguard Worker 
1101*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> operatedIndices;
1102*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Operated(operatedIndices);
1103*f6dc9357SAndroid Build Coastguard Worker 
1104*f6dc9357SAndroid Build Coastguard Worker   // negative x,y are possible for multi-screen modes.
1105*f6dc9357SAndroid Build Coastguard Worker   // x=-1 && y=-1 for keyboard call (SHIFT+F10 and others).
1106*f6dc9357SAndroid Build Coastguard Worker   if (xPos == -1 && yPos == -1)
1107*f6dc9357SAndroid Build Coastguard Worker   {
1108*f6dc9357SAndroid Build Coastguard Worker     if (operatedIndices.Size() == 0)
1109*f6dc9357SAndroid Build Coastguard Worker     {
1110*f6dc9357SAndroid Build Coastguard Worker       xPos = 0;
1111*f6dc9357SAndroid Build Coastguard Worker       yPos = 0;
1112*f6dc9357SAndroid Build Coastguard Worker     }
1113*f6dc9357SAndroid Build Coastguard Worker     else
1114*f6dc9357SAndroid Build Coastguard Worker     {
1115*f6dc9357SAndroid Build Coastguard Worker       int itemIndex = _listView.GetNextItem(-1, LVNI_FOCUSED);
1116*f6dc9357SAndroid Build Coastguard Worker       if (itemIndex == -1)
1117*f6dc9357SAndroid Build Coastguard Worker         return false;
1118*f6dc9357SAndroid Build Coastguard Worker       RECT rect;
1119*f6dc9357SAndroid Build Coastguard Worker       if (!_listView.GetItemRect(itemIndex, &rect, LVIR_ICON))
1120*f6dc9357SAndroid Build Coastguard Worker         return false;
1121*f6dc9357SAndroid Build Coastguard Worker       xPos = (rect.left + rect.right) / 2;
1122*f6dc9357SAndroid Build Coastguard Worker       yPos = (rect.top + rect.bottom) / 2;
1123*f6dc9357SAndroid Build Coastguard Worker     }
1124*f6dc9357SAndroid Build Coastguard Worker     POINT point = {xPos, yPos};
1125*f6dc9357SAndroid Build Coastguard Worker     _listView.ClientToScreen(&point);
1126*f6dc9357SAndroid Build Coastguard Worker     xPos = point.x;
1127*f6dc9357SAndroid Build Coastguard Worker     yPos = point.y;
1128*f6dc9357SAndroid Build Coastguard Worker   }
1129*f6dc9357SAndroid Build Coastguard Worker 
1130*f6dc9357SAndroid Build Coastguard Worker   CMenu menu;
1131*f6dc9357SAndroid Build Coastguard Worker   CMenuDestroyer menuDestroyer(menu);
1132*f6dc9357SAndroid Build Coastguard Worker   menu.CreatePopup();
1133*f6dc9357SAndroid Build Coastguard Worker 
1134*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IContextMenu> sevenZipContextMenu;
1135*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IContextMenu> systemContextMenu;
1136*f6dc9357SAndroid Build Coastguard Worker   CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false); // programMenu
1137*f6dc9357SAndroid Build Coastguard Worker 
1138*f6dc9357SAndroid Build Coastguard Worker   const unsigned id = (unsigned)menu.Track(TPM_LEFTALIGN
1139*f6dc9357SAndroid Build Coastguard Worker       #ifndef UNDER_CE
1140*f6dc9357SAndroid Build Coastguard Worker       | TPM_RIGHTBUTTON
1141*f6dc9357SAndroid Build Coastguard Worker       #endif
1142*f6dc9357SAndroid Build Coastguard Worker       | TPM_RETURNCMD | TPM_NONOTIFY,
1143*f6dc9357SAndroid Build Coastguard Worker     xPos, yPos, _listView);
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker   if (id == 0)
1146*f6dc9357SAndroid Build Coastguard Worker     return true;
1147*f6dc9357SAndroid Build Coastguard Worker 
1148*f6dc9357SAndroid Build Coastguard Worker   if (id >= kMenuCmdID_Plugin_Start)
1149*f6dc9357SAndroid Build Coastguard Worker   {
1150*f6dc9357SAndroid Build Coastguard Worker     InvokePluginCommand(id, sevenZipContextMenu, systemContextMenu);
1151*f6dc9357SAndroid Build Coastguard Worker     return true;
1152*f6dc9357SAndroid Build Coastguard Worker   }
1153*f6dc9357SAndroid Build Coastguard Worker   if (ExecuteFileCommand(id))
1154*f6dc9357SAndroid Build Coastguard Worker     return true;
1155*f6dc9357SAndroid Build Coastguard Worker   return true;
1156*f6dc9357SAndroid Build Coastguard Worker }
1157