From 4677d362982a38c6e2aabb667e33aaa7f921f018 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Tue, 9 Jun 2015 16:04:24 +0200 Subject: Update source tree with version 9.38.beta of LZMA SDK. - Remove unused files. - Split in .pri files. - Add HEADERS section. - Adjust lib7z_facade. Change-Id: I31e7bafbfe1a9346364bd58c391601955f98ad3a Reviewed-by: Kai Koehne --- src/libs/7zip/win/CPP/Windows/DLL.cpp | 130 +-- src/libs/7zip/win/CPP/Windows/DLL.h | 25 +- src/libs/7zip/win/CPP/Windows/Error.cpp | 50 - src/libs/7zip/win/CPP/Windows/Error.h | 33 - src/libs/7zip/win/CPP/Windows/FileDir.cpp | 1050 +++++++------------- src/libs/7zip/win/CPP/Windows/FileDir.h | 180 +--- src/libs/7zip/win/CPP/Windows/FileFind.cpp | 605 ++++++----- src/libs/7zip/win/CPP/Windows/FileFind.h | 127 ++- src/libs/7zip/win/CPP/Windows/FileIO.cpp | 430 ++++---- src/libs/7zip/win/CPP/Windows/FileIO.h | 217 ++-- src/libs/7zip/win/CPP/Windows/FileLink.cpp | 426 ++++++++ src/libs/7zip/win/CPP/Windows/FileMapping.cpp | 12 - src/libs/7zip/win/CPP/Windows/FileMapping.h | 8 +- src/libs/7zip/win/CPP/Windows/FileName.cpp | 675 ++++++++++++- src/libs/7zip/win/CPP/Windows/FileName.h | 69 +- src/libs/7zip/win/CPP/Windows/MemoryLock.cpp | 82 -- src/libs/7zip/win/CPP/Windows/MemoryLock.h | 15 - src/libs/7zip/win/CPP/Windows/NtCheck.h | 44 - src/libs/7zip/win/CPP/Windows/PropVariant.cpp | 105 +- src/libs/7zip/win/CPP/Windows/PropVariant.h | 97 +- src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp | 99 ++ src/libs/7zip/win/CPP/Windows/PropVariantConv.h | 30 + .../win/CPP/Windows/PropVariantConversions.cpp | 105 -- .../7zip/win/CPP/Windows/PropVariantConversions.h | 14 - src/libs/7zip/win/CPP/Windows/Registry.cpp | 369 ------- src/libs/7zip/win/CPP/Windows/Registry.h | 85 -- src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp | 179 ++++ src/libs/7zip/win/CPP/Windows/SecurityUtils.h | 167 ++++ src/libs/7zip/win/CPP/Windows/StdAfx.h | 3 +- src/libs/7zip/win/CPP/Windows/System.h | 2 +- src/libs/7zip/win/CPP/Windows/Thread.h | 2 +- src/libs/7zip/win/CPP/Windows/Time.cpp | 170 ---- src/libs/7zip/win/CPP/Windows/Time.h | 21 - src/libs/7zip/win/CPP/Windows/TimeUtils.cpp | 203 ++++ src/libs/7zip/win/CPP/Windows/TimeUtils.h | 23 + src/libs/7zip/win/CPP/Windows/Windows.pri | 29 + 36 files changed, 3298 insertions(+), 2583 deletions(-) delete mode 100644 src/libs/7zip/win/CPP/Windows/Error.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Error.h create mode 100644 src/libs/7zip/win/CPP/Windows/FileLink.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/FileMapping.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/MemoryLock.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/MemoryLock.h delete mode 100644 src/libs/7zip/win/CPP/Windows/NtCheck.h create mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConv.h delete mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/PropVariantConversions.h delete mode 100644 src/libs/7zip/win/CPP/Windows/Registry.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Registry.h create mode 100644 src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/SecurityUtils.h delete mode 100644 src/libs/7zip/win/CPP/Windows/Time.cpp delete mode 100644 src/libs/7zip/win/CPP/Windows/Time.h create mode 100644 src/libs/7zip/win/CPP/Windows/TimeUtils.cpp create mode 100644 src/libs/7zip/win/CPP/Windows/TimeUtils.h create mode 100644 src/libs/7zip/win/CPP/Windows/Windows.pri (limited to 'src/libs/7zip/win/CPP/Windows') diff --git a/src/libs/7zip/win/CPP/Windows/DLL.cpp b/src/libs/7zip/win/CPP/Windows/DLL.cpp index 5afd72d9d..cf3dd1ceb 100644 --- a/src/libs/7zip/win/CPP/Windows/DLL.cpp +++ b/src/libs/7zip/win/CPP/Windows/DLL.cpp @@ -2,109 +2,109 @@ #include "StdAfx.h" -#ifndef _UNICODE -#include "../Common/StringConvert.h" -#endif - #include "DLL.h" #ifndef _UNICODE extern bool g_IsNT; #endif +extern HINSTANCE g_hInstance; + namespace NWindows { namespace NDLL { -bool CLibrary::Free() +bool CLibrary::Free() throw() { if (_module == 0) return true; - // MessageBox(0, TEXT(""), TEXT("Free"), 0); - // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } -bool CLibrary::LoadOperations(HMODULE newModule) +bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw() { - if (newModule == NULL) - return false; if (!Free()) return false; - _module = newModule; - return true; -} - -bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) -{ - // MessageBox(0, fileName, TEXT("LoadEx"), 0); - return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); -} - -bool CLibrary::Load(LPCTSTR fileName) -{ - // MessageBox(0, fileName, TEXT("Load"), 0); - // Sleep(5000); - // OutputDebugString(fileName); - // OutputDebugString(TEXT("\n")); - return LoadOperations(::LoadLibrary(fileName)); + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); + } + else + #endif + { + _module = ::LoadLibraryExW(fs2us(path), NULL, flags); + } + return (_module != NULL); } -#ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } -CSysString GetSysPath(LPCWSTR sysPath) - { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } - -bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) +bool CLibrary::Load(CFSTR path) throw() { - if (g_IsNT) - return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); - return LoadEx(GetSysPath(fileName), flags); -} -bool CLibrary::Load(LPCWSTR fileName) -{ - if (g_IsNT) - return LoadOperations(::LoadLibraryW(fileName)); - return Load(GetSysPath(fileName)); + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibrary(fs2fas(path)); + } + else + #endif + { + _module = ::LoadLibraryW(fs2us(path)); + } + return (_module != NULL); } -#endif -bool MyGetModuleFileName(HMODULE hModule, CSysString &result) +bool MyGetModuleFileName(FString &path) { - result.Empty(); - TCHAR fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); - if (size <= MAX_PATH && size != 0) + HMODULE hModule = g_hInstance; + path.Empty(); + #ifndef _UNICODE + if (!g_IsNT) { - result = fullPath; - return true; + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = fas2fs(s); + return true; + } + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = us2fs(s); + return true; + } } return false; } -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result) +#ifndef _SFX + +FString GetModuleDirPrefix() { - result.Empty(); - if (g_IsNT) + FString s; + if (MyGetModuleFileName(s)) { - wchar_t fullPath[MAX_PATH + 2]; - DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); - if (size <= MAX_PATH && size != 0) + int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos >= 0) { - result = fullPath; - return true; + s.DeleteFrom(pos + 1); + return s; } - return false; } - CSysString resultSys; - if (!MyGetModuleFileName(hModule, resultSys)) - return false; - result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); - return true; + return FTEXT(".") FSTRING_PATH_SEPARATOR; } + #endif }} diff --git a/src/libs/7zip/win/CPP/Windows/DLL.h b/src/libs/7zip/win/CPP/Windows/DLL.h index 4a253b326..d8848ce95 100644 --- a/src/libs/7zip/win/CPP/Windows/DLL.h +++ b/src/libs/7zip/win/CPP/Windows/DLL.h @@ -9,15 +9,13 @@ namespace NWindows { namespace NDLL { #ifdef UNDER_CE -#define My_GetProcAddress(module, proceName) GetProcAddressA(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName) #else -#define My_GetProcAddress(module, proceName) ::GetProcAddress(module, proceName) +#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName) #endif - + class CLibrary { - bool LoadOperations(HMODULE newModule); -protected: HMODULE _module; public: CLibrary(): _module(NULL) {}; @@ -39,20 +37,15 @@ public: return m; } - bool Free(); - bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCTSTR fileName); - #ifndef _UNICODE - bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); - bool Load(LPCWSTR fileName); - #endif + bool Free() throw(); + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); + bool Load(CFSTR path) throw(); FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } }; -bool MyGetModuleFileName(HMODULE hModule, CSysString &result); -#ifndef _UNICODE -bool MyGetModuleFileName(HMODULE hModule, UString &result); -#endif +bool MyGetModuleFileName(FString &path); + +FString GetModuleDirPrefix(); }} diff --git a/src/libs/7zip/win/CPP/Windows/Error.cpp b/src/libs/7zip/win/CPP/Windows/Error.cpp deleted file mode 100644 index 7b18c29cc..000000000 --- a/src/libs/7zip/win/CPP/Windows/Error.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Windows/Error.h - -#include "StdAfx.h" - -#include "Windows/Error.h" -#ifndef _UNICODE -#include "Common/StringConvert.h" -#endif - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -namespace NWindows { -namespace NError { - -bool MyFormatMessage(DWORD messageID, CSysString &message) -{ - LPVOID msgBuf; - if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) - return false; - message = (LPCTSTR)msgBuf; - ::LocalFree(msgBuf); - return true; -} - -#ifndef _UNICODE -bool MyFormatMessage(DWORD messageID, UString &message) -{ - if (g_IsNT) - { - LPVOID msgBuf; - if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) - return false; - message = (LPCWSTR)msgBuf; - ::LocalFree(msgBuf); - return true; - } - CSysString messageSys; - bool result = MyFormatMessage(messageID, messageSys); - message = GetUnicodeString(messageSys); - return result; -} -#endif - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Error.h b/src/libs/7zip/win/CPP/Windows/Error.h deleted file mode 100644 index 05b5cd0ea..000000000 --- a/src/libs/7zip/win/CPP/Windows/Error.h +++ /dev/null @@ -1,33 +0,0 @@ -// Windows/Error.h - -#ifndef __WINDOWS_ERROR_H -#define __WINDOWS_ERROR_H - -#include "Common/MyString.h" - -namespace NWindows { -namespace NError { - -bool MyFormatMessage(DWORD messageID, CSysString &message); -inline CSysString MyFormatMessage(DWORD messageID) -{ - CSysString message; - MyFormatMessage(messageID, message); - return message; -} -#ifdef _UNICODE -inline UString MyFormatMessageW(DWORD messageID) - { return MyFormatMessage(messageID); } -#else -bool MyFormatMessage(DWORD messageID, UString &message); -inline UString MyFormatMessageW(DWORD messageID) -{ - UString message; - MyFormatMessage(messageID, message); - return message; -} -#endif - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.cpp b/src/libs/7zip/win/CPP/Windows/FileDir.cpp index 857946031..097f81efb 100644 --- a/src/libs/7zip/win/CPP/Windows/FileDir.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileDir.cpp @@ -14,81 +14,62 @@ extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { - -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - -// SetCurrentDirectory doesn't support \\?\ prefix - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR fileName, UString &res); -bool GetLongPath(LPCWSTR fileName, UString &res); -#endif - -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 +namespace NDir { #ifndef UNDER_CE -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) +bool GetWindowsDir(FString &path) { - UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } return (needLength > 0 && needLength <= MAX_PATH); } -#endif - -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path) +bool GetSystemDir(FString &path) { - if (g_IsNT) + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) { - UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); } - CSysString sysPath; - if (!MyGetWindowsDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} - -bool MyGetSystemDirectory(UString &path) -{ - if (g_IsNT) + else + #endif { - UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); } - CSysString sysPath; - if (!MyGetSystemDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; + return (needLength > 0 && needLength <= MAX_PATH); } #endif -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) @@ -97,17 +78,18 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return false; } #endif - HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + HANDLE hDir = INVALID_HANDLE_VALUE; + IF_USE_MAIN_PATH + hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH - if (hDir == INVALID_HANDLE_VALUE) + if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(fileName, longPath)) - hDir = ::CreateFileW(longPath, GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif @@ -120,790 +102,482 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, return res; } -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) -{ - if (::SetFileAttributes(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); - #endif - return false; -} - -bool MyRemoveDirectory(LPCTSTR pathName) -{ - if (::RemoveDirectory(pathName)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); - #endif - return false; -} - -#ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) -{ - if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) - return false; - if (d1.IsEmpty() && d2.IsEmpty()) return false; - if (d1.IsEmpty()) d1 = s1; - if (d2.IsEmpty()) d2 = s2; - return true; -} -#endif - -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) -{ - if (::MoveFile(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH2 - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); - #endif - return false; -} - -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) +bool SetFileAttrib(CFSTR path, DWORD attrib) { + #ifndef _UNICODE if (!g_IsNT) - return MySetFileAttributes(GetSysPath(fileName), fileAttributes); - if (::SetFileAttributesW(fileName, fileAttributes)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(fileName, longPath)) - return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); + { + if (::SetFileAttributes(fs2fas(path), attrib)) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::SetFileAttributesW(fs2us(path), attrib)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::SetFileAttributesW(longPath, attrib)); + } + #endif + } return false; } - -bool MyRemoveDirectory(LPCWSTR pathName) +bool RemoveDir(CFSTR path) { + #ifndef _UNICODE if (!g_IsNT) - return MyRemoveDirectory(GetSysPath(pathName)); - if (::RemoveDirectoryW(pathName)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::RemoveDirectoryW(longPath)); + { + if (::RemoveDirectory(fs2fas(path))) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::RemoveDirectoryW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::RemoveDirectoryW(longPath)); + } + #endif + } return false; } -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) { + #ifndef _UNICODE if (!g_IsNT) - return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); - if (::MoveFileW(existFileName, newFileName)) - return true; - #ifdef WIN_LONG_PATH - UString d1, d2; - if (GetLongPaths(existFileName, newFileName, d1, d2)) - return BOOLToBool(::MoveFileW(d1, d2)); - #endif - return false; -} -#endif - -bool MyCreateDirectory(LPCTSTR pathName) -{ - if (::CreateDirectory(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH2 - if (::GetLastError() != ERROR_ALREADY_EXISTS) { - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) + return true; } + else #endif + { + IF_USE_MAIN_PATH_2(oldFile, newFile) + if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileW(d1, d2)); + } + #endif + } return false; } -#ifndef _UNICODE -bool MyCreateDirectory(LPCWSTR pathName) +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); +EXTERN_C_END + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { + #ifndef _UNICODE if (!g_IsNT) - return MyCreateDirectory(GetSysPath(pathName)); - if (::CreateDirectoryW(pathName, NULL)) - return true; - #ifdef WIN_LONG_PATH - if (::GetLastError() != ERROR_ALREADY_EXISTS) { - UString longPath; - if (GetLongPath(pathName, longPath)) - return BOOLToBool(::CreateDirectoryW(longPath, NULL)); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + /* + if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) + return true; + */ } + else #endif - return false; -} -#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)) + Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + if (!my_CreateHardLinkW) + return false; + IF_USE_MAIN_PATH_2(newFileName, existFileName) + if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) { - DWORD errorCode = GetLastError(); - if (errorCode != ERROR_ALREADY_EXISTS) - return false; + UString d1, d2; + if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); } - fullPath += NName::kDirDelimiter; + #endif } - return true; + return false; } -*/ -bool CreateComplexDirectory(LPCTSTR _aPathName) +#endif + +bool CreateDir(CFSTR path) { - CSysString pathName = _aPathName; - int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - if (pos > 0 && pos == pathName.Length() - 1) + #ifndef _UNICODE + if (!g_IsNT) { - if (pathName.Length() == 3 && pathName[1] == ':') - return true; // Disk folder; - pathName.Delete(pos); + if (::CreateDirectory(fs2fas(path), NULL)) + return true; } - CSysString pathName2 = pathName; - pos = pathName.Length(); - for (;;) + else + #endif { - if (MyCreateDirectory(pathName)) - break; - if (::GetLastError() == ERROR_ALREADY_EXISTS) - { - NFind::CFileInfo fileInfo; - if (!fileInfo.Find(pathName)) // For network folders + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) return true; - if (!fileInfo.IsDir()) - return false; - break; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } - pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); - 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(CHAR_PATH_SEPARATOR), pos + 1); - if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) - return false; + #endif } - return true; + return false; } -#ifndef _UNICODE - -bool CreateComplexDirectory(LPCWSTR _aPathName) +bool CreateComplexDir(CFSTR _aPathName) { - UString pathName = _aPathName; - int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos > 0 && pos == pathName.Length() - 1) + FString pathName = _aPathName; + int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos > 0 && (unsigned)pos == pathName.Len() - 1) { - if (pathName.Length() == 3 && pathName[1] == L':') + if (pathName.Len() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } - UString pathName2 = pathName; - pos = pathName.Length(); + const FString pathName2 = pathName; + pos = pathName.Len(); + for (;;) { - if (MyCreateDirectory(pathName)) + if (CreateDir(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { - NFind::CFileInfoW fileInfo; + NFind::CFileInfo fileInfo; if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } - pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; - pathName = pathName.Left(pos); + pathName.DeleteFrom(pos); } - pathName = pathName2; - while (pos < pathName.Length()) + + while (pos < (int)pathName2.Len()) { - pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); + pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) - pos = pathName.Length(); - if (!MyCreateDirectory(pathName.Left(pos))) + pos = pathName2.Len(); + pathName.SetFrom(pathName2, pos); + if (!CreateDir(pathName)) return false; } + return true; } -#endif - -bool DeleteFileAlways(LPCTSTR name) +bool DeleteFileAlways(CFSTR path) { - if (!MySetFileAttributes(name, 0)) + if (!SetFileAttrib(path, 0)) return false; - if (::DeleteFile(name)) - return true; - #ifdef WIN_LONG_PATH2 - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); - #endif - return false; -} - -#ifndef _UNICODE -bool DeleteFileAlways(LPCWSTR name) -{ + #ifndef _UNICODE if (!g_IsNT) - return DeleteFileAlways(GetSysPath(name)); - if (!MySetFileAttributes(name, 0)) - return false; - if (::DeleteFileW(name)) - return true; - #ifdef WIN_LONG_PATH - UString longPath; - if (GetLongPath(name, longPath)) - return BOOLToBool(::DeleteFileW(longPath)); + { + if (::DeleteFile(fs2fas(path))) + return true; + } + else #endif + { + IF_USE_MAIN_PATH + if (::DeleteFileW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + return BOOLToBool(::DeleteFileW(longPath)); + } + #endif + } return false; } -#endif - -static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) -{ - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} -bool RemoveDirectoryWithSubItems(const CSysString &path) +bool RemoveDirWithSubItems(const FString &path) { - NFind::CFileInfo fileInfo; - CSysString pathPrefix = path + NName::kDirDelimiter; + bool needRemoveSubItems = true; { - NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) - return false; + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; } - if (!MySetFileAttributes(path, 0)) - return false; - return MyRemoveDirectory(path); -} -#ifndef _UNICODE -static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) -{ - if (fileInfo.IsDir()) - return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); - return DeleteFileAlways(pathPrefix + fileInfo.Name); -} -bool RemoveDirectoryWithSubItems(const UString &path) -{ - NFind::CFileInfoW fileInfo; - UString pathPrefix = path + UString(NName::kDirDelimiter); + if (needRemoveSubItems) { - NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); - while (enumerator.Next(fileInfo)) - if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) + FString s = path; + s += FCHAR_PATH_SEPARATOR; + unsigned prefixSize = s.Len(); + s += FCHAR_ANY_MASK; + NFind::CEnumerator enumerator(s); + NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + return false; + } + else if (!DeleteFileAlways(s)) return false; + } } - if (!MySetFileAttributes(path, 0)) - return false; - return MyRemoveDirectory(path); -} -#endif -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) + if (!SetFileAttrib(path, 0)) return false; - resultName = resultName.Left(index); - return true; -} - -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; + return RemoveDir(path); } #ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath) -{ - resultPath = fileName; - return true; -} -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - resultPath = fileName; - // change it - fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR); - fileNamePartStartIndex++; + resFullPath = path; return true; } #else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) +bool MyGetFullPathName(CFSTR path, FString &resFullPath) { - DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); - shortPath.ReleaseBuffer(); - return (needLength > 0 && needLength < MAX_PATH); + return GetFullPath(path, resFullPath); } -#ifdef WIN_LONG_PATH - -static UString GetLastPart(LPCWSTR path) +bool SetCurrentDir(CFSTR path) { - int i = (int)wcslen(path); - for (; i > 0; i--) - { - WCHAR c = path[i - 1]; - if (c == WCHAR_PATH_SEPARATOR || c == '/') - break; - } - return path + i; -} - -static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) -{ - int len = (int)wcslen(oldPath); - int i; - for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); - if (i == 0 || i == len) - return; - UString oldName = GetLastPart(oldPath); - UString newName = GetLastPart(newPath); - int nonDotsLen = oldName.Length() - (len - i); - if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) - return; - for (; i != len; i++) - newPath += '.'; -} - -#endif - -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) - return false; - if (needLength >= MAX_PATH) + // SetCurrentDirectory doesn't support \\?\ prefix + #ifndef _UNICODE + if (!g_IsNT) { - #ifdef WIN_LONG_PATH2 - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif - return false; + return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); } - if (fileNamePointer == 0) - fileNamePartStartIndex = lstrlen(fileName); else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); - #ifdef _UNICODE - #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); #endif - #endif - return true; + { + return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); + } } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) +bool GetCurrentDir(FString &path) { - resultPath.Empty(); - if (g_IsNT) + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + 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) - return false; - if (needLength >= MAX_PATH) - { - #ifdef WIN_LONG_PATH - needLength++; - buffer = resultPath.GetBuffer(needLength + 1); - DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); - resultPath.ReleaseBuffer(); - if (needLength2 == 0 || needLength2 > needLength) - #endif - return false; - } - if (fileNamePointer == 0) - fileNamePartStartIndex = MyStringLen(fileName); - else - fileNamePartStartIndex = (int)(fileNamePointer - buffer); - #ifdef WIN_LONG_PATH - AddTrailingDots(fileName, resultPath); - #endif + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fas2fs(s); } else + #endif { - 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; + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = us2fs(s); } - return true; -} -#endif - - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) -{ - int index; - return MyGetFullPathName(fileName, path, index); + return (needLength > 0 && needLength <= MAX_PATH); } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &path) -{ - int index; - return MyGetFullPathName(fileName, path, index); -} #endif -#ifndef _UNICODE -bool GetOnlyName(LPCWSTR fileName, UString &resultName) +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Mid(index); - return true; -} -#endif - -#ifndef _UNICODE -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) -{ - int index; - if (!MyGetFullPathName(fileName, resultName, index)) - return false; - resultName = resultName.Left(index); - return true; + bool res = MyGetFullPathName(path, resDirPrefix); + if (!res) + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR); + resFileName = resDirPrefix.Ptr(pos + 1); + resDirPrefix.DeleteFrom(pos + 1); + return res; } -#endif -bool MyGetCurrentDirectory(CSysString &path) +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) { - DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); } -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path) +bool MyGetTempPath(FString &path) { - if (g_IsNT) - return BOOLToBool(::SetCurrentDirectoryW(path)); - return MySetCurrentDirectory(GetSysPath(path)); -} -bool MyGetCurrentDirectory(UString &path) -{ - if (g_IsNT) + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); - path.ReleaseBuffer(); - return (needLength > 0 && needLength <= MAX_PATH); + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPath(MAX_PATH + 1, s); + path = fas2fs(s); } - CSysString sysPath; - if (!MyGetCurrentDirectory(sysPath)) - return false; - path = GetUnicodePath(sysPath); - return true; -} -#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); -} -#endif - -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, - UString &resultPath, UINT32 &filePart) -{ - if (g_IsNT) + else + #endif { - 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); + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPathW(MAX_PATH + 1, s);; + path = us2fs(s); } - - 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) +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) { - if (g_IsNT) + UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (unsigned i = 0; i < 100; i++) { - UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); - path.ReleaseBuffer(); - return number; + path = prefix; + if (addRandom) + { + FChar s[16]; + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += FChar('.'); + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += FTEXT(".tmp"); + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (CreateDir(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; } - CSysString sysPath; - UINT number = MyGetTempFileName( - dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, - prefix ? (LPCTSTR)GetSysPath(prefix): 0, - sysPath); - path = GetUnicodePath(sysPath); - return number; + path.Empty(); + return false; } -#endif -UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; + if (!Remove()) + return false; + if (!CreateTempFile(prefix, false, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; } -bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) { - CSysString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - #ifdef UNDER_CE - return false; - #else - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) return false; - return (Create(tempPath, prefix, resultPath) != 0); - #endif + _mustBeDeleted = true; + return true; } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !DeleteFileAlways(_path); return !_mustBeDeleted; } -#ifndef _UNICODE - -UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { - Remove(); - UINT number = MyGetTempFileName(dirPath, prefix, resultPath); - if (number != 0) - { - _fileName = resultPath; - _mustBeDeleted = true; - } - return number; + if (deleteDestBefore) + if (NFind::DoesFileExist(name)) + if (!DeleteFileAlways(name)) + return false; + DisableDeleting(); + return MyMoveFile(_path, name); } -bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) +bool CTempDir::Create(CFSTR prefix) { - UString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - if (!MyGetWindowsDirectory(tempPath)) + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) return false; - return (Create(tempPath, prefix, resultPath) != 0); + _mustBeDeleted = true; + return true; } -bool CTempFileW::Remove() +bool CTempDir::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !RemoveDirWithSubItems(_path); return !_mustBeDeleted; } -#endif - -bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) -{ - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFile tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(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(); - */ - for (;;) - { - { - CTempFileW tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) - return false; - } - /* - UINT32 randomNumber = random.Generate(); - TCHAR randomNumberString[32]; - _stprintf(randomNumberString, _T("%04X"), randomNumber); - dirName = prefix + randomNumberString; - */ - if (NFind::DoesFileOrDirExist(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 - }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileDir.h b/src/libs/7zip/win/CPP/Windows/FileDir.h index 04542d872..02d3e5a57 100644 --- a/src/libs/7zip/win/CPP/Windows/FileDir.h +++ b/src/libs/7zip/win/CPP/Windows/FileDir.h @@ -1,174 +1,94 @@ // Windows/FileDir.h -#ifndef __WINDOWS_FILEDIR_H -#define __WINDOWS_FILEDIR_H +#ifndef __WINDOWS_FILE_DIR_H +#define __WINDOWS_FILE_DIR_H #include "../Common/MyString.h" -#include "Defs.h" + +#include "FileIO.h" namespace NWindows { namespace NFile { -namespace NDirectory { +namespace NDir { -#ifdef WIN_LONG_PATH -bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); -#endif +bool GetWindowsDir(FString &path); +bool GetSystemDir(FString &path); -bool MyGetWindowsDirectory(CSysString &path); -bool MyGetSystemDirectory(CSysString &path); -#ifndef _UNICODE -bool MyGetWindowsDirectory(UString &path); -bool MyGetSystemDirectory(UString &path); -#endif +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +bool SetFileAttrib(CFSTR path, DWORD attrib); +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); -bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); - -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); -bool MyRemoveDirectory(LPCTSTR pathName); -bool MyCreateDirectory(LPCTSTR pathName); -bool CreateComplexDirectory(LPCTSTR pathName); -bool DeleteFileAlways(LPCTSTR name); -bool RemoveDirectoryWithSubItems(const CSysString &path); - -#ifndef _UNICODE -bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); -bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); -bool MyRemoveDirectory(LPCWSTR pathName); -bool MyCreateDirectory(LPCWSTR pathName); -bool CreateComplexDirectory(LPCWSTR pathName); -bool DeleteFileAlways(LPCWSTR name); -bool RemoveDirectoryWithSubItems(const UString &path); +#ifndef UNDER_CE +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); #endif -bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); -bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); -#ifdef UNDER_CE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); -#else -bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); - -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, - int &fileNamePartStartIndex); -bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); -bool GetOnlyName(LPCWSTR fileName, UString &resultName); -bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); -#endif +bool RemoveDir(CFSTR path); +bool CreateDir(CFSTR path); +bool CreateComplexDir(CFSTR path); +bool DeleteFileAlways(CFSTR name); +bool RemoveDirWithSubItems(const FString &path); -inline bool MySetCurrentDirectory(LPCTSTR path) - { return BOOLToBool(::SetCurrentDirectory(path)); } -bool MyGetCurrentDirectory(CSysString &resultPath); -#ifndef _UNICODE -bool MySetCurrentDirectory(LPCWSTR path); -bool MyGetCurrentDirectory(UString &resultPath); -#endif +bool MyGetFullPathName(CFSTR path, FString &resFullPath); +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); -bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); -#ifndef _UNICODE -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); -#endif +#ifndef UNDER_CE -inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} - -#ifndef _UNICODE -inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) -{ - UINT32 value; - return MySearchPath(path, fileName, extension, resultPath, value); -} -#endif +bool SetCurrentDir(CFSTR path); +bool GetCurrentDir(FString &resultPath); #endif -bool MyGetTempPath(CSysString &resultPath); -#ifndef _UNICODE -bool MyGetTempPath(UString &resultPath); -#endif - -UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); -#ifndef _UNICODE -UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); -#endif +bool MyGetTempPath(FString &resultPath); class CTempFile { bool _mustBeDeleted; - CSysString _fileName; + FString _path; + void DisableDeleting() { _mustBeDeleted = false; } public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } - void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); - bool Create(LPCTSTR prefix, CSysString &resultPath); + const FString &GetPath() const { return _path; } + bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix + bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); bool Remove(); + bool MoveTo(CFSTR name, bool deleteDestBefore); }; -#ifdef _UNICODE -typedef CTempFile CTempFileW; -#else -class CTempFileW +class CTempDir { bool _mustBeDeleted; - UString _fileName; + FString _path; public: - CTempFileW(): _mustBeDeleted(false) {} - ~CTempFileW() { Remove(); } + CTempDir(): _mustBeDeleted(false) {} + ~CTempDir() { Remove(); } + const FString &GetPath() const { return _path; } void DisableDeleting() { _mustBeDeleted = false; } - UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); - bool Create(LPCWSTR prefix, UString &resultPath); + bool Create(CFSTR namePrefix) ; bool Remove(); }; -#endif - -bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); -class CTempDirectory +#if !defined(UNDER_CE) +class CCurrentDirRestorer { - bool _mustBeDeleted; - CSysString _tempDir; + FString _path; public: - const CSysString &GetPath() const { return _tempDir; } - CTempDirectory(): _mustBeDeleted(false) {} - ~CTempDirectory() { Remove(); } - bool Create(LPCTSTR prefix) ; - bool Remove() + bool NeedRestore; + + CCurrentDirRestorer(): NeedRestore(true) { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); + GetCurrentDir(_path); } - void DisableDeleting() { _mustBeDeleted = false; } -}; - -#ifdef _UNICODE -typedef CTempDirectory CTempDirectoryW; -#else -class CTempDirectoryW -{ - bool _mustBeDeleted; - UString _tempDir; -public: - const UString &GetPath() const { return _tempDir; } - CTempDirectoryW(): _mustBeDeleted(false) {} - ~CTempDirectoryW() { Remove(); } - bool Create(LPCWSTR prefix) ; - bool Remove() + ~CCurrentDirRestorer() { - if (!_mustBeDeleted) - return true; - _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); - return (!_mustBeDeleted); + if (!NeedRestore) + return; + FString s; + if (GetCurrentDir(s)) + if (s != _path) + SetCurrentDir(_path); } - void DisableDeleting() { _mustBeDeleted = false; } }; #endif diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.cpp b/src/libs/7zip/win/CPP/Windows/FileFind.cpp index e3358f905..7f58288fe 100644 --- a/src/libs/7zip/win/CPP/Windows/FileFind.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileFind.cpp @@ -4,6 +4,7 @@ #include "FileFind.h" #include "FileIO.h" +#include "FileName.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif @@ -12,45 +13,55 @@ extern bool g_IsNT; #endif -namespace NWindows { -namespace NFile { +using namespace NWindows; +using namespace NFile; +using namespace NName; -#ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n); -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n); -#endif -#endif +#if defined(_WIN32) && !defined(UNDER_CE) -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif +EXTERN_C_BEGIN + +typedef enum +{ + My_FindStreamInfoStandard, + My_FindStreamInfoMaxInfoLevel +} MY_STREAM_INFO_LEVELS; + +typedef struct +{ + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; -bool GetLongPath(LPCWSTR fileName, UString &res); +typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, + LPVOID findStreamData, DWORD flags); -namespace NFind { +typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); -static const TCHAR kDot = TEXT('.'); +EXTERN_C_END -bool CFileInfo::IsDots() const +#endif + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE +namespace NSystem { - if (!IsDir() || Name.IsEmpty()) - return false; - if (Name[0] != kDot) - return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } +#endif -#ifndef _UNICODE -bool CFileInfoW::IsDots() const +namespace NFind { + +bool CFileInfo::IsDots() const throw() { if (!IsDir() || Name.IsEmpty()) return false; - if (Name[0] != kDot) + if (Name[0] != FTEXT('.')) return false; - return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.')); } -#endif #define WIN_FD_TO_MY_FI(fi, fd) \ fi.Attrib = fd.dwFileAttributes; \ @@ -58,6 +69,7 @@ bool CFileInfoW::IsDots() const fi.ATime = fd.ftLastAccessTime; \ fi.MTime = fd.ftLastWriteTime; \ fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + fi.IsAltStream = false; \ fi.IsDevice = false; /* @@ -68,33 +80,31 @@ bool CFileInfoW::IsDots() const #endif */ -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; + fi.Name = us2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = us2fs(fd.cAlternateFileName); + #endif } #ifndef _UNICODE -static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) -{ - WIN_FD_TO_MY_FI(fi, fd); - fi.Name = fd.cFileName; -} - -static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { WIN_FD_TO_MY_FI(fi, fd); - fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); + fi.Name = fas2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = fas2fs(fd.cAlternateFileName); + #endif } #endif - + //////////////////////////////// // CFindFile -bool CFindFile::Close() +bool CFindFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; @@ -104,183 +114,344 @@ bool CFindFile::Close() return true; } - -bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fi) +bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) { if (!Close()) return false; - WIN32_FIND_DATA fd; - _handle = ::FindFirstFile(wildcard, &fd); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) + #ifndef _UNICODE + if (!g_IsNT) { - UString longPath; - if (GetLongPath(wildcard, longPath)) - _handle = ::FindFirstFileW(longPath, &fd); + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(fs2fas(path), &fd); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } + else #endif - if (_handle == INVALID_HANDLE_VALUE) - return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return true; -} - -#ifndef _UNICODE -bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fi) -{ - if (!Close()) - return false; - if (g_IsNT) { WIN32_FIND_DATAW fd; - _handle = ::FindFirstFileW(wildcard, &fd); + + IF_USE_MAIN_PATH + _handle = ::FindFirstFileW(fs2us(path), &fd); #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString longPath; - if (GetLongPath(wildcard, longPath)) + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) _handle = ::FindFirstFileW(longPath, &fd); } #endif - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } - else + return true; +} + +bool CFindFile::FindNext(CFileInfo &fi) +{ + #ifndef _UNICODE + if (!g_IsNT) { WIN32_FIND_DATAA fd; - _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, - GetCurrentCodePage()), &fd); - if (_handle != INVALID_HANDLE_VALUE) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + if (!::FindNextFileA(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); } - return (_handle != INVALID_HANDLE_VALUE); + else + #endif + { + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; } -#endif -bool CFindFile::FindNext(CFileInfo &fi) +#if defined(_WIN32) && !defined(UNDER_CE) + +//////////////////////////////// +// AltStreams + +static FindFirstStreamW_Ptr g_FindFirstStreamW; +static FindNextStreamW_Ptr g_FindNextStreamW; + +struct CFindStreamLoader { - WIN32_FIND_DATA fd; - bool result = BOOLToBool(::FindNextFile(_handle, &fd)); - if (result) - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); - return result; + CFindStreamLoader() + { + g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW"); + } +} g_FindStreamLoader; + +bool CStreamInfo::IsMainStream() const throw() +{ + return Name == L"::$DATA"; +}; + +UString CStreamInfo::GetReducedName() const +{ + UString s = Name; + if (s.Len() >= 6) + if (wcscmp(s.RightPtr(6), L":$DATA") == 0) + s.DeleteFrom(s.Len() - 6); + return s; } -#ifndef _UNICODE -bool CFindFile::FindNext(CFileInfoW &fi) +static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) +{ + si.Size = sd.StreamSize.QuadPart; + si.Name = sd.cStreamName; +} + +bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) { - if (g_IsNT) + if (!Close()) + return false; + if (!g_FindFirstStreamW) { - WIN32_FIND_DATAW fd; - if (!::FindNextFileW(_handle, &fd)) + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + IF_USE_MAIN_PATH + _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); + if (_handle == INVALID_HANDLE_VALUE) + { + if (::GetLastError() == ERROR_HANDLE_EOF) + return false; + // long name can be tricky for path like ".\dirName". + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + _handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0); + } + #endif + } + if (_handle == INVALID_HANDLE_VALUE) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } - else + return true; +} + +bool CFindStream::FindNext(CStreamInfo &si) +{ + if (!g_FindNextStreamW) { - WIN32_FIND_DATAA fd; - if (!::FindNextFileA(_handle, &fd)) + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + if (!g_FindNextStreamW(_handle, &sd)) return false; - ConvertWIN32_FIND_DATA_To_FileInfo(fd, fi); + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); } return true; } + +bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) +{ + bool res; + if (_find.IsHandleAllocated()) + res = _find.FindNext(si); + else + res = _find.FindFirst(_filePath, si); + if (res) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_HANDLE_EOF); +} + #endif + #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; -void CFileInfoBase::Clear() +void CFileInfoBase::Clear() throw() { Size = 0; MY_CLEAR_FILETIME(CTime); MY_CLEAR_FILETIME(ATime); MY_CLEAR_FILETIME(MTime); Attrib = 0; + IsAltStream = false; + IsDevice = false; } - -bool CFileInfo::Find(LPCTSTR wildcard) + +#if defined(_WIN32) && !defined(UNDER_CE) + +static int FindAltStreamColon(CFSTR path) { - #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) + for (int i = 0;; i++) { - Clear(); - IsDevice = true; - NIO::CInFile inFile; - if (!inFile.Open(wildcard)) - return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; - return true; + FChar c = path[i]; + if (c == 0) + return -1; + if (c == ':') + { + if (path[i + 1] == '\\') + if (i == 1 || (i > 1 && path[i - 2] == '\\')) + { + wchar_t c0 = path[i - 1]; + if (c0 >= 'a' && c0 <= 'z' || + c0 >= 'A' && c0 <= 'Z') + continue; + } + return i; + } } - #endif - CFindFile finder; - return finder.FindFirst(wildcard, *this); } +#endif -#ifndef _UNICODE -bool CFileInfoW::Find(LPCWSTR wildcard) +bool CFileInfo::Find(CFSTR path) { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceName(wildcard)) + if (IsDevicePath(path)) { Clear(); + Name = path + 4; + IsDevice = true; + if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */ + path[5] == ':' && path[6] == 0) + { + FChar drive[4] = { path[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) + { + Size = totalSize; + return true; + } + } + NIO::CInFile inFile; - if (!inFile.Open(wildcard)) + // ::OutputDebugStringW(path); + if (!inFile.Open(path)) return false; - Name = wildcard + 4; - if (inFile.LengthDefined) - Size = inFile.Length; + // ::OutputDebugStringW(L"---"); + if (inFile.SizeDefined) + Size = inFile.Size; return true; } #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + int colonPos = FindAltStreamColon(path); + if (colonPos >= 0) + { + UString streamName = fs2us(path + (unsigned)colonPos); + FString filePath = path; + filePath.DeleteFrom(colonPos); + streamName += L":$DATA"; // change it!!!! + if (Find(filePath)) + { + // if (IsDir()) + Attrib &= ~FILE_ATTRIBUTE_DIRECTORY; + Size = 0; + CStreamEnumerator enumerator(filePath); + for (;;) + { + CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + return false; + if (!found) + { + ::SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } + if (si.Name.IsEqualToNoCase(streamName)) + { + Name += us2fs(si.Name); + Name.DeleteFrom(Name.Len() - 6); + Size = si.Size; + IsAltStream = true; + return true; + } + } + } + } + + #endif + CFindFile finder; - return finder.FindFirst(wildcard, *this); + if (finder.FindFirst(path, *this)) + return true; + #ifdef _WIN32 + { + DWORD lastError = GetLastError(); + if (lastError == ERROR_BAD_NETPATH || + lastError == ERROR_FILE_NOT_FOUND || + lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared" + ) + { + unsigned len = MyStringLen(path); + if (len > 2 && path[0] == '\\' && path[1] == '\\') + { + int startPos = 2; + if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path)) + startPos = kSuperUncPathPrefixSize; + int pos = FindCharPosInString(path + startPos, FTEXT('\\')); + if (pos >= 0) + { + pos += startPos + 1; + len -= pos; + int pos2 = FindCharPosInString(path + pos, FTEXT('\\')); + if (pos2 < 0 || pos2 == (int)len - 1) + { + FString s = path; + if (pos2 < 0) + { + pos2 = len; + s += FTEXT('\\'); + } + s += FCHAR_ANY_MASK; + if (finder.FindFirst(s, *this)) + if (Name == FTEXT(".")) + { + Name.SetFrom(s.Ptr(pos), pos2); + return true; + } + ::SetLastError(lastError); + } + } + } + } + } + #endif + return false; } -#endif -bool DoesFileExist(LPCTSTR name) +bool DoesFileExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && !fi.IsDir(); } -bool DoesDirExist(LPCTSTR name) +bool DoesDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name) && fi.IsDir(); } - -bool DoesFileOrDirExist(LPCTSTR name) +bool DoesFileOrDirExist(CFSTR name) { CFileInfo fi; return fi.Find(name); } -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && !fi.IsDir(); -} - -bool DoesDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name) && fi.IsDir(); -} -bool DoesFileOrDirExist(LPCWSTR name) -{ - CFileInfoW fi; - return fi.Find(name); -} -#endif - -///////////////////////////////////// -// CEnumerator - bool CEnumerator::NextAny(CFileInfo &fi) { if (_findFile.IsHandleAllocated()) @@ -311,44 +482,11 @@ bool CEnumerator::Next(CFileInfo &fi, bool &found) return (::GetLastError() == ERROR_NO_MORE_FILES); } -#ifndef _UNICODE -bool CEnumeratorW::NextAny(CFileInfoW &fi) -{ - if (_findFile.IsHandleAllocated()) - return _findFile.FindNext(fi); - else - return _findFile.FindFirst(_wildcard, fi); -} - -bool CEnumeratorW::Next(CFileInfoW &fi) -{ - for (;;) - { - if (!NextAny(fi)) - return false; - if (!fi.IsDots()) - return true; - } -} - -bool CEnumeratorW::Next(CFileInfoW &fi, bool &found) -{ - if (Next(fi)) - { - found = true; - return true; - } - found = false; - return (::GetLastError() == ERROR_NO_MORE_FILES); -} - -#endif - //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. -bool CFindChangeNotification::Close() +bool CFindChangeNotification::Close() throw() { if (!IsHandleAllocated()) return true; @@ -357,105 +495,84 @@ bool CFindChangeNotification::Close() _handle = INVALID_HANDLE_VALUE; return true; } - -HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) -{ - _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH2 - if (!IsHandleAllocated()) - { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); - } - #endif - return _handle; -} -#ifndef _UNICODE -HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) +HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) { + #ifndef _UNICODE if (!g_IsNT) - return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); - _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); - #ifdef WIN_LONG_PATH - if (!IsHandleAllocated()) + _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); + else + #endif { - UString longPath; - if (GetLongPath(pathName, longPath)) - _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + IF_USE_MAIN_PATH + _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString longPath; + if (GetSuperPath(path, longPath, USE_MAIN_PATH)) + _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif } - #endif return _handle; } -#endif #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) + +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings) { driveStrings.Clear(); - UINT32 size = GetLogicalDriveStrings(0, NULL); - if (size == 0) - return false; - CSysString buffer; - UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); - if (newSize == 0) - return false; - if (newSize > size) - return false; - CSysString string; - for (UINT32 i = 0; i < newSize; i++) + #ifndef _UNICODE + if (!g_IsNT) { - TCHAR c = buffer[i]; - if (c == TEXT('\0')) + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + AString buf; + UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) + return false; + AString s; + for (UINT32 i = 0; i < newSize; i++) { - driveStrings.Add(string); - string.Empty(); + char c = buf[i]; + if (c == '\0') + { + driveStrings.Add(fas2fs(s)); + s.Empty(); + } + else + s += c; } - else - string += c; + return s.IsEmpty(); } - if (!string.IsEmpty()) - return false; - return true; -} - -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings) -{ - driveStrings.Clear(); - if (g_IsNT) + else + #endif { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; - UString buffer; - UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); - if (newSize == 0) - return false; - if (newSize > size) + UString buf; + UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size)); + if (newSize == 0 || newSize > size) return false; - UString string; + UString s; for (UINT32 i = 0; i < newSize; i++) { - WCHAR c = buffer[i]; + WCHAR c = buf[i]; if (c == L'\0') { - driveStrings.Add(string); - string.Empty(); + driveStrings.Add(us2fs(s)); + s.Empty(); } else - string += c; + s += c; } - return string.IsEmpty(); + return s.IsEmpty(); } - CSysStringVector driveStringsA; - bool res = MyGetLogicalDriveStrings(driveStringsA); - for (int i = 0; i < driveStringsA.Size(); i++) - driveStrings.Add(GetUnicodeString(driveStringsA[i])); - return res; } -#endif #endif diff --git a/src/libs/7zip/win/CPP/Windows/FileFind.h b/src/libs/7zip/win/CPP/Windows/FileFind.h index 63631f66b..aaa7499bd 100644 --- a/src/libs/7zip/win/CPP/Windows/FileFind.h +++ b/src/libs/7zip/win/CPP/Windows/FileFind.h @@ -1,12 +1,10 @@ // Windows/FileFind.h -#ifndef __WINDOWS_FILEFIND_H -#define __WINDOWS_FILEFIND_H +#ifndef __WINDOWS_FILE_FIND_H +#define __WINDOWS_FILE_FIND_H #include "../Common/MyString.h" -#include "../Common/Types.h" #include "Defs.h" -#include "FileName.h" namespace NWindows { namespace NFile { @@ -26,14 +24,13 @@ namespace NAttributes class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } -protected: - void Clear(); public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; + bool IsAltStream; bool IsDevice; /* @@ -44,6 +41,11 @@ public: #endif */ + CFileInfoBase() { Clear(); } + void Clear() throw(); + + void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } + bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } @@ -60,78 +62,80 @@ public: struct CFileInfo: public CFileInfoBase { - CSysString Name; + FString Name; + #if defined(_WIN32) && !defined(UNDER_CE) + // FString ShortName; + #endif + + bool IsDots() const throw(); + bool Find(CFSTR wildcard); +}; + +class CFindFileBase +{ +protected: + HANDLE _handle; +public: + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } + CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFileBase() { Close(); } + bool Close() throw(); +}; - bool IsDots() const; - bool Find(LPCTSTR wildcard); +class CFindFile: public CFindFileBase +{ +public: + bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); + bool FindNext(CFileInfo &fileInfo); }; -#ifdef _UNICODE -typedef CFileInfo CFileInfoW; -#else -struct CFileInfoW: public CFileInfoBase +#if defined(_WIN32) && !defined(UNDER_CE) + +struct CStreamInfo { UString Name; + UInt64 Size; - bool IsDots() const; - bool Find(LPCWSTR wildcard); + UString GetReducedName() const; + bool IsMainStream() const throw(); }; -#endif -class CFindFile +class CFindStream: public CFindFileBase { - friend class CEnumerator; - HANDLE _handle; public: - bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } - CFindFile(): _handle(INVALID_HANDLE_VALUE) {} - ~CFindFile() { Close(); } - bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); - bool FindNext(CFileInfo &fileInfo); - #ifndef _UNICODE - bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); - bool FindNext(CFileInfoW &fileInfo); - #endif - bool Close(); + bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); + bool FindNext(CStreamInfo &streamInfo); +}; + +class CStreamEnumerator +{ + CFindStream _find; + FString _filePath; + + bool NextAny(CFileInfo &fileInfo); +public: + CStreamEnumerator(const FString &filePath): _filePath(filePath) {} + bool Next(CStreamInfo &streamInfo, bool &found); }; -bool DoesFileExist(LPCTSTR name); -bool DoesDirExist(LPCTSTR name); -bool DoesFileOrDirExist(LPCTSTR name); -#ifndef _UNICODE -bool DoesFileExist(LPCWSTR name); -bool DoesDirExist(LPCWSTR name); -bool DoesFileOrDirExist(LPCWSTR name); #endif +bool DoesFileExist(CFSTR name); +bool DoesDirExist(CFSTR name); +bool DoesFileOrDirExist(CFSTR name); + class CEnumerator { CFindFile _findFile; - CSysString _wildcard; + FString _wildcard; + bool NextAny(CFileInfo &fileInfo); public: - CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} - CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} + CEnumerator(const FString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; -#ifdef _UNICODE -typedef CEnumerator CEnumeratorW; -#else -class CEnumeratorW -{ - CFindFile _findFile; - UString _wildcard; - bool NextAny(CFileInfoW &fileInfo); -public: - CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} - CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} - bool Next(CFileInfoW &fileInfo); - bool Next(CFileInfoW &fileInfo, bool &found); -}; -#endif - class CFindChangeNotification { HANDLE _handle; @@ -140,22 +144,15 @@ public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } - bool Close(); - HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); - #ifndef _UNICODE - HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); - #endif + bool Close() throw(); + HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef UNDER_CE -bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); -#ifndef _UNICODE -bool MyGetLogicalDriveStrings(UStringVector &driveStrings); -#endif +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings); #endif }}} #endif - diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.cpp b/src/libs/7zip/win/CPP/Windows/FileIO.cpp index 938e6c701..fec859ed3 100644 --- a/src/libs/7zip/win/CPP/Windows/FileIO.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileIO.cpp @@ -2,161 +2,86 @@ #include "StdAfx.h" -#include "FileIO.h" - -#if defined(WIN_LONG_PATH) || defined(SUPPORT_DEVICE_FILE) -#include "../Common/MyString.h" -#endif -#ifndef _UNICODE -#include "../Common/StringConvert.h" +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" #endif +#include "FileIO.h" +#include "FileName.h" + #ifndef _UNICODE extern bool g_IsNT; #endif +using namespace NWindows; +using namespace NFile; +using namespace NName; + namespace NWindows { namespace NFile { #ifdef SUPPORT_DEVICE_FILE -bool IsDeviceName(LPCTSTR n) -{ - #ifdef UNDER_CE - int len = (int)MyStringLen(n); - if (len < 5 || len > 5 || memcmp(n, TEXT("DSK"), 3 * sizeof(TCHAR)) != 0) - return false; - if (n[4] != ':') - return false; - // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); - #else - if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') - return false; - int len = (int)MyStringLen(n); - if (len == 6 && n[5] == ':') - return true; - if (len < 18 || len > 22 || memcmp(n + 4, TEXT("PhysicalDrive"), 13 * sizeof(TCHAR)) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - #endif - return true; -} -#ifndef _UNICODE -bool IsDeviceName(LPCWSTR n) +namespace NSystem { - if (n[0] != '\\' || n[1] != '\\' || n[2] != '.' || n[3] != '\\') - return false; - int len = (int)wcslen(n); - if (len == 6 && n[5] == ':') - return true; - if (len < 18 || len > 22 || wcsncmp(n + 4, L"PhysicalDrive", 13) != 0) - return false; - for (int i = 17; i < len; i++) - if (n[i] < '0' || n[i] > '9') - return false; - return true; +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); } #endif -#endif -#if defined(WIN_LONG_PATH) && defined(_UNICODE) -#define WIN_LONG_PATH2 -#endif - -#ifdef WIN_LONG_PATH -bool GetLongPathBase(LPCWSTR s, UString &res) -{ - res.Empty(); - int len = MyStringLen(s); - wchar_t c = s[0]; - if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) - return true; - UString curDir; - bool isAbs = false; - if (len > 3) - isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); +namespace NIO { - if (!isAbs) - { - DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); - curDir.ReleaseBuffer(); - if (needLength == 0 || needLength > MAX_PATH) - return false; - if (curDir[curDir.Length() - 1] != L'\\') - curDir += L'\\'; - } - res = UString(L"\\\\?\\") + curDir + s; - return true; -} +/* +WinXP-64 CreateFile(): + "" - ERROR_PATH_NOT_FOUND + :stream - OK + .:stream - ERROR_PATH_NOT_FOUND + .\:stream - OK -bool GetLongPath(LPCWSTR path, UString &longPath) -{ - if (GetLongPathBase(path, longPath)) - return !longPath.IsEmpty(); - return false; -} -#endif + folder\:stream - ERROR_INVALID_NAME + folder:stream - OK -namespace NIO { + c:\:stream - OK -CFileBase::~CFileBase() { Close(); } + c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) + c::stream - OK, if current dir is ROOT ( c:\ ) +*/ -bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, +bool CFileBase::Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; - _handle = ::CreateFile(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH2 - if (_handle == INVALID_HANDLE_VALUE) - { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - } - #endif + #ifdef SUPPORT_DEVICE_FILE IsDeviceFile = false; #endif - return (_handle != INVALID_HANDLE_VALUE); -} -#ifndef _UNICODE -bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ + #ifndef _UNICODE if (!g_IsNT) - return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), - desiredAccess, shareMode, creationDisposition, flagsAndAttributes); - if (!Close()) - return false; - _handle = ::CreateFileW(fileName, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); - #ifdef WIN_LONG_PATH - if (_handle == INVALID_HANDLE_VALUE) { - UString longPath; - if (GetLongPath(fileName, longPath)) - _handle = ::CreateFileW(longPath, desiredAccess, shareMode, - (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, - flagsAndAttributes, (HANDLE)NULL); + _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } + else #endif - #ifdef SUPPORT_DEVICE_FILE - IsDeviceFile = false; - #endif + { + IF_USE_MAIN_PATH + _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::CreateFileW(superPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + #endif + } return (_handle != INVALID_HANDLE_VALUE); } -#endif -bool CFileBase::Close() +bool CFileBase::Close() throw() { if (_handle == INVALID_HANDLE_VALUE) return true; @@ -166,17 +91,17 @@ bool CFileBase::Close() return true; } -bool CFileBase::GetPosition(UInt64 &position) const +bool CFileBase::GetPosition(UInt64 &position) const throw() { return Seek(0, FILE_CURRENT, position); } -bool CFileBase::GetLength(UInt64 &length) const +bool CFileBase::GetLength(UInt64 &length) const throw() { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined) + if (IsDeviceFile && SizeDefined) { - length = Length; + length = Size; return true; } #endif @@ -190,127 +115,211 @@ bool CFileBase::GetLength(UInt64 &length) const return true; } -bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() { #ifdef SUPPORT_DEVICE_FILE - if (IsDeviceFile && LengthDefined && moveMethod == FILE_END) + if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) { - distanceToMove += Length; + distanceToMove += Size; moveMethod = FILE_BEGIN; } #endif - LARGE_INTEGER value; - value.QuadPart = distanceToMove; - value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); - if (value.LowPart == 0xFFFFFFFF) + LONG high = (LONG)(distanceToMove >> 32); + DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); + if (low == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; - newPosition = value.QuadPart; + newPosition = (((UInt64)high) << 32) + low; return true; } -bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() { return Seek(position, FILE_BEGIN, newPosition); } -bool CFileBase::SeekToBegin() +bool CFileBase::SeekToBegin() const throw() { UInt64 newPosition; return Seek(0, newPosition); } -bool CFileBase::SeekToEnd(UInt64 &newPosition) +bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() { return Seek(0, FILE_END, newPosition); } -bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const +// ---------- CInFile --------- + +#ifdef SUPPORT_DEVICE_FILE + +void CInFile::CorrectDeviceSize() { - BY_HANDLE_FILE_INFORMATION winFileInfo; - if (!::GetFileInformationByHandle(_handle, &winFileInfo)) - return false; - fileInfo.Attrib = winFileInfo.dwFileAttributes; - fileInfo.CTime = winFileInfo.ftCreationTime; - fileInfo.ATime = winFileInfo.ftLastAccessTime; - fileInfo.MTime = winFileInfo.ftLastWriteTime; - fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; - fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; - fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; - fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; - return true; + // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail + static const UInt32 kClusterSize = 1 << 14; + UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); + UInt64 realNewPosition; + if (!Seek(pos, realNewPosition)) + return; + Byte *buf = (Byte *)MidAlloc(kClusterSize); + + bool needbackward = true; + + for (;;) + { + UInt32 processed = 0; + // up test is slow for "PhysicalDrive". + // processed size for latest block for "PhysicalDrive0" is 0. + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed == 0) + break; + needbackward = false; + Size = pos + processed; + if (processed != kClusterSize) + break; + pos += kClusterSize; + } + + if (needbackward && pos != 0) + { + pos -= kClusterSize; + for (;;) + { + // break; + if (!Seek(pos, realNewPosition)) + break; + if (!buf) + { + buf = (Byte *)MidAlloc(kClusterSize); + if (!buf) + break; + } + UInt32 processed = 0; + // that code doesn't work for "PhysicalDrive0" + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed != 0) + { + Size = pos + processed; + break; + } + if (pos == 0) + break; + pos -= kClusterSize; + } + } + MidFree(buf); } -///////////////////////// -// CInFile -#ifdef SUPPORT_DEVICE_FILE -void CInFile::GetDeviceLength() +void CInFile::CalcDeviceSize(CFSTR s) { - if (_handle != INVALID_HANDLE_VALUE && IsDeviceFile) - { - #ifdef UNDER_CE - LengthDefined = true; - Length = 128 << 20; + SizeDefined = false; + Size = 0; + if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) + return; + #ifdef UNDER_CE + + SizeDefined = true; + Size = 128 << 20; + + #else + + PARTITION_INFORMATION partInfo; + bool needCorrectSize = true; - #else - PARTITION_INFORMATION partInfo; - LengthDefined = true; - Length = 0; + /* + WinXP 64-bit: + + HDD \\.\PhysicalDrive0 (MBR): + GetPartitionInfo == GeometryEx : corrrect size? (includes tail) + Geometry : smaller than GeometryEx (no tail, maybe correct too?) + MyGetDiskFreeSpace : FAIL + Size correction is slow and block size (kClusterSize) must be small? + + HDD partition \\.\N: (NTFS): + MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction + GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS + Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) + + CD-ROM drive (ISO): + MyGetDiskFreeSpace : correct size. Same size can be calculated after correction + Geometry == CdRomGeometry : smaller than corrrect size + GetPartitionInfo == GeometryEx : larger than corrrect size + + Floppy \\.\a: (FAT): + Geometry : correct size. + CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL + correction works OK for FAT. + correction works OK for non-FAT, if kClusterSize = 512. + */ + + if (GetPartitionInfo(&partInfo)) + { + Size = partInfo.PartitionLength.QuadPart; + SizeDefined = true; + needCorrectSize = false; + if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) + { + FChar path[4] = { s[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) + Size = totalSize; + else + needCorrectSize = true; + } + } - if (GetPartitionInfo(&partInfo)) - Length = partInfo.PartitionLength.QuadPart; + if (!SizeDefined) + { + my_DISK_GEOMETRY_EX geomEx; + SizeDefined = GetGeometryEx(&geomEx); + if (SizeDefined) + Size = geomEx.DiskSize.QuadPart; else { DISK_GEOMETRY geom; - if (!GetGeometry(&geom)) - if (!GetCdRomGeometry(&geom)) - LengthDefined = false; - if (LengthDefined) - Length = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + SizeDefined = GetGeometry(&geom); + if (!SizeDefined) + SizeDefined = GetCdRomGeometry(&geom); + if (SizeDefined) + Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; } - // SeekToBegin(); - #endif } + + if (needCorrectSize && SizeDefined && Size != 0) + { + CorrectDeviceSize(); + SeekToBegin(); + } + + // SeekToBegin(); + #endif } // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && #define MY_DEVICE_EXTRA_CODE \ - IsDeviceFile = IsDeviceName(fileName); \ - GetDeviceLength(); + IsDeviceFile = IsDevicePath(fileName); \ + CalcDeviceSize(fileName); #else #define MY_DEVICE_EXTRA_CODE #endif -bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) -{ - bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); - MY_DEVICE_EXTRA_CODE - return res; -} - -bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } - -bool CInFile::Open(LPCTSTR fileName) - { return OpenShared(fileName, false); } - -#ifndef _UNICODE -bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); MY_DEVICE_EXTRA_CODE return res; } -bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) +bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } -bool CInFile::Open(LPCWSTR fileName) +bool CInFile::Open(CFSTR fileName) { return OpenShared(fileName, false); } -#endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) @@ -323,7 +332,7 @@ bool CInFile::Open(LPCWSTR fileName) static UInt32 kChunkSizeMax = (1 << 22); -bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() { DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); @@ -331,14 +340,14 @@ bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) return res; } -bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; return Read1(data, size, processedSize); } -bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do @@ -357,40 +366,29 @@ bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) return true; } -///////////////////////// -// COutFile - -bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) - { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } +// ---------- COutFile --------- static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } -bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) - { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } - -bool COutFile::Create(LPCTSTR fileName, bool createAlways) - { return Open(fileName, GetCreationDisposition(createAlways)); } - -#ifndef _UNICODE - -bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } -bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) +bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } -bool COutFile::Create(LPCWSTR fileName, bool createAlways) +bool COutFile::Create(CFSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } -#endif +bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) + { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } -bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } -bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } +bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } -bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() { if (size > kChunkSizeMax) size = kChunkSizeMax; @@ -400,7 +398,7 @@ bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) return res; } -bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() { processedSize = 0; do @@ -419,9 +417,9 @@ bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) return true; } -bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } +bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } -bool COutFile::SetLength(UInt64 length) +bool COutFile::SetLength(UInt64 length) throw() { UInt64 newPosition; if (!Seek(length, newPosition)) diff --git a/src/libs/7zip/win/CPP/Windows/FileIO.h b/src/libs/7zip/win/CPP/Windows/FileIO.h index dce692fed..f595121ef 100644 --- a/src/libs/7zip/win/CPP/Windows/FileIO.h +++ b/src/libs/7zip/win/CPP/Windows/FileIO.h @@ -1,134 +1,199 @@ // Windows/FileIO.h -#ifndef __WINDOWS_FILEIO_H -#define __WINDOWS_FILEIO_H +#ifndef __WINDOWS_FILE_IO_H +#define __WINDOWS_FILE_IO_H -#include "../Common/Types.h" +#if defined(_WIN32) && !defined(UNDER_CE) +#include +#endif + +#include "../Common/MyString.h" +#include "../Common/MyBuffer.h" #include "Defs.h" +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER + namespace NWindows { namespace NFile { -namespace NIO { -struct CByHandleFileInfo +#if defined(_WIN32) && !defined(UNDER_CE) +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink); +#endif + +struct CReparseShortInfo +{ + unsigned Offset; + unsigned Size; + + bool Parse(const Byte *p, size_t size); +}; + +struct CReparseAttr { - DWORD Attrib; - FILETIME CTime; - FILETIME ATime; - FILETIME MTime; - DWORD VolumeSerialNumber; - UInt64 Size; - DWORD NumberOfLinks; - UInt64 FileIndex; + UInt32 Tag; + UInt32 Flags; + UString SubsName; + UString PrintName; + + CReparseAttr(): Tag(0), Flags(0) {} + bool Parse(const Byte *p, size_t size); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + // bool IsVolume() const; + + bool IsOkNamePair() const; + UString GetPath() const; }; +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); + class CFileBase { protected: HANDLE _handle; - - bool Create(LPCTSTR fileName, DWORD desiredAccess, - DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #ifndef _UNICODE - bool Create(LPCWSTR fileName, DWORD desiredAccess, + + bool Create(CFSTR path, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - #endif + +public: + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const + { + return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { + DWORD bytesReturned; + return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); + } public: #ifdef SUPPORT_DEVICE_FILE bool IsDeviceFile; - bool LengthDefined; - UInt64 Length; + bool SizeDefined; + UInt64 Size; // it can be larger than real available size #endif CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; - ~CFileBase(); + ~CFileBase() { Close(); } + + bool Close() throw(); + + bool GetPosition(UInt64 &position) const throw(); + bool GetLength(UInt64 &length) const throw(); - bool Close(); + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); + bool Seek(UInt64 position, UInt64 &newPosition) const throw(); + bool SeekToBegin() const throw(); + bool SeekToEnd(UInt64 &newPosition) const throw(); - bool GetPosition(UInt64 &position) const; - bool GetLength(UInt64 &length) const; + bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const + { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } - bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; - bool Seek(UInt64 position, UInt64 &newPosition); - bool SeekToBegin(); - bool SeekToEnd(UInt64 &newPosition); - - bool GetFileInformation(CByHandleFileInfo &fileInfo) const; + static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) + { + NIO::CFileBase file; + if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) + return false; + return file.GetFileInformation(info); + } }; +#ifndef UNDER_CE #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + +// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP +#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct my_DISK_GEOMETRY_EX +{ + DISK_GEOMETRY Geometry; + LARGE_INTEGER DiskSize; + BYTE Data[1]; +}; +#endif class CInFile: public CFileBase { #ifdef SUPPORT_DEVICE_FILE - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, - LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped) const - { - return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, - outBuffer, outSize, bytesReturned, overlapped)); - } - - bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, - DWORD inSize, LPVOID outBuffer, DWORD outSize) const - { - DWORD ret; - return DeviceIoControl(controlCode, inBuffer, inSize, outBuffer, outSize, &ret, 0); - } - - bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const - { return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize); } #ifndef UNDER_CE + bool GetGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const + { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } + bool GetCdRomGeometry(DISK_GEOMETRY *res) const { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } - + bool GetPartitionInfo(PARTITION_INFORMATION *res) { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + #endif - void GetDeviceLength(); + void CorrectDeviceSize(); + void CalcDeviceSize(CFSTR name); + #endif public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCTSTR fileName, bool shareForWrite); - bool Open(LPCTSTR fileName); - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool OpenShared(LPCWSTR fileName, bool shareForWrite); - bool Open(LPCWSTR fileName); + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(CFSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName); + + #ifndef UNDER_CE + + bool OpenReparse(CFSTR fileName) + { + return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); + } + #endif - bool Read1(void *data, UInt32 size, UInt32 &processedSize); - bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); - bool Read(void *data, UInt32 size, UInt32 &processedSize); + + bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); }; class COutFile: public CFileBase { public: - bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCTSTR fileName, DWORD creationDisposition); - bool Create(LPCTSTR fileName, bool createAlways); - - #ifndef _UNICODE - bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); - bool Open(LPCWSTR fileName, DWORD creationDisposition); - bool Create(LPCWSTR fileName, bool createAlways); - #endif - - bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); - bool SetMTime(const FILETIME *mTime); - bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); - bool Write(const void *data, UInt32 size, UInt32 &processedSize); - bool SetEndOfFile(); - bool SetLength(UInt64 length); + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(CFSTR fileName, DWORD creationDisposition); + bool Create(CFSTR fileName, bool createAlways); + bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool SetEndOfFile() throw(); + bool SetLength(UInt64 length) throw(); }; }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileLink.cpp b/src/libs/7zip/win/CPP/Windows/FileLink.cpp new file mode 100644 index 000000000..dc524700d --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/FileLink.cpp @@ -0,0 +1,426 @@ +// Windows/FileLink.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +using namespace NName; + +/* + Reparse Points (Junctions and Symbolic Links): + struct + { + UInt32 Tag; + UInt16 Size; // not including starting 8 bytes + UInt16 Reserved; // = 0 + + UInt16 SubstituteOffset; // offset in bytes from start of namesChars + UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL + UInt16 PrintOffset; // offset in bytes from start of namesChars + UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL + + [UInt32] Flags; // for Symbolic Links only. + + UInt16 namesChars[] + } + + MOUNT_POINT (Junction point): + 1) there is NUL wchar after path + 2) Default Order in table: + Substitute Path + Print Path + 3) pathnames can not contain dot directory names + + SYMLINK: + 1) there is no NUL wchar after path + 2) Default Order in table: + Print Path + Substitute Path +*/ + +/* +static const UInt32 kReparseFlags_Alias = (1 << 29); +static const UInt32 kReparseFlags_HighLatency = (1 << 30); +static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); + +#define _my_IO_REPARSE_TAG_HSM (0xC0000004L) +#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L) +#define _my_IO_REPARSE_TAG_SIS (0x80000007L) +#define _my_IO_REPARSE_TAG_WIM (0x80000008L) +#define _my_IO_REPARSE_TAG_CSV (0x80000009L) +#define _my_IO_REPARSE_TAG_DFS (0x8000000AL) +#define _my_IO_REPARSE_TAG_DFSR (0x80000012L) +*/ + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static const wchar_t *k_LinkPrefix = L"\\??\\"; +static const unsigned k_LinkPrefix_Size = 4; + +static const bool IsLinkPrefix(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_LinkPrefix); +} + +/* +static const wchar_t *k_VolumePrefix = L"Volume{"; +static const bool IsVolumeName(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_VolumePrefix); +} +*/ + +void WriteString(Byte *dest, const wchar_t *path) +{ + for (;;) + { + wchar_t c = *path++; + if (c == 0) + return; + Set16(dest, (UInt16)c); + dest += 2; + } +} + +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) +{ + bool isAbs = IsAbsolutePath(path); + if (!isAbs && !isSymLink) + return false; + + bool needPrintName = true; + + if (IsSuperPath(path)) + { + path += kSuperPathPrefixSize; + if (!IsDrivePath(path)) + needPrintName = false; + } + + const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; + + unsigned len2 = MyStringLen(path) * 2; + const unsigned len1 = len2 + add_Prefix_Len * 2; + if (!needPrintName) + len2 = 0; + + unsigned totalNamesSize = (len1 + len2); + + /* some WIM imagex software uses old scheme for symbolic links. + so we can old scheme for byte to byte compatibility */ + + bool newOrderScheme = isSymLink; + // newOrderScheme = false; + + if (!newOrderScheme) + totalNamesSize += 2 * 2; + + const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + dest.Alloc(size); + memset(dest, 0, size); + const UInt32 tag = isSymLink ? + _my_IO_REPARSE_TAG_SYMLINK : + _my_IO_REPARSE_TAG_MOUNT_POINT; + Byte *p = dest; + Set32(p, tag); + Set16(p + 4, (UInt16)(size - 8)); + Set16(p + 6, 0); + p += 8; + + unsigned subOffs = 0; + unsigned printOffs = 0; + if (newOrderScheme) + subOffs = len2; + else + printOffs = len1 + 2; + + Set16(p + 0, (UInt16)subOffs); + Set16(p + 2, (UInt16)len1); + Set16(p + 4, (UInt16)printOffs); + Set16(p + 6, (UInt16)len2); + + p += 8; + if (isSymLink) + { + UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE; + Set32(p, flags); + p += 4; + } + + if (add_Prefix_Len != 0) + WriteString(p + subOffs, k_LinkPrefix); + WriteString(p + subOffs + add_Prefix_Len * 2, path); + if (needPrintName) + WriteString(p + printOffs, path); + return true; +} + +static void GetString(const Byte *p, unsigned len, UString &res) +{ + wchar_t *s = res.GetBuffer(len); + for (unsigned i = 0; i < len; i++) + s[i] = Get16(p + i * 2); + s[len] = 0; + res.ReleaseBuffer(); +} + +bool CReparseAttr::Parse(const Byte *p, size_t size) +{ + if (size < 8) + return false; + Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + GetString(p + subOffs, subLen >> 1, SubsName); + GetString(p + printOffs, printLen >> 1, PrintName); + + return true; +} + +bool CReparseShortInfo::Parse(const Byte *p, size_t size) +{ + const Byte *start = p; + Offset= 0; + Size = 0; + if (size < 8) + return false; + UInt32 Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + // UInt32 Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + // Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + + Offset = (unsigned)(p - start) + subOffs; + Size = subLen; + return true; +} + +bool CReparseAttr::IsOkNamePair() const +{ + if (IsLinkPrefix(SubsName)) + { + if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) + return PrintName.IsEmpty(); + if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) + return true; + } + return wcscmp(SubsName, PrintName) == 0; +} + +/* +bool CReparseAttr::IsVolume() const +{ + if (!IsLinkPrefix(SubsName)) + return false; + return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); +} +*/ + +UString CReparseAttr::GetPath() const +{ + UString s = SubsName; + if (IsLinkPrefix(s)) + { + s.ReplaceOneCharAtPos(1, '\\'); + if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) + s.DeleteFrontal(k_LinkPrefix_Size); + } + return s; +} + + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +#ifndef UNDER_CE + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) +{ + reparseData.Free(); + CInFile file; + if (!file.OpenReparse(path)) + return false; + + if (fileInfo) + file.GetFileInformation(fileInfo); + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + reparseData.CopyFrom(buf, returnedSize); + return true; +} + +static bool CreatePrefixDirOfFile(CFSTR path) +{ + FString path2 = path; + int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos < 0) + return true; + #ifdef _WIN32 + if (pos == 2 && path2[1] == L':') + return true; // we don't create Disk folder; + #endif + path2.DeleteFrom(pos); + return NDir::CreateComplexDir(path2); +} + +// If there is Reprase data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + NFile::NFind::CFileInfo fi; + if (fi.Find(path)) + { + if (fi.IsDir() != isDir) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + } + else + { + if (isDir) + { + if (!NDir::CreateComplexDir(path)) + return false; + } + else + { + CreatePrefixDirOfFile(path); + COutFile file; + if (!file.Create(path, CREATE_NEW)) + return false; + } + } + + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize)) + return false; + return true; +} + +} + +#endif + +}} diff --git a/src/libs/7zip/win/CPP/Windows/FileMapping.cpp b/src/libs/7zip/win/CPP/Windows/FileMapping.cpp deleted file mode 100644 index 55048fdb2..000000000 --- a/src/libs/7zip/win/CPP/Windows/FileMapping.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Windows/FileMapping.cpp - -#include "StdAfx.h" - -#include "Windows/FileMapping.h" - -namespace NWindows { -namespace NFile { -namespace NMapping { - - -}}} diff --git a/src/libs/7zip/win/CPP/Windows/FileMapping.h b/src/libs/7zip/win/CPP/Windows/FileMapping.h index 3f0ebd74c..f90c429f1 100644 --- a/src/libs/7zip/win/CPP/Windows/FileMapping.h +++ b/src/libs/7zip/win/CPP/Windows/FileMapping.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H -#include "Common/Types.h" +#include "../Common/MyTypes.h" #include "Handle.h" @@ -18,7 +18,11 @@ public: return ::GetLastError(); } - WRes Open(DWORD desiredAccess, LPCTSTR name) + WRes Open(DWORD + #ifndef UNDER_CE + desiredAccess + #endif + , LPCTSTR name) { #ifdef UNDER_CE WRes res = Create(PAGE_READONLY, 0, name); diff --git a/src/libs/7zip/win/CPP/Windows/FileName.cpp b/src/libs/7zip/win/CPP/Windows/FileName.cpp index 8443a4af9..0a6aee100 100644 --- a/src/libs/7zip/win/CPP/Windows/FileName.cpp +++ b/src/libs/7zip/win/CPP/Windows/FileName.cpp @@ -2,49 +2,686 @@ #include "StdAfx.h" -#include "Windows/FileName.h" -#include "Common/Wildcard.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif namespace NWindows { namespace NFile { namespace NName { -void NormalizeDirPathPrefix(CSysString &dirPath) +#ifndef USE_UNICODE_FSTRING +void NormalizeDirPathPrefix(FString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) - dirPath += kDirDelimiter; + if (dirPath.Back() != FCHAR_PATH_SEPARATOR) + dirPath += FCHAR_PATH_SEPARATOR; } +#endif -#ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; - if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) - dirPath += wchar_t(kDirDelimiter); + if (dirPath.Back() != WCHAR_PATH_SEPARATOR) + dirPath += WCHAR_PATH_SEPARATOR; +} + + +#ifdef _WIN32 + +const wchar_t *kSuperPathPrefix = L"\\\\?\\"; +static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\"; + +#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\') +#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\') +#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\') +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +#define IS_UNC_WITH_SLASH(s) ( \ + ((s)[0] == 'U' || (s)[0] == 'u') && \ + ((s)[1] == 'N' || (s)[1] == 'n') && \ + ((s)[2] == 'C' || (s)[2] == 'c') && \ + (s)[3] == '\\') + +bool IsDevicePath(CFSTR s) throw() +{ + #ifdef UNDER_CE + + s = s; + return false; + /* + // actually we don't know the way to open device file in WinCE. + unsigned len = MyStringLen(s); + if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0) + return false; + if (s[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + */ + + #else + + if (!IS_DEVICE_PATH(s)) + return false; + unsigned len = MyStringLen(s); + if (len == 6 && s[5] == ':') + return true; + if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0) + return false; + for (unsigned i = 17; i < len; i++) + if (s[i] < '0' || s[i] > '9') + return false; + return true; + + #endif +} + +bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } +bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +#endif // USE_UNICODE_FSTRING + +bool IsAbsolutePath(const wchar_t *s) throw() +{ + return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s); +} + +static const unsigned kDrivePrefixSize = 3; /* c:\ */ + +#ifndef USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, '\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, '\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(CFSTR s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#endif // USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindCharPosInString(s, L'\\'); + if (pos < 0) + return 0; + int pos2 = FindCharPosInString(s + pos + 1, L'\\'); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (s[0] != '\\' || s[1] != '\\') + return 0; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\'); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(const wchar_t *s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#else // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR } + +#ifndef USE_UNICODE_FSTRING +unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } +#endif +unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } + +#endif // _WIN32 + + +#ifndef UNDER_CE + +static bool GetCurDir(UString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fs2us(fas2fs(s)); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = s; + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +static bool ResolveDotsFolders(UString &s) +{ + #ifdef _WIN32 + s.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + for (int i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + return true; + if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR)) + { + wchar_t c1 = s[i + 1]; + if (c1 == '.') + { + wchar_t c2 = s[i + 2]; + if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0) + { + if (i == 0) + return false; + int k = i - 2; + for (; k >= 0; k--) + if (s[k] == WCHAR_PATH_SEPARATOR) + break; + unsigned num; + if (k >= 0) + { + num = i + 2 - k; + i = k; + } + else + { + num = (c2 == 0 ? (i + 2) : (i + 3)); + i = 0; + } + s.Delete(i, num); + continue; + } + } + else + { + if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0) + { + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; + } + } + } + i++; + } +} + +#endif // UNDER_CE + +#define LONG_PATH_DOTS_FOLDERS_PARSING + + +/* +Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ +To solve that problem we check such path: + - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper + - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain +*/ +#ifdef LONG_PATH_DOTS_FOLDERS_PARSING +#ifndef UNDER_CE +static bool AreThereDotsFolders(CFSTR s) +{ + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return false; + if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)) + { + FChar c1 = s[i + 1]; + if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR || + (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR))) + return true; + } + } } #endif +#endif // LONG_PATH_DOTS_FOLDERS_PARSING + +#ifdef WIN_LONG_PATH + +/* +Most of Windows versions have problems, if some file or dir name +contains '.' or ' ' at the end of name (Bad Path). +To solve that problem, we always use Super Path ("\\?\" prefix and full path) +in such cases. Note that "." and ".." are not bad names. + +There are 3 cases: + 1) If the path is already Super Path, we use that path + 2) If the path is not Super Path : + 2.1) Bad Path; we use only Super Path. + 2.2) Good Path; we use Main Path. If it fails, we use Super Path. + + NeedToUseOriginalPath returns: + kSuperPathType_UseOnlyMain : Super already + kSuperPathType_UseOnlySuper : not Super, Bad Path + kSuperPathType_UseMainAndSuper : not Super, Good Path +*/ + +int GetUseSuperPathType(CFSTR s) throw() +{ + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + if ((s)[2] != '.') + if (AreThereDotsFolders(s + kSuperPathPrefixSize)) + return kSuperPathType_UseOnlySuper; + #endif + return kSuperPathType_UseOnlyMain; + } + + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return kSuperPathType_UseMainAndSuper; + if (c == '.' || c == ' ') + { + FChar c2 = s[i + 1]; + if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR) + { + // if it's "." or "..", it's not bad name. + if (c == '.') + { + if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR) + continue; + if (s[i - 1] == '.') + { + if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR) + continue; + } + } + return kSuperPathType_UseOnlySuper; + } + } + } +} + + +/* + returns false in two cases: + - if GetCurDir was used, and GetCurDir returned error. + - if we can't resolve ".." name. + if path is ".", "..", res is empty. + if it's Super Path already, res is empty. + for \**** , and if GetCurDir is not drive (c:\), res is empty + for absolute paths, returns true, res is Super path. +*/ + + +static bool GetSuperPathBase(CFSTR s, UString &res) +{ + res.Empty(); + + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + + if ((s)[2] == '.') + return true; + + // we will return true here, so we will try to use these problem paths. + + if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) + return true; + + UString temp = fs2us(s); + unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); + if (fixedSize == 0) + return true; + + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return true; + + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + + #endif + + return true; + } + + if (c == CHAR_PATH_SEPARATOR) + { + if (s[1] == CHAR_PATH_SEPARATOR) + { + UString temp = fs2us(s + 2); + unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); + if (fixedSize == 0) // maybe we must ignore that error to allow short network paths? + return false; + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return false; + res += kSuperUncPrefix; + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + return true; + } + } + else + { + if (IsDrivePath(s)) + { + UString temp = fs2us(s); + UString rem = &temp[kDrivePrefixSize]; + if (!ResolveDotsFolders(rem)) + return true; + res += kSuperPathPrefix; + temp.DeleteFrom(kDrivePrefixSize); + res += temp; + res += rem; + return true; + } + } + + UString curDir; + if (!GetCurDir(curDir)) + return false; + if (curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSizeStart = 0; + unsigned fixedSize = 0; + const wchar_t *superMarker = NULL; + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + { + superMarker = kSuperPathPrefix; + fixedSize = kDrivePrefixSize; + } + else + { + if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR) + return false; + fixedSizeStart = 2; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + superMarker = kSuperUncPrefix; + } + } + + UString temp; + if (c == CHAR_PATH_SEPARATOR) + { + temp = fs2us(s + 1); + } + else + { + temp += &curDir[fixedSizeStart + fixedSize]; + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + if (superMarker) + res += superMarker; + res += curDir.Mid(fixedSizeStart, fixedSize); + res += temp; + return true; +} + -const wchar_t kExtensionDelimiter = L'.'; +/* + In that case if GetSuperPathBase doesn't return new path, we don't need + to use same path that was used as main path -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension) + GetSuperPathBase superPath.IsEmpty() onlyIfNew + false * * GetCurDir Error + true false * use Super path + true true true don't use any path, we already used mainPath + true true false use main path as Super Path, we don't try mainMath + That case is possible now if GetCurDir returns unknow + type of path (not drive and not network) + + We can change that code if we want to try mainPath, if GetSuperPathBase returns error, + and we didn't try mainPath still. + If we want to work that way, we don't need to use GetSuperPathBase return code. +*/ + +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) +{ + if (GetSuperPathBase(path, superPath)) + { + if (superPath.IsEmpty()) + { + // actually the only possible when onlyIfNew == true and superPath is empty + // is case when + + if (onlyIfNew) + return false; + superPath = fs2us(path); + } + return true; + } + return false; +} + +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) +{ + if (!GetSuperPathBase(s1, d1) || + !GetSuperPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; +} + + +/* +// returns true, if we need additional use with New Super path. +bool GetSuperPath(CFSTR path, UString &superPath) +{ + if (GetSuperPathBase(path, superPath)) + return !superPath.IsEmpty(); + return false; +} +*/ +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) { - int index = fullName.ReverseFind(kExtensionDelimiter); - if (index < 0) + res = s; + + #ifdef UNDER_CE + + if (s[0] != CHAR_PATH_SEPARATOR) + { + if (!dirPrefix) + return false; + res = dirPrefix; + res += s; + } + + #else + + unsigned prefixSize = GetRootPrefixSize(s); + if (prefixSize != 0) + { + if (!AreThereDotsFolders(s + prefixSize)) + return true; + + UString rem = fs2us(s + prefixSize); + if (!ResolveDotsFolders(rem)) + return true; // maybe false; + res.DeleteFrom(prefixSize); + res += us2fs(rem); + return true; + } + + /* + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) + return true; + if (IsDrivePath(s)) + return true; + */ + + UString curDir; + if (dirPrefix) + curDir = fs2us(dirPrefix); + else + { + if (!GetCurDir(curDir)) + return false; + } + if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR) + curDir += WCHAR_PATH_SEPARATOR; + + unsigned fixedSize = 0; + + #ifdef _WIN32 + + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + fixedSize = kDrivePrefixSize; + else + { + if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR) + return false; + fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); + if (fixedSize == 0) + return false; + fixedSize += 2; + } + } + + #endif // _WIN32 + + UString temp; + if (s[0] == CHAR_PATH_SEPARATOR) { - pureName = fullName; - extensionDelimiter.Empty(); - extension.Empty(); + temp = fs2us(s + 1); } else { - pureName = fullName.Left(index); - extensionDelimiter = kExtensionDelimiter; - extension = fullName.Mid(index + 1); + temp += curDir.Ptr(fixedSize); + temp += fs2us(s); } + if (!ResolveDotsFolders(temp)) + return false; + curDir.DeleteFrom(fixedSize); + res = us2fs(curDir); + res += us2fs(temp); + + #endif // UNDER_CE + + return true; +} + +bool GetFullPath(CFSTR path, FString &fullPath) +{ + return GetFullPath(NULL, path, fullPath); } }}} diff --git a/src/libs/7zip/win/CPP/Windows/FileName.h b/src/libs/7zip/win/CPP/Windows/FileName.h index d98079026..04fc79b2d 100644 --- a/src/libs/7zip/win/CPP/Windows/FileName.h +++ b/src/libs/7zip/win/CPP/Windows/FileName.h @@ -1,9 +1,7 @@ // Windows/FileName.h -#ifndef __WINDOWS_FILENAME_H -#define __WINDOWS_FILENAME_H - -#include "../../C/Types.h" +#ifndef __WINDOWS_FILE_NAME_H +#define __WINDOWS_FILE_NAME_H #include "../Common/MyString.h" @@ -11,16 +9,65 @@ namespace NWindows { namespace NFile { namespace NName { -const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; -const TCHAR kAnyStringWildcard = '*'; +void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty +void NormalizeDirPathPrefix(UString &dirPath); + +#ifdef _WIN32 + +extern const wchar_t *kSuperPathPrefix; /* \\?\ */ +const unsigned kDevicePathPrefixSize = 4; +const unsigned kSuperPathPrefixSize = 4; +const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; + +bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ +bool IsSuperUncPath(CFSTR s) throw(); -void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' -#ifndef _UNICODE -void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' +bool IsDrivePath(const wchar_t *s) throw(); +bool IsSuperPath(const wchar_t *s) throw(); +bool IsSuperOrDevicePath(const wchar_t *s) throw(); + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath(CFSTR s) throw(); +bool IsSuperPath(CFSTR s) throw(); +bool IsSuperOrDevicePath(CFSTR s) throw(); #endif -void SplitNameToPureNameAndExtension(const UString &fullName, - UString &pureName, UString &extensionDelimiter, UString &extension); +#endif // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw(); +unsigned GetRootPrefixSize(const wchar_t *s) throw(); + +#ifdef WIN_LONG_PATH + +const int kSuperPathType_UseOnlyMain = 0; +const int kSuperPathType_UseOnlySuper = 1; +const int kSuperPathType_UseMainAndSuper = 2; + +int GetUseSuperPathType(CFSTR s) throw(); +bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew); +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); + +#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper) +#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper) + +#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain) +#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain) + +#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) +#define IF_USE_MAIN_PATH_2(x1, x2) \ + int __useSuperPathType1 = GetUseSuperPathType(x1); \ + int __useSuperPathType2 = GetUseSuperPathType(x2); \ + if (USE_MAIN_PATH_2) + +#else + +#define IF_USE_MAIN_PATH +#define IF_USE_MAIN_PATH_2(x1, x2) + +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); +bool GetFullPath(CFSTR path, FString &fullPath); }}} diff --git a/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp b/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp deleted file mode 100644 index e0f430996..000000000 --- a/src/libs/7zip/win/CPP/Windows/MemoryLock.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Common/MemoryLock.cpp - -#include "StdAfx.h" - -namespace NWindows { -namespace NSecurity { - -#ifndef UNDER_CE - -#ifndef _UNICODE -typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); -typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); -typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, - PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); -#endif - -#ifdef _UNICODE -bool EnableLockMemoryPrivilege( -#else -static bool EnableLockMemoryPrivilege2(HMODULE hModule, -#endif -bool enable) -{ - #ifndef _UNICODE - if (hModule == NULL) - return false; - OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); - LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); - AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); - if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) - return false; - #endif - - HANDLE token; - if (! - #ifdef _UNICODE - ::OpenProcessToken - #else - openProcessToken - #endif - (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) - return false; - TOKEN_PRIVILEGES tp; - bool res = false; - if ( - #ifdef _UNICODE - ::LookupPrivilegeValue - #else - lookupPrivilegeValue - #endif - (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) - { - tp.PrivilegeCount = 1; - tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; - if ( - #ifdef _UNICODE - ::AdjustTokenPrivileges - #else - adjustTokenPrivileges - #endif - (token, FALSE, &tp, 0, NULL, NULL)) - res = (GetLastError() == ERROR_SUCCESS); - } - ::CloseHandle(token); - return res; -} - -#ifndef _UNICODE -bool EnableLockMemoryPrivilege(bool enable) -{ - HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); - if (hModule == NULL) - return false; - bool res = EnableLockMemoryPrivilege2(hModule, enable); - ::FreeLibrary(hModule); - return res; -} -#endif - -#endif - -}} diff --git a/src/libs/7zip/win/CPP/Windows/MemoryLock.h b/src/libs/7zip/win/CPP/Windows/MemoryLock.h deleted file mode 100644 index 5fe619de0..000000000 --- a/src/libs/7zip/win/CPP/Windows/MemoryLock.h +++ /dev/null @@ -1,15 +0,0 @@ -// Windows/MemoryLock.h - -#ifndef __WINDOWS_MEMORYLOCK_H -#define __WINDOWS_MEMORYLOCK_H - -namespace NWindows { -namespace NSecurity { - -#ifndef UNDER_CE -bool EnableLockMemoryPrivilege(bool enable = true); -#endif - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/NtCheck.h b/src/libs/7zip/win/CPP/Windows/NtCheck.h deleted file mode 100644 index e56318f00..000000000 --- a/src/libs/7zip/win/CPP/Windows/NtCheck.h +++ /dev/null @@ -1,44 +0,0 @@ -// Windows/NtCheck.h - -#ifndef __WINDOWS_NT_CHECK_H -#define __WINDOWS_NT_CHECK_H - -#ifdef _WIN32 - -#if !defined(_WIN64) && !defined(UNDER_CE) -static inline bool IsItWindowsNT() -{ - OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(vi); - return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT); -} -#endif - -#ifndef _UNICODE - #if defined(_WIN64) || defined(UNDER_CE) - bool g_IsNT = true; - #define SET_IS_NT - #else - bool g_IsNT = false; - #define SET_IS_NT g_IsNT = IsItWindowsNT(); - #endif - #define NT_CHECK_ACTION - // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION } -#else - #if !defined(_WIN64) && !defined(UNDER_CE) - #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION } - #else - #define NT_CHECK_ACTION - #endif - #define SET_IS_NT -#endif - -#define NT_CHECK NT_CHECK_ACTION SET_IS_NT - -#else - -#define NT_CHECK - -#endif - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp b/src/libs/7zip/win/CPP/Windows/PropVariant.cpp index 90212e08f..d16f576cc 100644 --- a/src/libs/7zip/win/CPP/Windows/PropVariant.cpp +++ b/src/libs/7zip/win/CPP/Windows/PropVariant.cpp @@ -2,13 +2,43 @@ #include "StdAfx.h" -#include "PropVariant.h" - #include "../Common/Defs.h" +#include "PropVariant.h" + namespace NWindows { namespace NCOM { +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() +{ + p->bstrVal = ::SysAllocStringLen(0, numChars); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + return S_OK; +} + +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() +{ + UINT len = (UINT)strlen(s); + p->bstrVal = ::SysAllocStringLen(0, len); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + BSTR dest = p->bstrVal; + for (UINT i = 0; i <= len; i++) + dest[i] = s[i]; + return S_OK; +} + CPropVariant::CPropVariant(const PROPVARIANT &varSrc) { vt = VT_EMPTY; @@ -58,7 +88,7 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); - if (bstrVal == NULL && lpszSrc != NULL) + if (!bstrVal && lpszSrc) { throw kMemException; // vt = VT_ERROR; @@ -67,15 +97,14 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) return *this; } - CPropVariant& CPropVariant::operator=(const char *s) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; UINT len = (UINT)strlen(s); - bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); - if (bstrVal == NULL) + bstrVal = ::SysAllocStringLen(0, len); + if (!bstrVal) { throw kMemException; // vt = VT_ERROR; @@ -89,7 +118,7 @@ CPropVariant& CPropVariant::operator=(const char *s) return *this; } -CPropVariant& CPropVariant::operator=(bool bSrc) +CPropVariant& CPropVariant::operator=(bool bSrc) throw() { if (vt != VT_BOOL) { @@ -100,22 +129,40 @@ CPropVariant& CPropVariant::operator=(bool bSrc) return *this; } +BSTR CPropVariant::AllocBstr(unsigned numChars) +{ + if (vt != VT_EMPTY) + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(0, numChars); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return bstrVal; +} + #define SET_PROP_FUNC(type, id, dest) \ - CPropVariant& CPropVariant::operator=(type value) \ + CPropVariant& CPropVariant::operator=(type value) throw() \ { if (vt != id) { InternalClear(); vt = id; } \ dest = value; return *this; } SET_PROP_FUNC(Byte, VT_UI1, bVal) -SET_PROP_FUNC(Int16, VT_I2, iVal) +// SET_PROP_FUNC(Int16, VT_I2, iVal) SET_PROP_FUNC(Int32, VT_I4, lVal) SET_PROP_FUNC(UInt32, VT_UI4, ulVal) SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) -static HRESULT MyPropVariantClear(PROPVARIANT *prop) +HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() { - switch(prop->vt) + switch (prop->vt) { + case VT_EMPTY: case VT_UI1: case VT_I1: case VT_I2: @@ -134,17 +181,24 @@ static HRESULT MyPropVariantClear(PROPVARIANT *prop) case VT_DATE: prop->vt = VT_EMPTY; prop->wReserved1 = 0; + prop->wReserved2 = 0; + prop->wReserved3 = 0; + prop->uhVal.QuadPart = 0; return S_OK; } return ::VariantClear((VARIANTARG *)prop); + // return ::PropVariantClear(prop); + // PropVariantClear can clear VT_BLOB. } -HRESULT CPropVariant::Clear() +HRESULT CPropVariant::Clear() throw() { - return MyPropVariantClear(this); + if (vt == VT_EMPTY) + return S_OK; + return PropVariant_Clear(this); } -HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) @@ -172,7 +226,7 @@ HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) } -HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) +HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() { HRESULT hr = Clear(); if (FAILED(hr)) @@ -182,18 +236,23 @@ HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) return S_OK; } -HRESULT CPropVariant::Detach(PROPVARIANT *pDest) +HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() { - HRESULT hr = MyPropVariantClear(pDest); - if (FAILED(hr)) - return hr; + if (pDest->vt != VT_EMPTY) + { + HRESULT hr = PropVariant_Clear(pDest); + if (FAILED(hr)) + return hr; + } memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } -HRESULT CPropVariant::InternalClear() +HRESULT CPropVariant::InternalClear() throw() { + if (vt == VT_EMPTY) + return S_OK; HRESULT hr = Clear(); if (FAILED(hr)) { @@ -215,7 +274,7 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) } } -int CPropVariant::Compare(const CPropVariant &a) +int CPropVariant::Compare(const CPropVariant &a) throw() { if (vt != a.vt) return MyCompare(vt, a.vt); @@ -233,9 +292,7 @@ int CPropVariant::Compare(const CPropVariant &a) case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); - case VT_BSTR: - return 0; // Not implemented - // return MyCompare(aPropVarint.cVal); + case VT_BSTR: return 0; // Not implemented default: return 0; } } diff --git a/src/libs/7zip/win/CPP/Windows/PropVariant.h b/src/libs/7zip/win/CPP/Windows/PropVariant.h index d018034eb..d71b85e1d 100644 --- a/src/libs/7zip/win/CPP/Windows/PropVariant.h +++ b/src/libs/7zip/win/CPP/Windows/PropVariant.h @@ -1,29 +1,73 @@ // Windows/PropVariant.h -#ifndef __WINDOWS_PROPVARIANT_H -#define __WINDOWS_PROPVARIANT_H +#ifndef __WINDOWS_PROP_VARIANT_H +#define __WINDOWS_PROP_VARIANT_H +#include "../Common/MyTypes.h" #include "../Common/MyWindows.h" -#include "../Common/Types.h" namespace NWindows { namespace NCOM { +HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); + +inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() +{ + p->vt = VT_UI4; + p->ulVal = v; +} + +inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_UI8; + p->uhVal.QuadPart = v; +} + +inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_FILETIME; + p->filetime.dwLowDateTime = (DWORD)v; + p->filetime.dwHighDateTime = (DWORD)(v >> 32); +} + +inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() +{ + p->vt = VT_BOOL; + p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); +} + + class CPropVariant : public tagPROPVARIANT { public: - CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } - ~CPropVariant() { Clear(); } + CPropVariant() + { + vt = VT_EMPTY; + wReserved1 = 0; + // wReserved2 = 0; + // wReserved3 = 0; + // uhVal.QuadPart = 0; + bstrVal = 0; + } + ~CPropVariant() throw() { Clear(); } CPropVariant(const PROPVARIANT &varSrc); CPropVariant(const CPropVariant &varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } - CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } - CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } + +private: + CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } + +public: CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant& operator=(const CPropVariant &varSrc); @@ -31,24 +75,31 @@ public: CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(const char *s); - CPropVariant& operator=(bool bSrc); - CPropVariant& operator=(Byte value); - CPropVariant& operator=(Int16 value); - CPropVariant& operator=(Int32 value); - CPropVariant& operator=(UInt32 value); - CPropVariant& operator=(Int64 value); - CPropVariant& operator=(UInt64 value); - CPropVariant& operator=(const FILETIME &value); - - HRESULT Clear(); - HRESULT Copy(const PROPVARIANT *pSrc); - HRESULT Attach(PROPVARIANT *pSrc); - HRESULT Detach(PROPVARIANT *pDest); - - HRESULT InternalClear(); + + CPropVariant& operator=(bool bSrc) throw(); + CPropVariant& operator=(Byte value) throw(); + +private: + CPropVariant& operator=(Int16 value) throw(); + +public: + CPropVariant& operator=(Int32 value) throw(); + CPropVariant& operator=(UInt32 value) throw(); + CPropVariant& operator=(UInt64 value) throw(); + CPropVariant& operator=(Int64 value) throw(); + CPropVariant& operator=(const FILETIME &value) throw(); + + BSTR AllocBstr(unsigned numChars); + + HRESULT Clear() throw(); + HRESULT Copy(const PROPVARIANT *pSrc) throw(); + HRESULT Attach(PROPVARIANT *pSrc) throw(); + HRESULT Detach(PROPVARIANT *pDest) throw(); + + HRESULT InternalClear() throw(); void InternalCopy(const PROPVARIANT *pSrc); - int Compare(const CPropVariant &a1); + int Compare(const CPropVariant &a) throw(); }; }} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp b/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp new file mode 100644 index 000000000..dfb93d6d6 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/PropVariantConv.cpp @@ -0,0 +1,99 @@ +// PropVariantConvert.cpp + +#include "StdAfx.h" + +#include "../Common/IntToString.h" + +#include "Defs.h" +#include "PropVariantConv.h" + +#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } + +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) throw() +{ + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + { + *s = 0; + return false; + } + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } + { + s[3] = (char)('0' + val % 10); val /= 10; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 4; + } + UINT_TO_STR_2('-', st.wMonth); + UINT_TO_STR_2('-', st.wDay); + if (includeTime) + { + UINT_TO_STR_2(' ', st.wHour); + UINT_TO_STR_2(':', st.wMinute); + if (includeSeconds) + UINT_TO_STR_2(':', st.wSecond); + } + *s = 0; + return true; +} + +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *dest, bool includeTime, bool includeSeconds) throw() +{ + char s[32]; + ConvertFileTimeToString(ft, s, includeTime, includeSeconds); + for (unsigned i = 0;; i++) + { + unsigned char c = s[i]; + dest[i] = c; + if (c == 0) + return; + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertFileTimeToString(prop.filetime, dest, true, true); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); + } +} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConv.h b/src/libs/7zip/win/CPP/Windows/PropVariantConv.h new file mode 100644 index 000000000..5d26357f0 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/PropVariantConv.h @@ -0,0 +1,30 @@ +// Windows/PropVariantConv.h + +#ifndef __PROP_VARIANT_CONV_H +#define __PROP_VARIANT_CONV_H + +#include "../Common/MyTypes.h" + +// provide at least 32 bytes for buffer including zero-end +bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true) throw(); +void ConvertFileTimeToString(const FILETIME &ft, wchar_t *s, bool includeTime = true, bool includeSeconds = true) throw(); + +// provide at least 32 bytes for buffer including zero-end +// don't send VT_BSTR to these functions +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); + +inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) +{ + switch (prop.vt) + { + case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; + case VT_UI4: value = prop.ulVal; return true; + case VT_UI2: value = prop.uiVal; return true; + case VT_UI1: value = prop.bVal; return true; + case VT_EMPTY: return false; + default: throw 151199; + } +} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp b/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp deleted file mode 100644 index 2d8456cd6..000000000 --- a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// PropVariantConversions.cpp - -#include "StdAfx.h" - -#include "Common/IntToString.h" -#include "Common/StringConvert.h" - -#include "Windows/Defs.h" - -#include "PropVariantConversions.h" - -static UString ConvertUInt64ToString(UInt64 value) -{ - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; -} - -static UString ConvertInt64ToString(Int64 value) -{ - wchar_t buffer[32]; - ConvertInt64ToString(value, buffer); - return buffer; -} - -static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) -{ - if (c != 0) - *s++ = c; - char temp[16]; - int pos = 0; - do - { - temp[pos++] = (char)('0' + value % 10); - value /= 10; - } - while (value != 0); - int i; - for (i = 0; i < numPos - pos; i++) - *s++ = '0'; - do - *s++ = temp[--pos]; - while (pos > 0); - *s = '\0'; - return s; -} - -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) -{ - s[0] = '\0'; - SYSTEMTIME st; - if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) - return false; - s = UIntToStringSpec(0, st.wYear, s, 4); - s = UIntToStringSpec('-', st.wMonth, s, 2); - s = UIntToStringSpec('-', st.wDay, s, 2); - if (includeTime) - { - s = UIntToStringSpec(' ', st.wHour, s, 2); - s = UIntToStringSpec(':', st.wMinute, s, 2); - if (includeSeconds) - UIntToStringSpec(':', st.wSecond, s, 2); - } - return true; -} - -UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime, bool includeSeconds) -{ - char s[32]; - ConvertFileTimeToString(ft, s, includeTime, includeSeconds); - return GetUnicodeString(s); -} - - -UString ConvertPropVariantToString(const PROPVARIANT &prop) -{ - switch (prop.vt) - { - case VT_EMPTY: return UString(); - case VT_BSTR: return prop.bstrVal; - case VT_UI1: return ConvertUInt64ToString(prop.bVal); - case VT_UI2: return ConvertUInt64ToString(prop.uiVal); - case VT_UI4: return ConvertUInt64ToString(prop.ulVal); - case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); - case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); - // case VT_I1: return ConvertInt64ToString(prop.cVal); - case VT_I2: return ConvertInt64ToString(prop.iVal); - case VT_I4: return ConvertInt64ToString(prop.lVal); - case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); - case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; - default: throw 150245; - } -} - -UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) -{ - switch (prop.vt) - { - case VT_UI1: return prop.bVal; - case VT_UI2: return prop.uiVal; - case VT_UI4: return prop.ulVal; - case VT_UI8: return (UInt64)prop.uhVal.QuadPart; - default: throw 151199; - } -} diff --git a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h b/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h deleted file mode 100644 index 3de4dedb3..000000000 --- a/src/libs/7zip/win/CPP/Windows/PropVariantConversions.h +++ /dev/null @@ -1,14 +0,0 @@ -// Windows/PropVariantConversions.h - -#ifndef __PROP_VARIANT_CONVERSIONS_H -#define __PROP_VARIANT_CONVERSIONS_H - -#include "Common/MyString.h" -#include "Common/Types.h" - -bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); -UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); -UString ConvertPropVariantToString(const PROPVARIANT &prop); -UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop); - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/Registry.cpp b/src/libs/7zip/win/CPP/Windows/Registry.cpp deleted file mode 100644 index 8b25375d9..000000000 --- a/src/libs/7zip/win/CPP/Windows/Registry.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// Windows/Registry.cpp - -#include "StdAfx.h" - -#ifndef _UNICODE -#include "Common/StringConvert.h" -#endif -#include "Windows/Registry.h" - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -namespace NWindows { -namespace NRegistry { - -#define MYASSERT(expr) // _ASSERTE(expr) - -LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, - LPTSTR keyClass, DWORD options, REGSAM accessMask, - LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) -{ - MYASSERT(parentKey != NULL); - DWORD dispositionReal; - HKEY key = NULL; - LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, - options, accessMask, securityAttributes, &key, &dispositionReal); - if (disposition != NULL) - *disposition = dispositionReal; - if (res == ERROR_SUCCESS) - { - res = Close(); - _object = key; - } - return res; -} - -LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) -{ - MYASSERT(parentKey != NULL); - HKEY key = NULL; - LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); - if (res == ERROR_SUCCESS) - { - res = Close(); - MYASSERT(res == ERROR_SUCCESS); - _object = key; - } - return res; -} - -LONG CKey::Close() -{ - LONG res = ERROR_SUCCESS; - if (_object != NULL) - { - res = RegCloseKey(_object); - _object = NULL; - } - return res; -} - -// win95, win98: deletes sunkey and all its subkeys -// winNT to be deleted must not have subkeys -LONG CKey::DeleteSubKey(LPCTSTR subKeyName) -{ - MYASSERT(_object != NULL); - return RegDeleteKey(_object, subKeyName); -} - -LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) -{ - CKey key; - LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); - if (res != ERROR_SUCCESS) - return res; - FILETIME fileTime; - const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL - DWORD size = kBufferSize; - TCHAR buffer[kBufferSize]; - while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) - { - res = key.RecurseDeleteKey(buffer); - if (res != ERROR_SUCCESS) - return res; - size = kBufferSize; - } - key.Close(); - return DeleteSubKey(subKeyName); -} - - -///////////////////////// -// Value Functions - -static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } -static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } - - -LONG CKey::DeleteValue(LPCTSTR name) -{ - MYASSERT(_object != NULL); - return ::RegDeleteValue(_object, name); -} - -#ifndef _UNICODE -LONG CKey::DeleteValue(LPCWSTR name) -{ - MYASSERT(_object != NULL); - if (g_IsNT) - return ::RegDeleteValueW(_object, name); - return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); -} -#endif - -LONG CKey::SetValue(LPCTSTR name, UInt32 value) -{ - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_DWORD, - (BYTE * const)&value, sizeof(UInt32)); -} - -LONG CKey::SetValue(LPCTSTR name, bool value) -{ - return SetValue(name, BoolToUINT32(value)); -} - -LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_SZ, - (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); -} - -/* -LONG CKey::SetValue(LPCTSTR name, const CSysString &value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_SZ, - (const BYTE *)(const TCHAR *)value, (value.Length() + 1) * sizeof(TCHAR)); -} -*/ - -#ifndef _UNICODE - -LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - if (g_IsNT) - return RegSetValueExW(_object, name, NULL, REG_SZ, - (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); - return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), - value == 0 ? 0 : (LPCSTR)GetSystemString(value)); -} - -#endif - - -LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) -{ - MYASSERT(value != NULL); - MYASSERT(_object != NULL); - return RegSetValueEx(_object, name, NULL, REG_BINARY, - (const BYTE *)value, size); -} - -LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) -{ - MYASSERT(value != NULL); - CKey key; - LONG res = key.Create(parentKey, keyName); - if (res == ERROR_SUCCESS) - res = key.SetValue(valueName, value); - return res; -} - -LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) -{ - MYASSERT(value != NULL); - CKey key; - LONG res = key.Create(_object, keyName); - if (res == ERROR_SUCCESS) - res = key.SetValue(valueName, value); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) -{ - DWORD type = NULL; - DWORD count = sizeof(DWORD); - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, - (LPBYTE)&value, &count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_DWORD)); - MYASSERT((res!=ERROR_SUCCESS) || (count == sizeof(UInt32))); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, bool &value) -{ - UInt32 uintValue = BoolToUINT32(value); - LONG res = QueryValue(name, uintValue); - value = UINT32ToBool(uintValue); - return res; -} - -LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) -{ - UInt32 newVal; - LONG res = QueryValue(name, newVal); - if (res == ERROR_SUCCESS) - value = newVal; - return res; -} - -LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) -{ - bool newVal; - LONG res = QueryValue(name, newVal); - if (res == ERROR_SUCCESS) - value = newVal; - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) -{ - MYASSERT(count != NULL); - DWORD type = NULL; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); - return res; -} - -LONG CKey::QueryValue(LPCTSTR name, CSysString &value) -{ - value.Empty(); - DWORD type = NULL; - UInt32 currentSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)¤tSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - res = QueryValue(name, value.GetBuffer(currentSize), currentSize); - value.ReleaseBuffer(); - return res; -} - -#ifndef _UNICODE -LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) -{ - MYASSERT(count != NULL); - DWORD type = NULL; - LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); - return res; -} -LONG CKey::QueryValue(LPCWSTR name, UString &value) -{ - value.Empty(); - DWORD type = NULL; - UInt32 currentSize = 0; - - LONG res; - if (g_IsNT) - { - res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)¤tSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - res = QueryValue(name, value.GetBuffer(currentSize), currentSize); - value.ReleaseBuffer(); - } - else - { - AString vTemp; - res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); - value = GetUnicodeString(vTemp); - } - return res; -} -#endif - -LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) -{ - DWORD type = NULL; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); - MYASSERT((res!=ERROR_SUCCESS) || (type == REG_BINARY)); - return res; -} - - -LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) -{ - DWORD type = NULL; - dataSize = 0; - LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) - return res; - value.SetCapacity(dataSize); - return QueryValue(name, (BYTE *)value, dataSize); -} - -LONG CKey::EnumKeys(CSysStringVector &keyNames) -{ - keyNames.Clear(); - CSysString keyName; - for (UInt32 index = 0; ; index++) - { - const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL - FILETIME lastWriteTime; - UInt32 nameSize = kBufferSize; - LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize), - (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); - keyName.ReleaseBuffer(); - if (result == ERROR_NO_MORE_ITEMS) - break; - if (result != ERROR_SUCCESS) - return result; - keyNames.Add(keyName); - } - return ERROR_SUCCESS; -} - -LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) -{ - UInt32 numChars = 0; - int i; - for (i = 0; i < strings.Size(); i++) - numChars += strings[i].Length() + 1; - CBuffer buffer; - buffer.SetCapacity(numChars); - int pos = 0; - for (i = 0; i < strings.Size(); i++) - { - const UString &s = strings[i]; - MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s); - pos += s.Length() + 1; - } - return SetValue(valueName, buffer, numChars * sizeof(wchar_t)); -} - -LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) -{ - strings.Clear(); - CByteBuffer buffer; - UInt32 dataSize; - LONG res = QueryValue(valueName, buffer, dataSize); - if (res != ERROR_SUCCESS) - return res; - if (dataSize % sizeof(wchar_t) != 0) - return E_FAIL; - const wchar_t *data = (const wchar_t *)(const Byte *)buffer; - int numChars = dataSize / sizeof(wchar_t); - UString s; - for (int i = 0; i < numChars; i++) - { - wchar_t c = data[i]; - if (c == 0) - { - strings.Add(s); - s.Empty(); - } - else - s += c; - } - return res; -} - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Registry.h b/src/libs/7zip/win/CPP/Windows/Registry.h deleted file mode 100644 index f0561e688..000000000 --- a/src/libs/7zip/win/CPP/Windows/Registry.h +++ /dev/null @@ -1,85 +0,0 @@ -// Windows/Registry.h - -#ifndef __WINDOWS_REGISTRY_H -#define __WINDOWS_REGISTRY_H - -#include "Common/Buffer.h" -#include "Common/MyString.h" -#include "Common/Types.h" - -namespace NWindows { -namespace NRegistry { - -LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); - -class CKey -{ - HKEY _object; -public: - CKey(): _object(NULL) {} - ~CKey() { Close(); } - - operator HKEY() const { return _object; } - void Attach(HKEY key) { _object = key; } - HKEY Detach() - { - HKEY key = _object; - _object = NULL; - return key; - } - - LONG Create(HKEY parentKey, LPCTSTR keyName, - LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, - REGSAM accessMask = KEY_ALL_ACCESS, - LPSECURITY_ATTRIBUTES securityAttributes = NULL, - LPDWORD disposition = NULL); - LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS); - - LONG Close(); - - LONG DeleteSubKey(LPCTSTR subKeyName); - LONG RecurseDeleteKey(LPCTSTR subKeyName); - - LONG DeleteValue(LPCTSTR name); - #ifndef _UNICODE - LONG DeleteValue(LPCWSTR name); - #endif - - LONG SetValue(LPCTSTR valueName, UInt32 value); - LONG SetValue(LPCTSTR valueName, bool value); - LONG SetValue(LPCTSTR valueName, LPCTSTR value); - // LONG SetValue(LPCTSTR valueName, const CSysString &value); - #ifndef _UNICODE - LONG SetValue(LPCWSTR name, LPCWSTR value); - // LONG SetValue(LPCWSTR name, const UString &value); - #endif - - LONG SetValue(LPCTSTR name, const void *value, UInt32 size); - - LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); - LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); - - LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); - - LONG QueryValue(LPCTSTR name, UInt32 &value); - LONG QueryValue(LPCTSTR name, bool &value); - LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize); - LONG QueryValue(LPCTSTR name, CSysString &value); - - LONG GetValue_IfOk(LPCTSTR name, UInt32 &value); - LONG GetValue_IfOk(LPCTSTR name, bool &value); - - #ifndef _UNICODE - LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); - LONG QueryValue(LPCWSTR name, UString &value); - #endif - - LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize); - LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); - - LONG EnumKeys(CSysStringVector &keyNames); -}; - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp b/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp new file mode 100644 index 000000000..f997738ce --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/SecurityUtils.cpp @@ -0,0 +1,179 @@ +// Windows/SecurityUtils.cpp + +#include "StdAfx.h" + +#include "SecurityUtils.h" + +namespace NWindows { +namespace NSecurity { + +/* +bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, + CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) +{ + DWORD accountNameSize = 0, domainNameSize = 0; + + if (!::LookupAccountSid(systemName, sid, + accountName.GetBuffer(0), &accountNameSize, + domainName.GetBuffer(0), &domainNameSize, sidNameUse)) + { + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return false; + } + bool result = BOOLToBool(::LookupAccountSid(systemName, sid, + accountName.GetBuffer(accountNameSize), &accountNameSize, + domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse)); + accountName.ReleaseBuffer(); + domainName.ReleaseBuffer(); + return result; +} +*/ + +static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) +{ + int len = (int)wcslen(src); + dest->Length = (USHORT)(len * sizeof(WCHAR)); + dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); + dest->Buffer = src; +} + +/* +static void MyLookupSids(CPolicy &policy, PSID ps) +{ + LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; + LSA_TRANSLATED_NAME *names = NULL; + NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); + int res = LsaNtStatusToWinError(nts); + LsaFreeMemory(referencedDomains); + LsaFreeMemory(names); +} +*/ + +#ifndef _UNICODE +typedef BOOL (WINAPI * LookupAccountNameWP)( + LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR ReferencedDomainName, + LPDWORD cchReferencedDomainName, + PSID_NAME_USE peUse + ); +#endif + +static PSID GetSid(LPWSTR accountName) +{ + #ifndef _UNICODE + HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); + if (hModule == NULL) + return NULL; + LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); + if (lookupAccountNameW == NULL) + return NULL; + #endif + + DWORD sidLen = 0, domainLen = 0; + SID_NAME_USE sidNameUse; + if (! + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) + { + if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); + LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); + BOOL res = + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); + ::HeapFree(GetProcessHeap(), 0, domainName); + if (res) + return pSid; + } + } + return NULL; +} + +#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" + +bool AddLockMemoryPrivilege() +{ + CPolicy policy; + LSA_OBJECT_ATTRIBUTES attr; + attr.Length = sizeof(attr); + attr.RootDirectory = NULL; + attr.ObjectName = NULL; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (policy.Open(NULL, &attr, + // GENERIC_WRITE) + POLICY_ALL_ACCESS) + // STANDARD_RIGHTS_REQUIRED, + // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) + != 0) + return false; + LSA_UNICODE_STRING userRights; + wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; + SetLsaString(s, &userRights); + WCHAR userName[256 + 2]; + DWORD size = 256; + if (!GetUserNameW(userName, &size)) + return false; + PSID psid = GetSid(userName); + if (psid == NULL) + return false; + bool res = false; + + /* + PLSA_UNICODE_STRING userRightsArray; + ULONG countOfRights; + NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); + if (status != 0) + return false; + bool finded = false; + for (ULONG i = 0; i < countOfRights; i++) + { + LSA_UNICODE_STRING &ur = userRightsArray[i]; + if (ur.Length != s.Length() * sizeof(WCHAR)) + continue; + if (wcsncmp(ur.Buffer, s, s.Length()) != 0) + continue; + finded = true; + res = true; + break; + } + if (!finded) + */ + { + /* + LSA_ENUMERATION_INFORMATION *enums; + ULONG countReturned; + NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); + if (status == 0) + { + for (ULONG i = 0; i < countReturned; i++) + MyLookupSids(policy, enums[i].Sid); + if (enums) + ::LsaFreeMemory(enums); + res = true; + } + */ + NTSTATUS status = policy.AddAccountRights(psid, &userRights); + if (status == 0) + res = true; + // ULONG res = LsaNtStatusToWinError(status); + } + HeapFree(GetProcessHeap(), 0, psid); + return res; +} + +}} + diff --git a/src/libs/7zip/win/CPP/Windows/SecurityUtils.h b/src/libs/7zip/win/CPP/Windows/SecurityUtils.h new file mode 100644 index 000000000..715de2505 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/SecurityUtils.h @@ -0,0 +1,167 @@ +// Windows/SecurityUtils.h + +#ifndef __WINDOWS_SECURITY_UTILS_H +#define __WINDOWS_SECURITY_UTILS_H + +#include + +#include "Defs.h" + +namespace NWindows { +namespace NSecurity { + +class CAccessToken +{ + HANDLE _handle; +public: + CAccessToken(): _handle(NULL) {}; + ~CAccessToken() { Close(); } + bool Close() + { + if (_handle == NULL) + return true; + bool res = BOOLToBool(::CloseHandle(_handle)); + if (res) + _handle = NULL; + return res; + } + + bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) + { + Close(); + return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); + } + + /* + bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) + { + Close(); + return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); + } + */ + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, + DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) + { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), + newState, bufferLength, previousState, returnLength)); } + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } + + bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(false, newState); } + +}; + +#ifndef _UNICODE +typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, + PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); +typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); +typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, + PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); +#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#endif + +struct CPolicy +{ +protected: + LSA_HANDLE _handle; + #ifndef _UNICODE + HMODULE hModule; + #endif +public: + operator LSA_HANDLE() const { return _handle; } + CPolicy(): _handle(NULL) + { + #ifndef _UNICODE + hModule = GetModuleHandle(TEXT("Advapi32.dll")); + #endif + }; + ~CPolicy() { Close(); } + + NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, + ACCESS_MASK desiredAccess) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); + if (lsaOpenPolicy == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + Close(); + return + #ifdef _UNICODE + ::LsaOpenPolicy + #else + lsaOpenPolicy + #endif + (systemName, objectAttributes, desiredAccess, &_handle); + } + + NTSTATUS Close() + { + if (_handle == NULL) + return 0; + + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); + if (lsaClose == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + NTSTATUS res = + #ifdef _UNICODE + ::LsaClose + #else + lsaClose + #endif + (_handle); + _handle = NULL; + return res; + } + + NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, + PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) + { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } + + NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) + { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } + + NTSTATUS LookupSids(ULONG count, PSID* sids, + PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) + { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } + + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); + if (lsaAddAccountRights == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + return + #ifdef _UNICODE + ::LsaAddAccountRights + #else + lsaAddAccountRights + #endif + (_handle, accountSid, userRights, countOfRights); + } + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) + { return AddAccountRights(accountSid, userRights, 1); } + + NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } +}; + +bool AddLockMemoryPrivilege(); + +}} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/StdAfx.h b/src/libs/7zip/win/CPP/Windows/StdAfx.h index 8b383c5ba..1766dfa86 100644 --- a/src/libs/7zip/win/CPP/Windows/StdAfx.h +++ b/src/libs/7zip/win/CPP/Windows/StdAfx.h @@ -3,7 +3,6 @@ #ifndef __STDAFX_H #define __STDAFX_H -#include "../Common/MyWindows.h" -#include "../Common/NewHandler.h" +#include "../Common/Common.h" #endif diff --git a/src/libs/7zip/win/CPP/Windows/System.h b/src/libs/7zip/win/CPP/Windows/System.h index e0067158f..4133a7b30 100644 --- a/src/libs/7zip/win/CPP/Windows/System.h +++ b/src/libs/7zip/win/CPP/Windows/System.h @@ -3,7 +3,7 @@ #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H -#include "../Common/Types.h" +#include "../Common/MyTypes.h" namespace NWindows { namespace NSystem { diff --git a/src/libs/7zip/win/CPP/Windows/Thread.h b/src/libs/7zip/win/CPP/Windows/Thread.h index 16a509d47..f9ecaed85 100644 --- a/src/libs/7zip/win/CPP/Windows/Thread.h +++ b/src/libs/7zip/win/CPP/Windows/Thread.h @@ -20,7 +20,7 @@ public: WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } - + #ifdef _WIN32 operator HANDLE() { return thread; } void Attach(HANDLE handle) { thread = handle; } diff --git a/src/libs/7zip/win/CPP/Windows/Time.cpp b/src/libs/7zip/win/CPP/Windows/Time.cpp deleted file mode 100644 index ec9ca47d9..000000000 --- a/src/libs/7zip/win/CPP/Windows/Time.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Windows/Time.cpp - -#include "StdAfx.h" - -#include "Windows/Defs.h" - -#include "Time.h" - -namespace NWindows { -namespace NTime { - -static const UInt32 kNumTimeQuantumsInSecond = 10000000; -static const UInt32 kFileTimeStartYear = 1601; -static const UInt32 kDosTimeStartYear = 1980; -static const UInt32 kUnixTimeStartYear = 1970; -static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * - 60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); - -bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) -{ - #if defined(_WIN32) && !defined(UNDER_CE) - return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); - #else - ft.dwLowDateTime = 0; - ft.dwHighDateTime = 0; - UInt64 res; - if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, - (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) - return false; - res *= kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (UInt32)res; - ft.dwHighDateTime = (UInt32)(res >> 32); - return true; - #endif -} - -static const UInt32 kHighDosTime = 0xFF9FBF7D; -static const UInt32 kLowDosTime = 0x210000; - -#define PERIOD_4 (4 * 365 + 1) -#define PERIOD_100 (PERIOD_4 * 25 - 1) -#define PERIOD_400 (PERIOD_100 * 4 + 1) - -bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) -{ - #if defined(_WIN32) && !defined(UNDER_CE) - - WORD datePart, timePart; - if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) - { - dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; - return false; - } - dosTime = (((UInt32)datePart) << 16) + timePart; - - #else - - unsigned year, mon, day, hour, min, sec; - UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); - Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - unsigned temp; - UInt32 v; - v64 += (kNumTimeQuantumsInSecond * 2 - 1); - v64 /= kNumTimeQuantumsInSecond; - sec = (unsigned)(v64 % 60); - v64 /= 60; - min = (unsigned)(v64 % 60); - v64 /= 60; - hour = (unsigned)(v64 % 24); - v64 /= 24; - - v = (UInt32)v64; - - year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); - v %= PERIOD_400; - - temp = (unsigned)(v / PERIOD_100); - if (temp == 4) - temp = 3; - year += temp * 100; - v -= temp * PERIOD_100; - - temp = v / PERIOD_4; - if (temp == 25) - temp = 24; - year += temp * 4; - v -= temp * PERIOD_4; - - temp = v / 365; - if (temp == 4) - temp = 3; - year += temp; - v -= temp * 365; - - if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) - ms[1] = 29; - for (mon = 1; mon <= 12; mon++) - { - unsigned s = ms[mon - 1]; - if (v < s) - break; - v -= s; - } - day = (unsigned)v + 1; - - dosTime = kLowDosTime; - if (year < kDosTimeStartYear) - return false; - year -= kDosTimeStartYear; - dosTime = kHighDosTime; - if (year >= 128) - return false; - dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); - #endif - return true; -} - -void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) -{ - UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; - ft.dwLowDateTime = (DWORD)v; - ft.dwHighDateTime = (DWORD)(v >> 32); -} - -bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) -{ - UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - if (winTime < kUnixTimeStartValue) - { - unixTime = 0; - return false; - } - winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; - if (winTime > 0xFFFFFFFF) - { - unixTime = 0xFFFFFFFF; - return false; - } - unixTime = (UInt32)winTime; - return true; -} - -bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, - unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) -{ - resSeconds = 0; - if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || - day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) - return false; - UInt32 numYears = year - kFileTimeStartYear; - UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; - Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) - ms[1] = 29; - month--; - for (unsigned i = 0; i < month; i++) - numDays += ms[i]; - numDays += day - 1; - resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; - return true; -} - -void GetCurUtcFileTime(FILETIME &ft) -{ - SYSTEMTIME st; - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); -} - -}} diff --git a/src/libs/7zip/win/CPP/Windows/Time.h b/src/libs/7zip/win/CPP/Windows/Time.h deleted file mode 100644 index 6f510b22b..000000000 --- a/src/libs/7zip/win/CPP/Windows/Time.h +++ /dev/null @@ -1,21 +0,0 @@ -// Windows/Time.h - -#ifndef __WINDOWS_TIME_H -#define __WINDOWS_TIME_H - -#include "Common/Types.h" - -namespace NWindows { -namespace NTime { - -bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); -bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); -void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); -bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); -bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, - unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); -void GetCurUtcFileTime(FILETIME &ft); - -}} - -#endif diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp b/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp new file mode 100644 index 000000000..7ef44d9cc --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/TimeUtils.cpp @@ -0,0 +1,203 @@ +// Windows/TimeUtils.cpp + +#include "StdAfx.h" + +#include "Defs.h" +#include "TimeUtils.h" + +namespace NWindows { +namespace NTime { + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +static const UInt32 kDosTimeStartYear = 1980; +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); + #else + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + UInt64 res; + if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, + (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) + return false; + res *= kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (UInt32)res; + ft.dwHighDateTime = (UInt32)(res >> 32); + return true; + #endif +} + +static const UInt32 kHighDosTime = 0xFF9FBF7D; +static const UInt32 kLowDosTime = 0x210000; + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + + WORD datePart, timePart; + if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) + { + dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; + return false; + } + dosTime = (((UInt32)datePart) << 16) + timePart; + + #else + + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned temp; + UInt32 v; + v64 += (kNumTimeQuantumsInSecond * 2 - 1); + v64 /= kNumTimeQuantumsInSecond; + sec = (unsigned)(v64 % 60); + v64 /= 60; + min = (unsigned)(v64 % 60); + v64 /= 60; + hour = (unsigned)(v64 % 24); + v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); + v %= PERIOD_400; + + temp = (unsigned)(v / PERIOD_100); + if (temp == 4) + temp = 3; + year += temp * 100; + v -= temp * PERIOD_100; + + temp = v / PERIOD_4; + if (temp == 25) + temp = 24; + year += temp * 4; + v -= temp * PERIOD_4; + + temp = v / 365; + if (temp == 4) + temp = 3; + year += temp; + v -= temp * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + + dosTime = kLowDosTime; + if (year < kDosTimeStartYear) + return false; + year -= kDosTimeStartYear; + dosTime = kHighDosTime; + if (year >= 128) + return false; + dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); + #endif + return true; +} + +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() +{ + UInt64 v = (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() +{ + if (unixTime > kNumSecondsInFileTime - kUnixTimeOffset) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - kUnixTimeOffset; +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) + { + unixTime = 0; + return false; + } + winTime -= kUnixTimeOffset; + if (winTime > 0xFFFFFFFF) + { + unixTime = 0xFFFFFFFF; + return false; + } + unixTime = (UInt32)winTime; + return true; +} + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw() +{ + resSeconds = 0; + if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) + return false; + UInt32 numYears = year - kFileTimeStartYear; + UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + month--; + for (unsigned i = 0; i < month; i++) + numDays += ms[i]; + numDays += day - 1; + resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; + return true; +} + +void GetCurUtcFileTime(FILETIME &ft) throw() +{ + // Both variants provide same low resolution on WinXP: about 15 ms. + // But GetSystemTimeAsFileTime is much faster. + + #ifdef UNDER_CE + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + #else + GetSystemTimeAsFileTime(&ft); + #endif +} + +}} diff --git a/src/libs/7zip/win/CPP/Windows/TimeUtils.h b/src/libs/7zip/win/CPP/Windows/TimeUtils.h new file mode 100644 index 000000000..2967214e6 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/TimeUtils.h @@ -0,0 +1,23 @@ +// Windows/TimeUtils.h + +#ifndef __WINDOWS_TIME_UTILS_H +#define __WINDOWS_TIME_UTILS_H + +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); +void GetCurUtcFileTime(FILETIME &ft) throw(); + +}} + +#endif diff --git a/src/libs/7zip/win/CPP/Windows/Windows.pri b/src/libs/7zip/win/CPP/Windows/Windows.pri new file mode 100644 index 000000000..a69279060 --- /dev/null +++ b/src/libs/7zip/win/CPP/Windows/Windows.pri @@ -0,0 +1,29 @@ +HEADERS += $$7ZIP_BASE/CPP/Windows/DLL.h \ + $$7ZIP_BASE/CPP/Windows/Defs.h \ + $$7ZIP_BASE/CPP/Windows/FileDir.h \ + $$7ZIP_BASE/CPP/Windows/FileFind.h \ + $$7ZIP_BASE/CPP/Windows/FileIO.h \ + $$7ZIP_BASE/CPP/Windows/FileMapping.h \ + $$7ZIP_BASE/CPP/Windows/FileName.h \ + $$7ZIP_BASE/CPP/Windows/Handle.h \ + $$7ZIP_BASE/CPP/Windows/PropVariant.h \ + $$7ZIP_BASE/CPP/Windows/PropVariantConv.h \ + $$7ZIP_BASE/CPP/Windows/SecurityUtils.h \ + $$7ZIP_BASE/CPP/Windows/StdAfx.h \ + $$7ZIP_BASE/CPP/Windows/Synchronization.h \ + $$7ZIP_BASE/CPP/Windows/System.h \ + $$7ZIP_BASE/CPP/Windows/Thread.h \ + $$7ZIP_BASE/CPP/Windows/TimeUtils.h + +SOURCES += $$7ZIP_BASE/CPP/Windows/DLL.cpp \ + $$7ZIP_BASE/CPP/Windows/FileDir.cpp \ + $$7ZIP_BASE/CPP/Windows/FileFind.cpp \ + $$7ZIP_BASE/CPP/Windows/FileIO.cpp \ + $$7ZIP_BASE/CPP/Windows/FileLink.cpp \ + $$7ZIP_BASE/CPP/Windows/FileName.cpp \ + $$7ZIP_BASE/CPP/Windows/PropVariant.cpp \ + $$7ZIP_BASE/CPP/Windows/PropVariantConv.cpp \ + $$7ZIP_BASE/CPP/Windows/SecurityUtils.cpp \ + $$7ZIP_BASE/CPP/Windows/Synchronization.cpp \ + $$7ZIP_BASE/CPP/Windows/System.cpp \ + $$7ZIP_BASE/CPP/Windows/TimeUtils.cpp -- cgit v1.2.3