//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  Copyright (C) Microsoft Corporation, 1995 - 1999
//
//  File:       frmtfunc.cpp
//
//  Contents:   OID format functions
//
//  Functions:  CryptFrmtFuncDllMain
//              CryptFormatObject
//              CryptQueryObject
//
//  History:    15-05-97    xiaohs   created
//              27 Oct 1999 dsie     add post win2k features.
//--------------------------------------------------------------------------

#include "global.hxx"
#include <dbgdef.h>
#include "frmtfunc.h"

HMODULE hFrmtFuncInst;

static HCRYPTOIDFUNCSET hFormatFuncSet;


//function type define
typedef BOOL (WINAPI *PFN_FORMAT_FUNC)(
	IN DWORD dwCertEncodingType,
    IN DWORD dwFormatType,
	IN DWORD dwFormatStrType,
	IN void	 *pFormatStruct,
    IN LPCSTR lpszStructType,
    IN const BYTE *pbEncoded,
    IN DWORD cbEncoded,
	OUT void *pbFormat,
    IN OUT DWORD *pcbFormat
    );

static BOOL
WINAPI
FormatBytesToHex(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL	
WINAPI	
CryptDllFormatAttr(
				DWORD		dwEncodingType,	
				DWORD		dwFormatType,
				DWORD		dwFormatStrType,
				void		*pStruct,
				LPCSTR		lpszStructType,
				const BYTE	*pbEncoded,
				DWORD		cbEncoded,
				void		*pBuffer,
				DWORD		*pcBuffer);


static BOOL	
WINAPI	
CryptDllFormatName(
				DWORD		dwEncodingType,	
				DWORD		dwFormatType,
				DWORD		dwFormatStrType,
				void		*pStruct,
				LPCSTR		lpszStructType,
				const BYTE	*pbEncoded,
				DWORD		cbEncoded,
				void		*pbBuffer,
				DWORD		*pcbBuffer);

static BOOL
WINAPI
FormatBasicConstraints2(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatBasicConstraints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatCRLReasonCode(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatEnhancedKeyUsage(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatAltName(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatAuthorityKeyID(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatAuthorityKeyID2(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatNextUpdateLocation(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatSubjectKeyID(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatFinancialCriteria(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatSMIMECapabilities(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatKeyUsage(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatAuthortiyInfoAccess(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatKeyAttributes(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatKeyRestriction(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatCRLDistPoints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatCertPolicies(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatCAVersion(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatAnyUnicodeStringExtension(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatAnyNameValueStringAttr(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatNetscapeCertType(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);


static BOOL
WINAPI
FormatSPAgencyInfo(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

//
// DSIE: Post Win2K.
//

static BOOL
WINAPI
FormatCrlNumber (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatCrlNextPublish (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatIssuingDistPoint (
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static BOOL
WINAPI
FormatNameConstraints (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatCertSrvPreviousCertHash (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatPolicyMappings (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatPolicyConstraints (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatCertificateTemplate (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat);

static BOOL
WINAPI
FormatXCertDistPoints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat);

static const CRYPT_OID_FUNC_ENTRY DefaultFormatTable[] = {
    CRYPT_DEFAULT_OID, FormatBytesToHex};

static const CRYPT_OID_FUNC_ENTRY OIDFormatTable[] = {
				szOID_COMMON_NAME,						CryptDllFormatAttr,	
				szOID_SUR_NAME,                      	CryptDllFormatAttr,
				szOID_DEVICE_SERIAL_NUMBER,          	CryptDllFormatAttr,
				szOID_COUNTRY_NAME,                  	CryptDllFormatAttr,
				szOID_LOCALITY_NAME,                 	CryptDllFormatAttr,
				szOID_STATE_OR_PROVINCE_NAME,        	CryptDllFormatAttr,
				szOID_STREET_ADDRESS,                	CryptDllFormatAttr,
				szOID_ORGANIZATION_NAME,             	CryptDllFormatAttr,
				szOID_ORGANIZATIONAL_UNIT_NAME,      	CryptDllFormatAttr,
				szOID_TITLE,                         	CryptDllFormatAttr,
				szOID_DESCRIPTION,                   	CryptDllFormatAttr,
				szOID_SEARCH_GUIDE,                  	CryptDllFormatAttr,
				szOID_BUSINESS_CATEGORY,             	CryptDllFormatAttr,
				szOID_POSTAL_ADDRESS,                	CryptDllFormatAttr,
				szOID_POSTAL_CODE,                   	CryptDllFormatAttr,
				szOID_POST_OFFICE_BOX,               	CryptDllFormatAttr,
				szOID_PHYSICAL_DELIVERY_OFFICE_NAME, 	CryptDllFormatAttr,
				szOID_TELEPHONE_NUMBER,              	CryptDllFormatAttr,
				szOID_TELEX_NUMBER,                  	CryptDllFormatAttr,
				szOID_TELETEXT_TERMINAL_IDENTIFIER,  	CryptDllFormatAttr,
				szOID_FACSIMILE_TELEPHONE_NUMBER,    	CryptDllFormatAttr,
				szOID_X21_ADDRESS,                   	CryptDllFormatAttr,
				szOID_INTERNATIONAL_ISDN_NUMBER,     	CryptDllFormatAttr,
				szOID_REGISTERED_ADDRESS,            	CryptDllFormatAttr,
				szOID_DESTINATION_INDICATOR,         	CryptDllFormatAttr,
				szOID_PREFERRED_DELIVERY_METHOD,     	CryptDllFormatAttr,
				szOID_PRESENTATION_ADDRESS,          	CryptDllFormatAttr,
				szOID_SUPPORTED_APPLICATION_CONTEXT, 	CryptDllFormatAttr,
				szOID_MEMBER,                        	CryptDllFormatAttr,
				szOID_OWNER,                         	CryptDllFormatAttr,
				szOID_ROLE_OCCUPANT,                 	CryptDllFormatAttr,
				szOID_SEE_ALSO,                      	CryptDllFormatAttr,
				szOID_USER_PASSWORD,                 	CryptDllFormatAttr,
				szOID_USER_CERTIFICATE,              	CryptDllFormatAttr,
				szOID_CA_CERTIFICATE,                	CryptDllFormatAttr,
				szOID_AUTHORITY_REVOCATION_LIST,     	CryptDllFormatAttr,
				szOID_CERTIFICATE_REVOCATION_LIST,   	CryptDllFormatAttr,
				szOID_CROSS_CERTIFICATE_PAIR,        	CryptDllFormatAttr,
				szOID_GIVEN_NAME,                    	CryptDllFormatAttr,
				szOID_INITIALS,                     	CryptDllFormatAttr,
                szOID_DOMAIN_COMPONENT,                 CryptDllFormatAttr,
                szOID_PKCS_12_FRIENDLY_NAME_ATTR,       CryptDllFormatAttr,
                szOID_PKCS_12_LOCAL_KEY_ID,             CryptDllFormatAttr,
				X509_NAME,								CryptDllFormatName,
				X509_UNICODE_NAME,						CryptDllFormatName,
				szOID_BASIC_CONSTRAINTS2,				FormatBasicConstraints2,
				X509_BASIC_CONSTRAINTS2,				FormatBasicConstraints2,
                szOID_BASIC_CONSTRAINTS,                FormatBasicConstraints,
                X509_BASIC_CONSTRAINTS,                 FormatBasicConstraints,
				szOID_CRL_REASON_CODE,					FormatCRLReasonCode,
				X509_CRL_REASON_CODE,					FormatCRLReasonCode,
				szOID_ENHANCED_KEY_USAGE,				FormatEnhancedKeyUsage,
				X509_ENHANCED_KEY_USAGE,				FormatEnhancedKeyUsage,
                szOID_SUBJECT_ALT_NAME,                 FormatAltName,
                szOID_ISSUER_ALT_NAME,                  FormatAltName,
                szOID_SUBJECT_ALT_NAME2,                FormatAltName,
                szOID_ISSUER_ALT_NAME2,                 FormatAltName,
                X509_ALTERNATE_NAME,                    FormatAltName,
                szOID_AUTHORITY_KEY_IDENTIFIER,         FormatAuthorityKeyID,
                X509_AUTHORITY_KEY_ID,                  FormatAuthorityKeyID,
                szOID_AUTHORITY_KEY_IDENTIFIER2,        FormatAuthorityKeyID2,
                X509_AUTHORITY_KEY_ID2,                 FormatAuthorityKeyID2,
                szOID_NEXT_UPDATE_LOCATION,             FormatNextUpdateLocation,
                szOID_SUBJECT_KEY_IDENTIFIER,           FormatSubjectKeyID,
                SPC_FINANCIAL_CRITERIA_OBJID,           FormatFinancialCriteria,
                SPC_FINANCIAL_CRITERIA_STRUCT,          FormatFinancialCriteria,
                szOID_RSA_SMIMECapabilities,            FormatSMIMECapabilities,
                PKCS_SMIME_CAPABILITIES,                FormatSMIMECapabilities,
                szOID_KEY_USAGE,                        FormatKeyUsage,
                X509_KEY_USAGE,                         FormatKeyUsage,
                szOID_AUTHORITY_INFO_ACCESS,            FormatAuthortiyInfoAccess,
                X509_AUTHORITY_INFO_ACCESS,             FormatAuthortiyInfoAccess,
                szOID_KEY_ATTRIBUTES,                   FormatKeyAttributes,
                X509_KEY_ATTRIBUTES,                    FormatKeyAttributes,
                szOID_KEY_USAGE_RESTRICTION,            FormatKeyRestriction,
                X509_KEY_USAGE_RESTRICTION,             FormatKeyRestriction,
                szOID_CRL_DIST_POINTS,                  FormatCRLDistPoints,
                X509_CRL_DIST_POINTS,                   FormatCRLDistPoints,
                szOID_FRESHEST_CRL,                     FormatCRLDistPoints,    // Post Win2K
                szOID_CERT_POLICIES,                    FormatCertPolicies,
                X509_CERT_POLICIES,                     FormatCertPolicies,
				szOID_ENROLL_CERTTYPE_EXTENSION,		FormatAnyUnicodeStringExtension,
				szOID_OS_VERSION,						FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_CERT_TYPE,				FormatNetscapeCertType,
				szOID_NETSCAPE_BASE_URL,				FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_REVOCATION_URL,			FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_CA_REVOCATION_URL,		FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_CERT_RENEWAL_URL,		FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_CA_POLICY_URL,			FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_SSL_SERVER_NAME,			FormatAnyUnicodeStringExtension,
				szOID_NETSCAPE_COMMENT,					FormatAnyUnicodeStringExtension,
				szOID_ENROLLMENT_NAME_VALUE_PAIR,		FormatAnyNameValueStringAttr,
				szOID_CERTSRV_CA_VERSION,				FormatCAVersion,
				SPC_SP_AGENCY_INFO_OBJID,               FormatSPAgencyInfo,
                SPC_SP_AGENCY_INFO_STRUCT,              FormatSPAgencyInfo,

                // Post Win2K
                szOID_CRL_NUMBER,                       FormatCrlNumber,
                szOID_DELTA_CRL_INDICATOR,              FormatCrlNumber,
				szOID_CRL_VIRTUAL_BASE,					FormatCrlNumber,
                szOID_CRL_NEXT_PUBLISH,                 FormatCrlNextPublish,
                szOID_ISSUING_DIST_POINT,               FormatIssuingDistPoint,
                X509_ISSUING_DIST_POINT,                FormatIssuingDistPoint,
                szOID_NAME_CONSTRAINTS,                 FormatNameConstraints,
                X509_NAME_CONSTRAINTS,                  FormatNameConstraints,
                szOID_CERTSRV_PREVIOUS_CERT_HASH,       FormatCertSrvPreviousCertHash,

                szOID_APPLICATION_CERT_POLICIES,        FormatCertPolicies,
                X509_POLICY_MAPPINGS,                   FormatPolicyMappings,
                szOID_POLICY_MAPPINGS,                  FormatPolicyMappings,
                szOID_APPLICATION_POLICY_MAPPINGS,      FormatPolicyMappings,
                X509_POLICY_CONSTRAINTS,                FormatPolicyConstraints,
                szOID_POLICY_CONSTRAINTS,               FormatPolicyConstraints,
                szOID_APPLICATION_POLICY_CONSTRAINTS,   FormatPolicyConstraints,
                X509_CERTIFICATE_TEMPLATE,              FormatCertificateTemplate,
                szOID_CERTIFICATE_TEMPLATE,             FormatCertificateTemplate,
                szOID_CRL_SELF_CDP,                     FormatCRLDistPoints,
                X509_CROSS_CERT_DIST_POINTS,            FormatXCertDistPoints,
                szOID_CROSS_CERT_DIST_POINTS,           FormatXCertDistPoints,
};

DWORD dwOIDFormatCount = sizeof(OIDFormatTable) / sizeof(OIDFormatTable[0]);

//+-------------------------------------------------------------------------
//  Dll initialization
//--------------------------------------------------------------------------
BOOL
WINAPI
CryptFrmtFuncDllMain(
        HMODULE hModule,
        DWORD  fdwReason,
        LPVOID lpReserved)
{
    BOOL    fRet;

    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:

		hFrmtFuncInst = hModule;

        if (NULL == (hFormatFuncSet = CryptInitOIDFunctionSet(
                CRYPT_OID_FORMAT_OBJECT_FUNC,
                0)))                                // dwFlags
            goto CryptInitFrmtFuncError;

		//install the default formatting routine
		if (!CryptInstallOIDFunctionAddress(
                NULL,                       // hModule
                X509_ASN_ENCODING,
                CRYPT_OID_FORMAT_OBJECT_FUNC,
                1,
                DefaultFormatTable,
                0))                         // dwFlags
            goto CryptInstallFrmtFuncError;

		//install the OID formatting routine
		if (!CryptInstallOIDFunctionAddress(
                NULL,                       // hModule
                X509_ASN_ENCODING,
                CRYPT_OID_FORMAT_OBJECT_FUNC,
                dwOIDFormatCount,
                OIDFormatTable,
                0))                         // dwFlags
            goto CryptInstallFrmtFuncError;


		break;

    case DLL_PROCESS_DETACH:
    case DLL_THREAD_DETACH:
    default:
        break;
    }

    fRet = TRUE;
CommonReturn:
    return fRet;

ErrorReturn:
    fRet = FALSE;
    goto CommonReturn;
TRACE_ERROR(CryptInitFrmtFuncError)
TRACE_ERROR(CryptInstallFrmtFuncError)
}


//------------------------------------------------------------------------
//	   Convert the byte to its Hex presentation.
//
//	   Precondition: byte is less than 15
//
//------------------------------------------------------------------------
ULONG ByteToHex(BYTE byte, LPWSTR wszZero, LPWSTR wszA)
{
	ULONG uValue=0;

	if(((ULONG)byte)<=9)
	{
		uValue=((ULONG)byte)+ULONG(*wszZero);	
	}
	else
	{
		uValue=(ULONG)byte-10+ULONG(*wszA);

	}

	return uValue;

}
//--------------------------------------------------------------------------
//
//	 Format the encoded bytes into a hex string in the format of
//   xxxx xxxx xxxx xxxx ...
//
//   DSIE 6/28/2000: change format to xx xx xx xx, per VicH's request.
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatBytesToHex(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	LPWSTR	pwszBuffer=NULL;
	DWORD	dwBufferSize=0;
	DWORD	dwBufferIndex=0;
	DWORD	dwEncodedIndex=0;
	WCHAR	wszSpace[CHAR_SIZE];
	WCHAR	wszZero[CHAR_SIZE];
	WCHAR	wszA[CHAR_SIZE];
	WCHAR	wszHex[HEX_SIZE];
	
	//check for input parameters
	if(( pbEncoded!=NULL && cbEncoded==0)
		||(pbEncoded==NULL && cbEncoded!=0)
		|| (pcbFormat==NULL))
	{
		SetLastError((DWORD) E_INVALIDARG);
		return FALSE;
	}

#if (0) // DSIE: Fix bug 128630.
	//check for simple case.  No work needed
	if(pbEncoded==NULL && cbEncoded==0)
	{
		*pcbFormat=0;
		return TRUE;
	}
#endif

	//calculate the memory needed, in bytes
	//we need 3 wchars per byte, along with the NULL terminator
	dwBufferSize=sizeof(WCHAR)*(cbEncoded*3+1);

	//length only calculation
	if(pcbFormat!=NULL && pbFormat==NULL)
	{
		*pcbFormat=dwBufferSize;
		return TRUE;
	}

	//load the string
	if(!LoadStringU(hFrmtFuncInst, IDS_FRMT_SPACE, wszSpace,
		CHAR_SIZE)
	  ||!LoadStringU(hFrmtFuncInst, IDS_FRMT_ZERO, wszZero,
	    CHAR_SIZE)
	  ||!LoadStringU(hFrmtFuncInst, IDS_FRMT_A, wszA,
	   CHAR_SIZE)
	  ||!LoadStringU(hFrmtFuncInst, IDS_FRMT_HEX, wszHex,
	  HEX_SIZE)
	  )
	{
		SetLastError((DWORD) E_UNEXPECTED);
		return FALSE;
	}

	pwszBuffer=(LPWSTR)malloc(dwBufferSize);
	if(!pwszBuffer)
	{
		SetLastError((DWORD) E_OUTOFMEMORY);
		return FALSE;
	}

	dwBufferIndex=0;

	//format the wchar buffer one byte at a time
	for(dwEncodedIndex=0; dwEncodedIndex<cbEncoded; dwEncodedIndex++)
	{
#if (0) // DSIE:
		//copy the space between every two bytes.  Skip for the 1st byte
        if((0!=dwEncodedIndex) && (0==(dwEncodedIndex % 2)))
#else
		//copy the space between every byte.  Skip for the 1st byte
        if(dwEncodedIndex != 0)
#endif
        {
		    pwszBuffer[dwBufferIndex]=wszSpace[0];
		    dwBufferIndex++;
        }

		//format the higher 4 bits
		pwszBuffer[dwBufferIndex]=(WCHAR)ByteToHex(
			 (BYTE)( (pbEncoded[dwEncodedIndex]&UPPER_BITS)>>4 ),
			 wszZero, wszA);

		dwBufferIndex++;

		//format the lower 4 bits
		pwszBuffer[dwBufferIndex]=(WCHAR)ByteToHex(
			 (BYTE)( pbEncoded[dwEncodedIndex]&LOWER_BITS ),
			 wszZero, wszA);

		dwBufferIndex++;
	}

	//add the NULL terminator to the string
	pwszBuffer[dwBufferIndex]=wszSpace[1];

    //calculate the real size for the buffer
    dwBufferSize=sizeof(WCHAR)*(wcslen(pwszBuffer)+1);

	//copy the buffer
	memcpy(pbFormat, pwszBuffer,
		(*pcbFormat>=dwBufferSize) ? dwBufferSize : *pcbFormat);

	free(pwszBuffer);

	//make sure the user has supplied enough memory
	if(*pcbFormat < dwBufferSize)
	{
		*pcbFormat=dwBufferSize;
		SetLastError((DWORD) ERROR_MORE_DATA);
		return FALSE;
	}
		
	*pcbFormat=dwBufferSize;

	return TRUE;
}

//+-----------------------------------------------------------------------------
//
//  AllocateAnsiToUnicode
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
AllocateAnsiToUnicode(
    LPCSTR pszAnsi, 
    LPWSTR * ppwszUnicode)
{
    BOOL   fResult     = FALSE;
    LPWSTR pwszUnicode = NULL;
    DWORD  dwWideSize  = 0;

    if (!ppwszUnicode)
    {
		goto InvalidArg;
    }

    *ppwszUnicode = NULL;

    if (!pszAnsi)
    {
        return TRUE;
    }

	if (!(dwWideSize = MultiByteToWideChar(CP_ACP,
                                           0,
	                                       pszAnsi,
                                           strlen(pszAnsi),
                                           NULL,
                                           0)))
    {
		goto szTOwszError;
    }

    //
	// Allocate memory, including the NULL terminator.
    //
	if (!(pwszUnicode = (WCHAR *) malloc(sizeof(WCHAR) * (dwWideSize + 1))))
    {
		goto MemoryError;
    }

    memset(pwszUnicode, 0, sizeof(WCHAR) * (dwWideSize + 1));

	if (!MultiByteToWideChar(CP_ACP,
                             0,
	                         pszAnsi,
                             strlen(pszAnsi),
                             pwszUnicode,
                             dwWideSize))
    {
        free(pwszUnicode);
		goto szTOwszError;
    }

    *ppwszUnicode = pwszUnicode;

    fResult = TRUE;

CommonReturn:

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(szTOwszError);
}

//+-----------------------------------------------------------------------------
//
//  FormatObjectId
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatObjectId (
    LPSTR    pszObjId,
    DWORD    dwGroupId,
    BOOL     bMultiLines,
    LPWSTR * ppwszFormat)
{
    BOOL              fResult;
	PCCRYPT_OID_INFO  pOIDInfo    = NULL;
    LPWSTR            pwszObjId   = NULL;

    //
    // Initialize.
    //
    *ppwszFormat = NULL;

    //
    // Convert OID to Unicode.
    //
    if (!AllocateAnsiToUnicode(pszObjId, &pwszObjId))
    {
        goto AnsiToUnicodeError;
    }

    //
    // Find OID info.
    //
    if (pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
                                    (void *) pszObjId,
                                    dwGroupId))
	{
        //
        // "%1!s!(%2!s!)%3!s!"
        //
        if (!FormatMessageUnicode(ppwszFormat, 
                                  IDS_GENERIC_OBJECT_ID,
                                  pOIDInfo->pwszName,
                                  pwszObjId,
                                  bMultiLines ? wszCRLF : wszEMPTY))
        {
            goto FormatMessageError;
        }
    }
    else
    {
        //
        // "%1!s!%2!s!"
        //
        if (!FormatMessageUnicode(ppwszFormat, 
                                  IDS_STRING,
                                  pwszObjId,
                                  bMultiLines ? wszCRLF : wszEMPTY))
        {
            goto FormatMessageError;
        }
    }

    fResult = TRUE;

CommonReturn:

    if (pwszObjId)
    {
        free(pwszObjId);
    }

    return fResult;

ErrorReturn:

	fResult = FALSE;
	goto CommonReturn;

TRACE_ERROR(AnsiToUnicodeError);
TRACE_ERROR(FormatMessageError);
}

//+-----------------------------------------------------------------------------
//
//  FormatIPAddress
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatIPAddress(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void	   *pFormatStruct,
	LPCSTR	    lpszStructType,
    UINT        idsPrefix,
    const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
    BOOL   fResult;
    DWORD  cbNeeded    = 0;
    LPWSTR pwszFormat  = NULL;
    WCHAR  wszPrefix[PRE_FIX_SIZE] = wszEMPTY;
    BOOL   bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
	// Check for input parameters.
    //
	if ((pbEncoded!=NULL && cbEncoded==0) ||
        (pbEncoded==NULL && cbEncoded!=0) || 
        (pcbFormat==NULL))
	{
		goto InvalidArg;
	}

    if (bMultiLines && idsPrefix)
    {
        if(!LoadStringU(hFrmtFuncInst, 
                        idsPrefix,
                        wszPrefix, 
                        sizeof(wszPrefix) / sizeof(wszPrefix[0])))
        {
            goto LoadStringError;
        }
    }

    switch (cbEncoded)
    {
        case 4:
        {
            //
            // "%1!d!.%2!d!.%3!d!.%4!d!"
            //
            if (!FormatMessageUnicode(&pwszFormat,
                                      IDS_IPADDRESS_V4_4,
                                      (DWORD) pbEncoded[0],
                                      (DWORD) pbEncoded[1],
                                      (DWORD) pbEncoded[2],
                                      (DWORD) pbEncoded[3]))
            {
                goto FormatMessageError;
            }

            break;
        }

        case 8:
        {
            //
            // "%1!d!.%2!d!.%3!d!.%4!d!%5!s!%6!s!Mask=%7!d!.%8!d!.%9!d!.%10!d!"
            //
            if (!FormatMessageUnicode(&pwszFormat,
                                      IDS_IPADDRESS_V4_8,
                                      (DWORD) pbEncoded[0],
                                      (DWORD) pbEncoded[1],
                                      (DWORD) pbEncoded[2],
                                      (DWORD) pbEncoded[3],
                                      bMultiLines ? wszCRLF : wszEMPTY,
                                      bMultiLines ? wszPrefix : wszCOMMA,
                                      (DWORD) pbEncoded[4],
                                      (DWORD) pbEncoded[5],
                                      (DWORD) pbEncoded[6],
                                      (DWORD) pbEncoded[7]))
            {
                goto FormatMessageError;
            }

            break;
        }

        case 16:
        {
            //
            // "%1!02x!%2!02x!:%3!02x!%4!02x!:%5!02x!%6!02x!:%7!02x!%8!02x!:%9!02x!%10!02x!:%11!02x!%12!02x!:%13!02x!%14!02x!:%15!02x!%16!02x!"
            //
            if (!FormatMessageUnicode(&pwszFormat,
                                      IDS_IPADDRESS_V6_16,
                                      (DWORD) pbEncoded[0],
                                      (DWORD) pbEncoded[1],
                                      (DWORD) pbEncoded[2],
                                      (DWORD) pbEncoded[3],
                                      (DWORD) pbEncoded[4],
                                      (DWORD) pbEncoded[5],
                                      (DWORD) pbEncoded[6],
                                      (DWORD) pbEncoded[7],
                                      (DWORD) pbEncoded[8],
                                      (DWORD) pbEncoded[9],
                                      (DWORD) pbEncoded[10],
                                      (DWORD) pbEncoded[11],
                                      (DWORD) pbEncoded[12],
                                      (DWORD) pbEncoded[13],
                                      (DWORD) pbEncoded[14],
                                      (DWORD) pbEncoded[15]))
            {
                goto FormatMessageError;
            }

            break;
        }

        case 32:
        {
            //
            // "%1!02x!%2!02x!:%3!02x!%4!02x!:%5!02x!%6!02x!:%7!02x!%8!02x!:%9!02x!%10!02x!:%11!02x!%12!02x!:%13!02x!%14!02x!:%15!02x!%16!02x!%17!s!%18!s!
            //  Mask=%19!02x!%20!02x!:%21!02x!%22!02x!:%23!02x!%24!02x!:%25!02x!%26!02x!:%27!02x!%28!02x!:%29!02x!%30!02x!:%31!02x!%32!02x!:%33!02x!%34!02x!"
            //
            if (!FormatMessageUnicode(&pwszFormat,
                                      IDS_IPADDRESS_V6_32,
                                      (DWORD) pbEncoded[0],
                                      (DWORD) pbEncoded[1],
                                      (DWORD) pbEncoded[2],
                                      (DWORD) pbEncoded[3],
                                      (DWORD) pbEncoded[4],
                                      (DWORD) pbEncoded[5],
                                      (DWORD) pbEncoded[6],
                                      (DWORD) pbEncoded[7],
                                      (DWORD) pbEncoded[8],
                                      (DWORD) pbEncoded[9],
                                      (DWORD) pbEncoded[10],
                                      (DWORD) pbEncoded[11],
                                      (DWORD) pbEncoded[12],
                                      (DWORD) pbEncoded[13],
                                      (DWORD) pbEncoded[14],
                                      (DWORD) pbEncoded[15],
                                      bMultiLines ? wszCRLF : wszEMPTY,
                                      bMultiLines ? wszPrefix : wszCOMMA,
                                      (DWORD) pbEncoded[16],
                                      (DWORD) pbEncoded[17],
                                      (DWORD) pbEncoded[18],
                                      (DWORD) pbEncoded[19],
                                      (DWORD) pbEncoded[20],
                                      (DWORD) pbEncoded[21],
                                      (DWORD) pbEncoded[22],
                                      (DWORD) pbEncoded[23],
                                      (DWORD) pbEncoded[24],
                                      (DWORD) pbEncoded[25],
                                      (DWORD) pbEncoded[26],
                                      (DWORD) pbEncoded[27],
                                      (DWORD) pbEncoded[28],
                                      (DWORD) pbEncoded[29],
                                      (DWORD) pbEncoded[30],
                                      (DWORD) pbEncoded[31]))
            {
                goto FormatMessageError;
            }

            break;
        }

        default:
        {
            if (!(fResult = FormatBytesToHex(dwCertEncodingType,
                                             dwFormatType,
                                             dwFormatStrType,
                                             pFormatStruct,
                                             lpszStructType,
                                             pbEncoded,
                                             cbEncoded,
                                             pbFormat,
                                             pcbFormat)))
            {
                goto FormatBytesToHexError;
            }

            goto CommonReturn;
        }
    }

    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // Length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    if (pwszFormat)
    {
        LocalFree((HLOCAL) pwszFormat);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);
TRACE_ERROR(FormatBytesToHexError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);

}

//+-------------------------------------------------------------------------
// format the specified data structure according to the certificate
// encoding type.
//--------------------------------------------------------------------------
BOOL
WINAPI
CryptFormatObject(
    IN DWORD dwCertEncodingType,
    IN DWORD dwFormatType,
	IN DWORD dwFormatStrType,
	IN void	 *pFormatStruct,
    IN LPCSTR lpszStructType,
    IN const BYTE *pbEncoded,
    IN DWORD cbEncoded,
	OUT void *pbFormat,
    IN OUT DWORD *pcbFormat
    )
{
    BOOL				fResult=FALSE;
    void				*pvFuncAddr;
    HCRYPTOIDFUNCADDR   hFuncAddr;

    if (CryptGetOIDFunctionAddress(
            hFormatFuncSet,
            dwCertEncodingType,
            lpszStructType,
            0,                      // dwFlags
            &pvFuncAddr,
            &hFuncAddr))
	{
        fResult = ((PFN_FORMAT_FUNC) pvFuncAddr)(
				dwCertEncodingType,
				dwFormatType,
				dwFormatStrType,
				pFormatStruct,
				lpszStructType,
				pbEncoded,
				cbEncoded,
				pbFormat,
				pcbFormat
            );
        CryptFreeOIDFunctionAddress(hFuncAddr, 0);
    }
	else
	{
        //do not call the default hex dump if CRYPT_FORMAT_STR_NO_HEX is set
        if(0==(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
        {
		    //call the default routine automatically
		    if (CryptGetOIDFunctionAddress(
                hFormatFuncSet,
                dwCertEncodingType,
                CRYPT_DEFAULT_OID,
                0,                      // dwFlags
                &pvFuncAddr,
                &hFuncAddr))
		    {
			    fResult = ((PFN_FORMAT_FUNC) pvFuncAddr)(
					dwCertEncodingType,
					dwFormatType,
					dwFormatStrType,
					pFormatStruct,
					lpszStructType,
					pbEncoded,
					cbEncoded,
					pbFormat,
					pcbFormat);

			    CryptFreeOIDFunctionAddress(hFuncAddr, 0);
		    }
            else
            {
			    *pcbFormat = 0;
			    fResult = FALSE;
            }
        }
		else
		{
			*pcbFormat = 0;
			fResult = FALSE;
		}
	}
    return fResult;
}



//-----------------------------------------------------------
//
//  This is the actual format routine for an particular RDN attribute.
//
//	lpszStructType is any OID for CERT_RDN_ATTR.  pbEncoded is
//	an encoded BLOB for CERT_NAME_INFO struct.  When pBuffer==NULL,
//	*pcbBuffer return the size of memory to be allocated in bytes.
//	Please notice the string is not NULL terminated.
//
//	For example, to ask for an unicode string of common name,
//	pass lpszStructType=szOID_COMMON_NAME,
//	pass dwFormatType==CRYPT_FORMAT_SIMPL,
//  pBuffer will be set the L"xiaohs@microsoft.com".
//
//
//-------------------------------------------------------------
static BOOL	WINAPI	CryptDllFormatAttr(
				DWORD		dwEncodingType,	
				DWORD		dwFormatType,
				DWORD		dwFormatStrType,
				void		*pStruct,
				LPCSTR		lpszStructType,
				const BYTE	*pbEncoded,
				DWORD		cbEncoded,
				void		*pBuffer,
				DWORD		*pcbBuffer)
{
		BOOL		fResult=FALSE;
		WCHAR		*pwszSeperator=NULL;
		BOOL		fHeader=FALSE;
		BOOL		flengthOnly=FALSE;
		DWORD		dwBufferCount=0;
		DWORD		dwBufferLimit=0;
		DWORD		dwBufferIncrement=0;
		DWORD		dwSeperator=0;
		DWORD		dwHeader=0;
		DWORD		dwOIDSize=0;
		WCHAR		*pwszBuffer=NULL;
		WCHAR		*pwszHeader=NULL;
		BOOL		fAddSeperator=FALSE;


		DWORD			cbStructInfo=0;
		CERT_NAME_INFO	*pStructInfo=NULL;
		DWORD			dwRDNIndex=0;
		DWORD			dwAttrIndex=0;
		DWORD			dwAttrCount=0;
		CERT_RDN_ATTR	*pCertRDNAttr=NULL;
		PCCRYPT_OID_INFO pOIDInfo=NULL;

        LPWSTR           pwszTemp;
		
		//check input parameters
		if(lpszStructType==NULL ||
			(pbEncoded==NULL && cbEncoded!=0) ||
			pcbBuffer==NULL	
		  )
			goto InvalidArg;

		if(cbEncoded==0)
		{
			*pcbBuffer=0;
			goto InvalidArg;
		}

		//get the seperator of the attributes
		//wszCOMMA is the default seperator
		if(dwFormatType & CRYPT_FORMAT_COMMA)
			pwszSeperator=wszCOMMA;
		else
		{
			if(dwFormatType & CRYPT_FORMAT_SEMICOLON)
				pwszSeperator=wszSEMICOLON;
			else
			{
				if(dwFormatType & CRYPT_FORMAT_CRLF)
					pwszSeperator=wszCRLF;
				else
                {
					pwszSeperator=wszPLUS;
                }
			}
		}

		//calculate the length of the seperator
		dwSeperator=wcslen(pwszSeperator)*sizeof(WCHAR);

		//check the requirement for the header
		if(dwFormatType & CRYPT_FORMAT_X509 ||
			dwFormatType & CRYPT_FORMAT_OID)
		{	
			fHeader=TRUE;
		}


		if(NULL==pBuffer)
			flengthOnly=TRUE;

		//decode the X509_UNICODE_NAME
		if(!CryptDecodeObject(dwEncodingType, X509_UNICODE_NAME,
			pbEncoded, cbEncoded, CRYPT_DECODE_NOCOPY_FLAG,
			NULL, &cbStructInfo))
			goto DecodeError;

		//allocate memory
		pStructInfo=(CERT_NAME_INFO *)malloc(cbStructInfo);
		if(!pStructInfo)
			goto MemoryError;	

		//decode the struct
 		if(!CryptDecodeObject(dwEncodingType, X509_UNICODE_NAME,
			pbEncoded, cbEncoded, CRYPT_DECODE_NOCOPY_FLAG,
			pStructInfo, &cbStructInfo))
			goto DecodeError;


		 //allocate the buffer for formatting
		if(!flengthOnly)
		{
			pwszBuffer=(WCHAR *)malloc(g_AllocateSize);
			if(!pwszBuffer)
				goto MemoryError;
				
			dwBufferLimit=g_AllocateSize;
		}

	   	//search for the OID requested.  If found one, put it
		//to the buffer.  If no requested attribut is found,
		//return.
		for(dwRDNIndex=0; dwRDNIndex<pStructInfo->cRDN; dwRDNIndex++)
		{
			//the following line is for code optimization
			dwAttrCount=(pStructInfo->rgRDN)[dwRDNIndex].cRDNAttr;

			for(dwAttrIndex=0; dwAttrIndex<dwAttrCount; dwAttrIndex++)
			{
				//look for the specific OIDs in the function
				if(_stricmp(lpszStructType,
				(pStructInfo->rgRDN)[dwRDNIndex].rgRDNAttr[dwAttrIndex].pszObjId)==0)
				{
					pCertRDNAttr=&((pStructInfo->rgRDN)[dwRDNIndex].rgRDNAttr[dwAttrIndex]);

					//init the dwBufferIncrement
					dwBufferIncrement=0;

					//get the header of the tag
					if(fHeader)
					{
						if(dwFormatType & CRYPT_FORMAT_X509)
						{
							//get the OID's name
							pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
														  (void *)lpszStructType,
														  CRYPT_RDN_ATTR_OID_GROUP_ID);

							if(pOIDInfo)
							{
								//allocate memory, including the NULL terminator
								pwszHeader=(WCHAR *)malloc((wcslen(pOIDInfo->pwszName)+wcslen(wszEQUAL)+1)*
									sizeof(WCHAR));
								if(!pwszHeader)
									goto MemoryError;

								wcscpy(pwszHeader,pOIDInfo->pwszName);

							}
						}

						//use the OID is no mapping is found or
						//OID is requested in the header
						if(pwszHeader==NULL)
						{
							//get the wide character string to the OID
							if(!(dwOIDSize=MultiByteToWideChar(CP_ACP,0,
							lpszStructType,strlen(lpszStructType),NULL,0)))
								goto szTOwszError;

							//allocate memory, including the NULL terminator
							pwszHeader=(WCHAR *)malloc((dwOIDSize+wcslen(wszEQUAL)+1)*
										sizeof(WCHAR));
							if(!pwszHeader)
								goto MemoryError;

							if(!(dwHeader=MultiByteToWideChar(CP_ACP,0,
							lpszStructType,strlen(lpszStructType),pwszHeader,dwOIDSize)))
								 goto szTOwszError;

							//NULL terminate the string
							*(pwszHeader+dwHeader)=L'\0';
							
						}

						//add the euqal sign
						wcscat(pwszHeader,	wszEQUAL);

						//get the header size, in bytes, excluding the NULL terminator
						dwHeader=wcslen(pwszHeader)*sizeof(WCHAR);
						dwBufferIncrement+=dwHeader;
					}


					//allocate enough memory.  Including the NULL terminator
					dwBufferIncrement+=pCertRDNAttr->Value.cbData;
					dwBufferIncrement+=dwSeperator;
					dwBufferIncrement+=2;
	

					if(!flengthOnly && ((dwBufferCount+dwBufferIncrement)>dwBufferLimit))
					{
					   //reallocate the memory
                        #if (0) // DSIE: Bug 27436
						pwszBuffer=(WCHAR *)realloc(pwszBuffer,
								max(dwBufferLimit+g_AllocateSize,
								dwBufferLimit+dwBufferIncrement));
						if(!pwszBuffer)
							goto MemoryError;
                        #endif

						pwszTemp=(WCHAR *)realloc(pwszBuffer,
								max(dwBufferLimit+g_AllocateSize,
    							dwBufferLimit+dwBufferIncrement));
						if(!pwszTemp)
							goto MemoryError;
                        pwszBuffer = pwszTemp;

                        dwBufferLimit+=max(g_AllocateSize,dwBufferIncrement);

					}
					
					//add the header if necessary
					if(fHeader)
					{							
						if(!flengthOnly)
						{
							memcpy((BYTE *)(pwszBuffer+dwBufferCount/sizeof(WCHAR)),
								pwszHeader,dwHeader);
						}

						dwBufferCount+=dwHeader;

						//do not need to do header anymore
						fHeader=FALSE;
					}

					//add the seperator	after the 1st iteration
					if(fAddSeperator)
					{
						
						if(!flengthOnly)
						{
							memcpy((BYTE *)(pwszBuffer+dwBufferCount/sizeof(WCHAR)),
								pwszSeperator,dwSeperator);
						}

						dwBufferCount+=dwSeperator;
					}
					else
						fAddSeperator=TRUE;

					//add the attr content
					if(!flengthOnly)
					{
						memcpy((BYTE *)(pwszBuffer+dwBufferCount/sizeof(WCHAR)),
							(pCertRDNAttr->Value.pbData),
							pCertRDNAttr->Value.cbData);
					}

					//increment the buffercount
					dwBufferCount+=pCertRDNAttr->Value.cbData;

				}
			}
		}


		//return the result as requested
		//check if the requested OID is actually in the DN
		if(0==dwBufferCount)
		{
			*pcbBuffer=dwBufferCount;
			goto NotFoundError;
		}


		//we need to NULL terminate the string
		if(!flengthOnly)
			*(pwszBuffer+dwBufferCount/sizeof(WCHAR))=L'\0';

		dwBufferCount+=2;

		if(pBuffer==NULL)
		{
			*pcbBuffer=dwBufferCount;
			fResult=TRUE;
			goto CommonReturn;
		}

		if((*pcbBuffer)<dwBufferCount)
		{
			*pcbBuffer=dwBufferCount;
			goto MoreDataError;		
		}


		*pcbBuffer=dwBufferCount;
		memcpy(pBuffer, pwszBuffer,dwBufferCount);

		fResult=TRUE;

CommonReturn:
		if(pwszHeader)
			free(pwszHeader);

		if(pwszBuffer)
			free(pwszBuffer);

		if(pStructInfo)
			free(pStructInfo);

		return fResult;

ErrorReturn:
    fResult = FALSE;
    goto CommonReturn;


SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(DecodeError);
TRACE_ERROR(szTOwszError);
SET_ERROR(NotFoundError, E_FAIL);
SET_ERROR(MoreDataError, ERROR_MORE_DATA);
}




//-----------------------------------------------------------
//
//  This is the actual format routine for an complete CERT_NAME
//
//
//	lpszStructType should be X509_NAME  pbEncoded is
//	an encoded BLOB for CERT_NAME_INFO struct.  When pBuffer==NULL,
//	*pcbBuffer return the size of memory to be allocated in bytes.
//	Please notice the string is NULL terminated.
//
//-------------------------------------------------------------
static BOOL	WINAPI	CryptDllFormatName(
				DWORD		dwEncodingType,	
				DWORD		dwFormatType,
				DWORD		dwFormatStrType,
				void		*pStruct,
				LPCSTR		lpszStructType,
				const BYTE	*pbEncoded,
				DWORD		cbEncoded,
				void		*pbBuffer,
				DWORD		*pcbBuffer)
{
    //makesure lpszStructType is X509_NAME or X509_UNICODE_NAME
	if((X509_NAME != lpszStructType) &&
		    (X509_UNICODE_NAME != lpszStructType))
    {
        SetLastError((DWORD) E_INVALIDARG);
        return FALSE;
    }

 	//check input parameters
	if((pbEncoded==NULL && cbEncoded!=0) || pcbBuffer==NULL)
    {
        SetLastError((DWORD) E_INVALIDARG);
        return FALSE;
    }

	if(cbEncoded==0)
    {
        SetLastError((DWORD) E_INVALIDARG);
        return FALSE;
    }

    //call CryptDllFormatNameAll with no prefix
    return  CryptDllFormatNameAll(dwEncodingType,	
                                  dwFormatType,
                                  dwFormatStrType,
                                  pStruct,
                                  0,
                                  FALSE,
                                  pbEncoded,
                                  cbEncoded,
                                  &pbBuffer,
                                  pcbBuffer);

}


//-----------------------------------------------------------
//
//  This is the actual format routine for an complete CERT_NAME
//
//
//	lpszStructType should be X509_NAME  pbEncoded is
//	an encoded BLOB for CERT_NAME_INFO struct.  When pBuffer==NULL,
//	*pcbBuffer return the size of memory to be allocated in bytes.
//	Please notice the string is NULL terminated.
//
//-------------------------------------------------------------
BOOL	CryptDllFormatNameAll(
				DWORD		dwEncodingType,	
				DWORD		dwFormatType,
				DWORD		dwFormatStrType,
				void		*pStruct,
                UINT        idsPreFix,
                BOOL        fToAllocate,
				const BYTE	*pbEncoded,
				DWORD		cbEncoded,
				void		**ppbBuffer,
				DWORD		*pcbBuffer)
{

		BOOL			    fResult=FALSE;
		DWORD			    dwStrType=0;
		CERT_NAME_BLOB	    Cert_Name_Blob;
		DWORD			    dwSize=0;
        LPWSTR              pwszName=NULL;
        LPWSTR              pwszMulti=NULL;

		Cert_Name_Blob.cbData=cbEncoded;
		Cert_Name_Blob.pbData=(BYTE *)pbEncoded;

	
		//calculate the dwStryType to use for CertNameToStrW
        dwStrType=FormatToStr(dwFormatType);

        //overwrite dwStrType to default if we are doing MULTI line format
        //since the options will be ignored
        //We want to use + and , for the seperator
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
        {

            dwStrType &=~(CERT_NAME_STR_CRLF_FLAG);
            dwStrType &=~(CERT_NAME_STR_COMMA_FLAG);
            dwStrType &=~(CERT_NAME_STR_SEMICOLON_FLAG);
            dwStrType &=~(CERT_NAME_STR_NO_QUOTING_FLAG);
            dwStrType &=~(CERT_NAME_STR_NO_PLUS_FLAG);


        }

        //if this function is not called from CryptDllFormatName,
        //make sure that we use the RESERSE Flag
        if(TRUE == fToAllocate)
            dwStrType |= CERT_NAME_STR_REVERSE_FLAG;

		//call the CertNameToStrW to convert
        dwSize=CertNameToStrW(dwEncodingType,
                        &Cert_Name_Blob,
                        dwStrType,
                        NULL,
                        0);

        if(0==dwSize)
            goto CertNameToStrError;

        pwszName=(LPWSTR)malloc(sizeof(WCHAR)*(dwSize));
        if(NULL==pwszName)
            goto MemoryError;

        dwSize=CertNameToStrW(dwEncodingType,
                        &Cert_Name_Blob,
                        dwStrType,
                        pwszName,
                        dwSize);
        if(0==dwSize)
            goto CertNameToStrError;

        //we do not need to parse the string for single line format
        if(0==(dwFormatStrType &  CRYPT_FORMAT_STR_MULTI_LINE))
        {
            //calculate the bytes needed
            dwSize=sizeof(WCHAR)*(wcslen(pwszName)+1);

            //if FALSE==fToAllocate, we do not allocate the memory on user's
            //behalf; otherwize, allocate memory to eliminate the need for
            //double call
            if(FALSE==fToAllocate)
            {
                if(NULL==(*ppbBuffer))
                {
                    *pcbBuffer=dwSize;
                    fResult=TRUE;
                    goto CommonReturn;
                }

                if(*pcbBuffer < dwSize)
                {
                    *pcbBuffer=dwSize;
                    goto MoreDataError;
                }

                memcpy(*ppbBuffer, pwszName, dwSize);
                *pcbBuffer=dwSize;
            }
            else
            {
                *ppbBuffer=malloc(dwSize);
                if(NULL==(*ppbBuffer))
                    goto MemoryError;

                memcpy(*ppbBuffer, pwszName, dwSize);

                //pcbBuffer can be NULL in this case
            }
        }
        else
        {
            //we need to parse the string to make the multiple format
            if(!GetCertNameMulti(pwszName, idsPreFix, &pwszMulti))
                goto GetCertNameError;

            //calculate the bytes needee
            dwSize=sizeof(WCHAR)*(wcslen(pwszMulti)+1);

            //if FALSE==fToAllocate, we do not allocate the memory on user's
            //behalf; otherwize, allocate memory to eliminate the need for
            //double call
            if(FALSE==fToAllocate)
            {
                if(NULL==(*ppbBuffer))
                {
                    *pcbBuffer=dwSize;
                    fResult=TRUE;
                    goto CommonReturn;
                }

                if(*pcbBuffer < dwSize)
                {
                    *pcbBuffer=dwSize;
                    goto MoreDataError;
                }

                memcpy(*ppbBuffer, pwszMulti, dwSize);
                *pcbBuffer=dwSize;

            }
            else
            {
                *ppbBuffer=malloc(dwSize);
                if(NULL==(*ppbBuffer))
                    goto MemoryError;

                memcpy(*ppbBuffer, pwszMulti, dwSize);

                //pcbBuffer can be NULL in this case
            }
        }


        fResult=TRUE;


CommonReturn:

    if(pwszName)
        free(pwszName);

    if(pwszMulti)
        free(pwszMulti);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(CertNameToStrError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(GetCertNameError);

}

//--------------------------------------------------------------------------
//
//	 FormatBasicConstraints2:   szOID_BASIC_CONSTRAINTS2
//                              X509_BASIC_CONSTRAINTS2
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatBasicConstraints2(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
	WCHAR							wszSubject[SUBJECT_SIZE];
	WCHAR							wszNone[NONE_SIZE];
	PCERT_BASIC_CONSTRAINTS2_INFO	pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
	UINT							idsSub=0;

	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_BASIC_CONSTRAINTS2,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//load the string for the subjectType
    if (pInfo->fCA)
		idsSub=IDS_SUB_CA;
	else
		idsSub=IDS_SUB_EE;

	if(!LoadStringU(hFrmtFuncInst,idsSub, wszSubject, sizeof(wszSubject)/sizeof(wszSubject[0])))
		goto LoadStringError;

    if (pInfo->fPathLenConstraint)
	{
        //decide between signle line and multi line display
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsSub=IDS_BASIC_CONS2_PATH_MULTI;
        else
            idsSub=IDS_BASIC_CONS2_PATH;

        if(!FormatMessageUnicode(&pwszFormat,idsSub,
								wszSubject, pInfo->dwPathLenConstraint))
			goto FormatMsgError;
	}
    else
	{
		if(!LoadStringU(hFrmtFuncInst,IDS_NONE, wszNone, sizeof(wszNone)/sizeof(wszNone[0])))
			goto LoadStringError;

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsSub=IDS_BASIC_CONS2_NONE_MULTI;
        else
            idsSub=IDS_BASIC_CONS2_NONE;

        if(!FormatMessageUnicode(&pwszFormat,idsSub,
								wszSubject, wszNone))
			goto FormatMsgError;
	}


	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);

}


//--------------------------------------------------------------------------
//
//	 FormatSPCObject:
//
//   idsPreFix is the pre fix for mulit-line display
//--------------------------------------------------------------------------
BOOL FormatSPCObject(
	DWORD		                dwFormatType,
	DWORD		                dwFormatStrType,
    void		                *pFormatStruct,
    UINT                        idsPreFix,
    PSPC_SERIALIZED_OBJECT      pInfo,
    LPWSTR                      *ppwszFormat)
{

    BOOL        fResult=FALSE;
    LPWSTR      pwszHex=NULL;
    LPWSTR      pwszClassId=NULL;
    WCHAR       wszPreFix[PRE_FIX_SIZE];
    DWORD       cbNeeded=0;

    LPWSTR      pwszClassFormat=NULL;
    LPWSTR      pwszDataFormat=NULL;

    LPWSTR      pwszTemp;

    assert(pInfo);

    *ppwszFormat=NULL;

   //load the pre-dix
   if(0!=idsPreFix)
   {
       if(!LoadStringU(hFrmtFuncInst, idsPreFix,
                        wszPreFix, sizeof(wszPreFix)/sizeof(wszPreFix[0])))
        goto LoadStringError;

   }


    cbNeeded=0;

    if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->ClassId,
                        16,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

    pwszClassId=(LPWSTR)malloc(cbNeeded);
    if(NULL==pwszClassId)
         goto MemoryError;

    if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->ClassId,
                        16,
                        pwszClassId,
	                    &cbNeeded))
        goto FormatBytesToHexError;


    //format
    if(!FormatMessageUnicode(&pwszClassFormat, IDS_SPC_OBJECT_CLASS, pwszClassId))
            goto FormatMsgError;

    //strcat
    *ppwszFormat=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszClassFormat)+wcslen(wszPreFix)+wcslen(wszCOMMA)+1));
    if(NULL==*ppwszFormat)
        goto MemoryError;

    **ppwszFormat=L'\0';

    if(0!=idsPreFix)
        wcscat(*ppwszFormat, wszPreFix);

    wcscat(*ppwszFormat, pwszClassFormat);

    //format based on the availability of SerializedData
    if(0!=pInfo->SerializedData.cbData)
    {
        //cancatenate the ", " or \n"
        if(NULL != (*ppwszFormat))
        {
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
               wcscat(*ppwszFormat, wszCRLF);
            else
               wcscat(*ppwszFormat, wszCOMMA);
        }

       cbNeeded=0;

       if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->SerializedData.pbData,
                        pInfo->SerializedData.cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszHex=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszHex)
            goto MemoryError;

        if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->SerializedData.pbData,
                        pInfo->SerializedData.cbData,
                        pwszHex,
	                    &cbNeeded))
            goto FormatBytesToHexError;

          if(!FormatMessageUnicode(&pwszDataFormat, IDS_SPC_OBJECT_DATA,pwszHex))
            goto FormatMsgError;

        //strcat
        #if (0) // DSIE: Bug 27436
        *ppwszFormat=(LPWSTR)realloc(*ppwszFormat,
                sizeof(WCHAR)* (wcslen(*ppwszFormat)+wcslen(pwszDataFormat)+wcslen(wszPreFix)+1));
        if(NULL==*ppwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(*ppwszFormat,
                sizeof(WCHAR)* (wcslen(*ppwszFormat)+wcslen(pwszDataFormat)+wcslen(wszPreFix)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        *ppwszFormat = pwszTemp;

        if(0!=idsPreFix)
            wcscat(*ppwszFormat, wszPreFix);

        wcscat(*ppwszFormat, pwszDataFormat);

    }

	fResult=TRUE;
	

CommonReturn:
    if(pwszHex)
        free(pwszHex);

    if(pwszClassId)
        free(pwszClassId);

    if(pwszClassFormat)
        LocalFree((HLOCAL)pwszClassFormat);

    if(pwszDataFormat)
        LocalFree((HLOCAL)pwszDataFormat);

	return fResult;

ErrorReturn:
    if(*ppwszFormat)
    {
        free(*ppwszFormat);
        *ppwszFormat=NULL;
    }


	fResult=FALSE;
	goto CommonReturn;


TRACE_ERROR(FormatBytesToHexError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(LoadStringError);
}


//--------------------------------------------------------------------------
//
//	 FormatSPCLink:
//--------------------------------------------------------------------------
BOOL FormatSPCLink(
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
    void		*pFormatStruct,
    UINT        idsPreFix,
    PSPC_LINK   pInfo,
    LPWSTR      *ppwsz)
{

    BOOL        fResult=FALSE;
    LPWSTR      pwszObj=NULL;
    UINT        ids=0;
    LPWSTR      pwszFormat=NULL;


    assert(pInfo);

    *ppwsz=NULL;

    switch(pInfo->dwLinkChoice)
    {
        case SPC_URL_LINK_CHOICE:
                if(!FormatMessageUnicode(&pwszFormat, IDS_SPC_URL_LINK,pInfo->pwszUrl))
                    goto FormatMsgError;
            break;

        case SPC_MONIKER_LINK_CHOICE:
                if(!FormatSPCObject(
                            dwFormatType,
                            dwFormatStrType,
                            pFormatStruct,
                            idsPreFix,
                            &(pInfo->Moniker),
                            &pwszObj))
                    goto FormatSPCObjectError;


                //decide between single line and mulitple line format
                if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                    ids=IDS_SPC_MONIKER_LINK_MULTI;
                else
                    ids=IDS_SPC_MONIKER_LINK;

                if(!FormatMessageUnicode(&pwszFormat,ids,pwszObj))
                    goto FormatMsgError;
            break;


        case SPC_FILE_LINK_CHOICE:
               if(!FormatMessageUnicode(&pwszFormat, IDS_SPC_FILE_LINK, pInfo->pwszFile))
                    goto FormatMsgError;

            break;

        default:

               if(!FormatMessageUnicode(&pwszFormat, IDS_SPC_LINK_UNKNOWN,
                        pInfo->dwLinkChoice))
                    goto FormatMsgError;
    }

    *ppwsz=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszFormat)+1));
    if(NULL==(*ppwsz))
        goto MemoryError;

    memcpy(*ppwsz, pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat)+1));
	fResult=TRUE;
	

CommonReturn:

    if(pwszObj)
        free(pwszObj);

    if(pwszFormat)
        LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

    if(*ppwsz)
    {
        free(*ppwsz);
        *ppwsz=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(FormatMsgError);
TRACE_ERROR(FormatSPCObjectError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
}


//--------------------------------------------------------------------------
//
//	 FormatSPCImage:
//--------------------------------------------------------------------------
BOOL FormatSPCImage(
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
    void		*pFormatStruct,
    UINT        idsPreFix,
    PSPC_IMAGE  pInfo,
    LPWSTR      *ppwszImageFormat)
{
    BOOL        fResult=FALSE;
    LPWSTR       pwszFormat=NULL;
    LPWSTR       pwszLink=NULL;
    LPWSTR       pwszLinkFormat=NULL;
    LPWSTR      pwszHex=NULL;
    LPWSTR      pwszHexFormat=NULL;
    UINT        ids=0;

    DWORD       cbNeeded=0;

    LPWSTR      pwszTemp;

    assert(pInfo);

    //init
    *ppwszImageFormat=NULL;

	pwszFormat=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwszFormat)
        goto MemoryError;

    *pwszFormat=L'\0';

    if(pInfo->pImageLink)
    {
        if(!FormatSPCLink(dwFormatType,
                          dwFormatStrType,
                          pFormatStruct,
                          idsPreFix,
                          pInfo->pImageLink,
                          &pwszLink))
            goto FormatSPCLinkError;

       //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_IMAGE_LINK_MULTI;
        else
            ids=IDS_IMAGE_LINK;


        if(!FormatMessageUnicode(&pwszLinkFormat, ids,
                            &pwszLink))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
                    sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszLinkFormat)+1));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
                    sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszLinkFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszLinkFormat);
    }

    if(0!=pInfo->Bitmap.cbData)
    {
        //strcat ", "
        if(0!=wcslen(pwszFormat))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwszFormat, wszCOMMA);
        }

       cbNeeded=0;

       if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->Bitmap.pbData,
                        pInfo->Bitmap.cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszHex=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszHex)
            goto MemoryError;

        if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->Bitmap.pbData,
                        pInfo->Bitmap.cbData,
                        pwszHex,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_IMAGE_BITMAP_MULTI;
        else
            ids=IDS_IMAGE_BITMAP;


        if(!FormatMessageUnicode(&pwszHexFormat, ids, pwszHex))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszHexFormat);

       //free memory
        free(pwszHex);
        pwszHex=NULL;
        LocalFree((HLOCAL)pwszHexFormat);
        pwszHexFormat=NULL;

    }

   if(0!=pInfo->Metafile.cbData)
    {
        //strcat ", "
        if(0!=wcslen(pwszFormat))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwszFormat, wszCOMMA);
        }

       cbNeeded=0;

       if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->Metafile.pbData,
                        pInfo->Metafile.cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszHex=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszHex)
            goto MemoryError;

        if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->Metafile.pbData,
                        pInfo->Metafile.cbData,
                        pwszHex,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_IMAGE_METAFILE_MULTI;
        else
            ids=IDS_IMAGE_METAFILE;

        if(!FormatMessageUnicode(&pwszHexFormat, ids, pwszHex))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszHexFormat);

       //free memory
        free(pwszHex);
        pwszHex=NULL;
        LocalFree((HLOCAL)pwszHexFormat);
        pwszHexFormat=NULL;

    }

   if(0!=pInfo->EnhancedMetafile.cbData)
    {
        //strcat ", "
        if(0!=wcslen(pwszFormat))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwszFormat, wszCOMMA);
        }

       cbNeeded=0;

       if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->EnhancedMetafile.pbData,
                        pInfo->EnhancedMetafile.cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszHex=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszHex)
            goto MemoryError;

        if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->EnhancedMetafile.pbData,
                        pInfo->EnhancedMetafile.cbData,
                        pwszHex,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_IMAGE_ENHANCED_METAFILE_MULTI;
        else
            ids=IDS_IMAGE_ENHANCED_METAFILE;

        if(!FormatMessageUnicode(&pwszHexFormat, ids, pwszHex))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszHexFormat);

       //free memory
        free(pwszHex);
        pwszHex=NULL;
        LocalFree((HLOCAL)pwszHexFormat);
        pwszHexFormat=NULL;

    }

   if(0!=pInfo->GifFile.cbData)
    {
        //strcat ", "
        if(0!=wcslen(pwszFormat))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwszFormat, wszCOMMA);
        }

       cbNeeded=0;

       if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->GifFile.pbData,
                        pInfo->GifFile.cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszHex=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszHex)
            goto MemoryError;

        if(!FormatBytesToHex(
                        0,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        NULL,
                        pInfo->GifFile.pbData,
                        pInfo->GifFile.cbData,
                        pwszHex,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_IMAGE_GIFFILE_MULTI;
        else
            ids=IDS_IMAGE_GIFFILE;

        if(!FormatMessageUnicode(&pwszHexFormat, IDS_IMAGE_GIFFILE,
            pwszHex))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
            sizeof(WCHAR) *(wcslen(pwszFormat)+wcslen(wszCOMMA)+wcslen(pwszHexFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszHexFormat);

       //free memory
        free(pwszHex);
        pwszHex=NULL;
        LocalFree((HLOCAL)pwszHexFormat);
        pwszHexFormat=NULL;

    }

    if(0==wcslen(pwszFormat))
    {
        //fine if nothing is formatted
        *ppwszImageFormat=NULL;
    }
    else
    {
        *ppwszImageFormat=(LPWSTR)malloc(sizeof(WCHAR)*(wcslen(pwszFormat)+1));  
        #if (0) //  DSIE: Bug 27432 & 27434
        if(NULL == ppwszImageFormat)
        #endif
        if(NULL == *ppwszImageFormat)
            goto MemoryError;

        memcpy(*ppwszImageFormat, pwszFormat, sizeof(WCHAR)*(wcslen(pwszFormat)+1));
    }

	fResult=TRUE;
	

CommonReturn:
    if(pwszHex)
        free(pwszHex);

    if(pwszHexFormat)
        LocalFree((HLOCAL)pwszHexFormat);

    if(pwszLink)
        free(pwszLink);

    if(pwszLinkFormat)
        LocalFree((HLOCAL)pwszLinkFormat);

    if(pwszFormat)
        free(pwszFormat);

	return fResult;

ErrorReturn:

    if(*ppwszImageFormat)
    {
        free(*ppwszImageFormat);
        *ppwszImageFormat=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(FormatSPCLinkError);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);

}


//--------------------------------------------------------------------------
//
//	 FormatSPAgencyInfo:   SPC_SP_AGENCY_INFO_STRUCT
//                         SPC_SP_AGENCY_INFO_OBJID
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatSPAgencyInfo(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;
	PSPC_SP_AGENCY_INFO         	pInfo=NULL;

    LPWSTR                          pwszPolicyInfo=NULL;
    LPWSTR                          pwszPolicyInfoFormat=NULL;
    LPWSTR                          pwszLogoLink=NULL;
    LPWSTR                          pwszLogoLinkFormat=NULL;
    LPWSTR                          pwszPolicyDsplyFormat=NULL;
    LPWSTR                          pwszLogoImage=NULL;
    LPWSTR                          pwszLogoImageFormat=NULL;

	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;

    LPWSTR                          pwszTemp;
	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,SPC_SP_AGENCY_INFO_STRUCT,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;

    *pwsz=L'\0';

    //format pPolicyInformation
    if(pInfo->pPolicyInformation)
    {

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_TWO_TABS;
        else
            ids=0;

        if(!FormatSPCLink(dwFormatType,
                             dwFormatStrType,
                             pFormatStruct,
                             ids,
                             pInfo->pPolicyInformation,
                             &pwszPolicyInfo))
            goto FormatSPCLinkError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_AGENCY_POLICY_INFO_MULTI;
        else
            ids=IDS_AGENCY_POLICY_INFO;

        if(!FormatMessageUnicode(&pwszPolicyInfoFormat, ids, pwszPolicyInfo))
            goto FormatMsgError;

        //strcat
        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyInfoFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyInfoFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszPolicyInfoFormat);
    }


    //format pwszPolicyDisplayText
    if(pInfo->pwszPolicyDisplayText)
    {
        //strcat ", "
        if(0!=wcslen(pwsz))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwsz, wszCOMMA);
        }

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_AGENCY_POLICY_DSPLY_MULTI;
        else
            ids=IDS_AGENCY_POLICY_DSPLY;

        if(!FormatMessageUnicode(&pwszPolicyDsplyFormat, ids, pInfo->pwszPolicyDisplayText))
            goto FormatMsgError;

        //strcat
        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz,
            sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyDsplyFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwsz,
            sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyDsplyFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszPolicyDsplyFormat);
    }

    //pLogoImage
    if(pInfo->pLogoImage)
    {

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_THREE_TABS;
        else
            ids=0;


        if(!FormatSPCImage(dwFormatType,
                             dwFormatStrType,
                             pFormatStruct,
                             ids,
                             pInfo->pLogoImage,
                             &pwszLogoImage))
            goto FormatSPCImageError;

        //spcImage can include nothing
        if(NULL!=pwszLogoImage)
        {
            //strcat ", "
            if(0!=wcslen(pwsz))
            {
                if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }

            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_AGENCY_LOGO_IMAGE_MULTI;
            else
                ids=IDS_AGENCY_LOGO_IMAGE;


            if(!FormatMessageUnicode(&pwszLogoImageFormat,ids,pwszLogoImage))
                goto FormatMsgError;

            //strcat
            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz,
                sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszLogoImageFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz,
                sizeof(WCHAR) *(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszLogoImageFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszLogoImageFormat);
        }

    }

    //format pLogoLink
    if(pInfo->pLogoLink)
    {
        //strcat ", "
        if(0!=wcslen(pwsz))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwsz, wszCOMMA);
        }

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_TWO_TABS;
        else
            ids=0;


        if(!FormatSPCLink(dwFormatType,
                             dwFormatStrType,
                             pFormatStruct,
                             ids,
                             pInfo->pLogoLink,
                             &pwszLogoLink))
            goto FormatSPCLinkError;


        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_AGENCY_LOGO_LINK_MULTI;
        else
            ids=IDS_AGENCY_LOGO_LINK;

        if(!FormatMessageUnicode(&pwszLogoLinkFormat, ids, pwszLogoLink))
            goto FormatMsgError;

        //strcat
        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz,
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszLogoLinkFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwsz,
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszLogoLinkFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszLogoLinkFormat);
    }

    if(0==wcslen(pwsz))
    {
       //no data
        pwszFormat=(LPWSTR)malloc((NO_INFO_SIZE+1)*sizeof(WCHAR));
        if(NULL==pwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat, NO_INFO_SIZE))
            goto LoadStringError;

    }
    else
    {
        pwszFormat=pwsz;
        pwsz=NULL;
    }


	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwszPolicyInfo)
        free(pwszPolicyInfo);

    if(pwszPolicyInfoFormat)
        LocalFree((HLOCAL)pwszPolicyInfoFormat);

    if(pwszLogoLink)
        free(pwszLogoLink);

    if(pwszLogoLinkFormat)
        LocalFree((HLOCAL)pwszLogoLinkFormat);

    if(pwszPolicyDsplyFormat)
        LocalFree((HLOCAL)pwszPolicyDsplyFormat);

    if(pwszLogoImage)
        free(pwszLogoImage);

    if(pwszLogoImageFormat)
        LocalFree((HLOCAL)pwszLogoImageFormat);

	if(pwszFormat)
		free(pwszFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatSPCLinkError);
