ixed calculation of buffer size in CRYPT_ANSIToUnicode and
[wine] / dlls / advapi32 / crypt.c
1 /*
2  * Copyright 1999 Ian Schmidt
3  * Copyright 2001 Travis Michielsen
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 /***********************************************************************
21  *
22  *  TODO:
23  *  - Reference counting
24  *  - Thread-safing
25  *  - Signature checking
26  */
27
28 #include <time.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "crypt.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "wine/debug.h"
36 #include "winternl.h"
37 #include "ntstatus.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
40
41 HWND crypt_hWindow = 0;
42
43 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
44
45 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
46 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
47
48 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
49 {
50         PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
51         PSTR keyname;
52
53         keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
54         if (keyname)
55         {
56                 strcpy(keyname, KEYSTR);
57                 strcpy(keyname + strlen(KEYSTR), pProvName);
58         } else
59                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
60         return keyname;
61 }
62
63 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
64 {
65         PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
66         PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
67         PSTR keyname;
68         PSTR ptr;
69
70         keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
71         if (keyname)
72         {
73                 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
74                 ptr = keyname + strlen(keyname);
75                 *(--ptr) = (dwType % 10) + '0';
76                 *(--ptr) = ((dwType / 10) % 10) + '0';
77                 *(--ptr) = (dwType / 100) + '0';
78         } else
79                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
80         return keyname;
81 }
82
83 /* CRYPT_UnicodeTOANSI
84  * wstr - unicode string
85  * str - pointer to ANSI string
86  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
87  *
88  * returns TRUE if unsuccessfull, FALSE otherwise.
89  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
90  */
91 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
92 {
93         int count;
94
95         if (!wstr)
96         {
97                 *str = NULL;
98                 return TRUE;
99         }
100         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
101         if (strsize == -1)
102                 *str = CRYPT_Alloc(count * sizeof(CHAR));
103         else
104                 count = min( count, strsize );
105         if (*str)
106         {
107                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
108                 return TRUE;
109         }
110         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
111         return FALSE;
112 }
113
114 /* CRYPT_ANSITOUnicode
115  * str - ANSI string
116  * wstr - pointer to unicode string
117  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
118  */
119 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
120 {
121         int wcount;
122
123         if (!str)
124         {
125                 *wstr = NULL;
126                 return TRUE;
127         }
128         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
129         if (wstrsize == -1)
130                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
131         else
132                 wcount = min( wcount, wstrsize/sizeof(WCHAR) );
133         if (*wstr)
134         {
135                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
136                 return TRUE;
137         }
138         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
139         return FALSE;
140 }
141
142 /* These next 2 functions are used by the VTableProvStruc structure */
143 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
144 {
145         if (!lpszImage || !pData)
146         {
147                 SetLastError(ERROR_INVALID_PARAMETER);
148                 return FALSE;
149         }
150
151         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
152
153         return TRUE;
154 }
155
156 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
157 {
158         if (!phWnd)
159                 return FALSE;
160         *phWnd = crypt_hWindow;
161         return TRUE;
162 }
163
164 #define CRYPT_GetProvFunc(name) \
165         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
166 #define CRYPT_GetProvFuncOpt(name) \
167         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
168 PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
169 {
170         PCRYPTPROV provider;
171         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
172
173         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
174         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
175         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
176         if ( !(provider->hModule = LoadLibraryA(pImage)) )
177         {
178                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
179                 FIXME("Failed to load dll %s\n", debugstr_a(pImage));
180                 goto error;
181         }
182         provider->refcount = 1;
183
184         errorcode = NTE_PROVIDER_DLL_FAIL;
185         CRYPT_GetProvFunc(CPAcquireContext);
186         CRYPT_GetProvFunc(CPCreateHash);
187         CRYPT_GetProvFunc(CPDecrypt);
188         CRYPT_GetProvFunc(CPDeriveKey);
189         CRYPT_GetProvFunc(CPDestroyHash);
190         CRYPT_GetProvFunc(CPDestroyKey);
191         CRYPT_GetProvFuncOpt(CPDuplicateHash);
192         CRYPT_GetProvFuncOpt(CPDuplicateKey);
193         CRYPT_GetProvFunc(CPEncrypt);
194         CRYPT_GetProvFunc(CPExportKey);
195         CRYPT_GetProvFunc(CPGenKey);
196         CRYPT_GetProvFunc(CPGenRandom);
197         CRYPT_GetProvFunc(CPGetHashParam);
198         CRYPT_GetProvFunc(CPGetKeyParam);
199         CRYPT_GetProvFunc(CPGetProvParam);
200         CRYPT_GetProvFunc(CPGetUserKey);
201         CRYPT_GetProvFunc(CPHashData);
202         CRYPT_GetProvFunc(CPHashSessionKey);
203         CRYPT_GetProvFunc(CPImportKey);
204         CRYPT_GetProvFunc(CPReleaseContext);
205         CRYPT_GetProvFunc(CPSetHashParam);
206         CRYPT_GetProvFunc(CPSetKeyParam);
207         CRYPT_GetProvFunc(CPSetProvParam);
208         CRYPT_GetProvFunc(CPSignHash);
209         CRYPT_GetProvFunc(CPVerifySignature);
210
211         /* FIXME: Not sure what the pbContextInfo field is for.
212          *        Does it need memory allocation?
213          */
214         provider->pVTable->Version = 3;
215         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
216         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
217         provider->pVTable->dwProvType = 0;
218         provider->pVTable->pbContextInfo = NULL;
219         provider->pVTable->cbContextInfo = 0;
220         provider->pVTable->pszProvName = NULL;
221         return provider;
222
223 error:
224         SetLastError(errorcode);
225         if (provider)
226         {
227                 if (provider->hModule)
228                         FreeLibrary(provider->hModule);
229                 CRYPT_Free(provider->pVTable);
230                 CRYPT_Free(provider->pFuncs);
231                 CRYPT_Free(provider);
232         }
233         return NULL;
234 }
235 #undef CRYPT_GetProvFunc
236 #undef CRYPT_GetProvFuncOpt
237
238
239 /******************************************************************************
240  * CryptAcquireContextA (ADVAPI32.@)
241  * Acquire a crypto provider context handle.
242  *
243  * PARAMS
244  * phProv: Pointer to HCRYPTPROV for the output.
245  * pszContainer: Key Container Name
246  * pszProvider: Cryptographic Service Provider Name
247  * dwProvType: Crypto provider type to get a handle.
248  * dwFlags: flags for the operation
249  *
250  * RETURNS TRUE on success, FALSE on failure.
251  */
252 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
253                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
254 {
255         PCRYPTPROV pProv = NULL;
256         HKEY key;
257         PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
258         BYTE* signature;
259         DWORD keytype, type, len;
260         ULONG r;
261
262         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
263                 pszProvider, dwProvType, dwFlags);
264
265         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
266         {
267                 SetLastError(NTE_BAD_PROV_TYPE);
268                 return FALSE;
269         }
270         
271         if (!phProv)
272         {
273                 SetLastError(ERROR_INVALID_PARAMETER);
274                 return FALSE;
275         }
276
277         if (!pszProvider || !*pszProvider)
278         {
279                 /* No CSP name specified so try the user default CSP first
280                  * then try the machine default CSP
281                  */
282                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
283                         TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
284                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
285                         return FALSE;
286                 }
287                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
288                 {
289                         CRYPT_Free(keyname);
290                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
291                                 TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
292                                 RegCloseKey(key);
293                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
294                                 goto error;
295                         }
296                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
297                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
298                                 CRYPT_Free(keyname);
299                                 RegCloseKey(key);
300                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
301                                 goto error;
302                         }
303                 }
304                 CRYPT_Free(keyname);
305                 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
306                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
307                 {
308                         TRACE("error %ld reading size of 'Name' from registry\n", r );
309                         RegCloseKey(key);
310                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
311                         goto error;
312                 }
313                 if(!(provname = CRYPT_Alloc(len)))
314                 {
315                         RegCloseKey(key);
316                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
317                         goto error;
318                 }
319                 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
320                 if( r != ERROR_SUCCESS )
321                 {
322                         TRACE("error %ld reading 'Name' from registry\n", r );
323                         RegCloseKey(key);
324                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
325                         goto error;
326                 }
327                 RegCloseKey(key);
328         } else {
329                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
330                 {
331                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
332                         goto error;
333                 }
334                 strcpy(provname, pszProvider);
335         }
336
337         keyname = CRYPT_GetProvKeyName(provname);
338         r = RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key);
339         CRYPT_Free(keyname);
340         if (r != ERROR_SUCCESS)
341         {
342                 SetLastError(NTE_KEYSET_NOT_DEF);
343                 goto error;
344         }
345         len = sizeof(DWORD);
346         r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
347         if (r != ERROR_SUCCESS)
348         {
349                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
350                 goto error;
351         }
352         if (type != dwProvType)
353         {
354                 TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
355                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
356                 goto error;
357         }
358
359         r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
360         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
361         {
362                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
363                 RegCloseKey(key);
364                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
365                 goto error;
366         }
367         if (!(temp = CRYPT_Alloc(len)))
368         {
369                 RegCloseKey(key);
370                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
371                 goto error;
372         }
373         r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
374         if( r != ERROR_SUCCESS )
375         {
376                 TRACE("error %ld reading 'Image Path' from registry\n", r );
377                 RegCloseKey(key);
378                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
379                 goto error;
380         }
381
382         r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
383         if ( r == ERROR_SUCCESS && keytype == REG_BINARY )
384         {
385                 if (!(signature = CRYPT_Alloc(len)))
386                 {
387                         RegCloseKey(key);
388                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
389                         goto error;
390                 }
391                 r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
392                 if ( r != ERROR_SUCCESS )
393                 {
394                         TRACE("error %ld reading 'Signature'\n", r );
395                         CRYPT_Free(signature);
396                         RegCloseKey(key);
397                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
398                         goto error;
399                 }
400         }
401         else
402         {
403                 r = RegQueryValueExA(key, "SigInFile", NULL, &keytype, NULL, &len);
404                 if (r != ERROR_SUCCESS)
405                 {
406                         TRACE("error %ld reading size of 'SigInFile'\n", r );
407                         RegCloseKey(key);
408                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
409                         goto error;
410                 }
411                 else
412                 {
413                         /* FIXME: The presence of the SigInFile value indicates the
414                          * provider's signature is in its resources, so need to read it.
415                          * But since CRYPT_VerifyImage is stubbed, provide any old thing
416                          * for now.
417                          */
418                         if (!(signature = CRYPT_Alloc(1)))
419                         {
420                                 RegCloseKey(key);
421                                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
422                                 goto error;
423                         }
424                 }
425         }
426         RegCloseKey(key);
427         len = ExpandEnvironmentStringsA(temp, NULL, 0);
428         if ( !(imagepath = CRYPT_Alloc(len)) )
429         {
430                 CRYPT_Free(signature);
431                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
432                 goto error;
433         }
434         if (!ExpandEnvironmentStringsA(temp, imagepath, len))
435         {
436                 CRYPT_Free(signature);
437                 /* ExpandEnvironmentStrings will call SetLastError */
438                 goto error;
439         }
440
441         if (!CRYPT_VerifyImage(imagepath, signature))
442         {
443                 CRYPT_Free(signature);
444                 SetLastError(NTE_SIGNATURE_FILE_BAD);
445                 goto error;
446         }
447         pProv = CRYPT_LoadProvider(imagepath);
448         CRYPT_Free(signature);
449         if (!pProv) {
450                 /* CRYPT_LoadProvider calls SetLastError */
451                 goto error;
452         }
453         pProv->pVTable->dwProvType = dwProvType;
454         pProv->pVTable->pszProvName = provname;
455         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
456         {
457                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
458                  *       and thus, the CryptReleaseContext function need not be called afterwards.
459                  *       Therefore, we must clean up everything now.
460                  */
461                 if (dwFlags & CRYPT_DELETEKEYSET)
462                 {
463                         FreeLibrary(pProv->hModule);
464                         CRYPT_Free(provname);
465                         CRYPT_Free(pProv->pFuncs);
466                         CRYPT_Free(pProv);
467                 } else {
468                         *phProv = (HCRYPTPROV)pProv;
469                 }
470                 CRYPT_Free(temp);
471                 CRYPT_Free(imagepath);
472                 return TRUE;
473         }
474         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
475 error:
476         if (pProv)
477         {
478                 if (pProv->hModule)
479                         FreeLibrary(pProv->hModule);
480                 if (pProv->pVTable)
481                         CRYPT_Free(pProv->pVTable);
482                 if (pProv->pFuncs)
483                         CRYPT_Free(pProv->pFuncs);
484                 CRYPT_Free(pProv);
485         }
486         if (provname)
487                 CRYPT_Free(provname);
488         if (temp)
489                 CRYPT_Free(temp);
490         if (imagepath)
491                 CRYPT_Free(imagepath);
492         return FALSE;
493 }
494
495 /******************************************************************************
496  * CryptAcquireContextW (ADVAPI32.@)
497  *
498  * see CryptAcquireContextA
499  */
500 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
501                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
502 {
503         PSTR pProvider = NULL, pContainer = NULL;
504         BOOL ret = FALSE;
505
506         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
507                 debugstr_w(pszProvider), dwProvType, dwFlags);
508
509         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
510                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
511         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
512         {
513                 CRYPT_Free(pContainer);
514                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
515         }
516
517         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
518
519         if (pContainer)
520                 CRYPT_Free(pContainer);
521         if (pProvider)
522                 CRYPT_Free(pProvider);
523
524         return ret;
525 }
526
527 /******************************************************************************
528  * CryptContextAddRef (ADVAPI32.@)
529  *
530  * Increases reference count of a cryptographic service provider handle
531  * by one.
532  *
533  * PARAMS
534  *  hProv       [I] Handle to the CSP whose reference is being incremented.
535  *  pdwReserved [IN] Reserved for future use and must be NULL.
536  *  dwFlags     [I] Reserved for future use and must be NULL.
537  *
538  * RETURNS
539  *  Success: TRUE
540  *  Failure: FALSE
541  */
542 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
543 {
544         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
545
546         TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
547
548         if (!pProv)
549         {
550                 SetLastError(NTE_BAD_UID);
551                 return FALSE;
552         }
553
554         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, %08ld)\n", hProv, dwFlags);
577
578         if (!pProv)
579         {
580                 SetLastError(NTE_BAD_UID);
581                 return FALSE;
582         }
583
584         pProv->refcount--;
585         if (pProv->refcount <= 0) 
586         {
587                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
588                 FreeLibrary(pProv->hModule);
589 #if 0
590                 CRYPT_Free(pProv->pVTable->pContextInfo);
591 #endif
592                 CRYPT_Free(pProv->pVTable->pszProvName);
593                 CRYPT_Free(pProv->pVTable);
594                 CRYPT_Free(pProv->pFuncs);
595                 CRYPT_Free(pProv);
596         }
597         return ret;
598 }
599
600 /******************************************************************************
601  * CryptGenRandom (ADVAPI32.@)
602  *
603  * Fills a buffer with cryptographically random bytes.
604  *
605  * PARAMS
606  *  hProv    [I] Handle of a CSP.
607  *  dwLen    [I] Number of bytes to generate.
608  *  pbBuffer [I/O] Buffer to contain random bytes.
609  *
610  * RETURNS
611  *  Success: TRUE
612  *  Failure: FALSE
613  *
614  * NOTES
615  *  pdBuffer must be at least dwLen bytes long.
616  */
617 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
618 {
619         PCRYPTPROV prov = (PCRYPTPROV)hProv;
620
621         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
622
623         if (!hProv)
624                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
625
626         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
627 }
628
629 /******************************************************************************
630  * CryptCreateHash (ADVAPI32.@)
631  *
632  * Initiates the hashing of a stream of data.
633  *
634  * PARAMS
635  *  hProv   [I] Handle of a CSP.
636  *  Algid   [I] Identifies the hash algorithm to use.
637  *  hKey    [I] Key for the hash (if required).
638  *  dwFlags [I] Reserved for future use and must be NULL.
639  *  phHash  [O] Address of the future handle to the new hash object.
640  *
641  * RETURNS
642  *  Success: TRUE
643  *  Failure: FALSE
644  *
645  * NOTES
646  *  If the algorithm is a keyed hash, hKey is the key.
647  */
648 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
649                 DWORD dwFlags, HCRYPTHASH *phHash)
650 {
651         PCRYPTPROV prov = (PCRYPTPROV)hProv;
652         PCRYPTKEY key = (PCRYPTKEY)hKey;
653         PCRYPTHASH hash;
654
655         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
656
657         if (!prov)
658                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
659         if (!phHash)
660                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
661         if (dwFlags)
662                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
663         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
664                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
665
666         hash->pProvider = prov;
667
668         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
669                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
670         {
671             *phHash = (HCRYPTHASH)hash;
672             return TRUE;
673         }
674
675         /* CSP error! */
676         CRYPT_Free(hash);
677         *phHash = 0;
678         return FALSE;
679 }
680
681 /******************************************************************************
682  * CryptDecrypt (ADVAPI32.@)
683  *
684  * Decrypts data encrypted by CryptEncrypt.
685  *
686  * PARAMS
687  *  hKey       [I] Handle to the decryption key.
688  *  hHash      [I] Handle to a hash object.
689  *  Final      [I] TRUE if this is the last section to be decrypted.
690  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
691  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
692  *                   data on return
693  *  pdwDataLen [I/O] Length of pbData before and after the call.
694  *
695  *  RETURNS
696  *   Success: TRUE
697  *   Failure: FALSE
698  */
699 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
700                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
701 {
702         PCRYPTPROV prov;
703         PCRYPTKEY key = (PCRYPTKEY)hKey;
704         PCRYPTHASH hash = (PCRYPTHASH)hHash;
705
706         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
707
708         if (!key || !pbData || !pdwDataLen)
709                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
710
711         prov = key->pProvider;
712         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
713                         Final, dwFlags, pbData, pdwDataLen);
714 }
715
716 /******************************************************************************
717  * CryptDeriveKey (ADVAPI32.@)
718  *
719  * Generates session keys derived from a base data value.
720  *
721  * PARAMS
722  *  hProv     [I] Handle to a CSP.
723  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
724  *  hBaseData [I] Handle to a hash object.
725  *  dwFlags   [I] Type of key to generate.
726  *  phKey     [I/O] Address of the newly generated key.
727  *
728  * RETURNS
729  *  Success: TRUE
730  *  Failure: FALSE
731  */
732 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
733                 DWORD dwFlags, HCRYPTKEY *phKey)
734 {
735         PCRYPTPROV prov = (PCRYPTPROV)hProv;
736         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
737         PCRYPTKEY key;
738
739         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
740
741         if (!prov || !hash)
742                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
743         if (!phKey)
744                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
745         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
746                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
747
748         key->pProvider = prov;
749         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
750         {
751             *phKey = (HCRYPTKEY)key;
752             return TRUE;
753         }
754
755         /* CSP error! */
756         CRYPT_Free(key);
757         *phKey = 0;
758         return FALSE;
759 }
760
761 /******************************************************************************
762  * CryptDestroyHash (ADVAPI32.@)
763  *
764  * Destroys the hash object referenced by hHash.
765  *
766  * PARAMS
767  *  hHash [I] Handle of the hash object to be destroyed.
768  *
769  * RETURNS
770  *  Success: TRUE
771  *  Failure: FALSE
772  */
773 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
774 {
775         PCRYPTHASH hash = (PCRYPTHASH)hHash;
776         PCRYPTPROV prov;
777         BOOL ret;
778
779         TRACE("(0x%lx)\n", hHash);
780
781         if (!hash)
782                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
783
784         prov = hash->pProvider;
785         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
786         CRYPT_Free(hash);
787         return ret;
788 }
789
790 /******************************************************************************
791  * CryptDestroyKey (ADVAPI32.@)
792  *
793  * Releases the handle referenced by hKey.
794  *
795  * PARAMS
796  *  hKey [I] Handle of the key to be destroyed.
797  *
798  * RETURNS
799  *  Success: TRUE
800  *  Failure: FALSE
801  */
802 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
803 {
804         PCRYPTKEY key = (PCRYPTKEY)hKey;
805         PCRYPTPROV prov;
806         BOOL ret;
807
808         TRACE("(0x%lx)\n", hKey);
809
810         if (!key)
811                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
812
813         prov = key->pProvider;
814         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
815         CRYPT_Free(key);
816         return ret;
817 }
818
819 /******************************************************************************
820  * CryptDuplicateHash (ADVAPI32.@)
821  *
822  * Duplicates a hash.
823  *
824  * PARAMS
825  *  hHash       [I] Handle to the hash to be copied.
826  *  pdwReserved [I] Reserved for future use and must be zero.
827  *  dwFlags     [I] Reserved for future use and must be zero.
828  *  phHash      [O] Address of the handle to receive the copy.
829  *
830  * RETURNS
831  *  Success: TRUE
832  *  Failure: FALSE
833  */
834 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
835                 DWORD dwFlags, HCRYPTHASH *phHash)
836 {
837         PCRYPTPROV prov;
838         PCRYPTHASH orghash, newhash;
839
840         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
841
842         orghash = (PCRYPTHASH)hHash;
843         if (!orghash || pdwReserved || !phHash)
844                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
845
846         prov = orghash->pProvider;
847         if (!prov->pFuncs->pCPDuplicateHash)
848                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
849
850         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
851                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
852
853         newhash->pProvider = prov;
854         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
855         {
856                 *phHash = (HCRYPTHASH)newhash;
857                 return TRUE;
858         }
859         CRYPT_Free(newhash);
860         return FALSE;
861 }
862
863 /******************************************************************************
864  * CryptDuplicateKey (ADVAPI32.@)
865  *
866  * Duplicate a key and the key's state.
867  *
868  * PARAMS
869  *  hKey        [I] Handle of the key to copy.
870  *  pdwReserved [I] Reserved for future use and must be NULL.
871  *  dwFlags     [I] Reserved for future use and must be zero.
872  *  phKey       [I] Address of the handle to the duplicated key.
873  *
874  * RETURNS
875  *  Success: TRUE
876  *  Failure: FALSE
877  */
878 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
879 {
880         PCRYPTPROV prov;
881         PCRYPTKEY orgkey, newkey;
882
883         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
884
885         orgkey = (PCRYPTKEY)hKey;
886         if (!orgkey || pdwReserved || !phKey)
887                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
888
889         prov = orgkey->pProvider;
890         if (!prov->pFuncs->pCPDuplicateKey)
891                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
892
893         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
894                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
895
896         newkey->pProvider = prov;
897         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
898         {
899                 *phKey = (HCRYPTKEY)newkey;
900                 return TRUE;
901         }
902         CRYPT_Free(newkey);
903         return FALSE;
904 }
905
906 /******************************************************************************
907  * CryptEncrypt (ADVAPI32.@)
908  *
909  * Encrypts data.
910  *
911  * PARAMS
912  *  hKey       [I] Handle to the enryption key.
913  *  hHash      [I] Handle to a hash object.
914  *  Final      [I] TRUE if this is the last section to encrypt.
915  *  dwFlags    [I] Can be CRYPT_OAEP.
916  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
917  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
918  *                   encrypted data after call.
919  *  dwBufLen   [I] Length of the input pbData buffer.
920  *
921  * RETURNS
922  *  Success: TRUE
923  *  Failure: FALSE
924  *
925  *  NOTES
926  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
927  *   required for the returned data in pdwDataLen.
928  */
929 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
930                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
931 {
932         PCRYPTPROV prov;
933         PCRYPTKEY key = (PCRYPTKEY)hKey;
934         PCRYPTHASH hash = (PCRYPTHASH)hHash;
935
936         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
937
938         if (!key || !pdwDataLen)
939                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
940
941         prov = key->pProvider;
942         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
943                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
944 }
945
946 /******************************************************************************
947  * CryptEnumProvidersW (ADVAPI32.@)
948  *
949  * Returns the next availabe CSP.
950  *
951  * PARAMS
952  *  dwIndex     [I] Index of the next provider to be enumerated.
953  *  pdwReserved [I] Reserved for future use and must be NULL.
954  *  dwFlags     [I] Reserved for future use and must be zero.
955  *  pdwProvType [O] DWORD designating the type of the provider.
956  *  pszProvName [O] Buffer that receives data from the provider.
957  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
958  *                    of bytes stored in the buffer on return.
959  *
960  *  RETURNS
961  *   Success: TRUE
962  *   Failure: FALSE
963  *
964  *  NOTES
965  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
966  *   for memory allocation purposes.
967  */
968 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
969                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
970 {
971         HKEY hKey;
972         
973         static const WCHAR providerW[] = {
974                 'S','o','f','t','w','a','r','e','\\',
975                 'M','i','c','r','o','s','o','f','t','\\',
976                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
977                 'D','e','f','a','u','l','t','s','\\',
978                 'P','r','o','v','i','d','e','r',0
979         };
980         
981         static const WCHAR typeW[] = {'T','y','p','e',0};
982
983         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
984                         pdwProvType, pszProvName, pcbProvName);
985
986         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
987         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
988
989         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
990                 CRYPT_ReturnLastError(NTE_FAIL);
991
992         if (!pszProvName)
993         {
994                 DWORD numkeys;
995                 WCHAR *provNameW;
996                 
997                 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
998                                  NULL, NULL, NULL, NULL, NULL, NULL);
999                 
1000                 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1001                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1002                 
1003                 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1004                 (*pcbProvName)++;
1005                 *pcbProvName *= sizeof(WCHAR);
1006                 
1007                 CRYPT_Free(provNameW);
1008                 
1009                 if (dwIndex >= numkeys)
1010                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1011         } else {
1012                 DWORD size = sizeof(DWORD);
1013                 DWORD result;
1014                 HKEY subkey;
1015                 
1016                 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1017                 if (result)
1018                         CRYPT_ReturnLastError(result);
1019                 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1020                         return FALSE;
1021                 if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1022                         return FALSE;
1023                 RegCloseKey(subkey);
1024         }
1025         RegCloseKey(hKey);
1026         return TRUE;
1027 }
1028
1029 /******************************************************************************
1030  * CryptEnumProvidersA (ADVAPI32.@)
1031  *
1032  * see CryptEnumProvidersW
1033  */
1034 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1035                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1036 {
1037         PWSTR str = NULL;
1038         DWORD strlen;
1039         BOOL ret; /* = FALSE; */
1040
1041         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1042                         pdwProvType, pszProvName, pcbProvName);
1043
1044         strlen = *pcbProvName * sizeof(WCHAR);
1045         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1046                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1047         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1048         if (str)
1049         {
1050                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1051                 CRYPT_Free(str);
1052         }
1053         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1054         return ret;
1055 }
1056
1057 /******************************************************************************
1058  * CryptEnumProviderTypesA (ADVAPI32i.@)
1059  *
1060  * Retrieves the next type of CSP supported.
1061  *
1062  * PARAMS
1063  *  dwIndex     [I] Index of the next provider to be enumerated.
1064  *  pdwReserved [I] Reserved for future use and must be NULL.
1065  *  dwFlags     [I] Reserved for future use and must be zero.
1066  *  pdwProvType [O] DWORD designating the type of the provider.
1067  *  pszTypeName [O] Buffer that receives data from the provider type.
1068  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1069  *                    of bytes stored in the buffer on return.
1070  *
1071  *  RETURNS
1072  *   Success: TRUE
1073  *   Failure: FALSE
1074  *
1075  *  NOTES
1076  *   If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name
1077  *   for memory allocation purposes.
1078  */
1079 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1080                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1081 {
1082         HKEY hKey, hSubkey;
1083         DWORD keylen, numkeys, dwType;
1084         PSTR keyname, ch;
1085         DWORD result;
1086
1087         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
1088                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1089
1090         if (pdwReserved || !pdwProvType || !pcbTypeName)
1091                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1092         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1093
1094         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
1095                 return FALSE;
1096
1097         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1098         if (dwIndex >= numkeys)
1099                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1100         keylen++;
1101         if ( !(keyname = CRYPT_Alloc(keylen)) )
1102                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1103         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
1104                 CRYPT_Free(keyname);
1105                 return FALSE;
1106         }
1107         RegOpenKeyA(hKey, keyname, &hSubkey);
1108         ch = keyname + strlen(keyname);
1109         /* Convert "Type 000" to 0, etc/ */
1110         *pdwProvType = *(--ch) - '0';
1111         *pdwProvType += (*(--ch) - '0') * 10;
1112         *pdwProvType += (*(--ch) - '0') * 100;
1113         CRYPT_Free(keyname);
1114         
1115         result = RegQueryValueExA(hSubkey, "TypeName", NULL, &dwType, pszTypeName, pcbTypeName);
1116         if (result)
1117                 CRYPT_ReturnLastError(result);
1118
1119         RegCloseKey(hSubkey);
1120         RegCloseKey(hKey);
1121         return TRUE;
1122 }
1123
1124 /******************************************************************************
1125  * CryptEnumProviderTypesW (ADVAPI32.@)
1126  *
1127  * see CryptEnumProviderTypesA
1128  */
1129 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1130                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1131 {
1132         PSTR str = NULL;
1133         DWORD strlen;
1134         BOOL ret;
1135
1136         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1137                         pdwProvType, pszTypeName, pcbTypeName);
1138         strlen = *pcbTypeName / sizeof(WCHAR);
1139         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1140                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1141         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1142         if (str)
1143         {
1144                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
1145                 CRYPT_Free(str);
1146         }
1147         *pcbTypeName = strlen * sizeof(WCHAR);
1148         return ret;
1149 }
1150
1151 /******************************************************************************
1152  * CryptExportKey (ADVAPI32.@)
1153  * 
1154  * Exports a cryptographic key from a CSP.
1155  *
1156  * PARAMS
1157  *  hKey       [I] Handle to the key to export.
1158  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1159  *  dwBlobType [I] Type of BLOB to be exported.
1160  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1161  *  pbData     [O] Buffer to receive BLOB data.
1162  *  pdwDataLen [I/O] Specifies the size of pbData.
1163  *
1164  * RETURNS
1165  *  Success: TRUE
1166  *  Failure: FALSE
1167  *
1168  * NOTES
1169  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1170  *  buffer needed to hold the BLOB.
1171  */
1172 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1173                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1174 {
1175         PCRYPTPROV prov;
1176         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1177
1178         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1179
1180         if (!key || !pdwDataLen)
1181                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1182
1183         prov = key->pProvider;
1184         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1185                         dwBlobType, dwFlags, pbData, pdwDataLen);
1186 }
1187
1188 /******************************************************************************
1189  * CryptGenKey (ADVAPI32.@)
1190  *
1191  * Generates a random cryptographic session key or a pub/priv key pair.
1192  *
1193  * PARAMS
1194  *  hProv   [I] Handle to a CSP.
1195  *  Algid   [I] Algorithm to use to make key.
1196  *  dwFlags [I] Specifies type of key to make.
1197  *  phKey   [I] Address of the handle to which the new key is copied.
1198  *
1199  *  RETURNS
1200  *   Success: TRUE
1201  *   Failure: FALSE
1202  */
1203 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1204 {
1205         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1206         PCRYPTKEY key;
1207
1208         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
1209
1210         if (!prov)
1211                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1212         if (!phKey)
1213                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1214         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1215                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1216
1217         key->pProvider = prov;
1218
1219         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1220         {
1221             *phKey = (HCRYPTKEY)key;
1222             return TRUE;
1223         }
1224
1225         /* CSP error! */
1226         CRYPT_Free(key);
1227         return FALSE;
1228 }
1229
1230 /******************************************************************************
1231  * CryptGetDefaultProviderA (ADVAPI32.@)
1232  *
1233  * Finds the default CSP of a certain provider type.
1234  *
1235  * PARAMS
1236  *  dwProvType  [I] Provider type to look for.
1237  *  pdwReserved [I] Reserved for future use and must be NULL.
1238  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1239  *  pszProvName [O] Name of the default CSP.
1240  *  pcbProvName [I/O] Size of pszProvName
1241  *
1242  * RETURNS
1243  *  Success: TRUE
1244  *  Failure: FALSE
1245  *
1246  * NOTES
1247  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1248  *  memory allocation purposes on return.
1249  */
1250 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1251                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1252 {
1253         HKEY hKey;
1254         PSTR keyname;
1255         DWORD result;
1256
1257         if (pdwReserved || !pcbProvName)
1258                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1259         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1260                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1261         if (dwProvType > 999)
1262                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1263         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1264                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1265         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1266         {
1267                 CRYPT_Free(keyname);
1268                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
1269         }
1270         CRYPT_Free(keyname);
1271         
1272         result = RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName); 
1273         if (result)
1274         {
1275                 if (result != ERROR_MORE_DATA)
1276                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1277                 else
1278                         SetLastError(result);
1279                 
1280                 return FALSE;
1281         }
1282         
1283         RegCloseKey(hKey);
1284         return TRUE;
1285 }
1286
1287 /******************************************************************************
1288  * CryptGetDefaultProviderW (ADVAPI32.@)
1289  *
1290  * see CryptGetDefaultProviderA
1291  */
1292 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1293                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1294 {
1295         PSTR str = NULL;
1296         DWORD strlen;
1297         BOOL ret = FALSE;
1298
1299         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1300
1301         strlen = *pcbProvName / sizeof(WCHAR);
1302         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1303                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1304         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
1305         if (str)
1306         {
1307                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
1308                 CRYPT_Free(str);
1309         }
1310         *pcbProvName = strlen * sizeof(WCHAR);
1311         return ret;
1312 }
1313
1314 /******************************************************************************
1315  * CryptGetHashParam (ADVAPI32.@)
1316  *
1317  * Retrieves data that controls the operations of a hash object.
1318  *
1319  * PARAMS
1320  *  hHash      [I] Handle of the hash object to question.
1321  *  dwParam    [I] Query type.
1322  *  pbData     [O] Buffer that receives the value data.
1323  *  pdwDataLen [I/O] Size of the pbData buffer.
1324  *  dwFlags    [I] Reserved for future use and must be zero.
1325  *
1326  * RETURNS
1327  *  Success: TRUE
1328  *  Failure: FALSE
1329  *
1330  * NOTES
1331  *  If pbData is NULL, pdwDataLen will contain the length required.
1332  */
1333 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1334                 DWORD *pdwDataLen, DWORD dwFlags)
1335 {
1336         PCRYPTPROV prov;
1337         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1338
1339         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1340
1341         if (!hash || !pdwDataLen)
1342                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1343
1344         prov = hash->pProvider;
1345         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1346                         pbData, pdwDataLen, dwFlags);
1347 }
1348
1349 /******************************************************************************
1350  * CryptGetKeyParam (ADVAPI32.@)
1351  *
1352  * Retrieves data that controls the operations of a key.
1353  *
1354  * PARAMS
1355  *  hKey       [I] Handle to they key in question.
1356  *  dwParam    [I] Specifies query type.
1357  *  pbData     [O] Sequence of bytes to receive data.
1358  *  pdwDataLen [I/O] Size of pbData.
1359  *  dwFlags    [I] Reserved for future use and must be zero.
1360  *
1361  * RETURNS
1362  *  Success: TRUE
1363  *  Failure: FALSE
1364  *
1365  * NOTES
1366  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1367  */
1368 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1369                 DWORD *pdwDataLen, DWORD dwFlags)
1370 {
1371         PCRYPTPROV prov;
1372         PCRYPTKEY key = (PCRYPTKEY)hKey;
1373
1374         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1375
1376         if (!key || !pdwDataLen)
1377                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1378
1379         prov = key->pProvider;
1380         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1381                         pbData, pdwDataLen, dwFlags);
1382 }
1383
1384 /******************************************************************************
1385  * CryptGetProvParam (ADVAPI32.@)
1386  *
1387  * Retrieves parameters that control the operations of a CSP.
1388  *
1389  * PARAMS
1390  *  hProv      [I] Handle of the CSP in question.
1391  *  dwParam    [I] Specifies query type.
1392  *  pbData     [O] Buffer to receive the data.
1393  *  pdwDataLen [I/O] Size of pbData.
1394  *  dwFlags    [I] see MSDN Docs.
1395  *
1396  * RETURNS
1397  *  Success: TRUE
1398  *  Failure: FALSE
1399  *
1400  * NOTES
1401  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1402  */
1403 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1404                 DWORD *pdwDataLen, DWORD dwFlags)
1405 {
1406         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1407
1408         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1409
1410         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1411 }
1412
1413 /******************************************************************************
1414  * CryptGetUserKey (ADVAPI32.@)
1415  *
1416  * Gets a handle of one of a user's two public/private key pairs.
1417  *
1418  * PARAMS
1419  *  hProv     [I] Handle of a CSP.
1420  *  dwKeySpec [I] Private key to use.
1421  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1422  *
1423  * RETURNS
1424  *  Success: TRUE
1425  *  Failure: FALSE
1426  */
1427 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1428 {
1429         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1430         PCRYPTKEY key;
1431
1432         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1433
1434         if (!prov)
1435                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1436         if (!phUserKey)
1437                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1438         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1439                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1440
1441         key->pProvider = prov;
1442
1443         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1444         {
1445             *phUserKey = (HCRYPTKEY)key;
1446             return TRUE;
1447         }
1448
1449         /* CSP Error */
1450         CRYPT_Free(key);
1451         *phUserKey = 0;
1452         return FALSE;
1453 }
1454
1455 /******************************************************************************
1456  * CryptHashData (ADVAPI32.@)
1457  *
1458  * Adds data to a hash object.
1459  *
1460  * PARAMS
1461  *  hHash     [I] Handle of the hash object.
1462  *  pbData    [I] Buffer of data to be hashed.
1463  *  dwDataLen [I] Number of bytes to add.
1464  *  dwFlags   [I] Can be CRYPT_USERDATA
1465  *
1466  * RETURNS
1467  *  Success: TRUE
1468  *  Failure: FALSE
1469  */
1470 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1471 {
1472         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1473         PCRYPTPROV prov;
1474
1475         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1476
1477         if (!hash)
1478                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1479         if (!pbData || !dwDataLen)
1480                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1481
1482         prov = hash->pProvider;
1483         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1484 }
1485
1486 /******************************************************************************
1487  * CryptHashSessionKey (ADVAPI32.@)
1488  *
1489  * PARAMS 
1490  *  hHash   [I] Handle to the hash object.
1491  *  hKey    [I] Handle to the key to be hashed.
1492  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1493  *
1494  * RETURNS
1495  *  Success: TRUE
1496  *  Failure: FALSE
1497  */
1498 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1499 {
1500         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1501         PCRYPTKEY key = (PCRYPTKEY)hKey;
1502         PCRYPTPROV prov;
1503
1504         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1505
1506         if (!hash || !key)
1507                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1508
1509         prov = hash->pProvider;
1510         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1511 }
1512
1513 /******************************************************************************
1514  * CryptImportKey (ADVAPI32.@)
1515  *
1516  * PARAMS
1517  *  hProv     [I] Handle of a CSP.
1518  *  pbData    [I] Contains the key to be imported.
1519  *  dwDataLen [I] Length of the key.
1520  *  hPubKey   [I] Cryptographic key that decrypts pdData
1521  *  dwFlags   [I] Used only with a public/private key pair.
1522  *  phKey     [O] Imported key.
1523  *
1524  * RETURNS
1525  *  Success: TRUE
1526  *  Failure: FALSE
1527  */
1528 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1529                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1530 {
1531         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1532         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1533
1534         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1535
1536         if (!prov || !pbData || !dwDataLen || !phKey)
1537                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1538
1539         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1540                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1541
1542         importkey->pProvider = prov;
1543         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1544                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1545         {
1546                 *phKey = (HCRYPTKEY)importkey;
1547                 return TRUE;
1548         }
1549
1550         CRYPT_Free(importkey);
1551         return FALSE;
1552 }
1553
1554 /******************************************************************************
1555  * CryptSignHashA
1556  *
1557  * Note: Since the sDesciption (string) is supposed to be NULL and
1558  *      is only retained for compatibility no string conversions are required
1559  *      and only one implementation is required for both ANSI and Unicode.
1560  *      We still need to export both:
1561  *
1562  * CryptSignHashA (ADVAPI32.@)
1563  * CryptSignHashW (ADVAPI32.@)
1564  *
1565  * Signs data.
1566  *
1567  * PARAMS
1568  *  hHash        [I] Handle of the hash object to be signed.
1569  *  dwKeySpec    [I] Private key to use.
1570  *  sDescription [I] Must be NULL.
1571  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1572  *  pbSignature  [O] Buffer of the signature data.
1573  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1574  *
1575  * RETURNS
1576  *  Success: TRUE
1577  *  Failure: FALSE
1578  */
1579 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1580                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1581 {
1582         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1583         PCRYPTPROV prov;
1584
1585         TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1586         if (sDescription)
1587                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1588
1589         if (!hash)
1590                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1591         if (!pdwSigLen)
1592                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1593
1594         prov = hash->pProvider;
1595         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1596                 dwFlags, pbSignature, pdwSigLen);
1597 }
1598
1599 /******************************************************************************
1600  * CryptSetHashParam (ADVAPI32.@)
1601  *
1602  * Customizes the operations of a hash object.
1603  *
1604  * PARAMS
1605  *  hHash   [I] Handle of the hash object to set parameters.
1606  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1607  *  pbData  [I] Value data buffer.
1608  *  dwFlags [I] Reserved for future use and must be zero.
1609  *
1610  * RETURNS
1611  *  Success: TRUE
1612  *  Failure: FALSE
1613  */
1614 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1615 {
1616         PCRYPTPROV prov;
1617         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1618
1619         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1620
1621         if (!hash || !pbData)
1622                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1623
1624         prov = hash->pProvider;
1625         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1626                         dwParam, pbData, dwFlags);
1627 }
1628
1629 /******************************************************************************
1630  * CryptSetKeyParam (ADVAPI32.@)
1631  *
1632  * Customizes a session key's operations.
1633  *
1634  * PARAMS
1635  *  hKey    [I] Handle to the key to set values.
1636  *  dwParam [I] See MSDN Doc.
1637  *  pbData  [I] Buffer of values to set.
1638  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1639  *
1640  * RETURNS
1641  *  Success: TRUE
1642  *  Failure: FALSE
1643  */
1644 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1645 {
1646         PCRYPTPROV prov;
1647         PCRYPTKEY key = (PCRYPTKEY)hKey;
1648
1649         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1650
1651         if (!key || !pbData)
1652                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1653
1654         prov = key->pProvider;
1655         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1656                         dwParam, pbData, dwFlags);
1657 }
1658
1659 /******************************************************************************
1660  * CryptSetProviderA (ADVAPI32.@)
1661  *
1662  * Specifies the current user's default CSP.
1663  *
1664  * PARAMS
1665  *  pszProvName [I] Name of the new default CSP.
1666  *  dwProvType  [I] Provider type of the CSP.
1667  *
1668  * RETURNS
1669  *  Success: TRUE
1670  *  Failure: FALSE
1671  */
1672 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1673 {
1674         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1675         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1676 }
1677
1678 /******************************************************************************
1679  * CryptSetProviderW (ADVAPI32.@)
1680  *
1681  * See CryptSetProviderA
1682  */
1683 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1684 {
1685         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1686         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1687 }
1688
1689 /******************************************************************************
1690  * CryptSetProviderExA (ADVAPI32.@)
1691  *
1692  * Specifies the default CSP.
1693  *
1694  * PARAMS
1695  *  pszProvName [I] Name of the new default CSP.
1696  *  dwProvType  [I] Provider type of the CSP.
1697  *  pdwReserved [I] Reserved for future use and must be NULL.
1698  *  dwFlags     [I] See MSDN Doc.
1699  *
1700  * RETURNS
1701  *  Success: TRUE
1702  *  Failure: FALSE
1703  */
1704 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1705 {
1706         HKEY hProvKey, hTypeKey;
1707         PSTR keyname;
1708
1709         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1710
1711         if (!pszProvName || pdwReserved)
1712                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1713         if (dwProvType > MAXPROVTYPES)
1714                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1715         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1716                         || dwFlags == CRYPT_DELETE_DEFAULT)
1717                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1718         
1719         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
1720                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1721         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1722                 keyname, &hTypeKey))
1723         {
1724                 CRYPT_Free(keyname);
1725                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1726         }
1727         CRYPT_Free(keyname);
1728         
1729         if (dwFlags & CRYPT_DELETE_DEFAULT)
1730         {
1731                 RegDeleteValueA(hTypeKey, "Name");
1732         }
1733         else
1734         {
1735                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
1736                 {
1737                         RegCloseKey(hTypeKey);
1738                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1739                 }
1740                 if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1741                         keyname, &hProvKey))
1742                 {
1743                         CRYPT_Free(keyname);
1744                         RegCloseKey(hTypeKey);
1745                         CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1746                 }
1747                 CRYPT_Free(keyname);
1748                 
1749                 if (RegSetValueExA(hTypeKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) + 1))
1750                 {
1751                         RegCloseKey(hTypeKey);
1752                         RegCloseKey(hProvKey);
1753                         return FALSE;
1754                 }
1755                 
1756                 RegCloseKey(hProvKey);
1757         }
1758         RegCloseKey(hTypeKey);
1759
1760         return TRUE;
1761 }
1762
1763 /******************************************************************************
1764  * CryptSetProviderExW (ADVAPI32.@)
1765  *
1766  * See CryptSetProviderExA
1767  */
1768 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1769 {
1770         BOOL ret = FALSE;
1771         PSTR str = NULL;
1772
1773         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1774
1775         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1776         {
1777                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1778                 CRYPT_Free(str);
1779         }
1780         return ret;
1781 }
1782
1783 /******************************************************************************
1784  * CryptSetProvParam (ADVAPI32.@)
1785  *
1786  * Customizes the operations of a CSP.
1787  *
1788  * PARAMS
1789  *  hProv   [I] Handle of a CSP.
1790  *  dwParam [I] See MSDN Doc.
1791  *  pbData  [I] Buffer that contains a value to set as a parameter.
1792  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
1793  *
1794  * RETURNS
1795  *  Success: TRUE
1796  *  Failure: FALSE
1797  */
1798 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1799 {
1800         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1801
1802         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1803
1804         if (!prov)
1805                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1806         if (dwFlags & PP_USE_HARDWARE_RNG)
1807         {
1808                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1809                 FIXME("\tLetting the CSP decide.\n");
1810         }
1811         if (dwFlags & PP_CLIENT_HWND)
1812         {
1813                 /* FIXME: Should verify the parameter */
1814                 if (pbData /* && IsWindow((HWND)pbData) */)
1815                 {
1816                         crypt_hWindow = (HWND)(pbData);
1817                         return TRUE;
1818                 } else {
1819                         SetLastError(ERROR_INVALID_PARAMETER);
1820                         return FALSE;
1821                 }
1822         }
1823         /* All other flags go to the CSP */
1824         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1825 }
1826
1827 /******************************************************************************
1828  * CryptVerifySignatureA
1829  *
1830  * Note: Since the sDesciption (string) is supposed to be NULL and
1831  *      is only retained for compatibility no string conversions are required
1832  *      and only one implementation is required for both ANSI and Unicode.
1833  *      We still need to export both:
1834  *
1835  * CryptVerifySignatureA (ADVAPI32.@)
1836  * CryptVerifySignatureW (ADVAPI32.@)
1837  *
1838  * Verifies the signature of a hash object.
1839  *
1840  * PARAMS
1841  *  hHash        [I] Handle of the hash object to verify.
1842  *  pbSignature  [I] Signature data to verify.
1843  *  dwSigLen     [I] Size of pbSignature.
1844  *  hPubKey      [I] Handle to the public key to authenticate signature.
1845  *  sDescription [I] Must be set to NULL.
1846  *  dwFlags      [I] See MSDN doc.
1847  *
1848  * RETURNS
1849  *  Success: TRUE
1850  *  Failure: FALSE
1851  */
1852 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1853                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1854 {
1855         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1856         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1857         PCRYPTPROV prov;
1858
1859         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1860                         dwSigLen, hPubKey, dwFlags);
1861         if (sDescription)
1862                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1863
1864         if (!hash || !key)
1865                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1866         if (!pbSignature || !dwSigLen)
1867                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1868
1869         prov = hash->pProvider;
1870         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1871                 key->hPrivate, NULL, dwFlags);
1872 }
1873
1874
1875 /*
1876    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
1877    in crypt32.dll.
1878  */
1879
1880 /******************************************************************************
1881  * SystemFunction040   (ADVAPI32.@)
1882  *
1883  * PARAMS
1884  *  memory [I/O] Pointer to memory to encrypt.
1885  *  length [I] Length of region to encrypt in bytes.
1886  *  flags  [I] Control whether other processes are able to decrypt the memory.
1887  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
1888  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
1889  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1890  *    
1891  * NOTES
1892  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1893  *  If flags are specified when encrypting, the same flag value must be given
1894  *  when decrypting the memory.
1895  */
1896 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
1897 {
1898         FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
1899         return STATUS_SUCCESS;
1900 }
1901
1902 /******************************************************************************
1903  * SystemFunction041  (ADVAPI32.@)
1904  *
1905  * PARAMS
1906  *  memory [I/O] Pointer to memory to decrypt.
1907  *  length [I] Length of region to decrypt in bytes.
1908  *  flags  [I] Control whether other processes are able to decrypt the memory.
1909  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
1910  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
1911  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1912  *
1913  * NOTES
1914  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1915  *  If flags are specified when encrypting, the same flag value must be given
1916  *  when decrypting the memory.
1917  */
1918 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
1919 {
1920         FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
1921         return STATUS_SUCCESS;
1922 }