1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/stdpaths.cpp 
   3 // Purpose:     wxStandardPaths implementation for Win32 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2004 Vadim Zeitlin <vadim@wxwindows.org> 
   9 // License:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  29 #include "wx/stdpaths.h" 
  35 #include "wx/dynlib.h" 
  36 #include "wx/filename.h" 
  38 #include "wx/msw/private.h" 
  39 #include "wx/msw/wrapshl.h" 
  41 // ---------------------------------------------------------------------------- 
  43 // ---------------------------------------------------------------------------- 
  45 typedef HRESULT (WINAPI 
*SHGetFolderPath_t
)(HWND
, int, HANDLE
, DWORD
, LPTSTR
); 
  46 typedef HRESULT (WINAPI 
*SHGetSpecialFolderPath_t
)(HWND
, LPTSTR
, int, BOOL
); 
  48 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 // used in our wxLogTrace messages 
  53 static const wxChar 
*TRACE_MASK 
= _T("stdpaths"); 
  56     #define CSIDL_APPDATA         0x001a 
  59 #ifndef CSIDL_LOCAL_APPDATA 
  60     #define CSIDL_LOCAL_APPDATA   0x001c 
  63 #ifndef CSIDL_COMMON_APPDATA 
  64     #define CSIDL_COMMON_APPDATA  0x0023 
  67 #ifndef CSIDL_PROGRAM_FILES 
  68     #define CSIDL_PROGRAM_FILES   0x0026 
  71 #ifndef CSIDL_PERSONAL 
  72     #define CSIDL_PERSONAL        0x0005 
  75 #ifndef SHGFP_TYPE_CURRENT 
  76     #define SHGFP_TYPE_CURRENT 0 
  79 #ifndef SHGFP_TYPE_DEFAULT 
  80     #define SHGFP_TYPE_DEFAULT 1 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  90         pSHGetFolderPath 
= NULL
; 
  91         pSHGetSpecialFolderPath 
= NULL
; 
  95     SHGetFolderPath_t pSHGetFolderPath
; 
  96     SHGetSpecialFolderPath_t pSHGetSpecialFolderPath
; 
 101 // in spite of using a static variable, this is MT-safe as in the worst case it 
 102 // results in initializing the function pointer several times -- but this is 
 104 static ShellFunctions gs_shellFuncs
; 
 106 // ---------------------------------------------------------------------------- 
 108 // ---------------------------------------------------------------------------- 
 110 static void ResolveShellFunctions() 
 112 #if wxUSE_DYNLIB_CLASS 
 114     // start with the newest functions, fall back to the oldest ones 
 116     wxString 
shellDllName(_T("coredll")); 
 118     // first check for SHGetFolderPath (shell32.dll 5.0) 
 119     wxString 
shellDllName(_T("shell32")); 
 122     wxDynamicLibrary 
dllShellFunctions( shellDllName 
); 
 123     if ( !dllShellFunctions
.IsLoaded() ) 
 125         wxLogTrace(TRACE_MASK
, _T("Failed to load %s.dll"), shellDllName
.c_str() ); 
 128     // don't give errors if the functions are unavailable, we're ready to deal 
 134         static const wchar_t UNICODE_SUFFIX 
= L
''; // WinCE SH functions don't seem to have 'W' 
 136         static const wchar_t UNICODE_SUFFIX 
= L
'W'; 
 139     static const char UNICODE_SUFFIX 
= 'A'; 
 140 #endif // Unicode/!Unicode 
 142     wxString 
funcname(_T("SHGetFolderPath")); 
 143     gs_shellFuncs
.pSHGetFolderPath 
= 
 144         (SHGetFolderPath_t
)dllShellFunctions
.GetSymbol(funcname 
+ UNICODE_SUFFIX
); 
 146     // then for SHGetSpecialFolderPath (shell32.dll 4.71) 
 147     if ( !gs_shellFuncs
.pSHGetFolderPath 
) 
 149         funcname 
= _T("SHGetSpecialFolderPath"); 
 150         gs_shellFuncs
.pSHGetSpecialFolderPath 
= (SHGetSpecialFolderPath_t
) 
 151             dllShellFunctions
.GetSymbol(funcname 
+ UNICODE_SUFFIX
); 
 154     // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0), 
 155     // but we don't need to test for it -- it is available even under Win95 
 157     // shell32.dll is going to be unloaded, but it still remains in memory 
 158     // because we also link to it statically, so it's ok 
 160     gs_shellFuncs
.initialized 
= true; 
 164 // ============================================================================ 
 165 // wxStandardPaths implementation 
 166 // ============================================================================ 
 168 // ---------------------------------------------------------------------------- 
 170 // ---------------------------------------------------------------------------- 
 173 wxString 
