gdi32: PATH_ExtTextOut remove incorrect shift to DC origin.
[wine/hacks.git] / dlls / crypt32 / object.c
blobe880f089090d21da132c632f49496d7dc0bb784e
1 /*
2 * crypt32 Crypt*Object functions
4 * Copyright 2007 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
21 #define NONAMELESSUNION
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wincrypt.h"
25 #include "mssip.h"
26 #include "winuser.h"
27 #include "wintrust.h"
28 #include "crypt32_private.h"
29 #include "cryptres.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
35 static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob)
37 BOOL ret = FALSE;
38 HANDLE file;
40 TRACE("%s\n", debugstr_w(fileName));
42 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
43 OPEN_EXISTING, 0, NULL);
44 if (file != INVALID_HANDLE_VALUE)
46 ret = TRUE;
47 blob->cbData = GetFileSize(file, NULL);
48 if (blob->cbData)
50 blob->pbData = CryptMemAlloc(blob->cbData);
51 if (blob->pbData)
53 DWORD read;
55 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
58 CloseHandle(file);
60 TRACE("returning %d\n", ret);
61 return ret;
64 static BOOL CRYPT_QueryContextBlob(const CERT_BLOB *blob,
65 DWORD dwExpectedContentTypeFlags, HCERTSTORE store,
66 DWORD *contentType, const void **ppvContext)
68 BOOL ret = FALSE;
70 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT)
72 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING,
73 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
74 if (ret && contentType)
75 *contentType = CERT_QUERY_CONTENT_CERT;
77 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL))
79 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
80 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
81 if (ret && contentType)
82 *contentType = CERT_QUERY_CONTENT_CRL;
84 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
86 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
87 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
88 if (ret && contentType)
89 *contentType = CERT_QUERY_CONTENT_CTL;
91 return ret;
94 static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject,
95 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
96 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType,
97 HCERTSTORE *phCertStore, const void **ppvContext)
99 CERT_BLOB fileBlob;
100 const CERT_BLOB *blob;
101 HCERTSTORE store;
102 BOOL ret;
103 DWORD formatType = 0;
105 switch (dwObjectType)
107 case CERT_QUERY_OBJECT_FILE:
108 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
109 * just read the file directly
111 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
112 blob = &fileBlob;
113 break;
114 case CERT_QUERY_OBJECT_BLOB:
115 blob = pvObject;
116 ret = TRUE;
117 break;
118 default:
119 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
120 ret = FALSE;
122 if (!ret)
123 return FALSE;
125 ret = FALSE;
126 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
127 CERT_STORE_CREATE_NEW_FLAG, NULL);
128 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)
130 ret = CRYPT_QueryContextBlob(blob, dwExpectedContentTypeFlags, store,
131 pdwContentType, ppvContext);
132 if (ret)
133 formatType = CERT_QUERY_FORMAT_BINARY;
135 if (!ret &&
136 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED))
138 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData };
139 CRYPT_DATA_BLOB decoded;
141 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1])
142 trimmed.cbData--;
143 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData,
144 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL);
145 if (ret)
147 decoded.pbData = CryptMemAlloc(decoded.cbData);
148 if (decoded.pbData)
150 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData,
151 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData,
152 &decoded.cbData, NULL, NULL);
153 if (ret)
155 ret = CRYPT_QueryContextBlob(&decoded,
156 dwExpectedContentTypeFlags, store, pdwContentType,
157 ppvContext);
158 if (ret)
159 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
161 CryptMemFree(decoded.pbData);
163 else
164 ret = FALSE;
167 if (ret)
169 if (pdwMsgAndCertEncodingType)
170 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
171 if (pdwFormatType)
172 *pdwFormatType = formatType;
173 if (phCertStore)
174 *phCertStore = CertDuplicateStore(store);
176 CertCloseStore(store, 0);
177 if (blob == &fileBlob)
178 CryptMemFree(blob->pbData);
179 TRACE("returning %d\n", ret);
180 return ret;
183 static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
184 const void *pvObject, DWORD dwExpectedContentTypeFlags,
185 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
186 HCERTSTORE *phCertStore, const void **ppvContext)
188 CERT_BLOB fileBlob;
189 const CERT_BLOB *blob;
190 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
191 const void *context;
192 DWORD contextType;
193 BOOL ret;
195 switch (dwObjectType)
197 case CERT_QUERY_OBJECT_FILE:
198 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
199 * just read the file directly
201 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
202 blob = &fileBlob;
203 break;
204 case CERT_QUERY_OBJECT_BLOB:
205 blob = pvObject;
206 ret = TRUE;
207 break;
208 default:
209 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
210 ret = FALSE;
212 if (!ret)
213 return FALSE;
215 ret = FALSE;
216 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
217 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
218 if (context)
220 DWORD contentType, certStoreOffset;
222 ret = TRUE;
223 switch (contextType)
225 case CERT_STORE_CERTIFICATE_CONTEXT:
226 contextInterface = pCertInterface;
227 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT;
228 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore);
229 if (!(dwExpectedContentTypeFlags &
230 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT))
232 SetLastError(ERROR_INVALID_DATA);
233 ret = FALSE;
234 goto end;
236 break;
237 case CERT_STORE_CRL_CONTEXT:
238 contextInterface = pCRLInterface;
239 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL;
240 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore);
241 if (!(dwExpectedContentTypeFlags &
242 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL))
244 SetLastError(ERROR_INVALID_DATA);
245 ret = FALSE;
246 goto end;
248 break;
249 case CERT_STORE_CTL_CONTEXT:
250 contextInterface = pCTLInterface;
251 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL;
252 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore);
253 if (!(dwExpectedContentTypeFlags &
254 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))
256 SetLastError(ERROR_INVALID_DATA);
257 ret = FALSE;
258 goto end;
260 break;
261 default:
262 SetLastError(ERROR_INVALID_DATA);
263 ret = FALSE;
264 goto end;
266 if (pdwMsgAndCertEncodingType)
267 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
268 if (pdwContentType)
269 *pdwContentType = contentType;
270 if (phCertStore)
271 *phCertStore = CertDuplicateStore(
272 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
273 if (ppvContext)
274 *ppvContext = contextInterface->duplicate(context);
277 end:
278 if (contextInterface && context)
279 contextInterface->free(context);
280 if (blob == &fileBlob)
281 CryptMemFree(blob->pbData);
282 TRACE("returning %d\n", ret);
283 return ret;
286 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
287 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
288 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
290 LPCWSTR fileName = pvObject;
291 HANDLE file;
292 BOOL ret = FALSE;
294 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
296 FIXME("unimplemented for non-file type %d\n", dwObjectType);
297 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
298 return FALSE;
300 TRACE("%s\n", debugstr_w(fileName));
301 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
302 OPEN_EXISTING, 0, NULL);
303 if (file != INVALID_HANDLE_VALUE)
305 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
306 CERT_STORE_CREATE_NEW_FLAG, NULL);
308 ret = CRYPT_ReadSerializedStoreFromFile(file, store);
309 if (ret)
311 if (pdwMsgAndCertEncodingType)
312 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
313 if (pdwContentType)
314 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
315 if (phCertStore)
316 *phCertStore = CertDuplicateStore(store);
318 CertCloseStore(store, 0);
319 CloseHandle(file);
321 TRACE("returning %d\n", ret);
322 return ret;
325 static BOOL CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB *blob,
326 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg)
328 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
329 BOOL ret = FALSE;
330 HCRYPTMSG msg;
332 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL)))
334 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
335 if (ret)
337 DWORD type, len = sizeof(type);
339 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
340 if (ret)
342 if (type != CMSG_SIGNED)
344 SetLastError(ERROR_INVALID_DATA);
345 ret = FALSE;
349 if (!ret)
351 CryptMsgClose(msg);
352 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL,
353 NULL);
354 if (msg)
356 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
357 if (!ret)
359 CryptMsgClose(msg);
360 msg = NULL;
365 if (ret)
367 if (pdwMsgAndCertEncodingType)
368 *pdwMsgAndCertEncodingType = encodingType;
369 if (pdwContentType)
370 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
371 if (phMsg)
372 *phMsg = msg;
374 return ret;
377 static BOOL CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB *blob,
378 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg)
380 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
381 BOOL ret = FALSE;
382 HCRYPTMSG msg;
384 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL)))
386 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
387 if (ret)
389 DWORD type, len = sizeof(type);
391 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
392 if (ret)
394 if (type != CMSG_DATA)
396 SetLastError(ERROR_INVALID_DATA);
397 ret = FALSE;
401 if (!ret)
403 CryptMsgClose(msg);
404 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0,
405 NULL, NULL);
406 if (msg)
408 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
409 if (!ret)
411 CryptMsgClose(msg);
412 msg = NULL;
417 if (ret)
419 if (pdwMsgAndCertEncodingType)
420 *pdwMsgAndCertEncodingType = encodingType;
421 if (pdwContentType)
422 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
423 if (phMsg)
424 *phMsg = msg;
426 return ret;
429 /* Used to decode non-embedded messages */
430 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
431 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
432 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType,
433 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
435 CERT_BLOB fileBlob;
436 const CERT_BLOB *blob;
437 BOOL ret;
438 HCRYPTMSG msg = NULL;
439 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
440 DWORD formatType = 0;
442 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject,
443 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
444 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
445 phMsg);
447 switch (dwObjectType)
449 case CERT_QUERY_OBJECT_FILE:
450 /* This isn't an embedded PKCS7 message, so just read the file
451 * directly
453 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
454 blob = &fileBlob;
455 break;
456 case CERT_QUERY_OBJECT_BLOB:
457 blob = pvObject;
458 ret = TRUE;
459 break;
460 default:
461 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
462 ret = FALSE;
464 if (!ret)
465 return FALSE;
467 ret = FALSE;
468 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)
470 /* Try it first as a signed message */
471 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
472 ret = CRYPT_QuerySignedMessage(blob, pdwMsgAndCertEncodingType,
473 pdwContentType, &msg);
474 /* Failing that, try as an unsigned message */
475 if (!ret &&
476 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
477 ret = CRYPT_QueryUnsignedMessage(blob, pdwMsgAndCertEncodingType,
478 pdwContentType, &msg);
479 if (ret)
480 formatType = CERT_QUERY_FORMAT_BINARY;
482 if (!ret &&
483 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED))
485 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData };
486 CRYPT_DATA_BLOB decoded;
488 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1])
489 trimmed.cbData--;
490 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData,
491 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL);
492 if (ret)
494 decoded.pbData = CryptMemAlloc(decoded.cbData);
495 if (decoded.pbData)
497 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData,
498 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData,
499 &decoded.cbData, NULL, NULL);
500 if (ret)
502 /* Try it first as a signed message */
503 if (dwExpectedContentTypeFlags &
504 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
505 ret = CRYPT_QuerySignedMessage(&decoded,
506 pdwMsgAndCertEncodingType, pdwContentType, &msg);
507 /* Failing that, try as an unsigned message */
508 if (!ret && (dwExpectedContentTypeFlags &
509 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
510 ret = CRYPT_QueryUnsignedMessage(&decoded,
511 pdwMsgAndCertEncodingType, pdwContentType, &msg);
512 if (ret)
513 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
515 CryptMemFree(decoded.pbData);
517 else
518 ret = FALSE;
520 if (!ret && !(blob->cbData % sizeof(WCHAR)))
522 CRYPT_DATA_BLOB decoded;
523 LPWSTR str = (LPWSTR)blob->pbData;
524 DWORD strLen = blob->cbData / sizeof(WCHAR);
526 /* Try again, assuming the input string is UTF-16 base64 */
527 while (strLen && !str[strLen - 1])
528 strLen--;
529 ret = CryptStringToBinaryW(str, strLen, CRYPT_STRING_BASE64_ANY,
530 NULL, &decoded.cbData, NULL, NULL);
531 if (ret)
533 decoded.pbData = CryptMemAlloc(decoded.cbData);
534 if (decoded.pbData)
536 ret = CryptStringToBinaryW(str, strLen,
537 CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData,
538 NULL, NULL);
539 if (ret)
541 /* Try it first as a signed message */
542 if (dwExpectedContentTypeFlags &
543 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
544 ret = CRYPT_QuerySignedMessage(&decoded,
545 pdwMsgAndCertEncodingType, pdwContentType, &msg);
546 /* Failing that, try as an unsigned message */
547 if (!ret && (dwExpectedContentTypeFlags &
548 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
549 ret = CRYPT_QueryUnsignedMessage(&decoded,
550 pdwMsgAndCertEncodingType, pdwContentType, &msg);
551 if (ret)
552 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
554 CryptMemFree(decoded.pbData);
556 else
557 ret = FALSE;
561 if (ret)
563 if (pdwFormatType)
564 *pdwFormatType = formatType;
565 if (phMsg)
566 *phMsg = msg;
567 if (phCertStore)
568 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
569 0, msg);
571 if (blob == &fileBlob)
572 CryptMemFree(blob->pbData);
573 TRACE("returning %d\n", ret);
574 return ret;
577 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
578 const void *pvObject, DWORD dwExpectedContentTypeFlags,
579 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
580 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
582 HANDLE file;
583 GUID subject;
584 BOOL ret = FALSE;
586 TRACE("%s\n", debugstr_w(pvObject));
588 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
590 WARN("don't know what to do for type %d embedded signed messages\n",
591 dwObjectType);
592 SetLastError(E_INVALIDARG);
593 return FALSE;
595 file = CreateFileW(pvObject, GENERIC_READ, FILE_SHARE_READ,
596 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
597 if (file != INVALID_HANDLE_VALUE)
599 ret = CryptSIPRetrieveSubjectGuid(pvObject, file, &subject);
600 if (ret)
602 SIP_DISPATCH_INFO sip;
604 memset(&sip, 0, sizeof(sip));
605 sip.cbSize = sizeof(sip);
606 ret = CryptSIPLoad(&subject, 0, &sip);
607 if (ret)
609 SIP_SUBJECTINFO subjectInfo;
610 CERT_BLOB blob;
611 DWORD encodingType;
613 memset(&subjectInfo, 0, sizeof(subjectInfo));
614 subjectInfo.cbSize = sizeof(subjectInfo);
615 subjectInfo.pgSubjectType = &subject;
616 subjectInfo.hFile = file;
617 subjectInfo.pwsFileName = pvObject;
618 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
619 NULL);
620 if (ret)
622 blob.pbData = CryptMemAlloc(blob.cbData);
623 if (blob.pbData)
625 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
626 &blob.cbData, blob.pbData);
627 if (ret)
629 ret = CRYPT_QueryMessageObject(
630 CERT_QUERY_OBJECT_BLOB, &blob,
631 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
632 CERT_QUERY_FORMAT_FLAG_BINARY,
633 pdwMsgAndCertEncodingType, NULL, NULL,
634 phCertStore, phMsg);
635 if (ret && pdwContentType)
636 *pdwContentType =
637 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
639 CryptMemFree(blob.pbData);
641 else
643 SetLastError(ERROR_OUTOFMEMORY);
644 ret = FALSE;
649 CloseHandle(file);
651 TRACE("returning %d\n", ret);
652 return ret;
655 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
656 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
657 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
658 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
659 const void **ppvContext)
661 static const DWORD unimplementedTypes =
662 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX |
663 CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
664 BOOL ret = TRUE;
666 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
667 dwObjectType, pvObject, dwExpectedContentTypeFlags,
668 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
669 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
671 if (dwObjectType != CERT_QUERY_OBJECT_BLOB &&
672 dwObjectType != CERT_QUERY_OBJECT_FILE)
674 WARN("unsupported type %d\n", dwObjectType);
675 SetLastError(E_INVALIDARG);
676 return FALSE;
678 if (!pvObject)
680 WARN("missing required argument\n");
681 SetLastError(E_INVALIDARG);
682 return FALSE;
684 if (dwExpectedContentTypeFlags & unimplementedTypes)
685 WARN("unimplemented for types %08x\n",
686 dwExpectedContentTypeFlags & unimplementedTypes);
688 if (pdwFormatType)
689 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
690 if (phCertStore)
691 *phCertStore = NULL;
692 if (phMsg)
693 *phMsg = NULL;
694 if (ppvContext)
695 *ppvContext = NULL;
697 ret = FALSE;
698 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
699 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
700 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
702 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
703 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
704 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
705 ppvContext);
707 if (!ret &&
708 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
710 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
711 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
713 if (!ret &&
714 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
715 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
716 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
718 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
719 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
720 phCertStore, ppvContext);
722 if (!ret &&
723 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
724 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
726 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
727 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
728 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType,
729 phCertStore, phMsg);
731 if (!ret &&
732 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
734 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
735 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
736 phCertStore, phMsg);
738 if (!ret)
739 SetLastError(CRYPT_E_NO_MATCH);
740 TRACE("returning %d\n", ret);
741 return ret;
744 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
745 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
746 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
747 DWORD *pcbFormat)
749 BOOL ret;
750 DWORD bytesNeeded;
752 if (cbEncoded)
753 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
754 else
755 bytesNeeded = sizeof(WCHAR);
756 if (!pbFormat)
758 *pcbFormat = bytesNeeded;
759 ret = TRUE;
761 else if (*pcbFormat < bytesNeeded)
763 *pcbFormat = bytesNeeded;
764 SetLastError(ERROR_MORE_DATA);
765 ret = FALSE;
767 else
769 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
770 static const WCHAR endFmt[] = { '%','0','2','x',0 };
771 DWORD i;
772 LPWSTR ptr = pbFormat;
774 *pcbFormat = bytesNeeded;
775 if (cbEncoded)
777 for (i = 0; i < cbEncoded; i++)
779 if (i < cbEncoded - 1)
780 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
781 else
782 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
785 else
786 *ptr = 0;
787 ret = TRUE;
789 return ret;
792 #define MAX_STRING_RESOURCE_LEN 128
794 static const WCHAR commaSpace[] = { ',',' ',0 };
796 struct BitToString
798 BYTE bit;
799 int id;
800 WCHAR str[MAX_STRING_RESOURCE_LEN];
803 static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map,
804 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first)
806 DWORD bytesNeeded = sizeof(WCHAR);
807 int i;
808 BOOL ret = TRUE, localFirst = *first;
810 for (i = 0; i < mapEntries; i++)
811 if (bits & map[i].bit)
813 if (!localFirst)
814 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR);
815 localFirst = FALSE;
816 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR);
818 if (!pbFormat)
820 *first = localFirst;
821 *pcbFormat = bytesNeeded;
823 else if (*pcbFormat < bytesNeeded)
825 *first = localFirst;
826 *pcbFormat = bytesNeeded;
827 SetLastError(ERROR_MORE_DATA);
828 ret = FALSE;
830 else
832 LPWSTR str = pbFormat;
834 localFirst = *first;
835 *pcbFormat = bytesNeeded;
836 for (i = 0; i < mapEntries; i++)
837 if (bits & map[i].bit)
839 if (!localFirst)
841 strcpyW(str, commaSpace);
842 str += strlenW(commaSpace);
844 localFirst = FALSE;
845 strcpyW(str, map[i].str);
846 str += strlenW(map[i].str);
848 *first = localFirst;
850 return ret;
853 static struct BitToString keyUsageByte0Map[] = {
854 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } },
855 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } },
856 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } },
857 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } },
858 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } },
859 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } },
860 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } },
861 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } },
862 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },
864 static struct BitToString keyUsageByte1Map[] = {
865 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },
868 static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType,
869 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
870 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
871 DWORD *pcbFormat)
873 DWORD size;
874 CRYPT_BIT_BLOB *bits;
875 BOOL ret;
877 if (!cbEncoded)
879 SetLastError(E_INVALIDARG);
880 return FALSE;
882 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE,
883 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
885 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
886 DWORD bytesNeeded = sizeof(WCHAR);
888 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
889 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
890 if (!bits->cbData || bits->cbData > 2)
892 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
893 if (!pbFormat)
894 *pcbFormat = bytesNeeded;
895 else if (*pcbFormat < bytesNeeded)
897 *pcbFormat = bytesNeeded;
898 SetLastError(ERROR_MORE_DATA);
899 ret = FALSE;
901 else
903 LPWSTR str = pbFormat;
905 *pcbFormat = bytesNeeded;
906 strcpyW(str, infoNotAvailable);
909 else
911 static BOOL stringsLoaded = FALSE;
912 int i;
913 DWORD bitStringLen;
914 BOOL first = TRUE;
916 if (!stringsLoaded)
918 for (i = 0;
919 i < sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]);
920 i++)
921 LoadStringW(hInstance, keyUsageByte0Map[i].id,
922 keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN);
923 for (i = 0;
924 i < sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]);
925 i++)
926 LoadStringW(hInstance, keyUsageByte1Map[i].id,
927 keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN);
928 stringsLoaded = TRUE;
930 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
931 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
932 NULL, &bitStringLen, &first);
933 bytesNeeded += bitStringLen;
934 if (bits->cbData == 2)
936 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
937 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
938 NULL, &bitStringLen, &first);
939 bytesNeeded += bitStringLen;
941 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
942 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
943 bits->cbData, NULL, &size);
944 bytesNeeded += size;
945 if (!pbFormat)
946 *pcbFormat = bytesNeeded;
947 else if (*pcbFormat < bytesNeeded)
949 *pcbFormat = bytesNeeded;
950 SetLastError(ERROR_MORE_DATA);
951 ret = FALSE;
953 else
955 LPWSTR str = pbFormat;
957 bitStringLen = bytesNeeded;
958 first = TRUE;
959 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
960 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
961 str, &bitStringLen, &first);
962 str += bitStringLen / sizeof(WCHAR) - 1;
963 if (bits->cbData == 2)
965 bitStringLen = bytesNeeded;
966 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
967 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
968 str, &bitStringLen, &first);
969 str += bitStringLen / sizeof(WCHAR) - 1;
971 *str++ = ' ';
972 *str++ = '(';
973 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
974 bits->cbData, str, &size);
975 str += size / sizeof(WCHAR) - 1;
976 *str++ = ')';
977 *str = 0;
980 LocalFree(bits);
982 return ret;
985 static const WCHAR crlf[] = { '\r','\n',0 };
987 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
988 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
989 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
990 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
992 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
993 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
994 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
995 DWORD *pcbFormat)
997 DWORD size;
998 CERT_BASIC_CONSTRAINTS2_INFO *info;
999 BOOL ret;
1001 if (!cbEncoded)
1003 SetLastError(E_INVALIDARG);
1004 return FALSE;
1006 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
1007 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1009 static const WCHAR pathFmt[] = { '%','d',0 };
1010 static BOOL stringsLoaded = FALSE;
1011 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1012 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
1013 LPCWSTR sep, subjectType;
1014 DWORD sepLen;
1016 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1018 sep = crlf;
1019 sepLen = strlenW(crlf) * sizeof(WCHAR);
1021 else
1023 sep = commaSpace;
1024 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1027 if (!stringsLoaded)
1029 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader,
1030 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0]));
1031 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA,
1032 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0]));
1033 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT,
1034 subjectTypeEndCert,
1035 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0]));
1036 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader,
1037 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0]));
1038 stringsLoaded = TRUE;
1040 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
1041 if (info->fCA)
1042 subjectType = subjectTypeCA;
1043 else
1044 subjectType = subjectTypeEndCert;
1045 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
1046 bytesNeeded += sepLen;
1047 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
1048 if (info->fPathLenConstraint)
1049 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
1050 else
1051 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength,
1052 sizeof(pathLength) / sizeof(pathLength[0]));
1053 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
1054 if (!pbFormat)
1055 *pcbFormat = bytesNeeded;
1056 else if (*pcbFormat < bytesNeeded)
1058 *pcbFormat = bytesNeeded;
1059 SetLastError(ERROR_MORE_DATA);
1060 ret = FALSE;
1062 else
1064 LPWSTR str = pbFormat;
1066 *pcbFormat = bytesNeeded;
1067 strcpyW(str, subjectTypeHeader);
1068 str += strlenW(subjectTypeHeader);
1069 strcpyW(str, subjectType);
1070 str += strlenW(subjectType);
1071 strcpyW(str, sep);
1072 str += sepLen / sizeof(WCHAR);
1073 strcpyW(str, pathLengthHeader);
1074 str += strlenW(pathLengthHeader);
1075 strcpyW(str, pathLength);
1076 str += strlenW(pathLength);
1078 LocalFree(info);
1080 return ret;
1083 static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id,
1084 LPWSTR str, DWORD *pcbStr)
1086 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1087 DWORD bytesNeeded;
1088 BOOL ret;
1090 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0]));
1091 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
1092 blob->pbData, blob->cbData, NULL, &bytesNeeded);
1093 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1094 if (!str)
1096 *pcbStr = bytesNeeded;
1097 ret = TRUE;
1099 else if (*pcbStr < bytesNeeded)
1101 *pcbStr = bytesNeeded;
1102 SetLastError(ERROR_MORE_DATA);
1103 ret = FALSE;
1105 else
1107 *pcbStr = bytesNeeded;
1108 strcpyW(str, buf);
1109 str += strlenW(str);
1110 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1111 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
1112 blob->pbData, blob->cbData, str, &bytesNeeded);
1114 return ret;
1117 static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str,
1118 DWORD *pcbStr)
1120 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
1123 static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str,
1124 DWORD *pcbStr)
1126 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
1127 str, pcbStr);
1130 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
1131 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
1133 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
1134 CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
1136 BOOL ret;
1137 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1138 WCHAR mask[MAX_STRING_RESOURCE_LEN];
1139 WCHAR ipAddrBuf[32];
1140 WCHAR maskBuf[16];
1141 DWORD bytesNeeded = sizeof(WCHAR);
1142 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
1144 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1145 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1146 switch (entry->dwAltNameChoice)
1148 case CERT_ALT_NAME_RFC822_NAME:
1149 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf,
1150 sizeof(buf) / sizeof(buf[0]));
1151 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
1152 ret = TRUE;
1153 break;
1154 case CERT_ALT_NAME_DNS_NAME:
1155 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf,
1156 sizeof(buf) / sizeof(buf[0]));
1157 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
1158 ret = TRUE;
1159 break;
1160 case CERT_ALT_NAME_DIRECTORY_NAME:
1162 DWORD directoryNameLen;
1164 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1165 strType |= CERT_NAME_STR_CRLF_FLAG;
1166 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING,
1167 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0);
1168 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf,
1169 sizeof(buf) / sizeof(buf[0]));
1170 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR);
1171 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1172 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR);
1173 else
1174 bytesNeeded += sizeof(WCHAR); /* '=' */
1175 ret = TRUE;
1176 break;
1178 case CERT_ALT_NAME_URL:
1179 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf,
1180 sizeof(buf) / sizeof(buf[0]));
1181 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
1182 ret = TRUE;
1183 break;
1184 case CERT_ALT_NAME_IP_ADDRESS:
1186 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
1187 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1189 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
1190 '.','%','d',0 };
1192 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf,
1193 sizeof(buf) / sizeof(buf[0]));
1194 if (entry->u.IPAddress.cbData == 8)
1196 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1198 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask,
1199 sizeof(mask) / sizeof(mask[0]));
1200 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
1201 sprintfW(ipAddrBuf, ipAddrFmt,
1202 entry->u.IPAddress.pbData[0],
1203 entry->u.IPAddress.pbData[1],
1204 entry->u.IPAddress.pbData[2],
1205 entry->u.IPAddress.pbData[3]);
1206 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
1207 /* indent again, for the mask line */
1208 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1209 sprintfW(maskBuf, ipAddrFmt,
1210 entry->u.IPAddress.pbData[4],
1211 entry->u.IPAddress.pbData[5],
1212 entry->u.IPAddress.pbData[6],
1213 entry->u.IPAddress.pbData[7]);
1214 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
1215 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
1217 else
1219 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
1220 entry->u.IPAddress.pbData[0],
1221 entry->u.IPAddress.pbData[1],
1222 entry->u.IPAddress.pbData[2],
1223 entry->u.IPAddress.pbData[3],
1224 entry->u.IPAddress.pbData[4],
1225 entry->u.IPAddress.pbData[5],
1226 entry->u.IPAddress.pbData[6],
1227 entry->u.IPAddress.pbData[7]);
1228 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
1230 ret = TRUE;
1232 else
1234 FIXME("unknown IP address format (%d bytes)\n",
1235 entry->u.IPAddress.cbData);
1236 ret = FALSE;
1238 break;
1240 default:
1241 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
1242 ret = FALSE;
1244 if (ret)
1246 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1247 if (!str)
1248 *pcbStr = bytesNeeded;
1249 else if (*pcbStr < bytesNeeded)
1251 *pcbStr = bytesNeeded;
1252 SetLastError(ERROR_MORE_DATA);
1253 ret = FALSE;
1255 else
1257 DWORD i;
1259 *pcbStr = bytesNeeded;
1260 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1262 for (i = 0; i < indentLevel; i++)
1264 strcpyW(str, indent);
1265 str += strlenW(indent);
1268 strcpyW(str, buf);
1269 str += strlenW(str);
1270 switch (entry->dwAltNameChoice)
1272 case CERT_ALT_NAME_RFC822_NAME:
1273 case CERT_ALT_NAME_DNS_NAME:
1274 case CERT_ALT_NAME_URL:
1275 strcpyW(str, entry->u.pwszURL);
1276 break;
1277 case CERT_ALT_NAME_DIRECTORY_NAME:
1278 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1280 strcpyW(str, colonCrlf);
1281 str += strlenW(colonCrlf);
1283 else
1284 *str++ = '=';
1285 cert_name_to_str_with_indent(X509_ASN_ENCODING,
1286 indentLevel + 1, &entry->u.DirectoryName, strType, str,
1287 bytesNeeded / sizeof(WCHAR));
1288 break;
1289 case CERT_ALT_NAME_IP_ADDRESS:
1290 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1292 strcpyW(str, ipAddrBuf);
1293 str += strlenW(ipAddrBuf);
1294 strcpyW(str, crlf);
1295 str += strlenW(crlf);
1296 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1298 for (i = 0; i < indentLevel; i++)
1300 strcpyW(str, indent);
1301 str += strlenW(indent);
1304 strcpyW(str, mask);
1305 str += strlenW(mask);
1306 strcpyW(str, maskBuf);
1308 else
1309 strcpyW(str, ipAddrBuf);
1310 break;
1314 return ret;
1317 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
1318 CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
1320 DWORD i, size, bytesNeeded = 0;
1321 BOOL ret = TRUE;
1322 LPCWSTR sep;
1323 DWORD sepLen;
1325 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1327 sep = crlf;
1328 sepLen = strlenW(crlf) * sizeof(WCHAR);
1330 else
1332 sep = commaSpace;
1333 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1336 for (i = 0; ret && i < name->cAltEntry; i++)
1338 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1339 &name->rgAltEntry[i], NULL, &size);
1340 if (ret)
1342 bytesNeeded += size - sizeof(WCHAR);
1343 if (i < name->cAltEntry - 1)
1344 bytesNeeded += sepLen;
1347 if (ret)
1349 bytesNeeded += sizeof(WCHAR);
1350 if (!str)
1351 *pcbStr = bytesNeeded;
1352 else if (*pcbStr < bytesNeeded)
1354 *pcbStr = bytesNeeded;
1355 SetLastError(ERROR_MORE_DATA);
1356 ret = FALSE;
1358 else
1360 *pcbStr = bytesNeeded;
1361 for (i = 0; ret && i < name->cAltEntry; i++)
1363 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1364 &name->rgAltEntry[i], str, &size);
1365 if (ret)
1367 str += size / sizeof(WCHAR) - 1;
1368 if (i < name->cAltEntry - 1)
1370 strcpyW(str, sep);
1371 str += sepLen / sizeof(WCHAR);
1377 return ret;
1380 static const WCHAR colonSep[] = { ':',' ',0 };
1382 static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType,
1383 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1384 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1385 DWORD *pcbFormat)
1387 BOOL ret;
1388 CERT_ALT_NAME_INFO *info;
1389 DWORD size;
1391 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME,
1392 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1394 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat);
1395 LocalFree(info);
1397 return ret;
1400 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
1401 CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
1403 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1404 DWORD bytesNeeded, sepLen;
1405 LPCWSTR sep;
1406 BOOL ret;
1408 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0]));
1409 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL,
1410 &bytesNeeded);
1411 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1412 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1414 sep = colonCrlf;
1415 sepLen = strlenW(colonCrlf) * sizeof(WCHAR);
1417 else
1419 sep = colonSep;
1420 sepLen = strlenW(colonSep) * sizeof(WCHAR);
1422 bytesNeeded += sepLen;
1423 if (ret)
1425 if (!str)
1426 *pcbStr = bytesNeeded;
1427 else if (*pcbStr < bytesNeeded)
1429 *pcbStr = bytesNeeded;
1430 SetLastError(ERROR_MORE_DATA);
1431 ret = FALSE;
1433 else
1435 *pcbStr = bytesNeeded;
1436 strcpyW(str, buf);
1437 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1438 str += strlenW(str);
1439 strcpyW(str, sep);
1440 str += sepLen / sizeof(WCHAR);
1441 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str,
1442 &bytesNeeded);
1445 return ret;
1448 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1449 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1450 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1451 DWORD *pcbFormat)
1453 CERT_AUTHORITY_KEY_ID2_INFO *info;
1454 DWORD size;
1455 BOOL ret = FALSE;
1457 if (!cbEncoded)
1459 SetLastError(E_INVALIDARG);
1460 return FALSE;
1462 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1463 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1465 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1466 LPCWSTR sep;
1467 DWORD sepLen;
1468 BOOL needSeparator = FALSE;
1470 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1472 sep = crlf;
1473 sepLen = strlenW(crlf) * sizeof(WCHAR);
1475 else
1477 sep = commaSpace;
1478 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1481 if (info->KeyId.cbData)
1483 needSeparator = TRUE;
1484 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1485 if (ret)
1487 /* don't include NULL-terminator more than once */
1488 bytesNeeded += size - sizeof(WCHAR);
1491 if (info->AuthorityCertIssuer.cAltEntry)
1493 if (needSeparator)
1494 bytesNeeded += sepLen;
1495 needSeparator = TRUE;
1496 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1497 &info->AuthorityCertIssuer, NULL, &size);
1498 if (ret)
1500 /* don't include NULL-terminator more than once */
1501 bytesNeeded += size - sizeof(WCHAR);
1504 if (info->AuthorityCertSerialNumber.cbData)
1506 if (needSeparator)
1507 bytesNeeded += sepLen;
1508 ret = CRYPT_FormatCertSerialNumber(
1509 &info->AuthorityCertSerialNumber, NULL, &size);
1510 if (ret)
1512 /* don't include NULL-terminator more than once */
1513 bytesNeeded += size - sizeof(WCHAR);
1516 if (ret)
1518 if (!pbFormat)
1519 *pcbFormat = bytesNeeded;
1520 else if (*pcbFormat < bytesNeeded)
1522 *pcbFormat = bytesNeeded;
1523 SetLastError(ERROR_MORE_DATA);
1524 ret = FALSE;
1526 else
1528 LPWSTR str = pbFormat;
1530 *pcbFormat = bytesNeeded;
1531 needSeparator = FALSE;
1532 if (info->KeyId.cbData)
1534 needSeparator = TRUE;
1535 /* Overestimate size available, it's already been checked
1536 * above.
1538 size = bytesNeeded;
1539 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1540 if (ret)
1541 str += size / sizeof(WCHAR) - 1;
1543 if (info->AuthorityCertIssuer.cAltEntry)
1545 if (needSeparator)
1547 strcpyW(str, sep);
1548 str += sepLen / sizeof(WCHAR);
1550 needSeparator = TRUE;
1551 /* Overestimate size available, it's already been checked
1552 * above.
1554 size = bytesNeeded;
1555 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1556 &info->AuthorityCertIssuer, str, &size);
1557 if (ret)
1558 str += size / sizeof(WCHAR) - 1;
1560 if (info->AuthorityCertSerialNumber.cbData)
1562 if (needSeparator)
1564 strcpyW(str, sep);
1565 str += sepLen / sizeof(WCHAR);
1567 /* Overestimate size available, it's already been checked
1568 * above.
1570 size = bytesNeeded;
1571 ret = CRYPT_FormatCertSerialNumber(
1572 &info->AuthorityCertSerialNumber, str, &size);
1576 LocalFree(info);
1578 return ret;
1581 static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1582 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1583 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1584 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1585 static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1586 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1588 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1589 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1590 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1591 DWORD *pcbFormat)
1593 CERT_AUTHORITY_INFO_ACCESS *info;
1594 DWORD size;
1595 BOOL ret = FALSE;
1597 if (!cbEncoded)
1599 SetLastError(E_INVALIDARG);
1600 return FALSE;
1602 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1603 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1604 NULL, &info, &size)))
1606 DWORD bytesNeeded = sizeof(WCHAR);
1608 if (!info->cAccDescr)
1610 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1612 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1613 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1614 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1615 if (!pbFormat)
1616 *pcbFormat = bytesNeeded;
1617 else if (*pcbFormat < bytesNeeded)
1619 *pcbFormat = bytesNeeded;
1620 SetLastError(ERROR_MORE_DATA);
1621 ret = FALSE;
1623 else
1625 *pcbFormat = bytesNeeded;
1626 strcpyW(pbFormat, infoNotAvailable);
1629 else
1631 static const WCHAR numFmt[] = { '%','d',0 };
1632 static const WCHAR equal[] = { '=',0 };
1633 static BOOL stringsLoaded = FALSE;
1634 DWORD i;
1635 LPCWSTR headingSep, accessMethodSep, locationSep;
1636 WCHAR accessDescrNum[11];
1638 if (!stringsLoaded)
1640 LoadStringW(hInstance, IDS_AIA, aia,
1641 sizeof(aia) / sizeof(aia[0]));
1642 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod,
1643 sizeof(accessMethod) / sizeof(accessMethod[0]));
1644 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp,
1645 sizeof(ocsp) / sizeof(ocsp[0]));
1646 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers,
1647 sizeof(caIssuers) / sizeof(caIssuers[0]));
1648 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown,
1649 sizeof(unknown) / sizeof(unknown[0]));
1650 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation,
1651 sizeof(accessLocation) / sizeof(accessLocation[0]));
1652 stringsLoaded = TRUE;
1654 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1656 headingSep = crlf;
1657 accessMethodSep = crlf;
1658 locationSep = colonCrlf;
1660 else
1662 headingSep = colonSep;
1663 accessMethodSep = commaSpace;
1664 locationSep = equal;
1667 for (i = 0; ret && i < info->cAccDescr; i++)
1669 /* Heading */
1670 bytesNeeded += sizeof(WCHAR); /* left bracket */
1671 sprintfW(accessDescrNum, numFmt, i + 1);
1672 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1673 bytesNeeded += sizeof(WCHAR); /* right bracket */
1674 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1675 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1676 /* Access method */
1677 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1678 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1679 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1680 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1681 szOID_PKIX_OCSP))
1682 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1683 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1684 szOID_PKIX_CA_ISSUERS))
1685 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1686 else
1687 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1688 bytesNeeded += sizeof(WCHAR); /* space */
1689 bytesNeeded += sizeof(WCHAR); /* left paren */
1690 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1691 * sizeof(WCHAR);
1692 bytesNeeded += sizeof(WCHAR); /* right paren */
1693 /* Delimiter between access method and location */
1694 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1695 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1696 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1697 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1698 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1699 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1700 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1701 if (ret)
1702 bytesNeeded += size - sizeof(WCHAR);
1703 /* Need extra delimiter between access method entries */
1704 if (i < info->cAccDescr - 1)
1705 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1707 if (ret)
1709 if (!pbFormat)
1710 *pcbFormat = bytesNeeded;
1711 else if (*pcbFormat < bytesNeeded)
1713 *pcbFormat = bytesNeeded;
1714 SetLastError(ERROR_MORE_DATA);
1715 ret = FALSE;
1717 else
1719 LPWSTR str = pbFormat;
1720 DWORD altNameEntrySize;
1722 *pcbFormat = bytesNeeded;
1723 for (i = 0; ret && i < info->cAccDescr; i++)
1725 LPCSTR oidPtr;
1727 *str++ = '[';
1728 sprintfW(accessDescrNum, numFmt, i + 1);
1729 strcpyW(str, accessDescrNum);
1730 str += strlenW(accessDescrNum);
1731 *str++ = ']';
1732 strcpyW(str, aia);
1733 str += strlenW(aia);
1734 strcpyW(str, headingSep);
1735 str += strlenW(headingSep);
1736 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1738 strcpyW(str, indent);
1739 str += strlenW(indent);
1741 strcpyW(str, accessMethod);
1742 str += strlenW(accessMethod);
1743 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1744 szOID_PKIX_OCSP))
1746 strcpyW(str, ocsp);
1747 str += strlenW(ocsp);
1749 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1750 szOID_PKIX_CA_ISSUERS))
1752 strcpyW(str, caIssuers);
1753 str += strlenW(caIssuers);
1755 else
1757 strcpyW(str, unknown);
1758 str += strlenW(unknown);
1760 *str++ = ' ';
1761 *str++ = '(';
1762 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1763 *oidPtr; oidPtr++, str++)
1764 *str = *oidPtr;
1765 *str++ = ')';
1766 strcpyW(str, accessMethodSep);
1767 str += strlenW(accessMethodSep);
1768 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1770 strcpyW(str, indent);
1771 str += strlenW(indent);
1773 strcpyW(str, accessLocation);
1774 str += strlenW(accessLocation);
1775 strcpyW(str, locationSep);
1776 str += strlenW(locationSep);
1777 /* This overestimates the size available, but that
1778 * won't matter since we checked earlier whether enough
1779 * space for the entire string was available.
1781 altNameEntrySize = bytesNeeded;
1782 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1783 &info->rgAccDescr[i].AccessLocation, str,
1784 &altNameEntrySize);
1785 if (ret)
1786 str += altNameEntrySize / sizeof(WCHAR) - 1;
1787 if (i < info->cAccDescr - 1)
1789 strcpyW(str, accessMethodSep);
1790 str += strlenW(accessMethodSep);
1796 LocalFree(info);
1798 return ret;
1801 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1802 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1803 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1804 static WCHAR superseded[MAX_STRING_RESOURCE_LEN];
1805 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1806 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1808 struct reason_map_entry
1810 BYTE reasonBit;
1811 LPWSTR reason;
1812 int id;
1814 static struct reason_map_entry reason_map[] = {
1815 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1816 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1817 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1818 IDS_REASON_AFFILIATION_CHANGED },
1819 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED },
1820 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1821 IDS_REASON_CESSATION_OF_OPERATION },
1822 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1823 IDS_REASON_CERTIFICATE_HOLD },
1826 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1827 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1829 static const WCHAR sep[] = { ',',' ',0 };
1830 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1831 static BOOL stringsLoaded = FALSE;
1832 int i, numReasons = 0;
1833 BOOL ret = TRUE;
1834 DWORD bytesNeeded = sizeof(WCHAR);
1835 WCHAR bits[6];
1837 if (!stringsLoaded)
1839 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1840 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1841 MAX_STRING_RESOURCE_LEN);
1842 stringsLoaded = TRUE;
1844 /* No need to check reasonFlags->cbData, we already know it's positive.
1845 * Ignore any other bytes, as they're for undefined bits.
1847 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1849 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1851 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1852 if (numReasons++)
1853 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1856 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1857 bytesNeeded += strlenW(bits);
1858 if (!str)
1859 *pcbStr = bytesNeeded;
1860 else if (*pcbStr < bytesNeeded)
1862 *pcbStr = bytesNeeded;
1863 SetLastError(ERROR_MORE_DATA);
1864 ret = FALSE;
1866 else
1868 *pcbStr = bytesNeeded;
1869 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1871 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1873 strcpyW(str, reason_map[i].reason);
1874 str += strlenW(reason_map[i].reason);
1875 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 &&
1876 numReasons)
1878 strcpyW(str, sep);
1879 str += strlenW(sep);
1883 strcpyW(str, bits);
1885 return ret;
1888 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1889 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1890 static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1891 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1892 static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1893 static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1895 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1896 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1898 DWORD *pcbFormat)
1900 CRL_DIST_POINTS_INFO *info;
1901 DWORD size;
1902 BOOL ret = FALSE;
1904 if (!cbEncoded)
1906 SetLastError(E_INVALIDARG);
1907 return FALSE;
1909 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1910 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1912 static const WCHAR numFmt[] = { '%','d',0 };
1913 static const WCHAR colon[] = { ':',0 };
1914 static BOOL stringsLoaded = FALSE;
1915 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1916 BOOL haveAnEntry = FALSE;
1917 LPCWSTR headingSep, nameSep;
1918 WCHAR distPointNum[11];
1919 DWORD i;
1921 if (!stringsLoaded)
1923 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint,
1924 sizeof(crlDistPoint) / sizeof(crlDistPoint[0]));
1925 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName,
1926 sizeof(distPointName) / sizeof(distPointName[0]));
1927 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName,
1928 sizeof(fullName) / sizeof(fullName[0]));
1929 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName,
1930 sizeof(rdnName) / sizeof(rdnName[0]));
1931 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason,
1932 sizeof(reason) / sizeof(reason[0]));
1933 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer,
1934 sizeof(issuer) / sizeof(issuer[0]));
1935 stringsLoaded = TRUE;
1937 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1939 headingSep = crlf;
1940 nameSep = colonCrlf;
1942 else
1944 headingSep = colonSep;
1945 nameSep = colon;
1948 for (i = 0; ret && i < info->cDistPoint; i++)
1950 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1952 if (distPoint->DistPointName.dwDistPointNameChoice !=
1953 CRL_DIST_POINT_NO_NAME)
1955 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
1956 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1957 if (distPoint->DistPointName.dwDistPointNameChoice ==
1958 CRL_DIST_POINT_FULL_NAME)
1959 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
1960 else
1961 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
1962 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1963 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1964 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR);
1965 /* The indent level (3) is higher than when used as the issuer,
1966 * because the name is subordinate to the name type (full vs.
1967 * RDN.)
1969 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1970 &distPoint->DistPointName.u.FullName, NULL, &size);
1971 if (ret)
1972 bytesNeeded += size - sizeof(WCHAR);
1973 haveAnEntry = TRUE;
1975 else if (distPoint->ReasonFlags.cbData)
1977 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
1978 ret = CRYPT_FormatReason(dwFormatStrType,
1979 &distPoint->ReasonFlags, NULL, &size);
1980 if (ret)
1981 bytesNeeded += size - sizeof(WCHAR);
1982 haveAnEntry = TRUE;
1984 else if (distPoint->CRLIssuer.cAltEntry)
1986 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
1987 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1988 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1989 &distPoint->CRLIssuer, NULL, &size);
1990 if (ret)
1991 bytesNeeded += size - sizeof(WCHAR);
1992 haveAnEntry = TRUE;
1994 if (haveAnEntry)
1996 bytesNeeded += sizeof(WCHAR); /* left bracket */
1997 sprintfW(distPointNum, numFmt, i + 1);
1998 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
1999 bytesNeeded += sizeof(WCHAR); /* right bracket */
2000 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
2001 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
2002 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2003 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
2006 if (!haveAnEntry)
2008 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2010 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
2011 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
2012 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2013 if (!pbFormat)
2014 *pcbFormat = bytesNeeded;
2015 else if (*pcbFormat < bytesNeeded)
2017 *pcbFormat = bytesNeeded;
2018 SetLastError(ERROR_MORE_DATA);
2019 ret = FALSE;
2021 else
2023 *pcbFormat = bytesNeeded;
2024 strcpyW(pbFormat, infoNotAvailable);
2027 else
2029 if (!pbFormat)
2030 *pcbFormat = bytesNeeded;
2031 else if (*pcbFormat < bytesNeeded)
2033 *pcbFormat = bytesNeeded;
2034 SetLastError(ERROR_MORE_DATA);
2035 ret = FALSE;
2037 else
2039 LPWSTR str = pbFormat;
2041 *pcbFormat = bytesNeeded;
2042 for (i = 0; ret && i < info->cDistPoint; i++)
2044 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
2046 *str++ = '[';
2047 sprintfW(distPointNum, numFmt, i + 1);
2048 strcpyW(str, distPointNum);
2049 str += strlenW(distPointNum);
2050 *str++ = ']';
2051 strcpyW(str, crlDistPoint);
2052 str += strlenW(crlDistPoint);
2053 strcpyW(str, headingSep);
2054 str += strlenW(headingSep);
2055 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2057 strcpyW(str, indent);
2058 str += strlenW(indent);
2060 if (distPoint->DistPointName.dwDistPointNameChoice !=
2061 CRL_DIST_POINT_NO_NAME)
2063 DWORD altNameSize = bytesNeeded;
2065 strcpyW(str, distPointName);
2066 str += strlenW(distPointName);
2067 strcpyW(str, nameSep);
2068 str += strlenW(nameSep);
2069 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2071 strcpyW(str, indent);
2072 str += strlenW(indent);
2073 strcpyW(str, indent);
2074 str += strlenW(indent);
2076 if (distPoint->DistPointName.dwDistPointNameChoice ==
2077 CRL_DIST_POINT_FULL_NAME)
2079 strcpyW(str, fullName);
2080 str += strlenW(fullName);
2082 else
2084 strcpyW(str, rdnName);
2085 str += strlenW(rdnName);
2087 strcpyW(str, nameSep);
2088 str += strlenW(nameSep);
2089 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
2090 &distPoint->DistPointName.u.FullName, str,
2091 &altNameSize);
2092 if (ret)
2093 str += altNameSize / sizeof(WCHAR) - 1;
2095 else if (distPoint->ReasonFlags.cbData)
2097 DWORD reasonSize = bytesNeeded;
2099 strcpyW(str, reason);
2100 str += strlenW(reason);
2101 ret = CRYPT_FormatReason(dwFormatStrType,
2102 &distPoint->ReasonFlags, str, &reasonSize);
2103 if (ret)
2104 str += reasonSize / sizeof(WCHAR) - 1;
2106 else if (distPoint->CRLIssuer.cAltEntry)
2108 DWORD crlIssuerSize = bytesNeeded;
2110 strcpyW(str, issuer);
2111 str += strlenW(issuer);
2112 strcpyW(str, nameSep);
2113 str += strlenW(nameSep);
2114 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
2115 &distPoint->CRLIssuer, str,
2116 &crlIssuerSize);
2117 if (ret)
2118 str += crlIssuerSize / sizeof(WCHAR) - 1;
2123 LocalFree(info);
2125 return ret;
2128 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
2129 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2131 DWORD *pcbFormat)
2133 CERT_ENHKEY_USAGE *usage;
2134 DWORD size;
2135 BOOL ret = FALSE;
2137 if (!cbEncoded)
2139 SetLastError(E_INVALIDARG);
2140 return FALSE;
2142 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
2143 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)))
2145 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
2146 DWORD i;
2147 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
2148 LPCWSTR sep;
2149 DWORD sepLen;
2151 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2153 sep = crlf;
2154 sepLen = strlenW(crlf) * sizeof(WCHAR);
2156 else
2158 sep = commaSpace;
2159 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2162 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown,
2163 sizeof(unknown) / sizeof(unknown[0]));
2164 for (i = 0; i < usage->cUsageIdentifier; i++)
2166 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2167 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2169 if (info)
2170 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
2171 else
2172 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
2173 bytesNeeded += sizeof(WCHAR); /* space */
2174 bytesNeeded += sizeof(WCHAR); /* left paren */
2175 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
2176 sizeof(WCHAR);
2177 bytesNeeded += sizeof(WCHAR); /* right paren */
2178 if (i < usage->cUsageIdentifier - 1)
2179 bytesNeeded += sepLen;
2181 if (!pbFormat)
2182 *pcbFormat = bytesNeeded;
2183 else if (*pcbFormat < bytesNeeded)
2185 *pcbFormat = bytesNeeded;
2186 SetLastError(ERROR_MORE_DATA);
2187 ret = FALSE;
2189 else
2191 LPWSTR str = pbFormat;
2193 *pcbFormat = bytesNeeded;
2194 for (i = 0; i < usage->cUsageIdentifier; i++)
2196 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2197 usage->rgpszUsageIdentifier[i],
2198 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2199 LPCSTR oidPtr;
2201 if (info)
2203 strcpyW(str, info->pwszName);
2204 str += strlenW(info->pwszName);
2206 else
2208 strcpyW(str, unknown);
2209 str += strlenW(unknown);
2211 *str++ = ' ';
2212 *str++ = '(';
2213 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
2214 *str++ = *oidPtr;
2215 *str++ = ')';
2216 *str = 0;
2217 if (i < usage->cUsageIdentifier - 1)
2219 strcpyW(str, sep);
2220 str += sepLen / sizeof(WCHAR);
2224 LocalFree(usage);
2226 return ret;
2229 static struct BitToString netscapeCertTypeMap[] = {
2230 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } },
2231 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } },
2232 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } },
2233 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } },
2234 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } },
2235 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } },
2236 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },
2239 static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType,
2240 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2241 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2242 DWORD *pcbFormat)
2244 DWORD size;
2245 CRYPT_BIT_BLOB *bits;
2246 BOOL ret;
2248 if (!cbEncoded)
2250 SetLastError(E_INVALIDARG);
2251 return FALSE;
2253 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS,
2254 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
2256 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2257 DWORD bytesNeeded = sizeof(WCHAR);
2259 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
2260 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
2261 if (!bits->cbData || bits->cbData > 1)
2263 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2264 if (!pbFormat)
2265 *pcbFormat = bytesNeeded;
2266 else if (*pcbFormat < bytesNeeded)
2268 *pcbFormat = bytesNeeded;
2269 SetLastError(ERROR_MORE_DATA);
2270 ret = FALSE;
2272 else
2274 LPWSTR str = pbFormat;
2276 *pcbFormat = bytesNeeded;
2277 strcpyW(str, infoNotAvailable);
2280 else
2282 static BOOL stringsLoaded = FALSE;
2283 int i;
2284 DWORD bitStringLen;
2285 BOOL first = TRUE;
2287 if (!stringsLoaded)
2289 for (i = 0; i < sizeof(netscapeCertTypeMap) /
2290 sizeof(netscapeCertTypeMap[0]); i++)
2291 LoadStringW(hInstance, netscapeCertTypeMap[i].id,
2292 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN);
2293 stringsLoaded = TRUE;
2295 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2296 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2297 NULL, &bitStringLen, &first);
2298 bytesNeeded += bitStringLen;
2299 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
2300 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2301 bits->cbData, NULL, &size);
2302 bytesNeeded += size;
2303 if (!pbFormat)
2304 *pcbFormat = bytesNeeded;
2305 else if (*pcbFormat < bytesNeeded)
2307 *pcbFormat = bytesNeeded;
2308 SetLastError(ERROR_MORE_DATA);
2309 ret = FALSE;
2311 else
2313 LPWSTR str = pbFormat;
2315 bitStringLen = bytesNeeded;
2316 first = TRUE;
2317 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2318 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2319 str, &bitStringLen, &first);
2320 str += bitStringLen / sizeof(WCHAR) - 1;
2321 *str++ = ' ';
2322 *str++ = '(';
2323 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2324 bits->cbData, str, &size);
2325 str += size / sizeof(WCHAR) - 1;
2326 *str++ = ')';
2327 *str = 0;
2330 LocalFree(bits);
2332 return ret;
2335 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
2336 static WCHAR available[MAX_STRING_RESOURCE_LEN];
2337 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
2338 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
2339 static WCHAR yes[MAX_STRING_RESOURCE_LEN];
2340 static WCHAR no[MAX_STRING_RESOURCE_LEN];
2342 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
2343 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2344 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2345 DWORD *pcbFormat)
2347 SPC_FINANCIAL_CRITERIA criteria;
2348 DWORD size = sizeof(criteria);
2349 BOOL ret = FALSE;
2351 if (!cbEncoded)
2353 SetLastError(E_INVALIDARG);
2354 return FALSE;
2356 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
2357 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
2358 &size)))
2360 static BOOL stringsLoaded = FALSE;
2361 DWORD bytesNeeded = sizeof(WCHAR);
2362 LPCWSTR sep;
2363 DWORD sepLen;
2365 if (!stringsLoaded)
2367 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria,
2368 sizeof(financialCriteria) / sizeof(financialCriteria[0]));
2369 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available,
2370 sizeof(available) / sizeof(available[0]));
2371 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE,
2372 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0]));
2373 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA,
2374 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0]));
2375 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0]));
2376 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0]));
2377 stringsLoaded = TRUE;
2379 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2381 sep = crlf;
2382 sepLen = strlenW(crlf) * sizeof(WCHAR);
2384 else
2386 sep = commaSpace;
2387 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2389 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
2390 if (criteria.fFinancialInfoAvailable)
2392 bytesNeeded += strlenW(available) * sizeof(WCHAR);
2393 bytesNeeded += sepLen;
2394 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
2395 if (criteria.fMeetsCriteria)
2396 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
2397 else
2398 bytesNeeded += strlenW(no) * sizeof(WCHAR);
2400 else
2401 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
2402 if (!pbFormat)
2403 *pcbFormat = bytesNeeded;
2404 else if (*pcbFormat < bytesNeeded)
2406 *pcbFormat = bytesNeeded;
2407 SetLastError(ERROR_MORE_DATA);
2408 ret = FALSE;
2410 else
2412 LPWSTR str = pbFormat;
2414 *pcbFormat = bytesNeeded;
2415 strcpyW(str, financialCriteria);
2416 str += strlenW(financialCriteria);
2417 if (criteria.fFinancialInfoAvailable)
2419 strcpyW(str, available);
2420 str += strlenW(available);
2421 strcpyW(str, sep);
2422 str += sepLen / sizeof(WCHAR);
2423 strcpyW(str, meetsCriteria);
2424 str += strlenW(meetsCriteria);
2425 if (criteria.fMeetsCriteria)
2426 strcpyW(str, yes);
2427 else
2428 strcpyW(str, no);
2430 else
2432 strcpyW(str, notAvailable);
2433 str += strlenW(notAvailable);
2437 return ret;
2440 static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType,
2441 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2443 DWORD *pcbFormat)
2445 CERT_NAME_VALUE *value;
2446 DWORD size;
2447 BOOL ret;
2449 if (!cbEncoded)
2451 SetLastError(E_INVALIDARG);
2452 return FALSE;
2454 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
2455 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size)))
2457 if (!pbFormat)
2458 *pcbFormat = value->Value.cbData;
2459 else if (*pcbFormat < value->Value.cbData)
2461 *pcbFormat = value->Value.cbData;
2462 SetLastError(ERROR_MORE_DATA);
2463 ret = FALSE;
2465 else
2467 LPWSTR str = pbFormat;
2469 *pcbFormat = value->Value.cbData;
2470 strcpyW(str, (LPWSTR)value->Value.pbData);
2473 return ret;
2476 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
2477 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
2479 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
2480 DWORD formatStrType, LPCSTR lpszStructType)
2482 CryptFormatObjectFunc format = NULL;
2484 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
2486 SetLastError(ERROR_FILE_NOT_FOUND);
2487 return NULL;
2489 if (!HIWORD(lpszStructType))
2491 switch (LOWORD(lpszStructType))
2493 case LOWORD(X509_KEY_USAGE):
2494 format = CRYPT_FormatKeyUsage;
2495 break;
2496 case LOWORD(X509_ALTERNATE_NAME):
2497 format = CRYPT_FormatAltName;
2498 break;
2499 case LOWORD(X509_BASIC_CONSTRAINTS2):
2500 format = CRYPT_FormatBasicConstraints2;
2501 break;
2502 case LOWORD(X509_AUTHORITY_KEY_ID2):
2503 format = CRYPT_FormatAuthorityKeyId2;
2504 break;
2505 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
2506 format = CRYPT_FormatAuthorityInfoAccess;
2507 break;
2508 case LOWORD(X509_CRL_DIST_POINTS):
2509 format = CRYPT_FormatCRLDistPoints;
2510 break;
2511 case LOWORD(X509_ENHANCED_KEY_USAGE):
2512 format = CRYPT_FormatEnhancedKeyUsage;
2513 break;
2514 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
2515 format = CRYPT_FormatSpcFinancialCriteria;
2516 break;
2519 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2520 format = CRYPT_FormatAltName;
2521 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2522 format = CRYPT_FormatAltName;
2523 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2524 format = CRYPT_FormatKeyUsage;
2525 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2526 format = CRYPT_FormatAltName;
2527 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2528 format = CRYPT_FormatAltName;
2529 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2530 format = CRYPT_FormatBasicConstraints2;
2531 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
2532 format = CRYPT_FormatAuthorityInfoAccess;
2533 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
2534 format = CRYPT_FormatAuthorityKeyId2;
2535 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2536 format = CRYPT_FormatCRLDistPoints;
2537 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2538 format = CRYPT_FormatEnhancedKeyUsage;
2539 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE))
2540 format = CRYPT_FormatNetscapeCertType;
2541 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) ||
2542 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) ||
2543 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) ||
2544 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) ||
2545 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) ||
2546 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) ||
2547 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT))
2548 format = CRYPT_FormatUnicodeString;
2549 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
2550 format = CRYPT_FormatSpcFinancialCriteria;
2551 return format;
2554 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
2555 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
2556 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
2558 CryptFormatObjectFunc format = NULL;
2559 HCRYPTOIDFUNCADDR hFunc = NULL;
2560 BOOL ret = FALSE;
2562 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
2563 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
2564 pbEncoded, cbEncoded, pbFormat, pcbFormat);
2566 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
2567 dwFormatStrType, lpszStructType)))
2569 static HCRYPTOIDFUNCSET set = NULL;
2571 if (!set)
2572 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
2573 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2574 (void **)&format, &hFunc);
2576 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) ==
2577 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
2578 format = CRYPT_FormatHexString;
2579 if (format)
2580 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
2581 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
2582 pcbFormat);
2583 if (hFunc)
2584 CryptFreeOIDFunctionAddress(hFunc, 0);
2585 return ret;