//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1995 - 1999 // // File: ceformat.cpp // // Contents: helper functions // //-------------------------------------------------------------------------- #include "pch.cpp" #pragma hdrstop #include "celib.h" #include #include HRESULT ceDupString( IN WCHAR const *pwszIn, IN WCHAR **ppwszOut) { DWORD cb; HRESULT hr; cb = (wcslen(pwszIn) + 1) * sizeof(WCHAR); *ppwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cb); if (NULL == *ppwszOut) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory(*ppwszOut, pwszIn, cb); hr = S_OK; error: return(hr); } #define cwcCNMAX 64 // 64 chars max for CN #define cwcCHOPHASHMAX (1 + 5) // "-%05hu" decimal USHORT hash digits #define cwcCHOPBASE (cwcCNMAX - (cwcCHOPHASHMAX + cwcSUFFIXMAX)) HRESULT ceSanitizedNameToDSName( IN WCHAR const *pwszSanitizedName, OUT WCHAR **ppwszNameOut) { HRESULT hr; DWORD cwc; DWORD cwcCopy; WCHAR wszDSName[cwcCHOPBASE + cwcCHOPHASHMAX + 1]; *ppwszNameOut = NULL; cwc = wcslen(pwszSanitizedName); cwcCopy = cwc; if (cwcCHOPBASE < cwcCopy) { cwcCopy = cwcCHOPBASE; } CopyMemory(wszDSName, pwszSanitizedName, cwcCopy * sizeof(WCHAR)); wszDSName[cwcCopy] = L'\0'; if (cwcCHOPBASE < cwc) { // Hash the rest of the name into a USHORT USHORT usHash = 0; DWORD i; WCHAR *pwsz; // Truncate an incomplete sanitized Unicode character pwsz = wcsrchr(wszDSName, L'!'); if (NULL != pwsz && wcslen(pwsz) < 5) { cwcCopy -= wcslen(pwsz); *pwsz = L'\0'; } for (i = cwcCopy; i < cwc; i++) { USHORT usLowBit = (0x8000 & usHash)? 1 : 0; usHash = ((usHash << 1) | usLowBit) + pwszSanitizedName[i]; } wsprintf(&wszDSName[cwcCopy], L"-%05hu", usHash); assert(wcslen(wszDSName) < ARRAYSIZE(wszDSName)); } hr = ceDupString(wszDSName, ppwszNameOut); _JumpIfError(hr, error, "ceDupString"); error: return(hr); } HRESULT ceInternetCanonicalizeUrl( IN WCHAR const *pwszIn, OUT WCHAR **ppwszOut) { HRESULT hr; WCHAR *pwsz = NULL; assert(NULL != pwszIn); if (0 == _wcsnicmp(L"file:", pwszIn, 5)) { hr = ceDupString(pwszIn, &pwsz); _JumpIfError(hr, error, "ceDupString"); } else { // Calculate required buffer size by passing a very small buffer // The call will fail, and tell us how big the buffer should be. WCHAR wszPlaceHolder[1]; DWORD cwc = ARRAYSIZE(wszPlaceHolder); BOOL bResult; bResult = InternetCanonicalizeUrl( pwszIn, // lpszUrl wszPlaceHolder, // lpszBuffer &cwc, // lpdwBufferLength 0); // dwFlags assert(!bResult); // This will always fail hr = ceHLastError(); if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) { // unexpected error _JumpError(hr, error, "InternetCanonicalizeUrl"); } // NOTE: InternetCanonicalizeUrl counts characters, not bytes as doc'd // cwc includes trailing L'0' pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR)); if (NULL == pwsz) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } // canonicalize if (!InternetCanonicalizeUrl( pwszIn, // lpszUrl pwsz, // lpszBuffer &cwc, // lpdwBufferLength 0)) // dwFlags { hr = ceHLastError(); _JumpError(hr, error, "InternetCanonicalizeUrl"); } } *ppwszOut = pwsz; pwsz = NULL; hr = S_OK; error: if (NULL != pwsz) { LocalFree(pwsz); } return(hr); } // ceFormatCertsrvStringArray FormatMessage arguments: // // %1 -- Machine full DNS name: pwszServerName_p1_2; // // %2 -- Machine short name: first DNS component of pwszServerName_p1_2 // // %3 -- Sanitized CA name: pwszSanitizedName_p3_7 // // %4 -- Cert Filename Suffix: // if 0 == iCert_p4 && MAXDWORD == iCertTarget_p4: L"" // else if MAXDWORD != iCertTarget_p4 L"(%u-%u)" // else L"(%u)" // // %5 -- DS DN path to Domain root: pwszDomainDN_p5 // // %6 -- DS DN path to Configuration container: pwszConfigDN_p6 // // %7 -- Sanitized CA name, truncated and hash suffix added if too long: // pwszSanitizedName_p3_7 // // %8 -- CRL Filename/Key Name Suffix: L"" if 0 == iCRL_p8; else L"(%u)" // // %9 -- CRL Filename Suffix: L"" if !fDeltaCRL_p9; else L"+" // // %10 -- DS CRL attribute: L"" if !fDSAttrib_p10_11; depends on fDeltaCRL_p9 // // %11 -- DS CA Cert attribute: L"" if !fDSAttrib_p10_11 // // %12 -- DS user cert attribute // // %13 -- DS KRA cert attribute // // %14 -- DS cross cert pair attribute #ifndef wszDSSEARCHBASECRLATTRIBUTE #define wszDSSEARCHBASECRLATTRIBUTE L"?certificateRevocationList?base?objectclass=cRLDistributionPoint" #endif #ifndef wszDSSEARCHDELTACRLATTRIBUTE #define wszDSSEARCHDELTACRLATTRIBUTE L"?deltaRevocationList?base?objectclass=cRLDistributionPoint" #endif #ifndef wszDSSEARCHCACERTATTRIBUTE #define wszDSSEARCHCACERTATTRIBUTE L"?cACertificate?base?objectclass=certificationAuthority" #endif #ifndef wszDSSEARCHUSERCERTATTRIBUTE #define wszDSSEARCHUSERCERTATTRIBUTE L"?userCertificate?base?objectClass=*" #endif #ifndef wszDSSEARCHKRACERTATTRIBUTE #define wszDSSEARCHKRACERTATTRIBUTE L"?userCertificate?one?objectClass=msPKI-PrivateKeyRecoveryAgent" #endif #ifndef wszDSSEARCHCROSSCERTPAIRATTRIBUTE #define wszDSSEARCHCROSSCERTPAIRATTRIBUTE L"?crossCertificatePair?one?objectClass=certificationAuthority" #endif HRESULT ceFormatCertsrvStringArray( IN BOOL fURL, IN LPCWSTR pwszServerName_p1_2, IN LPCWSTR pwszSanitizedName_p3_7, IN DWORD iCert_p4, IN DWORD iCertTarget_p4, IN LPCWSTR pwszDomainDN_p5, IN LPCWSTR pwszConfigDN_p6, IN DWORD iCRL_p8, IN BOOL fDeltaCRL_p9, IN BOOL fDSAttrib_p10_11, IN DWORD cStrings, IN LPCWSTR *apwszStringsIn, OUT LPWSTR *apwszStringsOut) { HRESULT hr = S_OK; LPCWSTR apwszInsertionArray[100]; // 100 'cause this is the max number of insertion numbers allowed by FormatMessage LPWSTR pwszCurrent = NULL; BSTR strShortMachineName = NULL; DWORD i; WCHAR *pwszSanitizedDSName = NULL; WCHAR wszCertSuffix[2 * cwcFILENAMESUFFIXMAX]; WCHAR wszCRLSuffix[cwcFILENAMESUFFIXMAX]; WCHAR wszDeltaCRLSuffix[cwcFILENAMESUFFIXMAX]; WCHAR const *pwszT; ZeroMemory(apwszStringsOut, cStrings * sizeof(apwszStringsOut[0])); ZeroMemory(apwszInsertionArray, sizeof(apwszInsertionArray)); // Format the template into a real name // Initialize the insertion string array. //+================================================ // Machine DNS name (%1) assert(L'1' == wszFCSAPARM_SERVERDNSNAME[1]); apwszInsertionArray[1 - 1] = pwszServerName_p1_2; //+================================================ // Short Machine Name (%2) assert(L'2' == wszFCSAPARM_SERVERSHORTNAME[1]); strShortMachineName = SysAllocString(pwszServerName_p1_2); if (strShortMachineName == NULL) { hr = E_OUTOFMEMORY; _JumpIfError(hr, error, "SysAllocString"); } pwszCurrent = wcschr(strShortMachineName, L'.'); if (NULL != pwszCurrent) { *pwszCurrent = 0; } apwszInsertionArray[2 - 1] = strShortMachineName; //+================================================ // sanitized name (%3) assert(L'3' == wszFCSAPARM_SANITIZEDCANAME[1]); apwszInsertionArray[3 - 1] = pwszSanitizedName_p3_7; //+================================================ // Cert filename suffix (%4) | (%4-%4) assert(L'4' == wszFCSAPARM_CERTFILENAMESUFFIX[1]); wszCertSuffix[0] = L'\0'; if (0 != iCert_p4 || MAXDWORD != iCertTarget_p4) { wsprintf( wszCertSuffix, MAXDWORD != iCertTarget_p4? L"(%u-%u)" : L"(%u)", iCert_p4, iCertTarget_p4); } apwszInsertionArray[4 - 1] = wszCertSuffix; //+================================================ // Domain DN (%5) if (NULL == pwszDomainDN_p5 || L'\0' == *pwszDomainDN_p5) { pwszDomainDN_p5 = L"DC=UnavailableDomainDN"; } assert(L'5' == wszFCSAPARM_DOMAINDN[1]); apwszInsertionArray[5 - 1] = pwszDomainDN_p5; //+================================================ // Config DN (%6) if (NULL == pwszConfigDN_p6 || L'\0' == *pwszConfigDN_p6) { pwszConfigDN_p6 = L"DC=UnavailableConfigDN"; } assert(L'6' == wszFCSAPARM_CONFIGDN[1]); apwszInsertionArray[6 - 1] = pwszConfigDN_p6; // Don't pass pwszSanitizedName_p3_7 to SysAllocStringLen with the extended // length to avoid faulting past end of pwszSanitizedName_p3_7. //+================================================ // Sanitized Short Name (%7) assert(L'7' == wszFCSAPARM_SANITIZEDCANAMEHASH[1]); hr = ceSanitizedNameToDSName(pwszSanitizedName_p3_7, &pwszSanitizedDSName); _JumpIfError(hr, error, "ceSanitizedNameToDSName"); apwszInsertionArray[7 - 1] = pwszSanitizedDSName; //+================================================ // CRL filename suffix (%8) assert(L'8' == wszFCSAPARM_CRLFILENAMESUFFIX[1]); wszCRLSuffix[0] = L'\0'; if (0 != iCRL_p8) { wsprintf(wszCRLSuffix, L"(%u)", iCRL_p8); } apwszInsertionArray[8 - 1] = wszCRLSuffix; //+================================================ // Delta CRL filename suffix (%9) assert(L'9' == wszFCSAPARM_CRLDELTAFILENAMESUFFIX[1]); wszDeltaCRLSuffix[0] = L'\0'; if (fDeltaCRL_p9) { wcscpy(wszDeltaCRLSuffix, L"+"); } apwszInsertionArray[9 - 1] = wszDeltaCRLSuffix; //+================================================ // CRL attribute (%10) assert(L'1' == wszFCSAPARM_DSCRLATTRIBUTE[1]); assert(L'0' == wszFCSAPARM_DSCRLATTRIBUTE[2]); pwszT = L""; if (fDSAttrib_p10_11) { pwszT = fDeltaCRL_p9? wszDSSEARCHDELTACRLATTRIBUTE : wszDSSEARCHBASECRLATTRIBUTE; } apwszInsertionArray[10 - 1] = pwszT; //+================================================ // CA cert attribute (%11) assert(L'1' == wszFCSAPARM_DSCACERTATTRIBUTE[1]); assert(L'1' == wszFCSAPARM_DSCACERTATTRIBUTE[2]); pwszT = L""; if (fDSAttrib_p10_11) { pwszT = wszDSSEARCHCACERTATTRIBUTE; } apwszInsertionArray[11 - 1] = pwszT; //+================================================ // User cert attribute (%12) assert(L'1' == wszFCSAPARM_DSUSERCERTATTRIBUTE[1]); assert(L'2' == wszFCSAPARM_DSUSERCERTATTRIBUTE[2]); pwszT = L""; if (fDSAttrib_p10_11) { pwszT = wszDSSEARCHUSERCERTATTRIBUTE; } apwszInsertionArray[12 - 1] = pwszT; //+================================================ // KRA cert attribute (%13) assert(L'1' == wszFCSAPARM_DSKRACERTATTRIBUTE[1]); assert(L'3' == wszFCSAPARM_DSKRACERTATTRIBUTE[2]); pwszT = L""; if (fDSAttrib_p10_11) { pwszT = wszDSSEARCHKRACERTATTRIBUTE; } apwszInsertionArray[13 - 1] = pwszT; //+================================================ // Cross cert pair attribute (%14) assert(L'1' == wszFCSAPARM_DSCROSSCERTPAIRATTRIBUTE[1]); assert(L'4' == wszFCSAPARM_DSCROSSCERTPAIRATTRIBUTE[2]); pwszT = L""; if (fDSAttrib_p10_11) { pwszT = wszDSSEARCHCROSSCERTPAIRATTRIBUTE; } apwszInsertionArray[14 - 1] = pwszT; //+================================================ // Now format the strings... for (i = 0; i < cStrings; i++) { if (0 == FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, (VOID *) apwszStringsIn[i], 0, // dwMessageID 0, // dwLanguageID (LPWSTR) &apwszStringsOut[i], wcslen(apwszStringsIn[i]), (va_list *) apwszInsertionArray)) { hr = ceHLastError(); _JumpError(hr, error, "FormatMessage"); } if (fURL) { WCHAR *pwsz; hr = ceInternetCanonicalizeUrl(apwszStringsOut[i], &pwsz); _JumpIfError(hr, error, "ceInternetCanonicalizeUrl"); LocalFree(apwszStringsOut[i]); apwszStringsOut[i] = pwsz; } } error: if (S_OK != hr) { for (i = 0; i < cStrings; i++) { if (NULL != apwszStringsOut[i]) { LocalFree(apwszStringsOut[i]); apwszStringsOut[i] = NULL; } } } if (NULL != strShortMachineName) { SysFreeString(strShortMachineName); } if (NULL != pwszSanitizedDSName) { LocalFree(pwszSanitizedDSName); } return (hr); }