diff options
Diffstat (limited to 'installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/FSFolderCopy.cpp')
-rw-r--r-- | installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/FSFolderCopy.cpp | 523 |
1 files changed, 523 insertions, 0 deletions
diff --git a/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/FSFolderCopy.cpp new file mode 100644 index 000000000..db1ba2ba4 --- /dev/null +++ b/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -0,0 +1,523 @@ +// FSFolderCopy.cpp + +#include "StdAfx.h" + +// FIXME #include <Winbase.h> + +#include "FSFolder.h" +#include "Windows/FileDir.h" +#include "Windows/Error.h" + +#include "Common/StringConvert.h" + +#include "../../Common/FilePathAutoRename.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NFsFolder { + +/* +static bool IsItWindows2000orHigher() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && + (versionInfo.dwMajorVersion >= 5); +} +*/ + +struct CProgressInfo +{ + UInt64 StartPos; + IProgress *Progress; +}; + +#ifdef _WIN32 + +static DWORD CALLBACK CopyProgressRoutine( + LARGE_INTEGER /* TotalFileSize */, // file size + LARGE_INTEGER TotalBytesTransferred, // bytes transferred + LARGE_INTEGER /* StreamSize */, // bytes in stream + LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream + DWORD /* dwStreamNumber */, // current stream + DWORD /* dwCallbackReason */, // callback reason + HANDLE /* hSourceFile */, // handle to source file + HANDLE /* hDestinationFile */, // handle to destination file + LPVOID lpData // from CopyFileEx +) +{ + CProgressInfo &progressInfo = *(CProgressInfo *)lpData; + UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart; + if (progressInfo.Progress->SetCompleted(&completed) != S_OK) + return PROGRESS_CANCEL; + return PROGRESS_CONTINUE; +} + +typedef BOOL (WINAPI * CopyFileExPointer)( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN LPBOOL pbCancel OPTIONAL, + IN DWORD dwCopyFlags + ); + +typedef BOOL (WINAPI * CopyFileExPointerW)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN LPBOOL pbCancel OPTIONAL, + IN DWORD dwCopyFlags + ); + +#ifndef _UNICODE +static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } +static CSysString GetSysPath(LPCWSTR sysPath) + { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } +#endif + +#endif + +static bool MyCopyFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +{ +#ifdef _WIN32 + CProgressInfo progressInfo; + progressInfo.Progress = progress; + progressInfo.StartPos = completedSize; + BOOL CancelFlag = FALSE; + #ifndef _UNICODE + if (g_IsNT) + #endif + { + CopyFileExPointerW copyFunctionW = (CopyFileExPointerW) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), + "CopyFileExW"); + if (copyFunctionW == 0) + return false; + if (copyFunctionW(existingFile, newFile, CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + #ifdef WIN_LONG_PATH + UString longPathExisting, longPathNew; + if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew)) + return false; + if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine, + &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + #endif + return false; + } + #ifndef _UNICODE + else + { + CopyFileExPointer copyFunction = (CopyFileExPointer) + ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), + "CopyFileExA"); + if (copyFunction != 0) + { + if (copyFunction(GetSysPath(existingFile), GetSysPath(newFile), + CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS)) + return true; + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; + } + return BOOLToBool(::CopyFile(GetSysPath(existingFile), GetSysPath(newFile), TRUE)); + } + #endif +#else + extern bool wxw_CopyFile(LPCWSTR existingFile, LPCWSTR newFile, bool overwrite); + return wxw_CopyFile(existingFile, newFile, true); +#endif +} + +#ifdef _WIN32 +typedef BOOL (WINAPI * MoveFileWithProgressPointer)( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN DWORD dwFlags + ); +#endif + +static bool MyMoveFile(LPCWSTR existingFile, LPCWSTR newFile, IProgress *progress, UInt64 &completedSize) +{ +#ifdef _WIN32 + // if (IsItWindows2000orHigher()) + // { + CProgressInfo progressInfo; + progressInfo.Progress = progress; + progressInfo.StartPos = completedSize; + + MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), + "MoveFileWithProgressW"); + if (moveFunction != 0) + { + if (moveFunction( + existingFile, newFile, CopyProgressRoutine, + &progressInfo, MOVEFILE_COPY_ALLOWED)) + return true; + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + { + #ifdef WIN_LONG_PATH + UString longPathExisting, longPathNew; + if (!NDirectory::GetLongPaths(existingFile, newFile, longPathExisting, longPathNew)) + return false; + if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine, + &progressInfo, MOVEFILE_COPY_ALLOWED)) + return true; + #endif + if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return false; + } + } + // } + // else +#endif + return NDirectory::MyMoveFile(existingFile, newFile); +} + +static HRESULT MyCopyFile( + const UString &srcPath, + const CFileInfoW &srcFileInfo, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + if (destPath.CompareNoCase(srcPath) == 0) + { + UString message = UString(L"can not move file \'") + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + INT32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite( + srcPath, + BoolToInt(false), + &srcFileInfo.MTime, &srcFileInfo.Size, + destPath, + &destPathResult, + &writeAskResult)); + if (IntToBool(writeAskResult)) + { + UString destPathNew = UString(destPathResult); + RINOK(callback->SetCurrentFilePath(srcPath)); + if (!MyCopyFile(srcPath, destPathNew, callback, completedSize)) + { + UString message = NError::MyFormatMessageW(GetLastError()) + + UString(L" \'") + + UString(destPathNew) + + UString(L"\'"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + completedSize += srcFileInfo.Size; + return callback->SetCompleted(&completedSize); +} + +static HRESULT CopyFolder( + const UString &srcPath, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + RINOK(callback->SetCompleted(&completedSize)); + + UString destPath = destPathSpec; + int len = srcPath.Length(); + if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + { + if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + { + UString message = UString(L"can not copy folder \'") + + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + CEnumeratorW enumerator(srcPath + UString(WSTRING_PATH_SEPARATOR L"*")); + CFileInfoEx fileInfo; + while (enumerator.Next(fileInfo)) + { + const UString srcPath2 = srcPath + UString(WSTRING_PATH_SEPARATOR) + fileInfo.Name; + const UString destPath2 = destPath + UString(WSTRING_PATH_SEPARATOR) + fileInfo.Name; + if (fileInfo.IsDir()) + { + RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize)); + } + else + { + RINOK(MyCopyFile(srcPath2, fileInfo, destPath2, callback, completedSize)); + } + } + return S_OK; +} + + +STDMETHODIMP CFSFolder::CopyTo(const UInt32 *indices, UInt32 numItems, + const wchar_t *path, IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + UInt64 numFolders, numFiles, totalSize; + GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback); + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + /* + // doesn't work in network + else + if (!NDirectory::CreateComplexDirectory(destPath))) + { + DWORD lastError = ::GetLastError(); + UString message = UString(L"can not create folder ") + + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + */ + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (UInt32 i = 0; i < numItems; i++) + { + const CDirItem &fileInfo = *_refs[indices[i]]; + UString destPath2 = destPath; + if (!directName) + destPath2 += fileInfo.Name; + UString srcPath = _path + GetPrefix(fileInfo) + fileInfo.Name; + if (fileInfo.IsDir()) + { + RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); + } + else + { + RINOK(MyCopyFile(srcPath, fileInfo, destPath2, callback, completedSize)); + } + } + return S_OK; +} + +///////////////////////////////////////////////// +// Move Operations + +HRESULT MyMoveFile( + const UString &srcPath, + const CFileInfoW &srcFileInfo, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + if (destPath.CompareNoCase(srcPath) == 0) + { + UString message = UString(L"can not move file \'") + + destPath + + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + INT32 writeAskResult; + CMyComBSTR destPathResult; + RINOK(callback->AskWrite( + srcPath, + BoolToInt(false), + &srcFileInfo.MTime, &srcFileInfo.Size, + destPath, + &destPathResult, + &writeAskResult)); + if (IntToBool(writeAskResult)) + { + UString destPathNew = UString(destPathResult); + RINOK(callback->SetCurrentFilePath(srcPath)); + if (!MyMoveFile(srcPath, destPathNew, callback, completedSize)) + { + UString message = UString(L"can not move to file ") + destPathNew; + RINOK(callback->ShowMessage(message)); + } + } + completedSize += srcFileInfo.Size; + RINOK(callback->SetCompleted(&completedSize)); + return S_OK; +} + +HRESULT MyMoveFolder( + const UString &srcPath, + const UString &destPathSpec, + IFolderOperationsExtractCallback *callback, + UInt64 &completedSize) +{ + UString destPath = destPathSpec; + int len = srcPath.Length(); + if (destPath.Length() >= len && srcPath.CompareNoCase(destPath.Left(len)) == 0) + { + if (destPath.Length() == len || destPath[len] == WCHAR_PATH_SEPARATOR) + { + UString message = UString(L"can not move folder \'") + + destPath + UString(L"\' onto itself"); + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + } + + if (MyMoveFile(srcPath, destPath, callback, completedSize)) + return S_OK; + + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + { + CEnumeratorW enumerator(srcPath + UString(WSTRING_PATH_SEPARATOR L"*")); + CFileInfoEx fileInfo; + while (enumerator.Next(fileInfo)) + { + const UString srcPath2 = srcPath + UString(WSTRING_PATH_SEPARATOR) + fileInfo.Name; + const UString destPath2 = destPath + UString(WSTRING_PATH_SEPARATOR) + fileInfo.Name; + if (fileInfo.IsDir()) + { + RINOK(MyMoveFolder(srcPath2, destPath2, callback, completedSize)); + } + else + { + RINOK(MyMoveFile(srcPath2, fileInfo, destPath2, callback, completedSize)); + } + } + } + if (!NDirectory::MyRemoveDirectory(srcPath)) + { + UString message = UString(L"can not remove folder") + srcPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + return S_OK; +} + +STDMETHODIMP CFSFolder::MoveTo( + const UInt32 *indices, + UInt32 numItems, + const wchar_t *path, + IFolderOperationsExtractCallback *callback) +{ + if (numItems == 0) + return S_OK; + + UInt64 numFolders, numFiles, totalSize; + GetItemsFullSize(indices, numItems, numFolders, numFiles, totalSize, callback); + RINOK(callback->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + + UString destPath = path; + if (destPath.IsEmpty()) + return E_INVALIDARG; + bool directName = (destPath[destPath.Length() - 1] != WCHAR_PATH_SEPARATOR); + if (directName) + { + if (numItems > 1) + return E_INVALIDARG; + } + else + if (!NDirectory::CreateComplexDirectory(destPath)) + { + UString message = UString(L"can not create folder ") + + destPath; + RINOK(callback->ShowMessage(message)); + return E_ABORT; + } + + UInt64 completedSize = 0; + RINOK(callback->SetCompleted(&completedSize)); + for (UInt32 i = 0; i < numItems; i++) + { + const CDirItem &fileInfo = *_refs[indices[i]]; + UString destPath2 = destPath; + if (!directName) + destPath2 += fileInfo.Name; + UString srcPath = _path + GetPrefix(fileInfo) + fileInfo.Name; + if (fileInfo.IsDir()) + { + RINOK(MyMoveFolder(srcPath, destPath2, callback, completedSize)); + } + else + { + RINOK(MyMoveFile(srcPath, fileInfo, destPath2, callback, completedSize)); + } + } + return S_OK; +} + +STDMETHODIMP CFSFolder::CopyFrom(const wchar_t * /* fromFolderPath */, + const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */) +{ + /* + UInt64 numFolders, numFiles, totalSize; + numFiles = numFolders = totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + { + UString path = (UString)fromFolderPath + itemsPaths[i]; + + CFileInfoW fileInfo; + if (!FindFile(path, fileInfo)) + return ::GetLastError(); + if (fileInfo.IsDir()) + { + UInt64 subFolders, subFiles, subSize; + RINOK(GetFolderSize(path + UString(WSTRING_PATH_SEPARATOR) + fileInfo.Name, subFolders, subFiles, subSize, progress)); + numFolders += subFolders; + numFolders++; + numFiles += subFiles; + totalSize += subSize; + } + else + { + numFiles++; + totalSize += fileInfo.Size; + } + } + RINOK(progress->SetTotal(totalSize)); + RINOK(callback->SetNumFiles(numFiles)); + for (i = 0; i < numItems; i++) + { + UString path = (UString)fromFolderPath + itemsPaths[i]; + } + return S_OK; + */ + return E_NOTIMPL; +} + +} |