Add bookmarks on Windows

This commit is contained in:
FreeSlave 2016-04-07 17:26:26 +03:00
parent 815a5beb3f
commit 1ae842a950
1 changed files with 87 additions and 0 deletions

View File

@ -344,6 +344,24 @@ private:
return res;
}
version(Windows)
{
private:
import core.sys.windows.windows;
import core.sys.windows.shlobj;
import core.sys.windows.wtypes;
import core.sys.windows.objbase;
import core.sys.windows.objidl;
pragma(lib, "Ole32");
alias GUID KNOWNFOLDERID;
extern(Windows) @nogc @system HRESULT _dummy_SHGetKnownFolderPath(const(KNOWNFOLDERID)* rfid, DWORD dwFlags, HANDLE hToken, wchar** ppszPath) nothrow;
enum KNOWNFOLDERID FOLDERID_Links = {0xbfb9d5e0, 0xc6a9, 0x404c, [0xb2,0xb2,0xae,0x6d,0xb6,0xaf,0x49,0x68]};
}
/// returns array of user bookmarked directories
RootEntry[] getBookmarkPaths() nothrow
{
@ -386,7 +404,76 @@ RootEntry[] getBookmarkPaths() nothrow
}
} else version(Windows) {
/*
* This will not include bookmarks of special items and virtual folders like Recent Files or Recycle bin.
*/
import core.stdc.wchar_ : wcslen;
import std.exception : enforce;
import std.utf : toUTF8, toUTF16z;
import std.file : dirEntries, SpanMode;
import std.string : endsWith;
try {
auto shell = enforce(LoadLibraryA("Shell32"));
scope(exit) FreeLibrary(shell);
auto ptrSHGetKnownFolderPath = cast(typeof(&_dummy_SHGetKnownFolderPath))enforce(GetProcAddress(shell, "SHGetKnownFolderPath"));
wchar* linksFolderZ;
const linksGuid = FOLDERID_Links;
enforce(ptrSHGetKnownFolderPath(&linksGuid, 0, null, &linksFolderZ) == S_OK);
scope(exit) CoTaskMemFree(linksFolderZ);
string linksFolder = linksFolderZ[0..wcslen(linksFolderZ)].toUTF8;
CoInitialize(null);
scope(exit) CoUninitialize();
HRESULT hres;
IShellLink psl;
auto clsidShellLink = CLSID_ShellLink;
auto iidShellLink = IID_IShellLinkW;
hres = CoCreateInstance(&clsidShellLink, null, CLSCTX_INPROC, &iidShellLink, cast(LPVOID*)&psl);
enforce(SUCCEEDED(hres), "Failed to create IShellLink instance");
scope(exit) psl.Release();
IPersistFile ppf;
auto iidPersistFile = IID_IPersistFile;
hres = psl.QueryInterface(&iidPersistFile, cast(void**)&ppf);
enforce(SUCCEEDED(hres), "Failed to query IPersistFile interface");
scope(exit) ppf.Release();
foreach(linkFile; dirEntries(linksFolder, SpanMode.shallow)) {
if (!linkFile.name.endsWith(".lnk")) {
continue;
}
try {
wchar[MAX_PATH] szGotPath;
WIN32_FIND_DATA wfd;
hres = ppf.Load(linkFile.name.toUTF16z, STGM_READ);
enforce(SUCCEEDED(hres), "Failed to load link file");
hres = psl.Resolve(null, 0);
enforce(SUCCEEDED(hres), "Failed to resolve link");
hres = psl.GetPath(szGotPath.ptr, szGotPath.length, &wfd, 0);
enforce(SUCCEEDED(hres), "Failed to get path of link target");
auto path = szGotPath[0..wcslen(szGotPath.ptr)];
if (path.length) {
res ~= RootEntry(RootEntryType.BOOKMARK, path.toUTF8, linkFile.name.baseName.stripExtension.toUTF32);
}
} catch(Exception e) {
}
}
} catch(Exception e) {
}
}
return res;
}