From: Vadim Zeitlin Date: Tue, 19 Oct 2004 18:50:06 +0000 (+0000) Subject: initial implementation for MSW X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/40e8ee374f4be8108096e953333eaf45b3f743ed initial implementation for MSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30005 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/msw/stdpaths.h b/include/wx/msw/stdpaths.h new file mode 100644 index 0000000000..c1e9bb3f3c --- /dev/null +++ b/include/wx/msw/stdpaths.h @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/stdpaths.h +// Purpose: wxStandardPaths for Win32 +// Author: Vadim Zeitlin +// Modified by: +// Created: 2004-10-19 +// RCS-ID: $Id$ +// Copyright: (c) 2004 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_STDPATHS_H_ +#define _WX_MSW_STDPATHS_H_ + +// ---------------------------------------------------------------------------- +// wxStandardPaths +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_BASE wxStandardPaths : public wxStandardPathsBase +{ +public: + // implement base class pure virtuals + virtual wxString GetConfigDir() const; + virtual wxString GetUserConfigDir() const; + virtual wxString GetDataDir() const; + virtual wxString GetUserDataDir() const; + virtual wxString GetUserLocalDataDir() const; + virtual wxString GetPluginsDir() const; + +protected: + // append "/appname" suffix if the app name is set + static wxString AppendAppName(const wxString& dir); + + // get the path corresponding to the given standard CSIDL_XXX constant + static wxString DoGetDirectory(int csidl); +}; + +// ---------------------------------------------------------------------------- +// wxStandardPathsWin16: this class is for internal use only +// ---------------------------------------------------------------------------- + +// override config file locations to be compatible with the values used by +// wxFileConfig (dating from Win16 days which explains the class name) +class WXDLLIMPEXP_BASE wxStandardPathsWin16 : public wxStandardPaths +{ +public: + virtual wxString GetConfigDir() const; + virtual wxString GetUserConfigDir() const; +}; + +#endif // _WX_MSW_STDPATHS_H_ diff --git a/src/msw/stdpaths.cpp b/src/msw/stdpaths.cpp new file mode 100644 index 0000000000..dcce507ce3 --- /dev/null +++ b/src/msw/stdpaths.cpp @@ -0,0 +1,292 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: msw/stdpaths.cpp +// Purpose: wxStandardPaths implementation for Win32 +// Author: Vadim Zeitlin +// Modified by: +// Created: 2004-10-19 +// RCS-ID: $Id$ +// Copyright: (c) 2004 Vadim Zeitlin +// License: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/app.h" +#endif //WX_PRECOMP + +#include "wx/dynlib.h" +#include "wx/filename.h" + +#include "wx/stdpaths.h" + +#include "wx/msw/private.h" +#include "wx/msw/wrapshl.h" + +// ---------------------------------------------------------------------------- +// types +// ---------------------------------------------------------------------------- + +typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND, int, HANDLE, DWORD, LPTSTR); +typedef HRESULT (WINAPI *SHGetSpecialFolderPath_t)(HWND, LPTSTR, int, BOOL); + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// used in our wxLogTrace messages +static const wxChar *TRACE_MASK = _T("stdpaths"); + +#ifndef CSIDL_LOCAL_APPDATA + #define CSIDL_LOCAL_APPDATA 0x001c +#endif + +#ifndef CSIDL_COMMON_APPDATA + #define CSIDL_COMMON_APPDATA 0x0023 +#endif + +#ifndef CSIDL_PROGRAM_FILES + #define CSIDL_PROGRAM_FILES 0x0026 +#endif + +// ---------------------------------------------------------------------------- +// module globals +// ---------------------------------------------------------------------------- + +struct ShellFunctions +{ + ShellFunctions() + { + pSHGetFolderPath = NULL; + pSHGetSpecialFolderPath = NULL; + initialized = false; + } + + SHGetFolderPath_t pSHGetFolderPath; + SHGetSpecialFolderPath_t pSHGetSpecialFolderPath; + + bool initialized; +}; + +// in spite of using a static variable, this is MT-safe as in the worst case it +// results in initializing the function pointer several times -- but this is +// harmless +static ShellFunctions gs_shellFuncs; + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +static void ResolveShellFunctions() +{ + // don't give errors if the functions are unavailable, we're ready to deal + // with this + wxLogNull noLog; + + // start with the newest functions, fall back to the oldest ones + + // first check for SHGetFolderPath (shell32.dll 5.0) + wxDynamicLibrary dllShell32(_T("shell32")); + if ( !dllShell32.IsLoaded() ) + { + wxLogTrace(TRACE_MASK, _T("Failed to load shell32.dll")); + } + +#if wxUSE_UNICODE + static const wchar_t UNICODE_SUFFIX = L'W'; +#else // !Unicode + static const char UNICODE_SUFFIX = 'A'; +#endif // Unicode/!Unicode + + wxString funcname(_T("SHGetFolderPath")); + gs_shellFuncs.pSHGetFolderPath = + (SHGetFolderPath_t)dllShell32.GetSymbol(funcname + UNICODE_SUFFIX); + + // then for SHGetSpecialFolderPath (shell32.dll 4.71) + if ( !gs_shellFuncs.pSHGetFolderPath ) + { + funcname = _T("SHGetSpecialFolderPath"); + gs_shellFuncs.pSHGetSpecialFolderPath = (SHGetSpecialFolderPath_t) + dllShell32.GetSymbol(funcname + UNICODE_SUFFIX); + } + + // finally we fall back on SHGetSpecialFolderLocation (shell32.dll 4.0), + // but we don't need to test for it -- it is available even under Win95 + + // shell32.dll is going to be unloaded, but it still remains in memory + // because we also link to it statically, so it's ok + + gs_shellFuncs.initialized = true; +} + +// ============================================================================ +// wxStandardPaths implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// private helpers +// ---------------------------------------------------------------------------- + +/* static */ +wxString wxStandardPaths::DoGetDirectory(int csidl) +{ + if ( !gs_shellFuncs.initialized ) + ResolveShellFunctions(); + + wxString dir; + HRESULT hr = E_FAIL; + + // test whether the function is available during compile-time (it must be + // defined as either "SHGetFolderPathA" or "SHGetFolderPathW") +#ifdef SHGetFolderPath + // and now test whether we have it during run-time + if ( gs_shellFuncs.pSHGetFolderPath ) + { + hr = gs_shellFuncs.pSHGetFolderPath + ( + NULL, // parent window, not used + csidl, + NULL, // access token (current user) + SHGFP_TYPE_CURRENT, // current path, not just default value + wxStringBuffer(dir, MAX_PATH) + ); + + // somewhat incredibly, the error code in the Unicode version is + // different from the one in ASCII version for this function +#if wxUSE_UNICODE + if ( hr == E_FAIL ) +#else + if ( hr == S_FALSE ) +#endif + { + // directory doesn't exist, maybe we can get its default value? + hr = gs_shellFuncs.pSHGetFolderPath + ( + NULL, + csidl, + NULL, + SHGFP_TYPE_DEFAULT, + wxStringBuffer(dir, MAX_PATH) + ); + } + } +#endif // SHGetFolderPath + +#ifdef SHGetSpecialFolderPath + if ( FAILED(hr) && gs_shellFuncs.pSHGetSpecialFolderPath ) + { + hr = gs_shellFuncs.pSHGetSpecialFolderPath + ( + NULL, // parent window + wxStringBuffer(dir, MAX_PATH), + csidl, + FALSE // don't create if doesn't exist + ); + } +#endif // SHGetSpecialFolderPath + + // SHGetSpecialFolderLocation should be available with all compilers and + // under all Win32 systems, so don't test for it (and as it doesn't exist + // in "A" and "W" versions anyhow, testing would be more involved, too) + if ( FAILED(hr) ) + { + LPITEMIDLIST pidl; + hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl); + + if ( SUCCEEDED(hr) ) + { + // creating this temp object has (nice) side effect of freeing pidl + dir = wxItemIdList(pidl).GetPath(); + } + } + + return dir; +} + +/* static */ +wxString wxStandardPaths::AppendAppName(const wxString& dir) +{ + wxString subdir(dir); + + // empty string indicates that an error has occured, don't touch it then + if ( !subdir.empty() ) + { + const wxString appname = wxTheApp->GetAppName(); + if ( !appname.empty() ) + subdir << _T('\\') << appname; + } + + return subdir; +} + +// ---------------------------------------------------------------------------- +// public functions +// ---------------------------------------------------------------------------- + +wxString wxStandardPaths::GetConfigDir() const +{ + return AppendAppName(DoGetDirectory(CSIDL_COMMON_APPDATA)); +} + +wxString wxStandardPaths::GetUserConfigDir() const +{ + return DoGetDirectory(CSIDL_APPDATA); +} + +wxString wxStandardPaths::GetDataDir() const +{ + return AppendAppName(DoGetDirectory(CSIDL_PROGRAM_FILES)); +} + +wxString wxStandardPaths::GetUserDataDir() const +{ + return AppendAppName(GetUserConfigDir()); +} + +wxString wxStandardPaths::GetUserLocalDataDir() const +{ + return AppendAppName(DoGetDirectory(CSIDL_LOCAL_APPDATA)); +} + +wxString wxStandardPaths::GetPluginsDir() const +{ + return wxFileName(wxGetFullModuleName()).GetPath(); +} + + +// ============================================================================ +// wxStandardPathsWin16 implementation +// ============================================================================ + +wxString wxStandardPathsWin16::GetConfigDir() const +{ + // this is for compatibility with earlier wxFileConfig versions + // which used the Windows directory for the global files + wxString dir; + if ( !::GetWindowsDirectory(wxStringBuffer(dir, MAX_PATH), MAX_PATH) ) + { + wxLogLastError(_T("GetWindowsDirectory")); + } + + return dir; +} + +wxString wxStandardPathsWin16::GetUserConfigDir() const +{ + // again, for wxFileConfig which uses $HOME for its user config file + return wxGetHomeDir(); +} +