void ConvertNameToFull(const wchar *Src,wchar *Dest) { if (Src==NULL || *Src==0) { *Dest=0; return; } #ifdef _WIN_32 if (WinNT()) { wchar FullName[NM],*NamePtr; if (GetFullPathNameW(Src,sizeof(FullName)/sizeof(FullName[0]),FullName,&NamePtr)) strcpyw(Dest,FullName); else if (Src!=Dest) strcpyw(Dest,Src); } else { char AnsiName[NM]; WideToChar(Src,AnsiName); ConvertNameToFull(AnsiName,AnsiName); CharToWide(AnsiName,Dest); } #else char AnsiName[NM]; WideToChar(Src,AnsiName); ConvertNameToFull(AnsiName,AnsiName); CharToWide(AnsiName,Dest); #endif }
void GetFullName(const string& Name, string &strFullName) { if (Name[0]==L'<') strFullName = Name; else ConvertNameToFull(Name,strFullName); }
int RemoveToRecycleBin(const wchar_t *Name) { string strFullName; ConvertNameToFull(Name, strFullName); // При удалении в корзину папки с симлинками получим траблу, если предварительно линки не убрать. if (WinVer.dwMajorVersion<6 && Opt.DeleteToRecycleBinKillLink && apiGetFileAttributes(Name) == FILE_ATTRIBUTE_DIRECTORY) { string strFullName2; FAR_FIND_DATA_EX FindData; ScanTree ScTree(TRUE,TRUE,FALSE); ScTree.SetFindPath(Name,L"*", 0); while (ScTree.GetNextName(&FindData,strFullName2)) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && FindData.dwFileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) ERemoveDirectory(strFullName2,FALSE); } } wchar_t *lpwszName = strFullName.GetBuffer(strFullName.GetLength()+2); lpwszName[strFullName.GetLength()+1] = 0; //dirty trick to make strFullName end with DOUBLE zero!!! return MoveToRecycleBinInternal(lpwszName); }
int CheckUpdateAnotherPanel(Panel *SrcPanel, const string& SelName) { if (!SrcPanel) SrcPanel = Global->CtrlObject->Cp()->ActivePanel(); const auto AnotherPanel = Global->CtrlObject->Cp()->GetAnotherPanel(SrcPanel); AnotherPanel->CloseFile(); if (AnotherPanel->GetMode() == NORMAL_PANEL) { string strFullName; string strAnotherCurDir(AnotherPanel->GetCurDir()); AddEndSlash(strAnotherCurDir); ConvertNameToFull(SelName, strFullName); AddEndSlash(strFullName); if (strAnotherCurDir.find(strFullName) != string::npos) { AnotherPanel->StopFSWatcher(); return TRUE; } } return FALSE; }
void NTPath::Transform() { string& Data = *this; if (!Data.empty()) { if(!HasPathPrefix(Data)) { ConvertNameToFull(Data,Data); if (!HasPathPrefix(Data)) { ReplaceSlashToBackslash(Data); string Prefix(ParsePath(Data) == PATH_DRIVELETTER? L"\\\\?\\" : L"\\\\?\\UNC"); while(ReplaceStrings(Data,L"\\\\",L"\\")) ; Data=Prefix+Data; } } if(Data.size() > 5 && Data[5] == L':') { // "\\?\C:" -> "\\?\c:" // Some file operations fails on Win2k if a drive letter is in upper case ToLower(Data, 4, 1); } } }
int CheckUpdateAnotherPanel(Panel *SrcPanel,const wchar_t *SelName) { if (!SrcPanel) SrcPanel=CtrlObject->Cp()->ActivePanel; Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(SrcPanel); AnotherPanel->CloseFile(); if (AnotherPanel->GetMode() == NORMAL_PANEL) { string strAnotherCurDir; string strFullName; AnotherPanel->GetCurDir(strAnotherCurDir); AddEndSlash(strAnotherCurDir); ConvertNameToFull(SelName, strFullName); AddEndSlash(strFullName); if (wcsstr(strAnotherCurDir,strFullName)) { ((FileList*)AnotherPanel)->StopFSWatcher(); return TRUE; } } return FALSE; }
bool ModifyReparsePoint(const wchar_t *Object,const wchar_t *NewData) { bool Result=false; LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if(szBuff) { PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff); if (GetREPARSE_DATA_BUFFER(Object,rdb)) { bool FillResult=false; switch (rdb->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: { string strPrintName,strSubstituteName; ConvertNameToFull(NewData,strPrintName); strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); FillResult=FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()); } break; case IO_REPARSE_TAG_SYMLINK: { string strPrintName=NewData,strSubstituteName=NewData; if (IsAbsolutePath(NewData)) { strSubstituteName=L"\\??\\"; strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } FillResult=FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()); } break; } if (FillResult) { Result=SetREPARSE_DATA_BUFFER(Object,rdb); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } delete[] szBuff; } return Result; }
BOOL FarChDir(const string& NewDir, BOOL ChangeDir) { if (NewDir.empty()) return FALSE; BOOL rc=FALSE; string Drive(L"=A:"); string strCurDir; // если указана только буква диска, то путь возьмем из переменной if (NewDir.size() == 2 && NewDir[1]==L':') { Drive[1] = ToUpper(NewDir[0]); if (!api::env::get_variable(Drive, strCurDir)) { strCurDir = NewDir; AddEndSlash(strCurDir); ReplaceSlashToBSlash(strCurDir); } if (ChangeDir) { rc=api::SetCurrentDirectory(strCurDir); } } else { if (ChangeDir) { strCurDir = NewDir; if (strCurDir == L"\\") api::GetCurrentDirectory(strCurDir); // здесь берем корень ReplaceSlashToBSlash(strCurDir); ConvertNameToFull(NewDir,strCurDir); PrepareDiskPath(strCurDir,false); // resolving not needed, very slow rc=api::SetCurrentDirectory(strCurDir); } } if (rc || !ChangeDir) { if ((!ChangeDir || api::GetCurrentDirectory(strCurDir)) && strCurDir.size() > 1 && strCurDir[1]==L':') { Drive[1] = ToUpper(strCurDir[0]); api::env::set_variable(Drive, strCurDir); } } return rc; }
int ERemoveDirectory(const string& Name,DIRDELTYPE Type) { ProcessedItems++; string strFullName; ConvertNameToFull(Name,strFullName); bool Success = false; while(!Success) { switch(Type) { case D_DEL: Success = apiRemoveDirectory(Name) != FALSE; break; case D_WIPE: Success = WipeDirectory(Name) != FALSE; break; case D_RECYCLE: Success = RemoveToRecycleBin(Name) != FALSE; break; } if(!Success) { int MsgCode; if (SkipFoldersMode!=-1) { MsgCode=SkipFoldersMode; } else { MsgCode=OperationFailed(Name, MError, MSG(MCannotDeleteFolder)); } switch (MsgCode) { case -1: case -2: case 3: return DELETE_CANCEL; case 1: return DELETE_SKIP; case 2: SkipFoldersMode=2; return DELETE_SKIP; } } } return DELETE_SUCCESS; }
void ConvertNameToFull(const wchar *Src,wchar *Dest) { if (Src==NULL || *Src==0) { *Dest=0; return; } #ifdef _WIN_32 #ifndef _WIN_CE if (WinNT()) #endif { //#ifndef _WIN_CE #if !defined(_WIN_CE) && !defined(_LINUX) wchar FullName[NM],*NamePtr; if (GetFullPathNameW(Src,sizeof(FullName)/sizeof(FullName[0]),FullName,&NamePtr)) strcpyw(Dest,FullName); else #endif if (Src!=Dest) strcpyw(Dest,Src); } #ifndef _WIN_CE else { char AnsiName[NM]; WideToChar(Src,AnsiName); ConvertNameToFull(AnsiName,AnsiName); CharToWide(AnsiName,Dest); } #endif #else char AnsiName[NM]; WideToChar(Src,AnsiName); ConvertNameToFull(AnsiName,AnsiName); CharToWide(AnsiName,Dest); #endif }
/* Используется для запуска внешнего редактора и вьювера */ void ProcessExternal(const wchar_t *Command, const wchar_t *Name, const wchar_t *ShortName, bool AlwaysWaitFinish) { string strListName, strAnotherListName; string strShortListName, strAnotherShortListName; string strFullName, strFullShortName; string strExecStr = Command; string strFullExecStr = Command; { int PreserveLFN=SubstFileName(strExecStr,Name,ShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); bool ListFileUsed=!strListName.IsEmpty()||!strAnotherListName.IsEmpty()||!strShortListName.IsEmpty()||!strAnotherShortListName.IsEmpty(); // Снова все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strExecStr)) return; PreserveLongName PreserveName(ShortName,PreserveLFN); ConvertNameToFull(Name,strFullName); ConvertNameToShort(strFullName,strFullShortName); //BUGBUGBUGBUGBUGBUG !!! Same ListNames!!! SubstFileName(strFullExecStr,strFullName,strFullShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); // Снова все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strFullExecStr)) return; CtrlObject->ViewHistory->AddToHistory(strFullExecStr,(AlwaysWaitFinish&1)+2); if (strExecStr.At(0) != L'@') CtrlObject->CmdLine->ExecString(strExecStr,AlwaysWaitFinish, 0, 0, ListFileUsed, true); else { SaveScreen SaveScr; CtrlObject->Cp()->LeftPanel->CloseFile(); CtrlObject->Cp()->RightPanel->CloseFile(); Execute(strExecStr.CPtr()+1,AlwaysWaitFinish, 0, 0, 0, ListFileUsed); } } if (!strListName.IsEmpty()) apiDeleteFile(strListName); if (!strAnotherListName.IsEmpty()) apiDeleteFile(strAnotherListName); if (!strShortListName.IsEmpty()) apiDeleteFile(strShortListName); if (!strAnotherShortListName.IsEmpty()) apiDeleteFile(strAnotherShortListName); }
string Panel::CreateFullPathName(string_view const Name, bool const Directory, bool const UNC, bool const ShortNameAsIs) const { auto FullName = FindSlash(Name) == string::npos? ConvertNameToFull(Name) : string(Name); if (m_ShowShortNames && ShortNameAsIs) FullName = ConvertNameToShort(FullName); /* $ 29.01.2001 VVM + По CTRL+ALT+F в командную строку сбрасывается UNC-имя текущего файла. */ if (UNC) FullName = ConvertNameToUNC(FullName); // $ 20.10.2000 SVS Сделаем фичу Ctrl-F опциональной! if (Global->Opt->PanelCtrlFRule) { /* $ 13.10.2000 tran по Ctrl-f имя должно отвечать условиям на панели */ if (m_ViewSettings.Flags&PVS_FOLDERUPPERCASE) { if (Directory) { inplace::upper(FullName); } else { inplace::upper(FullName, 0, FindLastSlash(FullName)); } } if ((m_ViewSettings.Flags&PVS_FILEUPPERTOLOWERCASE) && !Directory) { const auto pos = FindLastSlash(FullName); if (pos != string::npos && !IsCaseMixed(string_view(FullName).substr(pos))) { inplace::lower(FullName, pos); } } if ((m_ViewSettings.Flags&PVS_FILELOWERCASE) && !Directory) { const auto pos = FindLastSlash(FullName); if (pos != string::npos) { inplace::lower(FullName, pos); } } } return FullName; }
bool ModifyReparsePoint(const string& Object,const string& NewData) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!GetREPARSE_DATA_BUFFER(Object, rdb.get())) return false; switch (rdb->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: { const auto strPrintName = ConvertNameToFull(NewData); const auto strSubstituteName = KernelPath(NTPath(strPrintName)); if (!FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } } break; case IO_REPARSE_TAG_SYMLINK: { const auto& strPrintName = NewData; auto strSubstituteName = NewData; if (IsAbsolutePath(NewData)) { strSubstituteName = KernelPath(NTPath(strSubstituteName)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } if (!FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } } break; default: return false; } return SetREPARSE_DATA_BUFFER(Object,rdb.get()); }
void ScanTree::ScanError(bool &Error) { #ifdef _WIN_ALL if (Error) { // Get attributes of parent folder and do not display an error // if it is reparse point. We cannot scan contents of standard // Windows reparse points like "C:\Documents and Settings" // and we do not want to issue numerous useless errors for them. // We cannot just check FD->FileAttr here, it can be undefined // if we process "folder\*" mask or if we process "folder" mask, // but "folder" is inaccessible. wchar *Slash=PointToName(CurMask); if (Slash>CurMask) { *(Slash-1)=0; DWORD Attr=GetFileAttributes(CurMask); *(Slash-1)=CPATHDIVIDER; if (Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) Error=false; } // Do not display an error if we cannot scan contents of // "System Volume Information" folder. Normally it is not accessible. if (wcsstr(CurMask,L"System Volume Information\\")!=NULL) Error=false; } #endif if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true)) Error=false; if (Error) { if (ErrDirList!=NULL) ErrDirList->AddString(CurMask); if (ErrDirSpecPathLength!=NULL) ErrDirSpecPathLength->Push((uint)SpecPathLength); wchar FullName[NM]; // This conversion works for wildcard masks too. ConvertNameToFull(CurMask,FullName,ASIZE(FullName)); uiMsg(UIERROR_DIRSCAN,FullName); ErrHandler.SysErrMsg(); } }
static void InitTemplateProfile(string &strTemplatePath) { if (strTemplatePath.empty()) { strTemplatePath = GetFarIniString(L"General"s, L"TemplateProfile"s, path::join(L"%FARHOME%"sv, L"Default.farconfig"sv)); } if (!strTemplatePath.empty()) { strTemplatePath = ConvertNameToFull(unquote(os::env::expand(strTemplatePath))); DeleteEndSlash(strTemplatePath); if (os::fs::is_directory(strTemplatePath)) path::append(strTemplatePath, L"Default.farconfig"sv); Global->Opt->TemplateProfilePath = strTemplatePath; } }
string ConvertNameToUNC(string_view const Object) { auto strFileName = ConvertNameToFull(Object); // Посмотрим на тип файловой системы string strFileSystemName; os::fs::GetVolumeInformation(GetPathRoot(strFileName), nullptr, nullptr, nullptr, nullptr, &strFileSystemName); DWORD uniSize = 1024; block_ptr<UNIVERSAL_NAME_INFO> uni(uniSize); // применяем WNetGetUniversalName для чего угодно, только не для Novell`а if (!equal_icase(strFileSystemName, L"NWFS"sv)) { switch (WNetGetUniversalName(strFileName.c_str(), UNIVERSAL_NAME_INFO_LEVEL, uni.get(), &uniSize)) { case NO_ERROR: strFileName = uni->lpUniversalName; break; case ERROR_MORE_DATA: uni.reset(uniSize); if (WNetGetUniversalName(strFileName.c_str(),UNIVERSAL_NAME_INFO_LEVEL,uni.get(),&uniSize)==NO_ERROR) strFileName = uni->lpUniversalName; break; } } else if (strFileName.size() > 1 && strFileName[1] == L':') { // BugZ#449 - Неверная работа CtrlAltF с ресурсами Novell DS // Здесь, если не получилось получить UniversalName и если это // мапленный диск - получаем как для меню выбора дисков string strTemp; if (DriveLocalToRemoteName(DRIVE_UNKNOWN,strFileName[0],strTemp)) { const auto SlashPos = FindSlash(strFileName); if (SlashPos != string::npos) path::append(strTemp, string_view(strFileName).substr(SlashPos + 1)); strFileName = strTemp; } } return ConvertNameToReal(strFileName); }
/* Преобразует Src в полный РЕАЛЬНЫЙ путь с учетом reparse point. Note that Src can be partially non-existent. */ string ConvertNameToReal(string_view const Object) { SCOPED_ACTION(elevation::suppress); // Получим сначала полный путь до объекта обычным способом const auto FullPath = ConvertNameToFull(Object); auto strDest = FullPath; string Path = FullPath; os::fs::file File; for (;;) { if (File.Open(Path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING)) break; if (IsRootPath(Path)) break; Path = ExtractFilePath(Path); } if (File) { string FinalFilePath; File.GetFinalPathName(FinalFilePath); File.Close(); //assert(!FinalFilePath.empty()); if (!FinalFilePath.empty()) { // append non-existent path part (if present) DeleteEndSlash(Path); if (FullPath.size() > Path.size() + 1) path::append(FinalFilePath, string_view(FullPath).substr(Path.size() + 1)); FinalFilePath = TryConvertVolumeGuidToDrivePath(FinalFilePath); strDest = FinalFilePath; } } return strDest; }
int FilePanels::GetTypeAndName(string &strType, string &strName) { strType = MSG(MScreensPanels); string strFullName, strShortName; switch (ActivePanel->GetType()) { case TREE_PANEL: case QVIEW_PANEL: case FILE_PANEL: case INFO_PANEL: ActivePanel->GetCurName(strFullName, strShortName); ConvertNameToFull(strFullName, strFullName); break; } strName = strFullName; return(MODALTYPE_PANELS); }
int ERemoveDirectory(const wchar_t *Name,int Wipe) { ProcessedItems++; string strFullName; ConvertNameToFull(Name,strFullName); for (;;) { if (Wipe) { if (WipeDirectory(Name)) break; } else if (apiRemoveDirectory(Name)) break; int MsgCode; if (SkipFoldersMode!=-1) MsgCode=SkipFoldersMode; else { MsgCode=Message(MSG_WARNING|MSG_ERRORTYPE,4,MSG(MError), MSG(MCannotDeleteFolder),Name,MSG(MDeleteRetry), MSG(MDeleteSkip),MSG(MDeleteFileSkipAll),MSG(MDeleteCancel)); } switch (MsgCode) { case -1: case -2: case 3: return DELETE_CANCEL; case 1: return DELETE_SKIP; case 2: SkipFoldersMode=2; return DELETE_SKIP; } } return DELETE_SUCCESS; }
bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath) { char *Name=ConvertPath(CheckName,NULL); char FullName[NM],*CurName; *FullName=0; Args->Rewind(); while ((CurName=Args->GetString())!=NULL) #ifndef SFX_MODULE if (CheckFullPath && IsFullPath(CurName)) { if (*FullName==0) ConvertNameToFull(CheckName,FullName); if (CmpName(CurName,FullName,MATCH_WILDSUBPATH)) return(true); } else #endif if (CmpName(ConvertPath(CurName,NULL),Name,MATCH_WILDSUBPATH)) return(true); return(false); }
void CreatePath(const string &InputPath, bool Simple) { string Path(InputPath); ConvertNameToFull(InputPath, Path); size_t DirOffset = 0; ParsePath(Path, &DirOffset); string Part; Part.reserve(Path.size()); for (size_t i = DirOffset; i <= Path.size(); ++i) { if (i == Path.size() || IsSlash(Path[i])) { Part = Path.substr(0, i); if (!api::fs::exists(Part)) { if(api::CreateDirectory(Part, nullptr) && !Simple) TreeList::AddTreeName(Part); } } } }
static void InitProfile(string &strProfilePath, string &strLocalProfilePath) { if (Global->Opt->ReadOnlyConfig < 0) // do not override 'far /ro', 'far /ro-' Global->Opt->ReadOnlyConfig = GetFarIniInt(L"General"s, L"ReadOnlyConfig"s, 0); if (!strProfilePath.empty()) { strProfilePath = ConvertNameToFull(unquote(os::env::expand(strProfilePath))); } if (!strLocalProfilePath.empty()) { strLocalProfilePath = ConvertNameToFull(unquote(os::env::expand(strLocalProfilePath))); } if (strProfilePath.empty()) { const auto UseSystemProfiles = GetFarIniInt(L"General"s, L"UseSystemProfiles"s, 1); if (UseSystemProfiles) { const auto& GetShellProfilePath = [](int Idl) { wchar_t Buffer[MAX_PATH]; SHGetFolderPath(nullptr, Idl | (Global->Opt->ReadOnlyConfig? 0 : CSIDL_FLAG_CREATE), nullptr, SHGFP_TYPE_CURRENT, Buffer); return path::join(Buffer, L"Far Manager"sv, L"Profile"sv); }; // roaming data default path: %APPDATA%\Far Manager\Profile Global->Opt->ProfilePath = GetShellProfilePath(CSIDL_APPDATA); Global->Opt->LocalProfilePath = UseSystemProfiles == 2? Global->Opt->ProfilePath : // local data default path: %LOCALAPPDATA%\Far Manager\Profile GetShellProfilePath(CSIDL_LOCAL_APPDATA); } else { const auto strUserProfileDir = GetFarIniString(L"General"s, L"UserProfileDir"s, path::join(L"%FARHOME%"sv, L"Profile"sv)); const auto strUserLocalProfileDir = GetFarIniString(L"General"s, L"UserLocalProfileDir"s, strUserProfileDir); Global->Opt->ProfilePath = ConvertNameToFull(unquote(os::env::expand(strUserProfileDir))); Global->Opt->LocalProfilePath = ConvertNameToFull(unquote(os::env::expand(strUserLocalProfileDir))); } } else { Global->Opt->ProfilePath = strProfilePath; Global->Opt->LocalProfilePath = !strLocalProfilePath.empty()? strLocalProfilePath : strProfilePath; } Global->Opt->LoadPlug.strPersonalPluginsPath = path::join(Global->Opt->ProfilePath, L"Plugins"sv); os::env::set(L"FARPROFILE"sv, Global->Opt->ProfilePath); os::env::set(L"FARLOCALPROFILE"sv, Global->Opt->LocalProfilePath); if (!Global->Opt->ReadOnlyConfig) { CreatePath(path::join(Global->Opt->ProfilePath, L"PluginsData"sv), true); if (Global->Opt->LocalProfilePath != Global->Opt->ProfilePath) CreatePath(path::join(Global->Opt->LocalProfilePath, L"PluginsData"sv), true); } }
bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode) { char *Name=ConvertPath(CheckName,NULL); char FullName[NM]; char CurMask[NM+1]; // We reserve the space to append "*" to mask. *FullName=0; Args->Rewind(); while (Args->GetString(CurMask,ASIZE(CurMask)-1)) { char *LastMaskChar=PointToLastChar(CurMask); bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. if (Dir) { // CheckName is a directory. if (DirMask) { // We process the directory and have the directory exclusion mask. // So let's convert "mask\" to "mask" and process it normally. *LastMaskChar=0; } else { // If mask has wildcards in name part and does not have the trailing // '\' character, we cannot use it for directories. if (IsWildcard(PointToName(CurMask))) continue; } } else { // If we process a file inside of directory excluded by "dirmask\". // we want to exclude such file too. So we convert "dirmask\" to // "dirmask\*". It is important for operations other than archiving. // When archiving, directory matched by "dirmask\" is excluded // from further scanning. if (DirMask) strcat(CurMask,"*"); } #ifndef SFX_MODULE if (CheckFullPath && IsFullPath(CurMask)) { // We do not need to do the special "*\" processing here, because // onlike the "else" part of this "if", now we convert names to full // format, so they all include the path, which is matched by "*\" // correctly. Moreover, removing "*\" from mask would break // the comparison, because now all names have the path. if (*FullName==0) ConvertNameToFull(CheckName,FullName); if (CmpName(CurMask,FullName,MatchMode)) return(true); } else #endif { char NewName[NM+2],*CurName=Name; if (CurMask[0]=='*' && IsPathDiv(CurMask[1])) { // We want "*\name" to match 'name' not only in subdirectories, // but also in the current directory. We convert the name // from 'name' to '.\name' to be matched by "*\" part even if it is // in current directory. NewName[0]='.'; NewName[1]=CPATHDIVIDER; strncpyz(NewName+2,Name,ASIZE(NewName)-2); CurName=NewName; } if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode)) return(true); } } return(false); }
void ShellDelete(Panel *SrcPanel,int Wipe) { ChangePriority ChPriority(Opt.DelThreadPriority); TPreRedrawFuncGuard preRedrawFuncGuard(PR_ShellDeleteMsg); FAR_FIND_DATA_EX FindData; string strDeleteFilesMsg; string strSelName; string strSelShortName; string strDizName; string strFullName; DWORD FileAttr; int SelCount,UpdateDiz; int DizPresent; int Ret; BOOL NeedUpdate=TRUE, NeedSetUpADir=FALSE; int Opt_DeleteToRecycleBin=Opt.DeleteToRecycleBin; /*& 31.05.2001 OT Запретить перерисовку текущего фрейма*/ Frame *FrameFromLaunched=FrameManager->GetCurrentFrame(); FrameFromLaunched->Lock(); DeleteAllFolders=!Opt.Confirm.DeleteFolder; UpdateDiz=(Opt.Diz.UpdateMode==DIZ_UPDATE_ALWAYS || (SrcPanel->IsDizDisplayed() && Opt.Diz.UpdateMode==DIZ_UPDATE_IF_DISPLAYED)); if (!(SelCount=SrcPanel->GetSelCount())) goto done; // Удаление в корзину только для FIXED-дисков { string strRoot; // char FSysNameSrc[NM]; SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); ConvertNameToFull(strSelName, strRoot); GetPathRoot(strRoot,strRoot); //_SVS(SysLog(L"Del: SelName='%s' Root='%s'",SelName,Root)); if (Opt.DeleteToRecycleBin && FAR_GetDriveType(strRoot) != DRIVE_FIXED) Opt.DeleteToRecycleBin=0; } if (SelCount==1) { SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); if (TestParentFolderName(strSelName) || strSelName.IsEmpty()) { NeedUpdate=FALSE; goto done; } strDeleteFilesMsg = strSelName; } else { // в зависимости от числа ставим нужное окончание const wchar_t *Ends; wchar_t StrItems[16]; _itow(SelCount,StrItems,10); Ends=MSG(MAskDeleteItemsA); int LenItems=StrLength(StrItems); if (LenItems > 0) { if ((LenItems >= 2 && StrItems[LenItems-2] == L'1') || StrItems[LenItems-1] >= L'5' || StrItems[LenItems-1] == L'0') Ends=MSG(MAskDeleteItemsS); else if (StrItems[LenItems-1] == L'1') Ends=MSG(MAskDeleteItems0); } strDeleteFilesMsg.Format(MSG(MAskDeleteItems),SelCount,Ends); } Ret=1; // Обработка "удаления" линков if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT) && SelCount==1) { string strJuncName; ConvertNameToFull(strSelName,strJuncName); if (GetReparsePointInfo(strJuncName, strJuncName)) // ? SelName ? { NormalizeSymlinkName(strJuncName); //SetMessageHelp(L"DeleteLink"); string strAskDeleteLink=MSG(MAskDeleteLink); DWORD dwAttr=apiGetFileAttributes(strJuncName); if (dwAttr!=INVALID_FILE_ATTRIBUTES) { strAskDeleteLink+=L" "; strAskDeleteLink+=dwAttr&FILE_ATTRIBUTE_DIRECTORY?MSG(MAskDeleteLinkFolder):MSG(MAskDeleteLinkFile); } Ret=Message(0,3,MSG(MDeleteLinkTitle), strDeleteFilesMsg, strAskDeleteLink, strJuncName, MSG(MDeleteLinkDelete),MSG(MDeleteLinkUnlink),MSG(MCancel)); if (Ret == 1) { ConvertNameToFull(strSelName, strJuncName); if (Opt.Confirm.Delete) { ; // ;-% } if ((NeedSetUpADir=CheckUpdateAnotherPanel(SrcPanel,strSelName)) != -1) //JuncName? { DeleteReparsePoint(strJuncName); ShellUpdatePanels(SrcPanel,NeedSetUpADir); } goto done; } if (Ret ) goto done; } } if (Ret && (Opt.Confirm.Delete || SelCount>1 || (FileAttr & FILE_ATTRIBUTE_DIRECTORY))) { const wchar_t *DelMsg; const wchar_t *TitleMsg=MSG(Wipe?MDeleteWipeTitle:MDeleteTitle); /* $ 05.01.2001 IS ! Косметика в сообщениях - разные сообщения в зависимости от того, какие и сколько элементов выделено. */ BOOL folder=(FileAttr & FILE_ATTRIBUTE_DIRECTORY); if (SelCount==1) { if (Wipe && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(folder?MAskWipeFolder:MAskWipeFile); else { if (Opt.DeleteToRecycleBin && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(folder?MAskDeleteRecycleFolder:MAskDeleteRecycleFile); else DelMsg=MSG(folder?MAskDeleteFolder:MAskDeleteFile); } } else { if (Wipe && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) { DelMsg=MSG(MAskWipe); TitleMsg=MSG(MDeleteWipeTitle); } else if (Opt.DeleteToRecycleBin && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(MAskDeleteRecycle); else DelMsg=MSG(MAskDelete); } SetMessageHelp(L"DeleteFile"); if (Message(0,2,TitleMsg,DelMsg,strDeleteFilesMsg,MSG(Wipe?MDeleteWipe:Opt.DeleteToRecycleBin?MDeleteRecycle:MDelete),MSG(MCancel))) { NeedUpdate=FALSE; goto done; } } if (Opt.Confirm.Delete && SelCount>1) { //SaveScreen SaveScr; SetCursorType(FALSE,0); SetMessageHelp(L"DeleteFile"); if (Message(MSG_WARNING,2,MSG(Wipe?MWipeFilesTitle:MDeleteFilesTitle),MSG(Wipe?MAskWipe:MAskDelete), strDeleteFilesMsg,MSG(MDeleteFileAll),MSG(MDeleteFileCancel))) { NeedUpdate=FALSE; goto done; } } if (UpdateDiz) SrcPanel->ReadDiz(); SrcPanel->GetDizName(strDizName); DizPresent=(!strDizName.IsEmpty() && apiGetFileAttributes(strDizName)!=INVALID_FILE_ATTRIBUTES); DeleteTitle = new ConsoleTitle(MSG(MDeletingTitle)); if ((NeedSetUpADir=CheckUpdateAnotherPanel(SrcPanel,strSelName)) == -1) goto done; if (SrcPanel->GetType()==TREE_PANEL) FarChDir(L"\\"); { TaskBar TB; wakeful W; bool Cancel=false; //SaveScreen SaveScr; SetCursorType(FALSE,0); ReadOnlyDeleteMode=-1; SkipMode=-1; SkipWipeMode=-1; SkipFoldersMode=-1; ULONG ItemsCount=0; ProcessedItems=0; if (Opt.DelOpt.DelShowTotal) { SrcPanel->GetSelName(nullptr,FileAttr); DWORD StartTime=GetTickCount(); bool FirstTime=true; while (SrcPanel->GetSelName(&strSelName,FileAttr,&strSelShortName) && !Cancel) { if (!(FileAttr&FILE_ATTRIBUTE_REPARSE_POINT)) { if (FileAttr&FILE_ATTRIBUTE_DIRECTORY) { DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout || FirstTime) { StartTime=CurTime; FirstTime=false; if (CheckForEscSilent() && ConfirmAbortOp()) { Cancel=true; break; } ShellDeleteMsg(strSelName,Wipe,-1); } ULONG CurrentFileCount,CurrentDirCount,ClusterSize; UINT64 FileSize,CompressedFileSize,RealSize; if (GetDirInfo(nullptr,strSelName,CurrentDirCount,CurrentFileCount,FileSize,CompressedFileSize,RealSize,ClusterSize,-1,nullptr,0)>0) { ItemsCount+=CurrentFileCount+CurrentDirCount+1; } else { Cancel=true; } } else { ItemsCount++; } } } } SrcPanel->GetSelName(nullptr,FileAttr); DWORD StartTime=GetTickCount(); bool FirstTime=true; while (SrcPanel->GetSelName(&strSelName,FileAttr,&strSelShortName) && !Cancel) { int Length=(int)strSelName.GetLength(); if (!Length || (strSelName.At(0)==L'\\' && Length<2) || (strSelName.At(1)==L':' && Length<4)) continue; DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout || FirstTime) { StartTime=CurTime; FirstTime=false; if (CheckForEscSilent() && ConfirmAbortOp()) { Cancel=true; break; } ShellDeleteMsg(strSelName,Wipe,Opt.DelOpt.DelShowTotal?(ItemsCount?(ProcessedItems*100/ItemsCount):0):-1); } if (FileAttr & FILE_ATTRIBUTE_DIRECTORY) { if (!DeleteAllFolders) { ConvertNameToFull(strSelName, strFullName); if (TestFolder(strFullName) == TSTFLD_NOTEMPTY) { int MsgCode=0; // для symlink`а не нужно подтверждение if (!(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) MsgCode=Message(MSG_WARNING,4,MSG(Wipe?MWipeFolderTitle:MDeleteFolderTitle), MSG(Wipe?MWipeFolderConfirm:MDeleteFolderConfirm),strFullName, MSG(Wipe?MDeleteFileWipe:MDeleteFileDelete),MSG(MDeleteFileAll), MSG(MDeleteFileSkip),MSG(MDeleteFileCancel)); if (MsgCode<0 || MsgCode==3) { NeedSetUpADir=FALSE; break; } if (MsgCode==1) DeleteAllFolders=1; if (MsgCode==2) continue; } } bool DirSymLink=(FileAttr&FILE_ATTRIBUTE_DIRECTORY && FileAttr&FILE_ATTRIBUTE_REPARSE_POINT); if (!DirSymLink && (!Opt.DeleteToRecycleBin || Wipe)) { string strFullName; ScanTree ScTree(TRUE,TRUE,FALSE); string strSelFullName; if (IsAbsolutePath(strSelName)) { strSelFullName=strSelName; } else { SrcPanel->GetCurDir(strSelFullName); AddEndSlash(strSelFullName); strSelFullName+=strSelName; } ScTree.SetFindPath(strSelFullName,L"*", 0); DWORD StartTime=GetTickCount(); while (ScTree.GetNextName(&FindData,strFullName)) { DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout) { StartTime=CurTime; if (CheckForEscSilent()) { int AbortOp = ConfirmAbortOp(); if (AbortOp) { Cancel=true; break; } } ShellDeleteMsg(strFullName,Wipe,Opt.DelOpt.DelShowTotal?(ItemsCount?(ProcessedItems*100/ItemsCount):0):-1); } if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strFullName,FILE_ATTRIBUTE_NORMAL); int MsgCode=ERemoveDirectory(strFullName,Wipe); if (MsgCode==DELETE_CANCEL) { Cancel=true; break; } else if (MsgCode==DELETE_SKIP) { ScTree.SkipDir(); continue; } TreeList::DelTreeName(strFullName); if (UpdateDiz) SrcPanel->DeleteDiz(strFullName,strSelShortName); continue; } if (!DeleteAllFolders && !ScTree.IsDirSearchDone() && TestFolder(strFullName) == TSTFLD_NOTEMPTY) { int MsgCode=Message(MSG_WARNING,4,MSG(Wipe?MWipeFolderTitle:MDeleteFolderTitle), MSG(Wipe?MWipeFolderConfirm:MDeleteFolderConfirm),strFullName, MSG(Wipe?MDeleteFileWipe:MDeleteFileDelete),MSG(MDeleteFileAll), MSG(MDeleteFileSkip),MSG(MDeleteFileCancel)); if (MsgCode<0 || MsgCode==3) { Cancel=true; break; } if (MsgCode==1) DeleteAllFolders=1; if (MsgCode==2) { ScTree.SkipDir(); continue; } } if (ScTree.IsDirSearchDone()) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strFullName,FILE_ATTRIBUTE_NORMAL); int MsgCode=ERemoveDirectory(strFullName,Wipe); if (MsgCode==DELETE_CANCEL) { Cancel=true;; break; } else if (MsgCode==DELETE_SKIP) { //ScTree.SkipDir(); continue; } TreeList::DelTreeName(strFullName); } } else { int AskCode=AskDeleteReadOnly(strFullName,FindData.dwFileAttributes,Wipe); if (AskCode==DELETE_CANCEL) { Cancel=true; break; } if (AskCode==DELETE_YES) if (ShellRemoveFile(strFullName,Wipe)==DELETE_CANCEL) { Cancel=true; break; } } } } if (!Cancel) { if (FileAttr & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strSelName,FILE_ATTRIBUTE_NORMAL); int DeleteCode; // нефига здесь выделываться, а надо учесть, что удаление // симлинка в корзину чревато потерей оригинала. if (DirSymLink || !Opt.DeleteToRecycleBin || Wipe) { DeleteCode=ERemoveDirectory(strSelName,Wipe); if (DeleteCode==DELETE_CANCEL) break; else if (DeleteCode==DELETE_SUCCESS) { TreeList::DelTreeName(strSelName); if (UpdateDiz) SrcPanel->DeleteDiz(strSelName,strSelShortName); } } else { DeleteCode=RemoveToRecycleBin(strSelName); if (!DeleteCode) Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError), MSG(MCannotDeleteFolder),strSelName,MSG(MOk)); else { TreeList::DelTreeName(strSelName); if (UpdateDiz) SrcPanel->DeleteDiz(strSelName,strSelShortName); } } } } else { int AskCode=AskDeleteReadOnly(strSelName,FileAttr,Wipe); if (AskCode==DELETE_CANCEL) break; if (AskCode==DELETE_YES) { int DeleteCode=ShellRemoveFile(strSelName,Wipe); if (DeleteCode==DELETE_SUCCESS && UpdateDiz) { SrcPanel->DeleteDiz(strSelName,strSelShortName); } if (DeleteCode==DELETE_CANCEL) break; } } } } if (UpdateDiz) if (DizPresent==(!strDizName.IsEmpty() && apiGetFileAttributes(strDizName)!=INVALID_FILE_ATTRIBUTES)) SrcPanel->FlushDiz(); delete DeleteTitle; done: Opt.DeleteToRecycleBin=Opt_DeleteToRecycleBin; // Разрешить перерисовку фрейма FrameFromLaunched->Unlock(); if (NeedUpdate) { ShellUpdatePanels(SrcPanel,NeedSetUpADir); } }
void QuickView::ShowFile(const string& FileName, bool TempFile, PluginHandle* hDirPlugin) { CloseFile(); if (!IsVisible()) return; if (FileName.empty()) { ProcessingPluginCommand++; Show(); ProcessingPluginCommand--; return; } m_CurDir = Parent()->GetAnotherPanel(this)->GetCurDir(); string FileFullName = FileName; if (!hDirPlugin) ConvertNameToFull(FileFullName, FileFullName); bool SameFile = strCurFileName == FileFullName; strCurFileName = FileFullName; size_t pos = strCurFileName.rfind(L'.'); if (pos != string::npos) { string strValue; if (GetShellType(strCurFileName.data()+pos, strValue)) { os::reg::GetValue(HKEY_CLASSES_ROOT, strValue, L"", strCurFileType); } } if (hDirPlugin || os::fs::is_directory(strCurFileName)) { // Не показывать тип файла для каталогов в "Быстром просмотре" strCurFileType.clear(); if (SameFile && !hDirPlugin) { Directory=1; } else if (hDirPlugin) { int ExitCode=GetPluginDirInfo(hDirPlugin,strCurFileName,Data.DirCount, Data.FileCount,Data.FileSize,Data.AllocationSize); Directory = (ExitCode ? 4 : 3); uncomplete_dirscan = (ExitCode == 0); } else { int ExitCode=GetDirInfo(MSG(MQuickViewTitle), strCurFileName, Data, getdirinfo_default_delay, nullptr, GETDIRINFO_ENHBREAK|GETDIRINFO_SCANSYMLINKDEF|GETDIRINFO_NOREDRAW); Directory = (ExitCode == -1 ? 2 : 1); // ExitCode: 1=done; 0=Esc,CtrlBreak; -1=Other uncomplete_dirscan = ExitCode != 1; } } else { if (!strCurFileName.empty()) { QView = std::make_unique<Viewer>(GetOwner(), true); QView->SetRestoreScreenMode(false); QView->SetPosition(m_X1+1,m_Y1+1,m_X2-1,m_Y2-3); QView->SetStatusMode(0); QView->EnableHideCursor(0); OldWrapMode = QView->GetWrapMode(); OldWrapType = QView->GetWrapType(); QView->SetWrapMode(LastWrapMode); QView->SetWrapType(LastWrapType); QView->OpenFile(strCurFileName,FALSE); } } if (this->Destroyed()) return; m_TemporaryFile = TempFile; Redraw(); if (Parent()->ActivePanel() == this) { DynamicUpdateKeyBar(); Parent()->GetKeybar().Redraw(); } }
bool CreateReparsePoint(const string& Target, const string& Object,ReparsePointTypes Type) { bool Result=false; { switch (Type) { case RP_HARDLINK: break; case RP_EXACTCOPY: Result=DuplicateReparsePoint(Target,Object); break; case RP_SYMLINK: case RP_SYMLINKFILE: case RP_SYMLINKDIR: { os::fs::file_status ObjectStatus(Object); if(Type == RP_SYMLINK) { Type = os::fs::is_directory(Target)? RP_SYMLINKDIR : RP_SYMLINKFILE; } if (imports.CreateSymbolicLinkW && !os::fs::exists(ObjectStatus)) { Result=os::fs::CreateSymbolicLink(Object,Target,Type==RP_SYMLINKDIR?SYMBOLIC_LINK_FLAG_DIRECTORY:0); } else { const auto ObjectCreated = Type==RP_SYMLINKDIR? os::fs::is_directory(ObjectStatus) || os::fs::create_directory(Object) : os::fs::is_file(ObjectStatus) || os::fs::file(Object, 0, 0, nullptr, CREATE_NEW); if (ObjectCreated) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK; const auto& strPrintName = Target; auto strSubstituteName = Target; if (IsAbsolutePath(Target)) { strSubstituteName = KernelPath(NTPath(strSubstituteName)); rdb->SymbolicLinkReparseBuffer.Flags=0; } else { rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE; } if (FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { Result=SetREPARSE_DATA_BUFFER(Object,rdb.get()); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } } } break; case RP_JUNCTION: case RP_VOLMOUNT: { const auto strPrintName = ConvertNameToFull(Target); auto strSubstituteName = KernelPath(NTPath(strPrintName)); block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; if (FillREPARSE_DATA_BUFFER(rdb.get(), strPrintName, strSubstituteName)) { Result=SetREPARSE_DATA_BUFFER(Object,rdb.get()); } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } break; } } return Result; }
// Косметические преобразования строки пути. // CheckFullPath используется в FCTL_SET[ANOTHER]PANELDIR void PrepareDiskPath(string &strPath, bool CheckFullPath) { // elevation not required during cosmetic operation SCOPED_ACTION(elevation::suppress); if (!strPath.empty()) { if (strPath.size() > 1 && (strPath[1]==L':' || (IsSlash(strPath[0]) && IsSlash(strPath[1])))) { ReplaceSlashToBackslash(strPath); bool DoubleSlash = strPath[1]==L'\\'; while(ReplaceStrings(strPath, L"\\\\"sv, L"\\"sv)) ; if(DoubleSlash) { strPath = L'\\' + strPath; } if (CheckFullPath) { strPath = ConvertNameToFull(strPath); size_t DirOffset = 0; const auto Type = ParsePath(strPath, &DirOffset); if (Type == root_type::unknown && HasPathPrefix(strPath)) { DirOffset = 4; } size_t StartPos = DirOffset; if (StartPos < strPath.size()) { string TmpStr; TmpStr.reserve(strPath.size()); size_t LastPos = StartPos; const auto EndsWithSlash = IsSlash(strPath.back()); for (size_t i = StartPos; i <= strPath.size(); ++i) { if ((i < strPath.size() && IsSlash(strPath[i])) || (i == strPath.size() && !EndsWithSlash)) { TmpStr.assign(strPath, 0, i); os::fs::find_data fd; if (os::fs::get_find_data(TmpStr, fd)) { strPath.replace(LastPos, i - LastPos, fd.FileName); i += fd.FileName.size() - (i - LastPos); } if (i != strPath.size()) { LastPos = i + 1; } } } } } if (ParsePath(strPath) == root_type::drive_letter) { strPath[0] = upper(strPath[0]); } } } }
int FarAppMain(int argc, char **argv) { Opt.IsUserAdmin = (geteuid()==0); _OT(SysLog(L"[[[[[[[[New Session of FAR]]]]]]]]]")); FARString strEditName; FARString strViewName; FARString DestNames[2]; int StartLine=-1,StartChar=-1; int CntDestName=0; // количество параметров-имен каталогов /*$ 18.04.2002 SKV Попользуем floating point что бы проинициализировался vc-ный fprtl. */ #ifdef _MSC_VER float x=1.1f; wchar_t buf[15]; swprintf(buf,L"%f",x); #endif // если под дебагером, то отключаем исключения однозначно, // иначе - смотря что указал юзвер. #if defined(_DEBUGEXC) Opt.ExceptRules=-1; #else Opt.ExceptRules=-1;//IsDebuggerPresent()?0:-1; #endif // Opt.ExceptRules=-1; #ifdef __GNUC__ Opt.ExceptRules=0; #endif //_SVS(SysLog(L"Opt.ExceptRules=%d",Opt.ExceptRules)); SetRegRootKey(HKEY_CURRENT_USER); Opt.strRegRoot = L"Software/Far2"; // По умолчанию - брать плагины из основного каталога Opt.LoadPlug.MainPluginDir=TRUE; Opt.LoadPlug.PluginsPersonal=TRUE; Opt.LoadPlug.PluginsCacheOnly=FALSE; g_strFarPath = g_strFarModuleName; bool translated = TranslateFarString<TranslateInstallPath_Bin2Share>(g_strFarPath); CutToSlash(g_strFarPath, true); if (translated) { // /usr/bin/something -> /usr/share/far2l g_strFarPath+= L"/" FAR_BASENAME; } WINPORT(SetEnvironmentVariable)(L"FARHOME", g_strFarPath); AddEndSlash(g_strFarPath); // don't inherit from parent process in any case WINPORT(SetEnvironmentVariable)(L"FARUSER", nullptr); WINPORT(SetEnvironmentVariable)(L"FARADMINMODE", Opt.IsUserAdmin?L"1":nullptr); // макросы не дисаблим Opt.Macro.DisableMacro=0; for (int I=1; I<argc; I++) { std::wstring arg_w = MB2Wide(argv[I]); if ((arg_w[0]==L'/' || arg_w[0]==L'-') && arg_w[1]) { switch (Upper(arg_w[1])) { case L'A': switch (Upper(arg_w[2])) { case 0: Opt.CleanAscii=TRUE; break; case L'G': if (!arg_w[3]) Opt.NoGraphics=TRUE; break; } break; case L'E': if (iswdigit(arg_w[2])) { StartLine=_wtoi((const wchar_t *)&arg_w[2]); wchar_t *ChPtr=wcschr((wchar_t *)&arg_w[2],L':'); if (ChPtr) StartChar=_wtoi(ChPtr+1); } if (I+1<argc) { strEditName = argv[I+1]; I++; } break; case L'V': if (I+1<argc) { strViewName = argv[I+1]; I++; } break; case L'M': switch (Upper(arg_w[2])) { case 0: Opt.Macro.DisableMacro|=MDOL_ALL; break; case L'A': if (!arg_w[3]) Opt.Macro.DisableMacro|=MDOL_AUTOSTART; break; } break; case L'I': Opt.SmallIcon=TRUE; break; case L'X': Opt.ExceptRules=0; #if defined(_DEBUGEXC) if (Upper(arg_w[2])==L'D' && !arg_w[3]) Opt.ExceptRules=1; #endif break; case L'C': if (Upper(arg_w[2])==L'O' && !arg_w[3]) { Opt.LoadPlug.PluginsCacheOnly=TRUE; Opt.LoadPlug.PluginsPersonal=FALSE; } break; case L'?': case L'H': ControlObject::ShowCopyright(1); show_help(); return 0; #ifdef DIRECT_RT case L'D': if (Upper(arg_w[2])==L'O' && !arg_w[3]) DirectRT=1; break; #endif case L'W': { Opt.WindowMode=TRUE; } break; } } else // простые параметры. Их может быть max две штукА. { if (CntDestName < 2) { if (IsPluginPrefixPath((const wchar_t *)arg_w.c_str())) { DestNames[CntDestName++] = (const wchar_t *)arg_w.c_str(); } else { apiExpandEnvironmentStrings((const wchar_t *)arg_w.c_str(), DestNames[CntDestName]); Unquote(DestNames[CntDestName]); ConvertNameToFull(DestNames[CntDestName],DestNames[CntDestName]); if (apiGetFileAttributes(DestNames[CntDestName]) != INVALID_FILE_ATTRIBUTES) CntDestName++; //??? } } } } //Настройка OEM сортировки. Должна быть после CopyGlobalSettings и перед InitKeysArray! //LocalUpperInit(); //InitLCIDSort(); //Инициализация массива клавиш. Должна быть после CopyGlobalSettings! InitKeysArray(); //WaitForInputIdle(GetCurrentProcess(),0); std::set_new_handler(nullptr); if (!Opt.LoadPlug.MainPluginDir) //если есть ключ /p то он отменяет /co Opt.LoadPlug.PluginsCacheOnly=FALSE; if (Opt.LoadPlug.PluginsCacheOnly) { Opt.LoadPlug.strCustomPluginsPath.Clear(); Opt.LoadPlug.MainPluginDir=FALSE; Opt.LoadPlug.PluginsPersonal=FALSE; } InitConsole(); GetRegKey(L"Language",L"Main",Opt.strLanguage,L"English"); if (!Lang.Init(g_strFarPath,true,MNewFileName)) { ControlObject::ShowCopyright(1); LPCWSTR LngMsg; switch(Lang.GetLastError()) { case LERROR_BAD_FILE: LngMsg = L"\nError: language data is incorrect or damaged.\n\nPress any key to exit..."; break; case LERROR_FILE_NOT_FOUND: LngMsg = L"\nError: cannot find language data.\n\nPress any key to exit..."; break; default: LngMsg = L"\nError: cannot load language data.\n\nPress any key to exit..."; break; } Console.Write(LngMsg,StrLength(LngMsg)); Console.FlushInputBuffer(); WaitKey(); // А стоит ли ожидать клавишу??? Стоит return 1; } WINPORT(SetEnvironmentVariable)(L"FARLANG",Opt.strLanguage); SetHighlighting(); initMacroVarTable(1); if (Opt.ExceptRules == -1) { GetRegKey(L"System",L"ExceptRules",Opt.ExceptRules,1); } //ErrorMode=SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX|(Opt.ExceptRules?SEM_NOGPFAULTERRORBOX:0)|(GetRegKey(L"System/Exception", L"IgnoreDataAlignmentFaults", 0)?SEM_NOALIGNMENTFAULTEXCEPT:0); //SetErrorMode(ErrorMode); int Result=MainProcessSEH(strEditName,strViewName,DestNames[0],DestNames[1],StartLine,StartChar); EmptyInternalClipboard(); doneMacroVarTable(1); VTShell_Shutdown();//ensure VTShell deinitialized before statics destructors called _OT(SysLog(L"[[[[[Exit of FAR]]]]]]]]]")); return Result; }
void ShellMakeDir(Panel *SrcPanel) { FarList ComboList={sizeof(FarList)}; FarListItem LinkTypeItems[3]={}; ComboList.ItemsNumber=ARRAYSIZE(LinkTypeItems); ComboList.Items=LinkTypeItems; ComboList.Items[0].Text=MSG(MMakeFolderLinkNone); ComboList.Items[1].Text=MSG(MMakeFolderLinkJunction); ComboList.Items[2].Text=MSG(MMakeFolderLinkSymlink); ComboList.Items[0].Flags|=LIF_SELECTED; #if 1 //Maximus: поддержка "узких" дисплеев if (ScrX < 10) { _ASSERTE(ScrX>=10); return; } int BorderW = (72<(ScrX-1))?72:(ScrX-1); // 72 int ElemW = BorderW - 2; // 70 #endif FarDialogItem MkDirDlgData[]= { #if 1 //Maximus: поддержка "узких" дисплеев {DI_DOUBLEBOX,3,1,BorderW,10,0,nullptr,nullptr,0,MSG(MMakeFolderTitle)}, #else {DI_DOUBLEBOX,3,1,72,10,0,nullptr,nullptr,0,MSG(MMakeFolderTitle)}, #endif {DI_TEXT, 5,2, 0,2,0,nullptr,nullptr,0,MSG(MCreateFolder)}, #if 1 //Maximus: поддержка "узких" дисплеев {DI_EDIT, 5,3,ElemW,3,0,L"NewFolder",nullptr,DIF_FOCUS|DIF_EDITEXPAND|DIF_HISTORY|DIF_USELASTHISTORY|DIF_EDITPATH,L""}, #else {DI_EDIT, 5,3,70,3,0,L"NewFolder",nullptr,DIF_FOCUS|DIF_EDITEXPAND|DIF_HISTORY|DIF_USELASTHISTORY|DIF_EDITPATH,L""}, #endif {DI_TEXT, -1,4, 0,4,0,nullptr,nullptr,DIF_SEPARATOR,L""}, {DI_TEXT, 5,5, 0,5,0,nullptr,nullptr,0,MSG(MMakeFolderLinkType)}, #if 1 //Maximus: поддержка "узких" дисплеев {DI_COMBOBOX,20,5,ElemW,5,0,nullptr,nullptr,DIF_DROPDOWNLIST|DIF_LISTNOAMPERSAND|DIF_LISTWRAPMODE,L""}, #else {DI_COMBOBOX,20,5,70,5,0,nullptr,nullptr,DIF_DROPDOWNLIST|DIF_LISTNOAMPERSAND|DIF_LISTWRAPMODE,L""}, #endif {DI_TEXT, 5,6, 0,6,0,nullptr,nullptr,0,MSG(MMakeFolderLinkTarget)}, #if 1 //Maximus: поддержка "узких" дисплеев {DI_EDIT, 20,6,ElemW,6,0,L"NewFolderLinkTarget",nullptr,DIF_DISABLE|DIF_EDITEXPAND|DIF_HISTORY|DIF_USELASTHISTORY|DIF_EDITPATH,L""}, #else {DI_EDIT, 20,6,70,6,0,L"NewFolderLinkTarget",nullptr,DIF_DISABLE|DIF_EDITEXPAND|DIF_HISTORY|DIF_USELASTHISTORY|DIF_EDITPATH,L""}, #endif {DI_CHECKBOX, 5,7, 0,7,Global->Opt->MultiMakeDir,nullptr,nullptr,0,MSG(MMultiMakeDir)}, {DI_TEXT, -1,8, 0,8,0,nullptr,nullptr,DIF_SEPARATOR,L""}, {DI_BUTTON, 0,9, 0,9,0,nullptr,nullptr,DIF_DEFAULTBUTTON|DIF_CENTERGROUP,MSG(MOk)}, {DI_BUTTON, 0,9, 0,9,0,nullptr,nullptr,DIF_CENTERGROUP,MSG(MCancel)}, }; auto MkDirDlg = MakeDialogItemsEx(MkDirDlgData); MkDirDlg[MKDIR_COMBOBOX_LINKTYPE].ListItems=&ComboList; std::vector<string> DirList; auto Dlg = Dialog::create(MkDirDlg, MkDirDlgProc, &DirList); #if 1 //Maximus: поддержка "узких" дисплеев Dlg->SetPosition(-1,-1,BorderW+4,12); #else Dlg->SetPosition(-1,-1,76,12); #endif Dlg->SetHelp(L"MakeFolder"); Dlg->SetId(MakeFolderId); Dlg->Process(); if (Dlg->GetExitCode()==MKDIR_OK) { string strDirName=MkDirDlg[MKDIR_EDIT].strData; string strOriginalDirName; bool SkipAll = false; FOR(const auto& i, DirList) { // TODO: almost the same code in dirmix::CreatePath() strDirName = i; strOriginalDirName = strDirName; ConvertNameToFull(strDirName, strDirName); DeleteEndSlash(strDirName); bool bSuccess = false; size_t DirOffset = 0; ParsePath(strDirName, &DirOffset); string Part; Part.reserve(strDirName.size()); for (size_t j = DirOffset; j <= strDirName.size(); ++j) { if (j == strDirName.size() || IsSlash(strDirName[j])) { Part = strDirName.substr(0, j); if (!os::fs::exists(Part) || j == strDirName.size()) // skip all intermediate dirs, but not last. { while(!(bSuccess=(os::CreateDirectory(Part, nullptr)!=FALSE)) && !SkipAll) { Global->CatchError(); int Ret = OperationFailed(strOriginalDirName, MError, MSG(MCannotCreateFolder)); if(Ret == 1) // skip { break; } else if(Ret == 2) { SkipAll = true; break; } else if (Ret < 0 || Ret == 3) // cancel { return; } } if(bSuccess) { TreeList::AddTreeName(Part); } } } } if (bSuccess) { if(MkDirDlg[MKDIR_COMBOBOX_LINKTYPE].ListPos) { string strTarget=MkDirDlg[MKDIR_EDIT_LINKPATH].strData; Unquote(strTarget); while(!CreateReparsePoint(strTarget, strDirName, MkDirDlg[MKDIR_COMBOBOX_LINKTYPE].ListPos==1?RP_JUNCTION:RP_SYMLINKDIR) && !SkipAll) { Global->CatchError(); int Ret = OperationFailed(strDirName, MError, MSG(MCopyCannotCreateLink)); if(Ret == 1) // skip { break; } else if(Ret == 2) { SkipAll = true; break; } else if (Ret < 0 || Ret == 3) // cancel { return; } } } } }
// Кусок для создания SymLink для каталогов. int MkSymLink(const string& Target, const string& LinkName, ReparsePointTypes LinkType, bool Silent, bool HoldTarget) { if (!Target.empty() && !LinkName.empty()) { string strFullTarget; // выделим имя auto strSelOnlyName = Target; DeleteEndSlash(strSelOnlyName); const auto SlashPos = FindLastSlash(strSelOnlyName); const auto symlink = LinkType==RP_SYMLINK || LinkType==RP_SYMLINKFILE || LinkType==RP_SYMLINKDIR; if (Target[1] == L':' && (!Target[2] || (IsSlash(Target[2]) && !Target[3]))) // C: или C:/ { // if(Flags&FCOPY_VOLMOUNT) { strFullTarget = Target; AddEndSlash(strFullTarget); } /* Вот здесь - ну очень умное поведение! Т.е. если в качестве SelName передали "C:", то в этом куске происходит коррекция типа линка - с symlink`а на volmount */ LinkType=RP_VOLMOUNT; } else strFullTarget = ConvertNameToFull(Target); auto strFullLink = ConvertNameToFull(LinkName); if (IsSlash(strFullLink.back())) { if (LinkType != RP_VOLMOUNT) { const auto SelName = SlashPos != string::npos? string_view(strSelOnlyName).substr(SlashPos + 1) : string_view(strSelOnlyName); append(strFullLink, SelName); } else { append(strFullLink, L"Disk_"sv, Target.front()); } } if (LinkType==RP_VOLMOUNT) { AddEndSlash(strFullTarget); AddEndSlash(strFullLink); } if (symlink) { // в этом случае создается путь, но не сам каталог string strPath=strFullLink; if (CutToSlash(strPath)) { if (!os::fs::exists(strPath)) CreatePath(strPath); } } else { bool CreateDir=true; if (LinkType==RP_EXACTCOPY) { // в этом случае создается или каталог, или пустой файл if (os::fs::is_file(strFullTarget)) CreateDir=false; } if (CreateDir) { if (os::fs::create_directory(strFullLink)) TreeList::AddTreeName(strFullLink); else CreatePath(strFullLink); } else { string strPath=strFullLink; if (CutToSlash(strPath)) { if (!os::fs::exists(strPath)) CreatePath(strPath); os::fs::file(strFullLink, 0, 0, nullptr, CREATE_NEW, os::fs::get_file_attributes(strFullTarget)); } } if (!os::fs::exists(strFullLink)) { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { msg(lng::MCopyCannotCreateLink), strFullLink }, { lng::MOk }); } return 0; } } if (LinkType!=RP_VOLMOUNT) { if (CreateReparsePoint(HoldTarget && symlink ? Target : strFullTarget, strFullLink, LinkType)) { return 1; } else { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { msg(lng::MCopyCannotCreateLink), strFullLink }, { lng::MOk }); } return 0; } } else { if (CreateVolumeMountPoint(strFullTarget,strFullLink)) { return 1; } else { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { format(msg(lng::MCopyMountVolFailed), Target), format(msg(lng::MCopyMountVolFailed2), strFullLink) }, { lng::MOk }); } return 0; } } } return 2; }