TRACE_ERROR(FormatSPCImageError);

}

//--------------------------------------------------------------------------
//
//	 GetNoticeNumberString:
//
//	 The memory should be allocated via malloc
//--------------------------------------------------------------------------
BOOL WINAPI	GetNoticeNumberString(	DWORD	cNoticeNumbers,
								int		*rgNoticeNumbers,
								LPWSTR	*ppwszNumber)
{
    BOOL		fResult=FALSE;
	WCHAR		wszNumber[INT_SIZE];
	DWORD		dwIndex=0;
    
    LPWSTR      pwszTemp;

	*ppwszNumber=NULL;

	if(NULL==rgNoticeNumbers || 0==cNoticeNumbers)
		goto InvalidArg;

	*ppwszNumber=(LPWSTR)malloc(sizeof(WCHAR));
	if(NULL==*ppwszNumber)
		goto MemoryError;

	**ppwszNumber=L'\0';

	for(dwIndex=0; dwIndex<cNoticeNumbers; dwIndex++)
	{
		wszNumber[0]='\0';

		_itow(rgNoticeNumbers[dwIndex], wszNumber, 10);

		if(wcslen(wszNumber) > 0)
		{
            #if (0) // DSIE: Bug 27436
			*ppwszNumber=(LPWSTR)realloc(*ppwszNumber,
				sizeof(WCHAR)*(wcslen(*ppwszNumber)+wcslen(wszNumber)+wcslen(wszCOMMA)+1));
			if(NULL==*ppwszNumber)
				goto MemoryError;
            #endif

			pwszTemp=(LPWSTR)realloc(*ppwszNumber,
				sizeof(WCHAR)*(wcslen(*ppwszNumber)+wcslen(wszNumber)+wcslen(wszCOMMA)+1));
			if(NULL==pwszTemp)
				goto MemoryError;
            *ppwszNumber = pwszTemp;

			wcscat(*ppwszNumber, wszNumber);

			if(dwIndex != (cNoticeNumbers-1))
				wcscat(*ppwszNumber, wszCOMMA);
		}
	}

	if(0==wcslen(*ppwszNumber))
		goto InvalidArg;

	fResult=TRUE;
	

CommonReturn:

	return fResult;

ErrorReturn:

	if(*ppwszNumber)
	{
		free(*ppwszNumber);
		*ppwszNumber=NULL;
	}

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
}


