2 * Copyright 2004-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
26 #include "wine/debug.h"
27 #include "wine/exception.h"
28 #include "crypt32_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
32 /* An extended certificate property in serialized form is prefixed by this
35 typedef struct _WINE_CERT_PROP_HEADER
38 DWORD unknown
; /* always 1 */
40 } WINE_CERT_PROP_HEADER
, *PWINE_CERT_PROP_HEADER
;
42 static BOOL
CRYPT_SerializeStoreElement(const void *context
,
43 const BYTE
*encodedContext
, DWORD cbEncodedContext
, DWORD contextPropID
,
44 PCWINE_CONTEXT_INTERFACE contextInterface
, DWORD dwFlags
, BOOL omitHashes
,
45 BYTE
*pbElement
, DWORD
*pcbElement
)
49 TRACE("(%p, %p, %08x, %d, %p, %p)\n", context
, contextInterface
, dwFlags
,
50 omitHashes
, pbElement
, pcbElement
);
54 DWORD bytesNeeded
= sizeof(WINE_CERT_PROP_HEADER
) + cbEncodedContext
;
59 prop
= contextInterface
->enumProps(context
, prop
);
60 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
64 ret
= contextInterface
->getProp(context
, prop
, NULL
, &propSize
);
66 bytesNeeded
+= sizeof(WINE_CERT_PROP_HEADER
) + propSize
;
68 } while (ret
&& prop
!= 0);
72 *pcbElement
= bytesNeeded
;
75 else if (*pcbElement
< bytesNeeded
)
77 *pcbElement
= bytesNeeded
;
78 SetLastError(ERROR_MORE_DATA
);
83 PWINE_CERT_PROP_HEADER hdr
;
89 prop
= contextInterface
->enumProps(context
, prop
);
90 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
94 ret
= contextInterface
->getProp(context
, prop
, NULL
,
98 if (bufSize
< propSize
)
101 buf
= CryptMemRealloc(buf
, propSize
);
103 buf
= CryptMemAlloc(propSize
);
108 ret
= contextInterface
->getProp(context
, prop
, buf
,
112 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
116 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
119 memcpy(pbElement
, buf
, propSize
);
120 pbElement
+= propSize
;
128 } while (ret
&& prop
!= 0);
131 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
132 hdr
->propID
= contextPropID
;
134 hdr
->cb
= cbEncodedContext
;
135 memcpy(pbElement
+ sizeof(WINE_CERT_PROP_HEADER
),
136 encodedContext
, cbEncodedContext
);
144 BOOL WINAPI
CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext
,
145 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
147 return CRYPT_SerializeStoreElement(pCertContext
,
148 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
149 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
152 BOOL WINAPI
CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext
,
153 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
155 return CRYPT_SerializeStoreElement(pCrlContext
,
156 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
157 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
160 BOOL WINAPI
CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext
,
161 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
163 return CRYPT_SerializeStoreElement(pCtlContext
,
164 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
165 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
168 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
169 * to its header if a valid header is found, NULL if not. Valid means the
170 * length of thte property won't overrun buf, and the unknown field is 1.
172 static const WINE_CERT_PROP_HEADER
*CRYPT_findPropID(const BYTE
*buf
,
173 DWORD size
, DWORD propID
)
175 const WINE_CERT_PROP_HEADER
*ret
= NULL
;
178 while (size
&& !ret
&& !done
)
180 if (size
< sizeof(WINE_CERT_PROP_HEADER
))
182 SetLastError(CRYPT_E_FILE_ERROR
);
187 const WINE_CERT_PROP_HEADER
*hdr
=
188 (const WINE_CERT_PROP_HEADER
*)buf
;
190 size
-= sizeof(WINE_CERT_PROP_HEADER
);
191 buf
+= sizeof(WINE_CERT_PROP_HEADER
);
194 SetLastError(E_INVALIDARG
);
197 else if (!hdr
->propID
)
199 /* assume a zero prop ID means the data are uninitialized, so
204 else if (hdr
->unknown
!= 1)
206 SetLastError(ERROR_FILE_NOT_FOUND
);
209 else if (hdr
->propID
== propID
)
221 static BOOL
CRYPT_ReadContextProp(
222 const WINE_CONTEXT_INTERFACE
*contextInterface
, const void *context
,
223 const WINE_CERT_PROP_HEADER
*hdr
, const BYTE
*pbElement
, DWORD cbElement
)
227 if (cbElement
< hdr
->cb
)
229 SetLastError(E_INVALIDARG
);
232 else if (hdr
->unknown
!= 1)
234 SetLastError(ERROR_FILE_NOT_FOUND
);
237 else if (hdr
->propID
!= CERT_CERT_PROP_ID
&&
238 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!= CERT_CTL_PROP_ID
)
240 /* Have to create a blob for most types, but not
245 case CERT_AUTO_ENROLL_PROP_ID
:
246 case CERT_CTL_USAGE_PROP_ID
:
247 case CERT_DESCRIPTION_PROP_ID
:
248 case CERT_FRIENDLY_NAME_PROP_ID
:
249 case CERT_HASH_PROP_ID
:
250 case CERT_KEY_IDENTIFIER_PROP_ID
:
251 case CERT_MD5_HASH_PROP_ID
:
252 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
253 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
254 case CERT_PVK_FILE_PROP_ID
:
255 case CERT_SIGNATURE_HASH_PROP_ID
:
256 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
257 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
258 case CERT_ENROLLMENT_PROP_ID
:
259 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
260 case CERT_RENEWAL_PROP_ID
:
262 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
265 ret
= contextInterface
->setProp(context
,
266 hdr
->propID
, 0, &blob
);
269 case CERT_DATE_STAMP_PROP_ID
:
270 ret
= contextInterface
->setProp(context
,
271 hdr
->propID
, 0, pbElement
);
273 case CERT_KEY_PROV_INFO_PROP_ID
:
275 PCRYPT_KEY_PROV_INFO info
=
276 (PCRYPT_KEY_PROV_INFO
)pbElement
;
278 CRYPT_FixKeyProvInfoPointers(info
);
279 ret
= contextInterface
->setProp(context
,
280 hdr
->propID
, 0, pbElement
);
289 /* ignore the context itself */
295 const void *CRYPT_ReadSerializedElement(const BYTE
*pbElement
, DWORD cbElement
,
296 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
300 TRACE("(%p, %d, %08x, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
305 SetLastError(ERROR_END_OF_MEDIA
);
311 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
312 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
318 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
320 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
322 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
325 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
327 type
= CERT_STORE_CRL_CONTEXT
;
330 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
333 type
= CERT_STORE_CTL_CONTEXT
;
337 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
339 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
340 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
342 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
344 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
345 type
= CERT_STORE_CRL_CONTEXT
;
347 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
349 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
350 type
= CERT_STORE_CTL_CONTEXT
;
355 case CERT_STORE_CERTIFICATE_CONTEXT
:
356 contextInterface
= pCertInterface
;
358 case CERT_STORE_CRL_CONTEXT
:
359 contextInterface
= pCRLInterface
;
361 case CERT_STORE_CTL_CONTEXT
:
362 contextInterface
= pCTLInterface
;
365 SetLastError(E_INVALIDARG
);
372 context
= contextInterface
->create(X509_ASN_ENCODING
,
373 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
376 BOOL noMoreProps
= FALSE
;
378 while (!noMoreProps
&& ret
)
380 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
384 const WINE_CERT_PROP_HEADER
*hdr
=
385 (const WINE_CERT_PROP_HEADER
*)pbElement
;
387 TRACE("prop is %d\n", hdr
->propID
);
388 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
389 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
392 /* Like in CRYPT_findPropID, stop if the propID is zero
397 ret
= CRYPT_ReadContextProp(contextInterface
, context
,
398 hdr
, pbElement
, cbElement
);
399 pbElement
+= hdr
->cb
;
400 cbElement
-= hdr
->cb
;
408 *pdwContentType
= type
;
412 contextInterface
->free(context
);
419 SetLastError(STATUS_ACCESS_VIOLATION
);
426 static const BYTE fileHeader
[] = { 0, 0, 0, 0, 'C','E','R','T' };
428 typedef BOOL (*read_serialized_func
)(void *handle
, void *buffer
,
429 DWORD bytesToRead
, DWORD
*bytesRead
);
431 static BOOL
CRYPT_ReadSerializedStore(void *handle
,
432 read_serialized_func read_func
, HCERTSTORE store
)
434 BYTE fileHeaderBuf
[sizeof(fileHeader
)];
438 /* Failure reading is non-critical, we'll leave the store empty */
439 ret
= read_func(handle
, fileHeaderBuf
, sizeof(fileHeaderBuf
), &read
);
443 ; /* an empty file is okay */
444 else if (read
!= sizeof(fileHeaderBuf
))
446 else if (!memcmp(fileHeaderBuf
, fileHeader
, read
))
448 WINE_CERT_PROP_HEADER propHdr
;
449 const void *context
= NULL
;
450 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
455 ret
= read_func(handle
, &propHdr
, sizeof(propHdr
), &read
);
456 if (ret
&& read
== sizeof(propHdr
))
458 if (contextInterface
&& context
&&
459 (propHdr
.propID
== CERT_CERT_PROP_ID
||
460 propHdr
.propID
== CERT_CRL_PROP_ID
||
461 propHdr
.propID
== CERT_CTL_PROP_ID
))
463 /* We have a new context, so free the existing one */
464 contextInterface
->free(context
);
466 if (propHdr
.cb
> bufSize
)
468 /* Not reusing realloc, because the old data aren't
472 buf
= CryptMemAlloc(propHdr
.cb
);
473 bufSize
= propHdr
.cb
;
476 ; /* Property is empty, nothing to do */
479 ret
= read_func(handle
, buf
, propHdr
.cb
, &read
);
480 if (ret
&& read
== propHdr
.cb
)
482 if (propHdr
.propID
== CERT_CERT_PROP_ID
)
484 contextInterface
= pCertInterface
;
485 ret
= contextInterface
->addEncodedToStore(store
,
486 X509_ASN_ENCODING
, buf
, read
,
487 CERT_STORE_ADD_NEW
, &context
);
489 else if (propHdr
.propID
== CERT_CRL_PROP_ID
)
491 contextInterface
= pCRLInterface
;
492 ret
= contextInterface
->addEncodedToStore(store
,
493 X509_ASN_ENCODING
, buf
, read
,
494 CERT_STORE_ADD_NEW
, &context
);
496 else if (propHdr
.propID
== CERT_CTL_PROP_ID
)
498 contextInterface
= pCTLInterface
;
499 ret
= contextInterface
->addEncodedToStore(store
,
500 X509_ASN_ENCODING
, buf
, read
,
501 CERT_STORE_ADD_NEW
, &context
);
505 if (!contextInterface
)
507 WARN("prop id %d before a context id\n",
512 ret
= CRYPT_ReadContextProp(
513 contextInterface
, context
, &propHdr
, buf
,
521 } while (ret
&& read
> 0 && propHdr
.cb
);
522 if (contextInterface
&& context
)
524 /* Free the last context added */
525 contextInterface
->free(context
);
538 static BOOL
read_file_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
541 return ReadFile(handle
, buffer
, bytesToRead
, bytesRead
, NULL
);
544 BOOL
CRYPT_ReadSerializedStoreFromFile(HANDLE file
, HCERTSTORE store
)
546 return CRYPT_ReadSerializedStore(file
, read_file_wrapper
, store
);
551 const CRYPT_DATA_BLOB
*blob
;
555 static BOOL
read_blob_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
558 struct BlobReader
*reader
= handle
;
561 if (reader
->current
< reader
->blob
->cbData
)
563 *bytesRead
= min(bytesToRead
, reader
->blob
->cbData
- reader
->current
);
564 memcpy(buffer
, reader
->blob
->pbData
+ reader
->current
, *bytesRead
);
565 reader
->current
+= *bytesRead
;
568 else if (reader
->current
== reader
->blob
->cbData
)
578 BOOL
CRYPT_ReadSerializedStoreFromBlob(const CRYPT_DATA_BLOB
*blob
,
581 struct BlobReader reader
= { blob
, 0 };
583 return CRYPT_ReadSerializedStore(&reader
, read_blob_wrapper
, store
);
586 static BOOL WINAPI
CRYPT_SerializeCertNoHash(PCCERT_CONTEXT pCertContext
,
587 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
589 return CRYPT_SerializeStoreElement(pCertContext
,
590 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
591 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
594 static BOOL WINAPI
CRYPT_SerializeCRLNoHash(PCCRL_CONTEXT pCrlContext
,
595 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
597 return CRYPT_SerializeStoreElement(pCrlContext
,
598 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
599 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
602 static BOOL WINAPI
CRYPT_SerializeCTLNoHash(PCCTL_CONTEXT pCtlContext
,
603 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
605 return CRYPT_SerializeStoreElement(pCtlContext
,
606 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
607 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
610 typedef BOOL (*SerializedOutputFunc
)(void *handle
, const void *buffer
,
613 static BOOL
CRYPT_SerializeContextsToStream(SerializedOutputFunc output
,
614 void *handle
, const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE store
)
616 const void *context
= NULL
;
620 context
= contextInterface
->enumContextsInStore(store
, context
);
626 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
628 buf
= CryptMemAlloc(size
);
631 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
633 ret
= output(handle
, buf
, size
);
639 } while (ret
&& context
!= NULL
);
641 contextInterface
->free(context
);
645 static BOOL
CRYPT_WriteSerializedStoreToStream(HCERTSTORE store
,
646 SerializedOutputFunc output
, void *handle
)
648 static const BYTE fileTrailer
[12] = { 0 };
649 WINE_CONTEXT_INTERFACE interface
;
652 ret
= output(handle
, fileHeader
, sizeof(fileHeader
));
655 memcpy(&interface
, pCertInterface
, sizeof(interface
));
656 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCertNoHash
;
657 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
662 memcpy(&interface
, pCRLInterface
, sizeof(interface
));
663 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCRLNoHash
;
664 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
669 memcpy(&interface
, pCTLInterface
, sizeof(interface
));
670 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCTLNoHash
;
671 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
675 ret
= output(handle
, fileTrailer
, sizeof(fileTrailer
));
679 static BOOL
CRYPT_FileOutputFunc(void *handle
, const void *buffer
, DWORD size
)
681 return WriteFile(handle
, buffer
, size
, &size
, NULL
);
684 static BOOL
CRYPT_WriteSerializedStoreToFile(HANDLE file
, HCERTSTORE store
)
686 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
687 return CRYPT_WriteSerializedStoreToStream(store
, CRYPT_FileOutputFunc
,
691 static BOOL
CRYPT_SavePKCSToMem(HCERTSTORE store
,
692 DWORD dwMsgAndCertEncodingType
, void *handle
)
694 CERT_BLOB
*blob
= handle
;
695 CRYPT_SIGNED_INFO signedInfo
= { 0 };
696 PCCERT_CONTEXT cert
= NULL
;
697 PCCRL_CONTEXT crl
= NULL
;
701 TRACE("(%d, %p)\n", blob
->pbData
? blob
->cbData
: 0, blob
->pbData
);
704 cert
= CertEnumCertificatesInStore(store
, cert
);
706 signedInfo
.cCertEncoded
++;
708 if (signedInfo
.cCertEncoded
)
710 signedInfo
.rgCertEncoded
= CryptMemAlloc(
711 signedInfo
.cCertEncoded
* sizeof(CERT_BLOB
));
712 if (!signedInfo
.rgCertEncoded
)
714 SetLastError(ERROR_OUTOFMEMORY
);
722 cert
= CertEnumCertificatesInStore(store
, cert
);
725 signedInfo
.rgCertEncoded
[i
].cbData
= cert
->cbCertEncoded
;
726 signedInfo
.rgCertEncoded
[i
].pbData
= cert
->pbCertEncoded
;
734 crl
= CertEnumCRLsInStore(store
, crl
);
736 signedInfo
.cCrlEncoded
++;
738 if (signedInfo
.cCrlEncoded
)
740 signedInfo
.rgCrlEncoded
= CryptMemAlloc(
741 signedInfo
.cCrlEncoded
* sizeof(CERT_BLOB
));
742 if (!signedInfo
.rgCrlEncoded
)
744 SetLastError(ERROR_OUTOFMEMORY
);
752 crl
= CertEnumCRLsInStore(store
, crl
);
755 signedInfo
.rgCrlEncoded
[i
].cbData
= crl
->cbCrlEncoded
;
756 signedInfo
.rgCrlEncoded
[i
].pbData
= crl
->pbCrlEncoded
;
764 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, NULL
, &size
);
769 else if (blob
->cbData
< size
)
772 SetLastError(ERROR_MORE_DATA
);
778 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, blob
->pbData
,
783 CryptMemFree(signedInfo
.rgCertEncoded
);
784 CryptMemFree(signedInfo
.rgCrlEncoded
);
785 TRACE("returning %d\n", ret
);
789 static BOOL
CRYPT_SavePKCSToFile(HCERTSTORE store
,
790 DWORD dwMsgAndCertEncodingType
, void *handle
)
792 CERT_BLOB blob
= { 0, NULL
};
795 TRACE("(%p)\n", handle
);
797 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
800 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
803 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
805 ret
= WriteFile(handle
, blob
.pbData
, blob
.cbData
,
810 SetLastError(ERROR_OUTOFMEMORY
);
814 TRACE("returning %d\n", ret
);
818 static BOOL
CRYPT_SaveSerializedToFile(HCERTSTORE store
,
819 DWORD dwMsgAndCertEncodingType
, void *handle
)
821 return CRYPT_WriteSerializedStoreToFile(handle
, store
);
824 struct MemWrittenTracker
831 /* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */
832 static BOOL
CRYPT_MemOutputFunc(void *handle
, const void *buffer
, DWORD size
)
834 struct MemWrittenTracker
*tracker
= handle
;
837 if (tracker
->written
+ size
> tracker
->cbData
)
839 SetLastError(ERROR_MORE_DATA
);
840 /* Update written so caller can notify its caller of the required size
842 tracker
->written
+= size
;
847 memcpy(tracker
->pbData
+ tracker
->written
, buffer
, size
);
848 tracker
->written
+= size
;
854 static BOOL
CRYPT_CountSerializedBytes(void *handle
, const void *buffer
,
857 *(DWORD
*)handle
+= size
;
861 static BOOL
CRYPT_SaveSerializedToMem(HCERTSTORE store
,
862 DWORD dwMsgAndCertEncodingType
, void *handle
)
864 CERT_BLOB
*blob
= handle
;
868 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_CountSerializedBytes
,
874 else if (blob
->cbData
< size
)
876 SetLastError(ERROR_MORE_DATA
);
882 struct MemWrittenTracker tracker
= { blob
->cbData
, blob
->pbData
,
885 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_MemOutputFunc
,
887 if (!ret
&& GetLastError() == ERROR_MORE_DATA
)
888 blob
->cbData
= tracker
.written
;
891 TRACE("returning %d\n", ret
);
895 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
896 DWORD dwSaveAs
, DWORD dwSaveTo
, void *pvSaveToPara
, DWORD dwFlags
)
898 BOOL (*saveFunc
)(HCERTSTORE
, DWORD
, void *);
900 BOOL ret
, closeFile
= TRUE
;
902 TRACE("(%p, %08x, %d, %d, %p, %08x)\n", hCertStore
,
903 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
907 case CERT_STORE_SAVE_AS_STORE
:
908 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
909 saveFunc
= CRYPT_SaveSerializedToMem
;
911 saveFunc
= CRYPT_SaveSerializedToFile
;
913 case CERT_STORE_SAVE_AS_PKCS7
:
914 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
915 saveFunc
= CRYPT_SavePKCSToMem
;
917 saveFunc
= CRYPT_SavePKCSToFile
;
920 WARN("unimplemented for %d\n", dwSaveAs
);
921 SetLastError(ERROR_INVALID_PARAMETER
);
926 case CERT_STORE_SAVE_TO_FILE
:
927 handle
= pvSaveToPara
;
930 case CERT_STORE_SAVE_TO_FILENAME_A
:
931 handle
= CreateFileA(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
932 CREATE_ALWAYS
, 0, NULL
);
934 case CERT_STORE_SAVE_TO_FILENAME_W
:
935 handle
= CreateFileW(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
936 CREATE_ALWAYS
, 0, NULL
);
938 case CERT_STORE_SAVE_TO_MEMORY
:
939 handle
= pvSaveToPara
;
942 WARN("unimplemented for %d\n", dwSaveTo
);
943 SetLastError(ERROR_INVALID_PARAMETER
);
946 ret
= saveFunc(hCertStore
, dwMsgAndCertEncodingType
, handle
);
949 TRACE("returning %d\n", ret
);
953 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
954 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
955 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
961 TRACE("(%p, %p, %d, %08x, %08x, %08x, %p, %p)\n", hCertStore
,
962 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
963 pdwContentType
, ppvContext
);
965 /* Call the internal function, then delete the hashes. Tests show this
966 * function uses real hash values, not whatever's stored in the hash
969 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
970 dwContextTypeFlags
, &type
);
973 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
977 case CERT_STORE_CERTIFICATE_CONTEXT
:
978 contextInterface
= pCertInterface
;
980 case CERT_STORE_CRL_CONTEXT
:
981 contextInterface
= pCRLInterface
;
983 case CERT_STORE_CTL_CONTEXT
:
984 contextInterface
= pCTLInterface
;
987 SetLastError(E_INVALIDARG
);
989 if (contextInterface
)
991 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
992 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
993 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
996 *pdwContentType
= type
;
997 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
998 dwAddDisposition
, ppvContext
);
999 contextInterface
->free(context
);