15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_co_mem.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" IMAGE_DOS_HEADER __ImageBase; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::FilePath; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PathProviderWin(int key, FilePath* result) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to go compute the value. It would be nice to support paths with 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names longer than MAX_PATH, but the system functions don't seem to be 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // designed for it either, with the exception of GetTempPath (but other 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // things will surely break if the temp path is too long, so we don't bother 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handling it. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t system_buffer[MAX_PATH]; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_buffer[0] = 0; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath cur; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (key) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::FILE_EXE: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModuleFileName(NULL, system_buffer, MAX_PATH); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::FILE_MODULE: { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the resource containing module is assumed to be the one that 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this code lives in, whether that's a dll or exe 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetModuleFileName(this_module, system_buffer, MAX_PATH); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_WINDOWS: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWindowsDirectory(system_buffer, MAX_PATH); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_SYSTEM: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemDirectory(system_buffer, MAX_PATH); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_PROGRAM_FILESX86: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::OSInfo::GetInstance()->architecture() != 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::OSInfo::X86_ARCHITECTURE) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, NULL, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall through to base::DIR_PROGRAM_FILES if we're on an X86 machine. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_PROGRAM_FILES: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_IE_INTERNET_CACHE: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_COMMON_START_MENU: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_START_MENU: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_APP_DATA: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_buffer))) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_COMMON_APP_DATA: 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_LOCAL_APP_DATA_LOW: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (win::GetVersion() < win::VERSION_VISTA) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_buffer))) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer).DirName().AppendASCII("LocalLow"); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_LOCAL_APP_DATA: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_SOURCE_ROOT: { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath executableDir; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Windows, unit tests execute two levels deep from the source root. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example: chrome/{Debug|Release}/ui_tests.exe 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(base::DIR_EXE, &executableDir); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = executableDir.DirName().DirName(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_APP_SHORTCUTS: { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (win::GetVersion() < win::VERSION_WIN8) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedCoMem<wchar_t> path_buf; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetKnownFolderPath(FOLDERID_ApplicationShortcuts, 0, NULL, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &path_buf))) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(string16(path_buf)); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_USER_DESKTOP: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_COMMON_DESKTOP: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHGFP_TYPE_CURRENT, system_buffer))) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = FilePath(system_buffer); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_USER_QUICK_LAUNCH: 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!PathService::Get(base::DIR_APP_DATA, &cur)) 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // According to various sources, appending 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // "Microsoft\Internet Explorer\Quick Launch" to %appdata% is the only 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // reliable way to get the quick launch folder across all versions of 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Windows. 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // http://stackoverflow.com/questions/76080/how-do-you-reliably-get-the-quick- 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0901.mspx 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cur = cur.AppendASCII("Microsoft") 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .AppendASCII("Internet Explorer") 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) .AppendASCII("Quick Launch"); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case base::DIR_TASKBAR_PINS: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::DIR_USER_QUICK_LAUNCH, &cur)) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = cur.AppendASCII("User Pinned"); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = cur.AppendASCII("TaskBar"); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 167effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case base::DIR_WINDOWS_FONTS: 168effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (FAILED(SHGetFolderPath( 169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, system_buffer))) { 170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch cur = FilePath(system_buffer); 173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch break; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = cur; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 183