//--------------------------------------------------------------------------
//
//	 FormatCertQualifier:
//
//	 The memory should be allocated via malloc
//--------------------------------------------------------------------------
BOOL	FormatPolicyUserNotice(
						DWORD		        dwCertEncodingType,
						DWORD		        dwFormatType,
						DWORD		        dwFormatStrType,
						void		        *pFormatStruct,
						UINT				idsPreFix,
						BYTE				*pbEncoded,	
						DWORD				cbEncoded,
						LPWSTR				*ppwsz)
{
    BOOL							fResult=FALSE;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
	WCHAR							wszPreFix[PREFIX_SIZE];
	WCHAR							wszNextPre[PREFIX_SIZE];
	WCHAR							wszText[SUBJECT_SIZE];
	BOOL							fComma=FALSE;

	CERT_POLICY_QUALIFIER_USER_NOTICE	*pInfo=NULL;
	LPWSTR							pwszOrg=NULL;
	LPWSTR							pwszNumber=NULL;

    LPWSTR                          pwszTemp;

	*ppwsz=NULL;

    if (!DecodeGenericBLOB(dwCertEncodingType,	szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	if(!LoadStringU(hFrmtFuncInst,idsPreFix, wszPreFix, sizeof(wszPreFix)/sizeof(wszPreFix[0])))
		goto LoadStringError;

	if(!LoadStringU(hFrmtFuncInst,idsPreFix+1, wszNextPre, sizeof(wszNextPre)/sizeof(wszNextPre[0])))
		goto LoadStringError;

	if(NULL == pInfo->pNoticeReference && NULL == pInfo->pszDisplayText)
	{

        //load the string "Info Not Available"
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

        *ppwsz=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(wszNoInfo) + wcslen(wszPreFix) + POSTFIX_SIZE + 1));
		if(NULL==*ppwsz)
			goto MemoryError;  

		**ppwsz=L'\0';

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
			wcscat(*ppwsz, wszPreFix);

		wcscat(*ppwsz, wszNoInfo);

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
			wcscat(*ppwsz, wszCRLF);
	}
	else
	{
		*ppwsz=(LPWSTR)malloc(sizeof(WCHAR));
		if(NULL==*ppwsz)
			goto MemoryError; 

		**ppwsz=L'\0';

		if(pInfo->pNoticeReference)
		{

			if(!LoadStringU(hFrmtFuncInst,IDS_USER_NOTICE_REF, wszText, sizeof(wszText)/sizeof(wszText[0])))
				goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            *ppwsz=(LPWSTR)realloc(*ppwsz, 
                 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(wszPreFix)+POSTFIX_SIZE+1));
			if(NULL==*ppwsz)
				 goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(*ppwsz, 
                 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(wszPreFix)+POSTFIX_SIZE+1));
			if(NULL==pwszTemp)
				 goto MemoryError;
            *ppwsz = pwszTemp;

			if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
				wcscat(*ppwsz, wszPreFix);

			wcscat(*ppwsz, wszText);

			if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
				wcscat(*ppwsz, wszCRLF);

			if(pInfo->pNoticeReference->pszOrganization)
			{
				if(S_OK!=SZtoWSZ(pInfo->pNoticeReference->pszOrganization, &pwszOrg))
					goto SZtoWSZError;

				if(!LoadStringU(hFrmtFuncInst,IDS_USER_NOTICE_REF_ORG, wszText, sizeof(wszText)/sizeof(wszText[0])))
					goto LoadStringError;

                #if (0) // DSIE: Bug 27436
			    *ppwsz=(LPWSTR)realloc(*ppwsz, 
					 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pwszOrg)+wcslen(wszNextPre)+POSTFIX_SIZE+1));
    			if(NULL==*ppwsz)
					 goto MemoryError;
                #endif

			    pwszTemp=(LPWSTR)realloc(*ppwsz, 
					 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pwszOrg)+wcslen(wszNextPre)+POSTFIX_SIZE+1));
    			if(NULL==pwszTemp)
					 goto MemoryError;
                *ppwsz = pwszTemp;

				if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
					wcscat(*ppwsz, wszNextPre);

				wcscat(*ppwsz, wszText);
				wcscat(*ppwsz, pwszOrg);

				if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
					wcscat(*ppwsz, wszCRLF);
				else
				{
					wcscat(*ppwsz, wszCOMMA);
					fComma=TRUE;
				}
			}

			if(pInfo->pNoticeReference->cNoticeNumbers)
			{
				if(NULL == pInfo->pNoticeReference->rgNoticeNumbers)
					goto InvalidArg;

				if(!GetNoticeNumberString(pInfo->pNoticeReference->cNoticeNumbers,
										  pInfo->pNoticeReference->rgNoticeNumbers,
										  &pwszNumber))
					goto GetNumberError;

				if(!LoadStringU(hFrmtFuncInst,IDS_USER_NOTICE_REF_NUMBER, wszText, sizeof(wszText)/sizeof(wszText[0])))
					goto LoadStringError;

                #if (0) // DSIE: Bug 27436
    		    *ppwsz=(LPWSTR)realloc(*ppwsz, 
					 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pwszNumber)+wcslen(wszNextPre)+POSTFIX_SIZE+1));
				if(NULL==*ppwsz)
					 goto MemoryError;
                #endif

    		    pwszTemp=(LPWSTR)realloc(*ppwsz, 
					 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pwszNumber)+wcslen(wszNextPre)+POSTFIX_SIZE+1));
				if(NULL==pwszTemp)
					 goto MemoryError;
                *ppwsz = pwszTemp;

				if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
					wcscat(*ppwsz, wszNextPre);

				wcscat(*ppwsz, wszText);
				wcscat(*ppwsz, pwszNumber);

				if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
					wcscat(*ppwsz, wszCRLF);
				else
				{
					wcscat(*ppwsz, wszCOMMA);
					fComma=TRUE;
				}
			}
		}

		if(pInfo->pszDisplayText)
		{
			if(!LoadStringU(hFrmtFuncInst,IDS_USER_NOTICE_TEXT, wszText, sizeof(wszText)/sizeof(wszText[0])))
				goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            *ppwsz=(LPWSTR)realloc(*ppwsz, 
                 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pInfo->pszDisplayText)+wcslen(wszPreFix)+POSTFIX_SIZE+1));
		    if(NULL==*ppwsz)
				 goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(*ppwsz, 
                 sizeof(WCHAR) * (wcslen(*ppwsz)+wcslen(wszText)+wcslen(pInfo->pszDisplayText)+wcslen(wszPreFix)+POSTFIX_SIZE+1));
		    if(NULL==pwszTemp)
				 goto MemoryError;
            *ppwsz = pwszTemp;

			if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
				wcscat(*ppwsz, wszPreFix);

			wcscat(*ppwsz, wszText);
			wcscat(*ppwsz, pInfo->pszDisplayText);

			if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
				wcscat(*ppwsz, wszCRLF);
			else
			{
				wcscat(*ppwsz, wszCOMMA);
				fComma=TRUE;
			}
		}

		//get rid of the last comma
		if(fComma)
			*(*ppwsz+wcslen(*ppwsz)-wcslen(wszCOMMA))=L'\0';
	}

	fResult=TRUE;
	

CommonReturn:

	if(pInfo)
		free(pInfo);

	if(pwszOrg)
		free(pwszOrg);

	if(pwszNumber)
		free(pwszNumber);

	return fResult;

ErrorReturn:

	if(*ppwsz)
	{
		free(*ppwsz);
		*ppwsz=NULL;
	}

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(LoadStringError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(SZtoWSZError);
TRACE_ERROR(GetNumberError);
SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
}


//--------------------------------------------------------------------------
//
//	 FormatCertQualifier:
//--------------------------------------------------------------------------
BOOL FormatCertQualifier(
	DWORD		                    dwCertEncodingType,
	DWORD		                    dwFormatType,
	DWORD		                    dwFormatStrType,
	void		                    *pFormatStruct,
    PCERT_POLICY_QUALIFIER_INFO     pInfo,
    LPWSTR                          *ppwszFormat)
{
    BOOL				fResult=FALSE;
    DWORD				cbNeeded=0;
    UINT				ids=0;
    PCCRYPT_OID_INFO	pOIDInfo=NULL;

    LPWSTR				pwszName=NULL;
	LPWSTR				pwszElement=NULL;
	LPWSTR				pwszOID=NULL;

    *ppwszFormat=NULL;

	//get the oid name
	pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
				pInfo->pszPolicyQualifierId,
				0);

	if(NULL == pOIDInfo)
	{
		if(S_OK!=SZtoWSZ(pInfo->pszPolicyQualifierId, &pwszOID))
			goto SZtoWSZError;
	}

    if(pInfo->Qualifier.cbData)
    {
	   if(0==strcmp(szOID_PKIX_POLICY_QUALIFIER_CPS, pInfo->pszPolicyQualifierId))
	   {
			//this is just a unicode format
			//turn off the multi line here
		   cbNeeded=0;

			if(!FormatAnyUnicodeStringExtension(
					dwCertEncodingType,
					dwFormatType,
					dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
					pFormatStruct,
					pInfo->pszPolicyQualifierId,
					pInfo->Qualifier.pbData,
					pInfo->Qualifier.cbData,
					NULL,		
					&cbNeeded))
				goto FormatUnicodeError;

			pwszName=(LPWSTR)malloc(cbNeeded);
			if(NULL==pwszName)
				goto MemoryError;

			if(!FormatAnyUnicodeStringExtension(
					dwCertEncodingType,
					dwFormatType,
					dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
					pFormatStruct,
					pInfo->pszPolicyQualifierId,
					pInfo->Qualifier.pbData,
					pInfo->Qualifier.cbData,
					pwszName,		
					&cbNeeded))
				goto FormatUnicodeError;

	   }
	   else
	   {
			if(0==strcmp(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,pInfo->pszPolicyQualifierId))
			{
				//this is yet another struct to format.  We remember to have
				//a 3 tab prefix
				if(!FormatPolicyUserNotice(
								dwCertEncodingType,
								dwFormatType,
								dwFormatStrType,
								pFormatStruct,
								IDS_THREE_TABS,
								pInfo->Qualifier.pbData,
								pInfo->Qualifier.cbData,
								&pwszName))
					goto FormatUserNoticdeError;
			}
			else
			{
			   //get the Hex dump of the Key Usage
			   cbNeeded=0;

			   if(!FormatBytesToHex(
								dwCertEncodingType,
								dwFormatType,
								dwFormatStrType,
								pFormatStruct,
								NULL,
								pInfo->Qualifier.pbData,
								pInfo->Qualifier.cbData,
								NULL,
								&cbNeeded))
					goto FormatBytesToHexError;

				pwszName=(LPWSTR)malloc(cbNeeded);
				if(NULL==pwszName)
					goto MemoryError;

				if(!FormatBytesToHex(
								dwCertEncodingType,
								dwFormatType,
								dwFormatStrType,
								pFormatStruct,
								NULL,
								pInfo->Qualifier.pbData,
								pInfo->Qualifier.cbData,
								pwszName,
								&cbNeeded))
					goto FormatBytesToHexError;

			}
	   }

	   //add the desired 3 tab prefix and new line for CSP and the new line
	   //for the multi line case
	   if((dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) &&
		   (0!=strcmp(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,pInfo->pszPolicyQualifierId)))
	   {
			if(!FormatMessageUnicode(&pwszElement, IDS_POLICY_QUALIFIER_ELEMENT,
					pwszName))
				goto FormatMsgError;
	   }

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_POLICY_QUALIFIER_MULTI;
        else
            ids=IDS_POLICY_QUALIFIER;


        if(!FormatMessageUnicode(ppwszFormat, ids,
            pOIDInfo? pOIDInfo->pwszName : pwszOID, 
			pwszElement? pwszElement : pwszName))
            goto FormatMsgError;
    }
    else
    {
        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_POLICY_QUALIFIER_NO_BLOB_MULTI;
        else
            ids=IDS_POLICY_QUALIFIER_NO_BLOB;

        if(!FormatMessageUnicode(ppwszFormat, ids,
           pOIDInfo? pOIDInfo->pwszName : pwszOID))
            goto FormatMsgError;

    }

	fResult=TRUE;
	

CommonReturn:

    if(pwszName)
        free(pwszName);

	if(pwszElement)
		LocalFree((HLOCAL)pwszElement);

	if(pwszOID)
		free(pwszOID);

	return fResult;

ErrorReturn:

    if(*ppwszFormat)
    {
        LocalFree((HLOCAL)(*ppwszFormat));
        *ppwszFormat=NULL;
    }


	fResult=FALSE;
	goto CommonReturn;


TRACE_ERROR(FormatBytesToHexError);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatUnicodeError);
TRACE_ERROR(FormatUserNoticdeError);
TRACE_ERROR(SZtoWSZError);
}


//--------------------------------------------------------------------------
//
//	 FormatCertPolicies:     X509_CERT_POLICIES
//                           szOID_CERT_POLICIES
//                           szOID_APPLICATION_CERT_POLICIES
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatCertPolicies(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    LPWSTR                           pwsz=NULL;
    LPWSTR                           pwszPolicyFormat=NULL;
    LPWSTR                           pwszQualifiers=NULL;
    LPWSTR                           pwszQualifierFormat=NULL;
    LPWSTR                           pwszOneQualifier=NULL;
	LPWSTR							 pwszOID=NULL;

	PCERT_POLICIES_INFO	            pInfo=NULL;

    PCERT_POLICY_INFO               pPolicyInfo=NULL;
    DWORD                           dwIndex=0;
    DWORD                           dwQualifierIndex=0;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;
    PCCRYPT_OID_INFO                pOIDInfo=NULL;

    LPWSTR                          pwszTemp;
	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_CERT_POLICIES,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;

    *pwsz=L'\0';

    for(dwIndex=0; dwIndex < pInfo->cPolicyInfo; dwIndex++)
    {
        //strcat ", "
        if(0!=wcslen(pwsz))
        {
            if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
               wcscat(pwsz, wszCOMMA);
        }

        pPolicyInfo=&(pInfo->rgPolicyInfo[dwIndex]);


        pwszQualifiers=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwszQualifiers)
            goto MemoryError;

        *pwszQualifiers=L'\0';

         //format the qualifiers
         for(dwQualifierIndex=0;  dwQualifierIndex < pPolicyInfo->cPolicyQualifier;
            dwQualifierIndex++)
         {
            //strcat ", "
            if(0!=wcslen(pwszQualifiers))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwszQualifiers, wszCOMMA);
            }

            if(!FormatCertQualifier(dwCertEncodingType,
                                    dwFormatType,
                                    dwFormatStrType,
                                    pFormatStruct,
                                    &(pPolicyInfo->rgPolicyQualifier[dwQualifierIndex]),
                                    &pwszOneQualifier))
                   goto FormatCertQualifierError;

            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_POLICY_QUALIFIER_INFO_MULTI;
            else
                ids=IDS_POLICY_QUALIFIER_INFO;

             //format
             if(!FormatMessageUnicode(&pwszQualifierFormat,ids,
                    dwIndex+1,
                    dwQualifierIndex+1,
                    pwszOneQualifier))
                    goto FormatMsgError;

             //strcat
             #if (0) // DSIE: Bug 27436
             pwszQualifiers=(LPWSTR)realloc(pwszQualifiers, 
                 sizeof(WCHAR) * (wcslen(pwszQualifiers)+wcslen(wszCOMMA)+wcslen(pwszQualifierFormat)+1));
             if(NULL==pwszQualifiers)
                 goto MemoryError;
             #endif

             pwszTemp=(LPWSTR)realloc(pwszQualifiers, 
                 sizeof(WCHAR) * (wcslen(pwszQualifiers)+wcslen(wszCOMMA)+wcslen(pwszQualifierFormat)+1));
             if(NULL==pwszTemp)
                 goto MemoryError;
             pwszQualifiers = pwszTemp;

             wcscat(pwszQualifiers, pwszQualifierFormat);

             LocalFree((HLOCAL)pwszOneQualifier);
             pwszOneQualifier=NULL;

             LocalFree((HLOCAL)pwszQualifierFormat);
             pwszQualifierFormat=NULL;
         }

         //now, format the certPolicyInfo
		 pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
						pPolicyInfo->pszPolicyIdentifier,
					    0);

		 if(NULL == pOIDInfo)
		 {
			if(S_OK!=SZtoWSZ(pPolicyInfo->pszPolicyIdentifier, &pwszOID))
				goto SZtoWSZError;
		 }

         if(0!=pPolicyInfo->cPolicyQualifier)
         {
            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                if (0 == strcmp(lpszStructType, szOID_CERT_POLICIES))
                    ids=IDS_CERT_POLICY_MULTI;
                else
                    ids=IDS_APPLICATION_CERT_POLICY_MULTI;
            else
                if (0 == strcmp(lpszStructType, szOID_CERT_POLICIES))
                    ids=IDS_CERT_POLICY;
                else
                    ids=IDS_APPLICATION_CERT_POLICY;

             if(!FormatMessageUnicode(&pwszPolicyFormat,ids,
						dwIndex+1, pOIDInfo? pOIDInfo->pwszName : pwszOID,
                        pwszQualifiers))
                goto FormatMsgError;
         }
         else
         {
            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                if (0 == strcmp(lpszStructType, szOID_CERT_POLICIES))
                    ids=IDS_CERT_POLICY_NO_QUA_MULTI;
                else
                    ids=IDS_APPLICATION_CERT_POLICY_NO_QUA_MULTI;
            else
                if (0 == strcmp(lpszStructType, szOID_CERT_POLICIES))
                    ids=IDS_CERT_POLICY_NO_QUA;
                else
                    ids=IDS_APPLICATION_CERT_POLICY_NO_QUA;

             if(!FormatMessageUnicode(&pwszPolicyFormat, ids,
                        dwIndex+1, pOIDInfo? pOIDInfo->pwszName : pwszOID))
                goto FormatMsgError;
         }

         //strcat
         #if (0) // DSIE: Bug 27436
         pwsz=(LPWSTR)realloc(pwsz, 
             sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyFormat)+1));
         if(NULL==pwsz)
             goto MemoryError;
         #endif

         pwszTemp=(LPWSTR)realloc(pwsz, 
             sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyFormat)+1));
         if(NULL==pwszTemp)
             goto MemoryError;
         pwsz = pwszTemp;

         wcscat(pwsz, pwszPolicyFormat);

         free(pwszQualifiers);
         pwszQualifiers=NULL;

         LocalFree((HLOCAL)pwszPolicyFormat);
         pwszPolicyFormat=NULL;

		 if(pwszOID)
			free(pwszOID);
		 pwszOID=NULL;
    }


    if(0==wcslen(pwsz))
    {
       //no data
        pwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(NO_INFO_SIZE+1));
        if(NULL==pwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat, NO_INFO_SIZE))
            goto LoadStringError;

    }
    else
    {
        pwszFormat=pwsz;
        pwsz=NULL;
    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
	if(pwszOID)
		free(pwszOID);

    if(pwszOneQualifier)
        LocalFree((HLOCAL)pwszOneQualifier);

    if(pwszQualifierFormat)
        LocalFree((HLOCAL)pwszQualifierFormat);

    if(pwszQualifiers)
      free(pwszQualifiers);

    if(pwszPolicyFormat)
        LocalFree((HLOCAL)pwszPolicyFormat);

    if(pwsz)
        free(pwsz);

	if(pwszFormat)
		free(pwszFormat);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError,E_OUTOFMEMORY);
TRACE_ERROR(FormatCertQualifierError);
TRACE_ERROR(SZtoWSZError);
}


//--------------------------------------------------------------------------
//
//	 FormatCAVersion:   szOID_CERTSRV_CA_VERSION
//						Decode as X509_INTEGER
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatCAVersion(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	BOOL							fResult=FALSE;
	DWORD							cbNeeded=0;
	UINT							ids=0;
	DWORD							dwCAVersion=0;
	DWORD							cbCAVersion=sizeof(dwCAVersion);

	LPWSTR							pwszFormat=NULL;

	//check for input parameters
	if((NULL==pbEncoded && 0!=cbEncoded) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

	if(!CryptDecodeObject(dwCertEncodingType,X509_INTEGER,pbEncoded, cbEncoded,
		0,&dwCAVersion,&cbCAVersion))
		goto DecodeGenericError;

    //decide between single line and mulitple line format
    if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
        ids=IDS_CA_VERSION_MULTI;
    else
        ids=IDS_CA_VERSION;

	if(!FormatMessageUnicode(&pwszFormat, ids,
            CANAMEIDTOICERT(dwCAVersion), CANAMEIDTOIKEY(dwCAVersion)))
		goto FormatMsgError;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;

CommonReturn:

	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMsgError);
}

