base_paths_win.cc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <windows.h>
  5. #include <KnownFolders.h>
  6. #include <shlobj.h>
  7. #include "base/base_paths.h"
  8. #include "base/environment.h"
  9. #include "base/files/file_path.h"
  10. #include "base/path_service.h"
  11. #include "base/strings/string_util.h"
  12. #include "base/strings/utf_string_conversions.h"
  13. #include "base/win/current_module.h"
  14. #include "base/win/scoped_co_mem.h"
  15. #include "base/win/windows_version.h"
  16. using base::FilePath;
  17. namespace base {
  18. bool PathProviderWin(int key, FilePath* result) {
  19. // We need to go compute the value. It would be nice to support paths with
  20. // names longer than MAX_PATH, but the system functions don't seem to be
  21. // designed for it either, with the exception of GetTempPath (but other
  22. // things will surely break if the temp path is too long, so we don't bother
  23. // handling it.
  24. wchar_t system_buffer[MAX_PATH];
  25. system_buffer[0] = 0;
  26. FilePath cur;
  27. switch (key) {
  28. case base::FILE_EXE:
  29. if (GetModuleFileName(NULL, system_buffer, MAX_PATH) == 0)
  30. return false;
  31. cur = FilePath(system_buffer);
  32. break;
  33. case base::FILE_MODULE: {
  34. // the resource containing module is assumed to be the one that
  35. // this code lives in, whether that's a dll or exe
  36. if (GetModuleFileName(CURRENT_MODULE(), system_buffer, MAX_PATH) == 0)
  37. return false;
  38. cur = FilePath(system_buffer);
  39. break;
  40. }
  41. case base::DIR_WINDOWS:
  42. GetWindowsDirectory(system_buffer, MAX_PATH);
  43. cur = FilePath(system_buffer);
  44. break;
  45. case base::DIR_SYSTEM:
  46. GetSystemDirectory(system_buffer, MAX_PATH);
  47. cur = FilePath(system_buffer);
  48. break;
  49. case base::DIR_PROGRAM_FILESX86:
  50. if (win::OSInfo::GetArchitecture() != win::OSInfo::X86_ARCHITECTURE) {
  51. if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, NULL,
  52. SHGFP_TYPE_CURRENT, system_buffer)))
  53. return false;
  54. cur = FilePath(system_buffer);
  55. break;
  56. }
  57. // Fall through to base::DIR_PROGRAM_FILES if we're on an X86 machine.
  58. [[fallthrough]];
  59. case base::DIR_PROGRAM_FILES:
  60. if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
  61. SHGFP_TYPE_CURRENT, system_buffer)))
  62. return false;
  63. cur = FilePath(system_buffer);
  64. break;
  65. case base::DIR_PROGRAM_FILES6432:
  66. #if !defined(_WIN64)
  67. if (base::win::OSInfo::GetInstance()->IsWowX86OnAMD64()) {
  68. std::unique_ptr<base::Environment> env(base::Environment::Create());
  69. std::string programfiles_w6432;
  70. // 32-bit process running in WOW64 sets ProgramW6432 environment
  71. // variable. See
  72. // https://msdn.microsoft.com/library/windows/desktop/aa384274.aspx.
  73. if (!env->GetVar("ProgramW6432", &programfiles_w6432))
  74. return false;
  75. // GetVar returns UTF8 - convert back to Wide.
  76. cur = FilePath(UTF8ToWide(programfiles_w6432));
  77. break;
  78. }
  79. #endif
  80. if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
  81. SHGFP_TYPE_CURRENT, system_buffer)))
  82. return false;
  83. cur = FilePath(system_buffer);
  84. break;
  85. case base::DIR_IE_INTERNET_CACHE:
  86. if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL,
  87. SHGFP_TYPE_CURRENT, system_buffer)))
  88. return false;
  89. cur = FilePath(system_buffer);
  90. break;
  91. case base::DIR_COMMON_START_MENU:
  92. if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL,
  93. SHGFP_TYPE_CURRENT, system_buffer)))
  94. return false;
  95. cur = FilePath(system_buffer);
  96. break;
  97. case base::DIR_START_MENU:
  98. if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT,
  99. system_buffer)))
  100. return false;
  101. cur = FilePath(system_buffer);
  102. break;
  103. case base::DIR_COMMON_STARTUP:
  104. if (FAILED(SHGetFolderPath(nullptr, CSIDL_COMMON_STARTUP, nullptr,
  105. SHGFP_TYPE_CURRENT, system_buffer)))
  106. return false;
  107. cur = FilePath(system_buffer);
  108. break;
  109. case base::DIR_USER_STARTUP:
  110. if (FAILED(SHGetFolderPath(nullptr, CSIDL_STARTUP, nullptr,
  111. SHGFP_TYPE_CURRENT, system_buffer)))
  112. return false;
  113. cur = FilePath(system_buffer);
  114. break;
  115. case base::DIR_ROAMING_APP_DATA:
  116. if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
  117. system_buffer)))
  118. return false;
  119. cur = FilePath(system_buffer);
  120. break;
  121. case base::DIR_COMMON_APP_DATA:
  122. if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
  123. SHGFP_TYPE_CURRENT, system_buffer)))
  124. return false;
  125. cur = FilePath(system_buffer);
  126. break;
  127. case base::DIR_LOCAL_APP_DATA:
  128. if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
  129. SHGFP_TYPE_CURRENT, system_buffer)))
  130. return false;
  131. cur = FilePath(system_buffer);
  132. break;
  133. case base::DIR_SRC_TEST_DATA_ROOT: {
  134. FilePath executableDir;
  135. // On Windows, unit tests execute two levels deep from the source root.
  136. // For example: chrome/{Debug|Release}/ui_tests.exe
  137. PathService::Get(base::DIR_EXE, &executableDir);
  138. cur = executableDir.DirName().DirName();
  139. break;
  140. }
  141. case base::DIR_APP_SHORTCUTS: {
  142. if (win::GetVersion() < win::Version::WIN8)
  143. return false;
  144. base::win::ScopedCoMem<wchar_t> path_buf;
  145. if (FAILED(SHGetKnownFolderPath(FOLDERID_ApplicationShortcuts, 0, NULL,
  146. &path_buf)))
  147. return false;
  148. cur = FilePath(path_buf.get());
  149. break;
  150. }
  151. case base::DIR_USER_DESKTOP:
  152. if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
  153. SHGFP_TYPE_CURRENT, system_buffer))) {
  154. return false;
  155. }
  156. cur = FilePath(system_buffer);
  157. break;
  158. case base::DIR_COMMON_DESKTOP:
  159. if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL,
  160. SHGFP_TYPE_CURRENT, system_buffer))) {
  161. return false;
  162. }
  163. cur = FilePath(system_buffer);
  164. break;
  165. case base::DIR_USER_QUICK_LAUNCH:
  166. if (!PathService::Get(base::DIR_ROAMING_APP_DATA, &cur))
  167. return false;
  168. // According to various sources, appending
  169. // "Microsoft\Internet Explorer\Quick Launch" to %appdata% is the only
  170. // reliable way to get the quick launch folder across all versions of
  171. // Windows.
  172. // http://stackoverflow.com/questions/76080/how-do-you-reliably-get-the-quick-
  173. // http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0901.mspx
  174. cur = cur.Append(FILE_PATH_LITERAL("Microsoft"))
  175. .Append(FILE_PATH_LITERAL("Internet Explorer"))
  176. .Append(FILE_PATH_LITERAL("Quick Launch"));
  177. break;
  178. case base::DIR_TASKBAR_PINS: {
  179. if (!PathService::Get(base::DIR_USER_QUICK_LAUNCH, &cur))
  180. return false;
  181. cur = cur.Append(FILE_PATH_LITERAL("User Pinned"))
  182. .Append(FILE_PATH_LITERAL("TaskBar"));
  183. break;
  184. }
  185. case base::DIR_IMPLICIT_APP_SHORTCUTS:
  186. if (!PathService::Get(base::DIR_USER_QUICK_LAUNCH, &cur))
  187. return false;
  188. cur = cur.Append(FILE_PATH_LITERAL("User Pinned"))
  189. .Append(FILE_PATH_LITERAL("ImplicitAppShortcuts"));
  190. break;
  191. case base::DIR_WINDOWS_FONTS:
  192. if (FAILED(SHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT,
  193. system_buffer))) {
  194. return false;
  195. }
  196. cur = FilePath(system_buffer);
  197. break;
  198. default:
  199. return false;
  200. }
  201. *result = cur;
  202. return true;
  203. }
  204. } // namespace base