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