//--------------------------------------------------------------------------
//
//	 FormatNetscapeCertType:     
//							szOID_NETSCAPE_CERT_TYPE
//							Decode as X509_BITS
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatNetscapeCertType(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	BOOL							fResult=FALSE;
	DWORD							cbNeeded=0;
    WCHAR                           wszCertType[CERT_TYPE_SIZE+1];
	FORMAT_CERT_TYPE_INFO			rgCertType[]={
		  NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE,	IDS_NETSCAPE_SSL_CLIENT_AUTH,  //0x80
		  NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE,	IDS_NETSCAPE_SSL_SERVER_AUTH,  //0x40
		  NETSCAPE_SMIME_CERT_TYPE,          	IDS_NETSCAPE_SMIME,			   //0x20
		  NETSCAPE_SIGN_CERT_TYPE,           	IDS_NETSCAPE_SIGN,			   //0x10
		  0x08,									IDS_UNKNOWN_CERT_TYPE,		   //0x08
		  NETSCAPE_SSL_CA_CERT_TYPE,         	IDS_NETSCAPE_SSL_CA,		   //0x04	
		  NETSCAPE_SMIME_CA_CERT_TYPE,       	IDS_NETSCAPE_SMIME_CA,		   //0x02
		  NETSCAPE_SIGN_CA_CERT_TYPE, 			IDS_NETSCAPE_SIGN_CA};		   //0x01
	DWORD							dwCertType=0;
	DWORD							dwIndex=0;

	CRYPT_BIT_BLOB					*pInfo=NULL;
    LPWSTR                          pwsz=NULL;
    LPWSTR                          pwszByte=NULL;
	LPWSTR							pwszFormat=NULL;

    LPWSTR                          pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded && 0!=cbEncoded) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

   if(!DecodeGenericBLOB(dwCertEncodingType,X509_BITS,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;	 

    if(0==pInfo->cbData)
	   goto InvalidArg;

    pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;

    *pwsz=L'\0';

    //the count of bits to consider
	dwCertType=sizeof(rgCertType)/sizeof(rgCertType[0]);

	//we need to consider the unused bits in the last byte
	if((1 == pInfo->cbData) && (8 > pInfo->cUnusedBits))
	{
		dwCertType=8-pInfo->cUnusedBits;
	}

	for(dwIndex=0; dwIndex<dwCertType; dwIndex++)
	{
		if(pInfo->pbData[0] & rgCertType[dwIndex].bCertType)
		{
			if(!LoadStringU(hFrmtFuncInst, rgCertType[dwIndex].idsCertType, wszCertType, CERT_TYPE_SIZE))
				goto LoadStringError;

            #if (0) // DSIE: Bug 27436
			pwsz=(LPWSTR)realloc(pwsz, 
				sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCertType)+1+wcslen(wszCOMMA)));
			if(NULL==pwsz)
				goto MemoryError;
            #endif

			pwszTemp=(LPWSTR)realloc(pwsz, 
				sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCertType)+1+wcslen(wszCOMMA)));
			if(NULL==pwszTemp)
				goto MemoryError;
            pwsz = pwszTemp;

			wcscat(pwsz, wszCertType);
			wcscat(pwsz, wszCOMMA);
		}
	}

	//there is data that we can not interpret if the bit number is more than 8
	if(8 < (8 * pInfo->cbData - pInfo->cUnusedBits))
	{
		if(!LoadStringU(hFrmtFuncInst, IDS_UNKNOWN_CERT_TYPE, wszCertType, CERT_TYPE_SIZE))
			goto LoadStringError;

        #if (0) // DSIE: Bug 27436
		pwsz=(LPWSTR)realloc(pwsz, 
			sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCertType)+1+wcslen(wszCOMMA)));
		if(NULL==pwsz)
			goto MemoryError;
        #endif

		pwszTemp=(LPWSTR)realloc(pwsz, 
			sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCertType)+1+wcslen(wszCOMMA)));
		if(NULL==pwszTemp)
			goto MemoryError;
        pwsz = pwszTemp;

		wcscat(pwsz, wszCertType);
		wcscat(pwsz, wszCOMMA);
	}

	
    if(0==wcslen(pwsz))
    {
       #if (0) // DSIE: Bug 27436
       pwsz=(LPWSTR)realloc(pwsz, sizeof(WCHAR) * (CERT_TYPE_SIZE+1));
	   if(NULL == pwsz)
		   goto MemoryError;
       #endif

       pwszTemp=(LPWSTR)realloc(pwsz, sizeof(WCHAR) * (CERT_TYPE_SIZE+1));
	   if(NULL == pwszTemp)
		   goto MemoryError;
       pwsz = pwszTemp;

       if(!LoadStringU(hFrmtFuncInst, IDS_UNKNOWN_CERT_TYPE, pwsz,
           CERT_TYPE_SIZE))
		        goto LoadStringError;
    }
    else
    {
        //get rid of the last comma
        *(pwsz+wcslen(pwsz)-wcslen(wszCOMMA))=L'\0';
    }

    //get the Hex dump of the cert type
   cbNeeded=0;

   if(!FormatBytesToHex(
                    dwCertEncodingType,
                    dwFormatType,
                    dwFormatStrType,
                    pFormatStruct,
                    lpszStructType,
                    pInfo->pbData,
                    pInfo->cbData,
                    NULL,
	                &cbNeeded))
		goto FormatBytesToHexError;

    pwszByte=(LPWSTR)malloc(cbNeeded);
    if(NULL==pwszByte)
        goto MemoryError;

    if(!FormatBytesToHex(
                    dwCertEncodingType,
                    dwFormatType,
                    dwFormatStrType,
                    pFormatStruct,
                    lpszStructType,
                    pInfo->pbData,
                    pInfo->cbData,
                    pwszByte,
	                &cbNeeded))
        goto FormatBytesToHexError;


    //convert the WSZ
    if(!FormatMessageUnicode(&pwszFormat, IDS_BIT_BLOB, pwsz,
        pwszByte))
        goto FormatMsgError;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

	if(pInfo)
		free(pInfo);

    if(pwsz)
        free(pwsz);

    if(pwszByte)
        free(pwszByte);

	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);	
TRACE_ERROR(LoadStringError);
}


//--------------------------------------------------------------------------
//
//	 FormatAnyUnicodeStringExtension:     
//									szOID_ENROLLMENT_NAME_VALUE_PAIR
//									Decode as szOID_ENROLLMENT_NAME_VALUE_PAIR
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAnyNameValueStringAttr(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	BOOL								fResult=FALSE;
	DWORD								cbNeeded=0;
	UINT								ids=0;

	CRYPT_ENROLLMENT_NAME_VALUE_PAIR	*pInfo=NULL;
	LPWSTR								pwszFormat=NULL;

	//check for input parameters
	if((NULL==pbEncoded && 0!=cbEncoded) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,szOID_ENROLLMENT_NAME_VALUE_PAIR,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	if(NULL == pInfo->pwszName || NULL == pInfo->pwszValue)
		goto InvalidArg;

    //decide between single line and mulitple line format
    if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
        ids=IDS_NAME_VALUE_MULTI;
    else
        ids=IDS_NAME_VALUE;

	if(!FormatMessageUnicode(&pwszFormat, ids,
            pInfo->pwszName, pInfo->pwszValue))
		goto FormatMsgError;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

	if(pInfo)
		free(pInfo);

	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMsgError);
}


//--------------------------------------------------------------------------
//
//	 FormatAnyUnicodeStringExtension:     
//									szOID_ENROLL_CERTTYPE_EXTENSION
//									szOID_NETSCAPE_REVOCATION_URL
//									Decode as X509_ANY_UNICODE_STRING
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAnyUnicodeStringExtension(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	BOOL							fResult=FALSE;
	DWORD							cbNeeded=0;
	UINT							ids=0;

	CERT_NAME_VALUE					*pInfo=NULL;
	LPWSTR							pwszFormat=NULL;

	//check for input parameters
	if((NULL==pbEncoded && 0!=cbEncoded) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_UNICODE_ANY_STRING,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//the data can not be the encoded blob or the octect string
	if(!IS_CERT_RDN_CHAR_STRING(pInfo->dwValueType))
		goto DecodeGenericError;

    //decide between single line and mulitple line format
    if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
        ids=IDS_UNICODE_STRING_MULTI;
    else
        ids=IDS_UNICODE_STRING;

	if(!FormatMessageUnicode(&pwszFormat, ids,
            (LPWSTR)(pInfo->Value.pbData)))
		goto FormatMsgError;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

	if(pInfo)
		free(pInfo);

	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMsgError);
}


//--------------------------------------------------------------------------
//
//	 FormatDistPointName:  Pre-condition: dwDistPointNameChoice!=0
//--------------------------------------------------------------------------
BOOL    FormatDistPointName(DWORD		            dwCertEncodingType,
	                        DWORD		            dwFormatType,
	                        DWORD		            dwFormatStrType,
	                        void		            *pFormatStruct,
                            PCRL_DIST_POINT_NAME    pInfo,
                            LPWSTR                  *ppwszFormat)
{
    BOOL            fResult=FALSE;
    DWORD           cbNeeded=0;
    LPWSTR          pwszCRLIssuer=NULL;
    UINT            ids=0;

    *ppwszFormat=NULL;

    if(CRL_DIST_POINT_FULL_NAME==pInfo->dwDistPointNameChoice)
    {
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
              ids=IDS_THREE_TABS;

        cbNeeded=0;
        if(!FormatAltNameInfo(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 ids,
                                 FALSE,
                                 &(pInfo->FullName),
                                 NULL,
                                 &cbNeeded))
                goto FormatAltNameError;

        pwszCRLIssuer=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszCRLIssuer)
            goto MemoryError;

         if(!FormatAltNameInfo(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 ids,
                                 FALSE,
                                 &(pInfo->FullName),
                                 pwszCRLIssuer,
                                 &cbNeeded))
              goto FormatAltNameError;

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
              ids=IDS_CRL_DIST_FULL_NAME_MULTI;
        else
              ids=IDS_CRL_DIST_FULL_NAME;


         if(!FormatMessageUnicode(ppwszFormat, ids,pwszCRLIssuer))
             goto FormatMsgError;
    }
    else if(CRL_DIST_POINT_ISSUER_RDN_NAME==pInfo->dwDistPointNameChoice)
    {
        *ppwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(CRL_DIST_NAME_SIZE+1));
        if(NULL==*ppwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst, IDS_CRL_DIST_ISSUER_RDN,
                *ppwszFormat,CRL_DIST_NAME_SIZE))
            goto LoadStringError;

    }
    else
    {
        if(!FormatMessageUnicode(ppwszFormat, IDS_DWORD,
            pInfo->dwDistPointNameChoice))
            goto FormatMsgError;
    }

	fResult=TRUE;
	

CommonReturn:
    if(pwszCRLIssuer)
        free(pwszCRLIssuer);

	return fResult;

ErrorReturn:
    if(*ppwszFormat)
    {
        LocalFree((HLOCAL)(*ppwszFormat));
        *ppwszFormat=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;


TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatAltNameError);

}
//--------------------------------------------------------------------------
//
//	 FormatCRLReason:  Pre-condition: pReason.cbData != 0
//--------------------------------------------------------------------------
BOOL    FormatCRLReason(DWORD		    dwCertEncodingType,
	                    DWORD		    dwFormatType,
	                    DWORD		    dwFormatStrType,
	                    void		    *pFormatStruct,
	                    LPCSTR		    lpszStructType,
                        PCRYPT_BIT_BLOB pInfo,
                        LPWSTR          *ppwszFormat)
{
    LPWSTR                          pwszFormat=NULL;
    LPWSTR                          pwszByte=NULL;

    WCHAR                           wszReason[CRL_REASON_SIZE+1];
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;

    LPWSTR                          pwszTemp;

	*ppwszFormat=NULL;

    pwszFormat=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwszFormat)
        goto MemoryError;

    *pwszFormat=L'\0';

    //format the 1st byte
    if(pInfo->pbData[0] & CRL_REASON_UNUSED_FLAG)
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_UNSPECIFIED, wszReason, CRL_REASON_SIZE))
	        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(pInfo->pbData[0] & CRL_REASON_KEY_COMPROMISE_FLAG)
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_KEY_COMPROMISE, wszReason,CRL_REASON_SIZE))
	        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(pInfo->pbData[0] & CRL_REASON_CA_COMPROMISE_FLAG )
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_CA_COMPROMISE,wszReason, CRL_REASON_SIZE))
		        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
				sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
				sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }


    if(pInfo->pbData[0] & CRL_REASON_AFFILIATION_CHANGED_FLAG )
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_AFFILIATION_CHANGED, wszReason, CRL_REASON_SIZE))
	        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(pInfo->pbData[0] & CRL_REASON_SUPERSEDED_FLAG )
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_SUPERSEDED, wszReason, CRL_REASON_SIZE))
	        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
		pwszFormat=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

		pwszTemp=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(pInfo->pbData[0] & CRL_REASON_CESSATION_OF_OPERATION_FLAG )
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_CESSATION_OF_OPERATION, wszReason, CRL_REASON_SIZE))
		        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
				sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
				sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(pInfo->pbData[0] & CRL_REASON_CERTIFICATE_HOLD_FLAG  )
    {
        if(!LoadStringU(hFrmtFuncInst, IDS_CERTIFICATE_HOLD, wszReason, CRL_REASON_SIZE))
	        goto LoadStringError;

        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, 
			sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(wszReason)+1+wcslen(wszCOMMA)));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, wszReason);
        wcscat(pwszFormat, wszCOMMA);
    }

    if(0==wcslen(pwszFormat))
    {
        #if (0) // DSIE: Bug 27436
        pwszFormat=(LPWSTR)realloc(pwszFormat, sizeof(WCHAR) * (UNKNOWN_CRL_REASON_SIZE+1));
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormat, sizeof(WCHAR) * (UNKNOWN_CRL_REASON_SIZE+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        if(!LoadStringU(hFrmtFuncInst, IDS_UNKNOWN_CRL_REASON, pwszFormat,
            UNKNOWN_CRL_REASON_SIZE))
	            goto LoadStringError;
    }
    else
    {
        //get rid of the last comma
        *(pwszFormat+wcslen(pwszFormat)-wcslen(wszCOMMA))=L'\0';
    }

    //get the Hex dump of the Key Usage
    cbNeeded=0;

    if(!FormatBytesToHex(
                    dwCertEncodingType,
                    dwFormatType,
                    dwFormatStrType,
                    pFormatStruct,
                    lpszStructType,
                    pInfo->pbData,
                    pInfo->cbData,
                    NULL,
	                &cbNeeded))
        goto FormatBytesToHexError;

    pwszByte=(LPWSTR)malloc(cbNeeded);
    if(NULL==pwszByte)
        goto MemoryError;

    if(!FormatBytesToHex(
                    dwCertEncodingType,
                    dwFormatType,
                    dwFormatStrType,
                    pFormatStruct,
                    lpszStructType,
                    pInfo->pbData,
                    pInfo->cbData,
                    pwszByte,
	                &cbNeeded))
        goto FormatBytesToHexError;

    //convert the WSZ
    if(!FormatMessageUnicode(ppwszFormat, IDS_BIT_BLOB, pwszFormat,
        pwszByte))
        goto FormatMsgError;

	fResult=TRUE;
	
CommonReturn:
    if(pwszFormat)
        free(pwszFormat);

    if(pwszByte)
        free(pwszByte);

	return fResult;

ErrorReturn:
    if(*ppwszFormat)
    {
        LocalFree((HLOCAL)(*ppwszFormat));
        *ppwszFormat=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(LoadStringError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);
TRACE_ERROR(FormatMsgError);

}

//--------------------------------------------------------------------------
//
//	 FormatCRLDistPoints:   X509_CRL_DIST_POINTS
//                          szOID_CRL_DIST_POINTS
//                          szOID_FRESHEST_CRL
//                          szOID_CRL_SELF_CDP
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatCRLDistPoints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR					pwszFormat=NULL;
    LPWSTR                  pwsz=NULL;
    LPWSTR                  pwszEntryFormat=NULL;
    LPWSTR                  pwszEntryTagFormat=NULL;

    LPWSTR                  pwszPointName=NULL;
    LPWSTR                  pwszNameFormat=NULL;
    LPWSTR                  pwszCRLReason=NULL;
    LPWSTR                  pwszReasonFormat=NULL;
    LPWSTR                  pwszCRLIssuer=NULL;
    LPWSTR                  pwszIssuerFormat=NULL;

	PCRL_DIST_POINTS_INFO	pInfo=NULL;

	DWORD					cbNeeded=0;
    DWORD                   dwIndex=0;
	BOOL					fResult=FALSE;
    UINT                    ids=0;

    LPWSTR                  pwszTemp;
    LPCSTR                  pszOID;
    
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    //DSIE: Cert server encodes szOID_CRL_SEL_CDP using szOID_CRL_DIST_POINTS,
    //      so we need to change the lpszStructType for decoding.
    if (0 == strcmp(lpszStructType, szOID_CRL_SELF_CDP))
    {
        pszOID = szOID_CRL_DIST_POINTS;
    }
    else
    {
        pszOID = lpszStructType;
    }
    
    if (!DecodeGenericBLOB(dwCertEncodingType, pszOID, //lpszStructType,
			pbEncoded, cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;
    *pwsz=L'\0';

    for(dwIndex=0; dwIndex<pInfo->cDistPoint; dwIndex++)
    {
        //format distribution name
        if(0!=pInfo->rgDistPoint[dwIndex].DistPointName.dwDistPointNameChoice)
        {
            if(!FormatDistPointName(
                    dwCertEncodingType,
                    dwFormatType,
                    dwFormatStrType,
                    pFormatStruct,
                    &(pInfo->rgDistPoint[dwIndex].DistPointName),
                    &pwszPointName))
                goto FormatDistPointNameError;

           //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_CRL_DIST_NAME_MULTI;
            else
                ids=IDS_CRL_DIST_NAME;


            if(!FormatMessageUnicode(&pwszNameFormat, ids,pwszPointName))
                goto FormatMsgError;
        }

        //format the CRL reason
        if(0!=pInfo->rgDistPoint[dwIndex].ReasonFlags.cbData)
        {
            if(!FormatCRLReason(dwCertEncodingType,
                                dwFormatType,
                                dwFormatStrType,
                                pFormatStruct,
                                lpszStructType,
                                &(pInfo->rgDistPoint[dwIndex].ReasonFlags),
                                &pwszCRLReason))
                goto FormatCRLReasonError;


            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_CRL_DIST_REASON_MULTI;
            else
                ids=IDS_CRL_DIST_REASON;

            if(!FormatMessageUnicode(&pwszReasonFormat, ids ,pwszCRLReason))
                goto FormatMsgError;

        }

        //format the Issuer
       if(0!=pInfo->rgDistPoint[dwIndex].CRLIssuer.cAltEntry)
       {
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_TWO_TABS;
            else
                ids=0;


            cbNeeded=0;
            if(!FormatAltNameInfo(dwCertEncodingType,
                                  dwFormatType,
                                  dwFormatStrType,
                                  pFormatStruct,
                                  ids,
                                  FALSE,
                                  &(pInfo->rgDistPoint[dwIndex].CRLIssuer),
                                  NULL,
                                  &cbNeeded))
                goto FormatAltNameError;

           pwszCRLIssuer=(LPWSTR)malloc(cbNeeded);
           if(NULL==pwszCRLIssuer)
               goto MemoryError;

            if(!FormatAltNameInfo(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 ids,
                                 FALSE,
                                 &(pInfo->rgDistPoint[dwIndex].CRLIssuer),
                                 pwszCRLIssuer,
                                 &cbNeeded))
                goto FormatAltNameError;

            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_CRL_DIST_ISSUER_MULTI;
            else
                ids=IDS_CRL_DIST_ISSUER;

            if(!FormatMessageUnicode(&pwszIssuerFormat,ids,pwszCRLIssuer))
                goto FormatMsgError;
       }

       cbNeeded=0;

       if(pwszNameFormat)
           cbNeeded+=wcslen(pwszNameFormat);

       if(pwszReasonFormat)
           cbNeeded+=wcslen(pwszReasonFormat);

       if(pwszIssuerFormat)
           cbNeeded+=wcslen(pwszIssuerFormat);

       if(0!=cbNeeded)
       {
            //add ", " between each element for single line format
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
            {
                if(0!=wcslen(pwsz))
                    wcscat(pwsz, wszCOMMA);
            }

            //strcat all the information, including the COMMA
            cbNeeded += wcslen(wszCOMMA)*2;

            pwszEntryFormat=(LPWSTR)malloc(sizeof(WCHAR) * (cbNeeded+1));
            if(NULL==pwszEntryFormat)
                goto MemoryError;

            *pwszEntryFormat=L'\0';

            //strcat all three fields one at a time
            if(pwszNameFormat)
                wcscat(pwszEntryFormat, pwszNameFormat);

            if(pwszReasonFormat)
            {
                if(0!=wcslen(pwszEntryFormat))
                {
                    if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                        wcscat(pwszEntryFormat, wszCOMMA);
                }

                wcscat(pwszEntryFormat, pwszReasonFormat);
            }

            if(pwszIssuerFormat)
            {
                if(0!=wcslen(pwszEntryFormat))
                {
                    if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                        wcscat(pwszEntryFormat, wszCOMMA);
                }

                wcscat(pwszEntryFormat, pwszIssuerFormat);
            }

            //format the entry
            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                //
                // DSIE: Load appropriate format string.
                //
                if (0 == strcmp(lpszStructType, szOID_FRESHEST_CRL))
                    ids=IDS_FRESHEST_CRL_MULTI;
                else if (0 == strcmp(lpszStructType, szOID_CRL_SELF_CDP))
                    ids=IDS_CRL_SELF_CDP_MULTI;
                else
                    ids=IDS_CRL_DIST_ENTRY_MULTI;
            else
                if (0 == strcmp(lpszStructType, szOID_FRESHEST_CRL))
                    ids=IDS_FRESHEST_CRL;
                else if (0 == strcmp(lpszStructType, szOID_CRL_SELF_CDP))
                    ids=IDS_CRL_SELF_CDP;
                else
                    ids=IDS_CRL_DIST_ENTRY;

            if(!FormatMessageUnicode(&pwszEntryTagFormat, ids, dwIndex+1,
                pwszEntryFormat))
                goto FormatMsgError;

            //strcat the entry
            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszEntryTagFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszEntryTagFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszEntryTagFormat);

            //free memory
            free(pwszEntryFormat);
            pwszEntryFormat=NULL;

            LocalFree(pwszEntryTagFormat);
            pwszEntryTagFormat=NULL;
       }

       //free memory
       if(pwszPointName)
       {
           LocalFree((HLOCAL)pwszPointName);
           pwszPointName=NULL;
       }

       if(pwszCRLReason)
       {
           LocalFree((HLOCAL)(pwszCRLReason));
           pwszCRLReason=NULL;
       }

       if(pwszCRLIssuer)
       {
           free(pwszCRLIssuer);
           pwszCRLIssuer=NULL;
       }

       if(pwszNameFormat)
       {
            LocalFree((HLOCAL)pwszNameFormat);
            pwszNameFormat=NULL;
       }

       if(pwszReasonFormat)
       {
            LocalFree((HLOCAL)pwszReasonFormat);
            pwszReasonFormat=NULL;
       }

       if(pwszIssuerFormat)
       {
            LocalFree((HLOCAL)pwszIssuerFormat);
            pwszIssuerFormat=NULL;
       }
    }

    if(0==wcslen(pwsz))
    {
       //no data
        pwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(NO_INFO_SIZE+1));
        if(NULL==pwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat, NO_INFO_SIZE))
            goto LoadStringError;

    }
    else
    {
        pwszFormat=pwsz;
        pwsz=NULL;

    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
    if(pwszEntryFormat)
      free(pwszEntryFormat);

    if(pwszEntryTagFormat)
      LocalFree((HLOCAL)pwszEntryTagFormat);

    //free memory
    if(pwszPointName)
       LocalFree((HLOCAL)pwszPointName);

    if(pwszCRLReason)
       LocalFree((HLOCAL)(pwszCRLReason));

    if(pwszCRLIssuer)
       free(pwszCRLIssuer);

    if(pwszNameFormat)
        LocalFree((HLOCAL)pwszNameFormat);

    if(pwszReasonFormat)
        LocalFree((HLOCAL)pwszReasonFormat);

    if(pwszIssuerFormat)
        LocalFree((HLOCAL)pwszIssuerFormat);

    if(pwsz)
        free(pwsz);

	if(pwszFormat)
		free(pwszFormat);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatDistPointNameError);
TRACE_ERROR(FormatCRLReasonError);
TRACE_ERROR(FormatAltNameError);

}

//--------------------------------------------------------------------------
//
//	FormatCertPolicyID:
//
//      Pre-condition: pCertPolicyID has to include the valid information.that is,
//      cCertPolicyElementId can not be 0.
//--------------------------------------------------------------------------
BOOL FormatCertPolicyID(PCERT_POLICY_ID pCertPolicyID, LPWSTR  *ppwszFormat)
{

    BOOL        fResult=FALSE;
    LPSTR       pszFormat=NULL;
    DWORD       dwIndex=0;
    HRESULT     hr=S_OK;

    LPSTR       pwszTemp;

    *ppwszFormat=NULL;

    if(0==pCertPolicyID->cCertPolicyElementId)
        goto InvalidArg;

    pszFormat=(LPSTR)malloc(sizeof(CHAR));
    if(NULL==pszFormat)
        goto MemoryError;

    *pszFormat='\0';


    for(dwIndex=0; dwIndex<pCertPolicyID->cCertPolicyElementId; dwIndex++)
    {
        #if (0) // DSIE: Bug 27436
        pszFormat=(LPSTR)realloc(pszFormat, strlen(pszFormat)+
                strlen(pCertPolicyID->rgpszCertPolicyElementId[dwIndex])+strlen(strCOMMA)+1);
        if(NULL==pszFormat)
            goto MemoryError;
        #endif

        pwszTemp=(LPSTR)realloc(pszFormat, strlen(pszFormat)+
                strlen(pCertPolicyID->rgpszCertPolicyElementId[dwIndex])+strlen(strCOMMA)+1);
        if(NULL==pwszTemp)
            goto MemoryError;
        pszFormat = pwszTemp;

        strcat(pszFormat,pCertPolicyID->rgpszCertPolicyElementId[dwIndex]);

        strcat(pszFormat, strCOMMA);
    }

    //get rid of the last COMMA
    *(pszFormat+strlen(pszFormat)-strlen(strCOMMA))='\0';

    //convert to WCHAR
    if(S_OK!=(hr=SZtoWSZ(pszFormat, ppwszFormat)))
        goto SZtoWSZError;

	fResult=TRUE;

CommonReturn:

    if(pszFormat)
        free(pszFormat);

	return fResult;

ErrorReturn:
    if(*ppwszFormat)
    {
        free(*ppwszFormat);
        *ppwszFormat=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
SET_ERROR_VAR(SZtoWSZError,hr);
}

//--------------------------------------------------------------------------
//
//	 FormatKeyRestriction:   X509_KEY_USAGE_RESTRICTION
//                           szOID_KEY_USAGE_RESTRICTION
//
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatKeyRestriction(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							    pwszFormat=NULL;
    LPWSTR                              pwsz=NULL;
	PCERT_KEY_USAGE_RESTRICTION_INFO	pInfo=NULL;
    LPWSTR                              pwszPolicy=NULL;
    LPWSTR                              pwszPolicyFormat=NULL;
    LPWSTR                              pwszKeyUsage=NULL;
    LPWSTR                              pwszKeyUsageFormat=NULL;

	DWORD							    cbNeeded=0;
    DWORD                               dwIndex=0;
	BOOL							    fResult=FALSE;
    UINT                                ids=0;

    LPWSTR                              pwszTemp;
    
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_KEY_USAGE_RESTRICTION,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;

    *pwsz=L'\0';

    for(dwIndex=0; dwIndex<pInfo->cCertPolicyId; dwIndex++)
    {

       if(0!=((pInfo->rgCertPolicyId)[dwIndex].cCertPolicyElementId))
       {
            //concatecate the comma if not the 1st item
            if(0!=wcslen(pwsz))
            {
                if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }

            if(!FormatCertPolicyID(&((pInfo->rgCertPolicyId)[dwIndex]), &pwszPolicy))
                goto FormatCertPolicyIDError;

            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_KEY_RES_ID_MULTI;
            else
                ids=IDS_KEY_RES_ID;

            if(!FormatMessageUnicode(&pwszPolicyFormat, ids,dwIndex+1,pwszPolicy))
                goto FormatMsgError;

            //allocate memory, including the ", "
            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszPolicyFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszPolicyFormat);

            free(pwszPolicy);
            pwszPolicy=NULL;

            LocalFree((HLOCAL)pwszPolicyFormat);
            pwszPolicyFormat=NULL;
       }
    }

    //format the RestrictedKeyUsage
    if(0!=pInfo->RestrictedKeyUsage.cbData)
    {
       //concatecate the comma if not the 1st item
        if(0!=wcslen(pwsz))
        {
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                wcscat(pwsz, wszCOMMA);
        }


        cbNeeded=0;

        if(!FormatKeyUsageBLOB(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        &(pInfo->RestrictedKeyUsage),
                        NULL,
	                    &cbNeeded))
             goto FormatKeyUsageBLOBError;

        pwszKeyUsage=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszKeyUsage)
               goto MemoryError;

       if(!FormatKeyUsageBLOB(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        &(pInfo->RestrictedKeyUsage),
                        pwszKeyUsage,
	                    &cbNeeded))
              goto FormatKeyUsageBLOBError;

      //decide between single line and mulitple line format
      if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_KEY_RES_USAGE_MULTI;
       else
                ids=IDS_KEY_RES_USAGE;

        //format the element string
        if(!FormatMessageUnicode(&pwszKeyUsageFormat, ids, pwszKeyUsage))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszKeyUsageFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif
        
        pwszTemp=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszKeyUsageFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszKeyUsageFormat);
    }

    if(0==wcslen(pwsz))
    {
       //no data
        pwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(NO_INFO_SIZE+1));
        if(NULL==pwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat, NO_INFO_SIZE))
            goto LoadStringError;

    }
    else
    {
        pwszFormat=pwsz;
        pwsz=NULL;
    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
    if(pwszPolicy)
        free(pwszPolicy);

    if(pwszPolicyFormat)
        LocalFree((HLOCAL)pwszPolicyFormat);

    if(pwszKeyUsage)
        free(pwszKeyUsage);

    if(pwszKeyUsageFormat)
        LocalFree((HLOCAL)pwszKeyUsageFormat);

    if(pwszFormat)
		free(pwszFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatCertPolicyIDError);
TRACE_ERROR(FormatKeyUsageBLOBError);

}

