WIN32: Use SHGetFolderPath to get the location of the Application Data folder (#1449)

This commit is contained in:
Cameron Cawley 2018-12-16 15:04:24 +00:00 committed by Filippos Karapetis
parent 9725716f26
commit 1de8f1e529
4 changed files with 38 additions and 80 deletions

View file

@ -43,6 +43,7 @@
#include "backends/audiocd/win32/win32-audiocd.h" #include "backends/audiocd/win32/win32-audiocd.h"
#include "backends/platform/sdl/win32/win32.h" #include "backends/platform/sdl/win32/win32.h"
#include "backends/platform/sdl/win32/win32-window.h" #include "backends/platform/sdl/win32/win32-window.h"
#include "backends/platform/sdl/win32/win32_wrapper.h"
#include "backends/saves/windows/windows-saves.h" #include "backends/saves/windows/windows-saves.h"
#include "backends/fs/windows/windows-fs-factory.h" #include "backends/fs/windows/windows-fs-factory.h"
#include "backends/taskbar/win32/win32-taskbar.h" #include "backends/taskbar/win32/win32-taskbar.h"
@ -196,20 +197,9 @@ Common::String OSystem_Win32::getScreenshotsPath() {
// Use the My Pictures folder. // Use the My Pictures folder.
char picturesPath[MAXPATHLEN]; char picturesPath[MAXPATHLEN];
// SHGetFolderPath didn't appear until Windows 2000, so we need to check for it at runtime if (SHGetFolderPathFunc(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, picturesPath) != S_OK) {
typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath); warning("Unable to access My Pictures directory");
SHGetFolderPathFunc pSHGetFolderPath = (SHGetFolderPathFunc)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetFolderPathA"); return Common::String();
if (pSHGetFolderPath) {
if (pSHGetFolderPath(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, picturesPath) != S_OK) {
warning("Unable to access My Pictures directory");
return Common::String();
}
} else {
if (!SHGetSpecialFolderPath(NULL, picturesPath, CSIDL_MYPICTURES, FALSE)) {
warning("Unable to access My Pictures directory");
return Common::String();
}
} }
screenshotsPath = Common::String(picturesPath) + "\\ScummVM Screenshots\\"; screenshotsPath = Common::String(picturesPath) + "\\ScummVM Screenshots\\";
@ -227,30 +217,8 @@ Common::String OSystem_Win32::getScreenshotsPath() {
Common::String OSystem_Win32::getDefaultConfigFileName() { Common::String OSystem_Win32::getDefaultConfigFileName() {
char configFile[MAXPATHLEN]; char configFile[MAXPATHLEN];
OSVERSIONINFO win32OsVersion; // Use the Application Data directory of the user profile.
ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configFile) == S_OK) {
win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&win32OsVersion);
// Check for non-9X version of Windows.
if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
// Use the Application Data directory of the user profile.
if (win32OsVersion.dwMajorVersion >= 5) {
if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile)))
error("Unable to access application data directory");
} else {
if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile)))
error("Unable to access user profile directory");
strcat(configFile, "\\Application Data");
// If the directory already exists (as it should in most cases),
// we don't want to fail, but we need to stop on other errors (such as ERROR_PATH_NOT_FOUND)
if (!CreateDirectory(configFile, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS)
error("Cannot create Application data folder");
}
}
strcat(configFile, "\\ScummVM"); strcat(configFile, "\\ScummVM");
if (!CreateDirectory(configFile, NULL)) { if (!CreateDirectory(configFile, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) if (GetLastError() != ERROR_ALREADY_EXISTS)
@ -277,6 +245,7 @@ Common::String OSystem_Win32::getDefaultConfigFileName() {
fclose(tmp); fclose(tmp);
} }
} else { } else {
warning("Unable to access application data directory");
// Check windows directory // Check windows directory
uint ret = GetWindowsDirectory(configFile, MAXPATHLEN); uint ret = GetWindowsDirectory(configFile, MAXPATHLEN);
if (ret == 0 || ret > MAXPATHLEN) if (ret == 0 || ret > MAXPATHLEN)
@ -295,24 +264,8 @@ Common::WriteStream *OSystem_Win32::createLogFile() {
char logFile[MAXPATHLEN]; char logFile[MAXPATHLEN];
OSVERSIONINFO win32OsVersion; // Use the Application Data directory of the user profile.
ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, logFile) == S_OK) {
win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&win32OsVersion);
// Check for non-9X version of Windows.
if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
// Use the Application Data directory of the user profile.
if (win32OsVersion.dwMajorVersion >= 5) {
if (!GetEnvironmentVariable("APPDATA", logFile, sizeof(logFile)))
error("Unable to access application data directory");
} else {
if (!GetEnvironmentVariable("USERPROFILE", logFile, sizeof(logFile)))
error("Unable to access user profile directory");
strcat(logFile, "\\Application Data");
CreateDirectory(logFile, NULL);
}
strcat(logFile, "\\ScummVM"); strcat(logFile, "\\ScummVM");
CreateDirectory(logFile, NULL); CreateDirectory(logFile, NULL);
strcat(logFile, "\\Logs"); strcat(logFile, "\\Logs");
@ -326,6 +279,7 @@ Common::WriteStream *OSystem_Win32::createLogFile() {
return stream; return stream;
} else { } else {
warning("Unable to access application data directory");
return 0; return 0;
} }
} }

