diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt index fb5a22129..4711822db 100644 --- a/tdutils/CMakeLists.txt +++ b/tdutils/CMakeLists.txt @@ -123,6 +123,7 @@ set(TDUTILS_SOURCE td/utils/port/EventFd.h td/utils/port/EventFdBase.h td/utils/port/FileFd.h + td/utils/port/FromApp.h td/utils/port/IPAddress.h td/utils/port/IoSlice.h td/utils/port/MemoryMapping.h diff --git a/tdutils/td/utils/port/FileFd.cpp b/tdutils/td/utils/port/FileFd.cpp index 634dacb64..9795128eb 100644 --- a/tdutils/td/utils/port/FileFd.cpp +++ b/tdutils/td/utils/port/FileFd.cpp @@ -7,6 +7,7 @@ #include "td/utils/port/FileFd.h" #if TD_PORT_WINDOWS +#include "td/utils/port/FromApp.h" #include "td/utils/port/Stat.h" #include "td/utils/port/wstring_convert.h" #endif @@ -211,7 +212,7 @@ Result FileFd::open(CSlice filepath, int32 flags, int32 mode) { extended_parameters.dwSize = sizeof(extended_parameters); extended_parameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; extended_parameters.dwFileFlags = native_flags; - auto handle = CreateFile2(w_filepath.c_str(), desired_access, share_mode, creation_disposition, &extended_parameters); + auto handle = td::CreateFile2FromAppW(w_filepath.c_str(), desired_access, share_mode, creation_disposition, &extended_parameters); #endif if (handle == INVALID_HANDLE_VALUE) { return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); diff --git a/tdutils/td/utils/port/FromApp.h b/tdutils/td/utils/port/FromApp.h new file mode 100644 index 000000000..d969ad34b --- /dev/null +++ b/tdutils/td/utils/port/FromApp.h @@ -0,0 +1,115 @@ +#pragma once +#include "td/utils/common.h" + +#ifdef TD_PORT_WINDOWS +#include +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) +inline HMODULE GetKernelModule() { + static HMODULE kernelModule; + if (kernelModule == nullptr) { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery(VirtualQuery, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) { + kernelModule = reinterpret_cast(mbi.AllocationBase); + } + } + + return kernelModule; +} + +inline HMODULE LoadLibrary(LPCTSTR lpFileName) { + typedef HMODULE(WINAPI * pLoadLibrary)(_In_ LPCTSTR); + static const auto procLoadLibrary = reinterpret_cast(GetProcAddress(GetKernelModule(), "LoadLibraryW")); + + return procLoadLibrary(lpFileName); +} + +inline HMODULE GetFromAppModule() { + static const HMODULE fromAppModule = LoadLibrary(L"api-ms-win-core-file-fromapp-l1-1-0.dll"); + return fromAppModule; +} + +namespace td { +inline HANDLE CreateFile2FromAppW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, + _In_ DWORD dwCreationDisposition, + _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) { + using pCreateFile2FromAppW = + HANDLE(WINAPI *)(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, + _In_ DWORD dwCreationDisposition, _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams); + static const auto createFile2FromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "CreateFile2FromAppW")); + if (createFile2FromAppW != nullptr) { + return createFile2FromAppW(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams); + } + + return CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams); +} + +inline BOOL CreateDirectoryFromAppW(_In_ LPCWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes) { + using pCreateDirectoryFromAppW = + BOOL(WINAPI *)(_In_ LPCWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes); + static const auto createDirectoryFromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "CreateDirectoryFromAppW")); + if (createDirectoryFromAppW != nullptr) { + return createDirectoryFromAppW(lpPathName, lpSecurityAttributes); + } + + return CreateDirectoryW(lpPathName, lpSecurityAttributes); +} + +inline BOOL RemoveDirectoryFromAppW(_In_ LPCWSTR lpPathName) { + using pRemoveDirectoryFromAppW = BOOL(WINAPI *)(_In_ LPCWSTR lpPathName); + static const auto removeDirectoryFromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "RemoveDirectoryFromAppW")); + if (removeDirectoryFromAppW != nullptr) { + return removeDirectoryFromAppW(lpPathName); + } + + return RemoveDirectoryW(lpPathName); +} + +inline BOOL DeleteFileFromAppW(_In_ LPCWSTR lpFileName) { + using pDeleteFileFromAppW = BOOL(WINAPI *)(_In_ LPCWSTR lpFileName); + static const auto deleteFileFromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "DeleteFileFromAppW")); + if (deleteFileFromAppW != nullptr) { + return deleteFileFromAppW(lpFileName); + } + + return DeleteFileW(lpFileName); +} + +inline BOOL MoveFileExFromAppW(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) { + using pMoveFileFromAppW = BOOL(WINAPI *)(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName); + static const auto moveFileFromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "MoveFileFromAppW")); + if (moveFileFromAppW != nullptr) { + if (dwFlags == MOVEFILE_REPLACE_EXISTING) { + DeleteFileFromAppW(lpNewFileName); + } + + return moveFileFromAppW(lpExistingFileName, lpNewFileName); + } + + return MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags); +} + +inline HANDLE FindFirstFileExFromAppW(_In_ LPCWSTR lpFileName, _In_ FINDEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData, + _In_ FINDEX_SEARCH_OPS fSearchOp, _Reserved_ LPVOID lpSearchFilter, + _In_ DWORD dwAdditionalFlags) { + using pFindFirstFileExFromAppW = HANDLE(WINAPI *)(_In_ LPCWSTR lpFileName, _In_ FINDEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData, + _In_ FINDEX_SEARCH_OPS fSearchOp, _Reserved_ LPVOID lpSearchFilter, + _In_ DWORD dwAdditionalFlags); + static const auto findFirstFileExFromAppW = + reinterpret_cast(GetProcAddress(GetFromAppModule(), "FindFirstFileExFromAppW")); + if (findFirstFileExFromAppW != nullptr) { + return findFirstFileExFromAppW(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, + dwAdditionalFlags); + } + + return FindFirstFileExW(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); +} +} // namespace td +#endif +#endif diff --git a/tdutils/td/utils/port/path.cpp b/tdutils/td/utils/port/path.cpp index 5935d5ed1..f2f53c69d 100644 --- a/tdutils/td/utils/port/path.cpp +++ b/tdutils/td/utils/port/path.cpp @@ -14,6 +14,7 @@ #include "td/utils/ScopeGuard.h" #if TD_PORT_WINDOWS +#include "td/utils/port/FromApp.h" #include "td/utils/port/wstring_convert.h" #include "td/utils/Random.h" #endif @@ -390,7 +391,11 @@ Status WalkPath::do_run(CSlice path, const detail::WalkFunction &func) { Status mkdir(CSlice dir, int32 mode) { TRY_RESULT(wdir, to_wstring(dir)); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) auto status = CreateDirectoryW(wdir.c_str(), nullptr); +#else + auto status = td::CreateDirectoryFromAppW(wdir.c_str(), nullptr); +#endif if (status == 0 && GetLastError() != ERROR_ALREADY_EXISTS) { return OS_ERROR(PSLICE() << "Can't create directory \"" << dir << '"'); } @@ -400,7 +405,11 @@ Status mkdir(CSlice dir, int32 mode) { Status rename(CSlice from, CSlice to) { TRY_RESULT(wfrom, to_wstring(from)); TRY_RESULT(wto, to_wstring(to)); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) auto status = MoveFileExW(wfrom.c_str(), wto.c_str(), MOVEFILE_REPLACE_EXISTING); +#else + auto status = td::MoveFileExFromAppW(wfrom.c_str(), wto.c_str(), MOVEFILE_REPLACE_EXISTING); +#endif if (status == 0) { return OS_ERROR(PSLICE() << "Can't rename \"" << from << "\" to \"" << to << '\"'); } @@ -443,7 +452,11 @@ Status chdir(CSlice dir) { Status rmdir(CSlice dir) { TRY_RESULT(wdir, to_wstring(dir)); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) int status = RemoveDirectoryW(wdir.c_str()); +#else + int status = td::RemoveDirectoryFromAppW(wdir.c_str()); +#endif if (!status) { return OS_ERROR(PSLICE() << "Can't delete directory \"" << dir << '"'); } @@ -452,7 +465,11 @@ Status rmdir(CSlice dir) { Status unlink(CSlice path) { TRY_RESULT(wpath, to_wstring(path)); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) int status = DeleteFileW(wpath.c_str()); +#else + int status = td::DeleteFileFromAppW(wpath.c_str()); +#endif if (!status) { return OS_ERROR(PSLICE() << "Can't unlink \"" << path << '"'); } @@ -549,7 +566,12 @@ static Result walk_path_dir(const std::wstring &dir_name, const std::function &func) { std::wstring name = dir_name + L"\\*"; WIN32_FIND_DATA file_data; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) auto handle = FindFirstFileExW(name.c_str(), FindExInfoStandard, &file_data, FindExSearchNameMatch, nullptr, 0); +#else + auto handle = + td::FindFirstFileExFromAppW(name.c_str(), FindExInfoStandard, &file_data, FindExSearchNameMatch, nullptr, 0); +#endif if (handle == INVALID_HANDLE_VALUE) { return OS_ERROR(PSLICE() << "FindFirstFileEx" << tag("name", from_wstring(name).ok())); }