advapi32: Implement CredEnumerateW.
[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         unsigned 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, ULONG_PTR dwFlags)
572 {
573         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
574         BOOL ret = TRUE;
575
576         TRACE("(0x%lx, %08lx)\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 encryption 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 available 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         if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
1143                 return FALSE;
1144         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1145         {
1146                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1147                 return FALSE;
1148         }
1149         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1150         if (str)
1151                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1152         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1153         if (str)
1154         {
1155                 CRYPT_Free(str);
1156                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1157                 {
1158                         SetLastError(ERROR_MORE_DATA);
1159                         return FALSE;
1160                 }
1161         }
1162         return ret;
1163 }
1164
1165 /******************************************************************************
1166  * CryptEnumProviderTypesW (ADVAPI32.@)
1167  *
1168  * Retrieves the next type of CSP supported.
1169  *
1170  * PARAMS
1171  *  dwIndex     [I] Index of the next provider to be enumerated.
1172  *  pdwReserved [I] Reserved for future use and must be NULL.
1173  *  dwFlags     [I] Reserved for future use and must be zero.
1174  *  pdwProvType [O] DWORD designating the type of the provider.
1175  *  pszTypeName [O] Buffer that receives data from the provider type.
1176  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1177  *                    of bytes stored in the buffer on return.
1178  *
1179  *  RETURNS
1180  *   Success: TRUE
1181  *   Failure: FALSE
1182  *
1183  *  NOTES
1184  *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1185  *   for memory allocation purposes.
1186  */
1187 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1188                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1189 {
1190         HKEY hKey, hSubkey;
1191         DWORD keylen, numkeys, dwType;
1192         PWSTR keyname, ch;
1193         DWORD result;
1194         static const WCHAR KEYSTR[] = {
1195                 'S','o','f','t','w','a','r','e','\\',
1196                 'M','i','c','r','o','s','o','f','t','\\',
1197                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1198                 'D','e','f','a','u','l','t','s','\\',
1199                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
1200         };
1201         static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
1202
1203         TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved,
1204                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1205
1206         if (pdwReserved || !pdwProvType || !pcbTypeName)
1207         {
1208                 SetLastError(ERROR_INVALID_PARAMETER);
1209                 return FALSE;
1210         }
1211         if (dwFlags)
1212         {
1213                 SetLastError(NTE_BAD_FLAGS);
1214                 return FALSE;
1215         }
1216
1217         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
1218                 return FALSE;
1219
1220         RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1221         if (dwIndex >= numkeys)
1222         {
1223                 SetLastError(ERROR_NO_MORE_ITEMS);
1224                 return FALSE;
1225         }
1226         keylen++;
1227         if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1228         {
1229                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1230                 return FALSE;
1231         }
1232         if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1233                 CRYPT_Free(keyname);
1234                 return FALSE;
1235         }
1236         RegOpenKeyW(hKey, keyname, &hSubkey);
1237         ch = keyname + strlenW(keyname);
1238         /* Convert "Type 000" to 0, etc/ */
1239         *pdwProvType = *(--ch) - '0';
1240         *pdwProvType += (*(--ch) - '0') * 10;
1241         *pdwProvType += (*(--ch) - '0') * 100;
1242         CRYPT_Free(keyname);
1243         
1244         result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1245         if (result)
1246         {
1247                 SetLastError(result);
1248                 return FALSE;
1249         }
1250
1251         RegCloseKey(hSubkey);
1252         RegCloseKey(hKey);
1253         return TRUE;
1254 }
1255
1256 /******************************************************************************
1257  * CryptEnumProviderTypesA (ADVAPI32.@)
1258  *
1259  * See CryptEnumProviderTypesW.
1260  */
1261 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1262                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1263 {
1264         PWSTR str = NULL;
1265         DWORD strlen;
1266         BOOL ret;
1267
1268         TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1269                         pdwProvType, pszTypeName, pcbTypeName);
1270
1271         if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &strlen))
1272                 return FALSE;
1273         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1274         {
1275                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1276                 return FALSE;
1277         }
1278         ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1279         if (str)
1280                 CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1281         *pcbTypeName = strlen / sizeof(WCHAR);
1282         if (str)
1283         {
1284                 CRYPT_Free(str);
1285                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1286                 {
1287                         SetLastError(ERROR_MORE_DATA);
1288                         return FALSE;
1289                 }
1290         }
1291         return ret;
1292 }
1293
1294 /******************************************************************************
1295  * CryptExportKey (ADVAPI32.@)
1296  * 
1297  * Exports a cryptographic key from a CSP.
1298  *
1299  * PARAMS
1300  *  hKey       [I] Handle to the key to export.
1301  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1302  *  dwBlobType [I] Type of BLOB to be exported.
1303  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1304  *  pbData     [O] Buffer to receive BLOB data.
1305  *  pdwDataLen [I/O] Specifies the size of pbData.
1306  *
1307  * RETURNS
1308  *  Success: TRUE
1309  *  Failure: FALSE
1310  *
1311  * NOTES
1312  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1313  *  buffer needed to hold the BLOB.
1314  */
1315 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1316                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1317 {
1318         PCRYPTPROV prov;
1319         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1320
1321         TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1322
1323         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1324         {
1325                 SetLastError(ERROR_INVALID_PARAMETER);
1326                 return FALSE;
1327         }
1328
1329         prov = key->pProvider;
1330         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1331                         dwBlobType, dwFlags, pbData, pdwDataLen);
1332 }
1333
1334 /******************************************************************************
1335  * CryptGenKey (ADVAPI32.@)
1336  *
1337  * Generates a random cryptographic session key or a pub/priv key pair.
1338  *
1339  * PARAMS
1340  *  hProv   [I] Handle to a CSP.
1341  *  Algid   [I] Algorithm to use to make key.
1342  *  dwFlags [I] Specifies type of key to make.
1343  *  phKey   [I] Address of the handle to which the new key is copied.
1344  *
1345  *  RETURNS
1346  *   Success: TRUE
1347  *   Failure: FALSE
1348  */
1349 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1350 {
1351         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1352         PCRYPTKEY key;
1353
1354         TRACE("(0x%lx, %d, %08x, %p)\n", hProv, Algid, dwFlags, phKey);
1355
1356         if (!prov)
1357         {
1358                 SetLastError(ERROR_INVALID_HANDLE);
1359                 return FALSE;
1360         }
1361         if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1362         {
1363                 SetLastError(ERROR_INVALID_PARAMETER);
1364                 return FALSE;
1365         }
1366         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1367         {
1368                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1369                 return FALSE;
1370         }
1371
1372         key->pProvider = prov;
1373
1374         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1375         {
1376             *phKey = (HCRYPTKEY)key;
1377             return TRUE;
1378         }
1379
1380         /* CSP error! */
1381         CRYPT_Free(key);
1382         return FALSE;
1383 }
1384
1385 /******************************************************************************
1386  * CryptGetDefaultProviderW (ADVAPI32.@)
1387  *
1388  * Finds the default CSP of a certain provider type.
1389  *
1390  * PARAMS
1391  *  dwProvType  [I] Provider type to look for.
1392  *  pdwReserved [I] Reserved for future use and must be NULL.
1393  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1394  *  pszProvName [O] Name of the default CSP.
1395  *  pcbProvName [I/O] Size of pszProvName
1396  *
1397  * RETURNS
1398  *  Success: TRUE
1399  *  Failure: FALSE
1400  *
1401  * NOTES
1402  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1403  *  memory allocation purposes on return.
1404  */
1405 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1406                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1407 {
1408         HKEY hKey;
1409         PWSTR keyname;
1410         DWORD result;
1411         static const WCHAR nameW[] = {'N','a','m','e',0};
1412
1413         if (pdwReserved || !pcbProvName)
1414         {
1415                 SetLastError(ERROR_INVALID_PARAMETER);
1416                 return FALSE;
1417         }
1418         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1419         {
1420                 SetLastError(NTE_BAD_FLAGS);
1421                 return FALSE;
1422         }
1423         if (dwProvType > 999)
1424         {
1425                 SetLastError(NTE_BAD_PROV_TYPE);
1426                 return FALSE;
1427         }
1428         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1429         {
1430                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1431                 return FALSE;
1432         }
1433         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1434         {
1435                 CRYPT_Free(keyname);
1436                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
1437                 return FALSE;
1438         }
1439         CRYPT_Free(keyname);
1440         
1441         result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName); 
1442         if (result)
1443         {
1444                 if (result != ERROR_MORE_DATA)
1445                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1446                 else
1447                         SetLastError(result);
1448                 
1449                 return FALSE;
1450         }
1451         
1452         RegCloseKey(hKey);
1453         return TRUE;
1454 }
1455
1456 /******************************************************************************
1457  * CryptGetDefaultProviderA (ADVAPI32.@)
1458  *
1459  * See CryptGetDefaultProviderW.
1460  */
1461 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1462                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1463 {
1464         PWSTR str = NULL;
1465         DWORD strlen;
1466         BOOL ret = FALSE;
1467
1468         TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1469
1470         CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &strlen);
1471         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1472         {
1473                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1474                 return FALSE;
1475         }
1476         ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &strlen);
1477         if (str)
1478                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1479         *pcbProvName = strlen / sizeof(WCHAR);
1480         if (str)
1481         {
1482                 CRYPT_Free(str);
1483                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1484                 {
1485                         SetLastError(ERROR_MORE_DATA);
1486                         return FALSE;
1487                 }
1488         }
1489         return ret;
1490 }
1491
1492 /******************************************************************************
1493  * CryptGetHashParam (ADVAPI32.@)
1494  *
1495  * Retrieves data that controls the operations of a hash object.
1496  *
1497  * PARAMS
1498  *  hHash      [I] Handle of the hash object to question.
1499  *  dwParam    [I] Query type.
1500  *  pbData     [O] Buffer that receives the value data.
1501  *  pdwDataLen [I/O] Size of the pbData buffer.
1502  *  dwFlags    [I] Reserved for future use and must be zero.
1503  *
1504  * RETURNS
1505  *  Success: TRUE
1506  *  Failure: FALSE
1507  *
1508  * NOTES
1509  *  If pbData is NULL, pdwDataLen will contain the length required.
1510  */
1511 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1512                 DWORD *pdwDataLen, DWORD dwFlags)
1513 {
1514         PCRYPTPROV prov;
1515         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1516
1517         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1518
1519         if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1520         {
1521                 SetLastError(ERROR_INVALID_PARAMETER);
1522                 return FALSE;
1523         }
1524
1525         prov = hash->pProvider;
1526         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1527                         pbData, pdwDataLen, dwFlags);
1528 }
1529
1530 /******************************************************************************
1531  * CryptGetKeyParam (ADVAPI32.@)
1532  *
1533  * Retrieves data that controls the operations of a key.
1534  *
1535  * PARAMS
1536  *  hKey       [I] Handle to they key in question.
1537  *  dwParam    [I] Specifies query type.
1538  *  pbData     [O] Sequence of bytes to receive data.
1539  *  pdwDataLen [I/O] Size of pbData.
1540  *  dwFlags    [I] Reserved for future use and must be zero.
1541  *
1542  * RETURNS
1543  *  Success: TRUE
1544  *  Failure: FALSE
1545  *
1546  * NOTES
1547  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1548  */
1549 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1550                 DWORD *pdwDataLen, DWORD dwFlags)
1551 {
1552         PCRYPTPROV prov;
1553         PCRYPTKEY key = (PCRYPTKEY)hKey;
1554
1555         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1556
1557         if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1558         {
1559                 SetLastError(ERROR_INVALID_PARAMETER);
1560                 return FALSE;
1561         }
1562
1563         prov = key->pProvider;
1564         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1565                         pbData, pdwDataLen, dwFlags);
1566 }
1567
1568 /******************************************************************************
1569  * CryptGetProvParam (ADVAPI32.@)
1570  *
1571  * Retrieves parameters that control the operations of a CSP.
1572  *
1573  * PARAMS
1574  *  hProv      [I] Handle of the CSP in question.
1575  *  dwParam    [I] Specifies query type.
1576  *  pbData     [O] Buffer to receive the data.
1577  *  pdwDataLen [I/O] Size of pbData.
1578  *  dwFlags    [I] see MSDN Docs.
1579  *
1580  * RETURNS
1581  *  Success: TRUE
1582  *  Failure: FALSE
1583  *
1584  * NOTES
1585  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1586  */
1587 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1588                 DWORD *pdwDataLen, DWORD dwFlags)
1589 {
1590         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1591
1592         TRACE("(0x%lx, %d, %p, %p, %08x)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1593
1594         if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1595         {
1596                 SetLastError(ERROR_INVALID_PARAMETER);
1597                 return FALSE;
1598         }
1599
1600         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1601 }
1602
1603 /******************************************************************************
1604  * CryptGetUserKey (ADVAPI32.@)
1605  *
1606  * Gets a handle of one of a user's two public/private key pairs.
1607  *
1608  * PARAMS
1609  *  hProv     [I] Handle of a CSP.
1610  *  dwKeySpec [I] Private key to use.
1611  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1612  *
1613  * RETURNS
1614  *  Success: TRUE
1615  *  Failure: FALSE
1616  */
1617 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1618 {
1619         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1620         PCRYPTKEY key;
1621
1622         TRACE("(0x%lx, %d, %p)\n", hProv, dwKeySpec, phUserKey);
1623
1624         if (!prov)
1625         {
1626                 SetLastError(ERROR_INVALID_HANDLE);
1627                 return FALSE;
1628         }
1629         if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1630         {
1631                 SetLastError(ERROR_INVALID_PARAMETER);
1632                 return FALSE;
1633         }
1634         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1635         {
1636                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1637                 return FALSE;
1638         }
1639
1640         key->pProvider = prov;
1641
1642         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1643         {
1644             *phUserKey = (HCRYPTKEY)key;
1645             return TRUE;
1646         }
1647
1648         /* CSP Error */
1649         CRYPT_Free(key);
1650         *phUserKey = 0;
1651         return FALSE;
1652 }
1653
1654 /******************************************************************************
1655  * CryptHashData (ADVAPI32.@)
1656  *
1657  * Adds data to a hash object.
1658  *
1659  * PARAMS
1660  *  hHash     [I] Handle of the hash object.
1661  *  pbData    [I] Buffer of data to be hashed.
1662  *  dwDataLen [I] Number of bytes to add.
1663  *  dwFlags   [I] Can be CRYPT_USERDATA
1664  *
1665  * RETURNS
1666  *  Success: TRUE
1667  *  Failure: FALSE
1668  */
1669 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1670 {
1671         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1672         PCRYPTPROV prov;
1673
1674         TRACE("(0x%lx, %p, %d, %08x)\n", hHash, pbData, dwDataLen, dwFlags);
1675
1676         if (!hash)
1677         {
1678                 SetLastError(ERROR_INVALID_HANDLE);
1679                 return FALSE;
1680         }
1681         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1682         {
1683                 SetLastError(ERROR_INVALID_PARAMETER);
1684                 return FALSE;
1685         }
1686
1687         prov = hash->pProvider;
1688         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1689 }
1690
1691 /******************************************************************************
1692  * CryptHashSessionKey (ADVAPI32.@)
1693  *
1694  * Compute the cryptographic hash of a session key object.
1695  *
1696  * PARAMS 
1697  *  hHash   [I] Handle to the hash object.
1698  *  hKey    [I] Handle to the key to be hashed.
1699  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1700  *
1701  * RETURNS
1702  *  Success: TRUE
1703  *  Failure: FALSE
1704  */
1705 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1706 {
1707         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1708         PCRYPTKEY key = (PCRYPTKEY)hKey;
1709         PCRYPTPROV prov;
1710
1711         TRACE("(0x%lx, 0x%lx, %08x)\n", hHash, hKey, dwFlags);
1712
1713         if (!hash || !key)
1714         {
1715                 SetLastError(ERROR_INVALID_HANDLE);
1716                 return FALSE;
1717         }
1718
1719         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1720         {
1721                 SetLastError(ERROR_INVALID_PARAMETER);
1722                 return FALSE;
1723         }
1724
1725         prov = hash->pProvider;
1726         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1727 }
1728
1729 /******************************************************************************
1730  * CryptImportKey (ADVAPI32.@)
1731  *
1732  * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
1733  *
1734  * PARAMS
1735  *  hProv     [I] Handle of a CSP.
1736  *  pbData    [I] Contains the key to be imported.
1737  *  dwDataLen [I] Length of the key.
1738  *  hPubKey   [I] Cryptographic key that decrypts pdData
1739  *  dwFlags   [I] Used only with a public/private key pair.
1740  *  phKey     [O] Imported key.
1741  *
1742  * RETURNS
1743  *  Success: TRUE
1744  *  Failure: FALSE
1745  */
1746 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
1747                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1748 {
1749         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1750         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1751
1752         TRACE("(0x%lx, %p, %d, 0x%lx, %08x, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1753
1754         if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
1755         {
1756                 SetLastError(ERROR_INVALID_PARAMETER);
1757                 return FALSE;
1758         }
1759
1760         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1761         {
1762                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1763                 return FALSE;
1764         }
1765
1766         importkey->pProvider = prov;
1767         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1768                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1769         {
1770                 *phKey = (HCRYPTKEY)importkey;
1771                 return TRUE;
1772         }
1773
1774         CRYPT_Free(importkey);
1775         return FALSE;
1776 }
1777
1778 /******************************************************************************
1779  * CryptSignHashW (ADVAPI32.@)
1780  *
1781  * Signs data.
1782  *
1783  * PARAMS
1784  *  hHash        [I] Handle of the hash object to be signed.
1785  *  dwKeySpec    [I] Private key to use.
1786  *  sDescription [I] Should be NULL.
1787  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1788  *  pbSignature  [O] Buffer of the signature data.
1789  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1790  *
1791  * RETURNS
1792  *  Success: TRUE
1793  *  Failure: FALSE
1794  *
1795  * NOTES
1796  *  Because of security flaws sDescription should not be used and should thus be
1797  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1798  *  Providers.
1799  */
1800 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1801                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1802 {
1803         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1804         PCRYPTPROV prov;
1805
1806         TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1807                 hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1808
1809         if (!hash)
1810         {
1811                 SetLastError(ERROR_INVALID_HANDLE);
1812                 return FALSE;
1813         }
1814         if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1815         {
1816                 SetLastError(ERROR_INVALID_PARAMETER);
1817                 return FALSE;
1818         }
1819
1820         prov = hash->pProvider;
1821         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1822                 dwFlags, pbSignature, pdwSigLen);
1823 }
1824
1825 /******************************************************************************
1826  * CryptSignHashA (ADVAPI32.@)
1827  *
1828  * See CryptSignHashW.
1829  */
1830 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1831                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1832 {
1833         LPWSTR wsDescription;
1834         BOOL result;
1835
1836         TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
1837                 hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1838
1839         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1840         result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1841         CRYPT_Free(wsDescription);
1842
1843         return result;
1844 }
1845
1846 /******************************************************************************
1847  * CryptSetHashParam (ADVAPI32.@)
1848  *
1849  * Customizes the operations of a hash object.
1850  *
1851  * PARAMS
1852  *  hHash   [I] Handle of the hash object to set parameters.
1853  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1854  *  pbData  [I] Value data buffer.
1855  *  dwFlags [I] Reserved for future use and must be zero.
1856  *
1857  * RETURNS
1858  *  Success: TRUE
1859  *  Failure: FALSE
1860  */
1861 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
1862 {
1863         PCRYPTPROV prov;
1864         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1865
1866         TRACE("(0x%lx, %d, %p, %08x)\n", hHash, dwParam, pbData, dwFlags);
1867
1868         if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1869         {
1870                 SetLastError(ERROR_INVALID_PARAMETER);
1871                 return FALSE;
1872         }
1873
1874         prov = hash->pProvider;
1875         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1876                         dwParam, pbData, dwFlags);
1877 }
1878
1879 /******************************************************************************
1880  * CryptSetKeyParam (ADVAPI32.@)
1881  *
1882  * Customizes a session key's operations.
1883  *
1884  * PARAMS
1885  *  hKey    [I] Handle to the key to set values.
1886  *  dwParam [I] See MSDN Doc.
1887  *  pbData  [I] Buffer of values to set.
1888  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1889  *
1890  * RETURNS
1891  *  Success: TRUE
1892  *  Failure: FALSE
1893  */
1894 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
1895 {
1896         PCRYPTPROV prov;
1897         PCRYPTKEY key = (PCRYPTKEY)hKey;
1898
1899         TRACE("(0x%lx, %d, %p, %08x)\n", hKey, dwParam, pbData, dwFlags);
1900
1901         if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1902         {
1903                 SetLastError(ERROR_INVALID_PARAMETER);
1904                 return FALSE;
1905         }
1906
1907         prov = key->pProvider;
1908         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1909                         dwParam, pbData, dwFlags);
1910 }
1911
1912 /******************************************************************************
1913  * CryptSetProviderA (ADVAPI32.@)
1914  *
1915  * Specifies the current user's default CSP.
1916  *
1917  * PARAMS
1918  *  pszProvName [I] Name of the new default CSP.
1919  *  dwProvType  [I] Provider type of the CSP.
1920  *
1921  * RETURNS
1922  *  Success: TRUE
1923  *  Failure: FALSE
1924  */
1925 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1926 {
1927         TRACE("(%s, %d)\n", pszProvName, dwProvType);
1928         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1929 }
1930
1931 /******************************************************************************
1932  * CryptSetProviderW (ADVAPI32.@)
1933  *
1934  * See CryptSetProviderA.
1935  */
1936 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1937 {
1938         TRACE("(%s, %d)\n", debugstr_w(pszProvName), dwProvType);
1939         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1940 }
1941
1942 /******************************************************************************
1943  * CryptSetProviderExW (ADVAPI32.@)
1944  *
1945  * Specifies the default CSP.
1946  *
1947  * PARAMS
1948  *  pszProvName [I] Name of the new default CSP.
1949  *  dwProvType  [I] Provider type of the CSP.
1950  *  pdwReserved [I] Reserved for future use and must be NULL.
1951  *  dwFlags     [I] See MSDN Doc.
1952  *
1953  * RETURNS
1954  *  Success: TRUE
1955  *  Failure: FALSE
1956  */
1957 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1958 {
1959         HKEY hProvKey, hTypeKey;
1960         PWSTR keyname;
1961         static const WCHAR nameW[] = {'N','a','m','e',0};
1962
1963         TRACE("(%s, %d, %p, %08x)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1964
1965         if (!pszProvName || pdwReserved)
1966         {
1967                 SetLastError(ERROR_INVALID_PARAMETER);
1968                 return FALSE;
1969         }
1970         if (dwProvType > MAXPROVTYPES)
1971         {
1972                 SetLastError(NTE_BAD_PROV_TYPE);
1973                 return FALSE;
1974         }
1975         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1976                         || dwFlags == CRYPT_DELETE_DEFAULT)
1977         {
1978                 SetLastError(NTE_BAD_FLAGS);
1979                 return FALSE;
1980         }
1981
1982         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
1983         {
1984                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1985                 return FALSE;
1986         }
1987         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1988                 keyname, &hTypeKey))
1989         {
1990                 CRYPT_Free(keyname);
1991                 SetLastError(NTE_BAD_PROVIDER);
1992                 return FALSE;
1993         }
1994         CRYPT_Free(keyname);
1995         
1996         if (dwFlags & CRYPT_DELETE_DEFAULT)
1997         {
1998                 RegDeleteValueW(hTypeKey, nameW);
1999         }
2000         else
2001         {
2002                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
2003                 {
2004                         RegCloseKey(hTypeKey);
2005                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2006                         return FALSE;
2007                 }
2008                 if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2009                         keyname, &hProvKey))
2010                 {
2011                         CRYPT_Free(keyname);
2012                         RegCloseKey(hTypeKey);
2013                         SetLastError(NTE_BAD_PROVIDER);
2014                         return FALSE;
2015                 }
2016                 CRYPT_Free(keyname);
2017                 
2018                 if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (const BYTE *)pszProvName,
2019                         (strlenW(pszProvName) + 1)*sizeof(WCHAR)))
2020                 {
2021                         RegCloseKey(hTypeKey);
2022                         RegCloseKey(hProvKey);
2023                         return FALSE;
2024                 }
2025                 
2026                 RegCloseKey(hProvKey);
2027         }
2028         RegCloseKey(hTypeKey);
2029
2030         return TRUE;
2031 }
2032
2033 /******************************************************************************
2034  * CryptSetProviderExA (ADVAPI32.@)
2035  *
2036  * See CryptSetProviderExW.
2037  */
2038 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2039 {
2040         BOOL ret = FALSE;
2041         PWSTR str = NULL;
2042
2043         TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
2044
2045         if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
2046         {
2047                 ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
2048                 CRYPT_Free(str);
2049         }
2050         return ret;
2051 }
2052
2053 /******************************************************************************
2054  * CryptSetProvParam (ADVAPI32.@)
2055  *
2056  * Customizes the operations of a CSP.
2057  *
2058  * PARAMS
2059  *  hProv   [I] Handle of a CSP.
2060  *  dwParam [I] See MSDN Doc.
2061  *  pbData  [I] Buffer that contains a value to set as a parameter.
2062  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
2063  *
2064  * RETURNS
2065  *  Success: TRUE
2066  *  Failure: FALSE
2067  */
2068 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
2069 {
2070         PCRYPTPROV prov = (PCRYPTPROV)hProv;
2071
2072         TRACE("(0x%lx, %d, %p, %08x)\n", hProv, dwParam, pbData, dwFlags);
2073
2074         if (!prov)
2075         {
2076                 SetLastError(ERROR_INVALID_HANDLE);
2077                 return FALSE;
2078         }
2079         if (prov->dwMagic != MAGIC_CRYPTPROV)
2080         {
2081                 SetLastError(ERROR_INVALID_PARAMETER);
2082                 return FALSE;
2083         }
2084         if (dwFlags & PP_USE_HARDWARE_RNG)
2085         {
2086                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
2087                 FIXME("\tLetting the CSP decide.\n");
2088         }
2089         if (dwFlags & PP_CLIENT_HWND)
2090         {
2091                 /* FIXME: Should verify the parameter */
2092                 if (pbData /* && IsWindow((HWND)pbData) */)
2093                 {
2094                         crypt_hWindow = (HWND)(pbData);
2095                         return TRUE;
2096                 } else {
2097                         SetLastError(ERROR_INVALID_PARAMETER);
2098                         return FALSE;
2099                 }
2100         }
2101         /* All other flags go to the CSP */
2102         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
2103 }
2104
2105 /******************************************************************************
2106  * CryptVerifySignatureW (ADVAPI32.@)
2107  *
2108  * Verifies the signature of a hash object.
2109  *
2110  * PARAMS
2111  *  hHash        [I] Handle of the hash object to verify.
2112  *  pbSignature  [I] Signature data to verify.
2113  *  dwSigLen     [I] Size of pbSignature.
2114  *  hPubKey      [I] Handle to the public key to authenticate signature.
2115  *  sDescription [I] Should be NULL.
2116  *  dwFlags      [I] See MSDN doc.
2117  *
2118  * RETURNS
2119  *  Success: TRUE
2120  *  Failure: FALSE
2121  * 
2122  * NOTES
2123  *  Because of security flaws sDescription should not be used and should thus be
2124  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
2125  *  Providers.
2126  */
2127 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
2128                 HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
2129 {
2130         PCRYPTHASH hash = (PCRYPTHASH)hHash;
2131         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
2132         PCRYPTPROV prov;
2133
2134         TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2135                         dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
2136
2137         if (!hash || !key ||
2138             !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
2139             !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2140         {
2141                 SetLastError(ERROR_INVALID_PARAMETER);
2142                 return FALSE;
2143         }
2144                 
2145         prov = hash->pProvider;
2146         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
2147                 key->hPrivate, sDescription, dwFlags);
2148 }
2149
2150 /******************************************************************************
2151  * CryptVerifySignatureA (ADVAPI32.@)
2152  *
2153  * See CryptVerifySignatureW.
2154  */
2155 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
2156                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
2157 {
2158         LPWSTR wsDescription;
2159         BOOL result;
2160
2161         TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2162                         dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
2163
2164         CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
2165         result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
2166         CRYPT_Free(wsDescription);
2167
2168         return result;
2169 }
2170
2171 /******************************************************************************
2172  * SystemFunction030   (ADVAPI32.@)
2173  *
2174  * Tests if two blocks of 16 bytes are equal
2175  *
2176  * PARAMS
2177  *  b1,b2   [I] block of 16 bytes
2178  *
2179  * RETURNS
2180  *  TRUE  if blocks are the same
2181  *  FALSE if blocks are different
2182  */
2183 BOOL WINAPI SystemFunction030(PVOID b1, PVOID b2)
2184 {
2185     return !memcmp(b1, b2, 0x10);
2186 }
2187
2188 /******************************************************************************
2189  * SystemFunction035   (ADVAPI32.@)
2190  *
2191  * Described here:
2192 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
2193  *
2194  * NOTES
2195  *  Stub, always return TRUE.
2196  */
2197 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
2198 {
2199     FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
2200     return TRUE;
2201 }
2202
2203 /******************************************************************************
2204  * SystemFunction036   (ADVAPI32.@)
2205  *
2206  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
2207  *
2208  * PARAMS
2209  *  pbBufer [O] Pointer to memory to receive random bytes.
2210  *  dwLen   [I] Number of random bytes to fetch.
2211  *
2212  * RETURNS
2213  *  Success: TRUE
2214  *  Failure: FALSE
2215  */
2216
2217 BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
2218 {
2219     int dev_random;
2220
2221     /* FIXME: /dev/urandom does not provide random numbers of a sufficient
2222      * quality for cryptographic applications. /dev/random is much better,  
2223      * but it blocks if the kernel has not yet collected enough entropy for
2224      * the request, which will suspend the calling thread for an indefinite
2225      * amount of time. */
2226     dev_random = open("/dev/urandom", O_RDONLY);
2227     if (dev_random != -1)
2228     {
2229         if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
2230         {
2231             close(dev_random);
2232             return TRUE;
2233         }
2234         close(dev_random);
2235     }
2236     SetLastError(NTE_FAIL);
2237     return FALSE;
2238 }    
2239     
2240 /*
2241    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
2242    in crypt32.dll.
2243  */
2244
2245 /******************************************************************************
2246  * SystemFunction040   (ADVAPI32.@)
2247  *
2248  * MSDN documents this function as RtlEncryptMemory.
2249  *
2250  * PARAMS
2251  *  memory [I/O] Pointer to memory to encrypt.
2252  *  length [I] Length of region to encrypt in bytes.
2253  *  flags  [I] Control whether other processes are able to decrypt the memory.
2254  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
2255  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
2256  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2257  *    
2258  * RETURNS
2259  *  Success: STATUS_SUCCESS
2260  *  Failure: NTSTATUS error code
2261  *
2262  * NOTES
2263  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2264  *  If flags are specified when encrypting, the same flag value must be given
2265  *  when decrypting the memory.
2266  */
2267 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2268 {
2269         FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
2270         return STATUS_SUCCESS;
2271 }
2272
2273 /******************************************************************************
2274  * SystemFunction041  (ADVAPI32.@)
2275  *
2276  * MSDN documents this function as RtlDecryptMemory.
2277  *
2278  * PARAMS
2279  *  memory [I/O] Pointer to memory to decrypt.
2280  *  length [I] Length of region to decrypt in bytes.
2281  *  flags  [I] Control whether other processes are able to decrypt the memory.
2282  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
2283  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
2284  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2285  *
2286  * RETURNS
2287  *  Success: STATUS_SUCCESS
2288  *  Failure: NTSTATUS error code
2289  *
2290  * NOTES
2291  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2292  *  If flags are specified when encrypting, the same flag value must be given
2293  *  when decrypting the memory.
2294  */
2295 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2296 {
2297         FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
2298         return STATUS_SUCCESS;
2299 }