View file

@ -24,10 +24,15 @@
// We need certain functions that are excluded by default // We need certain functions that are excluded by default
#undef NONLS #undef NONLS
#include <windows.h> #include <windows.h>
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
// required for SHGetSpecialFolderPath in shlobj.h
#define _WIN32_IE 0x400
#endif
#include <shlobj.h>
#include "backends/platform/sdl/win32/win32_wrapper.h" #include "backends/platform/sdl/win32/win32_wrapper.h"
// VerSetConditionMask and VerifyVersionInfo didn't appear until Windows 2000, // VerSetConditionMask, VerifyVersionInfo and SHGetFolderPath didn't appear until Windows 2000,
// so we need to check for them at runtime // so we need to check for them at runtime
ULONGLONG VerSetConditionMaskFunc(ULONGLONG dwlConditionMask, DWORD dwTypeMask, BYTE dwConditionMask) { ULONGLONG VerSetConditionMaskFunc(ULONGLONG dwlConditionMask, DWORD dwTypeMask, BYTE dwConditionMask) {
typedef ULONGLONG(WINAPI *VerSetConditionMaskFunction)(ULONGLONG conditionMask, DWORD typeMask, BYTE conditionOperator); typedef ULONGLONG(WINAPI *VerSetConditionMaskFunction)(ULONGLONG conditionMask, DWORD typeMask, BYTE conditionOperator);
@ -49,6 +54,16 @@ BOOL VerifyVersionInfoFunc(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwType
return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask); return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask);
} }
HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath) {
typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath);
SHGetFolderPathFunc pSHGetFolderPath = (SHGetFolderPathFunc)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetFolderPathA");
if (pSHGetFolderPath)
return pSHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
return SHGetSpecialFolderPath(hwnd, pszPath, csidl & !CSIDL_FLAG_MASK, csidl & CSIDL_FLAG_CREATE) ? S_OK : E_NOTIMPL;
}
namespace Win32 { namespace Win32 {
bool confirmWindowsVersion(int majorVersion, int minorVersion) { bool confirmWindowsVersion(int majorVersion, int minorVersion) {

View file

@ -23,6 +23,8 @@
#ifndef PLATFORM_SDL_WIN32_WRAPPER_H #ifndef PLATFORM_SDL_WIN32_WRAPPER_H
#define PLATFORM_SDL_WIN32_WRAPPER_H #define PLATFORM_SDL_WIN32_WRAPPER_H
HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath);
// Helper functions // Helper functions
namespace Win32 { namespace Win32 {

View file

@ -32,37 +32,22 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#undef ARRAYSIZE // winnt.h defines ARRAYSIZE, but we want our own one... #undef ARRAYSIZE // winnt.h defines ARRAYSIZE, but we want our own one...
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
// required for SHGFP_TYPE_CURRENT in shlobj.h
#define _WIN32_IE 0x500
#endif
#include <shlobj.h>
#include "common/config-manager.h" #include "common/config-manager.h"
#include "common/savefile.h" #include "common/savefile.h"
#include "backends/platform/sdl/win32/win32_wrapper.h"
WindowsSaveFileManager::WindowsSaveFileManager() { WindowsSaveFileManager::WindowsSaveFileManager() {
char defaultSavepath[MAXPATHLEN]; char defaultSavepath[MAXPATHLEN];
OSVERSIONINFO win32OsVersion;
ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO));
win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&win32OsVersion);
// Check for non-9X version of Windows.
if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
// Use the Application Data directory of the user profile.
if (win32OsVersion.dwMajorVersion >= 5) {
if (!GetEnvironmentVariable("APPDATA", defaultSavepath, sizeof(defaultSavepath)))
error("Unable to access application data directory");
} else {
if (!GetEnvironmentVariable("USERPROFILE", defaultSavepath, sizeof(defaultSavepath)))
error("Unable to access user profile directory");
strcat(defaultSavepath, "\\Application Data");
// If the directory already exists (as it should in most cases),
// we don't want to fail, but we need to stop on other errors (such as ERROR_PATH_NOT_FOUND)
if (!CreateDirectory(defaultSavepath, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS)
error("Cannot create Application data folder");
}
}
// Use the Application Data directory of the user profile.
if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, defaultSavepath) == S_OK) {
strcat(defaultSavepath, "\\ScummVM"); strcat(defaultSavepath, "\\ScummVM");
if (!CreateDirectory(defaultSavepath, NULL)) { if (!CreateDirectory(defaultSavepath, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) if (GetLastError() != ERROR_ALREADY_EXISTS)
@ -76,6 +61,8 @@ WindowsSaveFileManager::WindowsSaveFileManager() {
} }
ConfMan.registerDefault("savepath", defaultSavepath); ConfMan.registerDefault("savepath", defaultSavepath);
} else {
warning("Unable to access application data directory");
} }
} }