wined3d: Implement parallel point lights in process_vertices_strided().
[wine.git] / dlls / crypt32 / object.c
blob1993a0a879812bce24717be90bef1493e02f61fc
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) && read == blob->cbData;
56 if (!ret) CryptMemFree(blob->pbData);
58 else
59 ret = FALSE;
61 CloseHandle(file);
63 TRACE("returning %d\n", ret);
64 return ret;
67 static BOOL CRYPT_QueryContextBlob(const CERT_BLOB *blob,
68 DWORD dwExpectedContentTypeFlags, HCERTSTORE store,
69 DWORD *contentType, const void **ppvContext)
71 BOOL ret = FALSE;
73 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT)
75 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING,
76 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
77 if (ret && contentType)
78 *contentType = CERT_QUERY_CONTENT_CERT;
80 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL))
82 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
83 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
84 if (ret && contentType)
85 *contentType = CERT_QUERY_CONTENT_CRL;
87 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
89 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
90 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
91 if (ret && contentType)
92 *contentType = CERT_QUERY_CONTENT_CTL;
94 return ret;
97 static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject,
98 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
99 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType,
100 HCERTSTORE *phCertStore, const void **ppvContext)
102 CERT_BLOB fileBlob;
103 const CERT_BLOB *blob;
104 HCERTSTORE store;
105 BOOL ret;
106 DWORD formatType = 0;
108 switch (dwObjectType)
110 case CERT_QUERY_OBJECT_FILE:
111 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
112 * just read the file directly
114 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
115 blob = &fileBlob;
116 break;
117 case CERT_QUERY_OBJECT_BLOB:
118 blob = pvObject;
119 ret = TRUE;
120 break;
121 default:
122 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
123 ret = FALSE;
125 if (!ret)
126 return FALSE;
128 ret = FALSE;
129 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
130 CERT_STORE_CREATE_NEW_FLAG, NULL);
131 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)
133 ret = CRYPT_QueryContextBlob(blob, dwExpectedContentTypeFlags, store,
134 pdwContentType, ppvContext);
135 if (ret)
136 formatType = CERT_QUERY_FORMAT_BINARY;
138 if (!ret &&
139 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED))
141 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData };
142 CRYPT_DATA_BLOB decoded;
144 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1])
145 trimmed.cbData--;
146 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData,
147 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL);
148 if (ret)
150 decoded.pbData = CryptMemAlloc(decoded.cbData);
151 if (decoded.pbData)
153 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData,
154 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData,
155 &decoded.cbData, NULL, NULL);
156 if (ret)
158 ret = CRYPT_QueryContextBlob(&decoded,
159 dwExpectedContentTypeFlags, store, pdwContentType,
160 ppvContext);
161 if (ret)
162 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
164 CryptMemFree(decoded.pbData);
166 else
167 ret = FALSE;
170 if (ret)
172 if (pdwMsgAndCertEncodingType)
173 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
174 if (pdwFormatType)
175 *pdwFormatType = formatType;
176 if (phCertStore)
177 *phCertStore = CertDuplicateStore(store);
179 CertCloseStore(store, 0);
180 if (blob == &fileBlob)
181 CryptMemFree(blob->pbData);
182 TRACE("returning %d\n", ret);
183 return ret;
186 static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
187 const void *pvObject, DWORD dwExpectedContentTypeFlags,
188 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
189 HCERTSTORE *phCertStore, const void **ppvContext)
191 CERT_BLOB fileBlob;
192 const CERT_BLOB *blob;
193 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
194 const void *context;
195 DWORD contextType;
196 BOOL ret;
198 switch (dwObjectType)
200 case CERT_QUERY_OBJECT_FILE:
201 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
202 * just read the file directly
204 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
205 blob = &fileBlob;
206 break;
207 case CERT_QUERY_OBJECT_BLOB:
208 blob = pvObject;
209 ret = TRUE;
210 break;
211 default:
212 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
213 ret = FALSE;
215 if (!ret)
216 return FALSE;
218 ret = FALSE;
219 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
220 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
221 if (context)
223 DWORD contentType, certStoreOffset;
225 ret = TRUE;
226 switch (contextType)
228 case CERT_STORE_CERTIFICATE_CONTEXT:
229 contextInterface = pCertInterface;
230 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT;
231 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore);
232 if (!(dwExpectedContentTypeFlags &
233 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT))
235 SetLastError(ERROR_INVALID_DATA);
236 ret = FALSE;
237 goto end;
239 break;
240 case CERT_STORE_CRL_CONTEXT:
241 contextInterface = pCRLInterface;
242 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL;
243 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore);
244 if (!(dwExpectedContentTypeFlags &
245 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL))
247 SetLastError(ERROR_INVALID_DATA);
248 ret = FALSE;
249 goto end;
251 break;
252 case CERT_STORE_CTL_CONTEXT:
253 contextInterface = pCTLInterface;
254 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL;
255 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore);
256 if (!(dwExpectedContentTypeFlags &
257 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))
259 SetLastError(ERROR_INVALID_DATA);
260 ret = FALSE;
261 goto end;
263 break;
264 default:
265 SetLastError(ERROR_INVALID_DATA);
266 ret = FALSE;
267 goto end;
269 if (pdwMsgAndCertEncodingType)
270 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
271 if (pdwContentType)
272 *pdwContentType = contentType;
273 if (phCertStore)
274 *phCertStore = CertDuplicateStore(
275 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
276 if (ppvContext)
278 *ppvContext = context;
279 Context_AddRef(context_from_ptr(context));
283 end:
284 if (contextInterface && context)
285 Context_Release(context_from_ptr(context));
286 if (blob == &fileBlob)
287 CryptMemFree(blob->pbData);
288 TRACE("returning %d\n", ret);
289 return ret;
292 static BOOL CRYPT_QuerySerializedStoreFromFile(LPCWSTR fileName,
293 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
294 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
296 HANDLE file;
297 BOOL ret = FALSE;
299 TRACE("%s\n", debugstr_w(fileName));
300 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
301 OPEN_EXISTING, 0, NULL);
302 if (file != INVALID_HANDLE_VALUE)
304 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
305 CERT_STORE_CREATE_NEW_FLAG, NULL);
307 ret = CRYPT_ReadSerializedStoreFromFile(file, store);
308 if (ret)
310 if (pdwMsgAndCertEncodingType)
311 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
312 if (pdwContentType)
313 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
314 if (phCertStore)
315 *phCertStore = CertDuplicateStore(store);
317 CertCloseStore(store, 0);
318 CloseHandle(file);
320 TRACE("returning %d\n", ret);
321 return ret;
324 static BOOL CRYPT_QuerySerializedStoreFromBlob(const CRYPT_DATA_BLOB *blob,
325 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
326 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
328 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
329 CERT_STORE_CREATE_NEW_FLAG, NULL);
330 BOOL ret;
332 TRACE("(%d, %p)\n", blob->cbData, blob->pbData);
334 ret = CRYPT_ReadSerializedStoreFromBlob(blob, store);
335 if (ret)
337 if (pdwMsgAndCertEncodingType)
338 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
339 if (pdwContentType)
340 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
341 if (phCertStore)
342 *phCertStore = CertDuplicateStore(store);
344 CertCloseStore(store, 0);
345 TRACE("returning %d\n", ret);
346 return ret;
349 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
350 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
351 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
353 switch (dwObjectType)
355 case CERT_QUERY_OBJECT_FILE:
356 return CRYPT_QuerySerializedStoreFromFile(pvObject,
357 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
358 case CERT_QUERY_OBJECT_BLOB:
359 return CRYPT_QuerySerializedStoreFromBlob(pvObject,
360 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
361 default:
362 FIXME("unimplemented for type %d\n", dwObjectType);
363 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
364 return FALSE;
368 static BOOL CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB *blob,
369 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg)
371 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
372 BOOL ret = FALSE;
373 HCRYPTMSG msg;
375 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL)))
377 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
378 if (ret)
380 DWORD type, len = sizeof(type);
382 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
383 if (ret)
385 if (type != CMSG_SIGNED)
387 SetLastError(ERROR_INVALID_DATA);
388 ret = FALSE;
392 if (!ret)
394 CryptMsgClose(msg);
395 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL,
396 NULL);
397 if (msg)
399 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
400 if (!ret)
402 CryptMsgClose(msg);
403 msg = NULL;
408 if (ret)
410 if (pdwMsgAndCertEncodingType)
411 *pdwMsgAndCertEncodingType = encodingType;
412 if (pdwContentType)
413 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
414 if (phMsg)
415 *phMsg = msg;
417 return ret;
420 static BOOL CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB *blob,
421 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCRYPTMSG *phMsg)
423 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
424 BOOL ret = FALSE;
425 HCRYPTMSG msg;
427 if ((msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL)))
429 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
430 if (ret)
432 DWORD type, len = sizeof(type);
434 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
435 if (ret)
437 if (type != CMSG_DATA)
439 SetLastError(ERROR_INVALID_DATA);
440 ret = FALSE;
444 if (!ret)
446 CryptMsgClose(msg);
447 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0,
448 NULL, NULL);
449 if (msg)
451 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
452 if (!ret)
454 CryptMsgClose(msg);
455 msg = NULL;
460 if (ret)
462 if (pdwMsgAndCertEncodingType)
463 *pdwMsgAndCertEncodingType = encodingType;
464 if (pdwContentType)
465 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
466 if (phMsg)
467 *phMsg = msg;
469 return ret;
472 /* Used to decode non-embedded messages */
473 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
474 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
475 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType,
476 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
478 CERT_BLOB fileBlob;
479 const CERT_BLOB *blob;
480 BOOL ret;
481 HCRYPTMSG msg = NULL;
482 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
483 DWORD formatType = 0;
485 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject,
486 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
487 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
488 phMsg);
490 switch (dwObjectType)
492 case CERT_QUERY_OBJECT_FILE:
493 /* This isn't an embedded PKCS7 message, so just read the file
494 * directly
496 ret = CRYPT_ReadBlobFromFile(pvObject, &fileBlob);
497 blob = &fileBlob;
498 break;
499 case CERT_QUERY_OBJECT_BLOB:
500 blob = pvObject;
501 ret = TRUE;
502 break;
503 default:
504 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
505 ret = FALSE;
507 if (!ret)
508 return FALSE;
510 ret = FALSE;
511 if (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)
513 /* Try it first as a signed message */
514 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
515 ret = CRYPT_QuerySignedMessage(blob, pdwMsgAndCertEncodingType,
516 pdwContentType, &msg);
517 /* Failing that, try as an unsigned message */
518 if (!ret &&
519 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
520 ret = CRYPT_QueryUnsignedMessage(blob, pdwMsgAndCertEncodingType,
521 pdwContentType, &msg);
522 if (ret)
523 formatType = CERT_QUERY_FORMAT_BINARY;
525 if (!ret &&
526 (dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED))
528 CRYPT_DATA_BLOB trimmed = { blob->cbData, blob->pbData };
529 CRYPT_DATA_BLOB decoded;
531 while (trimmed.cbData && !trimmed.pbData[trimmed.cbData - 1])
532 trimmed.cbData--;
533 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData,
534 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL);
535 if (ret)
537 decoded.pbData = CryptMemAlloc(decoded.cbData);
538 if (decoded.pbData)
540 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData,
541 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData,
542 &decoded.cbData, NULL, NULL);
543 if (ret)
545 /* Try it first as a signed message */
546 if (dwExpectedContentTypeFlags &
547 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
548 ret = CRYPT_QuerySignedMessage(&decoded,
549 pdwMsgAndCertEncodingType, pdwContentType, &msg);
550 /* Failing that, try as an unsigned message */
551 if (!ret && (dwExpectedContentTypeFlags &
552 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
553 ret = CRYPT_QueryUnsignedMessage(&decoded,
554 pdwMsgAndCertEncodingType, pdwContentType, &msg);
555 if (ret)
556 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
558 CryptMemFree(decoded.pbData);
560 else
561 ret = FALSE;
563 if (!ret && !(blob->cbData % sizeof(WCHAR)))
565 CRYPT_DATA_BLOB decoded;
566 LPWSTR str = (LPWSTR)blob->pbData;
567 DWORD strLen = blob->cbData / sizeof(WCHAR);
569 /* Try again, assuming the input string is UTF-16 base64 */
570 while (strLen && !str[strLen - 1])
571 strLen--;
572 ret = CryptStringToBinaryW(str, strLen, CRYPT_STRING_BASE64_ANY,
573 NULL, &decoded.cbData, NULL, NULL);
574 if (ret)
576 decoded.pbData = CryptMemAlloc(decoded.cbData);
577 if (decoded.pbData)
579 ret = CryptStringToBinaryW(str, strLen,
580 CRYPT_STRING_BASE64_ANY, decoded.pbData, &decoded.cbData,
581 NULL, NULL);
582 if (ret)
584 /* Try it first as a signed message */
585 if (dwExpectedContentTypeFlags &
586 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
587 ret = CRYPT_QuerySignedMessage(&decoded,
588 pdwMsgAndCertEncodingType, pdwContentType, &msg);
589 /* Failing that, try as an unsigned message */
590 if (!ret && (dwExpectedContentTypeFlags &
591 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
592 ret = CRYPT_QueryUnsignedMessage(&decoded,
593 pdwMsgAndCertEncodingType, pdwContentType, &msg);
594 if (ret)
595 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
597 CryptMemFree(decoded.pbData);
599 else
600 ret = FALSE;
604 if (ret)
606 if (pdwFormatType)
607 *pdwFormatType = formatType;
608 if (phCertStore)
609 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
610 0, msg);
611 if (phMsg)
612 *phMsg = msg;
613 else
614 CryptMsgClose(msg);
616 if (blob == &fileBlob)
617 CryptMemFree(blob->pbData);
618 TRACE("returning %d\n", ret);
619 return ret;
622 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
623 const void *pvObject, DWORD dwExpectedContentTypeFlags,
624 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
625 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
627 HANDLE file;
628 GUID subject;
629 BOOL ret = FALSE;
631 TRACE("%s\n", debugstr_w(pvObject));
633 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
635 WARN("don't know what to do for type %d embedded signed messages\n",
636 dwObjectType);
637 SetLastError(E_INVALIDARG);
638 return FALSE;
640 file = CreateFileW(pvObject, GENERIC_READ, FILE_SHARE_READ,
641 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
642 if (file != INVALID_HANDLE_VALUE)
644 ret = CryptSIPRetrieveSubjectGuid(pvObject, file, &subject);
645 if (ret)
647 SIP_DISPATCH_INFO sip;
649 memset(&sip, 0, sizeof(sip));
650 sip.cbSize = sizeof(sip);
651 ret = CryptSIPLoad(&subject, 0, &sip);
652 if (ret)
654 SIP_SUBJECTINFO subjectInfo;
655 CERT_BLOB blob;
656 DWORD encodingType;
658 memset(&subjectInfo, 0, sizeof(subjectInfo));
659 subjectInfo.cbSize = sizeof(subjectInfo);
660 subjectInfo.pgSubjectType = &subject;
661 subjectInfo.hFile = file;
662 subjectInfo.pwsFileName = pvObject;
663 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
664 NULL);
665 if (ret)
667 blob.pbData = CryptMemAlloc(blob.cbData);
668 if (blob.pbData)
670 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
671 &blob.cbData, blob.pbData);
672 if (ret)
674 ret = CRYPT_QueryMessageObject(
675 CERT_QUERY_OBJECT_BLOB, &blob,
676 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
677 CERT_QUERY_FORMAT_FLAG_BINARY,
678 pdwMsgAndCertEncodingType, NULL, NULL,
679 phCertStore, phMsg);
680 if (ret && pdwContentType)
681 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED;
683 CryptMemFree(blob.pbData);
685 else
687 SetLastError(ERROR_OUTOFMEMORY);
688 ret = FALSE;
693 CloseHandle(file);
695 TRACE("returning %d\n", ret);
696 return ret;
699 static BOOL CRYPT_QueryPFXObject(DWORD dwObjectType, const void *pvObject,
700 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
701 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, DWORD *pdwFormatType,
702 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
704 CRYPT_DATA_BLOB blob = {0}, *ptr;
705 BOOL ret;
707 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType, pvObject,
708 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
709 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
710 phMsg);
712 switch (dwObjectType)
714 case CERT_QUERY_OBJECT_FILE:
715 if (!CRYPT_ReadBlobFromFile(pvObject, &blob)) return FALSE;
716 ptr = &blob;
717 break;
719 case CERT_QUERY_OBJECT_BLOB:
720 ptr = (CRYPT_DATA_BLOB *)pvObject;
721 break;
723 default:
724 return FALSE;
727 ret = PFXIsPFXBlob(ptr);
728 if (ret)
730 if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
731 if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PFX;
732 if (pdwFormatType) *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
733 if (phCertStore) *phCertStore = NULL;
734 if (phMsg) *phMsg = NULL;
737 CryptMemFree(blob.pbData);
738 return ret;
741 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
742 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
743 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
744 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
745 const void **ppvContext)
747 static const DWORD unimplementedTypes =
748 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
749 BOOL ret = TRUE;
751 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
752 dwObjectType, pvObject, dwExpectedContentTypeFlags,
753 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
754 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
756 if (dwObjectType != CERT_QUERY_OBJECT_BLOB &&
757 dwObjectType != CERT_QUERY_OBJECT_FILE)
759 WARN("unsupported type %d\n", dwObjectType);
760 SetLastError(E_INVALIDARG);
761 return FALSE;
763 if (!pvObject)
765 WARN("missing required argument\n");
766 SetLastError(E_INVALIDARG);
767 return FALSE;
769 if (dwExpectedContentTypeFlags & unimplementedTypes)
770 WARN("unimplemented for types %08x\n",
771 dwExpectedContentTypeFlags & unimplementedTypes);
773 if (pdwFormatType)
774 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
775 if (phCertStore)
776 *phCertStore = NULL;
777 if (phMsg)
778 *phMsg = NULL;
779 if (ppvContext)
780 *ppvContext = NULL;
782 ret = FALSE;
783 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
784 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
785 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
787 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
788 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
789 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
790 ppvContext);
792 if (!ret &&
793 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
795 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
796 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
798 if (!ret &&
799 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
800 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
801 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
803 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
804 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
805 phCertStore, ppvContext);
807 if (!ret &&
808 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
809 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
811 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
812 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
813 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType,
814 phCertStore, phMsg);
816 if (!ret &&
817 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
819 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
820 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
821 phCertStore, phMsg);
823 if (!ret &&
824 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PFX))
826 ret = CRYPT_QueryPFXObject(dwObjectType, pvObject,
827 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
828 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType,
829 phCertStore, phMsg);
831 if (!ret)
832 SetLastError(CRYPT_E_NO_MATCH);
833 TRACE("returning %d\n", ret);
834 return ret;
837 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
838 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
839 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
840 DWORD *pcbFormat)
842 BOOL ret;
843 DWORD bytesNeeded;
845 if (cbEncoded)
846 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
847 else
848 bytesNeeded = sizeof(WCHAR);
849 if (!pbFormat)
851 *pcbFormat = bytesNeeded;
852 ret = TRUE;
854 else if (*pcbFormat < bytesNeeded)
856 *pcbFormat = bytesNeeded;
857 SetLastError(ERROR_MORE_DATA);
858 ret = FALSE;
860 else
862 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
863 static const WCHAR endFmt[] = { '%','0','2','x',0 };
864 DWORD i;
865 LPWSTR ptr = pbFormat;
867 *pcbFormat = bytesNeeded;
868 if (cbEncoded)
870 for (i = 0; i < cbEncoded; i++)
872 if (i < cbEncoded - 1)
873 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
874 else
875 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
878 else
879 *ptr = 0;
880 ret = TRUE;
882 return ret;
885 #define MAX_STRING_RESOURCE_LEN 128
887 static const WCHAR commaSpace[] = { ',',' ',0 };
889 struct BitToString
891 BYTE bit;
892 int id;
893 WCHAR str[MAX_STRING_RESOURCE_LEN];
896 static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map,
897 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first)
899 DWORD bytesNeeded = sizeof(WCHAR);
900 unsigned int i;
901 BOOL ret = TRUE, localFirst = *first;
903 for (i = 0; i < mapEntries; i++)
904 if (bits & map[i].bit)
906 if (!localFirst)
907 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR);
908 localFirst = FALSE;
909 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR);
911 if (!pbFormat)
913 *first = localFirst;
914 *pcbFormat = bytesNeeded;
916 else if (*pcbFormat < bytesNeeded)
918 *first = localFirst;
919 *pcbFormat = bytesNeeded;
920 SetLastError(ERROR_MORE_DATA);
921 ret = FALSE;
923 else
925 LPWSTR str = pbFormat;
927 localFirst = *first;
928 *pcbFormat = bytesNeeded;
929 for (i = 0; i < mapEntries; i++)
930 if (bits & map[i].bit)
932 if (!localFirst)
934 strcpyW(str, commaSpace);
935 str += strlenW(commaSpace);
937 localFirst = FALSE;
938 strcpyW(str, map[i].str);
939 str += strlenW(map[i].str);
941 *first = localFirst;
943 return ret;
946 static struct BitToString keyUsageByte0Map[] = {
947 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } },
948 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } },
949 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } },
950 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } },
951 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } },
952 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } },
953 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } },
954 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } },
955 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },
957 static struct BitToString keyUsageByte1Map[] = {
958 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },
961 static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType,
962 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
963 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
964 DWORD *pcbFormat)
966 DWORD size;
967 CRYPT_BIT_BLOB *bits;
968 BOOL ret;
970 if (!cbEncoded)
972 SetLastError(E_INVALIDARG);
973 return FALSE;
975 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE,
976 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
978 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
979 DWORD bytesNeeded = sizeof(WCHAR);
981 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable));
982 if (!bits->cbData || bits->cbData > 2)
984 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
985 if (!pbFormat)
986 *pcbFormat = bytesNeeded;
987 else if (*pcbFormat < bytesNeeded)
989 *pcbFormat = bytesNeeded;
990 SetLastError(ERROR_MORE_DATA);
991 ret = FALSE;
993 else
995 LPWSTR str = pbFormat;
997 *pcbFormat = bytesNeeded;
998 strcpyW(str, infoNotAvailable);
1001 else
1003 static BOOL stringsLoaded = FALSE;
1004 unsigned int i;
1005 DWORD bitStringLen;
1006 BOOL first = TRUE;
1008 if (!stringsLoaded)
1010 for (i = 0; i < ARRAY_SIZE(keyUsageByte0Map); i++)
1011 LoadStringW(hInstance, keyUsageByte0Map[i].id, keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN);
1012 for (i = 0; i < ARRAY_SIZE(keyUsageByte1Map); i++)
1013 LoadStringW(hInstance, keyUsageByte1Map[i].id, keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN);
1014 stringsLoaded = TRUE;
1016 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, ARRAY_SIZE(keyUsageByte0Map),
1017 NULL, &bitStringLen, &first);
1018 bytesNeeded += bitStringLen;
1019 if (bits->cbData == 2)
1021 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, ARRAY_SIZE(keyUsageByte1Map),
1022 NULL, &bitStringLen, &first);
1023 bytesNeeded += bitStringLen;
1025 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
1026 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
1027 bits->cbData, NULL, &size);
1028 bytesNeeded += size;
1029 if (!pbFormat)
1030 *pcbFormat = bytesNeeded;
1031 else if (*pcbFormat < bytesNeeded)
1033 *pcbFormat = bytesNeeded;
1034 SetLastError(ERROR_MORE_DATA);
1035 ret = FALSE;
1037 else
1039 LPWSTR str = pbFormat;
1041 bitStringLen = bytesNeeded;
1042 first = TRUE;
1043 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map, ARRAY_SIZE(keyUsageByte0Map),
1044 str, &bitStringLen, &first);
1045 str += bitStringLen / sizeof(WCHAR) - 1;
1046 if (bits->cbData == 2)
1048 bitStringLen = bytesNeeded;
1049 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map, ARRAY_SIZE(keyUsageByte1Map),
1050 str, &bitStringLen, &first);
1051 str += bitStringLen / sizeof(WCHAR) - 1;
1053 *str++ = ' ';
1054 *str++ = '(';
1055 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
1056 bits->cbData, str, &size);
1057 str += size / sizeof(WCHAR) - 1;
1058 *str++ = ')';
1059 *str = 0;
1062 LocalFree(bits);
1064 return ret;
1067 static const WCHAR crlf[] = { '\r','\n',0 };
1069 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
1070 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
1071 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
1072 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
1074 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
1075 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1076 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1077 DWORD *pcbFormat)
1079 DWORD size;
1080 CERT_BASIC_CONSTRAINTS2_INFO *info;
1081 BOOL ret;
1083 if (!cbEncoded)
1085 SetLastError(E_INVALIDARG);
1086 return FALSE;
1088 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
1089 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1091 static const WCHAR pathFmt[] = { '%','d',0 };
1092 static BOOL stringsLoaded = FALSE;
1093 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1094 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
1095 LPCWSTR sep, subjectType;
1096 DWORD sepLen;
1098 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1100 sep = crlf;
1101 sepLen = strlenW(crlf) * sizeof(WCHAR);
1103 else
1105 sep = commaSpace;
1106 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1109 if (!stringsLoaded)
1111 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader, ARRAY_SIZE(subjectTypeHeader));
1112 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA, ARRAY_SIZE(subjectTypeCA));
1113 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT, subjectTypeEndCert, ARRAY_SIZE(subjectTypeEndCert));
1114 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader, ARRAY_SIZE(pathLengthHeader));
1115 stringsLoaded = TRUE;
1117 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
1118 if (info->fCA)
1119 subjectType = subjectTypeCA;
1120 else
1121 subjectType = subjectTypeEndCert;
1122 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
1123 bytesNeeded += sepLen;
1124 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
1125 if (info->fPathLenConstraint)
1126 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
1127 else
1128 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength, ARRAY_SIZE(pathLength));
1129 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
1130 if (!pbFormat)
1131 *pcbFormat = bytesNeeded;
1132 else if (*pcbFormat < bytesNeeded)
1134 *pcbFormat = bytesNeeded;
1135 SetLastError(ERROR_MORE_DATA);
1136 ret = FALSE;
1138 else
1140 LPWSTR str = pbFormat;
1142 *pcbFormat = bytesNeeded;
1143 strcpyW(str, subjectTypeHeader);
1144 str += strlenW(subjectTypeHeader);
1145 strcpyW(str, subjectType);
1146 str += strlenW(subjectType);
1147 strcpyW(str, sep);
1148 str += sepLen / sizeof(WCHAR);
1149 strcpyW(str, pathLengthHeader);
1150 str += strlenW(pathLengthHeader);
1151 strcpyW(str, pathLength);
1153 LocalFree(info);
1155 return ret;
1158 static BOOL CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB *blob, int id,
1159 LPWSTR str, DWORD *pcbStr)
1161 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1162 DWORD bytesNeeded;
1163 BOOL ret;
1165 LoadStringW(hInstance, id, buf, ARRAY_SIZE(buf));
1166 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
1167 blob->pbData, blob->cbData, NULL, &bytesNeeded);
1168 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1169 if (!str)
1171 *pcbStr = bytesNeeded;
1172 ret = TRUE;
1174 else if (*pcbStr < bytesNeeded)
1176 *pcbStr = bytesNeeded;
1177 SetLastError(ERROR_MORE_DATA);
1178 ret = FALSE;
1180 else
1182 *pcbStr = bytesNeeded;
1183 strcpyW(str, buf);
1184 str += strlenW(str);
1185 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1186 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
1187 blob->pbData, blob->cbData, str, &bytesNeeded);
1189 return ret;
1192 static BOOL CRYPT_FormatKeyId(const CRYPT_DATA_BLOB *keyId, LPWSTR str,
1193 DWORD *pcbStr)
1195 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
1198 static BOOL CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB *serialNum, LPWSTR str,
1199 DWORD *pcbStr)
1201 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
1202 str, pcbStr);
1205 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
1206 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
1208 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
1209 const CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
1211 BOOL ret;
1212 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1213 WCHAR mask[MAX_STRING_RESOURCE_LEN];
1214 WCHAR ipAddrBuf[32];
1215 WCHAR maskBuf[16];
1216 DWORD bytesNeeded = sizeof(WCHAR);
1217 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
1219 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1220 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1221 switch (entry->dwAltNameChoice)
1223 case CERT_ALT_NAME_RFC822_NAME:
1224 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf, ARRAY_SIZE(buf));
1225 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
1226 ret = TRUE;
1227 break;
1228 case CERT_ALT_NAME_DNS_NAME:
1229 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf, ARRAY_SIZE(buf));
1230 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
1231 ret = TRUE;
1232 break;
1233 case CERT_ALT_NAME_DIRECTORY_NAME:
1235 DWORD directoryNameLen;
1237 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1238 strType |= CERT_NAME_STR_CRLF_FLAG;
1239 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING,
1240 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0);
1241 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf, ARRAY_SIZE(buf));
1242 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR);
1243 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1244 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR);
1245 else
1246 bytesNeeded += sizeof(WCHAR); /* '=' */
1247 ret = TRUE;
1248 break;
1250 case CERT_ALT_NAME_URL:
1251 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf, ARRAY_SIZE(buf));
1252 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
1253 ret = TRUE;
1254 break;
1255 case CERT_ALT_NAME_IP_ADDRESS:
1257 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
1258 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1260 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
1261 '.','%','d',0 };
1263 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf, ARRAY_SIZE(buf));
1264 if (entry->u.IPAddress.cbData == 8)
1266 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1268 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask, ARRAY_SIZE(mask));
1269 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
1270 sprintfW(ipAddrBuf, ipAddrFmt,
1271 entry->u.IPAddress.pbData[0],
1272 entry->u.IPAddress.pbData[1],
1273 entry->u.IPAddress.pbData[2],
1274 entry->u.IPAddress.pbData[3]);
1275 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
1276 /* indent again, for the mask line */
1277 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1278 sprintfW(maskBuf, ipAddrFmt,
1279 entry->u.IPAddress.pbData[4],
1280 entry->u.IPAddress.pbData[5],
1281 entry->u.IPAddress.pbData[6],
1282 entry->u.IPAddress.pbData[7]);
1283 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
1284 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
1286 else
1288 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
1289 entry->u.IPAddress.pbData[0],
1290 entry->u.IPAddress.pbData[1],
1291 entry->u.IPAddress.pbData[2],
1292 entry->u.IPAddress.pbData[3],
1293 entry->u.IPAddress.pbData[4],
1294 entry->u.IPAddress.pbData[5],
1295 entry->u.IPAddress.pbData[6],
1296 entry->u.IPAddress.pbData[7]);
1297 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
1299 ret = TRUE;
1301 else
1303 FIXME("unknown IP address format (%d bytes)\n",
1304 entry->u.IPAddress.cbData);
1305 ret = FALSE;
1307 break;
1309 default:
1310 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
1311 ret = FALSE;
1313 if (ret)
1315 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1316 if (!str)
1317 *pcbStr = bytesNeeded;
1318 else if (*pcbStr < bytesNeeded)
1320 *pcbStr = bytesNeeded;
1321 SetLastError(ERROR_MORE_DATA);
1322 ret = FALSE;
1324 else
1326 DWORD i;
1328 *pcbStr = bytesNeeded;
1329 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1331 for (i = 0; i < indentLevel; i++)
1333 strcpyW(str, indent);
1334 str += strlenW(indent);
1337 strcpyW(str, buf);
1338 str += strlenW(str);
1339 switch (entry->dwAltNameChoice)
1341 case CERT_ALT_NAME_RFC822_NAME:
1342 case CERT_ALT_NAME_DNS_NAME:
1343 case CERT_ALT_NAME_URL:
1344 strcpyW(str, entry->u.pwszURL);
1345 break;
1346 case CERT_ALT_NAME_DIRECTORY_NAME:
1347 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1349 strcpyW(str, colonCrlf);
1350 str += strlenW(colonCrlf);
1352 else
1353 *str++ = '=';
1354 cert_name_to_str_with_indent(X509_ASN_ENCODING,
1355 indentLevel + 1, &entry->u.DirectoryName, strType, str,
1356 bytesNeeded / sizeof(WCHAR));
1357 break;
1358 case CERT_ALT_NAME_IP_ADDRESS:
1359 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1361 strcpyW(str, ipAddrBuf);
1362 str += strlenW(ipAddrBuf);
1363 strcpyW(str, crlf);
1364 str += strlenW(crlf);
1365 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1367 for (i = 0; i < indentLevel; i++)
1369 strcpyW(str, indent);
1370 str += strlenW(indent);
1373 strcpyW(str, mask);
1374 str += strlenW(mask);
1375 strcpyW(str, maskBuf);
1377 else
1378 strcpyW(str, ipAddrBuf);
1379 break;
1383 return ret;
1386 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
1387 const CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
1389 DWORD i, size, bytesNeeded = 0;
1390 BOOL ret = TRUE;
1391 LPCWSTR sep;
1392 DWORD sepLen;
1394 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1396 sep = crlf;
1397 sepLen = strlenW(crlf) * sizeof(WCHAR);
1399 else
1401 sep = commaSpace;
1402 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1405 for (i = 0; ret && i < name->cAltEntry; i++)
1407 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1408 &name->rgAltEntry[i], NULL, &size);
1409 if (ret)
1411 bytesNeeded += size - sizeof(WCHAR);
1412 if (i < name->cAltEntry - 1)
1413 bytesNeeded += sepLen;
1416 if (ret)
1418 bytesNeeded += sizeof(WCHAR);
1419 if (!str)
1420 *pcbStr = bytesNeeded;
1421 else if (*pcbStr < bytesNeeded)
1423 *pcbStr = bytesNeeded;
1424 SetLastError(ERROR_MORE_DATA);
1425 ret = FALSE;
1427 else
1429 *pcbStr = bytesNeeded;
1430 for (i = 0; ret && i < name->cAltEntry; i++)
1432 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1433 &name->rgAltEntry[i], str, &size);
1434 if (ret)
1436 str += size / sizeof(WCHAR) - 1;
1437 if (i < name->cAltEntry - 1)
1439 strcpyW(str, sep);
1440 str += sepLen / sizeof(WCHAR);
1446 return ret;
1449 static const WCHAR colonSep[] = { ':',' ',0 };
1451 static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType,
1452 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1453 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1454 DWORD *pcbFormat)
1456 BOOL ret;
1457 CERT_ALT_NAME_INFO *info;
1458 DWORD size;
1460 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME,
1461 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1463 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat);
1464 LocalFree(info);
1466 return ret;
1469 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
1470 const CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
1472 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1473 DWORD bytesNeeded, sepLen;
1474 LPCWSTR sep;
1475 BOOL ret;
1477 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, ARRAY_SIZE(buf));
1478 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL,
1479 &bytesNeeded);
1480 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1481 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1483 sep = colonCrlf;
1484 sepLen = strlenW(colonCrlf) * sizeof(WCHAR);
1486 else
1488 sep = colonSep;
1489 sepLen = strlenW(colonSep) * sizeof(WCHAR);
1491 bytesNeeded += sepLen;
1492 if (ret)
1494 if (!str)
1495 *pcbStr = bytesNeeded;
1496 else if (*pcbStr < bytesNeeded)
1498 *pcbStr = bytesNeeded;
1499 SetLastError(ERROR_MORE_DATA);
1500 ret = FALSE;
1502 else
1504 *pcbStr = bytesNeeded;
1505 strcpyW(str, buf);
1506 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1507 str += strlenW(str);
1508 strcpyW(str, sep);
1509 str += sepLen / sizeof(WCHAR);
1510 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str,
1511 &bytesNeeded);
1514 return ret;
1517 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1518 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1519 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1520 DWORD *pcbFormat)
1522 CERT_AUTHORITY_KEY_ID2_INFO *info;
1523 DWORD size;
1524 BOOL ret = FALSE;
1526 if (!cbEncoded)
1528 SetLastError(E_INVALIDARG);
1529 return FALSE;
1531 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1532 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1534 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1535 LPCWSTR sep;
1536 DWORD sepLen;
1537 BOOL needSeparator = FALSE;
1539 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1541 sep = crlf;
1542 sepLen = strlenW(crlf) * sizeof(WCHAR);
1544 else
1546 sep = commaSpace;
1547 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1550 if (info->KeyId.cbData)
1552 needSeparator = TRUE;
1553 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1554 if (ret)
1556 /* don't include NULL-terminator more than once */
1557 bytesNeeded += size - sizeof(WCHAR);
1560 if (info->AuthorityCertIssuer.cAltEntry)
1562 if (needSeparator)
1563 bytesNeeded += sepLen;
1564 needSeparator = TRUE;
1565 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1566 &info->AuthorityCertIssuer, NULL, &size);
1567 if (ret)
1569 /* don't include NULL-terminator more than once */
1570 bytesNeeded += size - sizeof(WCHAR);
1573 if (info->AuthorityCertSerialNumber.cbData)
1575 if (needSeparator)
1576 bytesNeeded += sepLen;
1577 ret = CRYPT_FormatCertSerialNumber(
1578 &info->AuthorityCertSerialNumber, NULL, &size);
1579 if (ret)
1581 /* don't include NULL-terminator more than once */
1582 bytesNeeded += size - sizeof(WCHAR);
1585 if (ret)
1587 if (!pbFormat)
1588 *pcbFormat = bytesNeeded;
1589 else if (*pcbFormat < bytesNeeded)
1591 *pcbFormat = bytesNeeded;
1592 SetLastError(ERROR_MORE_DATA);
1593 ret = FALSE;
1595 else
1597 LPWSTR str = pbFormat;
1599 *pcbFormat = bytesNeeded;
1600 needSeparator = FALSE;
1601 if (info->KeyId.cbData)
1603 needSeparator = TRUE;
1604 /* Overestimate size available, it's already been checked
1605 * above.
1607 size = bytesNeeded;
1608 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1609 if (ret)
1610 str += size / sizeof(WCHAR) - 1;
1612 if (info->AuthorityCertIssuer.cAltEntry)
1614 if (needSeparator)
1616 strcpyW(str, sep);
1617 str += sepLen / sizeof(WCHAR);
1619 needSeparator = TRUE;
1620 /* Overestimate size available, it's already been checked
1621 * above.
1623 size = bytesNeeded;
1624 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1625 &info->AuthorityCertIssuer, str, &size);
1626 if (ret)
1627 str += size / sizeof(WCHAR) - 1;
1629 if (info->AuthorityCertSerialNumber.cbData)
1631 if (needSeparator)
1633 strcpyW(str, sep);
1634 str += sepLen / sizeof(WCHAR);
1636 /* Overestimate size available, it's already been checked
1637 * above.
1639 size = bytesNeeded;
1640 ret = CRYPT_FormatCertSerialNumber(
1641 &info->AuthorityCertSerialNumber, str, &size);
1645 LocalFree(info);
1647 return ret;
1650 static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1651 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1652 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1653 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1654 static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1655 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1657 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1658 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1659 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1660 DWORD *pcbFormat)
1662 CERT_AUTHORITY_INFO_ACCESS *info;
1663 DWORD size;
1664 BOOL ret = FALSE;
1666 if (!cbEncoded)
1668 SetLastError(E_INVALIDARG);
1669 return FALSE;
1671 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1672 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1673 NULL, &info, &size)))
1675 DWORD bytesNeeded = sizeof(WCHAR);
1677 if (!info->cAccDescr)
1679 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1681 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable));
1682 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1683 if (!pbFormat)
1684 *pcbFormat = bytesNeeded;
1685 else if (*pcbFormat < bytesNeeded)
1687 *pcbFormat = bytesNeeded;
1688 SetLastError(ERROR_MORE_DATA);
1689 ret = FALSE;
1691 else
1693 *pcbFormat = bytesNeeded;
1694 strcpyW(pbFormat, infoNotAvailable);
1697 else
1699 static const WCHAR numFmt[] = { '%','d',0 };
1700 static const WCHAR equal[] = { '=',0 };
1701 static BOOL stringsLoaded = FALSE;
1702 DWORD i;
1703 LPCWSTR headingSep, accessMethodSep, locationSep;
1704 WCHAR accessDescrNum[11];
1706 if (!stringsLoaded)
1708 LoadStringW(hInstance, IDS_AIA, aia, ARRAY_SIZE(aia));
1709 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod, ARRAY_SIZE(accessMethod));
1710 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp, ARRAY_SIZE(ocsp));
1711 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers, ARRAY_SIZE(caIssuers));
1712 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown, ARRAY_SIZE(unknown));
1713 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation, ARRAY_SIZE(accessLocation));
1714 stringsLoaded = TRUE;
1716 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1718 headingSep = crlf;
1719 accessMethodSep = crlf;
1720 locationSep = colonCrlf;
1722 else
1724 headingSep = colonSep;
1725 accessMethodSep = commaSpace;
1726 locationSep = equal;
1729 for (i = 0; ret && i < info->cAccDescr; i++)
1731 /* Heading */
1732 bytesNeeded += sizeof(WCHAR); /* left bracket */
1733 sprintfW(accessDescrNum, numFmt, i + 1);
1734 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1735 bytesNeeded += sizeof(WCHAR); /* right bracket */
1736 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1737 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1738 /* Access method */
1739 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1740 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1741 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1742 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1743 szOID_PKIX_OCSP))
1744 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1745 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1746 szOID_PKIX_CA_ISSUERS))
1747 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1748 else
1749 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1750 bytesNeeded += sizeof(WCHAR); /* space */
1751 bytesNeeded += sizeof(WCHAR); /* left paren */
1752 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1753 * sizeof(WCHAR);
1754 bytesNeeded += sizeof(WCHAR); /* right paren */
1755 /* Delimiter between access method and location */
1756 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1757 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1758 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1759 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1760 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1761 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1762 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1763 if (ret)
1764 bytesNeeded += size - sizeof(WCHAR);
1765 /* Need extra delimiter between access method entries */
1766 if (i < info->cAccDescr - 1)
1767 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1769 if (ret)
1771 if (!pbFormat)
1772 *pcbFormat = bytesNeeded;
1773 else if (*pcbFormat < bytesNeeded)
1775 *pcbFormat = bytesNeeded;
1776 SetLastError(ERROR_MORE_DATA);
1777 ret = FALSE;
1779 else
1781 LPWSTR str = pbFormat;
1782 DWORD altNameEntrySize;
1784 *pcbFormat = bytesNeeded;
1785 for (i = 0; ret && i < info->cAccDescr; i++)
1787 LPCSTR oidPtr;
1789 *str++ = '[';
1790 sprintfW(accessDescrNum, numFmt, i + 1);
1791 strcpyW(str, accessDescrNum);
1792 str += strlenW(accessDescrNum);
1793 *str++ = ']';
1794 strcpyW(str, aia);
1795 str += strlenW(aia);
1796 strcpyW(str, headingSep);
1797 str += strlenW(headingSep);
1798 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1800 strcpyW(str, indent);
1801 str += strlenW(indent);
1803 strcpyW(str, accessMethod);
1804 str += strlenW(accessMethod);
1805 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1806 szOID_PKIX_OCSP))
1808 strcpyW(str, ocsp);
1809 str += strlenW(ocsp);
1811 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1812 szOID_PKIX_CA_ISSUERS))
1814 strcpyW(str, caIssuers);
1815 str += strlenW(caIssuers);
1817 else
1819 strcpyW(str, unknown);
1820 str += strlenW(unknown);
1822 *str++ = ' ';
1823 *str++ = '(';
1824 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1825 *oidPtr; oidPtr++, str++)
1826 *str = *oidPtr;
1827 *str++ = ')';
1828 strcpyW(str, accessMethodSep);
1829 str += strlenW(accessMethodSep);
1830 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1832 strcpyW(str, indent);
1833 str += strlenW(indent);
1835 strcpyW(str, accessLocation);
1836 str += strlenW(accessLocation);
1837 strcpyW(str, locationSep);
1838 str += strlenW(locationSep);
1839 /* This overestimates the size available, but that
1840 * won't matter since we checked earlier whether enough
1841 * space for the entire string was available.
1843 altNameEntrySize = bytesNeeded;
1844 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1845 &info->rgAccDescr[i].AccessLocation, str,
1846 &altNameEntrySize);
1847 if (ret)
1848 str += altNameEntrySize / sizeof(WCHAR) - 1;
1849 if (i < info->cAccDescr - 1)
1851 strcpyW(str, accessMethodSep);
1852 str += strlenW(accessMethodSep);
1858 LocalFree(info);
1860 return ret;
1863 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1864 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1865 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1866 static WCHAR superseded[MAX_STRING_RESOURCE_LEN];
1867 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1868 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1870 struct reason_map_entry
1872 BYTE reasonBit;
1873 LPWSTR reason;
1874 int id;
1876 static struct reason_map_entry reason_map[] = {
1877 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1878 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1879 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1880 IDS_REASON_AFFILIATION_CHANGED },
1881 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED },
1882 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1883 IDS_REASON_CESSATION_OF_OPERATION },
1884 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1885 IDS_REASON_CERTIFICATE_HOLD },
1888 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1889 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1891 static const WCHAR sep[] = { ',',' ',0 };
1892 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1893 static BOOL stringsLoaded = FALSE;
1894 unsigned int i, numReasons = 0;
1895 BOOL ret = TRUE;
1896 DWORD bytesNeeded = sizeof(WCHAR);
1897 WCHAR bits[6];
1899 if (!stringsLoaded)
1901 for (i = 0; i < ARRAY_SIZE(reason_map); i++)
1902 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1903 MAX_STRING_RESOURCE_LEN);
1904 stringsLoaded = TRUE;
1906 /* No need to check reasonFlags->cbData, we already know it's positive.
1907 * Ignore any other bytes, as they're for undefined bits.
1909 for (i = 0; i < ARRAY_SIZE(reason_map); i++)
1911 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1913 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1914 if (numReasons++)
1915 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1918 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1919 bytesNeeded += strlenW(bits);
1920 if (!str)
1921 *pcbStr = bytesNeeded;
1922 else if (*pcbStr < bytesNeeded)
1924 *pcbStr = bytesNeeded;
1925 SetLastError(ERROR_MORE_DATA);
1926 ret = FALSE;
1928 else
1930 *pcbStr = bytesNeeded;
1931 for (i = 0; i < ARRAY_SIZE(reason_map); i++)
1933 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1935 strcpyW(str, reason_map[i].reason);
1936 str += strlenW(reason_map[i].reason);
1937 if (i < ARRAY_SIZE(reason_map) - 1 && numReasons)
1939 strcpyW(str, sep);
1940 str += strlenW(sep);
1944 strcpyW(str, bits);
1946 return ret;
1949 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1950 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1951 static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1952 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1953 static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1954 static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1956 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1957 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1959 DWORD *pcbFormat)
1961 CRL_DIST_POINTS_INFO *info;
1962 DWORD size;
1963 BOOL ret = FALSE;
1965 if (!cbEncoded)
1967 SetLastError(E_INVALIDARG);
1968 return FALSE;
1970 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1971 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1973 static const WCHAR numFmt[] = { '%','d',0 };
1974 static const WCHAR colon[] = { ':',0 };
1975 static BOOL stringsLoaded = FALSE;
1976 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1977 BOOL haveAnEntry = FALSE;
1978 LPCWSTR headingSep, nameSep;
1979 WCHAR distPointNum[11];
1980 DWORD i;
1982 if (!stringsLoaded)
1984 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint, ARRAY_SIZE(crlDistPoint));
1985 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName, ARRAY_SIZE(distPointName));
1986 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName, ARRAY_SIZE(fullName));
1987 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName, ARRAY_SIZE(rdnName));
1988 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason, ARRAY_SIZE(reason));
1989 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer, ARRAY_SIZE(issuer));
1990 stringsLoaded = TRUE;
1992 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1994 headingSep = crlf;
1995 nameSep = colonCrlf;
1997 else
1999 headingSep = colonSep;
2000 nameSep = colon;
2003 for (i = 0; ret && i < info->cDistPoint; i++)
2005 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
2007 if (distPoint->DistPointName.dwDistPointNameChoice !=
2008 CRL_DIST_POINT_NO_NAME)
2010 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
2011 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
2012 if (distPoint->DistPointName.dwDistPointNameChoice ==
2013 CRL_DIST_POINT_FULL_NAME)
2014 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
2015 else
2016 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
2017 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
2018 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2019 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR);
2020 /* The indent level (3) is higher than when used as the issuer,
2021 * because the name is subordinate to the name type (full vs.
2022 * RDN.)
2024 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
2025 &distPoint->DistPointName.u.FullName, NULL, &size);
2026 if (ret)
2027 bytesNeeded += size - sizeof(WCHAR);
2028 haveAnEntry = TRUE;
2030 else if (distPoint->ReasonFlags.cbData)
2032 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
2033 ret = CRYPT_FormatReason(dwFormatStrType,
2034 &distPoint->ReasonFlags, NULL, &size);
2035 if (ret)
2036 bytesNeeded += size - sizeof(WCHAR);
2037 haveAnEntry = TRUE;
2039 else if (distPoint->CRLIssuer.cAltEntry)
2041 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
2042 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
2043 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
2044 &distPoint->CRLIssuer, NULL, &size);
2045 if (ret)
2046 bytesNeeded += size - sizeof(WCHAR);
2047 haveAnEntry = TRUE;
2049 if (haveAnEntry)
2051 bytesNeeded += sizeof(WCHAR); /* left bracket */
2052 sprintfW(distPointNum, numFmt, i + 1);
2053 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
2054 bytesNeeded += sizeof(WCHAR); /* right bracket */
2055 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
2056 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
2057 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2058 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
2061 if (!haveAnEntry)
2063 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2065 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable));
2066 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2067 if (!pbFormat)
2068 *pcbFormat = bytesNeeded;
2069 else if (*pcbFormat < bytesNeeded)
2071 *pcbFormat = bytesNeeded;
2072 SetLastError(ERROR_MORE_DATA);
2073 ret = FALSE;
2075 else
2077 *pcbFormat = bytesNeeded;
2078 strcpyW(pbFormat, infoNotAvailable);
2081 else
2083 if (!pbFormat)
2084 *pcbFormat = bytesNeeded;
2085 else if (*pcbFormat < bytesNeeded)
2087 *pcbFormat = bytesNeeded;
2088 SetLastError(ERROR_MORE_DATA);
2089 ret = FALSE;
2091 else
2093 LPWSTR str = pbFormat;
2095 *pcbFormat = bytesNeeded;
2096 for (i = 0; ret && i < info->cDistPoint; i++)
2098 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
2100 *str++ = '[';
2101 sprintfW(distPointNum, numFmt, i + 1);
2102 strcpyW(str, distPointNum);
2103 str += strlenW(distPointNum);
2104 *str++ = ']';
2105 strcpyW(str, crlDistPoint);
2106 str += strlenW(crlDistPoint);
2107 strcpyW(str, headingSep);
2108 str += strlenW(headingSep);
2109 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2111 strcpyW(str, indent);
2112 str += strlenW(indent);
2114 if (distPoint->DistPointName.dwDistPointNameChoice !=
2115 CRL_DIST_POINT_NO_NAME)
2117 DWORD altNameSize = bytesNeeded;
2119 strcpyW(str, distPointName);
2120 str += strlenW(distPointName);
2121 strcpyW(str, nameSep);
2122 str += strlenW(nameSep);
2123 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2125 strcpyW(str, indent);
2126 str += strlenW(indent);
2127 strcpyW(str, indent);
2128 str += strlenW(indent);
2130 if (distPoint->DistPointName.dwDistPointNameChoice ==
2131 CRL_DIST_POINT_FULL_NAME)
2133 strcpyW(str, fullName);
2134 str += strlenW(fullName);
2136 else
2138 strcpyW(str, rdnName);
2139 str += strlenW(rdnName);
2141 strcpyW(str, nameSep);
2142 str += strlenW(nameSep);
2143 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
2144 &distPoint->DistPointName.u.FullName, str,
2145 &altNameSize);
2146 if (ret)
2147 str += altNameSize / sizeof(WCHAR) - 1;
2149 else if (distPoint->ReasonFlags.cbData)
2151 DWORD reasonSize = bytesNeeded;
2153 strcpyW(str, reason);
2154 str += strlenW(reason);
2155 ret = CRYPT_FormatReason(dwFormatStrType,
2156 &distPoint->ReasonFlags, str, &reasonSize);
2157 if (ret)
2158 str += reasonSize / sizeof(WCHAR) - 1;
2160 else if (distPoint->CRLIssuer.cAltEntry)
2162 DWORD crlIssuerSize = bytesNeeded;
2164 strcpyW(str, issuer);
2165 str += strlenW(issuer);
2166 strcpyW(str, nameSep);
2167 str += strlenW(nameSep);
2168 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
2169 &distPoint->CRLIssuer, str,
2170 &crlIssuerSize);
2171 if (ret)
2172 str += crlIssuerSize / sizeof(WCHAR) - 1;
2177 LocalFree(info);
2179 return ret;
2182 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
2183 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2184 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2185 DWORD *pcbFormat)
2187 CERT_ENHKEY_USAGE *usage;
2188 DWORD size;
2189 BOOL ret = FALSE;
2191 if (!cbEncoded)
2193 SetLastError(E_INVALIDARG);
2194 return FALSE;
2196 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
2197 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)))
2199 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
2200 DWORD i;
2201 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
2202 LPCWSTR sep;
2203 DWORD sepLen;
2205 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2207 sep = crlf;
2208 sepLen = strlenW(crlf) * sizeof(WCHAR);
2210 else
2212 sep = commaSpace;
2213 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2216 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown, ARRAY_SIZE(unknown));
2217 for (i = 0; i < usage->cUsageIdentifier; i++)
2219 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2220 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2222 if (info)
2223 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
2224 else
2225 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
2226 bytesNeeded += sizeof(WCHAR); /* space */
2227 bytesNeeded += sizeof(WCHAR); /* left paren */
2228 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
2229 sizeof(WCHAR);
2230 bytesNeeded += sizeof(WCHAR); /* right paren */
2231 if (i < usage->cUsageIdentifier - 1)
2232 bytesNeeded += sepLen;
2234 if (!pbFormat)
2235 *pcbFormat = bytesNeeded;
2236 else if (*pcbFormat < bytesNeeded)
2238 *pcbFormat = bytesNeeded;
2239 SetLastError(ERROR_MORE_DATA);
2240 ret = FALSE;
2242 else
2244 LPWSTR str = pbFormat;
2246 *pcbFormat = bytesNeeded;
2247 for (i = 0; i < usage->cUsageIdentifier; i++)
2249 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2250 usage->rgpszUsageIdentifier[i],
2251 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2252 LPCSTR oidPtr;
2254 if (info)
2256 strcpyW(str, info->pwszName);
2257 str += strlenW(info->pwszName);
2259 else
2261 strcpyW(str, unknown);
2262 str += strlenW(unknown);
2264 *str++ = ' ';
2265 *str++ = '(';
2266 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
2267 *str++ = *oidPtr;
2268 *str++ = ')';
2269 *str = 0;
2270 if (i < usage->cUsageIdentifier - 1)
2272 strcpyW(str, sep);
2273 str += sepLen / sizeof(WCHAR);
2277 LocalFree(usage);
2279 return ret;
2282 static struct BitToString netscapeCertTypeMap[] = {
2283 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } },
2284 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } },
2285 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } },
2286 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } },
2287 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } },
2288 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } },
2289 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },
2292 static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType,
2293 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2294 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2295 DWORD *pcbFormat)
2297 DWORD size;
2298 CRYPT_BIT_BLOB *bits;
2299 BOOL ret;
2301 if (!cbEncoded)
2303 SetLastError(E_INVALIDARG);
2304 return FALSE;
2306 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS,
2307 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
2309 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2310 DWORD bytesNeeded = sizeof(WCHAR);
2312 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable, ARRAY_SIZE(infoNotAvailable));
2313 if (!bits->cbData || bits->cbData > 1)
2315 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2316 if (!pbFormat)
2317 *pcbFormat = bytesNeeded;
2318 else if (*pcbFormat < bytesNeeded)
2320 *pcbFormat = bytesNeeded;
2321 SetLastError(ERROR_MORE_DATA);
2322 ret = FALSE;
2324 else
2326 LPWSTR str = pbFormat;
2328 *pcbFormat = bytesNeeded;
2329 strcpyW(str, infoNotAvailable);
2332 else
2334 static BOOL stringsLoaded = FALSE;
2335 unsigned int i;
2336 DWORD bitStringLen;
2337 BOOL first = TRUE;
2339 if (!stringsLoaded)
2341 for (i = 0; i < ARRAY_SIZE(netscapeCertTypeMap); i++)
2342 LoadStringW(hInstance, netscapeCertTypeMap[i].id,
2343 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN);
2344 stringsLoaded = TRUE;
2346 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, ARRAY_SIZE(netscapeCertTypeMap),
2347 NULL, &bitStringLen, &first);
2348 bytesNeeded += bitStringLen;
2349 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
2350 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2351 bits->cbData, NULL, &size);
2352 bytesNeeded += size;
2353 if (!pbFormat)
2354 *pcbFormat = bytesNeeded;
2355 else if (*pcbFormat < bytesNeeded)
2357 *pcbFormat = bytesNeeded;
2358 SetLastError(ERROR_MORE_DATA);
2359 ret = FALSE;
2361 else
2363 LPWSTR str = pbFormat;
2365 bitStringLen = bytesNeeded;
2366 first = TRUE;
2367 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap, ARRAY_SIZE(netscapeCertTypeMap),
2368 str, &bitStringLen, &first);
2369 str += bitStringLen / sizeof(WCHAR) - 1;
2370 *str++ = ' ';
2371 *str++ = '(';
2372 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2373 bits->cbData, str, &size);
2374 str += size / sizeof(WCHAR) - 1;
2375 *str++ = ')';
2376 *str = 0;
2379 LocalFree(bits);
2381 return ret;
2384 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
2385 static WCHAR available[MAX_STRING_RESOURCE_LEN];
2386 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
2387 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
2388 static WCHAR yes[MAX_STRING_RESOURCE_LEN];
2389 static WCHAR no[MAX_STRING_RESOURCE_LEN];
2391 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
2392 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2393 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2394 DWORD *pcbFormat)
2396 SPC_FINANCIAL_CRITERIA criteria;
2397 DWORD size = sizeof(criteria);
2398 BOOL ret = FALSE;
2400 if (!cbEncoded)
2402 SetLastError(E_INVALIDARG);
2403 return FALSE;
2405 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
2406 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
2407 &size)))
2409 static BOOL stringsLoaded = FALSE;
2410 DWORD bytesNeeded = sizeof(WCHAR);
2411 LPCWSTR sep;
2412 DWORD sepLen;
2414 if (!stringsLoaded)
2416 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria, ARRAY_SIZE(financialCriteria));
2417 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available, ARRAY_SIZE(available));
2418 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE, notAvailable, ARRAY_SIZE(notAvailable));
2419 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA, meetsCriteria, ARRAY_SIZE(meetsCriteria));
2420 LoadStringW(hInstance, IDS_YES, yes, ARRAY_SIZE(yes));
2421 LoadStringW(hInstance, IDS_NO, no, ARRAY_SIZE(no));
2422 stringsLoaded = TRUE;
2424 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2426 sep = crlf;
2427 sepLen = strlenW(crlf) * sizeof(WCHAR);
2429 else
2431 sep = commaSpace;
2432 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2434 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
2435 if (criteria.fFinancialInfoAvailable)
2437 bytesNeeded += strlenW(available) * sizeof(WCHAR);
2438 bytesNeeded += sepLen;
2439 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
2440 if (criteria.fMeetsCriteria)
2441 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
2442 else
2443 bytesNeeded += strlenW(no) * sizeof(WCHAR);
2445 else
2446 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
2447 if (!pbFormat)
2448 *pcbFormat = bytesNeeded;
2449 else if (*pcbFormat < bytesNeeded)
2451 *pcbFormat = bytesNeeded;
2452 SetLastError(ERROR_MORE_DATA);
2453 ret = FALSE;
2455 else
2457 LPWSTR str = pbFormat;
2459 *pcbFormat = bytesNeeded;
2460 strcpyW(str, financialCriteria);
2461 str += strlenW(financialCriteria);
2462 if (criteria.fFinancialInfoAvailable)
2464 strcpyW(str, available);
2465 str += strlenW(available);
2466 strcpyW(str, sep);
2467 str += sepLen / sizeof(WCHAR);
2468 strcpyW(str, meetsCriteria);
2469 str += strlenW(meetsCriteria);
2470 if (criteria.fMeetsCriteria)
2471 strcpyW(str, yes);
2472 else
2473 strcpyW(str, no);
2475 else
2477 strcpyW(str, notAvailable);
2481 return ret;
2484 static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType,
2485 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2486 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2487 DWORD *pcbFormat)
2489 CERT_NAME_VALUE *value;
2490 DWORD size;
2491 BOOL ret;
2493 if (!cbEncoded)
2495 SetLastError(E_INVALIDARG);
2496 return FALSE;
2498 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
2499 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size)))
2501 if (!pbFormat)
2502 *pcbFormat = value->Value.cbData;
2503 else if (*pcbFormat < value->Value.cbData)
2505 *pcbFormat = value->Value.cbData;
2506 SetLastError(ERROR_MORE_DATA);
2507 ret = FALSE;
2509 else
2511 LPWSTR str = pbFormat;
2513 *pcbFormat = value->Value.cbData;
2514 strcpyW(str, (LPWSTR)value->Value.pbData);
2517 return ret;
2520 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
2521 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
2523 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
2524 DWORD formatStrType, LPCSTR lpszStructType)
2526 CryptFormatObjectFunc format = NULL;
2528 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
2530 SetLastError(ERROR_FILE_NOT_FOUND);
2531 return NULL;
2533 if (IS_INTOID(lpszStructType))
2535 switch (LOWORD(lpszStructType))
2537 case LOWORD(X509_KEY_USAGE):
2538 format = CRYPT_FormatKeyUsage;
2539 break;
2540 case LOWORD(X509_ALTERNATE_NAME):
2541 format = CRYPT_FormatAltName;
2542 break;
2543 case LOWORD(X509_BASIC_CONSTRAINTS2):
2544 format = CRYPT_FormatBasicConstraints2;
2545 break;
2546 case LOWORD(X509_AUTHORITY_KEY_ID2):
2547 format = CRYPT_FormatAuthorityKeyId2;
2548 break;
2549 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
2550 format = CRYPT_FormatAuthorityInfoAccess;
2551 break;
2552 case LOWORD(X509_CRL_DIST_POINTS):
2553 format = CRYPT_FormatCRLDistPoints;
2554 break;
2555 case LOWORD(X509_ENHANCED_KEY_USAGE):
2556 format = CRYPT_FormatEnhancedKeyUsage;
2557 break;
2558 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
2559 format = CRYPT_FormatSpcFinancialCriteria;
2560 break;
2563 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2564 format = CRYPT_FormatAltName;
2565 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2566 format = CRYPT_FormatAltName;
2567 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2568 format = CRYPT_FormatKeyUsage;
2569 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2570 format = CRYPT_FormatAltName;
2571 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2572 format = CRYPT_FormatAltName;
2573 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2574 format = CRYPT_FormatBasicConstraints2;
2575 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
2576 format = CRYPT_FormatAuthorityInfoAccess;
2577 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
2578 format = CRYPT_FormatAuthorityKeyId2;
2579 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2580 format = CRYPT_FormatCRLDistPoints;
2581 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2582 format = CRYPT_FormatEnhancedKeyUsage;
2583 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE))
2584 format = CRYPT_FormatNetscapeCertType;
2585 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) ||
2586 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) ||
2587 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) ||
2588 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) ||
2589 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) ||
2590 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) ||
2591 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT))
2592 format = CRYPT_FormatUnicodeString;
2593 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
2594 format = CRYPT_FormatSpcFinancialCriteria;
2595 return format;
2598 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
2599 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
2600 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
2602 CryptFormatObjectFunc format = NULL;
2603 HCRYPTOIDFUNCADDR hFunc = NULL;
2604 BOOL ret = FALSE;
2606 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
2607 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
2608 pbEncoded, cbEncoded, pbFormat, pcbFormat);
2610 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
2611 dwFormatStrType, lpszStructType)))
2613 static HCRYPTOIDFUNCSET set = NULL;
2615 if (!set)
2616 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
2617 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2618 (void **)&format, &hFunc);
2620 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) ==
2621 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
2622 format = CRYPT_FormatHexString;
2623 if (format)
2624 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
2625 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
2626 pcbFormat);
2627 if (hFunc)
2628 CryptFreeOIDFunctionAddress(hFunc, 0);
2629 return ret;