Juan Lang : crypt32: Implement CertSaveStore.
Alexandre Julliard
julliard at winehq.org
Fri Sep 28 06:46:01 CDT 2007
Module: wine
Branch: master
Commit: 6471621f5e776948d0ced9d372338aab90e295cf
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6471621f5e776948d0ced9d372338aab90e295cf
Author: Juan Lang <juan.lang at gmail.com>
Date: Thu Sep 27 13:49:16 2007 -0700
crypt32: Implement CertSaveStore.
---
dlls/crypt32/store.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 252 insertions(+), 2 deletions(-)
diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c
index 8a710a1..c647af5 100644
--- a/dlls/crypt32/store.c
+++ b/dlls/crypt32/store.c
@@ -781,12 +781,262 @@ HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
}
+static BOOL CRYPT_SavePKCSToMem(HCERTSTORE store,
+ DWORD dwMsgAndCertEncodingType, void *handle)
+{
+ CERT_BLOB *blob = (CERT_BLOB *)handle;
+ CRYPT_SIGNED_INFO signedInfo = { 0 };
+ PCCERT_CONTEXT cert = NULL;
+ PCCRL_CONTEXT crl = NULL;
+ DWORD size;
+ BOOL ret = TRUE;
+
+ TRACE("(%d, %p)\n", blob->pbData ? blob->cbData : 0, blob->pbData);
+
+ do {
+ cert = CertEnumCertificatesInStore(store, cert);
+ if (cert)
+ signedInfo.cCertEncoded++;
+ } while (cert);
+ if (signedInfo.cCertEncoded)
+ {
+ signedInfo.rgCertEncoded = CryptMemAlloc(
+ signedInfo.cCertEncoded * sizeof(CERT_BLOB));
+ if (!signedInfo.rgCertEncoded)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ }
+ else
+ {
+ DWORD i = 0;
+
+ do {
+ cert = CertEnumCertificatesInStore(store, cert);
+ if (cert)
+ {
+ signedInfo.rgCertEncoded[i].cbData = cert->cbCertEncoded;
+ signedInfo.rgCertEncoded[i].pbData = cert->pbCertEncoded;
+ i++;
+ }
+ } while (cert);
+ }
+ }
+
+ do {
+ crl = CertEnumCRLsInStore(store, crl);
+ if (crl)
+ signedInfo.cCrlEncoded++;
+ } while (crl);
+ if (signedInfo.cCrlEncoded)
+ {
+ signedInfo.rgCrlEncoded = CryptMemAlloc(
+ signedInfo.cCrlEncoded * sizeof(CERT_BLOB));
+ if (!signedInfo.rgCrlEncoded)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ }
+ else
+ {
+ DWORD i = 0;
+
+ do {
+ crl = CertEnumCRLsInStore(store, crl);
+ if (crl)
+ {
+ signedInfo.rgCrlEncoded[i].cbData = crl->cbCrlEncoded;
+ signedInfo.rgCrlEncoded[i].pbData = crl->pbCrlEncoded;
+ i++;
+ }
+ } while (crl);
+ }
+ }
+ if (ret)
+ {
+ ret = CRYPT_AsnEncodePKCSSignedInfo(&signedInfo, NULL, &size);
+ if (ret)
+ {
+ if (!blob->pbData)
+ blob->cbData = size;
+ else if (blob->cbData < size)
+ {
+ blob->cbData = size;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ blob->cbData = size;
+ ret = CRYPT_AsnEncodePKCSSignedInfo(&signedInfo, blob->pbData,
+ &blob->cbData);
+ }
+ }
+ }
+ CryptMemFree(signedInfo.rgCertEncoded);
+ CryptMemFree(signedInfo.rgCrlEncoded);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_SavePKCSToFile(HCERTSTORE store,
+ DWORD dwMsgAndCertEncodingType, void *handle)
+{
+ CERT_BLOB blob = { 0, NULL };
+ BOOL ret;
+
+ TRACE("(%p)\n", handle);
+
+ ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob);
+ if (ret)
+ {
+ blob.pbData = CryptMemAlloc(blob.cbData);
+ if (blob.pbData)
+ {
+ ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob);
+ if (ret)
+ ret = WriteFile((HANDLE)handle, blob.pbData, blob.cbData,
+ &blob.cbData, NULL);
+ }
+ else
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ }
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_SaveSerializedToFile(HCERTSTORE store,
+ DWORD dwMsgAndCertEncodingType, void *handle)
+{
+ return CRYPT_WriteSerializedStoreToFile((HANDLE)handle, store);
+}
+
+struct MemWrittenTracker
+{
+ DWORD cbData;
+ BYTE *pbData;
+ DWORD written;
+};
+
+/* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */
+static BOOL CRYPT_MemOutputFunc(void *handle, const void *buffer, DWORD size)
+{
+ struct MemWrittenTracker *tracker = (struct MemWrittenTracker *)handle;
+ BOOL ret;
+
+ if (tracker->written + size > tracker->cbData)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ /* Update written so caller can notify its caller of the required size
+ */
+ tracker->written += size;
+ ret = FALSE;
+ }
+ else
+ {
+ memcpy(tracker->pbData + tracker->written, buffer, size);
+ tracker->written += size;
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static BOOL CRYPT_CountSerializedBytes(void *handle, const void *buffer,
+ DWORD size)
+{
+ *(DWORD *)handle += size;
+ return TRUE;
+}
+
+static BOOL CRYPT_SaveSerializedToMem(HCERTSTORE store,
+ DWORD dwMsgAndCertEncodingType, void *handle)
+{
+ CERT_BLOB *blob = (CERT_BLOB *)handle;
+ DWORD size;
+ BOOL ret;
+
+ ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_CountSerializedBytes,
+ &size);
+ if (ret)
+ {
+ if (!blob->pbData)
+ blob->cbData = size;
+ else if (blob->cbData < size)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ blob->cbData = size;
+ ret = FALSE;
+ }
+ else
+ {
+ struct MemWrittenTracker tracker = { blob->cbData, blob->pbData,
+ 0 };
+
+ ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_MemOutputFunc,
+ &tracker);
+ if (!ret && GetLastError() == ERROR_MORE_DATA)
+ blob->cbData = tracker.written;
+ }
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags)
{
- FIXME("(%p,%d,%d,%d,%p,%08x) stub!\n", hCertStore,
+ BOOL (*saveFunc)(HCERTSTORE, DWORD, void *);
+ void *handle;
+ BOOL ret;
+
+ TRACE("(%p, %08x, %d, %d, %p, %08x)\n", hCertStore,
dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags);
- return TRUE;
+
+ switch (dwSaveAs)
+ {
+ case CERT_STORE_SAVE_AS_STORE:
+ case CERT_STORE_SAVE_AS_PKCS7:
+ break;
+ default:
+ WARN("unimplemented for %d\n", dwSaveAs);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ switch (dwSaveTo)
+ {
+ case CERT_STORE_SAVE_TO_FILE:
+ handle = (HANDLE)pvSaveToPara;
+ saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ?
+ CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile;
+ break;
+ case CERT_STORE_SAVE_TO_FILENAME_A:
+ handle = CreateFileA((LPCSTR)pvSaveToPara, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, 0, NULL);
+ saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ?
+ CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile;
+ break;
+ case CERT_STORE_SAVE_TO_FILENAME_W:
+ handle = CreateFileW((LPCWSTR)pvSaveToPara, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, 0, NULL);
+ saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ?
+ CRYPT_SaveSerializedToFile : CRYPT_SavePKCSToFile;
+ break;
+ case CERT_STORE_SAVE_TO_MEMORY:
+ handle = pvSaveToPara;
+ saveFunc = dwSaveAs == CERT_STORE_SAVE_AS_STORE ?
+ CRYPT_SaveSerializedToMem : CRYPT_SavePKCSToMem;
+ break;
+ default:
+ WARN("unimplemented for %d\n", dwSaveTo);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ ret = saveFunc(hCertStore, dwMsgAndCertEncodingType, handle);
+ TRACE("returning %d\n", ret);
+ return ret;
}
#define CertContext_CopyProperties(to, from) \
More information about the wine-cvs
mailing list