Fixed issue #1264: TortoiseProc might crash if commands are executed w/o a working...
[TortoiseGit.git] / src / Utils / BugTraqAssociations.cpp
blobfee27e0a9680196bdc787441839260b5d9870190
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008 - 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 "BugTraqAssociations.h"
22 #include <initguid.h>
24 // {3494FA92-B139-4730-9591-01135D5E7831}
25 DEFINE_GUID(CATID_BugTraqProvider,
26 0x3494fa92, 0xb139, 0x4730, 0x95, 0x91, 0x1, 0x13, 0x5d, 0x5e, 0x78, 0x31);
28 #define BUGTRAQ_ASSOCIATIONS_REGPATH _T("Software\\TortoiseGit\\BugTraq Associations")
30 CBugTraqAssociations::~CBugTraqAssociations()
32 for (inner_t::iterator it = m_inner.begin(); it != m_inner.end(); ++it)
33 delete *it;
36 void CBugTraqAssociations::Load()
38 HKEY hk;
39 if (RegOpenKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, KEY_READ, &hk) != ERROR_SUCCESS)
40 return;
42 for (DWORD dwIndex = 0; /* nothing */; ++dwIndex)
44 TCHAR szSubKey[MAX_PATH];
45 DWORD cchSubKey = MAX_PATH;
46 LSTATUS status = RegEnumKeyEx(hk, dwIndex, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL);
47 if (status != ERROR_SUCCESS)
48 break;
50 HKEY hk2;
51 if (RegOpenKeyEx(hk, szSubKey, 0, KEY_READ, &hk2) == ERROR_SUCCESS)
53 TCHAR szWorkingCopy[MAX_PATH];
54 DWORD cbWorkingCopy = sizeof(szWorkingCopy);
55 RegQueryValueEx(hk2, _T("WorkingCopy"), NULL, NULL, (LPBYTE)szWorkingCopy, &cbWorkingCopy);
57 TCHAR szClsid[MAX_PATH];
58 DWORD cbClsid = sizeof(szClsid);
59 RegQueryValueEx(hk2, _T("Provider"), NULL, NULL, (LPBYTE)szClsid, &cbClsid);
61 CLSID provider_clsid;
62 CLSIDFromString(szClsid, &provider_clsid);
64 DWORD cbParameters = 0;
65 RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)NULL, &cbParameters);
66 TCHAR * szParameters = new TCHAR[cbParameters+1];
67 RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)szParameters, &cbParameters);
68 szParameters[cbParameters] = 0;
69 m_inner.push_back(new CBugTraqAssociation(szWorkingCopy, provider_clsid, LookupProviderName(provider_clsid), szParameters));
70 delete [] szParameters;
72 RegCloseKey(hk2);
76 RegCloseKey(hk);
79 void CBugTraqAssociations::Add(const CBugTraqAssociation &assoc)
81 m_inner.push_back(new CBugTraqAssociation(assoc));
84 bool CBugTraqAssociations::FindProvider(const CTGitPathList &pathList, CBugTraqAssociation *assoc) const
86 return FindProviderForPathList(pathList, assoc);
89 bool CBugTraqAssociations::FindProvider(const CString &path, CBugTraqAssociation *assoc) const
92 CTGitPath gitpath;
93 gitpath.SetFromUnknown(path);
94 return FindProviderForPath(gitpath,assoc);
97 bool CBugTraqAssociations::FindProviderForPathList(const CTGitPathList &pathList, CBugTraqAssociation *assoc) const
99 for (int i = 0; i < pathList.GetCount(); ++i)
101 CTGitPath path = pathList[i];
102 if (FindProviderForPath(path, assoc))
103 return true;
106 return false;
109 bool CBugTraqAssociations::FindProviderForPath(CTGitPath path, CBugTraqAssociation *assoc) const
113 inner_t::const_iterator it = std::find_if(m_inner.begin(), m_inner.end(), FindByPathPred(path));
114 if (it != m_inner.end())
116 *assoc = *(*it);
117 return true;
120 path = path.GetContainingDirectory();
121 } while(!path.IsEmpty());
123 return false;
126 /* static */
127 CString CBugTraqAssociations::LookupProviderName(const CLSID &provider_clsid)
129 OLECHAR szClsid[40];
130 StringFromGUID2(provider_clsid, szClsid, ARRAYSIZE(szClsid));
132 TCHAR szSubKey[MAX_PATH];
133 _stprintf_s(szSubKey, _T("CLSID\\%ls"), szClsid);
135 CString provider_name = CString(szClsid);
137 HKEY hk;
138 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, KEY_READ, &hk) == ERROR_SUCCESS)
140 TCHAR szClassName[MAX_PATH];
141 DWORD cbClassName = sizeof(szClassName);
143 if (RegQueryValueEx(hk, NULL, NULL, NULL, (LPBYTE)szClassName, &cbClassName) == ERROR_SUCCESS)
144 provider_name = CString(szClassName);
146 RegCloseKey(hk);
149 return provider_name;
152 LSTATUS RegSetValueFromCString(HKEY hKey, LPCTSTR lpValueName, CString str)
154 LPCTSTR lpsz = str;
155 DWORD cb = (str.GetLength() + 1) * sizeof(TCHAR);
156 return RegSetValueEx(hKey, lpValueName, 0, REG_SZ, (const BYTE *)lpsz, cb);
159 void CBugTraqAssociations::Save() const
161 SHDeleteKey(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH);
163 HKEY hk;
164 if (RegCreateKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hk, NULL) != ERROR_SUCCESS)
165 return;
167 DWORD dwIndex = 0;
168 for (const_iterator it = begin(); it != end(); ++it)
170 TCHAR szSubKey[MAX_PATH];
171 _stprintf_s(szSubKey, _T("%d"), dwIndex);
173 HKEY hk2;
174 if (RegCreateKeyEx(hk, szSubKey, 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL) == ERROR_SUCCESS)
176 RegSetValueFromCString(hk2, _T("Provider"), (*it)->GetProviderClassAsString());
177 RegSetValueFromCString(hk2, _T("WorkingCopy"), (*it)->GetPath().GetWinPath());
178 RegSetValueFromCString(hk2, _T("Parameters"), (*it)->GetParameters());
180 RegCloseKey(hk2);
183 ++dwIndex;
186 RegCloseKey(hk);
189 void CBugTraqAssociations::RemoveByPath(const CTGitPath &path)
191 inner_t::iterator it = std::find_if(m_inner.begin(), m_inner.end(), FindByPathPred(path));
192 if (it != m_inner.end())
194 delete *it;
195 m_inner.erase(it);
199 CString CBugTraqAssociation::GetProviderClassAsString() const
201 OLECHAR szTemp[40];
202 StringFromGUID2(m_provider.clsid, szTemp, ARRAYSIZE(szTemp));
204 return CString(szTemp);
207 /* static */
208 std::vector<CBugTraqProvider> CBugTraqAssociations::GetAvailableProviders()
210 std::vector<CBugTraqProvider> results;
212 ICatInformation *pCatInformation = NULL;
214 HRESULT hr;
215 if (SUCCEEDED(hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_ALL, IID_ICatInformation, (void **)&pCatInformation)))
217 IEnumGUID *pEnum = NULL;
218 if (SUCCEEDED(hr = pCatInformation->EnumClassesOfCategories(1, &CATID_BugTraqProvider, 0, NULL, &pEnum)))
220 HRESULT hrEnum;
223 CLSID clsids[5];
224 ULONG cClsids;
226 hrEnum = pEnum->Next(ARRAYSIZE(clsids), clsids, &cClsids);
227 if (SUCCEEDED(hrEnum))
229 for (ULONG i = 0; i < cClsids; ++i)
231 CBugTraqProvider provider;
232 provider.clsid = clsids[i];
233 provider.name = LookupProviderName(clsids[i]);
234 results.push_back(provider);
237 } while (hrEnum == S_OK);
240 if (pEnum)
241 pEnum->Release();
242 pEnum = NULL;
245 if (pCatInformation)
246 pCatInformation->Release();
247 pCatInformation = NULL;
249 return results;