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