Files
wxWidgets/src/msw/stdpaths.cpp
Vadim Zeitlin f69dbaa1ae Introduce MSW ARM64 support
This is a preliminary ARM64 platform support for wxWidgets at "it
compiles" stage. This will allow building and testing wxWidgets based
apps for oncoming Windows 10 ARM64.

Requirements:
- Visual Studio 2017 Update 4 or later with Visual C++ compilers and
  libraries for ARM64 component installed

Building:
1. Open command prompt.
2. Change directory to build\msw subfolder.
3. Run "C:\Program Files (x86)\Microsoft Visual
   Studio\2017\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat" once.
4. Use `nmake TARGET_CPU=ARM64 ...` to build required flavor of wxWidget
   libraries.

Notes:
1. Building of *.sln/*.vcxproj files does not support ARM64 yet. This
   requires to hardcode Windows SDK to 10.0.15063.0 or later in
   *.vcxproj files, which would render them non-compilable in older
   Visual Studio versions. Microsoft is aware of this issue and is
   planning a fix in the next version of Visual Studio.
2. wxmsw31ud_gl.dll does not build yet. Awaiting Microsoft to deliver
   missing opengl32.lib for ARM64. Please, specify USE_OPENGL=0.

Closes https://github.com/wxWidgets/wxWidgets/pull/923
2018-09-17 22:34:32 +02:00

383 lines
10 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/msw/stdpaths.cpp
// Purpose: wxStandardPaths implementation for Win32
// Author: Vadim Zeitlin
// Modified by:
// Created: 2004-10-19
// Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_STDPATHS
#include "wx/stdpaths.h"
#ifndef WX_PRECOMP
#include "wx/utils.h"
#endif //WX_PRECOMP
#include "wx/dynlib.h"
#include "wx/filename.h"
#include "wx/msw/private.h"
#include "wx/msw/wrapshl.h"
#include <initguid.h>
// ----------------------------------------------------------------------------
// types
// ----------------------------------------------------------------------------
typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID&, DWORD, HANDLE, PWSTR *);
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// used in our wxLogTrace messages
#define TRACE_MASK wxT("stdpaths")
#ifndef CSIDL_PERSONAL
#define CSIDL_PERSONAL 0x0005
#endif
// ----------------------------------------------------------------------------
// module globals
// ----------------------------------------------------------------------------
namespace
{
DEFINE_GUID(wxFOLDERID_Downloads,
0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
struct ShellFunctions
{
ShellFunctions()
{
pSHGetKnownFolderPath = NULL;
initialized = false;
}
SHGetKnownFolderPath_t pSHGetKnownFolderPath;
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
ShellFunctions gs_shellFuncs;
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
void ResolveShellFunctions()
{
#if wxUSE_DYNLIB_CLASS
// start with the newest functions, fall back to the oldest ones
// first check for SHGetFolderPath (shell32.dll 5.0)
wxString shellDllName(wxT("shell32"));
wxDynamicLibrary dllShellFunctions( shellDllName );
if ( !dllShellFunctions.IsLoaded() )
{
wxLogTrace(TRACE_MASK, wxT("Failed to load %s.dll"), shellDllName.c_str() );
}
// don't give errors if the functions are unavailable, we're ready to deal
// with this
wxLogNull noLog;
gs_shellFuncs.pSHGetKnownFolderPath = (SHGetKnownFolderPath_t)
dllShellFunctions.GetSymbol("SHGetKnownFolderPath");
// 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;
#endif
}
} // anonymous namespace
// ============================================================================
// wxStandardPaths implementation
// ============================================================================
// ----------------------------------------------------------------------------
// private helpers
// ----------------------------------------------------------------------------
/* static */
wxString wxStandardPaths::DoGetDirectory(int csidl)
{
wxString dir;
HRESULT hr = E_FAIL;
hr = ::SHGetFolderPath
(
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 = ::SHGetFolderPath
(
NULL,
csidl,
NULL,
SHGFP_TYPE_DEFAULT,
wxStringBuffer(dir, MAX_PATH)
);
}
return dir;
}
wxString wxStandardPaths::DoGetKnownFolder(const GUID& rfid)
{
if (!gs_shellFuncs.initialized)
ResolveShellFunctions();
wxString dir;
if ( gs_shellFuncs.pSHGetKnownFolderPath )
{
PWSTR pDir;
HRESULT hr = gs_shellFuncs.pSHGetKnownFolderPath(rfid, 0, 0, &pDir);
if ( SUCCEEDED(hr) )
{
dir = pDir;
CoTaskMemFree(pDir);
}
}
return dir;
}
wxString wxStandardPaths::GetAppDir() const
{
if ( m_appDir.empty() )
{
m_appDir = wxFileName(wxGetFullModuleName()).GetPath();
}
return m_appDir;
}
wxString wxStandardPaths::GetUserDir(Dir userDir) const
{
int csidl;
switch (userDir)
{
case Dir_Cache:
csidl = CSIDL_LOCAL_APPDATA;
break;
case Dir_Desktop:
csidl = CSIDL_DESKTOPDIRECTORY;
break;
case Dir_Downloads:
{
csidl = CSIDL_PERSONAL;
// Downloads folder is only available since Vista
wxString dir = DoGetKnownFolder(wxFOLDERID_Downloads);
if ( !dir.empty() )
return dir;
break;
}
case Dir_Music:
csidl = CSIDL_MYMUSIC;
break;
case Dir_Pictures:
csidl = CSIDL_MYPICTURES;
break;
case Dir_Videos:
csidl = CSIDL_MYVIDEO;
break;
default:
csidl = CSIDL_PERSONAL;
break;
}
return DoGetDirectory(csidl);
}
// ----------------------------------------------------------------------------
// MSW-specific functions
// ----------------------------------------------------------------------------
void wxStandardPaths::IgnoreAppSubDir(const wxString& subdirPattern)
{
wxFileName fn = wxFileName::DirName(GetAppDir());
if ( !fn.GetDirCount() )
{
// no last directory to ignore anyhow
return;
}
const wxString lastdir = fn.GetDirs().Last().Lower();
if ( lastdir.Matches(subdirPattern.Lower()) )
{
fn.RemoveLastDir();
// store the cached value so that subsequent calls to GetAppDir() will
// reuse it instead of using just the program binary directory
m_appDir = fn.GetPath();
}
}
void wxStandardPaths::IgnoreAppBuildSubDirs()
{
IgnoreAppSubDir("debug");
IgnoreAppSubDir("release");
// there can also be an architecture-dependent parent directory, ignore it
// as well
#ifdef __WIN64__
IgnoreAppSubDir("x64");
IgnoreAppSubDir("ARM64");
#else // __WIN32__
IgnoreAppSubDir("Win32");
#endif // __WIN64__/__WIN32__
wxString compilerPrefix;
#ifdef __VISUALC__
compilerPrefix = "vc";
#elif defined(__GNUG__)
compilerPrefix = "gcc";
#elif defined(__BORLANDC__)
compilerPrefix = "bcc";
#else
return;
#endif
IgnoreAppSubDir(compilerPrefix + "_msw*");
}
void wxStandardPaths::DontIgnoreAppSubDir()
{
// this will force the next call to GetAppDir() to use the program binary
// path as the application directory
m_appDir.clear();
}
/* static */
wxString wxStandardPaths::MSWGetShellDir(int csidl)
{
return DoGetDirectory(csidl);
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
wxStandardPaths::wxStandardPaths()
{
// make it possible to run uninstalled application from the build directory
IgnoreAppBuildSubDirs();
}
wxString wxStandardPaths::GetExecutablePath() const
{
return wxGetFullModuleName();
}
wxString wxStandardPaths::GetConfigDir() const
{
return AppendAppInfo(DoGetDirectory(CSIDL_COMMON_APPDATA));
}
wxString wxStandardPaths::GetUserConfigDir() const
{
return DoGetDirectory(CSIDL_APPDATA);
}
wxString wxStandardPaths::GetDataDir() const
{
// under Windows each program is usually installed in its own directory and
// so its datafiles are in the same directory as its main executable
return GetAppDir();
}
wxString wxStandardPaths::GetUserDataDir() const
{
return AppendAppInfo(GetUserConfigDir());
}
wxString wxStandardPaths::GetUserLocalDataDir() const
{
return AppendAppInfo(DoGetDirectory(CSIDL_LOCAL_APPDATA));
}
wxString wxStandardPaths::GetPluginsDir() const
{
// there is no standard location for plugins, suppose they're in the same
// directory as the .exe
return GetAppDir();
}
wxString
wxStandardPaths::MakeConfigFileName(const wxString& basename,
ConfigFileConv WXUNUSED(conv)) const
{
wxFileName fn(wxEmptyString, basename);
fn.SetExt(wxT("ini"));
return fn.GetFullName();
}
// ============================================================================
// 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(wxT("GetWindowsDirectory"));
}
return dir;
}
wxString wxStandardPathsWin16::GetUserConfigDir() const
{
// again, for wxFileConfig which uses $HOME for its user config file
return wxGetHomeDir();
}
#endif // wxUSE_STDPATHS