From 1ae842a950ee0f2d3ca4eaa48f15d5e7afac0d3f Mon Sep 17 00:00:00 2001 From: FreeSlave Date: Thu, 7 Apr 2016 17:26:26 +0300 Subject: [PATCH] Add bookmarks on Windows --- src/dlangui/core/files.d | 87 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/dlangui/core/files.d b/src/dlangui/core/files.d index deadbb89..13624972 100644 --- a/src/dlangui/core/files.d +++ b/src/dlangui/core/files.d @@ -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; }