tools/c2man.pl: Generate correct html.
[wine/testsucceed.git] / dlls / crypt32 / str.c
bloba35ce21d17c948d18346502f32770f9e6b16e23f
1 /*
2 * Copyright 2006 Juan Lang for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
26 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
27 LPSTR psz, DWORD csz)
29 DWORD ret = 0;
31 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
33 switch (dwValueType)
35 case CERT_RDN_ANY_TYPE:
36 break;
37 case CERT_RDN_PRINTABLE_STRING:
38 case CERT_RDN_IA5_STRING:
39 if (!psz || !csz)
40 ret = pValue->cbData;
41 else
43 DWORD chars = min(pValue->cbData, csz - 1);
45 if (chars)
47 memcpy(psz, pValue->pbData, chars);
48 ret += chars;
49 csz -= chars;
52 break;
53 default:
54 FIXME("string type %ld unimplemented\n", dwValueType);
56 if (psz && csz)
58 *(psz + ret) = '\0';
59 csz--;
60 ret++;
62 else
63 ret++;
64 return ret;
67 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
68 LPWSTR psz, DWORD csz)
70 DWORD ret = 0;
72 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
74 switch (dwValueType)
76 case CERT_RDN_ANY_TYPE:
77 break;
78 case CERT_RDN_PRINTABLE_STRING:
79 case CERT_RDN_IA5_STRING:
80 if (!psz || !csz)
81 ret = pValue->cbData;
82 else
84 DWORD chars = min(pValue->cbData, csz - 1);
86 if (chars)
88 DWORD i;
90 for (i = 0; i < chars; i++)
91 psz[i] = pValue->pbData[i];
92 ret += chars;
93 csz -= chars;
96 break;
97 default:
98 FIXME("string type %ld unimplemented\n", dwValueType);
100 if (psz && csz)
102 *(psz + ret) = '\0';
103 csz--;
104 ret++;
106 else
107 ret++;
108 return ret;
112 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
113 DWORD dwStrType, LPSTR psz, DWORD csz)
115 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
116 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
117 static const char commaSep[] = ", ";
118 static const char semiSep[] = "; ";
119 static const char crlfSep[] = "\r\n";
120 static const char plusSep[] = " + ";
121 static const char spaceSep[] = " ";
122 DWORD ret = 0, bytes = 0;
123 BOOL bRet;
124 CERT_NAME_INFO *info;
126 TRACE("(%ld, %p, %p, %ld)\n", dwCertEncodingType, pName, psz, csz);
127 if (dwStrType & unsupportedFlags)
128 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
130 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
131 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
132 if (bRet)
134 DWORD i, j, sepLen, rdnSepLen;
135 LPCSTR sep, rdnSep;
137 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
138 sep = semiSep;
139 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
140 sep = crlfSep;
141 else
142 sep = commaSep;
143 sepLen = strlen(sep);
144 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
145 rdnSep = spaceSep;
146 else
147 rdnSep = plusSep;
148 rdnSepLen = strlen(rdnSep);
149 for (i = 0; ret < csz && i < info->cRDN; i++)
151 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
153 DWORD chars;
155 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
157 /* - 1 is needed to account for the NULL terminator. */
158 chars = min(
159 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
160 csz - ret - 1);
161 if (psz && chars)
162 memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
163 chars);
164 ret += chars;
165 csz -= chars;
166 if (csz > 1)
168 if (psz)
169 *(psz + ret) = '=';
170 ret++;
171 csz--;
174 /* FIXME: handle quoting */
175 chars = CertRDNValueToStrA(
176 info->rgRDN[i].rgRDNAttr[j].dwValueType,
177 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
178 csz - ret - 1);
179 if (chars)
180 ret += chars - 1;
181 if (j < info->rgRDN[i].cRDNAttr - 1)
183 if (psz && ret < csz - rdnSepLen - 1)
184 memcpy(psz + ret, rdnSep, rdnSepLen);
185 ret += rdnSepLen;
188 if (i < info->cRDN - 1)
190 if (psz && ret < csz - sepLen - 1)
191 memcpy(psz + ret, sep, sepLen);
192 ret += sepLen;
195 LocalFree(info);
197 if (psz && csz)
199 *(psz + ret) = '\0';
200 csz--;
201 ret++;
203 else
204 ret++;
205 return ret;
208 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
209 DWORD dwStrType, LPWSTR psz, DWORD csz)
211 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
212 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
213 static const WCHAR commaSep[] = { ',',' ',0 };
214 static const WCHAR semiSep[] = { ';',' ',0 };
215 static const WCHAR crlfSep[] = { '\r','\n',0 };
216 static const WCHAR plusSep[] = { ' ','+',' ',0 };
217 static const WCHAR spaceSep[] = { ' ',0 };
218 DWORD ret = 0, bytes = 0;
219 BOOL bRet;
220 CERT_NAME_INFO *info;
222 TRACE("(%ld, %p, %p, %ld)\n", dwCertEncodingType, pName, psz, csz);
223 if (dwStrType & unsupportedFlags)
224 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
226 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
227 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
228 if (bRet)
230 DWORD i, j, sepLen, rdnSepLen;
231 LPCWSTR sep, rdnSep;
233 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
234 sep = semiSep;
235 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
236 sep = crlfSep;
237 else
238 sep = commaSep;
239 sepLen = lstrlenW(sep);
240 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
241 rdnSep = spaceSep;
242 else
243 rdnSep = plusSep;
244 rdnSepLen = lstrlenW(rdnSep);
245 for (i = 0; ret < csz && i < info->cRDN; i++)
247 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
249 DWORD chars;
251 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
253 /* - 1 is needed to account for the NULL terminator. */
254 chars = min(
255 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
256 csz - ret - 1);
257 if (psz && chars)
259 DWORD k;
261 for (k = 0; k < chars; k++)
262 *(psz + ret + k) =
263 info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
265 ret += chars;
266 csz -= chars;
267 if (csz > 1)
269 if (psz)
270 *(psz + ret) = '=';
271 ret++;
272 csz--;
275 /* FIXME: handle quoting */
276 chars = CertRDNValueToStrW(
277 info->rgRDN[i].rgRDNAttr[j].dwValueType,
278 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
279 csz - ret - 1);
280 if (chars)
281 ret += chars - 1;
282 if (j < info->rgRDN[i].cRDNAttr - 1)
284 if (psz && ret < csz - rdnSepLen - 1)
285 memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
286 ret += rdnSepLen;
289 if (i < info->cRDN - 1)
291 if (psz && ret < csz - sepLen - 1)
292 memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
293 ret += sepLen;
296 LocalFree(info);
298 if (psz && csz)
300 *(psz + ret) = '\0';
301 csz--;
302 ret++;
304 else
305 ret++;
306 return ret;