wxStandardPaths::DoGetDirectory(int csidl
) 
 175     if ( !gs_shellFuncs
.initialized 
) 
 176         ResolveShellFunctions(); 
 181     // test whether the function is available during compile-time (it must be 
 182     // defined as either "SHGetFolderPathA" or "SHGetFolderPathW") 
 183 #ifdef SHGetFolderPath 
 184     // and now test whether we have it during run-time 
 185     if ( gs_shellFuncs
.pSHGetFolderPath 
) 
 187         hr 
= gs_shellFuncs
.pSHGetFolderPath
 
 189                 NULL
,               // parent window, not used 
 191                 NULL
,               // access token (current user) 
 192                 SHGFP_TYPE_CURRENT
, // current path, not just default value 
 193                 wxStringBuffer(dir
, MAX_PATH
) 
 196         // somewhat incredibly, the error code in the Unicode version is 
 197         // different from the one in ASCII version for this function 
 204             // directory doesn't exist, maybe we can get its default value? 
 205             hr 
= gs_shellFuncs
.pSHGetFolderPath
 
 211                     wxStringBuffer(dir
, MAX_PATH
) 
 215 #endif // SHGetFolderPath 
 217 #ifdef SHGetSpecialFolderPath 
 218     if ( FAILED(hr
) && gs_shellFuncs
.pSHGetSpecialFolderPath 
) 
 220         hr 
= gs_shellFuncs
.pSHGetSpecialFolderPath
 
 222                 NULL
,               // parent window 
 223                 wxStringBuffer(dir
, MAX_PATH
), 
 225                 FALSE               
// don't create if doesn't exist 
 228 #endif // SHGetSpecialFolderPath 
 230     // SHGetSpecialFolderLocation should be available with all compilers and 
 231     // under all Win32 systems, so don't test for it (and as it doesn't exist 
 232     // in "A" and "W" versions anyhow, testing would be more involved, too) 
 236         hr 
= SHGetSpecialFolderLocation(NULL
, csidl
, &pidl
); 
 240             // creating this temp object has (nice) side effect of freeing pidl 
 241             dir 
= wxItemIdList(pidl
).GetPath(); 
 249 wxString 
wxStandardPaths::GetAppDir() 
 251     wxFileName 
fn(wxGetFullModuleName()); 
 253     // allow running the apps directly from build directory in debug builds 
 256     if ( fn
.GetDirCount() ) 
 258         lastdir 
= fn
.GetDirs().Last(); 
 260         if ( lastdir
.Matches(_T("debug*")) || lastdir
.Matches(_T("vc_msw*")) ) 
 263 #endif // __WXDEBUG__ 
 268 wxString 
wxStandardPaths::GetDocumentsDir() const 
 270     return DoGetDirectory(CSIDL_PERSONAL
); 
 273 // ---------------------------------------------------------------------------- 
 275 // ---------------------------------------------------------------------------- 
 277 wxString 
wxStandardPaths::GetConfigDir() const 
 279     return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA
)); 
 282 wxString 
wxStandardPaths::GetUserConfigDir() const 
 284     return DoGetDirectory(CSIDL_APPDATA
); 
 287 wxString 
wxStandardPaths::GetDataDir() const 
 289     // under Windows each program is usually installed in its own directory and 
 290     // so its datafiles are in the same directory as its main executable 
 294 wxString 
wxStandardPaths::GetUserDataDir() const 
 296     return AppendAppName(GetUserConfigDir()); 
 299 wxString 
wxStandardPaths::GetUserLocalDataDir() const 
 301     return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA
)); 
 304 wxString 
wxStandardPaths::GetPluginsDir() const 
 306     // there is no standard location for plugins, suppose they're in the same 
 307     // directory as the .exe 
 311 // ============================================================================ 
 312 // wxStandardPathsWin16 implementation 
 313 // ============================================================================ 
 315 wxString 
wxStandardPathsWin16::GetConfigDir() const 
 317     // this is for compatibility with earlier wxFileConfig versions 
 318     // which used the Windows directory for the global files 
 321     if ( !::GetWindowsDirectory(wxStringBuffer(dir
, MAX_PATH
), MAX_PATH
) ) 
 323         wxLogLastError(_T("GetWindowsDirectory")); 
 326     // TODO: use CSIDL_WINDOWS (eVC4, possibly not eVC3) 
 327     dir 
= wxT("\\Windows"); 
 333 wxString 
wxStandardPathsWin16::GetUserConfigDir() const 
 335     // again, for wxFileConfig which uses $HOME for its user config file 
 336     return wxGetHomeDir(); 
 339 #endif // wxUSE_STDPATHS