/* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */ static BOOL CRYPT_WriteSerializedToReg(HKEY key, DWORD flags, const BYTE *hash, const BYTE *buf, DWORD len) { WCHAR asciiHash[20 * 2 + 1]; LONG rc; HKEY subKey; BOOL ret; CRYPT_HashToStr(hash, asciiHash); rc = RegCreateKeyExW(key, asciiHash, 0, NULL, flags, KEY_ALL_ACCESS, NULL, &subKey, NULL); if (!rc) { rc = RegSetValueExW(subKey, BlobW, 0, REG_BINARY, buf, len); RegCloseKey(subKey); } if (!rc) ret = TRUE; else { SetLastError(rc); ret = FALSE; } return ret; }
static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store) { static const WCHAR * const subKeys[] = { CertsW, CRLsW, CTLsW }; const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface, pCRLInterface, pCTLInterface }; struct list *listToDelete[] = { &store->certsToDelete, &store->crlsToDelete, &store->ctlsToDelete }; BOOL ret = TRUE; DWORD i; for (i = 0; ret && i < sizeof(subKeys) / sizeof(subKeys[0]); i++) { HKEY key; LONG rc = RegCreateKeyExW(store->key, subKeys[i], 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL); if (!rc) { if (listToDelete[i]) { PWINE_HASH_TO_DELETE toDelete, next; WCHAR asciiHash[20 * 2 + 1]; EnterCriticalSection(&store->cs); LIST_FOR_EACH_ENTRY_SAFE(toDelete, next, listToDelete[i], WINE_HASH_TO_DELETE, entry) { LONG rc; CRYPT_HashToStr(toDelete->hash, asciiHash); TRACE("Removing %s\n", debugstr_w(asciiHash)); rc = RegDeleteKeyW(key, asciiHash); if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND) { SetLastError(rc); ret = FALSE; } list_remove(&toDelete->entry); CryptMemFree(toDelete); } LeaveCriticalSection(&store->cs); } ret = CRYPT_SerializeContextsToReg(key, interfaces[i], store->memStore); RegCloseKey(key); } else {
static void CRYPT_RegReadSerializedFromReg(HKEY key, DWORD contextType, HCERTSTORE store) { LONG rc; DWORD index = 0; WCHAR subKeyName[MAX_PATH]; do { DWORD size = sizeof(subKeyName) / sizeof(WCHAR); rc = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, NULL, NULL); if (!rc) { HKEY subKey; rc = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); if (!rc) { LPBYTE buf = NULL; size = 0; rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, NULL, &size); if (!rc) buf = CryptMemAlloc(size); if (buf) { rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, buf, &size); if (!rc) { const void *context; DWORD addedType; TRACE("Adding cert with hash %s\n", debugstr_w(subKeyName)); context = CRYPT_ReadSerializedElement(buf, size, contextType, &addedType); if (context) { const WINE_CONTEXT_INTERFACE *contextInterface; BYTE hash[20]; switch (addedType) { case CERT_STORE_CERTIFICATE_CONTEXT: contextInterface = pCertInterface; break; case CERT_STORE_CRL_CONTEXT: contextInterface = pCRLInterface; break; case CERT_STORE_CTL_CONTEXT: contextInterface = pCTLInterface; break; default: contextInterface = NULL; } if (contextInterface) { size = sizeof(hash); if (contextInterface->getProp(context, CERT_HASH_PROP_ID, hash, &size)) { WCHAR asciiHash[20 * 2 + 1]; CRYPT_HashToStr(hash, asciiHash); TRACE("comparing %s\n", debugstr_w(asciiHash)); TRACE("with %s\n", debugstr_w(subKeyName)); if (!lstrcmpW(asciiHash, subKeyName)) { TRACE("hash matches, adding\n"); contextInterface->addContextToStore( store, context, CERT_STORE_ADD_REPLACE_EXISTING, NULL); } else TRACE("hash doesn't match, ignoring\n"); } Context_Release(context_from_ptr(context)); } } } CryptMemFree(buf); } RegCloseKey(subKey); } /* Ignore intermediate errors, continue enumerating */ rc = ERROR_SUCCESS; } } while (!rc); }