#include "stdafx.h"
#include "ZdActivex.h"
#include "ZdActivexCtrl.h"
#include "ZdActivexPropPage.h"
#include "afxdialogex.h"
#include
#include
#include
#define MAXSIZE 4096
#pragma comment(lib, "Wininet.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//CSP
#include
#pragma comment(lib,"crypt32.lib")
#define MALLOC(l) (BYTE*)malloc(l)
IMPLEMENT_DYNCREATE(CZdActivexCtrl, COleControl)
// 消息映射
BEGIN_MESSAGE_MAP(CZdActivexCtrl, COleControl)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
// 调度映射
BEGIN_DISPATCH_MAP(CZdActivexCtrl, COleControl)
DISP_FUNCTION_ID(CZdActivexCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(CZdActivexCtrl, "ImportPFX", dispidImportPFX, ImportPFX, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
DISP_FUNCTION_ID(CZdActivexCtrl, "DownLoadToLocal", dispidDownLoadToLocal, DownLoadToLocal, VT_I4, VTS_BSTR VTS_BSTR)
DISP_FUNCTION_ID(CZdActivexCtrl, "ImportExchangePFX", dispidImportExchangePFX, ImportExchangePFX, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
DISP_FUNCTION_ID(CZdActivexCtrl, "EnumCspProvider", dispidEnumCspProvider, EnumCspProvider, VT_BSTR, VTS_NONE)
END_DISPATCH_MAP()
// 事件映射
BEGIN_EVENT_MAP(CZdActivexCtrl, COleControl)
END_EVENT_MAP()
// 属性页
// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CZdActivexCtrl, 1)
PROPPAGEID(CZdActivexPropPage::guid)
END_PROPPAGEIDS(CZdActivexCtrl)
// 初始化类工厂和 guid
IMPLEMENT_OLECREATE_EX(CZdActivexCtrl, "ZDACTIVEX.ZdActivexCtrl.1",
0x5f0ece95, 0x9bbb, 0x4f87, 0xb2, 0xc6, 0x2d, 0x7e, 0xb0, 0xf0, 0xf4, 0x54)
// 键入库 ID 和版本
IMPLEMENT_OLETYPELIB(CZdActivexCtrl, _tlid, _wVerMajor, _wVerMinor)
// 接口 ID
const IID IID_DZdActivex = { 0xA8294AA6, 0x8C40, 0x4029, { 0xB9, 0x5E, 0xAB, 0x71, 0xFC, 0xC, 0xB7, 0xEF } };
const IID IID_DZdActivexEvents = { 0x47A58B2B, 0xCDD8, 0x4BF9, { 0xBB, 0xE3, 0x13, 0xDB, 0x32, 0xB8, 0x5E, 0x6A } };
// 控件类型信息
static const DWORD _dwZdActivexOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CZdActivexCtrl, IDS_ZDACTIVEX, _dwZdActivexOleMisc)
// CZdActivexCtrl::CZdActivexCtrlFactory::UpdateRegistry -
// 添加或移除 CZdActivexCtrl 的系统注册表项
BOOL CZdActivexCtrl::CZdActivexCtrlFactory::UpdateRegistry(BOOL bRegister){
// TODO: 验证您的控件是否符合单元模型线程处理规则。
// 有关更多信息,请参考 MFC 技术说明 64。
// 如果您的控件不符合单元模型规则,则
// 必须修改如下代码,将第六个参数从
// afxRegApartmentThreading 改为 0。
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_ZDACTIVEX,
IDB_ZDACTIVEX,
afxRegApartmentThreading,
_dwZdActivexOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
// CZdActivexCtrl::CZdActivexCtrl - 构造函数
CZdActivexCtrl::CZdActivexCtrl()
{
InitializeIIDs(&IID_DZdActivex, &IID_DZdActivexEvents);
// TODO: 在此初始化控件的实例数据。
}
// CZdActivexCtrl::~CZdActivexCtrl - 析构函数
CZdActivexCtrl::~CZdActivexCtrl()
{
// TODO: 在此清理控件的实例数据。
}
// CZdActivexCtrl::OnDraw - 绘图函数
void CZdActivexCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid){
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
}
// CZdActivexCtrl::DoPropExchange - 持久性支持
void CZdActivexCtrl::DoPropExchange(CPropExchange* pPX){
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: 为每个持久的自定义属性调用 PX_ 函数。
}
// CZdActivexCtrl::OnResetState - 将控件重置为默认状态
void CZdActivexCtrl::OnResetState()
{
COleControl::OnResetState(); // 重置 DoPropExchange 中找到的默认值
// TODO: 在此重置任意其他控件状态。
}
// CZdActivexCtrl::AboutBox - 向用户显示“关于”框
void CZdActivexCtrl::AboutBox(){
CDialogEx dlgAbout(IDD_ABOUTBOX_ZDACTIVEX);
dlgAbout.DoModal();
}
// CZdActivexCtrl 消息处理程序
/*
导入pfx——》签名密钥
* @param CSP_NAME: CSP Provider 标识
* @param FILEDIR: 本地pfx文件路径
* @param PFX_PASS: pfx文件密码
* @param CONTAINERNAME: 导入容器名称
*/
void CZdActivexCtrl::ImportPFX(LPCTSTR CSP_NAME,LPCTSTR FILEDIR,LPCTSTR PWD,LPCTSTR CONTAINERNAME){
//使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
int keyType = 0;
//文件操作句柄
HANDLE hFile = NULL;
hFile = CreateFile(FILEDIR,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hFile == INVALID_HANDLE_VALUE){
::AfxMessageBox(_T("获取用户证书 出错!"));
return;
}
//分配内存
DWORD dwSize = ::GetFileSize(hFile, NULL);
BYTE *pP12 = NULL;
if (!(pP12 = new BYTE[dwSize]))
{
::CloseHandle(hFile);
::AfxMessageBox(_T("构建用户证书 出错!"));
return;
}
//读取证书内容
DWORD dwRead = 0;
if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL)){
::CloseHandle(hFile);
::AfxMessageBox(_T("读取用户证书 出错!"));
return;
}
//关闭文件
::CloseHandle(hFile);
//生成结构体
CRYPT_DATA_BLOB CDB;
CDB.cbData = dwSize;
CDB.pbData = pP12;
//转换密码格式
USES_CONVERSION;
LPCWSTR PW = T2CW(PWD);
//将证书导入临时证书库
HCERTSTORE hStore = NULL;
if (!(hStore = PFXImportCertStore(&CDB, PW, CRYPT_EXPORTABLE))){
if (!hStore)
hStore = PFXImportCertStore(&CDB, L"", CRYPT_EXPORTABLE);
if (!hStore)
hStore = PFXImportCertStore(&CDB, NULL, CRYPT_EXPORTABLE);
}
if(!hStore){
delete pP12; pP12 = NULL;
::AfxMessageBox(_T("将用户证书导入临时证书库 出错!"));
return;
}
delete pP12; pP12 = NULL;
//枚举临时证书库中导入的证书
PCCERT_CONTEXT pCertContext = NULL;
HCRYPTPROV hCertProv = NULL;
HCRYPTKEY hKey = NULL;
BYTE *pPK = NULL;
HCRYPTKEY hPrvKey = NULL;
HCRYPTPROV hProv = NULL;
while (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext)){
//对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)
if (!CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
&pCertContext->pCertInfo->Issuer,
&pCertContext->pCertInfo->Subject))
{
//获取私钥临时 CSP 句柄
DWORD dwKeySpec = 0;
if (!CryptAcquireCertificatePrivateKey(pCertContext,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hCertProv,
&dwKeySpec,
NULL)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取私钥临时 CSP 句柄 出错!"));
goto cleanup;
}
//获取密钥对,前者加密,后者签名,自签名的hPubKey一定是AT_SIGNATURE
if (!CryptGetUserKey(hCertProv, ((keyType == 0) ? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey)) {
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取密钥对 出错!"));
goto cleanup;
}
//获取私钥长度
DWORD dwPKSize = 0;
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取私钥大小 出错!"));
goto cleanup;
}
//分配内存
if (!(pPK = new BYTE[dwPKSize])){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("构建用户证书结构体 出错!"));
goto cleanup;
}
//导出私钥
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("导出私钥 出错!"));
goto cleanup;
}
/*Algid
[in] An value that identifies the algorithm for which the key is to be generated. 该参数的值将根据CSP的作用而不同。 ALG_ID 表明产生私钥所使用的算法。有如下参数:
微软提供的基本算法
CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1,CALG_MAC,CALG_HMAC,CALG_SSL3_SHAMD5, CALG_MD2,CALG_MD2
CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES
微软提供的增强型算法:
CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1
CALG_MAC,CALG_HMAC ,CALG_SSL3_SHAMD5,CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2, CALG_RC4,CALG_DES,CALG_3DES_112,CALG_3DES
使用DH的CSP有如下两个参数,CALG_DH_EPHEM,CALG_DH_SF
使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
*/
PUBLICKEYSTRUC* p = (PUBLICKEYSTRUC*)pPK;
p->aiKeyAlg = CALG_RSA_SIGN;
//获取 UKEY 的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, 0)) {
//构建新容器的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
//创建密钥容器成功,并得到CSP句柄
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("构建新容器 出错!"));
goto cleanup;
}else{
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
goto cleanup;
}else{
//将证书导入到密钥容器
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
goto cleanup;
}
::AfxMessageBox(_T("用户证书 导入成功 !"));
}
}
}else{
::AfxMessageBox("是否将用户证书导入已存在容器,该操作会删除现有容器证书?",MB_YESNO|MB_ICONQUESTION);
int a = MessageBox( "是否确认导入现有容器?" , "警告!该操作会删除现有容器证书!",MB_YESNO|MB_ICONWARNING);
if (a == IDYES){
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_DELETEKEYSET)){
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("删除现有容器 出错!"));
goto cleanup;
}else{
//构建新容器的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
//创建密钥容器成功,并得到CSP句柄
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("构建新容器 出错!"));
goto cleanup;
}else{
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
goto cleanup;
}else{
//将证书导入到密钥容器
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
goto cleanup;
}
::AfxMessageBox(_T("用户证书 导入成功 !"));
}
}
}
}else{
::AfxMessageBox(_T("用户证书未成功导入,容器中已包含其它用户证书 !"));
}
}
}
}
goto cleanup;
cleanup:
//销毁私钥句柄
CryptDestroyKey(hPrvKey);
//关闭硬件加密设备CSP操作句柄
CryptReleaseContext(hProv, 0);
//释放私钥内存
delete pPK; pPK = NULL;
//销毁密钥对句柄
CryptDestroyKey(hKey);
//释放证书句柄
CertFreeCertificateContext(pCertContext);
//关闭临时证书库
CertCloseStore(hStore, 0);
//删除临时用户证书文件
DeleteFile(FILEDIR);
}
/*
导入pfx——》交换密钥
* @param CSP_NAME: CSP Provider 标识
* @param FILEDIR: 本地pfx文件路径
* @param PFX_PASS: pfx文件密码
* @param CONTAINERNAME: 导入容器名称
*/
void CZdActivexCtrl::ImportExchangePFX(LPCTSTR CSP_NAME,LPCTSTR FILEDIR,LPCTSTR PWD,LPCTSTR CONTAINERNAME){
//使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
int keyType = 0;
//文件操作句柄
HANDLE hFile = NULL;
hFile = CreateFile(FILEDIR,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hFile == INVALID_HANDLE_VALUE){
::AfxMessageBox(_T("获取用户证书 出错!"));
return;
}
//分配内存
DWORD dwSize = ::GetFileSize(hFile, NULL);
BYTE *pP12 = NULL;
if (!(pP12 = new BYTE[dwSize])){
::CloseHandle(hFile);
::AfxMessageBox(_T("构建用户证书 出错!"));
return;
}
//读取证书内容
DWORD dwRead = 0;
if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL)){
::CloseHandle(hFile);
::AfxMessageBox(_T("读取用户证书 出错!"));
return;
}
//关闭文件
::CloseHandle(hFile);
//生成结构体
CRYPT_DATA_BLOB CDB;
CDB.cbData = dwSize;
CDB.pbData = pP12;
//转换密码格式
USES_CONVERSION;
LPCWSTR PW = T2CW(PWD);
//将证书导入临时证书库
HCERTSTORE hStore = NULL;
if (!(hStore = PFXImportCertStore(&CDB, PW, CRYPT_EXPORTABLE))){
if (!hStore)
hStore = PFXImportCertStore(&CDB, L"", CRYPT_EXPORTABLE);
if (!hStore)
hStore = PFXImportCertStore(&CDB, NULL, CRYPT_EXPORTABLE);
}
if(!hStore){
delete pP12; pP12 = NULL;
::AfxMessageBox(_T("将用户证书导入临时证书库 出错!"));
return;
}
//枚举临时证书库中导入的证书
PCCERT_CONTEXT pCertContext = NULL;
HCRYPTPROV hCertProv = NULL;
HCRYPTKEY hKey = NULL;
BYTE *pPK = NULL;
HCRYPTKEY hPrvKey = NULL;
HCRYPTPROV hProv = NULL;
while (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext)){
//对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)
if (!CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
&pCertContext->pCertInfo->Issuer,
&pCertContext->pCertInfo->Subject))
{
//获取私钥临时 CSP 句柄
DWORD dwKeySpec = 0;
if (!CryptAcquireCertificatePrivateKey(pCertContext,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hCertProv,
&dwKeySpec,
NULL)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取私钥临时 CSP 句柄 出错!"));
goto cleanup;
}
//获取密钥对,前者加密,后者签名,自签名的hPubKey一定是AT_SIGNATURE
if (!CryptGetUserKey(hCertProv, ((keyType == 0) ? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey)) {
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取密钥对 出错!"));
goto cleanup;
}
//获取私钥长度
DWORD dwPKSize = 0;
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("获取私钥大小 出错!"));
goto cleanup;
}
//分配内存
if (!(pPK = new BYTE[dwPKSize])){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("构建用户证书结构体 出错!"));
goto cleanup;
}
//导出私钥
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("导出私钥 出错!"));
goto cleanup;
}
/*Algid
[in] An value that identifies the algorithm for which the key is to be generated. 该参数的值将根据CSP的作用而不同。 ALG_ID 表明产生私钥所使用的算法。有如下参数:
微软提供的基本算法
CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1,CALG_MAC,CALG_HMAC,CALG_SSL3_SHAMD5, CALG_MD2,CALG_MD2
CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2,CALG_RC4,CALG_DES
微软提供的增强型算法:
CALG_MD2,CALG_MD5,CALG_SHA,CALG_SHA1
CALG_MAC,CALG_HMAC ,CALG_SSL3_SHAMD5,CALG_RSA_SIGN,CALG_RSA_KEYX,CALG_RC2, CALG_RC4,CALG_DES,CALG_3DES_112,CALG_3DES
使用DH的CSP有如下两个参数,CALG_DH_EPHEM,CALG_DH_SF
使用公开密钥算法产生公/私密钥对,有以下两个:AT_SIGNATURE 用于进行数字签名而产生的密钥对。 AT_KEYEXCHANGE 用于进行加解密(密钥交换)产生的密钥对;
*/
/*
PUBLICKEYSTRUC* p = (PUBLICKEYSTRUC*)pPK;
p->aiKeyAlg = CALG_RSA_SIGN;
*/
//获取 UKEY 的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, 0)) {
//构建新容器的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
//创建密钥容器成功,并得到CSP句柄
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("构建新容器 出错!"));
goto cleanup;
}else{
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
goto cleanup;
}else{
//将证书导入到密钥容器
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
goto cleanup;
}
::AfxMessageBox(_T("用户证书 导入成功 !"));
}
}
}else{
::AfxMessageBox("是否将用户证书导入已存在容器,该操作会删除现有容器证书?",MB_YESNO|MB_ICONQUESTION);
int a = MessageBox( "是否确认导入现有容器?" , "警告!该操作会删除现有容器证书!",MB_YESNO|MB_ICONWARNING);
if (a == IDYES){
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_DELETEKEYSET)){
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("删除现有容器 出错!"));
goto cleanup;
}else{
//构建新容器的 CSP 句柄
if(!CryptAcquireContext(&hProv, CONTAINERNAME, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)){
//创建密钥容器成功,并得到CSP句柄
DWORD dwRst = ::GetLastError();
::AfxMessageBox(_T("构建新容器 出错!"));
goto cleanup;
}else{
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将私钥导入到 CSP 出错!"));
goto cleanup;
}else{
//将证书导入到密钥容器
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)){
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("将证书导入到密钥容器 出错!"));
goto cleanup;
}
::AfxMessageBox(_T("用户证书 导入成功 !"));
}
}
}
}else{
::AfxMessageBox(_T("用户证书未成功导入,容器中已包含其它用户证书 !"));
}
}
}
}
goto cleanup;
cleanup:
//销毁私钥句柄
CryptDestroyKey(hPrvKey);
//关闭硬件加密设备CSP操作句柄
CryptReleaseContext(hProv, 0);
//释放私钥内存
delete pPK; pPK = NULL;
//销毁密钥对句柄
CryptDestroyKey(hKey);
//释放证书句柄
CertFreeCertificateContext(pCertContext);
//关闭临时证书库
CertCloseStore(hStore, 0);
//删除临时用户证书文件
DeleteFile(FILEDIR);
}
/**
* 执行 文件下载 操作
* @param Url: 目标URL下载地址
* @param LOCALPATH:本地保存路径
*/
LONG CZdActivexCtrl::DownLoadToLocal(LPCTSTR Url,LPCTSTR LOCALPATH){
//清除URL 缓存
DeleteUrlCacheEntry(Url);
//下载文件
//Url 下载地址
//LOCALPATH 本地保存地址
if (S_OK ==URLDownloadToFile(NULL,Url,LOCALPATH,0,NULL))
return 1;//下载成功
else
return -1;//下载失败
}
/*
遍历系统CSP Provider
*/
BSTR CZdActivexCtrl::EnumCspProvider(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strResult = "";
CString result = "";
long i = 0;
//枚举CSP设备
DWORD cbName;
DWORD dwType;
DWORD dwIndex;
CHAR *pszName = NULL;
// 遍历列举CSP
dwIndex = 0;
while(CryptEnumProviders(
dwIndex,
NULL,
0,
&dwType,
NULL,
&cbName
))
{
//--------------------------------------------------------------------
// cbName returns the length of the name of the next provider.
// Allocate memory in a buffer to retrieve that name.
if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cbName)))
{
::AfxMessageBox(_T("ERROR - LocalAlloc failed!"));
exit(1);
}
//--------------------------------------------------------------------
// Get the provider name.
if (CryptEnumProviders(
dwIndex++,
NULL,
0,
&dwType,
pszName,
&cbName
)){
if(PROV_RSA_FULL == dwType){
i++;
CString value = _T(pszName);
strResult +="{'value':'"+value+"'},";
}
}else{
::AfxMessageBox(_T("ERROR - CryptEnumProviders"));
exit(1);
}
LocalFree(pszName);
}
strResult = strResult.Mid(0,strResult.GetLength()-1);
char c[7];
itoa(i,c,10);
result.Append("{'total':");
result.Append(c);
result.Append(", 'rows': [");
result.Append(strResult+"]}");
// TODO: 在此添加调度处理程序代码
return result.AllocSysString();
}