gdi32: Use NtGdiPolyPolyDraw for PolylineTo implementation.
[wine.git] / dlls / crypt32 / oid.c
blob95e34528a04c587457e0d98b14e9fa87c333e1cc
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005-2006 Juan Lang
4 * Copyright 2018 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #define NONAMELESSUNION
25 #include "windef.h"
26 #include "winbase.h"
27 #define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
28 #include "wincrypt.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "winuser.h"
32 #include "wine/debug.h"
33 #include "wine/list.h"
34 #include "crypt32_private.h"
35 #include "cryptres.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
39 static CRITICAL_SECTION funcSetCS;
40 static CRITICAL_SECTION_DEBUG funcSetCSDebug =
42 0, 0, &funcSetCS,
43 { &funcSetCSDebug.ProcessLocksList, &funcSetCSDebug.ProcessLocksList },
44 0, 0, { (DWORD_PTR)(__FILE__ ": funcSetCS") }
46 static CRITICAL_SECTION funcSetCS = { &funcSetCSDebug, -1, 0, 0, 0, 0 };
47 static struct list funcSets = { &funcSets, &funcSets };
49 struct OIDFunctionSet
51 LPSTR name;
52 CRITICAL_SECTION cs; /* protects functions */
53 struct list functions;
54 struct list next;
57 struct OIDFunction
59 HMODULE hModule;
60 DWORD encoding;
61 CRYPT_OID_FUNC_ENTRY entry;
62 struct list next;
65 static const LPCWSTR LocalizedKeys[] =
67 L"ROOT",
68 L"MY",
69 L"CA",
70 L"ADDRESSBOOK",
71 L"TrustedPublisher",
72 L"Disallowed"
74 static WCHAR LocalizedNames[ARRAY_SIZE(LocalizedKeys)][256];
76 static void free_function_sets(void)
78 struct OIDFunctionSet *setCursor, *setNext;
80 LIST_FOR_EACH_ENTRY_SAFE(setCursor, setNext, &funcSets,
81 struct OIDFunctionSet, next)
83 struct OIDFunction *functionCursor, *funcNext;
85 list_remove(&setCursor->next);
86 CryptMemFree(setCursor->name);
87 LIST_FOR_EACH_ENTRY_SAFE(functionCursor, funcNext,
88 &setCursor->functions, struct OIDFunction, next)
90 list_remove(&functionCursor->next);
91 CryptMemFree(functionCursor);
93 setCursor->cs.DebugInfo->Spare[0] = 0;
94 DeleteCriticalSection(&setCursor->cs);
95 CryptMemFree(setCursor);
97 DeleteCriticalSection(&funcSetCS);
100 /* There is no free function associated with this; therefore, the sets are
101 * freed when crypt32.dll is unloaded.
103 HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName,
104 DWORD dwFlags)
106 struct OIDFunctionSet *cursor, *ret = NULL;
108 TRACE("(%s, %x)\n", debugstr_a(pszFuncName), dwFlags);
110 EnterCriticalSection(&funcSetCS);
111 LIST_FOR_EACH_ENTRY(cursor, &funcSets, struct OIDFunctionSet, next)
113 if (!stricmp(pszFuncName, cursor->name))
115 ret = cursor;
116 break;
119 if (!ret)
121 ret = CryptMemAlloc(sizeof(struct OIDFunctionSet));
122 if (ret)
124 memset(ret, 0, sizeof(*ret));
125 ret->name = CryptMemAlloc(strlen(pszFuncName) + 1);
126 if (ret->name)
128 InitializeCriticalSection(&ret->cs);
129 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": OIDFunctionSet.cs");
130 list_init(&ret->functions);
131 strcpy(ret->name, pszFuncName);
132 list_add_tail(&funcSets, &ret->next);
134 else
136 CryptMemFree(ret);
137 ret = NULL;
141 LeaveCriticalSection(&funcSetCS);
143 return ret;
146 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
147 LPCSTR pszOID)
149 static const char szEncodingTypeFmt[] =
150 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %d\\%s\\%s";
151 UINT len;
152 char numericOID[7]; /* enough for "#65535" */
153 const char *oid;
154 LPSTR szKey;
156 /* MSDN says the encoding type is a mask, but it isn't treated that way.
157 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
158 * "EncodingType 2" would be expected if it were a mask. Instead native
159 * stores values in "EncodingType 3".
161 if (IS_INTOID(pszOID))
163 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
164 oid = numericOID;
166 else
167 oid = pszOID;
169 /* This is enough: the lengths of the two string parameters are explicitly
170 * counted, and we need up to five additional characters for the encoding
171 * type. These are covered by the "%d", "%s", and "%s" characters in the
172 * format specifier that are removed by sprintf.
174 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
175 szKey = CryptMemAlloc(len);
176 if (szKey)
177 sprintf(szKey, szEncodingTypeFmt,
178 GET_CERT_ENCODING_TYPE(dwEncodingType), pszFuncName, oid);
179 return szKey;
182 BOOL WINAPI CryptGetDefaultOIDDllList(HCRYPTOIDFUNCSET hFuncSet,
183 DWORD dwEncodingType, LPWSTR pwszDllList, DWORD *pcchDllList)
185 struct OIDFunctionSet *set = hFuncSet;
186 char *keyName;
187 HKEY key;
188 LSTATUS rc;
190 TRACE("(%p, %d, %p, %p)\n", hFuncSet, dwEncodingType, pwszDllList,
191 pcchDllList);
193 keyName = CRYPT_GetKeyName(dwEncodingType, set->name, "DEFAULT");
194 rc = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, NULL, 0,
195 KEY_READ, NULL, &key, NULL);
196 if (!rc)
198 DWORD size = *pcchDllList * sizeof(WCHAR);
200 rc = RegQueryValueExW(key, L"Dll", NULL, NULL, (LPBYTE)pwszDllList,
201 &size);
202 if (!rc)
203 *pcchDllList = size / sizeof(WCHAR);
204 else
206 /* No value, return an empty list */
207 if (pwszDllList && *pcchDllList)
208 *pwszDllList = '\0';
209 *pcchDllList = 1;
211 RegCloseKey(key);
213 else
215 /* No value, return an empty list */
216 if (pwszDllList && *pcchDllList)
217 *pwszDllList = '\0';
218 *pcchDllList = 1;
220 CryptMemFree(keyName);
222 return TRUE;
225 BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
226 DWORD dwEncodingType, LPCSTR pszFuncName, DWORD cFuncEntry,
227 const CRYPT_OID_FUNC_ENTRY rgFuncEntry[], DWORD dwFlags)
229 BOOL ret = TRUE;
230 struct OIDFunctionSet *set;
232 TRACE("(%p, %d, %s, %d, %p, %08x)\n", hModule, dwEncodingType,
233 debugstr_a(pszFuncName), cFuncEntry, rgFuncEntry, dwFlags);
235 set = CryptInitOIDFunctionSet(pszFuncName, 0);
236 if (set)
238 DWORD i;
240 EnterCriticalSection(&set->cs);
241 for (i = 0; ret && i < cFuncEntry; i++)
243 struct OIDFunction *func;
245 TRACE("OID %s, func %p\n", debugstr_a(rgFuncEntry[i].pszOID), rgFuncEntry[i].pvFuncAddr);
247 if (!IS_INTOID(rgFuncEntry[i].pszOID))
248 func = CryptMemAlloc(sizeof(struct OIDFunction)
249 + strlen(rgFuncEntry[i].pszOID) + 1);
250 else
251 func = CryptMemAlloc(sizeof(struct OIDFunction));
252 if (func)
254 func->encoding = GET_CERT_ENCODING_TYPE(dwEncodingType);
255 if (!IS_INTOID(rgFuncEntry[i].pszOID))
257 LPSTR oid;
259 oid = (LPSTR)((LPBYTE)func + sizeof(*func));
260 strcpy(oid, rgFuncEntry[i].pszOID);
261 func->entry.pszOID = oid;
263 else
264 func->entry.pszOID = rgFuncEntry[i].pszOID;
265 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
266 func->hModule = hModule;
267 list_add_tail(&set->functions, &func->next);
269 else
270 ret = FALSE;
272 LeaveCriticalSection(&set->cs);
274 else
275 ret = FALSE;
276 return ret;
279 struct FuncAddr
281 HMODULE lib;
282 LPWSTR dllList;
283 LPWSTR currentDll;
286 static BOOL CRYPT_GetFuncFromReg(DWORD dwEncodingType, LPCSTR pszOID,
287 LPCSTR szFuncName, LPVOID *ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
289 BOOL ret = FALSE;
290 char *keyName;
291 const char *funcName;
292 HKEY key;
293 LSTATUS rc;
295 keyName = CRYPT_GetKeyName(dwEncodingType, szFuncName, pszOID);
296 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
297 if (!rc)
299 DWORD type, size = 0;
301 rc = RegQueryValueExA(key, "FuncName", NULL, &type, NULL, &size);
302 if ((!rc || rc == ERROR_MORE_DATA) && type == REG_SZ)
304 funcName = CryptMemAlloc(size);
305 rc = RegQueryValueExA(key, "FuncName", NULL, &type,
306 (LPBYTE)funcName, &size);
308 else
309 funcName = szFuncName;
310 rc = RegQueryValueExW(key, L"Dll", NULL, &type, NULL, &size);
311 if ((!rc || rc == ERROR_MORE_DATA) && type == REG_SZ)
313 LPWSTR dllName = CryptMemAlloc(size);
315 if (dllName)
317 rc = RegQueryValueExW(key, L"Dll", NULL, NULL,
318 (LPBYTE)dllName, &size);
319 if (!rc)
321 HMODULE lib;
323 /* This is a bit of a hack; MSDN describes a more
324 * complicated unload routine than this will allow.
325 * Still, this seems to suffice for now.
327 lib = LoadLibraryW(dllName);
328 if (lib)
330 *ppvFuncAddr = GetProcAddress(lib, funcName);
331 if (*ppvFuncAddr)
333 struct FuncAddr *addr =
334 CryptMemAlloc(sizeof(struct FuncAddr));
336 if (addr)
338 addr->lib = lib;
339 addr->dllList = addr->currentDll = NULL;
340 *phFuncAddr = addr;
341 ret = TRUE;
343 else
345 *phFuncAddr = NULL;
346 FreeLibrary(lib);
349 else
351 /* Unload the library, the caller doesn't want
352 * to unload it when the return value is NULL.
354 FreeLibrary(lib);
358 else
359 SetLastError(rc);
360 CryptMemFree(dllName);
363 else
364 SetLastError(rc);
365 if (funcName != szFuncName)
366 CryptMemFree((char *)funcName);
367 RegCloseKey(key);
369 else
370 SetLastError(rc);
371 CryptMemFree(keyName);
372 return ret;
375 BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
376 DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr,
377 HCRYPTOIDFUNCADDR *phFuncAddr)
379 BOOL ret = FALSE;
380 struct OIDFunctionSet *set = hFuncSet;
382 TRACE("(%p, %d, %s, %08x, %p, %p)\n", hFuncSet, dwEncodingType,
383 debugstr_a(pszOID), dwFlags, ppvFuncAddr, phFuncAddr);
385 *ppvFuncAddr = NULL;
386 if (!(dwFlags & CRYPT_GET_INSTALLED_OID_FUNC_FLAG))
388 struct OIDFunction *function;
390 EnterCriticalSection(&set->cs);
391 LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
393 if (function->encoding == GET_CERT_ENCODING_TYPE(dwEncodingType))
395 if (!IS_INTOID(pszOID))
397 if (!IS_INTOID(function->entry.pszOID) &&
398 !stricmp(function->entry.pszOID, pszOID))
400 *ppvFuncAddr = function->entry.pvFuncAddr;
401 *phFuncAddr = NULL; /* FIXME: what should it be? */
402 ret = TRUE;
403 break;
406 else if (function->entry.pszOID == pszOID)
408 *ppvFuncAddr = function->entry.pvFuncAddr;
409 *phFuncAddr = NULL; /* FIXME: what should it be? */
410 ret = TRUE;
411 break;
415 LeaveCriticalSection(&set->cs);
417 if (!*ppvFuncAddr)
418 ret = CRYPT_GetFuncFromReg(dwEncodingType, pszOID, set->name,
419 ppvFuncAddr, phFuncAddr);
420 TRACE("returning %d\n", ret);
421 return ret;
424 static BOOL is_module_registered(HMODULE hModule)
426 struct OIDFunctionSet *set;
427 BOOL ret = FALSE;
429 EnterCriticalSection(&funcSetCS);
431 LIST_FOR_EACH_ENTRY(set, &funcSets, struct OIDFunctionSet, next)
433 struct OIDFunction *function;
435 EnterCriticalSection(&set->cs);
437 LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
439 if (function->hModule == hModule)
441 ret = TRUE;
442 break;
446 LeaveCriticalSection(&set->cs);
448 if (ret) break;
451 LeaveCriticalSection(&funcSetCS);
453 return ret;
456 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
457 DWORD dwFlags)
459 TRACE("(%p, %08x)\n", hFuncAddr, dwFlags);
461 /* FIXME: as MSDN states, need to check for DllCanUnloadNow in the DLL,
462 * and only unload it if it can be unloaded. Also need to implement ref
463 * counting on the functions.
465 if (hFuncAddr)
467 struct FuncAddr *addr = hFuncAddr;
469 if (!is_module_registered(addr->lib))
471 CryptMemFree(addr->dllList);
472 FreeLibrary(addr->lib);
473 CryptMemFree(addr);
476 return TRUE;
479 static BOOL CRYPT_GetFuncFromDll(LPCWSTR dll, LPCSTR func, HMODULE *lib,
480 void **ppvFuncAddr)
482 BOOL ret = FALSE;
484 *lib = LoadLibraryW(dll);
485 if (*lib)
487 *ppvFuncAddr = GetProcAddress(*lib, func);
488 if (*ppvFuncAddr)
489 ret = TRUE;
490 else
492 FreeLibrary(*lib);
493 *lib = NULL;
496 return ret;
499 BOOL WINAPI CryptGetDefaultOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
500 DWORD dwEncodingType, LPCWSTR pwszDll, DWORD dwFlags, void **ppvFuncAddr,
501 HCRYPTOIDFUNCADDR *phFuncAddr)
503 struct OIDFunctionSet *set = hFuncSet;
504 BOOL ret = FALSE;
506 TRACE("(%p, %d, %s, %08x, %p, %p)\n", hFuncSet, dwEncodingType,
507 debugstr_w(pwszDll), dwFlags, ppvFuncAddr, phFuncAddr);
509 if (pwszDll)
511 HMODULE lib;
513 *phFuncAddr = NULL;
514 ret = CRYPT_GetFuncFromDll(pwszDll, set->name, &lib, ppvFuncAddr);
515 if (ret)
517 struct FuncAddr *addr = CryptMemAlloc(sizeof(struct FuncAddr));
519 if (addr)
521 addr->lib = lib;
522 addr->dllList = addr->currentDll = NULL;
523 *phFuncAddr = addr;
525 else
527 FreeLibrary(lib);
528 *ppvFuncAddr = NULL;
529 SetLastError(ERROR_OUTOFMEMORY);
530 ret = FALSE;
533 else
534 SetLastError(ERROR_FILE_NOT_FOUND);
536 else
538 struct FuncAddr *addr = *phFuncAddr;
540 if (!addr)
542 DWORD size;
544 ret = CryptGetDefaultOIDDllList(hFuncSet, dwEncodingType, NULL,
545 &size);
546 if (ret)
548 LPWSTR dllList = CryptMemAlloc(size * sizeof(WCHAR));
550 if (dllList)
552 ret = CryptGetDefaultOIDDllList(hFuncSet, dwEncodingType,
553 dllList, &size);
554 if (ret)
556 addr = CryptMemAlloc(sizeof(struct FuncAddr));
557 if (addr)
559 addr->dllList = dllList;
560 addr->currentDll = dllList;
561 addr->lib = NULL;
562 *phFuncAddr = addr;
564 else
566 CryptMemFree(dllList);
567 SetLastError(ERROR_OUTOFMEMORY);
568 ret = FALSE;
572 else
574 SetLastError(ERROR_OUTOFMEMORY);
575 ret = FALSE;
579 if (addr)
581 if (!*addr->currentDll)
583 CryptFreeOIDFunctionAddress(*phFuncAddr, 0);
584 SetLastError(ERROR_FILE_NOT_FOUND);
585 *phFuncAddr = NULL;
586 ret = FALSE;
588 else
590 /* FIXME: as elsewhere, can't free until DllCanUnloadNow says
591 * it's possible, and should defer unloading for some time to
592 * avoid repeated LoadLibrary/FreeLibrary on the same dll.
594 FreeLibrary(addr->lib);
595 ret = CRYPT_GetFuncFromDll(addr->currentDll, set->name,
596 &addr->lib, ppvFuncAddr);
597 if (ret)
599 /* Move past the current DLL */
600 addr->currentDll += lstrlenW(addr->currentDll) + 1;
601 *phFuncAddr = addr;
603 else
605 CryptFreeOIDFunctionAddress(*phFuncAddr, 0);
606 SetLastError(ERROR_FILE_NOT_FOUND);
607 *phFuncAddr = NULL;
612 return ret;
615 /***********************************************************************
616 * CryptRegisterOIDFunction (CRYPT32.@)
618 * Register the DLL and the functions it uses to cover the combination
619 * of encoding type, function name and OID.
621 * PARAMS
622 * dwEncodingType [I] Encoding type to be used.
623 * pszFuncName [I] Name of the function to be registered.
624 * pszOID [I] OID of the function (numeric or string).
625 * pwszDll [I] The DLL that is to be registered.
626 * pszOverrideFuncName [I] Name of the function in the DLL.
628 * RETURNS
629 * Success: TRUE.
630 * Failure: FALSE. (Look at GetLastError()).
632 * NOTES
633 * Registry errors are always reported via SetLastError().
635 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
636 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
638 LONG r;
639 HKEY hKey;
640 LPSTR szKey;
642 TRACE("(%x, %s, %s, %s, %s)\n", dwEncodingType, debugstr_a(pszFuncName),
643 debugstr_a(pszOID), debugstr_w(pwszDll), debugstr_a(pszOverrideFuncName));
645 /* Native does nothing pwszDll is NULL */
646 if (!pwszDll)
647 return TRUE;
649 /* I'm not matching MS bug for bug here, because I doubt any app depends on
650 * it: native "succeeds" if pszFuncName is NULL, but the nonsensical entry
651 * it creates would never be used.
653 if (!pszFuncName || !pszOID)
655 SetLastError(E_INVALIDARG);
656 return FALSE;
659 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
660 TRACE("Key name is %s\n", debugstr_a(szKey));
662 if (!szKey)
663 return FALSE;
665 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
666 CryptMemFree(szKey);
668 if (r != ERROR_SUCCESS) goto error_close_key;
670 /* write the values */
671 if (pszOverrideFuncName)
673 r = RegSetValueExA(hKey, "FuncName", 0, REG_SZ,
674 (const BYTE*)pszOverrideFuncName, lstrlenA(pszOverrideFuncName) + 1);
675 if (r != ERROR_SUCCESS) goto error_close_key;
677 r = RegSetValueExW(hKey, L"Dll", 0, REG_SZ, (const BYTE*) pwszDll,
678 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
680 error_close_key:
682 RegCloseKey(hKey);
684 if (r != ERROR_SUCCESS)
686 SetLastError(r);
687 return FALSE;
690 return TRUE;
693 /***********************************************************************
694 * CryptUnregisterOIDInfo (CRYPT32.@)
696 BOOL WINAPI CryptUnregisterOIDInfo(PCCRYPT_OID_INFO info)
698 char *key_name;
699 HKEY root;
700 DWORD err;
702 TRACE("(%p)\n", info);
704 if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
706 SetLastError(E_INVALIDARG);
707 return FALSE;
710 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo", 0, KEY_ALL_ACCESS, &root);
711 if (err != ERROR_SUCCESS)
713 SetLastError(err);
714 return FALSE;
717 key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
718 if (key_name)
720 sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
721 err = RegDeleteKeyA(root, key_name);
723 else
724 err = ERROR_OUTOFMEMORY;
726 CryptMemFree(key_name);
727 RegCloseKey(root);
729 if (err)
730 SetLastError(err);
732 return !err;
735 /***********************************************************************
736 * CryptRegisterOIDInfo (CRYPT32.@)
738 BOOL WINAPI CryptRegisterOIDInfo(PCCRYPT_OID_INFO info, DWORD flags)
740 char *key_name;
741 HKEY root = 0, key = 0;
742 DWORD err;
744 TRACE("(%p, %x)\n", info, flags );
746 if (!info || info->cbSize != sizeof(*info) || !info->pszOID)
748 SetLastError(E_INVALIDARG);
749 return FALSE;
752 if (!info->dwGroupId) return TRUE;
754 key_name = CryptMemAlloc(strlen(info->pszOID) + 16);
755 if (!key_name)
757 err = ERROR_OUTOFMEMORY;
758 goto done;
761 err = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
762 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root, NULL);
763 if (err != ERROR_SUCCESS) goto done;
765 sprintf(key_name, "%s!%u", info->pszOID, info->dwGroupId);
766 err = RegCreateKeyA(root, key_name, &key);
767 if (err != ERROR_SUCCESS) goto done;
769 if (flags)
771 err = RegSetValueExW(key, L"Flags", 0, REG_DWORD, (const BYTE *)&flags, sizeof(flags));
772 if (err != ERROR_SUCCESS) goto done;
775 if (info->pwszName)
777 err = RegSetValueExW(key, L"Name", 0, REG_SZ, (const BYTE *)info->pwszName, (lstrlenW(info->pwszName) + 1) * sizeof(WCHAR));
778 if (err != ERROR_SUCCESS) goto done;
781 if (info->u.Algid)
783 err = RegSetValueExW(key, L"Algid", 0, REG_DWORD, (const BYTE *)&info->u.Algid, sizeof(info->u.Algid));
784 if (err != ERROR_SUCCESS) goto done;
787 if (info->ExtraInfo.cbData && info->ExtraInfo.pbData)
789 err = RegSetValueExW(key, L"ExtraInfo", 0, REG_BINARY, info->ExtraInfo.pbData, info->ExtraInfo.cbData);
790 if (err != ERROR_SUCCESS) goto done;
793 if (info->pwszCNGAlgid)
795 err = RegSetValueExW(key, L"CNGAlgid", 0, REG_SZ, (const BYTE *)info->pwszCNGAlgid, (lstrlenW(info->pwszCNGAlgid) + 1) * sizeof(WCHAR));
796 if (err != ERROR_SUCCESS) goto done;
799 if (info->pwszCNGExtraAlgid)
801 err = RegSetValueExW(key, L"CNGExtraAlgid", 0, REG_SZ, (const BYTE *)info->pwszCNGExtraAlgid, (lstrlenW(info->pwszCNGExtraAlgid) + 1) * sizeof(WCHAR));
802 if (err != ERROR_SUCCESS) goto done;
805 done:
806 CryptMemFree(key_name);
807 if (key) RegCloseKey(key);
808 if (root) RegCloseKey(root);
810 if (err)
811 SetLastError(err);
813 return !err;
816 /***********************************************************************
817 * CryptUnregisterOIDFunction (CRYPT32.@)
819 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
820 LPCSTR pszOID)
822 LPSTR szKey;
823 LONG rc;
825 TRACE("%x %s %s\n", dwEncodingType, debugstr_a(pszFuncName),
826 debugstr_a(pszOID));
828 if (!pszFuncName || !pszOID)
830 SetLastError(ERROR_INVALID_PARAMETER);
831 return FALSE;
834 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
835 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
836 CryptMemFree(szKey);
837 if (rc)
838 SetLastError(rc);
839 return !rc;
842 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
843 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
844 DWORD *pcbValueData)
846 LPSTR szKey;
847 LONG rc;
848 HKEY hKey;
850 TRACE("%x %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
851 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
852 pcbValueData);
854 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
855 return TRUE;
857 if (!pszFuncName || !pszOID || !pwszValueName)
859 SetLastError(ERROR_INVALID_PARAMETER);
860 return FALSE;
863 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
864 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
865 CryptMemFree(szKey);
866 if (rc)
867 SetLastError(rc);
868 else
870 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
871 pbValueData, pcbValueData);
872 if (rc)
873 SetLastError(rc);
874 RegCloseKey(hKey);
876 return !rc;
879 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
880 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
881 const BYTE *pbValueData, DWORD cbValueData)
883 LPSTR szKey;
884 LONG rc;
885 HKEY hKey;
887 TRACE("%x %s %s %s %d %p %d\n", dwEncodingType, debugstr_a(pszFuncName),
888 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
889 cbValueData);
891 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
892 return TRUE;
894 if (!pszFuncName || !pszOID || !pwszValueName)
896 SetLastError(ERROR_INVALID_PARAMETER);
897 return FALSE;
900 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
901 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
902 CryptMemFree(szKey);
903 if (rc)
904 SetLastError(rc);
905 else
907 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
908 cbValueData);
909 if (rc)
910 SetLastError(rc);
911 RegCloseKey(hKey);
913 return !rc;
916 static LPCWSTR CRYPT_FindStringInMultiString(LPCWSTR multi, LPCWSTR toFind)
918 LPCWSTR ret = NULL, ptr;
920 for (ptr = multi; ptr && *ptr && !ret; ptr += lstrlenW(ptr) + 1)
922 if (!lstrcmpiW(ptr, toFind))
923 ret = ptr;
925 return ret;
928 static DWORD CRYPT_GetMultiStringCharacterLen(LPCWSTR multi)
930 DWORD ret;
932 if (multi)
934 LPCWSTR ptr;
936 /* Count terminating empty string */
937 ret = 1;
938 for (ptr = multi; *ptr; ptr += lstrlenW(ptr) + 1)
939 ret += lstrlenW(ptr) + 1;
941 else
942 ret = 0;
943 return ret;
946 static LPWSTR CRYPT_AddStringToMultiString(LPWSTR multi, LPCWSTR toAdd,
947 DWORD index)
949 LPWSTR ret;
951 if (!multi)
953 /* FIXME: ignoring index, is that okay? */
954 ret = CryptMemAlloc((lstrlenW(toAdd) + 2) * sizeof(WCHAR));
955 if (ret)
957 /* copy string, including NULL terminator */
958 memcpy(ret, toAdd, (lstrlenW(toAdd) + 1) * sizeof(WCHAR));
959 /* add terminating empty string */
960 *(ret + lstrlenW(toAdd) + 1) = 0;
963 else
965 DWORD len = CRYPT_GetMultiStringCharacterLen(multi);
967 ret = CryptMemRealloc(multi, (len + lstrlenW(toAdd) + 1) *
968 sizeof(WCHAR));
969 if (ret)
971 LPWSTR spotToAdd;
973 if (index == CRYPT_REGISTER_LAST_INDEX)
974 spotToAdd = ret + len - 1;
975 else
977 DWORD i;
979 /* FIXME: if index is too large for the string, toAdd is
980 * added to the end. Is that okay?
982 for (i = 0, spotToAdd = ret; i < index && *spotToAdd;
983 spotToAdd += lstrlenW(spotToAdd) + 1)
986 if (spotToAdd)
988 /* Copy existing string "right" */
989 memmove(spotToAdd + lstrlenW(toAdd) + 1, spotToAdd,
990 (len - (spotToAdd - ret)) * sizeof(WCHAR));
991 /* Copy new string */
992 memcpy(spotToAdd, toAdd, (lstrlenW(toAdd) + 1) * sizeof(WCHAR));
994 else
996 CryptMemFree(ret);
997 ret = NULL;
1001 return ret;
1004 static BOOL CRYPT_RemoveStringFromMultiString(LPWSTR multi, LPCWSTR toRemove)
1006 LPWSTR spotToRemove = (LPWSTR)CRYPT_FindStringInMultiString(multi,
1007 toRemove);
1008 BOOL ret;
1010 if (spotToRemove)
1012 DWORD len = CRYPT_GetMultiStringCharacterLen(multi);
1014 if (spotToRemove + lstrlenW(toRemove) + 2 >= multi + len)
1016 /* Removing last string in list, terminate multi string directly */
1017 *spotToRemove = 0;
1018 *(spotToRemove + 1) = 0;
1020 else
1022 LPCWSTR nextStr = spotToRemove + lstrlenW(toRemove) + 1;
1024 /* Copy remainder of string "left" */
1025 memmove(spotToRemove, nextStr,
1026 (len - (nextStr - multi)) * sizeof(WCHAR));
1028 ret = TRUE;
1030 else
1032 SetLastError(ERROR_FILE_NOT_FOUND);
1033 ret = FALSE;
1035 return ret;
1038 static BOOL CRYPT_GetDefaultOIDKey(DWORD dwEncodingType, LPCSTR pszFuncName,
1039 PHKEY key)
1041 LPSTR keyName;
1042 LONG r;
1044 keyName = CRYPT_GetKeyName(dwEncodingType, pszFuncName, "DEFAULT");
1045 TRACE("Key name is %s\n", debugstr_a(keyName));
1047 if (!keyName)
1048 return FALSE;
1050 r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, NULL, 0, KEY_ALL_ACCESS,
1051 NULL, key, NULL);
1052 CryptMemFree(keyName);
1053 if (r != ERROR_SUCCESS)
1055 SetLastError(r);
1056 return FALSE;
1058 return TRUE;
1061 static LPWSTR CRYPT_GetDefaultOIDDlls(HKEY key)
1063 LONG r;
1064 DWORD type, size;
1065 LPWSTR dlls;
1067 r = RegQueryValueExW(key, L"Dll", NULL, &type, NULL, &size);
1068 if (r == ERROR_SUCCESS && type == REG_MULTI_SZ)
1070 dlls = CryptMemAlloc(size);
1071 r = RegQueryValueExW(key, L"Dll", NULL, &type, (LPBYTE)dlls, &size);
1072 if (r != ERROR_SUCCESS)
1074 CryptMemFree(dlls);
1075 dlls = NULL;
1078 else
1079 dlls = NULL;
1080 return dlls;
1083 static inline BOOL CRYPT_SetDefaultOIDDlls(HKEY key, LPCWSTR dlls)
1085 DWORD len = CRYPT_GetMultiStringCharacterLen(dlls);
1086 LONG r;
1088 if ((r = RegSetValueExW(key, L"Dll", 0, REG_MULTI_SZ, (const BYTE *)dlls,
1089 len * sizeof (WCHAR))))
1090 SetLastError(r);
1091 return r == ERROR_SUCCESS;
1094 /***********************************************************************
1095 * CryptRegisterDefaultOIDFunction (CRYPT32.@)
1097 BOOL WINAPI CryptRegisterDefaultOIDFunction(DWORD dwEncodingType,
1098 LPCSTR pszFuncName, DWORD dwIndex, LPCWSTR pwszDll)
1100 HKEY key;
1101 LPWSTR dlls;
1102 BOOL ret = FALSE;
1104 TRACE("(%x, %s, %d, %s)\n", dwEncodingType, debugstr_a(pszFuncName),
1105 dwIndex, debugstr_w(pwszDll));
1107 if (!pwszDll)
1109 SetLastError(E_INVALIDARG);
1110 return FALSE;
1113 if (!CRYPT_GetDefaultOIDKey(dwEncodingType, pszFuncName, &key))
1114 return FALSE;
1116 dlls = CRYPT_GetDefaultOIDDlls(key);
1117 if (CRYPT_FindStringInMultiString(dlls, pwszDll))
1118 SetLastError(ERROR_FILE_EXISTS);
1119 else
1121 dlls = CRYPT_AddStringToMultiString(dlls, pwszDll, dwIndex);
1122 if (dlls)
1123 ret = CRYPT_SetDefaultOIDDlls(key, dlls);
1125 CryptMemFree(dlls);
1126 RegCloseKey(key);
1127 return ret;
1130 BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType,
1131 LPCSTR pszFuncName, LPCWSTR pwszDll)
1133 HKEY key;
1134 LPWSTR dlls;
1135 BOOL ret;
1137 TRACE("(%x, %s, %s)\n", dwEncodingType, debugstr_a(pszFuncName),
1138 debugstr_w(pwszDll));
1140 if (!pwszDll)
1142 SetLastError(E_INVALIDARG);
1143 return FALSE;
1146 if (!CRYPT_GetDefaultOIDKey(dwEncodingType, pszFuncName, &key))
1147 return FALSE;
1149 dlls = CRYPT_GetDefaultOIDDlls(key);
1150 if ((ret = CRYPT_RemoveStringFromMultiString(dlls, pwszDll)))
1151 ret = CRYPT_SetDefaultOIDDlls(key, dlls);
1152 CryptMemFree(dlls);
1153 RegCloseKey(key);
1154 return ret;
1157 static void oid_init_localizednames(void)
1159 unsigned int i;
1161 for(i = 0; i < ARRAY_SIZE(LocalizedKeys); i++)
1163 LoadStringW(hInstance, IDS_LOCALIZEDNAME_ROOT+i, LocalizedNames[i], 256);
1167 /********************************************************************
1168 * CryptFindLocalizedName (CRYPT32.@)
1170 LPCWSTR WINAPI CryptFindLocalizedName(LPCWSTR pwszCryptName)
1172 unsigned int i;
1174 for(i = 0; i < ARRAY_SIZE(LocalizedKeys); i++)
1176 if(!lstrcmpiW(LocalizedKeys[i], pwszCryptName))
1178 return LocalizedNames[i];
1182 FIXME("No name for: %s - stub\n",debugstr_w(pwszCryptName));
1183 return NULL;
1186 static CRITICAL_SECTION oidInfoCS;
1187 static CRITICAL_SECTION_DEBUG oidInfoCSDebug =
1189 0, 0, &oidInfoCS,
1190 { &oidInfoCSDebug.ProcessLocksList, &oidInfoCSDebug.ProcessLocksList },
1191 0, 0, { (DWORD_PTR)(__FILE__ ": oidInfoCS") }
1193 static CRITICAL_SECTION oidInfoCS = { &oidInfoCSDebug, -1, 0, 0, 0, 0 };
1194 static struct list oidInfo = { &oidInfo, &oidInfo };
1196 static const DWORD noNullFlag = CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
1197 static const DWORD mosaicFlags = CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
1198 CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
1199 static const CRYPT_DATA_BLOB noNullBlob = { sizeof(noNullFlag),
1200 (LPBYTE)&noNullFlag };
1201 static const CRYPT_DATA_BLOB mosaicFlagsBlob = { sizeof(mosaicFlags),
1202 (LPBYTE)&mosaicFlags };
1204 static const DWORD rsaSign = CALG_RSA_SIGN;
1205 static const DWORD dssSign[2] = { CALG_DSS_SIGN,
1206 CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG };
1207 static const DWORD mosaicSign[2] = { CALG_DSS_SIGN,
1208 CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
1209 CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG };
1210 static const DWORD ecdsaSign[2] = { CALG_OID_INFO_PARAMETERS, CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG };
1211 static const CRYPT_DATA_BLOB rsaSignBlob = { sizeof(rsaSign),
1212 (LPBYTE)&rsaSign };
1213 static const CRYPT_DATA_BLOB dssSignBlob = { sizeof(dssSign),
1214 (LPBYTE)dssSign };
1215 static const CRYPT_DATA_BLOB mosaicSignBlob = { sizeof(mosaicSign),
1216 (LPBYTE)mosaicSign };
1217 static const CRYPT_DATA_BLOB ecdsaSignBlob = { sizeof(ecdsaSign), (BYTE *)ecdsaSign };
1219 static const DWORD ia5String[] = { CERT_RDN_IA5_STRING, 0 };
1220 static const DWORD numericString[] = { CERT_RDN_NUMERIC_STRING, 0 };
1221 static const DWORD printableString[] = { CERT_RDN_PRINTABLE_STRING, 0 };
1222 static const DWORD domainCompTypes[] = { CERT_RDN_IA5_STRING,
1223 CERT_RDN_UTF8_STRING, 0 };
1224 static const CRYPT_DATA_BLOB ia5StringBlob = { sizeof(ia5String),
1225 (LPBYTE)ia5String };
1226 static const CRYPT_DATA_BLOB numericStringBlob = { sizeof(numericString),
1227 (LPBYTE)numericString };
1228 static const CRYPT_DATA_BLOB printableStringBlob = { sizeof(printableString),
1229 (LPBYTE)printableString };
1230 static const CRYPT_DATA_BLOB domainCompTypesBlob = { sizeof(domainCompTypes),
1231 (LPBYTE)domainCompTypes };
1233 static const struct OIDInfoConstructor {
1234 DWORD dwGroupId;
1235 LPCSTR pszOID;
1236 UINT Algid;
1237 LPCWSTR pwszName;
1238 const CRYPT_DATA_BLOB *blob;
1239 const WCHAR *pwszCNGAlgid;
1240 const WCHAR *pwszCNGExtraAlgid;
1241 } oidInfoConstructors[] = {
1242 { 1, szOID_OIWSEC_sha1, CALG_SHA1, L"sha1", NULL },
1243 { 1, szOID_OIWSEC_sha1, CALG_SHA1, L"sha", NULL },
1244 { 1, szOID_OIWSEC_sha, CALG_SHA, L"sha", NULL },
1245 { 1, szOID_RSA_MD5, CALG_MD5, L"md5", NULL },
1246 { 1, szOID_RSA_MD4, CALG_MD4, L"md4", NULL },
1247 { 1, szOID_RSA_MD2, CALG_MD2, L"md2", NULL },
1248 /* NOTE: Windows Vista+ uses -1 instead of CALG_SHA_* following SHA entries. */
1249 { 1, szOID_NIST_sha256, CALG_SHA_256, L"sha256", NULL },
1250 { 1, szOID_NIST_sha384, CALG_SHA_384, L"sha384", NULL },
1251 { 1, szOID_NIST_sha512, CALG_SHA_512, L"sha512", NULL },
1253 { 2, szOID_OIWSEC_desCBC, CALG_DES, L"des", NULL },
1254 { 2, szOID_RSA_DES_EDE3_CBC, CALG_3DES, L"3des", NULL },
1255 { 2, szOID_RSA_RC2CBC, CALG_RC2, L"rc2", NULL },
1256 { 2, szOID_RSA_RC4, CALG_RC4, L"rc4", NULL },
1257 { 2, szOID_RSA_SMIMEalgCMS3DESwrap, CALG_3DES, L"CMS3DESwrap", NULL },
1258 { 2, szOID_RSA_SMIMEalgCMSRC2wrap, CALG_RC2, L"CMSRC2wrap", NULL },
1260 { 3, szOID_RSA_RSA, CALG_RSA_KEYX, L"RSA", NULL },
1261 { 3, szOID_X957_DSA, CALG_DSS_SIGN, L"DSA", &noNullBlob },
1262 { 3, szOID_ANSI_X942_DH, CALG_DH_SF, L"DH", &noNullBlob },
1263 { 3, szOID_RSA_RSA, CALG_RSA_KEYX, L"RSA_KEYX", NULL },
1264 { 3, szOID_RSA_RSA, CALG_RSA_SIGN, L"RSA", NULL },
1265 { 3, szOID_RSA_RSA, CALG_RSA_SIGN, L"RSA_SIGN", NULL },
1266 { 3, szOID_OIWSEC_dsa, CALG_DSS_SIGN, L"DSA", &noNullBlob },
1267 { 3, szOID_OIWSEC_dsa, CALG_DSS_SIGN, L"DSS", &noNullBlob },
1268 { 3, szOID_OIWSEC_dsa, CALG_DSS_SIGN, L"DSA_SIGN", &noNullBlob },
1269 { 3, szOID_RSA_DH, CALG_DH_SF, L"DH", &noNullBlob },
1270 { 3, szOID_OIWSEC_rsaXchg, CALG_RSA_KEYX, L"RSA_KEYX", NULL },
1271 { 3, szOID_INFOSEC_mosaicKMandUpdSig, CALG_DSS_SIGN, L"mosaicKMandUpdSig", &mosaicFlagsBlob },
1272 { 3, szOID_RSA_SMIMEalgESDH, CALG_DH_EPHEM, L"ESDH", &noNullBlob },
1273 { 3, szOID_PKIX_NO_SIGNATURE, CALG_NO_SIGN, L"NOSIGN", NULL },
1275 { 4, szOID_RSA_SHA1RSA, CALG_SHA1, L"sha1RSA", &rsaSignBlob },
1276 { 4, szOID_RSA_SHA256RSA, CALG_SHA_256, L"sha256RSA", &rsaSignBlob },
1277 { 4, szOID_RSA_SHA384RSA, CALG_SHA_384, L"sha384RSA", &rsaSignBlob },
1278 { 4, szOID_RSA_SHA512RSA, CALG_SHA_512, L"sha512RSA", &rsaSignBlob },
1279 { 4, szOID_RSA_MD5RSA, CALG_MD5, L"md5RSA", &rsaSignBlob },
1280 { 4, szOID_X957_SHA1DSA, CALG_SHA1, L"sha1DSA", &dssSignBlob },
1281 { 4, szOID_OIWSEC_sha1RSASign, CALG_SHA1, L"sha1RSA", &rsaSignBlob },
1282 { 4, szOID_OIWSEC_sha1RSASign, CALG_SHA1, L"shaRSA", &rsaSignBlob },
1283 { 4, szOID_OIWSEC_shaRSA, CALG_SHA1, L"shaRSA", &rsaSignBlob },
1284 { 4, szOID_OIWSEC_md5RSA, CALG_MD5, L"md5RSA", &rsaSignBlob },
1285 { 4, szOID_RSA_MD2RSA, CALG_MD2, L"md2RSA", &rsaSignBlob },
1286 { 4, szOID_RSA_MD4RSA, CALG_MD4, L"md4RSA", &rsaSignBlob },
1287 { 4, szOID_OIWSEC_md4RSA, CALG_MD4, L"md4RSA", &rsaSignBlob },
1288 { 4, szOID_OIWSEC_md4RSA2, CALG_MD4, L"md4RSA", &rsaSignBlob },
1289 { 4, szOID_OIWDIR_md2RSA, CALG_MD2, L"md2RSA", &rsaSignBlob },
1290 { 4, szOID_OIWSEC_shaDSA, CALG_SHA1, L"sha1DSA", &dssSignBlob },
1291 { 4, szOID_OIWSEC_shaDSA, CALG_SHA1, L"shaDSA", &dssSignBlob },
1292 { 4, szOID_OIWSEC_dsaSHA1, CALG_SHA1, L"dsaSHA1", &dssSignBlob },
1293 { 4, szOID_INFOSEC_mosaicUpdatedSig, CALG_SHA1, L"mosaicUpdatedSig", &mosaicSignBlob },
1294 { 4, szOID_ECDSA_SHA256, CALG_OID_INFO_CNG_ONLY, L"sha256ECDSA", &ecdsaSignBlob,
1295 BCRYPT_SHA256_ALGORITHM, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM },
1296 { 4, szOID_ECDSA_SHA384, CALG_OID_INFO_CNG_ONLY, L"sha384ECDSA", &ecdsaSignBlob,
1297 BCRYPT_SHA384_ALGORITHM, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM },
1299 { 5, szOID_COMMON_NAME, 0, L"CN", NULL },
1300 { 5, szOID_LOCALITY_NAME, 0, L"L", NULL },
1301 { 5, szOID_ORGANIZATION_NAME, 0, L"O", NULL },
1302 { 5, szOID_ORGANIZATIONAL_UNIT_NAME, 0, L"OU", NULL },
1303 { 5, szOID_RSA_emailAddr, 0, L"E", &ia5StringBlob },
1304 { 5, szOID_RSA_emailAddr, 0, L"Email", &ia5StringBlob },
1305 { 5, szOID_COUNTRY_NAME, 0, L"C", &printableStringBlob },
1306 { 5, szOID_STATE_OR_PROVINCE_NAME, 0, L"S", NULL },
1307 { 5, szOID_STATE_OR_PROVINCE_NAME, 0, L"ST", NULL },
1308 { 5, szOID_STREET_ADDRESS, 0, L"STREET", NULL },
1309 { 5, szOID_TITLE, 0, L"T", NULL },
1310 { 5, szOID_TITLE, 0, L"Title", NULL },
1311 { 5, szOID_GIVEN_NAME, 0, L"G", NULL },
1312 { 5, szOID_GIVEN_NAME, 0, L"GN", NULL },
1313 { 5, szOID_GIVEN_NAME, 0, L"GivenName", NULL },
1314 { 5, szOID_INITIALS, 0, L"I", NULL },
1315 { 5, szOID_INITIALS, 0, L"Initials", NULL },
1316 { 5, szOID_SUR_NAME, 0, L"SN", NULL },
1317 { 5, szOID_DOMAIN_COMPONENT, 0, L"DC", &domainCompTypesBlob },
1318 { 5, szOID_DESCRIPTION, 0, L"Description", NULL },
1319 { 5, szOID_POSTAL_CODE, 0, L"PostalCode", NULL },
1320 { 5, szOID_POST_OFFICE_BOX, 0, L"POBox", NULL },
1321 { 5, szOID_TELEPHONE_NUMBER, 0, L"Phone", &printableStringBlob },
1322 { 5, szOID_X21_ADDRESS, 0, L"X21Address", &numericStringBlob },
1323 { 5, szOID_DN_QUALIFIER, 0, L"dnQualifier", NULL },
1324 { 5, szOID_DEVICE_SERIAL_NUMBER, 0, L"SERIALNUMBER", NULL },
1326 { 6, szOID_AUTHORITY_KEY_IDENTIFIER2, 0, (LPCWSTR)IDS_AUTHORITY_KEY_ID, NULL },
1327 { 6, szOID_AUTHORITY_KEY_IDENTIFIER, 0, (LPCWSTR)IDS_AUTHORITY_KEY_ID, NULL },
1328 { 6, szOID_KEY_ATTRIBUTES, 0, (LPCWSTR)IDS_KEY_ATTRIBUTES, NULL },
1329 { 6, szOID_KEY_USAGE_RESTRICTION, 0, (LPCWSTR)IDS_KEY_USAGE_RESTRICTION, NULL },
1330 { 6, szOID_SUBJECT_ALT_NAME2, 0, (LPCWSTR)IDS_SUBJECT_ALT_NAME, NULL },
1331 { 6, szOID_SUBJECT_ALT_NAME, 0, (LPCWSTR)IDS_SUBJECT_ALT_NAME, NULL },
1332 { 6, szOID_ISSUER_ALT_NAME2, 0, (LPCWSTR)IDS_ISSUER_ALT_NAME, NULL },
1333 { 6, szOID_ISSUER_ALT_NAME2, 0, (LPCWSTR)IDS_ISSUER_ALT_NAME, NULL },
1334 { 6, szOID_BASIC_CONSTRAINTS2, 0, (LPCWSTR)IDS_BASIC_CONSTRAINTS, NULL },
1335 { 6, szOID_BASIC_CONSTRAINTS, 0, (LPCWSTR)IDS_BASIC_CONSTRAINTS, NULL },
1336 { 6, szOID_KEY_USAGE, 0, (LPCWSTR)IDS_KEY_USAGE, NULL },
1337 { 6, szOID_CERT_POLICIES, 0, (LPCWSTR)IDS_CERT_POLICIES, NULL },
1338 { 6, szOID_SUBJECT_KEY_IDENTIFIER, 0, (LPCWSTR)IDS_SUBJECT_KEY_IDENTIFIER, NULL },
1339 { 6, szOID_CRL_REASON_CODE, 0, (LPCWSTR)IDS_CRL_REASON_CODE, NULL },
1340 { 6, szOID_CRL_DIST_POINTS, 0, (LPCWSTR)IDS_CRL_DIST_POINTS, NULL },
1341 { 6, szOID_ENHANCED_KEY_USAGE, 0, (LPCWSTR)IDS_ENHANCED_KEY_USAGE, NULL },
1342 { 6, szOID_AUTHORITY_INFO_ACCESS, 0, (LPCWSTR)IDS_AUTHORITY_INFO_ACCESS, NULL },
1343 { 6, szOID_CERT_EXTENSIONS, 0, (LPCWSTR)IDS_CERT_EXTENSIONS, NULL },
1344 { 6, szOID_RSA_certExtensions, 0, (LPCWSTR)IDS_CERT_EXTENSIONS, NULL },
1345 { 6, szOID_NEXT_UPDATE_LOCATION, 0, (LPCWSTR)IDS_NEXT_UPDATE_LOCATION, NULL },
1346 { 6, szOID_YESNO_TRUST_ATTR, 0, (LPCWSTR)IDS_YES_OR_NO_TRUST, NULL },
1347 { 6, szOID_RSA_emailAddr, 0, (LPCWSTR)IDS_EMAIL_ADDRESS, NULL },
1348 { 6, szOID_RSA_unstructName, 0, (LPCWSTR)IDS_UNSTRUCTURED_NAME, NULL },
1349 { 6, szOID_RSA_contentType, 0, (LPCWSTR)IDS_CONTENT_TYPE, NULL },
1350 { 6, szOID_RSA_messageDigest, 0, (LPCWSTR)IDS_MESSAGE_DIGEST, NULL },
1351 { 6, szOID_RSA_signingTime, 0, (LPCWSTR)IDS_SIGNING_TIME, NULL },
1352 { 6, szOID_RSA_counterSign, 0, (LPCWSTR)IDS_COUNTER_SIGN, NULL },
1353 { 6, szOID_RSA_challengePwd, 0, (LPCWSTR)IDS_CHALLENGE_PASSWORD, NULL },
1354 { 6, szOID_RSA_unstructAddr, 0, (LPCWSTR)IDS_UNSTRUCTURED_ADDRESS, NULL },
1355 { 6, szOID_RSA_SMIMECapabilities, 0, (LPCWSTR)IDS_SMIME_CAPABILITIES, NULL },
1356 { 6, szOID_RSA_preferSignedData, 0, (LPCWSTR)IDS_PREFER_SIGNED_DATA, NULL },
1357 { 6, szOID_PKIX_POLICY_QUALIFIER_CPS, 0, (LPCWSTR)IDS_CPS, NULL },
1358 { 6, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE, 0, (LPCWSTR)IDS_USER_NOTICE, NULL },
1359 { 6, szOID_PKIX_OCSP, 0, (LPCWSTR)IDS_OCSP, NULL },
1360 { 6, szOID_PKIX_CA_ISSUERS, 0, (LPCWSTR)IDS_CA_ISSUER, NULL },
1361 { 6, szOID_ENROLL_CERTTYPE_EXTENSION, 0, (LPCWSTR)IDS_CERT_TEMPLATE_NAME, NULL },
1362 { 6, szOID_ENROLL_CERTTYPE_EXTENSION, 0, (LPCWSTR)IDS_CERT_TYPE, NULL },
1363 { 6, szOID_CERT_MANIFOLD, 0, (LPCWSTR)IDS_CERT_MANIFOLD, NULL },
1364 { 6, szOID_NETSCAPE_CERT_TYPE, 0, (LPCWSTR)IDS_NETSCAPE_CERT_TYPE, NULL },
1365 { 6, szOID_NETSCAPE_BASE_URL, 0, (LPCWSTR)IDS_NETSCAPE_BASE_URL, NULL },
1366 { 6, szOID_NETSCAPE_REVOCATION_URL, 0, (LPCWSTR)IDS_NETSCAPE_REVOCATION_URL, NULL },
1367 { 6, szOID_NETSCAPE_CA_REVOCATION_URL, 0, (LPCWSTR)IDS_NETSCAPE_CA_REVOCATION_URL, NULL },
1368 { 6, szOID_NETSCAPE_CERT_RENEWAL_URL, 0, (LPCWSTR)IDS_NETSCAPE_CERT_RENEWAL_URL, NULL },
1369 { 6, szOID_NETSCAPE_CA_POLICY_URL, 0, (LPCWSTR)IDS_NETSCAPE_CA_POLICY_URL, NULL },
1370 { 6, szOID_NETSCAPE_SSL_SERVER_NAME, 0, (LPCWSTR)IDS_NETSCAPE_SSL_SERVER_NAME, NULL },
1371 { 6, szOID_NETSCAPE_COMMENT, 0, (LPCWSTR)IDS_NETSCAPE_COMMENT, NULL },
1372 { 6, "1.3.6.1.4.1.311.2.1.10", 0, L"SpcSpAgencyInfo", NULL },
1373 { 6, "1.3.6.1.4.1.311.2.1.27", 0, L"SpcFinancialCriteria", NULL },
1374 { 6, "1.3.6.1.4.1.311.2.1.26", 0, L"SpcMinimalCriteria", NULL },
1375 { 6, szOID_COUNTRY_NAME, 0, (LPCWSTR)IDS_COUNTRY, NULL },
1376 { 6, szOID_ORGANIZATION_NAME, 0, (LPCWSTR)IDS_ORGANIZATION, NULL },
1377 { 6, szOID_ORGANIZATIONAL_UNIT_NAME, 0, (LPCWSTR)IDS_ORGANIZATIONAL_UNIT, NULL },
1378 { 6, szOID_COMMON_NAME, 0, (LPCWSTR)IDS_COMMON_NAME, NULL },
1379 { 6, szOID_LOCALITY_NAME, 0, (LPCWSTR)IDS_LOCALITY, NULL },
1380 { 6, szOID_STATE_OR_PROVINCE_NAME, 0, (LPCWSTR)IDS_STATE_OR_PROVINCE, NULL },
1381 { 6, szOID_TITLE, 0, (LPCWSTR)IDS_TITLE, NULL },
1382 { 6, szOID_GIVEN_NAME, 0, (LPCWSTR)IDS_GIVEN_NAME, NULL },
1383 { 6, szOID_INITIALS, 0, (LPCWSTR)IDS_INITIALS, NULL },
1384 { 6, szOID_SUR_NAME, 0, (LPCWSTR)IDS_SUR_NAME, NULL },
1385 { 6, szOID_DOMAIN_COMPONENT, 0, (LPCWSTR)IDS_DOMAIN_COMPONENT, NULL },
1386 { 6, szOID_STREET_ADDRESS, 0, (LPCWSTR)IDS_STREET_ADDRESS, NULL },
1387 { 6, szOID_DEVICE_SERIAL_NUMBER, 0, (LPCWSTR)IDS_SERIAL_NUMBER, NULL },
1388 { 6, szOID_CERTSRV_CA_VERSION, 0, (LPCWSTR)IDS_CA_VERSION, NULL },
1389 { 6, szOID_CERTSRV_CROSSCA_VERSION, 0, (LPCWSTR)IDS_CROSS_CA_VERSION, NULL },
1390 { 6, szOID_SERIALIZED, 0, (LPCWSTR)IDS_SERIALIZED_SIG_SERIAL_NUMBER, NULL },
1391 { 6, szOID_NT_PRINCIPAL_NAME, 0, (LPCWSTR)IDS_PRINCIPAL_NAME, NULL },
1392 { 6, szOID_PRODUCT_UPDATE, 0, (LPCWSTR)IDS_WINDOWS_PRODUCT_UPDATE, NULL },
1393 { 6, szOID_ENROLLMENT_NAME_VALUE_PAIR, 0, (LPCWSTR)IDS_ENROLLMENT_NAME_VALUE_PAIR, NULL },
1394 { 6, szOID_OS_VERSION, 0, (LPCWSTR)IDS_OS_VERSION, NULL },
1395 { 6, szOID_ENROLLMENT_CSP_PROVIDER, 0, (LPCWSTR)IDS_ENROLLMENT_CSP, NULL },
1396 { 6, szOID_CRL_NUMBER, 0, (LPCWSTR)IDS_CRL_NUMBER, NULL },
1397 { 6, szOID_DELTA_CRL_INDICATOR, 0, (LPCWSTR)IDS_DELTA_CRL_INDICATOR, NULL },
1398 { 6, szOID_ISSUING_DIST_POINT, 0, (LPCWSTR)IDS_ISSUING_DIST_POINT, NULL },
1399 { 6, szOID_FRESHEST_CRL, 0, (LPCWSTR)IDS_FRESHEST_CRL, NULL },
1400 { 6, szOID_NAME_CONSTRAINTS, 0, (LPCWSTR)IDS_NAME_CONSTRAINTS, NULL },
1401 { 6, szOID_POLICY_MAPPINGS, 0, (LPCWSTR)IDS_POLICY_MAPPINGS, NULL },
1402 { 6, szOID_LEGACY_POLICY_MAPPINGS, 0, (LPCWSTR)IDS_POLICY_MAPPINGS, NULL },
1403 { 6, szOID_POLICY_CONSTRAINTS, 0, (LPCWSTR)IDS_POLICY_CONSTRAINTS, NULL },
1404 { 6, szOID_CROSS_CERT_DIST_POINTS, 0, (LPCWSTR)IDS_CROSS_CERT_DIST_POINTS, NULL },
1405 { 6, szOID_APPLICATION_CERT_POLICIES, 0, (LPCWSTR)IDS_APPLICATION_POLICIES, NULL },
1406 { 6, szOID_APPLICATION_POLICY_MAPPINGS, 0, (LPCWSTR)IDS_APPLICATION_POLICY_MAPPINGS, NULL },
1407 { 6, szOID_APPLICATION_POLICY_CONSTRAINTS, 0, (LPCWSTR)IDS_APPLICATION_POLICY_CONSTRAINTS, NULL },
1408 { 6, szOID_CT_PKI_DATA, 0, (LPCWSTR)IDS_CMC_DATA, NULL },
1409 { 6, szOID_CT_PKI_RESPONSE, 0, (LPCWSTR)IDS_CMC_RESPONSE, NULL },
1410 { 6, szOID_CMC, 0, (LPCWSTR)IDS_UNSIGNED_CMC_REQUEST, NULL },
1411 { 6, szOID_CMC_STATUS_INFO, 0, (LPCWSTR)IDS_CMC_STATUS_INFO, NULL },
1412 { 6, szOID_CMC_ADD_EXTENSIONS, 0, (LPCWSTR)IDS_CMC_EXTENSIONS, NULL },
1413 { 6, szOID_CTL, 0, (LPCWSTR)IDS_CMC_ATTRIBUTES, NULL },
1414 { 6, szOID_RSA_data, 0, (LPCWSTR)IDS_PKCS_7_DATA, NULL },
1415 { 6, szOID_RSA_signedData, 0, (LPCWSTR)IDS_PKCS_7_SIGNED, NULL },
1416 { 6, szOID_RSA_envelopedData, 0, (LPCWSTR)IDS_PKCS_7_ENVELOPED, NULL },
1417 { 6, szOID_RSA_signEnvData, 0, (LPCWSTR)IDS_PKCS_7_SIGNED_ENVELOPED, NULL },
1418 { 6, szOID_RSA_digestedData, 0, (LPCWSTR)IDS_PKCS_7_DIGESTED, NULL },
1419 { 6, szOID_RSA_encryptedData, 0, (LPCWSTR)IDS_PKCS_7_ENCRYPTED, NULL },
1420 { 6, szOID_CERTSRV_PREVIOUS_CERT_HASH, 0, (LPCWSTR)IDS_PREVIOUS_CA_CERT_HASH, NULL },
1421 { 6, szOID_CRL_VIRTUAL_BASE, 0, (LPCWSTR)IDS_CRL_VIRTUAL_BASE, NULL },
1422 { 6, szOID_CRL_NEXT_PUBLISH, 0, (LPCWSTR)IDS_CRL_NEXT_PUBLISH, NULL },
1423 { 6, szOID_KP_CA_EXCHANGE, 0, (LPCWSTR)IDS_CA_EXCHANGE, NULL },
1424 { 6, szOID_KP_KEY_RECOVERY_AGENT, 0, (LPCWSTR)IDS_KEY_RECOVERY_AGENT, NULL },
1425 { 6, szOID_CERTIFICATE_TEMPLATE, 0, (LPCWSTR)IDS_CERTIFICATE_TEMPLATE, NULL },
1426 { 6, szOID_ENTERPRISE_OID_ROOT, 0, (LPCWSTR)IDS_ENTERPRISE_ROOT_OID, NULL },
1427 { 6, szOID_RDN_DUMMY_SIGNER, 0, (LPCWSTR)IDS_RDN_DUMMY_SIGNER, NULL },
1428 { 6, szOID_ARCHIVED_KEY_ATTR, 0, (LPCWSTR)IDS_ARCHIVED_KEY_ATTR, NULL },
1429 { 6, szOID_CRL_SELF_CDP, 0, (LPCWSTR)IDS_CRL_SELF_CDP, NULL },
1430 { 6, szOID_REQUIRE_CERT_CHAIN_POLICY, 0, (LPCWSTR)IDS_REQUIRE_CERT_CHAIN_POLICY, NULL },
1431 { 6, szOID_CMC_TRANSACTION_ID, 0, (LPCWSTR)IDS_TRANSACTION_ID, NULL },
1432 { 6, szOID_CMC_SENDER_NONCE, 0, (LPCWSTR)IDS_SENDER_NONCE, NULL },
1433 { 6, szOID_CMC_RECIPIENT_NONCE, 0, (LPCWSTR)IDS_RECIPIENT_NONCE, NULL },
1434 { 6, szOID_CMC_REG_INFO, 0, (LPCWSTR)IDS_REG_INFO, NULL },
1435 { 6, szOID_CMC_GET_CERT, 0, (LPCWSTR)IDS_GET_CERTIFICATE, NULL },
1436 { 6, szOID_CMC_GET_CRL, 0, (LPCWSTR)IDS_GET_CRL, NULL },
1437 { 6, szOID_CMC_REVOKE_REQUEST, 0, (LPCWSTR)IDS_REVOKE_REQUEST, NULL },
1438 { 6, szOID_CMC_QUERY_PENDING, 0, (LPCWSTR)IDS_QUERY_PENDING, NULL },
1439 { 6, szOID_SORTED_CTL, 0, (LPCWSTR)IDS_SORTED_CTL, NULL },
1440 { 6, szOID_ARCHIVED_KEY_CERT_HASH, 0, (LPCWSTR)IDS_ARCHIVED_KEY_CERT_HASH, NULL },
1441 { 6, szOID_PRIVATEKEY_USAGE_PERIOD, 0, (LPCWSTR)IDS_PRIVATE_KEY_USAGE_PERIOD, NULL },
1442 { 6, szOID_REQUEST_CLIENT_INFO, 0, (LPCWSTR)IDS_CLIENT_INFORMATION, NULL },
1444 { 7, szOID_PKIX_KP_SERVER_AUTH, 0, (LPCWSTR)IDS_SERVER_AUTHENTICATION, NULL },
1445 { 7, szOID_PKIX_KP_CLIENT_AUTH, 0, (LPCWSTR)IDS_CLIENT_AUTHENTICATION, NULL },
1446 { 7, szOID_PKIX_KP_CODE_SIGNING, 0, (LPCWSTR)IDS_CODE_SIGNING, NULL },
1447 { 7, szOID_PKIX_KP_EMAIL_PROTECTION, 0, (LPCWSTR)IDS_SECURE_EMAIL, NULL },
1448 { 7, szOID_PKIX_KP_TIMESTAMP_SIGNING, 0, (LPCWSTR)IDS_TIME_STAMPING, NULL },
1449 { 7, szOID_KP_CTL_USAGE_SIGNING, 0, (LPCWSTR)IDS_MICROSOFT_TRUST_LIST_SIGNING, NULL },
1450 { 7, szOID_KP_TIME_STAMP_SIGNING, 0, (LPCWSTR)IDS_MICROSOFT_TIME_STAMPING, NULL },
1451 { 7, szOID_PKIX_KP_IPSEC_END_SYSTEM, 0, (LPCWSTR)IDS_IPSEC_END_SYSTEM, NULL },
1452 { 7, szOID_PKIX_KP_IPSEC_TUNNEL, 0, (LPCWSTR)IDS_IPSEC_TUNNEL, NULL },
1453 { 7, szOID_PKIX_KP_IPSEC_USER, 0, (LPCWSTR)IDS_IPSEC_USER, NULL },
1454 { 7, szOID_KP_EFS, 0, (LPCWSTR)IDS_EFS, NULL },
1455 { 7, szOID_WHQL_CRYPTO, 0, (LPCWSTR)IDS_WHQL_CRYPTO, NULL },
1456 { 7, szOID_NT5_CRYPTO, 0, (LPCWSTR)IDS_NT5_CRYPTO, NULL },
1457 { 7, szOID_OEM_WHQL_CRYPTO, 0, (LPCWSTR)IDS_OEM_WHQL_CRYPTO, NULL },
1458 { 7, szOID_EMBEDDED_NT_CRYPTO, 0, (LPCWSTR)IDS_EMBEDDED_NT_CRYPTO, NULL },
1459 { 7, szOID_LICENSES, 0, (LPCWSTR)IDS_KEY_PACK_LICENSES, NULL },
1460 { 7, szOID_LICENSE_SERVER, 0, (LPCWSTR)IDS_LICENSE_SERVER, NULL },
1461 { 7, szOID_KP_SMARTCARD_LOGON, 0, (LPCWSTR)IDS_SMART_CARD_LOGON, NULL },
1462 { 7, szOID_DRM, 0, (LPCWSTR)IDS_DIGITAL_RIGHTS, NULL },
1463 { 7, szOID_KP_QUALIFIED_SUBORDINATION, 0, (LPCWSTR)IDS_QUALIFIED_SUBORDINATION, NULL },
1464 { 7, szOID_KP_KEY_RECOVERY, 0, (LPCWSTR)IDS_KEY_RECOVERY, NULL },
1465 { 7, szOID_KP_DOCUMENT_SIGNING, 0, (LPCWSTR)IDS_DOCUMENT_SIGNING, NULL },
1466 { 7, szOID_IPSEC_KP_IKE_INTERMEDIATE, 0, (LPCWSTR)IDS_IPSEC_IKE_INTERMEDIATE, NULL },
1467 { 7, szOID_EFS_RECOVERY, 0, (LPCWSTR)IDS_FILE_RECOVERY, NULL },
1468 { 7, szOID_ROOT_LIST_SIGNER, 0, (LPCWSTR)IDS_ROOT_LIST_SIGNER, NULL },
1469 { 7, szOID_ANY_APPLICATION_POLICY, 0, (LPCWSTR)IDS_ANY_APPLICATION_POLICIES, NULL },
1470 { 7, szOID_DS_EMAIL_REPLICATION, 0, (LPCWSTR)IDS_DS_EMAIL_REPLICATION, NULL },
1471 { 7, szOID_ENROLLMENT_AGENT, 0, (LPCWSTR)IDS_ENROLLMENT_AGENT, NULL },
1472 { 7, szOID_KP_KEY_RECOVERY_AGENT, 0, (LPCWSTR)IDS_KEY_RECOVERY_AGENT, NULL },
1473 { 7, szOID_KP_CA_EXCHANGE, 0, (LPCWSTR)IDS_CA_EXCHANGE, NULL },
1474 { 7, szOID_KP_LIFETIME_SIGNING, 0, (LPCWSTR)IDS_LIFETIME_SIGNING, NULL },
1476 { 8, szOID_ANY_CERT_POLICY, 0, (LPCWSTR)IDS_ANY_CERT_POLICY, NULL },
1479 struct OIDInfo {
1480 CRYPT_OID_INFO info;
1481 struct list entry;
1484 static struct OIDInfo *read_oid_info(HKEY root, char *key_name, DWORD *flags)
1486 HKEY key;
1487 DWORD len, oid_len, name_len = 0, extra_len = 0, cngalgid_len = 0, cngextra_len = 0, group_id = 0;
1488 struct OIDInfo *info;
1489 char *p;
1491 if (RegOpenKeyExA(root, key_name, 0, KEY_READ, &key))
1492 return NULL;
1494 p = strchr(key_name, '!');
1495 if (p)
1497 group_id = strtol(p + 1, NULL, 10);
1498 *p = 0;
1501 oid_len = strlen(key_name) + 1;
1503 RegQueryValueExW(key, L"Name", NULL, NULL, NULL, &name_len);
1504 RegQueryValueExW(key, L"ExtraInfo", NULL, NULL, NULL, &extra_len);
1505 RegQueryValueExW(key, L"CNGAlgid", NULL, NULL, NULL, &cngalgid_len);
1506 RegQueryValueExW(key, L"CNGExtraAlgid", NULL, NULL, NULL, &cngextra_len);
1508 info = CryptMemAlloc(sizeof(*info) + oid_len + name_len + extra_len + cngalgid_len + cngextra_len);
1509 if (info)
1511 *flags = 0;
1512 len = sizeof(*flags);
1513 RegQueryValueExW(key, L"Flags", NULL, NULL, (BYTE *)flags, &len);
1515 memset(info, 0, sizeof(*info));
1516 info->info.cbSize = sizeof(info->info);
1518 p = (char *)(info + 1);
1520 info->info.pszOID = p;
1521 strcpy((char *)info->info.pszOID, key_name);
1522 p += oid_len;
1524 if (name_len)
1526 info->info.pwszName = (WCHAR *)p;
1527 RegQueryValueExW(key, L"Name", NULL, NULL, (BYTE *)info->info.pwszName, &name_len);
1528 p += name_len;
1531 info->info.dwGroupId = group_id;
1533 len = sizeof(info->info.u.Algid);
1534 RegQueryValueExW(key, L"Algid", NULL, NULL, (BYTE *)&info->info.u.Algid, &len);
1536 if (extra_len)
1538 info->info.ExtraInfo.cbData = extra_len;
1539 info->info.ExtraInfo.pbData = (BYTE *)p;
1540 RegQueryValueExW(key, L"ExtraInfo", NULL, NULL, info->info.ExtraInfo.pbData, &extra_len);
1541 p += extra_len;
1544 if (cngalgid_len)
1546 info->info.pwszCNGAlgid = (WCHAR *)p;
1547 RegQueryValueExW(key, L"CNGAlgid", NULL, NULL, (BYTE *)info->info.pwszCNGAlgid, &cngalgid_len);
1548 p += cngalgid_len;
1551 if (cngextra_len)
1553 info->info.pwszCNGExtraAlgid = (WCHAR *)p;
1554 RegQueryValueExW(key, L"CNGExtraAlgid", NULL, NULL, (BYTE *)info->info.pwszCNGExtraAlgid, &cngalgid_len);
1558 RegCloseKey(key);
1560 return info;
1563 static void init_registered_oid_info(void)
1565 DWORD err, idx;
1566 HKEY root;
1568 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllFindOIDInfo",
1569 0, KEY_ALL_ACCESS, &root);
1570 if (err != ERROR_SUCCESS) return;
1572 idx = 0;
1573 for (;;)
1575 char key_name[MAX_PATH];
1576 struct OIDInfo *info;
1577 DWORD flags;
1579 err = RegEnumKeyA(root, idx++, key_name, MAX_PATH);
1580 if (err == ERROR_NO_MORE_ITEMS)
1581 break;
1583 if (err == ERROR_SUCCESS)
1585 if ((info = read_oid_info(root, key_name, &flags)))
1587 TRACE("adding oid %s, name %s, groupid %u, algid %u, extra %u, CNG algid %s, CNG extra %s\n",
1588 debugstr_a(info->info.pszOID), debugstr_w(info->info.pwszName),
1589 info->info.dwGroupId, info->info.u.Algid, info->info.ExtraInfo.cbData,
1590 debugstr_w(info->info.pwszCNGAlgid), debugstr_w(info->info.pwszCNGExtraAlgid));
1592 if (flags & CRYPT_INSTALL_OID_INFO_BEFORE_FLAG)
1593 list_add_head(&oidInfo, &info->entry);
1594 else
1595 list_add_tail(&oidInfo, &info->entry);
1600 RegCloseKey(root);
1603 static void init_oid_info(void)
1605 DWORD i;
1607 oid_init_localizednames();
1608 for (i = 0; i < ARRAY_SIZE(oidInfoConstructors); i++)
1610 if (!IS_INTRESOURCE(oidInfoConstructors[i].pwszName))
1612 struct OIDInfo *info;
1614 /* The name is a static string, so just use the same pointer */
1615 info = CryptMemAlloc(sizeof(struct OIDInfo));
1616 if (info)
1618 memset(info, 0, sizeof(*info));
1619 info->info.cbSize = sizeof(CRYPT_OID_INFO);
1620 info->info.pszOID = oidInfoConstructors[i].pszOID;
1621 info->info.pwszName = oidInfoConstructors[i].pwszName;
1622 info->info.dwGroupId = oidInfoConstructors[i].dwGroupId;
1623 info->info.u.Algid = oidInfoConstructors[i].Algid;
1624 if (oidInfoConstructors[i].blob)
1626 info->info.ExtraInfo.cbData =
1627 oidInfoConstructors[i].blob->cbData;
1628 info->info.ExtraInfo.pbData =
1629 oidInfoConstructors[i].blob->pbData;
1631 info->info.pwszCNGAlgid = oidInfoConstructors[i].pwszCNGAlgid;
1632 info->info.pwszCNGExtraAlgid = oidInfoConstructors[i].pwszCNGExtraAlgid;
1633 list_add_tail(&oidInfo, &info->entry);
1636 else
1638 LPCWSTR stringresource;
1639 int len = LoadStringW(hInstance,
1640 (UINT_PTR)oidInfoConstructors[i].pwszName,
1641 (LPWSTR)&stringresource, 0);
1643 if (len)
1645 struct OIDInfo *info = CryptMemAlloc(sizeof(struct OIDInfo) +
1646 (len + 1) * sizeof(WCHAR));
1648 if (info)
1650 memset(info, 0, sizeof(*info));
1651 info->info.cbSize = sizeof(CRYPT_OID_INFO);
1652 info->info.pszOID = oidInfoConstructors[i].pszOID;
1653 info->info.pwszName = (LPWSTR)(info + 1);
1654 info->info.dwGroupId = oidInfoConstructors[i].dwGroupId;
1655 info->info.u.Algid = oidInfoConstructors[i].Algid;
1656 memcpy(info + 1, stringresource, len*sizeof(WCHAR));
1657 ((LPWSTR)(info + 1))[len] = 0;
1658 if (oidInfoConstructors[i].blob)
1660 info->info.ExtraInfo.cbData =
1661 oidInfoConstructors[i].blob->cbData;
1662 info->info.ExtraInfo.pbData =
1663 oidInfoConstructors[i].blob->pbData;
1665 info->info.pwszCNGAlgid = oidInfoConstructors[i].pwszCNGAlgid;
1666 info->info.pwszCNGExtraAlgid = oidInfoConstructors[i].pwszCNGExtraAlgid;
1667 list_add_tail(&oidInfo, &info->entry);
1674 static void free_oid_info(void)
1676 struct OIDInfo *info, *next;
1678 LIST_FOR_EACH_ENTRY_SAFE(info, next, &oidInfo, struct OIDInfo, entry)
1680 list_remove(&info->entry);
1681 CryptMemFree(info);
1683 DeleteCriticalSection(&oidInfoCS);
1686 /***********************************************************************
1687 * CryptEnumOIDInfo (CRYPT32.@)
1689 BOOL WINAPI CryptEnumOIDInfo(DWORD dwGroupId, DWORD dwFlags, void *pvArg,
1690 PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo)
1692 BOOL ret = TRUE;
1693 struct OIDInfo *info;
1695 TRACE("(%d, %08x, %p, %p)\n", dwGroupId, dwFlags, pvArg,
1696 pfnEnumOIDInfo);
1698 EnterCriticalSection(&oidInfoCS);
1699 LIST_FOR_EACH_ENTRY(info, &oidInfo, struct OIDInfo, entry)
1701 if (!dwGroupId || dwGroupId == info->info.dwGroupId)
1703 ret = pfnEnumOIDInfo(&info->info, pvArg);
1704 if (!ret)
1705 break;
1708 LeaveCriticalSection(&oidInfoCS);
1709 return ret;
1712 PCCRYPT_OID_INFO WINAPI CryptFindOIDInfo(DWORD dwKeyType, void *pvKey,
1713 DWORD dwGroupId)
1715 PCCRYPT_OID_INFO ret = NULL;
1717 TRACE("(%d, %p, %d)\n", dwKeyType, pvKey, dwGroupId);
1719 switch(dwKeyType)
1721 case CRYPT_OID_INFO_ALGID_KEY:
1723 struct OIDInfo *info;
1725 TRACE("CRYPT_OID_INFO_ALGID_KEY: %d\n", *(DWORD *)pvKey);
1726 EnterCriticalSection(&oidInfoCS);
1727 LIST_FOR_EACH_ENTRY(info, &oidInfo, struct OIDInfo, entry)
1729 if (info->info.u.Algid == *(DWORD *)pvKey &&
1730 (!dwGroupId || info->info.dwGroupId == dwGroupId))
1732 ret = &info->info;
1733 break;
1736 LeaveCriticalSection(&oidInfoCS);
1737 break;
1739 case CRYPT_OID_INFO_NAME_KEY:
1741 struct OIDInfo *info;
1743 TRACE("CRYPT_OID_INFO_NAME_KEY: %s\n", debugstr_w(pvKey));
1744 EnterCriticalSection(&oidInfoCS);
1745 LIST_FOR_EACH_ENTRY(info, &oidInfo, struct OIDInfo, entry)
1747 if (!wcscmp(info->info.pwszName, pvKey) &&
1748 (!dwGroupId || info->info.dwGroupId == dwGroupId))
1750 ret = &info->info;
1751 break;
1754 LeaveCriticalSection(&oidInfoCS);
1755 break;
1757 case CRYPT_OID_INFO_OID_KEY:
1759 struct OIDInfo *info;
1760 LPSTR oid = pvKey;
1762 TRACE("CRYPT_OID_INFO_OID_KEY: %s\n", debugstr_a(oid));
1763 EnterCriticalSection(&oidInfoCS);
1764 LIST_FOR_EACH_ENTRY(info, &oidInfo, struct OIDInfo, entry)
1766 if (!lstrcmpA(info->info.pszOID, oid) &&
1767 (!dwGroupId || info->info.dwGroupId == dwGroupId))
1769 ret = &info->info;
1770 break;
1773 LeaveCriticalSection(&oidInfoCS);
1774 break;
1776 case CRYPT_OID_INFO_SIGN_KEY:
1778 struct OIDInfo *info;
1780 TRACE("CRYPT_OID_INFO_SIGN_KEY: %d\n", *(DWORD *)pvKey);
1781 EnterCriticalSection(&oidInfoCS);
1782 LIST_FOR_EACH_ENTRY(info, &oidInfo, struct OIDInfo, entry)
1784 if (info->info.u.Algid == *(DWORD *)pvKey &&
1785 info->info.ExtraInfo.cbData >= sizeof(DWORD) &&
1786 *(DWORD *)info->info.ExtraInfo.pbData ==
1787 *(DWORD *)((LPBYTE)pvKey + sizeof(DWORD)) &&
1788 (!dwGroupId || info->info.dwGroupId == dwGroupId))
1790 ret = &info->info;
1791 break;
1794 LeaveCriticalSection(&oidInfoCS);
1795 break;
1798 return ret;
1801 LPCSTR WINAPI CertAlgIdToOID(DWORD dwAlgId)
1803 LPCSTR ret;
1804 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
1805 &dwAlgId, 0);
1807 if (info)
1808 ret = info->pszOID;
1809 else
1810 ret = NULL;
1811 return ret;
1814 DWORD WINAPI CertOIDToAlgId(LPCSTR pszObjId)
1816 DWORD ret;
1817 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
1818 (void *)pszObjId, 0);
1820 if (info)
1821 ret = info->u.Algid;
1822 else
1823 ret = 0;
1824 return ret;
1827 void crypt_oid_init(void)
1829 init_oid_info();
1830 init_registered_oid_info();
1833 void crypt_oid_free(void)
1835 free_function_sets();
1836 free_oid_info();