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
21 #define NONAMELESSUNION
27 #include "crypt32_private.h"
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
34 static BOOL
CRYPT_ReadBlobFromFile(LPCWSTR fileName
, PCERT_BLOB blob
)
39 TRACE("%s\n", debugstr_w(fileName
));
41 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
42 OPEN_EXISTING
, 0, NULL
);
43 if (file
!= INVALID_HANDLE_VALUE
)
46 blob
->cbData
= GetFileSize(file
, NULL
);
49 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
54 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
);
59 TRACE("returning %d\n", ret
);
63 static BOOL
CRYPT_QueryContextObject(DWORD dwObjectType
, const void *pvObject
,
64 DWORD dwExpectedContentTypeFlags
, DWORD
*pdwMsgAndCertEncodingType
,
65 DWORD
*pdwContentType
, HCERTSTORE
*phCertStore
, const void **ppvContext
)
68 const CERT_BLOB
*blob
;
75 case CERT_QUERY_OBJECT_FILE
:
76 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
77 * just read the file directly
79 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
82 case CERT_QUERY_OBJECT_BLOB
:
83 blob
= (const CERT_BLOB
*)pvObject
;
87 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
93 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
94 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
96 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
)
98 ret
= pCertInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
99 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
101 contentType
= CERT_QUERY_CONTENT_CERT
;
103 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
))
105 ret
= pCRLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
106 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
108 contentType
= CERT_QUERY_CONTENT_CRL
;
110 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
112 ret
= pCTLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
113 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
115 contentType
= CERT_QUERY_CONTENT_CTL
;
119 if (pdwMsgAndCertEncodingType
)
120 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
122 *pdwContentType
= contentType
;
124 *phCertStore
= CertDuplicateStore(store
);
126 CertCloseStore(store
, 0);
127 if (blob
== &fileBlob
)
128 CryptMemFree(blob
->pbData
);
129 TRACE("returning %d\n", ret
);
133 static BOOL
CRYPT_QuerySerializedContextObject(DWORD dwObjectType
,
134 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
135 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
136 HCERTSTORE
*phCertStore
, const void **ppvContext
)
139 const CERT_BLOB
*blob
;
140 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
145 switch (dwObjectType
)
147 case CERT_QUERY_OBJECT_FILE
:
148 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
149 * just read the file directly
151 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
154 case CERT_QUERY_OBJECT_BLOB
:
155 blob
= (const CERT_BLOB
*)pvObject
;
159 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
165 context
= CRYPT_ReadSerializedElement(blob
->pbData
, blob
->cbData
,
166 CERT_STORE_ALL_CONTEXT_FLAG
, &contextType
);
169 DWORD contentType
, certStoreOffset
;
174 case CERT_STORE_CERTIFICATE_CONTEXT
:
175 contextInterface
= pCertInterface
;
176 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CERT
;
177 certStoreOffset
= offsetof(CERT_CONTEXT
, hCertStore
);
178 if (!(dwExpectedContentTypeFlags
&
179 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
))
181 SetLastError(ERROR_INVALID_DATA
);
186 case CERT_STORE_CRL_CONTEXT
:
187 contextInterface
= pCRLInterface
;
188 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CRL
;
189 certStoreOffset
= offsetof(CRL_CONTEXT
, hCertStore
);
190 if (!(dwExpectedContentTypeFlags
&
191 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
))
193 SetLastError(ERROR_INVALID_DATA
);
198 case CERT_STORE_CTL_CONTEXT
:
199 contextInterface
= pCTLInterface
;
200 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CTL
;
201 certStoreOffset
= offsetof(CTL_CONTEXT
, hCertStore
);
202 if (!(dwExpectedContentTypeFlags
&
203 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
))
205 SetLastError(ERROR_INVALID_DATA
);
211 SetLastError(ERROR_INVALID_DATA
);
215 if (pdwMsgAndCertEncodingType
)
216 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
218 *pdwContentType
= contentType
;
220 *phCertStore
= CertDuplicateStore(
221 *(HCERTSTORE
*)((const BYTE
*)context
+ certStoreOffset
));
223 *ppvContext
= contextInterface
->duplicate(context
);
227 if (contextInterface
&& context
)
228 contextInterface
->free(context
);
229 if (blob
== &fileBlob
)
230 CryptMemFree(blob
->pbData
);
231 TRACE("returning %d\n", ret
);
235 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
236 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
237 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
239 LPCWSTR fileName
= (LPCWSTR
)pvObject
;
243 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
245 FIXME("unimplemented for non-file type %d\n", dwObjectType
);
246 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
249 TRACE("%s\n", debugstr_w(fileName
));
250 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
251 OPEN_EXISTING
, 0, NULL
);
252 if (file
!= INVALID_HANDLE_VALUE
)
254 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
255 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
257 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
260 if (pdwMsgAndCertEncodingType
)
261 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
263 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
265 *phCertStore
= CertDuplicateStore(store
);
267 CertCloseStore(store
, 0);
270 TRACE("returning %d\n", ret
);
274 /* Used to decode non-embedded messages */
275 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
276 DWORD dwExpectedContentTypeFlags
, DWORD
*pdwMsgAndCertEncodingType
,
277 DWORD
*pdwContentType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
280 const CERT_BLOB
*blob
;
282 HCRYPTMSG msg
= NULL
;
283 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
285 switch (dwObjectType
)
287 case CERT_QUERY_OBJECT_FILE
:
288 /* This isn't an embedded PKCS7 message, so just read the file
291 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
294 case CERT_QUERY_OBJECT_BLOB
:
295 blob
= (const CERT_BLOB
*)pvObject
;
299 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
306 /* Try it first as a PKCS content info */
307 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
308 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
310 msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
);
313 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
316 DWORD type
, len
= sizeof(type
);
318 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
321 if ((dwExpectedContentTypeFlags
&
322 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
324 if (type
!= CMSG_SIGNED
)
326 SetLastError(ERROR_INVALID_DATA
);
329 else if (pdwContentType
)
330 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
332 else if ((dwExpectedContentTypeFlags
&
333 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
335 if (type
!= CMSG_DATA
)
337 SetLastError(ERROR_INVALID_DATA
);
340 else if (pdwContentType
)
341 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
352 /* Failing that, try explicitly typed messages */
354 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
356 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
, NULL
);
359 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
366 if (msg
&& pdwContentType
)
367 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
370 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
372 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0, NULL
, NULL
);
375 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
382 if (msg
&& pdwContentType
)
383 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
385 if (pdwMsgAndCertEncodingType
)
386 *pdwMsgAndCertEncodingType
= encodingType
;
392 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
395 if (blob
== &fileBlob
)
396 CryptMemFree(blob
->pbData
);
397 TRACE("returning %d\n", ret
);
401 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
402 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
403 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
404 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
410 TRACE("%s\n", debugstr_w((LPCWSTR
)pvObject
));
412 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
414 FIXME("don't know what to do for type %d embedded signed messages\n",
416 SetLastError(E_INVALIDARG
);
419 file
= CreateFileW((LPCWSTR
)pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
420 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
421 if (file
!= INVALID_HANDLE_VALUE
)
423 ret
= CryptSIPRetrieveSubjectGuid((LPCWSTR
)pvObject
, file
, &subject
);
426 SIP_DISPATCH_INFO sip
;
428 memset(&sip
, 0, sizeof(sip
));
429 sip
.cbSize
= sizeof(sip
);
430 ret
= CryptSIPLoad(&subject
, 0, &sip
);
433 SIP_SUBJECTINFO subjectInfo
;
437 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
438 subjectInfo
.cbSize
= sizeof(subjectInfo
);
439 subjectInfo
.pgSubjectType
= &subject
;
440 subjectInfo
.hFile
= file
;
441 subjectInfo
.pwsFileName
= (LPCWSTR
)pvObject
;
442 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
446 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
449 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
450 &blob
.cbData
, blob
.pbData
);
453 ret
= CRYPT_QueryMessageObject(
454 CERT_QUERY_OBJECT_BLOB
, &blob
,
455 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
456 pdwMsgAndCertEncodingType
, NULL
, phCertStore
,
458 if (ret
&& pdwContentType
)
460 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
462 CryptMemFree(blob
.pbData
);
466 SetLastError(ERROR_OUTOFMEMORY
);
474 TRACE("returning %d\n", ret
);
478 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
479 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
480 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
481 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
482 const void **ppvContext
)
484 static const DWORD unimplementedTypes
=
485 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
486 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
489 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
490 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
491 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
492 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
494 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
495 WARN("unimplemented for types %08x\n",
496 dwExpectedContentTypeFlags
& unimplementedTypes
);
497 if (!(dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
))
499 FIXME("unimplemented for anything but binary\n");
500 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
504 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
514 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
515 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
516 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
518 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
519 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
520 phCertStore
, ppvContext
);
523 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
525 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
526 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
529 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
530 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
531 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
533 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
534 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
535 phCertStore
, ppvContext
);
538 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
539 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
541 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
542 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
546 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
548 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
549 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
552 TRACE("returning %d\n", ret
);
556 static BOOL WINAPI
CRYPT_FormatHexString(DWORD dwCertEncodingType
,
557 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
558 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
565 bytesNeeded
= (cbEncoded
* 3) * sizeof(WCHAR
);
567 bytesNeeded
= sizeof(WCHAR
);
570 *pcbFormat
= bytesNeeded
;
573 else if (*pcbFormat
< bytesNeeded
)
575 *pcbFormat
= bytesNeeded
;
576 SetLastError(ERROR_MORE_DATA
);
581 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
582 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
584 LPWSTR ptr
= pbFormat
;
586 *pcbFormat
= bytesNeeded
;
589 for (i
= 0; i
< cbEncoded
; i
++)
591 if (i
< cbEncoded
- 1)
592 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
594 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
604 #define MAX_STRING_RESOURCE_LEN 128
606 static BOOL
CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB
*blob
, int id
,
607 LPWSTR str
, DWORD
*pcbStr
)
609 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
613 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
614 CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
615 blob
->pbData
, blob
->cbData
, NULL
, &bytesNeeded
);
616 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
619 *pcbStr
= bytesNeeded
;
622 else if (*pcbStr
< bytesNeeded
)
624 *pcbStr
= bytesNeeded
;
625 SetLastError(ERROR_MORE_DATA
);
630 *pcbStr
= bytesNeeded
;
633 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
634 ret
= CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
635 blob
->pbData
, blob
->cbData
, str
, &bytesNeeded
);
640 static BOOL
CRYPT_FormatKeyId(CRYPT_DATA_BLOB
*keyId
, LPWSTR str
,
643 return CRYPT_FormatHexStringWithPrefix(keyId
, IDS_KEY_ID
, str
, pcbStr
);
646 static BOOL
CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB
*serialNum
, LPWSTR str
,
649 return CRYPT_FormatHexStringWithPrefix(serialNum
, IDS_CERT_SERIAL_NUMBER
,
653 static const WCHAR crlf
[] = { '\r','\n',0 };
655 static BOOL
CRYPT_FormatAltNameEntry(DWORD dwFormatStrType
,
656 CERT_ALT_NAME_ENTRY
*entry
, LPWSTR str
, DWORD
*pcbStr
)
659 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
660 WCHAR mask
[MAX_STRING_RESOURCE_LEN
];
663 DWORD bytesNeeded
= sizeof(WCHAR
);
665 switch (entry
->dwAltNameChoice
)
667 case CERT_ALT_NAME_RFC822_NAME
:
668 LoadStringW(hInstance
, IDS_ALT_NAME_RFC822_NAME
, buf
,
669 sizeof(buf
) / sizeof(buf
[0]));
670 bytesNeeded
+= strlenW(entry
->u
.pwszRfc822Name
) * sizeof(WCHAR
);
673 case CERT_ALT_NAME_DNS_NAME
:
674 LoadStringW(hInstance
, IDS_ALT_NAME_DNS_NAME
, buf
,
675 sizeof(buf
) / sizeof(buf
[0]));
676 bytesNeeded
+= strlenW(entry
->u
.pwszDNSName
) * sizeof(WCHAR
);
679 case CERT_ALT_NAME_URL
:
680 LoadStringW(hInstance
, IDS_ALT_NAME_URL
, buf
,
681 sizeof(buf
) / sizeof(buf
[0]));
682 bytesNeeded
+= strlenW(entry
->u
.pwszURL
) * sizeof(WCHAR
);
685 case CERT_ALT_NAME_IP_ADDRESS
:
687 static const WCHAR ipAddrWithMaskFmt
[] = { '%','d','.','%','d','.',
688 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
690 static const WCHAR ipAddrFmt
[] = { '%','d','.','%','d','.','%','d',
693 LoadStringW(hInstance
, IDS_ALT_NAME_IP_ADDRESS
, buf
,
694 sizeof(buf
) / sizeof(buf
[0]));
695 if (entry
->u
.IPAddress
.cbData
== 8)
697 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
699 LoadStringW(hInstance
, IDS_ALT_NAME_MASK
, mask
,
700 sizeof(mask
) / sizeof(mask
[0]));
701 bytesNeeded
+= strlenW(mask
) * sizeof(WCHAR
);
702 sprintfW(ipAddrBuf
, ipAddrFmt
,
703 entry
->u
.IPAddress
.pbData
[0],
704 entry
->u
.IPAddress
.pbData
[1],
705 entry
->u
.IPAddress
.pbData
[2],
706 entry
->u
.IPAddress
.pbData
[3]);
707 bytesNeeded
+= strlenW(ipAddrBuf
) * sizeof(WCHAR
);
708 sprintfW(maskBuf
, ipAddrFmt
,
709 entry
->u
.IPAddress
.pbData
[4],
710 entry
->u
.IPAddress
.pbData
[5],
711 entry
->u
.IPAddress
.pbData
[6],
712 entry
->u
.IPAddress
.pbData
[7]);
713 bytesNeeded
+= strlenW(maskBuf
) * sizeof(WCHAR
);
714 bytesNeeded
+= strlenW(crlf
) * sizeof(WCHAR
);
718 sprintfW(ipAddrBuf
, ipAddrWithMaskFmt
,
719 entry
->u
.IPAddress
.pbData
[0],
720 entry
->u
.IPAddress
.pbData
[1],
721 entry
->u
.IPAddress
.pbData
[2],
722 entry
->u
.IPAddress
.pbData
[3],
723 entry
->u
.IPAddress
.pbData
[4],
724 entry
->u
.IPAddress
.pbData
[5],
725 entry
->u
.IPAddress
.pbData
[6],
726 entry
->u
.IPAddress
.pbData
[7]);
727 bytesNeeded
+= (strlenW(ipAddrBuf
) + 1) * sizeof(WCHAR
);
733 FIXME("unknown IP address format (%d bytes)\n",
734 entry
->u
.IPAddress
.cbData
);
740 FIXME("unimplemented for %d\n", entry
->dwAltNameChoice
);
745 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
747 *pcbStr
= bytesNeeded
;
748 else if (*pcbStr
< bytesNeeded
)
750 *pcbStr
= bytesNeeded
;
751 SetLastError(ERROR_MORE_DATA
);
756 *pcbStr
= bytesNeeded
;
759 switch (entry
->dwAltNameChoice
)
761 case CERT_ALT_NAME_RFC822_NAME
:
762 case CERT_ALT_NAME_DNS_NAME
:
763 case CERT_ALT_NAME_URL
:
764 strcpyW(str
, entry
->u
.pwszURL
);
766 case CERT_ALT_NAME_IP_ADDRESS
:
767 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
769 strcpyW(str
, ipAddrBuf
);
770 str
+= strlenW(ipAddrBuf
);
772 str
+= strlenW(crlf
);
774 str
+= strlenW(mask
);
775 strcpyW(str
, maskBuf
);
778 strcpyW(str
, ipAddrBuf
);
786 static const WCHAR commaSpace
[] = { ',',' ',0 };
788 static BOOL
CRYPT_FormatAltNameInfo(DWORD dwFormatStrType
,
789 CERT_ALT_NAME_INFO
*name
, LPWSTR str
, DWORD
*pcbStr
)
791 DWORD i
, size
, bytesNeeded
= 0;
796 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
799 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
804 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
807 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
809 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, &name
->rgAltEntry
[i
],
813 bytesNeeded
+= size
- sizeof(WCHAR
);
814 if (i
< name
->cAltEntry
- 1)
815 bytesNeeded
+= sepLen
;
820 bytesNeeded
+= sizeof(WCHAR
);
822 *pcbStr
= bytesNeeded
;
823 else if (*pcbStr
< bytesNeeded
)
825 *pcbStr
= bytesNeeded
;
826 SetLastError(ERROR_MORE_DATA
);
831 *pcbStr
= bytesNeeded
;
832 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
834 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
,
835 &name
->rgAltEntry
[i
], str
, &size
);
838 str
+= size
/ sizeof(WCHAR
) - 1;
839 if (i
< name
->cAltEntry
- 1)
842 str
+= sepLen
/ sizeof(WCHAR
);
851 static BOOL
CRYPT_FormatCertIssuer(DWORD dwFormatStrType
,
852 CERT_ALT_NAME_INFO
*issuer
, LPWSTR str
, DWORD
*pcbStr
)
854 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
858 LoadStringW(hInstance
, IDS_CERT_ISSUER
, buf
, sizeof(buf
) / sizeof(buf
[0]));
859 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, issuer
, NULL
, &bytesNeeded
);
860 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
864 *pcbStr
= bytesNeeded
;
865 else if (*pcbStr
< bytesNeeded
)
867 *pcbStr
= bytesNeeded
;
868 SetLastError(ERROR_MORE_DATA
);
873 *pcbStr
= bytesNeeded
;
876 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
877 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, issuer
, str
,
884 static BOOL WINAPI
CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType
,
885 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
886 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
889 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
895 SetLastError(E_INVALIDARG
);
898 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_AUTHORITY_KEY_ID2
,
899 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
901 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
904 BOOL needSeparator
= FALSE
;
906 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
909 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
914 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
917 if (info
->KeyId
.cbData
)
919 needSeparator
= TRUE
;
920 ret
= CRYPT_FormatKeyId(&info
->KeyId
, NULL
, &size
);
923 /* don't include NULL-terminator more than once */
924 bytesNeeded
+= size
- sizeof(WCHAR
);
927 if (info
->AuthorityCertIssuer
.cAltEntry
)
930 bytesNeeded
+= sepLen
;
931 needSeparator
= TRUE
;
932 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
933 &info
->AuthorityCertIssuer
, NULL
, &size
);
936 /* don't include NULL-terminator more than once */
937 bytesNeeded
+= size
- sizeof(WCHAR
);
940 if (info
->AuthorityCertSerialNumber
.cbData
)
943 bytesNeeded
+= sepLen
;
944 ret
= CRYPT_FormatCertSerialNumber(
945 &info
->AuthorityCertSerialNumber
, NULL
, &size
);
948 /* don't include NULL-terminator more than once */
949 bytesNeeded
+= size
- sizeof(WCHAR
);
955 *pcbFormat
= bytesNeeded
;
956 else if (*pcbFormat
< bytesNeeded
)
958 *pcbFormat
= bytesNeeded
;
959 SetLastError(ERROR_MORE_DATA
);
964 LPWSTR str
= pbFormat
;
966 *pcbFormat
= bytesNeeded
;
967 needSeparator
= FALSE
;
968 if (info
->KeyId
.cbData
)
970 needSeparator
= TRUE
;
971 ret
= CRYPT_FormatKeyId(&info
->KeyId
, str
, &size
);
973 str
+= size
/ sizeof(WCHAR
);
975 if (info
->AuthorityCertIssuer
.cAltEntry
)
980 str
+= sepLen
/ sizeof(WCHAR
);
982 needSeparator
= TRUE
;
983 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
984 &info
->AuthorityCertIssuer
, str
, &size
);
986 str
+= size
/ sizeof(WCHAR
);
988 if (info
->AuthorityCertSerialNumber
.cbData
)
993 str
+= sepLen
/ sizeof(WCHAR
);
995 ret
= CRYPT_FormatCertSerialNumber(
996 &info
->AuthorityCertSerialNumber
, str
, &size
);
1005 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
1006 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
1008 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
1009 DWORD formatStrType
, LPCSTR lpszStructType
)
1011 CryptFormatObjectFunc format
= NULL
;
1013 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
1015 SetLastError(ERROR_FILE_NOT_FOUND
);
1018 if (!HIWORD(lpszStructType
))
1020 switch (LOWORD(lpszStructType
))
1022 case LOWORD(X509_AUTHORITY_KEY_ID2
):
1023 format
= CRYPT_FormatAuthorityKeyId2
;
1027 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
1028 format
= CRYPT_FormatAuthorityKeyId2
;
1029 if (!format
&& !(formatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
1030 format
= CRYPT_FormatHexString
;
1034 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
1035 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
1036 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
1038 CryptFormatObjectFunc format
= NULL
;
1039 HCRYPTOIDFUNCADDR hFunc
= NULL
;
1042 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
1043 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
1044 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
1046 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
1047 dwFormatStrType
, lpszStructType
)))
1049 static HCRYPTOIDFUNCSET set
= NULL
;
1052 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
1053 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
1054 (void **)&format
, &hFunc
);
1057 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
1058 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
1061 CryptFreeOIDFunctionAddress(hFunc
, 0);