Esempio n. 1
0
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);
		}
	}
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
string ConvertNameToLong(string_view const Object)
{
	string strDest;
	if (!os::fs::GetLongPathName(null_terminated(Object).c_str(), strDest))
	{
		assign(strDest, Object);

		if (!HasPathPrefix(Object))
		{
			if (os::fs::GetLongPathName(NTPath(Object), strDest))
			{
				switch (ParsePath(strDest))
				{
				case root_type::unc_drive_letter:
					strDest.erase(0, 4); // \\?\X:\path -> X:\path
					break;

				case root_type::unc_remote:
					strDest.erase(2, 6); // \\?\UNC\server -> \\server
					break;

				default:
					// should never happen
					break;
				}
			}
		}
	}
	return strDest;
}
Esempio n. 4
0
bool CutToSlash(string &strStr, bool bInclude)
{
	size_t pos;

	if (FindLastSlash(pos,strStr))
	{
		if (pos==3 && HasPathPrefix(strStr))
			return false;

		if (bInclude)
			strStr.SetLength(pos);
		else
			strStr.SetLength(pos+1);

		return true;
	}

	return false;
}
Esempio n. 5
0
void ShellMakeDir(Panel *SrcPanel)
{
	string strDirName;
	string strOriginalDirName;
	wchar_t *lpwszDirName;
	UserDefinedList DirList(0,0,ULF_UNIQUE);
	DialogDataEx MkDirDlgData[]=
	{
		DI_DOUBLEBOX,3,1,72,8,0,0,MSG(MMakeFolderTitle),
		DI_TEXT,     5,2, 0,2,0,0,MSG(MCreateFolder),
		DI_EDIT,     5,3,70,3,(DWORD_PTR)L"NewFolder",DIF_FOCUS|DIF_EDITEXPAND|DIF_HISTORY|DIF_USELASTHISTORY|DIF_EDITPATH,L"",
		DI_TEXT,     0,4, 0,4,0,DIF_SEPARATOR,L"",
		DI_CHECKBOX, 5,5, 0,5,Opt.MultiMakeDir,0,MSG(MMultiMakeDir),
		DI_TEXT,     0,6, 0,6,0,DIF_SEPARATOR,L"",
		DI_BUTTON,   0,7, 0,7,0,DIF_DEFAULT|DIF_CENTERGROUP,MSG(MOk),
		DI_BUTTON,   0,7, 0,7,0,DIF_CENTERGROUP,MSG(MCancel),
	};
	MakeDialogItemsEx(MkDirDlgData,MkDirDlg);
	Dialog Dlg(MkDirDlg,ARRAYSIZE(MkDirDlg),MkDirDlgProc,reinterpret_cast<LONG_PTR>(&DirList));
	Dlg.SetPosition(-1,-1,76,10);
	Dlg.SetHelp(L"MakeFolder");
	Dlg.SetId(MakeFolderId);
	Dlg.Process();

	if (Dlg.GetExitCode()==MKDIR_OK)
	{
		strDirName=MkDirDlg[MKDIR_EDIT].strData;
		const wchar_t *OneDir;
		DirList.Reset();

		while (nullptr!=(OneDir=DirList.GetNext()))
		{
			strDirName = OneDir;
			strOriginalDirName = strDirName;

			//Unquote(DirName);
			if (Opt.CreateUppercaseFolders && !IsCaseMixed(strDirName))
				strDirName.Upper();

			DeleteEndSlash(strDirName,true);
			lpwszDirName = strDirName.GetBuffer();
			bool bSuccess = false;

			if(HasPathPrefix(lpwszDirName))
			{
				lpwszDirName += 4;
			}
			for (wchar_t *ChPtr=lpwszDirName; *ChPtr; ChPtr++)
			{
				if (IsSlash(*ChPtr))
				{
					WCHAR Ch = ChPtr[1];
					ChPtr[1] = 0;

					if (*lpwszDirName &&
						(apiGetFileAttributes(lpwszDirName) == INVALID_FILE_ATTRIBUTES) &&
						apiCreateDirectory(lpwszDirName,nullptr))
					{
						TreeList::AddTreeName(lpwszDirName);
						bSuccess = true;
					}

					ChPtr[1] = Ch;
				}
			}

			strDirName.ReleaseBuffer();
			BOOL bSuccess2;
			bool bSkip=false;

			while (!(bSuccess2=apiCreateDirectory(strDirName,nullptr)))
			{
				int LastError=GetLastError();

				if (LastError==ERROR_ALREADY_EXISTS || LastError==ERROR_BAD_PATHNAME ||
				        LastError==ERROR_INVALID_NAME || LastError == ERROR_DIRECTORY)
				{
					int ret;

					if (DirList.IsEmpty())
						ret=Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError),MSG(MCannotCreateFolder),strOriginalDirName,MSG(MCancel));
					else
						ret=Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MError),MSG(MCannotCreateFolder),strOriginalDirName,MSG(MOk),MSG(MSkip));

					bSkip = ret==1;

					if (bSuccess || bSkip)
						break;
					else
						return;
				}
				else
				{
					int ret;

					if (DirList.IsEmpty())
					{
						ret=Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MError),MSG(MCannotCreateFolder),strOriginalDirName,MSG(MRetry),MSG(MCancel));
					}
					else
					{
						ret=Message(MSG_WARNING|MSG_ERRORTYPE,3,MSG(MError),MSG(MCannotCreateFolder),strOriginalDirName,MSG(MRetry),MSG(MSkip),MSG(MCancel));
						bSkip = ret==1;
					}

					if (ret)
					{
						if (bSuccess || bSkip) break;
						else return;
					}
				}
			}

			if (bSuccess2)
				TreeList::AddTreeName(strDirName);
			else if (!bSkip)
				break;
		}

		SrcPanel->Update(UPDATE_KEEP_SELECTION);

		if (!strDirName.IsEmpty())
		{
			size_t pos;

			if (FindSlash(pos,strDirName))
				strDirName.SetLength(pos);

			if (!SrcPanel->GoToFile(strDirName) && strDirName.At(strDirName.GetLength()-1)==L'.')
			{
				strDirName.SetLength(strDirName.GetLength()-1);
				SrcPanel->GoToFile(strDirName);
			}
		}

		SrcPanel->Redraw();
		Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(SrcPanel);
		int AnotherType=AnotherPanel->GetType();

		if (AnotherPanel->NeedUpdatePanel(SrcPanel) || AnotherType==QVIEW_PANEL)
		{
			AnotherPanel->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY);
			AnotherPanel->Redraw();
		}
	}
}
Esempio n. 6
0
// Косметические преобразования строки пути.
// 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]);
			}
		}
	}
}
Esempio n. 7
0
static void MixToFullPath(const string_view stPath, string& Dest, const string_view stCurrentDir)
{
		string strDest;
		string_view pstCurrentDir;
		bool blIgnore = false;
		size_t PathDirOffset = 0;
		const auto PathType = ParsePath(stPath, &PathDirOffset);
		size_t PathOffset = PathDirOffset;
		switch (PathType)
		{
			case root_type::unknown:
			{
				if (HasPathPrefix(stPath)) // \\?\<ANY_UNKNOWN_FORMAT>
				{
					blIgnore = true;
				}
				else if (!stPath.empty() && IsSlash(stPath.front())) //"\" or "\abc"
				{
					++PathOffset;
					if (!stCurrentDir.empty())
					{
						size_t CurDirDirOffset = 0;
						if (ParsePath(stCurrentDir, &CurDirDirOffset) != root_type::unknown)
						{
							assign(strDest, stCurrentDir.substr(0, CurDirDirOffset));
						}
					}
				}
				else //"abc" or whatever
				{
					pstCurrentDir = stCurrentDir;
				}
			}
			break;
			case root_type::drive_letter: //"C:" or "C:abc"
			{
				if(stPath.size() > 2 && IsSlash(stPath[2]))
				{
					PathOffset = 0;
				}
				else
				{
					const auto Drive = os::fs::get_drive(stPath[0]);
					const auto Value = os::env::get(L'=' + Drive);

					if (!Value.empty())
					{
						strDest = Value;
					}
					else
					{
						if (upper(stPath[0])==upper(stCurrentDir[0]))
						{
							assign(strDest, stCurrentDir);
						}
						else
						{
							strDest = Drive;
						}
					}
					AddEndSlash(strDest);
				}
			}
			break;
			case root_type::remote: //"\\abc"
			{
				PathOffset = 0;
			}
			break;
			case root_type::unc_drive_letter: //"\\?\whatever"
			case root_type::unc_remote:
			case root_type::volume:
			case root_type::pipe:
			{
				blIgnore=true;
				PathOffset = 0;
			}
			break;
		}

		if (!pstCurrentDir.empty())
		{
			append(strDest, pstCurrentDir);
			AddEndSlash(strDest);
		}

		append(strDest, stPath.substr(PathOffset));

		if (!blIgnore && !HasPathPrefix(strDest))
			MixToFullPath(strDest);

		Dest = std::move(strDest);
}
Esempio n. 8
0
bool WINAPI CreateReparsePoint(const wchar_t *Target, const wchar_t *Object,DWORD Type)
{
	bool Result=false;

	if (Object && *Object && Target && *Target)
	{
		switch (Type)
		{
			case RP_EXACTCOPY:
				Result=DuplicateReparsePoint(Target,Object);
				break;
			case RP_SYMLINK:
			case RP_SYMLINKFILE:
			case RP_SYMLINKDIR:
				if(Type == RP_SYMLINK)
				{
					DWORD Attr = apiGetFileAttributes(Target);
					Type = ((Attr != INVALID_FILE_ATTRIBUTES) && (Attr&FILE_ATTRIBUTE_DIRECTORY)? RP_SYMLINKDIR : RP_SYMLINKFILE);
				}
				if (ifn.pfnCreateSymbolicLink)
				{
					Result=apiCreateSymbolicLink(Object,Target,Type==RP_SYMLINKDIR?SYMBOLIC_LINK_FLAG_DIRECTORY:0);
				}
				else
				{
					bool ObjectCreated=false;

					if (Type==RP_SYMLINKDIR)
					{
						ObjectCreated=apiCreateDirectory(Object,nullptr)!=FALSE;
					}
					else
					{
						File file;
						if(file.Open(Object,0,0,nullptr,CREATE_NEW))
						{
							ObjectCreated=true;
							file.Close();
						}
					}

					if (ObjectCreated)
					{
						LPBYTE szBuff=new BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
						if(szBuff)
						{
							PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff);
							rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK;
							string strPrintName=Target,strSubstituteName=Target;

							if (IsAbsolutePath(Target))
							{
								strSubstituteName=L"\\??\\";
								strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0));
								rdb->SymbolicLinkReparseBuffer.Flags=0;
							}
							else
							{
								rdb->SymbolicLinkReparseBuffer.Flags=SYMLINK_FLAG_RELATIVE;
							}

							if (FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()))
							{
								Result=SetREPARSE_DATA_BUFFER(Object,rdb);
							}
							else
							{
								SetLastError(ERROR_INSUFFICIENT_BUFFER);
							}
							delete[] szBuff;
						}
					}
				}

				break;
			case RP_JUNCTION:
			case RP_VOLMOUNT:
			{
				string strPrintName,strSubstituteName;
				ConvertNameToFull(Target,strPrintName);
				strSubstituteName=L"\\??\\";
				strSubstituteName+=(strPrintName.CPtr()+(HasPathPrefix(strPrintName)?4:0));
				BYTE szBuff[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
				PREPARSE_DATA_BUFFER rdb=reinterpret_cast<PREPARSE_DATA_BUFFER>(szBuff);
				rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT;

				if (FillREPARSE_DATA_BUFFER(rdb,strPrintName,strPrintName.GetLength(),strSubstituteName,strSubstituteName.GetLength()))
				{
					Result=SetREPARSE_DATA_BUFFER(Object,rdb);
				}
				else
				{
					SetLastError(ERROR_INSUFFICIENT_BUFFER);
				}
			}
			break;
		}
	}

	return Result;
}