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