UString GetMyDocsPath() { UString us; WCHAR s[MAX_PATH + 1]; SHGetSpecialFolderPathWp getW = (SHGetSpecialFolderPathWp) #ifdef UNDER_CE My_GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), "SHGetSpecialFolderPath"); #else My_GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetSpecialFolderPathW"); #endif if (getW && getW(0, s, CSIDL_PERSONAL, FALSE)) us = s; #ifndef _UNICODE else { SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp) ::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA"); CHAR s2[MAX_PATH + 1]; if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE)) us = GetUnicodeString(s2); } #endif if (us.Length() > 0 && us.Back() != WCHAR_PATH_SEPARATOR) us += WCHAR_PATH_SEPARATOR; return us; }
void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.Back() != WCHAR_PATH_SEPARATOR) dirPath += WCHAR_PATH_SEPARATOR; }
UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName.Back() == kOSDirDelimiter) newName.DeleteBack(); return newName; }
void ConvertToOSName2(UString &name) { if (!name.IsEmpty()) { name.Replace(kDirDelimiter, kOSDirDelimiter); if (name.Back() == kOSDirDelimiter) name.DeleteBack(); } }
static void AddName(UStringVector &strings, UString &s) { s.Trim(); if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) { s.DeleteBack(); s.Delete(0); } if (!s.IsEmpty()) strings.Add(s); }
bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name) { parentPrefix.Empty(); name.Empty(); if (path.IsEmpty()) return false; if (_topDirPrefix == path) return false; UString s = path; if (s.Back() == WCHAR_PATH_SEPARATOR) s.DeleteBack(); if (s.IsEmpty()) return false; if (s.Back() == WCHAR_PATH_SEPARATOR) return false; int pos = s.ReverseFind_PathSepar(); parentPrefix.SetFrom(s, pos + 1); name = s.Ptr(pos + 1); return true; }
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.Back() != 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 &fi = *_refs[indices[i]]; FString destPath2 = us2fs(destPath); if (!directName) destPath2 += fi.Name; FString srcPath = _path + GetPrefix(fi) + fi.Name; if (fi.IsDir()) { RINOK(CopyFolder(srcPath, destPath2, callback, completedSize)); } else { RINOK(MyCopyFile(srcPath, fi, destPath2, callback, completedSize)); } } return S_OK; }
bool ParseName(const UString &name) { if (name.Len() < 2) return false; if (name.Back() != L'1' || name[name.Len() - 2] != L'0') return false; unsigned pos = name.Len() - 2; for (; pos > 0 && name[pos - 1] == '0'; pos--); UnchangedPart.SetFrom(name, pos); ChangedPart = name.Ptr(pos); return true; }
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name.Back(); if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name.DeleteBack(); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; }
void CPanel::LoadFullPathAndShow() { LoadFullPath(); _appState->FolderHistory.AddString(_currentFolderPrefix); _headerComboBox.SetText(_currentFolderPrefix); #ifndef UNDER_CE COMBOBOXEXITEM item; item.mask = 0; UString path = _currentFolderPrefix; if (path.Len() > #ifdef _WIN32 3 #else 1 #endif && path.Back() == WCHAR_PATH_SEPARATOR) path.DeleteBack(); DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path if (path.IsPrefixedBy(L"\\\\.\\")) path = L"_TestFolder_"; else { CFileInfo fi; if (fi.Find(us2fs(path))) attrib = fi.Attrib; } item.iImage = GetRealIconIndex(us2fs(path), attrib); if (item.iImage >= 0) { item.iSelectedImage = item.iImage; item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE); } item.iItem = -1; _headerComboBox.SetItem(&item); #endif RefreshTitle(); }
void CPanel::OpenAltStreams() { CRecordVector<UInt32> indices; GetOperatedItemIndices(indices); Int32 realIndex = -1; if (indices.Size() > 1) return; if (indices.Size() == 1) realIndex = indices[0]; if (_folderAltStreams) { CMyComPtr<IFolderFolder> newFolder; _folderAltStreams->BindToAltStreams(realIndex, &newFolder); if (newFolder) { CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); SetNewFolder(newFolder); RefreshListCtrl(UString(), -1, true, UStringVector()); return; } return; } #if defined(_WIN32) && !defined(UNDER_CE) UString path; if (realIndex >= 0) path = GetItemFullPath(realIndex); else { path = GetFsPath(); if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path))) if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back())) path.DeleteBack(); } path += L':'; BindToPathAndRefresh(path); #endif }
void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback) { if (!callback) return; CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback; callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); if (!volumeCallback) return; NWindows::NCOM::CPropVariant prop; if (volumeCallback->GetProperty(kpidName, &prop) != S_OK || prop.vt != VT_BSTR) return; UString s = prop.bstrVal; if (s.IsEmpty() || s.Back() != L'_') return; s.DeleteBack(); _name = s; if (replaceByte == 0) { if (s.Len() < 3 || s[s.Len() - 3] != '.') return; for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++) { const char *ext = g_Exts[i]; if (s[s.Len() - 2] == (Byte)ext[0] && s[s.Len() - 1] == (Byte)ext[1]) { replaceByte = ext[2]; break; } } } if (replaceByte >= 0x20 && replaceByte < 0x80) _name += (wchar_t)replaceByte; }
bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) { res = s; #ifdef UNDER_CE if (s[0] != CHAR_PATH_SEPARATOR) { if (!dirPrefix) return false; res = dirPrefix; res += s; } #else unsigned prefixSize = GetRootPrefixSize(s); if (prefixSize != 0) { if (!AreThereDotsFolders(s + prefixSize)) return true; UString rem = fs2us(s + prefixSize); if (!ResolveDotsFolders(rem)) return true; // maybe false; res.DeleteFrom(prefixSize); res += us2fs(rem); return true; } /* FChar c = s[0]; if (c == 0) return true; if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) return true; if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) return true; if (IsDrivePath(s)) return true; */ UString curDir; if (dirPrefix) curDir = fs2us(dirPrefix); else { if (!GetCurDir(curDir)) return false; } if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR) curDir += WCHAR_PATH_SEPARATOR; unsigned fixedSize = 0; if (IsDrivePath(curDir)) fixedSize = kDrivePrefixSize; UString temp; if (s[0] == CHAR_PATH_SEPARATOR) { temp = fs2us(s + 1); } else { temp += curDir.Ptr(fixedSize); temp += fs2us(s); } if (!ResolveDotsFolders(temp)) return false; curDir.DeleteFrom(fixedSize); res = us2fs(curDir); res += us2fs(temp); #endif // UNDER_CE return true; }
static bool GetSuperPathBase(CFSTR s, UString &res) { res.Empty(); FChar c = s[0]; if (c == 0) return true; if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) return true; if (IsSuperOrDevicePath(s)) { #ifdef LONG_PATH_DOTS_FOLDERS_PARSING if ((s)[2] == '.') return true; // we will return true here, so we will try to use these problem paths. if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) return true; UString temp = fs2us(s); unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); if (fixedSize == 0) return true; UString rem = &temp[fixedSize]; if (!ResolveDotsFolders(rem)) return true; temp.DeleteFrom(fixedSize); res += temp; res += rem; #endif return true; } if (c == CHAR_PATH_SEPARATOR) { if (s[1] == CHAR_PATH_SEPARATOR) { UString temp = fs2us(s + 2); unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); if (fixedSize == 0) // maybe we must ignore that error to allow short network paths? return false; UString rem = &temp[fixedSize]; if (!ResolveDotsFolders(rem)) return false; res += kSuperUncPrefix; temp.DeleteFrom(fixedSize); res += temp; res += rem; return true; } } else { if (IsDrivePath(s)) { UString temp = fs2us(s); UString rem = &temp[kDrivePrefixSize]; if (!ResolveDotsFolders(rem)) return true; res += kSuperPathPrefix; temp.DeleteFrom(kDrivePrefixSize); res += temp; res += rem; return true; } } UString curDir; if (!GetCurDir(curDir)) return false; if (curDir.Back() != WCHAR_PATH_SEPARATOR) curDir += WCHAR_PATH_SEPARATOR; unsigned fixedSizeStart = 0; unsigned fixedSize = 0; const wchar_t *superMarker = NULL; if (IsSuperPath(curDir)) { fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); if (fixedSize == 0) return false; } else { if (IsDrivePath(curDir)) { superMarker = kSuperPathPrefix; fixedSize = kDrivePrefixSize; } else { if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR) return false; fixedSizeStart = 2; fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); if (fixedSize == 0) return false; superMarker = kSuperUncPrefix; } } UString temp; if (c == CHAR_PATH_SEPARATOR) { temp = fs2us(s + 1); } else { temp += &curDir[fixedSizeStart + fixedSize]; temp += fs2us(s); } if (!ResolveDotsFolders(temp)) return false; if (superMarker) res += superMarker; res += curDir.Mid(fixedSizeStart, fixedSize); res += temp; return true; }
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (index >= (UInt32)_archive.Refs.Size()) { index -= _archive.Refs.Size(); const CBootInitialEntry &be = _archive.BootEntries[index]; switch (propID) { case kpidPath: { AString s = "[BOOT]" STRING_PATH_SEPARATOR; if (_archive.BootEntries.Size() != 1) { char temp[16]; ConvertUInt32ToString(index + 1, temp); s += temp; s += '-'; } s += be.GetName(); prop = s; break; } case kpidIsDir: prop = false; break; case kpidSize: case kpidPackSize: prop = (UInt64)_archive.GetBootItemSize(index); break; } } else { const CRef &ref = _archive.Refs[index]; const CDir &item = ref.Dir->_subItems[ref.Index]; switch (propID) { case kpidPath: // if (item.FileId.GetCapacity() >= 0) { UString s; if (_archive.IsJoliet()) item.GetPathU(s); else s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP); if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1') s.DeleteFrom(s.Len() - 2); if (!s.IsEmpty() && s.Back() == L'.') s.DeleteBack(); NItemName::ConvertToOSName2(s); prop = s; } break; case kpidIsDir: prop = item.IsDir(); break; case kpidSize: case kpidPackSize: if (!item.IsDir()) prop = (UInt64)ref.TotalSize; break; case kpidMTime: { FILETIME utc; if (item.DateTime.GetFileTime(utc)) prop = utc; break; } } } prop.Detach(value); return S_OK; COM_TRY_END }
HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted) { UString path = fullPath; #ifdef _WIN32 path.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif archiveIsOpened = false; encrypted = false; CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); for (; !_parentFolders.IsEmpty(); CloseOneLevel()) { // ---------- we try to use open archive ---------- const CFolderLink &link = _parentFolders.Back(); const UString &virtPath = link.VirtualPath; if (!path.IsPrefixedBy(virtPath)) continue; UString relatPath = path.Ptr(virtPath.Len()); if (!relatPath.IsEmpty()) { if (!IS_PATH_SEPAR(relatPath[0])) continue; else relatPath.Delete(0); } UString relatPath2 = relatPath; if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back())) relatPath2.Add_PathSepar(); for (;;) { const UString foldPath = GetFolderPath(_folder); if (relatPath2 == foldPath) break; if (relatPath.IsPrefixedBy(foldPath)) { path = relatPath.Ptr(foldPath.Len()); break; } CMyComPtr<IFolderFolder> newFolder; if (_folder->BindToParentFolder(&newFolder) != S_OK) throw 20140918; if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder) throw 20140918; SetNewFolder(newFolder); } break; } if (_parentFolders.IsEmpty()) { // ---------- we open file or folder from file system ---------- CloseOpenFolders(); UString sysPath = path; unsigned prefixSize = NName::GetRootPrefixSize(sysPath); if (prefixSize == 0 || sysPath[prefixSize] == 0) sysPath.Empty(); #if defined(_WIN32) && !defined(UNDER_CE) if (!sysPath.IsEmpty() && sysPath.Back() == ':' && (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath))) { UString baseFile = sysPath; baseFile.DeleteBack(); if (NFind::DoesFileOrDirExist(us2fs(baseFile))) sysPath.Empty(); } #endif CFileInfo fileInfo; while (!sysPath.IsEmpty()) { if (fileInfo.Find(us2fs(sysPath))) break; int pos = sysPath.ReverseFind_PathSepar(); if (pos < 0) sysPath.Empty(); else { /* if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1) reducedParts.Add(sysPath.Ptr(pos + 1)); */ #if defined(_WIN32) && !defined(UNDER_CE) if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3) pos++; #endif sysPath.DeleteFrom(pos); } } SetToRootFolder(); CMyComPtr<IFolderFolder> newFolder; if (sysPath.IsEmpty()) { _folder->BindToFolder(path, &newFolder); } else if (fileInfo.IsDir()) { NName::NormalizeDirPathPrefix(sysPath); _folder->BindToFolder(sysPath, &newFolder); } else { FString dirPrefix, fileName; NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); HRESULT res; // = OpenAsArc(fs2us(fileName), arcFormat, encrypted); { CTempFileInfo tfi; tfi.RelPath = fs2us(fileName); tfi.FolderPath = dirPrefix; tfi.FilePath = us2fs(sysPath); res = OpenAsArc(NULL, tfi, sysPath, arcFormat, encrypted); } if (res == S_FALSE) _folder->BindToFolder(fs2us(dirPrefix), &newFolder); else { RINOK(res); archiveIsOpened = true; _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix); path.DeleteFrontal(sysPath.Len()); if (!path.IsEmpty() && IS_PATH_SEPAR(path[0])) path.Delete(0); } } if (newFolder) { SetNewFolder(newFolder); // LoadFullPath(); return S_OK; } } { // ---------- we open folder remPath in archive and sub archives ---------- for (unsigned curPos = 0; curPos != path.Len();) { UString s = path.Ptr(curPos); int slashPos = NName::FindSepar(s); unsigned skipLen = s.Len(); if (slashPos >= 0) { s.DeleteFrom(slashPos); skipLen = slashPos + 1; } CMyComPtr<IFolderFolder> newFolder; _folder->BindToFolder(s, &newFolder); if (newFolder) curPos += skipLen; else if (_folderAltStreams) { int pos = s.Find(L':'); if (pos >= 0) { UString baseName = s; baseName.DeleteFrom(pos); if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder) curPos += pos + 1; } } if (!newFolder) break; SetNewFolder(newFolder); } } return S_OK; }
void CContentsView::OnCopy(bool move, bool copyToSame) { CContentsView &srcPanel = *this; CContentsView &destPanel = *this; CDisableTimerProcessing disableTimerProcessing1(destPanel); CDisableTimerProcessing disableTimerProcessing2(srcPanel); if (move) { if (!srcPanel.CheckBeforeUpdate(IDS_MOVE)) return; } else if (!srcPanel.DoesItSupportOperations()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } CRecordVector<UInt32> indices; UString destPath; bool useDestPanel = false; { if (copyToSame) { int focusedItem = srcPanel.GetFocusedItem(); if (focusedItem < 0) return; int realIndex = srcPanel.GetRealItemIndex(focusedItem); if (realIndex == kParentIndex) return; indices.Add(realIndex); destPath = srcPanel.GetItemName(realIndex); } else { srcPanel.GetOperatedIndicesSmart(indices); if (indices.Size() == 0) return; destPath = destPanel.GetFsPath(); ReducePathToRealFileSystemPath(destPath); } } UStringVector copyFolders; // ReadCopyHistory(copyFolders); { CCopyDialog copyDialog; copyDialog.Strings = copyFolders; copyDialog.Value = destPath; LangString(move ? IDS_MOVE : IDS_COPY, copyDialog.Title); LangString(move ? IDS_MOVE_TO : IDS_COPY_TO, copyDialog.Static); copyDialog.Info = srcPanel.GetItemsInfoString(indices); if (copyDialog.DoModal() != IDOK) return; destPath = copyDialog.Value; } { if (destPath.IsEmpty()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } UString correctName; if (!srcPanel.CorrectFsPath(destPath, correctName)) { srcPanel.MessageBoxError(E_INVALIDARG); return; } if (IsAbsolutePath(destPath)) destPath.Empty(); else destPath = srcPanel.GetFsPath(); destPath += correctName; #if defined(_WIN32) && !defined(UNDER_CE) if (destPath.Len() > 0 && destPath[0] == '\\') if (destPath.Len() == 1 || destPath[1] != '\\') { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } #endif if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0) { srcPanel.MessageBoxMyError(L"Can not copy files onto itself"); return; } bool destIsFsPath = false; if (IsAltPathPrefix(us2fs(destPath))) { // we allow alt streams dest only to alt stream folder in second panel srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; /* FString basePath = us2fs(destPath); basePath.DeleteBack(); if (!DoesFileOrDirExist(basePath)) { srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError() return; } destIsFsPath = true; */ } else { if (indices.Size() == 1 && !destPath.IsEmpty() && destPath.Back() != WCHAR_PATH_SEPARATOR) { int pos = destPath.ReverseFind_PathSepar(); if (pos < 0) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } { /* #ifdef _WIN32 UString name = destPath.Ptr(pos + 1); if (name.Find(L':') >= 0) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } #endif */ UString prefix = destPath.Left(pos + 1); if (!CreateComplexDir(us2fs(prefix))) { srcPanel.MessageBoxError2Lines(prefix, GetLastError()); return; } } // bool isFolder = srcPanael.IsItem_Folder(indices[0]); } else { NName::NormalizeDirPathPrefix(destPath); if (!CreateComplexDir(us2fs(destPath))) { srcPanel.MessageBoxError2Lines(destPath, GetLastError()); return; } } destIsFsPath = true; } if (!destIsFsPath) useDestPanel = true; // AddUniqueStringToHeadOfList(copyFolders, destPath); while (copyFolders.Size() > 20) copyFolders.DeleteBack(); // SaveCopyHistory(copyFolders); } bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder(); bool useTemp = useSrcPanel && useDestPanel; if (useTemp) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED); return; } CTempDir tempDirectory; FString tempDirPrefix; if (useTemp) { tempDirectory.Create(kTempDirPrefix); tempDirPrefix = tempDirectory.GetPath(); NFile::NName::NormalizeDirPathPrefix(tempDirPrefix); } CSelectedState srcSelState; CSelectedState destSelState; srcPanel.SaveSelectedState(srcSelState); destPanel.SaveSelectedState(destSelState); CDisableNotify disableNotify1(destPanel); CDisableNotify disableNotify2(srcPanel); HRESULT result = S_OK; if (useSrcPanel) { CCopyToOptions options; options.folder = useTemp ? fs2us(tempDirPrefix) : destPath; options.moveMode = move; options.includeAltStreams = true; options.replaceAltStreamChars = false; options.showErrorMessages = true; result = srcPanel.CopyTo(options, indices, NULL); } if (result == S_OK && useDestPanel) { UStringVector filePaths; UString folderPrefix; if (useTemp) folderPrefix = fs2us(tempDirPrefix); else folderPrefix = srcPanel.GetFsPath(); filePaths.ClearAndReserve(indices.Size()); FOR_VECTOR(i, indices) filePaths.AddInReserved(srcPanel.GetItemRelPath2(indices[i])); result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0); } if (result != S_OK) { // disableNotify1.Restore(); // disableNotify2.Restore(); // For Password: // srcPanel.SetFocusToList(); // srcPanel.InvalidateList(NULL, true); if (result != E_ABORT) srcPanel.MessageBoxError(result, L"Error"); // return; } RefreshTitle(); if (copyToSame || move) { srcPanel.RefreshListCtrl(srcSelState); } if (!copyToSame) { destPanel.RefreshListCtrl(destSelState); srcPanel.KillSelection(); } disableNotify1.Restore(); disableNotify2.Restore(); srcPanel.SetFocus(); }
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex) { int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &srcPanel = Panels[srcPanelIndex]; CPanel &destPanel = Panels[destPanelIndex]; CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel); CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel); if (!srcPanel.DoesItSupportOperations()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } CRecordVector<UInt32> indices; UString destPath; bool useDestPanel = false; { if (copyToSame) { int focusedItem = srcPanel._listView.GetFocusedItem(); if (focusedItem < 0) return; int realIndex = srcPanel.GetRealItemIndex(focusedItem); if (realIndex == kParentIndex) return; indices.Add(realIndex); destPath = srcPanel.GetItemName(realIndex); } else { srcPanel.GetOperatedIndicesSmart(indices); if (indices.Size() == 0) return; destPath = destPanel._currentFolderPrefix; if (NumPanels == 1) ReducePathToRealFileSystemPath(destPath); } CCopyDialog copyDialog; UStringVector copyFolders; ReadCopyHistory(copyFolders); copyDialog.Strings = copyFolders; copyDialog.Value = destPath; copyDialog.Title = move ? LangString(IDS_MOVE, 0x03020202): LangString(IDS_COPY, 0x03020201); copyDialog.Static = move ? LangString(IDS_MOVE_TO, 0x03020204): LangString(IDS_COPY_TO, 0x03020203); copyDialog.Info = srcPanel.GetItemsInfoString(indices); if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) return; destPath = copyDialog.Value; if (destPath.IsEmpty()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } if (!IsPathAbsolute(destPath)) { if (!srcPanel.IsFSFolder()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } destPath = srcPanel._currentFolderPrefix + destPath; } #ifndef UNDER_CE if (destPath.Length() > 0 && destPath[0] == '\\') if (destPath.Length() == 1 || destPath[1] != '\\') { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } #endif if (indices.Size() > 1 || (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) || NFind::DoesDirExist(us2fs(destPath)) || srcPanel.IsArcFolder()) { NDirectory::CreateComplexDirectory(us2fs(destPath)); NName::NormalizeDirPathPrefix(destPath); if (!CheckFolderPath(destPath)) { if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } useDestPanel = true; } } else { if (!IsCorrectFsName(destPath)) { srcPanel.MessageBoxError(E_INVALIDARG); return; } int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos >= 0) { UString prefix = destPath.Left(pos + 1); NDirectory::CreateComplexDirectory(us2fs(prefix)); if (!CheckFolderPath(prefix)) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } } } AddUniqueStringToHeadOfList(copyFolders, destPath); while (copyFolders.Size() > 20) copyFolders.DeleteBack(); SaveCopyHistory(copyFolders); } /* if (destPath == destPanel._currentFolderPrefix) { if (destPanel.GetFolderTypeID() == L"PhysDrive") useDestPanel = true; } */ bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder()); bool useTemp = useSrcPanel && useDestPanel; NFile::NDirectory::CTempDir tempDirectory; FString tempDirPrefix; if (useTemp) { tempDirectory.Create(kTempDirPrefix); tempDirPrefix = tempDirectory.GetPath(); NFile::NName::NormalizeDirPathPrefix(tempDirPrefix); } CSelectedState srcSelState; CSelectedState destSelState; srcPanel.SaveSelectedState(srcSelState); destPanel.SaveSelectedState(destSelState); HRESULT result; if (useSrcPanel) { UString folder = useTemp ? fs2us(tempDirPrefix) : destPath; result = srcPanel.CopyTo(indices, folder, move, true, 0); if (result != S_OK) { disableTimerProcessing1.Restore(); disableTimerProcessing2.Restore(); // For Password: srcPanel.SetFocusToList(); if (result != E_ABORT) srcPanel.MessageBoxError(result, L"Error"); return; } } if (useDestPanel) { UStringVector filePaths; UString folderPrefix; if (useTemp) folderPrefix = fs2us(tempDirPrefix); else folderPrefix = srcPanel._currentFolderPrefix; filePaths.Reserve(indices.Size()); for (int i = 0; i < indices.Size(); i++) filePaths.Add(srcPanel.GetItemRelPath(indices[i])); result = destPanel.CopyFrom(folderPrefix, filePaths, true, 0); if (result != S_OK) { disableTimerProcessing1.Restore(); disableTimerProcessing2.Restore(); // For Password: srcPanel.SetFocusToList(); if (result != E_ABORT) srcPanel.MessageBoxError(result, L"Error"); return; } } RefreshTitleAlways(); if (copyToSame || move) { srcPanel.RefreshListCtrl(srcSelState); } if (!copyToSame) { destPanel.RefreshListCtrl(destSelState); srcPanel.KillSelection(); } disableTimerProcessing1.Restore(); disableTimerProcessing2.Restore(); srcPanel.SetFocusToList(); }
// Make sure the path is terminated with only a single / void FixPathFormat(UString& path) { while (path.Back() == L'/') path.DeleteBack(); path += L'/'; }
NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *panelItems, int itemsNumber, int move, const char *destPathLoc, int opMode, bool showBox) { if (move != 0) { g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported); return NFileOperationReturnCode::kError; } AString destPath = destPathLoc; UString destPathU = GetUnicodeString(destPath, CP_OEMCP); NFile::NName::NormalizeDirPathPrefix(destPathU); destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP); bool extractSelectedFiles = true; NExtract::CInfo extractionInfo; extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; bool silent = (opMode & OPM_SILENT) != 0; bool decompressAllItems = false; UString password = Password; bool passwordIsDefined = PasswordIsDefined; if (!silent) { const int kPathIndex = 2; extractionInfo.Load(); const int kPathModeRadioIndex = 4; const int kOverwriteModeRadioIndex = kPathModeRadioIndex + 4; const int kNumOverwriteOptions = 6; const int kFilesModeIndex = kOverwriteModeRadioIndex + kNumOverwriteOptions; const int kXSize = 76; const int kYSize = 19; const int kPasswordYPos = 12; const int kXMid = kXSize / 2; AString oemPassword = UnicodeStringToMultiByte(password, CP_OEMCP); struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL }, { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kExtractTo, NULL, NULL }, { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, kExractPathHistoryName}, // { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, 0, false, -1, destPath, NULL}, { DI_SINGLEBOX, 4, 5, kXMid - 2, 5 + 4, false, false, 0, false, NMessageID::kExtractPathMode, NULL, NULL }, { DI_RADIOBUTTON, 6, 6, 0, 0, false, extractionInfo.PathMode == NExtract::NPathMode::kFullPathnames, DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL }, { DI_RADIOBUTTON, 6, 7, 0, 0, false, extractionInfo.PathMode == NExtract::NPathMode::kCurrentPathnames, 0, false, NMessageID::kExtractPathCurrent, NULL, NULL }, { DI_RADIOBUTTON, 6, 8, 0, 0, false, extractionInfo.PathMode == NExtract::NPathMode::kNoPathnames, false, 0, NMessageID::kExtractPathNo, NULL, NULL }, { DI_SINGLEBOX, kXMid, 5, kXSize - 6, 5 + kNumOverwriteOptions, false, false, 0, false, NMessageID::kExtractOwerwriteMode, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAskBefore, DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kWithoutPrompt, 0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkipExisting, 0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false, extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRename, 0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false, extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting, 0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL }, { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL }, { DI_RADIOBUTTON, 6, 11, 0, 0, false, true, DIF_GROUP, false, NMessageID::kExtractFilesSelected, NULL, NULL }, { DI_RADIOBUTTON, 6, 12, 0, 0, false, false, 0, false, NMessageID::kExtractFilesAll, NULL, NULL }, { DI_SINGLEBOX, kXMid, kPasswordYPos, kXSize - 6, kPasswordYPos + 2, false, false, 0, false, NMessageID::kExtractPassword, NULL, NULL }, { DI_PSWEDIT, kXMid + 2, kPasswordYPos + 1, kXSize - 8, 12, false, false, 0, false, -1, oemPassword, NULL}, { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kExtractExtract, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kExtractCancel, NULL, NULL } }; const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); const int kOkButtonIndex = kNumDialogItems - 2; const int kPasswordIndex = kNumDialogItems - 4; FarDialogItem dialogItems[kNumDialogItems]; g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); for (;;) { int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize, kHelpTopicExtrFromSevenZip, dialogItems, kNumDialogItems); if (askCode != kOkButtonIndex) return NFileOperationReturnCode::kInterruptedByUser; destPath = dialogItems[kPathIndex].Data; destPathU = GetUnicodeString(destPath, CP_OEMCP); destPathU.Trim(); if (destPathU.IsEmpty()) { #ifdef UNDER_CE destPathU = L"\\"; #else if (!NFile::NDirectory::MyGetCurrentDirectory(destPathU)) throw 318016; NFile::NName::NormalizeDirPathPrefix(destPathU); #endif break; } else { if (destPathU.Back() == kDirDelimiter) break; } g_StartupInfo.ShowMessage("You must specify directory path"); } if (dialogItems[kPathModeRadioIndex].Selected) extractionInfo.PathMode = NExtract::NPathMode::kFullPathnames; else if (dialogItems[kPathModeRadioIndex + 1].Selected) extractionInfo.PathMode = NExtract::NPathMode::kCurrentPathnames; else if (dialogItems[kPathModeRadioIndex + 2].Selected) extractionInfo.PathMode = NExtract::NPathMode::kNoPathnames; else throw 31806; if (dialogItems[kOverwriteModeRadioIndex].Selected) extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected) extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected) extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkipExisting; else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected) extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRename; else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected) extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAutoRenameExisting; else throw 31806; if (dialogItems[kFilesModeIndex].Selected) decompressAllItems = false; else if (dialogItems[kFilesModeIndex + 1].Selected) decompressAllItems = true; else throw 31806; extractionInfo.Save(); if (dialogItems[kFilesModeIndex].Selected) extractSelectedFiles = true; else if (dialogItems[kFilesModeIndex + 1].Selected) extractSelectedFiles = false; else throw 31806; oemPassword = dialogItems[kPasswordIndex].Data; password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); passwordIsDefined = !password.IsEmpty(); } NFile::NDirectory::CreateComplexDirectory(destPathU); /* vector<int> realIndices; if (!decompressAllItems) GetRealIndexes(panelItems, itemsNumber, realIndices); */ CRecordVector<UINT32> indices; indices.Reserve(itemsNumber); for (int i = 0; i < itemsNumber; i++) indices.Add((UINT32)panelItems[i].UserData); HRESULT result = ExtractFiles(decompressAllItems, &indices.Front(), itemsNumber, !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode, destPathU, passwordIsDefined, password); // HRESULT result = ExtractFiles(decompressAllItems, realIndices, !showBox, // extractionInfo, destPath, passwordIsDefined, password); if (result != S_OK) { if (result == E_ABORT) return NFileOperationReturnCode::kInterruptedByUser; ShowErrorMessage(result); return NFileOperationReturnCode::kError; } // if (move != 0) // { // if (DeleteFiles(panelItems, itemsNumber, opMode) == FALSE) // return NFileOperationReturnCode::kError; // } return NFileOperationReturnCode::kSuccess; }
STDMETHODIMP CFSDrives::CopyTo(const UInt32 *indices, UInt32 numItems, const wchar_t *path, IFolderOperationsExtractCallback *callback) { if (numItems == 0) return S_OK; if (!_volumeMode) return E_NOTIMPL; UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) { const CDriveInfo &di = _drives[indices[i]]; if (di.KnownSizes) totalSize += di.DriveSize; } RINOK(callback->SetTotal(totalSize)); RINOK(callback->SetNumFiles(numItems)); UString destPath = path; if (destPath.IsEmpty()) return E_INVALIDARG; bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR); if (directName) { if (numItems > 1) return E_INVALIDARG; } UInt64 completedSize = 0; RINOK(callback->SetCompleted(&completedSize)); for (i = 0; i < numItems; i++) { int index = indices[i]; const CDriveInfo &di = _drives[index]; UString destPath2 = destPath; UString name = fs2us(di.Name); if (!directName) { UString destName = name; if (!destName.IsEmpty() && destName.Back() == L':') { destName.DeleteBack(); destName += GetExt(index); } destPath2 += destName; } FString srcPath = di.GetDeviceFileIoName(); UInt64 fileSize = 0; if (GetLength(index, fileSize) != S_OK) { return E_FAIL; } if (!di.KnownSizes) totalSize += fileSize; RINOK(callback->SetTotal(totalSize)); Int32 writeAskResult; CMyComBSTR destPathResult; RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize, destPath2, &destPathResult, &writeAskResult)); if (!IntToBool(writeAskResult)) continue; RINOK(callback->SetCurrentFilePath(fs2us(srcPath))); static const UInt32 kBufferSize = (4 << 20); UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize; RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback)); completedSize += fileSize; } return S_OK; }