• R/O
  • SSH
  • HTTPS

tortoisesvn: Commit


Commit MetaInfo

Revision29468 (tree)
Zeit2022-10-05 03:00:51
Autorstefankueng

Log Message

fix determining the path for a folder background on right-click when using not the first tab in Win11 explorer view

Ändern Zusammenfassung

Diff

--- trunk/src/Changelog.txt (revision 29467)
+++ trunk/src/Changelog.txt (revision 29468)
@@ -1,4 +1,9 @@
1-Version 1.14.5
1+Version 1.14.6
2+- BUG: context menu for a directory background in
3+ Win11 when not using the first tab in explorer
4+ used the wrong path. (Stefan)
5+
6+Version 1.14.5
27 - BUG: 1.14.4 was wrongly linked against svn 1.14.1
38 instead of svn 1.14.2
49
--- trunk/src/TortoiseShell/ContextMenu.cpp (revision 29467)
+++ trunk/src/TortoiseShell/ContextMenu.cpp (revision 29468)
@@ -316,7 +316,7 @@
316316 m_files.push_back(strPath.GetWinPath());
317317 if (i != 0)
318318 continue;
319- //get the Subversion status of the item
319+ // get the Subversion status of the item
320320 svn_wc_status_kind status = svn_wc_status_none;
321321 try
322322 {
@@ -394,7 +394,7 @@
394394 } // if (m_State == FileStateDropHandler)
395395 else
396396 {
397- //Enumerate PIDLs which the user has selected
397+ // Enumerate PIDLs which the user has selected
398398 CIDA* cida = static_cast<CIDA*>(GlobalLock(medium.hGlobal));
399399 ItemIDList parent(GetPIDLFolder(cida));
400400
@@ -457,7 +457,7 @@
457457 }
458458 if (str.empty() || (!g_shellCache.IsContextPathAllowed(str.c_str())))
459459 continue;
460- //check if our menu is requested for a subversion admin directory
460+ // check if our menu is requested for a subversion admin directory
461461 if (g_SVNAdminDir.IsAdminDirPath(str.c_str()))
462462 continue;
463463
@@ -468,7 +468,7 @@
468468 itemStates |= (strPath.GetFileExtension().CompareNoCase(L".patch") == 0) ? ITEMIS_PATCHFILE : 0;
469469 if (statFetched)
470470 continue;
471- //get the Subversion status of the item
471+ // get the Subversion status of the item
472472 svn_wc_status_kind status = svn_wc_status_none;
473473 try
474474 {
@@ -770,8 +770,8 @@
770770
771771 if (isTop && menu)
772772 {
773- //menu entry for the top context menu, so append an "SVN " before
774- //the menu text to indicate where the entry comes from
773+ // menu entry for the top context menu, so append an "SVN " before
774+ // the menu text to indicate where the entry comes from
775775 wcscpy_s(menuTextBuffer, L"SVN ");
776776 if (!g_shellCache.HasShellMenuAccelerators())
777777 {
@@ -824,8 +824,8 @@
824824 bool CShellExt::WriteClipboardPathsToTempFile(std::wstring& tempFile)
825825 {
826826 tempFile = std::wstring();
827- //write all selected files and paths to a temporary file
828- //for TortoiseProc.exe to read out again.
827+ // write all selected files and paths to a temporary file
828+ // for TortoiseProc.exe to read out again.
829829 DWORD pathLength = GetTempPath(0, nullptr);
830830 auto path = std::make_unique<wchar_t[]>(pathLength + 1LL);
831831 auto tempFileBuf = std::make_unique<wchar_t[]>(pathLength + 100LL);
@@ -880,8 +880,8 @@
880880
881881 std::wstring CShellExt::WriteFileListToTempFile(const std::vector<std::wstring>& files, const std::wstring folder)
882882 {
883- //write all selected files and paths to a temporary file
884- //for TortoiseProc.exe to read out again.
883+ // write all selected files and paths to a temporary file
884+ // for TortoiseProc.exe to read out again.
885885 DWORD pathLength = GetTempPath(0, nullptr);
886886 auto path = std::make_unique<wchar_t[]>(pathLength + 1);
887887 auto tempFile = std::make_unique<wchar_t[]>(pathLength + 100);
@@ -890,12 +890,12 @@
890890 std::wstring retFilePath = std::wstring(tempFile.get());
891891
892892 CAutoFile file = ::CreateFile(tempFile.get(),
893- GENERIC_WRITE,
894- FILE_SHARE_READ,
895- nullptr,
896- CREATE_ALWAYS,
897- FILE_ATTRIBUTE_TEMPORARY,
898- nullptr);
893+ GENERIC_WRITE,
894+ FILE_SHARE_READ,
895+ nullptr,
896+ CREATE_ALWAYS,
897+ FILE_ATTRIBUTE_TEMPORARY,
898+ nullptr);
899899
900900 if (!file)
901901 return std::wstring();
@@ -924,7 +924,7 @@
924924 LoadLangDll();
925925
926926 if ((uFlags & CMF_DEFAULTONLY) != 0)
927- return S_OK; //we don't change the default action
927+ return S_OK; // we don't change the default action
928928
929929 if (m_files.empty() || m_folder.empty())
930930 return S_OK;
@@ -934,11 +934,11 @@
934934
935935 bool bSourceAndTargetFromSameRepository = (uuidSource.compare(uuidTarget) == 0) || uuidSource.empty() || uuidTarget.empty();
936936
937- //the drop handler only has eight commands, but not all are visible at the same time:
938- //if the source file(s) are under version control then those files can be moved
939- //to the new location or they can be moved with a rename,
940- //if they are unversioned then they can be added to the working copy
941- //if they are versioned, they also can be exported to an unversioned location
937+ // the drop handler only has eight commands, but not all are visible at the same time:
938+ // if the source file(s) are under version control then those files can be moved
939+ // to the new location or they can be moved with a rename,
940+ // if they are unversioned then they can be added to the working copy
941+ // if they are versioned, they also can be exported to an unversioned location
942942 UINT idCmd = idCmdFirst;
943943
944944 // SVN move here
@@ -1016,9 +1016,9 @@
10161016 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Shell :: QueryContextMenu itemStates=%ld\n", itemStates);
10171017 PreserveChdir preserveChdir;
10181018
1019- //first check if our drop handler is called
1020- //and then (if true) provide the context menu for the
1021- //drop handler
1019+ // first check if our drop handler is called
1020+ // and then (if true) provide the context menu for the
1021+ // drop handler
10221022 if (m_state == FileStateDropHandler)
10231023 {
10241024 return QueryDropContext(uFlags, idCmdFirst, hMenu, indexMenu);
@@ -1025,7 +1025,7 @@
10251025 }
10261026
10271027 if ((uFlags & CMF_DEFAULTONLY) != 0)
1028- return S_OK; //we don't change the default action
1028+ return S_OK; // we don't change the default action
10291029
10301030 if (m_files.empty() && m_folder.empty())
10311031 return S_OK;
@@ -1081,7 +1081,7 @@
10811081 if ((itemStates & (ITEMIS_INSVN | ITEMIS_INVERSIONEDFOLDER | ITEMIS_FOLDERINSVN)) == 0)
10821082 return S_OK;
10831083 }
1084- //check if our menu is requested for a subversion admin directory
1084+ // check if our menu is requested for a subversion admin directory
10851085 if (g_SVNAdminDir.IsAdminDirPath(m_folder.c_str()))
10861086 return S_OK;
10871087
@@ -1106,10 +1106,10 @@
11061106 }
11071107 }
11081108
1109- //check if we already added our menu entry for a folder.
1110- //we check that by iterating through all menu entries and check if
1111- //the dwItemData member points to our global ID string. That string is set
1112- //by our shell extension when the folder menu is inserted.
1109+ // check if we already added our menu entry for a folder.
1110+ // we check that by iterating through all menu entries and check if
1111+ // the dwItemData member points to our global ID string. That string is set
1112+ // by our shell extension when the folder menu is inserted.
11131113 if (hMenu)
11141114 {
11151115 wchar_t menuBuf[MAX_PATH] = {0};
@@ -1130,7 +1130,7 @@
11301130 LoadLangDll();
11311131 UINT idCmd = idCmdFirst;
11321132
1133- //create the sub menu
1133+ // create the sub menu
11341134 HMENU subMenu = hMenu ? CreateMenu() : nullptr;
11351135 int indexSubMenu = 0;
11361136
@@ -1222,9 +1222,9 @@
12221222 }
12231223 }
12241224
1225- //add sub menu to main context menu
1226- //don't use InsertMenu because this will lead to multiple menu entries in the explorer file menu.
1227- //see http://support.microsoft.com/default.aspx?scid=kb;en-us;214477 for details of that.
1225+ // add sub menu to main context menu
1226+ // don't use InsertMenu because this will lead to multiple menu entries in the explorer file menu.
1227+ // see http://support.microsoft.com/default.aspx?scid=kb;en-us;214477 for details of that.
12281228 MAKESTRING(IDS_MENUSUBMENU);
12291229 if (!g_shellCache.HasShellMenuAccelerators())
12301230 {
@@ -1282,13 +1282,13 @@
12821282 {
12831283 InsertMenuItem(hMenu, indexMenu++, TRUE, &menuItemInfo);
12841284
1285- //separator after
1285+ // separator after
12861286 InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr);
12871287 TweakMenu(hMenu);
12881288 }
12891289 idCmd++;
12901290
1291- //return number of menu items added
1291+ // return number of menu items added
12921292 return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, static_cast<USHORT>(idCmd - idCmdFirst)));
12931293 }
12941294
@@ -1404,15 +1404,15 @@
14041404
14051405 void CShellExt::InvokeCommand(int cmd, const std::wstring& cwd, const std::wstring& appDir, const std::wstring uuidSource, HWND hParent, DWORD itemStates, DWORD itemStatesFolder, const std::vector<std::wstring>& paths, const std::wstring& folder, CRegStdString& regDiffLater, Microsoft::WRL::ComPtr<IUnknown> site)
14061406 {
1407- //TortoiseProc expects a command line of the form:
1407+ // TortoiseProc expects a command line of the form:
14081408 //"/command:<commandname> /pathfile:<path> /startrev:<startrevision> /endrev:<endrevision> /deletepathfile
1409- // or
1409+ // or
14101410 //"/command:<commandname> /path:<path> /startrev:<startrevision> /endrev:<endrevision>
14111411 //
14121412 //* path is a path to a single file/directory for commands which only act on single items (log, checkout, ...)
14131413 //* pathfile is a path to a temporary file which contains a list of file paths
14141414 std::wstring svnCmd = L" /command:";
1415- CTraceToOutputDebugString::Instance()(__FUNCTION__ );
1415+ CTraceToOutputDebugString::Instance()(__FUNCTION__);
14161416
14171417 switch (cmd)
14181418 {
@@ -1831,16 +1831,16 @@
18311831 // This is for the status bar and things like that:
18321832 STDMETHODIMP CShellExt::GetCommandString(UINT_PTR idCmd,
18331833 UINT uFlags,
1834- UINT FAR* /*reserved*/,
1835- LPSTR pszName,
1836- UINT cchMax)
1834+ UINT FAR* /*reserved*/,
1835+ LPSTR pszName,
1836+ UINT cchMax)
18371837 {
18381838 PreserveChdir preserveChdir;
1839- //do we know the id?
1839+ // do we know the id?
18401840 auto idIt = myIDMap.lower_bound(idCmd);
18411841 if (idIt == myIDMap.end() || idIt->first != idCmd)
18421842 {
1843- return E_INVALIDARG; //no, we don't
1843+ return E_INVALIDARG; // no, we don't
18441844 }
18451845
18461846 LoadLangDll();
@@ -1933,7 +1933,7 @@
19331933 LPCWSTR resource;
19341934 DRAWITEMSTRUCT* lpdis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
19351935 if ((lpdis == nullptr) || (lpdis->CtlType != ODT_MENU))
1936- return S_OK; //not for a menu
1936+ return S_OK; // not for a menu
19371937 resource = GetMenuTextFromResource(static_cast<int>(myIDMap[lpdis->itemID]));
19381938 if (resource == nullptr)
19391939 return S_OK;
@@ -2095,7 +2095,7 @@
20952095
20962096 bool CShellExt::IsIllegalFolder(const std::wstring& folder, int* csidlarray)
20972097 {
2098- wchar_t buf[MAX_PATH] = {0}; //MAX_PATH ok, since SHGetSpecialFolderPath doesn't return the required buffer length!
2098+ wchar_t buf[MAX_PATH] = {0}; // MAX_PATH ok, since SHGetSpecialFolderPath doesn't return the required buffer length!
20992099 PIDLIST_ABSOLUTE pidl = nullptr;
21002100 for (int i = 0; csidlarray[i]; i++)
21012101 {
@@ -2554,7 +2554,7 @@
25542554 }
25552555 // currently, explorer does not support subcommands which their own subcommands. Once it does,
25562556 // use the line below instead of the ones above
2557- //m_explorerCommands.push_back(CExplorerCommand(stringTableBuffer, icon, ShellMenuUnIgnoreSub, GetAppDirectory(), uuidSource, itemStates, itemStatesFolder, m_files, exCmds));
2557+ // m_explorerCommands.push_back(CExplorerCommand(stringTableBuffer, icon, ShellMenuUnIgnoreSub, GetAppDirectory(), uuidSource, itemStates, itemStatesFolder, m_files, exCmds));
25582558 }
25592559 if (itemStates & ITEMIS_IGNORED)
25602560 {
@@ -2690,6 +2690,7 @@
26902690 Microsoft::WRL::ComPtr<IShellItemArray> ownItemArray;
26912691 if (m_site)
26922692 {
2693+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Shell :: GetState - have m_site\n");
26932694 Microsoft::WRL::ComPtr<IOleWindow> oleWindow;
26942695 m_site.As(&oleWindow);
26952696 if (oleWindow)
@@ -2773,7 +2774,7 @@
27732774 {
27742775 // context menu for a folder background (no selection),
27752776 // so try to get the current path of the explorer window instead
2776- auto path = ExplorerViewPath();
2777+ auto path = ExplorerViewPath(m_site);
27772778 if (path.empty())
27782779 {
27792780 *pCmdState = ECS_HIDDEN;
@@ -2844,83 +2845,52 @@
28442845 return S_OK;
28452846 }
28462847
2847-std::wstring CShellExt::ExplorerViewPath()
2848+std::wstring CShellExt::ExplorerViewPath(const Microsoft::WRL::ComPtr<IUnknown>& site)
28482849 {
2850+ CTraceToOutputDebugString::Instance()(__FUNCTION__ "\n");
28492851 std::wstring path;
2850- HRESULT hr = NOERROR;
2851-
2852- // the top context menu in Win11 does not
2853- // provide an IOleWindow with the SetSite() object,
2854- // so we have to use a trick to get it: since the
2855- // context menu must always be the top window, we
2856- // just grab the foreground window and assume that
2857- // this is the explorer window.
2858- auto hwnd = ::GetForegroundWindow();
2859- if (hwnd == nullptr)
2860- return path;
2861-
2862- wchar_t szName[1024] = {0};
2863- ::GetClassName(hwnd, szName, _countof(szName));
2864- if (StrCmp(szName, L"WorkerW") == 0 ||
2865- StrCmp(szName, L"Progman") == 0)
2852+ if (site)
28662853 {
2867- //special folder: desktop
2868- hr = ::SHGetFolderPath(nullptr, CSIDL_DESKTOP, nullptr, SHGFP_TYPE_CURRENT, szName);
2869- if (FAILED(hr))
2870- return path;
2871-
2872- path = szName;
2873- return path;
2874- }
2875-
2876- if (StrCmp(szName, L"CabinetWClass") != 0)
2877- return path;
2878-
2879- // get the shell windows object to enumerate all active explorer
2880- // instances. We use those to compare the foreground hwnd to it.
2881- Microsoft::WRL::ComPtr<IShellWindows> shell;
2882- if (FAILED(CoCreateInstance(CLSID_ShellWindows, nullptr, CLSCTX_ALL,
2883- IID_IShellWindows, reinterpret_cast<LPVOID*>(shell.GetAddressOf()))))
2884- return path;
2885-
2886- if (shell == nullptr)
2887- return path;
2888-
2889- Microsoft::WRL::ComPtr<IDispatch> disp;
2890- VARIANT variant{};
2891- variant.vt = VT_I4;
2892-
2893- Microsoft::WRL::ComPtr<IWebBrowserApp> browser;
2894- // look for correct explorer window
2895- for (variant.intVal = 0; shell->Item(variant, disp.GetAddressOf()) == S_OK; variant.intVal++)
2896- {
2897- Microsoft::WRL::ComPtr<IWebBrowserApp> tmp;
2898- if (FAILED(disp->QueryInterface(tmp.GetAddressOf())))
2899- continue;
2900-
2901- HWND tmpHwnd = nullptr;
2902- hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHwnd));
2903- if (hwnd == tmpHwnd)
2854+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got site\n");
2855+ Microsoft::WRL::ComPtr<IServiceProvider> serviceProvider;
2856+ if (SUCCEEDED(site.As(&serviceProvider)))
29042857 {
2905- browser = tmp;
2906- break; // found it!
2858+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got IServiceProvider\n");
2859+ Microsoft::WRL::ComPtr<IShellBrowser> shellBrowser;
2860+ if (SUCCEEDED(serviceProvider->QueryService(SID_SShellBrowser, IID_IShellBrowser, &shellBrowser)))
2861+ {
2862+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got IShellBrowser\n");
2863+ Microsoft::WRL::ComPtr<IShellView> shellView;
2864+ if (SUCCEEDED(shellBrowser->QueryActiveShellView(&shellView)))
2865+ {
2866+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got IShellView\n");
2867+ Microsoft::WRL::ComPtr<IFolderView> folderView;
2868+ if (SUCCEEDED(shellView.As(&folderView)))
2869+ {
2870+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got IFolderView\n");
2871+ Microsoft::WRL::ComPtr<IPersistFolder2> persistFolder;
2872+ if (SUCCEEDED(folderView->GetFolder(IID_IPersistFolder2, (LPVOID*)&persistFolder)))
2873+ {
2874+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got IPersistFolder2\n");
2875+ PIDLIST_ABSOLUTE curFolder;
2876+ if (SUCCEEDED(persistFolder->GetCurFolder(&curFolder)))
2877+ {
2878+ CTraceToOutputDebugString::Instance()(__FUNCTION__ ": got GetCurFolder\n");
2879+ wchar_t buf[MAX_PATH] = {0};
2880+ // find the path of the folder
2881+ if (SHGetPathFromIDList(curFolder, buf))
2882+ {
2883+ CTraceToOutputDebugString::Instance()(__FUNCTION__ L": got SHGetPathFromIDList : %s\n", buf);
2884+ path = buf;
2885+ }
2886+ CoTaskMemFree(curFolder);
2887+ }
2888+ }
2889+ }
2890+ }
2891+ }
29072892 }
29082893 }
2909-
2910- if (browser != nullptr)
2911- {
2912- BSTR url;
2913- hr = browser->get_LocationURL(&url);
2914- if (FAILED(hr))
2915- return path;
2916-
2917- std::wstring sUrl(url, SysStringLen(url));
2918- SysFreeString(url);
2919- DWORD size = _countof(szName);
2920- hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
2921- if (SUCCEEDED(hr))
2922- path = szName;
2923- }
2924-
2894+
29252895 return path;
29262896 }
--- trunk/src/TortoiseShell/ShellExt.h (revision 29467)
+++ trunk/src/TortoiseShell/ShellExt.h (revision 29468)
@@ -247,7 +247,7 @@
247247 static void AddPathCommand(std::wstring& svnCmd, LPCWSTR command, bool bFilesAllowed, const std::vector<std::wstring>& files, const std::wstring folder);
248248 static void AddPathFileCommand(std::wstring& svnCmd, LPCWSTR command, const std::vector<std::wstring>& files, const std::wstring folder);
249249 static void AddPathFileDropCommand(std::wstring& svnCmd, LPCWSTR command, const std::vector<std::wstring>& files, const std::wstring folder);
250- static std::wstring ExplorerViewPath();
250+ static std::wstring ExplorerViewPath(const Microsoft::WRL::ComPtr<IUnknown>& site);
251251
252252 public:
253253 explicit CShellExt(FileState state);
Show on old repository browser