1 // Copyright (c) 2010 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 "base/base_paths_win.h" 6 7 #include <windows.h> 8 #include <shlobj.h> 9 10 #include "base/file_path.h" 11 #include "base/file_util.h" 12 #include "base/path_service.h" 13 #include "base/win/windows_version.h" 14 15 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx 16 extern "C" IMAGE_DOS_HEADER __ImageBase; 17 18 namespace base { 19 20 bool PathProviderWin(int key, FilePath* result) { 21 22 // We need to go compute the value. It would be nice to support paths with 23 // names longer than MAX_PATH, but the system functions don't seem to be 24 // designed for it either, with the exception of GetTempPath (but other 25 // things will surely break if the temp path is too long, so we don't bother 26 // handling it. 27 wchar_t system_buffer[MAX_PATH]; 28 system_buffer[0] = 0; 29 30 FilePath cur; 31 switch (key) { 32 case base::FILE_EXE: 33 GetModuleFileName(NULL, system_buffer, MAX_PATH); 34 cur = FilePath(system_buffer); 35 break; 36 case base::FILE_MODULE: { 37 // the resource containing module is assumed to be the one that 38 // this code lives in, whether that's a dll or exe 39 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); 40 GetModuleFileName(this_module, system_buffer, MAX_PATH); 41 cur = FilePath(system_buffer); 42 break; 43 } 44 case base::DIR_WINDOWS: 45 GetWindowsDirectory(system_buffer, MAX_PATH); 46 cur = FilePath(system_buffer); 47 break; 48 case base::DIR_SYSTEM: 49 GetSystemDirectory(system_buffer, MAX_PATH); 50 cur = FilePath(system_buffer); 51 break; 52 case base::DIR_PROGRAM_FILES: 53 if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 54 SHGFP_TYPE_CURRENT, system_buffer))) 55 return false; 56 cur = FilePath(system_buffer); 57 break; 58 case base::DIR_IE_INTERNET_CACHE: 59 if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, 60 SHGFP_TYPE_CURRENT, system_buffer))) 61 return false; 62 cur = FilePath(system_buffer); 63 break; 64 case base::DIR_COMMON_START_MENU: 65 if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL, 66 SHGFP_TYPE_CURRENT, system_buffer))) 67 return false; 68 cur = FilePath(system_buffer); 69 break; 70 case base::DIR_START_MENU: 71 if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 72 SHGFP_TYPE_CURRENT, system_buffer))) 73 return false; 74 cur = FilePath(system_buffer); 75 break; 76 case base::DIR_APP_DATA: 77 if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, 78 system_buffer))) 79 return false; 80 cur = FilePath(system_buffer); 81 break; 82 case base::DIR_PROFILE: 83 if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, 84 system_buffer))) 85 return false; 86 cur = FilePath(system_buffer); 87 break; 88 case base::DIR_LOCAL_APP_DATA_LOW: 89 if (win::GetVersion() < win::VERSION_VISTA) { 90 return false; 91 } 92 // TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128 93 if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, 94 system_buffer))) 95 return false; 96 cur = FilePath(system_buffer).DirName().AppendASCII("LocalLow"); 97 break; 98 case base::DIR_LOCAL_APP_DATA: 99 if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 100 SHGFP_TYPE_CURRENT, system_buffer))) 101 return false; 102 cur = FilePath(system_buffer); 103 break; 104 case base::DIR_SOURCE_ROOT: { 105 FilePath executableDir; 106 // On Windows, unit tests execute two levels deep from the source root. 107 // For example: chrome/{Debug|Release}/ui_tests.exe 108 PathService::Get(base::DIR_EXE, &executableDir); 109 cur = executableDir.DirName().DirName(); 110 FilePath checkedPath = 111 cur.Append(FILE_PATH_LITERAL("base/base_paths_win.cc")); 112 if (!file_util::PathExists(checkedPath)) { 113 // Check for WebKit-only checkout. Executable files are put into 114 // WebKit/WebKit/chromium/{Debug|Relese}, and we should return 115 // WebKit/WebKit/chromium. 116 cur = executableDir.DirName(); 117 } 118 break; 119 } 120 default: 121 return false; 122 } 123 124 *result = cur; 125 return true; 126 } 127 128 } // namespace base 129