xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/FSFolderCopy.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // FSFolderCopy.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyWindows.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Defs.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/DLL.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/ErrorMsg.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FilePathAutoRename.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "FSFolder.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
21*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
22*f6dc9357SAndroid Build Coastguard Worker using namespace NDir;
23*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
24*f6dc9357SAndroid Build Coastguard Worker using namespace NFind;
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
27*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
28*f6dc9357SAndroid Build Coastguard Worker #endif
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker namespace NFsFolder {
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker static const char * const k_CannotCopyDirToAltStream = "Cannot copy folder as alternate stream";
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker 
MyCopyFile(CFSTR inPath,CFSTR outPath,DWORD attrib)35*f6dc9357SAndroid Build Coastguard Worker HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib)
36*f6dc9357SAndroid Build Coastguard Worker {
37*f6dc9357SAndroid Build Coastguard Worker   ErrorFileIndex = -1;
38*f6dc9357SAndroid Build Coastguard Worker   ErrorMessage.Empty();
39*f6dc9357SAndroid Build Coastguard Worker   CurrentSize = 0;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker   {
42*f6dc9357SAndroid Build Coastguard Worker     const size_t kBufSize = 1 << 16;
43*f6dc9357SAndroid Build Coastguard Worker     CByteArr buf(kBufSize);
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker     NIO::CInFile inFile;
46*f6dc9357SAndroid Build Coastguard Worker     NIO::COutFile outFile;
47*f6dc9357SAndroid Build Coastguard Worker 
48*f6dc9357SAndroid Build Coastguard Worker     if (!inFile.Open(inPath))
49*f6dc9357SAndroid Build Coastguard Worker     {
50*f6dc9357SAndroid Build Coastguard Worker       ErrorFileIndex = 0;
51*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
52*f6dc9357SAndroid Build Coastguard Worker     }
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker     if (!outFile.Create_ALWAYS(outPath))
55*f6dc9357SAndroid Build Coastguard Worker     {
56*f6dc9357SAndroid Build Coastguard Worker       ErrorFileIndex = 1;
57*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
58*f6dc9357SAndroid Build Coastguard Worker     }
59*f6dc9357SAndroid Build Coastguard Worker 
60*f6dc9357SAndroid Build Coastguard Worker     for (;;)
61*f6dc9357SAndroid Build Coastguard Worker     {
62*f6dc9357SAndroid Build Coastguard Worker       UInt32 num;
63*f6dc9357SAndroid Build Coastguard Worker       if (!inFile.Read(buf, kBufSize, num))
64*f6dc9357SAndroid Build Coastguard Worker       {
65*f6dc9357SAndroid Build Coastguard Worker         ErrorFileIndex = 0;
66*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
67*f6dc9357SAndroid Build Coastguard Worker       }
68*f6dc9357SAndroid Build Coastguard Worker       if (num == 0)
69*f6dc9357SAndroid Build Coastguard Worker         break;
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker       UInt32 written = 0;
72*f6dc9357SAndroid Build Coastguard Worker       if (!outFile.Write(buf, num, written))
73*f6dc9357SAndroid Build Coastguard Worker       {
74*f6dc9357SAndroid Build Coastguard Worker         ErrorFileIndex = 1;
75*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
76*f6dc9357SAndroid Build Coastguard Worker       }
77*f6dc9357SAndroid Build Coastguard Worker       if (written != num)
78*f6dc9357SAndroid Build Coastguard Worker       {
79*f6dc9357SAndroid Build Coastguard Worker         ErrorMessage = "Write error";
80*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
81*f6dc9357SAndroid Build Coastguard Worker       }
82*f6dc9357SAndroid Build Coastguard Worker       CurrentSize += num;
83*f6dc9357SAndroid Build Coastguard Worker       if (Progress)
84*f6dc9357SAndroid Build Coastguard Worker       {
85*f6dc9357SAndroid Build Coastguard Worker         UInt64 completed = StartPos + CurrentSize;
86*f6dc9357SAndroid Build Coastguard Worker         RINOK(Progress->SetCompleted(&completed))
87*f6dc9357SAndroid Build Coastguard Worker       }
88*f6dc9357SAndroid Build Coastguard Worker     }
89*f6dc9357SAndroid Build Coastguard Worker   }
90*f6dc9357SAndroid Build Coastguard Worker 
91*f6dc9357SAndroid Build Coastguard Worker   /* SetFileAttrib("path:alt_stream_name") sets attributes for main file "path".
92*f6dc9357SAndroid Build Coastguard Worker      But we don't want to change attributes of main file, when we write alt stream.
93*f6dc9357SAndroid Build Coastguard Worker      So we need INVALID_FILE_ATTRIBUTES for alt stream here */
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker   if (attrib != INVALID_FILE_ATTRIBUTES)
96*f6dc9357SAndroid Build Coastguard Worker     SetFileAttrib(outPath, attrib);
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker   if (DeleteSrcFile)
99*f6dc9357SAndroid Build Coastguard Worker   {
100*f6dc9357SAndroid Build Coastguard Worker     if (!DeleteFileAlways(inPath))
101*f6dc9357SAndroid Build Coastguard Worker     {
102*f6dc9357SAndroid Build Coastguard Worker       ErrorFileIndex = 0;
103*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
104*f6dc9357SAndroid Build Coastguard Worker     }
105*f6dc9357SAndroid Build Coastguard Worker   }
106*f6dc9357SAndroid Build Coastguard Worker 
107*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
108*f6dc9357SAndroid Build Coastguard Worker }
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker 
111*f6dc9357SAndroid Build Coastguard Worker /*
112*f6dc9357SAndroid Build Coastguard Worker static bool IsItWindows2000orHigher()
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker   OSVERSIONINFO versionInfo;
115*f6dc9357SAndroid Build Coastguard Worker   versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
116*f6dc9357SAndroid Build Coastguard Worker   if (!::GetVersionEx(&versionInfo))
117*f6dc9357SAndroid Build Coastguard Worker     return false;
118*f6dc9357SAndroid Build Coastguard Worker   return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
119*f6dc9357SAndroid Build Coastguard Worker       (versionInfo.dwMajorVersion >= 5);
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker */
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker struct CProgressInfo
124*f6dc9357SAndroid Build Coastguard Worker {
125*f6dc9357SAndroid Build Coastguard Worker   UInt64 TotalSize;
126*f6dc9357SAndroid Build Coastguard Worker   UInt64 StartPos;
127*f6dc9357SAndroid Build Coastguard Worker   UInt64 FileSize;
128*f6dc9357SAndroid Build Coastguard Worker   IProgress *Progress;
129*f6dc9357SAndroid Build Coastguard Worker   HRESULT ProgressResult;
130*f6dc9357SAndroid Build Coastguard Worker 
InitNFsFolder::CProgressInfo131*f6dc9357SAndroid Build Coastguard Worker   void Init() { ProgressResult = S_OK; }
132*f6dc9357SAndroid Build Coastguard Worker };
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker #ifndef PROGRESS_CONTINUE
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker #define PROGRESS_CONTINUE 0
137*f6dc9357SAndroid Build Coastguard Worker #define PROGRESS_CANCEL 1
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker #define COPY_FILE_FAIL_IF_EXISTS 0x00000001
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker typedef
142*f6dc9357SAndroid Build Coastguard Worker DWORD
143*f6dc9357SAndroid Build Coastguard Worker (WINAPI* LPPROGRESS_ROUTINE)(
144*f6dc9357SAndroid Build Coastguard Worker     LARGE_INTEGER TotalFileSize,
145*f6dc9357SAndroid Build Coastguard Worker     LARGE_INTEGER TotalBytesTransferred,
146*f6dc9357SAndroid Build Coastguard Worker     LARGE_INTEGER StreamSize,
147*f6dc9357SAndroid Build Coastguard Worker     LARGE_INTEGER StreamBytesTransferred,
148*f6dc9357SAndroid Build Coastguard Worker     DWORD dwStreamNumber,
149*f6dc9357SAndroid Build Coastguard Worker     DWORD dwCallbackReason,
150*f6dc9357SAndroid Build Coastguard Worker     HANDLE hSourceFile,
151*f6dc9357SAndroid Build Coastguard Worker     HANDLE hDestinationFile,
152*f6dc9357SAndroid Build Coastguard Worker     LPVOID lpData
153*f6dc9357SAndroid Build Coastguard Worker     );
154*f6dc9357SAndroid Build Coastguard Worker 
155*f6dc9357SAndroid Build Coastguard Worker #endif
156*f6dc9357SAndroid Build Coastguard Worker 
CopyProgressRoutine(LARGE_INTEGER TotalFileSize,LARGE_INTEGER TotalBytesTransferred,LARGE_INTEGER,LARGE_INTEGER,DWORD,DWORD,HANDLE,HANDLE,LPVOID lpData)157*f6dc9357SAndroid Build Coastguard Worker static DWORD CALLBACK CopyProgressRoutine(
158*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER TotalFileSize,          // file size
159*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER TotalBytesTransferred,  // bytes transferred
160*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER /* StreamSize */,             // bytes in stream
161*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
162*f6dc9357SAndroid Build Coastguard Worker   DWORD /* dwStreamNumber */,                 // current stream
163*f6dc9357SAndroid Build Coastguard Worker   DWORD /* dwCallbackReason */,               // callback reason
164*f6dc9357SAndroid Build Coastguard Worker   HANDLE /* hSourceFile */,                   // handle to source file
165*f6dc9357SAndroid Build Coastguard Worker   HANDLE /* hDestinationFile */,              // handle to destination file
166*f6dc9357SAndroid Build Coastguard Worker   LPVOID lpData                         // from CopyFileEx
167*f6dc9357SAndroid Build Coastguard Worker )
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker   // StreamSize = StreamSize;
170*f6dc9357SAndroid Build Coastguard Worker   // StreamBytesTransferred = StreamBytesTransferred;
171*f6dc9357SAndroid Build Coastguard Worker   // dwStreamNumber = dwStreamNumber;
172*f6dc9357SAndroid Build Coastguard Worker   // dwCallbackReason = dwCallbackReason;
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker   CProgressInfo &pi = *(CProgressInfo *)lpData;
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   if ((UInt64)TotalFileSize.QuadPart > pi.FileSize)
177*f6dc9357SAndroid Build Coastguard Worker   {
178*f6dc9357SAndroid Build Coastguard Worker     pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize;
179*f6dc9357SAndroid Build Coastguard Worker     pi.FileSize = (UInt64)TotalFileSize.QuadPart;
180*f6dc9357SAndroid Build Coastguard Worker     pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize);
181*f6dc9357SAndroid Build Coastguard Worker   }
182*f6dc9357SAndroid Build Coastguard Worker   const UInt64 completed = pi.StartPos + (UInt64)TotalBytesTransferred.QuadPart;
183*f6dc9357SAndroid Build Coastguard Worker   pi.ProgressResult = pi.Progress->SetCompleted(&completed);
184*f6dc9357SAndroid Build Coastguard Worker   return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
185*f6dc9357SAndroid Build Coastguard Worker }
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500  // win2000
188*f6dc9357SAndroid Build Coastguard Worker #define Z7_USE_DYN_MoveFileWithProgressW
189*f6dc9357SAndroid Build Coastguard Worker #endif
190*f6dc9357SAndroid Build Coastguard Worker 
191*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
192*f6dc9357SAndroid Build Coastguard Worker // nt4
193*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI * Func_CopyFileExA)(
194*f6dc9357SAndroid Build Coastguard Worker     IN LPCSTR lpExistingFileName,
195*f6dc9357SAndroid Build Coastguard Worker     IN LPCSTR lpNewFileName,
196*f6dc9357SAndroid Build Coastguard Worker     IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
197*f6dc9357SAndroid Build Coastguard Worker     IN LPVOID lpData OPTIONAL,
198*f6dc9357SAndroid Build Coastguard Worker     IN LPBOOL pbCancel OPTIONAL,
199*f6dc9357SAndroid Build Coastguard Worker     IN DWORD dwCopyFlags
200*f6dc9357SAndroid Build Coastguard Worker     );
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker // nt4
203*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI * Func_CopyFileExW)(
204*f6dc9357SAndroid Build Coastguard Worker     IN LPCWSTR lpExistingFileName,
205*f6dc9357SAndroid Build Coastguard Worker     IN LPCWSTR lpNewFileName,
206*f6dc9357SAndroid Build Coastguard Worker     IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
207*f6dc9357SAndroid Build Coastguard Worker     IN LPVOID lpData OPTIONAL,
208*f6dc9357SAndroid Build Coastguard Worker     IN LPBOOL pbCancel OPTIONAL,
209*f6dc9357SAndroid Build Coastguard Worker     IN DWORD dwCopyFlags
210*f6dc9357SAndroid Build Coastguard Worker     );
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker // win2000
213*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
214*f6dc9357SAndroid Build Coastguard Worker     IN LPCWSTR lpExistingFileName,
215*f6dc9357SAndroid Build Coastguard Worker     IN LPCWSTR lpNewFileName,
216*f6dc9357SAndroid Build Coastguard Worker     IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
217*f6dc9357SAndroid Build Coastguard Worker     IN LPVOID lpData OPTIONAL,
218*f6dc9357SAndroid Build Coastguard Worker     IN DWORD dwFlags
219*f6dc9357SAndroid Build Coastguard Worker     );
220*f6dc9357SAndroid Build Coastguard Worker #endif
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker struct CCopyState
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker   CProgressInfo ProgressInfo;
225*f6dc9357SAndroid Build Coastguard Worker   IFolderOperationsExtractCallback *Callback;
226*f6dc9357SAndroid Build Coastguard Worker   bool MoveMode;
227*f6dc9357SAndroid Build Coastguard Worker   bool UseReadWriteMode;
228*f6dc9357SAndroid Build Coastguard Worker   bool IsAltStreamsDest;
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
231*f6dc9357SAndroid Build Coastguard Worker private:
232*f6dc9357SAndroid Build Coastguard Worker   Func_CopyFileExW my_CopyFileExW;
233*f6dc9357SAndroid Build Coastguard Worker   #ifndef UNDER_CE
234*f6dc9357SAndroid Build Coastguard Worker   Func_MoveFileWithProgressW my_MoveFileWithProgressW;
235*f6dc9357SAndroid Build Coastguard Worker   #endif
236*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
237*f6dc9357SAndroid Build Coastguard Worker   Func_CopyFileExA my_CopyFileExA;
238*f6dc9357SAndroid Build Coastguard Worker   #endif
239*f6dc9357SAndroid Build Coastguard Worker public:
240*f6dc9357SAndroid Build Coastguard Worker   CCopyState();
241*f6dc9357SAndroid Build Coastguard Worker #endif
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker   bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
244*f6dc9357SAndroid Build Coastguard Worker   bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
245*f6dc9357SAndroid Build Coastguard Worker   bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
246*f6dc9357SAndroid Build Coastguard Worker 
247*f6dc9357SAndroid Build Coastguard Worker   HRESULT CallProgress();
248*f6dc9357SAndroid Build Coastguard Worker 
IsCallbackProgressErrorNFsFolder::CCopyState249*f6dc9357SAndroid Build Coastguard Worker   bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; }
250*f6dc9357SAndroid Build Coastguard Worker };
251*f6dc9357SAndroid Build Coastguard Worker 
CallProgress()252*f6dc9357SAndroid Build Coastguard Worker HRESULT CCopyState::CallProgress()
253*f6dc9357SAndroid Build Coastguard Worker {
254*f6dc9357SAndroid Build Coastguard Worker   return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
258*f6dc9357SAndroid Build Coastguard Worker 
CCopyState()259*f6dc9357SAndroid Build Coastguard Worker CCopyState::CCopyState()
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker   my_CopyFileExW = NULL;
262*f6dc9357SAndroid Build Coastguard Worker   #ifndef UNDER_CE
263*f6dc9357SAndroid Build Coastguard Worker   my_MoveFileWithProgressW = NULL;
264*f6dc9357SAndroid Build Coastguard Worker   #endif
265*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
266*f6dc9357SAndroid Build Coastguard Worker   my_CopyFileExA = NULL;
267*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
268*f6dc9357SAndroid Build Coastguard Worker   {
269*f6dc9357SAndroid Build Coastguard Worker       my_CopyFileExA = Z7_GET_PROC_ADDRESS(
270*f6dc9357SAndroid Build Coastguard Worker     Func_CopyFileExA, ::GetModuleHandleA("kernel32.dll"),
271*f6dc9357SAndroid Build Coastguard Worker         "CopyFileExA");
272*f6dc9357SAndroid Build Coastguard Worker   }
273*f6dc9357SAndroid Build Coastguard Worker   else
274*f6dc9357SAndroid Build Coastguard Worker   #endif
275*f6dc9357SAndroid Build Coastguard Worker   {
276*f6dc9357SAndroid Build Coastguard Worker     const HMODULE module = ::GetModuleHandleW(
277*f6dc9357SAndroid Build Coastguard Worker       #ifdef UNDER_CE
278*f6dc9357SAndroid Build Coastguard Worker         L"coredll.dll"
279*f6dc9357SAndroid Build Coastguard Worker       #else
280*f6dc9357SAndroid Build Coastguard Worker         L"kernel32.dll"
281*f6dc9357SAndroid Build Coastguard Worker       #endif
282*f6dc9357SAndroid Build Coastguard Worker         );
283*f6dc9357SAndroid Build Coastguard Worker       my_CopyFileExW = Z7_GET_PROC_ADDRESS(
284*f6dc9357SAndroid Build Coastguard Worker     Func_CopyFileExW, module,
285*f6dc9357SAndroid Build Coastguard Worker         "CopyFileExW");
286*f6dc9357SAndroid Build Coastguard Worker     #ifndef UNDER_CE
287*f6dc9357SAndroid Build Coastguard Worker       my_MoveFileWithProgressW = Z7_GET_PROC_ADDRESS(
288*f6dc9357SAndroid Build Coastguard Worker     Func_MoveFileWithProgressW, module,
289*f6dc9357SAndroid Build Coastguard Worker         "MoveFileWithProgressW");
290*f6dc9357SAndroid Build Coastguard Worker     #endif
291*f6dc9357SAndroid Build Coastguard Worker   }
292*f6dc9357SAndroid Build Coastguard Worker }
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker #endif
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker /* WinXP-64:
297*f6dc9357SAndroid Build Coastguard Worker   CopyFileW(fromFile, toFile:altStream)
298*f6dc9357SAndroid Build Coastguard Worker     OK                       - there are NO alt streams in fromFile
299*f6dc9357SAndroid Build Coastguard Worker     ERROR_INVALID_PARAMETER  - there are    alt streams in fromFile
300*f6dc9357SAndroid Build Coastguard Worker */
301*f6dc9357SAndroid Build Coastguard Worker 
CopyFile_NT(const wchar_t * oldFile,const wchar_t * newFile)302*f6dc9357SAndroid Build Coastguard Worker bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker   BOOL cancelFlag = FALSE;
305*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
306*f6dc9357SAndroid Build Coastguard Worker   if (my_CopyFileExW)
307*f6dc9357SAndroid Build Coastguard Worker #endif
308*f6dc9357SAndroid Build Coastguard Worker     return BOOLToBool(
309*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
310*f6dc9357SAndroid Build Coastguard Worker       my_CopyFileExW
311*f6dc9357SAndroid Build Coastguard Worker #else
312*f6dc9357SAndroid Build Coastguard Worker          CopyFileExW
313*f6dc9357SAndroid Build Coastguard Worker #endif
314*f6dc9357SAndroid Build Coastguard Worker       (oldFile, newFile, CopyProgressRoutine,
315*f6dc9357SAndroid Build Coastguard Worker         &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
316*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
317*f6dc9357SAndroid Build Coastguard Worker   return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
318*f6dc9357SAndroid Build Coastguard Worker #endif
319*f6dc9357SAndroid Build Coastguard Worker }
320*f6dc9357SAndroid Build Coastguard Worker 
CopyFile_Sys(CFSTR oldFile,CFSTR newFile)321*f6dc9357SAndroid Build Coastguard Worker bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
322*f6dc9357SAndroid Build Coastguard Worker {
323*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
324*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
325*f6dc9357SAndroid Build Coastguard Worker   {
326*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
327*f6dc9357SAndroid Build Coastguard Worker     if (my_CopyFileExA)
328*f6dc9357SAndroid Build Coastguard Worker #endif
329*f6dc9357SAndroid Build Coastguard Worker     {
330*f6dc9357SAndroid Build Coastguard Worker       BOOL cancelFlag = FALSE;
331*f6dc9357SAndroid Build Coastguard Worker       if (
332*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
333*f6dc9357SAndroid Build Coastguard Worker           my_CopyFileExA
334*f6dc9357SAndroid Build Coastguard Worker #else
335*f6dc9357SAndroid Build Coastguard Worker              CopyFileExA
336*f6dc9357SAndroid Build Coastguard Worker #endif
337*f6dc9357SAndroid Build Coastguard Worker           (fs2fas(oldFile), fs2fas(newFile),
338*f6dc9357SAndroid Build Coastguard Worker           CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
339*f6dc9357SAndroid Build Coastguard Worker         return true;
340*f6dc9357SAndroid Build Coastguard Worker       if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
341*f6dc9357SAndroid Build Coastguard Worker         return false;
342*f6dc9357SAndroid Build Coastguard Worker     }
343*f6dc9357SAndroid Build Coastguard Worker     return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
344*f6dc9357SAndroid Build Coastguard Worker   }
345*f6dc9357SAndroid Build Coastguard Worker   else
346*f6dc9357SAndroid Build Coastguard Worker   #endif
347*f6dc9357SAndroid Build Coastguard Worker   {
348*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH_2(oldFile, newFile)
349*f6dc9357SAndroid Build Coastguard Worker     {
350*f6dc9357SAndroid Build Coastguard Worker       if (CopyFile_NT(fs2us(oldFile), fs2us(newFile)))
351*f6dc9357SAndroid Build Coastguard Worker         return true;
352*f6dc9357SAndroid Build Coastguard Worker     }
353*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
354*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH_2)
355*f6dc9357SAndroid Build Coastguard Worker     {
356*f6dc9357SAndroid Build Coastguard Worker       if (IsCallbackProgressError())
357*f6dc9357SAndroid Build Coastguard Worker         return false;
358*f6dc9357SAndroid Build Coastguard Worker       UString superPathOld, superPathNew;
359*f6dc9357SAndroid Build Coastguard Worker       if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
360*f6dc9357SAndroid Build Coastguard Worker         return false;
361*f6dc9357SAndroid Build Coastguard Worker       if (CopyFile_NT(superPathOld, superPathNew))
362*f6dc9357SAndroid Build Coastguard Worker         return true;
363*f6dc9357SAndroid Build Coastguard Worker     }
364*f6dc9357SAndroid Build Coastguard Worker     #endif
365*f6dc9357SAndroid Build Coastguard Worker     return false;
366*f6dc9357SAndroid Build Coastguard Worker   }
367*f6dc9357SAndroid Build Coastguard Worker }
368*f6dc9357SAndroid Build Coastguard Worker 
MoveFile_Sys(CFSTR oldFile,CFSTR newFile)369*f6dc9357SAndroid Build Coastguard Worker bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker   #ifndef UNDER_CE
372*f6dc9357SAndroid Build Coastguard Worker   // if (IsItWindows2000orHigher())
373*f6dc9357SAndroid Build Coastguard Worker   // {
374*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
375*f6dc9357SAndroid Build Coastguard Worker     if (my_MoveFileWithProgressW)
376*f6dc9357SAndroid Build Coastguard Worker #endif
377*f6dc9357SAndroid Build Coastguard Worker     {
378*f6dc9357SAndroid Build Coastguard Worker       IF_USE_MAIN_PATH_2(oldFile, newFile)
379*f6dc9357SAndroid Build Coastguard Worker       {
380*f6dc9357SAndroid Build Coastguard Worker         if (
381*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
382*f6dc9357SAndroid Build Coastguard Worker           my_MoveFileWithProgressW
383*f6dc9357SAndroid Build Coastguard Worker #else
384*f6dc9357SAndroid Build Coastguard Worker              MoveFileWithProgressW
385*f6dc9357SAndroid Build Coastguard Worker #endif
386*f6dc9357SAndroid Build Coastguard Worker           (fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
387*f6dc9357SAndroid Build Coastguard Worker             &ProgressInfo, MOVEFILE_COPY_ALLOWED))
388*f6dc9357SAndroid Build Coastguard Worker           return true;
389*f6dc9357SAndroid Build Coastguard Worker       }
390*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_LONG_PATH
391*f6dc9357SAndroid Build Coastguard Worker       if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2)
392*f6dc9357SAndroid Build Coastguard Worker       {
393*f6dc9357SAndroid Build Coastguard Worker         if (IsCallbackProgressError())
394*f6dc9357SAndroid Build Coastguard Worker           return false;
395*f6dc9357SAndroid Build Coastguard Worker         UString superPathOld, superPathNew;
396*f6dc9357SAndroid Build Coastguard Worker         if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
397*f6dc9357SAndroid Build Coastguard Worker           return false;
398*f6dc9357SAndroid Build Coastguard Worker         if (
399*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_MoveFileWithProgressW
400*f6dc9357SAndroid Build Coastguard Worker           my_MoveFileWithProgressW
401*f6dc9357SAndroid Build Coastguard Worker #else
402*f6dc9357SAndroid Build Coastguard Worker              MoveFileWithProgressW
403*f6dc9357SAndroid Build Coastguard Worker #endif
404*f6dc9357SAndroid Build Coastguard Worker             (superPathOld, superPathNew, CopyProgressRoutine,
405*f6dc9357SAndroid Build Coastguard Worker             &ProgressInfo, MOVEFILE_COPY_ALLOWED))
406*f6dc9357SAndroid Build Coastguard Worker           return true;
407*f6dc9357SAndroid Build Coastguard Worker       }
408*f6dc9357SAndroid Build Coastguard Worker       #endif
409*f6dc9357SAndroid Build Coastguard Worker       if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
410*f6dc9357SAndroid Build Coastguard Worker         return false;
411*f6dc9357SAndroid Build Coastguard Worker     }
412*f6dc9357SAndroid Build Coastguard Worker   // }
413*f6dc9357SAndroid Build Coastguard Worker   // else
414*f6dc9357SAndroid Build Coastguard Worker   #endif
415*f6dc9357SAndroid Build Coastguard Worker     return MyMoveFile(oldFile, newFile);
416*f6dc9357SAndroid Build Coastguard Worker }
417*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError(IFolderOperationsExtractCallback * callback,const wchar_t * message,const FString & fileName)418*f6dc9357SAndroid Build Coastguard Worker static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
419*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *message, const FString &fileName)
420*f6dc9357SAndroid Build Coastguard Worker {
421*f6dc9357SAndroid Build Coastguard Worker   UString s = message;
422*f6dc9357SAndroid Build Coastguard Worker   s += " : ";
423*f6dc9357SAndroid Build Coastguard Worker   s += fs2us(fileName);
424*f6dc9357SAndroid Build Coastguard Worker   return callback->ShowMessage(s);
425*f6dc9357SAndroid Build Coastguard Worker }
426*f6dc9357SAndroid Build Coastguard Worker 
SendMessageError(IFolderOperationsExtractCallback * callback,const char * message,const FString & fileName)427*f6dc9357SAndroid Build Coastguard Worker static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
428*f6dc9357SAndroid Build Coastguard Worker     const char *message, const FString &fileName)
429*f6dc9357SAndroid Build Coastguard Worker {
430*f6dc9357SAndroid Build Coastguard Worker   return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
431*f6dc9357SAndroid Build Coastguard Worker }
432*f6dc9357SAndroid Build Coastguard Worker 
Return_LastError_or_FAIL()433*f6dc9357SAndroid Build Coastguard Worker static DWORD Return_LastError_or_FAIL()
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker   DWORD errorCode = GetLastError();
436*f6dc9357SAndroid Build Coastguard Worker   if (errorCode == 0)
437*f6dc9357SAndroid Build Coastguard Worker     errorCode = (DWORD)E_FAIL;
438*f6dc9357SAndroid Build Coastguard Worker   return errorCode;
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker 
GetLastErrorMessage()441*f6dc9357SAndroid Build Coastguard Worker static UString GetLastErrorMessage()
442*f6dc9357SAndroid Build Coastguard Worker {
443*f6dc9357SAndroid Build Coastguard Worker   return NError::MyFormatMessage(Return_LastError_or_FAIL());
444*f6dc9357SAndroid Build Coastguard Worker }
445*f6dc9357SAndroid Build Coastguard Worker 
SendLastErrorMessage(IFolderOperationsExtractCallback * callback,const FString & fileName)446*f6dc9357SAndroid Build Coastguard Worker HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName)
447*f6dc9357SAndroid Build Coastguard Worker {
448*f6dc9357SAndroid Build Coastguard Worker   return SendMessageError(callback, GetLastErrorMessage(), fileName);
449*f6dc9357SAndroid Build Coastguard Worker }
450*f6dc9357SAndroid Build Coastguard Worker 
CopyFile_Ask(CCopyState & state,const FString & srcPath,const CFileInfo & srcFileInfo,const FString & destPath)451*f6dc9357SAndroid Build Coastguard Worker static HRESULT CopyFile_Ask(
452*f6dc9357SAndroid Build Coastguard Worker     CCopyState &state,
453*f6dc9357SAndroid Build Coastguard Worker     const FString &srcPath,
454*f6dc9357SAndroid Build Coastguard Worker     const CFileInfo &srcFileInfo,
455*f6dc9357SAndroid Build Coastguard Worker     const FString &destPath)
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker   if (CompareFileNames(destPath, srcPath) == 0)
458*f6dc9357SAndroid Build Coastguard Worker   {
459*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError(state.Callback,
460*f6dc9357SAndroid Build Coastguard Worker         state.MoveMode ?
461*f6dc9357SAndroid Build Coastguard Worker           "Cannot move file onto itself" :
462*f6dc9357SAndroid Build Coastguard Worker           "Cannot copy file onto itself"
463*f6dc9357SAndroid Build Coastguard Worker         , destPath))
464*f6dc9357SAndroid Build Coastguard Worker     return E_ABORT;
465*f6dc9357SAndroid Build Coastguard Worker   }
466*f6dc9357SAndroid Build Coastguard Worker 
467*f6dc9357SAndroid Build Coastguard Worker   Int32 writeAskResult;
468*f6dc9357SAndroid Build Coastguard Worker   CMyComBSTR destPathResult;
469*f6dc9357SAndroid Build Coastguard Worker   RINOK(state.Callback->AskWrite(
470*f6dc9357SAndroid Build Coastguard Worker       fs2us(srcPath),
471*f6dc9357SAndroid Build Coastguard Worker       BoolToInt(false),
472*f6dc9357SAndroid Build Coastguard Worker       &srcFileInfo.MTime, &srcFileInfo.Size,
473*f6dc9357SAndroid Build Coastguard Worker       fs2us(destPath),
474*f6dc9357SAndroid Build Coastguard Worker       &destPathResult,
475*f6dc9357SAndroid Build Coastguard Worker       &writeAskResult))
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker   if (IntToBool(writeAskResult))
478*f6dc9357SAndroid Build Coastguard Worker   {
479*f6dc9357SAndroid Build Coastguard Worker     FString destPathNew = us2fs((LPCOLESTR)destPathResult);
480*f6dc9357SAndroid Build Coastguard Worker     RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath)))
481*f6dc9357SAndroid Build Coastguard Worker 
482*f6dc9357SAndroid Build Coastguard Worker     if (state.UseReadWriteMode)
483*f6dc9357SAndroid Build Coastguard Worker     {
484*f6dc9357SAndroid Build Coastguard Worker       NFsFolder::CCopyStateIO state2;
485*f6dc9357SAndroid Build Coastguard Worker       state2.Progress = state.Callback;
486*f6dc9357SAndroid Build Coastguard Worker       state2.DeleteSrcFile = state.MoveMode;
487*f6dc9357SAndroid Build Coastguard Worker       state2.TotalSize = state.ProgressInfo.TotalSize;
488*f6dc9357SAndroid Build Coastguard Worker       state2.StartPos = state.ProgressInfo.StartPos;
489*f6dc9357SAndroid Build Coastguard Worker 
490*f6dc9357SAndroid Build Coastguard Worker       RINOK(state2.MyCopyFile(srcPath, destPathNew,
491*f6dc9357SAndroid Build Coastguard Worker           state.IsAltStreamsDest ? INVALID_FILE_ATTRIBUTES: srcFileInfo.Attrib))
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker       if (state2.ErrorFileIndex >= 0)
494*f6dc9357SAndroid Build Coastguard Worker       {
495*f6dc9357SAndroid Build Coastguard Worker         if (state2.ErrorMessage.IsEmpty())
496*f6dc9357SAndroid Build Coastguard Worker           state2.ErrorMessage = GetLastErrorMessage();
497*f6dc9357SAndroid Build Coastguard Worker         FString errorName;
498*f6dc9357SAndroid Build Coastguard Worker         if (state2.ErrorFileIndex == 0)
499*f6dc9357SAndroid Build Coastguard Worker           errorName = srcPath;
500*f6dc9357SAndroid Build Coastguard Worker         else
501*f6dc9357SAndroid Build Coastguard Worker           errorName = destPathNew;
502*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName))
503*f6dc9357SAndroid Build Coastguard Worker         return E_ABORT;
504*f6dc9357SAndroid Build Coastguard Worker       }
505*f6dc9357SAndroid Build Coastguard Worker       state.ProgressInfo.StartPos += state2.CurrentSize;
506*f6dc9357SAndroid Build Coastguard Worker     }
507*f6dc9357SAndroid Build Coastguard Worker     else
508*f6dc9357SAndroid Build Coastguard Worker     {
509*f6dc9357SAndroid Build Coastguard Worker       state.ProgressInfo.FileSize = srcFileInfo.Size;
510*f6dc9357SAndroid Build Coastguard Worker       bool res;
511*f6dc9357SAndroid Build Coastguard Worker       if (state.MoveMode)
512*f6dc9357SAndroid Build Coastguard Worker         res = state.MoveFile_Sys(srcPath, destPathNew);
513*f6dc9357SAndroid Build Coastguard Worker       else
514*f6dc9357SAndroid Build Coastguard Worker         res = state.CopyFile_Sys(srcPath, destPathNew);
515*f6dc9357SAndroid Build Coastguard Worker       RINOK(state.ProgressInfo.ProgressResult)
516*f6dc9357SAndroid Build Coastguard Worker       if (!res)
517*f6dc9357SAndroid Build Coastguard Worker       {
518*f6dc9357SAndroid Build Coastguard Worker         const DWORD errorCode = GetLastError();
519*f6dc9357SAndroid Build Coastguard Worker         UString errorMessage = NError::MyFormatMessage(Return_LastError_or_FAIL());
520*f6dc9357SAndroid Build Coastguard Worker         if (errorCode == ERROR_INVALID_PARAMETER)
521*f6dc9357SAndroid Build Coastguard Worker         {
522*f6dc9357SAndroid Build Coastguard Worker           NFind::CFileInfo fi;
523*f6dc9357SAndroid Build Coastguard Worker           if (fi.Find(srcPath) &&
524*f6dc9357SAndroid Build Coastguard Worker               fi.Size > (UInt32)(Int32)-1)
525*f6dc9357SAndroid Build Coastguard Worker           {
526*f6dc9357SAndroid Build Coastguard Worker             // bool isFsDetected = false;
527*f6dc9357SAndroid Build Coastguard Worker             // if (NSystem::Is_File_LimitedBy_4GB(destPathNew, isFsDetected) || !isFsDetected)
528*f6dc9357SAndroid Build Coastguard Worker               errorMessage += " File size exceeds 4 GB";
529*f6dc9357SAndroid Build Coastguard Worker           }
530*f6dc9357SAndroid Build Coastguard Worker         }
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker         // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
533*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(state.Callback, errorMessage, destPathNew))
534*f6dc9357SAndroid Build Coastguard Worker         return E_ABORT;
535*f6dc9357SAndroid Build Coastguard Worker       }
536*f6dc9357SAndroid Build Coastguard Worker       state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
537*f6dc9357SAndroid Build Coastguard Worker     }
538*f6dc9357SAndroid Build Coastguard Worker   }
539*f6dc9357SAndroid Build Coastguard Worker   else
540*f6dc9357SAndroid Build Coastguard Worker   {
541*f6dc9357SAndroid Build Coastguard Worker     if (state.ProgressInfo.TotalSize >= srcFileInfo.Size)
542*f6dc9357SAndroid Build Coastguard Worker     {
543*f6dc9357SAndroid Build Coastguard Worker       state.ProgressInfo.TotalSize -= srcFileInfo.Size;
544*f6dc9357SAndroid Build Coastguard Worker       RINOK(state.ProgressInfo.Progress->SetTotal(state.ProgressInfo.TotalSize))
545*f6dc9357SAndroid Build Coastguard Worker     }
546*f6dc9357SAndroid Build Coastguard Worker   }
547*f6dc9357SAndroid Build Coastguard Worker   return state.CallProgress();
548*f6dc9357SAndroid Build Coastguard Worker }
549*f6dc9357SAndroid Build Coastguard Worker 
CombinePath(const FString & folderPath,const FString & fileName)550*f6dc9357SAndroid Build Coastguard Worker static FString CombinePath(const FString &folderPath, const FString &fileName)
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker   FString s (folderPath);
553*f6dc9357SAndroid Build Coastguard Worker   s.Add_PathSepar(); // FCHAR_PATH_SEPARATOR
554*f6dc9357SAndroid Build Coastguard Worker   s += fileName;
555*f6dc9357SAndroid Build Coastguard Worker   return s;
556*f6dc9357SAndroid Build Coastguard Worker }
557*f6dc9357SAndroid Build Coastguard Worker 
IsDestChild(const FString & src,const FString & dest)558*f6dc9357SAndroid Build Coastguard Worker static bool IsDestChild(const FString &src, const FString &dest)
559*f6dc9357SAndroid Build Coastguard Worker {
560*f6dc9357SAndroid Build Coastguard Worker   unsigned len = src.Len();
561*f6dc9357SAndroid Build Coastguard Worker   if (dest.Len() < len)
562*f6dc9357SAndroid Build Coastguard Worker     return false;
563*f6dc9357SAndroid Build Coastguard Worker   if (dest.Len() != len && dest[len] != FCHAR_PATH_SEPARATOR)
564*f6dc9357SAndroid Build Coastguard Worker     return false;
565*f6dc9357SAndroid Build Coastguard Worker   return CompareFileNames(dest.Left(len), src) == 0;
566*f6dc9357SAndroid Build Coastguard Worker }
567*f6dc9357SAndroid Build Coastguard Worker 
CopyFolder(CCopyState & state,const FString & srcPath,const FString & destPath)568*f6dc9357SAndroid Build Coastguard Worker static HRESULT CopyFolder(
569*f6dc9357SAndroid Build Coastguard Worker     CCopyState &state,
570*f6dc9357SAndroid Build Coastguard Worker     const FString &srcPath,   // without TAIL separator
571*f6dc9357SAndroid Build Coastguard Worker     const FString &destPath)  // without TAIL separator
572*f6dc9357SAndroid Build Coastguard Worker {
573*f6dc9357SAndroid Build Coastguard Worker   RINOK(state.CallProgress())
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker   if (IsDestChild(srcPath, destPath))
576*f6dc9357SAndroid Build Coastguard Worker   {
577*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError(state.Callback,
578*f6dc9357SAndroid Build Coastguard Worker         state.MoveMode ?
579*f6dc9357SAndroid Build Coastguard Worker           "Cannot copy folder onto itself" :
580*f6dc9357SAndroid Build Coastguard Worker           "Cannot move folder onto itself"
581*f6dc9357SAndroid Build Coastguard Worker         , destPath))
582*f6dc9357SAndroid Build Coastguard Worker     return E_ABORT;
583*f6dc9357SAndroid Build Coastguard Worker   }
584*f6dc9357SAndroid Build Coastguard Worker 
585*f6dc9357SAndroid Build Coastguard Worker   if (state.MoveMode)
586*f6dc9357SAndroid Build Coastguard Worker   {
587*f6dc9357SAndroid Build Coastguard Worker     if (state.MoveFile_Sys(srcPath, destPath))
588*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
589*f6dc9357SAndroid Build Coastguard Worker 
590*f6dc9357SAndroid Build Coastguard Worker     // MSDN: MoveFile() fails for dirs on different volumes.
591*f6dc9357SAndroid Build Coastguard Worker   }
592*f6dc9357SAndroid Build Coastguard Worker 
593*f6dc9357SAndroid Build Coastguard Worker   if (!CreateComplexDir(destPath))
594*f6dc9357SAndroid Build Coastguard Worker   {
595*f6dc9357SAndroid Build Coastguard Worker     RINOK(SendMessageError(state.Callback, "Cannot create folder", destPath))
596*f6dc9357SAndroid Build Coastguard Worker     return E_ABORT;
597*f6dc9357SAndroid Build Coastguard Worker   }
598*f6dc9357SAndroid Build Coastguard Worker 
599*f6dc9357SAndroid Build Coastguard Worker   CEnumerator enumerator;
600*f6dc9357SAndroid Build Coastguard Worker   enumerator.SetDirPrefix(CombinePath(srcPath, FString()));
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker   for (;;)
603*f6dc9357SAndroid Build Coastguard Worker   {
604*f6dc9357SAndroid Build Coastguard Worker     NFind::CFileInfo fi;
605*f6dc9357SAndroid Build Coastguard Worker     bool found;
606*f6dc9357SAndroid Build Coastguard Worker     if (!enumerator.Next(fi, found))
607*f6dc9357SAndroid Build Coastguard Worker     {
608*f6dc9357SAndroid Build Coastguard Worker       SendLastErrorMessage(state.Callback, srcPath);
609*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
610*f6dc9357SAndroid Build Coastguard Worker     }
611*f6dc9357SAndroid Build Coastguard Worker     if (!found)
612*f6dc9357SAndroid Build Coastguard Worker       break;
613*f6dc9357SAndroid Build Coastguard Worker     const FString srcPath2 = CombinePath(srcPath, fi.Name);
614*f6dc9357SAndroid Build Coastguard Worker     const FString destPath2 = CombinePath(destPath, fi.Name);
615*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
616*f6dc9357SAndroid Build Coastguard Worker     {
617*f6dc9357SAndroid Build Coastguard Worker       RINOK(CopyFolder(state, srcPath2, destPath2))
618*f6dc9357SAndroid Build Coastguard Worker     }
619*f6dc9357SAndroid Build Coastguard Worker     else
620*f6dc9357SAndroid Build Coastguard Worker     {
621*f6dc9357SAndroid Build Coastguard Worker       RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2))
622*f6dc9357SAndroid Build Coastguard Worker     }
623*f6dc9357SAndroid Build Coastguard Worker   }
624*f6dc9357SAndroid Build Coastguard Worker 
625*f6dc9357SAndroid Build Coastguard Worker   if (state.MoveMode)
626*f6dc9357SAndroid Build Coastguard Worker   {
627*f6dc9357SAndroid Build Coastguard Worker     if (!RemoveDir(srcPath))
628*f6dc9357SAndroid Build Coastguard Worker     {
629*f6dc9357SAndroid Build Coastguard Worker       RINOK(SendMessageError(state.Callback, "Cannot remove folder", srcPath))
630*f6dc9357SAndroid Build Coastguard Worker       return E_ABORT;
631*f6dc9357SAndroid Build Coastguard Worker     }
632*f6dc9357SAndroid Build Coastguard Worker   }
633*f6dc9357SAndroid Build Coastguard Worker 
634*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
635*f6dc9357SAndroid Build Coastguard Worker }
636*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CFSFolder::CopyTo (Int32 moveMode,const UInt32 * indices,UInt32 numItems,Int32,Int32,const wchar_t * path,IFolderOperationsExtractCallback * callback))637*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
638*f6dc9357SAndroid Build Coastguard Worker     Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
639*f6dc9357SAndroid Build Coastguard Worker     const wchar_t *path, IFolderOperationsExtractCallback *callback))
640*f6dc9357SAndroid Build Coastguard Worker {
641*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
642*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
643*f6dc9357SAndroid Build Coastguard Worker 
644*f6dc9357SAndroid Build Coastguard Worker   const FString destPath = us2fs(path);
645*f6dc9357SAndroid Build Coastguard Worker   if (destPath.IsEmpty())
646*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
647*f6dc9357SAndroid Build Coastguard Worker 
648*f6dc9357SAndroid Build Coastguard Worker   const bool isAltDest = NName::IsAltPathPrefix(destPath);
649*f6dc9357SAndroid Build Coastguard Worker   const bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
650*f6dc9357SAndroid Build Coastguard Worker 
651*f6dc9357SAndroid Build Coastguard Worker   if (isDirectPath)
652*f6dc9357SAndroid Build Coastguard Worker     if (numItems > 1)
653*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
654*f6dc9357SAndroid Build Coastguard Worker 
655*f6dc9357SAndroid Build Coastguard Worker   CFsFolderStat stat;
656*f6dc9357SAndroid Build Coastguard Worker   stat.Progress = callback;
657*f6dc9357SAndroid Build Coastguard Worker 
658*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
659*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
660*f6dc9357SAndroid Build Coastguard Worker   {
661*f6dc9357SAndroid Build Coastguard Worker     const UInt32 index = indices[i];
662*f6dc9357SAndroid Build Coastguard Worker     /*
663*f6dc9357SAndroid Build Coastguard Worker     if (index >= Files.Size())
664*f6dc9357SAndroid Build Coastguard Worker     {
665*f6dc9357SAndroid Build Coastguard Worker       size += Streams[index - Files.Size()].Size;
666*f6dc9357SAndroid Build Coastguard Worker       // numFiles++;
667*f6dc9357SAndroid Build Coastguard Worker       continue;
668*f6dc9357SAndroid Build Coastguard Worker     }
669*f6dc9357SAndroid Build Coastguard Worker     */
670*f6dc9357SAndroid Build Coastguard Worker     const CDirItem &fi = Files[index];
671*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
672*f6dc9357SAndroid Build Coastguard Worker     {
673*f6dc9357SAndroid Build Coastguard Worker       if (!isAltDest)
674*f6dc9357SAndroid Build Coastguard Worker       {
675*f6dc9357SAndroid Build Coastguard Worker         stat.Path = _path;
676*f6dc9357SAndroid Build Coastguard Worker         stat.Path += GetRelPath(fi);
677*f6dc9357SAndroid Build Coastguard Worker         RINOK(stat.Enumerate())
678*f6dc9357SAndroid Build Coastguard Worker       }
679*f6dc9357SAndroid Build Coastguard Worker       stat.NumFolders++;
680*f6dc9357SAndroid Build Coastguard Worker     }
681*f6dc9357SAndroid Build Coastguard Worker     else
682*f6dc9357SAndroid Build Coastguard Worker     {
683*f6dc9357SAndroid Build Coastguard Worker       stat.NumFiles++;
684*f6dc9357SAndroid Build Coastguard Worker       stat.Size += fi.Size;
685*f6dc9357SAndroid Build Coastguard Worker     }
686*f6dc9357SAndroid Build Coastguard Worker   }
687*f6dc9357SAndroid Build Coastguard Worker 
688*f6dc9357SAndroid Build Coastguard Worker   /*
689*f6dc9357SAndroid Build Coastguard Worker   if (stat.NumFolders != 0 && isAltDest)
690*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
691*f6dc9357SAndroid Build Coastguard Worker   */
692*f6dc9357SAndroid Build Coastguard Worker 
693*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->SetTotal(stat.Size))
694*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->SetNumFiles(stat.NumFiles))
695*f6dc9357SAndroid Build Coastguard Worker 
696*f6dc9357SAndroid Build Coastguard Worker   UInt64 completedSize = 0;
697*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->SetCompleted(&completedSize))
698*f6dc9357SAndroid Build Coastguard Worker 
699*f6dc9357SAndroid Build Coastguard Worker   CCopyState state;
700*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.TotalSize = stat.Size;
701*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.StartPos = 0;
702*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.Progress = callback;
703*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.Init();
704*f6dc9357SAndroid Build Coastguard Worker   state.Callback = callback;
705*f6dc9357SAndroid Build Coastguard Worker   state.MoveMode = IntToBool(moveMode);
706*f6dc9357SAndroid Build Coastguard Worker   state.IsAltStreamsDest = isAltDest;
707*f6dc9357SAndroid Build Coastguard Worker   /* CopyFileW(fromFile, toFile:altStream) returns ERROR_INVALID_PARAMETER,
708*f6dc9357SAndroid Build Coastguard Worker        if there are alt streams in fromFile.
709*f6dc9357SAndroid Build Coastguard Worker      So we don't use CopyFileW() for alt Streams. */
710*f6dc9357SAndroid Build Coastguard Worker   state.UseReadWriteMode = isAltDest;
711*f6dc9357SAndroid Build Coastguard Worker 
712*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
713*f6dc9357SAndroid Build Coastguard Worker   {
714*f6dc9357SAndroid Build Coastguard Worker     const UInt32 index = indices[i];
715*f6dc9357SAndroid Build Coastguard Worker     if (index >= (UInt32)Files.Size())
716*f6dc9357SAndroid Build Coastguard Worker       continue;
717*f6dc9357SAndroid Build Coastguard Worker     const CDirItem &fi = Files[index];
718*f6dc9357SAndroid Build Coastguard Worker     FString destPath2 = destPath;
719*f6dc9357SAndroid Build Coastguard Worker     if (!isDirectPath)
720*f6dc9357SAndroid Build Coastguard Worker       destPath2 += fi.Name;
721*f6dc9357SAndroid Build Coastguard Worker     FString srcPath;
722*f6dc9357SAndroid Build Coastguard Worker     GetFullPath(fi, srcPath);
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
725*f6dc9357SAndroid Build Coastguard Worker     {
726*f6dc9357SAndroid Build Coastguard Worker       if (isAltDest)
727*f6dc9357SAndroid Build Coastguard Worker       {
728*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(callback, k_CannotCopyDirToAltStream, srcPath))
729*f6dc9357SAndroid Build Coastguard Worker       }
730*f6dc9357SAndroid Build Coastguard Worker       else
731*f6dc9357SAndroid Build Coastguard Worker       {
732*f6dc9357SAndroid Build Coastguard Worker         RINOK(CopyFolder(state, srcPath, destPath2))
733*f6dc9357SAndroid Build Coastguard Worker       }
734*f6dc9357SAndroid Build Coastguard Worker     }
735*f6dc9357SAndroid Build Coastguard Worker     else
736*f6dc9357SAndroid Build Coastguard Worker     {
737*f6dc9357SAndroid Build Coastguard Worker       RINOK(CopyFile_Ask(state, srcPath, fi, destPath2))
738*f6dc9357SAndroid Build Coastguard Worker     }
739*f6dc9357SAndroid Build Coastguard Worker   }
740*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
741*f6dc9357SAndroid Build Coastguard Worker }
742*f6dc9357SAndroid Build Coastguard Worker 
743*f6dc9357SAndroid Build Coastguard Worker 
744*f6dc9357SAndroid Build Coastguard Worker 
745*f6dc9357SAndroid Build Coastguard Worker /* we can call CopyFileSystemItems() from CDropTarget::Drop() */
746*f6dc9357SAndroid Build Coastguard Worker 
CopyFileSystemItems(const UStringVector & itemsPaths,const FString & destDirPrefix,bool moveMode,IFolderOperationsExtractCallback * callback)747*f6dc9357SAndroid Build Coastguard Worker HRESULT CopyFileSystemItems(
748*f6dc9357SAndroid Build Coastguard Worker     const UStringVector &itemsPaths,
749*f6dc9357SAndroid Build Coastguard Worker     const FString &destDirPrefix,
750*f6dc9357SAndroid Build Coastguard Worker     bool moveMode,
751*f6dc9357SAndroid Build Coastguard Worker     IFolderOperationsExtractCallback *callback)
752*f6dc9357SAndroid Build Coastguard Worker {
753*f6dc9357SAndroid Build Coastguard Worker   if (itemsPaths.IsEmpty())
754*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
755*f6dc9357SAndroid Build Coastguard Worker 
756*f6dc9357SAndroid Build Coastguard Worker   if (destDirPrefix.IsEmpty())
757*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
758*f6dc9357SAndroid Build Coastguard Worker 
759*f6dc9357SAndroid Build Coastguard Worker   const bool isAltDest = NName::IsAltPathPrefix(destDirPrefix);
760*f6dc9357SAndroid Build Coastguard Worker 
761*f6dc9357SAndroid Build Coastguard Worker   CFsFolderStat stat;
762*f6dc9357SAndroid Build Coastguard Worker   stat.Progress = callback;
763*f6dc9357SAndroid Build Coastguard Worker 
764*f6dc9357SAndroid Build Coastguard Worker  {
765*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, itemsPaths)
766*f6dc9357SAndroid Build Coastguard Worker   {
767*f6dc9357SAndroid Build Coastguard Worker     const UString &path = itemsPaths[i];
768*f6dc9357SAndroid Build Coastguard Worker     CFileInfo fi;
769*f6dc9357SAndroid Build Coastguard Worker     if (!fi.Find(us2fs(path)))
770*f6dc9357SAndroid Build Coastguard Worker       continue;
771*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
772*f6dc9357SAndroid Build Coastguard Worker     {
773*f6dc9357SAndroid Build Coastguard Worker       if (!isAltDest)
774*f6dc9357SAndroid Build Coastguard Worker       {
775*f6dc9357SAndroid Build Coastguard Worker         stat.Path = us2fs(path);
776*f6dc9357SAndroid Build Coastguard Worker         RINOK(stat.Enumerate())
777*f6dc9357SAndroid Build Coastguard Worker       }
778*f6dc9357SAndroid Build Coastguard Worker       stat.NumFolders++;
779*f6dc9357SAndroid Build Coastguard Worker     }
780*f6dc9357SAndroid Build Coastguard Worker     else
781*f6dc9357SAndroid Build Coastguard Worker     {
782*f6dc9357SAndroid Build Coastguard Worker       stat.NumFiles++;
783*f6dc9357SAndroid Build Coastguard Worker       stat.Size += fi.Size;
784*f6dc9357SAndroid Build Coastguard Worker     }
785*f6dc9357SAndroid Build Coastguard Worker   }
786*f6dc9357SAndroid Build Coastguard Worker  }
787*f6dc9357SAndroid Build Coastguard Worker 
788*f6dc9357SAndroid Build Coastguard Worker   /*
789*f6dc9357SAndroid Build Coastguard Worker   if (stat.NumFolders != 0 && isAltDest)
790*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
791*f6dc9357SAndroid Build Coastguard Worker   */
792*f6dc9357SAndroid Build Coastguard Worker 
793*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->SetTotal(stat.Size))
794*f6dc9357SAndroid Build Coastguard Worker   // RINOK(progress->SetNumFiles(stat.NumFiles));
795*f6dc9357SAndroid Build Coastguard Worker 
796*f6dc9357SAndroid Build Coastguard Worker   UInt64 completedSize = 0;
797*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->SetCompleted(&completedSize))
798*f6dc9357SAndroid Build Coastguard Worker 
799*f6dc9357SAndroid Build Coastguard Worker   CCopyState state;
800*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.TotalSize = stat.Size;
801*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.StartPos = 0;
802*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.Progress = callback;
803*f6dc9357SAndroid Build Coastguard Worker   state.ProgressInfo.Init();
804*f6dc9357SAndroid Build Coastguard Worker   state.Callback = callback;
805*f6dc9357SAndroid Build Coastguard Worker   state.MoveMode = moveMode;
806*f6dc9357SAndroid Build Coastguard Worker   state.IsAltStreamsDest = isAltDest;
807*f6dc9357SAndroid Build Coastguard Worker   /* CopyFileW(fromFile, toFile:altStream) returns ERROR_INVALID_PARAMETER,
808*f6dc9357SAndroid Build Coastguard Worker        if there are alt streams in fromFile.
809*f6dc9357SAndroid Build Coastguard Worker      So we don't use CopyFileW() for alt Streams. */
810*f6dc9357SAndroid Build Coastguard Worker   state.UseReadWriteMode = isAltDest;
811*f6dc9357SAndroid Build Coastguard Worker 
812*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, itemsPaths)
813*f6dc9357SAndroid Build Coastguard Worker   {
814*f6dc9357SAndroid Build Coastguard Worker     const UString path = itemsPaths[i];
815*f6dc9357SAndroid Build Coastguard Worker     CFileInfo fi;
816*f6dc9357SAndroid Build Coastguard Worker 
817*f6dc9357SAndroid Build Coastguard Worker     if (!fi.Find(us2fs(path)))
818*f6dc9357SAndroid Build Coastguard Worker     {
819*f6dc9357SAndroid Build Coastguard Worker       RINOK(SendMessageError(callback, "Cannot find the file", us2fs(path)))
820*f6dc9357SAndroid Build Coastguard Worker       continue;
821*f6dc9357SAndroid Build Coastguard Worker     }
822*f6dc9357SAndroid Build Coastguard Worker 
823*f6dc9357SAndroid Build Coastguard Worker     FString destPath = destDirPrefix;
824*f6dc9357SAndroid Build Coastguard Worker     destPath += fi.Name;
825*f6dc9357SAndroid Build Coastguard Worker 
826*f6dc9357SAndroid Build Coastguard Worker     if (fi.IsDir())
827*f6dc9357SAndroid Build Coastguard Worker     {
828*f6dc9357SAndroid Build Coastguard Worker       if (isAltDest)
829*f6dc9357SAndroid Build Coastguard Worker       {
830*f6dc9357SAndroid Build Coastguard Worker         RINOK(SendMessageError(callback, k_CannotCopyDirToAltStream, us2fs(path)))
831*f6dc9357SAndroid Build Coastguard Worker       }
832*f6dc9357SAndroid Build Coastguard Worker       else
833*f6dc9357SAndroid Build Coastguard Worker       {
834*f6dc9357SAndroid Build Coastguard Worker         RINOK(CopyFolder(state, us2fs(path), destPath))
835*f6dc9357SAndroid Build Coastguard Worker       }
836*f6dc9357SAndroid Build Coastguard Worker     }
837*f6dc9357SAndroid Build Coastguard Worker     else
838*f6dc9357SAndroid Build Coastguard Worker     {
839*f6dc9357SAndroid Build Coastguard Worker       RINOK(CopyFile_Ask(state, us2fs(path), fi, destPath))
840*f6dc9357SAndroid Build Coastguard Worker     }
841*f6dc9357SAndroid Build Coastguard Worker   }
842*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
843*f6dc9357SAndroid Build Coastguard Worker }
844*f6dc9357SAndroid Build Coastguard Worker 
845*f6dc9357SAndroid Build Coastguard Worker 
846*f6dc9357SAndroid Build Coastguard Worker /* we don't use CFSFolder::CopyFrom() because the caller of CopyFrom()
847*f6dc9357SAndroid Build Coastguard Worker    is optimized for IFolderArchiveUpdateCallback interface,
848*f6dc9357SAndroid Build Coastguard Worker    but we want to use IFolderOperationsExtractCallback interface instead */
849*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CFSFolder::CopyFrom (Int32,const wchar_t *,const wchar_t * const *,UInt32,IProgress *))850*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
851*f6dc9357SAndroid Build Coastguard Worker     const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */))
852*f6dc9357SAndroid Build Coastguard Worker {
853*f6dc9357SAndroid Build Coastguard Worker   /*
854*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
855*f6dc9357SAndroid Build Coastguard Worker       IFolderOperationsExtractCallback,
856*f6dc9357SAndroid Build Coastguard Worker       callback, progress)
857*f6dc9357SAndroid Build Coastguard Worker   if (!callback)
858*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
859*f6dc9357SAndroid Build Coastguard Worker   return CopyFileSystemItems(_path,
860*f6dc9357SAndroid Build Coastguard Worker       moveMode, fromDirPrefix,
861*f6dc9357SAndroid Build Coastguard Worker       itemsPaths, numItems, callback);
862*f6dc9357SAndroid Build Coastguard Worker   */
863*f6dc9357SAndroid Build Coastguard Worker   return E_NOTIMPL;
864*f6dc9357SAndroid Build Coastguard Worker }
865*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CFSFolder::CopyFromFile (UInt32,const wchar_t *,IProgress *))866*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CFSFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */))
867*f6dc9357SAndroid Build Coastguard Worker {
868*f6dc9357SAndroid Build Coastguard Worker   return E_NOTIMPL;
869*f6dc9357SAndroid Build Coastguard Worker }
870*f6dc9357SAndroid Build Coastguard Worker 
871*f6dc9357SAndroid Build Coastguard Worker }
872