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.
20 #include "ExplorerCommand.h"
22 CExplorerCommandEnum::CExplorerCommandEnum(const std::vector
<CExplorerCommand
> &vec
)
27 HRESULT __stdcall
CExplorerCommandEnum::QueryInterface(REFIID refiid
, void **ppv
)
30 if (IID_IUnknown
== refiid
|| IID_IEnumExplorerCommand
== refiid
)
35 static_cast<LPUNKNOWN
>(*ppv
)->AddRef();
41 ULONG __stdcall
CExplorerCommandEnum::AddRef()
46 ULONG __stdcall
CExplorerCommandEnum::Release()
57 HRESULT __stdcall
CExplorerCommandEnum::Next(ULONG celt
, IExplorerCommand
**rgelt
, ULONG
*pceltFetched
)
69 if (m_iCur
== static_cast<ULONG
>(m_vecCommands
.size()))
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
);
96 HRESULT __stdcall
CExplorerCommandEnum::Skip(ULONG celt
)
98 if ((m_iCur
+ static_cast<int>(celt
)) >= m_vecCommands
.size())
104 HRESULT __stdcall
CExplorerCommandEnum::Reset()
110 HRESULT __stdcall
CExplorerCommandEnum::Clone(IEnumExplorerCommand
**ppenum
)
117 CExplorerCommandEnum
*newEnum
= new CExplorerCommandEnum(m_vecCommands
);
120 newEnum
->m_iCur
= m_iCur
;
123 catch (const std::bad_alloc
&)
125 return E_OUTOFMEMORY
;
130 CExplorerCommand::CExplorerCommand(const std::wstring
&title
, UINT iconId
,
132 const std::wstring
& appDir
,
133 const std::wstring
& uuidSource
,
135 DWORD itemStatesFolder
,
136 std::vector
<std::wstring
> paths
,
137 std::vector
<CExplorerCommand
> subItems
,
138 Microsoft::WRL::ComPtr
<IUnknown
> site
)
144 , m_uuidSource(uuidSource
)
145 , m_itemStates(itemStates
)
146 , m_itemStatesFolder(itemStatesFolder
)
148 , m_subItems(subItems
)
149 , m_regDiffLater(L
"Software\\TortoiseGitMerge\\DiffLater", L
"")
154 HRESULT __stdcall
CExplorerCommand::QueryInterface(REFIID refiid
, void **ppv
)
157 if (IID_IUnknown
== refiid
|| IID_IExplorerCommand
== refiid
)
162 static_cast<LPUNKNOWN
>(*ppv
)->AddRef();
165 return E_NOINTERFACE
;
168 ULONG __stdcall
CExplorerCommand::AddRef()
170 return ++m_cRefCount
;
173 ULONG __stdcall
CExplorerCommand::Release()
176 if (m_cRefCount
== 0)
184 HRESULT __stdcall
CExplorerCommand::GetTitle(IShellItemArray
* /*psiItemArray*/, LPWSTR
*ppszName
)
186 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
192 SHStrDupW(m_title
.c_str(), ppszName
);
196 HRESULT __stdcall
CExplorerCommand::GetIcon(IShellItemArray
* /*psiItemArray*/, LPWSTR
*ppszIcon
)
198 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
201 SHStrDupW(L
"", ppszIcon
);
204 std::wstring iconPath
= m_appDir
+ L
"TortoiseGitProc.exe,-";
205 iconPath
+= std::to_wstring(m_iconId
);
206 SHStrDupW(iconPath
.c_str(), ppszIcon
);
210 HRESULT __stdcall
CExplorerCommand::GetToolTip(IShellItemArray
* /*psiItemArray*/, LPWSTR
* ppszInfotip
)
212 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
213 *ppszInfotip
= nullptr;
217 HRESULT __stdcall
CExplorerCommand::GetCanonicalName(GUID
*pguidCommandName
)
219 CTraceToOutputDebugString::Instance()(__FUNCTION__
);
220 *pguidCommandName
= __uuidof(this);
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
;
233 HRESULT __stdcall
CExplorerCommand::Invoke(IShellItemArray
* /*psiItemArray*/, IBindCtx
* /*pbc*/)
235 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
236 std::wstring cwdFolder
;
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
;
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
);
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
;
267 *pFlags
= ECF_ISSEPARATOR
;
271 HRESULT __stdcall
CExplorerCommand::EnumSubCommands(IEnumExplorerCommand
**ppEnum
)
273 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
274 if (m_subItems
.empty())
276 *ppEnum
= new CExplorerCommandEnum(m_subItems
);
281 HRESULT __stdcall
CExplorerCommand::SetSite(IUnknown
* pUnkSite
)
283 CTraceToOutputDebugString::Instance()(__FUNCTION__
": title: %s\n", m_title
.c_str());
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
);