Fixed issue #3307: Abort Merge on a single file always results in a parameter error...
[TortoiseGit.git] / src / Utils / JumpListHelpers.cpp
blob9ac0bac749a4dd61a7c71942021b7cace1220d3a
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009-2013 - 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 "SmartHandle.h"
21 #include "JumpListHelpers.h"
22 #include "propvarutil.h"
23 #include "propsys.h"
24 #include <propkey.h>
26 HRESULT SetAppID(LPCTSTR appID)
28 HRESULT hRes = S_FALSE;
29 typedef HRESULT STDAPICALLTYPE SetCurrentProcessExplicitAppUserModelIDFN(PCWSTR AppID);
30 CAutoLibrary hShell = AtlLoadSystemLibraryUsingFullPath(L"shell32.dll");
31 if (hShell)
33 SetCurrentProcessExplicitAppUserModelIDFN *pfnSetCurrentProcessExplicitAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDFN*)GetProcAddress(hShell, "SetCurrentProcessExplicitAppUserModelID");
34 if (pfnSetCurrentProcessExplicitAppUserModelID)
35 hRes = pfnSetCurrentProcessExplicitAppUserModelID(appID);
37 return hRes;
40 HRESULT CreateShellLink(PCWSTR pszArguments, PCWSTR pszTitle, int iconIndex, IShellLink **ppsl)
42 ATL::CComPtr<IShellLink> psl;
43 HRESULT hr = psl.CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER);
44 if (FAILED(hr))
45 return hr;
47 WCHAR szAppPath[MAX_PATH] = {0};
48 if (GetModuleFileName(nullptr, szAppPath, ARRAYSIZE(szAppPath)) == 0)
50 hr = HRESULT_FROM_WIN32(GetLastError());
51 return hr;
53 hr = psl->SetPath(szAppPath);
54 if (FAILED(hr))
55 return hr;
57 hr = psl->SetArguments(pszArguments);
58 if (FAILED(hr))
59 return hr;
61 hr = psl->SetIconLocation(szAppPath, iconIndex);
62 if (FAILED(hr))
63 return hr;
65 ATL::CComPtr<IPropertyStore> pps;
66 hr = psl.QueryInterface(&pps);
67 if (FAILED(hr))
68 return hr;
70 PROPVARIANT propvar;
71 hr = InitPropVariantFromString(pszTitle, &propvar);
72 if (SUCCEEDED(hr))
74 hr = pps->SetValue(PKEY_Title, propvar);
75 if (SUCCEEDED(hr)) {
76 hr = pps->Commit();
77 if (SUCCEEDED(hr)) {
78 hr = psl.QueryInterface(ppsl);
81 PropVariantClear(&propvar);
83 return hr;
86 HRESULT CreateSeparatorLink(IShellLink **ppsl)
88 ATL::CComPtr<IPropertyStore> pps;
89 HRESULT hr = pps.CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER);
90 if (FAILED(hr))
91 return hr;
93 PROPVARIANT propvar;
94 hr = InitPropVariantFromBoolean(TRUE, &propvar);
95 if (FAILED(hr))
96 return hr;
98 hr = pps->SetValue(PKEY_AppUserModel_IsDestListSeparator, propvar);
99 if (SUCCEEDED(hr)) {
100 hr = pps->Commit();
101 if (SUCCEEDED(hr))
103 hr = pps.QueryInterface(ppsl);
106 PropVariantClear(&propvar);
107 return hr;
110 bool IsItemInArray(IShellItem *psi, IObjectArray *poaRemoved)
112 UINT cItems;
113 if (FAILED(poaRemoved->GetCount(&cItems)))
114 return false;
116 bool fRet = false;
117 for (UINT i = 0; !fRet && i < cItems; i++) {
118 ATL::CComPtr<IShellItem> psiCompare;
119 if (FAILED(poaRemoved->GetAt(i, IID_PPV_ARGS(&psiCompare))))
120 continue;
121 int iOrder;
122 fRet = SUCCEEDED(psiCompare->Compare(psi, SICHINT_CANONICAL, &iOrder)) && (0 == iOrder);
124 return fRet;
127 void DeleteJumpList(LPCTSTR appID)
129 ATL::CComPtr<ICustomDestinationList> pcdl;
130 HRESULT hr = pcdl.CoCreateInstance(CLSID_DestinationList, nullptr, CLSCTX_INPROC_SERVER);
131 if (SUCCEEDED(hr)) {
132 pcdl->DeleteList(appID);