Improve c2man Documented-Total count.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "crypt.h"
43 #include "winnls.h"
44 #include "winreg.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
47 #include "winternl.h"
48 #include "ntstatus.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
51
52 HWND crypt_hWindow = 0;
53
54 #define CRYPT_ReturnLastError(err) do {SetLastError(err); return FALSE;} while(0)
55
56 #define CRYPT_Alloc(size) ((LPVOID)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 unsuccessfull, 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         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(PWSTR 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 /******************************************************************************
271  * CryptAcquireContextW (ADVAPI32.@)
272  *
273  * Acquire a crypto provider context handle.
274  *
275  * PARAMS
276  *  phProv       [O] Pointer to HCRYPTPROV for the output.
277  *  pszContainer [I] Key Container Name
278  *  pszProvider  [I] Cryptographic Service Provider Name
279  *  dwProvType   [I] Crypto provider type to get a handle.
280  *  dwFlags      [I] flags for the operation
281  *
282  * RETURNS 
283  *  TRUE on success, FALSE on failure.
284  */
285 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
286                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
287 {
288         PCRYPTPROV pProv = NULL;
289         HKEY key;
290         PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
291         PSTR provnameA = NULL, pszContainerA = NULL;
292         DWORD keytype, type, len;
293         ULONG r;
294         static const WCHAR nameW[] = {'N','a','m','e',0};
295         static const WCHAR typeW[] = {'T','y','p','e',0};
296         static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
297
298         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
299                 debugstr_w(pszProvider), dwProvType, dwFlags);
300
301         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
302         {
303                 SetLastError(NTE_BAD_PROV_TYPE);
304                 return FALSE;
305         }
306         
307         if (!phProv)
308         {
309                 SetLastError(ERROR_INVALID_PARAMETER);
310                 return FALSE;
311         }
312
313         if (!pszProvider || !*pszProvider)
314         {
315                 /* No CSP name specified so try the user default CSP first
316                  * then try the machine default CSP
317                  */
318                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
319                         TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
320                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
321                         return FALSE;
322                 }
323                 if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
324                 {
325                         CRYPT_Free(keyname);
326                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
327                                 TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
328                                 RegCloseKey(key);
329                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
330                                 goto error;
331                         }
332                         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
333                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
334                                 CRYPT_Free(keyname);
335                                 RegCloseKey(key);
336                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
337                                 goto error;
338                         }
339                 }
340                 CRYPT_Free(keyname);
341                 r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
342                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
343                 {
344                         TRACE("error %ld reading size of 'Name' from registry\n", r );
345                         RegCloseKey(key);
346                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
347                         goto error;
348                 }
349                 if(!(provname = CRYPT_Alloc(len)))
350                 {
351                         RegCloseKey(key);
352                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
353                         goto error;
354                 }
355                 r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
356                 if( r != ERROR_SUCCESS )
357                 {
358                         TRACE("error %ld reading 'Name' from registry\n", r );
359                         RegCloseKey(key);
360                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
361                         goto error;
362                 }
363                 RegCloseKey(key);
364         } else {
365                 if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
366                 {
367                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
368                         goto error;
369                 }
370                 strcpyW(provname, pszProvider);
371         }
372
373         keyname = CRYPT_GetProvKeyName(provname);
374         r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
375         CRYPT_Free(keyname);
376         if (r != ERROR_SUCCESS)
377         {
378                 SetLastError(NTE_KEYSET_NOT_DEF);
379                 goto error;
380         }
381         len = sizeof(DWORD);
382         r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
383         if (r != ERROR_SUCCESS)
384         {
385                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
386                 goto error;
387         }
388         if (type != dwProvType)
389         {
390                 TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
391                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
392                 goto error;
393         }
394
395         r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
396         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
397         {
398                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
399                 RegCloseKey(key);
400                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
401                 goto error;
402         }
403         if (!(temp = CRYPT_Alloc(len)))
404         {
405                 RegCloseKey(key);
406                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
407                 goto error;
408         }
409         r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
410         if( r != ERROR_SUCCESS )
411         {
412                 TRACE("error %ld reading 'Image Path' from registry\n", r );
413                 RegCloseKey(key);
414                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
415                 goto error;
416         }
417         RegCloseKey(key);
418         len = ExpandEnvironmentStringsW(temp, NULL, 0);
419         if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
420         {
421                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
422                 goto error;
423         }
424         if (!ExpandEnvironmentStringsW(temp, imagepath, len))
425         {
426                 /* ExpandEnvironmentStrings will call SetLastError */
427                 goto error;
428         }
429         pProv = CRYPT_LoadProvider(imagepath);
430         if (!pProv) {
431                 /* CRYPT_LoadProvider calls SetLastError */
432                 goto error;
433         }
434         pProv->pVTable->dwProvType = dwProvType;
435         if(!CRYPT_UnicodeToANSI(provname, &provnameA, -1))
436         {
437                 /* CRYPT_UnicodeToANSI calls SetLastError */
438                 goto error;
439         }
440         pProv->pVTable->pszProvName = provnameA;
441         if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, -1))
442         {
443                 /* CRYPT_UnicodeToANSI calls SetLastError */
444                 goto error;
445         }
446         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
447         {
448                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
449                  *       and thus, the CryptReleaseContext function need not be called afterwards.
450                  *       Therefore, we must clean up everything now.
451                  */
452                 if (dwFlags & CRYPT_DELETEKEYSET)
453                 {
454                         pProv->dwMagic = 0;
455                         FreeLibrary(pProv->hModule);
456                         CRYPT_Free(provnameA);
457                         CRYPT_Free(pProv->pVTable);
458                         CRYPT_Free(pProv->pFuncs);
459                         CRYPT_Free(pProv);
460                 } else {
461                         *phProv = (HCRYPTPROV)pProv;
462                 }
463                 CRYPT_Free(pszContainerA);
464                 CRYPT_Free(provname);
465                 CRYPT_Free(temp);
466                 CRYPT_Free(imagepath);
467                 return TRUE;
468         }
469         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
470 error:
471         if (pProv)
472         {
473                 pProv->dwMagic = 0;
474                 if (pProv->hModule)
475                         FreeLibrary(pProv->hModule);
476                 if (pProv->pVTable)
477                         CRYPT_Free(pProv->pVTable);
478                 if (pProv->pFuncs)
479                         CRYPT_Free(pProv->pFuncs);
480                 CRYPT_Free(pProv);
481         }
482         if (pszContainerA)
483                 CRYPT_Free(pszContainerA);
484         if (provnameA)
485                 CRYPT_Free(provnameA);
486         if (provname)
487                 CRYPT_Free(provname);
488         if (temp)
489                 CRYPT_Free(temp);
490         if (imagepath)
491                 CRYPT_Free(imagepath);
492         return FALSE;
493 }
494
495 /******************************************************************************
496  * CryptAcquireContextA (ADVAPI32.@)
497  *
498  * See CryptAcquireContextW.
499  */
500 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
501                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
502 {
503         PWSTR pProvider = NULL, pContainer = NULL;
504         BOOL ret = FALSE;
505
506         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
507                 pszProvider, dwProvType, dwFlags);
508
509         if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
510                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
511         if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
512         {
513                 CRYPT_Free(pContainer);
514                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
515         }
516
517         ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
518
519         if (pContainer)
520                 CRYPT_Free(pContainer);
521         if (pProvider)
522                 CRYPT_Free(pProvider);
523
524         return ret;
525 }
526
527 /******************************************************************************
528  * CryptContextAddRef (ADVAPI32.@)
529  *
530  * Increases reference count of a cryptographic service provider handle
531  * by one.
532  *
533  * PARAMS
534  *  hProv       [I] Handle to the CSP whose reference is being incremented.
535  *  pdwReserved [IN] Reserved for future use and must be NULL.
536  *  dwFlags     [I] Reserved for future use and must be NULL.
537  *
538  * RETURNS
539  *  Success: TRUE
540  *  Failure: FALSE
541  */
542 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
543 {
544         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
545
546         TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
547
548         if (!pProv)
549         {
550                 SetLastError(NTE_BAD_UID);
551                 return FALSE;
552         }
553
554         if (pProv->dwMagic != MAGIC_CRYPTPROV)
555         {
556                 SetLastError(ERROR_INVALID_PARAMETER);
557                 return FALSE;
558         }
559
560         pProv->refcount++;
561         return TRUE;
562 }
563
564 /******************************************************************************
565  * CryptReleaseContext (ADVAPI32.@)
566  *
567  * Releases the handle of a CSP.  Reference count is decreased.
568  *
569  * PARAMS
570  *  hProv   [I] Handle of a CSP.
571  *  dwFlags [I] Reserved for future use and must be NULL.
572  *
573  * RETURNS
574  *  Success: TRUE
575  *  Failure: FALSE
576  */
577 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
578 {
579         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
580         BOOL ret = TRUE;
581
582         TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
583
584         if (!pProv)
585         {
586                 SetLastError(NTE_BAD_UID);
587                 return FALSE;
588         }
589
590         if (pProv->dwMagic != MAGIC_CRYPTPROV)
591         {
592                 SetLastError(ERROR_INVALID_PARAMETER);
593                 return FALSE;
594         }
595
596         pProv->refcount--;
597         if (pProv->refcount <= 0) 
598         {
599                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
600                 pProv->dwMagic = 0;
601                 FreeLibrary(pProv->hModule);
602 #if 0
603                 CRYPT_Free(pProv->pVTable->pContextInfo);
604 #endif
605                 CRYPT_Free(pProv->pVTable->pszProvName);
606                 CRYPT_Free(pProv->pVTable);
607                 CRYPT_Free(pProv->pFuncs);
608                 CRYPT_Free(pProv);
609         }
610         return ret;
611 }
612
613 /******************************************************************************
614  * CryptGenRandom (ADVAPI32.@)
615  *
616  * Fills a buffer with cryptographically random bytes.
617  *
618  * PARAMS
619  *  hProv    [I] Handle of a CSP.
620  *  dwLen    [I] Number of bytes to generate.
621  *  pbBuffer [I/O] Buffer to contain random bytes.
622  *
623  * RETURNS
624  *  Success: TRUE
625  *  Failure: FALSE
626  *
627  * NOTES
628  *  pdBuffer must be at least dwLen bytes long.
629  */
630 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
631 {
632         PCRYPTPROV prov = (PCRYPTPROV)hProv;
633
634         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
635
636         if (!hProv)
637                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
638
639         if (prov->dwMagic != MAGIC_CRYPTPROV)
640                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
641
642         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
643 }
644
645 /******************************************************************************
646  * CryptCreateHash (ADVAPI32.@)
647  *
648  * Initiates the hashing of a stream of data.
649  *
650  * PARAMS
651  *  hProv   [I] Handle of a CSP.
652  *  Algid   [I] Identifies the hash algorithm to use.
653  *  hKey    [I] Key for the hash (if required).
654  *  dwFlags [I] Reserved for future use and must be NULL.
655  *  phHash  [O] Address of the future handle to the new hash object.
656  *
657  * RETURNS
658  *  Success: TRUE
659  *  Failure: FALSE
660  *
661  * NOTES
662  *  If the algorithm is a keyed hash, hKey is the key.
663  */
664 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
665                 DWORD dwFlags, HCRYPTHASH *phHash)
666 {
667         PCRYPTPROV prov = (PCRYPTPROV)hProv;
668         PCRYPTKEY key = (PCRYPTKEY)hKey;
669         PCRYPTHASH hash;
670
671         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
672
673         if (!prov)
674                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
675         if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
676                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
677         if (dwFlags)
678                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
679         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
680                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
681
682         hash->pProvider = prov;
683
684         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
685                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
686         {
687             *phHash = (HCRYPTHASH)hash;
688             return TRUE;
689         }
690
691         /* CSP error! */
692         CRYPT_Free(hash);
693         *phHash = 0;
694         return FALSE;
695 }
696
697 /******************************************************************************
698  * CryptDecrypt (ADVAPI32.@)
699  *
700  * Decrypts data encrypted by CryptEncrypt.
701  *
702  * PARAMS
703  *  hKey       [I] Handle to the decryption key.
704  *  hHash      [I] Handle to a hash object.
705  *  Final      [I] TRUE if this is the last section to be decrypted.
706  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
707  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
708  *                   data on return
709  *  pdwDataLen [I/O] Length of pbData before and after the call.
710  *
711  *  RETURNS
712  *   Success: TRUE
713  *   Failure: FALSE
714  */
715 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
716                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
717 {
718         PCRYPTPROV prov;
719         PCRYPTKEY key = (PCRYPTKEY)hKey;
720         PCRYPTHASH hash = (PCRYPTHASH)hHash;
721
722         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
723
724         if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
725                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
726
727         prov = key->pProvider;
728         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
729                         Final, dwFlags, pbData, pdwDataLen);
730 }
731
732 /******************************************************************************
733  * CryptDeriveKey (ADVAPI32.@)
734  *
735  * Generates session keys derived from a base data value.
736  *
737  * PARAMS
738  *  hProv     [I] Handle to a CSP.
739  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
740  *  hBaseData [I] Handle to a hash object.
741  *  dwFlags   [I] Type of key to generate.
742  *  phKey     [I/O] Address of the newly generated key.
743  *
744  * RETURNS
745  *  Success: TRUE
746  *  Failure: FALSE
747  */
748 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
749                 DWORD dwFlags, HCRYPTKEY *phKey)
750 {
751         PCRYPTPROV prov = (PCRYPTPROV)hProv;
752         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
753         PCRYPTKEY key;
754
755         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
756
757         if (!prov || !hash)
758                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
759         if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
760                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
761         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
762                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
763
764         key->pProvider = prov;
765         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
766         {
767             *phKey = (HCRYPTKEY)key;
768             return TRUE;
769         }
770
771         /* CSP error! */
772         CRYPT_Free(key);
773         *phKey = 0;
774         return FALSE;
775 }
776
777 /******************************************************************************
778  * CryptDestroyHash (ADVAPI32.@)
779  *
780  * Destroys the hash object referenced by hHash.
781  *
782  * PARAMS
783  *  hHash [I] Handle of the hash object to be destroyed.
784  *
785  * RETURNS
786  *  Success: TRUE
787  *  Failure: FALSE
788  */
789 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
790 {
791         PCRYPTHASH hash = (PCRYPTHASH)hHash;
792         PCRYPTPROV prov;
793         BOOL ret;
794
795         TRACE("(0x%lx)\n", hHash);
796
797         if (!hash)
798                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
799
800         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
801                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
802         
803         prov = hash->pProvider;
804         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
805         CRYPT_Free(hash);
806         return ret;
807 }
808
809 /******************************************************************************
810  * CryptDestroyKey (ADVAPI32.@)
811  *
812  * Releases the handle referenced by hKey.
813  *
814  * PARAMS
815  *  hKey [I] Handle of the key to be destroyed.
816  *
817  * RETURNS
818  *  Success: TRUE
819  *  Failure: FALSE
820  */
821 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
822 {
823         PCRYPTKEY key = (PCRYPTKEY)hKey;
824         PCRYPTPROV prov;
825         BOOL ret;
826
827         TRACE("(0x%lx)\n", hKey);
828
829         if (!key)
830                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
831
832         if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
833                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
834
835         prov = key->pProvider;
836         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
837         CRYPT_Free(key);
838         return ret;
839 }
840
841 /******************************************************************************
842  * CryptDuplicateHash (ADVAPI32.@)
843  *
844  * Duplicates a hash.
845  *
846  * PARAMS
847  *  hHash       [I] Handle to the hash to be copied.
848  *  pdwReserved [I] Reserved for future use and must be zero.
849  *  dwFlags     [I] Reserved for future use and must be zero.
850  *  phHash      [O] Address of the handle to receive the copy.
851  *
852  * RETURNS
853  *  Success: TRUE
854  *  Failure: FALSE
855  */
856 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
857                 DWORD dwFlags, HCRYPTHASH *phHash)
858 {
859         PCRYPTPROV prov;
860         PCRYPTHASH orghash, newhash;
861
862         TRACE("(0x%lx, %p, %08lx, %p)\n", hHash, pdwReserved, dwFlags, phHash);
863
864         orghash = (PCRYPTHASH)hHash;
865         if (!orghash || pdwReserved || !phHash || !orghash->pProvider || 
866                 orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
867         {
868                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
869         }
870
871         prov = orghash->pProvider;
872         if (!prov->pFuncs->pCPDuplicateHash)
873                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
874
875         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
876                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
877
878         newhash->pProvider = prov;
879         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
880         {
881                 *phHash = (HCRYPTHASH)newhash;
882                 return TRUE;
883         }
884         CRYPT_Free(newhash);
885         return FALSE;
886 }
887
888 /******************************************************************************
889  * CryptDuplicateKey (ADVAPI32.@)
890  *
891  * Duplicate a key and the key's state.
892  *
893  * PARAMS
894  *  hKey        [I] Handle of the key to copy.
895  *  pdwReserved [I] Reserved for future use and must be NULL.
896  *  dwFlags     [I] Reserved for future use and must be zero.
897  *  phKey       [I] Address of the handle to the duplicated key.
898  *
899  * RETURNS
900  *  Success: TRUE
901  *  Failure: FALSE
902  */
903 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
904 {
905         PCRYPTPROV prov;
906         PCRYPTKEY orgkey, newkey;
907
908         TRACE("(0x%lx, %p, %08lx, %p)\n", hKey, pdwReserved, dwFlags, phKey);
909
910         orgkey = (PCRYPTKEY)hKey;
911         if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider || 
912                 orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
913         {
914                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
915         }
916
917         prov = orgkey->pProvider;
918         if (!prov->pFuncs->pCPDuplicateKey)
919                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
920
921         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
922                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
923
924         newkey->pProvider = prov;
925         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
926         {
927                 *phKey = (HCRYPTKEY)newkey;
928                 return TRUE;
929         }
930         CRYPT_Free(newkey);
931         return FALSE;
932 }
933
934 /******************************************************************************
935  * CryptEncrypt (ADVAPI32.@)
936  *
937  * Encrypts data.
938  *
939  * PARAMS
940  *  hKey       [I] Handle to the enryption key.
941  *  hHash      [I] Handle to a hash object.
942  *  Final      [I] TRUE if this is the last section to encrypt.
943  *  dwFlags    [I] Can be CRYPT_OAEP.
944  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
945  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
946  *                   encrypted data after call.
947  *  dwBufLen   [I] Length of the input pbData buffer.
948  *
949  * RETURNS
950  *  Success: TRUE
951  *  Failure: FALSE
952  *
953  *  NOTES
954  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
955  *   required for the returned data in pdwDataLen.
956  */
957 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
958                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
959 {
960         PCRYPTPROV prov;
961         PCRYPTKEY key = (PCRYPTKEY)hKey;
962         PCRYPTHASH hash = (PCRYPTHASH)hHash;
963
964         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
965
966         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
967                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
968
969         prov = key->pProvider;
970         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
971                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
972 }
973
974 /******************************************************************************
975  * CryptEnumProvidersW (ADVAPI32.@)
976  *
977  * Returns the next availabe CSP.
978  *
979  * PARAMS
980  *  dwIndex     [I] Index of the next provider to be enumerated.
981  *  pdwReserved [I] Reserved for future use and must be NULL.
982  *  dwFlags     [I] Reserved for future use and must be zero.
983  *  pdwProvType [O] DWORD designating the type of the provider.
984  *  pszProvName [O] Buffer that receives data from the provider.
985  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
986  *                    of bytes stored in the buffer on return.
987  *
988  *  RETURNS
989  *   Success: TRUE
990  *   Failure: FALSE
991  *
992  *  NOTES
993  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
994  *   for memory allocation purposes.
995  */
996 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
997                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
998 {
999         HKEY hKey;
1000         static const WCHAR providerW[] = {
1001                 'S','o','f','t','w','a','r','e','\\',
1002                 'M','i','c','r','o','s','o','f','t','\\',
1003                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1004                 'D','e','f','a','u','l','t','s','\\',
1005                 'P','r','o','v','i','d','e','r',0
1006         };
1007         static const WCHAR typeW[] = {'T','y','p','e',0};
1008
1009         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1010                         pdwProvType, pszProvName, pcbProvName);
1011
1012         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1013         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1014
1015         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
1016                 CRYPT_ReturnLastError(NTE_FAIL);
1017
1018         if (!pszProvName)
1019         {
1020                 DWORD numkeys;
1021                 WCHAR *provNameW;
1022                 
1023                 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
1024                                  NULL, NULL, NULL, NULL, NULL, NULL);
1025                 
1026                 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1027                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1028                 
1029                 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1030                 CRYPT_Free(provNameW);
1031                 (*pcbProvName)++;
1032                 *pcbProvName *= sizeof(WCHAR);
1033
1034                 if (dwIndex >= numkeys)
1035                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1036         } else {
1037                 DWORD size = sizeof(DWORD);
1038                 DWORD result;
1039                 HKEY subkey;
1040                 
1041                 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1042                 if (result)
1043                         CRYPT_ReturnLastError(result);
1044                 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1045                         return FALSE;
1046                 if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1047                         return FALSE;
1048                 RegCloseKey(subkey);
1049         }
1050         RegCloseKey(hKey);
1051         return TRUE;
1052 }
1053
1054 /******************************************************************************
1055  * CryptEnumProvidersA (ADVAPI32.@)
1056  *
1057  * See CryptEnumProvidersW.
1058  */
1059 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1060                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1061 {
1062         PWSTR str = NULL;
1063         DWORD strlen;
1064         BOOL ret; /* = FALSE; */
1065
1066         TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1067                         pdwProvType, pszProvName, pcbProvName);
1068
1069         CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen);
1070         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1071                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1072         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1073         if (str)
1074                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1075         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1076         if (str)
1077         {
1078                 CRYPT_Free(str);
1079                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1080                         CRYPT_ReturnLastError(ERROR_MORE_DATA);
1081         }
1082         return ret;
1083 }
1084
1085 /******************************************************************************
1086  * CryptEnumProviderTypesW (ADVAPI32.@)
1087  *
1088  * Retrieves the next type of CSP supported.
1089  *
1090  * PARAMS
1091  *  dwIndex     [I] Index of the next provider to be enumerated.
1092  *  pdwReserved [I] Reserved for future use and must be NULL.
1093  *  dwFlags     [I] Reserved for future use and must be zero.
1094  *  pdwProvType [O] DWORD designating the type of the provider.
1095  *  pszTypeName [O] Buffer that receives data from the provider type.
1096  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1097  *                    of bytes stored in the buffer on return.
1098  *
1099  *  RETURNS
1100  *   Success: TRUE
1101  *   Failure: FALSE
1102  *
1103  *  NOTES
1104  *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1105  *   for memory allocation purposes.
1106  */
1107 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1108                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1109 {
1110         HKEY hKey, hSubkey;
1111         DWORD keylen, numkeys, dwType;
1112         PWSTR keyname, ch;
1113         DWORD result;
1114         static const WCHAR KEYSTR[] = {
1115                 'S','o','f','t','w','a','r','e','\\',
1116                 'M','i','c','r','o','s','o','f','t','\\',
1117                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1118                 'D','e','f','a','u','l','t','s','\\',
1119                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
1120         };
1121         static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
1122
1123         TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved,
1124                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1125
1126         if (pdwReserved || !pdwProvType || !pcbTypeName)
1127                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1128         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1129
1130         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
1131                 return FALSE;
1132
1133         RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1134         if (dwIndex >= numkeys)
1135                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1136         keylen++;
1137         if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1138                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1139         if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1140                 CRYPT_Free(keyname);
1141                 return FALSE;
1142         }
1143         RegOpenKeyW(hKey, keyname, &hSubkey);
1144         ch = keyname + strlenW(keyname);
1145         /* Convert "Type 000" to 0, etc/ */
1146         *pdwProvType = *(--ch) - '0';
1147         *pdwProvType += (*(--ch) - '0') * 10;
1148         *pdwProvType += (*(--ch) - '0') * 100;
1149         CRYPT_Free(keyname);
1150         
1151         result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1152         if (result)
1153                 CRYPT_ReturnLastError(result);
1154
1155         RegCloseKey(hSubkey);
1156         RegCloseKey(hKey);
1157         return TRUE;
1158 }
1159
1160 /******************************************************************************
1161  * CryptEnumProviderTypesA (ADVAPI32.@)
1162  *
1163  * See CryptEnumProviderTypesW.
1164  */
1165 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1166                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1167 {
1168         PWSTR str = NULL;
1169         DWORD strlen;
1170         BOOL ret;
1171
1172         TRACE("(%ld, %p, %08lx, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1173                         pdwProvType, pszTypeName, pcbTypeName);
1174
1175         CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen);
1176         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1177                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1178         ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1179         if (str)
1180                 CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1181         *pcbTypeName = strlen / sizeof(WCHAR);
1182         if (str)
1183         {
1184                 CRYPT_Free(str);
1185                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1186                         CRYPT_ReturnLastError(ERROR_MORE_DATA);
1187         }
1188         return ret;
1189 }
1190
1191 /******************************************************************************
1192  * CryptExportKey (ADVAPI32.@)
1193  * 
1194  * Exports a cryptographic key from a CSP.
1195  *
1196  * PARAMS
1197  *  hKey       [I] Handle to the key to export.
1198  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1199  *  dwBlobType [I] Type of BLOB to be exported.
1200  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1201  *  pbData     [O] Buffer to receive BLOB data.
1202  *  pdwDataLen [I/O] Specifies the size of pbData.
1203  *
1204  * RETURNS
1205  *  Success: TRUE
1206  *  Failure: FALSE
1207  *
1208  * NOTES
1209  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1210  *  buffer needed to hold the BLOB.
1211  */
1212 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1213                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1214 {
1215         PCRYPTPROV prov;
1216         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1217
1218         TRACE("(0x%lx, 0x%lx, %ld, %08lx, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1219
1220         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1221                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1222
1223         prov = key->pProvider;
1224         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1225                         dwBlobType, dwFlags, pbData, pdwDataLen);
1226 }
1227
1228 /******************************************************************************
1229  * CryptGenKey (ADVAPI32.@)
1230  *
1231  * Generates a random cryptographic session key or a pub/priv key pair.
1232  *
1233  * PARAMS
1234  *  hProv   [I] Handle to a CSP.
1235  *  Algid   [I] Algorithm to use to make key.
1236  *  dwFlags [I] Specifies type of key to make.
1237  *  phKey   [I] Address of the handle to which the new key is copied.
1238  *
1239  *  RETURNS
1240  *   Success: TRUE
1241  *   Failure: FALSE
1242  */
1243 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1244 {
1245         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1246         PCRYPTKEY key;
1247
1248         TRACE("(0x%lx, %d, %08lx, %p)\n", hProv, Algid, dwFlags, phKey);
1249
1250         if (!prov)
1251                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1252         if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1253                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1254         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1255                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1256
1257         key->pProvider = prov;
1258
1259         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1260         {
1261             *phKey = (HCRYPTKEY)key;
1262             return TRUE;
1263         }
1264
1265         /* CSP error! */
1266         CRYPT_Free(key);
1267         return FALSE;
1268 }
1269
1270 /******************************************************************************
1271  * CryptGetDefaultProviderW (ADVAPI32.@)
1272  *
1273  * Finds the default CSP of a certain provider type.
1274  *
1275  * PARAMS
1276  *  dwProvType  [I] Provider type to look for.
1277  *  pdwReserved [I] Reserved for future use and must be NULL.
1278  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1279  *  pszProvName [O] Name of the default CSP.
1280  *  pcbProvName [I/O] Size of pszProvName
1281  *
1282  * RETURNS
1283  *  Success: TRUE
1284  *  Failure: FALSE
1285  *
1286  * NOTES
1287  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1288  *  memory allocation purposes on return.
1289  */
1290 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1291                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1292 {
1293         HKEY hKey;
1294         PWSTR keyname;
1295         DWORD result;
1296         static const WCHAR nameW[] = {'N','a','m','e',0};
1297
1298         if (pdwReserved || !pcbProvName)
1299                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1300         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1301                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1302         if (dwProvType > 999)
1303                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1304         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1305                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1306         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1307         {
1308                 CRYPT_Free(keyname);
1309                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
1310         }
1311         CRYPT_Free(keyname);
1312         
1313         result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName); 
1314         if (result)
1315         {
1316                 if (result != ERROR_MORE_DATA)
1317                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1318                 else
1319                         SetLastError(result);
1320                 
1321                 return FALSE;
1322         }
1323         
1324         RegCloseKey(hKey);
1325         return TRUE;
1326 }
1327
1328 /******************************************************************************
1329  * CryptGetDefaultProviderA (ADVAPI32.@)
1330  *
1331  * See CryptGetDefaultProviderW.
1332  */
1333 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1334                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1335 {
1336         PWSTR str = NULL;
1337         DWORD strlen;
1338         BOOL ret = FALSE;
1339
1340         TRACE("(%ld, %p, %08lx, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1341
1342         CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &strlen);
1343         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1344                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1345         ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &strlen);
1346         if (str)
1347                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1348         *pcbProvName = strlen / sizeof(WCHAR);
1349         if (str)
1350         {
1351                 CRYPT_Free(str);
1352                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1353                         CRYPT_ReturnLastError(ERROR_MORE_DATA);
1354         }
1355         return ret;
1356 }
1357
1358 /******************************************************************************
1359  * CryptGetHashParam (ADVAPI32.@)
1360  *
1361  * Retrieves data that controls the operations of a hash object.
1362  *
1363  * PARAMS
1364  *  hHash      [I] Handle of the hash object to question.
1365  *  dwParam    [I] Query type.
1366  *  pbData     [O] Buffer that receives the value data.
1367  *  pdwDataLen [I/O] Size of the pbData buffer.
1368  *  dwFlags    [I] Reserved for future use and must be zero.
1369  *
1370  * RETURNS
1371  *  Success: TRUE
1372  *  Failure: FALSE
1373  *
1374  * NOTES
1375  *  If pbData is NULL, pdwDataLen will contain the length required.
1376  */
1377 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1378                 DWORD *pdwDataLen, DWORD dwFlags)
1379 {
1380         PCRYPTPROV prov;
1381         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1382
1383         TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1384
1385         if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1386                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1387
1388         prov = hash->pProvider;
1389         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1390                         pbData, pdwDataLen, dwFlags);
1391 }
1392
1393 /******************************************************************************
1394  * CryptGetKeyParam (ADVAPI32.@)
1395  *
1396  * Retrieves data that controls the operations of a key.
1397  *
1398  * PARAMS
1399  *  hKey       [I] Handle to they key in question.
1400  *  dwParam    [I] Specifies query type.
1401  *  pbData     [O] Sequence of bytes to receive data.
1402  *  pdwDataLen [I/O] Size of pbData.
1403  *  dwFlags    [I] Reserved for future use and must be zero.
1404  *
1405  * RETURNS
1406  *  Success: TRUE
1407  *  Failure: FALSE
1408  *
1409  * NOTES
1410  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1411  */
1412 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1413                 DWORD *pdwDataLen, DWORD dwFlags)
1414 {
1415         PCRYPTPROV prov;
1416         PCRYPTKEY key = (PCRYPTKEY)hKey;
1417
1418         TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1419
1420         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1421                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1422
1423         prov = key->pProvider;
1424         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1425                         pbData, pdwDataLen, dwFlags);
1426 }
1427
1428 /******************************************************************************
1429  * CryptGetProvParam (ADVAPI32.@)
1430  *
1431  * Retrieves parameters that control the operations of a CSP.
1432  *
1433  * PARAMS
1434  *  hProv      [I] Handle of the CSP in question.
1435  *  dwParam    [I] Specifies query type.
1436  *  pbData     [O] Buffer to receive the data.
1437  *  pdwDataLen [I/O] Size of pbData.
1438  *  dwFlags    [I] see MSDN Docs.
1439  *
1440  * RETURNS
1441  *  Success: TRUE
1442  *  Failure: FALSE
1443  *
1444  * NOTES
1445  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1446  */
1447 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1448                 DWORD *pdwDataLen, DWORD dwFlags)
1449 {
1450         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1451
1452         TRACE("(0x%lx, %ld, %p, %p, %08lx)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1453
1454         if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1455                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1456
1457         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1458 }
1459
1460 /******************************************************************************
1461  * CryptGetUserKey (ADVAPI32.@)
1462  *
1463  * Gets a handle of one of a user's two public/private key pairs.
1464  *
1465  * PARAMS
1466  *  hProv     [I] Handle of a CSP.
1467  *  dwKeySpec [I] Private key to use.
1468  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1469  *
1470  * RETURNS
1471  *  Success: TRUE
1472  *  Failure: FALSE
1473  */
1474 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1475 {
1476         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1477         PCRYPTKEY key;
1478
1479         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1480
1481         if (!prov)
1482                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1483         if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1484                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1485         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1486                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1487
1488         key->pProvider = prov;
1489
1490         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1491         {
1492             *phUserKey = (HCRYPTKEY)key;
1493             return TRUE;
1494         }
1495
1496         /* CSP Error */
1497         CRYPT_Free(key);
1498         *phUserKey = 0;
1499         return FALSE;
1500 }
1501
1502 /******************************************************************************
1503  * CryptHashData (ADVAPI32.@)
1504  *
1505  * Adds data to a hash object.
1506  *
1507  * PARAMS
1508  *  hHash     [I] Handle of the hash object.
1509  *  pbData    [I] Buffer of data to be hashed.
1510  *  dwDataLen [I] Number of bytes to add.
1511  *  dwFlags   [I] Can be CRYPT_USERDATA
1512  *
1513  * RETURNS
1514  *  Success: TRUE
1515  *  Failure: FALSE
1516  */
1517 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1518 {
1519         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1520         PCRYPTPROV prov;
1521
1522         TRACE("(0x%lx, %p, %ld, %08lx)\n", hHash, pbData, dwDataLen, dwFlags);
1523
1524         if (!hash)
1525                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1526         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1527                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1528
1529         prov = hash->pProvider;
1530         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1531 }
1532
1533 /******************************************************************************
1534  * CryptHashSessionKey (ADVAPI32.@)
1535  *
1536  * PARAMS 
1537  *  hHash   [I] Handle to the hash object.
1538  *  hKey    [I] Handle to the key to be hashed.
1539  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1540  *
1541  * RETURNS
1542  *  Success: TRUE
1543  *  Failure: FALSE
1544  */
1545 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1546 {
1547         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1548         PCRYPTKEY key = (PCRYPTKEY)hKey;
1549         PCRYPTPROV prov;
1550
1551         TRACE("(0x%lx, 0x%lx, %08lx)\n", hHash, hKey, dwFlags);
1552
1553         if (!hash || !key)
1554                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1555
1556         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1557                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1558
1559         prov = hash->pProvider;
1560         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1561 }
1562
1563 /******************************************************************************
1564  * CryptImportKey (ADVAPI32.@)
1565  *
1566  * PARAMS
1567  *  hProv     [I] Handle of a CSP.
1568  *  pbData    [I] Contains the key to be imported.
1569  *  dwDataLen [I] Length of the key.
1570  *  hPubKey   [I] Cryptographic key that decrypts pdData
1571  *  dwFlags   [I] Used only with a public/private key pair.
1572  *  phKey     [O] Imported key.
1573  *
1574  * RETURNS
1575  *  Success: TRUE
1576  *  Failure: FALSE
1577  */
1578 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1579                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1580 {
1581         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1582         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1583
1584         TRACE("(0x%lx, %p, %ld, 0x%lx, %08lx, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1585
1586         if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
1587                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1588
1589         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1590                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1591
1592         importkey->pProvider = prov;
1593         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1594                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1595         {
1596                 *phKey = (HCRYPTKEY)importkey;
1597                 return TRUE;
1598         }
1599
1600         CRYPT_Free(importkey);
1601         return FALSE;
1602 }
1603
1604 /******************************************************************************
1605  * CryptSignHashW (ADVAPI32.@)
1606  *
1607  * Signs data.
1608  *
1609  * PARAMS
1610  *  hHash        [I] Handle of the hash object to be signed.
1611  *  dwKeySpec    [I] Private key to use.
1612  *  sDescription [I] Should be NULL.
1613  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1614  *  pbSignature  [O] Buffer of the signature data.
1615  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1616  *
1617  * RETURNS
1618  *  Success: TRUE
1619  *  Failure: FALSE
1620  *
1621  * NOTES
1622  *  Because of security flaws sDescription should not be used and should thus be
1623  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1624  *  Providers.
1625  */
1626 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1627                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1628 {
1629         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1630         PCRYPTPROV prov;
1631
1632         TRACE("(0x%lx, %ld, %s, %08lx, %p, %p)\n", 
1633                 hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1634
1635         if (!hash)
1636                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1637         if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1638                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1639
1640         prov = hash->pProvider;
1641         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1642                 dwFlags, pbSignature, pdwSigLen);
1643 }
1644
1645 /******************************************************************************
1646  * CryptSignHashA (ADVAPI32.@)
1647  *
1648  * See CryptSignHashW.
1649  */
1650 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1651                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1652 {
1653         LPWSTR wsDescription;
1654         BOOL result;
1655
1656         TRACE("(0x%lx, %ld, %s, %08lx, %p, %p)\n", 
1657                 hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1658
1659         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1660         result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1661         if (wsDescription) CRYPT_Free(wsDescription);
1662
1663         return result;
1664 }
1665
1666 /******************************************************************************
1667  * CryptSetHashParam (ADVAPI32.@)
1668  *
1669  * Customizes the operations of a hash object.
1670  *
1671  * PARAMS
1672  *  hHash   [I] Handle of the hash object to set parameters.
1673  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1674  *  pbData  [I] Value data buffer.
1675  *  dwFlags [I] Reserved for future use and must be zero.
1676  *
1677  * RETURNS
1678  *  Success: TRUE
1679  *  Failure: FALSE
1680  */
1681 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1682 {
1683         PCRYPTPROV prov;
1684         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1685
1686         TRACE("(0x%lx, %ld, %p, %08lx)\n", hHash, dwParam, pbData, dwFlags);
1687
1688         if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1689                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1690
1691         prov = hash->pProvider;
1692         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1693                         dwParam, pbData, dwFlags);
1694 }
1695
1696 /******************************************************************************
1697  * CryptSetKeyParam (ADVAPI32.@)
1698  *
1699  * Customizes a session key's operations.
1700  *
1701  * PARAMS
1702  *  hKey    [I] Handle to the key to set values.
1703  *  dwParam [I] See MSDN Doc.
1704  *  pbData  [I] Buffer of values to set.
1705  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1706  *
1707  * RETURNS
1708  *  Success: TRUE
1709  *  Failure: FALSE
1710  */
1711 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1712 {
1713         PCRYPTPROV prov;
1714         PCRYPTKEY key = (PCRYPTKEY)hKey;
1715
1716         TRACE("(0x%lx, %ld, %p, %08lx)\n", hKey, dwParam, pbData, dwFlags);
1717
1718         if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1719                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1720
1721         prov = key->pProvider;
1722         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1723                         dwParam, pbData, dwFlags);
1724 }
1725
1726 /******************************************************************************
1727  * CryptSetProviderA (ADVAPI32.@)
1728  *
1729  * Specifies the current user's default CSP.
1730  *
1731  * PARAMS
1732  *  pszProvName [I] Name of the new default CSP.
1733  *  dwProvType  [I] Provider type of the CSP.
1734  *
1735  * RETURNS
1736  *  Success: TRUE
1737  *  Failure: FALSE
1738  */
1739 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1740 {
1741         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1742         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1743 }
1744
1745 /******************************************************************************
1746  * CryptSetProviderW (ADVAPI32.@)
1747  *
1748  * See CryptSetProviderA.
1749  */
1750 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1751 {
1752         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1753         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1754 }
1755
1756 /******************************************************************************
1757  * CryptSetProviderExW (ADVAPI32.@)
1758  *
1759  * Specifies the default CSP.
1760  *
1761  * PARAMS
1762  *  pszProvName [I] Name of the new default CSP.
1763  *  dwProvType  [I] Provider type of the CSP.
1764  *  pdwReserved [I] Reserved for future use and must be NULL.
1765  *  dwFlags     [I] See MSDN Doc.
1766  *
1767  * RETURNS
1768  *  Success: TRUE
1769  *  Failure: FALSE
1770  */
1771 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1772 {
1773         HKEY hProvKey, hTypeKey;
1774         PWSTR keyname;
1775         static const WCHAR nameW[] = {'N','a','m','e',0};
1776
1777         TRACE("(%s, %ld, %p, %08lx)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1778
1779         if (!pszProvName || pdwReserved)
1780                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1781         if (dwProvType > MAXPROVTYPES)
1782                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1783         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1784                         || dwFlags == CRYPT_DELETE_DEFAULT)
1785                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1786         
1787         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
1788                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1789         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1790                 keyname, &hTypeKey))
1791         {
1792                 CRYPT_Free(keyname);
1793                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1794         }
1795         CRYPT_Free(keyname);
1796         
1797         if (dwFlags & CRYPT_DELETE_DEFAULT)
1798         {
1799                 RegDeleteValueW(hTypeKey, nameW);
1800         }
1801         else
1802         {
1803                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
1804                 {
1805                         RegCloseKey(hTypeKey);
1806                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1807                 }
1808                 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1809                         keyname, &hProvKey))
1810                 {
1811                         CRYPT_Free(keyname);
1812                         RegCloseKey(hTypeKey);
1813                         CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1814                 }
1815                 CRYPT_Free(keyname);
1816                 
1817                 if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (LPBYTE)pszProvName, (strlenW(pszProvName) + 1)*sizeof(WCHAR)))
1818                 {
1819                         RegCloseKey(hTypeKey);
1820                         RegCloseKey(hProvKey);
1821                         return FALSE;
1822                 }
1823                 
1824                 RegCloseKey(hProvKey);
1825         }
1826         RegCloseKey(hTypeKey);
1827
1828         return TRUE;
1829 }
1830
1831 /******************************************************************************
1832  * CryptSetProviderExA (ADVAPI32.@)
1833  *
1834  * See CryptSetProviderExW.
1835  */
1836 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1837 {
1838         BOOL ret = FALSE;
1839         PWSTR str = NULL;
1840
1841         TRACE("(%s, %ld, %p, %08lx)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1842
1843         if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
1844         {
1845                 ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
1846                 CRYPT_Free(str);
1847         }
1848         return ret;
1849 }
1850
1851 /******************************************************************************
1852  * CryptSetProvParam (ADVAPI32.@)
1853  *
1854  * Customizes the operations of a CSP.
1855  *
1856  * PARAMS
1857  *  hProv   [I] Handle of a CSP.
1858  *  dwParam [I] See MSDN Doc.
1859  *  pbData  [I] Buffer that contains a value to set as a parameter.
1860  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
1861  *
1862  * RETURNS
1863  *  Success: TRUE
1864  *  Failure: FALSE
1865  */
1866 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1867 {
1868         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1869
1870         TRACE("(0x%lx, %ld, %p, %08lx)\n", hProv, dwParam, pbData, dwFlags);
1871
1872         if (!prov)
1873                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1874         if (prov->dwMagic != MAGIC_CRYPTPROV)
1875                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1876         if (dwFlags & PP_USE_HARDWARE_RNG)
1877         {
1878                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1879                 FIXME("\tLetting the CSP decide.\n");
1880         }
1881         if (dwFlags & PP_CLIENT_HWND)
1882         {
1883                 /* FIXME: Should verify the parameter */
1884                 if (pbData /* && IsWindow((HWND)pbData) */)
1885                 {
1886                         crypt_hWindow = (HWND)(pbData);
1887                         return TRUE;
1888                 } else {
1889                         SetLastError(ERROR_INVALID_PARAMETER);
1890                         return FALSE;
1891                 }
1892         }
1893         /* All other flags go to the CSP */
1894         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1895 }
1896
1897 /******************************************************************************
1898  * CryptVerifySignatureW (ADVAPI32.@)
1899  *
1900  * Verifies the signature of a hash object.
1901  *
1902  * PARAMS
1903  *  hHash        [I] Handle of the hash object to verify.
1904  *  pbSignature  [I] Signature data to verify.
1905  *  dwSigLen     [I] Size of pbSignature.
1906  *  hPubKey      [I] Handle to the public key to authenticate signature.
1907  *  sDescription [I] Should be NULL.
1908  *  dwFlags      [I] See MSDN doc.
1909  *
1910  * RETURNS
1911  *  Success: TRUE
1912  *  Failure: FALSE
1913  * 
1914  * NOTES
1915  *  Because of security flaws sDescription should not be used and should thus be
1916  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1917  *  Providers.
1918  */
1919 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1920                 HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
1921 {
1922         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1923         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1924         PCRYPTPROV prov;
1925
1926         TRACE("(0x%lx, %p, %ld, 0x%lx, %s, %08lx)\n", hHash, pbSignature,
1927                         dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
1928
1929         if (!hash || !key)
1930                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1931         if (!pbSignature || !dwSigLen || 
1932             !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
1933             !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1934         {
1935                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1936         }
1937                 
1938         prov = hash->pProvider;
1939         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1940                 key->hPrivate, sDescription, dwFlags);
1941 }
1942
1943 /******************************************************************************
1944  * CryptVerifySignatureA (ADVAPI32.@)
1945  *
1946  * See CryptVerifySignatureW.
1947  */
1948 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1949                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1950 {
1951         LPWSTR wsDescription;
1952         BOOL result;
1953
1954         TRACE("(0x%lx, %p, %ld, 0x%lx, %s, %08lx)\n", hHash, pbSignature,
1955                         dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
1956
1957         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1958         result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
1959         if (wsDescription) CRYPT_Free(wsDescription);
1960
1961         return result;
1962 }
1963
1964 /******************************************************************************
1965  * SystemFunction036   (ADVAPI32.@)
1966  *
1967  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
1968  *
1969  * PARAMS
1970  *  pbBufer [O] Pointer to memory to receive random bytes.
1971  *  dwLen   [I] Number of random bytes to fetch.
1972  *
1973  * RETURNS
1974  *  Success: TRUE
1975  *  Failure: FALSE
1976  */
1977
1978 BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
1979 {
1980     int dev_random;
1981
1982     /* FIXME: /dev/urandom does not provide random numbers of a sufficient
1983      * quality for cryptographic applications. /dev/random is much better,  
1984      * but it blocks if the kernel has not yet collected enough entropy for
1985      * the request, which will suspend the calling thread for an indefinite
1986      * amount of time. */
1987     dev_random = open("/dev/urandom", O_RDONLY);
1988     if (dev_random != -1)
1989     {
1990         if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
1991         {
1992             close(dev_random);
1993             return TRUE;
1994         }
1995         close(dev_random);
1996     }
1997     SetLastError(NTE_FAIL);
1998     return FALSE;
1999 }    
2000     
2001 /*
2002    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
2003    in crypt32.dll.
2004  */
2005
2006 /******************************************************************************
2007  * SystemFunction040   (ADVAPI32.@)
2008  *
2009  * MSDN documents this function as RtlEncryptMemory.
2010  *
2011  * PARAMS
2012  *  memory [I/O] Pointer to memory to encrypt.
2013  *  length [I] Length of region to encrypt in bytes.
2014  *  flags  [I] Control whether other processes are able to decrypt the memory.
2015  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
2016  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
2017  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2018  *    
2019  * RETURNS
2020  *  Success: STATUS_SUCCESS
2021  *  Failure: NTSTATUS error code
2022  *
2023  * NOTES
2024  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2025  *  If flags are specified when encrypting, the same flag value must be given
2026  *  when decrypting the memory.
2027  */
2028 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2029 {
2030         FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
2031         return STATUS_SUCCESS;
2032 }
2033
2034 /******************************************************************************
2035  * SystemFunction041  (ADVAPI32.@)
2036  *
2037  * MSDN documents this function as RtlDecryptMemory.
2038  *
2039  * PARAMS
2040  *  memory [I/O] Pointer to memory to decrypt.
2041  *  length [I] Length of region to decrypt in bytes.
2042  *  flags  [I] Control whether other processes are able to decrypt the memory.
2043  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
2044  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
2045  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2046  *
2047  * RETURNS
2048  *  Success: STATUS_SUCCESS
2049  *  Failure: NTSTATUS error code
2050  *
2051  * NOTES
2052  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2053  *  If flags are specified when encrypting, the same flag value must be given
2054  *  when decrypting the memory.
2055  */
2056 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2057 {
2058         FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
2059         return STATUS_SUCCESS;
2060 }