base_paths_win.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2006-2008 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_util.h"
14
15// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
16extern "C" IMAGE_DOS_HEADER __ImageBase;
17
18namespace base {
19
20bool 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  std::wstring wstring_path;
32  switch (key) {
33    case base::FILE_EXE:
34      GetModuleFileName(NULL, system_buffer, MAX_PATH);
35      cur = FilePath(system_buffer);
36      break;
37    case base::FILE_MODULE: {
38      // the resource containing module is assumed to be the one that
39      // this code lives in, whether that's a dll or exe
40      HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
41      GetModuleFileName(this_module, system_buffer, MAX_PATH);
42      cur = FilePath(system_buffer);
43      break;
44    }
45    case base::DIR_WINDOWS:
46      GetWindowsDirectory(system_buffer, MAX_PATH);
47      cur = FilePath(system_buffer);
48      break;
49    case base::DIR_SYSTEM:
50      GetSystemDirectory(system_buffer, MAX_PATH);
51      cur = FilePath(system_buffer);
52      break;
53    case base::DIR_PROGRAM_FILES:
54      if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
55                                 SHGFP_TYPE_CURRENT, system_buffer)))
56        return false;
57      cur = FilePath(system_buffer);
58      break;
59    case base::DIR_IE_INTERNET_CACHE:
60      if (FAILED(SHGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL,
61                                 SHGFP_TYPE_CURRENT, system_buffer)))
62        return false;
63      cur = FilePath(system_buffer);
64      break;
65    case base::DIR_COMMON_START_MENU:
66      if (FAILED(SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL,
67                                 SHGFP_TYPE_CURRENT, system_buffer)))
68        return false;
69      cur = FilePath(system_buffer);
70      break;
71    case base::DIR_START_MENU:
72      if (FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL,
73                                 SHGFP_TYPE_CURRENT, system_buffer)))
74        return false;
75      cur = FilePath(system_buffer);
76      break;
77    case base::DIR_APP_DATA:
78      if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
79                                 system_buffer)))
80        return false;
81      cur = FilePath(system_buffer);
82      break;
83    case base::DIR_PROFILE:
84      if (FAILED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT,
85                                 system_buffer)))
86        return false;
87      cur = FilePath(system_buffer);
88      break;
89    case base::DIR_LOCAL_APP_DATA_LOW:
90      if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) {
91        return false;
92      }
93      // TODO(nsylvain): We should use SHGetKnownFolderPath instead. Bug 1281128
94      if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT,
95                                 system_buffer)))
96        return false;
97      wstring_path = system_buffer;
98      file_util::UpOneDirectory(&wstring_path);
99      file_util::AppendToPath(&wstring_path, L"LocalLow");
100      cur = FilePath(wstring_path);
101      break;
102    case base::DIR_LOCAL_APP_DATA:
103      if (FAILED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
104                                 SHGFP_TYPE_CURRENT, system_buffer)))
105        return false;
106      cur = FilePath(system_buffer);
107      break;
108    case base::DIR_SOURCE_ROOT:
109      // On Windows, unit tests execute two levels deep from the source root.
110      // For example:  chrome/{Debug|Release}/ui_tests.exe
111      PathService::Get(base::DIR_EXE, &cur);
112      cur = cur.DirName().DirName();
113      break;
114    default:
115      return false;
116  }
117
118  *result = cur;
119  return true;
120}
121
122}  // namespace base
123