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