1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009, 2012-2016 - TortoiseGit
4 // Copyright (C) 2008,2014 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "BugTraqAssociations.h"
25 // {3494FA92-B139-4730-9591-01135D5E7831}
26 DEFINE_GUID(CATID_BugTraqProvider
,
27 0x3494fa92, 0xb139, 0x4730, 0x95, 0x91, 0x1, 0x13, 0x5d, 0x5e, 0x78, 0x31);
29 #define BUGTRAQ_ASSOCIATIONS_REGPATH L"Software\\TortoiseGit\\BugTraq Associations"
31 CBugTraqAssociations::CBugTraqAssociations()
32 : pProjectProvider(nullptr)
36 CBugTraqAssociations::~CBugTraqAssociations()
38 for (inner_t::iterator it
= m_inner
.begin(); it
!= m_inner
.end(); ++it
)
41 delete pProjectProvider
;
44 void CBugTraqAssociations::Load(LPCTSTR uuid
/* = nullptr */, LPCTSTR params
/* = nullptr */)
47 if (RegOpenKeyEx(HKEY_CURRENT_USER
, BUGTRAQ_ASSOCIATIONS_REGPATH
, 0, KEY_READ
, &hk
) != ERROR_SUCCESS
)
52 providerParams
= params
;
56 for (DWORD dwIndex
= 0; /* nothing */; ++dwIndex
)
58 TCHAR szSubKey
[MAX_PATH
] = {0};
59 DWORD cchSubKey
= MAX_PATH
;
60 LSTATUS status
= RegEnumKeyEx(hk
, dwIndex
, szSubKey
, &cchSubKey
, nullptr, nullptr, nullptr, nullptr);
61 if (status
!= ERROR_SUCCESS
)
65 if (RegOpenKeyEx(hk
, szSubKey
, 0, KEY_READ
, &hk2
) == ERROR_SUCCESS
)
67 TCHAR szWorkingCopy
[MAX_PATH
] = {0};
68 DWORD cbWorkingCopy
= sizeof(szWorkingCopy
);
69 RegQueryValueEx(hk2
, L
"WorkingCopy", nullptr, nullptr, (LPBYTE
)szWorkingCopy
, &cbWorkingCopy
);
71 TCHAR szClsid
[MAX_PATH
] = {0};
72 DWORD cbClsid
= sizeof(szClsid
);
73 RegQueryValueEx(hk2
, L
"Provider", nullptr, nullptr, (LPBYTE
)szClsid
, &cbClsid
);
76 CLSIDFromString(szClsid
, &provider_clsid
);
78 DWORD cbParameters
= 0;
79 RegQueryValueEx(hk2
, L
"Parameters", nullptr, nullptr, nullptr, &cbParameters
);
80 auto szParameters
= std::make_unique
<TCHAR
[]>(cbParameters
+ 1);
81 RegQueryValueEx(hk2
, L
"Parameters", nullptr, nullptr, (LPBYTE
)szParameters
.get(), &cbParameters
);
82 szParameters
.get()[cbParameters
] = 0;
85 DWORD size
= sizeof(enabled
);
86 RegQueryValueEx(hk2
, L
"Enabled", nullptr, nullptr, (BYTE
*)&enabled
, &size
);
88 m_inner
.push_back(new CBugTraqAssociation(szWorkingCopy
, provider_clsid
, LookupProviderName(provider_clsid
), szParameters
.get(), enabled
!= FALSE
));
99 providerParams
= params
;
102 void CBugTraqAssociations::Add(const CBugTraqAssociation
&assoc
)
104 m_inner
.push_back(new CBugTraqAssociation(assoc
));
107 bool CBugTraqAssociations::FindProvider(const CString
&path
, CBugTraqAssociation
*assoc
)
110 gitpath
.SetFromUnknown(path
);
112 if (FindProviderForPath(gitpath
, assoc
))
115 if (pProjectProvider
)
118 *assoc
= *pProjectProvider
;
121 if (!providerUUID
.IsEmpty())
123 CLSID provider_clsid
;
124 CLSIDFromString((LPOLESTR
)(LPCWSTR
)providerUUID
, &provider_clsid
);
125 pProjectProvider
= new CBugTraqAssociation(L
"", provider_clsid
, L
"bugtraq:provider", (LPCWSTR
)providerParams
, true);
126 if (pProjectProvider
)
129 *assoc
= *pProjectProvider
;
136 bool CBugTraqAssociations::FindProviderForPath(const CTGitPath
& path
, CBugTraqAssociation
*assoc
) const
138 const auto it
= std::find_if(m_inner
.cbegin(), m_inner
.cend(), [&path
](const CBugTraqAssociation
* assoc
) { return assoc
->IsEnabled() && assoc
->GetPath().IsEquivalentToWithoutCase(path
); });
139 if (it
!= m_inner
.end())
149 CString
CBugTraqAssociations::LookupProviderName(const CLSID
&provider_clsid
)
151 OLECHAR szClsid
[40] = { 0 };
152 StringFromGUID2(provider_clsid
, szClsid
, ARRAYSIZE(szClsid
));
154 TCHAR szSubKey
[MAX_PATH
] = {0};
155 swprintf_s(szSubKey
, L
"CLSID\\%ls", szClsid
);
157 CString provider_name
= CString(szClsid
);
160 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, szSubKey
, 0, KEY_READ
, &hk
) == ERROR_SUCCESS
)
162 TCHAR szClassName
[MAX_PATH
] = {0};
163 DWORD cbClassName
= sizeof(szClassName
);
165 if (RegQueryValueEx(hk
, nullptr, nullptr, nullptr, (LPBYTE
)szClassName
, &cbClassName
) == ERROR_SUCCESS
)
166 provider_name
= CString(szClassName
);
171 return provider_name
;
174 LSTATUS
RegSetValueFromCString(HKEY hKey
, LPCTSTR lpValueName
, CString str
)
177 DWORD cb
= (str
.GetLength() + 1) * sizeof(TCHAR
);
178 return RegSetValueEx(hKey
, lpValueName
, 0, REG_SZ
, (const BYTE
*)lpsz
, cb
);
181 void CBugTraqAssociations::Save() const
183 SHDeleteKey(HKEY_CURRENT_USER
, BUGTRAQ_ASSOCIATIONS_REGPATH
);
186 if (RegCreateKeyEx(HKEY_CURRENT_USER
, BUGTRAQ_ASSOCIATIONS_REGPATH
, 0, nullptr, 0, KEY_READ
| KEY_WRITE
, nullptr, &hk
, nullptr) != ERROR_SUCCESS
)
190 for (const_iterator it
= begin(); it
!= end(); ++it
)
192 TCHAR szSubKey
[MAX_PATH
] = {0};
193 swprintf_s(szSubKey
, L
"%lu", dwIndex
);
196 if (RegCreateKeyEx(hk
, szSubKey
, 0, nullptr, 0, KEY_WRITE
, nullptr, &hk2
, nullptr) == ERROR_SUCCESS
)
198 RegSetValueFromCString(hk2
, L
"Provider", (*it
)->GetProviderClassAsString());
199 RegSetValueFromCString(hk2
, L
"WorkingCopy", (*it
)->GetPath().GetWinPath());
200 RegSetValueFromCString(hk2
, L
"Parameters", (*it
)->GetParameters());
201 DWORD enabled
= (*it
)->IsEnabled() ? 1 : 0;
202 RegSetValueEx(hk2
, L
"Enabled", 0, REG_DWORD
, (BYTE
*)&enabled
, sizeof(enabled
));
213 void CBugTraqAssociations::Remove(CBugTraqAssociation
* assoc
)
215 inner_t::iterator it
= std::find(m_inner
.begin(), m_inner
.end(), assoc
);
216 if (it
!= m_inner
.end())
223 CString
CBugTraqAssociation::GetProviderClassAsString() const
225 OLECHAR szTemp
[40] = { 0 };
226 StringFromGUID2(m_provider
.clsid
, szTemp
, ARRAYSIZE(szTemp
));
228 return CString(szTemp
);
232 std::vector
<CBugTraqProvider
> CBugTraqAssociations::GetAvailableProviders()
234 std::vector
<CBugTraqProvider
> results
;
236 ICatInformation
* pCatInformation
= nullptr;
239 if (SUCCEEDED(hr
= CoCreateInstance(CLSID_StdComponentCategoriesMgr
, nullptr, CLSCTX_ALL
, IID_ICatInformation
, (void**)&pCatInformation
)))
241 IEnumGUID
* pEnum
= nullptr;
242 if (SUCCEEDED(hr
= pCatInformation
->EnumClassesOfCategories(1, &CATID_BugTraqProvider
, 0, nullptr, &pEnum
)))
250 hrEnum
= pEnum
->Next(ARRAYSIZE(clsids
), clsids
, &cClsids
);
251 if (SUCCEEDED(hrEnum
))
253 for (ULONG i
= 0; i
< cClsids
; ++i
)
255 CBugTraqProvider provider
;
256 provider
.clsid
= clsids
[i
];
257 provider
.name
= LookupProviderName(clsids
[i
]);
258 results
.push_back(provider
);
261 } while (hrEnum
== S_OK
);
270 pCatInformation
->Release();
271 pCatInformation
= nullptr;