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