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
22 #include "wine/debug.h"
23 #include "wine/exception.h"
24 #include "crypt32_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
28 /* An extended certificate property in serialized form is prefixed by this
31 typedef struct _WINE_CERT_PROP_HEADER
34 DWORD unknown
; /* always 1 */
36 } WINE_CERT_PROP_HEADER
, *PWINE_CERT_PROP_HEADER
;
38 static BOOL
CRYPT_SerializeStoreElement(const void *context
,
39 const BYTE
*encodedContext
, DWORD cbEncodedContext
, DWORD contextPropID
,
40 PCWINE_CONTEXT_INTERFACE contextInterface
, DWORD dwFlags
, BOOL omitHashes
,
41 BYTE
*pbElement
, DWORD
*pcbElement
)
45 TRACE("(%p, %p, %08x, %d, %p, %p)\n", context
, contextInterface
, dwFlags
,
46 omitHashes
, pbElement
, pcbElement
);
50 DWORD bytesNeeded
= sizeof(WINE_CERT_PROP_HEADER
) + cbEncodedContext
;
55 prop
= contextInterface
->enumProps(context
, prop
);
56 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
60 ret
= contextInterface
->getProp(context
, prop
, NULL
, &propSize
);
62 bytesNeeded
+= sizeof(WINE_CERT_PROP_HEADER
) + propSize
;
64 } while (ret
&& prop
!= 0);
68 *pcbElement
= bytesNeeded
;
71 else if (*pcbElement
< bytesNeeded
)
73 *pcbElement
= bytesNeeded
;
74 SetLastError(ERROR_MORE_DATA
);
79 PWINE_CERT_PROP_HEADER hdr
;
85 prop
= contextInterface
->enumProps(context
, prop
);
86 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
90 ret
= contextInterface
->getProp(context
, prop
, NULL
,
94 if (bufSize
< propSize
)
97 buf
= CryptMemRealloc(buf
, propSize
);
99 buf
= CryptMemAlloc(propSize
);
104 ret
= contextInterface
->getProp(context
, prop
, buf
,
108 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
112 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
115 memcpy(pbElement
, buf
, propSize
);
116 pbElement
+= propSize
;
124 } while (ret
&& prop
!= 0);
127 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
128 hdr
->propID
= contextPropID
;
130 hdr
->cb
= cbEncodedContext
;
131 memcpy(pbElement
+ sizeof(WINE_CERT_PROP_HEADER
),
132 encodedContext
, cbEncodedContext
);
140 BOOL WINAPI
CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext
,
141 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
143 return CRYPT_SerializeStoreElement(pCertContext
,
144 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
145 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
148 BOOL WINAPI
CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext
,
149 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
151 return CRYPT_SerializeStoreElement(pCrlContext
,
152 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
153 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
156 BOOL WINAPI
CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext
,
157 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
159 return CRYPT_SerializeStoreElement(pCtlContext
,
160 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
161 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
164 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
165 * to its header if a valid header is found, NULL if not. Valid means the
166 * length of thte property won't overrun buf, and the unknown field is 1.
168 static const WINE_CERT_PROP_HEADER
*CRYPT_findPropID(const BYTE
*buf
,
169 DWORD size
, DWORD propID
)
171 const WINE_CERT_PROP_HEADER
*ret
= NULL
;
174 while (size
&& !ret
&& !done
)
176 if (size
< sizeof(WINE_CERT_PROP_HEADER
))
178 SetLastError(CRYPT_E_FILE_ERROR
);
183 const WINE_CERT_PROP_HEADER
*hdr
=
184 (const WINE_CERT_PROP_HEADER
*)buf
;
186 size
-= sizeof(WINE_CERT_PROP_HEADER
);
187 buf
+= sizeof(WINE_CERT_PROP_HEADER
);
190 SetLastError(E_INVALIDARG
);
193 else if (!hdr
->propID
)
195 /* assume a zero prop ID means the data are uninitialized, so
200 else if (hdr
->unknown
!= 1)
202 SetLastError(ERROR_FILE_NOT_FOUND
);
205 else if (hdr
->propID
== propID
)
217 static BOOL
CRYPT_ReadContextProp(
218 const WINE_CONTEXT_INTERFACE
*contextInterface
, const void *context
,
219 const WINE_CERT_PROP_HEADER
*hdr
, const BYTE
*pbElement
, DWORD cbElement
)
223 if (cbElement
< hdr
->cb
)
225 SetLastError(E_INVALIDARG
);
228 else if (hdr
->unknown
!= 1)
230 SetLastError(ERROR_FILE_NOT_FOUND
);
233 else if (hdr
->propID
!= CERT_CERT_PROP_ID
&&
234 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!= CERT_CTL_PROP_ID
)
236 /* Have to create a blob for most types, but not
241 case CERT_AUTO_ENROLL_PROP_ID
:
242 case CERT_CTL_USAGE_PROP_ID
:
243 case CERT_DESCRIPTION_PROP_ID
:
244 case CERT_FRIENDLY_NAME_PROP_ID
:
245 case CERT_HASH_PROP_ID
:
246 case CERT_KEY_IDENTIFIER_PROP_ID
:
247 case CERT_MD5_HASH_PROP_ID
:
248 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
249 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
250 case CERT_PVK_FILE_PROP_ID
:
251 case CERT_SIGNATURE_HASH_PROP_ID
:
252 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
253 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
254 case CERT_ENROLLMENT_PROP_ID
:
255 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
256 case CERT_RENEWAL_PROP_ID
:
258 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
261 ret
= contextInterface
->setProp(context
,
262 hdr
->propID
, 0, &blob
);
265 case CERT_DATE_STAMP_PROP_ID
:
266 ret
= contextInterface
->setProp(context
,
267 hdr
->propID
, 0, pbElement
);
269 case CERT_KEY_PROV_INFO_PROP_ID
:
271 PCRYPT_KEY_PROV_INFO info
=
272 (PCRYPT_KEY_PROV_INFO
)pbElement
;
274 CRYPT_FixKeyProvInfoPointers(info
);
275 ret
= contextInterface
->setProp(context
,
276 hdr
->propID
, 0, pbElement
);
285 /* ignore the context itself */
291 const void *CRYPT_ReadSerializedElement(const BYTE
*pbElement
, DWORD cbElement
,
292 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
296 TRACE("(%p, %d, %08x, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
301 SetLastError(ERROR_END_OF_MEDIA
);
307 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
308 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
314 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
316 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
318 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
321 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
323 type
= CERT_STORE_CRL_CONTEXT
;
326 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
329 type
= CERT_STORE_CTL_CONTEXT
;
333 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
335 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
336 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
338 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
340 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
341 type
= CERT_STORE_CRL_CONTEXT
;
343 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
345 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
346 type
= CERT_STORE_CTL_CONTEXT
;
351 case CERT_STORE_CERTIFICATE_CONTEXT
:
352 contextInterface
= pCertInterface
;
354 case CERT_STORE_CRL_CONTEXT
:
355 contextInterface
= pCRLInterface
;
357 case CERT_STORE_CTL_CONTEXT
:
358 contextInterface
= pCTLInterface
;
361 SetLastError(E_INVALIDARG
);
368 context
= contextInterface
->create(X509_ASN_ENCODING
,
369 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
372 BOOL noMoreProps
= FALSE
;
374 while (!noMoreProps
&& ret
)
376 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
380 const WINE_CERT_PROP_HEADER
*hdr
=
381 (const WINE_CERT_PROP_HEADER
*)pbElement
;
383 TRACE("prop is %d\n", hdr
->propID
);
384 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
385 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
388 /* Like in CRYPT_findPropID, stop if the propID is zero
393 ret
= CRYPT_ReadContextProp(contextInterface
, context
,
394 hdr
, pbElement
, cbElement
);
395 pbElement
+= hdr
->cb
;
396 cbElement
-= hdr
->cb
;
404 *pdwContentType
= type
;
408 contextInterface
->free(context
);
415 SetLastError(STATUS_ACCESS_VIOLATION
);
422 static const BYTE fileHeader
[] = { 0, 0, 0, 0, 'C','E','R','T' };
424 BOOL
CRYPT_ReadSerializedStoreFromFile(HANDLE file
, HCERTSTORE store
)
426 BYTE fileHeaderBuf
[sizeof(fileHeader
)];
430 /* Failure reading is non-critical, we'll leave the store empty */
431 ret
= ReadFile(file
, fileHeaderBuf
, sizeof(fileHeaderBuf
), &read
, NULL
);
435 ; /* an empty file is okay */
436 else if (read
!= sizeof(fileHeaderBuf
))
438 else if (!memcmp(fileHeaderBuf
, fileHeader
, read
))
440 WINE_CERT_PROP_HEADER propHdr
;
441 const void *context
= NULL
;
442 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
447 ret
= ReadFile(file
, &propHdr
, sizeof(propHdr
), &read
, NULL
);
448 if (ret
&& read
== sizeof(propHdr
))
450 if (contextInterface
&& context
&&
451 (propHdr
.propID
== CERT_CERT_PROP_ID
||
452 propHdr
.propID
== CERT_CRL_PROP_ID
||
453 propHdr
.propID
== CERT_CTL_PROP_ID
))
455 /* We have a new context, so free the existing one */
456 contextInterface
->free(context
);
458 if (propHdr
.cb
> bufSize
)
460 /* Not reusing realloc, because the old data aren't
464 buf
= CryptMemAlloc(propHdr
.cb
);
465 bufSize
= propHdr
.cb
;
469 ret
= ReadFile(file
, buf
, propHdr
.cb
, &read
, NULL
);
470 if (ret
&& read
== propHdr
.cb
)
472 if (propHdr
.propID
== CERT_CERT_PROP_ID
)
474 contextInterface
= pCertInterface
;
475 ret
= contextInterface
->addEncodedToStore(store
,
476 X509_ASN_ENCODING
, buf
, read
,
477 CERT_STORE_ADD_NEW
, &context
);
479 else if (propHdr
.propID
== CERT_CRL_PROP_ID
)
481 contextInterface
= pCRLInterface
;
482 ret
= contextInterface
->addEncodedToStore(store
,
483 X509_ASN_ENCODING
, buf
, read
,
484 CERT_STORE_ADD_NEW
, &context
);
486 else if (propHdr
.propID
== CERT_CTL_PROP_ID
)
488 contextInterface
= pCTLInterface
;
489 ret
= contextInterface
->addEncodedToStore(store
,
490 X509_ASN_ENCODING
, buf
, read
,
491 CERT_STORE_ADD_NEW
, &context
);
494 ret
= CRYPT_ReadContextProp(contextInterface
,
495 context
, &propHdr
, buf
, read
);
501 } while (ret
&& read
> 0);
502 if (contextInterface
&& context
)
504 /* Free the last context added */
505 contextInterface
->free(context
);
518 static BOOL WINAPI
CRYPT_SerializeCertNoHash(PCCERT_CONTEXT pCertContext
,
519 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
521 return CRYPT_SerializeStoreElement(pCertContext
,
522 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
523 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
526 static BOOL WINAPI
CRYPT_SerializeCRLNoHash(PCCRL_CONTEXT pCrlContext
,
527 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
529 return CRYPT_SerializeStoreElement(pCrlContext
,
530 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
531 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
534 static BOOL WINAPI
CRYPT_SerializeCTLNoHash(PCCTL_CONTEXT pCtlContext
,
535 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
537 return CRYPT_SerializeStoreElement(pCtlContext
,
538 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
539 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
542 typedef BOOL (*SerializedOutputFunc
)(void *handle
, const void *buffer
,
545 static BOOL
CRYPT_SerializeContextsToStream(SerializedOutputFunc output
,
546 void *handle
, const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE store
)
548 const void *context
= NULL
;
552 context
= contextInterface
->enumContextsInStore(store
, context
);
558 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
560 buf
= CryptMemAlloc(size
);
563 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
565 ret
= output(handle
, buf
, size
);
571 } while (ret
&& context
!= NULL
);
573 contextInterface
->free(context
);
577 static BOOL
CRYPT_WriteSerializedStoreToStream(HCERTSTORE store
,
578 SerializedOutputFunc output
, void *handle
)
580 static const BYTE fileTrailer
[12] = { 0 };
581 WINE_CONTEXT_INTERFACE interface
;
584 ret
= output(handle
, fileHeader
, sizeof(fileHeader
));
587 memcpy(&interface
, pCertInterface
, sizeof(interface
));
588 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCertNoHash
;
589 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
594 memcpy(&interface
, pCRLInterface
, sizeof(interface
));
595 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCRLNoHash
;
596 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
601 memcpy(&interface
, pCTLInterface
, sizeof(interface
));
602 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCTLNoHash
;
603 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
607 ret
= output(handle
, fileTrailer
, sizeof(fileTrailer
));
611 static BOOL
CRYPT_FileOutputFunc(void *handle
, const void *buffer
, DWORD size
)
613 return WriteFile(handle
, buffer
, size
, &size
, NULL
);
616 static BOOL
CRYPT_WriteSerializedStoreToFile(HANDLE file
, HCERTSTORE store
)
618 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
619 return CRYPT_WriteSerializedStoreToStream(store
, CRYPT_FileOutputFunc
,
623 static BOOL
CRYPT_SavePKCSToMem(HCERTSTORE store
,
624 DWORD dwMsgAndCertEncodingType
, void *handle
)
626 CERT_BLOB
*blob
= (CERT_BLOB
*)handle
;
627 CRYPT_SIGNED_INFO signedInfo
= { 0 };
628 PCCERT_CONTEXT cert
= NULL
;
629 PCCRL_CONTEXT crl
= NULL
;
633 TRACE("(%d, %p)\n", blob
->pbData
? blob
->cbData
: 0, blob
->pbData
);
636 cert
= CertEnumCertificatesInStore(store
, cert
);
638 signedInfo
.cCertEncoded
++;
640 if (signedInfo
.cCertEncoded
)
642 signedInfo
.rgCertEncoded
= CryptMemAlloc(
643 signedInfo
.cCertEncoded
* sizeof(CERT_BLOB
));
644 if (!signedInfo
.rgCertEncoded
)
646 SetLastError(ERROR_OUTOFMEMORY
);
654 cert
= CertEnumCertificatesInStore(store
, cert
);
657 signedInfo
.rgCertEncoded
[i
].cbData
= cert
->cbCertEncoded
;
658 signedInfo
.rgCertEncoded
[i
].pbData
= cert
->pbCertEncoded
;
666 crl
= CertEnumCRLsInStore(store
, crl
);
668 signedInfo
.cCrlEncoded
++;
670 if (signedInfo
.cCrlEncoded
)
672 signedInfo
.rgCrlEncoded
= CryptMemAlloc(
673 signedInfo
.cCrlEncoded
* sizeof(CERT_BLOB
));
674 if (!signedInfo
.rgCrlEncoded
)
676 SetLastError(ERROR_OUTOFMEMORY
);
684 crl
= CertEnumCRLsInStore(store
, crl
);
687 signedInfo
.rgCrlEncoded
[i
].cbData
= crl
->cbCrlEncoded
;
688 signedInfo
.rgCrlEncoded
[i
].pbData
= crl
->pbCrlEncoded
;
696 ret
= CRYPT_AsnEncodePKCSSignedInfo(&signedInfo
, NULL
, &size
);
701 else if (blob
->cbData
< size
)
704 SetLastError(ERROR_MORE_DATA
);
710 ret
= CRYPT_AsnEncodePKCSSignedInfo(&signedInfo
, blob
->pbData
,
715 CryptMemFree(signedInfo
.rgCertEncoded
);
716 CryptMemFree(signedInfo
.rgCrlEncoded
);
717 TRACE("returning %d\n", ret
);
721 static BOOL
CRYPT_SavePKCSToFile(HCERTSTORE store
,
722 DWORD dwMsgAndCertEncodingType
, void *handle
)
724 CERT_BLOB blob
= { 0, NULL
};
727 TRACE("(%p)\n", handle
);
729 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
732 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
735 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
737 ret
= WriteFile(handle
, blob
.pbData
, blob
.cbData
,
742 SetLastError(ERROR_OUTOFMEMORY
);
746 TRACE("returning %d\n", ret
);
750 static BOOL
CRYPT_SaveSerializedToFile(HCERTSTORE store
,
751 DWORD dwMsgAndCertEncodingType
, void *handle
)
753 return CRYPT_WriteSerializedStoreToFile(handle
, store
);
756 struct MemWrittenTracker
763 /* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */
764 static BOOL
CRYPT_MemOutputFunc(void *handle
, const void *buffer
, DWORD size
)
766 struct MemWrittenTracker
*tracker
= (struct MemWrittenTracker
*)handle
;
769 if (tracker
->written
+ size
> tracker
->cbData
)
771 SetLastError(ERROR_MORE_DATA
);
772 /* Update written so caller can notify its caller of the required size
774 tracker
->written
+= size
;
779 memcpy(tracker
->pbData
+ tracker
->written
, buffer
, size
);
780 tracker
->written
+= size
;
786 static BOOL
CRYPT_CountSerializedBytes(void *handle
, const void *buffer
,
789 *(DWORD
*)handle
+= size
;
793 static BOOL
CRYPT_SaveSerializedToMem(HCERTSTORE store
,
794 DWORD dwMsgAndCertEncodingType
, void *handle
)
796 CERT_BLOB
*blob
= (CERT_BLOB
*)handle
;
800 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_CountSerializedBytes
,
806 else if (blob
->cbData
< size
)
808 SetLastError(ERROR_MORE_DATA
);
814 struct MemWrittenTracker tracker
= { blob
->cbData
, blob
->pbData
,
817 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_MemOutputFunc
,
819 if (!ret
&& GetLastError() == ERROR_MORE_DATA
)
820 blob
->cbData
= tracker
.written
;
823 TRACE("returning %d\n", ret
);
827 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
828 DWORD dwSaveAs
, DWORD dwSaveTo
, void *pvSaveToPara
, DWORD dwFlags
)
830 BOOL (*saveFunc
)(HCERTSTORE
, DWORD
, void *);
834 TRACE("(%p, %08x, %d, %d, %p, %08x)\n", hCertStore
,
835 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
839 case CERT_STORE_SAVE_AS_STORE
:
840 case CERT_STORE_SAVE_AS_PKCS7
:
843 WARN("unimplemented for %d\n", dwSaveAs
);
844 SetLastError(ERROR_INVALID_PARAMETER
);
849 case CERT_STORE_SAVE_TO_FILE
:
850 handle
= pvSaveToPara
;
851 saveFunc
= dwSaveAs
== CERT_STORE_SAVE_AS_STORE
?
852 CRYPT_SaveSerializedToFile
: CRYPT_SavePKCSToFile
;
854 case CERT_STORE_SAVE_TO_FILENAME_A
:
855 handle
= CreateFileA((LPCSTR
)pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
856 CREATE_ALWAYS
, 0, NULL
);
857 saveFunc
= dwSaveAs
== CERT_STORE_SAVE_AS_STORE
?
858 CRYPT_SaveSerializedToFile
: CRYPT_SavePKCSToFile
;
860 case CERT_STORE_SAVE_TO_FILENAME_W
:
861 handle
= CreateFileW((LPCWSTR
)pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
862 CREATE_ALWAYS
, 0, NULL
);
863 saveFunc
= dwSaveAs
== CERT_STORE_SAVE_AS_STORE
?
864 CRYPT_SaveSerializedToFile
: CRYPT_SavePKCSToFile
;
866 case CERT_STORE_SAVE_TO_MEMORY
:
867 handle
= pvSaveToPara
;
868 saveFunc
= dwSaveAs
== CERT_STORE_SAVE_AS_STORE
?
869 CRYPT_SaveSerializedToMem
: CRYPT_SavePKCSToMem
;
872 WARN("unimplemented for %d\n", dwSaveTo
);
873 SetLastError(ERROR_INVALID_PARAMETER
);
876 ret
= saveFunc(hCertStore
, dwMsgAndCertEncodingType
, handle
);
877 TRACE("returning %d\n", ret
);
881 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
882 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
883 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
889 TRACE("(%p, %p, %d, %08x, %08x, %08x, %p, %p)\n", hCertStore
,
890 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
891 pdwContentType
, ppvContext
);
893 /* Call the internal function, then delete the hashes. Tests show this
894 * function uses real hash values, not whatever's stored in the hash
897 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
898 dwContextTypeFlags
, &type
);
901 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
905 case CERT_STORE_CERTIFICATE_CONTEXT
:
906 contextInterface
= pCertInterface
;
908 case CERT_STORE_CRL_CONTEXT
:
909 contextInterface
= pCRLInterface
;
911 case CERT_STORE_CTL_CONTEXT
:
912 contextInterface
= pCTLInterface
;
915 SetLastError(E_INVALIDARG
);
917 if (contextInterface
)
919 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
920 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
921 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
924 *pdwContentType
= type
;
925 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
926 dwAddDisposition
, ppvContext
);
927 contextInterface
->free(context
);