void CDirItems::EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; int parent = AddPrefix(phyParent, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } }
void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { AddError(phyPrefix); return; } if (!found) break; int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (ReadSecure) AddSecurityItem(phyPrefix + fi.Name, secureIndex); #endif AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); EnumerateDir(parent, parent, phyPrefix + name2); } } }
void CDirItems::EnumerateDirItems2(const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; int parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); }
void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, const NFind::CFileInfo &fi) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.IsAltStream = fi.IsAltStream; di.PhyParent = phyParent; di.LogParent = logParent; di.SecureIndex = secureIndex; di.Name = fs2us(fi.Name); #if defined(_WIN32) && !defined(UNDER_CE) // di.ShortName = fs2us(fi.ShortName); #endif Items.Add(di); if (fi.IsDir()) Stat.NumDirs++; else if (fi.IsAltStream) { Stat.NumAltStreams++; Stat.AltStreamsSize += fi.Size; } else { Stat.NumFiles++; Stat.FilesSize += fi.Size; } }
HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &resPath) { filled = false; for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FileNames.Size()) return S_OK; const FString &path = FileNames[Index]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); resPath.Empty(); if (pos >= 0) resPath = path.Left(pos + 1); #ifdef _WIN32 // it's for "c:" paths/ if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':') { fileInfo.Name = path; fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY; fileInfo.Size = 0; } else #endif if (!fileInfo.Find(BasePrefix + path)) { WRes errorCode = GetNormalizedError(); resPath = path; return errorCode; } Index++; break; } bool found; if (!Enumerators.Back().Next(fileInfo, found)) { HRESULT errorCode = GetNormalizedError(); resPath = Prefixes.Back(); return errorCode; } if (found) { resPath = Prefixes.Back(); break; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fileInfo.Name; if (!FlatMode && fileInfo.IsDir()) { FString prefix = resPath + FCHAR_PATH_SEPARATOR; Enumerators.Add(NFind::CEnumerator(BasePrefix + prefix + FCHAR_ANY_MASK)); Prefixes.Add(prefix); } filled = true; return S_OK; }
HRESULT CDirItems::EnumerateItems2( const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector *requestedPaths) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); FOR_VECTOR (i, filePaths) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { RINOK(AddError(phyPath)); continue; } if (requestedPaths) requestedPaths->Add(phyPath); int delimiter = filePath.ReverseFind_PathSepar(); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur.SetFrom(filePath, delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (ReadSecure) { RINOK(AddSecurityItem(phyPath, secureIndex)); } #endif AddDirFileInfo(phyParentCur, logParent, secureIndex, fi); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2)); } } ReserveDown(); return S_OK; }
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) { NFind::CFileInfo fileInfo; FString pathPrefix = path + FCHAR_PATH_SEPARATOR; { NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) return false; } } /* // we don't need clear read-only for folders if (!MySetFileAttributes(path, 0)) return false; */ return RemoveDir(path); }
HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) { RINOK(ScanProgress(phyPrefix)); NFind::CEnumerator enumerator; enumerator.SetDirPrefix(phyPrefix); for (unsigned ttt = 0; ; ttt++) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { return AddError(phyPrefix); } if (!found) return S_OK; int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (ReadSecure) { RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex)); } #endif AddDirFileInfo(phyParent, logParent, secureIndex, fi); if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) { RINOK(ScanProgress(phyPrefix)); } if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); RINOK(EnumerateDir(parent, parent, phyPrefix + name2)); } } }
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path) { NFind::CFileInfo fileInfo; FString pathPrefix = path; pathPrefix.Add_PathSepar(); { NFind::CEnumerator enumerator; enumerator.SetDirPrefix(pathPrefix); while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name)) return false; } } /* // we don't need clear readonly for folders if (!SetFileAttrib(path, 0)) return false; */ return RemoveDir(path); }
void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins) { plugins.Clear(); FString baseFolderPrefix = NDLL::GetModuleDirPrefix(); { CPluginInfo pluginInfo; pluginInfo.FilePath = baseFolderPrefix + FTEXT("7-zip.dll"); if (::ReadPluginInfo(pluginInfo, false)) plugins.Add(pluginInfo); } FString folderPath = baseFolderPrefix + FTEXT("Plugins") FSTRING_PATH_SEPARATOR; NFind::CEnumerator enumerator(folderPath + FCHAR_ANY_MASK); NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDir()) continue; CPluginInfo pluginInfo; pluginInfo.FilePath = folderPath + fileInfo.Name; if (::ReadPluginInfo(pluginInfo, true)) plugins.Add(pluginInfo); } }
HRESULT CThreadCrc::ProcessVirt() { DataSize = NumFolders = NumFiles = NumFilesScan = DataCrcSum = DataNameCrcSum = 0; memset(Sha256Sum, 0, SHA256_DIGEST_SIZE); // ProgressDialog.WaitCreating(); CMyBuffer bufferObject; if (!bufferObject.Allocate(kBufSize)) return E_OUTOFMEMORY; Byte *buffer = (Byte *)(void *)bufferObject; UInt64 totalSize = 0; Enumerator.Init(); UString scanningStr = LangString(IDS_SCANNING, 0x03020800); scanningStr += L' '; CProgressSync &sync = ProgressDialog.Sync; for (;;) { NFind::CFileInfo fileInfo; bool filled; FString resPath; HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); if (errorCode != 0) { SetErrorPath1(resPath); return errorCode; } if (!filled) break; if (!fileInfo.IsDir()) { totalSize += fileInfo.Size; NumFilesScan++; } sync.SetCurrentFileName(scanningStr + fs2us(resPath)); sync.SetProgress(totalSize, 0); RINOK(sync.SetPosAndCheckPaused(0)); } sync.SetNumFilesTotal(NumFilesScan); sync.SetProgress(totalSize, 0); Enumerator.Init(); for (;;) { NFind::CFileInfo fileInfo; bool filled; FString resPath; HRESULT errorCode = Enumerator.GetNextFile(fileInfo, filled, resPath); if (errorCode != 0) { SetErrorPath1(resPath); return errorCode; } if (!filled) break; UInt32 crc = CRC_INIT_VAL; CSha256 sha256; Sha256_Init(&sha256); if (fileInfo.IsDir()) NumFolders++; else { NIO::CInFile inFile; if (!inFile.Open(Enumerator.BasePrefix + resPath)) { errorCode = GetNormalizedError(); SetErrorPath1(resPath); return errorCode; } sync.SetCurrentFileName(fs2us(resPath)); sync.SetNumFilesCur(NumFiles); NumFiles++; for (;;) { UInt32 processedSize; if (!inFile.Read(buffer, kBufSize, processedSize)) { errorCode = GetNormalizedError(); SetErrorPath1(resPath); return errorCode; } if (processedSize == 0) break; crc = CrcUpdate(crc, buffer, processedSize); if (NumFilesScan == 1) Sha256_Update(&sha256, buffer, processedSize); DataSize += processedSize; RINOK(sync.SetPosAndCheckPaused(DataSize)); } DataCrcSum += CRC_GET_DIGEST(crc); if (NumFilesScan == 1) Sha256_Final(&sha256, Sha256Sum); } for (int i = 0; i < resPath.Length(); i++) { wchar_t c = resPath[i]; crc = CRC_UPDATE_BYTE(crc, ((Byte)(c & 0xFF))); crc = CRC_UPDATE_BYTE(crc, ((Byte)((c >> 8) & 0xFF))); } DataNameCrcSum += CRC_GET_DIGEST(crc); RINOK(sync.SetPosAndCheckPaused(DataSize)); } sync.SetNumFilesCur(NumFiles); OkMessage = GetResultMessage(); OkMessageTitle = LangString(IDS_CHECKSUM_INFORMATION, 0x03020720); return S_OK; }
bool CLinkDialog::OnInit() { #ifdef LANG LangSetWindowText(*this, IDD_LINK); LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM)); _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO)); if (!FilePath.IsEmpty()) { NFind::CFileInfo fi; int linkType = 0; if (!fi.Find(us2fs(FilePath))) linkType = IDR_LINK_TYPE_SYM_FILE; else { if (fi.HasReparsePoint()) { CReparseAttr attr; bool res = GetSymLink(us2fs(FilePath), attr); UString s = attr.PrintName; if (!attr.IsOkNamePair()) { s += L" : "; s += attr.SubsName; } if (!res) s = L"ERROR: " + s; SetItemText(IDT_LINK_PATH_TO_CUR, s); UString destPath = attr.GetPath(); _pathFromCombo.SetText(FilePath); _pathToCombo.SetText(destPath); if (res) { if (attr.IsMountPoint()) linkType = IDR_LINK_TYPE_JUNCTION; if (attr.IsSymLink()) { linkType = fi.IsDir() ? IDR_LINK_TYPE_SYM_DIR : IDR_LINK_TYPE_SYM_FILE; // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE; } if (linkType != 0) Set_LinkType_Radio(linkType); } } else { _pathFromCombo.SetText(AnotherPath); _pathToCombo.SetText(FilePath); if (fi.IsDir()) linkType = g_SymLink_Supported ? IDR_LINK_TYPE_SYM_DIR : IDR_LINK_TYPE_JUNCTION; else linkType = IDR_LINK_TYPE_HARD; } } if (linkType != 0) Set_LinkType_Radio(linkType); } NormalizeSize(); return CModalDialog::OnInit(); }
HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems) { if (pluginPanelItems.Size() == 0) return E_FAIL; UStringVector fileNames; int i; for (i = 0; i < pluginPanelItems.Size(); i++) { const PluginPanelItem &panelItem = pluginPanelItems[i]; if (strcmp(panelItem.FindData.cFileName, "..") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; if (strcmp(panelItem.FindData.cFileName, ".") == 0 && NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes)) return E_FAIL; FString fullPath; FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP)); if (!MyGetFullPathName(fileNameUnicode, fullPath)) return E_FAIL; fileNames.Add(fs2us(fullPath)); } NCompression::CInfo compressionInfo; compressionInfo.Load(); int archiverIndex = 0; CCodecs *codecs = new CCodecs; CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; if (codecs->Load() != S_OK) throw "Can't load 7-Zip codecs"; { for (int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arcInfo = codecs->Formats[i]; if (arcInfo.UpdateEnabled) { if (archiverIndex == -1) archiverIndex = i; if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0) archiverIndex = i; } } } UString resultPath; { CParsedPath parsedPath; parsedPath.ParsePath(fileNames.Front()); if (parsedPath.PathParts.Size() == 0) return E_FAIL; if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1) { // CSysString pureName, dot, extension; resultPath = parsedPath.PathParts.Back(); } else { parsedPath.PathParts.DeleteBack(); resultPath = parsedPath.PathParts.Back(); } } UString archiveNameSrc = resultPath; UString archiveName = archiveNameSrc; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; int prevFormat = archiverIndex; if (!arcInfo.KeepName) { int dotPos = archiveName.ReverseFind('.'); int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); if (dotPos > slashPos) archiveName = archiveName.Left(dotPos); } archiveName += L'.'; archiveName += arcInfo.GetMainExt(); const CActionSet *actionSet = &kAddActionSet; for (;;) { AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP); const int kYSize = 16; const int kXMid = 38; const int kArchiveNameIndex = 2; const int kMethodRadioIndex = kArchiveNameIndex + 2; const int kModeRadioIndex = kMethodRadioIndex + 7; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; char updateAddToArchiveString[512]; const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP); sprintf(updateAddToArchiveString, g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s); int methodIndex = 0; int i; for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--) if (compressionInfo.Level >= g_MethodMap[i]) { methodIndex = i; break; } struct CInitDialogItem initItems[]= { { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL }, { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL }, { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName}, // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL}, { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL }, { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL }, { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1, 0, false, NMessageID::kUpdateMethodFastest, NULL, NULL }, { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2, 0, false, NMessageID::kUpdateMethodFast, NULL, NULL }, { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3, 0, false, NMessageID::kUpdateMethodNormal, NULL, NULL }, { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4, false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL }, { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5, false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL }, { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, actionSet == &kAddActionSet, DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, actionSet == &kUpdateActionSet, 0, false, NMessageID::kUpdateModeUpdate, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, actionSet == &kFreshActionSet, 0, false, NMessageID::kUpdateModeFreshen, NULL, NULL }, { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, actionSet == &kSynchronizeActionSet, 0, false, NMessageID::kUpdateModeSynchronize, NULL, 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::kUpdateAdd, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL } }; const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]); const int kOkButtonIndex = kNumDialogItems - 3; const int kSelectarchiverButtonIndex = kNumDialogItems - 2; FarDialogItem dialogItems[kNumDialogItems]; g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems); int askCode = g_StartupInfo.ShowDialog(76, kYSize, kHelpTopic, dialogItems, kNumDialogItems); archiveNameA = dialogItems[kArchiveNameIndex].Data; archiveNameA.Trim(); archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP); compressionInfo.Level = g_MethodMap[0]; for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++) if (dialogItems[kMethodRadioIndex + i].Selected) compressionInfo.Level = g_MethodMap[i]; if (dialogItems[kModeRadioIndex].Selected) actionSet = &kAddActionSet; else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &kUpdateActionSet; else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &kFreshActionSet; else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &kSynchronizeActionSet; else throw 51751; if (askCode == kSelectarchiverButtonIndex) { CIntVector indices; CSysStringVector archiverNames; for (int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; if (arc.UpdateEnabled) { indices.Add(i); archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP)); } } int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT, g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle), NULL, archiverNames, archiverIndex); if (index >= 0) { const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat]; if (prevArchiverInfo.KeepName) { const UString &prevExtension = prevArchiverInfo.GetMainExt(); const int prevExtensionLen = prevExtension.Length(); if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0) { int pos = archiveName.Length() - prevExtensionLen; if (pos > 1) { int dotPos = archiveName.ReverseFind('.'); if (dotPos == pos - 1) archiveName = archiveName.Left(dotPos); } } } archiverIndex = indices[index]; const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex]; prevFormat = archiverIndex; if (arcInfo.KeepName) archiveName = archiveNameSrc; else { int dotPos = archiveName.ReverseFind('.'); int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/')); if (dotPos > slashPos) archiveName = archiveName.Left(dotPos); } archiveName += L'.'; archiveName += arcInfo.GetMainExt(); } continue; } if (askCode != kOkButtonIndex) return E_ABORT; break; } const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex]; compressionInfo.ArcType = archiverInfoFinal.Name; compressionInfo.Save(); NWorkDir::CInfo workDirInfo; workDirInfo.Load(); FString fullArchiveName; if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName)) return E_FAIL; CWorkDirTempFile tempFile; RINOK(tempFile.CreateTempFile(fullArchiveName)); CScreenRestorer screenRestorer; CProgressBox progressBox; CProgressBox *progressBoxPointer = NULL; screenRestorer.Save(); progressBoxPointer = &progressBox; progressBox.Init( // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle), g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48); NFind::CFileInfo fileInfo; CMyComPtr<IOutFolderArchive> outArchive; CMyComPtr<IInFolderArchive> archiveHandler; if (fileInfo.Find(fullArchiveName)) { if (fileInfo.IsDir()) throw "There is Directory with such name"; CAgent *agentSpec = new CAgent; archiveHandler = agentSpec; // CLSID realClassID; CMyComBSTR archiveType; RINOK(agentSpec->Open(NULL, GetUnicodeString(fullArchiveName, CP_OEMCP), UString(), // &realClassID, &archiveType, NULL)); if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0) throw "Type of existing archive differs from specified type"; HRESULT result = archiveHandler.QueryInterface( IID_IOutFolderArchive, &outArchive); if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return E_FAIL; } } else { // HRESULT result = outArchive.CoCreateInstance(classID); CAgent *agentSpec = new CAgent; outArchive = agentSpec; /* HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler); if (result != S_OK) { g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive); return E_FAIL; } */ } CRecordVector<const wchar_t *> fileNamePointers; fileNamePointers.Reserve(fileNames.Size()); for (i = 0; i < fileNames.Size(); i++) fileNamePointers.Add(fileNames[i]); outArchive->SetFolder(NULL); outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size()); BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (BYTE)actionSet->StateActions[i]; CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp; CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec ); updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer); RINOK(SetOutProperties(outArchive, compressionInfo.Level)); HRESULT result = outArchive->DoOperation( codecs, archiverIndex, tempFile.OutStream, actionSetByte, NULL, updateCallback); updateCallback.Release(); outArchive.Release(); if (result != S_OK) { ShowErrorMessage(result); return result; } if (archiveHandler) { archiveHandler->Close(); } if (!tempFile.MoveToOriginal(archiveHandler != NULL)) { ShowLastErrorMessage(); return E_FAIL; } return S_OK; }
static HRESULT CopyFolder( CCopyState &state, const FString &srcPath, // without TAIL separator const FString &destPath) // without TAIL separator { RINOK(state.CallProgress()); if (IsDestChild(srcPath, destPath)) { RINOK(SendMessageError(state.Callback, state.MoveMode ? "can not copy folder onto itself" : "can not move folder onto itself" , destPath)); return E_ABORT; } if (state.MoveMode) { if (state.MoveFile_Sys(srcPath, destPath)) return S_OK; // MSDN: MoveFile() fails for dirs on different volumes. } if (!CreateComplexDir(destPath)) { RINOK(SendMessageError(state.Callback, "can not create folder", destPath)); return E_ABORT; } CEnumerator enumerator; enumerator.SetDirPrefix(CombinePath(srcPath, FString())); for (;;) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { SendLastErrorMessage(state.Callback, srcPath); return S_OK; } if (!found) break; const FString srcPath2 = CombinePath(srcPath, fi.Name); const FString destPath2 = CombinePath(destPath, fi.Name); if (fi.IsDir()) { RINOK(CopyFolder(state, srcPath2, destPath2)) } else { RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2)); } } if (state.MoveMode) { if (!RemoveDir(srcPath)) { RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath)); return E_ABORT; } } return S_OK; }
static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); }
static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const FString fullPath = phyPrefix + us2fs(name); NFind::CFileInfo fi; if (!fi.Find(fullPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const FString fullPath = phyPrefix + us2fs(nextNode.Name); NFind::CFileInfo fi; if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (int ttt = 0; ; ttt++) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); const UString &name = fs2us(fi.Name); bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; }
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; resPath.Empty(); for (;;) { #if defined(_WIN32) && !defined(UNDER_CE) bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0)); #endif if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; int pos = path.ReverseFind_PathSepar(); if (pos >= 0) resPath.SetFrom(path, pos + 1); #if defined(_WIN32) && !defined(UNDER_CE) if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path)) { // we use "c:" item as directory item fi.ClearBase(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; } else #endif if (!fi.Find(BasePrefix + path)) { DWORD error = GetNormalizedError(); resPath = path; return error; } break; } bool found; if (Enumerators.Back().Next(fi, found)) { if (found) { resPath = Prefixes.Back(); break; } } else { DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); Enumerators.DeleteBack(); Prefixes.DeleteBack(); return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fi.Name; if (EnterToDirs && fi.IsDir()) { FString s = resPath; s.Add_PathSepar(); Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } filled = true; return S_OK; }
HRESULT CThreadCrc::ProcessVirt() { Hash.Init(); CMyBuffer buf; if (!buf.Allocate(kBufSize)) return E_OUTOFMEMORY; CProgressSync &sync = ProgressDialog.Sync; SetStatus(LangString(IDS_SCANNING)); Enumerator.Init(); FString path; NFind::CFileInfo fi; UInt64 numFiles = 0; UInt64 numItems = 0, numItems_Prev = 0; UInt64 totalSize = 0; for (;;) { bool filled; DWORD error = Enumerator.GetNextFile(fi, filled, path); if (error != 0) { AddErrorMessage(error, path); continue; } if (!filled) break; if (!fi.IsDir()) { totalSize += fi.Size; numFiles++; } numItems++; bool needPrint = false; // if (fi.IsDir()) { if (numItems - numItems_Prev >= 100) { needPrint = true; numItems_Prev = numItems; } } /* else if (numFiles - numFiles_Prev >= 200) { needPrint = true; numFiles_Prev = numFiles; } */ if (needPrint) { RINOK(sync.ScanProgress(numFiles, totalSize, path, fi.IsDir())); } } RINOK(sync.ScanProgress(numFiles, totalSize, FString(), false)); // sync.SetNumFilesTotal(numFiles); // sync.SetProgress(totalSize, 0); // SetStatus(LangString(IDS_CHECKSUM_CALCULATING)); // sync.SetCurFilePath(L""); SetStatus(L""); Enumerator.Init(); FString tempPath; FString firstFilePath; bool isFirstFile = true; UInt64 errorsFilesSize = 0; for (;;) { bool filled; DWORD error = Enumerator.GetNextFile(fi, filled, path); if (error != 0) { AddErrorMessage(error, path); continue; } if (!filled) break; error = 0; Hash.InitForNewFile(); if (!fi.IsDir()) { NIO::CInFile inFile; tempPath = Enumerator.BasePrefix_for_Open; tempPath += path; if (!inFile.Open(tempPath)) { error = GetNormalizedError(); AddErrorMessage(error, path); continue; } if (isFirstFile) { firstFilePath = path; isFirstFile = false; } sync.Set_FilePath(fs2us(path)); sync.Set_NumFilesCur(Hash.NumFiles); UInt64 progress_Prev = 0; for (;;) { UInt32 size; if (!inFile.Read(buf, kBufSize, size)) { error = GetNormalizedError(); AddErrorMessage(error, path); UInt64 errorSize = 0; if (inFile.GetLength(errorSize)) errorsFilesSize += errorSize; break; } if (size == 0) break; Hash.Update(buf, size); if (Hash.CurSize - progress_Prev >= ((UInt32)1 << 21)) { RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize + Hash.CurSize)); progress_Prev = Hash.CurSize; } } } if (error == 0) Hash.Final(fi.IsDir(), false, fs2us(path)); RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize)); } RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize)); sync.Set_NumFilesCur(Hash.NumFiles); if (Hash.NumFiles != 1) sync.Set_FilePath(L""); SetStatus(L""); CProgressMessageBoxPair &pair = GetMessagePair(Hash.NumErrors != 0); AddHashBundleRes(pair.Message, Hash, fs2us(firstFilePath)); LangString(IDS_CHECKSUM_INFORMATION, pair.Title); return S_OK; }
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; resPath.Empty(); for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos >= 0) resPath.SetFrom(path, pos + 1); #ifdef _WIN32 if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':') { // we use "c:" item as directory item fi.Clear(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; } else #endif if (!fi.Find(BasePrefix + path)) { DWORD error = GetNormalizedError(); resPath = path; return error; } break; } bool found; if (Enumerators.Back().Next(fi, found)) { if (found) { resPath = Prefixes.Back(); break; } } else { DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); Enumerators.DeleteBack(); Prefixes.DeleteBack(); return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fi.Name; if (EnterToDirs && fi.IsDir()) { FString s = resPath; s += FCHAR_PATH_SEPARATOR; Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } filled = true; return S_OK; }
static HRESULT EnumerateForItem( NFind::CFileInfo &fi, const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders) { const UString name = fs2us(fi.Name); bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) return S_OK; } int dirItemIndex = -1; bool addAllSubStreams = false; if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { int secureIndex = -1; #ifdef _USE_SECURITY_CODE if (dirItems.ReadSecure) { RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex)); } #endif dirItemIndex = dirItems.Items.Size(); dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); if (fi.IsDir()) enterToSubFolders2 = true; addAllSubStreams = true; } #ifndef UNDER_CE if (dirItems.ScanAltStreams) { RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix + fi.Name, addArchivePrefixNew, addAllSubStreams, dirItems)); } if (dirItemIndex >= 0) { CDirItem &dirItem = dirItems.Items[dirItemIndex]; RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); if (dirItem.ReparseData.Size() != 0) return S_OK; } #endif if (!fi.IsDir()) return S_OK; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) return S_OK; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } return EnumerateDirItems_Spec( *nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2); }
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT commandIDFirst, UINT commandIDLast, UINT flags) { // OutputDebugStringA("QueryContextMenu"); LoadLangOneTime(); if (_fileNames.Size() == 0) return E_FAIL; UINT currentCommandID = commandIDFirst; if ((flags & 0x000F) != CMF_NORMAL && (flags & CMF_VERBSONLY) == 0 && (flags & CMF_EXPLORE) == 0) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); _commandMap.Clear(); CMenu popupMenu; CMenuDestroyer menuDestroyer; CContextMenuInfo ci; ci.Load(); _elimDup = ci.ElimDup; HBITMAP bitmap = NULL; if (ci.MenuIcons.Val) bitmap = _bitmap; UINT subIndex = indexMenu; if (ci.Cascaded.Val) { if (!popupMenu.CreatePopup()) return E_FAIL; menuDestroyer.Attach(popupMenu); /* 9.31: we commented the following code. Probably we don't need. Check more systems. Maybe it was for old Windows? */ /* AddMapItem_ForSubMenu(); currentCommandID++; */ subIndex = 0; } else { popupMenu.Attach(hMenu); CMenuItem mi; mi.fType = MFT_SEPARATOR; mi.fMask = MIIM_TYPE; popupMenu.InsertItem(subIndex++, true, mi); } UInt32 contextMenuFlags = ci.Flags; NFind::CFileInfo fi0; FString folderPrefix; if (_fileNames.Size() > 0) { const UString &fileName = _fileNames.Front(); #if defined(_WIN32) && !defined(UNDER_CE) if (NName::IsDevicePath(us2fs(fileName))) { // CFileInfo::Find can be slow for device files. So we don't call it. // we need only name here. fi0.Name = us2fs(fileName.Ptr(NName::kDevicePathPrefixSize)); // change it 4 - must be constant folderPrefix = #ifdef UNDER_CE FTEXT("\\"); #else FTEXT("C:\\"); #endif } else #endif { if (!fi0.Find(us2fs(fileName))) return E_FAIL; GetOnlyDirPrefix(us2fs(fileName), folderPrefix); } } UString mainString; if (_fileNames.Size() == 1 && currentCommandID + 14 <= commandIDLast) { if (!fi0.IsDir() && DoNeedExtract(fi0.Name)) { // Open bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0); if (thereIsMainOpenItem) { CCommandMapItem commandMapItem; FillCommand(kOpen, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 // && (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fi0.Name)) ) { CMenu subMenu; if (subMenu.CreatePopup()) { CMenuItem mi; mi.fType = MFT_STRING; mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; if (bitmap) mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = subMenu; mi.hbmpUnchecked = bitmap; LangString(IDS_CONTEXT_OPEN, mi.StringValue); popupMenu.InsertItem(subIndex++, true, mi); AddMapItem_ForSubMenu(kOpenCascadedVerb); UINT subIndex2 = 0; for (unsigned i = (thereIsMainOpenItem ? 1 : 0); i < ARRAY_SIZE(kOpenTypes); i++) { CCommandMapItem commandMapItem; if (i == 0) FillCommand(kOpen, mainString, commandMapItem); else { mainString.SetFromAscii(kOpenTypes[i]); commandMapItem.CommandInternalID = kOpen; commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString; commandMapItem.HelpString = mainString; commandMapItem.ArcType = mainString; } MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } subMenu.Detach(); } } } } if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) { bool needExtract = (!fi0.IsDir() && DoNeedExtract(fi0.Name)); if (!needExtract) { for (unsigned i = 1; i < _fileNames.Size(); i++) { NFind::CFileInfo fi; if (!fi.Find(us2fs(_fileNames[i]))) return E_FAIL; if (!fi.IsDir() && DoNeedExtract(fi.Name)) { needExtract = true; break; } } } const UString &fileName = _fileNames.Front(); if (needExtract) { { UString baseFolder = fs2us(folderPrefix); if (_dropMode) baseFolder = _dropPath; UString specFolder = L'*'; if (_fileNames.Size() == 1) specFolder = GetSubFolderNameForExtract(fs2us(fi0.Name)); specFolder.Add_PathSepar(); if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) { // Extract CCommandMapItem commandMapItem; FillCommand(kExtract, mainString, commandMapItem); commandMapItem.Folder = baseFolder + specFolder; MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) { // Extract Here CCommandMapItem commandMapItem; FillCommand(kExtractHere, mainString, commandMapItem); commandMapItem.Folder = baseFolder; MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) { // Extract To CCommandMapItem commandMapItem; UString s; FillCommand(kExtractTo, s, commandMapItem); commandMapItem.Folder = baseFolder + specFolder; MyFormatNew_ReducedName(s, specFolder); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } } if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) { // Test CCommandMapItem commandMapItem; FillCommand(kTest, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } } UString arcName; if (_fileNames.Size() == 1) arcName = CreateArchiveName(fi0, false); else arcName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); UString arcName7z = arcName + L".7z"; UString arcNameZip = arcName + L".zip"; // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) { CCommandMapItem commandMapItem; if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = arcName; FillCommand(kCompress, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressEmail if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; commandMapItem.ArcName = arcName; FillCommand(kCompressEmail, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); _commandMap.Add(commandMapItem); } #endif // CompressTo7z if (contextMenuFlags & NContextMenuFlags::kCompressTo7z && !arcName7z.IsEqualTo_NoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressTo7z, s, commandMapItem); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = arcName7z; commandMapItem.ArcType.SetFromAscii("7z"); MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressTo7zEmail if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressTo7zEmail, s, commandMapItem); commandMapItem.ArcName = arcName7z; commandMapItem.ArcType.SetFromAscii("7z"); MyFormatNew_ReducedName(s, arcName7z); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #endif // CompressToZip if (contextMenuFlags & NContextMenuFlags::kCompressToZip && !arcNameZip.IsEqualTo_NoCase(fs2us(fi0.Name))) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressToZip, s, commandMapItem); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = fs2us(folderPrefix); commandMapItem.ArcName = arcNameZip; commandMapItem.ArcType.SetFromAscii("zip"); MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressToZipEmail if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressToZipEmail, s, commandMapItem); commandMapItem.ArcName = arcNameZip; commandMapItem.ArcType.SetFromAscii("zip"); MyFormatNew_ReducedName(s, arcNameZip); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } #endif } // don't use InsertMenu: See MSDN: // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension // ID: Q214477 if (ci.Cascaded.Val) { CMenuItem mi; mi.fType = MFT_STRING; mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; if (bitmap) mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = popupMenu.Detach(); mi.StringValue.SetFromAscii("7-Zip"); // LangString(IDS_CONTEXT_POPUP_CAPTION); mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); menuDestroyer.Disable(); menu.InsertItem(indexMenu++, true, mi); AddMapItem_ForSubMenu(kMainVerb); } else { popupMenu.Detach(); indexMenu = subIndex; } if (!_isMenuForFM && ((contextMenuFlags & NContextMenuFlags::kCRC) != 0 && currentCommandID + 6 <= commandIDLast)) { CMenu subMenu; // CMenuDestroyer menuDestroyer_CRC; UINT subIndex_CRC = 0; if (subMenu.CreatePopup()) { // menuDestroyer_CRC.Attach(subMenu); CMenuItem mi; mi.fType = MFT_STRING; mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; if (bitmap) mi.fMask |= MIIM_CHECKMARKS; mi.wID = currentCommandID++; mi.hSubMenu = subMenu; mi.StringValue.SetFromAscii("CRC SHA"); mi.hbmpUnchecked = bitmap; CMenu menu; menu.Attach(hMenu); // menuDestroyer_CRC.Disable(); menu.InsertItem(indexMenu++, true, mi); AddMapItem_ForSubMenu(kCheckSumCascadedVerb); for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++) { const CHashCommand &hc = g_HashCommands[i]; CCommandMapItem commandMapItem; commandMapItem.CommandInternalID = hc.CommandInternalID; commandMapItem.Verb = (UString)kCheckSumCascadedVerb + (UString)hc.MethodName; // commandMapItem.HelpString = hc.Name; MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, hc.UserName, bitmap); _commandMap.Add(commandMapItem); } subMenu.Detach(); } } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); }