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