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