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 PCCRYPT_OID_INFO WINAPI
CryptFindOIDInfo(DWORD dwKeyType
, void *pvKey
,
90 FIXME("(%ld, %p, %ld): stub\n", dwKeyType
, pvKey
, dwGroupId
);
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
,
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
;
115 ret
= CryptMemAlloc(sizeof(struct OIDFunctionSet
));
118 memset(ret
, 0, sizeof(*ret
));
119 ret
->name
= CryptMemAlloc(strlen(pszFuncName
) + 1);
122 InitializeCriticalSection(&ret
->cs
);
123 list_init(&ret
->functions
);
124 strcpy(ret
->name
, pszFuncName
);
125 list_add_tail(&funcSets
, &ret
->next
);
134 LeaveCriticalSection(&funcSetCS
);
136 return (HCRYPTOIDFUNCSET
)ret
;
139 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
142 static const char szEncodingTypeFmt
[] =
143 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
145 char numericOID
[7]; /* enough for "#65535" */
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".
156 snprintf(numericOID
, sizeof(numericOID
), "#%d", LOWORD(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
);
170 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
174 BOOL WINAPI
CryptGetDefaultOIDDllList(HCRYPTOIDFUNCSET hFuncSet
,
175 DWORD dwEncodingType
, LPWSTR pwszDllList
, DWORD
*pcchDllList
)
178 struct OIDFunctionSet
*set
= (struct OIDFunctionSet
*)hFuncSet
;
183 TRACE("(%p, %ld, %p, %p)\n", hFuncSet
, dwEncodingType
, pwszDllList
,
186 keyName
= CRYPT_GetKeyName(dwEncodingType
, set
->name
, "DEFAULT");
187 rc
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, keyName
, 0, NULL
, 0,
188 KEY_READ
, NULL
, &key
, NULL
);
191 DWORD size
= *pcchDllList
* sizeof(WCHAR
);
193 rc
= RegQueryValueExW(key
, DllW
, NULL
, NULL
, (LPBYTE
)pwszDllList
,
196 *pcchDllList
= size
/ sizeof(WCHAR
);
199 /* No value, return an empty list */
211 CryptMemFree(keyName
);
216 BOOL WINAPI
CryptInstallOIDFunctionAddress(HMODULE hModule
,
217 DWORD dwEncodingType
, LPCSTR pszFuncName
, DWORD cFuncEntry
,
218 const CRYPT_OID_FUNC_ENTRY rgFuncEntry
[], DWORD dwFlags
)
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);
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);
240 func
= CryptMemAlloc(sizeof(struct OIDFunction
));
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
);
250 func
->entry
.pszOID
= rgFuncEntry
[i
].pszOID
;
251 func
->entry
.pvFuncAddr
= rgFuncEntry
[i
].pvFuncAddr
;
252 list_add_tail(&set
->functions
, &func
->next
);
257 LeaveCriticalSection(&set
->cs
);
264 static BOOL
CRYPT_GetFuncFromReg(DWORD dwEncodingType
, LPCSTR pszOID
,
265 LPCSTR szFuncName
, LPVOID
*ppvFuncAddr
, HCRYPTOIDFUNCADDR
*phFuncAddr
)
269 const char *funcName
;
273 keyName
= CRYPT_GetKeyName(dwEncodingType
, szFuncName
, pszOID
);
274 rc
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, keyName
, 0, KEY_READ
, &key
);
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
);
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
);
295 rc
= RegQueryValueExW(key
, DllW
, NULL
, NULL
,
296 (LPBYTE
)dllName
, &size
);
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
);
308 *ppvFuncAddr
= GetProcAddress(lib
, szFuncName
);
311 *phFuncAddr
= (HCRYPTOIDFUNCADDR
)lib
;
316 /* Unload the library, the caller doesn't want
317 * to unload it when the return value is NULL.
325 CryptMemFree(dllName
);
330 if (funcName
!= szFuncName
)
331 CryptMemFree((char *)funcName
);
336 CryptMemFree(keyName
);
340 BOOL WINAPI
CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet
,
341 DWORD dwEncodingType
, LPCSTR pszOID
, DWORD dwFlags
, void **ppvFuncAddr
,
342 HCRYPTOIDFUNCADDR
*phFuncAddr
)
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
);
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
)
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? */
371 else if (function
->entry
.pszOID
== pszOID
)
373 *ppvFuncAddr
= function
->entry
.pvFuncAddr
;
374 *phFuncAddr
= NULL
; /* FIXME: what should it be? */
380 LeaveCriticalSection(&set
->cs
);
383 ret
= CRYPT_GetFuncFromReg(dwEncodingType
, pszOID
, set
->name
,
384 ppvFuncAddr
, phFuncAddr
);
388 BOOL WINAPI
CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr
,
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
);
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
));
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
));
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
);
426 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
427 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
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
))
440 /* Native does nothing pwszDll is NULL */
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
));
454 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
455 TRACE("Key name is %s\n", debugstr_a(szKey
));
460 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
462 if(r
!= ERROR_SUCCESS
)
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
));
476 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
482 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
484 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
487 if (!pszFuncName
|| !pszOID
)
489 SetLastError(ERROR_INVALID_PARAMETER
);
493 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
494 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
498 return rc
? FALSE
: TRUE
;
501 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
502 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
509 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
510 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
513 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
516 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
518 SetLastError(ERROR_INVALID_PARAMETER
);
522 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
523 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
529 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
530 pbValueData
, pcbValueData
);
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
)
546 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
547 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
550 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
553 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
555 SetLastError(ERROR_INVALID_PARAMETER
);
559 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
560 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
566 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
572 return rc
? FALSE
: TRUE
;