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"
31 #include "wx/dynlib.h"
32 #include "wx/filename.h"
34 #include "wx/stdpaths.h"
36 #include "wx/msw/private.h"
37 #include "wx/msw/wrapshl.h"
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 typedef HRESULT (WINAPI
*SHGetFolderPath_t
)(HWND
, int, HANDLE
, DWORD
, LPTSTR
);
44 typedef HRESULT (WINAPI
*SHGetSpecialFolderPath_t
)(HWND
, LPTSTR
, int, BOOL
);
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 // used in our wxLogTrace messages
51 static const wxChar
*TRACE_MASK
= _T("stdpaths");
54 #define CSIDL_APPDATA 0x001a
57 #ifndef CSIDL_LOCAL_APPDATA
58 #define CSIDL_LOCAL_APPDATA 0x001c
61 #ifndef CSIDL_COMMON_APPDATA
62 #define CSIDL_COMMON_APPDATA 0x0023
65 #ifndef CSIDL_PROGRAM_FILES
66 #define CSIDL_PROGRAM_FILES 0x0026
69 #ifndef SHGFP_TYPE_CURRENT
70 #define SHGFP_TYPE_CURRENT 0
73 #ifndef SHGFP_TYPE_DEFAULT
74 #define SHGFP_TYPE_DEFAULT 1
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
85 pSHGetFolderPath
= NULL
;
86 pSHGetSpecialFolderPath
= NULL
;
90 SHGetFolderPath_t pSHGetFolderPath
;
91 SHGetSpecialFolderPath_t pSHGetSpecialFolderPath
;
96 // in spite of using a static variable, this is MT-safe as in the worst case it
97 // results in initializing the function pointer several times -- but this is
99 static ShellFunctions gs_shellFuncs
;
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 static void ResolveShellFunctions()
107 // don't give errors if the functions are unavailable, we're ready to deal
111 // start with the newest functions, fall back to the oldest ones
113 // first check for SHGetFolderPath (shell32.dll 5.0)
114 wxDynamicLibrary
dllShell32(_T("shell32"));
115 if ( !dllShell32
.IsLoaded() )
117 wxLogTrace(TRACE_MASK
, _T("Failed to load shell32.dll"));
121 static const wchar_t UNICODE_SUFFIX
= L
'W';
123 static const char UNICODE_SUFFIX
= 'A';
124 #endif // Unicode/!Unicode
126 wxString
funcname(_T("SHGetFolderPath"));
127 gs_shellFuncs
.pSHGetFolderPath
=
128 (SHGetFolderPath_t
)dllShell32
.GetSymbol(funcname
+ UNICODE_SUFFIX
);
130 // then for SHGetSpecialFolderPath (shell32.dll 4.71)
131 if ( !gs_shellFuncs
.pSHGetFolderPath
)
133 funcname
= _T("SHGetSpecialFolderPath");
134 gs_shellFuncs
.pSHGetSpecialFolderPath
= (SHGetSpecialFolderPath_t
)
135 dllShell32
.GetSymbol(funcname
+ UNICODE_SUFFIX
);
138 // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0),
139 // but we don't need to test for it -- it is available even under Win95
141 // shell32.dll is going to be unloaded, but it still remains in memory
142 // because we also link to it statically, so it's ok
144 gs_shellFuncs
.initialized
= true;
147 // ============================================================================
148 // wxStandardPaths implementation
149 // ============================================================================
151 // ----------------------------------------------------------------------------
153 // ----------------------------------------------------------------------------
156 wxString
wxStandardPaths::DoGetDirectory(int csidl
)
158 if ( !gs_shellFuncs
.initialized
)
159 ResolveShellFunctions();
164 // test whether the function is available during compile-time (it must be
165 // defined as either "SHGetFolderPathA" or "SHGetFolderPathW")
166 #ifdef SHGetFolderPath
167 // and now test whether we have it during run-time
168 if ( gs_shellFuncs
.pSHGetFolderPath
)
170 hr
= gs_shellFuncs
.pSHGetFolderPath
172 NULL
, // parent window, not used
174 NULL
, // access token (current user)
175 SHGFP_TYPE_CURRENT
, // current path, not just default value
176 wxStringBuffer(dir
, MAX_PATH
)
179 // somewhat incredibly, the error code in the Unicode version is
180 // different from the one in ASCII version for this function
187 // directory doesn't exist, maybe we can get its default value?
188 hr
= gs_shellFuncs
.pSHGetFolderPath
194 wxStringBuffer(dir
, MAX_PATH
)
198 #endif // SHGetFolderPath
200 #ifdef SHGetSpecialFolderPath
201 if ( FAILED(hr
) && gs_shellFuncs
.pSHGetSpecialFolderPath
)
203 hr
= gs_shellFuncs
.pSHGetSpecialFolderPath
205 NULL
, // parent window
206 wxStringBuffer(dir
, MAX_PATH
),
208 FALSE
// don't create if doesn't exist
211 #endif // SHGetSpecialFolderPath
213 // SHGetSpecialFolderLocation should be available with all compilers and
214 // under all Win32 systems, so don't test for it (and as it doesn't exist
215 // in "A" and "W" versions anyhow, testing would be more involved, too)
219 hr
= SHGetSpecialFolderLocation(NULL
, csidl
, &pidl
);
223 // creating this temp object has (nice) side effect of freeing pidl
224 dir
= wxItemIdList(pidl
).GetPath();
231 // ----------------------------------------------------------------------------
233 // ----------------------------------------------------------------------------
235 wxString
wxStandardPaths::GetConfigDir() const
237 return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA
));
240 wxString
wxStandardPaths::GetUserConfigDir() const
242 return DoGetDirectory(CSIDL_APPDATA
);
245 wxString
wxStandardPaths::GetDataDir() const
247 return AppendAppName(DoGetDirectory(CSIDL_PROGRAM_FILES
));
250 wxString
wxStandardPaths::GetUserDataDir() const
252 return AppendAppName(GetUserConfigDir());
255 wxString
wxStandardPaths::GetUserLocalDataDir() const
257 return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA
));
260 wxString
wxStandardPaths::GetPluginsDir() const
262 return wxFileName(wxGetFullModuleName()).GetPath();
266 // ============================================================================
267 // wxStandardPathsWin16 implementation
268 // ============================================================================
270 wxString
wxStandardPathsWin16::GetConfigDir() const
272 // this is for compatibility with earlier wxFileConfig versions
273 // which used the Windows directory for the global files
276 if ( !::GetWindowsDirectory(wxStringBuffer(dir
, MAX_PATH
), MAX_PATH
) )
278 wxLogLastError(_T("GetWindowsDirectory"));
282 // eVC4 - use CSIDL_WINDOWS
283 // eVC3 - probably not possible through API
289 wxString
wxStandardPathsWin16::GetUserConfigDir() const
291 // again, for wxFileConfig which uses $HOME for its user config file
292 return wxGetHomeDir();