//-----------------------------------------------------------------------
//
//	 FormatFileTime
//
//   Pre-condition: pFileTime points to valid data
//
//------------------------------------------------------------------------
BOOL	FormatFileTime(FILETIME *pFileTime,LPWSTR *ppwszFormat)
{
	SYSTEMTIME		SysTime;
	FILETIME		LocalFileTime;
	BOOL			fResult=FALSE;
    WCHAR           wszDay[DAY_SIZE];
    WCHAR           wszMonth[MONTH_SIZE];
    WCHAR           wszAMPM[AMPM_SIZE];
    UINT            idsDay=0;
    UINT            idsMonth=0;
    UINT            idsAMPM=0;

    *ppwszFormat=NULL;

	//now we format FileTime to SysTime as default.
	if(FileTimeToLocalFileTime(pFileTime, &LocalFileTime) && 
       FileTimeToSystemTime(&LocalFileTime,&SysTime))
	{
         if (SysTime.wHour < 12)
        {
            if (SysTime.wHour == 0)
            {
                SysTime.wHour = 12;
            }

            idsAMPM = IDS_AM;
        }
        else
        {
            if (SysTime.wHour > 12)
            {
                SysTime.wHour -= 12;
            }

            idsAMPM = IDS_PM;
        }

        //Sunday is 0
        idsDay=IDS_SUNDAY+SysTime.wDayOfWeek;

        //January is 1
        idsMonth=IDS_JAN+SysTime.wMonth-1;

        //load the string
        if(!LoadStringU(hFrmtFuncInst,idsDay, wszDay, sizeof(wszDay)/sizeof(wszDay[0])))
            goto LoadStringError;

        if(!LoadStringU(hFrmtFuncInst,idsMonth, wszMonth,
                    sizeof(wszMonth)/sizeof(wszMonth[0])))
            goto LoadStringError;

        if(!LoadStringU(hFrmtFuncInst,idsAMPM, wszAMPM,
                    sizeof(wszAMPM)/sizeof(wszAMPM[0])))
            goto LoadStringError;

        //"%s, %s %u, %u %u:%u:%u %s"
		if(!FormatMessageUnicode(ppwszFormat, IDS_FILE_TIME,
			 wszDay, wszMonth, SysTime.wDay, SysTime.wYear,
   			 SysTime.wHour, SysTime.wMinute, SysTime.wSecond, wszAMPM))
             goto FormatMsgError;
	}
	else
	{
	  	//if failed, pFileTime is more than 0x8000000000000000.
		// all we can do is to print out the integer
        //"HighDateTime: %d LowDateTime: %d"
        if(!FormatMessageUnicode(ppwszFormat, IDS_FILE_TIME_DWORD,
			pFileTime->dwHighDateTime, pFileTime->dwLowDateTime))
            goto FormatMsgError;
	}

	fResult=TRUE;

CommonReturn:

	return fResult;

ErrorReturn:
    if(*ppwszFormat)
    {
        LocalFree((HLOCAL)(*ppwszFormat));
        *ppwszFormat=NULL;
    }

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(FormatMsgError);
TRACE_ERROR(LoadStringError);

}




//--------------------------------------------------------------------------
//
//	 FormatKeyAttributes:   X509_KEY_ATTRIBUTES
//                          szOID_KEY_ATTRIBUTES
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatKeyAttributes(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{

    LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;

    LPWSTR                          pwszKeyIDFormat=NULL;
    LPWSTR                          pwszKeyID=NULL;

    LPWSTR                          pwszKeyUsageFormat=NULL;
    LPWSTR                          pwszKeyUsage=NULL;

    LPWSTR                          pwszKeyBeforeFormat=NULL;
    LPWSTR                          pwszKeyBefore=NULL;

    LPWSTR                          pwszKeyAfterFormat=NULL;
    LPWSTR                          pwszKeyAfter=NULL;
	PCERT_KEY_ATTRIBUTES_INFO   	pInfo=NULL;


	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;

    LPWSTR                          pwszTemp;
	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_KEY_ATTRIBUTES,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    pwsz=(LPWSTR)malloc(sizeof(WCHAR));
    if(NULL==pwsz)
        goto MemoryError;

    *pwsz=L'\0';


    if(0!=pInfo->KeyId.cbData)
    {
        cbNeeded=0;

        if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        pInfo->KeyId.pbData,
                        pInfo->KeyId.cbData,
                        NULL,
	                    &cbNeeded))
             goto FormatBytesToHexError;

        pwszKeyID=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszKeyID)
               goto MemoryError;

       if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        pInfo->KeyId.pbData,
                        pInfo->KeyId.cbData,
                        pwszKeyID,
	                    &cbNeeded))
              goto FormatBytesToHexError;


        //format the element string

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_KEY_ATTR_ID_MULTI;
        else
            ids=IDS_KEY_ATTR_ID;

        if(!FormatMessageUnicode(&pwszKeyIDFormat, ids, pwszKeyID))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszKeyIDFormat);
    }


    //check the no data situation
    if(0!=pInfo->IntendedKeyUsage.cbData)
    {
        //strcat a ", " symbol for signle line format
       if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
        {
            if(0!=wcslen(pwsz))
                wcscat(pwsz, wszCOMMA);
        }


        cbNeeded=0;

        if(!FormatKeyUsageBLOB(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        &(pInfo->IntendedKeyUsage),
                        NULL,
	                    &cbNeeded))
             goto FormatKeyUsageBLOBError;

        pwszKeyUsage=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszKeyUsage)
               goto MemoryError;

       if(!FormatKeyUsageBLOB(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        &(pInfo->IntendedKeyUsage),
                        pwszKeyUsage,
	                    &cbNeeded))
              goto FormatKeyUsageBLOBError;


        //format the element string

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            ids=IDS_KEY_ATTR_USAGE_MULTI;
        else
            ids=IDS_KEY_ATTR_USAGE;

        if(!FormatMessageUnicode(&pwszKeyUsageFormat, ids, pwszKeyUsage))
            goto FormatMsgError;

        #if (0) // DSIE: Bug 27436
        pwsz=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyUsageFormat)+1));
        if(NULL==pwsz)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwsz, 
            sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyUsageFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        wcscat(pwsz, pwszKeyUsageFormat);

    }

    if(NULL!=pInfo->pPrivateKeyUsagePeriod)
    {
        //format only if there is some information
        if(!((0==pInfo->pPrivateKeyUsagePeriod->NotBefore.dwHighDateTime)
           &&(0==pInfo->pPrivateKeyUsagePeriod->NotBefore.dwLowDateTime)))
        {
            //strcat a ", " symbol for signle line format
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
            {
                if(0!=wcslen(pwsz))
                    wcscat(pwsz, wszCOMMA);
            }


            if(!FormatFileTime(&(pInfo->pPrivateKeyUsagePeriod->NotBefore),
                            &pwszKeyBefore))
                goto FormatFileTimeError;


            //format the element string

            //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_KEY_ATTR_BEFORE_MULTI;
            else
                ids=IDS_KEY_ATTR_BEFORE;

            if(!FormatMessageUnicode(&pwszKeyBeforeFormat, ids,
                    pwszKeyBefore))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR)*(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyBeforeFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR)*(wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyBeforeFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszKeyBeforeFormat);
        }

        if(!((0==pInfo->pPrivateKeyUsagePeriod->NotAfter.dwHighDateTime)
           &&(0==pInfo->pPrivateKeyUsagePeriod->NotAfter.dwLowDateTime)))
        {

            //strcat a ", " symbol for signle line format
            if(0== (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
            {
                if(0!=wcslen(pwsz))
                    wcscat(pwsz, wszCOMMA);
            }


            if(!FormatFileTime(&(pInfo->pPrivateKeyUsagePeriod->NotAfter),
                            &pwszKeyAfter))
                goto FormatFileTimeError;

            //format the element string

           //decide between single line and mulitple line format
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_KEY_ATTR_AFTER_MULTI;
            else
                ids=IDS_KEY_ATTR_AFTER;

            if(!FormatMessageUnicode(&pwszKeyAfterFormat, ids,
                    pwszKeyAfter))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyAfterFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyAfterFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszKeyAfterFormat);

        }

    }

    if(0==wcslen(pwsz))
    {
       pwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(NO_INFO_SIZE+1));
       if(NULL==pwszFormat)
           goto MemoryError;

       if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat,NO_INFO_SIZE))
           goto LoadStringError;

    }
    else
    {
        pwszFormat=pwsz;
        pwsz=NULL;

    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwszKeyIDFormat)
        LocalFree((HLOCAL)pwszKeyIDFormat);

    if(pwszKeyID)
        free(pwszKeyID);

    if(pwszKeyUsageFormat)
        LocalFree((HLOCAL)pwszKeyUsageFormat);

    if(pwszKeyUsage)
        free(pwszKeyUsage);

    if(pwszKeyBeforeFormat)
        LocalFree((HLOCAL)pwszKeyBeforeFormat);

    if(pwszKeyBefore)
        LocalFree((HLOCAL)pwszKeyBefore);

    if(pwszKeyAfterFormat)
        LocalFree((HLOCAL)pwszKeyAfterFormat);

    if(pwszKeyAfter)
        LocalFree((HLOCAL)pwszKeyAfter);

	if(pwszFormat)
		free(pwszFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatKeyUsageBLOBError);
TRACE_ERROR(FormatFileTimeError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);
TRACE_ERROR(FormatMsgError);
}

//--------------------------------------------------------------------------
//
//	 FormatAuthortiyInfoAccess:   X509_AUTHORITY_INFO_ACCESS
//                                szOID_AUTHORITY_INFO_ACCESS
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAuthortiyInfoAccess(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
    BOOL                            fMethodAllocated=FALSE;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
    WCHAR                           wszUnknownAccess[UNKNOWN_ACCESS_METHOD_SIZE];
    PCCRYPT_OID_INFO                pOIDInfo=NULL;
    CERT_ALT_NAME_INFO              CertAltNameInfo;


	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;
    LPWSTR                          pwszMethod=NULL;
    LPWSTR                          pwszAltName=NULL;
    LPWSTR                          pwszEntryFormat=NULL;
	PCERT_AUTHORITY_INFO_ACCESS	    pInfo=NULL;

    DWORD                           dwIndex=0;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;

    LPWSTR                          pwszTemp;
    
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_AUTHORITY_INFO_ACCESS,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;


    if(0==pInfo->cAccDescr)
    {
        //load the string "Info Not Available"
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

        pwszFormat=wszNoInfo;
    }
    else
    {
        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;

        *pwsz=L'\0';

        //load the string "Unknown Access Method:
	    if(!LoadStringU(hFrmtFuncInst,IDS_UNKNOWN_ACCESS_METHOD, wszUnknownAccess,
            sizeof(wszUnknownAccess)/sizeof(wszUnknownAccess[0])))
		    goto LoadStringError;

        for(dwIndex=0; dwIndex < pInfo->cAccDescr; dwIndex++)
        {
            fMethodAllocated=FALSE;

            //need a ", " between each element for single line format
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) )
                    wcscat(pwsz, wszCOMMA);
            }

            //get the name of the access method
            if(pInfo->rgAccDescr[dwIndex].pszAccessMethod)
            {

                pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
									 (void *)(pInfo->rgAccDescr[dwIndex].pszAccessMethod),
									  CRYPT_EXT_OR_ATTR_OID_GROUP_ID);

                //get the access method OID
                if(pOIDInfo)
			    {
				    //allocate memory, including the NULL terminator
				    pwszMethod=(LPWSTR)malloc((wcslen(pOIDInfo->pwszName)+1)*
				    					sizeof(WCHAR));
				    if(NULL==pwszMethod)
					    goto MemoryError;

                    fMethodAllocated=TRUE;

				    wcscpy(pwszMethod,pOIDInfo->pwszName);

			    }else
                    pwszMethod=wszUnknownAccess;
            }

            memset(&CertAltNameInfo, 0, sizeof(CERT_ALT_NAME_INFO));
            CertAltNameInfo.cAltEntry=1;
            CertAltNameInfo.rgAltEntry=&(pInfo->rgAccDescr[dwIndex].AccessLocation);

            //need to tell if it is for multi line format.  We need two \t\t
            //in front of each alt name entry
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_TWO_TABS;
            else
                ids=0;

            //get the alternative name entry
            cbNeeded=0;
            if(!FormatAltNameInfo(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 ids,
                                 FALSE,
                                 &CertAltNameInfo,
                                 NULL,
                                 &cbNeeded))
                goto FormatAltNameError;

           pwszAltName=(LPWSTR)malloc(cbNeeded);
           if(NULL==pwszAltName)
               goto MemoryError;

            if(!FormatAltNameInfo(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 ids,
                                 FALSE,
                                 &CertAltNameInfo,
                                 pwszAltName,
                                 &cbNeeded))
                goto FormatAltNameError;

            //format the entry
            if(pInfo->rgAccDescr[dwIndex].pszAccessMethod)
            {

                //decide between single line and mulitple line format
                if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                    ids=IDS_AUTHORITY_ACCESS_INFO_MULTI;
                else
                    ids=IDS_AUTHORITY_ACCESS_INFO;


                if(!FormatMessageUnicode(&pwszEntryFormat, ids,
                    dwIndex+1, pwszMethod, pInfo->rgAccDescr[dwIndex].pszAccessMethod,
                    pwszAltName))
                    goto FormatMsgError;
            }
            else
            {
                //decide between single line and mulitple line format
                if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                    ids=IDS_AUTHORITY_ACCESS_NO_METHOD_MULTI;
                else
                    ids=IDS_AUTHORITY_ACCESS_NO_METHOD;


                if(!FormatMessageUnicode(&pwszEntryFormat, ids, dwIndex+1, pwszAltName))
                    goto FormatMsgError;

            }

            //reallocat the memory.  Leave space for szComma
            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszEntryFormat)+
                                        wcslen(wszCOMMA)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszEntryFormat)+
                                        wcslen(wszCOMMA)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, pwszEntryFormat);

            //free memory
            LocalFree((HLOCAL)pwszEntryFormat);
            pwszEntryFormat=NULL;

            free(pwszAltName);
            pwszAltName=NULL;

            if(TRUE==fMethodAllocated)
                free(pwszMethod);

            pwszMethod=NULL;

        }

        //convert to WCHAR
        pwszFormat=pwsz;
    }


	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwsz)
        free(pwsz);

    if(pwszEntryFormat)
         LocalFree((HLOCAL)pwszEntryFormat);

    if(pwszAltName)
        free(pwszAltName);

    if(fMethodAllocated)
    {
        if(pwszMethod)
             free(pwszMethod);
    }

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(FormatAltNameError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);

}

//--------------------------------------------------------------------------
//
//	 FormatKeyUsageBLOB
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatKeyUsageBLOB(
	DWORD		    dwCertEncodingType,
	DWORD		    dwFormatType,
	DWORD		    dwFormatStrType,
	void		    *pFormatStruct,
	LPCSTR		    lpszStructType,
    PCRYPT_BIT_BLOB	pInfo,
	void	        *pbFormat,
	DWORD	        *pcbFormat)
{
	LPWSTR							pwszFinal=NULL;
   	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;
    LPWSTR                          pwszByte=NULL;

    WCHAR                           wszKeyUsage[KEY_USAGE_SIZE+1];
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;

    LPWSTR                          pwszTemp;

        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;

        *pwsz=L'\0';

        //format the 1st byte
        if(pInfo->pbData[0] & CERT_DIGITAL_SIGNATURE_KEY_USAGE)
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_DIG_SIG, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        if(pInfo->pbData[0] & CERT_NON_REPUDIATION_KEY_USAGE)
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_NON_REPUDIATION, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        if(pInfo->pbData[0] & CERT_KEY_ENCIPHERMENT_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_KEY_ENCIPHERMENT, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
       }


        if(pInfo->pbData[0] & CERT_DATA_ENCIPHERMENT_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_DATA_ENCIPHERMENT, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        if(pInfo->pbData[0] & CERT_KEY_AGREEMENT_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_KEY_AGREEMENT, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        if(pInfo->pbData[0] & CERT_KEY_CERT_SIGN_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_CERT_SIGN, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
       }

         if(pInfo->pbData[0] & CERT_OFFLINE_CRL_SIGN_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_OFFLINE_CRL_SIGN, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        if(pInfo->pbData[0] & CERT_CRL_SIGN_KEY_USAGE )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_CRL_SIGN, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
       }

        if(pInfo->pbData[0] & CERT_ENCIPHER_ONLY_KEY_USAGE  )
        {
            if(!LoadStringU(hFrmtFuncInst, IDS_ENCIPHER_ONLY, wszKeyUsage, KEY_USAGE_SIZE))
		        goto LoadStringError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz, wszKeyUsage);
            wcscat(pwsz, wszCOMMA);
        }

        //deal with the second byte
        if(pInfo->cbData>=2)
        {

            if(pInfo->pbData[1] & CERT_DECIPHER_ONLY_KEY_USAGE  )
            {
                if(!LoadStringU(hFrmtFuncInst, IDS_DECIPHER_ONLY, wszKeyUsage, KEY_USAGE_SIZE))
		            goto LoadStringError;

                #if (0) // DSIE: Bug 27436
                pwsz=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
                if(NULL==pwsz)
                    goto MemoryError;
                #endif

                pwszTemp=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszKeyUsage)+1+wcslen(wszCOMMA)));
                if(NULL==pwszTemp)
                    goto MemoryError;
                pwsz = pwszTemp;

                wcscat(pwsz, wszKeyUsage);
                wcscat(pwsz, wszCOMMA);
            }
        }

        if(0==wcslen(pwsz))
        {
            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, sizeof(WCHAR) * (UNKNOWN_KEY_USAGE_SIZE+1));
		    // if(NULL==pwszFormat) DSIE: Bug 27348
		    if(NULL==pwsz)
				goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, sizeof(WCHAR) * (UNKNOWN_KEY_USAGE_SIZE+1));
		    if(NULL==pwszTemp)
				goto MemoryError;
            pwsz = pwszTemp;

            if(!LoadStringU(hFrmtFuncInst, IDS_UNKNOWN_KEY_USAGE, pwsz,
                UNKNOWN_KEY_USAGE_SIZE))
		            goto LoadStringError;
        }
        else
        {
            //get rid of the last comma
            *(pwsz+wcslen(pwsz)-wcslen(wszCOMMA))=L'\0';
        }

        //get the Hex dump of the Key Usage
       cbNeeded=0;

       if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        pInfo->pbData,
                        pInfo->cbData,
                        NULL,
	                    &cbNeeded))
            goto FormatBytesToHexError;

        pwszByte=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszByte)
            goto MemoryError;

        if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        pInfo->pbData,
                        pInfo->cbData,
                        pwszByte,
	                    &cbNeeded))
            goto FormatBytesToHexError;


    //convert the WSZ
    if(!FormatMessageUnicode(&pwszFormat, IDS_BIT_BLOB, pwsz,
        pwszByte))
        goto FormatMsgError;

	//
	// DSIE: Fix bug 91502, 256396.
	//
    pwszFinal=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszFormat)+1+wcslen(wszCRLF)));
    if(NULL==pwszFinal)
        goto MemoryError;
	wcscpy(pwszFinal, pwszFormat);
    if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
        wcscat(pwszFinal, wszCRLF);

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFinal)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}

	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFinal, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;

CommonReturn:

	if (pwszFinal)
		free(pwszFinal);

    if(pwszFormat)
        LocalFree((HLOCAL)pwszFormat);

    if(pwsz)
        free(pwsz);

    if(pwszByte)
        free(pwszByte);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);
TRACE_ERROR(FormatMsgError);

}
//--------------------------------------------------------------------------
//
//	 FormatKeyUsage:  X509_KEY_USAGE
//                    szOID_KEY_USAGE
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatKeyUsage(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
	PCRYPT_BIT_BLOB	                pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;

	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_KEY_USAGE,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

   //load the string "Info Not Available"
	if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		 goto LoadStringError;

    //check the no data situation
    if(0==pInfo->cbData)
        pwszFormat=wszNoInfo;
    else
    {
        if(1==pInfo->cbData)
        {
           if(0==pInfo->pbData[0])
                pwszFormat=wszNoInfo;
        }
        else
        {
            if(2==pInfo->cbData)
            {
                if((0==pInfo->pbData[0])&&(0==pInfo->pbData[1]))
                    pwszFormat=wszNoInfo;
            }
        }
    }

    if(NULL==pwszFormat)
    {
        fResult=FormatKeyUsageBLOB(dwCertEncodingType,
                                   dwFormatType,
                                   dwFormatStrType,
                                   pFormatStruct,
                                   lpszStructType,
                                   pInfo,
                                   pbFormat,
                                   pcbFormat);

        if(FALSE==fResult)
            goto FormatKeyUsageBLOBError;
    }
    else
    {
       	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	    //length only calculation
	    if(NULL==pbFormat)
	    {
		    *pcbFormat=cbNeeded;
		    fResult=TRUE;
		    goto CommonReturn;
    	}


	    if((*pcbFormat)<cbNeeded)
        {
            *pcbFormat=cbNeeded;
		    goto MoreDataError;
        }

	    //copy the data
	    memcpy(pbFormat, pwszFormat, cbNeeded);

	    //copy the size
	    *pcbFormat=cbNeeded;

	    fResult=TRUE;
    }


CommonReturn:
   	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatKeyUsageBLOBError);
}


//--------------------------------------------------------------------------
//
//	 FormatSMIMECapabilities:   PKCS_SMIME_CAPABILITIES
//                              szOID_RSA_SMIMECapabilities
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatSMIMECapabilities(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;
    LPWSTR                          pwszElementFormat=NULL;
    LPWSTR                          pwszParam=NULL;


	WCHAR							wszNoInfo[NO_INFO_SIZE];
    BOOL                            fParamAllocated=FALSE;
	PCRYPT_SMIME_CAPABILITIES	    pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    DWORD                           dwIndex =0;
    UINT                            idsSub=0;

	LPWSTR                          pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,PKCS_SMIME_CAPABILITIES,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//check to see if information if available
    if(0==pInfo->cCapability)
    {
         //load the string "Info Not Available"
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

        pwszFormat=wszNoInfo;
    }
    else
    {
        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;

        *pwsz=L'\0';

        for(dwIndex=0; dwIndex < pInfo->cCapability; dwIndex++)
        {
            fParamAllocated=FALSE;

           //strcat ", " if single line.  No need for multi-line
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                 wcscat(pwsz, wszCOMMA);
            }


            if(0!=(pInfo->rgCapability)[dwIndex].Parameters.cbData)
            {
                cbNeeded=0;

                if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        (pInfo->rgCapability)[dwIndex].Parameters.pbData,
                        (pInfo->rgCapability)[dwIndex].Parameters.cbData,
                        NULL,
	                    &cbNeeded))
                        goto FormatBytesToHexError;

                pwszParam=(LPWSTR)malloc(cbNeeded);
                if(NULL==pwszParam)
                    goto MemoryError;

                fParamAllocated=TRUE;

                if(!FormatBytesToHex(
                        dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        pFormatStruct,
                        lpszStructType,
                        (pInfo->rgCapability)[dwIndex].Parameters.pbData,
                        (pInfo->rgCapability)[dwIndex].Parameters.cbData,
                        pwszParam,
	                    &cbNeeded))
                        goto FormatBytesToHexError;

                //decide between single line and mulitple line format
                if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                    idsSub=IDS_MIME_CAPABILITY_MULTI;
                else
                    idsSub=IDS_MIME_CAPABILITY;

                 //format the element string
                if(!FormatMessageUnicode(&pwszElementFormat, idsSub,
                        dwIndex+1,
                        (pInfo->rgCapability)[dwIndex].pszObjId,
                        pwszParam))
                    goto FormatMsgError;
            }
            else
            {
                //decide between single line and mulitple line format
                if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                    idsSub=IDS_MIME_CAPABILITY_NO_PARAM_MULTI;
                else
                    idsSub=IDS_MIME_CAPABILITY_NO_PARAM;

                 //format the element string
                if(!FormatMessageUnicode(&pwszElementFormat, idsSub,
                        dwIndex+1,
                        (pInfo->rgCapability)[dwIndex].pszObjId))
                    goto FormatMsgError;
            }

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszElementFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszElementFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            //strcat the element
            wcscat(pwsz, pwszElementFormat);

            //free the memory
            LocalFree((HLOCAL)pwszElementFormat);
            pwszElementFormat=NULL;

            if(fParamAllocated)
                free(pwszParam);

            pwszParam=NULL;

        }

        pwszFormat=pwsz;

    }


	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwszElementFormat)
        LocalFree((HLOCAL)pwszElementFormat);

    if(fParamAllocated)
    {
        if(pwszParam)
            free(pwszParam);
    }


	if(pInfo)
		free(pInfo);

    if(pwsz)
        free(pwsz);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);
}

//--------------------------------------------------------------------------
//
//	 FormatFinancialCriteria: SPC_FINANCIAL_CRITERIA_OBJID
//                            SPC_FINANCIAL_CRITERIA_STRUCT
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatFinancialCriteria(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
	WCHAR							wszYesNo[YES_NO_SIZE];
	WCHAR							wszAvailable[AVAIL_SIZE];
	PSPC_FINANCIAL_CRITERIA     	pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            idsInfo=0;


	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,SPC_FINANCIAL_CRITERIA_STRUCT,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//load the string for financial info
    if(TRUE==pInfo->fFinancialInfoAvailable)
    {
        if(TRUE==pInfo->fMeetsCriteria)
            idsInfo=IDS_YES;
        else
            idsInfo=IDS_NO;

        //load the string for "yes" or "no"
        if(!LoadStringU(hFrmtFuncInst,idsInfo, wszYesNo, sizeof(wszYesNo)/sizeof(wszYesNo[0])))
		        goto LoadStringError;

        //mark the avaiblility of the financial info
        idsInfo=IDS_AVAILABLE;
    }
    else
        idsInfo=IDS_NOT_AVAILABLE;

	if(!LoadStringU(hFrmtFuncInst,idsInfo, wszAvailable,
        sizeof(wszAvailable)/sizeof(wszAvailable[0])))
		goto LoadStringError;

    //format the output string
    if(TRUE==pInfo->fFinancialInfoAvailable)
    {
        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsInfo=IDS_SPC_FINANCIAL_AVAIL_MULTI;
        else
            idsInfo=IDS_SPC_FINANCIAL_AVAIL;

        if(!FormatMessageUnicode(&pwszFormat, idsInfo,
            wszAvailable, wszYesNo))
            goto FormatMsgError;
    }
    else
    {
        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsInfo=IDS_SPC_FINANCIAL_NOT_AVAIL_MULTI;
        else
            idsInfo=IDS_SPC_FINANCIAL_NOT_AVAIL;

        if(!FormatMessageUnicode(&pwszFormat, idsInfo,
            wszAvailable))
            goto FormatMsgError;
    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);

}

//--------------------------------------------------------------------------
//
//	 FormatNextUpdateLocation: szOID_NEXT_UPDATE_LOCATION
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatNextUpdateLocation(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	PCERT_ALT_NAME_INFO	            pInfo=NULL;
	BOOL							fResult=FALSE;

	//check for input parameters
	if((NULL==pbEncoded && cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,szOID_NEXT_UPDATE_LOCATION,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//format the alternative name
    fResult=FormatAltNameInfo(dwCertEncodingType, dwFormatType,dwFormatStrType,
                            pFormatStruct,
                            0,      //no prefix
                            TRUE,
                            pInfo, pbFormat, pcbFormat);

    if(FALSE==fResult)
        goto FormatAltNameError;

CommonReturn:

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatAltNameError);

}

//--------------------------------------------------------------------------
//
//	 FormatSubjectKeyID: szOID_SUBJECT_KEY_IDENTIFIER
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatSubjectKeyID(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	PCRYPT_DATA_BLOB	            pInfo=NULL;
	BOOL							fResult=FALSE;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
    DWORD                           cbNeeded=0;

	// DSIE: Fix bug 91502
	LPWSTR							pwsz=NULL;
	LPWSTR							pwszFormat=NULL;
  
	LPWSTR                          pwszKeyID=NULL;
    LPWSTR                          pwszKeyIDFormat=NULL;

	LPWSTR							pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded && cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,szOID_SUBJECT_KEY_IDENTIFIER,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//format the key subject ID
    //handle NULL data case
    if(0==pInfo->cbData)
    {
         //load the string "Info Not Available"
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

		pwszFormat = wszNoInfo;
    }
    else
    {
        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;
        *pwsz=L'\0';

        cbNeeded=0;

        if(!FormatBytesToHex(dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        NULL,
                        NULL,
                        pInfo->pbData,
                        pInfo->cbData,
                        NULL,
                        &cbNeeded))
            goto KeyIDBytesToHexError;

        pwszKeyID=(LPWSTR)malloc(cbNeeded);
        if(NULL==pwszKeyID)
            goto MemoryError;

        if(!FormatBytesToHex(dwCertEncodingType,
                        dwFormatType,
                        dwFormatStrType,
                        NULL,
                        NULL,
                        pInfo->pbData,
                        pInfo->cbData,
                        pwszKeyID,
                        &cbNeeded))
            goto KeyIDBytesToHexError;

        if(!FormatMessageUnicode(&pwszKeyIDFormat,IDS_UNICODE_STRING,pwszKeyID))
            goto FormatMsgError;

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
	        pwszTemp=(LPWSTR)realloc(pwsz, 
		        sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszKeyIDFormat)+wcslen(wszCRLF)+1));
		else
	        pwszTemp=(LPWSTR)realloc(pwsz, 
		        sizeof(WCHAR) * (wcslen(pwsz)+wcslen(pwszKeyIDFormat)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwsz = pwszTemp;

        //strcat the KeyID
        wcscat(pwsz,pwszKeyIDFormat);

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            wcscat(pwsz, wszCRLF);

        pwszFormat=pwsz;
	}

    cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
	    *pcbFormat=cbNeeded;
	    fResult=TRUE;
	    goto CommonReturn;
	}

	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
	    goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;

CommonReturn:

    if(pwszKeyID)
       free(pwszKeyID);

    if(pwszKeyIDFormat)
        LocalFree((HLOCAL)pwszKeyIDFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(KeyIDBytesToHexError);
//TRACE_ERROR(FormatBytestToHexError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
}

//--------------------------------------------------------------------------
//
//	 FormatAuthorityKeyID: szOID_AUTHORITY_KEY_IDENTIFIER
//                         X509_AUTHORITY_KEY_ID
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAuthorityKeyID(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;

    LPWSTR                          pwszKeyID=NULL;
    LPWSTR                          pwszKeyIDFormat=NULL;
    LPWSTR                          pwszCertIssuer=NULL;
    LPWSTR                          pwszCertIssuerFormat=NULL;
    LPWSTR                          pwszCertNumber=NULL;
    LPWSTR                          pwszCertNumberFormat=NULL;
    BYTE                            *pByte=NULL;

    DWORD                           dwByteIndex=0;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
	PCERT_AUTHORITY_KEY_ID_INFO	    pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;

	LPWSTR                          pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded && cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_AUTHORITY_KEY_ID,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    //load the string "Info Not Available"
    if((0==pInfo->KeyId.cbData)&&(0==pInfo->CertIssuer.cbData)
        &&(0==pInfo->CertSerialNumber.cbData))
    {
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

        pwszFormat=wszNoInfo;
    }
    else
    {
        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;
        *pwsz=L'\0';

        //format the three fields in the struct: KeyID; CertIssuer; CertSerialNumber
        if(0!=pInfo->KeyId.cbData)
        {
            cbNeeded=0;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pInfo->KeyId.pbData,
                            pInfo->KeyId.cbData,
                            NULL,
                            &cbNeeded))
                goto KeyIDBytesToHexError;

            pwszKeyID=(LPWSTR)malloc(cbNeeded);
            if(NULL==pwszKeyID)
                goto MemoryError;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pInfo->KeyId.pbData,
                            pInfo->KeyId.cbData,
                            pwszKeyID,
                            &cbNeeded))
                goto KeyIDBytesToHexError;

            if(!FormatMessageUnicode(&pwszKeyIDFormat, IDS_AUTH_KEY_ID,pwszKeyID))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

