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
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;
38 CRITICAL_SECTION cs; /* protects functions */
39 struct list functions;
46 CRYPT_OID_FUNC_ENTRY entry;
50 void CRYPT_InitFunctionSets(void)
52 InitializeCriticalSection(&funcSetCS);
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,
87 /* There is no free function associated with this; therefore, the sets are
88 * freed when crypt32.dll is unloaded.
90 HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName,
93 struct OIDFunctionSet *cursor, *ret = NULL;
95 TRACE("(%s, %lx)\n", debugstr_a(pszFuncName), dwFlags);
97 EnterCriticalSection(&funcSetCS);
98 LIST_FOR_EACH_ENTRY(cursor, &funcSets, struct OIDFunctionSet, next)
100 if (!strcasecmp(pszFuncName, cursor->name))
102 ret = (HCRYPTOIDFUNCSET)cursor;
108 ret = CryptMemAlloc(sizeof(struct OIDFunctionSet));
111 memset(ret, 0, sizeof(*ret));
112 ret->name = CryptMemAlloc(strlen(pszFuncName) + 1);
115 InitializeCriticalSection(&ret->cs);
116 list_init(&ret->functions);
117 strcpy(ret->name, pszFuncName);
118 list_add_tail(&funcSets, &ret->next);
127 LeaveCriticalSection(&funcSetCS);
129 return (HCRYPTOIDFUNCSET)ret;
132 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
135 static const char szEncodingTypeFmt[] =
136 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
138 char numericOID[7]; /* enough for "#65535" */
142 /* MSDN says the encoding type is a mask, but it isn't treated that way.
143 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
144 * "EncodingType 2" would be expected if it were a mask. Instead native
145 * stores values in "EncodingType 3".
149 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
155 /* This is enough: the lengths of the two string parameters are explicitly
156 * counted, and we need up to five additional characters for the encoding
157 * type. These are covered by the "%d", "%s", and "%s" characters in the
158 * format specifier that are removed by sprintf.
160 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
161 szKey = CryptMemAlloc(len);
163 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
167 BOOL WINAPI CryptGetDefaultOIDDllList(HCRYPTOIDFUNCSET hFuncSet,
168 DWORD dwEncodingType, LPWSTR pwszDllList, DWORD *pcchDllList)
171 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
176 TRACE("(%p, %ld, %p, %p)\n", hFuncSet, dwEncodingType, pwszDllList,
179 keyName = CRYPT_GetKeyName(dwEncodingType, set->name, "DEFAULT");
180 rc = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, NULL, 0,
181 KEY_READ, NULL, &key, NULL);
184 DWORD size = *pcchDllList * sizeof(WCHAR);
186 rc = RegQueryValueExW(key, DllW, NULL, NULL, (LPBYTE)pwszDllList,
189 *pcchDllList = size / sizeof(WCHAR);
192 /* No value, return an empty list */
204 CryptMemFree(keyName);
209 BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
210 DWORD dwEncodingType, LPCSTR pszFuncName, DWORD cFuncEntry,
211 const CRYPT_OID_FUNC_ENTRY rgFuncEntry[], DWORD dwFlags)
214 struct OIDFunctionSet *set;
216 TRACE("(%p, %ld, %s, %ld, %p, %08lx)\n", hModule, dwEncodingType,
217 debugstr_a(pszFuncName), cFuncEntry, rgFuncEntry, dwFlags);
219 set = (struct OIDFunctionSet *)CryptInitOIDFunctionSet(pszFuncName, 0);
224 EnterCriticalSection(&set->cs);
225 for (i = 0; ret && i < cFuncEntry; i++)
227 struct OIDFunction *func;
229 if (HIWORD(rgFuncEntry[i].pszOID))
230 func = CryptMemAlloc(sizeof(struct OIDFunction)
231 + strlen(rgFuncEntry[i].pszOID) + 1);
233 func = CryptMemAlloc(sizeof(struct OIDFunction));
236 func->encoding = dwEncodingType;
237 if (HIWORD(rgFuncEntry[i].pszOID))
239 func->entry.pszOID = (LPSTR)((LPBYTE)func + sizeof(*func));
240 strcpy((LPSTR)func->entry.pszOID, rgFuncEntry[i].pszOID);
243 func->entry.pszOID = rgFuncEntry[i].pszOID;
244 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
245 list_add_tail(&set->functions, &func->next);
250 LeaveCriticalSection(&set->cs);
257 static BOOL CRYPT_GetFuncFromReg(DWORD dwEncodingType, LPCSTR pszOID,
258 LPCSTR szFuncName, LPVOID *ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
262 const char *funcName;
266 keyName = CRYPT_GetKeyName(dwEncodingType, szFuncName, pszOID);
267 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
270 DWORD type, size = 0;
272 rc = RegQueryValueExA(key, "FuncName", NULL, &type, NULL, &size);
273 if (rc == ERROR_MORE_DATA && type == REG_SZ)
275 funcName = CryptMemAlloc(size);
276 rc = RegQueryValueExA(key, "FuncName", NULL, &type,
277 (LPBYTE)funcName, &size);
280 funcName = szFuncName;
281 rc = RegQueryValueExW(key, DllW, NULL, &type, NULL, &size);
282 if (rc == ERROR_MORE_DATA && type == REG_SZ)
284 LPWSTR dllName = CryptMemAlloc(size);
288 rc = RegQueryValueExW(key, DllW, NULL, NULL,
289 (LPBYTE)dllName, &size);
294 /* This is a bit of a hack; MSDN describes a more
295 * complicated unload routine than this will allow.
296 * Still, this seems to suffice for now.
298 lib = LoadLibraryW(dllName);
301 *ppvFuncAddr = GetProcAddress(lib, szFuncName);
304 *phFuncAddr = (HCRYPTOIDFUNCADDR)lib;
309 /* Unload the library, the caller doesn't want
310 * to unload it when the return value is NULL.
318 CryptMemFree(dllName);
323 if (funcName != szFuncName)
324 CryptMemFree((char *)funcName);
329 CryptMemFree(keyName);
333 BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
334 DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr,
335 HCRYPTOIDFUNCADDR *phFuncAddr)
338 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
340 TRACE("(%p, %ld, %s, %08lx, %p, %p)\n", hFuncSet, dwEncodingType,
341 debugstr_a(pszOID), dwFlags, ppvFuncAddr, phFuncAddr);
344 if (!(dwFlags & CRYPT_GET_INSTALLED_OID_FUNC_FLAG))
346 struct OIDFunction *function;
348 EnterCriticalSection(&set->cs);
349 LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
351 if (function->encoding == dwEncodingType)
355 if (HIWORD(function->entry.pszOID &&
356 !strcasecmp(function->entry.pszOID, pszOID)))
358 *ppvFuncAddr = function->entry.pvFuncAddr;
359 *phFuncAddr = NULL; /* FIXME: what should it be? */
364 else if (function->entry.pszOID == pszOID)
366 *ppvFuncAddr = function->entry.pvFuncAddr;
367 *phFuncAddr = NULL; /* FIXME: what should it be? */
373 LeaveCriticalSection(&set->cs);
376 ret = CRYPT_GetFuncFromReg(dwEncodingType, pszOID, set->name,
377 ppvFuncAddr, phFuncAddr);
381 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
384 TRACE("(%p, %08lx)\n", hFuncAddr, dwFlags);
386 /* FIXME: as MSDN states, need to check for DllCanUnloadNow in the DLL,
387 * and only unload it if it can be unloaded. Also need to implement ref
388 * counting on the functions.
390 FreeLibrary((HMODULE)hFuncAddr);
394 BOOL WINAPI CryptRegisterDefaultOIDFunction(DWORD dwEncodingType,
395 LPCSTR pszFuncName, DWORD dwIndex, LPCWSTR pwszDll)
397 FIXME("(%lx,%s,%lx,%s) stub!\n", dwEncodingType, pszFuncName, dwIndex,
398 debugstr_w(pwszDll));
402 BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType,
403 LPCSTR pszFuncName, LPCWSTR pwszDll)
405 FIXME("(%lx %s %s): stub\n", dwEncodingType, debugstr_a(pszFuncName),
406 debugstr_w(pwszDll));
410 BOOL WINAPI CryptGetDefaultOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
411 DWORD dwEncodingType, LPCWSTR pwszDll, DWORD dwFlags, void *ppvFuncAddr,
412 HCRYPTOIDFUNCADDR *phFuncAddr)
414 FIXME("(%p, %ld, %s, %08lx, %p, %p): stub\n", hFuncSet, dwEncodingType,
415 debugstr_w(pwszDll), dwFlags, ppvFuncAddr, phFuncAddr);
419 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
420 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
426 TRACE("(%lx, %s, %s, %s, %s)\n", dwEncodingType, pszFuncName, pszOID,
427 debugstr_w(pwszDll), pszOverrideFuncName);
429 /* This only registers functions for encoding certs, not messages */
430 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
433 /* Native does nothing pwszDll is NULL */
437 /* I'm not matching MS bug for bug here, because I doubt any app depends on
438 * it: native "succeeds" if pszFuncName is NULL, but the nonsensical entry
439 * it creates would never be used.
441 if (!pszFuncName || !pszOID)
443 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
447 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
448 TRACE("Key name is %s\n", debugstr_a(szKey));
453 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
455 if(r != ERROR_SUCCESS)
458 /* write the values */
459 if (pszOverrideFuncName)
460 RegSetValueExA(hKey, "FuncName", 0, REG_SZ,
461 (const BYTE*)pszOverrideFuncName, lstrlenA(pszOverrideFuncName) + 1);
462 RegSetValueExW(hKey, DllW, 0, REG_SZ, (const BYTE*) pwszDll,
463 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
469 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
475 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
477 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
480 if (!pszFuncName || !pszOID)
482 SetLastError(ERROR_INVALID_PARAMETER);
486 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
487 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
491 return rc ? FALSE : TRUE;
494 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
495 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
502 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
503 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
506 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
509 if (!pszFuncName || !pszOID || !pwszValueName)
511 SetLastError(ERROR_INVALID_PARAMETER);
515 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
516 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
522 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
523 pbValueData, pcbValueData);
528 return rc ? FALSE : TRUE;
531 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
532 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
533 const BYTE *pbValueData, DWORD cbValueData)
539 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
540 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
543 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
546 if (!pszFuncName || !pszOID || !pwszValueName)
548 SetLastError(ERROR_INVALID_PARAMETER);
552 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
553 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
559 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
565 return rc ? FALSE : TRUE;