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