Home | History | Annotate | Download | only in base
      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