Move include/bitmaps/*.xpm where they belong.
[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         ULONG r;
262
263         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
264                 pszProvider, dwProvType, dwFlags);
265
266         if (!phProv || !dwProvType)
267         {
268                 SetLastError(ERROR_INVALID_PARAMETER);
269                 return FALSE;
270         }
271         if (dwProvType > MAXPROVTYPES)
272         {
273                 SetLastError(NTE_BAD_PROV_TYPE);
274                 return FALSE;
275         }
276
277         if (!pszProvider)
278         {
279                 /* No CSP name specified so try the user default CSP first
280                  * then try the machine default CSP
281                  */
282                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
283                         FIXME("No provider registered for crypto provider type %ld.\n", dwProvType);
284                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
285                         return FALSE;
286                 }
287                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
288                 {
289                         CRYPT_Free(keyname);
290                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
291                                 FIXME("No type registered for crypto provider type %ld.\n", dwProvType);
292                                 RegCloseKey(key);
293                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
294                                 goto error;
295                         }
296                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
297                                 FIXME("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
298                                 RegCloseKey(key);
299                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
300                                 goto error;
301                         }
302                 }
303                 CRYPT_Free(keyname);
304                 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
305                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
306                 {
307                         TRACE("error %ld reading size of 'Name' from registry\n", r );
308                         RegCloseKey(key);
309                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
310                         goto error;
311                 }
312                 if(!(provname = CRYPT_Alloc(len)))
313                 {
314                         RegCloseKey(key);
315                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
316                         goto error;
317                 }
318                 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
319                 if( r != ERROR_SUCCESS )
320                 {
321                         TRACE("error %ld reading 'Name' from registry\n", r );
322                         RegCloseKey(key);
323                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
324                         goto error;
325                 }
326                 RegCloseKey(key);
327         } else {
328                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
329                 {
330                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
331                         goto error;
332                 }
333                 strcpy(provname, pszProvider);
334         }
335
336         keyname = CRYPT_GetProvKeyName(provname);
337         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) goto error;
338         CRYPT_Free(keyname);
339         len = sizeof(DWORD);
340         r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
341         if (r != ERROR_SUCCESS || type != dwProvType)
342         {
343                 FIXME("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
344                 SetLastError(NTE_BAD_PROV_TYPE);
345                 goto error;
346         }
347
348         r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
349         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
350         {
351                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
352                 RegCloseKey(key);
353                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
354                 goto error;
355         }
356         if (!(temp = CRYPT_Alloc(len)))
357         {
358                 RegCloseKey(key);
359                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
360                 goto error;
361         }
362         r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
363         if( r != ERROR_SUCCESS )
364         {
365                 TRACE("error %ld reading 'Image Path' from registry\n", r );
366                 RegCloseKey(key);
367                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
368                 goto error;
369         }
370
371         r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
372         if ( r != ERROR_SUCCESS || keytype != REG_BINARY)
373         {
374                 TRACE("error %ld reading size of 'Signature'\n", r );
375                 RegCloseKey(key);
376                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
377                 goto error;
378         }
379         if (!(signature = CRYPT_Alloc(len)))
380         {
381                 RegCloseKey(key);
382                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
383                 goto error;
384         }
385         r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
386         if ( r != ERROR_SUCCESS )
387         {
388                 TRACE("error %ld reading 'Signature'\n", r );
389                 RegCloseKey(key);
390                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
391                 goto error;
392         }
393         RegCloseKey(key);
394         len = ExpandEnvironmentStringsA(temp, NULL, 0);
395         if ( !(imagepath = CRYPT_Alloc(len)) )
396         {
397                 CRYPT_Free(signature);
398                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
399                 goto error;
400         }
401         if (!ExpandEnvironmentStringsA(temp, imagepath, len))
402         {
403                 CRYPT_Free(signature);
404                 /* ExpandEnvironmentStrings will call SetLastError */
405                 goto error;
406         }
407
408         if (!CRYPT_VerifyImage(imagepath, signature))
409         {
410                 CRYPT_Free(signature);
411                 SetLastError(NTE_SIGNATURE_FILE_BAD);
412                 goto error;
413         }
414         pProv = CRYPT_LoadProvider(imagepath);
415         CRYPT_Free(temp);
416         CRYPT_Free(imagepath);
417         CRYPT_Free(signature);
418         if (!pProv) {
419                 FIXME("Could not load crypto provider from DLL %s\n", debugstr_a(imagepath));
420                 /* CRYPT_LoadProvider calls SetLastError */
421                 goto error;
422         }
423         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
424         {
425                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
426                  *       and thus, the CryptReleaseContext function need not be called afterwards.
427                  *       Therefore, we must clean up everything now.
428                  */
429                 if (dwFlags & CRYPT_DELETEKEYSET)
430                 {
431                         FreeLibrary(pProv->hModule);
432                         CRYPT_Free(provname);
433                         CRYPT_Free(pProv->pFuncs);
434                         CRYPT_Free(pProv);
435                 } else {
436                         pProv->pVTable->pszProvName = provname;
437                         pProv->pVTable->dwProvType = dwProvType;
438                         *phProv = (HCRYPTPROV)pProv;
439                 }
440                 return TRUE;
441         }
442         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
443 error:
444         if (pProv)
445         {
446                 FreeLibrary(pProv->hModule);
447                 CRYPT_Free(pProv->pVTable);
448                 CRYPT_Free(pProv->pFuncs);
449                 CRYPT_Free(pProv);
450         }
451         CRYPT_Free(provname);
452         CRYPT_Free(temp);
453         CRYPT_Free(imagepath);
454         CRYPT_Free(keyname);
455         return FALSE;
456 }
457
458 /******************************************************************************
459  * CryptAcquireContextW (ADVAPI32.@)
460  */
461 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
462                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
463 {
464         PSTR pProvider = NULL, pContainer = NULL;
465         BOOL ret = FALSE;
466
467         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
468                 debugstr_w(pszProvider), dwProvType, dwFlags);
469
470         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
471                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
472         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
473         {
474                 CRYPT_Free(pContainer);
475                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
476         }
477
478         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
479
480         if (pContainer)
481                 CRYPT_Free(pContainer);
482         if (pProvider)
483                 CRYPT_Free(pProvider);
484
485         return ret;
486 }
487
488 /******************************************************************************
489  * CryptContextAddRef (ADVAPI32.@)
490  */
491 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
492 {
493         FIXME("(0x%lx, %p, %08lx): stub!\n", hProv, pdwReserved, dwFlags);
494         return FALSE;
495         /* InterlockIncrement?? */
496 }
497
498 /******************************************************************************
499  * CryptReleaseContext (ADVAPI32.@)
500  */
501 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
502 {
503         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
504         BOOL ret;
505
506         TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
507
508         if (!pProv)
509         {
510                 SetLastError(NTE_BAD_UID);
511                 return FALSE;
512         }
513         /* FIXME: Decrement the counter here first if possible */
514         ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
515         FreeLibrary(pProv->hModule);
516 #if 0
517         CRYPT_Free(pProv->pVTable->pContextInfo);
518 #endif
519         CRYPT_Free(pProv->pVTable->pszProvName);
520         CRYPT_Free(pProv->pVTable);
521         CRYPT_Free(pProv->pFuncs);
522         CRYPT_Free(pProv);
523         return ret;
524 }
525
526 /******************************************************************************
527  * CryptGenRandom (ADVAPI32.@)
528  */
529 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
530 {
531         PCRYPTPROV prov = (PCRYPTPROV)hProv;
532
533         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
534
535         if (!hProv)
536                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
537
538         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
539 }
540
541 /******************************************************************************
542  * CryptCreateHash (ADVAPI32.@)
543  */
544 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
545                 DWORD dwFlags, HCRYPTHASH *phHash)
546 {
547         PCRYPTPROV prov = (PCRYPTPROV)hProv;
548         PCRYPTKEY key = (PCRYPTKEY)hKey;
549         PCRYPTHASH hash;
550
551         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
552
553         if (!prov)
554                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
555         if (!phHash)
556                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
557         if (dwFlags)
558                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
559         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
560                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
561
562         hash->pProvider = prov;
563
564         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
565                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
566         {
567             *phHash = (HCRYPTHASH)hash;
568             return TRUE;
569         }
570
571         /* CSP error! */
572         CRYPT_Free(hash);
573         return FALSE;
574 }
575
576 /******************************************************************************
577  * CryptDecrypt (ADVAPI32.@)
578  */
579 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
580                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
581 {
582         PCRYPTPROV prov;
583         PCRYPTKEY key = (PCRYPTKEY)hKey;
584         PCRYPTHASH hash = (PCRYPTHASH)hHash;
585
586         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
587
588         if (!key || !pbData || !pdwDataLen)
589                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
590
591         prov = key->pProvider;
592         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
593                         Final, dwFlags, pbData, pdwDataLen);
594 }
595
596 /******************************************************************************
597  * CryptDeriveKey (ADVAPI32.@)
598  */
599 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
600                 DWORD dwFlags, HCRYPTKEY *phKey)
601 {
602         PCRYPTPROV prov = (PCRYPTPROV)hProv;
603         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
604         PCRYPTKEY key;
605
606         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
607
608         if (!prov || !hash)
609                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
610         if (!phKey)
611                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
612         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
613                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
614
615         key->pProvider = prov;
616         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
617         {
618             *phKey = (HCRYPTKEY)key;
619             return TRUE;
620         }
621
622         /* CSP error! */
623         CRYPT_Free(key);
624         return FALSE;
625 }
626
627 /******************************************************************************
628  * CryptDestroyHash (ADVAPI32.@)
629  */
630 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
631 {
632         PCRYPTHASH hash = (PCRYPTHASH)hHash;
633         PCRYPTPROV prov;
634         BOOL ret;
635
636         TRACE("(0x%lx)\n", hHash);
637
638         if (!hash)
639                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
640
641         prov = hash->pProvider;
642         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
643         CRYPT_Free(hash);
644         return ret;
645 }
646
647 /******************************************************************************
648  *  CryptDestroyKey (ADVAPI32.@)
649  */
650 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
651 {
652         PCRYPTKEY key = (PCRYPTKEY)hKey;
653         PCRYPTPROV prov;
654         BOOL ret;
655
656         TRACE("(0x%lx)\n", hKey);
657
658         if (!key)
659                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
660
661         prov = key->pProvider;
662         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
663         CRYPT_Free(key);
664         return ret;
665 }
666
667 /******************************************************************************
668  * CryptDuplicateHash (ADVAPI32.@)
669  */
670 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
671                 DWORD dwFlags, HCRYPTHASH *phHash)
672 {
673         PCRYPTPROV prov;
674         PCRYPTHASH orghash, newhash;
675
676         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
677
678         orghash = (PCRYPTHASH)hHash;
679         if (!orghash || pdwReserved || !phHash)
680                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
681
682         prov = orghash->pProvider;
683         if (!prov->pFuncs->pCPDuplicateHash)
684                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
685
686         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
687                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
688
689         newhash->pProvider = prov;
690         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
691         {
692                 *phHash = (HCRYPTHASH)newhash;
693                 return TRUE;
694         }
695         CRYPT_Free(newhash);
696         return FALSE;
697 }
698
699 /******************************************************************************
700  * CryptDuplicateKey (ADVAPI32.@)
701  */
702 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
703 {
704         PCRYPTPROV prov;
705         PCRYPTKEY orgkey, newkey;
706
707         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
708
709         orgkey = (PCRYPTKEY)hKey;
710         if (!orgkey || pdwReserved || !phKey)
711                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
712
713         prov = orgkey->pProvider;
714         if (!prov->pFuncs->pCPDuplicateKey)
715                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
716
717         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
718                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
719
720         newkey->pProvider = prov;
721         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
722         {
723                 *phKey = (HCRYPTKEY)newkey;
724                 return TRUE;
725         }
726         CRYPT_Free(newkey);
727         return FALSE;
728 }
729
730 /******************************************************************************
731  * CryptEncrypt (ADVAPI32.@)
732  */
733 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
734                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
735 {
736         PCRYPTPROV prov;
737         PCRYPTKEY key = (PCRYPTKEY)hKey;
738         PCRYPTHASH hash = (PCRYPTHASH)hHash;
739
740         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
741
742         if (!key || !pdwDataLen)
743                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
744
745         prov = key->pProvider;
746         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
747                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
748 }
749
750 /******************************************************************************
751  * CryptEnumProvidersA (ADVAPI32.@)
752  */
753 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
754                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
755 {
756         HKEY hKey;
757
758         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
759                         pdwProvType, pszProvName, pcbProvName);
760
761         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
762         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
763
764         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
765                 CRYPT_ReturnLastError(NTE_FAIL);
766
767         if (!pszProvName)
768         {
769                 DWORD numkeys;
770                 RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, pcbProvName, NULL, NULL, NULL, NULL, NULL, NULL);
771                 (*pcbProvName)++;
772                 if (dwIndex >= numkeys)
773                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
774         } else {
775                 DWORD size = sizeof(DWORD);
776                 HKEY subkey;
777                 if (RegEnumKeyA(hKey, dwIndex, pszProvName, *pcbProvName))
778                         return FALSE;
779                 if (RegOpenKeyA(hKey, pszProvName, &subkey))
780                         return FALSE;
781                 if (RegQueryValueExA(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size))
782                         return FALSE;
783                 RegCloseKey(subkey);
784         }
785         RegCloseKey(hKey);
786         return TRUE;
787 }
788
789 /******************************************************************************
790  * CryptEnumProvidersW (ADVAPI32.@)
791  */
792 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
793                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
794 {
795         PSTR str = NULL;
796         DWORD strlen;
797         BOOL ret; /* = FALSE; */
798
799         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
800                         pdwProvType, pszProvName, pcbProvName);
801
802         strlen = *pcbProvName / sizeof(WCHAR);
803         if ( pszProvName && (str = CRYPT_Alloc(strlen)) )
804                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
805         ret = CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
806         if (str)
807         {
808                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
809                 CRYPT_Free(str);
810         }
811         *pcbProvName = strlen * sizeof(WCHAR);
812         return ret;
813 }
814
815 /******************************************************************************
816  * CryptEnumProviderTypesA (ADVAPI32.@)
817  */
818 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
819                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
820 {
821         HKEY hKey, hSubkey;
822         DWORD keylen, numkeys;
823         PSTR keyname, ch;
824
825         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
826                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
827
828         if (pdwReserved || !pdwProvType || !pcbTypeName)
829                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
830         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
831
832         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
833                 return FALSE;
834
835         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
836         if (dwIndex >= numkeys)
837                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
838         keylen++;
839         if ( !(keyname = CRYPT_Alloc(keylen)) )
840                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
841         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
842                 CRYPT_Free(keyname);
843                 return FALSE;
844         }
845         RegOpenKeyA(hKey, keyname, &hSubkey);
846         ch = keyname + strlen(keyname);
847         /* Convert "Type 000" to 0, etc/ */
848         *pdwProvType = *(--ch) - '0';
849         *pdwProvType += (*(--ch) - '0') * 10;
850         *pdwProvType += (*(--ch) - '0') * 100;
851         CRYPT_Free(keyname);
852         RegQueryValueA(hSubkey, "TypeName", pszTypeName, pcbTypeName);
853         RegCloseKey(hSubkey);
854         RegCloseKey(hKey);
855         return TRUE;
856 }
857
858 /******************************************************************************
859  * CryptEnumProviderTypesW (ADVAPI32.@)
860  */
861 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
862                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
863 {
864         PSTR str = NULL;
865         DWORD strlen;
866         BOOL ret;
867
868         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
869                         pdwProvType, pszTypeName, pcbTypeName);
870         strlen = *pcbTypeName / sizeof(WCHAR);
871         if ( pszTypeName && (str = CRYPT_Alloc(strlen)) )
872                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
873         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
874         if (str)
875         {
876                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
877                 CRYPT_Free(str);
878         }
879         *pcbTypeName = strlen * sizeof(WCHAR);
880         return ret;
881 }
882
883 /******************************************************************************
884  * CryptExportKey (ADVAPI32.@)
885  */
886 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
887                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
888 {
889         PCRYPTPROV prov;
890         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
891
892         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
893
894         if (!key || pdwDataLen)
895                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
896
897         prov = key->pProvider;
898         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
899                         dwBlobType, dwFlags, pbData, pdwDataLen);
900 }
901
902 /******************************************************************************
903  * CryptGenKey (ADVAPI32.@)
904  */
905 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
906 {
907         PCRYPTPROV prov = (PCRYPTPROV)hProv;
908         PCRYPTKEY key;
909
910         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
911
912         if (!prov)
913                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
914         if (!phKey)
915                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
916         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
917                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
918
919         key->pProvider = prov;
920
921         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
922         {
923             *phKey = (HCRYPTKEY)key;
924             return TRUE;
925         }
926
927         /* CSP error! */
928         CRYPT_Free(key);
929         return FALSE;
930 }
931
932 /******************************************************************************
933  * CryptGetDefaultProviderA (ADVAPI32.@)
934  */
935 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
936                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
937 {
938         HKEY hKey;
939         PSTR keyname;
940
941         if (pdwReserved || !pcbProvName)
942                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
943         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
944                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
945         if (dwProvType > 999)
946                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
947         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
948                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
949         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
950         {
951                 CRYPT_Free(keyname);
952                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
953         }
954         CRYPT_Free(keyname);
955         if (RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName))
956         {
957                 if (GetLastError() != ERROR_MORE_DATA)
958                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
959                 return FALSE;
960         }
961         RegCloseKey(hKey);
962         return TRUE;
963 }
964
965 /******************************************************************************
966  * CryptGetDefaultProviderW (ADVAPI32.@)
967  */
968 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
969                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
970 {
971         PSTR str = NULL;
972         DWORD strlen;
973         BOOL ret = FALSE;
974
975         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
976
977         strlen = *pcbProvName / sizeof(WCHAR);
978         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
979                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
980         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
981         if (str)
982         {
983                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
984                 CRYPT_Free(str);
985         }
986         *pcbProvName = strlen * sizeof(WCHAR);
987         return ret;
988 }
989
990 /******************************************************************************
991  * CryptGetHashParam (ADVAPI32.@)
992  */
993 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
994                 DWORD *pdwDataLen, DWORD dwFlags)
995 {
996         PCRYPTPROV prov;
997         PCRYPTHASH hash = (PCRYPTHASH)hHash;
998
999         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1000
1001         if (!hash || !pdwDataLen)
1002                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1003
1004         prov = hash->pProvider;
1005         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1006                         pbData, pdwDataLen, dwFlags);
1007 }
1008
1009 /******************************************************************************
1010  * CryptGetKeyParam (ADVAPI32.@)
1011  */
1012 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1013                 DWORD *pdwDataLen, DWORD dwFlags)
1014 {
1015         PCRYPTPROV prov;
1016         PCRYPTKEY key = (PCRYPTKEY)hKey;
1017
1018         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1019
1020         if (!key || !pdwDataLen)
1021                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1022
1023         prov = key->pProvider;
1024         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1025                         pbData, pdwDataLen, dwFlags);
1026 }
1027
1028 /******************************************************************************
1029  * CryptGetProvParam (ADVAPI32.@)
1030  */
1031 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1032                 DWORD *pdwDataLen, DWORD dwFlags)
1033 {
1034         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1035
1036         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1037
1038         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1039 }
1040
1041 /******************************************************************************
1042  * CryptGetUserKey (ADVAPI32.@)
1043  */
1044 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1045 {
1046         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1047         PCRYPTKEY key;
1048
1049         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1050
1051         if (!prov)
1052                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1053         if (!phUserKey)
1054                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1055         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1056                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1057
1058         key->pProvider = prov;
1059
1060         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1061         {
1062             *phUserKey = (HCRYPTKEY)key;
1063             return TRUE;
1064         }
1065
1066         /* CSP Error */
1067         CRYPT_Free(key);
1068         return FALSE;
1069 }
1070
1071 /******************************************************************************
1072  * CryptHashData (ADVAPI32.@)
1073  */
1074 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1075 {
1076         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1077         PCRYPTPROV prov;
1078
1079         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1080
1081         if (!hash)
1082                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1083         if (!pbData || !dwDataLen)
1084                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1085
1086         prov = hash->pProvider;
1087         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1088 }
1089
1090 /******************************************************************************
1091  * CryptHashSessionKey (ADVAPI32.@)
1092  */
1093 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1094 {
1095         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1096         PCRYPTKEY key = (PCRYPTKEY)hKey;
1097         PCRYPTPROV prov;
1098
1099         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1100
1101         if (!hash || !key)
1102                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1103
1104         prov = hash->pProvider;
1105         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1106 }
1107
1108 /******************************************************************************
1109  * CryptImportKey (ADVAPI32.@)
1110  */
1111 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1112                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1113 {
1114         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1115         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1116
1117         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1118
1119         if (!prov || !pbData || !dwDataLen || !phKey)
1120                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1121
1122         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1123                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1124
1125         importkey->pProvider = prov;
1126         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1127                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1128         {
1129                 *phKey = (HCRYPTKEY)importkey;
1130                 return TRUE;
1131         }
1132
1133         CRYPT_Free(importkey);
1134         return FALSE;
1135 }
1136
1137 /******************************************************************************
1138  * CryptSignHashA
1139  *
1140  * Note: Since the sDesciption (string) is supposed to be NULL and
1141  *      is only retained for compatibility no string conversions are required
1142  *      and only one implementation is required for both ANSI and Unicode.
1143  *      We still need to export both:
1144  *
1145  * CryptSignHashA (ADVAPI32.@)
1146  * CryptSignHashW (ADVAPI32.@)
1147  */
1148 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1149                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1150 {
1151         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1152         PCRYPTPROV prov;
1153
1154         TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1155         if (sDescription)
1156                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1157
1158         if (!hash)
1159                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1160         if (!pdwSigLen)
1161                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1162
1163         prov = hash->pProvider;
1164         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1165                 dwFlags, pbSignature, pdwSigLen);
1166 }
1167
1168 /******************************************************************************
1169  * CryptSetHashParam (ADVAPI32.@)
1170  */
1171 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1172 {
1173         PCRYPTPROV prov;
1174         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1175
1176         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1177
1178         if (!hash || !pbData)
1179                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1180
1181         prov = hash->pProvider;
1182         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1183                         dwParam, pbData, dwFlags);
1184 }
1185
1186 /******************************************************************************
1187  * CryptSetKeyParam (ADVAPI32.@)
1188  */
1189 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1190 {
1191         PCRYPTPROV prov;
1192         PCRYPTKEY key = (PCRYPTKEY)hKey;
1193
1194         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1195
1196         if (!key || !pbData)
1197                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1198
1199         prov = key->pProvider;
1200         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1201                         dwParam, pbData, dwFlags);
1202 }
1203
1204 /******************************************************************************
1205  * CryptSetProviderA (ADVAPI32.@)
1206  */
1207 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1208 {
1209         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1210         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1211 }
1212
1213 /******************************************************************************
1214  * CryptSetProviderW (ADVAPI32.@)
1215  */
1216 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1217 {
1218         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1219         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1220 }
1221
1222 /******************************************************************************
1223  * CryptSetProviderExA (ADVAPI32.@)
1224  */
1225 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1226 {
1227         HKEY hKey;
1228         PSTR keyname;
1229
1230         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1231
1232         if (!pszProvName || pdwReserved)
1233                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1234         if (dwProvType > MAXPROVTYPES)
1235                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1236         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1237                         || dwFlags == CRYPT_DELETE_DEFAULT)
1238                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1239
1240         if (dwFlags & CRYPT_DELETE_DEFAULT)
1241         {
1242                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1243                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1244                 RegDeleteKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname);
1245                 CRYPT_Free(keyname);
1246                 return TRUE;
1247         }
1248
1249         if ( !(keyname = CRYPT_GetProvKeyName(pszProvName)) )
1250                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1251         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &hKey))
1252         {
1253                 CRYPT_Free(keyname);
1254                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1255         }
1256         CRYPT_Free(keyname);
1257         RegCloseKey(hKey);
1258         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1259                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1260         RegCreateKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname, &hKey);
1261         CRYPT_Free(keyname);
1262         if (RegSetValueExA(hKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) +1))
1263                 return FALSE;
1264         return TRUE;
1265 }
1266
1267 /******************************************************************************
1268  * CryptSetProviderExW (ADVAPI32.@)
1269  */
1270 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1271 {
1272         BOOL ret = FALSE;
1273         PSTR str = NULL;
1274
1275         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1276
1277         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1278         {
1279                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1280                 CRYPT_Free(str);
1281         }
1282         return ret;
1283 }
1284
1285 /******************************************************************************
1286  * CryptSetProvParam (ADVAPI32.@)
1287  */
1288 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1289 {
1290         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1291
1292         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1293
1294         if (!prov)
1295                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1296         if (dwFlags & PP_USE_HARDWARE_RNG)
1297         {
1298                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1299                 FIXME("\tLetting the CSP decide.\n");
1300         }
1301         if (dwFlags & PP_CLIENT_HWND)
1302         {
1303                 /* FIXME: Should verify the parameter */
1304                 if (pbData /* && IsWindow((HWND)pbData) */)
1305                 {
1306                         crypt_hWindow = (HWND)(pbData);
1307                         return TRUE;
1308                 } else {
1309                         SetLastError(ERROR_INVALID_PARAMETER);
1310                         return FALSE;
1311                 }
1312         }
1313         /* All other flags go to the CSP */
1314         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1315 }
1316
1317 /******************************************************************************
1318  * CryptVerifySignatureA
1319  *
1320  * Note: Since the sDesciption (string) is supposed to be NULL and
1321  *      is only retained for compatibility no string conversions are required
1322  *      and only one implementation is required for both ANSI and Unicode.
1323  *      We still need to export both:
1324  *
1325  * CryptVerifySignatureA (ADVAPI32.@)
1326  * CryptVerifySignatureW (ADVAPI32.@)
1327  */
1328 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1329                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1330 {
1331         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1332         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1333         PCRYPTPROV prov;
1334
1335         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1336                         dwSigLen, hPubKey, dwFlags);
1337         if (sDescription)
1338                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1339
1340         if (!hash || !key)
1341                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1342         if (!pbSignature || !dwSigLen)
1343                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1344
1345         prov = hash->pProvider;
1346         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1347                 key->hPrivate, NULL, dwFlags);
1348 }