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"
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
29 static const WCHAR szDllName[] = { 'D','l','l',0 };
31 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
34 static const char szEncodingTypeFmt[] =
35 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
37 char numericOID[7]; /* enough for "#65535" */
41 /* MSDN says the encoding type is a mask, but it isn't treated that way.
42 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
43 * "EncodingType 2" would be expected if it were a mask. Instead native
44 * stores values in "EncodingType 3".
48 snprintf(numericOID, sizeof(numericOID), "#%d", (int)pszOID);
54 /* This is enough: the lengths of the two string parameters are explicitly
55 * counted, and we need up to five additional characters for the encoding
56 * type. These are covered by the "%d", "%s", and "%s" characters in the
57 * format specifier that are removed by sprintf.
59 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
60 szKey = HeapAlloc(GetProcessHeap(), 0, len);
62 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
66 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
67 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
73 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
74 debugstr_w(pwszDll), pszOverrideFuncName);
76 /* This only registers functions for encoding certs, not messages */
77 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
80 /* I'm not matching MS bug for bug here, because I doubt any app depends on
82 * - native does nothing if pwszDll is NULL
83 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
84 * it creates would never be used
85 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
86 * Instead I disallow all of these with ERROR_INVALID_PARAMETER.
88 if (!pszFuncName || !pszOID || !pwszDll)
90 SetLastError(ERROR_INVALID_PARAMETER);
94 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
95 TRACE("Key name is %s\n", debugstr_a(szKey));
100 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
101 HeapFree(GetProcessHeap(), 0, szKey);
102 if(r != ERROR_SUCCESS)
105 /* write the values */
106 if (pszOverrideFuncName)
107 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, pszOverrideFuncName,
108 lstrlenA(pszOverrideFuncName) + 1);
109 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
110 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
116 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
122 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
124 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
127 if (!pszFuncName || !pszOID)
129 SetLastError(ERROR_INVALID_PARAMETER);
133 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
134 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
137 return rc ? FALSE : TRUE;
140 /* Gets the registered function named szFuncName for dwCertEncodingType and
141 * lpszStructType, or NULL if one could not be found. *lib will be set to the
142 * handle of the module it's in, or NULL if no module was loaded. If the
143 * return value is NULL, *lib will also be NULL, to simplify error handling.
145 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
146 LPCSTR szFuncName, HMODULE *lib)
149 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
151 const char *funcName;
154 DWORD type, size = 0;
157 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
158 HeapFree(GetProcessHeap(), 0, szKey);
159 if(r != ERROR_SUCCESS)
162 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
163 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
165 funcName = HeapAlloc(GetProcessHeap(), 0, size);
166 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
170 funcName = szFuncName;
171 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
172 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
174 LPWSTR dllName = HeapAlloc(GetProcessHeap(), 0, size);
176 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
178 *lib = LoadLibraryW(dllName);
181 ret = GetProcAddress(*lib, funcName);
184 /* Unload the library, the caller doesn't want to unload it
185 * when the return value is NULL.
191 HeapFree(GetProcessHeap(), 0, dllName);
193 if (funcName != szFuncName)
194 HeapFree(GetProcessHeap(), 0, (char *)funcName);
198 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
201 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
202 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
206 CryptEncodeObjectFunc pCryptEncodeObject;
208 TRACE("(0x%08lx, %s, %p, %p, %p)\n",
209 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
210 "(integer value)", pvStructInfo, pbEncoded, pcbEncoded);
212 if (!pbEncoded && !pcbEncoded)
214 SetLastError(ERROR_INVALID_PARAMETER);
218 /* Try registered DLL first.. */
220 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
221 lpszStructType, "CryptEncodeObject", &lib);
222 if (pCryptEncodeObject)
224 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
225 pvStructInfo, pbEncoded, pcbEncoded);
230 /* If not, use CryptEncodeObjectEx */
231 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
232 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
237 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
238 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
240 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
241 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
242 BYTE *pbEncoded, DWORD *pcbEncoded)
244 BOOL ret = FALSE, encoded = FALSE;
246 FIXME("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p): stub\n",
247 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
248 "(integer value)", pvStructInfo, dwFlags, pEncodePara, pbEncoded,
251 if (!pbEncoded && !pcbEncoded)
253 SetLastError(ERROR_INVALID_PARAMETER);
257 if (!HIWORD(lpszStructType))
259 switch (LOWORD(lpszStructType))
262 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
268 CryptEncodeObjectExFunc pCryptEncodeObjectEx =
269 (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
270 lpszStructType, "CryptEncodeObjectEx", &lib);
272 if (pCryptEncodeObjectEx)
274 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
275 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
282 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
283 DWORD, DWORD, void *, DWORD *);
285 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
286 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
287 DWORD *pcbStructInfo)
291 CryptDecodeObjectFunc pCryptDecodeObject;
293 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n",
294 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
295 "(integer value)", pbEncoded, cbEncoded, dwFlags, pvStructInfo,
298 if (!pvStructInfo && !pcbStructInfo)
300 SetLastError(ERROR_INVALID_PARAMETER);
304 /* Try registered DLL first.. */
306 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
307 lpszStructType, "CryptDecodeObject", &lib);
308 if (pCryptDecodeObject)
310 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
311 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
316 /* If not, use CryptDecodeObjectEx */
317 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
318 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
323 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
324 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
326 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
327 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
328 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
330 BOOL ret = FALSE, decoded = FALSE;
332 FIXME("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p): stub\n",
333 dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
334 "(integer value)", pbEncoded, cbEncoded, dwFlags, pDecodePara,
335 pvStructInfo, pcbStructInfo);
337 if (!pvStructInfo && !pcbStructInfo)
339 SetLastError(ERROR_INVALID_PARAMETER);
343 if (!HIWORD(lpszStructType))
345 switch (LOWORD(lpszStructType))
348 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
354 CryptDecodeObjectExFunc pCryptDecodeObjectEx =
355 (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
356 lpszStructType, "CryptDecodeObjectEx", &lib);
358 if (pCryptDecodeObjectEx)
360 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
361 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,