protected:
// code from https://github.com/microsoft/terminal/blob/main/src/cascadia/ShellExtension/OpenTerminalHere.cpp
- std::wstring _GetPathFromExplorer() const
- {
- std::wstring path;
- HRESULT hr = NOERROR;
-
- auto hwnd = ::GetForegroundWindow();
- if (hwnd == nullptr)
- {
- return path;
- }
-
- TCHAR szName[MAX_PATH] = { 0 };
- ::GetClassName(hwnd, szName, MAX_PATH);
- if (0 == StrCmp(szName, L"WorkerW") ||
- 0 == StrCmp(szName, L"Progman"))
- {
- //special folder: desktop
- hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
- if (FAILED(hr))
- {
- return path;
- }
-
- path = szName;
- return path;
- }
-
- if (0 != StrCmp(szName, L"CabinetWClass"))
- {
- return path;
- }
-
- ComPtr<IShellWindows> shell;
- hr = CoCreateInstance(CLSID_ShellWindows, nullptr, CLSCTX_ALL, IID_IShellWindows, &shell);
- if (FAILED(hr) || shell == nullptr)
- {
- return path;
- }
-
- ComPtr<IDispatch> disp;
- wil::unique_variant variant;
- variant.vt = VT_I4;
-
- ComPtr<IWebBrowserApp> browser;
- // look for correct explorer window
- for (variant.intVal = 0;
- shell->Item(variant, &disp) == S_OK;
- variant.intVal++)
- {
- ComPtr<IWebBrowserApp> tmp;
- if (FAILED(disp->QueryInterface<IWebBrowserApp>(&tmp)))
- {
- disp = nullptr; // get rid of DEBUG non-nullptr warning
- continue;
- }
-
- HWND tmpHWND = NULL;
- hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
- if (hwnd == tmpHWND)
- {
- browser = tmp;
- disp = nullptr; // get rid of DEBUG non-nullptr warning
- break; //found
- }
-
- disp = nullptr; // get rid of DEBUG non-nullptr warning
- }
-
- if (browser != nullptr)
- {
- wil::unique_bstr url;
- hr = browser->get_LocationURL(&url);
- if (FAILED(hr))
- {
- return path;
- }
-
- std::wstring sUrl(url.get(), SysStringLen(url.get()));
- DWORD size = MAX_PATH;
- hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
- if (SUCCEEDED(hr))
- {
- path = szName;
- }
- }
-
- return path;
- }
+ HRESULT GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept
+ {
+ ComPtr<IShellItem> psi;
+ if (psiArray)
+ {
+ DWORD count{};
+ RETURN_IF_FAILED(psiArray->GetCount(&count));
+ if (count) // Sometimes we get an array with a count of 0. Fall back to the site chain.
+ {
+ RETURN_IF_FAILED(psiArray->GetItemAt(0, &psi));
+ }
+ }
+
+ if (!psi)
+ {
+ RETURN_IF_FAILED(GetLocationFromSite(&psi));
+ }
+
+ RETURN_HR_IF(S_FALSE, !psi);
+ RETURN_IF_FAILED(psi.CopyTo(location));
+ return S_OK;
+ }
+
+ HRESULT GetLocationFromSite(IShellItem** location) const noexcept
+ {
+ ComPtr<IServiceProvider> serviceProvider;
+ RETURN_IF_FAILED(m_site.As<IServiceProvider>(&serviceProvider));
+ ComPtr<IFolderView> folderView;
+ RETURN_IF_FAILED(serviceProvider->QueryService<IFolderView>(SID_SFolderView, &folderView));
+ RETURN_IF_FAILED(folderView->GetFolder(IID_PPV_ARGS(location)));
+ return S_OK;
+ }
std::vector<std::wstring> GetPaths(_In_opt_ IShellItemArray* selection)
{
DWORD dwNumItems = 0;
if (!selection)
{
- std::wstring path = _GetPathFromExplorer();
- if (!path.empty())
- paths.push_back(path);
+ ComPtr<IShellItem> psi;
+ if (SUCCEEDED(GetBestLocationFromSelectionOrSite(selection, &psi)))
+ {
+ wil::unique_cotaskmem_string pszFilePath;
+ if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath)))
+ {
+ std::wstring path = pszFilePath.get();
+ if (!path.empty())
+ paths.push_back(path);
+ }
+ }
}
else
{