user32: Implement SystemParametersInfo(SPI_[GS]ETCOMBOBOXANIMATION).
[wine/testsucceed.git] / dlls / crypt32 / str.c
blobcf56c479fb9441f1ff81bad4ceefc056bff4399a
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 "winnls.h"
22 #include "wincrypt.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
28 LPSTR psz, DWORD csz)
30 DWORD ret = 0;
32 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
34 switch (dwValueType)
36 case CERT_RDN_ANY_TYPE:
37 break;
38 case CERT_RDN_PRINTABLE_STRING:
39 case CERT_RDN_IA5_STRING:
40 if (!psz || !csz)
41 ret = pValue->cbData;
42 else
44 DWORD chars = min(pValue->cbData, csz - 1);
46 if (chars)
48 memcpy(psz, pValue->pbData, chars);
49 ret += chars;
50 csz -= chars;
53 break;
54 default:
55 FIXME("string type %ld unimplemented\n", dwValueType);
57 if (psz && csz)
59 *(psz + ret) = '\0';
60 csz--;
61 ret++;
63 else
64 ret++;
65 return ret;
68 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
69 LPWSTR psz, DWORD csz)
71 DWORD ret = 0;
73 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
75 switch (dwValueType)
77 case CERT_RDN_ANY_TYPE:
78 break;
79 case CERT_RDN_PRINTABLE_STRING:
80 case CERT_RDN_IA5_STRING:
81 if (!psz || !csz)
82 ret = pValue->cbData;
83 else
85 DWORD chars = min(pValue->cbData, csz - 1);
87 if (chars)
89 DWORD i;
91 for (i = 0; i < chars; i++)
92 psz[i] = pValue->pbData[i];
93 ret += chars;
94 csz -= chars;
97 break;
98 default:
99 FIXME("string type %ld unimplemented\n", dwValueType);
101 if (psz && csz)
103 *(psz + ret) = '\0';
104 csz--;
105 ret++;
107 else
108 ret++;
109 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, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
127 psz, csz);
128 if (dwStrType & unsupportedFlags)
129 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
131 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
132 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
133 if (bRet)
135 DWORD i, j, sepLen, rdnSepLen;
136 LPCSTR sep, rdnSep;
138 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
139 sep = semiSep;
140 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
141 sep = crlfSep;
142 else
143 sep = commaSep;
144 sepLen = strlen(sep);
145 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
146 rdnSep = spaceSep;
147 else
148 rdnSep = plusSep;
149 rdnSepLen = strlen(rdnSep);
150 for (i = 0; ret < csz && i < info->cRDN; i++)
152 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
154 DWORD chars;
156 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
158 /* - 1 is needed to account for the NULL terminator. */
159 chars = min(
160 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
161 csz - ret - 1);
162 if (psz && chars)
163 memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
164 chars);
165 ret += chars;
166 csz -= chars;
167 if (csz > 1)
169 if (psz)
170 *(psz + ret) = '=';
171 ret++;
172 csz--;
175 /* FIXME: handle quoting */
176 chars = CertRDNValueToStrA(
177 info->rgRDN[i].rgRDNAttr[j].dwValueType,
178 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
179 csz - ret - 1);
180 if (chars)
181 ret += chars - 1;
182 if (j < info->rgRDN[i].cRDNAttr - 1)
184 if (psz && ret < csz - rdnSepLen - 1)
185 memcpy(psz + ret, rdnSep, rdnSepLen);
186 ret += rdnSepLen;
189 if (i < info->cRDN - 1)
191 if (psz && ret < csz - sepLen - 1)
192 memcpy(psz + ret, sep, sepLen);
193 ret += sepLen;
196 LocalFree(info);
198 if (psz && csz)
200 *(psz + ret) = '\0';
201 csz--;
202 ret++;
204 else
205 ret++;
206 return ret;
209 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
210 DWORD dwStrType, LPWSTR psz, DWORD csz)
212 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
213 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
214 static const WCHAR commaSep[] = { ',',' ',0 };
215 static const WCHAR semiSep[] = { ';',' ',0 };
216 static const WCHAR crlfSep[] = { '\r','\n',0 };
217 static const WCHAR plusSep[] = { ' ','+',' ',0 };
218 static const WCHAR spaceSep[] = { ' ',0 };
219 DWORD ret = 0, bytes = 0;
220 BOOL bRet;
221 CERT_NAME_INFO *info;
223 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
224 psz, csz);
225 if (dwStrType & unsupportedFlags)
226 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
228 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
229 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
230 if (bRet)
232 DWORD i, j, sepLen, rdnSepLen;
233 LPCWSTR sep, rdnSep;
235 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
236 sep = semiSep;
237 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
238 sep = crlfSep;
239 else
240 sep = commaSep;
241 sepLen = lstrlenW(sep);
242 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
243 rdnSep = spaceSep;
244 else
245 rdnSep = plusSep;
246 rdnSepLen = lstrlenW(rdnSep);
247 for (i = 0; ret < csz && i < info->cRDN; i++)
249 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
251 DWORD chars;
253 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
255 /* - 1 is needed to account for the NULL terminator. */
256 chars = min(
257 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
258 csz - ret - 1);
259 if (psz && chars)
261 DWORD k;
263 for (k = 0; k < chars; k++)
264 *(psz + ret + k) =
265 info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
267 ret += chars;
268 csz -= chars;
269 if (csz > 1)
271 if (psz)
272 *(psz + ret) = '=';
273 ret++;
274 csz--;
277 /* FIXME: handle quoting */
278 chars = CertRDNValueToStrW(
279 info->rgRDN[i].rgRDNAttr[j].dwValueType,
280 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
281 csz - ret - 1);
282 if (chars)
283 ret += chars - 1;
284 if (j < info->rgRDN[i].cRDNAttr - 1)
286 if (psz && ret < csz - rdnSepLen - 1)
287 memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
288 ret += rdnSepLen;
291 if (i < info->cRDN - 1)
293 if (psz && ret < csz - sepLen - 1)
294 memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
295 ret += sepLen;
298 LocalFree(info);
300 if (psz && csz)
302 *(psz + ret) = '\0';
303 csz--;
304 ret++;
306 else
307 ret++;
308 return ret;
311 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
312 DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString)
314 DWORD ret;
316 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags,
317 pvTypePara, pszNameString, cchNameString);
319 if (pszNameString)
321 LPWSTR wideName;
322 DWORD nameLen;
324 nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
325 NULL, 0);
326 wideName = CryptMemAlloc(nameLen * sizeof(WCHAR));
327 if (wideName)
329 CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
330 wideName, nameLen);
331 nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen,
332 pszNameString, cchNameString, NULL, NULL);
333 if (nameLen <= cchNameString)
334 ret = nameLen;
335 else
337 pszNameString[cchNameString - 1] = '\0';
338 ret = cchNameString;
340 CryptMemFree(wideName);
342 else
344 *pszNameString = '\0';
345 ret = 1;
348 else
349 ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
350 NULL, 0);
351 return ret;
354 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
355 DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
357 DWORD ret;
358 PCERT_NAME_BLOB name;
359 LPCSTR altNameOID;
361 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType,
362 dwFlags, pvTypePara, pszNameString, cchNameString);
364 if (dwFlags & CERT_NAME_ISSUER_FLAG)
366 name = &pCertContext->pCertInfo->Issuer;
367 altNameOID = szOID_ISSUER_ALT_NAME;
369 else
371 name = &pCertContext->pCertInfo->Subject;
372 altNameOID = szOID_SUBJECT_ALT_NAME;
375 switch (dwType)
377 case CERT_NAME_SIMPLE_DISPLAY_TYPE:
379 static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME,
380 szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME,
381 szOID_RSA_emailAddr };
382 CERT_NAME_INFO *info = NULL;
383 PCERT_RDN_ATTR nameAttr = NULL;
384 DWORD bytes = 0, i;
386 if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME,
387 name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info,
388 &bytes))
390 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
391 sizeof(simpleAttributeOIDs[0]); i++)
392 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
394 else
395 ret = 0;
396 if (!nameAttr)
398 PCERT_EXTENSION ext = CertFindExtension(altNameOID,
399 pCertContext->pCertInfo->cExtension,
400 pCertContext->pCertInfo->rgExtension);
402 if (ext)
404 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
405 sizeof(simpleAttributeOIDs[0]); i++)
406 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
407 if (!nameAttr)
409 /* FIXME: gotta then look for a rfc822Name choice in ext.
410 * Failing that, look for the first attribute.
412 FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n");
413 ret = 0;
417 ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
418 pszNameString, cchNameString);
419 if (info)
420 LocalFree(info);
421 break;
423 case CERT_NAME_FRIENDLY_DISPLAY_TYPE:
425 DWORD cch = cchNameString;
427 if (CertGetCertificateContextProperty(pCertContext,
428 CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch))
429 ret = cch;
430 else
431 ret = CertGetNameStringW(pCertContext,
432 CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString,
433 cchNameString);
434 break;
436 default:
437 FIXME("unimplemented for type %ld\n", dwType);
438 ret = 0;
440 return ret;