Add support for more than 2 audio channels.
[wine] / dlls / crypt32 / encode.c
1 /*
2  * Copyright 2002 Mike McCormack for CodeWeavers
3  * Copyright 2005 Juan Lang
4  *
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.
9  *
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.
14  *
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
18  */
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wincrypt.h"
24 #include "winreg.h"
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28
29 static const WCHAR szDllName[] = { 'D','l','l',0 };
30
31 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
32  LPCSTR pszOID)
33 {
34     static const char szEncodingTypeFmt[] =
35      "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
36     UINT len;
37     char numericOID[7]; /* enough for "#65535" */
38     const char *oid;
39     LPSTR szKey;
40
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".
45      */
46     if (!HIWORD(pszOID))
47     {
48         snprintf(numericOID, sizeof(numericOID), "#%d", (int)pszOID);
49         oid = numericOID;
50     }
51     else
52         oid = pszOID;
53
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.
58      */
59     len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
60     szKey = HeapAlloc(GetProcessHeap(), 0, len);
61     if (szKey)
62         sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
63     return szKey;
64 }
65
66 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
67                   LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
68 {
69     LONG r;
70     HKEY hKey;
71     LPSTR szKey;
72
73     TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
74           debugstr_w(pwszDll), pszOverrideFuncName);
75
76     /* This only registers functions for encoding certs, not messages */
77     if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
78         return TRUE;
79
80     /* I'm not matching MS bug for bug here, because I doubt any app depends on
81      * it:
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.
87      */
88     if (!pszFuncName || !pszOID || !pwszDll)
89     {
90         SetLastError(ERROR_INVALID_PARAMETER);
91         return FALSE;
92     }
93
94     szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
95     TRACE("Key name is %s\n", debugstr_a(szKey));
96
97     if (!szKey)
98         return FALSE;
99
100     r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
101     HeapFree(GetProcessHeap(), 0, szKey);
102     if(r != ERROR_SUCCESS)
103         return FALSE;
104
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));
111
112     RegCloseKey(hKey);
113     return TRUE;
114 }
115
116 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
117  LPCSTR pszOID)
118 {
119     LPSTR szKey;
120     LONG rc;
121
122     TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
123
124     if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
125         return TRUE;
126
127     if (!pszFuncName || !pszOID)
128     {
129         SetLastError(ERROR_INVALID_PARAMETER);
130         return FALSE;
131     }
132
133     szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
134     rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
135     if (!rc)
136         SetLastError(rc);
137     return rc ? FALSE : TRUE;
138 }
139
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.
144  */
145 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
146  LPCSTR szFuncName, HMODULE *lib)
147 {
148     void *ret = NULL;
149     char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
150      lpszStructType);
151     const char *funcName;
152     long r;
153     HKEY hKey;
154     DWORD type, size = 0;
155
156     *lib = NULL;
157     r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
158     HeapFree(GetProcessHeap(), 0, szKey);
159     if(r != ERROR_SUCCESS)
160         return NULL;
161
162     RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
163     if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
164     {
165         funcName = HeapAlloc(GetProcessHeap(), 0, size);
166         RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
167          &size);
168     }
169     else
170         funcName = szFuncName;
171     RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
172     if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
173     {
174         LPWSTR dllName = HeapAlloc(GetProcessHeap(), 0, size);
175
176         RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
177          &size);
178         *lib = LoadLibraryW(dllName);
179         if (*lib)
180         {
181              ret = GetProcAddress(*lib, funcName);
182              if (!ret)
183              {
184                  /* Unload the library, the caller doesn't want to unload it
185                   * when the return value is NULL.
186                   */
187                  FreeLibrary(*lib);
188                  *lib = NULL;
189              }
190         }
191         HeapFree(GetProcessHeap(), 0, dllName);
192     }
193     if (funcName != szFuncName)
194         HeapFree(GetProcessHeap(), 0, (char *)funcName);
195     return ret;
196 }
197
198 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
199  BYTE *, DWORD *);
200
201 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
202  const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
203 {
204     BOOL ret = FALSE;
205     HMODULE lib;
206     CryptEncodeObjectFunc pCryptEncodeObject;
207
208     TRACE("(0x%08lx, %s, %p, %p, %p)\n",
209      dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
210      "(integer value)", pvStructInfo, pbEncoded, pcbEncoded);
211
212     if (!pbEncoded && !pcbEncoded)
213     {
214         SetLastError(ERROR_INVALID_PARAMETER);
215         return FALSE;
216     }
217
218     /* Try registered DLL first.. */
219     pCryptEncodeObject =
220      (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
221      lpszStructType, "CryptEncodeObject", &lib);
222     if (pCryptEncodeObject)
223     {
224         ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
225          pvStructInfo, pbEncoded, pcbEncoded);
226         FreeLibrary(lib);
227     }
228     else
229     {
230         /* If not, use CryptEncodeObjectEx */
231         ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
232          pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
233     }
234     return ret;
235 }
236
237 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
238  DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
239
240 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
241  const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
242  BYTE *pbEncoded, DWORD *pcbEncoded)
243 {
244     BOOL ret = FALSE, encoded = FALSE;
245
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,
249      pcbEncoded);
250
251     if (!pbEncoded && !pcbEncoded)
252     {
253         SetLastError(ERROR_INVALID_PARAMETER);
254         return FALSE;
255     }
256
257     if (!HIWORD(lpszStructType))
258     {
259         switch (LOWORD(lpszStructType))
260         {
261         default:
262             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
263         }
264     }
265     if (!encoded)
266     {
267         HMODULE lib;
268         CryptEncodeObjectExFunc pCryptEncodeObjectEx =
269          (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
270          lpszStructType, "CryptEncodeObjectEx", &lib);
271
272         if (pCryptEncodeObjectEx)
273         {
274             ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
275              pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
276             FreeLibrary(lib);
277         }
278     }
279     return ret;
280 }
281
282 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
283  DWORD, DWORD, void *, DWORD *);
284
285 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
286  const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
287  DWORD *pcbStructInfo)
288 {
289     BOOL ret = FALSE;
290     HMODULE lib;
291     CryptDecodeObjectFunc pCryptDecodeObject;
292
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,
296      pcbStructInfo);
297
298     if (!pvStructInfo && !pcbStructInfo)
299     {
300         SetLastError(ERROR_INVALID_PARAMETER);
301         return FALSE;
302     }
303
304     /* Try registered DLL first.. */
305     pCryptDecodeObject =
306      (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
307      lpszStructType, "CryptDecodeObject", &lib);
308     if (pCryptDecodeObject)
309     {
310         ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
311          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
312         FreeLibrary(lib);
313     }
314     else
315     {
316         /* If not, use CryptDecodeObjectEx */
317         ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
318          cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
319     }
320     return ret;
321 }
322
323 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
324  DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
325
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)
329 {
330     BOOL ret = FALSE, decoded = FALSE;
331
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);
336
337     if (!pvStructInfo && !pcbStructInfo)
338     {
339         SetLastError(ERROR_INVALID_PARAMETER);
340         return FALSE;
341     }
342
343     if (!HIWORD(lpszStructType))
344     {
345         switch (LOWORD(lpszStructType))
346         {
347         default:
348             FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
349         }
350     }
351     if (!decoded)
352     {
353         HMODULE lib;
354         CryptDecodeObjectExFunc pCryptDecodeObjectEx =
355          (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
356          lpszStructType, "CryptDecodeObjectEx", &lib);
357
358         if (pCryptDecodeObjectEx)
359         {
360             ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
361              pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
362              pcbStructInfo);
363             FreeLibrary(lib);
364         }
365     }
366     return ret;
367 }