Directory.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include "il2cpp-config.h"
  2. #if IL2CPP_TARGET_WINDOWS
  3. #include "WindowsHeaders.h"
  4. #undef FindFirstFile
  5. #undef FindNextFile
  6. #include "os/Directory.h"
  7. #include "os/ErrorCodes.h"
  8. #include "utils/StringUtils.h"
  9. #include "utils/PathUtils.h"
  10. #if IL2CPP_TARGET_WINRT
  11. #include "os/BrokeredFileSystem.h"
  12. #endif
  13. static inline int DirectoryWin32ErrorToErrorCode(DWORD win32ErrorCode)
  14. {
  15. return win32ErrorCode;
  16. }
  17. using namespace il2cpp::utils::PathUtils;
  18. namespace il2cpp
  19. {
  20. namespace os
  21. {
  22. std::string Directory::GetCurrent(int *error)
  23. {
  24. UTF16String buf;
  25. int len, res_len;
  26. len = MAX_PATH + 1;
  27. buf.resize(len, 0);
  28. *error = ERROR_SUCCESS;
  29. res_len = ::GetCurrentDirectory(len, (LPWSTR)buf.c_str());
  30. if (res_len > len) /*buf is too small.*/
  31. {
  32. int old_res_len = res_len;
  33. buf.resize(res_len, 0);
  34. res_len = ::GetCurrentDirectory(res_len, (LPWSTR)buf.c_str()) == old_res_len;
  35. }
  36. std::string directory;
  37. if (res_len)
  38. {
  39. len = 0;
  40. while (buf[len])
  41. ++len;
  42. directory = il2cpp::utils::StringUtils::Utf16ToUtf8(buf.c_str());
  43. }
  44. else
  45. {
  46. *error = DirectoryWin32ErrorToErrorCode(::GetLastError());
  47. }
  48. return directory;
  49. }
  50. bool Directory::SetCurrent(const std::string& path, int* error)
  51. {
  52. *error = kErrorCodeSuccess;
  53. const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str()));
  54. if (::SetCurrentDirectory((LPWSTR)utf16Path.c_str()))
  55. return true;
  56. *error = DirectoryWin32ErrorToErrorCode(::GetLastError());
  57. return false;
  58. }
  59. bool Directory::Create(const std::string& path, int *error)
  60. {
  61. *error = kErrorCodeSuccess;
  62. const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str()));
  63. if (::CreateDirectory((LPWSTR)utf16Path.c_str(), NULL))
  64. return true;
  65. auto lastError = ::GetLastError();
  66. #if IL2CPP_TARGET_WINRT
  67. if (lastError == ERROR_ACCESS_DENIED)
  68. {
  69. *error = BrokeredFileSystem::CreateDirectoryW(utf16Path);
  70. return *error == kErrorCodeSuccess;
  71. }
  72. #endif
  73. *error = DirectoryWin32ErrorToErrorCode(lastError);
  74. return false;
  75. }
  76. bool Directory::Remove(const std::string& path, int *error)
  77. {
  78. *error = kErrorCodeSuccess;
  79. const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str()));
  80. if (::RemoveDirectory((LPWSTR)utf16Path.c_str()))
  81. return true;
  82. auto lastError = ::GetLastError();
  83. #if IL2CPP_TARGET_WINRT
  84. if (lastError == ERROR_ACCESS_DENIED)
  85. {
  86. *error = BrokeredFileSystem::RemoveDirectoryW(utf16Path);
  87. return *error == kErrorCodeSuccess;
  88. }
  89. #endif
  90. *error = DirectoryWin32ErrorToErrorCode(lastError);
  91. return false;
  92. }
  93. std::set<std::string> Directory::GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attrs, int32_t mask, int* error)
  94. {
  95. *error = kErrorCodeSuccess;
  96. std::set<std::string> files;
  97. WIN32_FIND_DATA ffd;
  98. const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(pathWithPattern));
  99. HANDLE handle = ::FindFirstFileExW((LPCWSTR)utf16Path.c_str(), FindExInfoStandard, &ffd, FindExSearchNameMatch, NULL, 0);
  100. if (INVALID_HANDLE_VALUE == handle)
  101. {
  102. auto lastError = ::GetLastError();
  103. #if IL2CPP_TARGET_WINRT
  104. if (lastError == ERROR_ACCESS_DENIED)
  105. return BrokeredFileSystem::GetFileSystemEntries(utils::StringUtils::Utf8ToUtf16(path), utf16Path, attrs, mask, error);
  106. #endif
  107. // Following the Mono implementation, do not treat a directory with no files as an error.
  108. int errorCode = DirectoryWin32ErrorToErrorCode(lastError);
  109. if (errorCode != ERROR_FILE_NOT_FOUND)
  110. *error = errorCode;
  111. return files;
  112. }
  113. do
  114. {
  115. const std::string fileName(il2cpp::utils::StringUtils::Utf16ToUtf8(ffd.cFileName));
  116. if ((fileName.length() == 1 && fileName.at(0) == '.') ||
  117. (fileName.length() == 2 && fileName.at(0) == '.' && fileName.at(1) == '.'))
  118. continue;
  119. if ((ffd.dwFileAttributes & mask) == attrs)
  120. {
  121. files.insert(Combine(path, fileName));
  122. }
  123. }
  124. while (::FindNextFileW(handle, &ffd) != 0);
  125. ::FindClose(handle);
  126. return files;
  127. }
  128. Directory::FindHandle::FindHandle(const utils::StringView<Il2CppNativeChar>& searchPathWithPattern) :
  129. osHandle(INVALID_HANDLE_VALUE),
  130. handleFlags(os::kNoFindHandleFlags),
  131. directoryPath(il2cpp::utils::PathUtils::DirectoryName(searchPathWithPattern)),
  132. pattern(il2cpp::utils::PathUtils::Basename(searchPathWithPattern))
  133. {
  134. }
  135. Directory::FindHandle::~FindHandle()
  136. {
  137. IL2CPP_ASSERT(osHandle == INVALID_HANDLE_VALUE);
  138. }
  139. int32_t Directory::FindHandle::CloseOSHandle()
  140. {
  141. int32_t result = os::kErrorCodeSuccess;
  142. if (osHandle != INVALID_HANDLE_VALUE)
  143. {
  144. #if IL2CPP_TARGET_WINRT
  145. if (handleFlags & kUseBrokeredFileSystem)
  146. {
  147. result = BrokeredFileSystem::FindClose(osHandle);
  148. }
  149. else
  150. #endif
  151. {
  152. result = ::FindClose(osHandle);
  153. }
  154. osHandle = INVALID_HANDLE_VALUE;
  155. }
  156. return result;
  157. }
  158. os::ErrorCode Directory::FindFirstFile(FindHandle* findHandle, const utils::StringView<Il2CppNativeChar>& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes)
  159. {
  160. WIN32_FIND_DATA findData;
  161. HANDLE handle = FindFirstFileExW(searchPathWithPattern.Str(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0);
  162. if (handle != INVALID_HANDLE_VALUE)
  163. {
  164. findHandle->SetOSHandle(handle);
  165. *resultFileName = findData.cFileName;
  166. *resultAttributes = findData.dwFileAttributes;
  167. return os::kErrorCodeSuccess;
  168. }
  169. else
  170. {
  171. auto lastError = GetLastError();
  172. #if IL2CPP_TARGET_WINRT
  173. if (lastError == ERROR_ACCESS_DENIED)
  174. return BrokeredFileSystem::FindFirstFileW(findHandle, searchPathWithPattern, resultFileName, resultAttributes);
  175. #endif
  176. return static_cast<os::ErrorCode>(lastError);
  177. }
  178. }
  179. os::ErrorCode Directory::FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes)
  180. {
  181. #if IL2CPP_TARGET_WINRT
  182. if (findHandle->handleFlags & kUseBrokeredFileSystem)
  183. return BrokeredFileSystem::FindNextFileW(findHandle, resultFileName, resultAttributes);
  184. #endif
  185. WIN32_FIND_DATA findData;
  186. if (FindNextFileW(findHandle->osHandle, &findData) == FALSE)
  187. return static_cast<os::ErrorCode>(GetLastError());
  188. *resultFileName = findData.cFileName;
  189. *resultAttributes = findData.dwFileAttributes;
  190. return os::kErrorCodeSuccess;
  191. }
  192. int32_t Directory::CloseOSFindHandleDirectly(intptr_t osHandle)
  193. {
  194. return ::FindClose((HANDLE)osHandle);
  195. }
  196. }
  197. }
  198. #endif