162 lines
6.8 KiB
C++
162 lines
6.8 KiB
C++
#include "stdafx.h"
|
|
|
|
#pragma comment(lib, "crypt32.lib")
|
|
|
|
|
|
namespace MSICA {
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// COpCertStore
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
COpCertStore::COpCertStore(LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) :
|
|
COpTypeSingleString(pszStore, iTicks),
|
|
m_dwEncodingType(dwEncodingType),
|
|
m_dwFlags(dwFlags)
|
|
{
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// COpCert
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
COpCert::COpCert(LPCVOID lpCert, SIZE_T nSize, LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) :
|
|
COpCertStore(pszStore, dwEncodingType, dwFlags, iTicks)
|
|
{
|
|
m_binCert.SetCount(nSize);
|
|
memcpy(m_binCert.GetData(), lpCert, nSize);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// COpCertInstall
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
COpCertInstall::COpCertInstall(LPCVOID lpCert, SIZE_T nSize, LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) : COpCert(lpCert, nSize, pszStore, dwEncodingType, dwFlags, iTicks)
|
|
{
|
|
}
|
|
|
|
|
|
HRESULT COpCertInstall::Execute(CSession *pSession)
|
|
{
|
|
DWORD dwError;
|
|
HCERTSTORE hCertStore;
|
|
|
|
// Open certificate store.
|
|
hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue);
|
|
if (hCertStore) {
|
|
// Create certificate context.
|
|
PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.GetData(), (DWORD)(m_binCert.GetCount()));
|
|
if (pCertContext) {
|
|
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
|
|
ATL::CAtlStringW sCertName;
|
|
|
|
// Display our custom message in the progress bar.
|
|
::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName);
|
|
::MsiRecordSetStringW(hRecordMsg, 1, sCertName);
|
|
if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL)
|
|
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
|
|
|
|
// Add certificate to certificate store.
|
|
if (::CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_NEW, NULL)) {
|
|
if (pSession->m_bRollbackEnabled) {
|
|
// Order rollback action to delete the certificate.
|
|
pSession->m_olRollback.AddHead(new COpCertRemove(m_binCert.GetData(), m_binCert.GetCount(), m_sValue, m_dwEncodingType, m_dwFlags));
|
|
}
|
|
dwError = NO_ERROR;
|
|
} else {
|
|
dwError = ::GetLastError();
|
|
if (dwError == CRYPT_E_EXISTS) {
|
|
// Certificate store already contains given certificate. Nothing to install then.
|
|
dwError = NO_ERROR;
|
|
}
|
|
}
|
|
::CertFreeCertificateContext(pCertContext);
|
|
} else
|
|
dwError = ::GetLastError();
|
|
::CertCloseStore(hCertStore, 0);
|
|
} else
|
|
dwError = ::GetLastError();
|
|
|
|
if (dwError == NO_ERROR)
|
|
return S_OK;
|
|
else {
|
|
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
|
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_INSTALL_FAILED);
|
|
::MsiRecordSetStringW(hRecordProg, 2, m_sValue );
|
|
::MsiRecordSetInteger(hRecordProg, 3, dwError );
|
|
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
return AtlHresultFromWin32(dwError);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// COpCertRemove
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
COpCertRemove::COpCertRemove(LPCVOID lpCert, SIZE_T nSize, LPCWSTR pszStore, DWORD dwEncodingType, DWORD dwFlags, int iTicks) : COpCert(lpCert, nSize, pszStore, dwEncodingType, dwFlags, iTicks)
|
|
{
|
|
}
|
|
|
|
|
|
HRESULT COpCertRemove::Execute(CSession *pSession)
|
|
{
|
|
DWORD dwError;
|
|
HCERTSTORE hCertStore;
|
|
|
|
// Open certificate store.
|
|
hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_W, m_dwEncodingType, NULL, m_dwFlags, m_sValue);
|
|
if (hCertStore) {
|
|
// Create certificate context.
|
|
PCCERT_CONTEXT pCertContext = ::CertCreateCertificateContext(m_dwEncodingType, m_binCert.GetData(), (DWORD)(m_binCert.GetCount()));
|
|
if (pCertContext) {
|
|
PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1);
|
|
ATL::CAtlStringW sCertName;
|
|
PCCERT_CONTEXT pCertContextExisting;
|
|
|
|
// Display our custom message in the progress bar.
|
|
::CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, sCertName);
|
|
::MsiRecordSetStringW(hRecordMsg, 1, sCertName);
|
|
if (MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ACTIONDATA, hRecordMsg) == IDCANCEL)
|
|
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
|
|
|
|
pCertContextExisting = ::CertFindCertificateInStore(hCertStore, m_dwEncodingType, 0, CERT_FIND_EXISTING, pCertContext, NULL);
|
|
if (pCertContextExisting) {
|
|
// Delete certificate from certificate store.
|
|
if (::CertDeleteCertificateFromStore(pCertContextExisting)) {
|
|
if (pSession->m_bRollbackEnabled) {
|
|
// Order rollback action to reinstall the certificate.
|
|
pSession->m_olRollback.AddHead(new COpCertInstall(m_binCert.GetData(), m_binCert.GetCount(), m_sValue, m_dwEncodingType, m_dwFlags));
|
|
}
|
|
dwError = NO_ERROR;
|
|
} else {
|
|
dwError = ::GetLastError();
|
|
::CertFreeCertificateContext(pCertContextExisting);
|
|
}
|
|
} else {
|
|
// We haven't found the certificate. Nothing to delete then.
|
|
dwError = NO_ERROR;
|
|
}
|
|
::CertFreeCertificateContext(pCertContext);
|
|
} else
|
|
dwError = ::GetLastError();
|
|
::CertCloseStore(hCertStore, 0);
|
|
} else
|
|
dwError = ::GetLastError();
|
|
|
|
if (dwError == NO_ERROR)
|
|
return S_OK;
|
|
else {
|
|
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
|
|
::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_CERT_REMOVE_FAILED);
|
|
::MsiRecordSetStringW(hRecordProg, 2, m_sValue );
|
|
::MsiRecordSetInteger(hRecordProg, 3, dwError );
|
|
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
|
|
return AtlHresultFromWin32(dwError);
|
|
}
|
|
}
|
|
|
|
} // namespace MSICA
|