Sync logging in TortoiseShell with TortoiseSVN
[TortoiseGit.git] / src / TortoiseShell / ExplorerCommand.cpp
blob4f63033816a6b617e76d7326b6ae64f057ef3e2c
1 // TortoiseGit- a Windows shell extension for easy version control
3 // Copyright (C) 2021-2022 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "stdafx.h"
20 #include "ExplorerCommand.h"
22 CExplorerCommandEnum::CExplorerCommandEnum(const std::vector<CExplorerCommand> &vec)
23 : m_vecCommands(vec)
27 HRESULT __stdcall CExplorerCommandEnum::QueryInterface(REFIID refiid, void **ppv)
29 *ppv = nullptr;
30 if (IID_IUnknown == refiid || IID_IEnumExplorerCommand == refiid)
31 *ppv = this;
33 if (*ppv)
35 static_cast<LPUNKNOWN>(*ppv)->AddRef();
36 return S_OK;
38 return E_NOINTERFACE;
41 ULONG __stdcall CExplorerCommandEnum::AddRef()
43 return ++m_cRefCount;
46 ULONG __stdcall CExplorerCommandEnum::Release()
48 --m_cRefCount;
49 if (m_cRefCount == 0)
51 delete this;
52 return 0;
54 return m_cRefCount;
57 HRESULT __stdcall CExplorerCommandEnum::Next(ULONG celt, IExplorerCommand **rgelt, ULONG *pceltFetched)
59 HRESULT hr = S_FALSE;
61 if (!celt)
62 celt = 1;
63 if (pceltFetched)
64 *pceltFetched = 0;
66 ULONG i = 0;
67 for (; i < celt; ++i)
69 if (m_iCur == static_cast<ULONG>(m_vecCommands.size()))
70 break;
72 rgelt[i] = new CExplorerCommand(m_vecCommands[m_iCur].m_title,
73 m_vecCommands[m_iCur].m_iconId,
74 m_vecCommands[m_iCur].m_cmd,
75 m_vecCommands[m_iCur].m_appDir,
76 m_vecCommands[m_iCur].m_uuidSource,
77 m_vecCommands[m_iCur].m_itemStates,
78 m_vecCommands[m_iCur].m_itemStatesFolder,
79 m_vecCommands[m_iCur].m_paths,
80 m_vecCommands[m_iCur].m_subItems,
81 m_vecCommands[m_iCur].m_site);
82 rgelt[i]->AddRef();
84 if (pceltFetched)
85 (*pceltFetched)++;
87 ++m_iCur;
90 if (i == celt)
91 hr = S_OK;
93 return hr;
96 HRESULT __stdcall CExplorerCommandEnum::Skip(ULONG celt)
98 if ((m_iCur + static_cast<int>(celt)) >= m_vecCommands.size())
99 return S_FALSE;
100 m_iCur += celt;
101 return S_OK;
104 HRESULT __stdcall CExplorerCommandEnum::Reset()
106 m_iCur = 0;
107 return S_OK;
110 HRESULT __stdcall CExplorerCommandEnum::Clone(IEnumExplorerCommand **ppenum)
112 if (!ppenum)
113 return E_POINTER;
117 CExplorerCommandEnum *newEnum = new CExplorerCommandEnum(m_vecCommands);
119 newEnum->AddRef();
120 newEnum->m_iCur = m_iCur;
121 *ppenum = newEnum;
123 catch (const std::bad_alloc &)
125 return E_OUTOFMEMORY;
127 return S_OK;
130 CExplorerCommand::CExplorerCommand(const std::wstring &title, UINT iconId,
131 int cmd,
132 const std::wstring & appDir,
133 const std::wstring & uuidSource,
134 DWORD itemStates,
135 DWORD itemStatesFolder,
136 std::vector<std::wstring> paths,
137 std::vector<CExplorerCommand> subItems,
138 Microsoft::WRL::ComPtr<IUnknown> site)
139 : m_cRefCount(0)
140 , m_title(title)
141 , m_iconId(iconId)
142 , m_cmd(cmd)
143 , m_appDir(appDir)
144 , m_uuidSource(uuidSource)
145 , m_itemStates(itemStates)
146 , m_itemStatesFolder(itemStatesFolder)
147 , m_paths(paths)
148 , m_subItems(subItems)
149 , m_regDiffLater(L"Software\\TortoiseGitMerge\\DiffLater", L"")
150 , m_site(site)
154 HRESULT __stdcall CExplorerCommand::QueryInterface(REFIID refiid, void **ppv)
156 *ppv = nullptr;
157 if (IID_IUnknown == refiid || IID_IExplorerCommand == refiid)
158 *ppv = this;
160 if (*ppv)
162 static_cast<LPUNKNOWN>(*ppv)->AddRef();
163 return S_OK;
165 return E_NOINTERFACE;
168 ULONG __stdcall CExplorerCommand::AddRef()
170 return ++m_cRefCount;
173 ULONG __stdcall CExplorerCommand::Release()
175 --m_cRefCount;
176 if (m_cRefCount == 0)
178 delete this;
179 return 0;
181 return m_cRefCount;
184 HRESULT __stdcall CExplorerCommand::GetTitle(IShellItemArray * /*psiItemArray*/, LPWSTR *ppszName)
186 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
187 if (m_title.empty())
189 *ppszName = nullptr;
190 return S_FALSE;
192 SHStrDupW(m_title.c_str(), ppszName);
193 return S_OK;
196 HRESULT __stdcall CExplorerCommand::GetIcon(IShellItemArray * /*psiItemArray*/, LPWSTR *ppszIcon)
198 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
199 if (m_iconId == 0)
201 SHStrDupW(L"", ppszIcon);
202 return S_FALSE;
204 std::wstring iconPath = m_appDir + L"TortoiseGitProc.exe,-";
205 iconPath += std::to_wstring(m_iconId);
206 SHStrDupW(iconPath.c_str(), ppszIcon);
207 return S_OK;
210 HRESULT __stdcall CExplorerCommand::GetToolTip(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszInfotip)
212 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
213 *ppszInfotip = nullptr;
214 return E_NOTIMPL;
217 HRESULT __stdcall CExplorerCommand::GetCanonicalName(GUID *pguidCommandName)
219 CTraceToOutputDebugString::Instance()(__FUNCTION__);
220 *pguidCommandName = __uuidof(this);
221 return S_OK;
224 HRESULT __stdcall CExplorerCommand::GetState(IShellItemArray * /*psiItemArray*/, BOOL /*fOkToBeSlow*/, EXPCMDSTATE *pCmdState)
226 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
227 *pCmdState = ECS_ENABLED;
228 if (m_title.empty())
229 return E_FAIL;
230 return S_OK;
233 HRESULT __stdcall CExplorerCommand::Invoke(IShellItemArray * /*psiItemArray*/, IBindCtx * /*pbc*/)
235 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
236 std::wstring cwdFolder;
237 if (m_paths.empty())
239 // use the users desktop path as the CWD
240 wchar_t desktopDir[MAX_PATH] = {0};
241 SHGetSpecialFolderPath(nullptr, desktopDir, CSIDL_DESKTOPDIRECTORY, TRUE);
242 cwdFolder = desktopDir;
244 else
246 cwdFolder = m_paths[0];
247 if (!PathIsDirectory(cwdFolder.c_str()))
249 cwdFolder = cwdFolder.substr(0, cwdFolder.rfind('\\'));
253 CShellExt::InvokeCommand(m_cmd, m_appDir, m_uuidSource,
254 GetForegroundWindow(), m_itemStates, m_itemStatesFolder, m_paths,
255 m_paths.empty() ? L"" : m_paths[0],
256 m_regDiffLater, m_site);
257 return S_OK;
260 HRESULT __stdcall CExplorerCommand::GetFlags(EXPCMDFLAGS *pFlags)
262 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
263 *pFlags = ECF_DEFAULT;
264 if (!m_subItems.empty())
265 *pFlags = ECF_HASSUBCOMMANDS;
266 if (m_title.empty())
267 *pFlags = ECF_ISSEPARATOR;
268 return S_OK;
271 HRESULT __stdcall CExplorerCommand::EnumSubCommands(IEnumExplorerCommand **ppEnum)
273 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
274 if (m_subItems.empty())
275 return E_INVALIDARG;
276 *ppEnum = new CExplorerCommandEnum(m_subItems);
277 (*ppEnum)->AddRef();
278 return S_OK;
281 HRESULT __stdcall CExplorerCommand::SetSite(IUnknown * pUnkSite)
283 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
284 m_site = pUnkSite;
285 return S_OK;
288 HRESULT __stdcall CExplorerCommand::GetSite(REFIID riid, void ** ppvSite)
290 CTraceToOutputDebugString::Instance()(__FUNCTION__ ": title: %s\n", m_title.c_str());
291 return m_site.CopyTo(riid, ppvSite);