crypt32: Add stubs for CryptFindOIDInfo and I_CryptInstallAsn1Module.
[wine/dcerpc.git] / dlls / crypt32 / oid.c
blobf474639e09d181c6dd28ff6000b9e305fd25ca68
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wincrypt.h"
24 #include "winreg.h"
25 #include "wine/debug.h"
26 #include "wine/list.h"
27 #include "crypt32_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
31 static const WCHAR DllW[] = { 'D','l','l',0 };
32 CRITICAL_SECTION funcSetCS;
33 struct list funcSets;
35 struct OIDFunctionSet
37 LPSTR name;
38 CRITICAL_SECTION cs; /* protects functions */
39 struct list functions;
40 struct list next;
43 struct OIDFunction
45 DWORD encoding;
46 CRYPT_OID_FUNC_ENTRY entry;
47 struct list next;
50 void CRYPT_InitFunctionSets(void)
52 InitializeCriticalSection(&funcSetCS);
53 list_init(&funcSets);
56 void CRYPT_FreeFunctionSets(void)
58 struct OIDFunctionSet *setCursor, *setNext;
60 LIST_FOR_EACH_ENTRY_SAFE(setCursor, setNext, &funcSets,
61 struct OIDFunctionSet, next)
63 struct OIDFunction *functionCursor, *funcNext;
65 list_remove(&setCursor->next);
66 CryptMemFree(setCursor->name);
67 CryptMemFree(setCursor);
68 LIST_FOR_EACH_ENTRY_SAFE(functionCursor, funcNext,
69 &setCursor->functions, struct OIDFunction, next)
71 list_remove(&functionCursor->next);
72 CryptMemFree(functionCursor);
74 DeleteCriticalSection(&setCursor->cs);
76 DeleteCriticalSection(&funcSetCS);
79 BOOL WINAPI CryptEnumOIDInfo(DWORD dwGroupId, DWORD dwFlags, void *pvArg,
80 PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo)
82 FIXME("(%ld, %08lx, %p, %p): stub\n", dwGroupId, dwFlags, pvArg,
83 pfnEnumOIDInfo);
84 return TRUE;
87 PCCRYPT_OID_INFO WINAPI CryptFindOIDInfo(DWORD dwKeyType, void *pvKey,
88 DWORD dwGroupId)
90 FIXME("(%ld, %p, %ld): stub\n", dwKeyType, pvKey, dwGroupId);
91 return NULL;
94 /* There is no free function associated with this; therefore, the sets are
95 * freed when crypt32.dll is unloaded.
97 HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName,
98 DWORD dwFlags)
100 struct OIDFunctionSet *cursor, *ret = NULL;
102 TRACE("(%s, %lx)\n", debugstr_a(pszFuncName), dwFlags);
104 EnterCriticalSection(&funcSetCS);
105 LIST_FOR_EACH_ENTRY(cursor, &funcSets, struct OIDFunctionSet, next)
107 if (!strcasecmp(pszFuncName, cursor->name))
109 ret = (HCRYPTOIDFUNCSET)cursor;
110 break;
113 if (!ret)
115 ret = CryptMemAlloc(sizeof(struct OIDFunctionSet));
116 if (ret)
118 memset(ret, 0, sizeof(*ret));
119 ret->name = CryptMemAlloc(strlen(pszFuncName) + 1);
120 if (ret->name)
122 InitializeCriticalSection(&ret->cs);
123 list_init(&ret->functions);
124 strcpy(ret->name, pszFuncName);
125 list_add_tail(&funcSets, &ret->next);
127 else
129 CryptMemFree(ret);
130 ret = NULL;
134 LeaveCriticalSection(&funcSetCS);
136 return (HCRYPTOIDFUNCSET)ret;
139 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
140 LPCSTR pszOID)
142 static const char szEncodingTypeFmt[] =
143 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
144 UINT len;
145 char numericOID[7]; /* enough for "#65535" */
146 const char *oid;
147 LPSTR szKey;
149 /* MSDN says the encoding type is a mask, but it isn't treated that way.
150 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
151 * "EncodingType 2" would be expected if it were a mask. Instead native
152 * stores values in "EncodingType 3".
154 if (!HIWORD(pszOID))
156 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
157 oid = numericOID;
159 else
160 oid = pszOID;
162 /* This is enough: the lengths of the two string parameters are explicitly
163 * counted, and we need up to five additional characters for the encoding
164 * type. These are covered by the "%d", "%s", and "%s" characters in the
165 * format specifier that are removed by sprintf.
167 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
168 szKey = CryptMemAlloc(len);
169 if (szKey)
170 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
171 return szKey;
174 BOOL WINAPI CryptGetDefaultOIDDllList(HCRYPTOIDFUNCSET hFuncSet,
175 DWORD dwEncodingType, LPWSTR pwszDllList, DWORD *pcchDllList)
177 BOOL ret = TRUE;
178 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
179 char *keyName;
180 HKEY key;
181 long rc;
183 TRACE("(%p, %ld, %p, %p)\n", hFuncSet, dwEncodingType, pwszDllList,
184 pcchDllList);
186 keyName = CRYPT_GetKeyName(dwEncodingType, set->name, "DEFAULT");
187 rc = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, NULL, 0,
188 KEY_READ, NULL, &key, NULL);
189 if (!rc)
191 DWORD size = *pcchDllList * sizeof(WCHAR);
193 rc = RegQueryValueExW(key, DllW, NULL, NULL, (LPBYTE)pwszDllList,
194 &size);
195 if (!rc)
196 *pcchDllList = size / sizeof(WCHAR);
197 else
199 /* No value, return an empty list */
200 if (*pcchDllList)
201 *pwszDllList = '\0';
202 *pcchDllList = 1;
204 RegCloseKey(key);
206 else
208 SetLastError(rc);
209 ret = FALSE;
211 CryptMemFree(keyName);
213 return ret;
216 BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
217 DWORD dwEncodingType, LPCSTR pszFuncName, DWORD cFuncEntry,
218 const CRYPT_OID_FUNC_ENTRY rgFuncEntry[], DWORD dwFlags)
220 BOOL ret = TRUE;
221 struct OIDFunctionSet *set;
223 TRACE("(%p, %ld, %s, %ld, %p, %08lx)\n", hModule, dwEncodingType,
224 debugstr_a(pszFuncName), cFuncEntry, rgFuncEntry, dwFlags);
226 set = (struct OIDFunctionSet *)CryptInitOIDFunctionSet(pszFuncName, 0);
227 if (set)
229 DWORD i;
231 EnterCriticalSection(&set->cs);
232 for (i = 0; ret && i < cFuncEntry; i++)
234 struct OIDFunction *func;
236 if (HIWORD(rgFuncEntry[i].pszOID))
237 func = CryptMemAlloc(sizeof(struct OIDFunction)
238 + strlen(rgFuncEntry[i].pszOID) + 1);
239 else
240 func = CryptMemAlloc(sizeof(struct OIDFunction));
241 if (func)
243 func->encoding = dwEncodingType;
244 if (HIWORD(rgFuncEntry[i].pszOID))
246 func->entry.pszOID = (LPSTR)((LPBYTE)func + sizeof(*func));
247 strcpy((LPSTR)func->entry.pszOID, rgFuncEntry[i].pszOID);
249 else
250 func->entry.pszOID = rgFuncEntry[i].pszOID;
251 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
252 list_add_tail(&set->functions, &func->next);
254 else
255 ret = FALSE;
257 LeaveCriticalSection(&set->cs);
259 else
260 ret = FALSE;
261 return ret;
264 static BOOL CRYPT_GetFuncFromReg(DWORD dwEncodingType, LPCSTR pszOID,
265 LPCSTR szFuncName, LPVOID *ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
267 BOOL ret = FALSE;
268 char *keyName;
269 const char *funcName;
270 HKEY key;
271 long rc;
273 keyName = CRYPT_GetKeyName(dwEncodingType, szFuncName, pszOID);
274 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
275 if (!rc)
277 DWORD type, size = 0;
279 rc = RegQueryValueExA(key, "FuncName", NULL, &type, NULL, &size);
280 if (rc == ERROR_MORE_DATA && type == REG_SZ)
282 funcName = CryptMemAlloc(size);
283 rc = RegQueryValueExA(key, "FuncName", NULL, &type,
284 (LPBYTE)funcName, &size);
286 else
287 funcName = szFuncName;
288 rc = RegQueryValueExW(key, DllW, NULL, &type, NULL, &size);
289 if (rc == ERROR_MORE_DATA && type == REG_SZ)
291 LPWSTR dllName = CryptMemAlloc(size);
293 if (dllName)
295 rc = RegQueryValueExW(key, DllW, NULL, NULL,
296 (LPBYTE)dllName, &size);
297 if (!rc)
299 HMODULE lib;
301 /* This is a bit of a hack; MSDN describes a more
302 * complicated unload routine than this will allow.
303 * Still, this seems to suffice for now.
305 lib = LoadLibraryW(dllName);
306 if (lib)
308 *ppvFuncAddr = GetProcAddress(lib, szFuncName);
309 if (*ppvFuncAddr)
311 *phFuncAddr = (HCRYPTOIDFUNCADDR)lib;
312 ret = TRUE;
314 else
316 /* Unload the library, the caller doesn't want
317 * to unload it when the return value is NULL.
319 FreeLibrary(lib);
323 else
324 SetLastError(rc);
325 CryptMemFree(dllName);
328 else
329 SetLastError(rc);
330 if (funcName != szFuncName)
331 CryptMemFree((char *)funcName);
332 RegCloseKey(key);
334 else
335 SetLastError(rc);
336 CryptMemFree(keyName);
337 return ret;
340 BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
341 DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr,
342 HCRYPTOIDFUNCADDR *phFuncAddr)
344 BOOL ret = FALSE;
345 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
347 TRACE("(%p, %ld, %s, %08lx, %p, %p)\n", hFuncSet, dwEncodingType,
348 debugstr_a(pszOID), dwFlags, ppvFuncAddr, phFuncAddr);
350 *ppvFuncAddr = NULL;
351 if (!(dwFlags & CRYPT_GET_INSTALLED_OID_FUNC_FLAG))
353 struct OIDFunction *function;
355 EnterCriticalSection(&set->cs);
356 LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
358 if (function->encoding == dwEncodingType)
360 if (HIWORD(pszOID))
362 if (HIWORD(function->entry.pszOID &&
363 !strcasecmp(function->entry.pszOID, pszOID)))
365 *ppvFuncAddr = function->entry.pvFuncAddr;
366 *phFuncAddr = NULL; /* FIXME: what should it be? */
367 ret = TRUE;
368 break;
371 else if (function->entry.pszOID == pszOID)
373 *ppvFuncAddr = function->entry.pvFuncAddr;
374 *phFuncAddr = NULL; /* FIXME: what should it be? */
375 ret = TRUE;
376 break;
380 LeaveCriticalSection(&set->cs);
382 if (!*ppvFuncAddr)
383 ret = CRYPT_GetFuncFromReg(dwEncodingType, pszOID, set->name,
384 ppvFuncAddr, phFuncAddr);
385 return ret;
388 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
389 DWORD dwFlags)
391 TRACE("(%p, %08lx)\n", hFuncAddr, dwFlags);
393 /* FIXME: as MSDN states, need to check for DllCanUnloadNow in the DLL,
394 * and only unload it if it can be unloaded. Also need to implement ref
395 * counting on the functions.
397 FreeLibrary((HMODULE)hFuncAddr);
398 return TRUE;
401 BOOL WINAPI CryptRegisterDefaultOIDFunction(DWORD dwEncodingType,
402 LPCSTR pszFuncName, DWORD dwIndex, LPCWSTR pwszDll)
404 FIXME("(%lx,%s,%lx,%s) stub!\n", dwEncodingType, pszFuncName, dwIndex,
405 debugstr_w(pwszDll));
406 return FALSE;
409 BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType,
410 LPCSTR pszFuncName, LPCWSTR pwszDll)
412 FIXME("(%lx %s %s): stub\n", dwEncodingType, debugstr_a(pszFuncName),
413 debugstr_w(pwszDll));
414 return FALSE;
417 BOOL WINAPI CryptGetDefaultOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
418 DWORD dwEncodingType, LPCWSTR pwszDll, DWORD dwFlags, void *ppvFuncAddr,
419 HCRYPTOIDFUNCADDR *phFuncAddr)
421 FIXME("(%p, %ld, %s, %08lx, %p, %p): stub\n", hFuncSet, dwEncodingType,
422 debugstr_w(pwszDll), dwFlags, ppvFuncAddr, phFuncAddr);
423 return FALSE;
426 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
427 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
429 LONG r;
430 HKEY hKey;
431 LPSTR szKey;
433 TRACE("(%lx, %s, %s, %s, %s)\n", dwEncodingType, pszFuncName, pszOID,
434 debugstr_w(pwszDll), pszOverrideFuncName);
436 /* This only registers functions for encoding certs, not messages */
437 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
438 return TRUE;
440 /* Native does nothing pwszDll is NULL */
441 if (!pwszDll)
442 return TRUE;
444 /* I'm not matching MS bug for bug here, because I doubt any app depends on
445 * it: native "succeeds" if pszFuncName is NULL, but the nonsensical entry
446 * it creates would never be used.
448 if (!pszFuncName || !pszOID)
450 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
451 return FALSE;
454 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
455 TRACE("Key name is %s\n", debugstr_a(szKey));
457 if (!szKey)
458 return FALSE;
460 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
461 CryptMemFree(szKey);
462 if(r != ERROR_SUCCESS)
463 return FALSE;
465 /* write the values */
466 if (pszOverrideFuncName)
467 RegSetValueExA(hKey, "FuncName", 0, REG_SZ,
468 (const BYTE*)pszOverrideFuncName, lstrlenA(pszOverrideFuncName) + 1);
469 RegSetValueExW(hKey, DllW, 0, REG_SZ, (const BYTE*) pwszDll,
470 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
472 RegCloseKey(hKey);
473 return TRUE;
476 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
477 LPCSTR pszOID)
479 LPSTR szKey;
480 LONG rc;
482 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
484 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
485 return TRUE;
487 if (!pszFuncName || !pszOID)
489 SetLastError(ERROR_INVALID_PARAMETER);
490 return FALSE;
493 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
494 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
495 CryptMemFree(szKey);
496 if (rc)
497 SetLastError(rc);
498 return rc ? FALSE : TRUE;
501 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
502 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
503 DWORD *pcbValueData)
505 LPSTR szKey;
506 LONG rc;
507 HKEY hKey;
509 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
510 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
511 pcbValueData);
513 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
514 return TRUE;
516 if (!pszFuncName || !pszOID || !pwszValueName)
518 SetLastError(ERROR_INVALID_PARAMETER);
519 return FALSE;
522 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
523 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
524 CryptMemFree(szKey);
525 if (rc)
526 SetLastError(rc);
527 else
529 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
530 pbValueData, pcbValueData);
531 if (rc)
532 SetLastError(rc);
533 RegCloseKey(hKey);
535 return rc ? FALSE : TRUE;
538 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
539 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
540 const BYTE *pbValueData, DWORD cbValueData)
542 LPSTR szKey;
543 LONG rc;
544 HKEY hKey;
546 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
547 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
548 cbValueData);
550 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
551 return TRUE;
553 if (!pszFuncName || !pszOID || !pwszValueName)
555 SetLastError(ERROR_INVALID_PARAMETER);
556 return FALSE;
559 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
560 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
561 CryptMemFree(szKey);
562 if (rc)
563 SetLastError(rc);
564 else
566 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
567 cbValueData);
568 if (rc)
569 SetLastError(rc);
570 RegCloseKey(hKey);
572 return rc ? FALSE : TRUE;