Adjust TortoisePot.vcxproj and update Tortoise.pot
[TortoiseGit.git] / src / Utils / BugTraqAssociations.cpp
blob505aa59b172b9ad92f9b420ded2b9a38db73391f
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.
20 #include "stdafx.h"
21 #include "BugTraqAssociations.h"
22 #include <memory>
23 #include <initguid.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)
39 delete *it;
40 if (pProjectProvider)
41 delete pProjectProvider;
44 void CBugTraqAssociations::Load(LPCTSTR uuid /* = nullptr */, LPCTSTR params /* = nullptr */)
46 HKEY hk;
47 if (RegOpenKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, KEY_READ, &hk) != ERROR_SUCCESS)
49 if (uuid)
50 providerUUID = uuid;
51 if (params)
52 providerParams = params;
53 return;
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)
62 break;
64 HKEY hk2;
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);
75 CLSID provider_clsid;
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[cbParameters] = 0;
84 DWORD enabled = TRUE;
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));
90 RegCloseKey(hk2);
94 RegCloseKey(hk);
96 if (uuid)
97 providerUUID = uuid;
98 if (params)
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)
109 CTGitPath gitpath;
110 gitpath.SetFromUnknown(path);
112 if (FindProviderForPath(gitpath, assoc))
113 return true;
115 if (pProjectProvider)
117 if (assoc)
118 *assoc = *pProjectProvider;
119 return true;
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)
128 if (assoc)
129 *assoc = *pProjectProvider;
130 return true;
133 return false;
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())
141 *assoc = *(*it);
142 return true;
145 return false;
148 /* static */
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);
159 HKEY hk;
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);
168 RegCloseKey(hk);
171 return provider_name;
174 LSTATUS RegSetValueFromCString(HKEY hKey, LPCTSTR lpValueName, CString str)
176 LPCTSTR lpsz = 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);
185 HKEY hk;
186 if (RegCreateKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, nullptr, 0, KEY_READ | KEY_WRITE, nullptr, &hk, nullptr) != ERROR_SUCCESS)
187 return;
189 DWORD dwIndex = 0;
190 for (const_iterator it = begin(); it != end(); ++it)
192 TCHAR szSubKey[MAX_PATH] = {0};
193 swprintf_s(szSubKey, L"%lu", dwIndex);
195 HKEY hk2;
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));
204 RegCloseKey(hk2);
207 ++dwIndex;
210 RegCloseKey(hk);
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())
218 delete *it;
219 m_inner.erase(it);
223 CString CBugTraqAssociation::GetProviderClassAsString() const
225 OLECHAR szTemp[40] = { 0 };
226 StringFromGUID2(m_provider.clsid, szTemp, ARRAYSIZE(szTemp));
228 return CString(szTemp);
231 /* static */
232 std::vector<CBugTraqProvider> CBugTraqAssociations::GetAvailableProviders()
234 std::vector<CBugTraqProvider> results;
236 ICatInformation* pCatInformation = nullptr;
238 HRESULT hr;
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)))
244 HRESULT hrEnum;
247 CLSID clsids[5];
248 ULONG cClsids;
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);
264 if (pEnum)
265 pEnum->Release();
266 pEnum = nullptr;
269 if (pCatInformation)
270 pCatInformation->Release();
271 pCatInformation = nullptr;
273 return results;