#if (0) //DSIE: Potential AV. Need two more chars, \r\n, for multi-lines.
            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+1));
#else
			if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
				pwszTemp=(LPWSTR)realloc(pwsz, 
					sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+wcslen(wszCRLF)+1));
			else
				pwszTemp=(LPWSTR)realloc(pwsz, 
					sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszKeyIDFormat)+1));
#endif
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            //strcat the KeyID
            wcscat(pwsz,pwszKeyIDFormat);

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);
        }

        //format certIssuer
        if(0!=pInfo->CertIssuer.cbData)
        {
            //strcat ", " if there is data before
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }

            if(!CryptDllFormatNameAll(
				dwCertEncodingType,	
				dwFormatType,
				dwFormatStrType,
				pFormatStruct,
                IDS_ONE_TAB,
                TRUE,             //memory allocation
				pInfo->CertIssuer.pbData,
				pInfo->CertIssuer.cbData,
				(void **)&pwszCertIssuer,
				NULL))
                goto GetCertNameError;

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_AUTH_CERT_ISSUER_MULTI;
            else
                ids=IDS_AUTH_CERT_ISSUER;

            if(!FormatMessageUnicode(&pwszCertIssuerFormat, ids,pwszCertIssuer))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszCertIssuerFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszCertIssuerFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz,pwszCertIssuerFormat);

            //no need for \n for CERT_NAME
        }

        //format CertSerialNumber
        if(0!=pInfo->CertSerialNumber.cbData)
        {

            //strcat ", " if there is data before
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }

            //copy the serial number into the correct order
            pByte=(BYTE *)malloc(pInfo->CertSerialNumber.cbData);
            if(NULL==pByte)
                goto MemoryError;

            for(dwByteIndex=0; dwByteIndex <pInfo->CertSerialNumber.cbData;
                dwByteIndex++)
            {

                pByte[dwByteIndex]=*(pInfo->CertSerialNumber.pbData+
                        pInfo->CertSerialNumber.cbData-1-dwByteIndex);
            }

            cbNeeded=0;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pByte,
                            pInfo->CertSerialNumber.cbData,
                            NULL,
                            &cbNeeded))
                goto CertNumberBytesToHexError;

            pwszCertNumber=(LPWSTR)malloc(cbNeeded);
            if(NULL==pwszCertNumber)
                goto MemoryError;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pByte,
                            pInfo->CertSerialNumber.cbData,
                            pwszCertNumber,
                            &cbNeeded))
             goto CertNumberBytesToHexError;


            if(!FormatMessageUnicode(&pwszCertNumberFormat, IDS_AUTH_CERT_NUMBER,pwszCertNumber))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszCertNumberFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszCertNumberFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz,pwszCertNumberFormat);

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);

        }

        pwszFormat=pwsz;
    }


	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
    if(pByte)
        free(pByte);

    if(pwszKeyID)
       free(pwszKeyID);

    if(pwszKeyIDFormat)
        LocalFree((HLOCAL)pwszKeyIDFormat);

    if(pwszCertIssuer)
       free(pwszCertIssuer);

    if(pwszCertIssuerFormat)
        LocalFree((HLOCAL)pwszCertIssuerFormat);

    if(pwszCertNumber)
       free(pwszCertNumber);


    if(pwszCertNumberFormat)
        LocalFree((HLOCAL)pwszCertNumberFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(KeyIDBytesToHexError);
TRACE_ERROR(GetCertNameError);
TRACE_ERROR(CertNumberBytesToHexError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
}

//--------------------------------------------------------------------------
//
//	 FormatAuthorityKeyID2: szOID_AUTHORITY_KEY_IDENTIFIER2
//                          X509_AUTHORITY_KEY_ID2
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAuthorityKeyID2(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
    LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;

    LPWSTR                          pwszKeyID=NULL;
    LPWSTR                          pwszKeyIDFormat=NULL;
    LPWSTR                          pwszCertIssuer=NULL;
    LPWSTR                          pwszCertIssuerFormat=NULL;
    LPWSTR                          pwszCertNumber=NULL;
    LPWSTR                          pwszCertNumberFormat=NULL;
    BYTE                            *pByte=NULL;

    DWORD                           dwByteIndex=0;
    WCHAR                           wszNoInfo[NO_INFO_SIZE];
	PCERT_AUTHORITY_KEY_ID2_INFO	pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    UINT                            ids=0;

	LPWSTR                          pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded && cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_AUTHORITY_KEY_ID2,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    //load the string "Info Not Available"
    if((0==pInfo->KeyId.cbData)&&(0==pInfo->AuthorityCertIssuer.cAltEntry)
        &&(0==pInfo->AuthorityCertSerialNumber.cbData))
    {
	    if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		    goto LoadStringError;

        pwszFormat=wszNoInfo;
    }
    else
    {
        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;
        *pwsz=L'\0';

        //format the three fields in the struct: KeyID; CertIssuer; CertSerialNumber
        if(0!=pInfo->KeyId.cbData)
        {
            cbNeeded=0;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pInfo->KeyId.pbData,
                            pInfo->KeyId.cbData,
                            NULL,
                            &cbNeeded))
                goto KeyIDBytesToHexError;

            pwszKeyID=(LPWSTR)malloc(cbNeeded);
            if(NULL==pwszKeyID)
                goto MemoryError;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pInfo->KeyId.pbData,
                            pInfo->KeyId.cbData,
                            pwszKeyID,
                            &cbNeeded))
                goto KeyIDBytesToHexError;

            if(!FormatMessageUnicode(&pwszKeyIDFormat, IDS_AUTH_KEY_ID,pwszKeyID))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+
                                wcslen(pwszKeyIDFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+
                                wcslen(pwszKeyIDFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz,pwszKeyIDFormat);

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);

        }

        //format certIssuer
        if(0!=pInfo->AuthorityCertIssuer.cAltEntry)
        {
            //strcat ", " if there is data before
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }


            cbNeeded=0;

            //need a \t before each entry of the alternative name
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                ids=IDS_ONE_TAB;
            else
                ids=0;

            //format the alternative name
            if(!FormatAltNameInfo(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            pFormatStruct,
                            ids,
                            FALSE,
                            &(pInfo->AuthorityCertIssuer),
                            NULL,
                            &cbNeeded))
                goto FormatAltNameError;

            pwszCertIssuer=(LPWSTR)malloc(cbNeeded);
            if(NULL==pwszCertIssuer)
                goto MemoryError;

            if(!FormatAltNameInfo(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            pFormatStruct,
                            ids,
                            FALSE,
                            &(pInfo->AuthorityCertIssuer),
                            pwszCertIssuer,
                            &cbNeeded))
                goto FormatAltNameError;

            //format the element.  Has to distinguish between the multi line
            //and single line for alternative name:
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            {
                if(!FormatMessageUnicode(&pwszCertIssuerFormat, IDS_AUTH_CERT_ISSUER_MULTI,pwszCertIssuer))
                    goto FormatMsgError;
            }
            else
            {
                if(!FormatMessageUnicode(&pwszCertIssuerFormat, IDS_AUTH_CERT_ISSUER,pwszCertIssuer))
                    goto FormatMsgError;
            }

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)
                        +wcslen(pwszCertIssuerFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)
                        +wcslen(pwszCertIssuerFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz,pwszCertIssuerFormat);

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);
        }

        //format CertSerialNumber
        if(0!=pInfo->AuthorityCertSerialNumber.cbData)
        {
            //strcat ", " if there is data before
            if(0!=wcslen(pwsz))
            {
                if(0==(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
                    wcscat(pwsz, wszCOMMA);
            }

            //copy the serial number into the correct order
            pByte=(BYTE *)malloc(pInfo->AuthorityCertSerialNumber.cbData);
            if(NULL==pByte)
                goto MemoryError;

            for(dwByteIndex=0; dwByteIndex <pInfo->AuthorityCertSerialNumber.cbData;
                dwByteIndex++)
            {

                pByte[dwByteIndex]=*(pInfo->AuthorityCertSerialNumber.pbData+
                        pInfo->AuthorityCertSerialNumber.cbData-1-dwByteIndex);
            }

            cbNeeded=0;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pByte,
                            pInfo->AuthorityCertSerialNumber.cbData,
                            NULL,
                            &cbNeeded))
                goto CertNumberBytesToHexError;

            pwszCertNumber=(LPWSTR)malloc(cbNeeded);
            if(NULL==pwszCertNumber)
                goto MemoryError;

            if(!FormatBytesToHex(dwCertEncodingType,
                            dwFormatType,
                            dwFormatStrType,
                            NULL,
                            NULL,
                            pByte,
                            pInfo->AuthorityCertSerialNumber.cbData,
                            pwszCertNumber,
                            &cbNeeded))
                goto CertNumberBytesToHexError;

            if(!FormatMessageUnicode(&pwszCertNumberFormat, IDS_AUTH_CERT_NUMBER,pwszCertNumber))
                goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)
                    +wcslen(pwszCertNumberFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)
                    +wcslen(pwszCertNumberFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            wcscat(pwsz,pwszCertNumberFormat);

            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);
        }

        //convert the WCHAR version
        pwszFormat=pwsz;
    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}

	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;

CommonReturn:
    if(pByte)
        free(pByte);

    if(pwszKeyID)
       free(pwszKeyID);

    if(pwszKeyIDFormat)
        LocalFree((HLOCAL)pwszKeyIDFormat);

    if(pwszCertIssuer)
       free(pwszCertIssuer);

    if(pwszCertIssuerFormat)
        LocalFree((HLOCAL)pwszCertIssuerFormat);

    if(pwszCertNumber)
       free(pwszCertNumber);


    if(pwszCertNumberFormat)
        LocalFree((HLOCAL)pwszCertNumberFormat);

    if(pwsz)
        free(pwsz);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(KeyIDBytesToHexError);
TRACE_ERROR(FormatAltNameError);
TRACE_ERROR(CertNumberBytesToHexError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);

}

//--------------------------------------------------------------------------
//
//	 FormatBasicConstraints:   szOID_BASIC_CONSTRAINTS
//                             X509_BASIC_CONSTRAINTS
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatBasicConstraints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
	WCHAR							wszSubject[SUBJECT_SIZE * 2];
	WCHAR							wszNone[NONE_SIZE];
    LPWSTR                          pwszFormatSub=NULL;
    LPWSTR                          pwszFormatWhole=NULL;
    LPWSTR                          pwszSubtreeName=NULL;
    LPWSTR                          pwszSubtreeFormat=NULL;
    DWORD                           dwIndex=0;
	PCERT_BASIC_CONSTRAINTS_INFO	pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
	UINT							idsSub=0;

	LPWSTR                          pwszTemp;

	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_BASIC_CONSTRAINTS,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;


	//load the string for the subjectType
    //init to "\0"
    *wszSubject=L'\0';

    if(0!=pInfo->SubjectType.cbData)
    {
        //get the subjectType info
        if ((pInfo->SubjectType.pbData[0]) & CERT_CA_SUBJECT_FLAG)
        {
       	    if(!LoadStringU(hFrmtFuncInst,IDS_SUB_CA, wszSubject, sizeof(wszSubject)/sizeof(wszSubject[0])))
		        goto LoadStringError;
        }

        if ((pInfo->SubjectType.pbData[0]) & CERT_END_ENTITY_SUBJECT_FLAG)
        {
            if(wcslen(wszSubject)!=0)
            {
                 wcscat(wszSubject, wszCOMMA);
            }

       	    if(!LoadStringU(hFrmtFuncInst,IDS_SUB_EE, wszSubject+wcslen(wszSubject),
                        SUBJECT_SIZE))
		          goto LoadStringError;
       }

        //load string "NONE"
        if(0==wcslen(wszSubject))
        {
            if(!LoadStringU(hFrmtFuncInst,IDS_NONE, wszSubject, sizeof(wszSubject)/sizeof(wszSubject[0])))
		    goto LoadStringError;
        }

    }

    //path contraints
    if (pInfo->fPathLenConstraint)
	{
        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsSub=IDS_BASIC_CONS2_PATH_MULTI;
        else
            idsSub=IDS_BASIC_CONS2_PATH;

        if(!FormatMessageUnicode(&pwszFormatSub,idsSub,
								wszSubject, pInfo->dwPathLenConstraint))
			goto FormatMsgError;
	}
    else
	{
		if(!LoadStringU(hFrmtFuncInst,IDS_NONE, wszNone, sizeof(wszNone)/sizeof(wszNone[0])))
			goto LoadStringError;

        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsSub=IDS_BASIC_CONS2_NONE_MULTI;
        else
            idsSub=IDS_BASIC_CONS2_NONE;

        if(!FormatMessageUnicode(&pwszFormatSub,idsSub,
								wszSubject, wszNone))
			goto FormatMsgError;
	}

    pwszFormatWhole=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszFormatSub)+1));
    if(!pwszFormatWhole)
        goto MemoryError;

    wcscpy(pwszFormatWhole, pwszFormatSub);

    //now, format SubTreeContraints one at a time

   for(dwIndex=0; dwIndex<pInfo->cSubtreesConstraint; dwIndex++)
    {
        //get WCHAR version of the name
        if(!CryptDllFormatNameAll(
				dwCertEncodingType,	
				dwFormatType,
				dwFormatStrType,
				pFormatStruct,
                IDS_ONE_TAB,
                TRUE,                 //memory allocation
				pInfo->rgSubtreesConstraint[dwIndex].pbData,
				pInfo->rgSubtreesConstraint[dwIndex].cbData,
				(void **)&pwszSubtreeName,
				NULL))
                goto GetCertNameError;

        //decide between single line and mulitple line format
        if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            idsSub=IDS_SUBTREE_CONSTRAINT_MULTI;
        else
            idsSub=IDS_SUBTREE_CONSTRAINT;

        if(!FormatMessageUnicode(&pwszSubtreeFormat,idsSub,
								dwIndex+1, pwszSubtreeName))
			goto FormatNameError;

        #if (0) // DSIE: Bug 27436
        pwszFormatWhole=(LPWSTR)realloc(pwszFormatWhole, 
            sizeof(WCHAR) * (wcslen(pwszFormatWhole)+1+wcslen(pwszSubtreeFormat)));
        if(NULL == pwszFormatWhole)
            goto MemoryError;
        #endif

        pwszTemp=(LPWSTR)realloc(pwszFormatWhole, 
            sizeof(WCHAR) * (wcslen(pwszFormatWhole)+1+wcslen(pwszSubtreeFormat)));
        if(NULL == pwszTemp)
            goto MemoryError;
        pwszFormatWhole = pwszTemp;

        wcscat(pwszFormatWhole,pwszSubtreeFormat);

        LocalFree((HLOCAL)pwszSubtreeFormat);
        pwszSubtreeFormat=NULL;

        free(pwszSubtreeName);
        pwszSubtreeName=NULL;

    }

    //format to the wide char version
    pwszFormat=pwszFormatWhole;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwszFormatSub)
        LocalFree((HLOCAL)pwszFormatSub);

    if(pwszSubtreeFormat)
        LocalFree((HLOCAL)pwszSubtreeFormat);

    if(pwszFormatWhole)
        free(pwszFormatWhole);

    if(pwszSubtreeName)
        free(pwszSubtreeName);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
TRACE_ERROR(FormatNameError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(GetCertNameError);
}


//--------------------------------------------------------------------------
//
//	 FormatCRLReasonCode:szOID_CRL_REASON_CODE
//                         X509_CRL_REASON_CODE
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatCRLReasonCode(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	WCHAR							wszReason[CRL_REASON_SIZE];
    LPWSTR                          pwszFormat=NULL;
	int								*pInfo=NULL;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
	UINT							idsCRLReason=0;

	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_CRL_REASON_CODE,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//decide which ids to use
	switch(*pInfo)
	{
		case CRL_REASON_UNSPECIFIED:
				idsCRLReason=IDS_UNSPECIFIED;
			break;
		case CRL_REASON_KEY_COMPROMISE:
				idsCRLReason=IDS_KEY_COMPROMISE;
			break;
		case CRL_REASON_CA_COMPROMISE:
				idsCRLReason=IDS_CA_COMPROMISE;
			break;
		case CRL_REASON_AFFILIATION_CHANGED:
				idsCRLReason=IDS_AFFILIATION_CHANGED;
			break;
		case CRL_REASON_SUPERSEDED:
				idsCRLReason=IDS_SUPERSEDED;
			break;
		case CRL_REASON_CESSATION_OF_OPERATION:
				idsCRLReason=IDS_CESSATION_OF_OPERATION;
			break;
		case CRL_REASON_CERTIFICATE_HOLD:
				idsCRLReason=IDS_CERTIFICATE_HOLD;
			break;
		case CRL_REASON_REMOVE_FROM_CRL:
				idsCRLReason=IDS_REMOVE_FROM_CRL;
			break;
		default:
				idsCRLReason=IDS_UNKNOWN_CRL_REASON;
			break;
	}

	//load string
	if(!LoadStringU(hFrmtFuncInst,idsCRLReason, wszReason, sizeof(wszReason)/sizeof(wszReason[0])))
		goto LoadStringError;

    //format
    if(!FormatMessageUnicode(&pwszFormat, IDS_CRL_REASON, wszReason, *pInfo))
        goto FormatMsgError;

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:
    if(pwszFormat)
        LocalFree((HLOCAL)pwszFormat);

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);

}

//--------------------------------------------------------------------------
//
//	 FormatEnhancedKeyUsage: szOID_ENHANCED_KEY_USAGE
//							 X509_ENHANCED_KEY_USAGE
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatEnhancedKeyUsage(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
    BOOL                            fOIDNameAllocated=FALSE;
	WCHAR							wszNoInfo[NO_INFO_SIZE];
    WCHAR                           wszUnknownOID[UNKNOWN_KEY_USAGE_SIZE];
	PCCRYPT_OID_INFO                pOIDInfo=NULL;

    LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwszOIDName=NULL;
	PCERT_ENHKEY_USAGE				pInfo=NULL;
	LPWSTR							pwsz=NULL;
    LPWSTR                          pwszOIDFormat=NULL;

	DWORD							dwIndex=0;
    DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;

    LPWSTR                          pwszTemp;
    
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_ENHANCED_KEY_USAGE,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

	//load string NONE if there is no value available
	if(0==pInfo->cUsageIdentifier)
	{
		if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
			goto LoadStringError;

	    pwszFormat=wszNoInfo;
	}
	else
	{
        //load the string for "unknown key usage"
        if(!LoadStringU(hFrmtFuncInst,IDS_UNKNOWN_KEY_USAGE, wszUnknownOID,
            sizeof(wszUnknownOID)/sizeof(wszUnknownOID[0])))
			goto LoadStringError;

        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;
        *pwsz=L'\0';

		//build the comma/\n seperated string
		for(dwIndex=0; dwIndex<pInfo->cUsageIdentifier; dwIndex++)
        {
            fOIDNameAllocated=FALSE;

           	pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
									 (void *)(pInfo->rgpszUsageIdentifier[dwIndex]),
									  CRYPT_ENHKEY_USAGE_OID_GROUP_ID);

            if(pOIDInfo)
			{
				//allocate memory, including the NULL terminator
				pwszOIDName=(LPWSTR)malloc((wcslen(pOIDInfo->pwszName)+1)*
									sizeof(WCHAR));
				if(NULL==pwszOIDName)
					goto MemoryError;

                fOIDNameAllocated=TRUE;

				wcscpy(pwszOIDName,pOIDInfo->pwszName);

			}else
                pwszOIDName=wszUnknownOID;

            if(!FormatMessageUnicode(&pwszOIDFormat, IDS_ENHANCED_KEY_USAGE, pwszOIDName,
                          (pInfo->rgpszUsageIdentifier)[dwIndex]))
                   goto FormatMsgError;

            #if (0) // DSIE: Bug 27436
            pwsz=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+
                            wcslen(wszCOMMA)+wcslen(pwszOIDFormat)+1));
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            pwszTemp=(LPWSTR)realloc(pwsz, 
                sizeof(WCHAR) * (wcslen(pwsz)+
                            wcslen(wszCOMMA)+wcslen(pwszOIDFormat)+1));
            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            //strcat the OID
            wcscat(pwsz, pwszOIDFormat);

            //strcat the , or '\n'
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                wcscat(pwsz, wszCRLF);
            else
            {
                if(dwIndex!=(pInfo->cUsageIdentifier-1))
                    wcscat(pwsz, wszCOMMA);
            }


            LocalFree((HLOCAL)pwszOIDFormat);
            pwszOIDFormat=NULL;

            if(fOIDNameAllocated)
                free(pwszOIDName);

            pwszOIDName=NULL;
        }

        pwszFormat=pwsz;

	}

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}


	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

	if(pwsz)
		free(pwsz);

    if(pwszOIDFormat)
        LocalFree((HLOCAL)pwszOIDFormat);

    if(fOIDNameAllocated)
    {
        if(pwszOIDName)
            free(pwszOIDName);
    }


	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatMsgError);
}

//--------------------------------------------------------------------------
//
//	 GetOtherName:
//
//		The idsPreFix is for multi line formatting only.
//		It should never be 0.
//--------------------------------------------------------------------------
BOOL GetOtherName(	DWORD		            dwCertEncodingType,
					DWORD		            dwFormatType,
					DWORD                   dwFormatStrType,
					void	            	*pFormatStruct,
					CERT_OTHER_NAME			*pOtherName,
					UINT					idsPreFix,
					LPWSTR					*ppwszOtherName)
{

	BOOL				fResult=FALSE;
	PCCRYPT_OID_INFO	pOIDInfo=NULL;
	DWORD				cbSize=0;
	WCHAR				wszPreFix[PREFIX_SIZE];

    LPWSTR              pwszObjId   = NULL;
	LPWSTR				pwszName=NULL;
	LPWSTR				pwszFormat=NULL;

	if(NULL == pOtherName || NULL == ppwszOtherName)
		goto InvalidArg;

	*ppwszOtherName=NULL;

	//get the OID name
	pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
							pOtherName->pszObjId,
							0);

	//get the value.  If OID is szOID_NT_PRINCIPAL_NAME, we format it 
	//as the unicode string.  Otherwise, we hex dump
	if(0 == strcmp(szOID_NT_PRINCIPAL_NAME, pOtherName->pszObjId))
	{
		//turn off the multi line here
		if(!FormatAnyUnicodeStringExtension(
				dwCertEncodingType,
				dwFormatType,
				dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
				pFormatStruct,
				pOtherName->pszObjId,
				pOtherName->Value.pbData,
				pOtherName->Value.cbData,
				NULL,		
				&cbSize))
			goto FormatUnicodeError;

		pwszName=(LPWSTR)malloc(cbSize);
		if(NULL==pwszName)
			goto MemoryError;

		if(!FormatAnyUnicodeStringExtension(
				dwCertEncodingType,
				dwFormatType,
				dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
				pFormatStruct,
				pOtherName->pszObjId,
				pOtherName->Value.pbData,
				pOtherName->Value.cbData,
				pwszName,		
				&cbSize))
			goto FormatUnicodeError;
	}
	else
	{
		if(!FormatBytesToHex(dwCertEncodingType,
							dwFormatType,
							dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
							pFormatStruct,
							NULL,
							pOtherName->Value.pbData,
							pOtherName->Value.cbData,
							NULL,
							&cbSize))
			goto FormatByesToHexError;

		pwszName=(LPWSTR)malloc(cbSize);
		if(NULL==pwszName)
			goto MemoryError;

		if(!FormatBytesToHex(dwCertEncodingType,
							dwFormatType,
							dwFormatStrType & (~CRYPT_FORMAT_STR_MULTI_LINE),
							pFormatStruct,
							NULL,
							pOtherName->Value.pbData,
							pOtherName->Value.cbData,
							pwszName,
							&cbSize))
			goto FormatByesToHexError;
	}

	if(pOIDInfo)
	{
		if(!FormatMessageUnicode(&pwszFormat,
                                 IDS_OTHER_NAME_OIDNAME, 
                                 pOIDInfo->pwszName,
			                     pwszName))
			goto FormatMsgError;
	}
	else
	{
        //
        // Convert OID to Unicode.
        //
        if (!AllocateAnsiToUnicode(pOtherName->pszObjId, &pwszObjId))
            goto AnsiToUnicodeError;

		if(!FormatMessageUnicode(&pwszFormat,IDS_OTHER_NAME_OID, pwszObjId,	pwszName))
			goto FormatMsgError;
	}

	//copy the prefix and content
    if(!LoadStringU(hFrmtFuncInst,idsPreFix, wszPreFix, sizeof(wszPreFix)/sizeof(wszPreFix[0])))
		    goto LoadStringError;

	*ppwszOtherName=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(wszPreFix) + wcslen(pwszFormat) + 1));
	if(NULL == *ppwszOtherName)
		goto MemoryError;

	**ppwszOtherName=L'\0';

	if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
		wcscat(*ppwszOtherName, wszPreFix);

	wcscat(*ppwszOtherName, pwszFormat);

	fResult=TRUE;
	

CommonReturn:

    if (pwszObjId)
        free(pwszObjId);

	if(pwszName)
		free(pwszName);

	if(pwszFormat)
		LocalFree((HLOCAL)pwszFormat);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(FormatByesToHexError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(AnsiToUnicodeError);
TRACE_ERROR(FormatUnicodeError);
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMsgError);
}

//--------------------------------------------------------------------------
//
//	 FormatAltNameInfo:
//
//--------------------------------------------------------------------------
BOOL FormatAltNameInfo(
    DWORD		            dwCertEncodingType,
	DWORD		            dwFormatType,
    DWORD                   dwFormatStrType,
    void	            	*pFormatStruct,
    UINT                    idsPreFix,
    BOOL                    fNewLine,
    PCERT_ALT_NAME_INFO	    pInfo,
    void	                *pbFormat,
	DWORD	                *pcbFormat)
{
	
	LPWSTR							pwszFormat=NULL;
    LPWSTR                          pwsz=NULL;

    LPWSTR                          pwszAltEntryFormat=NULL;
    LPWSTR                          pwszAltEntry=NULL;

	WCHAR							wszNoInfo[NO_INFO_SIZE];
    WCHAR                           wszAltName[ALT_NAME_SIZE];
    WCHAR                           wszPreFix[PRE_FIX_SIZE];
    BOOL                            fEntryAllocated=FALSE;
    DWORD                           dwIndex=0;
	DWORD							cbNeeded=0;
	BOOL							fResult=FALSE;
    HRESULT                         hr=S_OK;
    UINT                            idsAltEntryName=0;

    LPWSTR                          pwszTemp;
    
    //load the string "info not available"
    if(!LoadStringU(hFrmtFuncInst,IDS_NO_ALT_NAME, wszNoInfo, sizeof(wszNoInfo)/sizeof(wszNoInfo[0])))
		goto LoadStringError;

	//build the list of alternative name entries
    //1st, check if any information is available
    if(0==pInfo->cAltEntry)
    {
	    pwszFormat=wszNoInfo;
    }
    else
    {
        //load the pre-dix
        if(0!=idsPreFix)
        {
            if(!LoadStringU(hFrmtFuncInst, idsPreFix,
                        wszPreFix, sizeof(wszPreFix)/sizeof(wszPreFix[0])))
                goto LoadStringError;

        }

        pwsz=(LPWSTR)malloc(sizeof(WCHAR));
        if(NULL==pwsz)
            goto MemoryError;

        //NULL terminate the string
        *pwsz=L'\0';

        //build the list of alternative name entries
        for(dwIndex=0; dwIndex<pInfo->cAltEntry; dwIndex++)
        {
			// DSIE: Fix bug 128630.
			cbNeeded = 0;

            fEntryAllocated=FALSE;

             switch((pInfo->rgAltEntry)[dwIndex].dwAltNameChoice)
             {
                case CERT_ALT_NAME_OTHER_NAME:
                         if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                            idsAltEntryName=IDS_OTHER_NAME_MULTI;
                         else
                            idsAltEntryName=IDS_OTHER_NAME;

						 if(!GetOtherName(
							 dwCertEncodingType,
                             dwFormatType,
                             dwFormatStrType,
                             pFormatStruct,
							 (pInfo->rgAltEntry)[dwIndex].pOtherName,
							 (0!=idsPreFix) ? idsPreFix+1 : IDS_ONE_TAB,
							 &pwszAltEntry))
								goto GetOtherNameError;

						 fEntryAllocated=TRUE;

                    break;

                case CERT_ALT_NAME_RFC822_NAME:
                         idsAltEntryName=IDS_RFC822_NAME;
                         pwszAltEntry=(pInfo->rgAltEntry)[dwIndex].pwszRfc822Name;
                    break;
                case CERT_ALT_NAME_DNS_NAME:
                         idsAltEntryName=IDS_DNS_NAME;
                         pwszAltEntry=(pInfo->rgAltEntry)[dwIndex].pwszDNSName;
                   break;

                case CERT_ALT_NAME_X400_ADDRESS:
                         idsAltEntryName=IDS_X400_ADDRESS;
                         pwszAltEntry=wszNoInfo;
                   break;

                case CERT_ALT_NAME_DIRECTORY_NAME:
                         if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
                            idsAltEntryName=IDS_DIRECTORY_NAME_MULTI;
                         else
                            idsAltEntryName=IDS_DIRECTORY_NAME;

                        if(!CryptDllFormatNameAll(
				            dwCertEncodingType,	
				            dwFormatType,
				            dwFormatStrType,
				            pFormatStruct,
                            (0!=idsPreFix) ? idsPreFix+1 : IDS_ONE_TAB,
                            TRUE,           //memory allocation
				            (pInfo->rgAltEntry)[dwIndex].DirectoryName.pbData,
				            (pInfo->rgAltEntry)[dwIndex].DirectoryName.cbData,
				            (void **)&pwszAltEntry,
				            NULL))
                            goto GetCertNameError;

                         fEntryAllocated=TRUE;

                    break;

                case CERT_ALT_NAME_EDI_PARTY_NAME:
                        idsAltEntryName=IDS_EDI_PARTY_NAME;
                        pwszAltEntry=wszNoInfo;
                    break;

                case CERT_ALT_NAME_URL:
                         idsAltEntryName=IDS_URL;
                         pwszAltEntry=(pInfo->rgAltEntry)[dwIndex].pwszURL;
                   break;

                case CERT_ALT_NAME_IP_ADDRESS:
                        idsAltEntryName=IDS_IP_ADDRESS;

#if (0) // DSIE: 7/25/2000
                        if(!FormatBytesToHex(dwCertEncodingType,
                                            dwFormatType,
                                            dwFormatStrType,
                                            pFormatStruct,
                                            NULL,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.pbData,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.cbData,
                                            NULL,
                                            &cbNeeded))
                            goto FormatByesToHexError;

                        pwszAltEntry=(LPWSTR)malloc(cbNeeded);
                        if(NULL==pwszAltEntry)
                            goto MemoryError;

                        if(!FormatBytesToHex(dwCertEncodingType,
                                            dwFormatType,
                                            dwFormatStrType,
                                            pFormatStruct,
                                            NULL,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.pbData,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.cbData,
                                            pwszAltEntry,
                                            &cbNeeded))
                            goto FormatByesToHexError;
#else
                        if (!FormatIPAddress(dwCertEncodingType,
                                            dwFormatType,
                                            dwFormatStrType,
                                            pFormatStruct,
                                            NULL,
                                            idsPreFix,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.pbData,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.cbData,
                                            pwszAltEntry,
                                            &cbNeeded))
                            goto FormatIPAddressError;

                        pwszAltEntry=(LPWSTR)malloc(cbNeeded);
                        if(NULL==pwszAltEntry)
                            goto MemoryError;

                        if (!FormatIPAddress(dwCertEncodingType,
                                            dwFormatType,
                                            dwFormatStrType,
                                            pFormatStruct,
                                            NULL,
                                            idsPreFix,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.pbData,
                                            (pInfo->rgAltEntry)[dwIndex].IPAddress.cbData,
                                            pwszAltEntry,
                                            &cbNeeded))
                            goto FormatIPAddressError;
#endif
                        fEntryAllocated=TRUE;

                    break;

                case CERT_ALT_NAME_REGISTERED_ID:
                        idsAltEntryName=IDS_REGISTERED_ID;

                        if(S_OK!=(hr=SZtoWSZ((pInfo->rgAltEntry)[dwIndex].pszRegisteredID,
                                            &pwszAltEntry)))
                            goto SZtoWSZError;

                        fEntryAllocated=TRUE;
                    break;

                default:
                        idsAltEntryName=IDS_UNKNOWN_VALUE;
                        pwszAltEntry=wszNoInfo;
                    break;

             }

             //load the alternative name string
            if(!LoadStringU(hFrmtFuncInst,idsAltEntryName, wszAltName, sizeof(wszAltName)/sizeof(wszAltName[0])))
		            goto LoadStringError;

            //format message
            if(idsAltEntryName!=IDS_UNKNOWN_VALUE)
            {
                if(!FormatMessageUnicode(&pwszAltEntryFormat,IDS_ALT_NAME_ENTRY, wszAltName,
                    pwszAltEntry))
                    goto FormatMsgError;
            }
            else
            {
                if(!FormatMessageUnicode(&pwszAltEntryFormat,IDS_ALT_NAME_ENTRY_UNKNOWN, wszAltName,
                    (pInfo->rgAltEntry)[dwIndex].dwAltNameChoice))
                    goto FormatMsgError;
            }

            //concatenate the string, including the postfix and prefix if necessary
            if(0!=idsPreFix)
            {
                #if (0) // DSIE: Bug 27436
                pwsz=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(wszPreFix)+wcslen(pwszAltEntryFormat)+1));
                #endif

                pwszTemp=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(wszPreFix)+wcslen(pwszAltEntryFormat)+1));
            }
            else
            {
                #if (0) // DSIE: Bug 27436
                pwsz=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszAltEntryFormat)+1));
                #endif

                pwszTemp=(LPWSTR)realloc(pwsz, 
                    sizeof(WCHAR) * (wcslen(pwsz)+wcslen(wszCOMMA)+wcslen(pwszAltEntryFormat)+1));
            }

            #if (0) // DSIE: Bug 27436
            if(NULL==pwsz)
                goto MemoryError;
            #endif

            if(NULL==pwszTemp)
                goto MemoryError;
            pwsz = pwszTemp;

            //strcat the preFix
            if(0!=idsPreFix)
                wcscat(pwsz, wszPreFix);

            //strcat the entry
            wcscat(pwsz, pwszAltEntryFormat);

            //strcat the postFix
            if(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
            {
                if((TRUE==fNewLine) || (dwIndex != (pInfo->cAltEntry-1)))
                {
                    //no need for \n if the name is directory name (CERT_NAME)
                    //in multi line format
                    if(idsAltEntryName !=IDS_DIRECTORY_NAME_MULTI)
                        wcscat(pwsz, wszCRLF);
                }

            }
            else
            {
                if(dwIndex != (pInfo->cAltEntry-1))
                    wcscat(pwsz, wszCOMMA);
            }

            LocalFree((HLOCAL)pwszAltEntryFormat);
            pwszAltEntryFormat=NULL;

            if(fEntryAllocated)
                free(pwszAltEntry);
            pwszAltEntry=NULL;
        }

        //if the last entry in the alternative name is  IDS_DIRECTORY_NAME_MULTI,
        //we need to get rid of the last \n if fNewLine is FALSE
        if(FALSE==fNewLine)
        {
            if(idsAltEntryName==IDS_DIRECTORY_NAME_MULTI)
            {
                *(pwsz+wcslen(pwsz)-wcslen(wszCRLF))=L'\0';
            }
        }

        //conver to the WCHAR format

        pwszFormat=pwsz;
    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}

	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;
	

CommonReturn:

    if(pwsz)
        free(pwsz);

    if(pwszAltEntryFormat)
        LocalFree((HLOCAL)pwszAltEntryFormat);

    if(fEntryAllocated)
    {
        if(pwszAltEntry)
            free(pwszAltEntry);
    }


	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(LoadStringError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(FormatMsgError);
SET_ERROR_VAR(SZtoWSZError, hr);
TRACE_ERROR(GetCertNameError);
#if (0) //DSIE
TRACE_ERROR(FormatByesToHexError);
#else
TRACE_ERROR(FormatIPAddressError);
#endif
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(GetOtherNameError);
}

//--------------------------------------------------------------------------
//
//	 FormatAltName:  X509_ALTERNATE_NAME
//                   szOID_SUBJECT_ALT_NAME
//                   szOID_ISSUER_ALT_NAME
//                   szOID_SUBJECT_ALT_NAME2
//                   szOID_ISSUER_ALT_NAME2
//
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatAltName(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	BOOL							fResult=FALSE;
	PCERT_ALT_NAME_INFO	            pInfo=NULL;
	
	//check for input parameters
	if((NULL==pbEncoded&& cbEncoded!=0) ||
			(NULL==pcbFormat))
		goto InvalidArg;

	if(cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}

    if (!DecodeGenericBLOB(dwCertEncodingType,X509_ALTERNATE_NAME,
			pbEncoded,cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    fResult=FormatAltNameInfo(dwCertEncodingType, dwFormatType,dwFormatStrType,
                            pFormatStruct,
                            0,
                            TRUE,
                            pInfo, pbFormat, pcbFormat);

    if(FALSE==fResult)
        goto FormatAltNameError;

CommonReturn:

	if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatAltNameError);

}

//--------------------------------------------------------------------------
//
//	  GetCertNameMulti
//
//    Get the multi line display of the certificate name
//--------------------------------------------------------------------------
BOOL    GetCertNameMulti(LPWSTR          pwszNameStr,
                         UINT            idsPreFix,
                         LPWSTR          *ppwsz)
{

    BOOL            fResult=FALSE;
    WCHAR           wszPreFix[PRE_FIX_SIZE];
    LPWSTR          pwszStart=NULL;
    LPWSTR          pwszEnd=NULL;
    DWORD           dwCopy=0;
    LPWSTR          pwszNameStart=NULL;
    BOOL            fDone=FALSE;
    BOOL            fInQuote=FALSE;

    LPWSTR          pwszTemp;

    //init
    *ppwsz=NULL;

    //load string for the preFix
    if(0!=idsPreFix && 1!=idsPreFix)
    {
        if(!LoadStringU(hFrmtFuncInst, idsPreFix, wszPreFix, PRE_FIX_SIZE))
            goto LoadStringError;
    }

   *ppwsz=(LPWSTR)malloc(sizeof(WCHAR));
   if(NULL==*ppwsz)
        goto MemoryError;
   **ppwsz=L'\0';

   //now, start the search for the symbol '+' or ','
   pwszStart=pwszNameStr;
   pwszEnd=pwszNameStr;

   //parse the whole string
   for(;FALSE==fDone; pwszEnd++)
   {
       //mark fInQuote to TRUE if we are inside " "
       if(L'\"'==*pwszEnd)
           fInQuote=!fInQuote;

       if((L'+'==*pwszEnd) || (L','==*pwszEnd) ||(L'\0'==*pwszEnd))
       {
           //make sure + and ; are not quoted
           if((L'+'==*pwszEnd) || (L','==*pwszEnd))
           {
                if(TRUE==fInQuote)
                    continue;

           }

           //skip the leading spaces
           for(;*pwszStart != L'\0'; pwszStart++)
           {
                if(*pwszStart != L' ')
                    break;
           }

           //we are done if NULL is reached
           if(L'\0'==*pwszStart)
               break;

           //calculate the length to copy
           dwCopy=(DWORD)(pwszEnd-pwszStart);

           if(0!=idsPreFix && 1!=idsPreFix)
           {
                #if (0) // DSIE: Bug 27436
                *ppwsz=(LPWSTR)realloc(*ppwsz,
                    (wcslen(*ppwsz)+dwCopy+wcslen(wszPreFix)+wcslen(wszCRLF)+1)*sizeof(WCHAR));
                #endif

                pwszTemp=(LPWSTR)realloc(*ppwsz,
                    (wcslen(*ppwsz)+dwCopy+wcslen(wszPreFix)+wcslen(wszCRLF)+1)*sizeof(WCHAR));
           }
           else
           {
                #if (0) // DSIE: Bug 27436
                *ppwsz=(LPWSTR)realloc(*ppwsz,
                    (wcslen(*ppwsz)+dwCopy+wcslen(wszCRLF)+1)*sizeof(WCHAR));
                #endif

                pwszTemp=(LPWSTR)realloc(*ppwsz,
                    (wcslen(*ppwsz)+dwCopy+wcslen(wszCRLF)+1)*sizeof(WCHAR));
           }

           #if (0) // DSIE: Bug 27436
           if(NULL == *ppwsz)
               goto MemoryError;
           #endif

           if(NULL == pwszTemp)
               goto MemoryError;
           *ppwsz = pwszTemp;

           //copy the prefix
           if(0!=idsPreFix && 1!=idsPreFix)
                wcscat(*ppwsz, wszPreFix);

           pwszNameStart=(*ppwsz)+wcslen(*ppwsz);

           //copy the string to *ppwsz
           memcpy(pwszNameStart, pwszStart, dwCopy*sizeof(WCHAR));
           pwszNameStart += dwCopy;

           //NULL terminate the string
           *pwszNameStart=L'\0';

           //copy the "\n"
           wcscat(*ppwsz, wszCRLF);

           //reset pwszStart and pwszEnd.
           pwszStart=pwszEnd+1;

           if(L'\0'==*pwszEnd)
               fDone=TRUE;
       }

   }


    fResult=TRUE;

CommonReturn:

     return fResult;

ErrorReturn:

     if(*ppwsz)
     {
         free(*ppwsz);
         *ppwsz=NULL;
     }

     fResult=FALSE;

     goto CommonReturn;

SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(LoadStringError);
}

//--------------------------------------------------------------------------
//
//	  FormatMessageUnicode
//
//--------------------------------------------------------------------------
BOOL FormatMessageUnicode(LPWSTR * ppwszFormat, UINT ids, ...)
{
    // get format string from resources
    WCHAR		wszFormat[1000];
	va_list		argList;
	DWORD		cbMsg=0;
	BOOL		fResult=FALSE;

    if(NULL == ppwszFormat)
        goto InvalidArgErr;

#if (0) //DSIE: Bug 160605
    if(!LoadStringU(hFrmtFuncInst, ids, wszFormat, sizeof(wszFormat)))
#else
    if(!LoadStringU(hFrmtFuncInst, ids, wszFormat, sizeof(wszFormat) / sizeof(wszFormat[0])))
#endif
		goto LoadStringError;

    // format message into requested buffer
    va_start(argList, ids);

    cbMsg = FormatMessageU(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
        wszFormat,
        0,                  // dwMessageId
        0,                  // dwLanguageId
        (LPWSTR) (ppwszFormat),
        0,                  // minimum size to allocate
        &argList);

    va_end(argList);

	if(!cbMsg)
#if (1) // DSIE: Fix bug #128630
		//
		// FormatMessageU() will return 0 byte, if data to be
		// formatted is empty. CertSrv generates extensions
		// with empty data for name constraints, so we need to
		// make sure we return an empty string, "", instead of
		// an error and NULL pointer.
		//
		if (0 == GetLastError())
		{
			if (NULL == (*ppwszFormat = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR))))
				goto MemoryError;
		}
		else
#endif
			goto FormatMessageError;

	fResult=TRUE;

CommonReturn:

	return fResult;

ErrorReturn:
	fResult=FALSE;

	goto CommonReturn;


TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
}

//--------------------------------------------------------------------------
//
//	  FormatMessageStr
//
//--------------------------------------------------------------------------
/*BOOL	FormatMessageStr(LPSTR	*ppszFormat,UINT ids,...)
{
    // get format string from resources
    CHAR		szFormat[1000];
	va_list		argList;
	BOOL		fResult=FALSE;
	HRESULT		hr=S_OK;

    if(!LoadStringA(hFrmtFuncInst, ids, szFormat, sizeof(szFormat)))
		goto LoadStringError;

    // format message into requested buffer
    va_start(argList, ids);

    if(0==FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
        szFormat,
        0,                  // dwMessageId
        0,                  // dwLanguageId
        (LPSTR) ppszFormat,
        0,                  // minimum size to allocate
        &argList))
        goto FormatMessageError;

    va_end(argList);

	fResult=TRUE;

CommonReturn:
	
	return fResult;

ErrorReturn:
	fResult=FALSE;

	goto CommonReturn;


TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);

} */

//--------------------------------------------------------------------------
//
//	  Decode a generic BLOB
//
//--------------------------------------------------------------------------
BOOL	DecodeGenericBLOB(DWORD dwEncodingType, LPCSTR lpszStructType,
			const BYTE *pbEncoded, DWORD cbEncoded,void **ppStructInfo)
{
	DWORD	cbStructInfo=0;

	//decode the object.  No copying
	if(!CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded, cbEncoded,
		0,NULL,	&cbStructInfo))
		return FALSE;

	*ppStructInfo=malloc(cbStructInfo);
	if(!(*ppStructInfo))
	{
		SetLastError((DWORD) E_OUTOFMEMORY);
		return FALSE;
	}

	return CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded, cbEncoded,
		0,*ppStructInfo,&cbStructInfo);
}

////////////////////////////////////////////////////////
//
// Convert STR to WSTR
//
HRESULT	SZtoWSZ(LPSTR szStr,LPWSTR *pwsz)
{
	DWORD	dwSize=0;
	DWORD	dwError=0;

	*pwsz=NULL;

	//return NULL
	if(!szStr)
		return S_OK;

	dwSize=MultiByteToWideChar(0, 0,szStr, -1,NULL,0);

	if(dwSize==0)
	{
		dwError=GetLastError();
		return HRESULT_FROM_WIN32(dwError);
	}

	//allocate memory
	*pwsz=(LPWSTR)malloc(dwSize * sizeof(WCHAR));
	if(*pwsz==NULL)
		return E_OUTOFMEMORY;

	if(MultiByteToWideChar(0, 0,szStr, -1,
		*pwsz,dwSize))
	{
		return S_OK;
	}
	else
	{
		 free(*pwsz);
         *pwsz=NULL;
		 dwError=GetLastError();
		 return HRESULT_FROM_WIN32(dwError);
	}
}

//--------------------------------------------------------------------------
//
//	  Convert dwFormatType to dwStrType
//
//--------------------------------------------------------------------------
DWORD   FormatToStr(DWORD   dwFormatType)
{
    DWORD   dwStrType=0;

    //we default to CERT_X500_NAME_STR
    if(0==dwFormatType)
    {
        return CERT_X500_NAME_STR;
    }

    if(dwFormatType &  CRYPT_FORMAT_SIMPLE)
		dwStrType |= CERT_SIMPLE_NAME_STR;

	if(dwFormatType & CRYPT_FORMAT_X509)
		dwStrType |= CERT_X500_NAME_STR;

	if(dwFormatType & CRYPT_FORMAT_OID)
		dwStrType |= CERT_OID_NAME_STR;

	if(dwFormatType & CRYPT_FORMAT_RDN_SEMICOLON)
		dwStrType |= CERT_NAME_STR_SEMICOLON_FLAG;

	if(dwFormatType & CRYPT_FORMAT_RDN_CRLF)
		dwStrType |= CERT_NAME_STR_CRLF_FLAG;

	if(dwFormatType & CRYPT_FORMAT_RDN_UNQUOTE)
		dwStrType |= CERT_NAME_STR_NO_QUOTING_FLAG;

	if(dwFormatType & CRYPT_FORMAT_RDN_REVERSE)
		dwStrType |= CERT_NAME_STR_REVERSE_FLAG;

    return dwStrType;

}


//+-----------------------------------------------------------------------------
//  Post Win2k.
//------------------------------------------------------------------------------

