Index: dlls/rsaenh/rsaenh.c =================================================================== RCS file: /home/wine/wine/dlls/rsaenh/rsaenh.c,v retrieving revision 1.20 diff -u -r1.20 rsaenh.c --- dlls/rsaenh/rsaenh.c 31 Jan 2005 11:28:41 -0000 1.20 +++ dlls/rsaenh/rsaenh.c 9 Feb 2005 14:13:24 -0000 @@ -119,6 +119,7 @@ DWORD dwFlags; DWORD dwPersonality; DWORD dwEnumAlgsCtr; + DWORD dwEnumContainersCtr; CHAR szName[MAX_PATH]; CHAR szProvName[MAX_PATH]; HCRYPTKEY hKeyExchangeKeyPair; @@ -977,6 +978,31 @@ pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG; } } + + /* The new key container has to be inserted into the CSP immediately + * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */ + if (!(dwFlags & CRYPT_VERIFYCONTEXT)) { + BYTE szRSABase[MAX_PATH]; + HKEY hRootKey, hKey; + LONG lResult; + + sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName); + + if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) { + hRootKey = HKEY_LOCAL_MACHINE; + } else { + hRootKey = HKEY_CURRENT_USER; + } + + lResult = RegCreateKeyExA(hRootKey, szRSABase, 0, NULL, + REG_OPTION_NON_VOLATILE, 0, NULL, &hKey, NULL); + if (lResult == ERROR_SUCCESS) { + RegCloseKey(hKey); + } else { + WARN("Failed to create new key container registry key: " + "%08lx\n", lResult); + } + } } return hKeyContainer; @@ -1862,10 +1888,10 @@ } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) { encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen); } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) { - if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { - SetLastError(NTE_BAD_KEY); - return FALSE; - } + if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { + SetLastError(NTE_BAD_KEY); + return FALSE; + } if (dwBufLen < pCryptKey->dwBlockLen) { SetLastError(ERROR_MORE_DATA); return FALSE; @@ -1982,10 +2008,10 @@ } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) { encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen); } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) { - if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { - SetLastError(NTE_BAD_KEY); - return FALSE; - } + if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { + SetLastError(NTE_BAD_KEY); + return FALSE; + } encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT); if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE; Final = TRUE; @@ -2717,6 +2743,9 @@ KEYCONTAINER *pKeyContainer; PROV_ENUMALGS provEnumalgs; DWORD dwTemp; + BYTE szRSABase[MAX_PATH]; + HKEY hKey, hRootKey; + LONG lResult; /* This is for dwParam 41, which does not seem to be documented * on MSDN. IE6 SP1 asks for it in the 'About' dialog, however. @@ -2763,7 +2792,53 @@ case PP_KEYX_KEYSIZE_INC: dwTemp = 8; return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); - + + case PP_ENUMCONTAINERS: + if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0; + + if (!pbData) { + *pdwDataLen = (DWORD)MAX_PATH + 1; + return TRUE; + } + + sprintf(szRSABase, RSAENH_REGKEY, ""); + + if (dwFlags & CRYPT_MACHINE_KEYSET) { + hRootKey = HKEY_LOCAL_MACHINE; + } else { + hRootKey = HKEY_CURRENT_USER; + } + + lResult = RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, &hKey); + if (lResult != ERROR_SUCCESS) + { + WARN("Failed to open CSP registry key: %08lx\n", lResult); + SetLastError(ERROR_NO_MORE_ITEMS); + return FALSE; + } + + dwTemp = *pdwDataLen; + lResult = RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, pbData, &dwTemp, + NULL, NULL, NULL, NULL); + switch (lResult) + { + case ERROR_MORE_DATA: + *pdwDataLen = (DWORD)MAX_PATH + 1; + + case ERROR_SUCCESS: + pKeyContainer->dwEnumContainersCtr++; + RegCloseKey(hKey); + return TRUE; + + default: + WARN("Error enumerating containers: %08lx\n", lResult); + + case ERROR_NO_MORE_ITEMS: + SetLastError(ERROR_NO_MORE_ITEMS); + RegCloseKey(hKey); + return FALSE; + } + case PP_ENUMALGS: case PP_ENUMALGS_EX: if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) || Index: dlls/rsaenh/tests/rsaenh.c =================================================================== RCS file: /home/wine/wine/dlls/rsaenh/tests/rsaenh.c,v retrieving revision 1.7 diff -u -r1.7 rsaenh.c --- dlls/rsaenh/tests/rsaenh.c 31 Jan 2005 11:28:41 -0000 1.7 +++ dlls/rsaenh/tests/rsaenh.c 9 Feb 2005 14:13:24 -0000 @@ -1366,6 +1366,31 @@ CryptReleaseContext(hProv, 0); } +void test_enum_container() +{ + BYTE abContainerName[256]; + DWORD dwBufferLen; + BOOL result, fFound = FALSE; + + /* If PP_ENUMCONTAINERS is queried with CRYPT_FIRST and abData == NULL, it returns + * the maximum legal length of container names (which is MAX_PATH + 1 == 261) */ + result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &dwBufferLen, CRYPT_FIRST); + ok (result && dwBufferLen == MAX_PATH + 1, "%08lx\n", GetLastError()); + + /* If the result fits into abContainerName dwBufferLen is left untouched */ + dwBufferLen = (DWORD)sizeof(abContainerName); + result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, CRYPT_FIRST); + ok (result && dwBufferLen == (DWORD)sizeof(abContainerName), "%08lx\n", GetLastError()); + + /* We only check, if the currently open 'winetest' container is among the enumerated. */ + do { + if (!strcmp(abContainerName, "winetest")) fFound = TRUE; + dwBufferLen = (DWORD)sizeof(abContainerName); + } while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, 0)); + + ok (fFound && GetLastError() == ERROR_NO_MORE_ITEMS, "%d, %08lx\n", fFound, GetLastError()); +} + START_TEST(rsaenh) { if (!init_environment()) @@ -1384,6 +1409,7 @@ test_import_private(); test_verify_signature(); test_rsa_encrypt(); + test_enum_container(); clean_up_environment(); test_schannel_provider(); }