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