summaryrefslogtreecommitdiff
path: root/lib/resolve_path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/resolve_path.cpp')
-rw-r--r--lib/resolve_path.cpp84
1 files changed, 63 insertions, 21 deletions
diff --git a/lib/resolve_path.cpp b/lib/resolve_path.cpp
index b735d1f9..bea62da3 100644
--- a/lib/resolve_path.cpp
+++ b/lib/resolve_path.cpp
@@ -7,10 +7,11 @@
#include <wx/utils.h> //wxGetEnv
#ifdef FFS_WIN
-#include <zen/win.h> //includes "windows.h"
-#include <Shlobj.h>
#include <zen/long_path_prefix.h>
#include <zen/file_handling.h>
+#include <zen/win.h> //includes "windows.h"
+#include <zen/dll.h>
+#include <Shlobj.h>
#ifdef _MSC_VER
#pragma comment(lib, "Mpr.lib")
#endif
@@ -106,6 +107,37 @@ private:
}
};
+ //================================================================================================
+ //SHGetKnownFolderPath: API available only with Windows Vista and later:
+#ifdef __MINGW32__ //MinGW is clueless about Vista...
+#define REFKNOWNFOLDERID const GUID&
+#define KF_FLAG_DONT_VERIFY 0x00004000
+ const GUID FOLDERID_Downloads = { 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b} };
+ const GUID FOLDERID_PublicDownloads = { 0x3d644c9b, 0x1fb8, 0x4f30, { 0x9b, 0x45, 0xf6, 0x70, 0x23, 0x5f, 0x79, 0xc0} };
+ const GUID FOLDERID_QuickLaunch = { 0x52a4f021, 0x7b75, 0x48a9, { 0x9f, 0x6b, 0x4b, 0x87, 0xa2, 0x10, 0xbc, 0x8f} };
+#endif
+ typedef HRESULT (STDAPICALLTYPE* SHGetKnownFolderPathFunc)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR* ppszPath);
+ const SysDllFun<SHGetKnownFolderPathFunc> shGetKnownFolderPath(L"Shell32.dll", "SHGetKnownFolderPath");
+
+ auto addFolderId = [&](REFKNOWNFOLDERID rfid, const Zstring& paramName)
+ {
+ if (shGetKnownFolderPath != nullptr) //[!] avoid bogus MSVC "performance warning"
+ {
+ PWSTR path = nullptr;
+ if (SUCCEEDED(shGetKnownFolderPath(rfid, //_In_ REFKNOWNFOLDERID rfid,
+ KF_FLAG_DONT_VERIFY, //_In_ DWORD dwFlags,
+ nullptr, //_In_opt_ HANDLE hToken,
+ &path))) //_Out_ PWSTR *ppszPath
+ {
+ ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(path));
+
+ Zstring dirname = path;
+ if (!dirname.empty())
+ csidlToDir.insert(std::make_pair(paramName, dirname));
+ }
+ }
+ };
+
addCsidl(CSIDL_DESKTOPDIRECTORY, L"csidl_Desktop"); // C:\Users\<user>\Desktop
addCsidl(CSIDL_COMMON_DESKTOPDIRECTORY, L"csidl_PublicDesktop"); // C:\Users\All Users\Desktop
@@ -140,6 +172,12 @@ private:
addCsidl(CSIDL_TEMPLATES, L"csidl_Templates"); // C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Templates
addCsidl(CSIDL_COMMON_TEMPLATES, L"csidl_PublicTemplates"); // C:\ProgramData\Microsoft\Windows\Templates
+ //Vista and later:
+ addFolderId(FOLDERID_Downloads, L"csidl_Downloads"); // C:\Users\<user>\Downloads
+ addFolderId(FOLDERID_PublicDownloads, L"csidl_PublicDownloads"); // C:\Users\Public\Downloads
+
+ addFolderId(FOLDERID_QuickLaunch, L"csidl_QuickLaunch"); // C:\Users\<user>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch
+
/*
CSIDL_APPDATA covered by %AppData%
CSIDL_LOCAL_APPDATA covered by %LocalAppData% -> not on XP!
@@ -154,6 +192,8 @@ private:
CSIDL_PROGRAM_FILES_COMMONX86 covered by %CommonProgramFiles(x86)% -> not on XP!
CSIDL_ADMINTOOLS not relevant?
CSIDL_COMMON_ADMINTOOLS not relevant?
+
+ FOLDERID_Public covered by %Public%
*/
}
@@ -298,14 +338,14 @@ Zstring getPathByVolumenName(const Zstring& volumeName) //return empty string on
findFirstMatch.addJob([path, volumeName]() -> std::unique_ptr<Zstring>
{
- UINT type = ::GetDriveType(path.c_str()); //non-blocking call!
+ UINT type = ::GetDriveType(appendSeparator(path).c_str()); //non-blocking call!
if (type == DRIVE_REMOTE || type == DRIVE_CDROM)
return nullptr;
//next call seriously blocks for non-existing network drives!
std::vector<wchar_t> volName(MAX_PATH + 1); //docu says so
- if (::GetVolumeInformation(path.c_str(), //__in_opt LPCTSTR lpRootPathName,
+ if (::GetVolumeInformation(appendSeparator(path).c_str(), //__in_opt LPCTSTR lpRootPathName,
&volName[0], //__out LPTSTR lpVolumeNameBuffer,
static_cast<DWORD>(volName.size()), //__in DWORD nVolumeNameSize,
nullptr, //__out_opt LPDWORD lpVolumeSerialNumber,
@@ -329,18 +369,20 @@ Zstring getPathByVolumenName(const Zstring& volumeName) //return empty string on
//networks and cdrom excluded - this should not block
Zstring getVolumeName(const Zstring& volumePath) //return empty string on error
{
- UINT rv = ::GetDriveType(volumePath.c_str()); //non-blocking call!
- if (rv != DRIVE_REMOTE && rv != DRIVE_CDROM)
+ UINT rv = ::GetDriveType(appendSeparator(volumePath).c_str()); //non-blocking call!
+ if (rv != DRIVE_REMOTE &&
+ rv != DRIVE_CDROM)
{
- std::vector<wchar_t> buffer(MAX_PATH + 1);
- if (::GetVolumeInformation(volumePath.c_str(), //__in_opt LPCTSTR lpRootPathName,
- &buffer[0], //__out LPTSTR lpVolumeNameBuffer,
- static_cast<DWORD>(buffer.size()), //__in DWORD nVolumeNameSize,
- nullptr, //__out_opt LPDWORD lpVolumeSerialNumber,
- nullptr, //__out_opt LPDWORD lpMaximumComponentLength,
- nullptr, //__out_opt LPDWORD lpFileSystemFlags,
- nullptr, //__out LPTSTR lpFileSystemNameBuffer,
- 0)) //__in DWORD nFileSystemNameSize
+ const DWORD bufferSize = MAX_PATH + 1;
+ std::vector<wchar_t> buffer(bufferSize);
+ if (::GetVolumeInformation(appendSeparator(volumePath).c_str(), //__in_opt LPCTSTR lpRootPathName,
+ &buffer[0], //__out LPTSTR lpVolumeNameBuffer,
+ bufferSize, //__in DWORD nVolumeNameSize,
+ nullptr, //__out_opt LPDWORD lpVolumeSerialNumber,
+ nullptr, //__out_opt LPDWORD lpMaximumComponentLength,
+ nullptr, //__out_opt LPDWORD lpFileSystemFlags,
+ nullptr, //__out LPTSTR lpFileSystemNameBuffer,
+ 0)) //__in DWORD nFileSystemNameSize
return &buffer[0];
}
return Zstring();
@@ -420,7 +462,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less
}
#endif
- //3. environment variables: C:\Users\username -> %USERPROFILE%
+ //3. environment variables: C:\Users\<user> -> %USERPROFILE%
{
std::map<Zstring, Zstring> envToDir;
@@ -432,15 +474,15 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less
};
#ifdef FFS_WIN
addEnvVar(L"AllUsersProfile"); // C:\ProgramData
- addEnvVar(L"AppData"); // C:\Users\username\AppData\Roaming
- addEnvVar(L"LocalAppData"); // C:\Users\username\AppData\Local
+ addEnvVar(L"AppData"); // C:\Users\<user>\AppData\Roaming
+ addEnvVar(L"LocalAppData"); // C:\Users\<user>\AppData\Local
addEnvVar(L"ProgramData"); // C:\ProgramData
addEnvVar(L"ProgramFiles"); // C:\Program Files
addEnvVar(L"ProgramFiles(x86)");// C:\Program Files (x86)
addEnvVar(L"CommonProgramFiles"); // C:\Program Files\Common Files
addEnvVar(L"CommonProgramFiles(x86)"); // C:\Program Files (x86)\Common Files
addEnvVar(L"Public"); // C:\Users\Public
- addEnvVar(L"UserProfile"); // C:\Users\username
+ addEnvVar(L"UserProfile"); // C:\Users\<user>
addEnvVar(L"WinDir"); // C:\Windows
addEnvVar(L"Temp"); // C:\Windows\Temp
@@ -449,7 +491,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less
envToDir.insert(csidlMap.begin(), csidlMap.end());
#elif defined FFS_LINUX || defined FFS_MAC
- addEnvVar("HOME"); //Linux: /home/zenju Mac: /Users/zenju
+ addEnvVar("HOME"); //Linux: /home/<user> Mac: /Users/<user>
#endif
//substitute paths by symbolic names
auto pathStartsWith = [](const Zstring& path, const Zstring& prefix) -> bool
@@ -472,7 +514,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirname, std::set<Zstring, Less
});
}
- //4. replace (all) macros: %USERPROFILE% -> C:\Users\username
+ //4. replace (all) macros: %USERPROFILE% -> C:\Users\<user>
{
Zstring testMacros = expandMacros(dirname);
if (testMacros != dirname)
bgstack15