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
383 lines
10 KiB
C++
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
|