/*
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2005-2006 Juan Lang
+ * Copyright 2018 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <stdio.h>
#include <stdarg.h>
+#ifdef __REACTOS__
+#include <stdlib.h>
+#endif
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
struct OIDFunction
{
+ HMODULE hModule;
DWORD encoding;
CRYPT_OID_FUNC_ENTRY entry;
struct list next;
static const LPCWSTR LocalizedKeys[] = {ROOT,MY,CA,ADDRESSBOOK,TRUSTEDPUBLISHER,DISALLOWED};
static WCHAR LocalizedNames[ARRAY_SIZE(LocalizedKeys)][256];
+static const WCHAR nameW[] = { 'N','a','m','e',0 };
+static const WCHAR algidW[] = { 'A','l','g','i','d',0 };
+static const WCHAR extraW[] = { 'E','x','t','r','a','I','n','f','o',0 };
+static const WCHAR cngalgidW[] = { 'C','N','G','A','l','g','i','d',0 };
+static const WCHAR cngextraalgidW[] = { 'C','N','G','E','x','t','r','a','A','l','g','i','d',0 };
+static const WCHAR flagsW[] = { 'F','l','a','g','s',0 };
+
static void free_function_sets(void)
{
struct OIDFunctionSet *setCursor, *setNext;
{
struct OIDFunction *func;
+ TRACE("OID %s, func %p\n", debugstr_a(rgFuncEntry[i].pszOID), rgFuncEntry[i].pvFuncAddr);
+
if (!IS_INTOID(rgFuncEntry[i].pszOID))
func = CryptMemAlloc(sizeof(struct OIDFunction)
+ strlen(rgFuncEntry[i].pszOID) + 1);
else
func->entry.pszOID = rgFuncEntry[i].pszOID;
func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
+ func->hModule = hModule;
list_add_tail(&set->functions, &func->next);
}
else
return ret;
}
+static BOOL is_module_registered(HMODULE hModule)
+{
+ struct OIDFunctionSet *set;
+ BOOL ret = FALSE;
+
+ EnterCriticalSection(&funcSetCS);
+
+ LIST_FOR_EACH_ENTRY(set, &funcSets, struct OIDFunctionSet, next)
+ {
+ struct OIDFunction *function;
+
+ EnterCriticalSection(&set->cs);
+
+ LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
+ {
+ if (function->hModule == hModule)
+ {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&set->cs);
+
+ if (ret) break;
+ }
+
+ LeaveCriticalSection(&funcSetCS);
+
+ return ret;
+}
+
BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
DWORD dwFlags)
{
{
struct FuncAddr *addr = hFuncAddr;
- CryptMemFree(addr->dllList);
- FreeLibrary(addr->lib);
- CryptMemFree(addr);
+ if (!is_module_registered(addr->lib))
+ {
+ CryptMemFree(addr->dllList);
+ FreeLibrary(addr->lib);
+ CryptMemFree(addr);
+ }
}
return TRUE;
}
return TRUE;
}
+/***********************************************************************
+ * CryptUnregisterOIDInfo (CRYPT32.@)
+ */
+BOOL WINAPI CryptUnregisterOIDInfo(PCCRYPT_OID_INFO info)
+{
+ char *key_name;
+ HKEY root;
+ DWORD err;
+
+ TRACE("(%p)\n", info);
+
+ if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
+ {
+ SetLastError(E_INVALIDARG);
+ return FALSE;
+ }
+
+ err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo", 0, KEY_ALL_ACCESS, &root);
+ if (err != ERROR_SUCCESS)
+ {
+ SetLastError(err);
+ return FALSE;
+ }
+
+ key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
+ if (key_name)
+ {
+ sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
+ err = RegDeleteKeyA(root, key_name);
+ }
+ else
+ err = ERROR_OUTOFMEMORY;
+
+ CryptMemFree(key_name);
+ RegCloseKey(root);
+
+ if (err)
+ SetLastError(err);
+
+ return !err;
+}
+
/***********************************************************************
* CryptRegisterOIDInfo (CRYPT32.@)
*/
-BOOL WINAPI CryptRegisterOIDInfo(PCCRYPT_OID_INFO pInfo, DWORD dwFlags)
+BOOL WINAPI CryptRegisterOIDInfo(PCCRYPT_OID_INFO info, DWORD flags)
{
- FIXME("(%p, %x): stub\n", pInfo, dwFlags );
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ char *key_name;
+ HKEY root = 0, key = 0;
+ DWORD err;
+
+ TRACE("(%p, %x)\n", info, flags );
+
+ if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
+ {
+ SetLastError(E_INVALIDARG);
+ return FALSE;
+ }
+
+ if (!info->dwGroupId) return TRUE;
+
+ key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
+ if (!key_name)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto done;
+ }
+
+ err = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
+ 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root, NULL);
+ if (err != ERROR_SUCCESS) goto done;
+
+ sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
+ err = RegCreateKeyA(root, key_name, &key);
+ if (err != ERROR_SUCCESS) goto done;
+
+ if (flags)
+ {
+ err = RegSetValueExW(key, flagsW, 0, REG_DWORD, (const BYTE *)&flags, sizeof(flags));
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+ if (info->pwszName)
+ {
+ err = RegSetValueExW(key, nameW, 0, REG_SZ, (const BYTE *)info->pwszName, (lstrlenW(info->pwszName) + 1) * sizeof(WCHAR));
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+ if (info->u.Algid)
+ {
+ err = RegSetValueExW(key, algidW, 0, REG_DWORD, (const BYTE *)&info->u.Algid, sizeof(info->u.Algid));
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+ if (info->ExtraInfo.cbData && info->ExtraInfo.pbData)
+ {
+ err = RegSetValueExW(key, extraW, 0, REG_BINARY, info->ExtraInfo.pbData, info->ExtraInfo.cbData);
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+ if (info->pwszCNGAlgid)
+ {
+ err = RegSetValueExW(key, cngalgidW, 0, REG_SZ, (const BYTE *)info->pwszCNGAlgid, (lstrlenW(info->pwszCNGAlgid) + 1) * sizeof(WCHAR));
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+ if (info->pwszCNGExtraAlgid)
+ {
+ err = RegSetValueExW(key, cngextraalgidW, 0, REG_SZ, (const BYTE *)info->pwszCNGExtraAlgid, (lstrlenW(info->pwszCNGExtraAlgid) + 1) * sizeof(WCHAR));
+ if (err != ERROR_SUCCESS) goto done;
+ }
+
+done:
+ CryptMemFree(key_name);
+ if (key) RegCloseKey(key);
+ if (root) RegCloseKey(root);
+
+ if (err)
+ SetLastError(err);
+
+ return !err;
}
/***********************************************************************
struct list entry;
};
+static struct OIDInfo *read_oid_info(HKEY root, char *key_name, DWORD *flags)
+{
+ HKEY key;
+ DWORD len, oid_len, name_len = 0, extra_len = 0, cngalgid_len = 0, cngextra_len = 0, group_id = 0;
+ struct OIDInfo *info;
+ char *p;
+
+ if (RegOpenKeyExA(root, key_name, 0, KEY_READ, &key))
+ return NULL;
+
+ p = strchr(key_name, '!');
+ if (p)
+ {
+ group_id = strtol(p + 1, NULL, 10);
+ *p = 0;
+ }
+
+ oid_len = strlen(key_name) + 1;
+
+ RegQueryValueExW(key, nameW, NULL, NULL, NULL, &name_len);
+ RegQueryValueExW(key, extraW, NULL, NULL, NULL, &extra_len);
+ RegQueryValueExW(key, cngalgidW, NULL, NULL, NULL, &cngalgid_len);
+ RegQueryValueExW(key, cngextraalgidW, NULL, NULL, NULL, &cngextra_len);
+
+ info = CryptMemAlloc(sizeof(*info) + oid_len + name_len + extra_len + cngalgid_len + cngextra_len);
+ if (info)
+ {
+ *flags = 0;
+ len = sizeof(*flags);
+ RegQueryValueExW(key, flagsW, NULL, NULL, (BYTE *)flags, &len);
+
+ memset(info, 0, sizeof(*info));
+ info->info.cbSize = sizeof(info->info);
+
+ p = (char *)(info + 1);
+
+ info->info.pszOID = p;
+ strcpy((char *)info->info.pszOID, key_name);
+ p += oid_len;
+
+ if (name_len)
+ {
+ info->info.pwszName = (WCHAR *)p;
+ RegQueryValueExW(key, nameW, NULL, NULL, (BYTE *)info->info.pwszName, &name_len);
+ p += name_len;
+ }
+
+ info->info.dwGroupId = group_id;
+
+ len = sizeof(info->info.u.Algid);
+ RegQueryValueExW(key, algidW, NULL, NULL, (BYTE *)&info->info.u.Algid, &len);
+
+ if (extra_len)
+ {
+ info->info.ExtraInfo.cbData = extra_len;
+ info->info.ExtraInfo.pbData = (BYTE *)p;
+ RegQueryValueExW(key, extraW, NULL, NULL, info->info.ExtraInfo.pbData, &extra_len);
+ p += extra_len;
+ }
+
+ if (cngalgid_len)
+ {
+ info->info.pwszCNGAlgid = (WCHAR *)p;
+ RegQueryValueExW(key, cngalgidW, NULL, NULL, (BYTE *)info->info.pwszCNGAlgid, &cngalgid_len);
+ p += cngalgid_len;
+ }
+
+ if (cngextra_len)
+ {
+ info->info.pwszCNGExtraAlgid = (WCHAR *)p;
+ RegQueryValueExW(key, cngextraalgidW, NULL, NULL, (BYTE *)info->info.pwszCNGExtraAlgid, &cngalgid_len);
+ }
+ }
+
+ RegCloseKey(key);
+
+ return info;
+}
+
+static void init_registered_oid_info(void)
+{
+ DWORD err, idx;
+ HKEY root;
+
+ err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
+ 0, KEY_ALL_ACCESS, &root);
+ if (err != ERROR_SUCCESS) return;
+
+ idx = 0;
+ for (;;)
+ {
+ char key_name[MAX_PATH];
+ struct OIDInfo *info;
+ DWORD flags;
+
+ err = RegEnumKeyA(root, idx++, key_name, MAX_PATH);
+ if (err == ERROR_NO_MORE_ITEMS)
+ break;
+
+ if (err == ERROR_SUCCESS)
+ {
+ if ((info = read_oid_info(root, key_name, &flags)))
+ {
+ TRACE("adding oid %s, name %s, groupid %u, algid %u, extra %u, CNG algid %s, CNG extra %s\n",
+ debugstr_a(info->info.pszOID), debugstr_w(info->info.pwszName),
+ info->info.dwGroupId, info->info.u.Algid, info->info.ExtraInfo.cbData,
+ debugstr_w(info->info.pwszCNGAlgid), debugstr_w(info->info.pwszCNGExtraAlgid));
+
+ if (flags & CRYPT_INSTALL_OID_INFO_BEFORE_FLAG)
+ list_add_head(&oidInfo, &info->entry);
+ else
+ list_add_tail(&oidInfo, &info->entry);
+ }
+ }
+ }
+
+ RegCloseKey(root);
+}
+
static void init_oid_info(void)
{
DWORD i;
void crypt_oid_init(void)
{
init_oid_info();
+ init_registered_oid_info();
}
void crypt_oid_free(void)