QSettings: Replace deprecated Win32 SHGetSpecialFolderPath

SHGetSpecialFolderPath is declared 'unsupported' by Microsoft, and has
problems with non-ASCII characters. Replace it by the newer
SHGetKnownFolderPath.

Task-number: QTBUG-50570
Change-Id: I8b2dfa10fa5dc30e6c3be094a2ba8d7c3504f2ca
GPush-Base: 4d181bd93234a3747b520d10417825a0147bfeb1
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
Kai Koehne 2016-11-02 13:58:54 +01:00
parent 04b276b0f5
commit 60054b5940

View File

@ -97,14 +97,6 @@ using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Storage; using namespace ABI::Windows::Storage;
#endif #endif
#ifndef CSIDL_COMMON_APPDATA
#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data
#endif
#ifndef CSIDL_APPDATA
#define CSIDL_APPDATA 0x001a // <username>\Application Data
#endif
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID)
#define Q_XDG_PLATFORM #define Q_XDG_PLATFORM
#endif #endif
@ -959,31 +951,34 @@ void QConfFileSettingsPrivate::initAccess()
} }
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
static QString windowsConfigPath(int type) static QString windowsConfigPath(const KNOWNFOLDERID &type)
{ {
QString result; QString result;
wchar_t path[MAX_PATH]; PWSTR path = nullptr;
if (SHGetSpecialFolderPath(0, path, type, false)) if (SHGetKnownFolderPath(type, KF_FLAG_DONT_VERIFY, NULL, &path) == S_OK) {
result = QString::fromWCharArray(path); result = QString::fromWCharArray(path);
CoTaskMemFree(path);
}
if (result.isEmpty()) { if (result.isEmpty()) {
switch (type) { if (type == FOLDERID_ProgramData) {
case CSIDL_COMMON_APPDATA:
result = QLatin1String("C:\\temp\\qt-common"); result = QLatin1String("C:\\temp\\qt-common");
break; } else if (type == FOLDERID_RoamingAppData) {
case CSIDL_APPDATA:
result = QLatin1String("C:\\temp\\qt-user"); result = QLatin1String("C:\\temp\\qt-user");
break;
default:
;
} }
} }
return result; return result;
} }
#elif defined(Q_OS_WINRT) // Q_OS_WIN && !Q_OS_WINRT #elif defined(Q_OS_WINRT) // Q_OS_WIN && !Q_OS_WINRT
static QString windowsConfigPath(int type)
enum ConfigPathType {
ConfigPath_CommonAppData,
ConfigPath_UserAppData
};
static QString windowsConfigPath(ConfigPathType type)
{ {
static QString result; static QString result;
while (result.isEmpty()) { while (result.isEmpty()) {
@ -1006,12 +1001,10 @@ static QString windowsConfigPath(int type)
} }
switch (type) { switch (type) {
case CSIDL_COMMON_APPDATA: case ConfigPath_CommonAppData:
return result + QLatin1String("\\qt-common"); return result + QLatin1String("\\qt-common");
case CSIDL_APPDATA: case ConfigPath_UserAppData:
return result + QLatin1String("\\qt-user"); return result + QLatin1String("\\qt-user");
default:
break;
} }
return result; return result;
} }
@ -1068,10 +1061,18 @@ static void initDefaultPaths(QMutexLocker *locker)
Windows registry and the Mac CFPreferences.) Windows registry and the Mac CFPreferences.)
*/ */
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# ifdef Q_OS_WINRT
const QString roamingAppDataFolder = windowsConfigPath(ConfigPath_UserAppData);
const QString programDataFolder = windowsConfigPath(ConfigPath_CommonAppData);
# else
const QString roamingAppDataFolder = windowsConfigPath(FOLDERID_RoamingAppData);
const QString programDataFolder = windowsConfigPath(FOLDERID_ProgramData);
# endif
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope),
windowsConfigPath(CSIDL_APPDATA) + QDir::separator()); roamingAppDataFolder + QDir::separator());
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator()); programDataFolder + QDir::separator());
#else #else
const QString userPath = make_user_path(); const QString userPath = make_user_path();
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath); pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
@ -2231,20 +2232,20 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
On Windows, the following files are used: On Windows, the following files are used:
\list 1 \list 1
\li \c{CSIDL_APPDATA\MySoft\Star Runner.ini} \li \c{FOLDERID_RoamingAppData\MySoft\Star Runner.ini}
\li \c{CSIDL_APPDATA\MySoft.ini} \li \c{FOLDERID_RoamingAppData\MySoft.ini}
\li \c{CSIDL_COMMON_APPDATA\MySoft\Star Runner.ini} \li \c{FOLDERID_ProgramData\MySoft\Star Runner.ini}
\li \c{CSIDL_COMMON_APPDATA\MySoft.ini} \li \c{FOLDERID_ProgramData\MySoft.ini}
\endlist \endlist
The identifiers prefixed by \c{CSIDL_} are special item ID lists to be passed The identifiers prefixed by \c{FOLDERID_} are special item ID lists to be passed
to the Win32 API function \c{SHGetSpecialFolderPath()} to obtain the to the Win32 API function \c{SHGetKnownFolderPath()} to obtain the
corresponding path. corresponding path.
\c{CSIDL_APPDATA} usually points to \tt{C:\\Users\\\e{User Name}\\AppData\\Roaming}, \c{FOLDERID_RoamingAppData} usually points to \tt{C:\\Users\\\e{User Name}\\AppData\\Roaming},
also shown by the environment variable \c{%APPDATA%}. also shown by the environment variable \c{%APPDATA%}.
\c{CSIDL_COMMON_APPDATA} usually points to \tt{C:\\ProgramData}. \c{FOLDERID_ProgramData} usually points to \tt{C:\\ProgramData}.
If the file format is IniFormat, this is "Settings/MySoft/Star Runner.ini" If the file format is IniFormat, this is "Settings/MySoft/Star Runner.ini"
in the application's home directory. in the application's home directory.
@ -3348,8 +3349,8 @@ void QSettings::setUserIniPath(const QString &dir)
\table \table
\header \li Platform \li Format \li Scope \li Path \header \li Platform \li Format \li Scope \li Path
\row \li{1,2} Windows \li{1,2} IniFormat \li UserScope \li \c CSIDL_APPDATA \row \li{1,2} Windows \li{1,2} IniFormat \li UserScope \li \c FOLDERID_RoamingAppData
\row \li SystemScope \li \c CSIDL_COMMON_APPDATA \row \li SystemScope \li \c FOLDERID_ProgramData
\row \li{1,2} Unix \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/.config \row \li{1,2} Unix \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/.config
\row \li SystemScope \li \c /etc/xdg \row \li SystemScope \li \c /etc/xdg
\row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings \row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings