diff --git a/dlls/cryptdlg/Makefile.in b/dlls/cryptdlg/Makefile.in index 0271fa3cc00..dd5a8155860 100644 --- a/dlls/cryptdlg/Makefile.in +++ b/dlls/cryptdlg/Makefile.in @@ -3,11 +3,13 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = cryptdlg.dll -IMPORTS = cryptui crypt32 wintrust advapi32 kernel32 +IMPORTS = cryptui crypt32 wintrust user32 advapi32 kernel32 C_SRCS = \ main.c +RC_SRCS = cryptdlg.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/cryptdlg/cryptdlg.rc b/dlls/cryptdlg/cryptdlg.rc new file mode 100644 index 00000000000..714151d2cb0 --- /dev/null +++ b/dlls/cryptdlg/cryptdlg.rc @@ -0,0 +1,25 @@ +/* + * cryptdlg dll resources + * + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "cryptres.h" + +#include "cryptdlg_En.rc" diff --git a/dlls/cryptdlg/cryptdlg.spec b/dlls/cryptdlg/cryptdlg.spec index 1536b101a39..b417d0d8b80 100644 --- a/dlls/cryptdlg/cryptdlg.spec +++ b/dlls/cryptdlg/cryptdlg.spec @@ -9,7 +9,7 @@ 9 stub EncodeAttrSequence 10 stub EncodeRecipientID 11 stub FormatPKIXEmailProtection -12 stub FormatVerisignExtension +12 stdcall FormatVerisignExtension(long long long ptr str ptr long ptr ptr) 13 stub CertModifyCertificatesToTrust 14 stub CertSelectCertificateA 15 stub CertSelectCertificateW diff --git a/dlls/cryptdlg/cryptdlg_En.rc b/dlls/cryptdlg/cryptdlg_En.rc new file mode 100644 index 00000000000..99126c42898 --- /dev/null +++ b/dlls/cryptdlg/cryptdlg_En.rc @@ -0,0 +1,36 @@ +/* + * cryptdlg dll resources + * + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_CERT_POLICY "Certificate Policy" + IDS_POLICY_ID "Policy Identifier: " + IDS_POLICY_QUALIFIER_INFO "Policy Qualifier Info" + IDS_POLICY_QUALIFIER_ID "Policy Qualifier Id=" + IDS_CPS "CPS" + IDS_USER_NOTICE "User Notice" + IDS_QUALIFIER "Qualifier" + IDS_NOTICE_REF "Notice Reference" + IDS_ORGANIZATION "Organization=" + IDS_NOTICE_NUM "Notice Number=" + IDS_NOTICE_TEXT "Notice Text=" +} diff --git a/dlls/cryptdlg/cryptres.h b/dlls/cryptdlg/cryptres.h new file mode 100644 index 00000000000..b64459aca78 --- /dev/null +++ b/dlls/cryptdlg/cryptres.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef __CRYPTRES_H__ +#define __CRYPTRES_H__ + +#define IDS_CERT_POLICY 100 +#define IDS_POLICY_ID 101 +#define IDS_POLICY_QUALIFIER_INFO 102 +#define IDS_POLICY_QUALIFIER_ID 103 +#define IDS_CPS 104 +#define IDS_USER_NOTICE 105 +#define IDS_QUALIFIER 106 +#define IDS_NOTICE_REF 107 +#define IDS_ORGANIZATION 108 +#define IDS_NOTICE_NUM 109 +#define IDS_NOTICE_TEXT 110 + +#endif /* ndef __CRYPTRES_H__ */ diff --git a/dlls/cryptdlg/main.c b/dlls/cryptdlg/main.c index 21012c58d7a..1971578dbf5 100644 --- a/dlls/cryptdlg/main.c +++ b/dlls/cryptdlg/main.c @@ -32,10 +32,14 @@ #include "objbase.h" #include "cryptdlg.h" #include "cryptuiapi.h" +#include "cryptres.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg); +static HINSTANCE hInstance; + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); @@ -46,6 +50,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); + hInstance = hinstDLL; break; case DLL_PROCESS_DETACH: break; @@ -466,6 +471,661 @@ BOOL WINAPI CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W *info) return ret; } +static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded, + WCHAR *str, DWORD *pcchStr) +{ + BOOL ret; + DWORD charsNeeded; + + if (cbEncoded) + charsNeeded = (cbEncoded * 3); + else + charsNeeded = 1; + if (!str) + { + *pcchStr = charsNeeded; + ret = TRUE; + } + else if (*pcchStr < charsNeeded) + { + *pcchStr = charsNeeded; + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + { + static const WCHAR fmt[] = { '%','0','2','x',' ',0 }; + static const WCHAR endFmt[] = { '%','0','2','x',0 }; + DWORD i; + LPWSTR ptr = str; + + *pcchStr = charsNeeded; + if (cbEncoded) + { + for (i = 0; i < cbEncoded; i++) + { + if (i < cbEncoded - 1) + ptr += sprintfW(ptr, fmt, pbEncoded[i]); + else + ptr += sprintfW(ptr, endFmt, pbEncoded[i]); + } + } + else + *ptr = 0; + ret = TRUE; + } + return ret; +} + +static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 }; +static const WCHAR colonCrlf[] = { ':','\r','\n',0 }; +static const WCHAR colonSpace[] = { ':',' ',0 }; +static const WCHAR crlf[] = { '\r','\n',0 }; +static const WCHAR commaSep[] = { ',',' ',0 }; + +static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType, + DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, + WCHAR *str, DWORD *pcchStr) +{ + BOOL ret; + DWORD size, charsNeeded = 1; + CERT_NAME_VALUE *cpsValue; + + if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING, + pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &cpsValue, &size))) + { + LPCWSTR headingSep, sep; + DWORD headingSepLen, sepLen; + + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + headingSep = colonCrlf; + sep = crlf; + } + else + { + headingSep = colonSpace; + sep = commaSep; + } + sepLen = strlenW(sep); + headingSepLen = strlenW(headingSep); + + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 3 * strlenW(indent); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += cpsValue->Value.cbData / sizeof(WCHAR); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, (LPWSTR)cpsValue->Value.pbData); + str += cpsValue->Value.cbData / sizeof(WCHAR); + } + charsNeeded += sepLen; + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, sep); + str += sepLen; + } + LocalFree(cpsValue); + if (!str) + *pcchStr = charsNeeded; + else if (*pcchStr < charsNeeded) + { + *pcchStr = charsNeeded; + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + *pcchStr = charsNeeded; + } + return ret; +} + +static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType, + DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, + WCHAR *str, DWORD *pcchStr) +{ + BOOL ret; + DWORD size, charsNeeded = 1; + CERT_POLICY_QUALIFIER_USER_NOTICE *notice; + + if ((ret = CryptDecodeObjectEx(dwCertEncodingType, + X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded, + CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size))) + { + static const WCHAR numFmt[] = { '%','d',0 }; + CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef = + notice->pNoticeReference; + LPCWSTR headingSep, sep; + DWORD headingSepLen, sepLen; + LPWSTR noticeRef, organization, noticeNum, noticeText; + DWORD noticeRefLen, organizationLen, noticeNumLen, noticeTextLen; + WCHAR noticeNumStr[11]; + + noticeRefLen = LoadStringW(hInstance, IDS_NOTICE_REF, + (LPWSTR)¬iceRef, 0); + organizationLen = LoadStringW(hInstance, IDS_ORGANIZATION, + (LPWSTR)&organization, 0); + noticeNumLen = LoadStringW(hInstance, IDS_NOTICE_NUM, + (LPWSTR)¬iceNum, 0); + noticeTextLen = LoadStringW(hInstance, IDS_NOTICE_TEXT, + (LPWSTR)¬iceText, 0); + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + headingSep = colonCrlf; + sep = crlf; + } + else + { + headingSep = colonSpace; + sep = commaSep; + } + sepLen = strlenW(sep); + headingSepLen = strlenW(headingSep); + + if (pNoticeRef) + { + DWORD k; + LPCSTR src; + + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 3 * strlenW(indent); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += noticeRefLen; + if (str && *pcchStr >= charsNeeded) + { + memcpy(str, noticeRef, noticeRefLen * sizeof(WCHAR)); + str += noticeRefLen; + } + charsNeeded += headingSepLen; + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, headingSep); + str += headingSepLen; + } + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 4 * strlenW(indent); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += organizationLen; + if (str && *pcchStr >= charsNeeded) + { + memcpy(str, organization, organizationLen * sizeof(WCHAR)); + str += organizationLen; + } + charsNeeded += strlen(pNoticeRef->pszOrganization); + if (str && *pcchStr >= charsNeeded) + for (src = pNoticeRef->pszOrganization; src && *src; + src++, str++) + *str = *src; + charsNeeded += sepLen; + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, sep); + str += sepLen; + } + for (k = 0; k < pNoticeRef->cNoticeNumbers; k++) + { + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 4 * strlenW(indent); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += noticeNumLen; + if (str && *pcchStr >= charsNeeded) + { + memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR)); + str += noticeNumLen; + } + sprintfW(noticeNumStr, numFmt, k + 1); + charsNeeded += strlenW(noticeNumStr); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, noticeNumStr); + str += strlenW(noticeNumStr); + } + charsNeeded += sepLen; + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, sep); + str += sepLen; + } + } + } + if (notice->pszDisplayText) + { + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 3 * strlenW(indent); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += noticeTextLen; + if (str && *pcchStr >= charsNeeded) + { + memcpy(str, noticeText, noticeTextLen * sizeof(WCHAR)); + str += noticeTextLen; + } + charsNeeded += strlenW(notice->pszDisplayText); + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, notice->pszDisplayText); + str += strlenW(notice->pszDisplayText); + } + charsNeeded += sepLen; + if (str && *pcchStr >= charsNeeded) + { + strcpyW(str, sep); + str += sepLen; + } + } + LocalFree(notice); + if (!str) + *pcchStr = charsNeeded; + else if (*pcchStr < charsNeeded) + { + *pcchStr = charsNeeded; + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + *pcchStr = charsNeeded; + } + return ret; +} + +/*********************************************************************** + * FormatVerisignExtension (CRYPTDLG.@) + */ +BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType, + DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, + LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, + DWORD *pcbFormat) +{ + CERT_POLICIES_INFO *policies; + DWORD size; + BOOL ret = FALSE; + + if (!cbEncoded) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES, + pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size))) + { + static const WCHAR numFmt[] = { '%','d',0 }; + DWORD charsNeeded = 1; /* space for NULL terminator */ + LPCWSTR headingSep, sep; + DWORD headingSepLen, sepLen; + WCHAR policyNum[11], policyQualifierNum[11]; + LPWSTR certPolicy, policyId, policyQualifierInfo, policyQualifierId; + LPWSTR cps, userNotice, qualifier; + DWORD certPolicyLen, policyIdLen, policyQualifierInfoLen; + DWORD policyQualifierIdLen, cpsLen, userNoticeLen, qualifierLen; + DWORD i; + LPWSTR str = pbFormat; + + certPolicyLen = LoadStringW(hInstance, IDS_CERT_POLICY, + (LPWSTR)&certPolicy, 0); + policyIdLen = LoadStringW(hInstance, IDS_POLICY_ID, (LPWSTR)&policyId, + 0); + policyQualifierInfoLen = LoadStringW(hInstance, + IDS_POLICY_QUALIFIER_INFO, (LPWSTR)&policyQualifierInfo, 0); + policyQualifierIdLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_ID, + (LPWSTR)&policyQualifierId, 0); + cpsLen = LoadStringW(hInstance, IDS_CPS, (LPWSTR)&cps, 0); + userNoticeLen = LoadStringW(hInstance, IDS_USER_NOTICE, + (LPWSTR)&userNotice, 0); + qualifierLen = LoadStringW(hInstance, IDS_QUALIFIER, + (LPWSTR)&qualifier, 0); + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + headingSep = colonCrlf; + sep = crlf; + } + else + { + headingSep = colonSpace; + sep = commaSep; + } + sepLen = strlenW(sep); + headingSepLen = strlenW(headingSep); + + for (i = 0; ret && i < policies->cPolicyInfo; i++) + { + CERT_POLICY_INFO *policy = &policies->rgPolicyInfo[i]; + DWORD j; + LPCSTR src; + + charsNeeded += 1; /* '['*/ + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + *str++ = '['; + sprintfW(policyNum, numFmt, i + 1); + charsNeeded += strlenW(policyNum); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, policyNum); + str += strlenW(policyNum); + } + charsNeeded += 1; /* ']'*/ + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + *str++ = ']'; + charsNeeded += certPolicyLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, certPolicy, certPolicyLen * sizeof(WCHAR)); + str += certPolicyLen; + } + charsNeeded += headingSepLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, headingSep); + str += headingSepLen; + } + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += strlenW(indent); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += policyIdLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, policyId, policyIdLen * sizeof(WCHAR)); + str += policyIdLen; + } + charsNeeded += strlen(policy->pszPolicyIdentifier); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + for (src = policy->pszPolicyIdentifier; src && *src; + src++, str++) + *str = *src; + } + charsNeeded += sepLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, sep); + str += sepLen; + } + for (j = 0; j < policy->cPolicyQualifier; j++) + { + CERT_POLICY_QUALIFIER_INFO *qualifierInfo = + &policy->rgPolicyQualifier[j]; + DWORD sizeRemaining; + + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += strlenW(indent); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += 1; /* '['*/ + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + *str++ = '['; + charsNeeded += strlenW(policyNum); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, policyNum); + str += strlenW(policyNum); + } + charsNeeded += 1; /* ','*/ + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + *str++ = ','; + sprintfW(policyQualifierNum, numFmt, j + 1); + charsNeeded += strlenW(policyQualifierNum); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, policyQualifierNum); + str += strlenW(policyQualifierNum); + } + charsNeeded += 1; /* ']'*/ + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + *str++ = ']'; + charsNeeded += policyQualifierInfoLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, policyQualifierInfo, + policyQualifierInfoLen * sizeof(WCHAR)); + str += policyQualifierInfoLen; + } + charsNeeded += headingSepLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, headingSep); + str += headingSepLen; + } + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 2 * strlenW(indent); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += policyQualifierIdLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, policyQualifierId, + policyQualifierIdLen * sizeof(WCHAR)); + str += policyQualifierIdLen; + } + if (!strcmp(qualifierInfo->pszPolicyQualifierId, + szOID_PKIX_POLICY_QUALIFIER_CPS)) + { + charsNeeded += cpsLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, cps, cpsLen * sizeof(WCHAR)); + str += cpsLen; + } + } + else if (!strcmp(qualifierInfo->pszPolicyQualifierId, + szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) + { + charsNeeded += userNoticeLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, userNotice, userNoticeLen * sizeof(WCHAR)); + str += userNoticeLen; + } + } + else + { + charsNeeded += strlen(qualifierInfo->pszPolicyQualifierId); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + for (src = qualifierInfo->pszPolicyQualifierId; + src && *src; src++, str++) + *str = *src; + } + } + charsNeeded += sepLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, sep); + str += sepLen; + } + if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) + { + charsNeeded += 2 * strlenW(indent); + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, indent); + str += strlenW(indent); + strcpyW(str, indent); + str += strlenW(indent); + } + } + charsNeeded += qualifierLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + memcpy(str, qualifier, qualifierLen * sizeof(WCHAR)); + str += qualifierLen; + } + charsNeeded += headingSepLen; + if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) + { + strcpyW(str, headingSep); + str += headingSepLen; + } + /* This if block is deliberately redundant with the same if + * block above, in order to keep the code more readable (the + * code flow follows the order in which the strings are output.) + */ + if (!strcmp(qualifierInfo->pszPolicyQualifierId, + szOID_PKIX_POLICY_QUALIFIER_CPS)) + { + if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) + { + /* Insufficient space, determine how much is needed. */ + ret = CRYPT_FormatCPS(dwCertEncodingType, + dwFormatStrType, qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, NULL, &size); + if (ret) + charsNeeded += size - 1; + } + else + { + sizeRemaining = *pcbFormat / sizeof(WCHAR); + sizeRemaining -= str - (LPWSTR)pbFormat; + ret = CRYPT_FormatCPS(dwCertEncodingType, + dwFormatStrType, qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, str, &sizeRemaining); + if (ret || GetLastError() == ERROR_MORE_DATA) + { + charsNeeded += sizeRemaining - 1; + str += sizeRemaining - 1; + } + } + } + else if (!strcmp(qualifierInfo->pszPolicyQualifierId, + szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) + { + if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) + { + /* Insufficient space, determine how much is needed. */ + ret = CRYPT_FormatUserNotice(dwCertEncodingType, + dwFormatStrType, qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, NULL, &size); + if (ret) + charsNeeded += size - 1; + } + else + { + sizeRemaining = *pcbFormat / sizeof(WCHAR); + sizeRemaining -= str - (LPWSTR)pbFormat; + ret = CRYPT_FormatUserNotice(dwCertEncodingType, + dwFormatStrType, qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, str, &sizeRemaining); + if (ret || GetLastError() == ERROR_MORE_DATA) + { + charsNeeded += sizeRemaining - 1; + str += sizeRemaining - 1; + } + } + } + else + { + if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) + { + /* Insufficient space, determine how much is needed. */ + ret = CRYPT_FormatHexString( + qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, NULL, &size); + if (ret) + charsNeeded += size - 1; + } + else + { + sizeRemaining = *pcbFormat / sizeof(WCHAR); + sizeRemaining -= str - (LPWSTR)pbFormat; + ret = CRYPT_FormatHexString( + qualifierInfo->Qualifier.pbData, + qualifierInfo->Qualifier.cbData, str, &sizeRemaining); + if (ret || GetLastError() == ERROR_MORE_DATA) + { + charsNeeded += sizeRemaining - 1; + str += sizeRemaining - 1; + } + } + } + } + } + LocalFree(policies); + if (ret) + { + if (!pbFormat) + *pcbFormat = charsNeeded * sizeof(WCHAR); + else if (*pcbFormat < charsNeeded * sizeof(WCHAR)) + { + *pcbFormat = charsNeeded * sizeof(WCHAR); + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + *pcbFormat = charsNeeded * sizeof(WCHAR); + } + } + return ret; +} + #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4" /***********************************************************************