//+-----------------------------------------------------------------------------
//
//  FormatInteger           X509_INTEGER
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatInteger (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatStrType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat,
    DWORD       ids)
{
	BOOL    fResult;
    DWORD   cbNeeded;
    int    *pInfo = NULL;
    LPWSTR  pwszFormat = NULL;
    BOOL    bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) ||
        (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_INTEGER,
			               pbEncoded,
                           cbEncoded, 
                           (void **)&pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Some extension name=%1!d!%2!s!
    //
    if (!FormatMessageUnicode(&pwszFormat, 
                              ids,
                              *pInfo,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;                                  
    }

    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    //
    // Free resources.
    //
	if (pInfo)
    {
        free(pInfo);
    }

    if (pwszFormat)
    {
        LocalFree((HLOCAL) pwszFormat);
    }

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatCrlNumber           szOID_CRL_NUMBER
//                            szOID_DELTA_CRL_INDICATOR
//                            szOID_CRL_VIRTUAL_BASE
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatCrlNumber (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL    fResult;
    DWORD   cbNeeded = 0;
    DWORD   ids = 0;
    BOOL    bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decide between single line and mulitple line format.
    //
    if (bMultiLines)
    {
        ids = 0 == strcmp(lpszStructType, szOID_CRL_NUMBER) ? IDS_CRL_NUMBER : 
              0 == strcmp(lpszStructType, szOID_DELTA_CRL_INDICATOR) ? IDS_DELTA_CRL_INDICATOR : IDS_CRL_VIRTUAL_BASE;
    }
    else
    {
        ids = IDS_INTEGER;
    }

    //
    // Decode extension to get length.
    //
    //  %1!d!%2!s!
    //  CRL Number=%1!d!%2!s!
    //  Delta CRL Number=%1!d!%2!s!
    //  Virtual Base CRL Number=%1!d!%2!s!
    //
    if (!FormatInteger(dwCertEncodingType, 
                       dwFormatStrType,
			           pbEncoded,
                       cbEncoded, 
                       NULL,
                       &cbNeeded,
                       ids))
    {
        goto FormatIntegerError;
    }

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Decode again to get data.
    //
    if (!FormatInteger(dwCertEncodingType, 
                       dwFormatStrType,
			           pbEncoded,
                       cbEncoded, 
                       pbFormat,
                       &cbNeeded,
                       ids))
    {
        goto FormatIntegerError;
    }

    //
    // Copy size .
    //
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(FormatIntegerError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatCrlNextPublish      szOID_CRL_NEXT_PUBLISH
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatCrlNextPublish (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL       fResult;
    DWORD      cbNeeded     = 0;
    FILETIME * pInfo        = NULL;
    LPWSTR     pwszFileTime = NULL;
    LPWSTR     pwszFormat   = NULL;
    BOOL       bMultiLines  = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_CHOICE_OF_TIME,
			               pbEncoded,
                           cbEncoded, 
                           (void **) &pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Get formatted date/time.
    //
    if (!FormatFileTime(pInfo, &pwszFileTime))
    {
        goto FormatFileTimeError;
    }

    if (!FormatMessageUnicode(&pwszFormat, 
                              IDS_STRING, 
                              pwszFileTime,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;
    }

    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

	if (pInfo)
    {
        free(pInfo);
    }

    if (pwszFileTime)
    {
        LocalFree((HLOCAL) pwszFileTime);
    }

    if (pwszFormat)
    {
        LocalFree((HLOCAL) pwszFormat);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
TRACE_ERROR(FormatFileTimeError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatIssuingDistPoint      X509_ISSUING_DIST_POINT
//                              szOID_ISSUING_DIST_POINT
//
//  typedef struct _CRL_ISSUING_DIST_POINT {
//      CRL_DIST_POINT_NAME     DistPointName;              // OPTIONAL
//      BOOL                    fOnlyContainsUserCerts;
//      BOOL                    fOnlyContainsCACerts;
//      CRYPT_BIT_BLOB          OnlySomeReasonFlags;        // OPTIONAL
//      BOOL                    fIndirectCRL;
//  } CRL_ISSUING_DIST_POINT, *PCRL_ISSUING_DIST_POINT;
//
//  typedef struct _CRL_DIST_POINT_NAME {
//      DWORD   dwDistPointNameChoice;
//      union {
//          CERT_ALT_NAME_INFO      FullName;       // 1
//          // Not implemented      IssuerRDN;      // 2
//      };
//  } CRL_DIST_POINT_NAME, *PCRL_DIST_POINT_NAME;
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatIssuingDistPoint (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL    fResult;
    DWORD   cbNeeded = 0;
    DWORD   ids = 0;
    WCHAR   wszYes[YES_NO_SIZE];
    WCHAR   wszNo[YES_NO_SIZE];
    LPWSTR  pwszTemp = NULL;
    LPWSTR  pwszFormat = NULL;
    LPWSTR  pwszPointName = NULL;
    LPWSTR  pwszNameFormat = NULL;
    LPWSTR  pwszOnlyContainsUserCerts = NULL;
    LPWSTR  pwszOnlyContainsCACerts = NULL;
    LPWSTR  pwszIndirectCRL = NULL;
    LPWSTR  pwszCRLReason=NULL;
    LPWSTR  pwszReasonFormat=NULL;
    BOOL    bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    PCRL_ISSUING_DIST_POINT pInfo = NULL;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           lpszStructType,
			               pbEncoded,
                           cbEncoded, 
                           (void **)&pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Allocate format buffer.
    //
    if (!(pwszFormat = (LPWSTR) malloc(sizeof(WCHAR))))
    {
        goto MemoryError;
    }
    *pwszFormat = L'\0';

    //
    // Format distribution name, if exists.
    //
    if (CRL_DIST_POINT_NO_NAME != pInfo->DistPointName.dwDistPointNameChoice)
    {
        if (!FormatDistPointName(dwCertEncodingType,
                                 dwFormatType,
                                 dwFormatStrType,
                                 pFormatStruct,
                                 &(pInfo->DistPointName),
                                 &pwszPointName))
        {
            goto FormatDistPointNameError;
        }

        //
        // Decide between single line and mulitple line format.
        //
        ids = bMultiLines ? IDS_ONLY_SOME_CRL_DIST_NAME_MULTI: IDS_ONLY_SOME_CRL_DIST_NAME;

        if (!FormatMessageUnicode(&pwszNameFormat, ids, pwszPointName))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszNameFormat) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszNameFormat);

        LocalFree((HLOCAL) pwszPointName);
        pwszPointName = NULL;

        LocalFree((HLOCAL) pwszNameFormat);
        pwszNameFormat = NULL;
    }

    //
    // Format onlyContainsXXX fields.
    //
    if (!LoadStringU(hFrmtFuncInst, 
                     IDS_YES, 
                     wszYes,
                     sizeof(wszYes) / sizeof(wszYes[0])))
    {
        goto LoadStringError;
    }

    if (!LoadStringU(hFrmtFuncInst, 
                     IDS_NO, 
                     wszNo,
                     sizeof(wszNo) / sizeof(wszNo[0])))
    {
        goto LoadStringError;
    }

    //
    // %1!s!Only Contains User Certs=%2!s!%3!s!
    //
    if (!FormatMessageUnicode(&pwszOnlyContainsUserCerts,
                              IDS_ONLY_CONTAINS_USER_CERTS,
                              bMultiLines ? wszEMPTY : wszCOMMA,
                              pInfo->fOnlyContainsUserCerts ? wszYes : wszNo,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;                                  
    }

    //
    // %1!s!Only Contains CA Certs=%2!s!%3!s!
    //
    if (!FormatMessageUnicode(&pwszOnlyContainsCACerts,
                              IDS_ONLY_CONTAINS_CA_CERTS,
                              bMultiLines ? wszEMPTY : wszCOMMA,
                              pInfo->fOnlyContainsCACerts ? wszYes : wszNo,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;                                  
    }

    //
    // %1!s!Indirect CRL=%2!s!%3!s!
    //
    if (!FormatMessageUnicode(&pwszIndirectCRL,
                              IDS_INDIRECT_CRL,
                              bMultiLines ? wszEMPTY : wszCOMMA,
                              pInfo->fIndirectCRL ? wszYes : wszNo,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;                                  
    }

    //
    // Reallocate and concate to format buffer.
    //
    pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * 
                      (wcslen(pwszFormat) + wcslen(pwszOnlyContainsUserCerts) + 
                       wcslen(pwszOnlyContainsCACerts) + wcslen(pwszIndirectCRL) + 1));
    if (NULL == pwszTemp)
    {
        goto MemoryError;
    }

    pwszFormat = pwszTemp;
    wcscat(pwszFormat, pwszOnlyContainsUserCerts);      
    wcscat(pwszFormat, pwszOnlyContainsCACerts);      
    wcscat(pwszFormat, pwszIndirectCRL);      

    //
    // Format the CRL reason.
    //
    if (0 != pInfo->OnlySomeReasonFlags.cbData)
    {
        if (!FormatCRLReason(dwCertEncodingType,
                             dwFormatType,
                             dwFormatStrType,
                             pFormatStruct,
                             lpszStructType,
                             &(pInfo->OnlySomeReasonFlags),
                             &pwszCRLReason))
        {
            goto FormatCRLReasonError;
        }

        //
        // Format Decide between single line and mulitple line format.
        //
        if (!FormatMessageUnicode(&pwszReasonFormat, 
                                  bMultiLines ? IDS_CRL_DIST_REASON_MULTI : IDS_CRL_DIST_REASON,
                                  pwszCRLReason))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszReasonFormat) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszReasonFormat);

        LocalFree((HLOCAL) pwszCRLReason);
        pwszCRLReason = NULL;

        LocalFree((HLOCAL) pwszReasonFormat);
        pwszReasonFormat = NULL;
    }

    //
    // length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    //
    // Free resources.
    //
    if (pwszCRLReason)
    {
        LocalFree((HLOCAL) pwszCRLReason);
    }

    if (pwszReasonFormat)
    {
        LocalFree((HLOCAL) pwszReasonFormat);
    }

    if(pwszIndirectCRL)
    {
        LocalFree((HLOCAL) pwszIndirectCRL);
    }

    if(pwszOnlyContainsCACerts)
    {
        LocalFree((HLOCAL) pwszOnlyContainsCACerts);
    }

    if(pwszOnlyContainsUserCerts)
    {
        LocalFree((HLOCAL) pwszOnlyContainsUserCerts);
    }

    if(pwszPointName)
    {
        LocalFree((HLOCAL) pwszPointName);
    }

    if (pwszNameFormat)
    {
        LocalFree((HLOCAL) pwszNameFormat);
    }

    if (pwszFormat)
    {
        free(pwszFormat);
    }

	if (pInfo)
    {
        free(pInfo);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MemoryError,E_OUTOFMEMORY);
TRACE_ERROR(FormatDistPointNameError);
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatCRLReasonError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
// FormatNameConstraintsSubtree.
//
// typedef struct _CERT_GENERAL_SUBTREE {
//      CERT_ALT_NAME_ENTRY     Base;
//      DWORD                   dwMinimum;
//      BOOL                    fMaximum;
//      DWORD                   dwMaximum;
// } CERT_GENERAL_SUBTREE, *PCERT_GENERAL_SUBTREE;
//
//
// Note: Intended to be called only by FormatNameConstrants. So no validity 
//       checks are done on parameters.
//
//------------------------------------------------------------------------------

//static 
BOOL
FormatNameConstraintsSubtree (
	DWORD                   dwCertEncodingType,
	DWORD                   dwFormatType,
	DWORD                   dwFormatStrType,
	void                   *pFormatStruct,
	void                   *pbFormat,
	DWORD                  *pcbFormat,
    DWORD                   idSubtree,
    DWORD                   cSubtree,
    PCERT_GENERAL_SUBTREE   pSubtree)
{
	BOOL        fResult;
    DWORD       dwIndex;
    DWORD       cbNeeded;
    WCHAR       wszOneTab[PRE_FIX_SIZE] = wszEMPTY;
    LPWSTR      pwszType = NULL;
    LPWSTR      pwszSubtree = NULL;
    LPWSTR      pwszAltName = NULL;
    LPWSTR      pwszFormat = NULL;
    BOOL        bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
    // Any subtree?
    //
    if (0 == cSubtree)
    {
        //
        // Permitted=None%1!s!
        // Excluded=None%1!s!
        //
        if (IDS_NAME_CONSTRAINTS_PERMITTED == idSubtree)
        {
            idSubtree = IDS_NAME_CONSTRAINTS_PERMITTED_NONE;
        }
        else // if (IDS_NAME_CONSTRAINTS_EXCLUDED == idSubtree)
        {
            idSubtree = IDS_NAME_CONSTRAINTS_EXCLUDED_NONE;
        }

        if (!FormatMessageUnicode(&pwszType, 
                                  idSubtree,
                                  bMultiLines ? wszCRLF : wszEMPTY))
        {
            goto FormatMessageError;                                  
        }
    }
    else
    {
        //
        // "Permitted%1!s!"
        // "Excluded%1!s!"
        //
        if (!FormatMessageUnicode(&pwszType,
                                  idSubtree,
                                  bMultiLines ? wszCRLF : wszCOLON))
        {
            goto FormatMessageError;                                  
        }

        //
        // Load tab strings.
        //
        if (!LoadStringU(hFrmtFuncInst, 
                         IDS_ONE_TAB, 
                         wszOneTab,
                         sizeof(wszOneTab) / sizeof(wszOneTab[0])))
        {
            goto LoadStringError;
        }
    }

    //
    // Allocate format buffer.
    //
    if (!(pwszFormat = (LPWSTR) malloc(sizeof(WCHAR) * (wcslen(pwszType) + 1))))
    {
        goto MemoryError;
    }

    //
    // Initialize formatted string.
    //
    wcscpy(pwszFormat, pwszType);

    //
    // Format each subtree parts.
    //
    for (dwIndex = 0; dwIndex < cSubtree; dwIndex++, pSubtree++) 
    {
        LPWSTR pwszTemp;
        
        //
        // Maximum specified?
        //
        if (pSubtree->fMaximum)
        {
            //
            // "%1!s![%2!d!]Subtrees (%3!d!..%4!d!):%5!s!"
            //
            if (!FormatMessageUnicode(&pwszSubtree,
                    IDS_NAME_CONSTRAINTS_SUBTREE,
                    bMultiLines ? wszOneTab : dwIndex ? wszCOMMA : wszEMPTY,
                    dwIndex + 1,
                    pSubtree->dwMinimum,
                    pSubtree->dwMaximum,
                    bMultiLines ? wszCRLF : wszEMPTY))
            {
                goto FormatMessageError;                                  
            }
        }
        else
        {
            //
            // "%1!s![%2!d!]Subtrees (%3!d!...):%4!s"
            //
            if (!FormatMessageUnicode(&pwszSubtree,
                    IDS_NAME_CONSTRAINTS_SUBTREE_NO_MAX,
                    bMultiLines ? wszOneTab : dwIndex ? wszCOMMA : wszEMPTY,
                    dwIndex + 1,
                    pSubtree->dwMinimum,
                    bMultiLines ? wszCRLF : wszEMPTY))
            {
                goto FormatMessageError;                                  
            }
        }

        //
        // Reallocate and concate to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + 1 + wcslen(pwszSubtree)));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszSubtree);
        LocalFree((HLOCAL) pwszSubtree);
        pwszSubtree = NULL;

        //
        // Format name.
        //
        CERT_ALT_NAME_INFO  CertAltNameInfo;

        memset(&CertAltNameInfo, 0, sizeof(CERT_ALT_NAME_INFO));
        CertAltNameInfo.cAltEntry = 1;
        CertAltNameInfo.rgAltEntry = &(pSubtree->Base);

        // Need to tell if it is for multi line format.  We need two \t\t
        // in front of each alt name entry
        DWORD ids = bMultiLines ? IDS_TWO_TABS : 0;

        // Get the alternative name entry
        cbNeeded = 0;
        
		if (!FormatAltNameInfo(dwCertEncodingType,
                               dwFormatType,
                               dwFormatStrType,
                               pFormatStruct,
                               ids,
                               FALSE,
                               &CertAltNameInfo,
                               NULL,
                               &cbNeeded))
        {
            goto FormatAltNameError;
        }

        if (NULL == (pwszAltName = (LPWSTR) malloc(cbNeeded)))
        {
            goto MemoryError;
        }

        if (!FormatAltNameInfo(dwCertEncodingType,
                               dwFormatType,
                               dwFormatStrType,
                               pFormatStruct,
                               ids,
                               FALSE,
                               &CertAltNameInfo,
                               pwszAltName,
                               &cbNeeded))
        {
            goto FormatAltNameError;
        }

        //
        // Append "\r\n" if multi-line.
        //
        if (bMultiLines)
        {
			pwszTemp = (LPWSTR) realloc(pwszAltName, sizeof(WCHAR) * (wcslen(pwszAltName) + wcslen(wszCRLF) + 1));
			if (NULL == pwszTemp)
			{
				goto MemoryError;
			}
			pwszAltName = pwszTemp;
            wcscat(pwszAltName, wszCRLF);
        }

        //
        // Reallocate and concate to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + 1 + wcslen(pwszAltName)));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszAltName);
        free(pwszAltName);
        pwszAltName = NULL;
    }

    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    //
    // Free resources.
    //
    if (pwszType)
    {
        LocalFree((HLOCAL) pwszType);
    }

    if (pwszSubtree)
    {
        LocalFree((HLOCAL) pwszSubtree);
    }

    if (pwszAltName)
    {
        free((HLOCAL) pwszAltName);
    }

    if (pwszFormat)
    {
        free(pwszFormat);
    }

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

TRACE_ERROR(FormatMessageError);
TRACE_ERROR(LoadStringError);
SET_ERROR(MemoryError,E_OUTOFMEMORY);
TRACE_ERROR(FormatAltNameError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatNameConstrains:   szOID_NAME_CONSTRAINTS
//                          X509_NAME_CONSTRAINTS
//
//  typedef struct _CERT_NAME_CONSTRAINTS_INFO {
//      DWORD                   cPermittedSubtree;
//      PCERT_GENERAL_SUBTREE   rgPermittedSubtree;
//      DWORD                   cExcludedSubtree;
//      PCERT_GENERAL_SUBTREE   rgExcludedSubtree;
//  } CERT_NAME_CONSTRAINTS_INFO, *PCERT_NAME_CONSTRAINTS_INFO;
//
//------------------------------------------------------------------------------

//static 
BOOL
WINAPI
FormatNameConstraints (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL  fResult = FALSE;
    DWORD cbPermitNeeded = 0;
    DWORD cbExcludeNeeded = 0;
    DWORD cbTotalNeeded = 0;

    PCERT_NAME_CONSTRAINTS_INFO pInfo = NULL;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           lpszStructType,
			               pbEncoded,
                           cbEncoded, 
                           (void **)&pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Find out memory size needed.
    //
    if ((!FormatNameConstraintsSubtree(dwCertEncodingType,
                                       dwFormatType,
                                       dwFormatStrType,
                                       pFormatStruct,
                                       NULL,
                                       &cbPermitNeeded,
                                       IDS_NAME_CONSTRAINTS_PERMITTED,
                                       pInfo->cPermittedSubtree,
                                       pInfo->rgPermittedSubtree)) ||
        (!FormatNameConstraintsSubtree(dwCertEncodingType,
                                       dwFormatType,
                                       dwFormatStrType,
                                       pFormatStruct,
                                       NULL,
                                       &cbExcludeNeeded,
                                       IDS_NAME_CONSTRAINTS_EXCLUDED,
                                       pInfo->cExcludedSubtree,
                                       pInfo->rgExcludedSubtree)))
    {
        goto ErrorReturn;
    }

    //
    // Total length needed.
    //
    cbTotalNeeded = cbPermitNeeded + cbExcludeNeeded;
    if (0 == cbTotalNeeded)
    {
        *pcbFormat = cbTotalNeeded;
        goto SuccessReturn;
    }

    //
    // One char less after we concate both strings.
    //
    if (cbPermitNeeded > 0 && cbExcludeNeeded > 0)
    {
        cbTotalNeeded -= sizeof(WCHAR);

        //
        // If not multi-lines and both strings are present, allow 2 more 
        // chars for ", " to separate the strings.
        //
        if (!(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE))
        {
            cbTotalNeeded += sizeof(WCHAR) * wcslen(wszCOMMA);
        }
    }

    //
    // length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbTotalNeeded;
        goto SuccessReturn;
    }
   
    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbTotalNeeded)
    {
        *pcbFormat = cbTotalNeeded;
        goto MoreDataError;
    }

    //
    // Now format both subtrees.
    //
    if (!FormatNameConstraintsSubtree(dwCertEncodingType,
                                      dwFormatType,
                                      dwFormatStrType,
                                      pFormatStruct,
                                      pbFormat,
                                      &cbPermitNeeded,
                                      IDS_NAME_CONSTRAINTS_PERMITTED,
                                      pInfo->cPermittedSubtree,
                                      pInfo->rgPermittedSubtree))
    {
       goto ErrorReturn;
    }

    //
    // If not multi-lines and both strings are present, then add ", "
    // to separate them.
    //
    if (!(dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) &&
        (cbPermitNeeded > 0) && (cbExcludeNeeded > 0))
    {
        wcscat((LPWSTR) pbFormat, wszCOMMA);
    }

    pbFormat = (void *) ((BYTE *) pbFormat + wcslen((LPWSTR) pbFormat) * sizeof(WCHAR));

    if (!FormatNameConstraintsSubtree(dwCertEncodingType,
                                      dwFormatType,
                                      dwFormatStrType,
                                      pFormatStruct,
                                      pbFormat,
                                      &cbExcludeNeeded,
                                      IDS_NAME_CONSTRAINTS_EXCLUDED,
                                      pInfo->cExcludedSubtree,
                                      pInfo->rgExcludedSubtree))
    {
       goto ErrorReturn;
    }

    //
    // Copy the size needed.
    //
    *pcbFormat = cbTotalNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    //
    // Free resources.
    //
	if (pInfo)
    {
        free(pInfo);
    }

	return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatCertSrvPreviousCertHash      szOID_CERTSRV_PREVIOUS_CERT_HASH
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatCertSrvPreviousCertHash (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL              fResult;
    DWORD             cbNeeded    = 0;
    CRYPT_DATA_BLOB * pInfo       = NULL;
    WCHAR           * pwszHex     = NULL;
    WCHAR           * pwszFormat  = NULL;
    BOOL              bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_OCTET_STRING,
			               pbEncoded,
                           cbEncoded, 
                           (void **) &pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Get formatted hex string.
    //
    if(!FormatBytesToHex(0,
                         dwFormatType,
                         dwFormatStrType,
                         pFormatStruct,
                         NULL,
                         pInfo->pbData,
                         pInfo->cbData,
                         NULL,
	                     &cbNeeded))
    {
        goto FormatBytesToHexError;
    }

    if (!(pwszHex = (LPWSTR) malloc(cbNeeded)))
    {
        goto MemoryError;
    }

    if(!FormatBytesToHex(0,
                         dwFormatType,
                         dwFormatStrType,
                         pFormatStruct,
                         NULL,
                         pInfo->pbData,
                         pInfo->cbData,
                         pwszHex,
	                     &cbNeeded))
    {
        goto FormatBytesToHexError;
    }

    if (!FormatMessageUnicode(&pwszFormat, 
                              IDS_STRING, 
                              pwszHex,
                              bMultiLines ? wszCRLF : wszEMPTY))
    {
        goto FormatMessageError;
    }
    
    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // Length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

	if (pInfo)
    {
        free(pInfo);
    }

    if (pwszHex)
    {
        free(pwszHex);
    }

    if (pwszFormat)
    {
        LocalFree((HLOCAL) pwszFormat);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatBytesToHexError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatPolicyMappings               X509_POLICY_MAPPINGS
//                                     szOID_POLICY_MAPPINGS
//                                     szOID_APPLICATION_POLICY_MAPPINGS
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatPolicyMappings (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL   fResult;
    DWORD  dwIndex     = 0;
    DWORD  cbNeeded    = 0;
    char   szEmpty[1]  = {'\0'};
    LPSTR  pszObjectId = NULL;
    LPWSTR pwszFormat  = NULL;
    LPWSTR pwszTemp    = NULL;
    LPWSTR pwszLine    = NULL;
    LPWSTR pwszPolicy  = NULL;
    BOOL   bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;
    CERT_POLICY_MAPPINGS_INFO * pInfo = NULL;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_POLICY_MAPPINGS,
			               pbEncoded,
                           cbEncoded, 
                           (void **) &pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Make sure data is valid.
    //
    if (pInfo->cPolicyMapping && !pInfo->rgPolicyMapping)
    {
        goto BadDataError;
    }

    //
    // Initialize formatted string.
    //
    if (!(pwszFormat = (LPWSTR) malloc(sizeof(WCHAR))))
    {
        goto MemoryError;
    }
    *pwszFormat = NULL;

    //
    // Loop thru each mapping.
    //
    for (dwIndex = 0; dwIndex < pInfo->cPolicyMapping; dwIndex++)
    {
        //
        // Format Issuer Domain Policy, if available.
        //
        if (pInfo->rgPolicyMapping[dwIndex].pszIssuerDomainPolicy)
        {
            pszObjectId = pInfo->rgPolicyMapping[dwIndex].pszIssuerDomainPolicy;
        }
        else
        {
            pszObjectId = szEmpty;
        }

        if (!FormatObjectId(pszObjectId,
                            CRYPT_POLICY_OID_GROUP_ID,
                            FALSE,
                            &pwszPolicy))
        {
            goto FormatObjectIdError;
        }

        //
        // "[%1!d!]Issuer Domain=%2!s!%3!s!"
        //
        if (!FormatMessageUnicode(&pwszLine, 
                                  IDS_ISSUER_DOMAIN_POLICY,
                                  dwIndex + 1,
                                  pwszPolicy,
                                  bMultiLines ? wszCRLF : wszCOMMA))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate line to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszLine);

        LocalFree((HLOCAL) pwszPolicy);
        pwszPolicy = NULL;

        LocalFree((HLOCAL) pwszLine);
        pwszLine = NULL;
 
        //
        // Format Subject Domain Policy, if available.
        //
        if (pInfo->rgPolicyMapping[dwIndex].pszSubjectDomainPolicy)
        {
            pszObjectId = pInfo->rgPolicyMapping[dwIndex].pszSubjectDomainPolicy;
        }
        else
        {
            pszObjectId = szEmpty;
        }

        if (!FormatObjectId(pszObjectId,
                            CRYPT_POLICY_OID_GROUP_ID,
                            FALSE,
                            &pwszPolicy))
        {
            goto FormatObjectIdError;
        }

        //
        // "%1!s!Subject Domain=%2!s!%3!s!"
        //
        if (!FormatMessageUnicode(&pwszLine, 
                                  IDS_SUBJECT_DOMAIN_POLICY,
                                  bMultiLines ? wszTAB : wszEMPTY,
                                  pwszPolicy,
                                  bMultiLines ? wszCRLF : (dwIndex + 1) < pInfo->cPolicyMapping ? wszCOMMA : wszEMPTY))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate line to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszLine);

        LocalFree((HLOCAL) pwszPolicy);
        pwszPolicy = NULL;

        LocalFree((HLOCAL) pwszLine);
        pwszLine = NULL;
    }
    
    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // Length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    if (pwszLine)
    {
        LocalFree((HLOCAL) pwszLine);
    }

    if (pwszPolicy)
    {
        LocalFree((HLOCAL) pwszPolicy);
    }

    if (pwszFormat)
    {
        free(pwszFormat);
    }

	if (pInfo)
    {
        free(pInfo);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(BadDataError, E_POINTER);
TRACE_ERROR(FormatObjectIdError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatPolicyConstraints            X509_POLICY_CONSTRAINTS
//                                     szOID_POLICY_CONSTRAINTS
//                                     szOID_APPLICATION_POLICY_CONSTRAINTS
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatPolicyConstraints (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL    fResult;
    DWORD   cbNeeded    = 0;
    LPWSTR  pwszFormat  = NULL;
    LPWSTR  pwszTemp    = NULL;
    LPWSTR  pwszLine    = NULL;
    BOOL    bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;
    CERT_POLICY_CONSTRAINTS_INFO * pInfo = NULL;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_POLICY_CONSTRAINTS,
			               pbEncoded,
                           cbEncoded, 
                           (void **) &pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Initialize formatted string.
    //
    if (!(pwszFormat = (LPWSTR) malloc(sizeof(WCHAR))))
    {
        goto MemoryError;
    }
    *pwszFormat = NULL;

    //
    // Format Required Explicit Policy Skip Certs, if available.
    //
    if (pInfo->fRequireExplicitPolicy)
    {
        //
        // "Required Explicit Policy Skip Certs=%1!d!%2!s!"
        //
        if (!FormatMessageUnicode(&pwszLine, 
                                  IDS_REQUIRED_EXPLICIT_POLICY_SKIP_CERTS,
                                  pInfo->dwRequireExplicitPolicySkipCerts,
                                  bMultiLines ? wszCRLF : wszCOMMA))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate line to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszLine);

        LocalFree((HLOCAL) pwszLine);
        pwszLine = NULL;
    }

    //
    // Format Inhibit Policy Mapping Skip Certs, if available.
    //
    if (pInfo->fInhibitPolicyMapping)
    {
        //
        // "Inhibit Policy Mapping Skip Certs=%1!d!%2!s!"
        //
        if (!FormatMessageUnicode(&pwszLine, 
                                  IDS_INHIBIT_POLICY_MAPPING_SKIP_CERTS,
                                  pInfo->dwInhibitPolicyMappingSkipCerts,
                                  bMultiLines ? wszCRLF : wszEMPTY))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate line to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszLine);

        LocalFree((HLOCAL) pwszLine);
        pwszLine = NULL;
    }
    
    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // Length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    if (pwszLine)
    {
        LocalFree((HLOCAL) pwszLine);
    }

    if (pwszFormat)
    {
        free(pwszFormat);
    }

	if (pInfo)
    {
        free(pInfo);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}

//+-----------------------------------------------------------------------------
//
//  FormatCertificateTemplate          X509_CERTIFICATE_TEMPLATE
//                                     szOID_CERTIFICATE_TEMPLATE
//
//------------------------------------------------------------------------------

static BOOL
WINAPI
FormatCertificateTemplate (
	DWORD       dwCertEncodingType,
	DWORD       dwFormatType,
	DWORD       dwFormatStrType,
	void       *pFormatStruct,
	LPCSTR      lpszStructType,
	const BYTE *pbEncoded,
	DWORD       cbEncoded,
	void       *pbFormat,
	DWORD      *pcbFormat)
{
	BOOL    fResult;
    DWORD   cbNeeded    = 0;
    LPWSTR  pwszFormat  = NULL;
    LPWSTR  pwszObjId   = NULL;
    LPWSTR  pwszTemp    = NULL;
    LPWSTR  pwszLine    = NULL;
    BOOL    bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;
    CERT_TEMPLATE_EXT * pInfo = NULL;

    //
	// Check input parameters.
    //
    if ((NULL == pbEncoded && 0 != cbEncoded) ||
        (NULL == pcbFormat) || (0 == cbEncoded))
	{
		goto InvalidArg;
	}

    //
    // Decode extension.
    //
    if (!DecodeGenericBLOB(dwCertEncodingType, 
                           X509_CERTIFICATE_TEMPLATE,
			               pbEncoded,
                           cbEncoded, 
                           (void **) &pInfo))
    {
        goto DecodeGenericError;
    }

    //
    // Initialize formatted string.
    //
    if (!(pwszFormat = (LPWSTR) malloc(sizeof(WCHAR))))
    {
        goto MemoryError;
    }
    *pwszFormat = NULL;

#if (0) //DSIE: Bug 157853
    //
    // Convert OID to Unicode.
    //
    if (!AllocateAnsiToUnicode(pInfo->pszObjId, &pwszObjId))
    {
        goto AnsiToUnicodeError;
    }
#else
    if (!FormatObjectId(pInfo->pszObjId,
                        CRYPT_TEMPLATE_OID_GROUP_ID,
                        FALSE,
                        &pwszObjId))
    {
        goto FormatObjectIdError;
    }
#endif

    //
    // "Template=%1!s!%2!s!Major Version Number=%3!d!%4!s!"
    //
    if (!FormatMessageUnicode(&pwszLine, 
                              IDS_CERTIFICATE_TEMPLATE_MAJOR_VERSION,
                              pwszObjId,
                              bMultiLines ? wszCRLF : wszCOMMA,
                              pInfo->dwMajorVersion,
                              bMultiLines ? wszCRLF : wszCOMMA))
    {
        goto FormatMessageError;
    }

    //
    // Reallocate and concate line to format buffer.
    //
    pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
    if (NULL == pwszTemp)
    {
        goto MemoryError;
    }

    pwszFormat = pwszTemp;
    wcscat(pwszFormat, pwszLine);

    LocalFree((HLOCAL) pwszLine);
    pwszLine = NULL;

    //
    // Format Minor Version, if available.
    //
    if (pInfo->fMinorVersion)
    {
        //
        // "Minor Version Number=%1!d!%2!s!"
        //
        if (!FormatMessageUnicode(&pwszLine, 
                                  IDS_CERTIFICATE_TEMPLATE_MINOR_VERSION,
                                  pInfo->dwMinorVersion,
                                  bMultiLines ? wszCRLF : wszEMPTY))
        {
            goto FormatMessageError;
        }

        //
        // Reallocate and concate line to format buffer.
        //
        pwszTemp = (LPWSTR) realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat) + wcslen(pwszLine) + 1));
        if (NULL == pwszTemp)
        {
            goto MemoryError;
        }

        pwszFormat = pwszTemp;
        wcscat(pwszFormat, pwszLine);

        LocalFree((HLOCAL) pwszLine);
        pwszLine = NULL;
    }
    
    //
    // Total length needed.
    //
    cbNeeded = sizeof(WCHAR) * (wcslen(pwszFormat) + 1);

    //
    // Length only calculation?
    //
    if (NULL == pbFormat)
    {
        *pcbFormat = cbNeeded;
        goto SuccessReturn;
    }

    //
    // Caller provided us with enough memory?
    //
    if (*pcbFormat < cbNeeded)
    {
        *pcbFormat = cbNeeded;
        goto MoreDataError;
    }

    //
    // Copy size and data.
    //
    memcpy(pbFormat, pwszFormat, cbNeeded);
    *pcbFormat = cbNeeded;

SuccessReturn:

    fResult = TRUE;

CommonReturn:

    if (pwszObjId)
    {
#if (0) //DSIE: Bug 157853
        free(pwszObjId);
#else
        LocalFree((HLOCAL) pwszObjId);
#endif
    }

    if (pwszLine)
    {
        LocalFree((HLOCAL) pwszLine);
    }

    if (pwszFormat)
    {
        free(pwszFormat);
    }

	if (pInfo)
    {
        free(pInfo);
    }

    return fResult;

ErrorReturn:

	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg,E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
#if (0) //DSIE: Bug 157853
TRACE_ERROR(AnsiToUnicodeError);
#else
TRACE_ERROR(FormatObjectIdError);
#endif
TRACE_ERROR(FormatMessageError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
}



//--------------------------------------------------------------------------
//
//	 FormatXCertDistPoints:   X509_CROSS_CERT_DIST_POINTS
//                            szOID_CROSS_CERT_DIST_POINTS
//--------------------------------------------------------------------------
static BOOL
WINAPI
FormatXCertDistPoints(
	DWORD		dwCertEncodingType,
	DWORD		dwFormatType,
	DWORD		dwFormatStrType,
	void		*pFormatStruct,
	LPCSTR		lpszStructType,
	const BYTE *pbEncoded,
	DWORD		cbEncoded,
	void	   *pbFormat,
	DWORD	   *pcbFormat)
{
	
	LPWSTR					        pwszFormat=NULL;
    LPWSTR                          pwszDeltaTime=NULL;
    LPWSTR                          pwszEntryLine=NULL;
    LPWSTR                          pwszDistPoint=NULL;

	PCROSS_CERT_DIST_POINTS_INFO    pInfo=NULL;

	DWORD					        cbNeeded=0;
    DWORD                           dwIndex=0;
	BOOL					        fResult=FALSE;
    BOOL                            bMultiLines = dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE;
                                    
    LPWSTR                          pwszTemp;
    
	//check for input parameters
	if ((NULL==pbEncoded && cbEncoded!=0) || (NULL==pcbFormat))
		goto InvalidArg;

	if (cbEncoded==0)
	{
		*pcbFormat=0;
		goto InvalidArg;
	}
  
    if (!DecodeGenericBLOB(dwCertEncodingType, lpszStructType,
			pbEncoded, cbEncoded, (void **)&pInfo))
		goto DecodeGenericError;

    //
    // "Delta Sync Time=%1!d! seconds%2!s!"
    //
    if (!FormatMessageUnicode(&pwszDeltaTime, 
                              IDS_XCERT_DELTA_SYNC_TIME,
                              pInfo->dwSyncDeltaTime,
                              bMultiLines ? wszCRLF : wszCOMMA))
    {
        goto FormatMessageError;
    }

    pwszFormat=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszDeltaTime)+1));
    if(NULL==pwszFormat)
        goto MemoryError;

    wcscpy(pwszFormat, pwszDeltaTime);

    //format the xcert dist point entries.
    for (dwIndex=0; dwIndex<pInfo->cDistPoint; dwIndex++)
    {
        cbNeeded=0;
        if (!FormatAltNameInfo(dwCertEncodingType,
                               dwFormatType,
                               dwFormatStrType,
                               pFormatStruct,
                               bMultiLines ? IDS_ONE_TAB : 0,
                               FALSE,
                               &pInfo->rgDistPoint[dwIndex],
                               NULL,
                               &cbNeeded))
            goto FormatAltNameError;

        pwszEntryLine=(LPWSTR)malloc(cbNeeded);
        if (NULL==pwszEntryLine)
            goto MemoryError;

        if (!FormatAltNameInfo(dwCertEncodingType,
                               dwFormatType,
                               dwFormatStrType,
                               pFormatStruct,
                               bMultiLines ? IDS_ONE_TAB : 0,
                               FALSE,
                               &pInfo->rgDistPoint[dwIndex],
                               pwszEntryLine,
                               &cbNeeded))
            goto FormatAltNameError;

        //"[%1!d!]Cross-Certificate Distribution Point: %2!s!%3!s!%4!s!"
        if(!FormatMessageUnicode(&pwszDistPoint,
                                 IDS_XCERT_DIST_POINT,
                                 dwIndex + 1,
                                 bMultiLines ? wszCRLF : wszEMPTY,
                                 pwszEntryLine,
                                 bMultiLines || (dwIndex == pInfo->cDistPoint - 1) ? wszCRLF : wszCOMMA))
            goto FormatMessageError;

        pwszTemp=(LPWSTR)realloc(pwszFormat, sizeof(WCHAR) * (wcslen(pwszFormat)+wcslen(pwszDistPoint)+1));
        if(NULL==pwszTemp)
            goto MemoryError;
        pwszFormat = pwszTemp;

        wcscat(pwszFormat, pwszDistPoint);

        //free memory
        free(pwszEntryLine);
        pwszEntryLine=NULL;

        LocalFree((HLOCAL) pwszDistPoint);
        pwszDistPoint=NULL;
    }

    if(0==wcslen(pwszFormat))
    {
        //no data
        pwszFormat=(LPWSTR)malloc(sizeof(WCHAR)*(NO_INFO_SIZE+1));
        if(NULL==pwszFormat)
            goto MemoryError;

        if(!LoadStringU(hFrmtFuncInst,IDS_NO_INFO, pwszFormat, NO_INFO_SIZE))
            goto LoadStringError;

    }

	cbNeeded=sizeof(WCHAR)*(wcslen(pwszFormat)+1);

	//length only calculation
	if(NULL==pbFormat)
	{
		*pcbFormat=cbNeeded;
		fResult=TRUE;
		goto CommonReturn;
	}

	if((*pcbFormat)<cbNeeded)
    {
        *pcbFormat=cbNeeded;
		goto MoreDataError;
    }

	//copy the data
	memcpy(pbFormat, pwszFormat, cbNeeded);

	//copy the size
	*pcbFormat=cbNeeded;

	fResult=TRUE;	

CommonReturn:
    if(pwszDeltaTime)
        LocalFree((HLOCAL) pwszDeltaTime);

    if(pwszDistPoint)
        LocalFree((HLOCAL) pwszDistPoint);

    if(pwszEntryLine)
        free(pwszEntryLine);

    if (pwszFormat)
        free(pwszFormat);

    if(pInfo)
		free(pInfo);

	return fResult;

ErrorReturn:


	fResult=FALSE;
	goto CommonReturn;

SET_ERROR(InvalidArg, E_INVALIDARG);
TRACE_ERROR(DecodeGenericError);
SET_ERROR(MoreDataError,ERROR_MORE_DATA);
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);
SET_ERROR(MemoryError, E_OUTOFMEMORY);
TRACE_ERROR(FormatAltNameError);

}