Module: wine Branch: refs/heads/master Commit: 89b3191c7c5173f09898ba80ba760507a1eda03e URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=89b3191c7c5173f09898ba80...
Author: Juan Lang juan_lang@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)