1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/utils/common.h"
10 
11 #ifdef TD_PORT_WINDOWS
12 
13 namespace td {
14 
15 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
GetKernelModule()16 inline HMODULE GetKernelModule() {
17   static const auto kernel_module = []() -> HMODULE {
18     MEMORY_BASIC_INFORMATION mbi;
19     if (VirtualQuery(VirtualQuery, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) {
20       return reinterpret_cast<HMODULE>(mbi.AllocationBase);
21     }
22     return nullptr;
23   }();
24   return kernel_module;
25 }
26 
LoadLibrary(LPCTSTR lpFileName)27 inline HMODULE LoadLibrary(LPCTSTR lpFileName) {
28   using pLoadLibrary = HMODULE(WINAPI *)(_In_ LPCTSTR);
29   static const auto proc_load_library =
30       reinterpret_cast<pLoadLibrary>(GetProcAddress(GetKernelModule(), "LoadLibraryW"));
31   return proc_load_library(lpFileName);
32 }
33 
GetFromAppModule()34 inline HMODULE GetFromAppModule() {
35   static const HMODULE from_app_module = LoadLibrary(L"api-ms-win-core-file-fromapp-l1-1-0.dll");
36   return from_app_module;
37 }
38 #endif
39 
40 template <int num, class T>
get_from_app_function(const char * name,T * original_func)41 T *get_from_app_function(const char *name, T *original_func) {
42 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
43   return original_func;
44 #else
45   static T *func = [name, original_func]() -> T * {
46     auto func_pointer = GetProcAddress(GetFromAppModule(), name);
47     if (func_pointer == nullptr) {
48       return original_func;
49     }
50     return reinterpret_cast<T *>(func_pointer);
51   }();
52   return func;
53 #endif
54 }
55 
CreateFile2FromAppW(_In_ LPCWSTR lpFileName,_In_ DWORD dwDesiredAccess,_In_ DWORD dwShareMode,_In_ DWORD dwCreationDisposition,_In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams)56 inline HANDLE CreateFile2FromAppW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,
57                                   _In_ DWORD dwCreationDisposition,
58                                   _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) {
59   auto func = get_from_app_function<0>("CreateFile2FromAppW", &CreateFile2);
60   return func(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams);
61 }
62 
CreateDirectoryFromAppW(_In_ LPCWSTR lpPathName,_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes)63 inline BOOL CreateDirectoryFromAppW(_In_ LPCWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes) {
64   auto func = get_from_app_function<1>("CreateDirectoryFromAppW", &CreateDirectory);
65   return func(lpPathName, lpSecurityAttributes);
66 }
67 
RemoveDirectoryFromAppW(_In_ LPCWSTR lpPathName)68 inline BOOL RemoveDirectoryFromAppW(_In_ LPCWSTR lpPathName) {
69   auto func = get_from_app_function<2>("RemoveDirectoryFromAppW", &RemoveDirectory);
70   return func(lpPathName);
71 }
72 
DeleteFileFromAppW(_In_ LPCWSTR lpFileName)73 inline BOOL DeleteFileFromAppW(_In_ LPCWSTR lpFileName) {
74   auto func = get_from_app_function<3>("DeleteFileFromAppW", &DeleteFile);
75   return func(lpFileName);
76 }
77 
MoveFileExFromAppW(_In_ LPCWSTR lpExistingFileName,_In_ LPCWSTR lpNewFileName,_In_ DWORD dwFlags)78 inline BOOL MoveFileExFromAppW(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) {
79   auto func = get_from_app_function<4>("MoveFileFromAppW", static_cast<BOOL(WINAPI *)(LPCWSTR, LPCWSTR)>(nullptr));
80   if (func == nullptr || (dwFlags & ~MOVEFILE_REPLACE_EXISTING) != 0) {
81     // if can't find MoveFileFromAppW or have unsupported flags, call MoveFileEx directly
82     return MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags);
83   }
84   if ((dwFlags & MOVEFILE_REPLACE_EXISTING) != 0) {
85     td::DeleteFileFromAppW(lpNewFileName);
86   }
87   return func(lpExistingFileName, lpNewFileName);
88 }
89 
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)90 inline HANDLE FindFirstFileExFromAppW(_In_ LPCWSTR lpFileName, _In_ FINDEX_INFO_LEVELS fInfoLevelId,
91                                       _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData,
92                                       _In_ FINDEX_SEARCH_OPS fSearchOp, _Reserved_ LPVOID lpSearchFilter,
93                                       _In_ DWORD dwAdditionalFlags) {
94   auto func = get_from_app_function<5>("FindFirstFileExFromAppW", &FindFirstFileEx);
95   return func(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
96 }
97 
98 }  // namespace td
99 
100 #endif
101