void CBugTraqAssociations::Load(LPCTSTR uuid /* = nullptr */, LPCTSTR params /* = nullptr */)
{
	HKEY hk;
	if (RegOpenKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, KEY_READ, &hk) != ERROR_SUCCESS)
	{
		if (uuid)
			providerUUID = uuid;
		if (params)
			providerParams = params;
		return;
	}

	for (DWORD dwIndex = 0; /* nothing */; ++dwIndex)
	{
		TCHAR szSubKey[MAX_PATH] = {0};
		DWORD cchSubKey = MAX_PATH;
		LSTATUS status = RegEnumKeyEx(hk, dwIndex, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL);
		if (status != ERROR_SUCCESS)
			break;

		HKEY hk2;
		if (RegOpenKeyEx(hk, szSubKey, 0, KEY_READ, &hk2) == ERROR_SUCCESS)
		{
			TCHAR szWorkingCopy[MAX_PATH] = {0};
			DWORD cbWorkingCopy = sizeof(szWorkingCopy);
			RegQueryValueEx(hk2, _T("WorkingCopy"), NULL, NULL, (LPBYTE)szWorkingCopy, &cbWorkingCopy);

			TCHAR szClsid[MAX_PATH] = {0};
			DWORD cbClsid = sizeof(szClsid);
			RegQueryValueEx(hk2, _T("Provider"), NULL, NULL, (LPBYTE)szClsid, &cbClsid);

			CLSID provider_clsid;
			CLSIDFromString(szClsid, &provider_clsid);

			DWORD cbParameters = 0;
			RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)NULL, &cbParameters);
			std::unique_ptr<TCHAR[]> szParameters(new TCHAR[cbParameters + 1]);
			RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)szParameters.get(), &cbParameters);
			szParameters.get()[cbParameters] = 0;
			m_inner.push_back(new CBugTraqAssociation(szWorkingCopy, provider_clsid, LookupProviderName(provider_clsid), szParameters.get()));

			RegCloseKey(hk2);
		}
	}

	RegCloseKey(hk);

	if (uuid)
		providerUUID = uuid;
	if (params)
		providerParams = params;
}
/* static */
std::vector<CBugTraqProvider> CBugTraqAssociations::GetAvailableProviders()
{
	std::vector<CBugTraqProvider> results;

	ICatInformation *pCatInformation = NULL;

	HRESULT hr;
	if (SUCCEEDED(hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_ALL, IID_ICatInformation, (void **)&pCatInformation)))
	{
		IEnumGUID *pEnum = NULL;
		if (SUCCEEDED(hr = pCatInformation->EnumClassesOfCategories(1, &CATID_BugTraqProvider, 0, NULL, &pEnum)))
		{
			HRESULT hrEnum;
			do
			{
				CLSID clsids[5];
				ULONG cClsids;

				hrEnum = pEnum->Next(ARRAYSIZE(clsids), clsids, &cClsids);
				if (SUCCEEDED(hrEnum))
				{
					for (ULONG i = 0; i < cClsids; ++i)
					{
						CBugTraqProvider provider;
						provider.clsid = clsids[i];
						provider.name = LookupProviderName(clsids[i]);
						results.push_back(provider);
					}
				}
			} while (hrEnum == S_OK);
		}

		if (pEnum)
			pEnum->Release();
		pEnum = NULL;
	}

	if (pCatInformation)
		pCatInformation->Release();
	pCatInformation = NULL;

	return results;
}
void CBugTraqAssociations::Load()
{
	HKEY hk;
	if (RegOpenKeyEx(HKEY_CURRENT_USER, BUGTRAQ_ASSOCIATIONS_REGPATH, 0, KEY_READ, &hk) != ERROR_SUCCESS)
		return;

	for (DWORD dwIndex = 0; /* nothing */; ++dwIndex)
	{
		TCHAR szSubKey[MAX_PATH];
		DWORD cchSubKey = MAX_PATH;
		LSTATUS status = RegEnumKeyEx(hk, dwIndex, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL);
		if (status != ERROR_SUCCESS)
			break;

		HKEY hk2;
		if (RegOpenKeyEx(hk, szSubKey, 0, KEY_READ, &hk2) == ERROR_SUCCESS)
		{
			TCHAR szWorkingCopy[MAX_PATH];
			DWORD cbWorkingCopy = sizeof(szWorkingCopy);
			RegQueryValueEx(hk2, _T("WorkingCopy"), NULL, NULL, (LPBYTE)szWorkingCopy, &cbWorkingCopy);

			TCHAR szClsid[MAX_PATH];
			DWORD cbClsid = sizeof(szClsid);
			RegQueryValueEx(hk2, _T("Provider"), NULL, NULL, (LPBYTE)szClsid, &cbClsid);

			CLSID provider_clsid;
			CLSIDFromString(szClsid, &provider_clsid);

			DWORD cbParameters = 0;
			RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)NULL, &cbParameters);
			TCHAR * szParameters = new TCHAR[cbParameters+1];
			RegQueryValueEx(hk2, _T("Parameters"), NULL, NULL, (LPBYTE)szParameters, &cbParameters);
			szParameters[cbParameters] = 0;
			m_inner.push_back(new CBugTraqAssociation(szWorkingCopy, provider_clsid, LookupProviderName(provider_clsid), szParameters));
			delete [] szParameters;

			RegCloseKey(hk2);
		}
	}

	RegCloseKey(hk);
}