michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/base_paths.h" michael@0: #include "base/files/file_path.h" michael@0: #include "base/path_service.h" michael@0: #include "base/win/scoped_co_mem.h" michael@0: #include "base/win/windows_version.h" michael@0: michael@0: // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx michael@0: extern "C" IMAGE_DOS_HEADER __ImageBase; michael@0: michael@0: using base::FilePath; michael@0: michael@0: namespace { michael@0: michael@0: bool GetQuickLaunchPath(bool default_user, FilePath* result) { michael@0: if (default_user) { michael@0: wchar_t system_buffer[MAX_PATH]; michael@0: system_buffer[0] = 0; michael@0: // As per MSDN, passing -1 for |hToken| indicates the Default user: michael@0: // http://msdn.microsoft.com/library/windows/desktop/bb762181.aspx michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, michael@0: reinterpret_cast(-1), SHGFP_TYPE_CURRENT, michael@0: system_buffer))) { michael@0: return false; michael@0: } michael@0: *result = FilePath(system_buffer); michael@0: } else if (!PathService::Get(base::DIR_APP_DATA, result)) { michael@0: // For the current user, grab the APPDATA directory directly from the michael@0: // PathService cache. michael@0: return false; michael@0: } michael@0: // According to various sources, appending michael@0: // "Microsoft\Internet Explorer\Quick Launch" to %appdata% is the only michael@0: // reliable way to get the quick launch folder across all versions of Windows. michael@0: // http://stackoverflow.com/questions/76080/how-do-you-reliably-get-the-quick- michael@0: // http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0901.mspx michael@0: *result = result->AppendASCII("Microsoft"); michael@0: *result = result->AppendASCII("Internet Explorer"); michael@0: *result = result->AppendASCII("Quick Launch"); michael@0: return true; michael@0: } michael@0: michael@0: } // namespace michael@0: michael@0: namespace base { michael@0: michael@0: bool PathProviderWin(int key, FilePath* result) { michael@0: // We need to go compute the value. It would be nice to support paths with michael@0: // names longer than MAX_PATH, but the system functions don't seem to be michael@0: // designed for it either, with the exception of GetTempPath (but other michael@0: // things will surely break if the temp path is too long, so we don't bother michael@0: // handling it. michael@0: wchar_t system_buffer[MAX_PATH]; michael@0: system_buffer[0] = 0; michael@0: michael@0: FilePath cur; michael@0: switch (key) { michael@0: case base::FILE_EXE: michael@0: GetModuleFileName(NULL, system_buffer, MAX_PATH); michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::FILE_MODULE: { michael@0: // the resource containing module is assumed to be the one that michael@0: // this code lives in, whether that's a dll or exe michael@0: HMODULE this_module = reinterpret_cast(&__ImageBase); michael@0: GetModuleFileName(this_module, system_buffer, MAX_PATH); michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: } michael@0: case base::DIR_WINDOWS: michael@0: GetWindowsDirectory(system_buffer, MAX_PATH); michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_SYSTEM: michael@0: GetSystemDirectory(system_buffer, MAX_PATH); michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_PROGRAM_FILESX86: michael@0: if (base::win::OSInfo::GetInstance()->architecture() != michael@0: base::win::OSInfo::X86_ARCHITECTURE) { michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: } michael@0: // Fall through to base::DIR_PROGRAM_FILES if we're on an X86 machine. michael@0: case base::DIR_PROGRAM_FILES: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_IE_INTERNET_CACHE: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_COMMON_START_MENU: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_START_MENU: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_APP_DATA: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, michael@0: system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_COMMON_APP_DATA: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_PROFILE: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, michael@0: system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_LOCAL_APP_DATA_LOW: michael@0: if (win::GetVersion() < win::VERSION_VISTA) michael@0: return false; michael@0: michael@0: // TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128 michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, michael@0: system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer).DirName().AppendASCII("LocalLow"); michael@0: break; michael@0: case base::DIR_LOCAL_APP_DATA: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) michael@0: return false; michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_SOURCE_ROOT: { michael@0: FilePath executableDir; michael@0: // On Windows, unit tests execute two levels deep from the source root. michael@0: // For example: chrome/{Debug|Release}/ui_tests.exe michael@0: PathService::Get(base::DIR_EXE, &executableDir); michael@0: cur = executableDir.DirName().DirName(); michael@0: break; michael@0: } michael@0: case base::DIR_APP_SHORTCUTS: { michael@0: if (win::GetVersion() < win::VERSION_WIN8) michael@0: return false; michael@0: michael@0: base::win::ScopedCoMem path_buf; michael@0: if (FAILED(SHGetKnownFolderPath(FOLDERID_ApplicationShortcuts, 0, NULL, michael@0: &path_buf))) michael@0: return false; michael@0: michael@0: cur = FilePath(string16(path_buf)); michael@0: break; michael@0: } michael@0: case base::DIR_USER_DESKTOP: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) { michael@0: return false; michael@0: } michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_COMMON_DESKTOP: michael@0: if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, michael@0: SHGFP_TYPE_CURRENT, system_buffer))) { michael@0: return false; michael@0: } michael@0: cur = FilePath(system_buffer); michael@0: break; michael@0: case base::DIR_USER_QUICK_LAUNCH: michael@0: if (!GetQuickLaunchPath(false, &cur)) michael@0: return false; michael@0: break; michael@0: case base::DIR_DEFAULT_USER_QUICK_LAUNCH: michael@0: if (!GetQuickLaunchPath(true, &cur)) michael@0: return false; michael@0: break; michael@0: case base::DIR_TASKBAR_PINS: michael@0: if (!PathService::Get(base::DIR_USER_QUICK_LAUNCH, &cur)) michael@0: return false; michael@0: cur = cur.AppendASCII("User Pinned"); michael@0: cur = cur.AppendASCII("TaskBar"); michael@0: break; michael@0: default: michael@0: return false; michael@0: } michael@0: michael@0: *result = cur; michael@0: return true; michael@0: } michael@0: michael@0: } // namespace base