ShellExecuteEx, ExtractIconEx, SHFileOperation, SHGetFileInfo,
[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 "crypt.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "wine/debug.h"
36 #include "winternl.h"
37 #include "ntstatus.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
40
41 HWND crypt_hWindow = 0;
42
43 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
44
45 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
46 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
47
48 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
49 {
50         PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
51         PSTR keyname;
52
53         keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
54         if (keyname)
55         {
56                 strcpy(keyname, KEYSTR);
57                 strcpy(keyname + strlen(KEYSTR), pProvName);
58         } else
59                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
60         return keyname;
61 }
62
63 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
64 {
65         PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
66         PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
67         PSTR keyname;
68         PSTR ptr;
69
70         keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
71         if (keyname)
72         {
73                 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
74                 ptr = keyname + strlen(keyname);
75                 *(--ptr) = (dwType % 10) + '0';
76                 *(--ptr) = ((dwType / 10) % 10) + '0';
77                 *(--ptr) = (dwType / 100) + '0';
78         } else
79                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
80         return keyname;
81 }
82
83 /* CRYPT_UnicodeTOANSI
84  * wstr - unicode string
85  * str - pointer to ANSI string
86  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
87  *
88  * returns TRUE if unsuccessfull, FALSE otherwise.
89  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
90  */
91 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
92 {
93         int count;
94
95         if (!wstr)
96         {
97                 *str = NULL;
98                 return TRUE;
99         }
100         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
101         count = count < strsize ? count : strsize;
102         if (strsize == -1)
103                 *str = CRYPT_Alloc(count * sizeof(CHAR));
104         if (*str)
105         {
106                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
107                 return TRUE;
108         }
109         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
110         return FALSE;
111 }
112
113 /* CRYPT_ANSITOUnicode
114  * str - ANSI string
115  * wstr - pointer to unicode string
116  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
117  */
118 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
119 {
120         int wcount;
121
122         if (!str)
123         {
124                 *wstr = NULL;
125                 return TRUE;
126         }
127         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
128         wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR);
129         if (wstrsize == -1)
130                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
131         if (*wstr)
132         {
133                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
134                 return TRUE;
135         }
136         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
137         return FALSE;
138 }
139
140 /* These next 2 functions are used by the VTableProvStruc structure */
141 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
142 {
143         if (!lpszImage || !pData)
144         {
145                 SetLastError(ERROR_INVALID_PARAMETER);
146                 return FALSE;
147         }
148
149         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
150
151         return TRUE;
152 }
153
154 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
155 {
156         if (!phWnd)
157                 return FALSE;
158         *phWnd = crypt_hWindow;
159         return TRUE;
160 }
161
162 #define CRYPT_GetProvFunc(name) \
163         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
164 #define CRYPT_GetProvFuncOpt(name) \
165         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
166 PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
167 {
168         PCRYPTPROV provider;
169         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
170
171         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
172         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
173         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
174         if ( !(provider->hModule = LoadLibraryA(pImage)) )
175         {
176                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
177                 FIXME("Failed to load dll %s\n", debugstr_a(pImage));
178                 goto error;
179         }
180         provider->refcount = 1;
181
182         errorcode = NTE_PROVIDER_DLL_FAIL;
183         CRYPT_GetProvFunc(CPAcquireContext);
184         CRYPT_GetProvFunc(CPCreateHash);
185         CRYPT_GetProvFunc(CPDecrypt);
186         CRYPT_GetProvFunc(CPDeriveKey);
187         CRYPT_GetProvFunc(CPDestroyHash);
188         CRYPT_GetProvFunc(CPDestroyKey);
189         CRYPT_GetProvFuncOpt(CPDuplicateHash);
190         CRYPT_GetProvFuncOpt(CPDuplicateKey);
191         CRYPT_GetProvFunc(CPEncrypt);
192         CRYPT_GetProvFunc(CPExportKey);
193         CRYPT_GetProvFunc(CPGenKey);
194         CRYPT_GetProvFunc(CPGenRandom);
195         CRYPT_GetProvFunc(CPGetHashParam);
196         CRYPT_GetProvFunc(CPGetKeyParam);
197         CRYPT_GetProvFunc(CPGetProvParam);
198         CRYPT_GetProvFunc(CPGetUserKey);
199         CRYPT_GetProvFunc(CPHashData);
200         CRYPT_GetProvFunc(CPHashSessionKey);
201         CRYPT_GetProvFunc(CPImportKey);
202         CRYPT_GetProvFunc(CPReleaseContext);
203         CRYPT_GetProvFunc(CPSetHashParam);
204         CRYPT_GetProvFunc(CPSetKeyParam);
205         CRYPT_GetProvFunc(CPSetProvParam);
206         CRYPT_GetProvFunc(CPSignHash);
207         CRYPT_GetProvFunc(CPVerifySignature);
208
209         /* FIXME: Not sure what the pbContextInfo field is for.
210          *        Does it need memory allocation?
211          */
212         provider->pVTable->Version = 3;
213         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
214         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
215         provider->pVTable->dwProvType = 0;
216         provider->pVTable->pbContextInfo = NULL;
217         provider->pVTable->cbContextInfo = 0;
218         provider->pVTable->pszProvName = NULL;
219         return provider;
220
221 error:
222         SetLastError(errorcode);
223         if (provider)
224         {
225                 if (provider->hModule)
226                         FreeLibrary(provider->hModule);
227                 CRYPT_Free(provider->pVTable);
228                 CRYPT_Free(provider->pFuncs);
229                 CRYPT_Free(provider);
230         }
231         return NULL;
232 }
233 #undef CRYPT_GetProvFunc
234 #undef CRYPT_GetProvFuncOpt
235
236
237 /******************************************************************************
238  * CryptAcquireContextA (ADVAPI32.@)
239  * Acquire a crypto provider context handle.
240  *
241  * PARAMS
242  * phProv: Pointer to HCRYPTPROV for the output.
243  * pszContainer: Key Container Name
244  * pszProvider: Cryptographic Service Provider Name
245  * dwProvType: Crypto provider type to get a handle.
246  * dwFlags: flags for the operation
247  *
248  * RETURNS TRUE on success, FALSE on failure.
249  */
250 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
251                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
252 {
253         PCRYPTPROV pProv = NULL;
254         HKEY key;
255         PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
256         BYTE* signature;
257         DWORD keytype, type, len;
258         ULONG r;
259
260         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
261                 pszProvider, dwProvType, dwFlags);
262
263         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
264         {
265                 SetLastError(NTE_BAD_PROV_TYPE);
266                 return FALSE;
267         }
268         
269         if (!phProv)
270         {
271                 SetLastError(ERROR_INVALID_PARAMETER);
272                 return FALSE;
273         }
274
275         if (!pszProvider || !*pszProvider)
276         {
277                 /* No CSP name specified so try the user default CSP first
278                  * then try the machine default CSP
279                  */
280                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
281                         TRACE("No provider registered for crypto provider type %ld.\n", dwProvType);
282                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
283                         return FALSE;
284                 }
285                 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
286                 {
287                         CRYPT_Free(keyname);
288                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
289                                 TRACE("No type registered for crypto provider type %ld.\n", dwProvType);
290                                 RegCloseKey(key);
291                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
292                                 goto error;
293                         }
294                         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
295                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
296                                 CRYPT_Free(keyname);
297                                 RegCloseKey(key);
298                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
299                                 goto error;
300                         }
301                 }
302                 CRYPT_Free(keyname);
303                 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
304                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
305                 {
306                         TRACE("error %ld reading size of 'Name' from registry\n", r );
307                         RegCloseKey(key);
308                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
309                         goto error;
310                 }
311                 if(!(provname = CRYPT_Alloc(len)))
312                 {
313                         RegCloseKey(key);
314                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
315                         goto error;
316                 }
317                 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
318                 if( r != ERROR_SUCCESS )
319                 {
320                         TRACE("error %ld reading 'Name' from registry\n", r );
321                         RegCloseKey(key);
322                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
323                         goto error;
324                 }
325                 RegCloseKey(key);
326         } else {
327                 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
328                 {
329                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
330                         goto error;
331                 }
332                 strcpy(provname, pszProvider);
333         }
334
335         keyname = CRYPT_GetProvKeyName(provname);
336         r = RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key);
337         CRYPT_Free(keyname);
338         if (r != ERROR_SUCCESS)
339         {
340                 SetLastError(NTE_KEYSET_NOT_DEF);
341                 goto error;
342         }
343         len = sizeof(DWORD);
344         r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
345         if (r != ERROR_SUCCESS)
346         {
347                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
348                 goto error;
349         }
350         if (type != dwProvType)
351         {
352                 TRACE("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
353                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
354                 goto error;
355         }
356
357         r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
358         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
359         {
360                 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
361                 RegCloseKey(key);
362                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
363                 goto error;
364         }
365         if (!(temp = CRYPT_Alloc(len)))
366         {
367                 RegCloseKey(key);
368                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
369                 goto error;
370         }
371         r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
372         if( r != ERROR_SUCCESS )
373         {
374                 TRACE("error %ld reading 'Image Path' from registry\n", r );
375                 RegCloseKey(key);
376                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
377                 goto error;
378         }
379
380         r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
381         if ( r == ERROR_SUCCESS && keytype == REG_BINARY )
382         {
383                 if (!(signature = CRYPT_Alloc(len)))
384                 {
385                         RegCloseKey(key);
386                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
387                         goto error;
388                 }
389                 r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
390                 if ( r != ERROR_SUCCESS )
391                 {
392                         TRACE("error %ld reading 'Signature'\n", r );
393                         CRYPT_Free(signature);
394                         RegCloseKey(key);
395                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
396                         goto error;
397                 }
398         }
399         else
400         {
401                 r = RegQueryValueExA(key, "SigInFile", NULL, &keytype, NULL, &len);
402                 if (r != ERROR_SUCCESS)
403                 {
404                         TRACE("error %ld reading size of 'SigInFile'\n", r );
405                         RegCloseKey(key);
406                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
407                         goto error;
408                 }
409                 else
410                 {
411                         /* FIXME: The presence of the SigInFile value indicates the
412                          * provider's signature is in its resources, so need to read it.
413                          * But since CRYPT_VerifyImage is stubbed, provide any old thing
414                          * for now.
415                          */
416                         if (!(signature = CRYPT_Alloc(1)))
417                         {
418                                 RegCloseKey(key);
419                                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
420                                 goto error;
421                         }
422                 }
423         }
424         RegCloseKey(key);
425         len = ExpandEnvironmentStringsA(temp, NULL, 0);
426         if ( !(imagepath = CRYPT_Alloc(len)) )
427         {
428                 CRYPT_Free(signature);
429                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
430                 goto error;
431         }
432         if (!ExpandEnvironmentStringsA(temp, imagepath, len))
433         {
434                 CRYPT_Free(signature);
435                 /* ExpandEnvironmentStrings will call SetLastError */
436                 goto error;
437         }
438
439         if (!CRYPT_VerifyImage(imagepath, signature))
440         {
441                 CRYPT_Free(signature);
442                 SetLastError(NTE_SIGNATURE_FILE_BAD);
443                 goto error;
444         }
445         pProv = CRYPT_LoadProvider(imagepath);
446         CRYPT_Free(signature);
447         if (!pProv) {
448                 /* CRYPT_LoadProvider calls SetLastError */
449                 goto error;
450         }
451         pProv->pVTable->dwProvType = dwProvType;
452         pProv->pVTable->pszProvName = provname;
453         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
454         {
455                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
456                  *       and thus, the CryptReleaseContext function need not be called afterwards.
457                  *       Therefore, we must clean up everything now.
458                  */
459                 if (dwFlags & CRYPT_DELETEKEYSET)
460                 {
461                         FreeLibrary(pProv->hModule);
462                         CRYPT_Free(provname);
463                         CRYPT_Free(pProv->pFuncs);
464                         CRYPT_Free(pProv);
465                 } else {
466                         *phProv = (HCRYPTPROV)pProv;
467                 }
468                 CRYPT_Free(temp);
469                 CRYPT_Free(imagepath);
470                 return TRUE;
471         }
472         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
473 error:
474         if (pProv)
475         {
476                 if (pProv->hModule)
477                         FreeLibrary(pProv->hModule);
478                 if (pProv->pVTable)
479                         CRYPT_Free(pProv->pVTable);
480                 if (pProv->pFuncs)
481                         CRYPT_Free(pProv->pFuncs);
482                 CRYPT_Free(pProv);
483         }
484         if (provname)
485                 CRYPT_Free(provname);
486         if (temp)
487                 CRYPT_Free(temp);
488         if (imagepath)
489                 CRYPT_Free(imagepath);
490         return FALSE;
491 }
492
493 /******************************************************************************
494  * CryptAcquireContextW (ADVAPI32.@)
495  *
496  * see CryptAcquireContextA
497  */
498 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
499                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
500 {
501         PSTR pProvider = NULL, pContainer = NULL;
502         BOOL ret = FALSE;
503
504         TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
505                 debugstr_w(pszProvider), dwProvType, dwFlags);
506
507         if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
508                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
509         if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
510         {
511                 CRYPT_Free(pContainer);
512                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
513         }
514
515         ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
516
517         if (pContainer)
518                 CRYPT_Free(pContainer);
519         if (pProvider)
520                 CRYPT_Free(pProvider);
521
522         return ret;
523 }
524
525 /******************************************************************************
526  * CryptContextAddRef (ADVAPI32.@)
527  *
528  * Increases reference count of a cryptographic service provider handle
529  * by one.
530  *
531  * PARAMS
532  *  hProv       [I] Handle to the CSP whose reference is being incremented.
533  *  pdwReserved [IN] Reserved for future use and must be NULL.
534  *  dwFlags     [I] Reserved for future use and must be NULL.
535  *
536  * RETURNS
537  *  Success: TRUE
538  *  Failure: FALSE
539  */
540 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
541 {
542         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
543
544         TRACE("(0x%lx, %p, %08lx)\n", hProv, pdwReserved, dwFlags);
545
546         if (!pProv)
547         {
548                 SetLastError(NTE_BAD_UID);
549                 return FALSE;
550         }
551
552         pProv->refcount++;
553         return TRUE;
554 }
555
556 /******************************************************************************
557  * CryptReleaseContext (ADVAPI32.@)
558  *
559  * Releases the handle of a CSP.  Reference count is decreased.
560  *
561  * PARAMS
562  *  hProv   [I] Handle of a CSP.
563  *  dwFlags [I] Reserved for future use and must be NULL.
564  *
565  * RETURNS
566  *  Success: TRUE
567  *  Failure: FALSE
568  */
569 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
570 {
571         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
572         BOOL ret = TRUE;
573
574         TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
575
576         if (!pProv)
577         {
578                 SetLastError(NTE_BAD_UID);
579                 return FALSE;
580         }
581
582         pProv->refcount--;
583         if (pProv->refcount <= 0) 
584         {
585                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
586                 FreeLibrary(pProv->hModule);
587 #if 0
588                 CRYPT_Free(pProv->pVTable->pContextInfo);
589 #endif
590                 CRYPT_Free(pProv->pVTable->pszProvName);
591                 CRYPT_Free(pProv->pVTable);
592                 CRYPT_Free(pProv->pFuncs);
593                 CRYPT_Free(pProv);
594         }
595         return ret;
596 }
597
598 /******************************************************************************
599  * CryptGenRandom (ADVAPI32.@)
600  *
601  * Fills a buffer with cryptographically random bytes.
602  *
603  * PARAMS
604  *  hProv    [I] Handle of a CSP.
605  *  dwLen    [I] Number of bytes to generate.
606  *  pbBuffer [I/O] Buffer to contain random bytes.
607  *
608  * RETURNS
609  *  Success: TRUE
610  *  Failure: FALSE
611  *
612  * NOTES
613  *  pdBuffer must be at least dwLen bytes long.
614  */
615 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
616 {
617         PCRYPTPROV prov = (PCRYPTPROV)hProv;
618
619         TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
620
621         if (!hProv)
622                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
623
624         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
625 }
626
627 /******************************************************************************
628  * CryptCreateHash (ADVAPI32.@)
629  *
630  * Initiates the hashing of a stream of data.
631  *
632  * PARAMS
633  *  hProv   [I] Handle of a CSP.
634  *  Algid   [I] Identifies the hash algorithm to use.
635  *  hKey    [I] Key for the hash (if required).
636  *  dwFlags [I] Reserved for future use and must be NULL.
637  *  phHash  [O] Address of the future handle to the new hash object.
638  *
639  * RETURNS
640  *  Success: TRUE
641  *  Failure: FALSE
642  *
643  * NOTES
644  *  If the algorithm is a keyed hash, hKey is the key.
645  */
646 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
647                 DWORD dwFlags, HCRYPTHASH *phHash)
648 {
649         PCRYPTPROV prov = (PCRYPTPROV)hProv;
650         PCRYPTKEY key = (PCRYPTKEY)hKey;
651         PCRYPTHASH hash;
652
653         TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
654
655         if (!prov)
656                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
657         if (!phHash)
658                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
659         if (dwFlags)
660                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
661         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
662                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
663
664         hash->pProvider = prov;
665
666         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
667                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
668         {
669             *phHash = (HCRYPTHASH)hash;
670             return TRUE;
671         }
672
673         /* CSP error! */
674         CRYPT_Free(hash);
675         *phHash = 0;
676         return FALSE;
677 }
678
679 /******************************************************************************
680  * CryptDecrypt (ADVAPI32.@)
681  *
682  * Decrypts data encrypted by CryptEncrypt.
683  *
684  * PARAMS
685  *  hKey       [I] Handle to the decryption key.
686  *  hHash      [I] Handle to a hash object.
687  *  Final      [I] TRUE if this is the last section to be decrypted.
688  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
689  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
690  *                   data on return
691  *  pdwDataLen [I/O] Length of pbData before and after the call.
692  *
693  *  RETURNS
694  *   Success: TRUE
695  *   Failure: FALSE
696  */
697 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
698                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
699 {
700         PCRYPTPROV prov;
701         PCRYPTKEY key = (PCRYPTKEY)hKey;
702         PCRYPTHASH hash = (PCRYPTHASH)hHash;
703
704         TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
705
706         if (!key || !pbData || !pdwDataLen)
707                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
708
709         prov = key->pProvider;
710         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
711                         Final, dwFlags, pbData, pdwDataLen);
712 }
713
714 /******************************************************************************
715  * CryptDeriveKey (ADVAPI32.@)
716  *
717  * Generates session keys derived from a base data value.
718  *
719  * PARAMS
720  *  hProv     [I] Handle to a CSP.
721  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
722  *  hBaseData [I] Handle to a hash object.
723  *  dwFlags   [I] Type of key to generate.
724  *  phKey     [I/O] Address of the newly generated key.
725  *
726  * RETURNS
727  *  Success: TRUE
728  *  Failure: FALSE
729  */
730 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
731                 DWORD dwFlags, HCRYPTKEY *phKey)
732 {
733         PCRYPTPROV prov = (PCRYPTPROV)hProv;
734         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
735         PCRYPTKEY key;
736
737         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
738
739         if (!prov || !hash)
740                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
741         if (!phKey)
742                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
743         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
744                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
745
746         key->pProvider = prov;
747         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
748         {
749             *phKey = (HCRYPTKEY)key;
750             return TRUE;
751         }
752
753         /* CSP error! */
754         CRYPT_Free(key);
755         *phKey = 0;
756         return FALSE;
757 }
758
759 /******************************************************************************
760  * CryptDestroyHash (ADVAPI32.@)
761  *
762  * Destroys the hash object referenced by hHash.
763  *
764  * PARAMS
765  *  hHash [I] Handle of the hash object to be destroyed.
766  *
767  * RETURNS
768  *  Success: TRUE
769  *  Failure: FALSE
770  */
771 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
772 {
773         PCRYPTHASH hash = (PCRYPTHASH)hHash;
774         PCRYPTPROV prov;
775         BOOL ret;
776
777         TRACE("(0x%lx)\n", hHash);
778
779         if (!hash)
780                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
781
782         prov = hash->pProvider;
783         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
784         CRYPT_Free(hash);
785         return ret;
786 }
787
788 /******************************************************************************
789  * CryptDestroyKey (ADVAPI32.@)
790  *
791  * Releases the handle referenced by hKey.
792  *
793  * PARAMS
794  *  hKey [I] Handle of the key to be destroyed.
795  *
796  * RETURNS
797  *  Success: TRUE
798  *  Failure: FALSE
799  */
800 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
801 {
802         PCRYPTKEY key = (PCRYPTKEY)hKey;
803         PCRYPTPROV prov;
804         BOOL ret;
805
806         TRACE("(0x%lx)\n", hKey);
807
808         if (!key)
809                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
810
811         prov = key->pProvider;
812         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
813         CRYPT_Free(key);
814         return ret;
815 }
816
817 /******************************************************************************
818  * CryptDuplicateHash (ADVAPI32.@)
819  *
820  * Duplicates a hash.
821  *
822  * PARAMS
823  *  hHash       [I] Handle to the hash to be copied.
824  *  pdwReserved [I] Reserved for future use and must be zero.
825  *  dwFlags     [I] Reserved for future use and must be zero.
826  *  phHash      [O] Address of the handle to receive the copy.
827  *
828  * RETURNS
829  *  Success: TRUE
830  *  Failure: FALSE
831  */
832 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
833                 DWORD dwFlags, HCRYPTHASH *phHash)
834 {
835         PCRYPTPROV prov;
836         PCRYPTHASH orghash, newhash;
837
838         TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
839
840         orghash = (PCRYPTHASH)hHash;
841         if (!orghash || pdwReserved || !phHash)
842                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
843
844         prov = orghash->pProvider;
845         if (!prov->pFuncs->pCPDuplicateHash)
846                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
847
848         if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
849                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
850
851         newhash->pProvider = prov;
852         if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
853         {
854                 *phHash = (HCRYPTHASH)newhash;
855                 return TRUE;
856         }
857         CRYPT_Free(newhash);
858         return FALSE;
859 }
860
861 /******************************************************************************
862  * CryptDuplicateKey (ADVAPI32.@)
863  *
864  * Duplicate a key and the key's state.
865  *
866  * PARAMS
867  *  hKey        [I] Handle of the key to copy.
868  *  pdwReserved [I] Reserved for future use and must be NULL.
869  *  dwFlags     [I] Reserved for future use and must be zero.
870  *  phKey       [I] Address of the handle to the duplicated key.
871  *
872  * RETURNS
873  *  Success: TRUE
874  *  Failure: FALSE
875  */
876 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
877 {
878         PCRYPTPROV prov;
879         PCRYPTKEY orgkey, newkey;
880
881         TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
882
883         orgkey = (PCRYPTKEY)hKey;
884         if (!orgkey || pdwReserved || !phKey)
885                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
886
887         prov = orgkey->pProvider;
888         if (!prov->pFuncs->pCPDuplicateKey)
889                 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
890
891         if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
892                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
893
894         newkey->pProvider = prov;
895         if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
896         {
897                 *phKey = (HCRYPTKEY)newkey;
898                 return TRUE;
899         }
900         CRYPT_Free(newkey);
901         return FALSE;
902 }
903
904 /******************************************************************************
905  * CryptEncrypt (ADVAPI32.@)
906  *
907  * Encrypts data.
908  *
909  * PARAMS
910  *  hKey       [I] Handle to the enryption key.
911  *  hHash      [I] Handle to a hash object.
912  *  Final      [I] TRUE if this is the last section to encrypt.
913  *  dwFlags    [I] Can be CRYPT_OAEP.
914  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
915  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
916  *                   encrypted data after call.
917  *  dwBufLen   [I] Length of the input pbData buffer.
918  *
919  * RETURNS
920  *  Success: TRUE
921  *  Failure: FALSE
922  *
923  *  NOTES
924  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
925  *   required for the returned data in pdwDataLen.
926  */
927 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
928                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
929 {
930         PCRYPTPROV prov;
931         PCRYPTKEY key = (PCRYPTKEY)hKey;
932         PCRYPTHASH hash = (PCRYPTHASH)hHash;
933
934         TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
935
936         if (!key || !pdwDataLen)
937                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
938
939         prov = key->pProvider;
940         return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
941                         Final, dwFlags, pbData, pdwDataLen, dwBufLen);
942 }
943
944 /******************************************************************************
945  * CryptEnumProvidersW (ADVAPI32.@)
946  *
947  * Returns the next availabe CSP.
948  *
949  * PARAMS
950  *  dwIndex     [I] Index of the next provider to be enumerated.
951  *  pdwReserved [I] Reserved for future use and must be NULL.
952  *  dwFlags     [I] Reserved for future use and must be zero.
953  *  pdwProvType [O] DWORD designating the type of the provider.
954  *  pszProvName [O] Buffer that receives data from the provider.
955  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
956  *                    of bytes stored in the buffer on return.
957  *
958  *  RETURNS
959  *   Success: TRUE
960  *   Failure: FALSE
961  *
962  *  NOTES
963  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
964  *   for memory allocation purposes.
965  */
966 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
967                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
968 {
969         HKEY hKey;
970         
971         static const WCHAR providerW[] = {
972                 'S','o','f','t','w','a','r','e','\\',
973                 'M','i','c','r','o','s','o','f','t','\\',
974                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
975                 'D','e','f','a','u','l','t','s','\\',
976                 'P','r','o','v','i','d','e','r',0
977         };
978         
979         static const WCHAR typeW[] = {'T','y','p','e',0};
980
981         TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
982                         pdwProvType, pszProvName, pcbProvName);
983
984         if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
985         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
986
987         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
988                 CRYPT_ReturnLastError(NTE_FAIL);
989
990         if (!pszProvName)
991         {
992                 DWORD numkeys;
993                 WCHAR *provNameW;
994                 
995                 RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
996                                  NULL, NULL, NULL, NULL, NULL, NULL);
997                 
998                 if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
999                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1000                 
1001                 RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1002                 (*pcbProvName)++;
1003                 *pcbProvName *= sizeof(WCHAR);
1004                 
1005                 CRYPT_Free(provNameW);
1006                 
1007                 if (dwIndex >= numkeys)
1008                         CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1009         } else {
1010                 DWORD size = sizeof(DWORD);
1011                 DWORD result;
1012                 HKEY subkey;
1013                 
1014                 result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1015                 if (result)
1016                         CRYPT_ReturnLastError(result);
1017                 if (RegOpenKeyW(hKey, pszProvName, &subkey))
1018                         return FALSE;
1019                 if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1020                         return FALSE;
1021                 RegCloseKey(subkey);
1022         }
1023         RegCloseKey(hKey);
1024         return TRUE;
1025 }
1026
1027 /******************************************************************************
1028  * CryptEnumProvidersA (ADVAPI32.@)
1029  *
1030  * see CryptEnumProvidersW
1031  */
1032 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1033                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1034 {
1035         PWSTR str = NULL;
1036         DWORD strlen;
1037         BOOL ret; /* = FALSE; */
1038
1039         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1040                         pdwProvType, pszProvName, pcbProvName);
1041
1042         strlen = *pcbProvName * sizeof(WCHAR);
1043         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1044                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1045         ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1046         if (str)
1047         {
1048                 CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1049                 CRYPT_Free(str);
1050         }
1051         *pcbProvName = strlen / sizeof(WCHAR);  /* FIXME: not correct */
1052         return ret;
1053 }
1054
1055 /******************************************************************************
1056  * CryptEnumProviderTypesA (ADVAPI32i.@)
1057  *
1058  * Retrieves the next type of CSP supported.
1059  *
1060  * PARAMS
1061  *  dwIndex     [I] Index of the next provider to be enumerated.
1062  *  pdwReserved [I] Reserved for future use and must be NULL.
1063  *  dwFlags     [I] Reserved for future use and must be zero.
1064  *  pdwProvType [O] DWORD designating the type of the provider.
1065  *  pszTypeName [O] Buffer that receives data from the provider type.
1066  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1067  *                    of bytes stored in the buffer on return.
1068  *
1069  *  RETURNS
1070  *   Success: TRUE
1071  *   Failure: FALSE
1072  *
1073  *  NOTES
1074  *   If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name
1075  *   for memory allocation purposes.
1076  */
1077 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1078                 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1079 {
1080         HKEY hKey, hSubkey;
1081         DWORD keylen, numkeys, dwType;
1082         PSTR keyname, ch;
1083         DWORD result;
1084
1085         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
1086                 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1087
1088         if (pdwReserved || !pdwProvType || !pcbTypeName)
1089                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1090         if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1091
1092         if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
1093                 return FALSE;
1094
1095         RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1096         if (dwIndex >= numkeys)
1097                 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1098         keylen++;
1099         if ( !(keyname = CRYPT_Alloc(keylen)) )
1100                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1101         if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
1102                 CRYPT_Free(keyname);
1103                 return FALSE;
1104         }
1105         RegOpenKeyA(hKey, keyname, &hSubkey);
1106         ch = keyname + strlen(keyname);
1107         /* Convert "Type 000" to 0, etc/ */
1108         *pdwProvType = *(--ch) - '0';
1109         *pdwProvType += (*(--ch) - '0') * 10;
1110         *pdwProvType += (*(--ch) - '0') * 100;
1111         CRYPT_Free(keyname);
1112         
1113         result = RegQueryValueExA(hSubkey, "TypeName", NULL, &dwType, pszTypeName, pcbTypeName);
1114         if (result)
1115                 CRYPT_ReturnLastError(result);
1116
1117         RegCloseKey(hSubkey);
1118         RegCloseKey(hKey);
1119         return TRUE;
1120 }
1121
1122 /******************************************************************************
1123  * CryptEnumProviderTypesW (ADVAPI32.@)
1124  *
1125  * see CryptEnumProviderTypesA
1126  */
1127 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1128                 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1129 {
1130         PSTR str = NULL;
1131         DWORD strlen;
1132         BOOL ret;
1133
1134         TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1135                         pdwProvType, pszTypeName, pcbTypeName);
1136         strlen = *pcbTypeName / sizeof(WCHAR);
1137         if ( pszTypeName && !(str = CRYPT_Alloc(strlen)) )
1138                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1139         ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1140         if (str)
1141         {
1142                 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
1143                 CRYPT_Free(str);
1144         }
1145         *pcbTypeName = strlen * sizeof(WCHAR);
1146         return ret;
1147 }
1148
1149 /******************************************************************************
1150  * CryptExportKey (ADVAPI32.@)
1151  * 
1152  * Exports a cryptographic key from a CSP.
1153  *
1154  * PARAMS
1155  *  hKey       [I] Handle to the key to export.
1156  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1157  *  dwBlobType [I] Type of BLOB to be exported.
1158  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1159  *  pbData     [O] Buffer to receive BLOB data.
1160  *  pdwDataLen [I/O] Specifies the size of pbData.
1161  *
1162  * RETURNS
1163  *  Success: TRUE
1164  *  Failure: FALSE
1165  *
1166  * NOTES
1167  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1168  *  buffer needed to hold the BLOB.
1169  */
1170 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1171                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1172 {
1173         PCRYPTPROV prov;
1174         PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1175
1176         TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1177
1178         if (!key || !pdwDataLen)
1179                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1180
1181         prov = key->pProvider;
1182         return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1183                         dwBlobType, dwFlags, pbData, pdwDataLen);
1184 }
1185
1186 /******************************************************************************
1187  * CryptGenKey (ADVAPI32.@)
1188  *
1189  * Generates a random cryptographic session key or a pub/priv key pair.
1190  *
1191  * PARAMS
1192  *  hProv   [I] Handle to a CSP.
1193  *  Algid   [I] Algorithm to use to make key.
1194  *  dwFlags [I] Specifies type of key to make.
1195  *  phKey   [I] Address of the handle to which the new key is copied.
1196  *
1197  *  RETURNS
1198  *   Success: TRUE
1199  *   Failure: FALSE
1200  */
1201 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1202 {
1203         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1204         PCRYPTKEY key;
1205
1206         TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
1207
1208         if (!prov)
1209                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1210         if (!phKey)
1211                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1212         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1213                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1214
1215         key->pProvider = prov;
1216
1217         if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1218         {
1219             *phKey = (HCRYPTKEY)key;
1220             return TRUE;
1221         }
1222
1223         /* CSP error! */
1224         CRYPT_Free(key);
1225         return FALSE;
1226 }
1227
1228 /******************************************************************************
1229  * CryptGetDefaultProviderA (ADVAPI32.@)
1230  *
1231  * Finds the default CSP of a certain provider type.
1232  *
1233  * PARAMS
1234  *  dwProvType  [I] Provider type to look for.
1235  *  pdwReserved [I] Reserved for future use and must be NULL.
1236  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1237  *  pszProvName [O] Name of the default CSP.
1238  *  pcbProvName [I/O] Size of pszProvName
1239  *
1240  * RETURNS
1241  *  Success: TRUE
1242  *  Failure: FALSE
1243  *
1244  * NOTES
1245  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1246  *  memory allocation purposes on return.
1247  */
1248 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1249                 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1250 {
1251         HKEY hKey;
1252         PSTR keyname;
1253         DWORD result;
1254
1255         if (pdwReserved || !pcbProvName)
1256                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1257         if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1258                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1259         if (dwProvType > 999)
1260                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1261         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1262                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1263         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1264         {
1265                 CRYPT_Free(keyname);
1266                 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
1267         }
1268         CRYPT_Free(keyname);
1269         
1270         result = RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName); 
1271         if (result)
1272         {
1273                 if (result != ERROR_MORE_DATA)
1274                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1275                 else
1276                         SetLastError(result);
1277                 
1278                 return FALSE;
1279         }
1280         
1281         RegCloseKey(hKey);
1282         return TRUE;
1283 }
1284
1285 /******************************************************************************
1286  * CryptGetDefaultProviderW (ADVAPI32.@)
1287  *
1288  * see CryptGetDefaultProviderA
1289  */
1290 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1291                 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1292 {
1293         PSTR str = NULL;
1294         DWORD strlen;
1295         BOOL ret = FALSE;
1296
1297         TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1298
1299         strlen = *pcbProvName / sizeof(WCHAR);
1300         if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1301                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1302         ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
1303         if (str)
1304         {
1305                 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
1306                 CRYPT_Free(str);
1307         }
1308         *pcbProvName = strlen * sizeof(WCHAR);
1309         return ret;
1310 }
1311
1312 /******************************************************************************
1313  * CryptGetHashParam (ADVAPI32.@)
1314  *
1315  * Retrieves data that controls the operations of a hash object.
1316  *
1317  * PARAMS
1318  *  hHash      [I] Handle of the hash object to question.
1319  *  dwParam    [I] Query type.
1320  *  pbData     [O] Buffer that receives the value data.
1321  *  pdwDataLen [I/O] Size of the pbData buffer.
1322  *  dwFlags    [I] Reserved for future use and must be zero.
1323  *
1324  * RETURNS
1325  *  Success: TRUE
1326  *  Failure: FALSE
1327  *
1328  * NOTES
1329  *  If pbData is NULL, pdwDataLen will contain the length required.
1330  */
1331 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1332                 DWORD *pdwDataLen, DWORD dwFlags)
1333 {
1334         PCRYPTPROV prov;
1335         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1336
1337         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1338
1339         if (!hash || !pdwDataLen)
1340                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1341
1342         prov = hash->pProvider;
1343         return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1344                         pbData, pdwDataLen, dwFlags);
1345 }
1346
1347 /******************************************************************************
1348  * CryptGetKeyParam (ADVAPI32.@)
1349  *
1350  * Retrieves data that controls the operations of a key.
1351  *
1352  * PARAMS
1353  *  hKey       [I] Handle to they key in question.
1354  *  dwParam    [I] Specifies query type.
1355  *  pbData     [O] Sequence of bytes to receive data.
1356  *  pdwDataLen [I/O] Size of pbData.
1357  *  dwFlags    [I] Reserved for future use and must be zero.
1358  *
1359  * RETURNS
1360  *  Success: TRUE
1361  *  Failure: FALSE
1362  *
1363  * NOTES
1364  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1365  */
1366 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1367                 DWORD *pdwDataLen, DWORD dwFlags)
1368 {
1369         PCRYPTPROV prov;
1370         PCRYPTKEY key = (PCRYPTKEY)hKey;
1371
1372         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1373
1374         if (!key || !pdwDataLen)
1375                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1376
1377         prov = key->pProvider;
1378         return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1379                         pbData, pdwDataLen, dwFlags);
1380 }
1381
1382 /******************************************************************************
1383  * CryptGetProvParam (ADVAPI32.@)
1384  *
1385  * Retrieves parameters that control the operations of a CSP.
1386  *
1387  * PARAMS
1388  *  hProv      [I] Handle of the CSP in question.
1389  *  dwParam    [I] Specifies query type.
1390  *  pbData     [O] Buffer to receive the data.
1391  *  pdwDataLen [I/O] Size of pbData.
1392  *  dwFlags    [I] see MSDN Docs.
1393  *
1394  * RETURNS
1395  *  Success: TRUE
1396  *  Failure: FALSE
1397  *
1398  * NOTES
1399  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1400  */
1401 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1402                 DWORD *pdwDataLen, DWORD dwFlags)
1403 {
1404         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1405
1406         TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1407
1408         return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1409 }
1410
1411 /******************************************************************************
1412  * CryptGetUserKey (ADVAPI32.@)
1413  *
1414  * Gets a handle of one of a user's two public/private key pairs.
1415  *
1416  * PARAMS
1417  *  hProv     [I] Handle of a CSP.
1418  *  dwKeySpec [I] Private key to use.
1419  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1420  *
1421  * RETURNS
1422  *  Success: TRUE
1423  *  Failure: FALSE
1424  */
1425 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1426 {
1427         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1428         PCRYPTKEY key;
1429
1430         TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1431
1432         if (!prov)
1433                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1434         if (!phUserKey)
1435                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1436         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1437                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1438
1439         key->pProvider = prov;
1440
1441         if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1442         {
1443             *phUserKey = (HCRYPTKEY)key;
1444             return TRUE;
1445         }
1446
1447         /* CSP Error */
1448         CRYPT_Free(key);
1449         *phUserKey = 0;
1450         return FALSE;
1451 }
1452
1453 /******************************************************************************
1454  * CryptHashData (ADVAPI32.@)
1455  *
1456  * Adds data to a hash object.
1457  *
1458  * PARAMS
1459  *  hHash     [I] Handle of the hash object.
1460  *  pbData    [I] Buffer of data to be hashed.
1461  *  dwDataLen [I] Number of bytes to add.
1462  *  dwFlags   [I] Can be CRYPT_USERDATA
1463  *
1464  * RETURNS
1465  *  Success: TRUE
1466  *  Failure: FALSE
1467  */
1468 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1469 {
1470         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1471         PCRYPTPROV prov;
1472
1473         TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1474
1475         if (!hash)
1476                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1477         if (!pbData || !dwDataLen)
1478                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1479
1480         prov = hash->pProvider;
1481         return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1482 }
1483
1484 /******************************************************************************
1485  * CryptHashSessionKey (ADVAPI32.@)
1486  *
1487  * PARAMS 
1488  *  hHash   [I] Handle to the hash object.
1489  *  hKey    [I] Handle to the key to be hashed.
1490  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1491  *
1492  * RETURNS
1493  *  Success: TRUE
1494  *  Failure: FALSE
1495  */
1496 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1497 {
1498         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1499         PCRYPTKEY key = (PCRYPTKEY)hKey;
1500         PCRYPTPROV prov;
1501
1502         TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1503
1504         if (!hash || !key)
1505                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1506
1507         prov = hash->pProvider;
1508         return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1509 }
1510
1511 /******************************************************************************
1512  * CryptImportKey (ADVAPI32.@)
1513  *
1514  * PARAMS
1515  *  hProv     [I] Handle of a CSP.
1516  *  pbData    [I] Contains the key to be imported.
1517  *  dwDataLen [I] Length of the key.
1518  *  hPubKey   [I] Cryptographic key that decrypts pdData
1519  *  dwFlags   [I] Used only with a public/private key pair.
1520  *  phKey     [O] Imported key.
1521  *
1522  * RETURNS
1523  *  Success: TRUE
1524  *  Failure: FALSE
1525  */
1526 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1527                 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1528 {
1529         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1530         PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1531
1532         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1533
1534         if (!prov || !pbData || !dwDataLen || !phKey)
1535                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1536
1537         if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1538                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1539
1540         importkey->pProvider = prov;
1541         if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1542                         pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1543         {
1544                 *phKey = (HCRYPTKEY)importkey;
1545                 return TRUE;
1546         }
1547
1548         CRYPT_Free(importkey);
1549         return FALSE;
1550 }
1551
1552 /******************************************************************************
1553  * CryptSignHashA
1554  *
1555  * Note: Since the sDesciption (string) is supposed to be NULL and
1556  *      is only retained for compatibility no string conversions are required
1557  *      and only one implementation is required for both ANSI and Unicode.
1558  *      We still need to export both:
1559  *
1560  * CryptSignHashA (ADVAPI32.@)
1561  * CryptSignHashW (ADVAPI32.@)
1562  *
1563  * Signs data.
1564  *
1565  * PARAMS
1566  *  hHash        [I] Handle of the hash object to be signed.
1567  *  dwKeySpec    [I] Private key to use.
1568  *  sDescription [I] Must be NULL.
1569  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1570  *  pbSignature  [O] Buffer of the signature data.
1571  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1572  *
1573  * RETURNS
1574  *  Success: TRUE
1575  *  Failure: FALSE
1576  */
1577 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1578                 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1579 {
1580         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1581         PCRYPTPROV prov;
1582
1583         TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1584         if (sDescription)
1585                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1586
1587         if (!hash)
1588                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1589         if (!pdwSigLen)
1590                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1591
1592         prov = hash->pProvider;
1593         return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1594                 dwFlags, pbSignature, pdwSigLen);
1595 }
1596
1597 /******************************************************************************
1598  * CryptSetHashParam (ADVAPI32.@)
1599  *
1600  * Customizes the operations of a hash object.
1601  *
1602  * PARAMS
1603  *  hHash   [I] Handle of the hash object to set parameters.
1604  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1605  *  pbData  [I] Value data buffer.
1606  *  dwFlags [I] Reserved for future use and must be zero.
1607  *
1608  * RETURNS
1609  *  Success: TRUE
1610  *  Failure: FALSE
1611  */
1612 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1613 {
1614         PCRYPTPROV prov;
1615         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1616
1617         TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1618
1619         if (!hash || !pbData)
1620                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1621
1622         prov = hash->pProvider;
1623         return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1624                         dwParam, pbData, dwFlags);
1625 }
1626
1627 /******************************************************************************
1628  * CryptSetKeyParam (ADVAPI32.@)
1629  *
1630  * Customizes a session key's operations.
1631  *
1632  * PARAMS
1633  *  hKey    [I] Handle to the key to set values.
1634  *  dwParam [I] See MSDN Doc.
1635  *  pbData  [I] Buffer of values to set.
1636  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1637  *
1638  * RETURNS
1639  *  Success: TRUE
1640  *  Failure: FALSE
1641  */
1642 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1643 {
1644         PCRYPTPROV prov;
1645         PCRYPTKEY key = (PCRYPTKEY)hKey;
1646
1647         TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1648
1649         if (!key || !pbData)
1650                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1651
1652         prov = key->pProvider;
1653         return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1654                         dwParam, pbData, dwFlags);
1655 }
1656
1657 /******************************************************************************
1658  * CryptSetProviderA (ADVAPI32.@)
1659  *
1660  * Specifies the current user's default CSP.
1661  *
1662  * PARAMS
1663  *  pszProvName [I] Name of the new default CSP.
1664  *  dwProvType  [I] Provider type of the CSP.
1665  *
1666  * RETURNS
1667  *  Success: TRUE
1668  *  Failure: FALSE
1669  */
1670 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1671 {
1672         TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1673         return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1674 }
1675
1676 /******************************************************************************
1677  * CryptSetProviderW (ADVAPI32.@)
1678  *
1679  * See CryptSetProviderA
1680  */
1681 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1682 {
1683         TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1684         return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1685 }
1686
1687 /******************************************************************************
1688  * CryptSetProviderExA (ADVAPI32.@)
1689  *
1690  * Specifies the default CSP.
1691  *
1692  * PARAMS
1693  *  pszProvName [I] Name of the new default CSP.
1694  *  dwProvType  [I] Provider type of the CSP.
1695  *  pdwReserved [I] Reserved for future use and must be NULL.
1696  *  dwFlags     [I] See MSDN Doc.
1697  *
1698  * RETURNS
1699  *  Success: TRUE
1700  *  Failure: FALSE
1701  */
1702 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1703 {
1704         HKEY hProvKey, hTypeKey;
1705         PSTR keyname;
1706
1707         TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1708
1709         if (!pszProvName || pdwReserved)
1710                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1711         if (dwProvType > MAXPROVTYPES)
1712                 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1713         if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1714                         || dwFlags == CRYPT_DELETE_DEFAULT)
1715                 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1716         
1717         if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
1718                 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1719         if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1720                 keyname, &hTypeKey))
1721         {
1722                 CRYPT_Free(keyname);
1723                 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1724         }
1725         CRYPT_Free(keyname);
1726         
1727         if (dwFlags & CRYPT_DELETE_DEFAULT)
1728         {
1729                 RegDeleteValueA(hTypeKey, "Name");
1730         }
1731         else
1732         {
1733                 if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
1734                 {
1735                         RegCloseKey(hTypeKey);
1736                         CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1737                 }
1738                 if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
1739                         keyname, &hProvKey))
1740                 {
1741                         CRYPT_Free(keyname);
1742                         RegCloseKey(hTypeKey);
1743                         CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1744                 }
1745                 CRYPT_Free(keyname);
1746                 
1747                 if (RegSetValueExA(hTypeKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) + 1))
1748                 {
1749                         RegCloseKey(hTypeKey);
1750                         RegCloseKey(hProvKey);
1751                         return FALSE;
1752                 }
1753                 
1754                 RegCloseKey(hProvKey);
1755         }
1756         RegCloseKey(hTypeKey);
1757
1758         return TRUE;
1759 }
1760
1761 /******************************************************************************
1762  * CryptSetProviderExW (ADVAPI32.@)
1763  *
1764  * See CryptSetProviderExA
1765  */
1766 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1767 {
1768         BOOL ret = FALSE;
1769         PSTR str = NULL;
1770
1771         TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1772
1773         if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1774         {
1775                 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1776                 CRYPT_Free(str);
1777         }
1778         return ret;
1779 }
1780
1781 /******************************************************************************
1782  * CryptSetProvParam (ADVAPI32.@)
1783  *
1784  * Customizes the operations of a CSP.
1785  *
1786  * PARAMS
1787  *  hProv   [I] Handle of a CSP.
1788  *  dwParam [I] See MSDN Doc.
1789  *  pbData  [I] Buffer that contains a value to set as a parameter.
1790  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
1791  *
1792  * RETURNS
1793  *  Success: TRUE
1794  *  Failure: FALSE
1795  */
1796 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1797 {
1798         PCRYPTPROV prov = (PCRYPTPROV)hProv;
1799
1800         TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1801
1802         if (!prov)
1803                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1804         if (dwFlags & PP_USE_HARDWARE_RNG)
1805         {
1806                 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1807                 FIXME("\tLetting the CSP decide.\n");
1808         }
1809         if (dwFlags & PP_CLIENT_HWND)
1810         {
1811                 /* FIXME: Should verify the parameter */
1812                 if (pbData /* && IsWindow((HWND)pbData) */)
1813                 {
1814                         crypt_hWindow = (HWND)(pbData);
1815                         return TRUE;
1816                 } else {
1817                         SetLastError(ERROR_INVALID_PARAMETER);
1818                         return FALSE;
1819                 }
1820         }
1821         /* All other flags go to the CSP */
1822         return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1823 }
1824
1825 /******************************************************************************
1826  * CryptVerifySignatureA
1827  *
1828  * Note: Since the sDesciption (string) is supposed to be NULL and
1829  *      is only retained for compatibility no string conversions are required
1830  *      and only one implementation is required for both ANSI and Unicode.
1831  *      We still need to export both:
1832  *
1833  * CryptVerifySignatureA (ADVAPI32.@)
1834  * CryptVerifySignatureW (ADVAPI32.@)
1835  *
1836  * Verifies the signature of a hash object.
1837  *
1838  * PARAMS
1839  *  hHash        [I] Handle of the hash object to verify.
1840  *  pbSignature  [I] Signature data to verify.
1841  *  dwSigLen     [I] Size of pbSignature.
1842  *  hPubKey      [I] Handle to the public key to authenticate signature.
1843  *  sDescription [I] Must be set to NULL.
1844  *  dwFlags      [I] See MSDN doc.
1845  *
1846  * RETURNS
1847  *  Success: TRUE
1848  *  Failure: FALSE
1849  */
1850 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1851                 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1852 {
1853         PCRYPTHASH hash = (PCRYPTHASH)hHash;
1854         PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1855         PCRYPTPROV prov;
1856
1857         TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1858                         dwSigLen, hPubKey, dwFlags);
1859         if (sDescription)
1860                 WARN("The sDescription parameter is not supported (and no longer used).  Ignoring.\n");
1861
1862         if (!hash || !key)
1863                 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1864         if (!pbSignature || !dwSigLen)
1865                 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1866
1867         prov = hash->pProvider;
1868         return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1869                 key->hPrivate, NULL, dwFlags);
1870 }
1871
1872
1873 /*
1874    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
1875    in crypt32.dll.
1876  */
1877
1878 /******************************************************************************
1879  * SystemFunction040   (ADVAPI32.@)
1880  *
1881  * PARAMS
1882  *  memory [I/O] Pointer to memory to encrypt.
1883  *  length [I] Length of region to encrypt in bytes.
1884  *  flags  [I] Control whether other processes are able to decrypt the memory.
1885  *    RTL_ENCRYPT_OPTION_SAME_PROCESS 
1886  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS 
1887  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1888  *    
1889  * NOTES
1890  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1891  *  If flags are specified when encrypting, the same flag value must be given
1892  *  when decrypting the memory.
1893  */
1894 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)  /* RtlEncryptMemory */
1895 {
1896         FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
1897         return STATUS_SUCCESS;
1898 }
1899
1900 /******************************************************************************
1901  * SystemFunction041  (ADVAPI32.@)
1902  *
1903  * PARAMS
1904  *  memory [I/O] Pointer to memory to decrypt.
1905  *  length [I] Length of region to decrypt in bytes.
1906  *  flags  [I] Control whether other processes are able to decrypt the memory.
1907  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
1908  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
1909  *    RTL_ENCRYPT_OPTION_SAME_LOGON
1910  *
1911  * NOTES
1912  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
1913  *  If flags are specified when encrypting, the same flag value must be given
1914  *  when decrypting the memory.
1915  */
1916 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)  /* RtlDecryptMemory */
1917 {
1918         FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
1919         return STATUS_SUCCESS;
1920 }