New XP debugging APIs: implemented DebugActiveProcessStop,
[wine] / dlls / advapi32 / crypt.c
1 /*
2  * dlls/advapi32/crypt.c
3  */
4
5 ///////////////////////
6 //
7 //  TODO:
8 //  - Reference counting
9 //  - Thread-safing
10 //  - Signature checking
11
12 #include <time.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15
16 #include "wine/unicode.h"
17 #include "crypt.h"
18 #include "winnls.h"
19 #include "wincrypt.h"
20 #include "windef.h"
21 #include "winerror.h"
22 #include "winreg.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "debugtools.h"
26
27 DEFAULT_DEBUG_CHANNEL(crypt);
28
29 HWND crypt_hWindow = 0;
30
31 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
32
33 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
34 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
35
36 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
37 {
38         const PSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
39         PSTR keyname;
40
41         keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
42         if (keyname)
43         {
44                 strcpy(keyname, KEYSTR);
45                 strcpy(keyname + strlen(KEYSTR), pProvName);
46         } else
47                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
48         return keyname;
49 }
50
51 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
52 {
53         const PSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
54         const PSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
55         PSTR keyname;
56         PSTR ptr;
57
58         keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
59         if (keyname)
60         {
61                 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
62                 ptr = keyname + strlen(keyname);
63                 *(--ptr) = (dwType % 10) + '0';
64                 *(--ptr) = (dwType / 10) + '0';
65                 *(--ptr) = (dwType / 100) + '0';
66         } else
67                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
68         return keyname;
69 }
70
71 /* CRYPT_UnicodeTOANSI
72  * wstr - unicode string
73  * str - pointer to ANSI string
74  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
75  *
76  * returns TRUE if unsuccessfull, FALSE otherwise.
77  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
78  */
79 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
80 {
81         int count;
82
83         if (!wstr)
84         {
85                 *str = NULL;
86                 return TRUE;
87         }
88         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
89         count = count < strsize ? count : strsize;
90         if (strsize == -1)
91                 *str = CRYPT_Alloc(count * sizeof(CHAR));
92         if (*str)
93         {
94                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
95                 return TRUE;
96         }
97         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
98         return FALSE;
99 }
100
101 /* CRYPT_ANSITOUnicode
102  * str - ANSI string
103  * wstr - pointer to unicode string
104  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
105  */
106 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
107 {
108         int wcount;
109
110         if (!str)
111         {
112                 *wstr = NULL;
113                 return TRUE;
114         }
115         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
116         wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR);
117         if (wstrsize == -1)
118                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
119         if (*wstr)
120         {
121                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
122                 return TRUE;
123         }
124         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
125         return FALSE;
126 }
127
128 //These next 2 functions are used by the VTableProvStruc structure
129 BOOL CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
130 {
131         if (!lpszImage || !pData)
132         {
133                 SetLastError(ERROR_INVALID_PARAMETER);
134                 return FALSE;
135         }
136         //FIXME: Actually verify the image!
137         return TRUE;
138 }
139
140 BOOL CRYPT_ReturnhWnd(DWORD *phWnd)
141 {
142         if (!phWnd)
143                 return FALSE;
144         *phWnd = crypt_hWindow;
145         return TRUE;
146 }
147
148 #define CRYPT_GetProvFunc(name) \
149         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
150 #define CRYPT_GetProvFuncOpt(name) \
151         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
152 PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
153 {
154         PCRYPTPROV provider;
155         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
156
157         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
158         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
159         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
160         if ( !(provider->hModule = LoadLibraryA(pImage)) )
161         {
162                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
163                 goto error;
164         }
165
166         errorcode = NTE_PROVIDER_DLL_FAIL;
167         CRYPT_GetProvFunc(CPAcquireContext);
168         CRYPT_GetProvFunc(CPCreateHash);
169         CRYPT_GetProvFunc(CPDecrypt);
170         CRYPT_GetProvFunc(CPDeriveKey);
171         CRYPT_GetProvFunc(CPDestroyHash);
172         CRYPT_GetProvFunc(CPDestroyKey);
173         CRYPT_GetProvFuncOpt(CPDuplicateHash);
174         CRYPT_GetProvFuncOpt(CPDuplicateKey);
175         CRYPT_GetProvFunc(CPEncrypt);
176         CRYPT_GetProvFunc(CPExportKey);
177         CRYPT_GetProvFunc(CPGenKey);
178         CRYPT_GetProvFunc(CPGenRandom);
179         CRYPT_GetProvFunc(CPGetHashParam);
180         CRYPT_GetProvFunc(CPGetKeyParam);
181         CRYPT_GetProvFunc(CPGetProvParam);
182         CRYPT_GetProvFunc(CPGetUserKey);
183         CRYPT_GetProvFunc(CPHashData);
184         CRYPT_GetProvFunc(CPHashSessionKey);
185         CRYPT_GetProvFunc(CPImportKey);
186         CRYPT_GetProvFunc(CPReleaseContext);
187         CRYPT_GetProvFunc(CPSetHashParam);
188         CRYPT_GetProvFunc(CPSetKeyParam);
189         CRYPT_GetProvFunc(CPSetProvParam);
190         CRYPT_GetProvFunc(CPSignHash);
191         CRYPT_GetProvFunc(CPVerifySignature);
192
193         //FIXME: Not sure what the pbContextInfo field is for
194         //  Does it need memory allocation?
195         provider->pVTable->Version = 3;
196         provider->pVTable->pFuncVerifyImage = CRYPT_VerifyImage;
197         provider->pVTable->pFuncReturnhWnd = CRYPT_ReturnhWnd;
198         provider->pVTable->dwProvType = 0;
199         provider->pVTable->pbContextInfo = NULL;
200         provider->pVTable->cbContextInfo = 0;
201         provider->pVTable->pszProvName = NULL;
202         return provider;
203
204 error:
205         SetLastError(errorcode);
206         if (provider)
207         {
208                 if (provider->hModule)
209                         FreeLibrary(provider->hModule);
210                 CRYPT_Free(provider->pVTable);
211                 CRYPT_Free(provider->pFuncs);
212                 CRYPT_Free(provider);
213         }
214         return NULL;
215 }
216 #undef CRYPT_GetProvFunc
217 #undef CRYPT_GetProvFuncOpt
218
219
220 /******************************************************************************
221  * CryptAcquireContextA (ADVAPI32.@)
222  * Acquire a crypto provider context handle.
223  *
224  * PARAMS
225  * phProv: Pointer to HCRYPTPROV for the output.
226  * pszContainer: Key Container Name
227  * pszProvider: Cryptographic Service Provider Name
228  * dwProvType: Crypto provider type to get a handle.
229  * dwFlags: flags for the operation
230  *
231  * RETURNS TRUE on success, FALSE on failure.
232  */
233 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
234                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
235 {
236         PCRYPTPROV pProv = NULL;
237         HKEY key;
238         PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
239 //      BYTE* signature;
240         DWORD keytype, type, len;//, siglen;
241
242         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
243                 pszProvider, dwProvType, dwFlags);
244
245         if (!phProv || !dwProvType)
246         {
247                 SetLastError(ERROR_INVALID_PARAMETER);
248                 return FALSE;
249         }
250         if (dwProvType > MAXPROVTYPES)
251         {
252                 SetLastError(NTE_BAD_PROV_TYPE);
253                 return FALSE;
254         }
255
256         if (!pszProvider)
257         {
258                 //No CSP name specified so try the user default CSP first
259                 //      then try the machine default CSP
260                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) )
261                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
262                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
263                 {
264                         CRYPT_Free(keyname);
265                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) )
266                                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
267                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) goto error;
268                 }
269                 CRYPT_Free(keyname);
270                 RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
271                 if (!len || keytype != REG_SZ || !(provname = CRYPT_Alloc(len))) goto error;
272                 RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
273                 RegCloseKey(key);
274         } else {
275                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
276                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
277                 strcpy(provname, pszProvider);
278         }
279
280         keyname = CRYPT_GetProvKeyName(provname);
281         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) goto error;
282         CRYPT_Free(keyname);
283         len = sizeof(DWORD);
284         RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
285         if (type != dwProvType)
286         {
287                 SetLastError(NTE_BAD_PROV_TYPE);
288                 goto error;
289         }
290
291         RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
292         if (keytype != REG_SZ || !(temp = CRYPT_Alloc(len))) goto error;
293         RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
294
295         RegCloseKey(key);
296         len = ExpandEnvironmentStringsA(temp, NULL, 0);
297         if ( !(imagepath = CRYPT_Alloc(len)) )
298         {
299                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
300                 goto error;
301         }
302         if (!ExpandEnvironmentStringsA(temp, imagepath, len)) goto error;
303
304 //      if (!CRYPT_VerifyImage(imagepath, signature)) goto error;
305         pProv = CRYPT_LoadProvider(imagepath);
306         CRYPT_Free(temp);
307         CRYPT_Free(imagepath);
308         if (!pProv) goto error;
309
310         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
311         {
312                 //MSDN:  When this flag is set, the value returned in phProv is undefined,
313                 //    and thus, the CryptReleaseContext function need not be called afterwards.
314                 //Therefore, we must clean up everything now.
315                 if (dwFlags & CRYPT_DELETEKEYSET)
316                 {
317                         FreeLibrary(pProv->hModule);
318                         CRYPT_Free(provname);
319                         CRYPT_Free(pProv->pFuncs);
320                         CRYPT_Free(pProv);
321                 } else {
322                         pProv->pVTable->pszProvName = provname;
323                         pProv->pVTable->dwProvType = dwProvType;
324                         *phProv = (HCRYPTPROV)pProv;
325                 }
326                 return TRUE;
327         }
328         //FALLTHROUGH TO ERROR IF FALSE - CSP internal error!
329 error:
330         if (pProv)
331         {
332                 FreeLibrary(pProv->hModule);
333                 CRYPT_Free(pProv->pVTable);
334                 CRYPT_Free(pProv->pFuncs);
335                 CRYPT_Free(pProv);
336         }
337         CRYPT_Free(provname);
338         CRYPT_Free(temp);
339         CRYPT_Free(imagepath);
340         CRYPT_Free(keyname);
341         return FALSE;
342 }
343
344 /******************************************************************************
345  * CryptAcquireContextW (ADVAPI32.@)
346  */
347 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
348                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
349 {
350         PSTR pProvider = NULL, pContainer = NULL;
351         BOOL ret = FALSE;
352
353         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
354                 debugstr_w(pszProvider), dwProvType, dwFlags);
355
356         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
357                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
358         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
359         {
360                 CRYPT_Free(pContainer);
361                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
362         }
363
364         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
365
366         if (pContainer)
367                 CRYPT_Free(pContainer);
368         if (pProvider)
369                 CRYPT_Free(pProvider);
370
371         return ret;
372 }
373
374 /******************************************************************************
375  * CryptContextAddRef (ADVAPI32.@)
376  */
377 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
378 {
379         FIXME("(0x%lx, %p, %08lx): stub!\n", hProv, pdwReserved, dwFlags);
380         return FALSE;
381         //InterlockIncrement??
382 }
383
384 /******************************************************************************
385  * CryptReleaseContext (ADVAPI32.@)
386  */
387 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
388 {
389         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
390         BOOL ret;
391
392         TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
393
394         if (!pProv)
395         {
396                 SetLastError(NTE_BAD_UID);
397                 return FALSE;
398         }
399         //FIXME: Decrement the counter here first if possible
400         ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
401         FreeLibrary(pProv->hModule);
402 //      CRYPT_Free(pProv->pVTable->pContextInfo);
403         CRYPT_Free(pProv->pVTable->pszProvName);
404         CRYPT_Free(pProv->pVTable);
405         CRYPT_Free(pProv->pFuncs);
406         CRYPT_Free(pProv);
407         return ret;
408 }
409
410 /******************************************************************************
411  * CryptGenRandom (ADVAPI32.@)
412  */
413 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
414 {
415         PCRYPTPROV prov = (PCRYPTPROV)hProv;
416
417         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
418
419         if (!hProv)
420                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
421
422         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
423 }
424
425 /******************************************************************************
426  * CryptCreateHash (ADVAPI32.@)
427  */
428 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
429                 DWORD dwFlags, HCRYPTHASH *phHash)
430 {
431         PCRYPTPROV prov = (PCRYPTPROV)hProv;
432         PCRYPTKEY key = (PCRYPTKEY)hKey;
433         PCRYPTHASH hash;
434
435         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
436
437         if (!prov)
438                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
439         if (!phHash)
440                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
441         if (dwFlags)
442                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
443         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
444                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
445
446         hash->pProvider = prov;
447
448         *phHash = (HCRYPTHASH)hash;
449         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
450                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
451                 return TRUE;
452
453         //CSP error!
454         CRYPT_Free(hash);
455         return FALSE;
456 }
457
458 /******************************************************************************
459  * CryptDecrypt (ADVAPI32.@)
460  */
461 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
462                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
463 {
464         PCRYPTPROV prov;
465         PCRYPTKEY key = (PCRYPTKEY)hKey;
466         PCRYPTHASH hash = (PCRYPTHASH)hHash;
467
468         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
469
470         if (!key || !pbData || !pdwDataLen)
471                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
472
473         prov = key->pProvider;
474         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
475                         Final, dwFlags, pbData, pdwDataLen);
476 }
477
478 /******************************************************************************
479  * CryptDeriveKey (ADVAPI32.@)
480  */
481 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
482                 DWORD dwFlags, HCRYPTKEY *phKey)
483 {
484         PCRYPTPROV prov = (PCRYPTPROV)hProv;
485         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
486         PCRYPTKEY key;
487
488         TRACE("(0x%lx, %d, 0x%ld, %08ld, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
489
490         if (!prov || !hash)
491                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
492         if (!phKey)
493                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
494         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
495                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
496
497         key->pProvider = prov;
498         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
499                 return TRUE;
500
501         //CSP error!
502         CRYPT_Free(key);
503         return FALSE;
504 }
505
506 /******************************************************************************
507  * CryptDestroyHash (ADVAPI32.@)
508  */
509 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
510 {
511         PCRYPTHASH hash = (PCRYPTHASH)hHash;
512         PCRYPTPROV prov;
513         BOOL ret;
514
515         TRACE("(0x%lx)\n", hHash);
516
517         if (!hash)
518                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
519
520         prov = hash->pProvider;
521         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
522         CRYPT_Free(hash);
523         return ret;
524 }
525
526 /******************************************************************************
527  *  CryptDestroyKey (ADVAPI32.@)
528  */
529 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
530 {
531         PCRYPTKEY key = (PCRYPTKEY)hKey;
532         PCRYPTPROV prov;
533         BOOL ret;
534
535         TRACE("(0x%lx)\n", hKey);
536
537         if (!key)
538                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
539
540         prov = key->pProvider;
541         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
542         CRYPT_Free(key);
543         return ret;
544 }
545
546 /******************************************************************************
547  * CryptDuplicateHash (ADVAPI32.@)
548  */
549 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
550                 DWORD dwFlags, HCRYPTHASH *phHash)
551 {
552         PCRYPTPROV prov;
553         PCRYPTHASH orghash, newhash;
554
555         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
556
557         orghash = (PCRYPTHASH)hHash;
558         if (!orghash || pdwReserved || !phHash)
559                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
560
561         prov = orghash->pProvider;
562         if (!prov->pFuncs->pCPDuplicateHash)
563                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
564
565         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
566                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
567
568         newhash->pProvider = prov;
569         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
570         {
571                 *phHash = (HCRYPTHASH)newhash;
572                 return TRUE;
573         }
574         CRYPT_Free(newhash);
575         return FALSE;
576 }
577
578 /******************************************************************************
579  * CryptDuplicateKey (ADVAPI32.@)
580  */
581 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
582 {
583         PCRYPTPROV prov;
584         PCRYPTKEY orgkey, newkey;
585
586         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
587
588         orgkey = (PCRYPTKEY)hKey;
589         if (!orgkey || pdwReserved || !phKey)
590                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
591
592         prov = orgkey->pProvider;
593         if (!prov->pFuncs->pCPDuplicateKey)
594                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
595
596         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
597                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
598
599         newkey->pProvider = prov;
600         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
601         {
602                 *phKey = (HCRYPTKEY)newkey;
603                 return TRUE;
604         }
605         CRYPT_Free(newkey);
606         return FALSE;
607 }
608
609 /******************************************************************************
610  * CryptEncrypt (ADVAPI32.@)
611  */
612 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
613                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
614 {
615         PCRYPTPROV prov;
616         PCRYPTKEY key = (PCRYPTKEY)hKey;
617         PCRYPTHASH hash = (PCRYPTHASH)hHash;
618
619         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
620
621         if (!key || !pdwDataLen)
622                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
623
624         prov = key->pProvider;
625         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
626                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
627 }
628
629 /******************************************************************************
630  * CryptEnumProvidersA (ADVAPI32.@)
631  */
632 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
633                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
634 {
635         HKEY hKey;
636
637         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
638                         pdwProvType, pszProvName, pcbProvName);
639
640         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
641         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
642
643         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
644                 CRYPT_ReturnLastError(NTE_FAIL);
645
646         if (!pszProvName)
647         {
648                 DWORD numkeys;
649                 RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, pcbProvName, NULL, NULL, NULL, NULL, NULL, NULL);
650                 (*pcbProvName)++;
651                 if (dwIndex >= numkeys)
652                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
653         } else {
654                 DWORD size = sizeof(DWORD);
655                 HKEY subkey;
656                 if (RegEnumKeyA(hKey, dwIndex, pszProvName, *pcbProvName))
657                         return FALSE;
658                 if (RegOpenKeyA(hKey, pszProvName, &subkey))
659                         return FALSE;
660                 if (RegQueryValueExA(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size))
661                         return FALSE;
662                 RegCloseKey(subkey);
663         }
664         RegCloseKey(hKey);
665         return TRUE;
666 }
667
668 /******************************************************************************
669  * CryptEnumProvidersW (ADVAPI32.@)
670  */
671 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
672                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
673 {
674         PSTR str = NULL;
675         DWORD strlen;
676         BOOL ret;// = FALSE;
677
678         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
679                         pdwProvType, pszProvName, pcbProvName);
680
681         strlen = *pcbProvName / sizeof(WCHAR);
682         if ( pszProvName && (str = CRYPT_Alloc(strlen)) )
683                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
684         ret = CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
685         if (str)
686         {
687                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
688                 CRYPT_Free(str);
689         }
690         *pcbProvName = strlen * sizeof(WCHAR);
691         return ret;
692 }
693
694 /******************************************************************************
695  * CryptEnumProviderTypesA (ADVAPI32.@)
696  */
697 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
698                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
699 {
700         HKEY hKey, hSubkey;
701         DWORD keylen, numkeys;
702         PSTR keyname, ch;
703
704         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
705                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
706
707         if (pdwReserved || !pdwProvType || !pcbTypeName)
708                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
709         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
710
711         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
712                 return FALSE;
713
714         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
715         if (dwIndex >= numkeys)
716                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
717         keylen++;
718         if ( !(keyname = CRYPT_Alloc(keylen)) )
719                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
720         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) )
721                 return FALSE;
722         RegOpenKeyA(hKey, keyname, &hSubkey);
723         ch = keyname + strlen(keyname);
724         //Convert "Type 000" to 0, etc/
725         *pdwProvType = *(--ch) - '0';
726         *pdwProvType += (*(--ch) - '0') * 10;
727         *pdwProvType += (*(--ch) - '0') * 100;
728         CRYPT_Free(keyname);
729         RegQueryValueA(hSubkey, "TypeName", pszTypeName, pcbTypeName);
730         RegCloseKey(hSubkey);
731         RegCloseKey(hKey);
732         return TRUE;
733 }
734
735 /******************************************************************************
736  * CryptEnumProviderTypesW (ADVAPI32.@)
737  */
738 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
739                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
740 {
741         PSTR str = NULL;
742         DWORD strlen;
743         BOOL ret;
744
745         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
746                         pdwProvType, pszTypeName, pcbTypeName);
747         strlen = *pcbTypeName / sizeof(WCHAR);
748         if ( pszTypeName && (str = CRYPT_Alloc(strlen)) )
749                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
750         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
751         if (str)
752         {
753                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
754                 CRYPT_Free(str);
755         }
756         *pcbTypeName = strlen * sizeof(WCHAR);
757         return ret;
758 }
759
760 /******************************************************************************
761  * CryptExportKey (ADVAPI32.@)
762  */
763 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
764                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
765 {
766         PCRYPTPROV prov;
767         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
768
769         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
770
771         if (!key || pdwDataLen)
772                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
773
774         prov = key->pProvider;
775         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
776                         dwBlobType, dwFlags, pbData, pdwDataLen);
777 }
778
779 /******************************************************************************
780  * CryptGenKey (ADVAPI32.@)
781  */
782 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
783 {
784         PCRYPTPROV prov = (PCRYPTPROV)hProv;
785         PCRYPTKEY key;
786
787         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
788
789         if (!prov)
790                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
791         if (!phKey)
792                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
793         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
794                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
795
796         key->pProvider = prov;
797
798         *phKey = (HCRYPTKEY)key;
799         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
800                 return TRUE;
801
802         //CSP error!
803         CRYPT_Free(key);
804         return FALSE;
805 }
806
807 /******************************************************************************
808  * CryptGetDefaultProviderA (ADVAPI32.@)
809  */
810 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
811                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
812 {
813         HKEY hKey;
814         PSTR keyname;
815
816         if (pdwReserved || !pcbProvName)
817                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
818         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
819                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
820         if (dwProvType < 0 || dwProvType > 999)
821                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
822         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
823                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
824         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
825         {
826                 CRYPT_Free(keyname);
827                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
828         }
829         CRYPT_Free(keyname);
830         if (RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName))
831         {
832                 if (GetLastError() != ERROR_MORE_DATA)
833                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
834                 return FALSE;
835         }
836         RegCloseKey(hKey);
837         return TRUE;
838 }
839
840 /******************************************************************************
841  * CryptGetDefaultProviderW (ADVAPI32.@)
842  */
843 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
844                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
845 {
846         PSTR str = NULL;
847         DWORD strlen;
848         BOOL ret = FALSE;
849
850         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
851
852         strlen = *pcbProvName / sizeof(WCHAR);
853         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
854                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
855         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
856         if (str)
857         {
858                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
859                 CRYPT_Free(str);
860         }
861         *pcbProvName = strlen * sizeof(WCHAR);
862         return ret;
863 }
864
865 /******************************************************************************
866  * CryptGetHashParam (ADVAPI32.@)
867  */
868 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
869                 DWORD *pdwDataLen, DWORD dwFlags)
870 {
871         PCRYPTPROV prov;
872         PCRYPTHASH hash = (PCRYPTHASH)hHash;
873
874         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
875
876         if (!hash || !pdwDataLen)
877                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
878
879         prov = hash->pProvider;
880         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
881                         pbData, pdwDataLen, dwFlags);
882 }
883
884 /******************************************************************************
885  * CryptGetKeyParam (ADVAPI32.@)
886  */
887 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
888                 DWORD *pdwDataLen, DWORD dwFlags)
889 {
890         PCRYPTPROV prov;
891         PCRYPTKEY key = (PCRYPTKEY)hKey;
892
893         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
894
895         if (!key || !pdwDataLen)
896                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
897
898         prov = key->pProvider;
899         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
900                         pbData, pdwDataLen, dwFlags);
901 }
902
903 /******************************************************************************
904  * CryptGetProvParam (ADVAPI32.@)
905  */
906 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
907                 DWORD *pdwDataLen, DWORD dwFlags)
908 {
909         PCRYPTPROV prov = (PCRYPTPROV)hProv;
910
911         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
912
913         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
914 }
915
916 /******************************************************************************
917  * CryptGetUserKey (ADVAPI32.@)
918  */
919 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
920 {
921         PCRYPTPROV prov = (PCRYPTPROV)hProv;
922         PCRYPTKEY key;
923
924         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
925
926         if (!prov)
927                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
928         if (!phUserKey)
929                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
930         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
931                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
932
933         key->pProvider = prov;
934
935         *phUserKey = (HCRYPTKEY)key;
936         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
937                 return TRUE;
938
939         //CSP Error
940         CRYPT_Free(key);
941         return FALSE;
942 }
943
944 /******************************************************************************
945  * CryptHashData (ADVAPI32.@)
946  */
947 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
948 {
949         PCRYPTHASH hash = (PCRYPTHASH)hHash;
950         PCRYPTPROV prov;
951
952         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
953
954         if (!hash)
955                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
956         if (!pbData || !dwDataLen)
957                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
958
959         prov = hash->pProvider;
960         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
961 }
962
963 /******************************************************************************
964  * CryptHashSessionKey (ADVAPI32.@)
965  */
966 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
967 {
968         PCRYPTHASH hash = (PCRYPTHASH)hHash;
969         PCRYPTKEY key = (PCRYPTKEY)hKey;
970         PCRYPTPROV prov;
971
972         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
973
974         if (!hash || !key)
975                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
976
977         prov = hash->pProvider;
978         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
979 }
980
981 /******************************************************************************
982  * CryptImportKey (ADVAPI32.@)
983  */
984 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
985                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
986 {
987         PCRYPTPROV prov = (PCRYPTPROV)hProv;
988         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
989
990         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
991
992         if (!prov || !pbData || !dwDataLen || !phKey)
993                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
994
995         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
996                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
997
998         importkey->pProvider = prov;
999         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1000                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1001         {
1002                 *phKey = (HCRYPTKEY)importkey;
1003                 return TRUE;
1004         }
1005
1006         CRYPT_Free(importkey);
1007         return FALSE;
1008 }
1009
1010 /******************************************************************************
1011  * CryptSignHashA
1012  *
1013  * Note: Since the sDesciption (string) is supposed to be NULL and
1014  *      is only retained for compatibility no string conversions are required
1015  *      and only one implementation is required for both ANSI and Unicode.
1016  *      We still need to export both:
1017  *
1018  * CryptSignHashA (ADVAPI32.@)
1019  * CryptSignHashW (ADVAPI32.@)
1020  */
1021 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1022                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1023 {
1024         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1025         PCRYPTPROV prov;
1026
1027         TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1028         if (sDescription)
1029                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.");
1030
1031         if (!hash)
1032                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1033         if (!pdwSigLen)
1034                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1035
1036         prov = hash->pProvider;
1037         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1038                 dwFlags, pbSignature, pdwSigLen);
1039 }
1040
1041 /******************************************************************************
1042  * CryptSetHashParam (ADVAPI32.@)
1043  */
1044 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1045 {
1046         PCRYPTPROV prov;
1047         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1048
1049         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1050
1051         if (!hash || !pbData)
1052                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1053
1054         prov = hash->pProvider;
1055         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1056                         dwParam, pbData, dwFlags);
1057 }
1058
1059 /******************************************************************************
1060  * CryptSetKeyParam (ADVAPI32.@)
1061  */
1062 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1063 {
1064         PCRYPTPROV prov;
1065         PCRYPTKEY key = (PCRYPTKEY)hKey;
1066
1067         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1068
1069         if (!key || !pbData)
1070                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1071
1072         prov = key->pProvider;
1073         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1074                         dwParam, pbData, dwFlags);
1075 }
1076
1077 /******************************************************************************
1078  * CryptSetProviderA (ADVAPI32.@)
1079  */
1080 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1081 {
1082         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1083         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1084 }
1085
1086 /******************************************************************************
1087  * CryptSetProviderW (ADVAPI32.@)
1088  */
1089 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1090 {
1091         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1092         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1093 }
1094
1095 /******************************************************************************
1096  * CryptSetProviderExA (ADVAPI32.@)
1097  */
1098 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1099 {
1100         HKEY hKey;
1101         PSTR keyname;
1102
1103         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1104
1105         if (!pszProvName || pdwReserved)
1106                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1107         if (dwProvType < 0 || dwProvType > MAXPROVTYPES)
1108                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1109         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1110                         || dwFlags == CRYPT_DELETE_DEFAULT)
1111                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1112
1113         if (dwFlags & CRYPT_DELETE_DEFAULT)
1114         {
1115                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1116                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1117                 RegDeleteKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname);
1118                 CRYPT_Free(keyname);
1119                 return TRUE;
1120         }
1121
1122         if ( !(keyname = CRYPT_GetProvKeyName(pszProvName)) )
1123                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1124         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &hKey))
1125         {
1126                 CRYPT_Free(keyname);
1127                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1128         }
1129         CRYPT_Free(keyname);
1130         RegCloseKey(hKey);
1131         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1132                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1133         RegCreateKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname, &hKey);
1134         CRYPT_Free(keyname);
1135         if (RegSetValueExA(hKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) +1))
1136                 return FALSE;
1137         return TRUE;
1138 }
1139
1140 /******************************************************************************
1141  * CryptSetProviderExW (ADVAPI32.@)
1142  */
1143 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1144 {
1145         BOOL ret = FALSE;
1146         PSTR str = NULL;
1147
1148         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1149
1150         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1151         {
1152                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1153                 CRYPT_Free(str);
1154         }
1155         return ret;
1156 }
1157
1158 /******************************************************************************
1159  * CryptSetProvParam (ADVAPI32.@)
1160  */
1161 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1162 {
1163         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1164
1165         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1166
1167         if (!prov)
1168                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1169         if (dwFlags & PP_USE_HARDWARE_RNG)
1170         {
1171                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1172                 FIXME("\tLetting the CSP decide.\n");
1173         }
1174         if (dwFlags & PP_CLIENT_HWND)
1175         {
1176                 //FIXME: Should verify the parameter
1177                 if (pbData /*&& IsWindow((HWND)pbData)*/)
1178                 {
1179                         crypt_hWindow = (HWND)(pbData);
1180                         return TRUE;
1181                 } else {
1182                         SetLastError(ERROR_INVALID_PARAMETER);
1183                         return FALSE;
1184                 }
1185         }
1186         //All other flags go to the CSP
1187         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1188 }
1189
1190 /******************************************************************************
1191  * CryptVerifySignatureA
1192  *
1193  * Note: Since the sDesciption (string) is supposed to be NULL and
1194  *      is only retained for compatibility no string conversions are required
1195  *      and only one implementation is required for both ANSI and Unicode.
1196  *      We still need to export both:
1197  *
1198  * CryptVerifySignatureA (ADVAPI32.@)
1199  * CryptVerifySignatureW (ADVAPI32.@)
1200  */
1201 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1202                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1203 {
1204         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1205         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1206         PCRYPTPROV prov;
1207
1208         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1209                         dwSigLen, hPubKey, dwFlags);
1210         if (sDescription)
1211                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.");
1212
1213         if (!hash || !key)
1214                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1215         if (!pbSignature || !dwSigLen)
1216                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1217
1218         prov = hash->pProvider;
1219         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1220                 key->hPrivate, NULL, dwFlags);
1221 }