Juan Lang : crypt32: Implement CertGetValidUsages.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Mar 8 06:08:36 CST 2006


Module: wine
Branch: refs/heads/master
Commit: 89b3191c7c5173f09898ba80ba760507a1eda03e
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=89b3191c7c5173f09898ba80ba760507a1eda03e

Author: Juan Lang <juan_lang at yahoo.com>
Date:   Tue Mar  7 18:29:18 2006 -0800

crypt32: Implement CertGetValidUsages.

---

 dlls/crypt32/cert.c       |  141 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/crypt32/crypt32.spec |    1 
 2 files changed, 142 insertions(+), 0 deletions(-)

diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index 1b38c40..52b8ce1 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -572,3 +572,144 @@ BOOL WINAPI CertRemoveEnhancedKeyUsageId
     }
     return ret;
 }
+
+BOOL WINAPI CertGetValidUsages(DWORD cCerts, PCCERT_CONTEXT *rghCerts,
+ int *cNumOIDSs, LPSTR *rghOIDs, DWORD *pcbOIDs)
+{
+    BOOL ret = TRUE;
+    DWORD i, cbOIDs = 0;
+    BOOL allUsagesValid = TRUE;
+    CERT_ENHKEY_USAGE validUsages = { 0, NULL };
+
+    TRACE("(%ld, %p, %p, %p, %ld)\n", cCerts, *rghCerts, cNumOIDSs,
+     rghOIDs, *pcbOIDs);
+
+    for (i = 0; ret && i < cCerts; i++)
+    {
+        CERT_ENHKEY_USAGE usage;
+        DWORD size = sizeof(usage);
+
+        ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, &usage, &size);
+        /* Success is deliberately ignored: it implies all usages are valid */
+        if (!ret && GetLastError() == ERROR_MORE_DATA)
+        {
+            PCERT_ENHKEY_USAGE pUsage = CryptMemAlloc(size);
+
+            allUsagesValid = FALSE;
+            if (pUsage)
+            {
+                ret = CertGetEnhancedKeyUsage(rghCerts[i], 0, pUsage, &size);
+                if (ret)
+                {
+                    if (!validUsages.cUsageIdentifier)
+                    {
+                        DWORD j;
+
+                        cbOIDs = pUsage->cUsageIdentifier * sizeof(LPSTR);
+                        validUsages.cUsageIdentifier = pUsage->cUsageIdentifier;
+                        for (j = 0; j < validUsages.cUsageIdentifier; j++)
+                            cbOIDs += lstrlenA(pUsage->rgpszUsageIdentifier[j])
+                             + 1;
+                        validUsages.rgpszUsageIdentifier =
+                         CryptMemAlloc(cbOIDs);
+                        if (validUsages.rgpszUsageIdentifier)
+                        {
+                            LPSTR nextOID = (LPSTR)
+                             ((LPBYTE)validUsages.rgpszUsageIdentifier +
+                             validUsages.cUsageIdentifier * sizeof(LPSTR));
+
+                            for (j = 0; j < validUsages.cUsageIdentifier; j++)
+                            {
+                                validUsages.rgpszUsageIdentifier[j] = nextOID;
+                                lstrcpyA(validUsages.rgpszUsageIdentifier[j],
+                                 pUsage->rgpszUsageIdentifier[j]);
+                                nextOID += lstrlenA(nextOID) + 1;
+                            }
+                        }
+                        else
+                            ret = FALSE;
+                    }
+                    else
+                    {
+                        DWORD j, k, validIndexes = 0, numRemoved = 0;
+
+                        /* Merge: build a bitmap of all the indexes of
+                         * validUsages.rgpszUsageIdentifier that are in pUsage.
+                         */
+                        for (j = 0; j < pUsage->cUsageIdentifier; j++)
+                        {
+                            for (k = 0; k < validUsages.cUsageIdentifier; k++)
+                            {
+                                if (!strcmp(pUsage->rgpszUsageIdentifier[j],
+                                 validUsages.rgpszUsageIdentifier[k]))
+                                {
+                                    validIndexes |= (1 << k);
+                                    break;
+                                }
+                            }
+                        }
+                        /* Merge by removing from validUsages those that are
+                         * not in the bitmap.
+                         */
+                        for (j = 0; j < validUsages.cUsageIdentifier; j++)
+                        {
+                            if (!(validIndexes & (1 << j)))
+                            {
+                                if (j < validUsages.cUsageIdentifier - 1)
+                                {
+                                    memcpy(&validUsages.rgpszUsageIdentifier[j],
+                                     &validUsages.rgpszUsageIdentifier[j +
+                                     numRemoved + 1],
+                                     (validUsages.cUsageIdentifier - numRemoved
+                                     - j - 1) * sizeof(LPSTR));
+                                    cbOIDs -= lstrlenA(
+                                     validUsages.rgpszUsageIdentifier[j]) + 1 +
+                                     sizeof(LPSTR);
+                                    numRemoved++;
+                                }
+                                else
+                                    validUsages.cUsageIdentifier--;
+                            }
+                        }
+                    }
+                }
+                CryptMemFree(pUsage);
+            }
+            else
+                ret = FALSE;
+        }
+    }
+    if (ret)
+    {
+        if (allUsagesValid)
+        {
+            *cNumOIDSs = -1;
+            *pcbOIDs = 0;
+        }
+        else
+        {
+            if (!rghOIDs || *pcbOIDs < cbOIDs)
+            {
+                *pcbOIDs = cbOIDs;
+                SetLastError(ERROR_MORE_DATA);
+                ret = FALSE;
+            }
+            else
+            {
+                LPSTR nextOID = (LPSTR)((LPBYTE)rghOIDs +
+                 validUsages.cUsageIdentifier * sizeof(LPSTR));
+
+                *pcbOIDs = cbOIDs;
+                *cNumOIDSs = validUsages.cUsageIdentifier;
+                for (i = 0; i < validUsages.cUsageIdentifier; i++)
+                {
+                    rghOIDs[i] = nextOID;
+                    lstrcpyA(nextOID, validUsages.rgpszUsageIdentifier[i]);
+                    nextOID += lstrlenA(nextOID) + 1;
+                }
+            }
+        }
+    }
+    CryptMemFree(validUsages.rgpszUsageIdentifier);
+    return ret;
+}
diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec
index 7d40394..4fc11b3 100644
--- a/dlls/crypt32/crypt32.spec
+++ b/dlls/crypt32/crypt32.spec
@@ -56,6 +56,7 @@
 @ stdcall CertGetNameStringW(ptr long long ptr ptr long)
 @ stub CertGetPublicKeyLength
 @ stub CertGetSubjectCertificateFromStore
+@ stdcall CertGetValidUsages(long ptr ptr ptr ptr)
 @ stub CertIsRDNAttrsInCertificateName
 @ stdcall CertNameToStrA(long ptr long ptr long)
 @ stdcall CertNameToStrW(long ptr long ptr long)




More information about the wine-cvs mailing list