From 089fc5ea0afb60a1ecddcf75f98d8baa2de71ff0 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 9 Apr 2015 15:33:56 +0100 Subject: [PATCH] WindowsXP workaround for SHGetKnowwFolder Fix from xDraconian after a bug report from Aleesandro. --- simgear/misc/sg_path.cxx | 83 ++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 1cfe465c..d1475b11 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -57,7 +57,7 @@ static const char sgSearchPathSep = ':'; #ifdef _WIN32 #include // for CSIDL -#include // for Standard Folder GUIDs +#include static SGPath pathForCSIDL(int csidl, const SGPath& def) { @@ -84,23 +84,34 @@ static SGPath pathForCSIDL(int csidl, const SGPath& def) static SGPath pathForKnownFolder(REFKNOWNFOLDERID folderId, const SGPath& def) { - // system call will allocate dynamic memory... which we must release when done - wchar_t* localFolder = 0; - if (SHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT_PATH, NULL, &localFolder) == S_OK) { - // copy into local memory - char path[MAX_PATH]; - size_t len; - if (wcstombs_s(&len, path, localFolder, MAX_PATH) != S_OK) { - path[0] = '\0'; - SG_LOG(SG_GENERAL, SG_WARN, "WCS to MBS failed"); - } + typedef HRESULT (WINAPI*PSHGKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*); + + HINSTANCE shellDll = LoadLibrary(TEXT("shell32")); + if (shellDll != NULL) { + PSHGKFP pSHGetKnownFolderPath = (PSHGKFP) GetProcAddress(shellDll, "SHGetKnownFolderPath"); + if (pSHGetKnownFolderPath != NULL) { + // system call will allocate dynamic memory... which we must release when done + wchar_t* localFolder = 0; + + if (pSHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT_PATH, NULL, &localFolder) == S_OK) { + // copy into local memory + char path[MAX_PATH]; + size_t len; + if (wcstombs_s(&len, path, localFolder, MAX_PATH) != S_OK) { + path[0] = '\0'; + SG_LOG(SG_GENERAL, SG_WARN, "WCS to MBS failed"); + } - SGPath folder_path = SGPath(path, def.getPermissionChecker()); + SGPath folder_path = SGPath(path, def.getPermissionChecker()); - // release dynamic memory - CoTaskMemFree(static_cast(localFolder)); + // release dynamic memory + CoTaskMemFree(static_cast(localFolder)); + + return folder_path; + } + } - return folder_path; + FreeLibrary(shellDll); } return def; @@ -730,31 +741,35 @@ SGPath SGPath::standardLocation(StandardLocation type, const SGPath& def) { case HOME: return home(def); + #ifdef _WIN32 -# if (WINVER > 0x0501) - case DESKTOP: - return pathForKnownFolder(FOLDERID_Desktop, def); - case DOWNLOADS: - return pathForKnownFolder(FOLDERID_Downloads, def); - case DOCUMENTS: - return pathForKnownFolder(FOLDERID_Documents, def); - case PICTURES: - return pathForKnownFolder(FOLDERID_Pictures, def); -# else case DESKTOP: - return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def); + if (IsWindowsVistaOrGreater()) + return pathForKnownFolder(FOLDERID_Desktop, def); + + return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def); + case DOWNLOADS: - // TODO use KnownFolders - // http://msdn.microsoft.com/en-us/library/bb776911%28v=vs.85%29.aspx - if( !def.isNull() ) - return def; + if (IsWindowsVistaOrGreater()) + return pathForKnownFolder(FOLDERID_Downloads, def); + + if (!def.isNull()) + return def; + + return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def); - return pathForCSIDL(CSIDL_DESKTOPDIRECTORY, def); case DOCUMENTS: - return pathForCSIDL(CSIDL_MYDOCUMENTS, def); + if (IsWindowsVistaOrGreater()) + return pathForKnownFolder(FOLDERID_Documents, def); + + return pathForCSIDL(CSIDL_MYDOCUMENTS, def); + case PICTURES: - return pathForCSIDL(CSIDL_MYPICTURES, def); -# endif + if (IsWindowsVistaOrGreater()) + return pathForKnownFolder(FOLDERID_Pictures, def); + + return pathForCSIDL(CSIDL_MYPICTURES, def); + #elif __APPLE__ // since this is C++, we can't include NSPathUtilities.h to access the enum // values, so hard-coding them here (they are stable, don't worry) -- 2.39.5