1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009,2012-2014 - 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 _T("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
, NULL
, NULL
, NULL
, NULL
);
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
, _T("WorkingCopy"), NULL
, NULL
, (LPBYTE
)szWorkingCopy
, &cbWorkingCopy
);
71 TCHAR szClsid
[MAX_PATH
] = {0};
72 DWORD cbClsid
= sizeof(szClsid
);
73 RegQueryValueEx(hk2
, _T("Provider"), NULL
, NULL
, (LPBYTE
)szClsid
, &cbClsid
);
76 CLSIDFromString(szClsid
, &provider_clsid
);
78 DWORD cbParameters
= 0;
79 RegQueryValueEx(hk2
, _T("Parameters"), NULL
, NULL
, (LPBYTE
)NULL
, &cbParameters
);
80 std::unique_ptr
<TCHAR
[]> szParameters(new TCHAR
[cbParameters
+ 1]);
81 RegQueryValueEx(hk2
, _T("Parameters"), NULL
, NULL
, (LPBYTE
)szParameters
.get(), &cbParameters
);
82 szParameters
.get()[cbParameters
] = 0;
83 m_inner
.push_back(new CBugTraqAssociation(szWorkingCopy
, provider_clsid
, LookupProviderName(provider_clsid
), szParameters
.get()));
94 providerParams
= params
;
97 void CBugTraqAssociations::Add(const CBugTraqAssociation
&assoc
)
99 m_inner
.push_back(new CBugTraqAssociation(assoc
));
102 bool CBugTraqAssociations::FindProvider(const CString
&path
, CBugTraqAssociation
*assoc
)
105 gitpath
.SetFromUnknown(path
);
107 if (FindProviderForPath(gitpath
, assoc
))
110 if (pProjectProvider
)
113 *assoc
= *pProjectProvider
;
116 if (!providerUUID
.IsEmpty())
118 CLSID provider_clsid
;
119 CLSIDFromString((LPOLESTR
)(LPCWSTR
)providerUUID
, &provider_clsid
);
120 pProjectProvider
= new CBugTraqAssociation(_T(""), provider_clsid
, _T("bugtraq:provider"), (LPCWSTR
)providerParams
);
121 if (pProjectProvider
)
124 *assoc
= *pProjectProvider
;
131 bool CBugTraqAssociations::FindProviderForPath(const CTGitPath
& path
, CBugTraqAssociation
*assoc
) const
133 inner_t::const_iterator it
= std::find_if(m_inner
.begin(), m_inner
.end(), FindByPathPred(path
));
134 if (it
!= m_inner
.end())
144 CString
CBugTraqAssociations::LookupProviderName(const CLSID
&provider_clsid
)
146 OLECHAR szClsid
[40] = { 0 };
147 StringFromGUID2(provider_clsid
, szClsid
, ARRAYSIZE(szClsid
));
149 TCHAR szSubKey
[MAX_PATH
] = {0};
150 _stprintf_s(szSubKey
, _T("CLSID\\%ls"), szClsid
);
152 CString provider_name
= CString(szClsid
);
155 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, szSubKey
, 0, KEY_READ
, &hk
) == ERROR_SUCCESS
)
157 TCHAR szClassName
[MAX_PATH
] = {0};
158 DWORD cbClassName
= sizeof(szClassName
);
160 if (RegQueryValueEx(hk
, NULL
, NULL
, NULL
, (LPBYTE
)szClassName
, &cbClassName
) == ERROR_SUCCESS
)
161 provider_name
= CString(szClassName
);
166 return provider_name
;
169 LSTATUS
RegSetValueFromCString(HKEY hKey
, LPCTSTR lpValueName
, CString str
)
172 DWORD cb
= (str
.GetLength() + 1) * sizeof(TCHAR
);
173 return RegSetValueEx(hKey
, lpValueName
, 0, REG_SZ
, (const BYTE
*)lpsz
, cb
);
176 void CBugTraqAssociations::Save() const
178 SHDeleteKey(HKEY_CURRENT_USER
, BUGTRAQ_ASSOCIATIONS_REGPATH
);
181 if (RegCreateKeyEx(HKEY_CURRENT_USER
, BUGTRAQ_ASSOCIATIONS_REGPATH
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
, &hk
, NULL
) != ERROR_SUCCESS
)
185 for (const_iterator it
= begin(); it
!= end(); ++it
)
187 TCHAR szSubKey
[MAX_PATH
] = {0};
188 _stprintf_s(szSubKey
, _T("%lu"), dwIndex
);
191 if (RegCreateKeyEx(hk
, szSubKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hk2
, NULL
) == ERROR_SUCCESS
)
193 RegSetValueFromCString(hk2
, _T("Provider"), (*it
)->GetProviderClassAsString());
194 RegSetValueFromCString(hk2
, _T("WorkingCopy"), (*it
)->GetPath().GetWinPath());
195 RegSetValueFromCString(hk2
, _T("Parameters"), (*it
)->GetParameters());
206 void CBugTraqAssociations::RemoveByPath(const CTGitPath
&path
)
208 inner_t::iterator it
= std::find_if(m_inner
.begin(), m_inner
.end(), FindByPathPred(path
));
209 if (it
!= m_inner
.end())
216 CString
CBugTraqAssociation::GetProviderClassAsString() const
218 OLECHAR szTemp
[40] = { 0 };
219 StringFromGUID2(m_provider
.clsid
, szTemp
, ARRAYSIZE(szTemp
));
221 return CString(szTemp
);
225 std::vector
<CBugTraqProvider
> CBugTraqAssociations::GetAvailableProviders()
227 std::vector
<CBugTraqProvider
> results
;
229 ICatInformation
*pCatInformation
= NULL
;
232 if (SUCCEEDED(hr
= CoCreateInstance(CLSID_StdComponentCategoriesMgr
, NULL
, CLSCTX_ALL
, IID_ICatInformation
, (void **)&pCatInformation
)))
234 IEnumGUID
*pEnum
= NULL
;
235 if (SUCCEEDED(hr
= pCatInformation
->EnumClassesOfCategories(1, &CATID_BugTraqProvider
, 0, NULL
, &pEnum
)))
243 hrEnum
= pEnum
->Next(ARRAYSIZE(clsids
), clsids
, &cClsids
);
244 if (SUCCEEDED(hrEnum
))
246 for (ULONG i
= 0; i
< cClsids
; ++i
)
248 CBugTraqProvider provider
;
249 provider
.clsid
= clsids
[i
];
250 provider
.name
= LookupProviderName(clsids
[i
]);
251 results
.push_back(provider
);
254 } while (hrEnum
== S_OK
);
263 pCatInformation
->Release();
264 pCatInformation
= NULL
;