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 #define 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 MSVC debug builds
256 if ( fn
.GetDirCount() )
258 lastdir
= fn
.GetDirs().Last();
260 if ( lastdir
.Matches(_T("debug*")) || lastdir
.Matches(_T("vc*msw*")) )
268 wxString
wxStandardPaths::GetDocumentsDir() const
270 return DoGetDirectory(CSIDL_PERSONAL
);
273 // ----------------------------------------------------------------------------
275 // ----------------------------------------------------------------------------
277 wxString
wxStandardPaths::GetExecutablePath() const
279 return wxGetFullModuleName();
282 wxString
wxStandardPaths::GetConfigDir() const
284 return AppendAppInfo(DoGetDirectory(CSIDL_COMMON_APPDATA
));
287 wxString
wxStandardPaths::GetUserConfigDir() const
289 return DoGetDirectory(CSIDL_APPDATA
);
292 wxString
wxStandardPaths::GetDataDir() const
294 // under Windows each program is usually installed in its own directory and
295 // so its datafiles are in the same directory as its main executable
299 wxString
wxStandardPaths::GetUserDataDir() const
301 return AppendAppInfo(GetUserConfigDir());
304 wxString
wxStandardPaths::GetUserLocalDataDir() const
306 return AppendAppInfo(DoGetDirectory(CSIDL_LOCAL_APPDATA
));
309 wxString
wxStandardPaths::GetPluginsDir() const
311 // there is no standard location for plugins, suppose they're in the same
312 // directory as the .exe
316 // ============================================================================
317 // wxStandardPathsWin16 implementation
318 // ============================================================================
320 wxString
wxStandardPathsWin16::GetConfigDir() const
322 // this is for compatibility with earlier wxFileConfig versions
323 // which used the Windows directory for the global files
326 if ( !::GetWindowsDirectory(wxStringBuffer(dir
, MAX_PATH
), MAX_PATH
) )
328 wxLogLastError(_T("GetWindowsDirectory"));
331 // TODO: use CSIDL_WINDOWS (eVC4, possibly not eVC3)
332 dir
= wxT("\\Windows");
338 wxString
wxStandardPathsWin16::GetUserConfigDir() const
340 // again, for wxFileConfig which uses $HOME for its user config file
341 return wxGetHomeDir();
344 #endif // wxUSE_STDPATHS