//---------------------------------------------------------------------------

#pragma hdrstop
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
DWORD err=0;
HCRYPTMSG hMsg=NULL;
PBYTE buffer = NULL;
DWORD dwBuffer=0;
PCRYPT_ATTRIBUTES attrs=NULL;
DWORD size_of_attr=0;
PCERT_NAME_VALUE cnv_messType=NULL;
BYTE messageType[1];
PCERT_NAME_VALUE cnv_pkiStatus=NULL;
BYTE pkiStatus[1];
DWORD cnv_size=0;
PCERT_NAME_VALUE cnv_failInfo=NULL;
BYTE failInfo[1];
PCERT_NAME_VALUE cnv_transID=NULL;
BYTE* transID=NULL;
DWORD ret=0;
try
{
	try
	{
		  // в переменной buffer содержится pkcs7 в бинарном виде, в переменно dwBuffer  - размер pkcs7
		   if (!(hMsg = CryptMsgOpenToDecode(MY_ENCODING_TYPE, 0, 0, 0, NULL, NULL))) throw GetLastError();
		   if(!CryptMsgUpdate(hMsg,buffer,dwBuffer,TRUE)) throw GetLastError();
		  // получаем подписанные атрибуты
		   if (!CryptMsgGetParam(hMsg,CMSG_SIGNER_AUTH_ATTR_PARAM,0,NULL,&size_of_attr)) throw GetLastError();
		   attrs = (PCRYPT_ATTRIBUTES)malloc(size_of_attr);
		   if  (!CryptMsgGetParam(hMsg,CMSG_SIGNER_AUTH_ATTR_PARAM,0,attrs,&size_of_attr)) throw GetLastError();
			// получаем значение атрибутов
		   for(int i=0;i<attrs->cAttr;i++)
		   {
					cnv_size=0;
					if (strcmp(attrs->rgAttr[i].pszObjId,"2.16.840.1.113733.1.9.2")==0) // VERISIGN_MESSAGE_TYPE(тип сообщения)
					{
							//декодируем значение 
						   if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, NULL, &cnv_size)) throw GetLastError();
						   cnv_messType = (PCERT_NAME_VALUE)malloc(cnv_size);
						   if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, cnv_messType, &cnv_size)) throw GetLastError();
						   memcpy(messageType,cnv_messType->Value.pbData,cnv_messType->Value.cbData);
					}

					if (strcmp(attrs->rgAttr[i].pszObjId,"2.16.840.1.113733.1.9.3")==0) // VERISIGN_PKI_STATUS(PKI Status)
					{
						   //декодируем значение
						   if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, NULL, &cnv_size)) throw GetLastError();
						   cnv_pkiStatus = (PCERT_NAME_VALUE)malloc(cnv_size);
						   if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, cnv_pkiStatus, &cnv_size)) throw GetLastError();
						   memcpy(pkiStatus,cnv_pkiStatus->Value.pbData,cnv_pkiStatus->Value.cbData);
					}
					if (strcmp(attrs->rgAttr[i].pszObjId,"2.16.840.1.113733.1.9.4")==0) //VERISIGN_FAIL_INFO (Fail Info)
					{
							//декодируем значение
							if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, NULL, &cnv_size)) throw GetLastError();
							cnv_failInfo = (PCERT_NAME_VALUE)malloc(cnv_size);
							if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, cnv_failInfo, &cnv_size)) throw GetLastError();
							memcpy(failInfo,cnv_failInfo->Value.pbData,cnv_failInfo->Value.cbData);
					}
					if (strcmp(attrs->rgAttr[i].pszObjId,"2.16.840.1.113733.1.9.7")==0) //VERISIGN_TRANSACTION_ID (Transaction ID)
					{
							//декодируем значение
							if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, NULL, &cnv_size)) throw GetLastError();
							cnv_transID = (PCERT_NAME_VALUE)malloc(cnv_size);
							if (!CryptDecodeObject(MY_ENCODING_TYPE, X509_ANY_STRING, attrs->rgAttr[i].rgValue->pbData,attrs->rgAttr[i].rgValue->cbData, 0, cnv_transID, &cnv_size)) throw GetLastError();
							transID = (BYTE*)malloc(cnv_transID->Value.cbData);
							memcpy(transID,cnv_transID->Value.pbData,cnv_transID->Value.cbData);
					}
		   }
	 }
	 catch(DWORD err)
	 {
			ret=err;
	 }
	 catch(int err)
	 {
			ret=err;
	 }
}
__finally
{
	 if (cnv_messType) free(cnv_messType);
	 if (cnv_pkiStatus) free(cnv_pkiStatus);
	 if (cnv_failInfo) free(cnv_failInfo);
	 if (cnv_transID) free(cnv_transID);
	 if (transID) free(transID);
	 if (attrs) free(attrs);
	 if (hMsg) CryptMsgClose(hMsg);
	 if (buffer) free(buffer);
}
 return ret;
}
//---------------------------------------------------------------------------
 