Environment.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "il2cpp-config.h"
  2. #if !IL2CPP_USE_GENERIC_ENVIRONMENT && IL2CPP_TARGET_WINDOWS
  3. #include "WindowsHelpers.h"
  4. #if !IL2CPP_TARGET_XBOXONE && !IL2CPP_TARGET_WINDOWS_GAMES
  5. #include <Shlobj.h>
  6. #endif
  7. // Windows.h defines GetEnvironmentVariable as GetEnvironmentVariableW for unicode and this will
  8. // change the string "Environment::GetEnvironmentVariable" below to "Environment::GetEnvironmentVariableW"
  9. // in the preprocessor. So we undef to avoid this issue and use GetEnvironmentVariableW directly.
  10. // Same for SetEnvironmentVariable
  11. #undef GetEnvironmentVariable
  12. #undef SetEnvironmentVariable
  13. #include "os/Environment.h"
  14. #include "utils/StringUtils.h"
  15. #include <string>
  16. #define BUFFER_SIZE 1024
  17. namespace il2cpp
  18. {
  19. namespace os
  20. {
  21. std::string Environment::GetMachineName()
  22. {
  23. Il2CppChar computerName[MAX_COMPUTERNAME_LENGTH + 1];
  24. DWORD size = sizeof(computerName) / sizeof(computerName[0]);
  25. if (!GetComputerNameW(computerName, &size))
  26. return NULL;
  27. return utils::StringUtils::Utf16ToUtf8(computerName);
  28. }
  29. int32_t Environment::GetProcessorCount()
  30. {
  31. SYSTEM_INFO info;
  32. GetSystemInfo(&info);
  33. return info.dwNumberOfProcessors;
  34. }
  35. // GetVersionEx is deprecated on desktop in Windows SDK, and we shim it for WinRT
  36. #pragma warning( push )
  37. #pragma warning( disable : 4996 )
  38. std::string Environment::GetOsVersionString()
  39. {
  40. OSVERSIONINFO verinfo;
  41. verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  42. if (GetVersionEx(&verinfo))
  43. {
  44. char version[64];
  45. /* maximum string length is 35 bytes
  46. 3 x 10 bytes per number, 1 byte for 0, 3 x 1 byte for dots, 1 for NULL */
  47. sprintf(version, "%ld.%ld.%ld.0",
  48. verinfo.dwMajorVersion,
  49. verinfo.dwMinorVersion,
  50. verinfo.dwBuildNumber);
  51. return version;
  52. }
  53. return "0.0.0.0";
  54. }
  55. #pragma warning( pop )
  56. std::string Environment::GetOsUserName()
  57. {
  58. #if !IL2CPP_TARGET_WINDOWS_GAMES
  59. Il2CppChar user_name[256 + 1];
  60. DWORD user_name_size = ARRAYSIZE(user_name);
  61. if (GetUserNameW(user_name, &user_name_size))
  62. return utils::StringUtils::Utf16ToUtf8(user_name);
  63. #endif // !IL2CPP_TARGET_WINDOWS_GAMES
  64. return "Unknown";
  65. }
  66. std::string Environment::GetEnvironmentVariable(const std::string& name)
  67. {
  68. std::vector<Il2CppChar> buffer(BUFFER_SIZE);
  69. const UTF16String varName = utils::StringUtils::Utf8ToUtf16(name.c_str());
  70. DWORD ret = GetEnvironmentVariableW(varName.c_str(), &buffer[0], BUFFER_SIZE);
  71. if (ret == 0) // Not found
  72. return std::string();
  73. if (ret < BUFFER_SIZE) // Found and fits into buffer
  74. return utils::StringUtils::Utf16ToUtf8(&buffer[0]);
  75. // Requires bigger buffer
  76. IL2CPP_ASSERT(ret >= BUFFER_SIZE);
  77. buffer.resize(ret + 1);
  78. ret = GetEnvironmentVariableW(varName.c_str(), &buffer[0], ret + 1);
  79. IL2CPP_ASSERT(ret != 0);
  80. return utils::StringUtils::Utf16ToUtf8(&buffer[0]);
  81. }
  82. void Environment::SetEnvironmentVariable(const std::string& name, const std::string& value)
  83. {
  84. const UTF16String varName = utils::StringUtils::Utf8ToUtf16(name.c_str());
  85. if (value.empty())
  86. SetEnvironmentVariableW((LPWSTR)varName.c_str(), NULL);
  87. else
  88. {
  89. const UTF16String varValue = utils::StringUtils::Utf8ToUtf16(value.c_str());
  90. SetEnvironmentVariableW((LPWSTR)varName.c_str(), (LPWSTR)varValue.c_str());
  91. }
  92. }
  93. std::vector<std::string> Environment::GetEnvironmentVariableNames()
  94. {
  95. WCHAR* env_strings;
  96. WCHAR* env_string;
  97. WCHAR* equal_str;
  98. std::vector<std::string> result;
  99. env_strings = GetEnvironmentStringsW();
  100. if (env_strings)
  101. {
  102. env_string = env_strings;
  103. while (*env_string != '\0')
  104. {
  105. // Skip over environment variables starting with '='
  106. if (*env_string != '=')
  107. {
  108. equal_str = wcschr(env_string, '=');
  109. result.push_back(utils::StringUtils::Utf16ToUtf8(env_string, (int)(equal_str - env_string)));
  110. }
  111. while (*env_string != '\0')
  112. env_string++;
  113. env_string++;
  114. }
  115. FreeEnvironmentStringsW(env_strings);
  116. }
  117. return result;
  118. }
  119. std::string Environment::GetHomeDirectory()
  120. {
  121. #if IL2CPP_TARGET_WINDOWS_DESKTOP
  122. std::string home_directory;
  123. PWSTR profile_path = NULL;
  124. HRESULT hr = SHGetKnownFolderPath(FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &profile_path);
  125. if (SUCCEEDED(hr))
  126. {
  127. home_directory = utils::StringUtils::Utf16ToUtf8(profile_path);
  128. CoTaskMemFree(profile_path);
  129. }
  130. if (home_directory.empty())
  131. {
  132. home_directory = GetEnvironmentVariable("USERPROFILE");
  133. }
  134. if (home_directory.empty())
  135. {
  136. std::string drive = GetEnvironmentVariable("HOMEDRIVE");
  137. std::string path = GetEnvironmentVariable("HOMEPATH");
  138. if (!drive.empty() && !path.empty())
  139. home_directory = drive + path;
  140. }
  141. return home_directory;
  142. #else
  143. IL2CPP_NOT_IMPLEMENTED_ICALL(Environment::GetHomeDirectory);
  144. return std::string();
  145. #endif
  146. }
  147. std::vector<std::string> SplitLogicalDriveString(Il2CppChar *buffer, DWORD size)
  148. {
  149. std::vector<std::string> retVal;
  150. Il2CppChar *ptr = buffer;
  151. for (DWORD i = 0; i < size; ++i)
  152. {
  153. Il2CppChar c = buffer[i];
  154. if (c == 0)
  155. {
  156. retVal.push_back(utils::StringUtils::Utf16ToUtf8(ptr));
  157. ptr = &buffer[i + 1];
  158. }
  159. }
  160. return retVal;
  161. }
  162. std::vector<std::string> Environment::GetLogicalDrives()
  163. {
  164. #if IL2CPP_TARGET_WINDOWS_DESKTOP
  165. std::vector<Il2CppChar> buffer(BUFFER_SIZE);
  166. DWORD size = GetLogicalDriveStringsW(BUFFER_SIZE, &buffer[0]);
  167. if (size == 0)
  168. return std::vector<std::string>();
  169. if (size > BUFFER_SIZE)
  170. {
  171. buffer.resize(size + 1);
  172. size = GetLogicalDriveStringsW(size + 1, &buffer[0]);
  173. IL2CPP_ASSERT(size != 0);
  174. }
  175. return SplitLogicalDriveString(&buffer[0], size);
  176. #else
  177. return std::vector<std::string>();
  178. #endif
  179. }
  180. void Environment::Exit(int result)
  181. {
  182. ::exit(result);
  183. }
  184. NORETURN void Environment::Abort()
  185. {
  186. // __fastfail() is available since VS2012
  187. #if _MSC_VER >= 1700
  188. __fastfail(FAST_FAIL_FATAL_APP_EXIT);
  189. #else
  190. abort();
  191. #endif
  192. }
  193. #if IL2CPP_TARGET_WINDOWS_DESKTOP
  194. utils::Expected<std::string> Environment::GetWindowsFolderPath(int32_t folder)
  195. {
  196. Il2CppChar path[MAX_PATH];
  197. if (SUCCEEDED(SHGetFolderPathW(NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path)))
  198. return utils::StringUtils::Utf16ToUtf8(path);
  199. return std::string();
  200. }
  201. typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  202. utils::Expected<bool> Environment::Is64BitOs()
  203. {
  204. BOOL isWow64Process = false;
  205. // Supported on XP SP2 and higher
  206. //IsWow64Process is not available on all supported versions of Windows.
  207. //Use GetModuleHandle to get a handle to the DLL that contains the function
  208. //and GetProcAddress to get a pointer to the function if available.
  209. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
  210. GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
  211. if (NULL != fnIsWow64Process)
  212. {
  213. if (fnIsWow64Process(GetCurrentProcess(), &isWow64Process))
  214. {
  215. return isWow64Process == TRUE;
  216. }
  217. }
  218. return false;
  219. }
  220. #elif IL2CPP_TARGET_WINDOWS_GAMES
  221. utils::Expected<std::string> Environment::GetWindowsFolderPath(int32_t folder)
  222. {
  223. return std::string();
  224. }
  225. utils::Expected<bool> Environment::Is64BitOs()
  226. {
  227. #if _WIN64 // the IsWow64Process(used above) function is not available on Windows Games,this is the best available.
  228. return true;
  229. #else
  230. return false;
  231. #endif
  232. }
  233. #endif
  234. }
  235. }
  236. #endif