xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/PanelDrag.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // PanelDrag.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
6*f6dc9357SAndroid Build Coastguard Worker #include <winuserm.h>
7*f6dc9357SAndroid Build Coastguard Worker #endif
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zVersion.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/COM.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/MemoryGlobal.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/Menu.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/Shell.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ArchiveName.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../Common/CompressCall.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ExtractingFilePath.h"
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #include "MessagesDialog.h"
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker #include "App.h"
29*f6dc9357SAndroid Build Coastguard Worker #include "EnumFormatEtc.h"
30*f6dc9357SAndroid Build Coastguard Worker #include "FormatUtils.h"
31*f6dc9357SAndroid Build Coastguard Worker #include "LangUtils.h"
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker #include "resource.h"
34*f6dc9357SAndroid Build Coastguard Worker #include "../Explorer/resource.h"
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
37*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
38*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
41*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
42*f6dc9357SAndroid Build Coastguard Worker #endif
43*f6dc9357SAndroid Build Coastguard Worker 
44*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
45*f6dc9357SAndroid Build Coastguard Worker #define PRF_W(x)
46*f6dc9357SAndroid Build Coastguard Worker // #define PRF2(x)
47*f6dc9357SAndroid Build Coastguard Worker #define PRF3(x)
48*f6dc9357SAndroid Build Coastguard Worker #define PRF3_W(x)
49*f6dc9357SAndroid Build Coastguard Worker #define PRF4(x)
50*f6dc9357SAndroid Build Coastguard Worker // #define PRF4(x) OutputDebugStringA(x)
51*f6dc9357SAndroid Build Coastguard Worker // #define PRF4_W(x) OutputDebugStringW(x)
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_DRAG
54*f6dc9357SAndroid Build Coastguard Worker 
55*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_DRAG
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker #define PRF_(x) { x; }
58*f6dc9357SAndroid Build Coastguard Worker 
Print_Point(const char * name,DWORD keyState,const POINTL & pt,DWORD effect)59*f6dc9357SAndroid Build Coastguard Worker static void Print_Point(const char *name, DWORD keyState, const POINTL &pt, DWORD effect)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker   AString s (name);
62*f6dc9357SAndroid Build Coastguard Worker   s += " x=";  s.Add_UInt32((unsigned)pt.x);
63*f6dc9357SAndroid Build Coastguard Worker   s += " y=";  s.Add_UInt32((unsigned)pt.y);
64*f6dc9357SAndroid Build Coastguard Worker   s += " k=";  s.Add_UInt32(keyState);
65*f6dc9357SAndroid Build Coastguard Worker   s += " e=";  s.Add_UInt32(effect);
66*f6dc9357SAndroid Build Coastguard Worker   PRF4(s);
67*f6dc9357SAndroid Build Coastguard Worker }
68*f6dc9357SAndroid Build Coastguard Worker 
69*f6dc9357SAndroid Build Coastguard Worker #else
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker #define PRF_(x)
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker #endif
74*f6dc9357SAndroid Build Coastguard Worker 
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker #define kTempDirPrefix  FTEXT("7zE")
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker // all versions: k_Format_7zip_SetTargetFolder format to transfer folder path from target to source
79*f6dc9357SAndroid Build Coastguard Worker static LPCTSTR const k_Format_7zip_SetTargetFolder = TEXT("7-Zip::SetTargetFolder");
80*f6dc9357SAndroid Build Coastguard Worker // new v23 formats:
81*f6dc9357SAndroid Build Coastguard Worker static LPCTSTR const k_Format_7zip_SetTransfer = TEXT("7-Zip::SetTransfer");
82*f6dc9357SAndroid Build Coastguard Worker static LPCTSTR const k_Format_7zip_GetTransfer = TEXT("7-Zip::GetTransfer");
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker /*
85*f6dc9357SAndroid Build Coastguard Worker   Win10: clipboard formats.
86*f6dc9357SAndroid Build Coastguard Worker   There are about 16K free ids (formats) per system that can be
87*f6dc9357SAndroid Build Coastguard Worker   registered with RegisterClipboardFormat() with different names.
88*f6dc9357SAndroid Build Coastguard Worker   Probably that 16K ids space is common for ids registering for both
89*f6dc9357SAndroid Build Coastguard Worker   formats: RegisterClipboardFormat(), and registered window classes:
90*f6dc9357SAndroid Build Coastguard Worker   RegisterClass(). But ids for window classes will be deleted from
91*f6dc9357SAndroid Build Coastguard Worker   the list after process finishing. And registered clipboard
92*f6dc9357SAndroid Build Coastguard Worker   formats probably will be deleted from the list only after reboot.
93*f6dc9357SAndroid Build Coastguard Worker */
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker // static bool const g_CreateArchive_for_Drag_from_7zip = false;
96*f6dc9357SAndroid Build Coastguard Worker // static bool const g_CreateArchive_for_Drag_from_Explorer = true;
97*f6dc9357SAndroid Build Coastguard Worker     // = false; // for debug
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker /*
100*f6dc9357SAndroid Build Coastguard Worker How DoDragDrop() works:
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker   IDropSource::QueryContinueDrag()  (keyState & MK_LBUTTON) != 0
103*f6dc9357SAndroid Build Coastguard Worker   IDropTarget::Enter()
104*f6dc9357SAndroid Build Coastguard Worker     IDropSource::GiveFeedback()
105*f6dc9357SAndroid Build Coastguard Worker   IDropTarget::DragOver()
106*f6dc9357SAndroid Build Coastguard Worker     IDropSource::GiveFeedback()
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker   for()
109*f6dc9357SAndroid Build Coastguard Worker   {
110*f6dc9357SAndroid Build Coastguard Worker     IDropSource::QueryContinueDrag()  (keyState & MK_LBUTTON) != 0
111*f6dc9357SAndroid Build Coastguard Worker     IDropTarget::DragOver()           (keyState & MK_LBUTTON) != 0
112*f6dc9357SAndroid Build Coastguard Worker       IDropSource::GiveFeedback()
113*f6dc9357SAndroid Build Coastguard Worker   }
114*f6dc9357SAndroid Build Coastguard Worker 
115*f6dc9357SAndroid Build Coastguard Worker   {
116*f6dc9357SAndroid Build Coastguard Worker     // DoDragDrop() in Win10 before calling // QueryContinueDrag()
117*f6dc9357SAndroid Build Coastguard Worker     // with (*(keyState & MK_LBUTTON) == 0) probably calls:
118*f6dc9357SAndroid Build Coastguard Worker     //   1) IDropTarget::DragOver() with same point values (x,y), but (keyState & MK_LBUTTON) != 0)
119*f6dc9357SAndroid Build Coastguard Worker     //   2) IDropSource::GiveFeedback().
120*f6dc9357SAndroid Build Coastguard Worker     // so DropSource can know exact GiveFeedback(effect) mode just before LBUTTON releasing.
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker     if (IDropSource::QueryContinueDrag() for (keyState & MK_LBUTTON) == 0
123*f6dc9357SAndroid Build Coastguard Worker       returns DRAGDROP_S_DROP), it will call
124*f6dc9357SAndroid Build Coastguard Worker     IDropTarget::Drop()
125*f6dc9357SAndroid Build Coastguard Worker   }
126*f6dc9357SAndroid Build Coastguard Worker   or
127*f6dc9357SAndroid Build Coastguard Worker   {
128*f6dc9357SAndroid Build Coastguard Worker     IDropSource::QueryContinueDrag()
129*f6dc9357SAndroid Build Coastguard Worker     IDropTarget::DragLeave()
130*f6dc9357SAndroid Build Coastguard Worker     IDropSource::GiveFeedback(0)
131*f6dc9357SAndroid Build Coastguard Worker   }
132*f6dc9357SAndroid Build Coastguard Worker   or
133*f6dc9357SAndroid Build Coastguard Worker   {
134*f6dc9357SAndroid Build Coastguard Worker     if (IDropSource::QueryContinueDrag()
135*f6dc9357SAndroid Build Coastguard Worker       returns DRAGDROP_S_CANCEL)
136*f6dc9357SAndroid Build Coastguard Worker     IDropTarget::DragLeave()
137*f6dc9357SAndroid Build Coastguard Worker   }
138*f6dc9357SAndroid Build Coastguard Worker }
139*f6dc9357SAndroid Build Coastguard Worker */
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker // ---------- CDropTarget ----------
143*f6dc9357SAndroid Build Coastguard Worker 
144*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Struct_Id_SetTranfer = 2;  // it's our selected id
145*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Struct_Id_GetTranfer = 3;  // it's our selected id
146*f6dc9357SAndroid Build Coastguard Worker 
147*f6dc9357SAndroid Build Coastguard Worker static const UInt64 k_Program_Id = 1; // "7-Zip"
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker enum E_Program_ISA
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_x86   = 2,
152*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_x64   = 3,
153*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_armt  = 4,
154*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_arm64 = 5,
155*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_arm32 = 6,
156*f6dc9357SAndroid Build Coastguard Worker   k_Program_ISA_ia64  = 9
157*f6dc9357SAndroid Build Coastguard Worker };
158*f6dc9357SAndroid Build Coastguard Worker 
159*f6dc9357SAndroid Build Coastguard Worker #define k_Program_Ver ((MY_VER_MAJOR << 16) | MY_VER_MINOR)
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker // k_SourceFlags_* are flags that are sent from Source to Target
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_DoNotProcessInTarget = 1 << 1;
165*f6dc9357SAndroid Build Coastguard Worker /* Do not process in Target. Source will process operation instead of Target.
166*f6dc9357SAndroid Build Coastguard Worker    By default Target processes Drop opearation. */
167*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 k_SourceFlags_ProcessInTarget      = 1 << 2;
168*f6dc9357SAndroid Build Coastguard Worker 
169*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_DoNotWaitFinish   = 1 << 3;
170*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_WaitFinish        = 1 << 4;
171*f6dc9357SAndroid Build Coastguard Worker /* usually Source needs WaitFinish, if temp files were created. */
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_TempFiles         = 1 << 6;
174*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_NamesAreParent    = 1 << 7;
175*f6dc9357SAndroid Build Coastguard Worker /* if returned path list for GetData(CF_HDROP) contains
176*f6dc9357SAndroid Build Coastguard Worker    path of parent temp folder instead of final paths of items
177*f6dc9357SAndroid Build Coastguard Worker    that will be extracted later from archive */
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_SetTargetFolder   = 1 << 8;
180*f6dc9357SAndroid Build Coastguard Worker /* SetData::("SetTargetFolder") was called (with empty or non-empty string) */
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_SetTargetFolder_NonEmpty  = 1 << 9;
183*f6dc9357SAndroid Build Coastguard Worker /* SetData::("SetTargetFolder") was called with non-empty string */
184*f6dc9357SAndroid Build Coastguard Worker 
185*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_NeedExtractOpToFs = 1 << 10;
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_Copy_WasCalled = 1 << 11;
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_LeftButton        = 1 << 14;
190*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SourceFlags_RightButton       = 1 << 15;
191*f6dc9357SAndroid Build Coastguard Worker 
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_WasCanceled = 1 << 0;
194*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_MustBeProcessedBySource = 1 << 1;
195*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_WasProcessed    = 1 << 2;
196*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_DoNotWaitFinish = 1 << 3;
197*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_WaitFinish      = 1 << 4;
198*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TargetFlags_MenuWasShown    = 1 << 16;
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker struct CDataObject_TransferBase
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker   UInt32 Struct_Id;
203*f6dc9357SAndroid Build Coastguard Worker   UInt32 Struct_Size;
204*f6dc9357SAndroid Build Coastguard Worker 
205*f6dc9357SAndroid Build Coastguard Worker   UInt64 Program_Id;
206*f6dc9357SAndroid Build Coastguard Worker   UInt32 Program_Ver_Main;
207*f6dc9357SAndroid Build Coastguard Worker   UInt32 Program_Ver_Build;
208*f6dc9357SAndroid Build Coastguard Worker   UInt32 Program_ISA;
209*f6dc9357SAndroid Build Coastguard Worker   UInt32 Program_Flags;
210*f6dc9357SAndroid Build Coastguard Worker 
211*f6dc9357SAndroid Build Coastguard Worker   UInt32 ProcessId;
212*f6dc9357SAndroid Build Coastguard Worker   UInt32 _reserved1[7];
213*f6dc9357SAndroid Build Coastguard Worker 
214*f6dc9357SAndroid Build Coastguard Worker protected:
215*f6dc9357SAndroid Build Coastguard Worker   void Init_Program();
216*f6dc9357SAndroid Build Coastguard Worker };
217*f6dc9357SAndroid Build Coastguard Worker 
218*f6dc9357SAndroid Build Coastguard Worker 
Init_Program()219*f6dc9357SAndroid Build Coastguard Worker void CDataObject_TransferBase::Init_Program()
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker   Program_Id = k_Program_Id;
222*f6dc9357SAndroid Build Coastguard Worker   Program_ISA =
223*f6dc9357SAndroid Build Coastguard Worker     #if defined(MY_CPU_AMD64)
224*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_x64
225*f6dc9357SAndroid Build Coastguard Worker     #elif defined(MY_CPU_X86)
226*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_x86
227*f6dc9357SAndroid Build Coastguard Worker     #elif defined(MY_CPU_ARM64)
228*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_arm64
229*f6dc9357SAndroid Build Coastguard Worker     #elif defined(MY_CPU_ARM32)
230*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_arm32
231*f6dc9357SAndroid Build Coastguard Worker     #elif defined(MY_CPU_ARMT) || defined(MY_CPU_ARM)
232*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_armt
233*f6dc9357SAndroid Build Coastguard Worker     #elif defined(MY_CPU_IA64)
234*f6dc9357SAndroid Build Coastguard Worker       k_Program_ISA_ia64
235*f6dc9357SAndroid Build Coastguard Worker     #else
236*f6dc9357SAndroid Build Coastguard Worker       0
237*f6dc9357SAndroid Build Coastguard Worker     #endif
238*f6dc9357SAndroid Build Coastguard Worker       ;
239*f6dc9357SAndroid Build Coastguard Worker   Program_Flags = sizeof(size_t);
240*f6dc9357SAndroid Build Coastguard Worker   Program_Ver_Main = k_Program_Ver;
241*f6dc9357SAndroid Build Coastguard Worker   // Program_Ver_Build = 0;
242*f6dc9357SAndroid Build Coastguard Worker   ProcessId = GetCurrentProcessId();
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker 
246*f6dc9357SAndroid Build Coastguard Worker #if defined(__GNUC__) && !defined(__clang__)
247*f6dc9357SAndroid Build Coastguard Worker /* 'void* memset(void*, int, size_t)' clearing an object
248*f6dc9357SAndroid Build Coastguard Worker     of non-trivial type 'struct CDataObject_SetTransfer' */
249*f6dc9357SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wclass-memaccess"
250*f6dc9357SAndroid Build Coastguard Worker #endif
251*f6dc9357SAndroid Build Coastguard Worker 
252*f6dc9357SAndroid Build Coastguard Worker 
253*f6dc9357SAndroid Build Coastguard Worker struct CDataObject_GetTransfer:
254*f6dc9357SAndroid Build Coastguard Worker public CDataObject_TransferBase
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker   UInt32 Flags;
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker   UInt32 _reserved2[11];
259*f6dc9357SAndroid Build Coastguard Worker 
CDataObject_GetTransferCDataObject_GetTransfer260*f6dc9357SAndroid Build Coastguard Worker   CDataObject_GetTransfer()
261*f6dc9357SAndroid Build Coastguard Worker   {
262*f6dc9357SAndroid Build Coastguard Worker     memset(this, 0, sizeof(*this));
263*f6dc9357SAndroid Build Coastguard Worker     Init_Program();
264*f6dc9357SAndroid Build Coastguard Worker     Struct_Id = k_Struct_Id_GetTranfer;
265*f6dc9357SAndroid Build Coastguard Worker     Struct_Size = sizeof(*this);
266*f6dc9357SAndroid Build Coastguard Worker   }
267*f6dc9357SAndroid Build Coastguard Worker 
CheckCDataObject_GetTransfer268*f6dc9357SAndroid Build Coastguard Worker   bool Check() const
269*f6dc9357SAndroid Build Coastguard Worker   {
270*f6dc9357SAndroid Build Coastguard Worker     return Struct_Size >= sizeof(*this) && Struct_Id == k_Struct_Id_GetTranfer;
271*f6dc9357SAndroid Build Coastguard Worker   }
272*f6dc9357SAndroid Build Coastguard Worker };
273*f6dc9357SAndroid Build Coastguard Worker 
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker enum Enum_FolderType
276*f6dc9357SAndroid Build Coastguard Worker {
277*f6dc9357SAndroid Build Coastguard Worker   k_FolderType_None,
278*f6dc9357SAndroid Build Coastguard Worker   k_FolderType_Unknown = 1,
279*f6dc9357SAndroid Build Coastguard Worker   k_FolderType_Fs = 2,
280*f6dc9357SAndroid Build Coastguard Worker   k_FolderType_AltStreams = 3,
281*f6dc9357SAndroid Build Coastguard Worker   k_FolderType_Archive = 4
282*f6dc9357SAndroid Build Coastguard Worker };
283*f6dc9357SAndroid Build Coastguard Worker 
284*f6dc9357SAndroid Build Coastguard Worker struct CTargetTransferInfo
285*f6dc9357SAndroid Build Coastguard Worker {
286*f6dc9357SAndroid Build Coastguard Worker   UInt32 Flags;
287*f6dc9357SAndroid Build Coastguard Worker   UInt32 FuncType;
288*f6dc9357SAndroid Build Coastguard Worker 
289*f6dc9357SAndroid Build Coastguard Worker   UInt32 KeyState;
290*f6dc9357SAndroid Build Coastguard Worker   UInt32 OkEffects;
291*f6dc9357SAndroid Build Coastguard Worker   POINTL Point;
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker   UInt32 Cmd_Effect;
294*f6dc9357SAndroid Build Coastguard Worker   UInt32 Cmd_Type;
295*f6dc9357SAndroid Build Coastguard Worker   UInt32 FolderType;
296*f6dc9357SAndroid Build Coastguard Worker   UInt32 _reserved3[3];
297*f6dc9357SAndroid Build Coastguard Worker 
CTargetTransferInfoCTargetTransferInfo298*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo()
299*f6dc9357SAndroid Build Coastguard Worker   {
300*f6dc9357SAndroid Build Coastguard Worker     memset(this, 0, sizeof(*this));
301*f6dc9357SAndroid Build Coastguard Worker   }
302*f6dc9357SAndroid Build Coastguard Worker };
303*f6dc9357SAndroid Build Coastguard Worker 
304*f6dc9357SAndroid Build Coastguard Worker struct CDataObject_SetTransfer:
305*f6dc9357SAndroid Build Coastguard Worker public CDataObject_TransferBase
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo Target;
308*f6dc9357SAndroid Build Coastguard Worker 
InitCDataObject_SetTransfer309*f6dc9357SAndroid Build Coastguard Worker   void Init()
310*f6dc9357SAndroid Build Coastguard Worker   {
311*f6dc9357SAndroid Build Coastguard Worker     memset(this, 0, sizeof(*this));
312*f6dc9357SAndroid Build Coastguard Worker     Init_Program();
313*f6dc9357SAndroid Build Coastguard Worker     Struct_Id = k_Struct_Id_SetTranfer;
314*f6dc9357SAndroid Build Coastguard Worker     Struct_Size = sizeof(*this);
315*f6dc9357SAndroid Build Coastguard Worker   }
316*f6dc9357SAndroid Build Coastguard Worker 
CheckCDataObject_SetTransfer317*f6dc9357SAndroid Build Coastguard Worker   bool Check() const
318*f6dc9357SAndroid Build Coastguard Worker   {
319*f6dc9357SAndroid Build Coastguard Worker     return Struct_Size >= sizeof(*this) && Struct_Id == k_Struct_Id_SetTranfer;
320*f6dc9357SAndroid Build Coastguard Worker   }
321*f6dc9357SAndroid Build Coastguard Worker };
322*f6dc9357SAndroid Build Coastguard Worker 
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker 
325*f6dc9357SAndroid Build Coastguard Worker 
326*f6dc9357SAndroid Build Coastguard Worker 
327*f6dc9357SAndroid Build Coastguard Worker enum Enum_DragTargetMode
328*f6dc9357SAndroid Build Coastguard Worker {
329*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_None   = 0,
330*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_Leave  = 1,
331*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_Enter  = 2,
332*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_Over   = 3,
333*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_Drop_Begin = 4,
334*f6dc9357SAndroid Build Coastguard Worker   k_DragTargetMode_Drop_End   = 5
335*f6dc9357SAndroid Build Coastguard Worker };
336*f6dc9357SAndroid Build Coastguard Worker 
337*f6dc9357SAndroid Build Coastguard Worker 
338*f6dc9357SAndroid Build Coastguard Worker // ---- menu ----
339*f6dc9357SAndroid Build Coastguard Worker 
340*f6dc9357SAndroid Build Coastguard Worker namespace NDragMenu {
341*f6dc9357SAndroid Build Coastguard Worker 
342*f6dc9357SAndroid Build Coastguard Worker enum Enum_CmdId
343*f6dc9357SAndroid Build Coastguard Worker {
344*f6dc9357SAndroid Build Coastguard Worker   k_None          = 0,
345*f6dc9357SAndroid Build Coastguard Worker   k_Cancel        = 1,
346*f6dc9357SAndroid Build Coastguard Worker   k_Copy_Base     = 2, // to fs
347*f6dc9357SAndroid Build Coastguard Worker   k_Copy_ToArc    = 3,
348*f6dc9357SAndroid Build Coastguard Worker   k_AddToArc      = 4
349*f6dc9357SAndroid Build Coastguard Worker   /*
350*f6dc9357SAndroid Build Coastguard Worker   k_OpenArc       = 8,
351*f6dc9357SAndroid Build Coastguard Worker   k_TestArc       = 9,
352*f6dc9357SAndroid Build Coastguard Worker   k_ExtractFiles  = 10,
353*f6dc9357SAndroid Build Coastguard Worker   k_ExtractHere   = 11
354*f6dc9357SAndroid Build Coastguard Worker   */
355*f6dc9357SAndroid Build Coastguard Worker };
356*f6dc9357SAndroid Build Coastguard Worker 
357*f6dc9357SAndroid Build Coastguard Worker struct CCmdLangPair
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker   unsigned CmdId_and_Flags;
360*f6dc9357SAndroid Build Coastguard Worker   unsigned LangId;
361*f6dc9357SAndroid Build Coastguard Worker };
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_MenuFlags_CmdMask = (1 << 7) - 1;
364*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_MenuFlag_Copy = 1 << 14;
365*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_MenuFlag_Move = 1 << 15;
366*f6dc9357SAndroid Build Coastguard Worker // #define IDS_CANCEL (IDCANCEL + 400)
367*f6dc9357SAndroid Build Coastguard Worker #define IDS_CANCEL 402
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker static const CCmdLangPair g_Pairs[] =
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker   { k_Copy_Base  | k_MenuFlag_Copy,  IDS_COPY },
372*f6dc9357SAndroid Build Coastguard Worker   { k_Copy_Base  | k_MenuFlag_Move,  IDS_MOVE },
373*f6dc9357SAndroid Build Coastguard Worker   { k_Copy_ToArc | k_MenuFlag_Copy,  IDS_COPY_TO },
374*f6dc9357SAndroid Build Coastguard Worker   // { k_Copy_ToArc | k_MenuFlag_Move,  IDS_MOVE_TO }, // IDS_CONTEXT_COMPRESS_TO
375*f6dc9357SAndroid Build Coastguard Worker   // { k_OpenArc,      IDS_CONTEXT_OPEN },
376*f6dc9357SAndroid Build Coastguard Worker   // { k_ExtractFiles, IDS_CONTEXT_EXTRACT },
377*f6dc9357SAndroid Build Coastguard Worker   // { k_ExtractHere,  IDS_CONTEXT_EXTRACT_HERE },
378*f6dc9357SAndroid Build Coastguard Worker   // { k_TestArc,      IDS_CONTEXT_TEST },
379*f6dc9357SAndroid Build Coastguard Worker   { k_AddToArc   | k_MenuFlag_Copy,  IDS_CONTEXT_COMPRESS },
380*f6dc9357SAndroid Build Coastguard Worker   { k_Cancel, IDS_CANCEL }
381*f6dc9357SAndroid Build Coastguard Worker };
382*f6dc9357SAndroid Build Coastguard Worker 
383*f6dc9357SAndroid Build Coastguard Worker }
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker 
386*f6dc9357SAndroid Build Coastguard Worker class CDropTarget Z7_final:
387*f6dc9357SAndroid Build Coastguard Worker   public IDropTarget,
388*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
389*f6dc9357SAndroid Build Coastguard Worker {
390*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_1_MT(IDropTarget)
391*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(DragEnter)(IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect) Z7_override;
392*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(DragOver)(DWORD keyState, POINTL pt, DWORD *effect) Z7_override;
393*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(DragLeave)() Z7_override;
394*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(Drop)(IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect) Z7_override;
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker   bool m_IsRightButton;
397*f6dc9357SAndroid Build Coastguard Worker   bool m_GetTransfer_WasSuccess;
398*f6dc9357SAndroid Build Coastguard Worker   bool m_DropIsAllowed;      // = true, if data IDataObject can return CF_HDROP (so we can get list of paths)
399*f6dc9357SAndroid Build Coastguard Worker   bool m_PanelDropIsAllowed; // = false, if current target_panel is source_panel.
400*f6dc9357SAndroid Build Coastguard Worker                              // check it only if m_DropIsAllowed == true
401*f6dc9357SAndroid Build Coastguard Worker                              // we use it to show icon effect that drop is not allowed here.
402*f6dc9357SAndroid Build Coastguard Worker 
403*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IDataObject> m_DataObject; // we set it in DragEnter()
404*f6dc9357SAndroid Build Coastguard Worker   UStringVector m_SourcePaths;
405*f6dc9357SAndroid Build Coastguard Worker 
406*f6dc9357SAndroid Build Coastguard Worker   // int m_DropHighlighted_SelectionIndex;
407*f6dc9357SAndroid Build Coastguard Worker   // int m_SubFolderIndex;      // realIndex of item in m_Panel list (if drop cursor to that item)
408*f6dc9357SAndroid Build Coastguard Worker   // UString m_DropHighlighted_SubFolderName;   // name of folder in m_Panel list (if drop cursor to that folder)
409*f6dc9357SAndroid Build Coastguard Worker 
410*f6dc9357SAndroid Build Coastguard Worker   CPanel *m_Panel;
411*f6dc9357SAndroid Build Coastguard Worker   bool m_IsAppTarget;        // true, if we want to drop to app window (not to panel)
412*f6dc9357SAndroid Build Coastguard Worker 
413*f6dc9357SAndroid Build Coastguard Worker   bool m_TargetPath_WasSent_ToDataObject;           // true, if TargetPath was sent
414*f6dc9357SAndroid Build Coastguard Worker   bool m_TargetPath_NonEmpty_WasSent_ToDataObject;  // true, if non-empty TargetPath was sent
415*f6dc9357SAndroid Build Coastguard Worker   bool m_Transfer_WasSent_ToDataObject;  // true, if Transfer was sent
416*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_SetTargetFolder;
417*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_SetTransfer;
418*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_GetTransfer;
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker   UInt32 m_ProcessId; // for sending
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker   bool IsItSameDrive() const;
423*f6dc9357SAndroid Build Coastguard Worker 
424*f6dc9357SAndroid Build Coastguard Worker   // void Try_QueryGetData(IDataObject *dataObject);
425*f6dc9357SAndroid Build Coastguard Worker   void LoadNames_From_DataObject(IDataObject *dataObject);
426*f6dc9357SAndroid Build Coastguard Worker 
427*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetFolderType() const;
428*f6dc9357SAndroid Build Coastguard Worker   bool IsFsFolderPath() const;
429*f6dc9357SAndroid Build Coastguard Worker   DWORD GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect) const;
430*f6dc9357SAndroid Build Coastguard Worker   void RemoveSelection();
431*f6dc9357SAndroid Build Coastguard Worker   void PositionCursor(const POINTL &ptl);
432*f6dc9357SAndroid Build Coastguard Worker   UString GetTargetPath() const;
433*f6dc9357SAndroid Build Coastguard Worker   bool SendToSource_TargetPath_enable(IDataObject *dataObject, bool enablePath);
434*f6dc9357SAndroid Build Coastguard Worker   bool SendToSource_UInt32(IDataObject *dataObject, UINT format, UInt32 value);
435*f6dc9357SAndroid Build Coastguard Worker   bool SendToSource_TransferInfo(IDataObject *dataObject,
436*f6dc9357SAndroid Build Coastguard Worker       const CTargetTransferInfo &info);
437*f6dc9357SAndroid Build Coastguard Worker   void SendToSource_auto(IDataObject *dataObject,
438*f6dc9357SAndroid Build Coastguard Worker       const CTargetTransferInfo &info);
SendToSource_Drag(CTargetTransferInfo & info)439*f6dc9357SAndroid Build Coastguard Worker   void SendToSource_Drag(CTargetTransferInfo &info)
440*f6dc9357SAndroid Build Coastguard Worker   {
441*f6dc9357SAndroid Build Coastguard Worker     SendToSource_auto(m_DataObject, info);
442*f6dc9357SAndroid Build Coastguard Worker   }
443*f6dc9357SAndroid Build Coastguard Worker 
444*f6dc9357SAndroid Build Coastguard Worker   void ClearState();
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker public:
447*f6dc9357SAndroid Build Coastguard Worker   CDropTarget();
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker   CApp *App;
450*f6dc9357SAndroid Build Coastguard Worker   int SrcPanelIndex;     // index of D&D source_panel
451*f6dc9357SAndroid Build Coastguard Worker   int TargetPanelIndex;  // what panel to use as target_panel of Application
452*f6dc9357SAndroid Build Coastguard Worker };
453*f6dc9357SAndroid Build Coastguard Worker 
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker 
457*f6dc9357SAndroid Build Coastguard Worker // ---------- CDataObject ----------
458*f6dc9357SAndroid Build Coastguard Worker 
459*f6dc9357SAndroid Build Coastguard Worker /*
460*f6dc9357SAndroid Build Coastguard Worker   Some programs (like Sticky Notes in Win10) do not like
461*f6dc9357SAndroid Build Coastguard Worker   virtual non-existing items (files/dirs) in CF_HDROP format.
462*f6dc9357SAndroid Build Coastguard Worker   So we use two versions of CF_HDROP data:
463*f6dc9357SAndroid Build Coastguard Worker     m_hGlobal_HDROP_Pre   : the list contains only destination path of temp directory.
464*f6dc9357SAndroid Build Coastguard Worker         That directory later will be filled with extracted items.
465*f6dc9357SAndroid Build Coastguard Worker     m_hGlobal_HDROP_Final : the list contains paths of all root items that
466*f6dc9357SAndroid Build Coastguard Worker         will be created in temp directory by archive extraction operation,
467*f6dc9357SAndroid Build Coastguard Worker         or the list of existing fs items, if source is filesystem directory.
468*f6dc9357SAndroid Build Coastguard Worker 
469*f6dc9357SAndroid Build Coastguard Worker   The DRAWBACK: some programs (like Edge in Win10) can use names from IDataObject::GetData()
470*f6dc9357SAndroid Build Coastguard Worker   call that was called before IDropSource::QueryContinueDrag() where we set (UseFinalGlobal = true)
471*f6dc9357SAndroid Build Coastguard Worker   So such programs will use non-relevant m_hGlobal_HDROP_Pre item,
472*f6dc9357SAndroid Build Coastguard Worker   instead of m_hGlobal_HDROP_Final items.
473*f6dc9357SAndroid Build Coastguard Worker */
474*f6dc9357SAndroid Build Coastguard Worker 
475*f6dc9357SAndroid Build Coastguard Worker class CDataObject Z7_final:
476*f6dc9357SAndroid Build Coastguard Worker   public IDataObject,
477*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
478*f6dc9357SAndroid Build Coastguard Worker {
479*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_1_MT(IDataObject)
480*f6dc9357SAndroid Build Coastguard Worker 
481*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM medium) Z7_override;
482*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM medium) Z7_override;
483*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B QueryGetData(LPFORMATETC pformatetc) Z7_override;
484*f6dc9357SAndroid Build Coastguard Worker 
GetCanonicalFormatEtc(LPFORMATETC,LPFORMATETC pformatetcOut)485*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B GetCanonicalFormatEtc(LPFORMATETC /* pformatetc */, LPFORMATETC pformatetcOut) Z7_override
486*f6dc9357SAndroid Build Coastguard Worker   {
487*f6dc9357SAndroid Build Coastguard Worker     if (!pformatetcOut)
488*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
489*f6dc9357SAndroid Build Coastguard Worker     pformatetcOut->ptd = NULL;
490*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
491*f6dc9357SAndroid Build Coastguard Worker   }
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release) Z7_override;
494*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B EnumFormatEtc(DWORD drection, LPENUMFORMATETC *enumFormatEtc) Z7_override;
495*f6dc9357SAndroid Build Coastguard Worker 
DAdvise(FORMATETC *,DWORD,LPADVISESINK,DWORD *)496*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B DAdvise(FORMATETC * /* etc */, DWORD /* advf */, LPADVISESINK /* pAdvSink */, DWORD * /* pdwConnection */) Z7_override
497*f6dc9357SAndroid Build Coastguard Worker     { return OLE_E_ADVISENOTSUPPORTED; }
DUnadvise(DWORD)498*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B DUnadvise(DWORD /* dwConnection */) Z7_override
499*f6dc9357SAndroid Build Coastguard Worker     { return OLE_E_ADVISENOTSUPPORTED; }
EnumDAdvise(LPENUMSTATDATA * ppenumAdvise)500*f6dc9357SAndroid Build Coastguard Worker   Z7_COMWF_B EnumDAdvise(LPENUMSTATDATA *ppenumAdvise) Z7_override
501*f6dc9357SAndroid Build Coastguard Worker   {
502*f6dc9357SAndroid Build Coastguard Worker     if (ppenumAdvise)
503*f6dc9357SAndroid Build Coastguard Worker       *ppenumAdvise = NULL;
504*f6dc9357SAndroid Build Coastguard Worker     return OLE_E_ADVISENOTSUPPORTED;
505*f6dc9357SAndroid Build Coastguard Worker   }
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker   bool m_PerformedDropEffect_WasSet;
508*f6dc9357SAndroid Build Coastguard Worker   bool m_LogicalPerformedDropEffect_WasSet;
509*f6dc9357SAndroid Build Coastguard Worker   bool m_DestDirPrefix_FromTarget_WasSet;
510*f6dc9357SAndroid Build Coastguard Worker public:
511*f6dc9357SAndroid Build Coastguard Worker   bool m_Transfer_WasSet;
512*f6dc9357SAndroid Build Coastguard Worker private:
513*f6dc9357SAndroid Build Coastguard Worker   // GetData formats (source to target):
514*f6dc9357SAndroid Build Coastguard Worker   FORMATETC m_Etc;
515*f6dc9357SAndroid Build Coastguard Worker   // UINT m_Format_FileOpFlags;
516*f6dc9357SAndroid Build Coastguard Worker   // UINT m_Format_PreferredDropEffect;
517*f6dc9357SAndroid Build Coastguard Worker 
518*f6dc9357SAndroid Build Coastguard Worker   // SetData() formats (target to source):
519*f6dc9357SAndroid Build Coastguard Worker   // 7-Zip's format:
520*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_SetTargetFolder;
521*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_SetTransfer;
522*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_7zip_GetTransfer; // for GetData()
523*f6dc9357SAndroid Build Coastguard Worker 
524*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_PerformedDropEffect;
525*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_LogicalPerformedDropEffect;
526*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_DisableDragText;
527*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_IsShowingLayered;
528*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_IsShowingText;
529*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_DropDescription;
530*f6dc9357SAndroid Build Coastguard Worker   UINT m_Format_TargetCLSID;
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker   DWORD m_PerformedDropEffect;
533*f6dc9357SAndroid Build Coastguard Worker   DWORD m_LogicalPerformedDropEffect;
534*f6dc9357SAndroid Build Coastguard Worker 
535*f6dc9357SAndroid Build Coastguard Worker   void CopyFromPanelTo_Folder();
536*f6dc9357SAndroid Build Coastguard Worker   HRESULT SetData2(const FORMATETC *formatetc, const STGMEDIUM *medium);
537*f6dc9357SAndroid Build Coastguard Worker 
538*f6dc9357SAndroid Build Coastguard Worker public:
539*f6dc9357SAndroid Build Coastguard Worker   bool IsRightButton;
540*f6dc9357SAndroid Build Coastguard Worker   bool IsTempFiles;
541*f6dc9357SAndroid Build Coastguard Worker 
542*f6dc9357SAndroid Build Coastguard Worker   bool UsePreGlobal;
543*f6dc9357SAndroid Build Coastguard Worker   bool DoNotProcessInTarget;
544*f6dc9357SAndroid Build Coastguard Worker 
545*f6dc9357SAndroid Build Coastguard Worker   bool NeedCall_Copy;
546*f6dc9357SAndroid Build Coastguard Worker   bool Copy_WasCalled;
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker   NMemory::CGlobal m_hGlobal_HDROP_Pre;
549*f6dc9357SAndroid Build Coastguard Worker   NMemory::CGlobal m_hGlobal_HDROP_Final;
550*f6dc9357SAndroid Build Coastguard Worker   // NMemory::CGlobal m_hGlobal_FileOpFlags;
551*f6dc9357SAndroid Build Coastguard Worker   // NMemory::CGlobal m_hGlobal_PreferredDropEffect;
552*f6dc9357SAndroid Build Coastguard Worker 
553*f6dc9357SAndroid Build Coastguard Worker   CPanel *Panel;
554*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> Indices;
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker   UString SrcDirPrefix_Temp; // FS directory with source files or Temp
557*f6dc9357SAndroid Build Coastguard Worker   UString DestDirPrefix_FromTarget;
558*f6dc9357SAndroid Build Coastguard Worker   /* destination Path that was sent by Target via SetData().
559*f6dc9357SAndroid Build Coastguard Worker      it can be altstreams prefix.
560*f6dc9357SAndroid Build Coastguard Worker      if (!DestDirPrefix_FromTarget.IsEmpty()) m_Panel->CompressDropFiles() was not called by Target.
561*f6dc9357SAndroid Build Coastguard Worker      So we must do drop actions in Source */
562*f6dc9357SAndroid Build Coastguard Worker   HRESULT Copy_HRESULT;
563*f6dc9357SAndroid Build Coastguard Worker   UStringVector Messages;
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker   CDataObject();
566*f6dc9357SAndroid Build Coastguard Worker public:
567*f6dc9357SAndroid Build Coastguard Worker   CDataObject_SetTransfer m_Transfer;
568*f6dc9357SAndroid Build Coastguard Worker };
569*f6dc9357SAndroid Build Coastguard Worker 
570*f6dc9357SAndroid Build Coastguard Worker 
571*f6dc9357SAndroid Build Coastguard Worker // for old mingw:
572*f6dc9357SAndroid Build Coastguard Worker #ifndef CFSTR_LOGICALPERFORMEDDROPEFFECT
573*f6dc9357SAndroid Build Coastguard Worker #define CFSTR_LOGICALPERFORMEDDROPEFFECT    TEXT("Logical Performed DropEffect")
574*f6dc9357SAndroid Build Coastguard Worker #endif
575*f6dc9357SAndroid Build Coastguard Worker #ifndef CFSTR_TARGETCLSID
576*f6dc9357SAndroid Build Coastguard Worker #define CFSTR_TARGETCLSID                   TEXT("TargetCLSID")                         // HGLOBAL with a CLSID of the drop target
577*f6dc9357SAndroid Build Coastguard Worker #endif
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker 
CDataObject()581*f6dc9357SAndroid Build Coastguard Worker CDataObject::CDataObject()
582*f6dc9357SAndroid Build Coastguard Worker {
583*f6dc9357SAndroid Build Coastguard Worker   // GetData formats (source to target):
584*f6dc9357SAndroid Build Coastguard Worker   // and we use CF_HDROP format to transfer file paths from source to target:
585*f6dc9357SAndroid Build Coastguard Worker   m_Etc.cfFormat = CF_HDROP;
586*f6dc9357SAndroid Build Coastguard Worker   m_Etc.ptd = NULL;
587*f6dc9357SAndroid Build Coastguard Worker   m_Etc.dwAspect = DVASPECT_CONTENT;
588*f6dc9357SAndroid Build Coastguard Worker   m_Etc.lindex = -1;
589*f6dc9357SAndroid Build Coastguard Worker   m_Etc.tymed = TYMED_HGLOBAL;
590*f6dc9357SAndroid Build Coastguard Worker 
591*f6dc9357SAndroid Build Coastguard Worker   // m_Format_FileOpFlags          = RegisterClipboardFormat(TEXT("FileOpFlags"));
592*f6dc9357SAndroid Build Coastguard Worker   // m_Format_PreferredDropEffect  = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); // "Preferred DropEffect"
593*f6dc9357SAndroid Build Coastguard Worker 
594*f6dc9357SAndroid Build Coastguard Worker   // SetData() formats (target to source):
595*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_SetTargetFolder = RegisterClipboardFormat(k_Format_7zip_SetTargetFolder);
596*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_SetTransfer     = RegisterClipboardFormat(k_Format_7zip_SetTransfer);
597*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_GetTransfer     = RegisterClipboardFormat(k_Format_7zip_GetTransfer);
598*f6dc9357SAndroid Build Coastguard Worker 
599*f6dc9357SAndroid Build Coastguard Worker   m_Format_PerformedDropEffect  = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); // "Performed DropEffect"
600*f6dc9357SAndroid Build Coastguard Worker   m_Format_LogicalPerformedDropEffect = RegisterClipboardFormat(CFSTR_LOGICALPERFORMEDDROPEFFECT); // "Logical Performed DropEffect"
601*f6dc9357SAndroid Build Coastguard Worker   m_Format_DisableDragText      = RegisterClipboardFormat(TEXT("DisableDragText"));
602*f6dc9357SAndroid Build Coastguard Worker   m_Format_IsShowingLayered     = RegisterClipboardFormat(TEXT("IsShowingLayered"));
603*f6dc9357SAndroid Build Coastguard Worker   m_Format_IsShowingText        = RegisterClipboardFormat(TEXT("IsShowingText"));
604*f6dc9357SAndroid Build Coastguard Worker   m_Format_DropDescription      = RegisterClipboardFormat(TEXT("DropDescription"));
605*f6dc9357SAndroid Build Coastguard Worker   m_Format_TargetCLSID          = RegisterClipboardFormat(CFSTR_TARGETCLSID);
606*f6dc9357SAndroid Build Coastguard Worker 
607*f6dc9357SAndroid Build Coastguard Worker   m_PerformedDropEffect = 0;
608*f6dc9357SAndroid Build Coastguard Worker   m_LogicalPerformedDropEffect = 0;
609*f6dc9357SAndroid Build Coastguard Worker 
610*f6dc9357SAndroid Build Coastguard Worker   m_PerformedDropEffect_WasSet = false;
611*f6dc9357SAndroid Build Coastguard Worker   m_LogicalPerformedDropEffect_WasSet = false;
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker   m_DestDirPrefix_FromTarget_WasSet = false;
614*f6dc9357SAndroid Build Coastguard Worker   m_Transfer_WasSet = false;
615*f6dc9357SAndroid Build Coastguard Worker 
616*f6dc9357SAndroid Build Coastguard Worker   IsRightButton = false;
617*f6dc9357SAndroid Build Coastguard Worker   IsTempFiles = false;
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker   UsePreGlobal = false;
620*f6dc9357SAndroid Build Coastguard Worker   DoNotProcessInTarget = false;
621*f6dc9357SAndroid Build Coastguard Worker 
622*f6dc9357SAndroid Build Coastguard Worker   NeedCall_Copy = false;
623*f6dc9357SAndroid Build Coastguard Worker   Copy_WasCalled = false;
624*f6dc9357SAndroid Build Coastguard Worker 
625*f6dc9357SAndroid Build Coastguard Worker   Copy_HRESULT = S_OK;
626*f6dc9357SAndroid Build Coastguard Worker }
627*f6dc9357SAndroid Build Coastguard Worker 
628*f6dc9357SAndroid Build Coastguard Worker 
629*f6dc9357SAndroid Build Coastguard Worker 
CopyFromPanelTo_Folder()630*f6dc9357SAndroid Build Coastguard Worker void CDataObject::CopyFromPanelTo_Folder()
631*f6dc9357SAndroid Build Coastguard Worker {
632*f6dc9357SAndroid Build Coastguard Worker   try
633*f6dc9357SAndroid Build Coastguard Worker   {
634*f6dc9357SAndroid Build Coastguard Worker     CCopyToOptions options;
635*f6dc9357SAndroid Build Coastguard Worker     options.folder = SrcDirPrefix_Temp;
636*f6dc9357SAndroid Build Coastguard Worker     /* 15.13: fixed problem with mouse cursor for password window.
637*f6dc9357SAndroid Build Coastguard Worker        DoDragDrop() probably calls SetCapture() to some hidden window.
638*f6dc9357SAndroid Build Coastguard Worker        But it's problem, if we show some modal window, like MessageBox.
639*f6dc9357SAndroid Build Coastguard Worker        So we return capture to our window.
640*f6dc9357SAndroid Build Coastguard Worker        If you know better way to solve the problem, please notify 7-Zip developer.
641*f6dc9357SAndroid Build Coastguard Worker     */
642*f6dc9357SAndroid Build Coastguard Worker     // MessageBoxW(*Panel, L"test", L"test", 0);
643*f6dc9357SAndroid Build Coastguard Worker     /* HWND oldHwnd = */ SetCapture(*Panel);
644*f6dc9357SAndroid Build Coastguard Worker     Copy_WasCalled = true;
645*f6dc9357SAndroid Build Coastguard Worker     Copy_HRESULT = E_FAIL;
646*f6dc9357SAndroid Build Coastguard Worker     Copy_HRESULT = Panel->CopyTo(options, Indices, &Messages);
647*f6dc9357SAndroid Build Coastguard Worker     // do we need to restore capture?
648*f6dc9357SAndroid Build Coastguard Worker     // ReleaseCapture();
649*f6dc9357SAndroid Build Coastguard Worker     // oldHwnd = SetCapture(oldHwnd);
650*f6dc9357SAndroid Build Coastguard Worker   }
651*f6dc9357SAndroid Build Coastguard Worker   catch(...)
652*f6dc9357SAndroid Build Coastguard Worker   {
653*f6dc9357SAndroid Build Coastguard Worker     Copy_HRESULT = E_FAIL;
654*f6dc9357SAndroid Build Coastguard Worker   }
655*f6dc9357SAndroid Build Coastguard Worker }
656*f6dc9357SAndroid Build Coastguard Worker 
657*f6dc9357SAndroid Build Coastguard Worker 
658*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_DRAG
659*f6dc9357SAndroid Build Coastguard Worker 
PrintFormat2(AString & s,unsigned format)660*f6dc9357SAndroid Build Coastguard Worker static void PrintFormat2(AString &s, unsigned format)
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker   s += " ";
663*f6dc9357SAndroid Build Coastguard Worker   s += "= format=";
664*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(format);
665*f6dc9357SAndroid Build Coastguard Worker   s += " ";
666*f6dc9357SAndroid Build Coastguard Worker   const int k_len = 512;
667*f6dc9357SAndroid Build Coastguard Worker   CHAR temp[k_len];
668*f6dc9357SAndroid Build Coastguard Worker   if (GetClipboardFormatNameA(format, temp, k_len) && strlen(temp) != 0)
669*f6dc9357SAndroid Build Coastguard Worker     s += temp;
670*f6dc9357SAndroid Build Coastguard Worker }
671*f6dc9357SAndroid Build Coastguard Worker 
PrintFormat(const char * title,unsigned format)672*f6dc9357SAndroid Build Coastguard Worker static void PrintFormat(const char *title, unsigned format)
673*f6dc9357SAndroid Build Coastguard Worker {
674*f6dc9357SAndroid Build Coastguard Worker   AString s (title);
675*f6dc9357SAndroid Build Coastguard Worker   PrintFormat2(s, format);
676*f6dc9357SAndroid Build Coastguard Worker   PRF4(s);
677*f6dc9357SAndroid Build Coastguard Worker }
678*f6dc9357SAndroid Build Coastguard Worker 
PrintFormat_AndData(const char * title,unsigned format,const void * data,size_t size)679*f6dc9357SAndroid Build Coastguard Worker static void PrintFormat_AndData(const char *title, unsigned format, const void *data, size_t size)
680*f6dc9357SAndroid Build Coastguard Worker {
681*f6dc9357SAndroid Build Coastguard Worker   AString s (title);
682*f6dc9357SAndroid Build Coastguard Worker   PrintFormat2(s, format);
683*f6dc9357SAndroid Build Coastguard Worker   s += " size=";
684*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32((UInt32)size);
685*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < size && i < 16; i++)
686*f6dc9357SAndroid Build Coastguard Worker   {
687*f6dc9357SAndroid Build Coastguard Worker     s += " ";
688*f6dc9357SAndroid Build Coastguard Worker     s.Add_UInt32(((const Byte *)data)[i]);
689*f6dc9357SAndroid Build Coastguard Worker   }
690*f6dc9357SAndroid Build Coastguard Worker   PRF4(s);
691*f6dc9357SAndroid Build Coastguard Worker }
692*f6dc9357SAndroid Build Coastguard Worker 
PrintFormat_GUIDToStringW(const void * p)693*f6dc9357SAndroid Build Coastguard Worker static void PrintFormat_GUIDToStringW(const void *p)
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker   const GUID *guid = (const GUID *)p;
696*f6dc9357SAndroid Build Coastguard Worker   UString s;
697*f6dc9357SAndroid Build Coastguard Worker   const unsigned kSize = 48;
698*f6dc9357SAndroid Build Coastguard Worker   StringFromGUID2(*guid, s.GetBuf(kSize), kSize);
699*f6dc9357SAndroid Build Coastguard Worker   s.ReleaseBuf_CalcLen(kSize);
700*f6dc9357SAndroid Build Coastguard Worker   PRF3_W(s);
701*f6dc9357SAndroid Build Coastguard Worker }
702*f6dc9357SAndroid Build Coastguard Worker 
703*f6dc9357SAndroid Build Coastguard Worker // Vista
704*f6dc9357SAndroid Build Coastguard Worker typedef enum
705*f6dc9357SAndroid Build Coastguard Worker {
706*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_INVALID  = -1,                // no image preference (use default)
707*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_NONE     = 0,                 // red "no" circle
708*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_COPY     = DROPEFFECT_COPY,   // plus for copy
709*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_MOVE     = DROPEFFECT_MOVE,   // movement arrow for move
710*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_LINK     = DROPEFFECT_LINK,   // link arrow for link
711*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_LABEL    = 6,                 // tag icon to indicate metadata will be changed
712*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_WARNING  = 7,                 // yellow exclamation, something is amiss with the operation
713*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGE_NOIMAGE  = 8                  // no image at all
714*f6dc9357SAndroid Build Coastguard Worker } MY_DROPIMAGETYPE;
715*f6dc9357SAndroid Build Coastguard Worker 
716*f6dc9357SAndroid Build Coastguard Worker typedef struct {
717*f6dc9357SAndroid Build Coastguard Worker   MY_DROPIMAGETYPE type;
718*f6dc9357SAndroid Build Coastguard Worker   WCHAR szMessage[MAX_PATH];
719*f6dc9357SAndroid Build Coastguard Worker   WCHAR szInsert[MAX_PATH];
720*f6dc9357SAndroid Build Coastguard Worker } MY_DROPDESCRIPTION;
721*f6dc9357SAndroid Build Coastguard Worker 
722*f6dc9357SAndroid Build Coastguard Worker #endif
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker 
725*f6dc9357SAndroid Build Coastguard Worker /*
726*f6dc9357SAndroid Build Coastguard Worker IDataObject::SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release)
727*f6dc9357SAndroid Build Coastguard Worker ======================================================================
728*f6dc9357SAndroid Build Coastguard Worker 
729*f6dc9357SAndroid Build Coastguard Worker   Main purpose of CDataObject is to transfer data from source to target
730*f6dc9357SAndroid Build Coastguard Worker   of drag and drop operation.
731*f6dc9357SAndroid Build Coastguard Worker   But also CDataObject can be used to transfer data in backward direction
732*f6dc9357SAndroid Build Coastguard Worker   from target to source (even if target and source are different processes).
733*f6dc9357SAndroid Build Coastguard Worker   There are some predefined Explorer's formats to transfer some data from target to source.
734*f6dc9357SAndroid Build Coastguard Worker   And 7-Zip uses 7-Zip's format k_Format_7zip_SetTargetFolder to transfer
735*f6dc9357SAndroid Build Coastguard Worker   destination directory path from target to source.
736*f6dc9357SAndroid Build Coastguard Worker 
737*f6dc9357SAndroid Build Coastguard Worker   Our CDataObject::SetData() function here is used only to transfer data from target to source.
738*f6dc9357SAndroid Build Coastguard Worker   Usual source_to_target data is filled to m_hGlobal_* objects directly without SetData() calling.
739*f6dc9357SAndroid Build Coastguard Worker 
740*f6dc9357SAndroid Build Coastguard Worker The main problem of SetData() is ownership of medium for (release == TRUE) case.
741*f6dc9357SAndroid Build Coastguard Worker 
742*f6dc9357SAndroid Build Coastguard Worker SetData(,, release = TRUE) from different processes (DropSource and DropTarget)
743*f6dc9357SAndroid Build Coastguard Worker ===============================================================================
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker   MS DOCs about (STGMEDIUM *medium) ownership:
746*f6dc9357SAndroid Build Coastguard Worker     The data object called does not take ownership of the data
747*f6dc9357SAndroid Build Coastguard Worker     until it has successfully received it and no error code is returned.
748*f6dc9357SAndroid Build Coastguard Worker 
749*f6dc9357SAndroid Build Coastguard Worker   Each of processes (Source and Target) has own copy of medium allocated.
750*f6dc9357SAndroid Build Coastguard Worker   Windows code creates proxy IDataObject object in Target process to transferr
751*f6dc9357SAndroid Build Coastguard Worker   SetData() call between Target and Source processes via special proxies:
752*f6dc9357SAndroid Build Coastguard Worker     DropTarget ->
753*f6dc9357SAndroid Build Coastguard Worker     proxy_DataObject_in_Target ->
754*f6dc9357SAndroid Build Coastguard Worker     proxy_in_Source ->
755*f6dc9357SAndroid Build Coastguard Worker     DataObject_in_Source
756*f6dc9357SAndroid Build Coastguard Worker   when Target calls SetData() with proxy_DataObject_in_Target,
757*f6dc9357SAndroid Build Coastguard Worker   the system and proxy_in_Source
758*f6dc9357SAndroid Build Coastguard Worker    - allocates proxy-medium-in-Source process
759*f6dc9357SAndroid Build Coastguard Worker    - copies medium data from Target to that proxy-medium-in-Source
760*f6dc9357SAndroid Build Coastguard Worker    - sends proxy-medium-in-Source to DataObject_in_Source->SetData().
761*f6dc9357SAndroid Build Coastguard Worker 
762*f6dc9357SAndroid Build Coastguard Worker   after returning from SetData() to Target process:
763*f6dc9357SAndroid Build Coastguard Worker     Win10 proxy_DataObject_in_Target releases original medium in Target process,
764*f6dc9357SAndroid Build Coastguard Worker     only if SetData() in Source returns S_OK. It's consistent with DOCs above.
765*f6dc9357SAndroid Build Coastguard Worker 
766*f6dc9357SAndroid Build Coastguard Worker   for unsupported cfFormat:
767*f6dc9357SAndroid Build Coastguard Worker   [DropSource is 7-Zip 22.01 (old) : (etc->cfFormat != m_Format_7zip_SetTargetFolder && release == TRUE)]
768*f6dc9357SAndroid Build Coastguard Worker   (DropSource is WinRAR case):
769*f6dc9357SAndroid Build Coastguard Worker   Source doesn't release medium and returns error (for example, E_NOTIMPL)
770*f6dc9357SAndroid Build Coastguard Worker   {
771*f6dc9357SAndroid Build Coastguard Worker     Then Win10 proxy_in_Source also doesn't release proxy-medium-in-Source.
772*f6dc9357SAndroid Build Coastguard Worker     So there is memory leak in Source process.
773*f6dc9357SAndroid Build Coastguard Worker     Probably Win10 proxy_in_Source tries to avoid possible double releasing
774*f6dc9357SAndroid Build Coastguard Worker     that can be more fatal than memory leak.
775*f6dc9357SAndroid Build Coastguard Worker 
776*f6dc9357SAndroid Build Coastguard Worker     Then Win10 proxy_DataObject_in_Target also doesn't release
777*f6dc9357SAndroid Build Coastguard Worker     original medium, that was allocated by DropTarget.
778*f6dc9357SAndroid Build Coastguard Worker     So if DropTarget also doesn't release medium, there is memory leak in
779*f6dc9357SAndroid Build Coastguard Worker     DropTarget process too.
780*f6dc9357SAndroid Build Coastguard Worker     DropTarget is Win10-Explorer probably doesn't release medium in that case.
781*f6dc9357SAndroid Build Coastguard Worker   }
782*f6dc9357SAndroid Build Coastguard Worker 
783*f6dc9357SAndroid Build Coastguard Worker   [DropSource is 7-Zip 22.01 (old) : (etc->cfFormat == m_Format_7zip_SetTargetFolder && release == TRUE)]
784*f6dc9357SAndroid Build Coastguard Worker   DropSource returns S_OK and doesn't release medium:
785*f6dc9357SAndroid Build Coastguard Worker   {
786*f6dc9357SAndroid Build Coastguard Worker     then there is memory leak in DropSource process only.
787*f6dc9357SAndroid Build Coastguard Worker   }
788*f6dc9357SAndroid Build Coastguard Worker 
789*f6dc9357SAndroid Build Coastguard Worker   (DropSource is 7-Zip v23 (new)):
790*f6dc9357SAndroid Build Coastguard Worker   (DropSource is Win10-Explorer case)
791*f6dc9357SAndroid Build Coastguard Worker   {
792*f6dc9357SAndroid Build Coastguard Worker     Win10-Explorer-DropSource probably always releases medium,
793*f6dc9357SAndroid Build Coastguard Worker     and then it always returns S_OK.
794*f6dc9357SAndroid Build Coastguard Worker     So Win10 proxy_DataObject_in_Target also releases
795*f6dc9357SAndroid Build Coastguard Worker     original medium, that was allocated by DropTarget.
796*f6dc9357SAndroid Build Coastguard Worker     So there is no memory leak in Source and Target processes.
797*f6dc9357SAndroid Build Coastguard Worker   }
798*f6dc9357SAndroid Build Coastguard Worker 
799*f6dc9357SAndroid Build Coastguard Worker   if (DropTarget is Win10-Explorer)
800*f6dc9357SAndroid Build Coastguard Worker   {
801*f6dc9357SAndroid Build Coastguard Worker     Explorer Target uses SetData(,, (release = TRUE)) and
802*f6dc9357SAndroid Build Coastguard Worker     Explorer Target probably doesn't free memory after SetData(),
803*f6dc9357SAndroid Build Coastguard Worker       even if SetData(,, (release = TRUE)) returns E_NOTIMPL;
804*f6dc9357SAndroid Build Coastguard Worker   }
805*f6dc9357SAndroid Build Coastguard Worker 
806*f6dc9357SAndroid Build Coastguard Worker   if (DropSource is Win10-Explorer)
807*f6dc9357SAndroid Build Coastguard Worker   {
808*f6dc9357SAndroid Build Coastguard Worker     (release == FALSE) doesn't work, and SetData() returns E_NOTIMPL;
809*f6dc9357SAndroid Build Coastguard Worker     (release == TRUE)  works, and SetData() returns S_OK, and
810*f6dc9357SAndroid Build Coastguard Worker                        it returns S_OK even for formats unsupported by Explorer.
811*f6dc9357SAndroid Build Coastguard Worker   }
812*f6dc9357SAndroid Build Coastguard Worker 
813*f6dc9357SAndroid Build Coastguard Worker   To be more compatible with DOCs and Win10-Explorer and to avoid memory leaks,
814*f6dc9357SAndroid Build Coastguard Worker   we use the following scheme for our IDataObject::SetData(,, release == TRUE)
815*f6dc9357SAndroid Build Coastguard Worker   in DropSource code:
816*f6dc9357SAndroid Build Coastguard Worker   if (release == TRUE) { our SetData() always releases medium
817*f6dc9357SAndroid Build Coastguard Worker       with ReleaseStgMedium() and returns S_OK; }
818*f6dc9357SAndroid Build Coastguard Worker   The DRAWBACK of that scheme:
819*f6dc9357SAndroid Build Coastguard Worker     The caller always receives S_OK,
820*f6dc9357SAndroid Build Coastguard Worker     so the caller doesn't know about any error in SetData() in that case.
821*f6dc9357SAndroid Build Coastguard Worker 
822*f6dc9357SAndroid Build Coastguard Worker for 7zip-Target to 7zip-Source calls:
823*f6dc9357SAndroid Build Coastguard Worker   we use (release == FALSE)
824*f6dc9357SAndroid Build Coastguard Worker   So we avoid (release == TRUE) memory leak problems,
825*f6dc9357SAndroid Build Coastguard Worker   and we can get real return code from SetData().
826*f6dc9357SAndroid Build Coastguard Worker 
827*f6dc9357SAndroid Build Coastguard Worker for 7zip-Target to Explorer-Source calls:
828*f6dc9357SAndroid Build Coastguard Worker   we use (release == TRUE).
829*f6dc9357SAndroid Build Coastguard Worker   beacuse Explorer-Source doesn't accept (release == FALSE).
830*f6dc9357SAndroid Build Coastguard Worker }
831*f6dc9357SAndroid Build Coastguard Worker */
832*f6dc9357SAndroid Build Coastguard Worker 
833*f6dc9357SAndroid Build Coastguard Worker /*
834*f6dc9357SAndroid Build Coastguard Worker https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/shell/datascenarios.md
835*f6dc9357SAndroid Build Coastguard Worker CFSTR_PERFORMEDDROPEFFECT:
836*f6dc9357SAndroid Build Coastguard Worker   is used by the target to inform the data object through its
837*f6dc9357SAndroid Build Coastguard Worker   IDataObject::SetData method of the outcome of a data transfer.
838*f6dc9357SAndroid Build Coastguard Worker CFSTR_PREFERREDDROPEFFECT:
839*f6dc9357SAndroid Build Coastguard Worker   is used by the source to specify whether its preferred method of data transfer is move or copy.
840*f6dc9357SAndroid Build Coastguard Worker */
841*f6dc9357SAndroid Build Coastguard Worker 
SetData(LPFORMATETC etc,STGMEDIUM * medium,BOOL release)842*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDataObject::SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release)
843*f6dc9357SAndroid Build Coastguard Worker {
844*f6dc9357SAndroid Build Coastguard Worker   try {
845*f6dc9357SAndroid Build Coastguard Worker   const HRESULT hres = SetData2(etc, medium);
846*f6dc9357SAndroid Build Coastguard Worker   // PrintFormat(release ? "SetData RELEASE=TRUE" : "SetData RELEASE=FALSE" , etc->cfFormat);
847*f6dc9357SAndroid Build Coastguard Worker   if (release)
848*f6dc9357SAndroid Build Coastguard Worker   {
849*f6dc9357SAndroid Build Coastguard Worker     /*
850*f6dc9357SAndroid Build Coastguard Worker     const DWORD tymed = medium->tymed;
851*f6dc9357SAndroid Build Coastguard Worker     IUnknown *pUnkForRelease = medium->pUnkForRelease;
852*f6dc9357SAndroid Build Coastguard Worker     */
853*f6dc9357SAndroid Build Coastguard Worker     // medium->tymed = NULL; // for debug
854*f6dc9357SAndroid Build Coastguard Worker     // return E_NOTIMPL;  // for debug
855*f6dc9357SAndroid Build Coastguard Worker     ReleaseStgMedium(medium);
856*f6dc9357SAndroid Build Coastguard Worker     /* ReleaseStgMedium() will change STGMEDIUM::tymed to (TYMED_NULL = 0).
857*f6dc9357SAndroid Build Coastguard Worker        but we also can clear (medium.hGlobal = NULL),
858*f6dc9357SAndroid Build Coastguard Worker        to prevent some incorrect releasing, if the caller will try to release the data  */
859*f6dc9357SAndroid Build Coastguard Worker     /*
860*f6dc9357SAndroid Build Coastguard Worker     if (medium->tymed == TYMED_NULL && tymed == TYMED_HGLOBAL && !pUnkForRelease)
861*f6dc9357SAndroid Build Coastguard Worker       medium->hGlobal = NULL;
862*f6dc9357SAndroid Build Coastguard Worker     */
863*f6dc9357SAndroid Build Coastguard Worker     // do we need return S_OK; for (tymed != TYMED_HGLOBAL) cases ?
864*f6dc9357SAndroid Build Coastguard Worker     /* we return S_OK here to shows that we take ownership of the data in (medium),
865*f6dc9357SAndroid Build Coastguard Worker        so the caller will not try to release (medium) */
866*f6dc9357SAndroid Build Coastguard Worker     return S_OK; // to be more compatible with Win10-Explorer and DOCs.
867*f6dc9357SAndroid Build Coastguard Worker   }
868*f6dc9357SAndroid Build Coastguard Worker   return hres;
869*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { return E_FAIL; }
870*f6dc9357SAndroid Build Coastguard Worker }
871*f6dc9357SAndroid Build Coastguard Worker 
872*f6dc9357SAndroid Build Coastguard Worker 
873*f6dc9357SAndroid Build Coastguard Worker 
SetData2(const FORMATETC * etc,const STGMEDIUM * medium)874*f6dc9357SAndroid Build Coastguard Worker HRESULT CDataObject::SetData2(const FORMATETC *etc, const STGMEDIUM *medium)
875*f6dc9357SAndroid Build Coastguard Worker {
876*f6dc9357SAndroid Build Coastguard Worker   // PRF3("== CDataObject::SetData()");
877*f6dc9357SAndroid Build Coastguard Worker 
878*f6dc9357SAndroid Build Coastguard Worker   HRESULT hres = S_OK;
879*f6dc9357SAndroid Build Coastguard Worker 
880*f6dc9357SAndroid Build Coastguard Worker   if (etc->cfFormat == 0)
881*f6dc9357SAndroid Build Coastguard Worker     return DV_E_FORMATETC;
882*f6dc9357SAndroid Build Coastguard Worker   if (etc->tymed != TYMED_HGLOBAL)
883*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL; // DV_E_TYMED;
884*f6dc9357SAndroid Build Coastguard Worker   if (etc->dwAspect != DVASPECT_CONTENT)
885*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL; // DV_E_DVASPECT;
886*f6dc9357SAndroid Build Coastguard Worker   if (medium->tymed != TYMED_HGLOBAL)
887*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL; // DV_E_TYMED;
888*f6dc9357SAndroid Build Coastguard Worker 
889*f6dc9357SAndroid Build Coastguard Worker   if (!medium->hGlobal)
890*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
891*f6dc9357SAndroid Build Coastguard Worker 
892*f6dc9357SAndroid Build Coastguard Worker   if (etc->cfFormat == m_Format_7zip_SetTargetFolder)
893*f6dc9357SAndroid Build Coastguard Worker   {
894*f6dc9357SAndroid Build Coastguard Worker     DestDirPrefix_FromTarget.Empty();
895*f6dc9357SAndroid Build Coastguard Worker     m_DestDirPrefix_FromTarget_WasSet = true;
896*f6dc9357SAndroid Build Coastguard Worker   }
897*f6dc9357SAndroid Build Coastguard Worker   else if (etc->cfFormat == m_Format_7zip_SetTransfer)
898*f6dc9357SAndroid Build Coastguard Worker     m_Transfer_WasSet = false;
899*f6dc9357SAndroid Build Coastguard Worker 
900*f6dc9357SAndroid Build Coastguard Worker   const size_t size = GlobalSize(medium->hGlobal);
901*f6dc9357SAndroid Build Coastguard Worker   // GlobalLock() can return NULL, if memory block has a zero size
902*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
903*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
904*f6dc9357SAndroid Build Coastguard Worker   const void *src = (const Byte *)GlobalLock(medium->hGlobal);
905*f6dc9357SAndroid Build Coastguard Worker   if (!src)
906*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker   PRF_(PrintFormat_AndData("SetData", etc->cfFormat, src, size))
909*f6dc9357SAndroid Build Coastguard Worker 
910*f6dc9357SAndroid Build Coastguard Worker   if (etc->cfFormat == m_Format_7zip_SetTargetFolder)
911*f6dc9357SAndroid Build Coastguard Worker   {
912*f6dc9357SAndroid Build Coastguard Worker     /* this is our registered k_Format_7zip_SetTargetFolder format.
913*f6dc9357SAndroid Build Coastguard Worker        so it's call from 7-zip's CDropTarget */
914*f6dc9357SAndroid Build Coastguard Worker     /* 7-zip's CDropTarget calls SetData() for m_Format_7zip_SetTargetFolder
915*f6dc9357SAndroid Build Coastguard Worker        with (release == FALSE) */
916*f6dc9357SAndroid Build Coastguard Worker     const size_t num = size / sizeof(wchar_t);
917*f6dc9357SAndroid Build Coastguard Worker     if (size != num * sizeof(wchar_t))
918*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
919*f6dc9357SAndroid Build Coastguard Worker     // if (num == 0) return S_OK;
920*f6dc9357SAndroid Build Coastguard Worker     // GlobalLock() can return NULL, if memory block has a zero-byte size
921*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *s = (const wchar_t *)src;
922*f6dc9357SAndroid Build Coastguard Worker     UString &dest = DestDirPrefix_FromTarget;
923*f6dc9357SAndroid Build Coastguard Worker     for (size_t i = 0; i < num; i++)
924*f6dc9357SAndroid Build Coastguard Worker     {
925*f6dc9357SAndroid Build Coastguard Worker       const wchar_t c = s[i];
926*f6dc9357SAndroid Build Coastguard Worker       if (c == 0)
927*f6dc9357SAndroid Build Coastguard Worker         break;
928*f6dc9357SAndroid Build Coastguard Worker       dest += c;
929*f6dc9357SAndroid Build Coastguard Worker     }
930*f6dc9357SAndroid Build Coastguard Worker     // PRF_(PrintFormat_AndData("SetData", etc->cfFormat, src, size))
931*f6dc9357SAndroid Build Coastguard Worker     PRF3_W(DestDirPrefix_FromTarget);
932*f6dc9357SAndroid Build Coastguard Worker   }
933*f6dc9357SAndroid Build Coastguard Worker   else if (etc->cfFormat == m_Format_7zip_SetTransfer)
934*f6dc9357SAndroid Build Coastguard Worker   {
935*f6dc9357SAndroid Build Coastguard Worker     /* 7-zip's CDropTarget calls SetData() for m_Format_7zip_SetTransfer
936*f6dc9357SAndroid Build Coastguard Worker        with (release == FALSE) */
937*f6dc9357SAndroid Build Coastguard Worker     if (size < sizeof(CDataObject_SetTransfer))
938*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
939*f6dc9357SAndroid Build Coastguard Worker     const CDataObject_SetTransfer *t = (const CDataObject_SetTransfer *)src;
940*f6dc9357SAndroid Build Coastguard Worker     if (!t->Check())
941*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
942*f6dc9357SAndroid Build Coastguard Worker     m_Transfer = *t;
943*f6dc9357SAndroid Build Coastguard Worker     if (t->Target.FuncType != k_DragTargetMode_Leave)
944*f6dc9357SAndroid Build Coastguard Worker       m_Transfer_WasSet = true;
945*f6dc9357SAndroid Build Coastguard Worker     bool needProcessBySource = !DestDirPrefix_FromTarget.IsEmpty();
946*f6dc9357SAndroid Build Coastguard Worker     if (t->Target.FuncType == k_DragTargetMode_Drop_Begin)
947*f6dc9357SAndroid Build Coastguard Worker     {
948*f6dc9357SAndroid Build Coastguard Worker       if (t->Target.Cmd_Type != NDragMenu::k_Copy_Base
949*f6dc9357SAndroid Build Coastguard Worker           // || t->Target.Cmd_Effect != DROPEFFECT_COPY
950*f6dc9357SAndroid Build Coastguard Worker           )
951*f6dc9357SAndroid Build Coastguard Worker         needProcessBySource = false;
952*f6dc9357SAndroid Build Coastguard Worker     }
953*f6dc9357SAndroid Build Coastguard Worker     if (t->Target.FuncType == k_DragTargetMode_Drop_End)
954*f6dc9357SAndroid Build Coastguard Worker     {
955*f6dc9357SAndroid Build Coastguard Worker       if (t->Target.Flags & k_TargetFlags_MustBeProcessedBySource)
956*f6dc9357SAndroid Build Coastguard Worker         needProcessBySource = true;
957*f6dc9357SAndroid Build Coastguard Worker       else if (t->Target.Flags & k_TargetFlags_WasProcessed)
958*f6dc9357SAndroid Build Coastguard Worker         needProcessBySource = false;
959*f6dc9357SAndroid Build Coastguard Worker     }
960*f6dc9357SAndroid Build Coastguard Worker     DoNotProcessInTarget = needProcessBySource;
961*f6dc9357SAndroid Build Coastguard Worker   }
962*f6dc9357SAndroid Build Coastguard Worker   else
963*f6dc9357SAndroid Build Coastguard Worker   {
964*f6dc9357SAndroid Build Coastguard Worker     // SetData() from Explorer Target:
965*f6dc9357SAndroid Build Coastguard Worker     if (etc->cfFormat == m_Format_PerformedDropEffect)
966*f6dc9357SAndroid Build Coastguard Worker     {
967*f6dc9357SAndroid Build Coastguard Worker       m_PerformedDropEffect_WasSet = false;
968*f6dc9357SAndroid Build Coastguard Worker       if (size == sizeof(DWORD))
969*f6dc9357SAndroid Build Coastguard Worker       {
970*f6dc9357SAndroid Build Coastguard Worker         m_PerformedDropEffect = *(const DWORD *)src;
971*f6dc9357SAndroid Build Coastguard Worker         m_PerformedDropEffect_WasSet = true;
972*f6dc9357SAndroid Build Coastguard Worker       }
973*f6dc9357SAndroid Build Coastguard Worker     }
974*f6dc9357SAndroid Build Coastguard Worker     else if (etc->cfFormat == m_Format_LogicalPerformedDropEffect)
975*f6dc9357SAndroid Build Coastguard Worker     {
976*f6dc9357SAndroid Build Coastguard Worker       m_LogicalPerformedDropEffect_WasSet = false;
977*f6dc9357SAndroid Build Coastguard Worker       if (size == sizeof(DWORD))
978*f6dc9357SAndroid Build Coastguard Worker       {
979*f6dc9357SAndroid Build Coastguard Worker         m_LogicalPerformedDropEffect = *(const DWORD *)src;
980*f6dc9357SAndroid Build Coastguard Worker         m_LogicalPerformedDropEffect_WasSet = true;
981*f6dc9357SAndroid Build Coastguard Worker       }
982*f6dc9357SAndroid Build Coastguard Worker     }
983*f6dc9357SAndroid Build Coastguard Worker     else if (etc->cfFormat == m_Format_DropDescription)
984*f6dc9357SAndroid Build Coastguard Worker     {
985*f6dc9357SAndroid Build Coastguard Worker       // drop description contains only name of dest folder without full path
986*f6dc9357SAndroid Build Coastguard Worker       #ifdef SHOW_DEBUG_DRAG
987*f6dc9357SAndroid Build Coastguard Worker       if (size == sizeof(MY_DROPDESCRIPTION))
988*f6dc9357SAndroid Build Coastguard Worker       {
989*f6dc9357SAndroid Build Coastguard Worker         // const MY_DROPDESCRIPTION *s = (const MY_DROPDESCRIPTION *)src;
990*f6dc9357SAndroid Build Coastguard Worker         // PRF3_W(s->szMessage);
991*f6dc9357SAndroid Build Coastguard Worker         // PRF3_W(s->szInsert);
992*f6dc9357SAndroid Build Coastguard Worker       }
993*f6dc9357SAndroid Build Coastguard Worker       #endif
994*f6dc9357SAndroid Build Coastguard Worker     }
995*f6dc9357SAndroid Build Coastguard Worker     else if (etc->cfFormat == m_Format_TargetCLSID)
996*f6dc9357SAndroid Build Coastguard Worker     {
997*f6dc9357SAndroid Build Coastguard Worker       // it's called after call QueryContinueDrag() (keyState & MK_LBUTTON) == 0
998*f6dc9357SAndroid Build Coastguard Worker       // Shell File System Folder (explorer) guid: F3364BA0-65B9-11CE-A9BA-00AA004AE837
999*f6dc9357SAndroid Build Coastguard Worker       #ifdef SHOW_DEBUG_DRAG
1000*f6dc9357SAndroid Build Coastguard Worker       if (size == 16)
1001*f6dc9357SAndroid Build Coastguard Worker       {
1002*f6dc9357SAndroid Build Coastguard Worker         PrintFormat_GUIDToStringW((const Byte *)src);
1003*f6dc9357SAndroid Build Coastguard Worker       }
1004*f6dc9357SAndroid Build Coastguard Worker       #endif
1005*f6dc9357SAndroid Build Coastguard Worker     }
1006*f6dc9357SAndroid Build Coastguard Worker     else if (etc->cfFormat == m_Format_DisableDragText)
1007*f6dc9357SAndroid Build Coastguard Worker     {
1008*f6dc9357SAndroid Build Coastguard Worker       // (size == 4) (UInt32 value)
1009*f6dc9357SAndroid Build Coastguard Worker       //    value==0 : if drag to folder item or folder
1010*f6dc9357SAndroid Build Coastguard Worker       //    value==1 : if drag to file or non list_view */
1011*f6dc9357SAndroid Build Coastguard Worker     }
1012*f6dc9357SAndroid Build Coastguard Worker     else if (
1013*f6dc9357SAndroid Build Coastguard Worker         etc->cfFormat == m_Format_IsShowingLayered ||
1014*f6dc9357SAndroid Build Coastguard Worker         etc->cfFormat == m_Format_IsShowingText)
1015*f6dc9357SAndroid Build Coastguard Worker     {
1016*f6dc9357SAndroid Build Coastguard Worker       // (size == 4) (UInt32 value) value==0 :
1017*f6dc9357SAndroid Build Coastguard Worker     }
1018*f6dc9357SAndroid Build Coastguard Worker     else
1019*f6dc9357SAndroid Build Coastguard Worker       hres = DV_E_FORMATETC;
1020*f6dc9357SAndroid Build Coastguard Worker     // hres = E_NOTIMPL; // for debug
1021*f6dc9357SAndroid Build Coastguard Worker     // hres = DV_E_FORMATETC; // for debug
1022*f6dc9357SAndroid Build Coastguard Worker   }
1023*f6dc9357SAndroid Build Coastguard Worker 
1024*f6dc9357SAndroid Build Coastguard Worker   GlobalUnlock(medium->hGlobal);
1025*f6dc9357SAndroid Build Coastguard Worker   return hres;
1026*f6dc9357SAndroid Build Coastguard Worker }
1027*f6dc9357SAndroid Build Coastguard Worker 
1028*f6dc9357SAndroid Build Coastguard Worker 
1029*f6dc9357SAndroid Build Coastguard Worker 
DuplicateGlobalMem(HGLOBAL srcGlobal)1030*f6dc9357SAndroid Build Coastguard Worker static HGLOBAL DuplicateGlobalMem(HGLOBAL srcGlobal)
1031*f6dc9357SAndroid Build Coastguard Worker {
1032*f6dc9357SAndroid Build Coastguard Worker   /* GlobalSize() returns 0: If the specified handle
1033*f6dc9357SAndroid Build Coastguard Worker      is not valid or if the object has been discarded */
1034*f6dc9357SAndroid Build Coastguard Worker   const SIZE_T size = GlobalSize(srcGlobal);
1035*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
1036*f6dc9357SAndroid Build Coastguard Worker     return NULL;
1037*f6dc9357SAndroid Build Coastguard Worker   // GlobalLock() can return NULL, if memory block has a zero-byte size
1038*f6dc9357SAndroid Build Coastguard Worker   const void *src = GlobalLock(srcGlobal);
1039*f6dc9357SAndroid Build Coastguard Worker   if (!src)
1040*f6dc9357SAndroid Build Coastguard Worker     return NULL;
1041*f6dc9357SAndroid Build Coastguard Worker   HGLOBAL destGlobal = GlobalAlloc(GHND | GMEM_SHARE, size);
1042*f6dc9357SAndroid Build Coastguard Worker   if (destGlobal)
1043*f6dc9357SAndroid Build Coastguard Worker   {
1044*f6dc9357SAndroid Build Coastguard Worker     void *dest = GlobalLock(destGlobal);
1045*f6dc9357SAndroid Build Coastguard Worker     if (!dest)
1046*f6dc9357SAndroid Build Coastguard Worker     {
1047*f6dc9357SAndroid Build Coastguard Worker       GlobalFree(destGlobal);
1048*f6dc9357SAndroid Build Coastguard Worker       destGlobal = NULL;
1049*f6dc9357SAndroid Build Coastguard Worker     }
1050*f6dc9357SAndroid Build Coastguard Worker     else
1051*f6dc9357SAndroid Build Coastguard Worker     {
1052*f6dc9357SAndroid Build Coastguard Worker       memcpy(dest, src, size);
1053*f6dc9357SAndroid Build Coastguard Worker       GlobalUnlock(destGlobal);
1054*f6dc9357SAndroid Build Coastguard Worker     }
1055*f6dc9357SAndroid Build Coastguard Worker   }
1056*f6dc9357SAndroid Build Coastguard Worker   GlobalUnlock(srcGlobal);
1057*f6dc9357SAndroid Build Coastguard Worker   return destGlobal;
1058*f6dc9357SAndroid Build Coastguard Worker }
1059*f6dc9357SAndroid Build Coastguard Worker 
1060*f6dc9357SAndroid Build Coastguard Worker 
Medium_CopyFrom(LPSTGMEDIUM medium,const void * data,size_t size)1061*f6dc9357SAndroid Build Coastguard Worker static bool Medium_CopyFrom(LPSTGMEDIUM medium, const void *data, size_t size)
1062*f6dc9357SAndroid Build Coastguard Worker {
1063*f6dc9357SAndroid Build Coastguard Worker   medium->tymed = TYMED_NULL;
1064*f6dc9357SAndroid Build Coastguard Worker   medium->pUnkForRelease = NULL;
1065*f6dc9357SAndroid Build Coastguard Worker   medium->hGlobal = NULL;
1066*f6dc9357SAndroid Build Coastguard Worker   const HGLOBAL global = GlobalAlloc(GHND | GMEM_SHARE, size);
1067*f6dc9357SAndroid Build Coastguard Worker   if (!global)
1068*f6dc9357SAndroid Build Coastguard Worker     return false;
1069*f6dc9357SAndroid Build Coastguard Worker   void *dest = GlobalLock(global);
1070*f6dc9357SAndroid Build Coastguard Worker   if (!dest)
1071*f6dc9357SAndroid Build Coastguard Worker   {
1072*f6dc9357SAndroid Build Coastguard Worker     GlobalFree(global);
1073*f6dc9357SAndroid Build Coastguard Worker     return false;
1074*f6dc9357SAndroid Build Coastguard Worker   }
1075*f6dc9357SAndroid Build Coastguard Worker   memcpy(dest, data, size);
1076*f6dc9357SAndroid Build Coastguard Worker   GlobalUnlock(global);
1077*f6dc9357SAndroid Build Coastguard Worker   medium->hGlobal = global;
1078*f6dc9357SAndroid Build Coastguard Worker   medium->tymed = TYMED_HGLOBAL;
1079*f6dc9357SAndroid Build Coastguard Worker   return true;
1080*f6dc9357SAndroid Build Coastguard Worker }
1081*f6dc9357SAndroid Build Coastguard Worker 
1082*f6dc9357SAndroid Build Coastguard Worker 
GetData(LPFORMATETC etc,LPSTGMEDIUM medium)1083*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDataObject::GetData(LPFORMATETC etc, LPSTGMEDIUM medium)
1084*f6dc9357SAndroid Build Coastguard Worker {
1085*f6dc9357SAndroid Build Coastguard Worker   try {
1086*f6dc9357SAndroid Build Coastguard Worker   PRF_(PrintFormat("-- GetData", etc->cfFormat))
1087*f6dc9357SAndroid Build Coastguard Worker 
1088*f6dc9357SAndroid Build Coastguard Worker   medium->tymed = TYMED_NULL;
1089*f6dc9357SAndroid Build Coastguard Worker   medium->pUnkForRelease = NULL;
1090*f6dc9357SAndroid Build Coastguard Worker   medium->hGlobal = NULL;
1091*f6dc9357SAndroid Build Coastguard Worker 
1092*f6dc9357SAndroid Build Coastguard Worker   if (NeedCall_Copy && !Copy_WasCalled)
1093*f6dc9357SAndroid Build Coastguard Worker     CopyFromPanelTo_Folder();
1094*f6dc9357SAndroid Build Coastguard Worker 
1095*f6dc9357SAndroid Build Coastguard Worker   // PRF3("+ CDataObject::GetData");
1096*f6dc9357SAndroid Build Coastguard Worker   // PrintFormat(etc->cfFormat);
1097*f6dc9357SAndroid Build Coastguard Worker   HGLOBAL global;
1098*f6dc9357SAndroid Build Coastguard Worker   RINOK(QueryGetData(etc))
1099*f6dc9357SAndroid Build Coastguard Worker 
1100*f6dc9357SAndroid Build Coastguard Worker   /*
1101*f6dc9357SAndroid Build Coastguard Worker   if (etc->cfFormat == m_Format_FileOpFlags)
1102*f6dc9357SAndroid Build Coastguard Worker     global = m_hGlobal_FileOpFlags;
1103*f6dc9357SAndroid Build Coastguard Worker   else if (etc->cfFormat == m_Format_PreferredDropEffect)
1104*f6dc9357SAndroid Build Coastguard Worker   {
1105*f6dc9357SAndroid Build Coastguard Worker     // Explorer requests PreferredDropEffect only if Move/Copy selection is possible:
1106*f6dc9357SAndroid Build Coastguard Worker     //   Shift is not pressed and Ctrl is not pressed
1107*f6dc9357SAndroid Build Coastguard Worker     PRF3("------ CDataObject::GetData() PreferredDropEffect");
1108*f6dc9357SAndroid Build Coastguard Worker     global = m_hGlobal_PreferredDropEffect;
1109*f6dc9357SAndroid Build Coastguard Worker   }
1110*f6dc9357SAndroid Build Coastguard Worker   else
1111*f6dc9357SAndroid Build Coastguard Worker   */
1112*f6dc9357SAndroid Build Coastguard Worker   if (etc->cfFormat == m_Etc.cfFormat) // CF_HDROP
1113*f6dc9357SAndroid Build Coastguard Worker     global = UsePreGlobal ? m_hGlobal_HDROP_Pre : m_hGlobal_HDROP_Final;
1114*f6dc9357SAndroid Build Coastguard Worker   else if (etc->cfFormat == m_Format_7zip_GetTransfer)
1115*f6dc9357SAndroid Build Coastguard Worker   {
1116*f6dc9357SAndroid Build Coastguard Worker     CDataObject_GetTransfer transfer;
1117*f6dc9357SAndroid Build Coastguard Worker     if (m_DestDirPrefix_FromTarget_WasSet)
1118*f6dc9357SAndroid Build Coastguard Worker     {
1119*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_SetTargetFolder;
1120*f6dc9357SAndroid Build Coastguard Worker     }
1121*f6dc9357SAndroid Build Coastguard Worker     if (!DestDirPrefix_FromTarget.IsEmpty())
1122*f6dc9357SAndroid Build Coastguard Worker     {
1123*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_SetTargetFolder_NonEmpty;
1124*f6dc9357SAndroid Build Coastguard Worker     }
1125*f6dc9357SAndroid Build Coastguard Worker     if (IsTempFiles)
1126*f6dc9357SAndroid Build Coastguard Worker     {
1127*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_TempFiles;
1128*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_WaitFinish;
1129*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_NeedExtractOpToFs;
1130*f6dc9357SAndroid Build Coastguard Worker       if (UsePreGlobal)
1131*f6dc9357SAndroid Build Coastguard Worker         transfer.Flags |= k_SourceFlags_NamesAreParent;
1132*f6dc9357SAndroid Build Coastguard Worker     }
1133*f6dc9357SAndroid Build Coastguard Worker     else
1134*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_DoNotWaitFinish;
1135*f6dc9357SAndroid Build Coastguard Worker 
1136*f6dc9357SAndroid Build Coastguard Worker     if (IsRightButton)
1137*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_RightButton;
1138*f6dc9357SAndroid Build Coastguard Worker     else
1139*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_LeftButton;
1140*f6dc9357SAndroid Build Coastguard Worker 
1141*f6dc9357SAndroid Build Coastguard Worker     if (DoNotProcessInTarget)
1142*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_DoNotProcessInTarget;
1143*f6dc9357SAndroid Build Coastguard Worker     if (Copy_WasCalled)
1144*f6dc9357SAndroid Build Coastguard Worker       transfer.Flags |= k_SourceFlags_Copy_WasCalled;
1145*f6dc9357SAndroid Build Coastguard Worker 
1146*f6dc9357SAndroid Build Coastguard Worker     if (Medium_CopyFrom(medium, &transfer, sizeof(transfer)))
1147*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1148*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
1149*f6dc9357SAndroid Build Coastguard Worker   }
1150*f6dc9357SAndroid Build Coastguard Worker   else
1151*f6dc9357SAndroid Build Coastguard Worker     return DV_E_FORMATETC;
1152*f6dc9357SAndroid Build Coastguard Worker 
1153*f6dc9357SAndroid Build Coastguard Worker   if (!global)
1154*f6dc9357SAndroid Build Coastguard Worker     return DV_E_FORMATETC;
1155*f6dc9357SAndroid Build Coastguard Worker   medium->tymed = m_Etc.tymed;
1156*f6dc9357SAndroid Build Coastguard Worker   medium->hGlobal = DuplicateGlobalMem(global);
1157*f6dc9357SAndroid Build Coastguard Worker   if (!medium->hGlobal)
1158*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
1159*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1160*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { return E_FAIL; }
1161*f6dc9357SAndroid Build Coastguard Worker }
1162*f6dc9357SAndroid Build Coastguard Worker 
GetDataHere(LPFORMATETC,LPSTGMEDIUM)1163*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDataObject::GetDataHere(LPFORMATETC /* etc */, LPSTGMEDIUM /* medium */)
1164*f6dc9357SAndroid Build Coastguard Worker {
1165*f6dc9357SAndroid Build Coastguard Worker   PRF3("CDataObject::GetDataHere()");
1166*f6dc9357SAndroid Build Coastguard Worker   // Seems Windows doesn't call it, so we will not implement it.
1167*f6dc9357SAndroid Build Coastguard Worker   return E_UNEXPECTED;
1168*f6dc9357SAndroid Build Coastguard Worker }
1169*f6dc9357SAndroid Build Coastguard Worker 
1170*f6dc9357SAndroid Build Coastguard Worker 
1171*f6dc9357SAndroid Build Coastguard Worker /*
1172*f6dc9357SAndroid Build Coastguard Worker   IDataObject::QueryGetData() Determines whether the data object is capable of
1173*f6dc9357SAndroid Build Coastguard Worker   rendering the data as specified. Objects attempting a paste or drop
1174*f6dc9357SAndroid Build Coastguard Worker   operation can call this method before calling IDataObject::GetData
1175*f6dc9357SAndroid Build Coastguard Worker   to get an indication of whether the operation may be successful.
1176*f6dc9357SAndroid Build Coastguard Worker 
1177*f6dc9357SAndroid Build Coastguard Worker   The client of a data object calls QueryGetData to determine whether
1178*f6dc9357SAndroid Build Coastguard Worker   passing the specified FORMATETC structure to a subsequent call to
1179*f6dc9357SAndroid Build Coastguard Worker   IDataObject::GetData is likely to be successful.
1180*f6dc9357SAndroid Build Coastguard Worker 
1181*f6dc9357SAndroid Build Coastguard Worker   we check Try_QueryGetData with CF_HDROP
1182*f6dc9357SAndroid Build Coastguard Worker */
1183*f6dc9357SAndroid Build Coastguard Worker 
QueryGetData(LPFORMATETC etc)1184*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDataObject::QueryGetData(LPFORMATETC etc)
1185*f6dc9357SAndroid Build Coastguard Worker {
1186*f6dc9357SAndroid Build Coastguard Worker   PRF3("-- CDataObject::QueryGetData()");
1187*f6dc9357SAndroid Build Coastguard Worker   if (    etc->cfFormat == m_Etc.cfFormat // CF_HDROP
1188*f6dc9357SAndroid Build Coastguard Worker       ||  etc->cfFormat == m_Format_7zip_GetTransfer
1189*f6dc9357SAndroid Build Coastguard Worker       // || (etc->cfFormat == m_Format_FileOpFlags && (HGLOBAL)m_hGlobal_FileOpFlags)
1190*f6dc9357SAndroid Build Coastguard Worker       // || (etc->cfFormat == m_Format_PreferredDropEffect && (HGLOBAL)m_hGlobal_PreferredDropEffect)
1191*f6dc9357SAndroid Build Coastguard Worker       )
1192*f6dc9357SAndroid Build Coastguard Worker   {
1193*f6dc9357SAndroid Build Coastguard Worker   }
1194*f6dc9357SAndroid Build Coastguard Worker   else
1195*f6dc9357SAndroid Build Coastguard Worker     return DV_E_FORMATETC;
1196*f6dc9357SAndroid Build Coastguard Worker   if (etc->dwAspect != m_Etc.dwAspect)
1197*f6dc9357SAndroid Build Coastguard Worker     return DV_E_DVASPECT;
1198*f6dc9357SAndroid Build Coastguard Worker   /* GetData(): It is possible to specify more than one medium by using the Boolean OR
1199*f6dc9357SAndroid Build Coastguard Worker      operator, allowing the method to choose the best medium among those specified. */
1200*f6dc9357SAndroid Build Coastguard Worker   if ((etc->tymed & m_Etc.tymed) == 0)
1201*f6dc9357SAndroid Build Coastguard Worker     return DV_E_TYMED;
1202*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1203*f6dc9357SAndroid Build Coastguard Worker }
1204*f6dc9357SAndroid Build Coastguard Worker 
EnumFormatEtc(DWORD direction,LPENUMFORMATETC FAR * enumFormatEtc)1205*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDataObject::EnumFormatEtc(DWORD direction, LPENUMFORMATETC FAR* enumFormatEtc)
1206*f6dc9357SAndroid Build Coastguard Worker {
1207*f6dc9357SAndroid Build Coastguard Worker   // we don't enumerate for DATADIR_SET. Seems it can work without it.
1208*f6dc9357SAndroid Build Coastguard Worker   if (direction != DATADIR_GET)
1209*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1210*f6dc9357SAndroid Build Coastguard Worker   // we don't enumerate for m_Format_FileOpFlags also. Seems it can work without it.
1211*f6dc9357SAndroid Build Coastguard Worker   return CreateEnumFormatEtc(1, &m_Etc, enumFormatEtc);
1212*f6dc9357SAndroid Build Coastguard Worker }
1213*f6dc9357SAndroid Build Coastguard Worker 
1214*f6dc9357SAndroid Build Coastguard Worker 
1215*f6dc9357SAndroid Build Coastguard Worker 
1216*f6dc9357SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////
1217*f6dc9357SAndroid Build Coastguard Worker 
1218*f6dc9357SAndroid Build Coastguard Worker class CDropSource Z7_final:
1219*f6dc9357SAndroid Build Coastguard Worker   public IDropSource,
1220*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
1221*f6dc9357SAndroid Build Coastguard Worker {
1222*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_1_MT(IDropSource)
1223*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(QueryContinueDrag)(BOOL escapePressed, DWORD keyState) Z7_override;
1224*f6dc9357SAndroid Build Coastguard Worker   STDMETHOD(GiveFeedback)(DWORD effect) Z7_override;
1225*f6dc9357SAndroid Build Coastguard Worker 
1226*f6dc9357SAndroid Build Coastguard Worker   DWORD m_Effect;
1227*f6dc9357SAndroid Build Coastguard Worker public:
1228*f6dc9357SAndroid Build Coastguard Worker   CDataObject *DataObjectSpec;
1229*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IDataObject> DataObject;
1230*f6dc9357SAndroid Build Coastguard Worker 
1231*f6dc9357SAndroid Build Coastguard Worker   HRESULT DragProcessing_HRESULT;
1232*f6dc9357SAndroid Build Coastguard Worker   bool DragProcessing_WasFinished;
1233*f6dc9357SAndroid Build Coastguard Worker 
CDropSource()1234*f6dc9357SAndroid Build Coastguard Worker   CDropSource():
1235*f6dc9357SAndroid Build Coastguard Worker       m_Effect(DROPEFFECT_NONE),
1236*f6dc9357SAndroid Build Coastguard Worker       // Panel(NULL),
1237*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_HRESULT(S_OK),
1238*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_WasFinished(false)
1239*f6dc9357SAndroid Build Coastguard Worker       {}
1240*f6dc9357SAndroid Build Coastguard Worker };
1241*f6dc9357SAndroid Build Coastguard Worker 
1242*f6dc9357SAndroid Build Coastguard Worker // static bool g_Debug = 0;
1243*f6dc9357SAndroid Build Coastguard Worker 
1244*f6dc9357SAndroid Build Coastguard Worker 
QueryContinueDrag(BOOL escapePressed,DWORD keyState)1245*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState)
1246*f6dc9357SAndroid Build Coastguard Worker {
1247*f6dc9357SAndroid Build Coastguard Worker   // try {
1248*f6dc9357SAndroid Build Coastguard Worker 
1249*f6dc9357SAndroid Build Coastguard Worker   /* Determines whether a drag-and-drop operation should be continued, canceled, or completed.
1250*f6dc9357SAndroid Build Coastguard Worker      escapePressed : Indicates whether the Esc key has been pressed
1251*f6dc9357SAndroid Build Coastguard Worker        since the previous call to QueryContinueDrag
1252*f6dc9357SAndroid Build Coastguard Worker        or to DoDragDrop if this is the first call to QueryContinueDrag:
1253*f6dc9357SAndroid Build Coastguard Worker          TRUE  : the end user has pressed the escape key;
1254*f6dc9357SAndroid Build Coastguard Worker          FALSE : it has not been pressed.
1255*f6dc9357SAndroid Build Coastguard Worker      keyState : The current state of the keyboard modifier keys on the keyboard.
1256*f6dc9357SAndroid Build Coastguard Worker       Possible values can be a combination of any of the flags:
1257*f6dc9357SAndroid Build Coastguard Worker       MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON.
1258*f6dc9357SAndroid Build Coastguard Worker   */
1259*f6dc9357SAndroid Build Coastguard Worker   #ifdef SHOW_DEBUG_DRAG
1260*f6dc9357SAndroid Build Coastguard Worker   {
1261*f6dc9357SAndroid Build Coastguard Worker     AString s ("CDropSource::QueryContinueDrag()");
1262*f6dc9357SAndroid Build Coastguard Worker     s.Add_Space();
1263*f6dc9357SAndroid Build Coastguard Worker     s += "keystate=";
1264*f6dc9357SAndroid Build Coastguard Worker     s.Add_UInt32(keyState);
1265*f6dc9357SAndroid Build Coastguard Worker     PRF4(s);
1266*f6dc9357SAndroid Build Coastguard Worker   }
1267*f6dc9357SAndroid Build Coastguard Worker   #endif
1268*f6dc9357SAndroid Build Coastguard Worker 
1269*f6dc9357SAndroid Build Coastguard Worker   /*
1270*f6dc9357SAndroid Build Coastguard Worker   if ((keyState & MK_LBUTTON) == 0)
1271*f6dc9357SAndroid Build Coastguard Worker   {
1272*f6dc9357SAndroid Build Coastguard Worker     // PRF4("CDropSource::QueryContinueDrag() (keyState & MK_LBUTTON) == 0");
1273*f6dc9357SAndroid Build Coastguard Worker     g_Debug = true;
1274*f6dc9357SAndroid Build Coastguard Worker   }
1275*f6dc9357SAndroid Build Coastguard Worker   else
1276*f6dc9357SAndroid Build Coastguard Worker   {
1277*f6dc9357SAndroid Build Coastguard Worker     // PRF4("CDropSource::QueryContinueDrag() (keyState & MK_LBUTTON) != 0");
1278*f6dc9357SAndroid Build Coastguard Worker   }
1279*f6dc9357SAndroid Build Coastguard Worker   */
1280*f6dc9357SAndroid Build Coastguard Worker 
1281*f6dc9357SAndroid Build Coastguard Worker   if (escapePressed)
1282*f6dc9357SAndroid Build Coastguard Worker   {
1283*f6dc9357SAndroid Build Coastguard Worker     // The drag operation should be canceled with no drop operation occurring.
1284*f6dc9357SAndroid Build Coastguard Worker     DragProcessing_WasFinished = true;
1285*f6dc9357SAndroid Build Coastguard Worker     DragProcessing_HRESULT = DRAGDROP_S_CANCEL;
1286*f6dc9357SAndroid Build Coastguard Worker     return DRAGDROP_S_CANCEL;
1287*f6dc9357SAndroid Build Coastguard Worker   }
1288*f6dc9357SAndroid Build Coastguard Worker 
1289*f6dc9357SAndroid Build Coastguard Worker   if (DragProcessing_WasFinished)
1290*f6dc9357SAndroid Build Coastguard Worker     return DragProcessing_HRESULT;
1291*f6dc9357SAndroid Build Coastguard Worker 
1292*f6dc9357SAndroid Build Coastguard Worker   if ((keyState & MK_RBUTTON) != 0)
1293*f6dc9357SAndroid Build Coastguard Worker   {
1294*f6dc9357SAndroid Build Coastguard Worker     if (!DataObjectSpec->IsRightButton)
1295*f6dc9357SAndroid Build Coastguard Worker     {
1296*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_WasFinished = true;
1297*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_HRESULT = DRAGDROP_S_CANCEL;
1298*f6dc9357SAndroid Build Coastguard Worker       return DRAGDROP_S_CANCEL;
1299*f6dc9357SAndroid Build Coastguard Worker     }
1300*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1301*f6dc9357SAndroid Build Coastguard Worker   }
1302*f6dc9357SAndroid Build Coastguard Worker 
1303*f6dc9357SAndroid Build Coastguard Worker   if ((keyState & MK_LBUTTON) != 0)
1304*f6dc9357SAndroid Build Coastguard Worker   {
1305*f6dc9357SAndroid Build Coastguard Worker     if (DataObjectSpec->IsRightButton)
1306*f6dc9357SAndroid Build Coastguard Worker     {
1307*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_WasFinished = true;
1308*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_HRESULT = DRAGDROP_S_CANCEL;
1309*f6dc9357SAndroid Build Coastguard Worker       return DRAGDROP_S_CANCEL;
1310*f6dc9357SAndroid Build Coastguard Worker     }
1311*f6dc9357SAndroid Build Coastguard Worker     /* The drag operation should continue. This result occurs if no errors are detected,
1312*f6dc9357SAndroid Build Coastguard Worker        the mouse button starting the drag-and-drop operation has not been released,
1313*f6dc9357SAndroid Build Coastguard Worker        and the Esc key has not been detected. */
1314*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1315*f6dc9357SAndroid Build Coastguard Worker   }
1316*f6dc9357SAndroid Build Coastguard Worker   {
1317*f6dc9357SAndroid Build Coastguard Worker     // the mouse button starting the drag-and-drop operation has been released.
1318*f6dc9357SAndroid Build Coastguard Worker 
1319*f6dc9357SAndroid Build Coastguard Worker     /* Win10 probably calls DragOver()/GiveFeedback() just before LBUTTON releasing.
1320*f6dc9357SAndroid Build Coastguard Worker        so m_Effect is effect returned by DropTarget::DragOver()
1321*f6dc9357SAndroid Build Coastguard Worker        just before LBUTTON releasing.
1322*f6dc9357SAndroid Build Coastguard Worker        So here we can use Effect sent to last GiveFeedback() */
1323*f6dc9357SAndroid Build Coastguard Worker 
1324*f6dc9357SAndroid Build Coastguard Worker     if (m_Effect == DROPEFFECT_NONE)
1325*f6dc9357SAndroid Build Coastguard Worker     {
1326*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_WasFinished = true;
1327*f6dc9357SAndroid Build Coastguard Worker       DragProcessing_HRESULT = DRAGDROP_S_CANCEL;
1328*f6dc9357SAndroid Build Coastguard Worker       // Drop target cannot accept the data. So we cancel drag and drop
1329*f6dc9357SAndroid Build Coastguard Worker       // maybe return DRAGDROP_S_DROP also OK here ?
1330*f6dc9357SAndroid Build Coastguard Worker       // return DRAGDROP_S_DROP; // for debug
1331*f6dc9357SAndroid Build Coastguard Worker       return DRAGDROP_S_CANCEL;
1332*f6dc9357SAndroid Build Coastguard Worker     }
1333*f6dc9357SAndroid Build Coastguard Worker 
1334*f6dc9357SAndroid Build Coastguard Worker     // we switch to real names for items that will be created in temp folder
1335*f6dc9357SAndroid Build Coastguard Worker     DataObjectSpec->UsePreGlobal = false;
1336*f6dc9357SAndroid Build Coastguard Worker     DataObjectSpec->Copy_HRESULT = S_OK;
1337*f6dc9357SAndroid Build Coastguard Worker     // MoveMode = (((keyState & MK_SHIFT) != 0) && MoveIsAllowed);
1338*f6dc9357SAndroid Build Coastguard Worker     /*
1339*f6dc9357SAndroid Build Coastguard Worker     if (DataObjectSpec->IsRightButton)
1340*f6dc9357SAndroid Build Coastguard Worker       return DRAGDROP_S_DROP;
1341*f6dc9357SAndroid Build Coastguard Worker     */
1342*f6dc9357SAndroid Build Coastguard Worker 
1343*f6dc9357SAndroid Build Coastguard Worker     if (DataObjectSpec->IsTempFiles)
1344*f6dc9357SAndroid Build Coastguard Worker     {
1345*f6dc9357SAndroid Build Coastguard Worker       if (!DataObjectSpec->DestDirPrefix_FromTarget.IsEmpty())
1346*f6dc9357SAndroid Build Coastguard Worker       {
1347*f6dc9357SAndroid Build Coastguard Worker         /* we know the destination Path.
1348*f6dc9357SAndroid Build Coastguard Worker            So we can copy or extract items later in Source with simpler code. */
1349*f6dc9357SAndroid Build Coastguard Worker         DataObjectSpec->DoNotProcessInTarget = true;
1350*f6dc9357SAndroid Build Coastguard Worker         // return DRAGDROP_S_CANCEL;
1351*f6dc9357SAndroid Build Coastguard Worker       }
1352*f6dc9357SAndroid Build Coastguard Worker       else
1353*f6dc9357SAndroid Build Coastguard Worker       {
1354*f6dc9357SAndroid Build Coastguard Worker         DataObjectSpec->NeedCall_Copy = true;
1355*f6dc9357SAndroid Build Coastguard Worker         /*
1356*f6dc9357SAndroid Build Coastguard Worker         if (Copy_HRESULT != S_OK || !Messages.IsEmpty())
1357*f6dc9357SAndroid Build Coastguard Worker         {
1358*f6dc9357SAndroid Build Coastguard Worker           DragProcessing_WasFinished = true;
1359*f6dc9357SAndroid Build Coastguard Worker           DragProcessing_HRESULT = DRAGDROP_S_CANCEL;
1360*f6dc9357SAndroid Build Coastguard Worker           return DRAGDROP_S_CANCEL;
1361*f6dc9357SAndroid Build Coastguard Worker         }
1362*f6dc9357SAndroid Build Coastguard Worker         */
1363*f6dc9357SAndroid Build Coastguard Worker       }
1364*f6dc9357SAndroid Build Coastguard Worker     }
1365*f6dc9357SAndroid Build Coastguard Worker     DragProcessing_HRESULT = DRAGDROP_S_DROP;
1366*f6dc9357SAndroid Build Coastguard Worker     DragProcessing_WasFinished = true;
1367*f6dc9357SAndroid Build Coastguard Worker     return DRAGDROP_S_DROP;
1368*f6dc9357SAndroid Build Coastguard Worker   }
1369*f6dc9357SAndroid Build Coastguard Worker   // } catch(...) { return E_FAIL; }
1370*f6dc9357SAndroid Build Coastguard Worker }
1371*f6dc9357SAndroid Build Coastguard Worker 
1372*f6dc9357SAndroid Build Coastguard Worker 
GiveFeedback(DWORD effect)1373*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropSource::GiveFeedback(DWORD effect)
1374*f6dc9357SAndroid Build Coastguard Worker {
1375*f6dc9357SAndroid Build Coastguard Worker   // PRF3("CDropSource::GiveFeedback");
1376*f6dc9357SAndroid Build Coastguard Worker   /* Enables a source application to give visual feedback to the end user
1377*f6dc9357SAndroid Build Coastguard Worker      during a drag-and-drop operation by providing the DoDragDrop function
1378*f6dc9357SAndroid Build Coastguard Worker      with an enumeration value specifying the visual effect.
1379*f6dc9357SAndroid Build Coastguard Worker   in (effect):
1380*f6dc9357SAndroid Build Coastguard Worker      The DROPEFFECT value returned by the most recent call to
1381*f6dc9357SAndroid Build Coastguard Worker         IDropTarget::DragEnter,
1382*f6dc9357SAndroid Build Coastguard Worker         IDropTarget::DragOver,
1383*f6dc9357SAndroid Build Coastguard Worker      or DROPEFFECT_NONE after IDropTarget::DragLeave.
1384*f6dc9357SAndroid Build Coastguard Worker     0: DROPEFFECT_NONE
1385*f6dc9357SAndroid Build Coastguard Worker     1: DROPEFFECT_COPY
1386*f6dc9357SAndroid Build Coastguard Worker     2: DROPEFFECT_MOVE
1387*f6dc9357SAndroid Build Coastguard Worker     4: DROPEFFECT_LINK
1388*f6dc9357SAndroid Build Coastguard Worker     0x80000000: DROPEFFECT_SCROLL
1389*f6dc9357SAndroid Build Coastguard Worker     The dwEffect parameter can include DROPEFFECT_SCROLL, indicating that the
1390*f6dc9357SAndroid Build Coastguard Worker     source should put up the drag-scrolling variation of the appropriate pointer.
1391*f6dc9357SAndroid Build Coastguard Worker   */
1392*f6dc9357SAndroid Build Coastguard Worker   m_Effect = effect;
1393*f6dc9357SAndroid Build Coastguard Worker 
1394*f6dc9357SAndroid Build Coastguard Worker  #ifdef SHOW_DEBUG_DRAG
1395*f6dc9357SAndroid Build Coastguard Worker   AString w ("GiveFeedback effect=");
1396*f6dc9357SAndroid Build Coastguard Worker   if (effect & DROPEFFECT_SCROLL)
1397*f6dc9357SAndroid Build Coastguard Worker     w += " SCROLL ";
1398*f6dc9357SAndroid Build Coastguard Worker   w.Add_UInt32(effect & ~DROPEFFECT_SCROLL);
1399*f6dc9357SAndroid Build Coastguard Worker   // if (g_Debug)
1400*f6dc9357SAndroid Build Coastguard Worker   PRF4(w);
1401*f6dc9357SAndroid Build Coastguard Worker  #endif
1402*f6dc9357SAndroid Build Coastguard Worker 
1403*f6dc9357SAndroid Build Coastguard Worker   /* S_OK : no special drag and drop cursors.
1404*f6dc9357SAndroid Build Coastguard Worker             Maybe it's for case where we created custom custom cursors.
1405*f6dc9357SAndroid Build Coastguard Worker      DRAGDROP_S_USEDEFAULTCURSORS: Indicates successful completion of the method,
1406*f6dc9357SAndroid Build Coastguard Worker        and requests OLE to update the cursor using the OLE-provided default cursors. */
1407*f6dc9357SAndroid Build Coastguard Worker   // return S_OK; // for debug
1408*f6dc9357SAndroid Build Coastguard Worker   return DRAGDROP_S_USEDEFAULTCURSORS;
1409*f6dc9357SAndroid Build Coastguard Worker }
1410*f6dc9357SAndroid Build Coastguard Worker 
1411*f6dc9357SAndroid Build Coastguard Worker 
1412*f6dc9357SAndroid Build Coastguard Worker 
1413*f6dc9357SAndroid Build Coastguard Worker /*
1414*f6dc9357SAndroid Build Coastguard Worker static bool Global_SetUInt32(NMemory::CGlobal &hg, const UInt32 v)
1415*f6dc9357SAndroid Build Coastguard Worker {
1416*f6dc9357SAndroid Build Coastguard Worker   if (!hg.Alloc(GHND | GMEM_SHARE, sizeof(v)))
1417*f6dc9357SAndroid Build Coastguard Worker     return false;
1418*f6dc9357SAndroid Build Coastguard Worker   NMemory::CGlobalLock dropLock(hg);
1419*f6dc9357SAndroid Build Coastguard Worker   *(UInt32 *)dropLock.GetPointer() = v;
1420*f6dc9357SAndroid Build Coastguard Worker   return true;
1421*f6dc9357SAndroid Build Coastguard Worker }
1422*f6dc9357SAndroid Build Coastguard Worker */
1423*f6dc9357SAndroid Build Coastguard Worker 
CopyNamesToHGlobal(NMemory::CGlobal & hgDrop,const UStringVector & names)1424*f6dc9357SAndroid Build Coastguard Worker static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &names)
1425*f6dc9357SAndroid Build Coastguard Worker {
1426*f6dc9357SAndroid Build Coastguard Worker   size_t totalLen = 1;
1427*f6dc9357SAndroid Build Coastguard Worker 
1428*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
1429*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
1430*f6dc9357SAndroid Build Coastguard Worker   {
1431*f6dc9357SAndroid Build Coastguard Worker     AStringVector namesA;
1432*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1433*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < names.Size(); i++)
1434*f6dc9357SAndroid Build Coastguard Worker       namesA.Add(GetSystemString(names[i]));
1435*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < namesA.Size(); i++)
1436*f6dc9357SAndroid Build Coastguard Worker       totalLen += namesA[i].Len() + 1;
1437*f6dc9357SAndroid Build Coastguard Worker 
1438*f6dc9357SAndroid Build Coastguard Worker     if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(CHAR) + sizeof(DROPFILES)))
1439*f6dc9357SAndroid Build Coastguard Worker       return false;
1440*f6dc9357SAndroid Build Coastguard Worker 
1441*f6dc9357SAndroid Build Coastguard Worker     NMemory::CGlobalLock dropLock(hgDrop);
1442*f6dc9357SAndroid Build Coastguard Worker     DROPFILES *dropFiles = (DROPFILES *)dropLock.GetPointer();
1443*f6dc9357SAndroid Build Coastguard Worker     if (!dropFiles)
1444*f6dc9357SAndroid Build Coastguard Worker       return false;
1445*f6dc9357SAndroid Build Coastguard Worker     dropFiles->fNC = FALSE;
1446*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pt.x = 0;
1447*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pt.y = 0;
1448*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pFiles = sizeof(DROPFILES);
1449*f6dc9357SAndroid Build Coastguard Worker     dropFiles->fWide = FALSE;
1450*f6dc9357SAndroid Build Coastguard Worker     CHAR *p = (CHAR *) (void *) ((BYTE *)dropFiles + sizeof(DROPFILES));
1451*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < namesA.Size(); i++)
1452*f6dc9357SAndroid Build Coastguard Worker     {
1453*f6dc9357SAndroid Build Coastguard Worker       const AString &s = namesA[i];
1454*f6dc9357SAndroid Build Coastguard Worker       const unsigned fullLen = s.Len() + 1;
1455*f6dc9357SAndroid Build Coastguard Worker       MyStringCopy(p, (const char *)s);
1456*f6dc9357SAndroid Build Coastguard Worker       p += fullLen;
1457*f6dc9357SAndroid Build Coastguard Worker       totalLen -= fullLen;
1458*f6dc9357SAndroid Build Coastguard Worker     }
1459*f6dc9357SAndroid Build Coastguard Worker     *p = 0;
1460*f6dc9357SAndroid Build Coastguard Worker   }
1461*f6dc9357SAndroid Build Coastguard Worker   else
1462*f6dc9357SAndroid Build Coastguard Worker   #endif
1463*f6dc9357SAndroid Build Coastguard Worker   {
1464*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1465*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < names.Size(); i++)
1466*f6dc9357SAndroid Build Coastguard Worker       totalLen += names[i].Len() + 1;
1467*f6dc9357SAndroid Build Coastguard Worker 
1468*f6dc9357SAndroid Build Coastguard Worker     if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(WCHAR) + sizeof(DROPFILES)))
1469*f6dc9357SAndroid Build Coastguard Worker       return false;
1470*f6dc9357SAndroid Build Coastguard Worker 
1471*f6dc9357SAndroid Build Coastguard Worker     NMemory::CGlobalLock dropLock(hgDrop);
1472*f6dc9357SAndroid Build Coastguard Worker     DROPFILES *dropFiles = (DROPFILES *)dropLock.GetPointer();
1473*f6dc9357SAndroid Build Coastguard Worker     if (!dropFiles)
1474*f6dc9357SAndroid Build Coastguard Worker       return false;
1475*f6dc9357SAndroid Build Coastguard Worker     /* fNC:
1476*f6dc9357SAndroid Build Coastguard Worker         TRUE  : pt specifies the screen coordinates of a point in a window's nonclient area.
1477*f6dc9357SAndroid Build Coastguard Worker         FALSE : pt specifies the client coordinates of a point in the client area.
1478*f6dc9357SAndroid Build Coastguard Worker     */
1479*f6dc9357SAndroid Build Coastguard Worker     dropFiles->fNC = FALSE;
1480*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pt.x = 0;
1481*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pt.y = 0;
1482*f6dc9357SAndroid Build Coastguard Worker     dropFiles->pFiles = sizeof(DROPFILES);
1483*f6dc9357SAndroid Build Coastguard Worker     dropFiles->fWide = TRUE;
1484*f6dc9357SAndroid Build Coastguard Worker     WCHAR *p = (WCHAR *) (void *) ((BYTE *)dropFiles + sizeof(DROPFILES));
1485*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < names.Size(); i++)
1486*f6dc9357SAndroid Build Coastguard Worker     {
1487*f6dc9357SAndroid Build Coastguard Worker       const UString &s = names[i];
1488*f6dc9357SAndroid Build Coastguard Worker       const unsigned fullLen = s.Len() + 1;
1489*f6dc9357SAndroid Build Coastguard Worker       MyStringCopy(p, (const WCHAR *)s);
1490*f6dc9357SAndroid Build Coastguard Worker       p += fullLen;
1491*f6dc9357SAndroid Build Coastguard Worker       totalLen -= fullLen;
1492*f6dc9357SAndroid Build Coastguard Worker     }
1493*f6dc9357SAndroid Build Coastguard Worker     *p = 0;
1494*f6dc9357SAndroid Build Coastguard Worker   }
1495*f6dc9357SAndroid Build Coastguard Worker   // if (totalLen != 1) return false;
1496*f6dc9357SAndroid Build Coastguard Worker   return true;
1497*f6dc9357SAndroid Build Coastguard Worker }
1498*f6dc9357SAndroid Build Coastguard Worker 
1499*f6dc9357SAndroid Build Coastguard Worker 
OnDrag(LPNMLISTVIEW,bool isRightButton)1500*f6dc9357SAndroid Build Coastguard Worker void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */, bool isRightButton)
1501*f6dc9357SAndroid Build Coastguard Worker {
1502*f6dc9357SAndroid Build Coastguard Worker   PRF("CPanel::OnDrag");
1503*f6dc9357SAndroid Build Coastguard Worker   if (!DoesItSupportOperations())
1504*f6dc9357SAndroid Build Coastguard Worker     return;
1505*f6dc9357SAndroid Build Coastguard Worker 
1506*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing2(*this);
1507*f6dc9357SAndroid Build Coastguard Worker 
1508*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> indices;
1509*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Operated(indices);
1510*f6dc9357SAndroid Build Coastguard Worker   if (indices.Size() == 0)
1511*f6dc9357SAndroid Build Coastguard Worker     return;
1512*f6dc9357SAndroid Build Coastguard Worker 
1513*f6dc9357SAndroid Build Coastguard Worker   // CSelectedState selState;
1514*f6dc9357SAndroid Build Coastguard Worker   // SaveSelectedState(selState);
1515*f6dc9357SAndroid Build Coastguard Worker 
1516*f6dc9357SAndroid Build Coastguard Worker   const bool isFSFolder = IsFSFolder();
1517*f6dc9357SAndroid Build Coastguard Worker   // why we don't allow drag with rightButton from archive?
1518*f6dc9357SAndroid Build Coastguard Worker   if (!isFSFolder && isRightButton)
1519*f6dc9357SAndroid Build Coastguard Worker     return;
1520*f6dc9357SAndroid Build Coastguard Worker 
1521*f6dc9357SAndroid Build Coastguard Worker   UString dirPrefix;
1522*f6dc9357SAndroid Build Coastguard Worker   CTempDir tempDirectory;
1523*f6dc9357SAndroid Build Coastguard Worker 
1524*f6dc9357SAndroid Build Coastguard Worker   CDataObject *dataObjectSpec = new CDataObject;
1525*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IDataObject> dataObject = dataObjectSpec;
1526*f6dc9357SAndroid Build Coastguard Worker   dataObjectSpec->IsRightButton = isRightButton;
1527*f6dc9357SAndroid Build Coastguard Worker 
1528*f6dc9357SAndroid Build Coastguard Worker   {
1529*f6dc9357SAndroid Build Coastguard Worker     /* we can change confirmation mode and another options.
1530*f6dc9357SAndroid Build Coastguard Worker        Explorer target requests that FILEOP_FLAGS value. */
1531*f6dc9357SAndroid Build Coastguard Worker     /*
1532*f6dc9357SAndroid Build Coastguard Worker     const FILEOP_FLAGS fopFlags =
1533*f6dc9357SAndroid Build Coastguard Worker         FOF_NOCONFIRMATION
1534*f6dc9357SAndroid Build Coastguard Worker       | FOF_NOCONFIRMMKDIR
1535*f6dc9357SAndroid Build Coastguard Worker       | FOF_NOERRORUI
1536*f6dc9357SAndroid Build Coastguard Worker       | FOF_SILENT;
1537*f6dc9357SAndroid Build Coastguard Worker       // | FOF_SIMPLEPROGRESS; // it doesn't work as expected in Win10
1538*f6dc9357SAndroid Build Coastguard Worker     Global_SetUInt32(dataObjectSpec->m_hGlobal_FileOpFlags, fopFlags);
1539*f6dc9357SAndroid Build Coastguard Worker     // dataObjectSpec->m_hGlobal_FileOpFlags.Free(); // for debug : disable these options
1540*f6dc9357SAndroid Build Coastguard Worker     */
1541*f6dc9357SAndroid Build Coastguard Worker   }
1542*f6dc9357SAndroid Build Coastguard Worker   {
1543*f6dc9357SAndroid Build Coastguard Worker     /* we can change Preferred DropEffect.
1544*f6dc9357SAndroid Build Coastguard Worker        Explorer target requests that FILEOP_FLAGS value. */
1545*f6dc9357SAndroid Build Coastguard Worker     /*
1546*f6dc9357SAndroid Build Coastguard Worker     const DWORD effect = DROPEFFECT_MOVE; // DROPEFFECT_COPY;
1547*f6dc9357SAndroid Build Coastguard Worker     Global_SetUInt32(dataObjectSpec->m_hGlobal_PreferredDropEffect, effect);
1548*f6dc9357SAndroid Build Coastguard Worker     */
1549*f6dc9357SAndroid Build Coastguard Worker   }
1550*f6dc9357SAndroid Build Coastguard Worker   if (isFSFolder)
1551*f6dc9357SAndroid Build Coastguard Worker   {
1552*f6dc9357SAndroid Build Coastguard Worker     dirPrefix = GetFsPath(); // why this in 22.01 ?
1553*f6dc9357SAndroid Build Coastguard Worker     dataObjectSpec->UsePreGlobal = false;
1554*f6dc9357SAndroid Build Coastguard Worker     // dataObjectSpec->IsTempFiles = false;
1555*f6dc9357SAndroid Build Coastguard Worker   }
1556*f6dc9357SAndroid Build Coastguard Worker   else
1557*f6dc9357SAndroid Build Coastguard Worker   {
1558*f6dc9357SAndroid Build Coastguard Worker     if (!tempDirectory.Create(kTempDirPrefix))
1559*f6dc9357SAndroid Build Coastguard Worker     {
1560*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error(L"Can't create temp folder");
1561*f6dc9357SAndroid Build Coastguard Worker       return;
1562*f6dc9357SAndroid Build Coastguard Worker     }
1563*f6dc9357SAndroid Build Coastguard Worker     dirPrefix = fs2us(tempDirectory.GetPath());
1564*f6dc9357SAndroid Build Coastguard Worker     {
1565*f6dc9357SAndroid Build Coastguard Worker       UStringVector names;
1566*f6dc9357SAndroid Build Coastguard Worker       names.Add(dirPrefix);
1567*f6dc9357SAndroid Build Coastguard Worker       dataObjectSpec->IsTempFiles = true;
1568*f6dc9357SAndroid Build Coastguard Worker       dataObjectSpec->UsePreGlobal = true;
1569*f6dc9357SAndroid Build Coastguard Worker       if (!CopyNamesToHGlobal(dataObjectSpec->m_hGlobal_HDROP_Pre, names))
1570*f6dc9357SAndroid Build Coastguard Worker         return;
1571*f6dc9357SAndroid Build Coastguard Worker     }
1572*f6dc9357SAndroid Build Coastguard Worker     NFile::NName::NormalizeDirPathPrefix(dirPrefix);
1573*f6dc9357SAndroid Build Coastguard Worker     /*
1574*f6dc9357SAndroid Build Coastguard Worker     {
1575*f6dc9357SAndroid Build Coastguard Worker       FString path2 = dirPrefix;
1576*f6dc9357SAndroid Build Coastguard Worker       path2 += "1.txt";
1577*f6dc9357SAndroid Build Coastguard Worker       CopyFileW(L"C:\\1\\1.txt", path2, FALSE);
1578*f6dc9357SAndroid Build Coastguard Worker     }
1579*f6dc9357SAndroid Build Coastguard Worker     */
1580*f6dc9357SAndroid Build Coastguard Worker   }
1581*f6dc9357SAndroid Build Coastguard Worker 
1582*f6dc9357SAndroid Build Coastguard Worker   {
1583*f6dc9357SAndroid Build Coastguard Worker     UStringVector names;
1584*f6dc9357SAndroid Build Coastguard Worker     // names variable is     USED for drag and drop from 7-zip to Explorer or to 7-zip archive folder.
1585*f6dc9357SAndroid Build Coastguard Worker     // names variable is NOT USED for drag and drop from 7-zip to 7-zip File System folder.
1586*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, indices)
1587*f6dc9357SAndroid Build Coastguard Worker     {
1588*f6dc9357SAndroid Build Coastguard Worker       const UInt32 index = indices[i];
1589*f6dc9357SAndroid Build Coastguard Worker       UString s;
1590*f6dc9357SAndroid Build Coastguard Worker       if (isFSFolder)
1591*f6dc9357SAndroid Build Coastguard Worker         s = GetItemRelPath(index);
1592*f6dc9357SAndroid Build Coastguard Worker       else
1593*f6dc9357SAndroid Build Coastguard Worker       {
1594*f6dc9357SAndroid Build Coastguard Worker         s = GetItemName(index);
1595*f6dc9357SAndroid Build Coastguard Worker         /*
1596*f6dc9357SAndroid Build Coastguard Worker         // We use (keepAndReplaceEmptyPrefixes = true) in CAgentFolder::Extract
1597*f6dc9357SAndroid Build Coastguard Worker         // So the following code is not required.
1598*f6dc9357SAndroid Build Coastguard Worker         // Maybe we also can change IFolder interface and send some flag also.
1599*f6dc9357SAndroid Build Coastguard Worker         if (s.IsEmpty())
1600*f6dc9357SAndroid Build Coastguard Worker         {
1601*f6dc9357SAndroid Build Coastguard Worker           // Correct_FsFile_Name("") returns "_".
1602*f6dc9357SAndroid Build Coastguard Worker           // If extracting code removes empty folder prefixes from path (as it was in old version),
1603*f6dc9357SAndroid Build Coastguard Worker           // Explorer can't find "_" folder in temp folder.
1604*f6dc9357SAndroid Build Coastguard Worker           // We can ask Explorer to copy parent temp folder "7zE" instead.
1605*f6dc9357SAndroid Build Coastguard Worker           names.Clear();
1606*f6dc9357SAndroid Build Coastguard Worker           names.Add(dirPrefix2);
1607*f6dc9357SAndroid Build Coastguard Worker           break;
1608*f6dc9357SAndroid Build Coastguard Worker         }
1609*f6dc9357SAndroid Build Coastguard Worker         */
1610*f6dc9357SAndroid Build Coastguard Worker         s = Get_Correct_FsFile_Name(s);
1611*f6dc9357SAndroid Build Coastguard Worker       }
1612*f6dc9357SAndroid Build Coastguard Worker       names.Add(dirPrefix + s);
1613*f6dc9357SAndroid Build Coastguard Worker     }
1614*f6dc9357SAndroid Build Coastguard Worker     if (!CopyNamesToHGlobal(dataObjectSpec->m_hGlobal_HDROP_Final, names))
1615*f6dc9357SAndroid Build Coastguard Worker       return;
1616*f6dc9357SAndroid Build Coastguard Worker   }
1617*f6dc9357SAndroid Build Coastguard Worker 
1618*f6dc9357SAndroid Build Coastguard Worker   CDropSource *dropSourceSpec = new CDropSource;
1619*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IDropSource> dropSource = dropSourceSpec;
1620*f6dc9357SAndroid Build Coastguard Worker   dataObjectSpec->Panel = this;
1621*f6dc9357SAndroid Build Coastguard Worker   dataObjectSpec->Indices = indices;
1622*f6dc9357SAndroid Build Coastguard Worker   dataObjectSpec->SrcDirPrefix_Temp = dirPrefix;
1623*f6dc9357SAndroid Build Coastguard Worker 
1624*f6dc9357SAndroid Build Coastguard Worker   dropSourceSpec->DataObjectSpec = dataObjectSpec;
1625*f6dc9357SAndroid Build Coastguard Worker   dropSourceSpec->DataObject = dataObjectSpec;
1626*f6dc9357SAndroid Build Coastguard Worker 
1627*f6dc9357SAndroid Build Coastguard Worker 
1628*f6dc9357SAndroid Build Coastguard Worker   /*
1629*f6dc9357SAndroid Build Coastguard Worker   CTime - file creation timestamp.
1630*f6dc9357SAndroid Build Coastguard Worker   There are two operations in Windows with Drag and Drop:
1631*f6dc9357SAndroid Build Coastguard Worker     COPY_OPERATION : icon with    Plus sign : CTime will be set as current_time.
1632*f6dc9357SAndroid Build Coastguard Worker     MOVE_OPERATION : icon without Plus sign : CTime will be preserved.
1633*f6dc9357SAndroid Build Coastguard Worker 
1634*f6dc9357SAndroid Build Coastguard Worker   Note: if we call DoDragDrop() with (effectsOK = DROPEFFECT_MOVE), then
1635*f6dc9357SAndroid Build Coastguard Worker     it will use MOVE_OPERATION and CTime will be preserved.
1636*f6dc9357SAndroid Build Coastguard Worker     But MoveFile() function doesn't preserve CTime, if different volumes are used.
1637*f6dc9357SAndroid Build Coastguard Worker     Why it's so?
1638*f6dc9357SAndroid Build Coastguard Worker     Does DoDragDrop() use some another function (not MoveFile())?
1639*f6dc9357SAndroid Build Coastguard Worker 
1640*f6dc9357SAndroid Build Coastguard Worker   if (effectsOK == DROPEFFECT_COPY) it works as COPY_OPERATION
1641*f6dc9357SAndroid Build Coastguard Worker 
1642*f6dc9357SAndroid Build Coastguard Worker   if (effectsOK == DROPEFFECT_MOVE) drag works as MOVE_OPERATION
1643*f6dc9357SAndroid Build Coastguard Worker 
1644*f6dc9357SAndroid Build Coastguard Worker   if (effectsOK == (DROPEFFECT_COPY | DROPEFFECT_MOVE))
1645*f6dc9357SAndroid Build Coastguard Worker   {
1646*f6dc9357SAndroid Build Coastguard Worker     if we drag file to same volume, then Windows suggests:
1647*f6dc9357SAndroid Build Coastguard Worker        CTRL      - COPY_OPERATION
1648*f6dc9357SAndroid Build Coastguard Worker        [default] - MOVE_OPERATION
1649*f6dc9357SAndroid Build Coastguard Worker 
1650*f6dc9357SAndroid Build Coastguard Worker     if we drag file to another volume, then Windows suggests
1651*f6dc9357SAndroid Build Coastguard Worker        [default] - COPY_OPERATION
1652*f6dc9357SAndroid Build Coastguard Worker        SHIFT     - MOVE_OPERATION
1653*f6dc9357SAndroid Build Coastguard Worker   }
1654*f6dc9357SAndroid Build Coastguard Worker 
1655*f6dc9357SAndroid Build Coastguard Worker   We want to use MOVE_OPERATION for extracting from archive (open in 7-Zip) to Explorer:
1656*f6dc9357SAndroid Build Coastguard Worker   It has the following advantages:
1657*f6dc9357SAndroid Build Coastguard Worker     1) it uses fast MOVE_OPERATION instead of slow COPY_OPERATION and DELETE, if same volume.
1658*f6dc9357SAndroid Build Coastguard Worker     2) it preserves CTime
1659*f6dc9357SAndroid Build Coastguard Worker 
1660*f6dc9357SAndroid Build Coastguard Worker   Some another programs support only COPY_OPERATION.
1661*f6dc9357SAndroid Build Coastguard Worker   So we can use (DROPEFFECT_COPY | DROPEFFECT_MOVE)
1662*f6dc9357SAndroid Build Coastguard Worker 
1663*f6dc9357SAndroid Build Coastguard Worker   Also another program can return from DoDragDrop() before
1664*f6dc9357SAndroid Build Coastguard Worker   files using. But we delete temp folder after DoDragDrop(),
1665*f6dc9357SAndroid Build Coastguard Worker   and another program can't open input files in that case.
1666*f6dc9357SAndroid Build Coastguard Worker 
1667*f6dc9357SAndroid Build Coastguard Worker   We create objects:
1668*f6dc9357SAndroid Build Coastguard Worker     IDropSource *dropSource
1669*f6dc9357SAndroid Build Coastguard Worker     IDataObject *dataObject
1670*f6dc9357SAndroid Build Coastguard Worker   if DropTarget is 7-Zip window, then 7-Zip's
1671*f6dc9357SAndroid Build Coastguard Worker     IDropTarget::DragOver() sets DestDirPrefix_FromTarget in IDataObject.
1672*f6dc9357SAndroid Build Coastguard Worker   and
1673*f6dc9357SAndroid Build Coastguard Worker     IDropSource::QueryContinueDrag() sets DoNotProcessInTarget, if DestDirPrefix_FromTarget is not empty.
1674*f6dc9357SAndroid Build Coastguard Worker   So we can detect destination path after DoDragDrop().
1675*f6dc9357SAndroid Build Coastguard Worker   Now we don't know any good way to detect destination path for D&D to Explorer.
1676*f6dc9357SAndroid Build Coastguard Worker   */
1677*f6dc9357SAndroid Build Coastguard Worker 
1678*f6dc9357SAndroid Build Coastguard Worker   /*
1679*f6dc9357SAndroid Build Coastguard Worker   DWORD effectsOK = DROPEFFECT_COPY;
1680*f6dc9357SAndroid Build Coastguard Worker   if (moveIsAllowed)
1681*f6dc9357SAndroid Build Coastguard Worker     effectsOK |= DROPEFFECT_MOVE;
1682*f6dc9357SAndroid Build Coastguard Worker   */
1683*f6dc9357SAndroid Build Coastguard Worker   const bool moveIsAllowed = isFSFolder;
1684*f6dc9357SAndroid Build Coastguard Worker   _panelCallback->DragBegin();
1685*f6dc9357SAndroid Build Coastguard Worker   PRF("=== DoDragDrop()");
1686*f6dc9357SAndroid Build Coastguard Worker   DWORD effect = 0;
1687*f6dc9357SAndroid Build Coastguard Worker   // 18.04: was changed
1688*f6dc9357SAndroid Build Coastguard Worker   const DWORD effectsOK = DROPEFFECT_MOVE | DROPEFFECT_COPY;
1689*f6dc9357SAndroid Build Coastguard Worker   // effectsOK |= (1 << 8); // for debug
1690*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = ::DoDragDrop(dataObject, dropSource, effectsOK, &effect);
1691*f6dc9357SAndroid Build Coastguard Worker   PRF("=== After DoDragDrop()");
1692*f6dc9357SAndroid Build Coastguard Worker   _panelCallback->DragEnd();
1693*f6dc9357SAndroid Build Coastguard Worker 
1694*f6dc9357SAndroid Build Coastguard Worker   /*
1695*f6dc9357SAndroid Build Coastguard Worker     Win10 drag and drop to Explorer:
1696*f6dc9357SAndroid Build Coastguard Worker       DoDragDrop() output variables:
1697*f6dc9357SAndroid Build Coastguard Worker        for MOVE operation:
1698*f6dc9357SAndroid Build Coastguard Worker        {
1699*f6dc9357SAndroid Build Coastguard Worker          effect == DROPEFFECT_NONE;
1700*f6dc9357SAndroid Build Coastguard Worker          dropSourceSpec->m_PerformedDropEffect == DROPEFFECT_MOVE;
1701*f6dc9357SAndroid Build Coastguard Worker        }
1702*f6dc9357SAndroid Build Coastguard Worker        for COPY operation:
1703*f6dc9357SAndroid Build Coastguard Worker        {
1704*f6dc9357SAndroid Build Coastguard Worker          effect == DROPEFFECT_COPY;
1705*f6dc9357SAndroid Build Coastguard Worker          dropSourceSpec->m_PerformedDropEffect == DROPEFFECT_COPY;
1706*f6dc9357SAndroid Build Coastguard Worker        }
1707*f6dc9357SAndroid Build Coastguard Worker     DOCs: The source inspects the two values that can be returned by the target.
1708*f6dc9357SAndroid Build Coastguard Worker        If both are set to DROPEFFECT_MOVE, it completes the unoptimized move
1709*f6dc9357SAndroid Build Coastguard Worker        by deleting the original data. Otherwise, the target did an optimized
1710*f6dc9357SAndroid Build Coastguard Worker        move and the original data has been deleted.
1711*f6dc9357SAndroid Build Coastguard Worker 
1712*f6dc9357SAndroid Build Coastguard Worker     We didn't see "unoptimized move" case (two values of DROPEFFECT_MOVE),
1713*f6dc9357SAndroid Build Coastguard Worker     where we still need to delete source files.
1714*f6dc9357SAndroid Build Coastguard Worker     So we don't delete files after DoDragDrop().
1715*f6dc9357SAndroid Build Coastguard Worker 
1716*f6dc9357SAndroid Build Coastguard Worker     Also DOCs say for "optimized move":
1717*f6dc9357SAndroid Build Coastguard Worker       The target also calls the data object's IDataObject::SetData method and passes
1718*f6dc9357SAndroid Build Coastguard Worker       it a CFSTR_PERFORMEDDROPEFFECT format identifier set to DROPEFFECT_NONE.
1719*f6dc9357SAndroid Build Coastguard Worker     but actually in Win10 we always have
1720*f6dc9357SAndroid Build Coastguard Worker       (dropSourceSpec->m_PerformedDropEffect == DROPEFFECT_MOVE)
1721*f6dc9357SAndroid Build Coastguard Worker     for any MOVE operation.
1722*f6dc9357SAndroid Build Coastguard Worker   */
1723*f6dc9357SAndroid Build Coastguard Worker 
1724*f6dc9357SAndroid Build Coastguard Worker   const bool canceled = (res == DRAGDROP_S_CANCEL);
1725*f6dc9357SAndroid Build Coastguard Worker 
1726*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
1727*f6dc9357SAndroid Build Coastguard Worker 
1728*f6dc9357SAndroid Build Coastguard Worker   if (res == DRAGDROP_S_DROP)
1729*f6dc9357SAndroid Build Coastguard Worker   {
1730*f6dc9357SAndroid Build Coastguard Worker     /* DRAGDROP_S_DROP is returned. It means that
1731*f6dc9357SAndroid Build Coastguard Worker          - IDropTarget::Drop() was called,
1732*f6dc9357SAndroid Build Coastguard Worker          - IDropTarget::Drop() returned (ret_code >= 0)
1733*f6dc9357SAndroid Build Coastguard Worker     */
1734*f6dc9357SAndroid Build Coastguard Worker     res = dataObjectSpec->Copy_HRESULT;
1735*f6dc9357SAndroid Build Coastguard Worker     bool need_Process = dataObjectSpec->DoNotProcessInTarget;
1736*f6dc9357SAndroid Build Coastguard Worker     if (dataObjectSpec->m_Transfer_WasSet)
1737*f6dc9357SAndroid Build Coastguard Worker     {
1738*f6dc9357SAndroid Build Coastguard Worker       if (dataObjectSpec->m_Transfer.Target.FuncType == k_DragTargetMode_Drop_End)
1739*f6dc9357SAndroid Build Coastguard Worker       {
1740*f6dc9357SAndroid Build Coastguard Worker         if (dataObjectSpec->m_Transfer.Target.Flags & k_TargetFlags_MustBeProcessedBySource)
1741*f6dc9357SAndroid Build Coastguard Worker           need_Process = true;
1742*f6dc9357SAndroid Build Coastguard Worker       }
1743*f6dc9357SAndroid Build Coastguard Worker     }
1744*f6dc9357SAndroid Build Coastguard Worker 
1745*f6dc9357SAndroid Build Coastguard Worker     if (need_Process)
1746*f6dc9357SAndroid Build Coastguard Worker       if (!dataObjectSpec->DestDirPrefix_FromTarget.IsEmpty())
1747*f6dc9357SAndroid Build Coastguard Worker       {
1748*f6dc9357SAndroid Build Coastguard Worker         if (!NFile::NName::IsAltStreamPrefixWithColon(dataObjectSpec->DestDirPrefix_FromTarget))
1749*f6dc9357SAndroid Build Coastguard Worker           NFile::NName::NormalizeDirPathPrefix(dataObjectSpec->DestDirPrefix_FromTarget);
1750*f6dc9357SAndroid Build Coastguard Worker         CCopyToOptions options;
1751*f6dc9357SAndroid Build Coastguard Worker         options.folder = dataObjectSpec->DestDirPrefix_FromTarget;
1752*f6dc9357SAndroid Build Coastguard Worker         // if MOVE is not allowed, we just use COPY operation
1753*f6dc9357SAndroid Build Coastguard Worker         /* it was 7-zip's Target that set non-empty dataObjectSpec->DestDirPrefix_FromTarget.
1754*f6dc9357SAndroid Build Coastguard Worker            it means that target didn't completed operation,
1755*f6dc9357SAndroid Build Coastguard Worker            and we can use (effect) value returned by target via DoDragDrop().
1756*f6dc9357SAndroid Build Coastguard Worker            as indicator of type of operation
1757*f6dc9357SAndroid Build Coastguard Worker         */
1758*f6dc9357SAndroid Build Coastguard Worker         // options.moveMode = (moveIsAllowed && effect == DROPEFFECT_MOVE) // before v23.00:
1759*f6dc9357SAndroid Build Coastguard Worker         options.moveMode = moveIsAllowed;
1760*f6dc9357SAndroid Build Coastguard Worker         if (moveIsAllowed)
1761*f6dc9357SAndroid Build Coastguard Worker         {
1762*f6dc9357SAndroid Build Coastguard Worker           if (dataObjectSpec->m_Transfer_WasSet)
1763*f6dc9357SAndroid Build Coastguard Worker             options.moveMode = (
1764*f6dc9357SAndroid Build Coastguard Worker               dataObjectSpec->m_Transfer.Target.Cmd_Effect == DROPEFFECT_MOVE);
1765*f6dc9357SAndroid Build Coastguard Worker           else
1766*f6dc9357SAndroid Build Coastguard Worker             options.moveMode = (effect == DROPEFFECT_MOVE);
1767*f6dc9357SAndroid Build Coastguard Worker             // we expect (DROPEFFECT_MOVE) as indicator of move operation for Drag&Drop MOVE ver 22.01.
1768*f6dc9357SAndroid Build Coastguard Worker         }
1769*f6dc9357SAndroid Build Coastguard Worker         res = CopyTo(options, indices, &dataObjectSpec->Messages);
1770*f6dc9357SAndroid Build Coastguard Worker       }
1771*f6dc9357SAndroid Build Coastguard Worker     /*
1772*f6dc9357SAndroid Build Coastguard Worker     if (effect & DROPEFFECT_MOVE)
1773*f6dc9357SAndroid Build Coastguard Worker       RefreshListCtrl(selState);
1774*f6dc9357SAndroid Build Coastguard Worker     */
1775*f6dc9357SAndroid Build Coastguard Worker   }
1776*f6dc9357SAndroid Build Coastguard Worker   else
1777*f6dc9357SAndroid Build Coastguard Worker   {
1778*f6dc9357SAndroid Build Coastguard Worker     // we ignore E_UNEXPECTED that is returned if we drag file to printer
1779*f6dc9357SAndroid Build Coastguard Worker     if (res != DRAGDROP_S_CANCEL
1780*f6dc9357SAndroid Build Coastguard Worker         && res != S_OK
1781*f6dc9357SAndroid Build Coastguard Worker         && res != E_UNEXPECTED)
1782*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT(res);
1783*f6dc9357SAndroid Build Coastguard Worker     res = dataObjectSpec->Copy_HRESULT;
1784*f6dc9357SAndroid Build Coastguard Worker   }
1785*f6dc9357SAndroid Build Coastguard Worker 
1786*f6dc9357SAndroid Build Coastguard Worker   if (!dataObjectSpec->Messages.IsEmpty())
1787*f6dc9357SAndroid Build Coastguard Worker   {
1788*f6dc9357SAndroid Build Coastguard Worker     CMessagesDialog messagesDialog;
1789*f6dc9357SAndroid Build Coastguard Worker     messagesDialog.Messages = &dataObjectSpec->Messages;
1790*f6dc9357SAndroid Build Coastguard Worker     messagesDialog.Create((*this));
1791*f6dc9357SAndroid Build Coastguard Worker   }
1792*f6dc9357SAndroid Build Coastguard Worker 
1793*f6dc9357SAndroid Build Coastguard Worker   if (res != S_OK && res != E_ABORT)
1794*f6dc9357SAndroid Build Coastguard Worker   {
1795*f6dc9357SAndroid Build Coastguard Worker     // we restore Notify before MessageBox_Error_HRESULT. So we will see files selection
1796*f6dc9357SAndroid Build Coastguard Worker     disableNotify.Restore();
1797*f6dc9357SAndroid Build Coastguard Worker     // SetFocusToList();
1798*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT(res);
1799*f6dc9357SAndroid Build Coastguard Worker   }
1800*f6dc9357SAndroid Build Coastguard Worker   if (res == S_OK && dataObjectSpec->Messages.IsEmpty() && !canceled)
1801*f6dc9357SAndroid Build Coastguard Worker     KillSelection();
1802*f6dc9357SAndroid Build Coastguard Worker }
1803*f6dc9357SAndroid Build Coastguard Worker 
1804*f6dc9357SAndroid Build Coastguard Worker 
1805*f6dc9357SAndroid Build Coastguard Worker 
1806*f6dc9357SAndroid Build Coastguard Worker 
1807*f6dc9357SAndroid Build Coastguard Worker 
CDropTarget()1808*f6dc9357SAndroid Build Coastguard Worker CDropTarget::CDropTarget():
1809*f6dc9357SAndroid Build Coastguard Worker       m_IsRightButton(false),
1810*f6dc9357SAndroid Build Coastguard Worker       m_GetTransfer_WasSuccess(false),
1811*f6dc9357SAndroid Build Coastguard Worker       m_DropIsAllowed(false),
1812*f6dc9357SAndroid Build Coastguard Worker       m_PanelDropIsAllowed(false),
1813*f6dc9357SAndroid Build Coastguard Worker       // m_DropHighlighted_SelectionIndex(-1),
1814*f6dc9357SAndroid Build Coastguard Worker       // m_SubFolderIndex(-1),
1815*f6dc9357SAndroid Build Coastguard Worker       m_Panel(NULL),
1816*f6dc9357SAndroid Build Coastguard Worker       m_IsAppTarget(false),
1817*f6dc9357SAndroid Build Coastguard Worker       m_TargetPath_WasSent_ToDataObject(false),
1818*f6dc9357SAndroid Build Coastguard Worker       m_TargetPath_NonEmpty_WasSent_ToDataObject(false),
1819*f6dc9357SAndroid Build Coastguard Worker       m_Transfer_WasSent_ToDataObject(false),
1820*f6dc9357SAndroid Build Coastguard Worker       App(NULL),
1821*f6dc9357SAndroid Build Coastguard Worker       SrcPanelIndex(-1),
1822*f6dc9357SAndroid Build Coastguard Worker       TargetPanelIndex(-1)
1823*f6dc9357SAndroid Build Coastguard Worker {
1824*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_SetTargetFolder = RegisterClipboardFormat(k_Format_7zip_SetTargetFolder);
1825*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_SetTransfer     = RegisterClipboardFormat(k_Format_7zip_SetTransfer);
1826*f6dc9357SAndroid Build Coastguard Worker   m_Format_7zip_GetTransfer     = RegisterClipboardFormat(k_Format_7zip_GetTransfer);
1827*f6dc9357SAndroid Build Coastguard Worker 
1828*f6dc9357SAndroid Build Coastguard Worker   m_ProcessId = GetCurrentProcessId();
1829*f6dc9357SAndroid Build Coastguard Worker   // m_TransactionId = ((UInt64)m_ProcessId << 32) + 1;
1830*f6dc9357SAndroid Build Coastguard Worker   // ClearState();
1831*f6dc9357SAndroid Build Coastguard Worker }
1832*f6dc9357SAndroid Build Coastguard Worker 
1833*f6dc9357SAndroid Build Coastguard Worker // clear internal state
ClearState()1834*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::ClearState()
1835*f6dc9357SAndroid Build Coastguard Worker {
1836*f6dc9357SAndroid Build Coastguard Worker   m_DataObject.Release();
1837*f6dc9357SAndroid Build Coastguard Worker   m_SourcePaths.Clear();
1838*f6dc9357SAndroid Build Coastguard Worker 
1839*f6dc9357SAndroid Build Coastguard Worker   m_IsRightButton = false;
1840*f6dc9357SAndroid Build Coastguard Worker 
1841*f6dc9357SAndroid Build Coastguard Worker   m_GetTransfer_WasSuccess = false;
1842*f6dc9357SAndroid Build Coastguard Worker   m_DropIsAllowed = false;
1843*f6dc9357SAndroid Build Coastguard Worker 
1844*f6dc9357SAndroid Build Coastguard Worker   m_PanelDropIsAllowed = false;
1845*f6dc9357SAndroid Build Coastguard Worker   // m_SubFolderIndex = -1;
1846*f6dc9357SAndroid Build Coastguard Worker   // m_DropHighlighted_SubFolderName.Empty();
1847*f6dc9357SAndroid Build Coastguard Worker   m_Panel = NULL;
1848*f6dc9357SAndroid Build Coastguard Worker   m_IsAppTarget = false;
1849*f6dc9357SAndroid Build Coastguard Worker   m_TargetPath_WasSent_ToDataObject = false;
1850*f6dc9357SAndroid Build Coastguard Worker   m_TargetPath_NonEmpty_WasSent_ToDataObject = false;
1851*f6dc9357SAndroid Build Coastguard Worker   m_Transfer_WasSent_ToDataObject = false;
1852*f6dc9357SAndroid Build Coastguard Worker }
1853*f6dc9357SAndroid Build Coastguard Worker 
1854*f6dc9357SAndroid Build Coastguard Worker /*
1855*f6dc9357SAndroid Build Coastguard Worker   IDataObject::QueryGetData() Determines whether the data object is capable of
1856*f6dc9357SAndroid Build Coastguard Worker   rendering the data as specified. Objects attempting a paste or drop
1857*f6dc9357SAndroid Build Coastguard Worker   operation can call this method before calling IDataObject::GetData
1858*f6dc9357SAndroid Build Coastguard Worker   to get an indication of whether the operation may be successful.
1859*f6dc9357SAndroid Build Coastguard Worker 
1860*f6dc9357SAndroid Build Coastguard Worker   The client of a data object calls QueryGetData to determine whether
1861*f6dc9357SAndroid Build Coastguard Worker   passing the specified FORMATETC structure to a subsequent call to
1862*f6dc9357SAndroid Build Coastguard Worker   IDataObject::GetData is likely to be successful.
1863*f6dc9357SAndroid Build Coastguard Worker 
1864*f6dc9357SAndroid Build Coastguard Worker   We check Try_QueryGetData with CF_HDROP
1865*f6dc9357SAndroid Build Coastguard Worker */
1866*f6dc9357SAndroid Build Coastguard Worker /*
1867*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::Try_QueryGetData(IDataObject *dataObject)
1868*f6dc9357SAndroid Build Coastguard Worker {
1869*f6dc9357SAndroid Build Coastguard Worker   FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
1870*f6dc9357SAndroid Build Coastguard Worker   m_DropIsAllowed = (dataObject->QueryGetData(&etc) == S_OK);
1871*f6dc9357SAndroid Build Coastguard Worker }
1872*f6dc9357SAndroid Build Coastguard Worker */
1873*f6dc9357SAndroid Build Coastguard Worker 
ListView_SetItemState_DropHighlighted(NControl::CListView & listView,int index,bool highlighted)1874*f6dc9357SAndroid Build Coastguard Worker static void ListView_SetItemState_DropHighlighted(
1875*f6dc9357SAndroid Build Coastguard Worker     NControl::CListView &listView, int index, bool highlighted)
1876*f6dc9357SAndroid Build Coastguard Worker {
1877*f6dc9357SAndroid Build Coastguard Worker   // LVIS_DROPHILITED : The item is highlighted as a drag-and-drop target
1878*f6dc9357SAndroid Build Coastguard Worker   /*
1879*f6dc9357SAndroid Build Coastguard Worker   LVITEM item;
1880*f6dc9357SAndroid Build Coastguard Worker   item.mask = LVIF_STATE;
1881*f6dc9357SAndroid Build Coastguard Worker   item.iItem = index;
1882*f6dc9357SAndroid Build Coastguard Worker   item.iSubItem = 0;
1883*f6dc9357SAndroid Build Coastguard Worker   item.state = enable ? LVIS_DROPHILITED : 0;
1884*f6dc9357SAndroid Build Coastguard Worker   item.stateMask = LVIS_DROPHILITED;
1885*f6dc9357SAndroid Build Coastguard Worker   item.pszText = NULL;
1886*f6dc9357SAndroid Build Coastguard Worker   listView.SetItem(&item);
1887*f6dc9357SAndroid Build Coastguard Worker   */
1888*f6dc9357SAndroid Build Coastguard Worker   listView.SetItemState(index, highlighted ? LVIS_DROPHILITED : 0, LVIS_DROPHILITED);
1889*f6dc9357SAndroid Build Coastguard Worker }
1890*f6dc9357SAndroid Build Coastguard Worker 
1891*f6dc9357SAndroid Build Coastguard Worker // Removes DropHighlighted state in ListView item, if it was set before
RemoveSelection()1892*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::RemoveSelection()
1893*f6dc9357SAndroid Build Coastguard Worker {
1894*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel)
1895*f6dc9357SAndroid Build Coastguard Worker   {
1896*f6dc9357SAndroid Build Coastguard Worker     m_Panel->m_DropHighlighted_SubFolderName.Empty();
1897*f6dc9357SAndroid Build Coastguard Worker     if (m_Panel->m_DropHighlighted_SelectionIndex >= 0)
1898*f6dc9357SAndroid Build Coastguard Worker     {
1899*f6dc9357SAndroid Build Coastguard Worker       ListView_SetItemState_DropHighlighted(m_Panel->_listView,
1900*f6dc9357SAndroid Build Coastguard Worker           m_Panel->m_DropHighlighted_SelectionIndex, false);
1901*f6dc9357SAndroid Build Coastguard Worker       m_Panel->m_DropHighlighted_SelectionIndex = -1;
1902*f6dc9357SAndroid Build Coastguard Worker     }
1903*f6dc9357SAndroid Build Coastguard Worker   }
1904*f6dc9357SAndroid Build Coastguard Worker }
1905*f6dc9357SAndroid Build Coastguard Worker 
1906*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
1907*f6dc9357SAndroid Build Coastguard Worker #define ChildWindowFromPointEx(hwndParent, pt, uFlags) ChildWindowFromPoint(hwndParent, pt)
1908*f6dc9357SAndroid Build Coastguard Worker #endif
1909*f6dc9357SAndroid Build Coastguard Worker 
1910*f6dc9357SAndroid Build Coastguard Worker 
1911*f6dc9357SAndroid Build Coastguard Worker /*
1912*f6dc9357SAndroid Build Coastguard Worker    PositionCursor() function sets m_Panel under cursor drop, and
1913*f6dc9357SAndroid Build Coastguard Worker    m_SubFolderIndex/m_DropHighlighted_SubFolderName, if drop to some folder in Panel list.
1914*f6dc9357SAndroid Build Coastguard Worker */
1915*f6dc9357SAndroid Build Coastguard Worker /*
1916*f6dc9357SAndroid Build Coastguard Worker PositionCursor() uses as input variables:
1917*f6dc9357SAndroid Build Coastguard Worker   m_DropIsAllowed must be set before PositionCursor()
1918*f6dc9357SAndroid Build Coastguard Worker   if (m_DropHighlighted_SelectionIndex >= 0 && m_Panel) it uses m_Panel and removes previous selection
1919*f6dc9357SAndroid Build Coastguard Worker PositionCursor() sets
1920*f6dc9357SAndroid Build Coastguard Worker   m_PanelDropIsAllowed
1921*f6dc9357SAndroid Build Coastguard Worker   m_Panel
1922*f6dc9357SAndroid Build Coastguard Worker   m_IsAppTarget
1923*f6dc9357SAndroid Build Coastguard Worker   m_SubFolderIndex
1924*f6dc9357SAndroid Build Coastguard Worker   m_DropHighlighted_SubFolderName
1925*f6dc9357SAndroid Build Coastguard Worker   m_DropHighlighted_SelectionIndex
1926*f6dc9357SAndroid Build Coastguard Worker */
PositionCursor(const POINTL & ptl)1927*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::PositionCursor(const POINTL &ptl)
1928*f6dc9357SAndroid Build Coastguard Worker {
1929*f6dc9357SAndroid Build Coastguard Worker   RemoveSelection();
1930*f6dc9357SAndroid Build Coastguard Worker 
1931*f6dc9357SAndroid Build Coastguard Worker   // m_SubFolderIndex = -1;
1932*f6dc9357SAndroid Build Coastguard Worker   // m_DropHighlighted_SubFolderName.Empty();
1933*f6dc9357SAndroid Build Coastguard Worker   m_IsAppTarget = true;
1934*f6dc9357SAndroid Build Coastguard Worker   m_Panel = NULL;
1935*f6dc9357SAndroid Build Coastguard Worker   m_PanelDropIsAllowed = false;
1936*f6dc9357SAndroid Build Coastguard Worker 
1937*f6dc9357SAndroid Build Coastguard Worker   if (!m_DropIsAllowed)
1938*f6dc9357SAndroid Build Coastguard Worker     return;
1939*f6dc9357SAndroid Build Coastguard Worker 
1940*f6dc9357SAndroid Build Coastguard Worker   POINT pt;
1941*f6dc9357SAndroid Build Coastguard Worker   pt.x = ptl.x;
1942*f6dc9357SAndroid Build Coastguard Worker   pt.y = ptl.y;
1943*f6dc9357SAndroid Build Coastguard Worker   {
1944*f6dc9357SAndroid Build Coastguard Worker     POINT pt2 = pt;
1945*f6dc9357SAndroid Build Coastguard Worker     if (App->_window.ScreenToClient(&pt2))
1946*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < kNumPanelsMax; i++)
1947*f6dc9357SAndroid Build Coastguard Worker         if (App->IsPanelVisible(i))
1948*f6dc9357SAndroid Build Coastguard Worker         {
1949*f6dc9357SAndroid Build Coastguard Worker           CPanel *panel = &App->Panels[i];
1950*f6dc9357SAndroid Build Coastguard Worker           if (panel->IsEnabled())
1951*f6dc9357SAndroid Build Coastguard Worker           if (::ChildWindowFromPointEx(App->_window, pt2,
1952*f6dc9357SAndroid Build Coastguard Worker               CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) == (HWND)*panel)
1953*f6dc9357SAndroid Build Coastguard Worker           {
1954*f6dc9357SAndroid Build Coastguard Worker             m_Panel = panel;
1955*f6dc9357SAndroid Build Coastguard Worker             m_IsAppTarget = false;
1956*f6dc9357SAndroid Build Coastguard Worker             if ((int)i == SrcPanelIndex)
1957*f6dc9357SAndroid Build Coastguard Worker               return; // we don't allow to drop to source panel
1958*f6dc9357SAndroid Build Coastguard Worker             break;
1959*f6dc9357SAndroid Build Coastguard Worker           }
1960*f6dc9357SAndroid Build Coastguard Worker         }
1961*f6dc9357SAndroid Build Coastguard Worker   }
1962*f6dc9357SAndroid Build Coastguard Worker 
1963*f6dc9357SAndroid Build Coastguard Worker   m_PanelDropIsAllowed = true;
1964*f6dc9357SAndroid Build Coastguard Worker 
1965*f6dc9357SAndroid Build Coastguard Worker   if (!m_Panel)
1966*f6dc9357SAndroid Build Coastguard Worker   {
1967*f6dc9357SAndroid Build Coastguard Worker     if (TargetPanelIndex >= 0)
1968*f6dc9357SAndroid Build Coastguard Worker       m_Panel = &App->Panels[TargetPanelIndex];
1969*f6dc9357SAndroid Build Coastguard Worker     // we don't need to find item in panel
1970*f6dc9357SAndroid Build Coastguard Worker     return;
1971*f6dc9357SAndroid Build Coastguard Worker   }
1972*f6dc9357SAndroid Build Coastguard Worker 
1973*f6dc9357SAndroid Build Coastguard Worker   // we will try to find and highlight drop folder item in listView under cursor
1974*f6dc9357SAndroid Build Coastguard Worker   /*
1975*f6dc9357SAndroid Build Coastguard Worker   m_PanelDropIsAllowed = m_Panel->DoesItSupportOperations();
1976*f6dc9357SAndroid Build Coastguard Worker   if (!m_PanelDropIsAllowed)
1977*f6dc9357SAndroid Build Coastguard Worker     return;
1978*f6dc9357SAndroid Build Coastguard Worker   */
1979*f6dc9357SAndroid Build Coastguard Worker   /* now we don't allow drop to subfolder under cursor, if dest panel is archive.
1980*f6dc9357SAndroid Build Coastguard Worker      Another code must be fixed for that case, where we must use m_SubFolderIndex/m_DropHighlighted_SubFolderName */
1981*f6dc9357SAndroid Build Coastguard Worker   if (!m_Panel->IsFsOrPureDrivesFolder())
1982*f6dc9357SAndroid Build Coastguard Worker     return;
1983*f6dc9357SAndroid Build Coastguard Worker 
1984*f6dc9357SAndroid Build Coastguard Worker   if (::WindowFromPoint(pt) != (HWND)m_Panel->_listView)
1985*f6dc9357SAndroid Build Coastguard Worker     return;
1986*f6dc9357SAndroid Build Coastguard Worker 
1987*f6dc9357SAndroid Build Coastguard Worker   LVHITTESTINFO info;
1988*f6dc9357SAndroid Build Coastguard Worker   m_Panel->_listView.ScreenToClient(&pt);
1989*f6dc9357SAndroid Build Coastguard Worker   info.pt = pt;
1990*f6dc9357SAndroid Build Coastguard Worker   const int index = ListView_HitTest(m_Panel->_listView, &info);
1991*f6dc9357SAndroid Build Coastguard Worker   if (index < 0)
1992*f6dc9357SAndroid Build Coastguard Worker     return;
1993*f6dc9357SAndroid Build Coastguard Worker   const unsigned realIndex = m_Panel->GetRealItemIndex(index);
1994*f6dc9357SAndroid Build Coastguard Worker   if (realIndex == kParentIndex)
1995*f6dc9357SAndroid Build Coastguard Worker     return;
1996*f6dc9357SAndroid Build Coastguard Worker   if (!m_Panel->IsItem_Folder(realIndex))
1997*f6dc9357SAndroid Build Coastguard Worker     return;
1998*f6dc9357SAndroid Build Coastguard Worker   // m_SubFolderIndex = (int)realIndex;
1999*f6dc9357SAndroid Build Coastguard Worker   m_Panel->m_DropHighlighted_SubFolderName = m_Panel->GetItemName(realIndex);
2000*f6dc9357SAndroid Build Coastguard Worker   ListView_SetItemState_DropHighlighted(m_Panel->_listView, index, true);
2001*f6dc9357SAndroid Build Coastguard Worker   m_Panel->m_DropHighlighted_SelectionIndex = index;
2002*f6dc9357SAndroid Build Coastguard Worker }
2003*f6dc9357SAndroid Build Coastguard Worker 
2004*f6dc9357SAndroid Build Coastguard Worker 
2005*f6dc9357SAndroid Build Coastguard Worker /* returns true, if !m_IsAppTarget
2006*f6dc9357SAndroid Build Coastguard Worker    and target is FS folder or altStream folder
2007*f6dc9357SAndroid Build Coastguard Worker */
2008*f6dc9357SAndroid Build Coastguard Worker 
GetFolderType() const2009*f6dc9357SAndroid Build Coastguard Worker UInt32 CDropTarget::GetFolderType() const
2010*f6dc9357SAndroid Build Coastguard Worker {
2011*f6dc9357SAndroid Build Coastguard Worker   if (m_IsAppTarget || !m_Panel)
2012*f6dc9357SAndroid Build Coastguard Worker     return k_FolderType_None;
2013*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsFSFolder() ||
2014*f6dc9357SAndroid Build Coastguard Worker       (m_Panel->IsFSDrivesFolder()
2015*f6dc9357SAndroid Build Coastguard Worker        && m_Panel->m_DropHighlighted_SelectionIndex >= 0))
2016*f6dc9357SAndroid Build Coastguard Worker     return k_FolderType_Fs;
2017*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsAltStreamsFolder())
2018*f6dc9357SAndroid Build Coastguard Worker     return k_FolderType_AltStreams;
2019*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsArcFolder())
2020*f6dc9357SAndroid Build Coastguard Worker     return k_FolderType_Archive;
2021*f6dc9357SAndroid Build Coastguard Worker   return k_FolderType_Unknown;
2022*f6dc9357SAndroid Build Coastguard Worker }
2023*f6dc9357SAndroid Build Coastguard Worker 
IsFsFolderPath() const2024*f6dc9357SAndroid Build Coastguard Worker bool CDropTarget::IsFsFolderPath() const
2025*f6dc9357SAndroid Build Coastguard Worker {
2026*f6dc9357SAndroid Build Coastguard Worker   if (m_IsAppTarget || !m_Panel)
2027*f6dc9357SAndroid Build Coastguard Worker     return false;
2028*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsFSFolder())
2029*f6dc9357SAndroid Build Coastguard Worker     return true;
2030*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsAltStreamsFolder())
2031*f6dc9357SAndroid Build Coastguard Worker     return true;
2032*f6dc9357SAndroid Build Coastguard Worker   return m_Panel->IsFSDrivesFolder() &&
2033*f6dc9357SAndroid Build Coastguard Worker       m_Panel->m_DropHighlighted_SelectionIndex >= 0;
2034*f6dc9357SAndroid Build Coastguard Worker }
2035*f6dc9357SAndroid Build Coastguard Worker 
2036*f6dc9357SAndroid Build Coastguard Worker 
2037*f6dc9357SAndroid Build Coastguard Worker #define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
2038*f6dc9357SAndroid Build Coastguard Worker 
DataObject_GetData_GetTransfer(IDataObject * dataObject,UINT a_Format_7zip_GetTransfer,CDataObject_GetTransfer & transfer)2039*f6dc9357SAndroid Build Coastguard Worker static bool DataObject_GetData_GetTransfer(IDataObject *dataObject,
2040*f6dc9357SAndroid Build Coastguard Worker     UINT a_Format_7zip_GetTransfer, CDataObject_GetTransfer &transfer)
2041*f6dc9357SAndroid Build Coastguard Worker {
2042*f6dc9357SAndroid Build Coastguard Worker   FORMATETC etc = INIT_FORMATETC_HGLOBAL((CLIPFORMAT)a_Format_7zip_GetTransfer);
2043*f6dc9357SAndroid Build Coastguard Worker   NCOM::CStgMedium medium;
2044*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = dataObject->GetData(&etc, &medium);
2045*f6dc9357SAndroid Build Coastguard Worker   if (res != S_OK)
2046*f6dc9357SAndroid Build Coastguard Worker     return false;
2047*f6dc9357SAndroid Build Coastguard Worker   if (medium.tymed != TYMED_HGLOBAL)
2048*f6dc9357SAndroid Build Coastguard Worker     return false;
2049*f6dc9357SAndroid Build Coastguard Worker   const size_t size = GlobalSize(medium.hGlobal);
2050*f6dc9357SAndroid Build Coastguard Worker   if (size < sizeof(transfer))
2051*f6dc9357SAndroid Build Coastguard Worker     return false;
2052*f6dc9357SAndroid Build Coastguard Worker   NMemory::CGlobalLock dropLock(medium.hGlobal);
2053*f6dc9357SAndroid Build Coastguard Worker   const CDataObject_GetTransfer *t = (const CDataObject_GetTransfer *)dropLock.GetPointer();
2054*f6dc9357SAndroid Build Coastguard Worker   if (!t)
2055*f6dc9357SAndroid Build Coastguard Worker     return false;
2056*f6dc9357SAndroid Build Coastguard Worker   if (!t->Check()) // isSetData
2057*f6dc9357SAndroid Build Coastguard Worker     return false;
2058*f6dc9357SAndroid Build Coastguard Worker   transfer = *t;
2059*f6dc9357SAndroid Build Coastguard Worker   return true;
2060*f6dc9357SAndroid Build Coastguard Worker }
2061*f6dc9357SAndroid Build Coastguard Worker 
2062*f6dc9357SAndroid Build Coastguard Worker /*
2063*f6dc9357SAndroid Build Coastguard Worker   returns true, if all m_SourcePaths[] items are same drive
2064*f6dc9357SAndroid Build Coastguard Worker   as destination drop path in m_Panel
2065*f6dc9357SAndroid Build Coastguard Worker */
IsItSameDrive() const2066*f6dc9357SAndroid Build Coastguard Worker bool CDropTarget::IsItSameDrive() const
2067*f6dc9357SAndroid Build Coastguard Worker {
2068*f6dc9357SAndroid Build Coastguard Worker   if (!m_Panel)
2069*f6dc9357SAndroid Build Coastguard Worker     return false;
2070*f6dc9357SAndroid Build Coastguard Worker   if (!IsFsFolderPath())
2071*f6dc9357SAndroid Build Coastguard Worker     return false;
2072*f6dc9357SAndroid Build Coastguard Worker 
2073*f6dc9357SAndroid Build Coastguard Worker   UString drive;
2074*f6dc9357SAndroid Build Coastguard Worker 
2075*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel->IsFSFolder())
2076*f6dc9357SAndroid Build Coastguard Worker   {
2077*f6dc9357SAndroid Build Coastguard Worker     drive = m_Panel->GetDriveOrNetworkPrefix();
2078*f6dc9357SAndroid Build Coastguard Worker     if (drive.IsEmpty())
2079*f6dc9357SAndroid Build Coastguard Worker       return false;
2080*f6dc9357SAndroid Build Coastguard Worker   }
2081*f6dc9357SAndroid Build Coastguard Worker   else if (m_Panel->IsFSDrivesFolder()
2082*f6dc9357SAndroid Build Coastguard Worker       && m_Panel->m_DropHighlighted_SelectionIndex >= 0)
2083*f6dc9357SAndroid Build Coastguard Worker   {
2084*f6dc9357SAndroid Build Coastguard Worker     drive = m_Panel->m_DropHighlighted_SubFolderName;
2085*f6dc9357SAndroid Build Coastguard Worker     drive.Add_PathSepar();
2086*f6dc9357SAndroid Build Coastguard Worker   }
2087*f6dc9357SAndroid Build Coastguard Worker   else
2088*f6dc9357SAndroid Build Coastguard Worker     return false;
2089*f6dc9357SAndroid Build Coastguard Worker 
2090*f6dc9357SAndroid Build Coastguard Worker   if (m_SourcePaths.Size() == 0)
2091*f6dc9357SAndroid Build Coastguard Worker     return false;
2092*f6dc9357SAndroid Build Coastguard Worker 
2093*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, m_SourcePaths)
2094*f6dc9357SAndroid Build Coastguard Worker   {
2095*f6dc9357SAndroid Build Coastguard Worker     if (!m_SourcePaths[i].IsPrefixedBy_NoCase(drive))
2096*f6dc9357SAndroid Build Coastguard Worker       return false;
2097*f6dc9357SAndroid Build Coastguard Worker   }
2098*f6dc9357SAndroid Build Coastguard Worker   return true;
2099*f6dc9357SAndroid Build Coastguard Worker }
2100*f6dc9357SAndroid Build Coastguard Worker 
2101*f6dc9357SAndroid Build Coastguard Worker 
2102*f6dc9357SAndroid Build Coastguard Worker /*
2103*f6dc9357SAndroid Build Coastguard Worker   There are 2 different actions, when we drag to 7-Zip:
2104*f6dc9357SAndroid Build Coastguard Worker   1) if target panel is "7-Zip" FS and any of the 2 cases:
2105*f6dc9357SAndroid Build Coastguard Worker      - Drag from any non "7-Zip" program;
2106*f6dc9357SAndroid Build Coastguard Worker      or
2107*f6dc9357SAndroid Build Coastguard Worker      - Drag from "7-Zip" to non-panel area of "7-Zip".
2108*f6dc9357SAndroid Build Coastguard Worker      We want to create new archive for that operation with "Add to Archive" window.
2109*f6dc9357SAndroid Build Coastguard Worker   2) all another operations work as usual file COPY/MOVE
2110*f6dc9357SAndroid Build Coastguard Worker     - Drag from "7-Zip" FS to "7-Zip" FS.
2111*f6dc9357SAndroid Build Coastguard Worker         COPY/MOVE are supported.
2112*f6dc9357SAndroid Build Coastguard Worker     - Drag to open archive in 7-Zip.
2113*f6dc9357SAndroid Build Coastguard Worker         We want to update archive.
2114*f6dc9357SAndroid Build Coastguard Worker         We replace COPY to MOVE.
2115*f6dc9357SAndroid Build Coastguard Worker     - Drag from "7-Zip" archive to "7-Zip" FS.
2116*f6dc9357SAndroid Build Coastguard Worker         We replace COPY to MOVE.
2117*f6dc9357SAndroid Build Coastguard Worker */
2118*f6dc9357SAndroid Build Coastguard Worker 
2119*f6dc9357SAndroid Build Coastguard Worker // we try to repeat Explorer's effects.
2120*f6dc9357SAndroid Build Coastguard Worker // out: 0 - means that use default effect
GetEffect_ForKeys(DWORD keyState)2121*f6dc9357SAndroid Build Coastguard Worker static DWORD GetEffect_ForKeys(DWORD keyState)
2122*f6dc9357SAndroid Build Coastguard Worker {
2123*f6dc9357SAndroid Build Coastguard Worker   if (keyState & MK_CONTROL)
2124*f6dc9357SAndroid Build Coastguard Worker   {
2125*f6dc9357SAndroid Build Coastguard Worker     if (keyState & MK_ALT)
2126*f6dc9357SAndroid Build Coastguard Worker       return 0;
2127*f6dc9357SAndroid Build Coastguard Worker     if (keyState & MK_SHIFT)
2128*f6dc9357SAndroid Build Coastguard Worker       return DROPEFFECT_LINK; // CONTROL + SHIFT
2129*f6dc9357SAndroid Build Coastguard Worker     return DROPEFFECT_COPY;   // CONTROL
2130*f6dc9357SAndroid Build Coastguard Worker   }
2131*f6dc9357SAndroid Build Coastguard Worker   // no CONTROL
2132*f6dc9357SAndroid Build Coastguard Worker   if (keyState & MK_SHIFT)
2133*f6dc9357SAndroid Build Coastguard Worker   {
2134*f6dc9357SAndroid Build Coastguard Worker     if (keyState & MK_ALT)
2135*f6dc9357SAndroid Build Coastguard Worker       return 0;
2136*f6dc9357SAndroid Build Coastguard Worker     return DROPEFFECT_MOVE; // SHIFT
2137*f6dc9357SAndroid Build Coastguard Worker   }
2138*f6dc9357SAndroid Build Coastguard Worker   // no CONTROL, no SHIFT
2139*f6dc9357SAndroid Build Coastguard Worker   if (keyState & MK_ALT)
2140*f6dc9357SAndroid Build Coastguard Worker     return DROPEFFECT_LINK; // ALT
2141*f6dc9357SAndroid Build Coastguard Worker   return 0;
2142*f6dc9357SAndroid Build Coastguard Worker }
2143*f6dc9357SAndroid Build Coastguard Worker 
2144*f6dc9357SAndroid Build Coastguard Worker 
2145*f6dc9357SAndroid Build Coastguard Worker /* GetEffect() uses m_TargetPath_WasSentToDataObject
2146*f6dc9357SAndroid Build Coastguard Worker    to disale MOVE operation, if Source is not 7-Zip
2147*f6dc9357SAndroid Build Coastguard Worker */
GetEffect(DWORD keyState,POINTL,DWORD allowedEffect) const2148*f6dc9357SAndroid Build Coastguard Worker DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect) const
2149*f6dc9357SAndroid Build Coastguard Worker {
2150*f6dc9357SAndroid Build Coastguard Worker   // (DROPEFFECT_NONE == 0)
2151*f6dc9357SAndroid Build Coastguard Worker   if (!m_DropIsAllowed || !m_PanelDropIsAllowed)
2152*f6dc9357SAndroid Build Coastguard Worker     return 0;
2153*f6dc9357SAndroid Build Coastguard Worker   if (!IsFsFolderPath() || !m_TargetPath_WasSent_ToDataObject)
2154*f6dc9357SAndroid Build Coastguard Worker   {
2155*f6dc9357SAndroid Build Coastguard Worker     // we don't allow MOVE, if Target is archive or Source is not 7-Zip
2156*f6dc9357SAndroid Build Coastguard Worker     // disabled for debug:
2157*f6dc9357SAndroid Build Coastguard Worker     // allowedEffect &= ~DROPEFFECT_MOVE;
2158*f6dc9357SAndroid Build Coastguard Worker   }
2159*f6dc9357SAndroid Build Coastguard Worker   DWORD effect;
2160*f6dc9357SAndroid Build Coastguard Worker   {
2161*f6dc9357SAndroid Build Coastguard Worker     effect = GetEffect_ForKeys(keyState);
2162*f6dc9357SAndroid Build Coastguard Worker     if (effect == DROPEFFECT_LINK)
2163*f6dc9357SAndroid Build Coastguard Worker       return 0;
2164*f6dc9357SAndroid Build Coastguard Worker     effect &= allowedEffect;
2165*f6dc9357SAndroid Build Coastguard Worker   }
2166*f6dc9357SAndroid Build Coastguard Worker   if (effect == 0)
2167*f6dc9357SAndroid Build Coastguard Worker   {
2168*f6dc9357SAndroid Build Coastguard Worker     if (allowedEffect & DROPEFFECT_COPY)
2169*f6dc9357SAndroid Build Coastguard Worker       effect = DROPEFFECT_COPY;
2170*f6dc9357SAndroid Build Coastguard Worker     if (allowedEffect & DROPEFFECT_MOVE)
2171*f6dc9357SAndroid Build Coastguard Worker     {
2172*f6dc9357SAndroid Build Coastguard Worker       /* MOVE operation can be optimized. So MOVE is preferred way
2173*f6dc9357SAndroid Build Coastguard Worker          for default action, if Source and Target are at same drive */
2174*f6dc9357SAndroid Build Coastguard Worker       if (IsItSameDrive())
2175*f6dc9357SAndroid Build Coastguard Worker         effect = DROPEFFECT_MOVE;
2176*f6dc9357SAndroid Build Coastguard Worker     }
2177*f6dc9357SAndroid Build Coastguard Worker   }
2178*f6dc9357SAndroid Build Coastguard Worker   return effect;
2179*f6dc9357SAndroid Build Coastguard Worker }
2180*f6dc9357SAndroid Build Coastguard Worker 
2181*f6dc9357SAndroid Build Coastguard Worker 
2182*f6dc9357SAndroid Build Coastguard Worker /* returns:
2183*f6dc9357SAndroid Build Coastguard Worker     - target folder path prefix, if target is FS folder
2184*f6dc9357SAndroid Build Coastguard Worker     - empty string, if target is not FS folder
2185*f6dc9357SAndroid Build Coastguard Worker */
GetTargetPath() const2186*f6dc9357SAndroid Build Coastguard Worker UString CDropTarget::GetTargetPath() const
2187*f6dc9357SAndroid Build Coastguard Worker {
2188*f6dc9357SAndroid Build Coastguard Worker   if (!IsFsFolderPath())
2189*f6dc9357SAndroid Build Coastguard Worker     return UString();
2190*f6dc9357SAndroid Build Coastguard Worker   UString path = m_Panel->GetFsPath();
2191*f6dc9357SAndroid Build Coastguard Worker   if (/* m_SubFolderIndex >= 0 && */
2192*f6dc9357SAndroid Build Coastguard Worker       !m_Panel->m_DropHighlighted_SubFolderName.IsEmpty())
2193*f6dc9357SAndroid Build Coastguard Worker   {
2194*f6dc9357SAndroid Build Coastguard Worker     path += m_Panel->m_DropHighlighted_SubFolderName;
2195*f6dc9357SAndroid Build Coastguard Worker     path.Add_PathSepar();
2196*f6dc9357SAndroid Build Coastguard Worker   }
2197*f6dc9357SAndroid Build Coastguard Worker   return path;
2198*f6dc9357SAndroid Build Coastguard Worker }
2199*f6dc9357SAndroid Build Coastguard Worker 
2200*f6dc9357SAndroid Build Coastguard Worker 
2201*f6dc9357SAndroid Build Coastguard Worker /*
2202*f6dc9357SAndroid Build Coastguard Worker if IDropSource is Win10-Explorer
2203*f6dc9357SAndroid Build Coastguard Worker --------------------------------
2204*f6dc9357SAndroid Build Coastguard Worker   As in MS DOCs:
2205*f6dc9357SAndroid Build Coastguard Worker   The source inspects the two (effect) values that can be returned by the target:
2206*f6dc9357SAndroid Build Coastguard Worker     1) SetData(CFSTR_PERFORMEDDROPEFFECT)
2207*f6dc9357SAndroid Build Coastguard Worker     2) returned value  (*effect) by
2208*f6dc9357SAndroid Build Coastguard Worker         CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,
2209*f6dc9357SAndroid Build Coastguard Worker         POINTL pt, DWORD *effect)
2210*f6dc9357SAndroid Build Coastguard Worker   If both are set to DROPEFFECT_MOVE, Explorer completes the unoptimized move by deleting
2211*f6dc9357SAndroid Build Coastguard Worker   the original data.
2212*f6dc9357SAndroid Build Coastguard Worker   // Otherwise, the target did an optimized move and the original data has been deleted.
2213*f6dc9357SAndroid Build Coastguard Worker */
2214*f6dc9357SAndroid Build Coastguard Worker 
2215*f6dc9357SAndroid Build Coastguard Worker 
2216*f6dc9357SAndroid Build Coastguard Worker /*
2217*f6dc9357SAndroid Build Coastguard Worker   Send targetPath from target to dataObject (to Source)
2218*f6dc9357SAndroid Build Coastguard Worker   input: set (enablePath = false) to send empty path
2219*f6dc9357SAndroid Build Coastguard Worker   returns true,  if SetData()         returns S_OK : (source is 7-zip)
2220*f6dc9357SAndroid Build Coastguard Worker   returns false, if SetData() doesn't return  S_OK : (source is Explorer)
2221*f6dc9357SAndroid Build Coastguard Worker */
SendToSource_TargetPath_enable(IDataObject * dataObject,bool enablePath)2222*f6dc9357SAndroid Build Coastguard Worker bool CDropTarget::SendToSource_TargetPath_enable(IDataObject *dataObject, bool enablePath)
2223*f6dc9357SAndroid Build Coastguard Worker {
2224*f6dc9357SAndroid Build Coastguard Worker   m_TargetPath_NonEmpty_WasSent_ToDataObject = false;
2225*f6dc9357SAndroid Build Coastguard Worker   UString path;
2226*f6dc9357SAndroid Build Coastguard Worker   if (enablePath)
2227*f6dc9357SAndroid Build Coastguard Worker     path = GetTargetPath();
2228*f6dc9357SAndroid Build Coastguard Worker   PRF("CDropTarget::SetPath");
2229*f6dc9357SAndroid Build Coastguard Worker   PRF_W(path);
2230*f6dc9357SAndroid Build Coastguard Worker   if (!dataObject || m_Format_7zip_SetTargetFolder == 0)
2231*f6dc9357SAndroid Build Coastguard Worker     return false;
2232*f6dc9357SAndroid Build Coastguard Worker   FORMATETC etc = INIT_FORMATETC_HGLOBAL((CLIPFORMAT)m_Format_7zip_SetTargetFolder);
2233*f6dc9357SAndroid Build Coastguard Worker   STGMEDIUM medium;
2234*f6dc9357SAndroid Build Coastguard Worker   medium.tymed = etc.tymed;
2235*f6dc9357SAndroid Build Coastguard Worker   medium.pUnkForRelease = NULL;
2236*f6dc9357SAndroid Build Coastguard Worker   const size_t num = path.Len() + 1; // + (1 << 19) // for debug
2237*f6dc9357SAndroid Build Coastguard Worker   medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, num * sizeof(wchar_t));
2238*f6dc9357SAndroid Build Coastguard Worker   if (!medium.hGlobal)
2239*f6dc9357SAndroid Build Coastguard Worker     return false;
2240*f6dc9357SAndroid Build Coastguard Worker   // Sleep(1000);
2241*f6dc9357SAndroid Build Coastguard Worker   wchar_t *dest = (wchar_t *)GlobalLock(medium.hGlobal);
2242*f6dc9357SAndroid Build Coastguard Worker   // Sleep(1000);
2243*f6dc9357SAndroid Build Coastguard Worker   bool res = false;
2244*f6dc9357SAndroid Build Coastguard Worker   if (dest)
2245*f6dc9357SAndroid Build Coastguard Worker   {
2246*f6dc9357SAndroid Build Coastguard Worker     MyStringCopy(dest, (const wchar_t *)path);
2247*f6dc9357SAndroid Build Coastguard Worker     GlobalUnlock(medium.hGlobal);
2248*f6dc9357SAndroid Build Coastguard Worker     // OutputDebugString("m_DataObject->SetData");
2249*f6dc9357SAndroid Build Coastguard Worker     const BOOL release = FALSE; // that way is more simple for correct releasing.
2250*f6dc9357SAndroid Build Coastguard Worker         // TRUE; // for debug : is not good for some cases.
2251*f6dc9357SAndroid Build Coastguard Worker     /* If DropSource is Win10-Explorer, dataObject->SetData() returns E_NOTIMPL; */
2252*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = dataObject->SetData(&etc, &medium, release);
2253*f6dc9357SAndroid Build Coastguard Worker     // Sleep(1000);
2254*f6dc9357SAndroid Build Coastguard Worker     res = (hres == S_OK);
2255*f6dc9357SAndroid Build Coastguard Worker   }
2256*f6dc9357SAndroid Build Coastguard Worker 
2257*f6dc9357SAndroid Build Coastguard Worker   ReleaseStgMedium(&medium);
2258*f6dc9357SAndroid Build Coastguard Worker   if (res && !path.IsEmpty())
2259*f6dc9357SAndroid Build Coastguard Worker     m_TargetPath_NonEmpty_WasSent_ToDataObject = true;
2260*f6dc9357SAndroid Build Coastguard Worker   // Sleep(1000);
2261*f6dc9357SAndroid Build Coastguard Worker   return res;
2262*f6dc9357SAndroid Build Coastguard Worker }
2263*f6dc9357SAndroid Build Coastguard Worker 
2264*f6dc9357SAndroid Build Coastguard Worker 
SendToSource_auto(IDataObject * dataObject,const CTargetTransferInfo & info)2265*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::SendToSource_auto(IDataObject *dataObject,
2266*f6dc9357SAndroid Build Coastguard Worker     const CTargetTransferInfo &info)
2267*f6dc9357SAndroid Build Coastguard Worker {
2268*f6dc9357SAndroid Build Coastguard Worker   /* we try to send target path to Source.
2269*f6dc9357SAndroid Build Coastguard Worker      If Source is 7-Zip, then it will accept k_Format_7zip_SetTargetFolder.
2270*f6dc9357SAndroid Build Coastguard Worker      That sent path will be non-Empty, if this target is FS folder and drop is allowed */
2271*f6dc9357SAndroid Build Coastguard Worker   bool need_Send = false;
2272*f6dc9357SAndroid Build Coastguard Worker   if (   info.FuncType == k_DragTargetMode_Enter
2273*f6dc9357SAndroid Build Coastguard Worker       || info.FuncType == k_DragTargetMode_Over
2274*f6dc9357SAndroid Build Coastguard Worker       || (info.FuncType == k_DragTargetMode_Drop_Begin
2275*f6dc9357SAndroid Build Coastguard Worker         // && targetOp_Cmd != NDragMenu::k_None
2276*f6dc9357SAndroid Build Coastguard Worker         && info.Cmd_Type != NDragMenu::k_Cancel))
2277*f6dc9357SAndroid Build Coastguard Worker   // if (!g_CreateArchive_for_Drag_from_7zip)
2278*f6dc9357SAndroid Build Coastguard Worker       need_Send = m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath();
2279*f6dc9357SAndroid Build Coastguard Worker   m_TargetPath_WasSent_ToDataObject = SendToSource_TargetPath_enable(dataObject, need_Send);
2280*f6dc9357SAndroid Build Coastguard Worker   SendToSource_TransferInfo(dataObject, info);
2281*f6dc9357SAndroid Build Coastguard Worker }
2282*f6dc9357SAndroid Build Coastguard Worker 
2283*f6dc9357SAndroid Build Coastguard Worker 
SendToSource_TransferInfo(IDataObject * dataObject,const CTargetTransferInfo & info)2284*f6dc9357SAndroid Build Coastguard Worker bool CDropTarget::SendToSource_TransferInfo(IDataObject *dataObject,
2285*f6dc9357SAndroid Build Coastguard Worker     const CTargetTransferInfo &info)
2286*f6dc9357SAndroid Build Coastguard Worker {
2287*f6dc9357SAndroid Build Coastguard Worker   m_Transfer_WasSent_ToDataObject = false;
2288*f6dc9357SAndroid Build Coastguard Worker   PRF("CDropTarget::SendToSource_TransferInfo");
2289*f6dc9357SAndroid Build Coastguard Worker 
2290*f6dc9357SAndroid Build Coastguard Worker   if (!dataObject || m_Format_7zip_SetTransfer == 0)
2291*f6dc9357SAndroid Build Coastguard Worker     return false;
2292*f6dc9357SAndroid Build Coastguard Worker   FORMATETC etc = INIT_FORMATETC_HGLOBAL((CLIPFORMAT)m_Format_7zip_SetTransfer);
2293*f6dc9357SAndroid Build Coastguard Worker   STGMEDIUM medium;
2294*f6dc9357SAndroid Build Coastguard Worker   medium.tymed = etc.tymed;
2295*f6dc9357SAndroid Build Coastguard Worker   medium.pUnkForRelease = NULL;
2296*f6dc9357SAndroid Build Coastguard Worker   CDataObject_SetTransfer transfer;
2297*f6dc9357SAndroid Build Coastguard Worker   const size_t size = sizeof(transfer); // + (1 << 19) // for debug
2298*f6dc9357SAndroid Build Coastguard Worker   // OutputDebugString("GlobalAlloc");
2299*f6dc9357SAndroid Build Coastguard Worker   medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size);
2300*f6dc9357SAndroid Build Coastguard Worker   // Sleep(1000);
2301*f6dc9357SAndroid Build Coastguard Worker   if (!medium.hGlobal)
2302*f6dc9357SAndroid Build Coastguard Worker     return false;
2303*f6dc9357SAndroid Build Coastguard Worker   // OutputDebugString("GlobalLock");
2304*f6dc9357SAndroid Build Coastguard Worker   void *dest = (wchar_t *)GlobalLock(medium.hGlobal);
2305*f6dc9357SAndroid Build Coastguard Worker   // Sleep(1000);
2306*f6dc9357SAndroid Build Coastguard Worker   bool res = false;
2307*f6dc9357SAndroid Build Coastguard Worker   if (dest)
2308*f6dc9357SAndroid Build Coastguard Worker   {
2309*f6dc9357SAndroid Build Coastguard Worker     transfer.Init();
2310*f6dc9357SAndroid Build Coastguard Worker     transfer.Target = info;
2311*f6dc9357SAndroid Build Coastguard Worker 
2312*f6dc9357SAndroid Build Coastguard Worker     memcpy(dest, &transfer, sizeof(transfer));
2313*f6dc9357SAndroid Build Coastguard Worker     GlobalUnlock(medium.hGlobal);
2314*f6dc9357SAndroid Build Coastguard Worker     // OutputDebugString("m_DataObject->SetData");
2315*f6dc9357SAndroid Build Coastguard Worker     const BOOL release = FALSE; // that way is more simple for correct releasing.
2316*f6dc9357SAndroid Build Coastguard Worker         // TRUE; // for debug : is not good for some cases
2317*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = dataObject->SetData(&etc, &medium, release);
2318*f6dc9357SAndroid Build Coastguard Worker     res = (hres == S_OK);
2319*f6dc9357SAndroid Build Coastguard Worker   }
2320*f6dc9357SAndroid Build Coastguard Worker 
2321*f6dc9357SAndroid Build Coastguard Worker   ReleaseStgMedium(&medium);
2322*f6dc9357SAndroid Build Coastguard Worker   if (res)
2323*f6dc9357SAndroid Build Coastguard Worker     m_Transfer_WasSent_ToDataObject = true;
2324*f6dc9357SAndroid Build Coastguard Worker   return res;
2325*f6dc9357SAndroid Build Coastguard Worker }
2326*f6dc9357SAndroid Build Coastguard Worker 
2327*f6dc9357SAndroid Build Coastguard Worker 
SendToSource_UInt32(IDataObject * dataObject,UINT format,UInt32 value)2328*f6dc9357SAndroid Build Coastguard Worker bool CDropTarget::SendToSource_UInt32(IDataObject *dataObject, UINT format, UInt32 value)
2329*f6dc9357SAndroid Build Coastguard Worker {
2330*f6dc9357SAndroid Build Coastguard Worker   PRF("CDropTarget::Send_UInt32 (Performed)");
2331*f6dc9357SAndroid Build Coastguard Worker 
2332*f6dc9357SAndroid Build Coastguard Worker   if (!dataObject || format == 0)
2333*f6dc9357SAndroid Build Coastguard Worker     return false;
2334*f6dc9357SAndroid Build Coastguard Worker   FORMATETC etc = INIT_FORMATETC_HGLOBAL((CLIPFORMAT)format);
2335*f6dc9357SAndroid Build Coastguard Worker   STGMEDIUM medium;
2336*f6dc9357SAndroid Build Coastguard Worker   medium.tymed = etc.tymed;
2337*f6dc9357SAndroid Build Coastguard Worker   medium.pUnkForRelease = NULL;
2338*f6dc9357SAndroid Build Coastguard Worker   const size_t size = 4;
2339*f6dc9357SAndroid Build Coastguard Worker   medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size);
2340*f6dc9357SAndroid Build Coastguard Worker   if (!medium.hGlobal)
2341*f6dc9357SAndroid Build Coastguard Worker     return false;
2342*f6dc9357SAndroid Build Coastguard Worker   void *dest = GlobalLock(medium.hGlobal);
2343*f6dc9357SAndroid Build Coastguard Worker   bool res = false;
2344*f6dc9357SAndroid Build Coastguard Worker   if (dest)
2345*f6dc9357SAndroid Build Coastguard Worker   {
2346*f6dc9357SAndroid Build Coastguard Worker     *(UInt32 *)dest = value;
2347*f6dc9357SAndroid Build Coastguard Worker     GlobalUnlock(medium.hGlobal);
2348*f6dc9357SAndroid Build Coastguard Worker     // OutputDebugString("m_DataObject->SetData");
2349*f6dc9357SAndroid Build Coastguard Worker     const BOOL release = TRUE;
2350*f6dc9357SAndroid Build Coastguard Worker         // FALSE; // for debug
2351*f6dc9357SAndroid Build Coastguard Worker     /* If DropSource is Win10-Explorer, then (release == FALSE) doesn't work
2352*f6dc9357SAndroid Build Coastguard Worker        and dataObject->SetData() returns E_NOTIMPL;
2353*f6dc9357SAndroid Build Coastguard Worker        So we use release = TRUE; here */
2354*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = dataObject->SetData(&etc, &medium, release);
2355*f6dc9357SAndroid Build Coastguard Worker     // we return here without calling ReleaseStgMedium().
2356*f6dc9357SAndroid Build Coastguard Worker     return (hres == S_OK);
2357*f6dc9357SAndroid Build Coastguard Worker     // Sleep(1000);
2358*f6dc9357SAndroid Build Coastguard Worker     /*
2359*f6dc9357SAndroid Build Coastguard Worker       if (we use release = TRUE), we expect that
2360*f6dc9357SAndroid Build Coastguard Worker           - SetData() will release medium, and
2361*f6dc9357SAndroid Build Coastguard Worker           - SetData() will set STGMEDIUM::tymed to (TYMED_NULL = 0).
2362*f6dc9357SAndroid Build Coastguard Worker       but some "incorrect" SetData() implementations can keep STGMEDIUM::tymed unchanged.
2363*f6dc9357SAndroid Build Coastguard Worker       And it's not safe to call ReleaseStgMedium() here for that case,
2364*f6dc9357SAndroid Build Coastguard Worker       because DropSource also could release medium.
2365*f6dc9357SAndroid Build Coastguard Worker       We can reset (medium.tymed = TYMED_NULL) manually here to disable
2366*f6dc9357SAndroid Build Coastguard Worker       unsafe medium releasing in ReleaseStgMedium().
2367*f6dc9357SAndroid Build Coastguard Worker     */
2368*f6dc9357SAndroid Build Coastguard Worker     /*
2369*f6dc9357SAndroid Build Coastguard Worker     if (release)
2370*f6dc9357SAndroid Build Coastguard Worker     {
2371*f6dc9357SAndroid Build Coastguard Worker       medium.tymed = TYMED_NULL;
2372*f6dc9357SAndroid Build Coastguard Worker       medium.pUnkForRelease = NULL;
2373*f6dc9357SAndroid Build Coastguard Worker       medium.hGlobal = NULL;
2374*f6dc9357SAndroid Build Coastguard Worker     }
2375*f6dc9357SAndroid Build Coastguard Worker     res = (hres == S_OK);
2376*f6dc9357SAndroid Build Coastguard Worker     */
2377*f6dc9357SAndroid Build Coastguard Worker   }
2378*f6dc9357SAndroid Build Coastguard Worker   ReleaseStgMedium(&medium);
2379*f6dc9357SAndroid Build Coastguard Worker   return res;
2380*f6dc9357SAndroid Build Coastguard Worker }
2381*f6dc9357SAndroid Build Coastguard Worker 
2382*f6dc9357SAndroid Build Coastguard Worker 
LoadNames_From_DataObject(IDataObject * dataObject)2383*f6dc9357SAndroid Build Coastguard Worker void CDropTarget::LoadNames_From_DataObject(IDataObject *dataObject)
2384*f6dc9357SAndroid Build Coastguard Worker {
2385*f6dc9357SAndroid Build Coastguard Worker   // "\\\\.\\" prefix is possible for long names
2386*f6dc9357SAndroid Build Coastguard Worker   m_DropIsAllowed = NShell::DataObject_GetData_HDROP_or_IDLIST_Names(dataObject, m_SourcePaths) == S_OK;
2387*f6dc9357SAndroid Build Coastguard Worker }
2388*f6dc9357SAndroid Build Coastguard Worker 
2389*f6dc9357SAndroid Build Coastguard Worker 
DragEnter(IDataObject * dataObject,DWORD keyState,POINTL pt,DWORD * effect)2390*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropTarget::DragEnter(IDataObject *dataObject, DWORD keyState, POINTL pt, DWORD *effect)
2391*f6dc9357SAndroid Build Coastguard Worker {
2392*f6dc9357SAndroid Build Coastguard Worker   /* *(effect):
2393*f6dc9357SAndroid Build Coastguard Worker        - on input  : value of the dwOKEffects parameter of the DoDragDrop() function.
2394*f6dc9357SAndroid Build Coastguard Worker        - on return : must contain one of the DROPEFFECT flags, which indicates
2395*f6dc9357SAndroid Build Coastguard Worker                      what the result of the drop operation would be.
2396*f6dc9357SAndroid Build Coastguard Worker      (pt): the current cursor coordinates in screen coordinates.
2397*f6dc9357SAndroid Build Coastguard Worker   */
2398*f6dc9357SAndroid Build Coastguard Worker   PRF_(Print_Point("CDropTarget::DragEnter", keyState, pt, *effect))
2399*f6dc9357SAndroid Build Coastguard Worker   try {
2400*f6dc9357SAndroid Build Coastguard Worker 
2401*f6dc9357SAndroid Build Coastguard Worker   if ((keyState & (MK_RBUTTON | MK_MBUTTON)) != 0)
2402*f6dc9357SAndroid Build Coastguard Worker     m_IsRightButton = true;
2403*f6dc9357SAndroid Build Coastguard Worker 
2404*f6dc9357SAndroid Build Coastguard Worker   LoadNames_From_DataObject(dataObject);
2405*f6dc9357SAndroid Build Coastguard Worker   // Try_QueryGetData(dataObject);
2406*f6dc9357SAndroid Build Coastguard Worker   // we will use (m_DataObject) later in DragOver() and DragLeave().
2407*f6dc9357SAndroid Build Coastguard Worker   m_DataObject = dataObject;
2408*f6dc9357SAndroid Build Coastguard Worker   // return DragOver(keyState, pt, effect);
2409*f6dc9357SAndroid Build Coastguard Worker   PositionCursor(pt);
2410*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo target;
2411*f6dc9357SAndroid Build Coastguard Worker   target.FuncType = k_DragTargetMode_Enter;
2412*f6dc9357SAndroid Build Coastguard Worker   target.KeyState = keyState;
2413*f6dc9357SAndroid Build Coastguard Worker   target.Point = pt;
2414*f6dc9357SAndroid Build Coastguard Worker   target.OkEffects = *effect;
2415*f6dc9357SAndroid Build Coastguard Worker   SendToSource_Drag(target);
2416*f6dc9357SAndroid Build Coastguard Worker 
2417*f6dc9357SAndroid Build Coastguard Worker   CDataObject_GetTransfer transfer;
2418*f6dc9357SAndroid Build Coastguard Worker   m_GetTransfer_WasSuccess = DataObject_GetData_GetTransfer(
2419*f6dc9357SAndroid Build Coastguard Worker       dataObject, m_Format_7zip_GetTransfer, transfer);
2420*f6dc9357SAndroid Build Coastguard Worker   if (m_GetTransfer_WasSuccess)
2421*f6dc9357SAndroid Build Coastguard Worker   {
2422*f6dc9357SAndroid Build Coastguard Worker     if (transfer.Flags & k_SourceFlags_LeftButton)
2423*f6dc9357SAndroid Build Coastguard Worker       m_IsRightButton = false;
2424*f6dc9357SAndroid Build Coastguard Worker     else if (transfer.Flags & k_SourceFlags_RightButton)
2425*f6dc9357SAndroid Build Coastguard Worker       m_IsRightButton = true;
2426*f6dc9357SAndroid Build Coastguard Worker   }
2427*f6dc9357SAndroid Build Coastguard Worker 
2428*f6dc9357SAndroid Build Coastguard Worker   *effect = GetEffect(keyState, pt, *effect);
2429*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2430*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { return E_FAIL; }
2431*f6dc9357SAndroid Build Coastguard Worker }
2432*f6dc9357SAndroid Build Coastguard Worker 
2433*f6dc9357SAndroid Build Coastguard Worker 
DragOver(DWORD keyState,POINTL pt,DWORD * effect)2434*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropTarget::DragOver(DWORD keyState, POINTL pt, DWORD *effect)
2435*f6dc9357SAndroid Build Coastguard Worker {
2436*f6dc9357SAndroid Build Coastguard Worker   PRF_(Print_Point("CDropTarget::DragOver", keyState, pt, *effect))
2437*f6dc9357SAndroid Build Coastguard Worker   /*
2438*f6dc9357SAndroid Build Coastguard Worker     For efficiency reasons, a data object is not passed in IDropTarget::DragOver.
2439*f6dc9357SAndroid Build Coastguard Worker     The data object passed in the most recent call to IDropTarget::DragEnter
2440*f6dc9357SAndroid Build Coastguard Worker     is available and can be used.
2441*f6dc9357SAndroid Build Coastguard Worker 
2442*f6dc9357SAndroid Build Coastguard Worker     When IDropTarget::DragOver has completed its operation, the DoDragDrop
2443*f6dc9357SAndroid Build Coastguard Worker     function calls IDropSource::GiveFeedback so the source application can display
2444*f6dc9357SAndroid Build Coastguard Worker     the appropriate visual feedback to the user.
2445*f6dc9357SAndroid Build Coastguard Worker   */
2446*f6dc9357SAndroid Build Coastguard Worker   /*
2447*f6dc9357SAndroid Build Coastguard Worker     we suppose that it's unexpected that (keyState) shows that mouse
2448*f6dc9357SAndroid Build Coastguard Worker     button is not pressed, because such cases will be processed by
2449*f6dc9357SAndroid Build Coastguard Worker     IDropSource::QueryContinueDrag() that returns DRAGDROP_S_DROP or DRAGDROP_S_CANCEL.
2450*f6dc9357SAndroid Build Coastguard Worker     So DragOver() will not be called.
2451*f6dc9357SAndroid Build Coastguard Worker   */
2452*f6dc9357SAndroid Build Coastguard Worker 
2453*f6dc9357SAndroid Build Coastguard Worker   if ((keyState & MK_LBUTTON) == 0)
2454*f6dc9357SAndroid Build Coastguard Worker   {
2455*f6dc9357SAndroid Build Coastguard Worker     PRF4("CDropTarget::DragOver() (keyState & MK_LBUTTON) == 0");
2456*f6dc9357SAndroid Build Coastguard Worker     // g_Debug = true;
2457*f6dc9357SAndroid Build Coastguard Worker   }
2458*f6dc9357SAndroid Build Coastguard Worker 
2459*f6dc9357SAndroid Build Coastguard Worker   try {
2460*f6dc9357SAndroid Build Coastguard Worker   /* we suppose that source names were not changed after DragEnter()
2461*f6dc9357SAndroid Build Coastguard Worker      so we don't request GetNames_From_DataObject() for each call of DragOver() */
2462*f6dc9357SAndroid Build Coastguard Worker   PositionCursor(pt);
2463*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo target;
2464*f6dc9357SAndroid Build Coastguard Worker   target.FuncType = k_DragTargetMode_Over;
2465*f6dc9357SAndroid Build Coastguard Worker   target.KeyState = keyState;
2466*f6dc9357SAndroid Build Coastguard Worker   target.Point = pt;
2467*f6dc9357SAndroid Build Coastguard Worker   target.OkEffects = *effect;
2468*f6dc9357SAndroid Build Coastguard Worker   SendToSource_Drag(target);
2469*f6dc9357SAndroid Build Coastguard Worker   *effect = GetEffect(keyState, pt, *effect);
2470*f6dc9357SAndroid Build Coastguard Worker   // *effect = 1 << 8; // for debug
2471*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2472*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { return E_FAIL; }
2473*f6dc9357SAndroid Build Coastguard Worker }
2474*f6dc9357SAndroid Build Coastguard Worker 
2475*f6dc9357SAndroid Build Coastguard Worker 
DragLeave()2476*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropTarget::DragLeave()
2477*f6dc9357SAndroid Build Coastguard Worker {
2478*f6dc9357SAndroid Build Coastguard Worker   PRF4("CDropTarget::DragLeave");
2479*f6dc9357SAndroid Build Coastguard Worker   try {
2480*f6dc9357SAndroid Build Coastguard Worker   RemoveSelection();
2481*f6dc9357SAndroid Build Coastguard Worker   // we send empty TargetPath to 7-Zip Source to clear value of TargetPath that was sent before
2482*f6dc9357SAndroid Build Coastguard Worker 
2483*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo target;
2484*f6dc9357SAndroid Build Coastguard Worker   target.FuncType = k_DragTargetMode_Leave;
2485*f6dc9357SAndroid Build Coastguard Worker   /*
2486*f6dc9357SAndroid Build Coastguard Worker   target.KeyState = 0;
2487*f6dc9357SAndroid Build Coastguard Worker   target.Point = pt;
2488*f6dc9357SAndroid Build Coastguard Worker   pt.x = 0; // -1
2489*f6dc9357SAndroid Build Coastguard Worker   pt.y = 0; // -1
2490*f6dc9357SAndroid Build Coastguard Worker   target.Effect = 0;
2491*f6dc9357SAndroid Build Coastguard Worker   */
2492*f6dc9357SAndroid Build Coastguard Worker   SendToSource_Drag(target);
2493*f6dc9357SAndroid Build Coastguard Worker   ClearState();
2494*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2495*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { return E_FAIL; }
2496*f6dc9357SAndroid Build Coastguard Worker }
2497*f6dc9357SAndroid Build Coastguard Worker 
2498*f6dc9357SAndroid Build Coastguard Worker 
2499*f6dc9357SAndroid Build Coastguard Worker static unsigned Drag_OnContextMenu(int xPos, int yPos, UInt32 cmdFlags);
2500*f6dc9357SAndroid Build Coastguard Worker 
2501*f6dc9357SAndroid Build Coastguard Worker /*
2502*f6dc9357SAndroid Build Coastguard Worker   We suppose that there was DragEnter/DragOver for same (POINTL pt) before Drop().
2503*f6dc9357SAndroid Build Coastguard Worker   But we can work without DragEnter/DragOver too.
2504*f6dc9357SAndroid Build Coastguard Worker */
Drop(IDataObject * dataObject,DWORD keyState,POINTL pt,DWORD * effect)2505*f6dc9357SAndroid Build Coastguard Worker Z7_COMWF_B CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,
2506*f6dc9357SAndroid Build Coastguard Worker     POINTL pt, DWORD *effect)
2507*f6dc9357SAndroid Build Coastguard Worker {
2508*f6dc9357SAndroid Build Coastguard Worker   PRF_(Print_Point("CDropTarget::Drop", keyState, pt, *effect))
2509*f6dc9357SAndroid Build Coastguard Worker   /* Drop() is called after SourceDrop::QueryContinueDrag() returned DRAGDROP_S_DROP.
2510*f6dc9357SAndroid Build Coastguard Worker      So it's possible that Source have done some operations already.
2511*f6dc9357SAndroid Build Coastguard Worker   */
2512*f6dc9357SAndroid Build Coastguard Worker   HRESULT hres = S_OK;
2513*f6dc9357SAndroid Build Coastguard Worker   bool needDrop_by_Source = false;
2514*f6dc9357SAndroid Build Coastguard Worker   DWORD opEffect = DROPEFFECT_NONE;
2515*f6dc9357SAndroid Build Coastguard Worker 
2516*f6dc9357SAndroid Build Coastguard Worker   try {
2517*f6dc9357SAndroid Build Coastguard Worker   // we don't need m_DataObject reference anymore, because we use local (dataObject)
2518*f6dc9357SAndroid Build Coastguard Worker   m_DataObject.Release();
2519*f6dc9357SAndroid Build Coastguard Worker 
2520*f6dc9357SAndroid Build Coastguard Worker   /* in normal case : we called LoadNames_From_DataObject() in DragEnter() already.
2521*f6dc9357SAndroid Build Coastguard Worker      But if by some reason DragEnter() was not called,
2522*f6dc9357SAndroid Build Coastguard Worker      we need to call LoadNames_From_DataObject() before PositionCursor().
2523*f6dc9357SAndroid Build Coastguard Worker   */
2524*f6dc9357SAndroid Build Coastguard Worker   if (!m_DropIsAllowed) LoadNames_From_DataObject(dataObject);
2525*f6dc9357SAndroid Build Coastguard Worker   PositionCursor(pt);
2526*f6dc9357SAndroid Build Coastguard Worker 
2527*f6dc9357SAndroid Build Coastguard Worker   CPanel::CDisableTimerProcessing2 disableTimerProcessing(m_Panel);
2528*f6dc9357SAndroid Build Coastguard Worker   // CDisableNotify disableNotify2(m_Panel);
2529*f6dc9357SAndroid Build Coastguard Worker 
2530*f6dc9357SAndroid Build Coastguard Worker   UInt32 cmd = NDragMenu::k_None;
2531*f6dc9357SAndroid Build Coastguard Worker   UInt32 cmdEffect = DROPEFFECT_NONE;
2532*f6dc9357SAndroid Build Coastguard Worker   bool menu_WasShown = false;
2533*f6dc9357SAndroid Build Coastguard Worker   if (m_IsRightButton && m_Panel)
2534*f6dc9357SAndroid Build Coastguard Worker   {
2535*f6dc9357SAndroid Build Coastguard Worker     UInt32 flagsMask;
2536*f6dc9357SAndroid Build Coastguard Worker     if (m_Panel->IsArcFolder())
2537*f6dc9357SAndroid Build Coastguard Worker       flagsMask = (UInt32)1 << NDragMenu::k_Copy_ToArc;
2538*f6dc9357SAndroid Build Coastguard Worker     else
2539*f6dc9357SAndroid Build Coastguard Worker     {
2540*f6dc9357SAndroid Build Coastguard Worker       flagsMask = (UInt32)1 << NDragMenu::k_AddToArc;
2541*f6dc9357SAndroid Build Coastguard Worker       if (IsFsFolderPath())
2542*f6dc9357SAndroid Build Coastguard Worker         flagsMask |= (UInt32)1 << NDragMenu::k_Copy_Base;
2543*f6dc9357SAndroid Build Coastguard Worker     }
2544*f6dc9357SAndroid Build Coastguard Worker     // flagsMask |= (UInt32)1 << NDragMenu::k_Cancel;
2545*f6dc9357SAndroid Build Coastguard Worker     const UInt32 cmd32 = Drag_OnContextMenu(pt.x, pt.y, flagsMask);
2546*f6dc9357SAndroid Build Coastguard Worker     cmd = cmd32 & NDragMenu::k_MenuFlags_CmdMask;
2547*f6dc9357SAndroid Build Coastguard Worker     if (cmd32 & NDragMenu::k_MenuFlag_Copy)
2548*f6dc9357SAndroid Build Coastguard Worker       cmdEffect = DROPEFFECT_COPY;
2549*f6dc9357SAndroid Build Coastguard Worker     else if (cmd32 & NDragMenu::k_MenuFlag_Move)
2550*f6dc9357SAndroid Build Coastguard Worker       cmdEffect = DROPEFFECT_MOVE;
2551*f6dc9357SAndroid Build Coastguard Worker     opEffect = cmdEffect;
2552*f6dc9357SAndroid Build Coastguard Worker     menu_WasShown = true;
2553*f6dc9357SAndroid Build Coastguard Worker   }
2554*f6dc9357SAndroid Build Coastguard Worker   else
2555*f6dc9357SAndroid Build Coastguard Worker   {
2556*f6dc9357SAndroid Build Coastguard Worker     opEffect = GetEffect(keyState, pt, *effect);
2557*f6dc9357SAndroid Build Coastguard Worker     if (m_IsAppTarget)
2558*f6dc9357SAndroid Build Coastguard Worker       cmd = NDragMenu::k_AddToArc;
2559*f6dc9357SAndroid Build Coastguard Worker     else if (m_Panel)
2560*f6dc9357SAndroid Build Coastguard Worker     {
2561*f6dc9357SAndroid Build Coastguard Worker       if (IsFsFolderPath())
2562*f6dc9357SAndroid Build Coastguard Worker       {
2563*f6dc9357SAndroid Build Coastguard Worker         const bool is7zip = m_TargetPath_WasSent_ToDataObject;
2564*f6dc9357SAndroid Build Coastguard Worker         bool createNewArchive = false;
2565*f6dc9357SAndroid Build Coastguard Worker         if (is7zip)
2566*f6dc9357SAndroid Build Coastguard Worker           createNewArchive = false; // g_CreateArchive_for_Drag_from_7zip;
2567*f6dc9357SAndroid Build Coastguard Worker         else
2568*f6dc9357SAndroid Build Coastguard Worker           createNewArchive = true; // g_CreateArchive_for_Drag_from_Explorer;
2569*f6dc9357SAndroid Build Coastguard Worker 
2570*f6dc9357SAndroid Build Coastguard Worker         if (createNewArchive)
2571*f6dc9357SAndroid Build Coastguard Worker           cmd = NDragMenu::k_AddToArc;
2572*f6dc9357SAndroid Build Coastguard Worker         else
2573*f6dc9357SAndroid Build Coastguard Worker         {
2574*f6dc9357SAndroid Build Coastguard Worker           if (opEffect != 0)
2575*f6dc9357SAndroid Build Coastguard Worker             cmd = NDragMenu::k_Copy_Base;
2576*f6dc9357SAndroid Build Coastguard Worker           cmdEffect = opEffect;
2577*f6dc9357SAndroid Build Coastguard Worker         }
2578*f6dc9357SAndroid Build Coastguard Worker       }
2579*f6dc9357SAndroid Build Coastguard Worker       else
2580*f6dc9357SAndroid Build Coastguard Worker       {
2581*f6dc9357SAndroid Build Coastguard Worker         /* if we are inside open archive:
2582*f6dc9357SAndroid Build Coastguard Worker            if archive support operations         -> we will call operations
2583*f6dc9357SAndroid Build Coastguard Worker            if archive doesn't support operations -> we will create new archove
2584*f6dc9357SAndroid Build Coastguard Worker         */
2585*f6dc9357SAndroid Build Coastguard Worker         if (m_Panel->IsArcFolder()
2586*f6dc9357SAndroid Build Coastguard Worker             || m_Panel->DoesItSupportOperations())
2587*f6dc9357SAndroid Build Coastguard Worker         {
2588*f6dc9357SAndroid Build Coastguard Worker           cmd = NDragMenu::k_Copy_ToArc;
2589*f6dc9357SAndroid Build Coastguard Worker           // we don't want move to archive operation here.
2590*f6dc9357SAndroid Build Coastguard Worker           // so we force to DROPEFFECT_COPY.
2591*f6dc9357SAndroid Build Coastguard Worker           if (opEffect != DROPEFFECT_NONE)
2592*f6dc9357SAndroid Build Coastguard Worker             opEffect = DROPEFFECT_COPY;
2593*f6dc9357SAndroid Build Coastguard Worker           cmdEffect = opEffect;
2594*f6dc9357SAndroid Build Coastguard Worker         }
2595*f6dc9357SAndroid Build Coastguard Worker         else
2596*f6dc9357SAndroid Build Coastguard Worker           cmd = NDragMenu::k_AddToArc;
2597*f6dc9357SAndroid Build Coastguard Worker       }
2598*f6dc9357SAndroid Build Coastguard Worker     }
2599*f6dc9357SAndroid Build Coastguard Worker   }
2600*f6dc9357SAndroid Build Coastguard Worker 
2601*f6dc9357SAndroid Build Coastguard Worker   if (cmd == 0)
2602*f6dc9357SAndroid Build Coastguard Worker     cmd = NDragMenu::k_AddToArc;
2603*f6dc9357SAndroid Build Coastguard Worker 
2604*f6dc9357SAndroid Build Coastguard Worker   if (cmd == NDragMenu::k_AddToArc)
2605*f6dc9357SAndroid Build Coastguard Worker   {
2606*f6dc9357SAndroid Build Coastguard Worker     opEffect = DROPEFFECT_COPY;
2607*f6dc9357SAndroid Build Coastguard Worker     cmdEffect = DROPEFFECT_COPY;
2608*f6dc9357SAndroid Build Coastguard Worker   }
2609*f6dc9357SAndroid Build Coastguard Worker 
2610*f6dc9357SAndroid Build Coastguard Worker   if (m_Panel)
2611*f6dc9357SAndroid Build Coastguard Worker   if (cmd == NDragMenu::k_Copy_ToArc)
2612*f6dc9357SAndroid Build Coastguard Worker   {
2613*f6dc9357SAndroid Build Coastguard Worker     const UString title = LangString(IDS_CONFIRM_FILE_COPY);
2614*f6dc9357SAndroid Build Coastguard Worker     UString s = LangString(cmdEffect == DROPEFFECT_MOVE ?
2615*f6dc9357SAndroid Build Coastguard Worker         IDS_MOVE_TO : IDS_COPY_TO);
2616*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
2617*f6dc9357SAndroid Build Coastguard Worker     // s += "\'";
2618*f6dc9357SAndroid Build Coastguard Worker     s += m_Panel->_currentFolderPrefix;
2619*f6dc9357SAndroid Build Coastguard Worker     // s += "\'";
2620*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
2621*f6dc9357SAndroid Build Coastguard Worker     AddLangString(s, IDS_WANT_TO_COPY_FILES);
2622*f6dc9357SAndroid Build Coastguard Worker     s += " ?";
2623*f6dc9357SAndroid Build Coastguard Worker     const int res = ::MessageBoxW(*m_Panel, s, title, MB_YESNOCANCEL | MB_ICONQUESTION);
2624*f6dc9357SAndroid Build Coastguard Worker     if (res != IDYES)
2625*f6dc9357SAndroid Build Coastguard Worker       cmd = NDragMenu::k_Cancel;
2626*f6dc9357SAndroid Build Coastguard Worker   }
2627*f6dc9357SAndroid Build Coastguard Worker 
2628*f6dc9357SAndroid Build Coastguard Worker   CTargetTransferInfo target;
2629*f6dc9357SAndroid Build Coastguard Worker   target.FuncType = k_DragTargetMode_Drop_Begin;
2630*f6dc9357SAndroid Build Coastguard Worker   target.KeyState = keyState;
2631*f6dc9357SAndroid Build Coastguard Worker   target.Point = pt;
2632*f6dc9357SAndroid Build Coastguard Worker   target.OkEffects = *effect;
2633*f6dc9357SAndroid Build Coastguard Worker   target.Flags = 0;
2634*f6dc9357SAndroid Build Coastguard Worker 
2635*f6dc9357SAndroid Build Coastguard Worker   target.Cmd_Effect = cmdEffect;
2636*f6dc9357SAndroid Build Coastguard Worker   target.Cmd_Type = cmd;
2637*f6dc9357SAndroid Build Coastguard Worker   target.FolderType = GetFolderType();
2638*f6dc9357SAndroid Build Coastguard Worker 
2639*f6dc9357SAndroid Build Coastguard Worker   if (cmd == NDragMenu::k_Cancel)
2640*f6dc9357SAndroid Build Coastguard Worker     target.Flags |= k_TargetFlags_WasCanceled;
2641*f6dc9357SAndroid Build Coastguard Worker   if (menu_WasShown)
2642*f6dc9357SAndroid Build Coastguard Worker     target.Flags |= k_TargetFlags_MenuWasShown;
2643*f6dc9357SAndroid Build Coastguard Worker 
2644*f6dc9357SAndroid Build Coastguard Worker   SendToSource_auto(dataObject, target);
2645*f6dc9357SAndroid Build Coastguard Worker 
2646*f6dc9357SAndroid Build Coastguard Worker   CDataObject_GetTransfer transfer;
2647*f6dc9357SAndroid Build Coastguard Worker   m_GetTransfer_WasSuccess = DataObject_GetData_GetTransfer(
2648*f6dc9357SAndroid Build Coastguard Worker       dataObject, m_Format_7zip_GetTransfer, transfer);
2649*f6dc9357SAndroid Build Coastguard Worker 
2650*f6dc9357SAndroid Build Coastguard Worker   /* The Source (for example, 7-zip) could change file names when drop was confirmed.
2651*f6dc9357SAndroid Build Coastguard Worker      So we must reload source file paths here */
2652*f6dc9357SAndroid Build Coastguard Worker   if (cmd != NDragMenu::k_Cancel)
2653*f6dc9357SAndroid Build Coastguard Worker     LoadNames_From_DataObject(dataObject);
2654*f6dc9357SAndroid Build Coastguard Worker 
2655*f6dc9357SAndroid Build Coastguard Worker   if (cmd == NDragMenu::k_Cancel)
2656*f6dc9357SAndroid Build Coastguard Worker   {
2657*f6dc9357SAndroid Build Coastguard Worker     opEffect = DROPEFFECT_NONE;
2658*f6dc9357SAndroid Build Coastguard Worker     cmdEffect = DROPEFFECT_NONE;
2659*f6dc9357SAndroid Build Coastguard Worker   }
2660*f6dc9357SAndroid Build Coastguard Worker   else
2661*f6dc9357SAndroid Build Coastguard Worker   {
2662*f6dc9357SAndroid Build Coastguard Worker     if (m_GetTransfer_WasSuccess)
2663*f6dc9357SAndroid Build Coastguard Worker       needDrop_by_Source = ((transfer.Flags & k_SourceFlags_DoNotProcessInTarget) != 0);
2664*f6dc9357SAndroid Build Coastguard Worker     if (!needDrop_by_Source)
2665*f6dc9357SAndroid Build Coastguard Worker     {
2666*f6dc9357SAndroid Build Coastguard Worker       bool moveMode = (cmdEffect == DROPEFFECT_MOVE);
2667*f6dc9357SAndroid Build Coastguard Worker       bool needDrop = false;
2668*f6dc9357SAndroid Build Coastguard Worker       if (m_IsRightButton && m_Panel)
2669*f6dc9357SAndroid Build Coastguard Worker         needDrop = true;
2670*f6dc9357SAndroid Build Coastguard Worker       if (m_DropIsAllowed && m_PanelDropIsAllowed)
2671*f6dc9357SAndroid Build Coastguard Worker       {
2672*f6dc9357SAndroid Build Coastguard Worker         /* if non-empty TargetPath was sent successfully to DataObject,
2673*f6dc9357SAndroid Build Coastguard Worker            then the Source is 7-Zip, and that 7zip-Source can copy to FS operation.
2674*f6dc9357SAndroid Build Coastguard Worker            So we can disable Drop operation here for such case.
2675*f6dc9357SAndroid Build Coastguard Worker         */
2676*f6dc9357SAndroid Build Coastguard Worker         needDrop_by_Source = (cmd != NDragMenu::k_AddToArc
2677*f6dc9357SAndroid Build Coastguard Worker             && m_TargetPath_WasSent_ToDataObject
2678*f6dc9357SAndroid Build Coastguard Worker             && m_TargetPath_NonEmpty_WasSent_ToDataObject);
2679*f6dc9357SAndroid Build Coastguard Worker         needDrop = !(needDrop_by_Source);
2680*f6dc9357SAndroid Build Coastguard Worker       }
2681*f6dc9357SAndroid Build Coastguard Worker       if (needDrop)
2682*f6dc9357SAndroid Build Coastguard Worker       {
2683*f6dc9357SAndroid Build Coastguard Worker         UString path = GetTargetPath();
2684*f6dc9357SAndroid Build Coastguard Worker         if (m_IsAppTarget && m_Panel)
2685*f6dc9357SAndroid Build Coastguard Worker           if (m_Panel->IsFSFolder())
2686*f6dc9357SAndroid Build Coastguard Worker             path = m_Panel->GetFsPath();
2687*f6dc9357SAndroid Build Coastguard Worker 
2688*f6dc9357SAndroid Build Coastguard Worker         UInt32 sourceFlags = 0;
2689*f6dc9357SAndroid Build Coastguard Worker         if (m_GetTransfer_WasSuccess)
2690*f6dc9357SAndroid Build Coastguard Worker           sourceFlags = transfer.Flags;
2691*f6dc9357SAndroid Build Coastguard Worker 
2692*f6dc9357SAndroid Build Coastguard Worker         if (menu_WasShown)
2693*f6dc9357SAndroid Build Coastguard Worker           target.Flags |= k_TargetFlags_MenuWasShown;
2694*f6dc9357SAndroid Build Coastguard Worker 
2695*f6dc9357SAndroid Build Coastguard Worker         target.Flags |= k_TargetFlags_WasProcessed;
2696*f6dc9357SAndroid Build Coastguard Worker 
2697*f6dc9357SAndroid Build Coastguard Worker         RemoveSelection();
2698*f6dc9357SAndroid Build Coastguard Worker         // disableTimerProcessing.Restore();
2699*f6dc9357SAndroid Build Coastguard Worker         m_Panel->CompressDropFiles(m_SourcePaths, path,
2700*f6dc9357SAndroid Build Coastguard Worker             (cmd == NDragMenu::k_AddToArc),  // createNewArchive,
2701*f6dc9357SAndroid Build Coastguard Worker             moveMode, sourceFlags,
2702*f6dc9357SAndroid Build Coastguard Worker             target.Flags
2703*f6dc9357SAndroid Build Coastguard Worker             );
2704*f6dc9357SAndroid Build Coastguard Worker       }
2705*f6dc9357SAndroid Build Coastguard Worker     }
2706*f6dc9357SAndroid Build Coastguard Worker   } // end of if (cmd != NDragMenu::k_Cancel)
2707*f6dc9357SAndroid Build Coastguard Worker   {
2708*f6dc9357SAndroid Build Coastguard Worker     /* note that, if (we send CFSTR_PERFORMEDDROPEFFECT as DROPEFFECT_MOVE
2709*f6dc9357SAndroid Build Coastguard Worker             and Drop() returns (*effect == DROPEFFECT_MOVE), then
2710*f6dc9357SAndroid Build Coastguard Worker        Win10-Explorer-Source will try to remove files just after Drop() exit.
2711*f6dc9357SAndroid Build Coastguard Worker        But our CompressFiles() could be run without waiting finishing.
2712*f6dc9357SAndroid Build Coastguard Worker        DOCs say, that we must send CFSTR_PERFORMEDDROPEFFECT
2713*f6dc9357SAndroid Build Coastguard Worker          - DROPEFFECT_NONE : for   optimized move
2714*f6dc9357SAndroid Build Coastguard Worker          - DROPEFFECT_MOVE : for unoptimized move.
2715*f6dc9357SAndroid Build Coastguard Worker        But actually Win10-Explorer-Target sends (DROPEFFECT_MOVE) for move operation.
2716*f6dc9357SAndroid Build Coastguard Worker        And it still works as in optimized mode, because "unoptimized" deleting by Source will be performed
2717*f6dc9357SAndroid Build Coastguard Worker        if both conditions are met:
2718*f6dc9357SAndroid Build Coastguard Worker           1) DROPEFFECT_MOVE is sent to (CFSTR_PERFORMEDDROPEFFECT) and
2719*f6dc9357SAndroid Build Coastguard Worker           2) (*effect == DROPEFFECT_MOVE) is returend by Drop().
2720*f6dc9357SAndroid Build Coastguard Worker        We don't want to send DROPEFFECT_MOVE here to protect from
2721*f6dc9357SAndroid Build Coastguard Worker        deleting file by Win10-Explorer.
2722*f6dc9357SAndroid Build Coastguard Worker        We are not sure that allfile fieree processed by move.
2723*f6dc9357SAndroid Build Coastguard Worker     */
2724*f6dc9357SAndroid Build Coastguard Worker 
2725*f6dc9357SAndroid Build Coastguard Worker     // for debug: we test the case when source tries to delete original files
2726*f6dc9357SAndroid Build Coastguard Worker     // bool res;
2727*f6dc9357SAndroid Build Coastguard Worker     // only CFSTR_PERFORMEDDROPEFFECT affects file removing in Win10-Explorer.
2728*f6dc9357SAndroid Build Coastguard Worker     // res = SendToSource_UInt32(dataObject, RegisterClipboardFormat(CFSTR_LOGICALPERFORMEDDROPEFFECT), DROPEFFECT_MOVE); // for debug
2729*f6dc9357SAndroid Build Coastguard Worker     /* res = */ SendToSource_UInt32(dataObject,
2730*f6dc9357SAndroid Build Coastguard Worker         RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT),
2731*f6dc9357SAndroid Build Coastguard Worker         cmd == NDragMenu::k_Cancel ? DROPEFFECT_NONE : DROPEFFECT_COPY);
2732*f6dc9357SAndroid Build Coastguard Worker     // res = res;
2733*f6dc9357SAndroid Build Coastguard Worker   }
2734*f6dc9357SAndroid Build Coastguard Worker   RemoveSelection();
2735*f6dc9357SAndroid Build Coastguard Worker 
2736*f6dc9357SAndroid Build Coastguard Worker   target.FuncType = k_DragTargetMode_Drop_End;
2737*f6dc9357SAndroid Build Coastguard Worker   target.Cmd_Type = cmd;
2738*f6dc9357SAndroid Build Coastguard Worker   if (needDrop_by_Source)
2739*f6dc9357SAndroid Build Coastguard Worker     target.Flags |= k_TargetFlags_MustBeProcessedBySource;
2740*f6dc9357SAndroid Build Coastguard Worker 
2741*f6dc9357SAndroid Build Coastguard Worker   SendToSource_TransferInfo(dataObject, target);
2742*f6dc9357SAndroid Build Coastguard Worker   } catch(...) { hres = E_FAIL; }
2743*f6dc9357SAndroid Build Coastguard Worker 
2744*f6dc9357SAndroid Build Coastguard Worker   ClearState();
2745*f6dc9357SAndroid Build Coastguard Worker   // *effect |= (1 << 10); // for debug
2746*f6dc9357SAndroid Build Coastguard Worker   // *effect = DROPEFFECT_COPY; // for debug
2747*f6dc9357SAndroid Build Coastguard Worker 
2748*f6dc9357SAndroid Build Coastguard Worker   /*
2749*f6dc9357SAndroid Build Coastguard Worker     if we return (*effect == DROPEFFECT_MOVE) here,
2750*f6dc9357SAndroid Build Coastguard Worker     Explorer-Source at some conditions can treat it as (unoptimized move) mode,
2751*f6dc9357SAndroid Build Coastguard Worker     and Explorer-Source will remove source files after DoDragDrop()
2752*f6dc9357SAndroid Build Coastguard Worker     in that (unoptimized move) mode.
2753*f6dc9357SAndroid Build Coastguard Worker     We want to avoid such (unoptimized move) cases.
2754*f6dc9357SAndroid Build Coastguard Worker     So we don't return (*effect == DROPEFFECT_MOVE), here if Source is not 7-Zip.
2755*f6dc9357SAndroid Build Coastguard Worker     If source is 7-Zip that will do acual opeartion, then we can return DROPEFFECT_MOVE.
2756*f6dc9357SAndroid Build Coastguard Worker   */
2757*f6dc9357SAndroid Build Coastguard Worker   if (hres != S_OK || (opEffect == DROPEFFECT_MOVE && !needDrop_by_Source))
2758*f6dc9357SAndroid Build Coastguard Worker   {
2759*f6dc9357SAndroid Build Coastguard Worker     // opEffect = opEffect;
2760*f6dc9357SAndroid Build Coastguard Worker     // opEffect = DROPEFFECT_NONE; // for debug disabled
2761*f6dc9357SAndroid Build Coastguard Worker   }
2762*f6dc9357SAndroid Build Coastguard Worker 
2763*f6dc9357SAndroid Build Coastguard Worker   *effect = opEffect;
2764*f6dc9357SAndroid Build Coastguard Worker   /* if (hres <  0), DoDragDrop() also will return (hres).
2765*f6dc9357SAndroid Build Coastguard Worker      if (hres >= 0), DoDragDrop() will return DRAGDROP_S_DROP;
2766*f6dc9357SAndroid Build Coastguard Worker   */
2767*f6dc9357SAndroid Build Coastguard Worker   return hres;
2768*f6dc9357SAndroid Build Coastguard Worker }
2769*f6dc9357SAndroid Build Coastguard Worker 
2770*f6dc9357SAndroid Build Coastguard Worker 
2771*f6dc9357SAndroid Build Coastguard Worker 
2772*f6dc9357SAndroid Build Coastguard Worker // ---------- CPanel ----------
2773*f6dc9357SAndroid Build Coastguard Worker 
2774*f6dc9357SAndroid Build Coastguard Worker 
Is_Path1_Prefixed_by_Path2(const UString & path,const UString & prefix)2775*f6dc9357SAndroid Build Coastguard Worker static bool Is_Path1_Prefixed_by_Path2(const UString &path, const UString &prefix)
2776*f6dc9357SAndroid Build Coastguard Worker {
2777*f6dc9357SAndroid Build Coastguard Worker   const unsigned len = prefix.Len();
2778*f6dc9357SAndroid Build Coastguard Worker   if (path.Len() < len)
2779*f6dc9357SAndroid Build Coastguard Worker     return false;
2780*f6dc9357SAndroid Build Coastguard Worker   return CompareFileNames(path.Left(len), prefix) == 0;
2781*f6dc9357SAndroid Build Coastguard Worker }
2782*f6dc9357SAndroid Build Coastguard Worker 
IsFolderInTemp(const UString & path)2783*f6dc9357SAndroid Build Coastguard Worker static bool IsFolderInTemp(const UString &path)
2784*f6dc9357SAndroid Build Coastguard Worker {
2785*f6dc9357SAndroid Build Coastguard Worker   FString tempPathF;
2786*f6dc9357SAndroid Build Coastguard Worker   if (!MyGetTempPath(tempPathF))
2787*f6dc9357SAndroid Build Coastguard Worker     return false;
2788*f6dc9357SAndroid Build Coastguard Worker   const UString tempPath = fs2us(tempPathF);
2789*f6dc9357SAndroid Build Coastguard Worker   if (tempPath.IsEmpty())
2790*f6dc9357SAndroid Build Coastguard Worker     return false;
2791*f6dc9357SAndroid Build Coastguard Worker   return Is_Path1_Prefixed_by_Path2(path, tempPath);
2792*f6dc9357SAndroid Build Coastguard Worker }
2793*f6dc9357SAndroid Build Coastguard Worker 
AreThereNamesFromTemp(const UStringVector & filePaths)2794*f6dc9357SAndroid Build Coastguard Worker static bool AreThereNamesFromTemp(const UStringVector &filePaths)
2795*f6dc9357SAndroid Build Coastguard Worker {
2796*f6dc9357SAndroid Build Coastguard Worker   FString tempPathF;
2797*f6dc9357SAndroid Build Coastguard Worker   if (!MyGetTempPath(tempPathF))
2798*f6dc9357SAndroid Build Coastguard Worker     return false;
2799*f6dc9357SAndroid Build Coastguard Worker   const UString tempPath = fs2us(tempPathF);
2800*f6dc9357SAndroid Build Coastguard Worker   if (tempPath.IsEmpty())
2801*f6dc9357SAndroid Build Coastguard Worker     return false;
2802*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, filePaths)
2803*f6dc9357SAndroid Build Coastguard Worker     if (Is_Path1_Prefixed_by_Path2(filePaths[i], tempPath))
2804*f6dc9357SAndroid Build Coastguard Worker       return true;
2805*f6dc9357SAndroid Build Coastguard Worker   return false;
2806*f6dc9357SAndroid Build Coastguard Worker }
2807*f6dc9357SAndroid Build Coastguard Worker 
2808*f6dc9357SAndroid Build Coastguard Worker 
2809*f6dc9357SAndroid Build Coastguard Worker /*
2810*f6dc9357SAndroid Build Coastguard Worker   empty folderPath means create new Archive to path of first fileName.
2811*f6dc9357SAndroid Build Coastguard Worker   createNewArchive == true : show "Add to archive ..." dialog with external program
2812*f6dc9357SAndroid Build Coastguard Worker     folderPath.IsEmpty()  : create archive in folder of filePaths[0].
2813*f6dc9357SAndroid Build Coastguard Worker   createNewArchive == false :
2814*f6dc9357SAndroid Build Coastguard Worker     folderPath.IsEmpty()  : copy to archive folder that is open in panel
2815*f6dc9357SAndroid Build Coastguard Worker     !folderPath.IsEmpty()  : CopyFsItems() to folderPath.
2816*f6dc9357SAndroid Build Coastguard Worker */
CompressDropFiles(const UStringVector & filePaths,const UString & folderPath,bool createNewArchive,bool moveMode,UInt32 sourceFlags,UInt32 & targetFlags)2817*f6dc9357SAndroid Build Coastguard Worker void CPanel::CompressDropFiles(
2818*f6dc9357SAndroid Build Coastguard Worker     const UStringVector &filePaths,
2819*f6dc9357SAndroid Build Coastguard Worker     const UString &folderPath,
2820*f6dc9357SAndroid Build Coastguard Worker     bool createNewArchive,
2821*f6dc9357SAndroid Build Coastguard Worker     bool moveMode,
2822*f6dc9357SAndroid Build Coastguard Worker     UInt32 sourceFlags,
2823*f6dc9357SAndroid Build Coastguard Worker     UInt32 &targetFlags
2824*f6dc9357SAndroid Build Coastguard Worker     )
2825*f6dc9357SAndroid Build Coastguard Worker {
2826*f6dc9357SAndroid Build Coastguard Worker   if (filePaths.Size() == 0)
2827*f6dc9357SAndroid Build Coastguard Worker     return;
2828*f6dc9357SAndroid Build Coastguard Worker   // createNewArchive = false; // for debug
2829*f6dc9357SAndroid Build Coastguard Worker 
2830*f6dc9357SAndroid Build Coastguard Worker   if (createNewArchive)
2831*f6dc9357SAndroid Build Coastguard Worker   {
2832*f6dc9357SAndroid Build Coastguard Worker     UString folderPath2 = folderPath;
2833*f6dc9357SAndroid Build Coastguard Worker     // folderPath2.Empty(); // for debug
2834*f6dc9357SAndroid Build Coastguard Worker     if (folderPath2.IsEmpty())
2835*f6dc9357SAndroid Build Coastguard Worker     {
2836*f6dc9357SAndroid Build Coastguard Worker       {
2837*f6dc9357SAndroid Build Coastguard Worker         FString folderPath2F;
2838*f6dc9357SAndroid Build Coastguard Worker         GetOnlyDirPrefix(us2fs(filePaths.Front()), folderPath2F);
2839*f6dc9357SAndroid Build Coastguard Worker         folderPath2 = fs2us(folderPath2F);
2840*f6dc9357SAndroid Build Coastguard Worker       }
2841*f6dc9357SAndroid Build Coastguard Worker       if (IsFolderInTemp(folderPath2))
2842*f6dc9357SAndroid Build Coastguard Worker       {
2843*f6dc9357SAndroid Build Coastguard Worker         /* we don't want archive to be created in temp directory.
2844*f6dc9357SAndroid Build Coastguard Worker            so we change the path to root folder (non-temp) */
2845*f6dc9357SAndroid Build Coastguard Worker         folderPath2 = ROOT_FS_FOLDER;
2846*f6dc9357SAndroid Build Coastguard Worker       }
2847*f6dc9357SAndroid Build Coastguard Worker     }
2848*f6dc9357SAndroid Build Coastguard Worker 
2849*f6dc9357SAndroid Build Coastguard Worker     UString arcName_base;
2850*f6dc9357SAndroid Build Coastguard Worker     const UString arcName = CreateArchiveName(filePaths,
2851*f6dc9357SAndroid Build Coastguard Worker         false, // isHash
2852*f6dc9357SAndroid Build Coastguard Worker         NULL,  // CFileInfo *fi
2853*f6dc9357SAndroid Build Coastguard Worker         arcName_base);
2854*f6dc9357SAndroid Build Coastguard Worker 
2855*f6dc9357SAndroid Build Coastguard Worker     bool needWait;
2856*f6dc9357SAndroid Build Coastguard Worker     if (sourceFlags & k_SourceFlags_WaitFinish)
2857*f6dc9357SAndroid Build Coastguard Worker       needWait = true;
2858*f6dc9357SAndroid Build Coastguard Worker     else if (sourceFlags & k_SourceFlags_DoNotWaitFinish)
2859*f6dc9357SAndroid Build Coastguard Worker       needWait = false;
2860*f6dc9357SAndroid Build Coastguard Worker     else if (sourceFlags & k_SourceFlags_TempFiles)
2861*f6dc9357SAndroid Build Coastguard Worker       needWait = true;
2862*f6dc9357SAndroid Build Coastguard Worker     else
2863*f6dc9357SAndroid Build Coastguard Worker       needWait = AreThereNamesFromTemp(filePaths);
2864*f6dc9357SAndroid Build Coastguard Worker 
2865*f6dc9357SAndroid Build Coastguard Worker     targetFlags |= (needWait ?
2866*f6dc9357SAndroid Build Coastguard Worker         k_TargetFlags_WaitFinish :
2867*f6dc9357SAndroid Build Coastguard Worker         k_TargetFlags_DoNotWaitFinish);
2868*f6dc9357SAndroid Build Coastguard Worker 
2869*f6dc9357SAndroid Build Coastguard Worker     CompressFiles(folderPath2, arcName,
2870*f6dc9357SAndroid Build Coastguard Worker         L"",      // arcType
2871*f6dc9357SAndroid Build Coastguard Worker         true,     // addExtension
2872*f6dc9357SAndroid Build Coastguard Worker         filePaths,
2873*f6dc9357SAndroid Build Coastguard Worker         false,    // email
2874*f6dc9357SAndroid Build Coastguard Worker         true,     // showDialog
2875*f6dc9357SAndroid Build Coastguard Worker         needWait);
2876*f6dc9357SAndroid Build Coastguard Worker   }
2877*f6dc9357SAndroid Build Coastguard Worker   else
2878*f6dc9357SAndroid Build Coastguard Worker   {
2879*f6dc9357SAndroid Build Coastguard Worker     targetFlags |= k_TargetFlags_WaitFinish;
2880*f6dc9357SAndroid Build Coastguard Worker     if (!folderPath.IsEmpty())
2881*f6dc9357SAndroid Build Coastguard Worker     {
2882*f6dc9357SAndroid Build Coastguard Worker       CCopyToOptions options;
2883*f6dc9357SAndroid Build Coastguard Worker       options.moveMode = moveMode;
2884*f6dc9357SAndroid Build Coastguard Worker       options.folder = folderPath;
2885*f6dc9357SAndroid Build Coastguard Worker       options.showErrorMessages = true; // showErrorMessages is not used for this operation
2886*f6dc9357SAndroid Build Coastguard Worker       options.NeedRegistryZone = false;
2887*f6dc9357SAndroid Build Coastguard Worker       options.ZoneIdMode = NExtract::NZoneIdMode::kNone;
2888*f6dc9357SAndroid Build Coastguard Worker       // maybe we need more options here: FIXME
2889*f6dc9357SAndroid Build Coastguard Worker       /* HRESULT hres = */ CopyFsItems(options,
2890*f6dc9357SAndroid Build Coastguard Worker           filePaths,
2891*f6dc9357SAndroid Build Coastguard Worker           NULL // UStringVector *messages
2892*f6dc9357SAndroid Build Coastguard Worker           );
2893*f6dc9357SAndroid Build Coastguard Worker       // hres = hres;
2894*f6dc9357SAndroid Build Coastguard Worker     }
2895*f6dc9357SAndroid Build Coastguard Worker     else
2896*f6dc9357SAndroid Build Coastguard Worker     {
2897*f6dc9357SAndroid Build Coastguard Worker       CopyFromNoAsk(moveMode, filePaths);
2898*f6dc9357SAndroid Build Coastguard Worker     }
2899*f6dc9357SAndroid Build Coastguard Worker   }
2900*f6dc9357SAndroid Build Coastguard Worker }
2901*f6dc9357SAndroid Build Coastguard Worker 
2902*f6dc9357SAndroid Build Coastguard Worker 
2903*f6dc9357SAndroid Build Coastguard Worker 
Drag_OnContextMenu(int xPos,int yPos,UInt32 cmdFlags)2904*f6dc9357SAndroid Build Coastguard Worker static unsigned Drag_OnContextMenu(int xPos, int yPos, UInt32 cmdFlags)
2905*f6dc9357SAndroid Build Coastguard Worker {
2906*f6dc9357SAndroid Build Coastguard Worker   CMenu menu;
2907*f6dc9357SAndroid Build Coastguard Worker   CMenuDestroyer menuDestroyer(menu);
2908*f6dc9357SAndroid Build Coastguard Worker   /*
2909*f6dc9357SAndroid Build Coastguard Worker     Esc key in shown menu doesn't work if we call Drag_OnContextMenu from ::Drop().
2910*f6dc9357SAndroid Build Coastguard Worker     We call SetFocus() tp solve that problem.
2911*f6dc9357SAndroid Build Coastguard Worker     But the focus will be changed to Target Window after Drag and Drop.
2912*f6dc9357SAndroid Build Coastguard Worker     Is it OK to use SetFocus() here ?
2913*f6dc9357SAndroid Build Coastguard Worker     Is there another way to enable Esc key ?
2914*f6dc9357SAndroid Build Coastguard Worker   */
2915*f6dc9357SAndroid Build Coastguard Worker   // _listView.SetFocus(); // for debug
2916*f6dc9357SAndroid Build Coastguard Worker   ::SetFocus(g_HWND);
2917*f6dc9357SAndroid Build Coastguard Worker   menu.CreatePopup();
2918*f6dc9357SAndroid Build Coastguard Worker   /*
2919*f6dc9357SAndroid Build Coastguard Worker   int defaultCmd; // = NDragMenu::k_Move;
2920*f6dc9357SAndroid Build Coastguard Worker   defaultCmd = NDragMenu::k_None;
2921*f6dc9357SAndroid Build Coastguard Worker   */
2922*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(NDragMenu::g_Pairs); i++)
2923*f6dc9357SAndroid Build Coastguard Worker   {
2924*f6dc9357SAndroid Build Coastguard Worker     const NDragMenu::CCmdLangPair &pair = NDragMenu::g_Pairs[i];
2925*f6dc9357SAndroid Build Coastguard Worker     const UInt32 cmdAndFlags = pair.CmdId_and_Flags;
2926*f6dc9357SAndroid Build Coastguard Worker     const UInt32 cmdId = cmdAndFlags & NDragMenu::k_MenuFlags_CmdMask;
2927*f6dc9357SAndroid Build Coastguard Worker     if (cmdId != NDragMenu::k_Cancel)
2928*f6dc9357SAndroid Build Coastguard Worker     if ((cmdFlags & ((UInt32)1 << cmdId)) == 0)
2929*f6dc9357SAndroid Build Coastguard Worker       continue;
2930*f6dc9357SAndroid Build Coastguard Worker     const UINT flags = MF_STRING;
2931*f6dc9357SAndroid Build Coastguard Worker     /*
2932*f6dc9357SAndroid Build Coastguard Worker     if (prop.IsVisible)
2933*f6dc9357SAndroid Build Coastguard Worker       flags |= MF_CHECKED;
2934*f6dc9357SAndroid Build Coastguard Worker     if (i == 0)
2935*f6dc9357SAndroid Build Coastguard Worker       flags |= MF_GRAYED;
2936*f6dc9357SAndroid Build Coastguard Worker     */
2937*f6dc9357SAndroid Build Coastguard Worker     // MF_DEFAULT doesn't work
2938*f6dc9357SAndroid Build Coastguard Worker     // if (i == 2) flags |= MF_DEFAULT;
2939*f6dc9357SAndroid Build Coastguard Worker     // if (i == 4) flags |= MF_HILITE;
2940*f6dc9357SAndroid Build Coastguard Worker     // if (cmd == defaultCmd) flags |= MF_HILITE;
2941*f6dc9357SAndroid Build Coastguard Worker     UString name = LangString(pair.LangId);
2942*f6dc9357SAndroid Build Coastguard Worker     if (name.IsEmpty())
2943*f6dc9357SAndroid Build Coastguard Worker     {
2944*f6dc9357SAndroid Build Coastguard Worker       if (cmdId == NDragMenu::k_Cancel)
2945*f6dc9357SAndroid Build Coastguard Worker         name = "Cancel";
2946*f6dc9357SAndroid Build Coastguard Worker       else
2947*f6dc9357SAndroid Build Coastguard Worker         name.Add_UInt32(pair.LangId);
2948*f6dc9357SAndroid Build Coastguard Worker     }
2949*f6dc9357SAndroid Build Coastguard Worker     if (cmdId == NDragMenu::k_Copy_ToArc)
2950*f6dc9357SAndroid Build Coastguard Worker     {
2951*f6dc9357SAndroid Build Coastguard Worker       // UString destPath = _currentFolderPrefix;
2952*f6dc9357SAndroid Build Coastguard Worker       /*
2953*f6dc9357SAndroid Build Coastguard Worker       UString destPath = LangString(IDS_CONTEXT_ARCHIVE);
2954*f6dc9357SAndroid Build Coastguard Worker       name = MyFormatNew(name, destPath);
2955*f6dc9357SAndroid Build Coastguard Worker       */
2956*f6dc9357SAndroid Build Coastguard Worker       name.Add_Space();
2957*f6dc9357SAndroid Build Coastguard Worker       AddLangString(name, IDS_CONTEXT_ARCHIVE);
2958*f6dc9357SAndroid Build Coastguard Worker     }
2959*f6dc9357SAndroid Build Coastguard Worker     if (cmdId == NDragMenu::k_Cancel)
2960*f6dc9357SAndroid Build Coastguard Worker       menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)NULL);
2961*f6dc9357SAndroid Build Coastguard Worker     menu.AppendItem(flags, cmdAndFlags, name);
2962*f6dc9357SAndroid Build Coastguard Worker   }
2963*f6dc9357SAndroid Build Coastguard Worker   /*
2964*f6dc9357SAndroid Build Coastguard Worker   if (defaultCmd != 0)
2965*f6dc9357SAndroid Build Coastguard Worker     SetMenuDefaultItem(menu, (unsigned)defaultCmd,
2966*f6dc9357SAndroid Build Coastguard Worker         FALSE); // byPos
2967*f6dc9357SAndroid Build Coastguard Worker   */
2968*f6dc9357SAndroid Build Coastguard Worker   int menuResult = menu.Track(
2969*f6dc9357SAndroid Build Coastguard Worker       TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
2970*f6dc9357SAndroid Build Coastguard Worker       xPos, yPos,
2971*f6dc9357SAndroid Build Coastguard Worker       g_HWND
2972*f6dc9357SAndroid Build Coastguard Worker       // _listView // for debug
2973*f6dc9357SAndroid Build Coastguard Worker       );
2974*f6dc9357SAndroid Build Coastguard Worker   /* menu.Track() return value is zero, if the user cancels
2975*f6dc9357SAndroid Build Coastguard Worker      the menu without making a selection, or if an error occurs */
2976*f6dc9357SAndroid Build Coastguard Worker   if (menuResult <= 0)
2977*f6dc9357SAndroid Build Coastguard Worker     menuResult = NDragMenu::k_Cancel;
2978*f6dc9357SAndroid Build Coastguard Worker   return (unsigned)menuResult;
2979*f6dc9357SAndroid Build Coastguard Worker }
2980*f6dc9357SAndroid Build Coastguard Worker 
2981*f6dc9357SAndroid Build Coastguard Worker 
2982*f6dc9357SAndroid Build Coastguard Worker 
CreateDragTarget()2983*f6dc9357SAndroid Build Coastguard Worker void CApp::CreateDragTarget()
2984*f6dc9357SAndroid Build Coastguard Worker {
2985*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec = new CDropTarget();
2986*f6dc9357SAndroid Build Coastguard Worker   _dropTarget = _dropTargetSpec;
2987*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->App = (this);
2988*f6dc9357SAndroid Build Coastguard Worker }
2989*f6dc9357SAndroid Build Coastguard Worker 
SetFocusedPanel(unsigned index)2990*f6dc9357SAndroid Build Coastguard Worker void CApp::SetFocusedPanel(unsigned index)
2991*f6dc9357SAndroid Build Coastguard Worker {
2992*f6dc9357SAndroid Build Coastguard Worker   LastFocusedPanel = index;
2993*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->TargetPanelIndex = (int)LastFocusedPanel;
2994*f6dc9357SAndroid Build Coastguard Worker }
2995*f6dc9357SAndroid Build Coastguard Worker 
DragBegin(unsigned panelIndex)2996*f6dc9357SAndroid Build Coastguard Worker void CApp::DragBegin(unsigned panelIndex)
2997*f6dc9357SAndroid Build Coastguard Worker {
2998*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->TargetPanelIndex = (int)(NumPanels > 1 ? 1 - panelIndex : panelIndex);
2999*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->SrcPanelIndex = (int)panelIndex;
3000*f6dc9357SAndroid Build Coastguard Worker }
3001*f6dc9357SAndroid Build Coastguard Worker 
DragEnd()3002*f6dc9357SAndroid Build Coastguard Worker void CApp::DragEnd()
3003*f6dc9357SAndroid Build Coastguard Worker {
3004*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->TargetPanelIndex = (int)LastFocusedPanel;
3005*f6dc9357SAndroid Build Coastguard Worker   _dropTargetSpec->SrcPanelIndex = -1;
3006*f6dc9357SAndroid Build Coastguard Worker }
3007