ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

str.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006 Juan Lang for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 #include <stdarg.h>
00019 
00020 #define NONAMELESSUNION
00021 
00022 #include "windef.h"
00023 #include "winbase.h"
00024 #include "winnls.h"
00025 #include "winuser.h"
00026 #include "wincrypt.h"
00027 #include "wine/debug.h"
00028 #include "wine/unicode.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
00031 
00032 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
00033  LPSTR psz, DWORD csz)
00034 {
00035     DWORD ret = 0, len;
00036 
00037     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
00038 
00039     switch (dwValueType)
00040     {
00041     case CERT_RDN_ANY_TYPE:
00042         break;
00043     case CERT_RDN_NUMERIC_STRING:
00044     case CERT_RDN_PRINTABLE_STRING:
00045     case CERT_RDN_TELETEX_STRING:
00046     case CERT_RDN_VIDEOTEX_STRING:
00047     case CERT_RDN_IA5_STRING:
00048     case CERT_RDN_GRAPHIC_STRING:
00049     case CERT_RDN_VISIBLE_STRING:
00050     case CERT_RDN_GENERAL_STRING:
00051         len = pValue->cbData;
00052         if (!psz || !csz)
00053             ret = len;
00054         else
00055         {
00056             DWORD chars = min(len, csz - 1);
00057 
00058             if (chars)
00059             {
00060                 memcpy(psz, pValue->pbData, chars);
00061                 ret += chars;
00062                 csz -= chars;
00063             }
00064         }
00065         break;
00066     case CERT_RDN_BMP_STRING:
00067     case CERT_RDN_UTF8_STRING:
00068         len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData,
00069          pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL);
00070         if (!psz || !csz)
00071             ret = len;
00072         else
00073         {
00074             DWORD chars = min(pValue->cbData / sizeof(WCHAR), csz - 1);
00075 
00076             if (chars)
00077             {
00078                 ret = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData,
00079                  chars, psz, csz - 1, NULL, NULL);
00080                 csz -= ret;
00081             }
00082         }
00083         break;
00084     default:
00085         FIXME("string type %d unimplemented\n", dwValueType);
00086     }
00087     if (psz && csz)
00088     {
00089         *(psz + ret) = '\0';
00090         csz--;
00091         ret++;
00092     }
00093     else
00094         ret++;
00095     TRACE("returning %d (%s)\n", ret, debugstr_a(psz));
00096     return ret;
00097 }
00098 
00099 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
00100  LPWSTR psz, DWORD csz)
00101 {
00102     DWORD ret = 0, len, i, strLen;
00103 
00104     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
00105 
00106     switch (dwValueType)
00107     {
00108     case CERT_RDN_ANY_TYPE:
00109         break;
00110     case CERT_RDN_NUMERIC_STRING:
00111     case CERT_RDN_PRINTABLE_STRING:
00112     case CERT_RDN_TELETEX_STRING:
00113     case CERT_RDN_VIDEOTEX_STRING:
00114     case CERT_RDN_IA5_STRING:
00115     case CERT_RDN_GRAPHIC_STRING:
00116     case CERT_RDN_VISIBLE_STRING:
00117     case CERT_RDN_GENERAL_STRING:
00118         len = pValue->cbData;
00119         if (!psz || !csz)
00120             ret = len;
00121         else
00122         {
00123             WCHAR *ptr = psz;
00124 
00125             for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++)
00126                 *ptr = pValue->pbData[i];
00127             ret = ptr - psz;
00128         }
00129         break;
00130     case CERT_RDN_BMP_STRING:
00131     case CERT_RDN_UTF8_STRING:
00132         strLen = len = pValue->cbData / sizeof(WCHAR);
00133         if (!psz || !csz)
00134             ret = len;
00135         else
00136         {
00137             WCHAR *ptr = psz;
00138 
00139             for (i = 0; i < strLen && ptr - psz < csz; ptr++, i++)
00140                 *ptr = ((LPCWSTR)pValue->pbData)[i];
00141             ret = ptr - psz;
00142         }
00143         break;
00144     default:
00145         FIXME("string type %d unimplemented\n", dwValueType);
00146     }
00147     if (psz && csz)
00148     {
00149         *(psz + ret) = '\0';
00150         csz--;
00151         ret++;
00152     }
00153     else
00154         ret++;
00155     TRACE("returning %d (%s)\n", ret, debugstr_w(psz));
00156     return ret;
00157 }
00158 
00159 static inline BOOL is_quotable_char(char c)
00160 {
00161     switch(c)
00162     {
00163     case '+':
00164     case ',':
00165     case '"':
00166     case '=':
00167     case '<':
00168     case '>':
00169     case ';':
00170     case '#':
00171     case '\n':
00172         return TRUE;
00173     default:
00174         return FALSE;
00175     }
00176 }
00177 
00178 static DWORD quote_rdn_value_to_str_a(DWORD dwValueType,
00179  PCERT_RDN_VALUE_BLOB pValue, LPSTR psz, DWORD csz)
00180 {
00181     DWORD ret = 0, len, i;
00182     BOOL needsQuotes = FALSE;
00183 
00184     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
00185 
00186     switch (dwValueType)
00187     {
00188     case CERT_RDN_ANY_TYPE:
00189         break;
00190     case CERT_RDN_NUMERIC_STRING:
00191     case CERT_RDN_PRINTABLE_STRING:
00192     case CERT_RDN_TELETEX_STRING:
00193     case CERT_RDN_VIDEOTEX_STRING:
00194     case CERT_RDN_IA5_STRING:
00195     case CERT_RDN_GRAPHIC_STRING:
00196     case CERT_RDN_VISIBLE_STRING:
00197     case CERT_RDN_GENERAL_STRING:
00198         len = pValue->cbData;
00199         if (pValue->cbData && isspace(pValue->pbData[0]))
00200             needsQuotes = TRUE;
00201         if (pValue->cbData && isspace(pValue->pbData[pValue->cbData - 1]))
00202             needsQuotes = TRUE;
00203         for (i = 0; i < pValue->cbData; i++)
00204         {
00205             if (is_quotable_char(pValue->pbData[i]))
00206                 needsQuotes = TRUE;
00207             if (pValue->pbData[i] == '"')
00208                 len += 1;
00209         }
00210         if (needsQuotes)
00211             len += 2;
00212         if (!psz || !csz)
00213             ret = len;
00214         else
00215         {
00216             char *ptr = psz;
00217 
00218             if (needsQuotes)
00219                 *ptr++ = '"';
00220             for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++)
00221             {
00222                 *ptr = pValue->pbData[i];
00223                 if (pValue->pbData[i] == '"' && ptr - psz < csz - 1)
00224                     *(++ptr) = '"';
00225             }
00226             if (needsQuotes && ptr - psz < csz)
00227                 *ptr++ = '"';
00228             ret = ptr - psz;
00229         }
00230         break;
00231     case CERT_RDN_BMP_STRING:
00232     case CERT_RDN_UTF8_STRING:
00233         len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData,
00234          pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL);
00235         if (pValue->cbData && isspaceW(((LPCWSTR)pValue->pbData)[0]))
00236             needsQuotes = TRUE;
00237         if (pValue->cbData &&
00238          isspaceW(((LPCWSTR)pValue->pbData)[pValue->cbData / sizeof(WCHAR)-1]))
00239             needsQuotes = TRUE;
00240         for (i = 0; i < pValue->cbData / sizeof(WCHAR); i++)
00241         {
00242             if (is_quotable_char(((LPCWSTR)pValue->pbData)[i]))
00243                 needsQuotes = TRUE;
00244             if (((LPCWSTR)pValue->pbData)[i] == '"')
00245                 len += 1;
00246         }
00247         if (needsQuotes)
00248             len += 2;
00249         if (!psz || !csz)
00250             ret = len;
00251         else
00252         {
00253             char *dst = psz;
00254 
00255             if (needsQuotes)
00256                 *dst++ = '"';
00257             for (i = 0; i < pValue->cbData / sizeof(WCHAR) &&
00258              dst - psz < csz; dst++, i++)
00259             {
00260                 LPCWSTR src = (LPCWSTR)pValue->pbData + i;
00261 
00262                 WideCharToMultiByte(CP_ACP, 0, src, 1, dst,
00263                  csz - (dst - psz) - 1, NULL, NULL);
00264                 if (*src == '"' && dst - psz < csz - 1)
00265                     *(++dst) = '"';
00266             }
00267             if (needsQuotes && dst - psz < csz)
00268                 *dst++ = '"';
00269             ret = dst - psz;
00270         }
00271         break;
00272     default:
00273         FIXME("string type %d unimplemented\n", dwValueType);
00274     }
00275     if (psz && csz)
00276     {
00277         *(psz + ret) = '\0';
00278         csz--;
00279         ret++;
00280     }
00281     else
00282         ret++;
00283     TRACE("returning %d (%s)\n", ret, debugstr_a(psz));
00284     return ret;
00285 }
00286 
00287 static DWORD quote_rdn_value_to_str_w(DWORD dwValueType,
00288  PCERT_RDN_VALUE_BLOB pValue, LPWSTR psz, DWORD csz)
00289 {
00290     DWORD ret = 0, len, i, strLen;
00291     BOOL needsQuotes = FALSE;
00292 
00293     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
00294 
00295     switch (dwValueType)
00296     {
00297     case CERT_RDN_ANY_TYPE:
00298         break;
00299     case CERT_RDN_NUMERIC_STRING:
00300     case CERT_RDN_PRINTABLE_STRING:
00301     case CERT_RDN_TELETEX_STRING:
00302     case CERT_RDN_VIDEOTEX_STRING:
00303     case CERT_RDN_IA5_STRING:
00304     case CERT_RDN_GRAPHIC_STRING:
00305     case CERT_RDN_VISIBLE_STRING:
00306     case CERT_RDN_GENERAL_STRING:
00307         len = pValue->cbData;
00308         if (pValue->cbData && isspace(pValue->pbData[0]))
00309             needsQuotes = TRUE;
00310         if (pValue->cbData && isspace(pValue->pbData[pValue->cbData - 1]))
00311             needsQuotes = TRUE;
00312         for (i = 0; i < pValue->cbData; i++)
00313         {
00314             if (is_quotable_char(pValue->pbData[i]))
00315                 needsQuotes = TRUE;
00316             if (pValue->pbData[i] == '"')
00317                 len += 1;
00318         }
00319         if (needsQuotes)
00320             len += 2;
00321         if (!psz || !csz)
00322             ret = len;
00323         else
00324         {
00325             WCHAR *ptr = psz;
00326 
00327             if (needsQuotes)
00328                 *ptr++ = '"';
00329             for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++)
00330             {
00331                 *ptr = pValue->pbData[i];
00332                 if (pValue->pbData[i] == '"' && ptr - psz < csz - 1)
00333                     *(++ptr) = '"';
00334             }
00335             if (needsQuotes && ptr - psz < csz)
00336                 *ptr++ = '"';
00337             ret = ptr - psz;
00338         }
00339         break;
00340     case CERT_RDN_BMP_STRING:
00341     case CERT_RDN_UTF8_STRING:
00342         strLen = len = pValue->cbData / sizeof(WCHAR);
00343         if (pValue->cbData && isspace(pValue->pbData[0]))
00344             needsQuotes = TRUE;
00345         if (pValue->cbData && isspace(pValue->pbData[strLen - 1]))
00346             needsQuotes = TRUE;
00347         for (i = 0; i < strLen; i++)
00348         {
00349             if (is_quotable_char(((LPCWSTR)pValue->pbData)[i]))
00350                 needsQuotes = TRUE;
00351             if (((LPCWSTR)pValue->pbData)[i] == '"')
00352                 len += 1;
00353         }
00354         if (needsQuotes)
00355             len += 2;
00356         if (!psz || !csz)
00357             ret = len;
00358         else
00359         {
00360             WCHAR *ptr = psz;
00361 
00362             if (needsQuotes)
00363                 *ptr++ = '"';
00364             for (i = 0; i < strLen && ptr - psz < csz; ptr++, i++)
00365             {
00366                 *ptr = ((LPCWSTR)pValue->pbData)[i];
00367                 if (((LPCWSTR)pValue->pbData)[i] == '"' && ptr - psz < csz - 1)
00368                     *(++ptr) = '"';
00369             }
00370             if (needsQuotes && ptr - psz < csz)
00371                 *ptr++ = '"';
00372             ret = ptr - psz;
00373         }
00374         break;
00375     default:
00376         FIXME("string type %d unimplemented\n", dwValueType);
00377     }
00378     if (psz && csz)
00379     {
00380         *(psz + ret) = '\0';
00381         csz--;
00382         ret++;
00383     }
00384     else
00385         ret++;
00386     TRACE("returning %d (%s)\n", ret, debugstr_w(psz));
00387     return ret;
00388 }
00389 
00390 /* Adds the prefix prefix to the string pointed to by psz, followed by the
00391  * character '='.  Copies no more than csz characters.  Returns the number of
00392  * characters copied.  If psz is NULL, returns the number of characters that
00393  * would be copied.
00394  */
00395 static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
00396 {
00397     DWORD chars;
00398 
00399     TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz);
00400 
00401     if (psz)
00402     {
00403         chars = min(strlen(prefix), csz);
00404         memcpy(psz, prefix, chars);
00405         *(psz + chars) = '=';
00406         chars++;
00407     }
00408     else
00409         chars = lstrlenA(prefix) + 1;
00410     return chars;
00411 }
00412 
00413 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
00414  DWORD dwStrType, LPSTR psz, DWORD csz)
00415 {
00416     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
00417      CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
00418     static const char commaSep[] = ", ";
00419     static const char semiSep[] = "; ";
00420     static const char crlfSep[] = "\r\n";
00421     static const char plusSep[] = " + ";
00422     static const char spaceSep[] = " ";
00423     DWORD ret = 0, bytes = 0;
00424     BOOL bRet;
00425     CERT_NAME_INFO *info;
00426 
00427     TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType,
00428      psz, csz);
00429     if (dwStrType & unsupportedFlags)
00430         FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags);
00431 
00432     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
00433      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
00434     if (bRet)
00435     {
00436         DWORD i, j, sepLen, rdnSepLen;
00437         LPCSTR sep, rdnSep;
00438         BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG;
00439         const CERT_RDN *rdn = info->rgRDN;
00440 
00441         if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1);
00442 
00443         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
00444             sep = semiSep;
00445         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
00446             sep = crlfSep;
00447         else
00448             sep = commaSep;
00449         sepLen = strlen(sep);
00450         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
00451             rdnSep = spaceSep;
00452         else
00453             rdnSep = plusSep;
00454         rdnSepLen = strlen(rdnSep);
00455         for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
00456         {
00457             for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
00458             {
00459                 DWORD chars;
00460                 char prefixBuf[10]; /* big enough for GivenName */
00461                 LPCSTR prefix = NULL;
00462 
00463                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
00464                     prefix = rdn->rgRDNAttr[j].pszObjId;
00465                 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
00466                 {
00467                     PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
00468                      CRYPT_OID_INFO_OID_KEY,
00469                      rdn->rgRDNAttr[j].pszObjId,
00470                      CRYPT_RDN_ATTR_OID_GROUP_ID);
00471 
00472                     if (oidInfo)
00473                     {
00474                         WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
00475                          prefixBuf, sizeof(prefixBuf), NULL, NULL);
00476                         prefix = prefixBuf;
00477                     }
00478                     else
00479                         prefix = rdn->rgRDNAttr[j].pszObjId;
00480                 }
00481                 if (prefix)
00482                 {
00483                     /* - 1 is needed to account for the NULL terminator. */
00484                     chars = CRYPT_AddPrefixA(prefix,
00485                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
00486                     ret += chars;
00487                 }
00488                 chars = quote_rdn_value_to_str_a(
00489                  rdn->rgRDNAttr[j].dwValueType,
00490                  &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL,
00491                  psz ? csz - ret : 0);
00492                 if (chars)
00493                     ret += chars - 1;
00494                 if (j < rdn->cRDNAttr - 1)
00495                 {
00496                     if (psz && ret < csz - rdnSepLen - 1)
00497                         memcpy(psz + ret, rdnSep, rdnSepLen);
00498                     ret += rdnSepLen;
00499                 }
00500             }
00501             if (i < info->cRDN - 1)
00502             {
00503                 if (psz && ret < csz - sepLen - 1)
00504                     memcpy(psz + ret, sep, sepLen);
00505                 ret += sepLen;
00506             }
00507             if(reverse) rdn--;
00508             else rdn++;
00509         }
00510         LocalFree(info);
00511     }
00512     if (psz && csz)
00513     {
00514         *(psz + ret) = '\0';
00515         ret++;
00516     }
00517     else
00518         ret++;
00519     TRACE("Returning %s\n", debugstr_a(psz));
00520     return ret;
00521 }
00522 
00523 /* Adds the prefix prefix to the wide-character string pointed to by psz,
00524  * followed by the character '='.  Copies no more than csz characters.  Returns
00525  * the number of characters copied.  If psz is NULL, returns the number of
00526  * characters that would be copied.
00527  * Assumes the characters in prefix are ASCII (not multibyte characters.)
00528  */
00529 static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz)
00530 {
00531     DWORD chars;
00532 
00533     TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz);
00534 
00535     if (psz)
00536     {
00537         DWORD i;
00538 
00539         chars = min(strlen(prefix), csz);
00540         for (i = 0; i < chars; i++)
00541             *(psz + i) = prefix[i];
00542         *(psz + chars) = '=';
00543         chars++;
00544     }
00545     else
00546         chars = lstrlenA(prefix) + 1;
00547     return chars;
00548 }
00549 
00550 /* Adds the prefix prefix to the string pointed to by psz, followed by the
00551  * character '='.  Copies no more than csz characters.  Returns the number of
00552  * characters copied.  If psz is NULL, returns the number of characters that
00553  * would be copied.
00554  */
00555 static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz)
00556 {
00557     DWORD chars;
00558 
00559     TRACE("(%s, %p, %d)\n", debugstr_w(prefix), psz, csz);
00560 
00561     if (psz)
00562     {
00563         chars = min(strlenW(prefix), csz);
00564         memcpy(psz, prefix, chars * sizeof(WCHAR));
00565         *(psz + chars) = '=';
00566         chars++;
00567     }
00568     else
00569         chars = lstrlenW(prefix) + 1;
00570     return chars;
00571 }
00572 
00573 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
00574 
00575 DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indentLevel,
00576  const CERT_NAME_BLOB *pName, DWORD dwStrType, LPWSTR psz, DWORD csz)
00577 {
00578     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
00579      CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
00580     static const WCHAR commaSep[] = { ',',' ',0 };
00581     static const WCHAR semiSep[] = { ';',' ',0 };
00582     static const WCHAR crlfSep[] = { '\r','\n',0 };
00583     static const WCHAR plusSep[] = { ' ','+',' ',0 };
00584     static const WCHAR spaceSep[] = { ' ',0 };
00585     DWORD ret = 0, bytes = 0;
00586     BOOL bRet;
00587     CERT_NAME_INFO *info;
00588 
00589     if (dwStrType & unsupportedFlags)
00590         FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags);
00591 
00592     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
00593      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
00594     if (bRet)
00595     {
00596         DWORD i, j, sepLen, rdnSepLen;
00597         LPCWSTR sep, rdnSep;
00598         BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG;
00599         const CERT_RDN *rdn = info->rgRDN;
00600 
00601         if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1);
00602 
00603         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
00604             sep = semiSep;
00605         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
00606             sep = crlfSep;
00607         else
00608             sep = commaSep;
00609         sepLen = lstrlenW(sep);
00610         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
00611             rdnSep = spaceSep;
00612         else
00613             rdnSep = plusSep;
00614         rdnSepLen = lstrlenW(rdnSep);
00615         for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
00616         {
00617             for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
00618             {
00619                 DWORD chars;
00620                 LPCSTR prefixA = NULL;
00621                 LPCWSTR prefixW = NULL;
00622 
00623                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
00624                     prefixA = rdn->rgRDNAttr[j].pszObjId;
00625                 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
00626                 {
00627                     PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
00628                      CRYPT_OID_INFO_OID_KEY,
00629                      rdn->rgRDNAttr[j].pszObjId,
00630                      CRYPT_RDN_ATTR_OID_GROUP_ID);
00631 
00632                     if (oidInfo)
00633                         prefixW = oidInfo->pwszName;
00634                     else
00635                         prefixA = rdn->rgRDNAttr[j].pszObjId;
00636                 }
00637                 if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
00638                 {
00639                     DWORD k;
00640 
00641                     for (k = 0; k < indentLevel; k++)
00642                     {
00643                         if (psz)
00644                         {
00645                             chars = min(strlenW(indent), csz - ret - 1);
00646                             memcpy(psz + ret, indent, chars * sizeof(WCHAR));
00647                         }
00648                         else
00649                             chars = strlenW(indent);
00650                         ret += chars;
00651                     }
00652                 }
00653                 if (prefixW)
00654                 {
00655                     /* - 1 is needed to account for the NULL terminator. */
00656                     chars = CRYPT_AddPrefixW(prefixW,
00657                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
00658                     ret += chars;
00659                 }
00660                 else if (prefixA)
00661                 {
00662                     /* - 1 is needed to account for the NULL terminator. */
00663                     chars = CRYPT_AddPrefixAToW(prefixA,
00664                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
00665                     ret += chars;
00666                 }
00667                 chars = quote_rdn_value_to_str_w(
00668                  rdn->rgRDNAttr[j].dwValueType,
00669                  &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL,
00670                  psz ? csz - ret : 0);
00671                 if (chars)
00672                     ret += chars - 1;
00673                 if (j < rdn->cRDNAttr - 1)
00674                 {
00675                     if (psz && ret < csz - rdnSepLen - 1)
00676                         memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
00677                     ret += rdnSepLen;
00678                 }
00679             }
00680             if (i < info->cRDN - 1)
00681             {
00682                 if (psz && ret < csz - sepLen - 1)
00683                     memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
00684                 ret += sepLen;
00685             }
00686             if(reverse) rdn--;
00687             else rdn++;
00688         }
00689         LocalFree(info);
00690     }
00691     if (psz && csz)
00692     {
00693         *(psz + ret) = '\0';
00694         ret++;
00695     }
00696     else
00697         ret++;
00698     return ret;
00699 }
00700 
00701 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
00702  DWORD dwStrType, LPWSTR psz, DWORD csz)
00703 {
00704     BOOL ret;
00705 
00706     TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType,
00707      psz, csz);
00708 
00709     ret = cert_name_to_str_with_indent(dwCertEncodingType, 0, pName, dwStrType,
00710      psz, csz);
00711     TRACE("Returning %s\n", debugstr_w(psz));
00712     return ret;
00713 }
00714 
00715 BOOL WINAPI CertStrToNameA(DWORD dwCertEncodingType, LPCSTR pszX500,
00716  DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded,
00717  LPCSTR *ppszError)
00718 {
00719     BOOL ret;
00720     int len;
00721 
00722     TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType,
00723      debugstr_a(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded,
00724      ppszError);
00725 
00726     len = MultiByteToWideChar(CP_ACP, 0, pszX500, -1, NULL, 0);
00727     if (len)
00728     {
00729         LPWSTR x500, errorStr;
00730 
00731         if ((x500 = CryptMemAlloc(len * sizeof(WCHAR))))
00732         {
00733             MultiByteToWideChar(CP_ACP, 0, pszX500, -1, x500, len);
00734             ret = CertStrToNameW(dwCertEncodingType, x500, dwStrType,
00735              pvReserved, pbEncoded, pcbEncoded,
00736              ppszError ? (LPCWSTR *)&errorStr : NULL);
00737             if (ppszError)
00738             {
00739                 if (!ret)
00740                 {
00741                     LONG i;
00742 
00743                     *ppszError = pszX500;
00744                     for (i = 0; i < errorStr - x500; i++)
00745                         *ppszError = CharNextA(*ppszError);
00746                 }
00747                 else
00748                     *ppszError = NULL;
00749             }
00750             CryptMemFree(x500);
00751         }
00752         else
00753         {
00754             SetLastError(ERROR_OUTOFMEMORY);
00755             ret = FALSE;
00756         }
00757     }
00758     else
00759     {
00760         SetLastError(CRYPT_E_INVALID_X500_STRING);
00761         if (ppszError)
00762             *ppszError = pszX500;
00763         ret = FALSE;
00764     }
00765     return ret;
00766 }
00767 
00768 struct KeynameKeeper
00769 {
00770     WCHAR  buf[10]; /* big enough for L"GivenName" */
00771     LPWSTR keyName; /* usually = buf, but may be allocated */
00772     DWORD  keyLen;
00773 };
00774 
00775 static void CRYPT_InitializeKeynameKeeper(struct KeynameKeeper *keeper)
00776 {
00777     keeper->keyName = keeper->buf;
00778     keeper->keyLen = sizeof(keeper->buf) / sizeof(keeper->buf[0]);
00779 }
00780 
00781 static void CRYPT_FreeKeynameKeeper(struct KeynameKeeper *keeper)
00782 {
00783     if (keeper->keyName != keeper->buf)
00784         CryptMemFree(keeper->keyName);
00785 }
00786 
00787 struct X500TokenW
00788 {
00789     LPCWSTR start;
00790     LPCWSTR end;
00791 };
00792 
00793 static void CRYPT_KeynameKeeperFromTokenW(struct KeynameKeeper *keeper,
00794  const struct X500TokenW *key)
00795 {
00796     DWORD len = key->end - key->start;
00797 
00798     if (len > keeper->keyLen)
00799     {
00800         if (keeper->keyName == keeper->buf)
00801             keeper->keyName = CryptMemAlloc(len * sizeof(WCHAR));
00802         else
00803             keeper->keyName = CryptMemRealloc(keeper->keyName,
00804              len * sizeof(WCHAR));
00805         keeper->keyLen = len;
00806     }
00807     memcpy(keeper->keyName, key->start, (key->end - key->start) *
00808      sizeof(WCHAR));
00809     keeper->keyName[len] = '\0';
00810     TRACE("Keyname is %s\n", debugstr_w(keeper->keyName));
00811 }
00812 
00813 static BOOL CRYPT_GetNextKeyW(LPCWSTR str, struct X500TokenW *token,
00814  LPCWSTR *ppszError)
00815 {
00816     BOOL ret = TRUE;
00817 
00818     while (*str && isspaceW(*str))
00819         str++;
00820     if (*str)
00821     {
00822         token->start = str;
00823         while (*str && *str != '=' && !isspaceW(*str))
00824             str++;
00825         if (*str && (*str == '=' || isspaceW(*str)))
00826             token->end = str;
00827         else
00828         {
00829             TRACE("missing equals char at %s\n", debugstr_w(token->start));
00830             if (ppszError)
00831                 *ppszError = token->start;
00832             SetLastError(CRYPT_E_INVALID_X500_STRING);
00833             ret = FALSE;
00834         }
00835     }
00836     else
00837         token->start = NULL;
00838     return ret;
00839 }
00840 
00841 /* Assumes separators are characters in the 0-255 range */
00842 static BOOL CRYPT_GetNextValueW(LPCWSTR str, DWORD dwFlags, LPCWSTR separators,
00843  struct X500TokenW *token, LPCWSTR *ppszError)
00844 {
00845     BOOL ret = TRUE;
00846 
00847     TRACE("(%s, %s, %p, %p)\n", debugstr_w(str), debugstr_w(separators), token,
00848      ppszError);
00849 
00850     while (*str && isspaceW(*str))
00851         str++;
00852     if (*str)
00853     {
00854         token->start = str;
00855         if (!(dwFlags & CERT_NAME_STR_NO_QUOTING_FLAG) && *str == '"')
00856         {
00857             token->end = NULL;
00858             str++;
00859             while (!token->end && ret)
00860             {
00861                 while (*str && *str != '"')
00862                     str++;
00863                 if (*str == '"')
00864                 {
00865                     if (*(str + 1) != '"')
00866                         token->end = str + 1;
00867                     else
00868                         str += 2;
00869                 }
00870                 else
00871                 {
00872                     TRACE("unterminated quote at %s\n", debugstr_w(str));
00873                     if (ppszError)
00874                         *ppszError = str;
00875                     SetLastError(CRYPT_E_INVALID_X500_STRING);
00876                     ret = FALSE;
00877                 }
00878             }
00879         }
00880         else
00881         {
00882             WCHAR map[256] = { 0 };
00883 
00884             while (*separators)
00885                 map[*separators++] = 1;
00886             while (*str && (*str >= 0xff || !map[*str]))
00887                 str++;
00888             token->end = str;
00889         }
00890     }
00891     else
00892     {
00893         TRACE("missing value at %s\n", debugstr_w(str));
00894         if (ppszError)
00895             *ppszError = str;
00896         SetLastError(CRYPT_E_INVALID_X500_STRING);
00897         ret = FALSE;
00898     }
00899     return ret;
00900 }
00901 
00902 /* Encodes the string represented by value as the string type type into the
00903  * CERT_NAME_BLOB output.  If there is an error and ppszError is not NULL,
00904  * *ppszError is set to the first failing character.  If there is no error,
00905  * output's pbData must be freed with LocalFree.
00906  */
00907 static BOOL CRYPT_EncodeValueWithType(DWORD dwCertEncodingType,
00908  const struct X500TokenW *value, PCERT_NAME_BLOB output, DWORD type,
00909  LPCWSTR *ppszError)
00910 {
00911     CERT_NAME_VALUE nameValue = { type, { 0, NULL } };
00912     BOOL ret = TRUE;
00913 
00914     if (value->end > value->start)
00915     {
00916         LONG i;
00917         LPWSTR ptr;
00918 
00919         nameValue.Value.pbData = CryptMemAlloc((value->end - value->start + 1) *
00920          sizeof(WCHAR));
00921         if (!nameValue.Value.pbData)
00922         {
00923             SetLastError(ERROR_OUTOFMEMORY);
00924             return FALSE;
00925         }
00926         ptr = (LPWSTR)nameValue.Value.pbData;
00927         for (i = 0; i < value->end - value->start; i++)
00928         {
00929             *ptr++ = value->start[i];
00930             if (value->start[i] == '"')
00931                 i++;
00932         }
00933         /* The string is NULL terminated because of a quirk in encoding
00934          * unicode names values:  if the length is given as 0, the value is
00935          * assumed to be a NULL-terminated string.
00936          */
00937         *ptr = 0;
00938         nameValue.Value.cbData = (LPBYTE)ptr - nameValue.Value.pbData;
00939     }
00940     ret = CryptEncodeObjectEx(dwCertEncodingType, X509_UNICODE_NAME_VALUE,
00941      &nameValue, CRYPT_ENCODE_ALLOC_FLAG, NULL, &output->pbData,
00942      &output->cbData);
00943     if (!ret && ppszError)
00944     {
00945         if (type == CERT_RDN_NUMERIC_STRING &&
00946          GetLastError() == CRYPT_E_INVALID_NUMERIC_STRING)
00947             *ppszError = value->start + output->cbData;
00948         else if (type == CERT_RDN_PRINTABLE_STRING &&
00949          GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING)
00950             *ppszError = value->start + output->cbData;
00951         else if (type == CERT_RDN_IA5_STRING &&
00952          GetLastError() == CRYPT_E_INVALID_IA5_STRING)
00953             *ppszError = value->start + output->cbData;
00954     }
00955     CryptMemFree(nameValue.Value.pbData);
00956     return ret;
00957 }
00958 
00959 static BOOL CRYPT_EncodeValue(DWORD dwCertEncodingType,
00960  const struct X500TokenW *value, PCERT_NAME_BLOB output, const DWORD *types,
00961  LPCWSTR *ppszError)
00962 {
00963     DWORD i;
00964     BOOL ret;
00965 
00966     ret = FALSE;
00967     for (i = 0; !ret && types[i]; i++)
00968         ret = CRYPT_EncodeValueWithType(dwCertEncodingType, value, output,
00969          types[i], ppszError);
00970     return ret;
00971 }
00972 
00973 static BOOL CRYPT_ValueToRDN(DWORD dwCertEncodingType, PCERT_NAME_INFO info,
00974  PCCRYPT_OID_INFO keyOID, struct X500TokenW *value, DWORD dwStrType, LPCWSTR *ppszError)
00975 {
00976     BOOL ret = FALSE;
00977 
00978     TRACE("OID %s, value %s\n", debugstr_a(keyOID->pszOID),
00979      debugstr_wn(value->start, value->end - value->start));
00980 
00981     if (!info->rgRDN)
00982         info->rgRDN = CryptMemAlloc(sizeof(CERT_RDN));
00983     else
00984         info->rgRDN = CryptMemRealloc(info->rgRDN,
00985          (info->cRDN + 1) * sizeof(CERT_RDN));
00986     if (info->rgRDN)
00987     {
00988         /* FIXME: support multiple RDN attrs */
00989         info->rgRDN[info->cRDN].rgRDNAttr =
00990          CryptMemAlloc(sizeof(CERT_RDN_ATTR));
00991         if (info->rgRDN[info->cRDN].rgRDNAttr)
00992         {
00993             static const DWORD defaultTypes[] = { CERT_RDN_PRINTABLE_STRING,
00994              CERT_RDN_BMP_STRING, 0 };
00995             const DWORD *types;
00996 
00997             info->rgRDN[info->cRDN].cRDNAttr = 1;
00998             info->rgRDN[info->cRDN].rgRDNAttr[0].pszObjId =
00999              (LPSTR)keyOID->pszOID;
01000             info->rgRDN[info->cRDN].rgRDNAttr[0].dwValueType =
01001              CERT_RDN_ENCODED_BLOB;
01002             if (keyOID->ExtraInfo.cbData)
01003                 types = (const DWORD *)keyOID->ExtraInfo.pbData;
01004             else
01005                 types = defaultTypes;
01006 
01007             /* Remove surrounding quotes */
01008             if (value->start[0] == '"' && !(dwStrType & CERT_NAME_STR_NO_QUOTING_FLAG))
01009             {
01010                 value->start++;
01011                 value->end--;
01012             }
01013             ret = CRYPT_EncodeValue(dwCertEncodingType, value,
01014              &info->rgRDN[info->cRDN].rgRDNAttr[0].Value, types, ppszError);
01015         }
01016         else
01017             SetLastError(ERROR_OUTOFMEMORY);
01018         info->cRDN++;
01019     }
01020     else
01021         SetLastError(ERROR_OUTOFMEMORY);
01022     return ret;
01023 }
01024 
01025 BOOL WINAPI CertStrToNameW(DWORD dwCertEncodingType, LPCWSTR pszX500,
01026  DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded,
01027  LPCWSTR *ppszError)
01028 {
01029     CERT_NAME_INFO info = { 0, NULL };
01030     LPCWSTR str;
01031     struct KeynameKeeper keeper;
01032     DWORD i;
01033     BOOL ret = TRUE;
01034 
01035     TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType,
01036      debugstr_w(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded,
01037      ppszError);
01038 
01039     CRYPT_InitializeKeynameKeeper(&keeper);
01040     str = pszX500;
01041     while (str && *str && ret)
01042     {
01043         struct X500TokenW token;
01044 
01045         ret = CRYPT_GetNextKeyW(str, &token, ppszError);
01046         if (ret && token.start)
01047         {
01048             PCCRYPT_OID_INFO keyOID;
01049 
01050             CRYPT_KeynameKeeperFromTokenW(&keeper, &token);
01051             keyOID = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, keeper.keyName,
01052              CRYPT_RDN_ATTR_OID_GROUP_ID);
01053             if (!keyOID)
01054             {
01055                 if (ppszError)
01056                     *ppszError = token.start;
01057                 SetLastError(CRYPT_E_INVALID_X500_STRING);
01058                 ret = FALSE;
01059             }
01060             else
01061             {
01062                 str = token.end;
01063                 while (isspace(*str))
01064                     str++;
01065                 if (*str != '=')
01066                 {
01067                     if (ppszError)
01068                         *ppszError = str;
01069                     SetLastError(CRYPT_E_INVALID_X500_STRING);
01070                     ret = FALSE;
01071                 }
01072                 else
01073                 {
01074                     static const WCHAR commaSep[] = { ',',0 };
01075                     static const WCHAR semiSep[] = { ';',0 };
01076                     static const WCHAR crlfSep[] = { '\r','\n',0 };
01077                     static const WCHAR allSepsWithoutPlus[] = { ',',';','\r','\n',0 };
01078                     static const WCHAR allSeps[] = { '+',',',';','\r','\n',0 };
01079                     LPCWSTR sep;
01080 
01081                     str++;
01082                     if (dwStrType & CERT_NAME_STR_COMMA_FLAG)
01083                         sep = commaSep;
01084                     else if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
01085                         sep = semiSep;
01086                     else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
01087                         sep = crlfSep;
01088                     else if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
01089                         sep = allSepsWithoutPlus;
01090                     else
01091                         sep = allSeps;
01092                     ret = CRYPT_GetNextValueW(str, dwStrType, sep, &token,
01093                      ppszError);
01094                     if (ret)
01095                     {
01096                         str = token.end;
01097                         ret = CRYPT_ValueToRDN(dwCertEncodingType, &info,
01098                          keyOID, &token, dwStrType, ppszError);
01099                     }
01100                 }
01101             }
01102         }
01103     }
01104     CRYPT_FreeKeynameKeeper(&keeper);
01105     if (ret)
01106     {
01107         if (ppszError)
01108             *ppszError = NULL;
01109         ret = CryptEncodeObjectEx(dwCertEncodingType, X509_NAME, &info,
01110          0, NULL, pbEncoded, pcbEncoded);
01111     }
01112     for (i = 0; i < info.cRDN; i++)
01113     {
01114         DWORD j;
01115 
01116         for (j = 0; j < info.rgRDN[i].cRDNAttr; j++)
01117             LocalFree(info.rgRDN[i].rgRDNAttr[j].Value.pbData);
01118         CryptMemFree(info.rgRDN[i].rgRDNAttr);
01119     }
01120     CryptMemFree(info.rgRDN);
01121     return ret;
01122 }
01123 
01124 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
01125  DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString)
01126 {
01127     DWORD ret;
01128 
01129     TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, dwFlags,
01130      pvTypePara, pszNameString, cchNameString);
01131 
01132     if (pszNameString)
01133     {
01134         LPWSTR wideName;
01135         DWORD nameLen;
01136 
01137         nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
01138          NULL, 0);
01139         wideName = CryptMemAlloc(nameLen * sizeof(WCHAR));
01140         if (wideName)
01141         {
01142             CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
01143              wideName, nameLen);
01144             nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen,
01145              pszNameString, cchNameString, NULL, NULL);
01146             if (nameLen <= cchNameString)
01147                 ret = nameLen;
01148             else
01149             {
01150                 pszNameString[cchNameString - 1] = '\0';
01151                 ret = cchNameString;
01152             }
01153             CryptMemFree(wideName);
01154         }
01155         else
01156         {
01157             *pszNameString = '\0';
01158             ret = 1;
01159         }
01160     }
01161     else
01162         ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
01163          NULL, 0);
01164     return ret;
01165 }
01166 
01167 /* Searches cert's extensions for the alternate name extension with OID
01168  * altNameOID, and if found, searches it for the alternate name type entryType.
01169  * If found, returns a pointer to the entry, otherwise returns NULL.
01170  * Regardless of whether an entry of the desired type is found, if the
01171  * alternate name extension is present, sets *info to the decoded alternate
01172  * name extension, which you must free using LocalFree.
01173  * The return value is a pointer within *info, so don't free *info before
01174  * you're done with the return value.
01175  */
01176 static PCERT_ALT_NAME_ENTRY cert_find_alt_name_entry(PCCERT_CONTEXT cert,
01177  LPCSTR altNameOID, DWORD entryType, PCERT_ALT_NAME_INFO *info)
01178 {
01179     PCERT_ALT_NAME_ENTRY entry = NULL;
01180     PCERT_EXTENSION ext = CertFindExtension(altNameOID,
01181      cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
01182 
01183     if (ext)
01184     {
01185         DWORD bytes = 0;
01186 
01187         if (CryptDecodeObjectEx(cert->dwCertEncodingType, X509_ALTERNATE_NAME,
01188          ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
01189          info, &bytes))
01190         {
01191             DWORD i;
01192 
01193             for (i = 0; !entry && i < (*info)->cAltEntry; i++)
01194                 if ((*info)->rgAltEntry[i].dwAltNameChoice == entryType)
01195                     entry = &(*info)->rgAltEntry[i];
01196         }
01197     }
01198     else
01199         *info = NULL;
01200     return entry;
01201 }
01202 
01203 static DWORD cert_get_name_from_rdn_attr(DWORD encodingType,
01204  const CERT_NAME_BLOB *name, LPCSTR oid, LPWSTR pszNameString, DWORD cchNameString)
01205 {
01206     CERT_NAME_INFO *nameInfo;
01207     DWORD bytes = 0, ret = 0;
01208 
01209     if (CryptDecodeObjectEx(encodingType, X509_NAME, name->pbData,
01210      name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &bytes))
01211     {
01212         PCERT_RDN_ATTR nameAttr;
01213 
01214         if (!oid)
01215             oid = szOID_RSA_emailAddr;
01216         nameAttr = CertFindRDNAttr(oid, nameInfo);
01217         if (nameAttr)
01218             ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
01219              pszNameString, cchNameString);
01220         LocalFree(nameInfo);
01221     }
01222     return ret;
01223 }
01224 
01225 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
01226  DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
01227 {
01228     DWORD ret = 0;
01229     PCERT_NAME_BLOB name;
01230     LPCSTR altNameOID;
01231 
01232     TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType,
01233      dwFlags, pvTypePara, pszNameString, cchNameString);
01234 
01235     if (!pCertContext)
01236         goto done;
01237 
01238     if (dwFlags & CERT_NAME_ISSUER_FLAG)
01239     {
01240         name = &pCertContext->pCertInfo->Issuer;
01241         altNameOID = szOID_ISSUER_ALT_NAME;
01242     }
01243     else
01244     {
01245         name = &pCertContext->pCertInfo->Subject;
01246         altNameOID = szOID_SUBJECT_ALT_NAME;
01247     }
01248 
01249     switch (dwType)
01250     {
01251     case CERT_NAME_EMAIL_TYPE:
01252     {
01253         CERT_ALT_NAME_INFO *info;
01254         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01255          altNameOID, CERT_ALT_NAME_RFC822_NAME, &info);
01256 
01257         if (entry)
01258         {
01259             if (!pszNameString)
01260                 ret = strlenW(entry->u.pwszRfc822Name) + 1;
01261             else if (cchNameString)
01262             {
01263                 ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1);
01264                 memcpy(pszNameString, entry->u.pwszRfc822Name,
01265                  ret * sizeof(WCHAR));
01266                 pszNameString[ret++] = 0;
01267             }
01268         }
01269         if (info)
01270             LocalFree(info);
01271         if (!ret)
01272             ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType,
01273              name, szOID_RSA_emailAddr, pszNameString, cchNameString);
01274         break;
01275     }
01276     case CERT_NAME_RDN_TYPE:
01277     {
01278         DWORD type = pvTypePara ? *(DWORD *)pvTypePara : 0;
01279 
01280         if (name->cbData)
01281             ret = CertNameToStrW(pCertContext->dwCertEncodingType, name,
01282              type, pszNameString, cchNameString);
01283         else
01284         {
01285             CERT_ALT_NAME_INFO *info;
01286             PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01287              altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &info);
01288 
01289             if (entry)
01290                 ret = CertNameToStrW(pCertContext->dwCertEncodingType,
01291                  &entry->u.DirectoryName, type, pszNameString, cchNameString);
01292             if (info)
01293                 LocalFree(info);
01294         }
01295         break;
01296     }
01297     case CERT_NAME_ATTR_TYPE:
01298         ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType,
01299          name, pvTypePara, pszNameString, cchNameString);
01300         if (!ret)
01301         {
01302             CERT_ALT_NAME_INFO *altInfo;
01303             PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01304              altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &altInfo);
01305 
01306             if (entry)
01307                 ret = cert_name_to_str_with_indent(X509_ASN_ENCODING, 0,
01308                  &entry->u.DirectoryName, 0, pszNameString, cchNameString);
01309             if (altInfo)
01310                 LocalFree(altInfo);
01311         }
01312         break;
01313     case CERT_NAME_SIMPLE_DISPLAY_TYPE:
01314     {
01315         static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME,
01316          szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME,
01317          szOID_RSA_emailAddr };
01318         CERT_NAME_INFO *nameInfo = NULL;
01319         DWORD bytes = 0, i;
01320 
01321         if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME,
01322          name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo,
01323          &bytes))
01324         {
01325             PCERT_RDN_ATTR nameAttr = NULL;
01326 
01327             for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
01328              sizeof(simpleAttributeOIDs[0]); i++)
01329                 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], nameInfo);
01330             if (nameAttr)
01331                 ret = CertRDNValueToStrW(nameAttr->dwValueType,
01332                  &nameAttr->Value, pszNameString, cchNameString);
01333             LocalFree(nameInfo);
01334         }
01335         if (!ret)
01336         {
01337             CERT_ALT_NAME_INFO *altInfo;
01338             PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01339              altNameOID, CERT_ALT_NAME_RFC822_NAME, &altInfo);
01340 
01341             if (altInfo)
01342             {
01343                 if (!entry && altInfo->cAltEntry)
01344                     entry = &altInfo->rgAltEntry[0];
01345                 if (entry)
01346                 {
01347                     if (!pszNameString)
01348                         ret = strlenW(entry->u.pwszRfc822Name) + 1;
01349                     else if (cchNameString)
01350                     {
01351                         ret = min(strlenW(entry->u.pwszRfc822Name),
01352                          cchNameString - 1);
01353                         memcpy(pszNameString, entry->u.pwszRfc822Name,
01354                          ret * sizeof(WCHAR));
01355                         pszNameString[ret++] = 0;
01356                     }
01357                 }
01358                 LocalFree(altInfo);
01359             }
01360         }
01361         break;
01362     }
01363     case CERT_NAME_FRIENDLY_DISPLAY_TYPE:
01364     {
01365         DWORD cch = cchNameString;
01366 
01367         if (CertGetCertificateContextProperty(pCertContext,
01368          CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch))
01369             ret = cch;
01370         else
01371             ret = CertGetNameStringW(pCertContext,
01372              CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString,
01373              cchNameString);
01374         break;
01375     }
01376     case CERT_NAME_DNS_TYPE:
01377     {
01378         CERT_ALT_NAME_INFO *info;
01379         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01380          altNameOID, CERT_ALT_NAME_DNS_NAME, &info);
01381 
01382         if (entry)
01383         {
01384             if (!pszNameString)
01385                 ret = strlenW(entry->u.pwszDNSName) + 1;
01386             else if (cchNameString)
01387             {
01388                 ret = min(strlenW(entry->u.pwszDNSName), cchNameString - 1);
01389                 memcpy(pszNameString, entry->u.pwszDNSName, ret * sizeof(WCHAR));
01390                 pszNameString[ret++] = 0;
01391             }
01392         }
01393         if (info)
01394             LocalFree(info);
01395         if (!ret)
01396             ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType,
01397              name, szOID_COMMON_NAME, pszNameString, cchNameString);
01398         break;
01399     }
01400     case CERT_NAME_URL_TYPE:
01401     {
01402         CERT_ALT_NAME_INFO *info;
01403         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
01404          altNameOID, CERT_ALT_NAME_URL, &info);
01405 
01406         if (entry)
01407         {
01408             if (!pszNameString)
01409                 ret = strlenW(entry->u.pwszURL) + 1;
01410             else if (cchNameString)
01411             {
01412                 ret = min(strlenW(entry->u.pwszURL), cchNameString - 1);
01413                 memcpy(pszNameString, entry->u.pwszURL, ret * sizeof(WCHAR));
01414                 pszNameString[ret++] = 0;
01415             }
01416         }
01417         if (info)
01418             LocalFree(info);
01419         break;
01420     }
01421     default:
01422         FIXME("unimplemented for type %d\n", dwType);
01423         ret = 0;
01424     }
01425 done:
01426     if (!ret)
01427     {
01428         if (!pszNameString)
01429             ret = 1;
01430         else if (cchNameString)
01431         {
01432             pszNameString[0] = 0;
01433             ret = 1;
01434         }
01435     }
01436     return ret;
01437 }

Generated on Mon May 28 2012 04:22:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.