Files
easy7zip/Windows/FileDir.cpp
Igor Pavlov e18587ba51 4.30 beta
2016-05-28 00:15:45 +01:00

673 lines
17 KiB
C++
Executable File

// Windows/FileDir.cpp
#include "StdAfx.h"
#include "FileDir.h"
#include "FileName.h"
#include "FileFind.h"
#include "Defs.h"
#ifndef _UNICODE
#include "../Common/StringConvert.h"
#endif
#ifndef _UNICODE
extern bool g_IsNT;
#endif
namespace NWindows {
namespace NFile {
namespace NDirectory {
#ifndef _UNICODE
static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
static UString GetUnicodePath(const CSysString &sysPath)
{ return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }
static CSysString GetSysPath(LPCWSTR sysPath)
{ return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }
#endif
bool MyGetWindowsDirectory(CSysString &path)
{
UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
bool MyGetSystemDirectory(CSysString &path)
{
UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
#ifndef _UNICODE
bool MyGetWindowsDirectory(UString &path)
{
if (g_IsNT)
{
UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
CSysString sysPath;
if (!MyGetWindowsDirectory(sysPath))
return false;
path = GetUnicodePath(sysPath);
return true;
}
bool MyGetSystemDirectory(UString &path)
{
if (g_IsNT)
{
UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
CSysString sysPath;
if (!MyGetSystemDirectory(sysPath))
return false;
path = GetUnicodePath(sysPath);
return true;
}
#endif
#ifndef _UNICODE
bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)
{
if (g_IsNT)
return BOOLToBool(::SetFileAttributesW(fileName, fileAttributes));
return MySetFileAttributes(GetSysPath(fileName), fileAttributes);
}
bool MyRemoveDirectory(LPCWSTR pathName)
{
if (g_IsNT)
return BOOLToBool(::RemoveDirectoryW(pathName));
return MyRemoveDirectory(GetSysPath(pathName));
}
bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)
{
if (g_IsNT)
return BOOLToBool(::MoveFileW(existFileName, newFileName));
return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));
}
#endif
bool MyCreateDirectory(LPCTSTR pathName) { return BOOLToBool(::CreateDirectory(pathName, NULL)); }
#ifndef _UNICODE
bool MyCreateDirectory(LPCWSTR pathName)
{
if (g_IsNT)
return BOOLToBool(::CreateDirectoryW(pathName, NULL));
return MyCreateDirectory(GetSysPath(pathName));
}
#endif
/*
bool CreateComplexDirectory(LPCTSTR pathName)
{
NName::CParsedPath path;
path.ParsePath(pathName);
CSysString fullPath = path.Prefix;
DWORD errorCode = ERROR_SUCCESS;
for(int i = 0; i < path.PathParts.Size(); i++)
{
const CSysString &string = path.PathParts[i];
if(string.IsEmpty())
{
if(i != path.PathParts.Size() - 1)
return false;
return true;
}
fullPath += path.PathParts[i];
if(!MyCreateDirectory(fullPath))
{
DWORD errorCode = GetLastError();
if(errorCode != ERROR_ALREADY_EXISTS)
return false;
}
fullPath += NName::kDirDelimiter;
}
return true;
}
*/
bool CreateComplexDirectory(LPCTSTR _aPathName)
{
CSysString pathName = _aPathName;
int pos = pathName.ReverseFind(TEXT('\\'));
if (pos > 0 && pos == pathName.Length() - 1)
{
if (pathName.Length() == 3 && pathName[1] == ':')
return true; // Disk folder;
pathName.Delete(pos);
}
CSysString pathName2 = pathName;
pos = pathName.Length();
while(true)
{
if(MyCreateDirectory(pathName))
break;
if(::GetLastError() == ERROR_ALREADY_EXISTS)
{
NFind::CFileInfo fileInfo;
if (!NFind::FindFile(pathName, fileInfo)) // For network folders
return true;
if (!fileInfo.IsDirectory())
return false;
break;
}
pos = pathName.ReverseFind(TEXT('\\'));
if (pos < 0 || pos == 0)
return false;
if (pathName[pos - 1] == ':')
return false;
pathName = pathName.Left(pos);
}
pathName = pathName2;
while(pos < pathName.Length())
{
pos = pathName.Find(TEXT('\\'), pos + 1);
if (pos < 0)
pos = pathName.Length();
if(!MyCreateDirectory(pathName.Left(pos)))
return false;
}
return true;
}
#ifndef _UNICODE
bool CreateComplexDirectory(LPCWSTR _aPathName)
{
UString pathName = _aPathName;
int pos = pathName.ReverseFind(L'\\');
if (pos > 0 && pos == pathName.Length() - 1)
{
if (pathName.Length() == 3 && pathName[1] == L':')
return true; // Disk folder;
pathName.Delete(pos);
}
UString pathName2 = pathName;
pos = pathName.Length();
while(true)
{
if(MyCreateDirectory(pathName))
break;
if(::GetLastError() == ERROR_ALREADY_EXISTS)
{
NFind::CFileInfoW fileInfo;
if (!NFind::FindFile(pathName, fileInfo)) // For network folders
return true;
if (!fileInfo.IsDirectory())
return false;
break;
}
pos = pathName.ReverseFind(L'\\');
if (pos < 0 || pos == 0)
return false;
if (pathName[pos - 1] == L':')
return false;
pathName = pathName.Left(pos);
}
pathName = pathName2;
while(pos < pathName.Length())
{
pos = pathName.Find(L'\\', pos + 1);
if (pos < 0)
pos = pathName.Length();
if(!MyCreateDirectory(pathName.Left(pos)))
return false;
}
return true;
}
#endif
bool DeleteFileAlways(LPCTSTR name)
{
if(!::SetFileAttributes(name, 0))
return false;
return BOOLToBool(::DeleteFile(name));
}
#ifndef _UNICODE
bool DeleteFileAlways(LPCWSTR name)
{
if (g_IsNT)
{
if(!MySetFileAttributes(name, 0))
return false;
return BOOLToBool(::DeleteFileW(name));
}
return DeleteFileAlways(GetSysPath(name));
}
#endif
static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)
{
if(fileInfo.IsDirectory())
return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
else
return DeleteFileAlways(pathPrefix + fileInfo.Name);
}
bool RemoveDirectoryWithSubItems(const CSysString &path)
{
NFind::CFileInfo fileInfo;
CSysString pathPrefix = path + NName::kDirDelimiter;
{
NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));
while(enumerator.Next(fileInfo))
if(!RemoveDirectorySubItems2(pathPrefix, fileInfo))
return false;
}
if(!BOOLToBool(::SetFileAttributes(path, 0)))
return false;
return BOOLToBool(::RemoveDirectory(path));
}
#ifndef _UNICODE
static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)
{
if(fileInfo.IsDirectory())
return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
else
return DeleteFileAlways(pathPrefix + fileInfo.Name);
}
bool RemoveDirectoryWithSubItems(const UString &path)
{
NFind::CFileInfoW fileInfo;
UString pathPrefix = path + UString(NName::kDirDelimiter);
{
NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));
while(enumerator.Next(fileInfo))
if(!RemoveDirectorySubItems2(pathPrefix, fileInfo))
return false;
}
if(!MySetFileAttributes(path, 0))
return false;
return MyRemoveDirectory(path);
}
#endif
#ifndef _WIN32_WCE
bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)
{
DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
shortPath.ReleaseBuffer();
return (needLength > 0 && needLength < MAX_PATH);
}
bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)
{
resultPath.Empty();
LPTSTR fileNamePointer = 0;
LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);
DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
resultPath.ReleaseBuffer();
if (needLength == 0 || needLength >= MAX_PATH)
return false;
if (fileNamePointer == 0)
fileNamePartStartIndex = lstrlen(fileName);
else
fileNamePartStartIndex = (int)(fileNamePointer - buffer);
return true;
}
#ifndef _UNICODE
bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)
{
resultPath.Empty();
if (g_IsNT)
{
LPWSTR fileNamePointer = 0;
LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);
DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
resultPath.ReleaseBuffer();
if (needLength == 0 || needLength >= MAX_PATH)
return false;
if (fileNamePointer == 0)
fileNamePartStartIndex = MyStringLen(fileName);
else
fileNamePartStartIndex = (int)(fileNamePointer - buffer);
}
else
{
CSysString sysPath;
if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))
return false;
UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));
UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));
fileNamePartStartIndex = resultPath1.Length();
resultPath = resultPath1 + resultPath2;
}
return true;
}
#endif
bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)
{
int index;
return MyGetFullPathName(fileName, path, index);
}
#ifndef _UNICODE
bool MyGetFullPathName(LPCWSTR fileName, UString &path)
{
int index;
return MyGetFullPathName(fileName, path, index);
}
#endif
bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Mid(index);
return true;
}
#ifndef _UNICODE
bool GetOnlyName(LPCWSTR fileName, UString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Mid(index);
return true;
}
#endif
bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Left(index);
return true;
}
#ifndef _UNICODE
bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Left(index);
return true;
}
#endif
bool MyGetCurrentDirectory(CSysString &path)
{
DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
#ifndef _UNICODE
bool MySetCurrentDirectory(LPCWSTR path)
{
if (g_IsNT)
return BOOLToBool(::SetCurrentDirectoryW(path));
return MySetCurrentDirectory(GetSysPath(path));
}
bool MyGetCurrentDirectory(UString &path)
{
if (g_IsNT)
{
DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
CSysString sysPath;
if (!MyGetCurrentDirectory(sysPath))
return false;
path = GetUnicodePath(sysPath);
return true;
}
#endif
#endif
bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension,
CSysString &resultPath, UINT32 &filePart)
{
LPTSTR filePartPointer;
DWORD value = ::SearchPath(path, fileName, extension,
MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);
resultPath.ReleaseBuffer();
return (value > 0 && value <= MAX_PATH);
}
#ifndef _UNICODE
bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension,
UString &resultPath, UINT32 &filePart)
{
if (g_IsNT)
{
LPWSTR filePartPointer = 0;
DWORD value = ::SearchPathW(path, fileName, extension,
MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);
resultPath.ReleaseBuffer();
return (value > 0 && value <= MAX_PATH);
}
CSysString sysPath;
if (!MySearchPath(
path != 0 ? (LPCTSTR)GetSysPath(path): 0,
fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,
extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,
sysPath, filePart))
return false;
UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));
UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));
filePart = resultPath1.Length();
resultPath = resultPath1 + resultPath2;
return true;
}
#endif
bool MyGetTempPath(CSysString &path)
{
DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
#ifndef _UNICODE
bool MyGetTempPath(UString &path)
{
path.Empty();
if (g_IsNT)
{
DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
path.ReleaseBuffer();
return (needLength > 0 && needLength <= MAX_PATH);
}
CSysString sysPath;
if (!MyGetTempPath(sysPath))
return false;
path = GetUnicodePath(sysPath);
return true;
}
#endif
UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)
{
UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));
path.ReleaseBuffer();
return number;
}
#ifndef _UNICODE
UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)
{
if (g_IsNT)
{
UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));
path.ReleaseBuffer();
return number;
}
CSysString sysPath;
UINT number = MyGetTempFileName(
dirPath ? (LPCTSTR)GetSysPath(dirPath): 0,
prefix ? (LPCTSTR)GetSysPath(prefix): 0,
sysPath);
path = GetUnicodePath(sysPath);
return number;
}
#endif
UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)
{
Remove();
UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
if(number != 0)
{
_fileName = resultPath;
_mustBeDeleted = true;
}
return number;
}
bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)
{
CSysString tempPath;
if(!MyGetTempPath(tempPath))
return false;
if (Create(tempPath, prefix, resultPath) != 0)
return true;
if(!MyGetWindowsDirectory(tempPath))
return false;
return (Create(tempPath, prefix, resultPath) != 0);
}
bool CTempFile::Remove()
{
if (!_mustBeDeleted)
return true;
_mustBeDeleted = !DeleteFileAlways(_fileName);
return !_mustBeDeleted;
}
#ifndef _UNICODE
UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)
{
Remove();
UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
if(number != 0)
{
_fileName = resultPath;
_mustBeDeleted = true;
}
return number;
}
bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)
{
UString tempPath;
if(!MyGetTempPath(tempPath))
return false;
if (Create(tempPath, prefix, resultPath) != 0)
return true;
if(!MyGetWindowsDirectory(tempPath))
return false;
return (Create(tempPath, prefix, resultPath) != 0);
}
bool CTempFileW::Remove()
{
if (!_mustBeDeleted)
return true;
_mustBeDeleted = !DeleteFileAlways(_fileName);
return !_mustBeDeleted;
}
#endif
bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)
{
/*
CSysString prefix = tempPath + prefixChars;
CRandom random;
random.Init();
*/
while(true)
{
CTempFile tempFile;
if (!tempFile.Create(prefix, dirName))
return false;
if (!::DeleteFile(dirName))
return false;
/*
UINT32 randomNumber = random.Generate();
TCHAR randomNumberString[32];
_stprintf(randomNumberString, _T("%04X"), randomNumber);
dirName = prefix + randomNumberString;
*/
if(NFind::DoesFileExist(dirName))
continue;
if (MyCreateDirectory(dirName))
return true;
if (::GetLastError() != ERROR_ALREADY_EXISTS)
return false;
}
}
bool CTempDirectory::Create(LPCTSTR prefix)
{
Remove();
return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));
}
#ifndef _UNICODE
bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)
{
/*
CSysString prefix = tempPath + prefixChars;
CRandom random;
random.Init();
*/
while(true)
{
CTempFileW tempFile;
if (!tempFile.Create(prefix, dirName))
return false;
if (!DeleteFileAlways(dirName))
return false;
/*
UINT32 randomNumber = random.Generate();
TCHAR randomNumberString[32];
_stprintf(randomNumberString, _T("%04X"), randomNumber);
dirName = prefix + randomNumberString;
*/
if(NFind::DoesFileExist(dirName))
continue;
if (MyCreateDirectory(dirName))
return true;
if (::GetLastError() != ERROR_ALREADY_EXISTS)
return false;
}
}
bool CTempDirectoryW::Create(LPCWSTR prefix)
{
Remove();
return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));
}
#endif
}}}