server: Added access rights mapping to token objects.
[wine/multimedia.git] / dlls / crypt32 / oid.c
blobe9733a1acce2a19030c95915010d16024c0b16fe
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 /* There is no free function associated with this; therefore, the sets are
80 * freed when crypt32.dll is unloaded.
82 HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName,
83 DWORD dwFlags)
85 struct OIDFunctionSet *cursor, *ret = NULL;
87 TRACE("(%s, %lx)\n", debugstr_a(pszFuncName), dwFlags);
89 EnterCriticalSection(&funcSetCS);
90 LIST_FOR_EACH_ENTRY(cursor, &funcSets, struct OIDFunctionSet, next)
92 if (!strcasecmp(pszFuncName, cursor->name))
94 ret = (HCRYPTOIDFUNCSET)cursor;
95 break;
98 if (!ret)
100 ret = CryptMemAlloc(sizeof(struct OIDFunctionSet));
101 if (ret)
103 memset(ret, 0, sizeof(*ret));
104 ret->name = CryptMemAlloc(strlen(pszFuncName) + 1);
105 if (ret->name)
107 InitializeCriticalSection(&ret->cs);
108 list_init(&ret->functions);
109 strcpy(ret->name, pszFuncName);
110 list_add_tail(&funcSets, &ret->next);
112 else
114 CryptMemFree(ret);
115 ret = NULL;
119 LeaveCriticalSection(&funcSetCS);
121 return (HCRYPTOIDFUNCSET)ret;
124 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
125 LPCSTR pszOID)
127 static const char szEncodingTypeFmt[] =
128 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
129 UINT len;
130 char numericOID[7]; /* enough for "#65535" */
131 const char *oid;
132 LPSTR szKey;
134 /* MSDN says the encoding type is a mask, but it isn't treated that way.
135 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
136 * "EncodingType 2" would be expected if it were a mask. Instead native
137 * stores values in "EncodingType 3".
139 if (!HIWORD(pszOID))
141 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
142 oid = numericOID;
144 else
145 oid = pszOID;
147 /* This is enough: the lengths of the two string parameters are explicitly
148 * counted, and we need up to five additional characters for the encoding
149 * type. These are covered by the "%d", "%s", and "%s" characters in the
150 * format specifier that are removed by sprintf.
152 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
153 szKey = CryptMemAlloc(len);
154 if (szKey)
155 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
156 return szKey;
159 BOOL WINAPI CryptGetDefaultOIDDllList(HCRYPTOIDFUNCSET hFuncSet,
160 DWORD dwEncodingType, LPWSTR pwszDllList, DWORD *pcchDllList)
162 BOOL ret = TRUE;
163 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
164 char *keyName;
165 HKEY key;
166 long rc;
168 TRACE("(%p, %ld, %p, %p)\n", hFuncSet, dwEncodingType, pwszDllList,
169 pcchDllList);
171 keyName = CRYPT_GetKeyName(dwEncodingType, set->name, "DEFAULT");
172 rc = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, NULL, 0,
173 KEY_READ, NULL, &key, NULL);
174 if (!rc)
176 DWORD size = *pcchDllList * sizeof(WCHAR);
178 rc = RegQueryValueExW(key, DllW, NULL, NULL, (LPBYTE)pwszDllList,
179 &size);
180 if (!rc)
181 *pcchDllList = size / sizeof(WCHAR);
182 else
184 /* No value, return an empty list */
185 if (*pcchDllList)
186 *pwszDllList = '\0';
187 *pcchDllList = 1;
189 RegCloseKey(key);
191 else
193 SetLastError(rc);
194 ret = FALSE;
196 CryptMemFree(keyName);
198 return ret;
201 BOOL WINAPI CryptInstallOIDFunctionAddress(HMODULE hModule,
202 DWORD dwEncodingType, LPCSTR pszFuncName, DWORD cFuncEntry,
203 const CRYPT_OID_FUNC_ENTRY rgFuncEntry[], DWORD dwFlags)
205 BOOL ret = TRUE;
206 struct OIDFunctionSet *set;
208 TRACE("(%p, %ld, %s, %ld, %p, %08lx)\n", hModule, dwEncodingType,
209 debugstr_a(pszFuncName), cFuncEntry, rgFuncEntry, dwFlags);
211 set = (struct OIDFunctionSet *)CryptInitOIDFunctionSet(pszFuncName, 0);
212 if (set)
214 DWORD i;
216 EnterCriticalSection(&set->cs);
217 for (i = 0; ret && i < cFuncEntry; i++)
219 struct OIDFunction *func;
221 if (HIWORD(rgFuncEntry[i].pszOID))
222 func = CryptMemAlloc(sizeof(struct OIDFunction)
223 + strlen(rgFuncEntry[i].pszOID) + 1);
224 else
225 func = CryptMemAlloc(sizeof(struct OIDFunction));
226 if (func)
228 func->encoding = dwEncodingType;
229 if (HIWORD(rgFuncEntry[i].pszOID))
231 func->entry.pszOID = (LPSTR)((LPBYTE)func + sizeof(*func));
232 strcpy((LPSTR)func->entry.pszOID, rgFuncEntry[i].pszOID);
234 else
235 func->entry.pszOID = rgFuncEntry[i].pszOID;
236 func->entry.pvFuncAddr = rgFuncEntry[i].pvFuncAddr;
237 list_add_tail(&set->functions, &func->next);
239 else
240 ret = FALSE;
242 LeaveCriticalSection(&set->cs);
244 else
245 ret = FALSE;
246 return ret;
249 static BOOL CRYPT_GetFuncFromReg(DWORD dwEncodingType, LPCSTR pszOID,
250 LPCSTR szFuncName, LPVOID *ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
252 BOOL ret = FALSE;
253 char *keyName;
254 const char *funcName;
255 HKEY key;
256 long rc;
258 keyName = CRYPT_GetKeyName(dwEncodingType, szFuncName, pszOID);
259 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
260 if (!rc)
262 DWORD type, size = 0;
264 rc = RegQueryValueExA(key, "FuncName", NULL, &type, NULL, &size);
265 if (rc == ERROR_MORE_DATA && type == REG_SZ)
267 funcName = CryptMemAlloc(size);
268 rc = RegQueryValueExA(key, "FuncName", NULL, &type,
269 (LPBYTE)funcName, &size);
271 else
272 funcName = szFuncName;
273 rc = RegQueryValueExW(key, DllW, NULL, &type, NULL, &size);
274 if (rc == ERROR_MORE_DATA && type == REG_SZ)
276 LPWSTR dllName = CryptMemAlloc(size);
278 if (dllName)
280 rc = RegQueryValueExW(key, DllW, NULL, NULL,
281 (LPBYTE)dllName, &size);
282 if (!rc)
284 HMODULE lib;
286 /* This is a bit of a hack; MSDN describes a more
287 * complicated unload routine than this will allow.
288 * Still, this seems to suffice for now.
290 lib = LoadLibraryW(dllName);
291 if (lib)
293 *ppvFuncAddr = GetProcAddress(lib, szFuncName);
294 if (*ppvFuncAddr)
296 *phFuncAddr = (HCRYPTOIDFUNCADDR)lib;
297 ret = TRUE;
299 else
301 /* Unload the library, the caller doesn't want
302 * to unload it when the return value is NULL.
304 FreeLibrary(lib);
308 else
309 SetLastError(rc);
310 CryptMemFree(dllName);
313 else
314 SetLastError(rc);
315 if (funcName != szFuncName)
316 CryptMemFree((char *)funcName);
317 RegCloseKey(key);
319 else
320 SetLastError(rc);
321 CryptMemFree(keyName);
322 return ret;
325 BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
326 DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr,
327 HCRYPTOIDFUNCADDR *phFuncAddr)
329 BOOL ret = FALSE;
330 struct OIDFunctionSet *set = (struct OIDFunctionSet *)hFuncSet;
332 TRACE("(%p, %ld, %s, %08lx, %p, %p)\n", hFuncSet, dwEncodingType,
333 debugstr_a(pszOID), dwFlags, ppvFuncAddr, phFuncAddr);
335 *ppvFuncAddr = NULL;
336 if (!(dwFlags & CRYPT_GET_INSTALLED_OID_FUNC_FLAG))
338 struct OIDFunction *function;
340 EnterCriticalSection(&set->cs);
341 LIST_FOR_EACH_ENTRY(function, &set->functions, struct OIDFunction, next)
343 if (function->encoding == dwEncodingType)
345 if (HIWORD(pszOID))
347 if (HIWORD(function->entry.pszOID &&
348 !strcasecmp(function->entry.pszOID, pszOID)))
350 *ppvFuncAddr = function->entry.pvFuncAddr;
351 *phFuncAddr = NULL; /* FIXME: what should it be? */
352 ret = TRUE;
353 break;
356 else if (function->entry.pszOID == pszOID)
358 *ppvFuncAddr = function->entry.pvFuncAddr;
359 *phFuncAddr = NULL; /* FIXME: what should it be? */
360 ret = TRUE;
361 break;
365 LeaveCriticalSection(&set->cs);
367 if (!*ppvFuncAddr)
368 ret = CRYPT_GetFuncFromReg(dwEncodingType, pszOID, set->name,
369 ppvFuncAddr, phFuncAddr);
370 return ret;
373 BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr,
374 DWORD dwFlags)
376 TRACE("(%p, %08lx)\n", hFuncAddr, dwFlags);
378 /* FIXME: as MSDN states, need to check for DllCanUnloadNow in the DLL,
379 * and only unload it if it can be unloaded. Also need to implement ref
380 * counting on the functions.
382 FreeLibrary((HMODULE)hFuncAddr);
383 return TRUE;
386 BOOL WINAPI CryptRegisterDefaultOIDFunction(DWORD dwEncodingType,
387 LPCSTR pszFuncName, DWORD dwIndex, LPCWSTR pwszDll)
389 FIXME("(%lx,%s,%lx,%s) stub!\n", dwEncodingType, pszFuncName, dwIndex,
390 debugstr_w(pwszDll));
391 return FALSE;
394 BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType,
395 LPCSTR pszFuncName, LPCWSTR pwszDll)
397 FIXME("(%lx %s %s): stub\n", dwEncodingType, debugstr_a(pszFuncName),
398 debugstr_w(pwszDll));
399 return FALSE;
402 BOOL WINAPI CryptGetDefaultOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet,
403 DWORD dwEncodingType, LPCWSTR pwszDll, DWORD dwFlags, void *ppvFuncAddr,
404 HCRYPTOIDFUNCADDR *phFuncAddr)
406 FIXME("(%p, %ld, %s, %08lx, %p, %p): stub\n", hFuncSet, dwEncodingType,
407 debugstr_w(pwszDll), dwFlags, ppvFuncAddr, phFuncAddr);
408 return FALSE;
411 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
412 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
414 LONG r;
415 HKEY hKey;
416 LPSTR szKey;
418 TRACE("(%lx, %s, %s, %s, %s)\n", dwEncodingType, pszFuncName, pszOID,
419 debugstr_w(pwszDll), pszOverrideFuncName);
421 /* This only registers functions for encoding certs, not messages */
422 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
423 return TRUE;
425 /* Native does nothing pwszDll is NULL */
426 if (!pwszDll)
427 return TRUE;
429 /* I'm not matching MS bug for bug here, because I doubt any app depends on
430 * it: native "succeeds" if pszFuncName is NULL, but the nonsensical entry
431 * it creates would never be used.
433 if (!pszFuncName || !pszOID)
435 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
436 return FALSE;
439 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
440 TRACE("Key name is %s\n", debugstr_a(szKey));
442 if (!szKey)
443 return FALSE;
445 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
446 CryptMemFree(szKey);
447 if(r != ERROR_SUCCESS)
448 return FALSE;
450 /* write the values */
451 if (pszOverrideFuncName)
452 RegSetValueExA(hKey, "FuncName", 0, REG_SZ,
453 (const BYTE*)pszOverrideFuncName, lstrlenA(pszOverrideFuncName) + 1);
454 RegSetValueExW(hKey, DllW, 0, REG_SZ, (const BYTE*) pwszDll,
455 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
457 RegCloseKey(hKey);
458 return TRUE;
461 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
462 LPCSTR pszOID)
464 LPSTR szKey;
465 LONG rc;
467 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
469 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
470 return TRUE;
472 if (!pszFuncName || !pszOID)
474 SetLastError(ERROR_INVALID_PARAMETER);
475 return FALSE;
478 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
479 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
480 CryptMemFree(szKey);
481 if (rc)
482 SetLastError(rc);
483 return rc ? FALSE : TRUE;
486 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
487 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
488 DWORD *pcbValueData)
490 LPSTR szKey;
491 LONG rc;
492 HKEY hKey;
494 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
495 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
496 pcbValueData);
498 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
499 return TRUE;
501 if (!pszFuncName || !pszOID || !pwszValueName)
503 SetLastError(ERROR_INVALID_PARAMETER);
504 return FALSE;
507 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
508 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
509 CryptMemFree(szKey);
510 if (rc)
511 SetLastError(rc);
512 else
514 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
515 pbValueData, pcbValueData);
516 if (rc)
517 SetLastError(rc);
518 RegCloseKey(hKey);
520 return rc ? FALSE : TRUE;
523 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
524 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
525 const BYTE *pbValueData, DWORD cbValueData)
527 LPSTR szKey;
528 LONG rc;
529 HKEY hKey;
531 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
532 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
533 cbValueData);
535 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
536 return TRUE;
538 if (!pszFuncName || !pszOID || !pwszValueName)
540 SetLastError(ERROR_INVALID_PARAMETER);
541 return FALSE;
544 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
545 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
546 CryptMemFree(szKey);
547 if (rc)
548 SetLastError(rc);
549 else
551 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
552 cbValueData);
553 if (rc)
554 SetLastError(rc);
555 RegCloseKey(hKey);
557 return rc ? FALSE : TRUE;