winex11: add owned windows to taskbar if owner is not mapped
[wine] / dlls / advapi32 / crypt.c
1 /*
2  * Copyright 1999 Ian Schmidt
3  * Copyright 2001 Travis Michielsen
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /***********************************************************************
21  *
22  *  TODO:
23  *  - Reference counting
24  *  - Thread-safing
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29
30 #include <time.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_STAT_H
35 # include <sys/stat.h>
36 #endif
37 #include <fcntl.h>
38 #ifdef HAVE_UNISTD_H
39 # include <unistd.h>
40 #endif
41
42 #include "ntstatus.h"
43 #define WIN32_NO_STATUS
44 #include "crypt.h"
45 #include "winnls.h"
46 #include "winreg.h"
47 #include "rpc.h"
48 #include "wine/debug.h"
49 #include "wine/unicode.h"
50 #include "winternl.h"
51
52 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
53
54 static HWND crypt_hWindow;
55
56 #define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
57 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
58
59 static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
60 {
61         static const WCHAR KEYSTR[] = {
62                 'S','o','f','t','w','a','r','e','\\',
63                 'M','i','c','r','o','s','o','f','t','\\',
64                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
65                 'D','e','f','a','u','l','t','s','\\',
66                 'P','r','o','v','i','d','e','r','\\',0
67         };
68         PWSTR keyname;
69
70         keyname = CRYPT_Alloc((strlenW(KEYSTR) + strlenW(pProvName) +1)*sizeof(WCHAR));
71         if (keyname)
72         {
73                 strcpyW(keyname, KEYSTR);
74                 strcpyW(keyname + strlenW(KEYSTR), pProvName);
75         } else
76                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
77         return keyname;
78 }
79
80 static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
81 {
82         static const WCHAR MACHINESTR[] = {
83                 'S','o','f','t','w','a','r','e','\\',
84                 'M','i','c','r','o','s','o','f','t','\\',
85                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
86                 'D','e','f','a','u','l','t','s','\\',
87                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s','\\',
88                 'T','y','p','e',' ','X','X','X',0
89         };
90         static const WCHAR USERSTR[] = {
91                 'S','o','f','t','w','a','r','e','\\',
92                 'M','i','c','r','o','s','o','f','t','\\',
93                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
94                 'P','r','o','v','i','d','e','r',' ','T','y','p','e',' ','X','X','X',0
95         };
96         PWSTR keyname;
97         PWSTR ptr;
98
99         keyname = CRYPT_Alloc( ((user ? strlenW(USERSTR) : strlenW(MACHINESTR)) +1)*sizeof(WCHAR));
100         if (keyname)
101         {
102                 user ? strcpyW(keyname, USERSTR) : strcpyW(keyname, MACHINESTR);
103                 ptr = keyname + strlenW(keyname);
104                 *(--ptr) = (dwType % 10) + '0';
105                 *(--ptr) = ((dwType / 10) % 10) + '0';
106                 *(--ptr) = (dwType / 100) + '0';
107         } else
108                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
109         return keyname;
110 }
111
112 /* CRYPT_UnicodeTOANSI
113  * wstr - unicode string
114  * str - pointer to ANSI string
115  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
116  *
117  * returns TRUE if unsuccessful, FALSE otherwise.
118  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
119  */
120 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
121 {
122         int count;
123
124         if (!wstr)
125         {
126                 *str = NULL;
127                 return TRUE;
128         }
129         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
130         if (strsize == -1)
131                 *str = CRYPT_Alloc(count * sizeof(CHAR));
132         else
133                 count = min( count, strsize );
134         if (*str)
135         {
136                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
137                 return TRUE;
138         }
139         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
140         return FALSE;
141 }
142
143 /* CRYPT_ANSITOUnicode
144  * str - ANSI string
145  * wstr - pointer to unicode string
146  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
147  */
148 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
149 {
150         unsigned int wcount;
151
152         if (!str)
153         {
154                 *wstr = NULL;
155                 return TRUE;
156         }
157         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
158         if (wstrsize == -1)
159                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
160         else
161                 wcount = min( wcount, wstrsize/sizeof(WCHAR) );
162         if (*wstr)
163         {
164                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
165                 return TRUE;
166         }
167         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
168         return FALSE;
169 }
170
171 /* These next 2 functions are used by the VTableProvStruc structure */
172 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
173 {
174         if (!lpszImage || !pData)
175         {
176                 SetLastError(ERROR_INVALID_PARAMETER);
177                 return FALSE;
178         }
179
180         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
181
182         return TRUE;
183 }
184
185 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
186 {
187         if (!phWnd)
188                 return FALSE;
189         *phWnd = crypt_hWindow;
190         return TRUE;
191 }
192
193 #define CRYPT_GetProvFunc(name) \
194         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
195 #define CRYPT_GetProvFuncOpt(name) \
196         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
197 static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
198 {
199         PCRYPTPROV provider;
200         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
201
202         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
203         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
204         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
205         if ( !(provider->hModule = LoadLibraryW(pImage)) )
206         {
207                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
208                 FIXME("Failed to load dll %s\n", debugstr_w(pImage));
209                 goto error;
210         }
211         provider->dwMagic = MAGIC_CRYPTPROV;
212         provider->refcount = 1;
213
214         errorcode = NTE_PROVIDER_DLL_FAIL;
215         CRYPT_GetProvFunc(CPAcquireContext);
216         CRYPT_GetProvFunc(CPCreateHash);
217         CRYPT_GetProvFunc(CPDecrypt);
218         CRYPT_GetProvFunc(CPDeriveKey);
219         CRYPT_GetProvFunc(CPDestroyHash);
220         CRYPT_GetProvFunc(CPDestroyKey);
221         CRYPT_GetProvFuncOpt(CPDuplicateHash);
222         CRYPT_GetProvFuncOpt(CPDuplicateKey);
223         CRYPT_GetProvFunc(CPEncrypt);
224         CRYPT_GetProvFunc(CPExportKey);
225         CRYPT_GetProvFunc(CPGenKey);
226         CRYPT_GetProvFunc(CPGenRandom);
227         CRYPT_GetProvFunc(CPGetHashParam);
228         CRYPT_GetProvFunc(CPGetKeyParam);
229         CRYPT_GetProvFunc(CPGetProvParam);
230         CRYPT_GetProvFunc(CPGetUserKey);
231         CRYPT_GetProvFunc(CPHashData);
232         CRYPT_GetProvFunc(CPHashSessionKey);
233         CRYPT_GetProvFunc(CPImportKey);
234         CRYPT_GetProvFunc(CPReleaseContext);
235         CRYPT_GetProvFunc(CPSetHashParam);
236         CRYPT_GetProvFunc(CPSetKeyParam);
237         CRYPT_GetProvFunc(CPSetProvParam);
238         CRYPT_GetProvFunc(CPSignHash);
239         CRYPT_GetProvFunc(CPVerifySignature);
240
241         /* FIXME: Not sure what the pbContextInfo field is for.
242          *        Does it need memory allocation?
243          */
244         provider->pVTable->Version = 3;
245         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
246         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
247         provider->pVTable->dwProvType = 0;
248         provider->pVTable->pbContextInfo = NULL;
249         provider->pVTable->cbContextInfo = 0;
250         provider->pVTable->pszProvName = NULL;
251         return provider;
252
253 error:
254         SetLastError(errorcode);
255         if (provider)
256         {
257                 provider->dwMagic = 0;
258                 if (provider->hModule)
259                         FreeLibrary(provider->hModule);
260                 CRYPT_Free(provider->pVTable);
261                 CRYPT_Free(provider->pFuncs);
262                 CRYPT_Free(provider);
263         }
264         return NULL;
265 }
266 #undef CRYPT_GetProvFunc
267 #undef CRYPT_GetProvFuncOpt
268
269
270 static void CRYPT_CreateMachineGuid(void)
271 {
272         static const WCHAR cryptographyW[] = {
273                 'S','o','f','t','w','a','r','e','\\',
274                 'M','i','c','r','o','s','o','f','t','\\',
275                 'C','r','y','p','t','o','g','r','a','p','h','y',0 };
276         static const WCHAR machineGuidW[] = {
277                 'M','a','c','h','i','n','e','G','u','i','d',0 };
278         LONG r;
279         HKEY key;
280
281         r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cryptographyW, 0, KEY_ALL_ACCESS,
282                           &key);
283         if (!r)
284         {
285                 DWORD size;
286
287                 r = RegQueryValueExW(key, machineGuidW, NULL, NULL, NULL, &size);
288                 if (r == ERROR_FILE_NOT_FOUND)
289                 {
290                         static const WCHAR rpcrt4[] = {
291                                 'r','p','c','r','t','4',0 };
292                         HMODULE lib = LoadLibraryW(rpcrt4);
293
294                         if (lib)
295                         {
296                                 RPC_STATUS (RPC_ENTRY *pUuidCreate)(UUID *);
297                                 RPC_STATUS (RPC_ENTRY *pUuidToString)(UUID *, WCHAR **);
298                                 RPC_STATUS (RPC_ENTRY *pRpcStringFree)(WCHAR **);
299                                 UUID uuid;
300                                 WCHAR *uuidStr;
301
302                                 pUuidCreate = GetProcAddress(lib, "UuidCreate");
303                                 pUuidToString = GetProcAddress(lib, "UuidToStringW");
304                                 pRpcStringFree = GetProcAddress(lib, "RpcStringFreeW");
305                                 pUuidCreate(&uuid);
306                                 pUuidToString(&uuid, &uuidStr);
307                                 RegSetValueExW(key, machineGuidW, 0, REG_SZ,
308                                                (const BYTE *)uuidStr,
309                                                (lstrlenW(uuidStr)+1)*sizeof(WCHAR));
310                                 pRpcStringFree(&uuidStr);
311                                 FreeLibrary(lib);
312                         }
313                 }
314                 RegCloseKey(key);
315         }
316 }
317
318 /******************************************************************************
319  * CryptAcquireContextW (ADVAPI32.@)
320  *
321  * Acquire a crypto provider context handle.
322  *
323  * PARAMS
324  *  phProv       [O] Pointer to HCRYPTPROV for the output.
325  *  pszContainer [I] Key Container Name
326  *  pszProvider  [I] Cryptographic Service Provider Name
327  *  dwProvType   [I] Crypto provider type to get a handle.
328  *  dwFlags      [I] flags for the operation
329  *
330  * RETURNS 
331  *  TRUE on success, FALSE on failure.
332  */
333 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
334                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
335 {
336         PCRYPTPROV pProv = NULL;
337         HKEY key;
338         PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
339         PSTR provnameA = NULL, pszContainerA = NULL;
340         DWORD keytype, type, len;
341         ULONG r;
342         static const WCHAR nameW[] = {'N','a','m','e',0};
343         static const WCHAR typeW[] = {'T','y','p','e',0};
344         static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
345
346         TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_w(pszContainer),
347                 debugstr_w(pszProvider), dwProvType, dwFlags);
348
349         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
350         {
351                 SetLastError(NTE_BAD_PROV_TYPE);
352                 return FALSE;
353         }
354         
355         if (!phProv)
356         {
357                 SetLastError(ERROR_INVALID_PARAMETER);
358                 return FALSE;
359         }
360
361         /* Make sure the MachineGuid value exists */
362         CRYPT_CreateMachineGuid();
363
364         if (!pszProvider || !*pszProvider)
365         {
366                 /* No CSP name specified so try the user default CSP first
367                  * then try the machine default CSP
368                  */
369                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
370                         TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
371                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
372                         return FALSE;
373                 }
374                 if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
375                 {
376                         CRYPT_Free(keyname);
377                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
378                                 TRACE("No type registered for crypto provider type %d.\n", dwProvType);
379                                 RegCloseKey(key);
380                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
381                                 goto error;
382                         }
383                         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
384                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
385                                 CRYPT_Free(keyname);
386                                 RegCloseKey(key);
387                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
388                                 goto error;
389                         }
390                 }
391                 CRYPT_Free(keyname);
392                 r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
393                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
394                 {
395                         TRACE("error %d reading size of 'Name' from registry\n", r );
396                         RegCloseKey(key);
397                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
398                         goto error;
399                 }
400                 if(!(provname = CRYPT_Alloc(len)))
401                 {
402                         RegCloseKey(key);
403                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
404                         goto error;
405                 }
406                 r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
407                 if( r != ERROR_SUCCESS )
408                 {
409                         TRACE("error %d reading 'Name' from registry\n", r );
410                         RegCloseKey(key);
411                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
412                         goto error;
413                 }
414                 RegCloseKey(key);
415         } else {
416                 if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
417                 {
418                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
419                         goto error;
420                 }
421                 strcpyW(provname, pszProvider);
422         }
423
424         keyname = CRYPT_GetProvKeyName(provname);
425         r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
426         CRYPT_Free(keyname);
427         if (r != ERROR_SUCCESS)
428         {
429                 SetLastError(NTE_KEYSET_NOT_DEF);
430                 goto error;
431         }
432         len = sizeof(DWORD);
433         r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
434         if (r != ERROR_SUCCESS)
435         {
436                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
437                 goto error;
438         }
439         if (type != dwProvType)
440         {
441                 TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
442                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
443                 goto error;
444         }
445
446         r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
447         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
448         {
449                 TRACE("error %d reading size of 'Image Path' from registry\n", r );
450                 RegCloseKey(key);
451                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
452                 goto error;
453         }
454         if (!(temp = CRYPT_Alloc(len)))
455         {
456                 RegCloseKey(key);
457                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
458                 goto error;
459         }
460         r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
461         if( r != ERROR_SUCCESS )
462         {
463                 TRACE("error %d reading 'Image Path' from registry\n", r );
464                 RegCloseKey(key);
465                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
466                 goto error;
467         }
468         RegCloseKey(key);
469         len = ExpandEnvironmentStringsW(temp, NULL, 0);
470         if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
471         {
472                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
473                 goto error;
474         }
475         if (!ExpandEnvironmentStringsW(temp, imagepath, len))
476         {
477                 /* ExpandEnvironmentStrings will call SetLastError */
478                 goto error;
479         }
480         pProv = CRYPT_LoadProvider(imagepath);
481         if (!pProv) {
482                 /* CRYPT_LoadProvider calls SetLastError */
483                 goto error;
484         }
485         pProv->pVTable->dwProvType = dwProvType;
486         if(!CRYPT_UnicodeToANSI(provname, &provnameA, -1))
487         {
488                 /* CRYPT_UnicodeToANSI calls SetLastError */
489                 goto error;
490         }
491         pProv->pVTable->pszProvName = provnameA;
492         if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, -1))
493         {
494                 /* CRYPT_UnicodeToANSI calls SetLastError */
495                 goto error;
496         }
497         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
498         {
499                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
500                  *       and thus, the CryptReleaseContext function need not be called afterwards.
501                  *       Therefore, we must clean up everything now.
502                  */
503                 if (dwFlags & CRYPT_DELETEKEYSET)
504                 {
505                         pProv->dwMagic = 0;
506                         FreeLibrary(pProv->hModule);
507                         CRYPT_Free(provnameA);
508                         CRYPT_Free(pProv->pVTable);
509                         CRYPT_Free(pProv->pFuncs);
510                         CRYPT_Free(pProv);
511                 } else {
512                         *phProv = (HCRYPTPROV)pProv;
513                 }
514                 CRYPT_Free(pszContainerA);
515                 CRYPT_Free(provname);
516                 CRYPT_Free(temp);
517                 CRYPT_Free(imagepath);
518                 return TRUE;
519         }
520         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
521 error:
522         if (pProv)
523         {
524                 pProv->dwMagic = 0;
525                 if (pProv->hModule)
526                         FreeLibrary(pProv->hModule);
527                 CRYPT_Free(pProv->pVTable);
528                 CRYPT_Free(pProv->pFuncs);
529                 CRYPT_Free(pProv);
530         }
531         CRYPT_Free(pszContainerA);
532         CRYPT_Free(provnameA);
533         CRYPT_Free(provname);
534         CRYPT_Free(temp);
535         CRYPT_Free(imagepath);
536         return FALSE;
537 }
538
539 /******************************************************************************
540  * CryptAcquireContextA (ADVAPI32.@)
541  *
542  * See CryptAcquireContextW.
543  */
544 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
545                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
546 {
547         PWSTR pProvider = NULL, pContainer = NULL;
548         BOOL ret = FALSE;
549
550         TRACE("(%p, %s, %s, %d, %08x)\n", phProv, pszContainer,
551                 pszProvider, dwProvType, dwFlags);
552
553         if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
554         {
555                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
556                 return FALSE;
557         }
558         if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
559         {
560                 CRYPT_Free(pContainer);
561                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
562                 return FALSE;
563         }
564
565         ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
566
567         CRYPT_Free(pContainer);
568         CRYPT_Free(pProvider);
569
570         return ret;
571 }
572
573 /******************************************************************************
574  * CryptContextAddRef (ADVAPI32.@)
575  *
576  * Increases reference count of a cryptographic service provider handle
577  * by one.
578  *
579  * PARAMS
580  *  hProv       [I] Handle to the CSP whose reference is being incremented.
581  *  pdwReserved [IN] Reserved for future use and must be NULL.
582  *  dwFlags     [I] Reserved for future use and must be NULL.
583  *
584  * RETURNS
585  *  Success: TRUE
586  *  Failure: FALSE
587  */
588 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
589 {
590         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
591
592         TRACE("(0x%lx, %p, %08x)\n", hProv, pdwReserved, dwFlags);
593
594         if (!pProv)
595         {
596                 SetLastError(NTE_BAD_UID);
597                 return FALSE;
598         }
599
600         if (pProv->dwMagic != MAGIC_CRYPTPROV)
601         {
602                 SetLastError(ERROR_INVALID_PARAMETER);
603                 return FALSE;
604         }
605
606         pProv->refcount++;
607         return TRUE;
608 }
609
610 /******************************************************************************
611  * CryptReleaseContext (ADVAPI32.@)
612  *
613  * Releases the handle of a CSP.  Reference count is decreased.
614  *
615  * PARAMS
616  *  hProv   [I] Handle of a CSP.
617  *  dwFlags [I] Reserved for future use and must be NULL.
618  *
619  * RETURNS
620  *  Success: TRUE
621  *  Failure: FALSE
622  */
623 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, ULONG_PTR dwFlags)
624 {
625         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
626         BOOL ret = TRUE;
627
628         TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
629
630         if (!pProv)
631         {
632                 SetLastError(NTE_BAD_UID);
633                 return FALSE;
634         }
635
636         if (pProv->dwMagic != MAGIC_CRYPTPROV)
637         {
638                 SetLastError(ERROR_INVALID_PARAMETER);
639                 return FALSE;
640         }
641
642         pProv->refcount--;
643         if (pProv->refcount <= 0) 
644         {
645                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
646                 pProv->dwMagic = 0;
647                 FreeLibrary(pProv->hModule);
648 #if 0
649                 CRYPT_Free(pProv->pVTable->pContextInfo);
650 #endif
651                 CRYPT_Free(pProv->pVTable->pszProvName);
652                 CRYPT_Free(pProv->pVTable);
653                 CRYPT_Free(pProv->pFuncs);
654                 CRYPT_Free(pProv);
655         }
656         return ret;
657 }
658
659 /******************************************************************************
660  * CryptGenRandom (ADVAPI32.@)
661  *
662  * Fills a buffer with cryptographically random bytes.
663  *
664  * PARAMS
665  *  hProv    [I] Handle of a CSP.
666  *  dwLen    [I] Number of bytes to generate.
667  *  pbBuffer [I/O] Buffer to contain random bytes.
668  *
669  * RETURNS
670  *  Success: TRUE
671  *  Failure: FALSE
672  *
673  * NOTES
674  *  pdBuffer must be at least dwLen bytes long.
675  */
676 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
677 {
678         PCRYPTPROV prov = (PCRYPTPROV)hProv;
679
680         TRACE("(0x%lx, %d, %p)\n", hProv, dwLen, pbBuffer);
681
682         if (!hProv)
683         {
684                 SetLastError(ERROR_INVALID_HANDLE);
685                 return FALSE;
686         }
687
688         if (prov->dwMagic != MAGIC_CRYPTPROV)
689         {
690                 SetLastError(ERROR_INVALID_PARAMETER);
691                 return FALSE;
692         }
693
694         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
695 }
696
697 /******************************************************************************
698  * CryptCreateHash (ADVAPI32.@)
699  *
700  * Initiates the hashing of a stream of data.
701  *
702  * PARAMS
703  *  hProv   [I] Handle of a CSP.
704  *  Algid   [I] Identifies the hash algorithm to use.
705  *  hKey    [I] Key for the hash (if required).
706  *  dwFlags [I] Reserved for future use and must be NULL.
707  *  phHash  [O] Address of the future handle to the new hash object.
708  *
709  * RETURNS
710  *  Success: TRUE
711  *  Failure: FALSE
712  *
713  * NOTES
714  *  If the algorithm is a keyed hash, hKey is the key.
715  */
716 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
717                 DWORD dwFlags, HCRYPTHASH *phHash)
718 {
719         PCRYPTPROV prov = (PCRYPTPROV)hProv;
720         PCRYPTKEY key = (PCRYPTKEY)hKey;
721         PCRYPTHASH hash;
722
723         TRACE("(0x%lx, 0x%x, 0x%lx, %08x, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
724
725         if (!prov)
726         {
727                 SetLastError(ERROR_INVALID_HANDLE);
728                 return FALSE;
729         }
730         if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
731         {
732                 SetLastError(ERROR_INVALID_PARAMETER);
733                 return FALSE;
734         }
735         if (dwFlags)
736         {
737                 SetLastError(NTE_BAD_FLAGS);
738                 return FALSE;
739         }
740         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
741         {
742                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
743                 return FALSE;
744         }
745
746         hash->pProvider = prov;
747
748         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
749                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
750         {
751             *phHash = (HCRYPTHASH)hash;
752             return TRUE;
753         }
754
755         /* CSP error! */
756         CRYPT_Free(hash);
757         *phHash = 0;
758         return FALSE;
759 }
760
761 /******************************************************************************
762  * CryptDecrypt (ADVAPI32.@)
763  *
764  * Decrypts data encrypted by CryptEncrypt.
765  *
766  * PARAMS
767  *  hKey       [I] Handle to the decryption key.
768  *  hHash      [I] Handle to a hash object.
769  *  Final      [I] TRUE if this is the last section to be decrypted.
770  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
771  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
772  *                   data on return
773  *  pdwDataLen [I/O] Length of pbData before and after the call.
774  *
775  *  RETURNS
776  *   Success: TRUE
777  *   Failure: FALSE
778  */
779 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
780                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
781 {
782         PCRYPTPROV prov;
783         PCRYPTKEY key = (PCRYPTKEY)hKey;
784         PCRYPTHASH hash = (PCRYPTHASH)hHash;
785
786         TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
787
788         if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
789         {
790                 SetLastError(ERROR_INVALID_PARAMETER);
791                 return FALSE;
792         }
793
794         prov = key->pProvider;
795         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
796                         Final, dwFlags, pbData, pdwDataLen);
797 }
798
799 /******************************************************************************
800  * CryptDeriveKey (ADVAPI32.@)
801  *
802  * Generates session keys derived from a base data value.
803  *
804  * PARAMS
805  *  hProv     [I] Handle to a CSP.
806  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
807  *  hBaseData [I] Handle to a hash object.
808  *  dwFlags   [I] Type of key to generate.
809  *  phKey     [I/O] Address of the newly generated key.
810  *
811  * RETURNS
812  *  Success: TRUE
813  *  Failure: FALSE
814  */
815 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
816                 DWORD dwFlags, HCRYPTKEY *phKey)
817 {
818         PCRYPTPROV prov = (PCRYPTPROV)hProv;
819         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
820         PCRYPTKEY key;
821
822         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08x, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
823
824         if (!prov || !hash)
825         {
826                 SetLastError(ERROR_INVALID_HANDLE);
827                 return FALSE;
828         }
829         if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
830         {
831                 SetLastError(ERROR_INVALID_PARAMETER);
832                 return FALSE;
833         }
834         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
835         {
836                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
837                 return FALSE;
838         }
839
840         key->pProvider = prov;
841         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
842         {
843             *phKey = (HCRYPTKEY)key;
844             return TRUE;
845         }
846
847         /* CSP error! */
848         CRYPT_Free(key);
849         *phKey = 0;
850         return FALSE;
851 }
852
853 /******************************************************************************
854  * CryptDestroyHash (ADVAPI32.@)
855  *
856  * Destroys the hash object referenced by hHash.
857  *
858  * PARAMS
859  *  hHash [I] Handle of the hash object to be destroyed.
860  *
861  * RETURNS
862  *  Success: TRUE
863  *  Failure: FALSE
864  */
865 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
866 {
867         PCRYPTHASH hash = (PCRYPTHASH)hHash;
868         PCRYPTPROV prov;
869         BOOL ret;
870
871         TRACE("(0x%lx)\n", hHash);
872
873         if (!hash)
874         {
875                 SetLastError(ERROR_INVALID_HANDLE);
876                 return FALSE;
877         }
878
879         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
880         {
881                 SetLastError(ERROR_INVALID_PARAMETER);
882                 return FALSE;
883         }
884
885         prov = hash->pProvider;
886         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
887         CRYPT_Free(hash);
888         return ret;
889 }
890
891 /******************************************************************************
892  * CryptDestroyKey (ADVAPI32.@)
893  *
894  * Releases the handle referenced by hKey.
895  *
896  * PARAMS
897  *  hKey [I] Handle of the key to be destroyed.
898  *
899  * RETURNS
900  *  Success: TRUE
901  *  Failure: FALSE
902  */
903 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
904 {
905         PCRYPTKEY key = (PCRYPTKEY)hKey;
906         PCRYPTPROV prov;
907         BOOL ret;
908
909         TRACE("(0x%lx)\n", hKey);
910
911         if (!key)
912         {
913                 SetLastError(ERROR_INVALID_HANDLE);
914                 return FALSE;
915         }
916
917         if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
918         {
919                 SetLastError(ERROR_INVALID_PARAMETER);
920                 return FALSE;
921         }
922
923         prov = key->pProvider;
924         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
925         CRYPT_Free(key);
926         return ret;
927 }
928
929 /******************************************************************************
930  * CryptDuplicateHash (ADVAPI32.@)
931  *
932  * Duplicates a hash.
933  *
934  * PARAMS
935  *  hHash       [I] Handle to the hash to be copied.
936  *  pdwReserved [I] Reserved for future use and must be zero.
937  *  dwFlags     [I] Reserved for future use and must be zero.
938  *  phHash      [O] Address of the handle to receive the copy.
939  *
940  * RETURNS
941  *  Success: TRUE
942  *  Failure: FALSE
943  */
944 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
945                 DWORD dwFlags, HCRYPTHASH *phHash)
946 {
947         PCRYPTPROV prov;
948         PCRYPTHASH orghash, newhash;
949
950         TRACE("(0x%lx, %p, %08x, %p)\n", hHash, pdwReserved, dwFlags, phHash);
951
952         orghash = (PCRYPTHASH)hHash;
953         if (!orghash || pdwReserved || !phHash || !orghash->pProvider || 
954                 orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
955         {
956                 SetLastError(ERROR_INVALID_PARAMETER);
957                 return FALSE;
958         }
959
960         prov = orghash->pProvider;
961         if (!prov->pFuncs->pCPDuplicateHash)
962         {
963                 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
964                 return FALSE;
965         }
966
967         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
968         {
969                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
970                 return FALSE;
971         }
972
973         newhash->pProvider = prov;
974         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
975         {
976                 *phHash = (HCRYPTHASH)newhash;
977                 return TRUE;
978         }
979         CRYPT_Free(newhash);
980         return FALSE;
981 }
982
983 /******************************************************************************
984  * CryptDuplicateKey (ADVAPI32.@)
985  *
986  * Duplicate a key and the key's state.
987  *
988  * PARAMS
989  *  hKey        [I] Handle of the key to copy.
990  *  pdwReserved [I] Reserved for future use and must be NULL.
991  *  dwFlags     [I] Reserved for future use and must be zero.
992  *  phKey       [I] Address of the handle to the duplicated key.
993  *
994  * RETURNS
995  *  Success: TRUE
996  *  Failure: FALSE
997  */
998 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
999 {
1000         PCRYPTPROV prov;
1001         PCRYPTKEY orgkey, newkey;
1002
1003         TRACE("(0x%lx, %p, %08x, %p)\n", hKey, pdwReserved, dwFlags, phKey);
1004
1005         orgkey = (PCRYPTKEY)hKey;
1006         if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider || 
1007                 orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
1008         {
1009                 SetLastError(ERROR_INVALID_PARAMETER);
1010                 return FALSE;
1011         }
1012
1013         prov = orgkey->pProvider;
1014         if (!prov->pFuncs->pCPDuplicateKey)
1015         {
1016                 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1017                 return FALSE;
1018         }
1019
1020         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1021         {
1022                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1023                 return FALSE;
1024         }
1025
1026         newkey->pProvider = prov;
1027         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
1028         {
1029                 *phKey = (HCRYPTKEY)newkey;
1030                 return TRUE;
1031         }
1032         CRYPT_Free(newkey);
1033         return FALSE;
1034 }
1035
1036 /******************************************************************************
1037  * CryptEncrypt (ADVAPI32.@)
1038  *
1039  * Encrypts data.
1040  *
1041  * PARAMS
1042  *  hKey       [I] Handle to the encryption key.
1043  *  hHash      [I] Handle to a hash object.
1044  *  Final      [I] TRUE if this is the last section to encrypt.
1045  *  dwFlags    [I] Can be CRYPT_OAEP.
1046  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
1047  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
1048  *                   encrypted data after call.
1049  *  dwBufLen   [I] Length of the input pbData buffer.
1050  *
1051  * RETURNS
1052  *  Success: TRUE
1053  *  Failure: FALSE
1054  *
1055  *  NOTES
1056  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
1057  *   required for the returned data in pdwDataLen.
1058  */
1059 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1060                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1061 {
1062         PCRYPTPROV prov;
1063         PCRYPTKEY key = (PCRYPTKEY)hKey;
1064         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1065
1066         TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p, %d)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1067
1068         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1069         {
1070                 SetLastError(ERROR_INVALID_PARAMETER);
1071                 return FALSE;
1072         }
1073
1074         prov = key->pProvider;
1075         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
1076                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1077 }
1078
1079 /******************************************************************************
1080  * CryptEnumProvidersW (ADVAPI32.@)
1081  *
1082  * Returns the next available CSP.
1083  *
1084  * PARAMS
1085  *  dwIndex     [I] Index of the next provider to be enumerated.
1086  *  pdwReserved [I] Reserved for future use and must be NULL.
1087  *  dwFlags     [I] Reserved for future use and must be zero.
1088  *  pdwProvType [O] DWORD designating the type of the provider.
1089  *  pszProvName [O] Buffer that receives data from the provider.
1090  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
1091  *                    of bytes stored in the buffer on return.
1092  *
1093  *  RETURNS
1094  *   Success: TRUE
1095  *   Failure: FALSE
1096  *
1097  *  NOTES
1098  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
1099  *   for memory allocation purposes.
1100  */
1101 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
1102                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
1103 {
1104         HKEY hKey;
1105         static const WCHAR providerW[] = {
1106                 'S','o','f','t','w','a','r','e','\\',
1107                 'M','i','c','r','o','s','o','f','t','\\',
1108                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1109                 'D','e','f','a','u','l','t','s','\\',
1110                 'P','r','o','v','i','d','e','r',0
1111         };
1112         static const WCHAR typeW[] = {'T','y','p','e',0};
1113
1114         TRACE("(%d, %p, %d, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1115                         pdwProvType, pszProvName, pcbProvName);
1116
1117         if (pdwReserved || !pcbProvName)
1118         {
1119                 SetLastError(ERROR_INVALID_PARAMETER);
1120                 return FALSE;
1121         }
1122         if (dwFlags)
1123         {
1124                 SetLastError(NTE_BAD_FLAGS);
1125                 return FALSE;
1126         }
1127
1128         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
1129         {
1130                 SetLastError(NTE_FAIL);
1131                 return FALSE;
1132         }
1133
1134         if (!pszProvName)
1135         {
1136                 DWORD numkeys;
1137                 WCHAR *provNameW;
1138                 
1139                 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
1140                                  NULL, NULL, NULL, NULL, NULL, NULL);
1141                 
1142                 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1143                 {
1144                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1145                         return FALSE;
1146                 }
1147
1148                 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1149                 CRYPT_Free(provNameW);
1150                 (*pcbProvName)++;
1151                 *pcbProvName *= sizeof(WCHAR);
1152
1153                 if (dwIndex >= numkeys)
1154                 {
1155                         SetLastError(ERROR_NO_MORE_ITEMS);
1156                         return FALSE;
1157                 }
1158         } else {
1159                 DWORD size = sizeof(DWORD);
1160                 DWORD result;
1161                 HKEY subkey;
1162                 
1163                 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1164                 if (result)
1165                 {
1166                         SetLastError(result);
1167                         return FALSE;
1168                 }
1169                 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1170                         return FALSE;
1171                 if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1172                         return FALSE;
1173                 RegCloseKey(subkey);
1174         }
1175         RegCloseKey(hKey);
1176         return TRUE;
1177 }
1178
1179 /******************************************************************************
1180  * CryptEnumProvidersA (ADVAPI32.@)
1181  *
1182  * See CryptEnumProvidersW.
1183  */
1184 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1185                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1186 {
1187         PWSTR str = NULL;
1188         DWORD strlen;
1189         BOOL ret; /* = FALSE; */
1190
1191         TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1192                         pdwProvType, pszProvName, pcbProvName);
1193
1194         if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
1195                 return FALSE;
1196         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1197         {
1198                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1199                 return FALSE;
1200         }
1201         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1202         if (str)
1203                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1204         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1205         if (str)
1206         {
1207                 CRYPT_Free(str);
1208                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1209                 {
1210                         SetLastError(ERROR_MORE_DATA);
1211                         return FALSE;
1212                 }
1213         }
1214         return ret;
1215 }
1216
1217 /******************************************************************************
1218  * CryptEnumProviderTypesW (ADVAPI32.@)
1219  *
1220  * Retrieves the next type of CSP supported.
1221  *
1222  * PARAMS
1223  *  dwIndex     [I] Index of the next provider to be enumerated.
1224  *  pdwReserved [I] Reserved for future use and must be NULL.
1225  *  dwFlags     [I] Reserved for future use and must be zero.
1226  *  pdwProvType [O] DWORD designating the type of the provider.
1227  *  pszTypeName [O] Buffer that receives data from the provider type.
1228  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1229  *                    of bytes stored in the buffer on return.
1230  *
1231  *  RETURNS
1232  *   Success: TRUE
1233  *   Failure: FALSE
1234  *
1235  *  NOTES
1236  *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1237  *   for memory allocation purposes.
1238  */
1239 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1240                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1241 {
1242         HKEY hKey, hSubkey;
1243         DWORD keylen, numkeys, dwType;
1244         PWSTR keyname, ch;
1245         DWORD result;
1246         static const WCHAR KEYSTR[] = {
1247                 'S','o','f','t','w','a','r','e','\\',
1248                 'M','i','c','r','o','s','o','f','t','\\',
1249                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1250                 'D','e','f','a','u','l','t','s','\\',
1251                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
1252         };
1253         static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
1254
1255         TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved,
1256                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1257
1258         if (pdwReserved || !pdwProvType || !pcbTypeName)
1259         {
1260                 SetLastError(ERROR_INVALID_PARAMETER);
1261                 return FALSE;
1262         }
1263         if (dwFlags)
1264         {
1265                 SetLastError(NTE_BAD_FLAGS);
1266                 return FALSE;
1267         }
1268
1269         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
1270                 return FALSE;
1271
1272         RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1273         if (dwIndex >= numkeys)
1274         {
1275                 SetLastError(ERROR_NO_MORE_ITEMS);
1276                 return FALSE;
1277         }
1278         keylen++;
1279         if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1280         {
1281                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1282                 return FALSE;
1283         }
1284         if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1285                 CRYPT_Free(keyname);
1286                 return FALSE;
1287         }
1288         RegOpenKeyW(hKey, keyname, &hSubkey);
1289         ch = keyname + strlenW(keyname);
1290         /* Convert "Type 000" to 0, etc/ */
1291         *pdwProvType = *(--ch) - '0';
1292         *pdwProvType += (*(--ch) - '0') * 10;
1293         *pdwProvType += (*(--ch) - '0') * 100;
1294         CRYPT_Free(keyname);
1295         
1296         result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1297         if (result)
1298         {
1299                 SetLastError(result);
1300                 return FALSE;
1301         }
1302
1303         RegCloseKey(hSubkey);
1304         RegCloseKey(hKey);
1305         return TRUE;
1306 }
1307
1308 /******************************************************************************
1309  * CryptEnumProviderTypesA (ADVAPI32.@)
1310  *
1311  * See CryptEnumProviderTypesW.
1312  */
1313 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1314                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1315 {
1316         PWSTR str = NULL;
1317         DWORD strlen;
1318         BOOL ret;
1319
1320         TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1321                         pdwProvType, pszTypeName, pcbTypeName);
1322
1323         if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
1324                 return FALSE;
1325         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1326         {
1327                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1328                 return FALSE;
1329         }
1330         ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1331         if (str)
1332                 CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1333         *pcbTypeName = strlen / sizeof(WCHAR);
1334         if (str)
1335         {
1336                 CRYPT_Free(str);
1337                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1338                 {
1339                         SetLastError(ERROR_MORE_DATA);
1340                         return FALSE;
1341                 }
1342         }
1343         return ret;
1344 }
1345
1346 /******************************************************************************
1347  * CryptExportKey (ADVAPI32.@)
1348  * 
1349  * Exports a cryptographic key from a CSP.
1350  *
1351  * PARAMS
1352  *  hKey       [I] Handle to the key to export.
1353  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1354  *  dwBlobType [I] Type of BLOB to be exported.
1355  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1356  *  pbData     [O] Buffer to receive BLOB data.
1357  *  pdwDataLen [I/O] Specifies the size of pbData.
1358  *
1359  * RETURNS
1360  *  Success: TRUE
1361  *  Failure: FALSE
1362  *
1363  * NOTES
1364  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1365  *  buffer needed to hold the BLOB.
1366  */
1367 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1368                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1369 {
1370         PCRYPTPROV prov;
1371         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1372
1373         TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1374
1375         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1376         {
1377                 SetLastError(ERROR_INVALID_PARAMETER);
1378                 return FALSE;
1379         }
1380
1381         prov = key->pProvider;
1382         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1383                         dwBlobType, dwFlags, pbData, pdwDataLen);
1384 }
1385
1386 /******************************************************************************
1387  * CryptGenKey (ADVAPI32.@)
1388  *
1389  * Generates a random cryptographic session key or a pub/priv key pair.
1390  *
1391  * PARAMS
1392  *  hProv   [I] Handle to a CSP.
1393  *  Algid   [I] Algorithm to use to make key.
1394  *  dwFlags [I] Specifies type of key to make.
1395  *  phKey   [I] Address of the handle to which the new key is copied.
1396  *
1397  *  RETURNS
1398  *   Success: TRUE
1399  *   Failure: FALSE
1400  */
1401 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1402 {
1403         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1404         PCRYPTKEY key;
1405
1406         TRACE("(0x%lx, %d, %08x, %p)\n", hProv, Algid, dwFlags, phKey);
1407
1408         if (!prov)
1409         {
1410                 SetLastError(ERROR_INVALID_HANDLE);
1411                 return FALSE;
1412         }
1413         if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1414         {
1415                 SetLastError(ERROR_INVALID_PARAMETER);
1416                 return FALSE;
1417         }
1418         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1419         {
1420                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1421                 return FALSE;
1422         }
1423
1424         key->pProvider = prov;
1425
1426         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1427         {
1428             *phKey = (HCRYPTKEY)key;
1429             return TRUE;
1430         }
1431
1432         /* CSP error! */
1433         CRYPT_Free(key);
1434         return FALSE;
1435 }
1436
1437 /******************************************************************************
1438  * CryptGetDefaultProviderW (ADVAPI32.@)
1439  *
1440  * Finds the default CSP of a certain provider type.
1441  *
1442  * PARAMS
1443  *  dwProvType  [I] Provider type to look for.
1444  *  pdwReserved [I] Reserved for future use and must be NULL.
1445  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1446  *  pszProvName [O] Name of the default CSP.
1447  *  pcbProvName [I/O] Size of pszProvName
1448  *
1449  * RETURNS
1450  *  Success: TRUE
1451  *  Failure: FALSE
1452  *
1453  * NOTES
1454  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1455  *  memory allocation purposes on return.
1456  */
1457 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1458                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1459 {
1460         HKEY hKey;
1461         PWSTR keyname;
1462         DWORD result;
1463         static const WCHAR nameW[] = {'N','a','m','e',0};
1464
1465         if (pdwReserved || !pcbProvName)
1466         {
1467                 SetLastError(ERROR_INVALID_PARAMETER);
1468                 return FALSE;
1469         }
1470         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1471         {
1472                 SetLastError(NTE_BAD_FLAGS);
1473                 return FALSE;
1474         }
1475         if (dwProvType > 999)
1476         {
1477                 SetLastError(NTE_BAD_PROV_TYPE);
1478                 return FALSE;
1479         }
1480         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1481         {
1482                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1483                 return FALSE;
1484         }
1485         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1486         {
1487                 CRYPT_Free(keyname);
1488                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
1489                 return FALSE;
1490         }
1491         CRYPT_Free(keyname);
1492         
1493         result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName); 
1494         if (result)
1495         {
1496                 if (result != ERROR_MORE_DATA)
1497                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1498                 else
1499                         SetLastError(result);
1500                 
1501                 return FALSE;
1502         }
1503         
1504         RegCloseKey(hKey);
1505         return TRUE;
1506 }
1507
1508 /******************************************************************************
1509  * CryptGetDefaultProviderA (ADVAPI32.@)
1510  *
1511  * See CryptGetDefaultProviderW.
1512  */
1513 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1514                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1515 {
1516         PWSTR str = NULL;
1517         DWORD strlen;
1518         BOOL ret = FALSE;
1519
1520         TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1521
1522         CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &strlen);
1523         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1524         {
1525                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1526                 return FALSE;
1527         }
1528         ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &strlen);
1529         if (str)
1530                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1531         *pcbProvName = strlen / sizeof(WCHAR);
1532         if (str)
1533         {
1534                 CRYPT_Free(str);
1535                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1536                 {
1537                         SetLastError(ERROR_MORE_DATA);
1538                         return FALSE;
1539                 }
1540         }
1541         return ret;
1542 }
1543
1544 /******************************************************************************
1545  * CryptGetHashParam (ADVAPI32.@)
1546  *
1547  * Retrieves data that controls the operations of a hash object.
1548  *
1549  * PARAMS
1550  *  hHash      [I] Handle of the hash object to question.
1551  *  dwParam    [I] Query type.
1552  *  pbData     [O] Buffer that receives the value data.
1553  *  pdwDataLen [I/O] Size of the pbData buffer.
1554  *  dwFlags    [I] Reserved for future use and must be zero.
1555  *
1556  * RETURNS
1557  *  Success: TRUE
1558  *  Failure: FALSE
1559  *
1560  * NOTES
1561  *  If pbData is NULL, pdwDataLen will contain the length required.
1562  */
1563 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1564                 DWORD *pdwDataLen, DWORD dwFlags)
1565 {
1566         PCRYPTPROV prov;
1567         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1568
1569         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1570
1571         if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1572         {
1573                 SetLastError(ERROR_INVALID_PARAMETER);
1574                 return FALSE;
1575         }
1576
1577         prov = hash->pProvider;
1578         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1579                         pbData, pdwDataLen, dwFlags);
1580 }
1581
1582 /******************************************************************************
1583  * CryptGetKeyParam (ADVAPI32.@)
1584  *
1585  * Retrieves data that controls the operations of a key.
1586  *
1587  * PARAMS
1588  *  hKey       [I] Handle to they key in question.
1589  *  dwParam    [I] Specifies query type.
1590  *  pbData     [O] Sequence of bytes to receive data.
1591  *  pdwDataLen [I/O] Size of pbData.
1592  *  dwFlags    [I] Reserved for future use and must be zero.
1593  *
1594  * RETURNS
1595  *  Success: TRUE
1596  *  Failure: FALSE
1597  *
1598  * NOTES
1599  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1600  */
1601 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1602                 DWORD *pdwDataLen, DWORD dwFlags)
1603 {
1604         PCRYPTPROV prov;
1605         PCRYPTKEY key = (PCRYPTKEY)hKey;
1606
1607         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1608
1609         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1610         {
1611                 SetLastError(ERROR_INVALID_PARAMETER);
1612                 return FALSE;
1613         }
1614
1615         prov = key->pProvider;
1616         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1617                         pbData, pdwDataLen, dwFlags);
1618 }
1619
1620 /******************************************************************************
1621  * CryptGetProvParam (ADVAPI32.@)
1622  *
1623  * Retrieves parameters that control the operations of a CSP.
1624  *
1625  * PARAMS
1626  *  hProv      [I] Handle of the CSP in question.
1627  *  dwParam    [I] Specifies query type.
1628  *  pbData     [O] Buffer to receive the data.
1629  *  pdwDataLen [I/O] Size of pbData.
1630  *  dwFlags    [I] see MSDN Docs.
1631  *
1632  * RETURNS
1633  *  Success: TRUE
1634  *  Failure: FALSE
1635  *
1636  * NOTES
1637  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1638  */
1639 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1640                 DWORD *pdwDataLen, DWORD dwFlags)
1641 {
1642         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1643
1644         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1645
1646         if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1647         {
1648                 SetLastError(ERROR_INVALID_PARAMETER);
1649                 return FALSE;
1650         }
1651
1652         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1653 }
1654
1655 /******************************************************************************
1656  * CryptGetUserKey (ADVAPI32.@)
1657  *
1658  * Gets a handle of one of a user's two public/private key pairs.
1659  *
1660  * PARAMS
1661  *  hProv     [I] Handle of a CSP.
1662  *  dwKeySpec [I] Private key to use.
1663  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1664  *
1665  * RETURNS
1666  *  Success: TRUE
1667  *  Failure: FALSE
1668  */
1669 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1670 {
1671         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1672         PCRYPTKEY key;
1673
1674         TRACE("(0x%lx, %d, %p)\n", hProv, dwKeySpec, phUserKey);
1675
1676         if (!prov)
1677         {
1678                 SetLastError(ERROR_INVALID_HANDLE);
1679                 return FALSE;
1680         }
1681         if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1682         {
1683                 SetLastError(ERROR_INVALID_PARAMETER);
1684                 return FALSE;
1685         }
1686         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1687         {
1688                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1689                 return FALSE;
1690         }
1691
1692         key->pProvider = prov;
1693
1694         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1695         {
1696             *phUserKey = (HCRYPTKEY)key;
1697             return TRUE;
1698         }
1699
1700         /* CSP Error */
1701         CRYPT_Free(key);
1702         *phUserKey = 0;
1703         return FALSE;
1704 }
1705
1706 /******************************************************************************
1707  * CryptHashData (ADVAPI32.@)
1708  *
1709  * Adds data to a hash object.
1710  *
1711  * PARAMS
1712  *  hHash     [I] Handle of the hash object.
1713  *  pbData    [I] Buffer of data to be hashed.
1714  *  dwDataLen [I] Number of bytes to add.
1715  *  dwFlags   [I] Can be CRYPT_USERDATA
1716  *
1717  * RETURNS
1718  *  Success: TRUE
1719  *  Failure: FALSE
1720  */
1721 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1722 {
1723         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1724         PCRYPTPROV prov;
1725
1726         TRACE("(0x%lx, %p, %d, %08x)\n", hHash, pbData, dwDataLen, dwFlags);
1727
1728         if (!hash)
1729         {
1730                 SetLastError(ERROR_INVALID_HANDLE);
1731                 return FALSE;
1732         }
1733         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1734         {
1735                 SetLastError(ERROR_INVALID_PARAMETER);
1736                 return FALSE;
1737         }
1738
1739         prov = hash->pProvider;
1740         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1741 }
1742
1743 /******************************************************************************
1744  * CryptHashSessionKey (ADVAPI32.@)
1745  *
1746  * Compute the cryptographic hash of a session key object.
1747  *
1748  * PARAMS 
1749  *  hHash   [I] Handle to the hash object.
1750  *  hKey    [I] Handle to the key to be hashed.
1751  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1752  *
1753  * RETURNS
1754  *  Success: TRUE
1755  *  Failure: FALSE
1756  */
1757 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1758 {
1759         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1760         PCRYPTKEY key = (PCRYPTKEY)hKey;
1761         PCRYPTPROV prov;
1762
1763         TRACE("(0x%lx, 0x%lx, %08x)\n", hHash, hKey, dwFlags);
1764
1765         if (!hash || !key)
1766         {
1767                 SetLastError(ERROR_INVALID_HANDLE);
1768                 return FALSE;
1769         }
1770
1771         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1772         {
1773                 SetLastError(ERROR_INVALID_PARAMETER);
1774                 return FALSE;
1775         }
1776
1777         prov = hash->pProvider;
1778         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1779 }
1780
1781 /******************************************************************************
1782  * CryptImportKey (ADVAPI32.@)
1783  *
1784  * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
1785  *
1786  * PARAMS
1787  *  hProv     [I] Handle of a CSP.
1788  *  pbData    [I] Contains the key to be imported.
1789  *  dwDataLen [I] Length of the key.
1790  *  hPubKey   [I] Cryptographic key that decrypts pdData
1791  *  dwFlags   [I] Used only with a public/private key pair.
1792  *  phKey     [O] Imported key.
1793  *
1794  * RETURNS
1795  *  Success: TRUE
1796  *  Failure: FALSE
1797  */
1798 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
1799                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1800 {
1801         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1802         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1803
1804         TRACE("(0x%lx, %p, %d, 0x%lx, %08x, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1805
1806         if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
1807         {
1808                 SetLastError(ERROR_INVALID_PARAMETER);
1809                 return FALSE;
1810         }
1811
1812         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1813         {
1814                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1815                 return FALSE;
1816         }
1817
1818         importkey->pProvider = prov;
1819         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1820                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1821         {
1822                 *phKey = (HCRYPTKEY)importkey;
1823                 return TRUE;
1824         }
1825
1826         CRYPT_Free(importkey);
1827         return FALSE;
1828 }
1829
1830 /******************************************************************************
1831  * CryptSignHashW (ADVAPI32.@)
1832  *
1833  * Signs data.
1834  *
1835  * PARAMS
1836  *  hHash        [I] Handle of the hash object to be signed.
1837  *  dwKeySpec    [I] Private key to use.
1838  *  sDescription [I] Should be NULL.
1839  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1840  *  pbSignature  [O] Buffer of the signature data.
1841  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1842  *
1843  * RETURNS
1844  *  Success: TRUE
1845  *  Failure: FALSE
1846  *
1847  * NOTES
1848  *  Because of security flaws sDescription should not be used and should thus be
1849  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1850  *  Providers.
1851  */
1852 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1853                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1854 {
1855         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1856         PCRYPTPROV prov;
1857
1858         TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1859                 hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1860
1861         if (!hash)
1862         {
1863                 SetLastError(ERROR_INVALID_HANDLE);
1864                 return FALSE;
1865         }
1866         if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1867         {
1868                 SetLastError(ERROR_INVALID_PARAMETER);
1869                 return FALSE;
1870         }
1871
1872         prov = hash->pProvider;
1873         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1874                 dwFlags, pbSignature, pdwSigLen);
1875 }
1876
1877 /******************************************************************************
1878  * CryptSignHashA (ADVAPI32.@)
1879  *
1880  * See CryptSignHashW.
1881  */
1882 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1883                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1884 {
1885         LPWSTR wsDescription;
1886         BOOL result;
1887
1888         TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1889                 hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1890
1891         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1892         result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1893         CRYPT_Free(wsDescription);
1894
1895         return result;
1896 }
1897
1898 /******************************************************************************
1899  * CryptSetHashParam (ADVAPI32.@)
1900  *
1901  * Customizes the operations of a hash object.
1902  *
1903  * PARAMS
1904  *  hHash   [I] Handle of the hash object to set parameters.
1905  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1906  *  pbData  [I] Value data buffer.
1907  *  dwFlags [I] Reserved for future use and must be zero.
1908  *
1909  * RETURNS
1910  *  Success: TRUE
1911  *  Failure: FALSE
1912  */
1913 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
1914 {
1915         PCRYPTPROV prov;
1916         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1917
1918         TRACE("(0x%lx, %d, %p, %08x)\n", hHash, dwParam, pbData, dwFlags);
1919
1920         if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1921         {
1922                 SetLastError(ERROR_INVALID_PARAMETER);
1923                 return FALSE;
1924         }
1925
1926         prov = hash->pProvider;
1927         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1928                         dwParam, pbData, dwFlags);
1929 }
1930
1931 /******************************************************************************
1932  * CryptSetKeyParam (ADVAPI32.@)
1933  *
1934  * Customizes a session key's operations.
1935  *
1936  * PARAMS
1937  *  hKey    [I] Handle to the key to set values.
1938  *  dwParam [I] See MSDN Doc.
1939  *  pbData  [I] Buffer of values to set.
1940  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1941  *
1942  * RETURNS
1943  *  Success: TRUE
1944  *  Failure: FALSE
1945  */
1946 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
1947 {
1948         PCRYPTPROV prov;
1949         PCRYPTKEY key = (PCRYPTKEY)hKey;
1950
1951         TRACE("(0x%lx, %d, %p, %08x)\n", hKey, dwParam, pbData, dwFlags);
1952
1953         if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1954         {
1955                 SetLastError(ERROR_INVALID_PARAMETER);
1956                 return FALSE;
1957         }
1958
1959         prov = key->pProvider;
1960         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1961                         dwParam, pbData, dwFlags);
1962 }
1963
1964 /******************************************************************************
1965  * CryptSetProviderA (ADVAPI32.@)
1966  *
1967  * Specifies the current user's default CSP.
1968  *
1969  * PARAMS
1970  *  pszProvName [I] Name of the new default CSP.
1971  *  dwProvType  [I] Provider type of the CSP.
1972  *
1973  * RETURNS
1974  *  Success: TRUE
1975  *  Failure: FALSE
1976  */
1977 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1978 {
1979         TRACE("(%s, %d)\n", pszProvName, dwProvType);
1980         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1981 }
1982
1983 /******************************************************************************
1984  * CryptSetProviderW (ADVAPI32.@)
1985  *
1986  * See CryptSetProviderA.
1987  */
1988 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1989 {
1990         TRACE("(%s, %d)\n", debugstr_w(pszProvName), dwProvType);
1991         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1992 }
1993
1994 /******************************************************************************
1995  * CryptSetProviderExW (ADVAPI32.@)
1996  *
1997  * Specifies the default CSP.
1998  *
1999  * PARAMS
2000  *  pszProvName [I] Name of the new default CSP.
2001  *  dwProvType  [I] Provider type of the CSP.
2002  *  pdwReserved [I] Reserved for future use and must be NULL.
2003  *  dwFlags     [I] See MSDN Doc.
2004  *
2005  * RETURNS
2006  *  Success: TRUE
2007  *  Failure: FALSE
2008  */
2009 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2010 {
2011         HKEY hProvKey, hTypeKey;
2012         PWSTR keyname;
2013         static const WCHAR nameW[] = {'N','a','m','e',0};
2014
2015         TRACE("(%s, %d, %p, %08x)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
2016
2017         if (!pszProvName || pdwReserved)
2018         {
2019                 SetLastError(ERROR_INVALID_PARAMETER);
2020                 return FALSE;
2021         }
2022         if (dwProvType > MAXPROVTYPES)
2023         {
2024                 SetLastError(NTE_BAD_PROV_TYPE);
2025                 return FALSE;
2026         }
2027         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
2028                         || dwFlags == CRYPT_DELETE_DEFAULT)
2029         {
2030                 SetLastError(NTE_BAD_FLAGS);
2031                 return FALSE;
2032         }
2033
2034         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
2035         {
2036                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2037                 return FALSE;
2038         }
2039         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2040                 keyname, &hTypeKey))
2041         {
2042                 CRYPT_Free(keyname);
2043                 SetLastError(NTE_BAD_PROVIDER);
2044                 return FALSE;
2045         }
2046         CRYPT_Free(keyname);
2047         
2048         if (dwFlags & CRYPT_DELETE_DEFAULT)
2049         {
2050                 RegDeleteValueW(hTypeKey, nameW);
2051         }
2052         else
2053         {
2054                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
2055                 {
2056                         RegCloseKey(hTypeKey);
2057                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2058                         return FALSE;
2059                 }
2060                 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2061                         keyname, &hProvKey))
2062                 {
2063                         CRYPT_Free(keyname);
2064                         RegCloseKey(hTypeKey);
2065                         SetLastError(NTE_BAD_PROVIDER);
2066                         return FALSE;
2067                 }
2068                 CRYPT_Free(keyname);
2069                 
2070                 if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (const BYTE *)pszProvName,
2071                         (strlenW(pszProvName) + 1)*sizeof(WCHAR)))
2072                 {
2073                         RegCloseKey(hTypeKey);
2074                         RegCloseKey(hProvKey);
2075                         return FALSE;
2076                 }
2077                 
2078                 RegCloseKey(hProvKey);
2079         }
2080         RegCloseKey(hTypeKey);
2081
2082         return TRUE;
2083 }
2084
2085 /******************************************************************************
2086  * CryptSetProviderExA (ADVAPI32.@)
2087  *
2088  * See CryptSetProviderExW.
2089  */
2090 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2091 {
2092         BOOL ret = FALSE;
2093         PWSTR str = NULL;
2094
2095         TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
2096
2097         if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
2098         {
2099                 ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
2100                 CRYPT_Free(str);
2101         }
2102         return ret;
2103 }
2104
2105 /******************************************************************************
2106  * CryptSetProvParam (ADVAPI32.@)
2107  *
2108  * Customizes the operations of a CSP.
2109  *
2110  * PARAMS
2111  *  hProv   [I] Handle of a CSP.
2112  *  dwParam [I] See MSDN Doc.
2113  *  pbData  [I] Buffer that contains a value to set as a parameter.
2114  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
2115  *
2116  * RETURNS
2117  *  Success: TRUE
2118  *  Failure: FALSE
2119  */
2120 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
2121 {
2122         PCRYPTPROV prov = (PCRYPTPROV)hProv;
2123
2124         TRACE("(0x%lx, %d, %p, %08x)\n", hProv, dwParam, pbData, dwFlags);
2125
2126         if (!prov)
2127         {
2128                 SetLastError(ERROR_INVALID_HANDLE);
2129                 return FALSE;
2130         }
2131         if (prov->dwMagic != MAGIC_CRYPTPROV)
2132         {
2133                 SetLastError(ERROR_INVALID_PARAMETER);
2134                 return FALSE;
2135         }
2136         if (dwFlags & PP_USE_HARDWARE_RNG)
2137         {
2138                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
2139                 FIXME("\tLetting the CSP decide.\n");
2140         }
2141         if (dwFlags & PP_CLIENT_HWND)
2142         {
2143                 /* FIXME: Should verify the parameter */
2144                 if (pbData /* && IsWindow((HWND)pbData) */)
2145                 {
2146                         crypt_hWindow = (HWND)(pbData);
2147                         return TRUE;
2148                 } else {
2149                         SetLastError(ERROR_INVALID_PARAMETER);
2150                         return FALSE;
2151                 }
2152         }
2153         /* All other flags go to the CSP */
2154         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
2155 }
2156
2157 /******************************************************************************
2158  * CryptVerifySignatureW (ADVAPI32.@)
2159  *
2160  * Verifies the signature of a hash object.
2161  *
2162  * PARAMS
2163  *  hHash        [I] Handle of the hash object to verify.
2164  *  pbSignature  [I] Signature data to verify.
2165  *  dwSigLen     [I] Size of pbSignature.
2166  *  hPubKey      [I] Handle to the public key to authenticate signature.
2167  *  sDescription [I] Should be NULL.
2168  *  dwFlags      [I] See MSDN doc.
2169  *
2170  * RETURNS
2171  *  Success: TRUE
2172  *  Failure: FALSE
2173  * 
2174  * NOTES
2175  *  Because of security flaws sDescription should not be used and should thus be
2176  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
2177  *  Providers.
2178  */
2179 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
2180                 HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
2181 {
2182         PCRYPTHASH hash = (PCRYPTHASH)hHash;
2183         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
2184         PCRYPTPROV prov;
2185
2186         TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2187                         dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
2188
2189         if (!hash || !key ||
2190             !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
2191             !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2192         {
2193                 SetLastError(ERROR_INVALID_PARAMETER);
2194                 return FALSE;
2195         }
2196                 
2197         prov = hash->pProvider;
2198         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
2199                 key->hPrivate, sDescription, dwFlags);
2200 }
2201
2202 /******************************************************************************
2203  * CryptVerifySignatureA (ADVAPI32.@)
2204  *
2205  * See CryptVerifySignatureW.
2206  */
2207 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
2208                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
2209 {
2210         LPWSTR wsDescription;
2211         BOOL result;
2212
2213         TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2214                         dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
2215
2216         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
2217         result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
2218         CRYPT_Free(wsDescription);
2219
2220         return result;
2221 }
2222
2223 /******************************************************************************
2224  * SystemFunction030   (ADVAPI32.@)
2225  *
2226  * Tests if two blocks of 16 bytes are equal
2227  *
2228  * PARAMS
2229  *  b1,b2   [I] block of 16 bytes
2230  *
2231  * RETURNS
2232  *  TRUE  if blocks are the same
2233  *  FALSE if blocks are different
2234  */
2235 BOOL WINAPI SystemFunction030(PVOID b1, PVOID b2)
2236 {
2237     return !memcmp(b1, b2, 0x10);
2238 }
2239
2240 /******************************************************************************
2241  * SystemFunction035   (ADVAPI32.@)
2242  *
2243  * Described here:
2244 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
2245  *
2246  * NOTES
2247  *  Stub, always return TRUE.
2248  */
2249 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
2250 {
2251     FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
2252     return TRUE;
2253 }
2254
2255 /******************************************************************************
2256  * SystemFunction036   (ADVAPI32.@)
2257  *
2258  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
2259  *
2260  * PARAMS
2261  *  pbBufer [O] Pointer to memory to receive random bytes.
2262  *  dwLen   [I] Number of random bytes to fetch.
2263  *
2264  * RETURNS
2265  *  Success: TRUE
2266  *  Failure: FALSE
2267  */
2268
2269 BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
2270 {
2271     int dev_random;
2272
2273     /* FIXME: /dev/urandom does not provide random numbers of a sufficient
2274      * quality for cryptographic applications. /dev/random is much better,  
2275      * but it blocks if the kernel has not yet collected enough entropy for
2276      * the request, which will suspend the calling thread for an indefinite
2277      * amount of time. */
2278     dev_random = open("/dev/urandom", O_RDONLY);
2279     if (dev_random != -1)
2280     {
2281         if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
2282         {
2283             close(dev_random);
2284             return TRUE;
2285         }
2286         close(dev_random);
2287     }
2288     SetLastError(NTE_FAIL);
2289     return FALSE;
2290 }    
2291     
2292 /*
2293    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
2294    in crypt32.dll.
2295  */
2296
2297 /******************************************************************************
2298  * SystemFunction040   (ADVAPI32.@)
2299  *
2300  * MSDN documents this function as RtlEncryptMemory.
2301  *
2302  * PARAMS
2303  *  memory [I/O] Pointer to memory to encrypt.
2304  *  length [I] Length of region to encrypt in bytes.
2305  *  flags  [I] Control whether other processes are able to decrypt the memory.
2306  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
2307  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
2308  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2309  *    
2310  * RETURNS
2311  *  Success: STATUS_SUCCESS
2312  *  Failure: NTSTATUS error code
2313  *
2314  * NOTES
2315  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2316  *  If flags are specified when encrypting, the same flag value must be given
2317  *  when decrypting the memory.
2318  */
2319 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2320 {
2321         FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
2322         return STATUS_SUCCESS;
2323 }
2324
2325 /******************************************************************************
2326  * SystemFunction041  (ADVAPI32.@)
2327  *
2328  * MSDN documents this function as RtlDecryptMemory.
2329  *
2330  * PARAMS
2331  *  memory [I/O] Pointer to memory to decrypt.
2332  *  length [I] Length of region to decrypt in bytes.
2333  *  flags  [I] Control whether other processes are able to decrypt the memory.
2334  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
2335  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
2336  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2337  *
2338  * RETURNS
2339  *  Success: STATUS_SUCCESS
2340  *  Failure: NTSTATUS error code
2341  *
2342  * NOTES
2343  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2344  *  If flags are specified when encrypting, the same flag value must be given
2345  *  when decrypting the memory.
2346  */
2347 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2348 {
2349         FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
2350         return STATUS_SUCCESS;
2351 }