xref: /reactos/dll/win32/advapi32/wine/crypt.c (revision 40462c92)
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 /***********************************************************************
21  *
22  *  TODO:
23  *  - Reference counting
24  *  - Thread-safing
25  */
26 
27 #ifdef __REACTOS__
28 #include <advapi32.h>
29 #else
30 #include "config.h"
31 #include "wine/port.h"
32 
33 #include <limits.h>
34 #include <time.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <sys/types.h>
38 #ifdef HAVE_SYS_STAT_H
39 # include <sys/stat.h>
40 #endif
41 #include <fcntl.h>
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45 
46 #include "ntstatus.h"
47 #define WIN32_NO_STATUS
48 #include "crypt.h"
49 #include "winnls.h"
50 #include "winreg.h"
51 #include "rpc.h"
52 #include "wine/debug.h"
53 #include "wine/unicode.h"
54 #include "winternl.h"
55 #endif /* __REACTOS__ */
56 
57 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
58 
59 static HWND crypt_hWindow;
60 
61 #define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
62 #define CRYPT_Free(buffer) (LocalFree(buffer))
63 
64 static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
65 {
66 	static const WCHAR KEYSTR[] = {
67                 'S','o','f','t','w','a','r','e','\\',
68                 'M','i','c','r','o','s','o','f','t','\\',
69                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
70                 'D','e','f','a','u','l','t','s','\\',
71                 'P','r','o','v','i','d','e','r','\\',0
72 	};
73 	PWSTR keyname;
74 
75 	keyname = CRYPT_Alloc((strlenW(KEYSTR) + strlenW(pProvName) +1)*sizeof(WCHAR));
76 	if (keyname)
77 	{
78 		strcpyW(keyname, KEYSTR);
79 		strcpyW(keyname + strlenW(KEYSTR), pProvName);
80 	} else
81 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
82 	return keyname;
83 }
84 
85 static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
86 {
87 	static const WCHAR MACHINESTR[] = {
88                 'S','o','f','t','w','a','r','e','\\',
89                 'M','i','c','r','o','s','o','f','t','\\',
90                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
91                 'D','e','f','a','u','l','t','s','\\',
92                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s','\\',
93                 'T','y','p','e',' ','X','X','X',0
94 	};
95 	static const WCHAR USERSTR[] = {
96                 'S','o','f','t','w','a','r','e','\\',
97                 'M','i','c','r','o','s','o','f','t','\\',
98                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
99                 'P','r','o','v','i','d','e','r',' ','T','y','p','e',' ','X','X','X',0
100 	};
101 	PWSTR keyname;
102 	PWSTR ptr;
103 
104 	keyname = CRYPT_Alloc( ((user ? strlenW(USERSTR) : strlenW(MACHINESTR)) +1)*sizeof(WCHAR));
105 	if (keyname)
106 	{
107 		user ? strcpyW(keyname, USERSTR) : strcpyW(keyname, MACHINESTR);
108 		ptr = keyname + strlenW(keyname);
109 		*(--ptr) = (dwType % 10) + '0';
110 		*(--ptr) = ((dwType / 10) % 10) + '0';
111 		*(--ptr) = (dwType / 100) + '0';
112 	} else
113 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
114 	return keyname;
115 }
116 
117 /* CRYPT_UnicodeToANSI
118  * wstr - unicode string
119  * str - pointer to ANSI string or pointer to null pointer if we have to do the allocation
120  * strsize - size of buffer pointed to by str
121  *
122  * returns TRUE if unsuccessful, FALSE otherwise.
123  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
124  */
125 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
126 {
127 	if (!wstr)
128 	{
129 		*str = NULL;
130 		return TRUE;
131 	}
132 
133 	if (!*str)
134 	{
135 		strsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
136 		*str = CRYPT_Alloc(strsize * sizeof(CHAR));
137 	}
138 	else if (strsize < 0)
139 	{
140 		strsize = INT_MAX; /* windows will pretend that the buffer is infinitely long */
141 	}
142 
143 	if (*str)
144 	{
145 		WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, strsize, NULL, NULL);
146 		return TRUE;
147 	}
148 
149 	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
150 	return FALSE;
151 }
152 
153 /* CRYPT_ANSITOUnicode
154  * str - ANSI string
155  * wstr - pointer to unicode string
156  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
157  */
158 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
159 {
160 	unsigned int wcount;
161 
162 	if (!str)
163 	{
164 		*wstr = NULL;
165 		return TRUE;
166 	}
167 	wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
168 	if (wstrsize == -1)
169 		*wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
170 	else
171 		wcount = min( wcount, wstrsize/sizeof(WCHAR) );
172 	if (*wstr)
173 	{
174 		MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
175 		return TRUE;
176 	}
177 	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
178 	return FALSE;
179 }
180 
181 /* These next 2 functions are used by the VTableProvStruc structure */
182 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
183 {
184 	if (!lpszImage || !pData)
185 	{
186 		SetLastError(ERROR_INVALID_PARAMETER);
187 		return FALSE;
188 	}
189 
190 	FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
191 
192 	return TRUE;
193 }
194 
195 static void CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
196 {
197 	if (phWnd) *phWnd = crypt_hWindow;
198 }
199 
200 #define CRYPT_GetProvFunc(name) \
201 	if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
202 #define CRYPT_GetProvFuncOpt(name) \
203 	provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
204 static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
205 {
206 	PCRYPTPROV provider;
207 	DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
208 
209 	if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
210 	if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
211 	if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
212 	if ( !(provider->hModule = LoadLibraryW(pImage)) )
213 	{
214 		errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
215 		FIXME("Failed to load dll %s\n", debugstr_w(pImage));
216 		goto error;
217 	}
218 	provider->dwMagic = MAGIC_CRYPTPROV;
219 	provider->refcount = 1;
220 
221 	errorcode = NTE_PROVIDER_DLL_FAIL;
222 	CRYPT_GetProvFunc(CPAcquireContext);
223 	CRYPT_GetProvFunc(CPCreateHash);
224 	CRYPT_GetProvFunc(CPDecrypt);
225 	CRYPT_GetProvFunc(CPDeriveKey);
226 	CRYPT_GetProvFunc(CPDestroyHash);
227 	CRYPT_GetProvFunc(CPDestroyKey);
228 	CRYPT_GetProvFuncOpt(CPDuplicateHash);
229 	CRYPT_GetProvFuncOpt(CPDuplicateKey);
230 	CRYPT_GetProvFunc(CPEncrypt);
231 	CRYPT_GetProvFunc(CPExportKey);
232 	CRYPT_GetProvFunc(CPGenKey);
233 	CRYPT_GetProvFunc(CPGenRandom);
234 	CRYPT_GetProvFunc(CPGetHashParam);
235 	CRYPT_GetProvFunc(CPGetKeyParam);
236 	CRYPT_GetProvFunc(CPGetProvParam);
237 	CRYPT_GetProvFunc(CPGetUserKey);
238 	CRYPT_GetProvFunc(CPHashData);
239 	CRYPT_GetProvFunc(CPHashSessionKey);
240 	CRYPT_GetProvFunc(CPImportKey);
241 	CRYPT_GetProvFunc(CPReleaseContext);
242 	CRYPT_GetProvFunc(CPSetHashParam);
243 	CRYPT_GetProvFunc(CPSetKeyParam);
244 	CRYPT_GetProvFunc(CPSetProvParam);
245 	CRYPT_GetProvFunc(CPSignHash);
246 	CRYPT_GetProvFunc(CPVerifySignature);
247 
248 	/* FIXME: Not sure what the pbContextInfo field is for.
249 	 *        Does it need memory allocation?
250          */
251 	provider->pVTable->Version = 3;
252 	provider->pVTable->FuncVerifyImage = CRYPT_VerifyImage;
253 	provider->pVTable->FuncReturnhWnd = CRYPT_ReturnhWnd;
254 	provider->pVTable->dwProvType = 0;
255 	provider->pVTable->pbContextInfo = NULL;
256 	provider->pVTable->cbContextInfo = 0;
257 	provider->pVTable->pszProvName = NULL;
258 	return provider;
259 
260 error:
261 	SetLastError(errorcode);
262 	if (provider)
263 	{
264 		provider->dwMagic = 0;
265 		if (provider->hModule)
266 			FreeLibrary(provider->hModule);
267 		CRYPT_Free(provider->pVTable);
268 		CRYPT_Free(provider->pFuncs);
269 		CRYPT_Free(provider);
270 	}
271 	return NULL;
272 }
273 #undef CRYPT_GetProvFunc
274 #undef CRYPT_GetProvFuncOpt
275 
276 
277 static void CRYPT_CreateMachineGuid(void)
278 {
279 	static const WCHAR cryptographyW[] = {
280                 'S','o','f','t','w','a','r','e','\\',
281                 'M','i','c','r','o','s','o','f','t','\\',
282                 'C','r','y','p','t','o','g','r','a','p','h','y',0 };
283 	static const WCHAR machineGuidW[] = {
284 		'M','a','c','h','i','n','e','G','u','i','d',0 };
285 	LONG r;
286 	HKEY key;
287 
288 	r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cryptographyW, 0, KEY_ALL_ACCESS,
289 			  &key);
290 	if (!r)
291 	{
292 		DWORD size;
293 
294 		r = RegQueryValueExW(key, machineGuidW, NULL, NULL, NULL, &size);
295 		if (r == ERROR_FILE_NOT_FOUND)
296 		{
297                     UUID uuid;
298                     WCHAR buf[37];
299                     RPC_STATUS rs;
300                     static const WCHAR uuidFmt[] = {
301                         '%','0','8','x','-','%','0','4','x','-',
302                         '%','0','4','x','-','%','0','2','x',
303                         '%','0','2','x','-','%','0','2','x',
304                         '%','0','2','x','%','0','2','x',
305                         '%','0','2','x','%','0','2','x',
306                         '%','0','2','x',0 };
307 
308                     rs = UuidCreate(&uuid);
309                     if (rs == S_OK)
310                     {
311                         sprintfW(buf, uuidFmt,
312                                  uuid.Data1, uuid.Data2, uuid.Data3,
313                                  uuid.Data4[0], uuid.Data4[1],
314                                  uuid.Data4[2], uuid.Data4[3],
315                                  uuid.Data4[4], uuid.Data4[5],
316                                  uuid.Data4[6], uuid.Data4[7] );
317                         RegSetValueExW(key, machineGuidW, 0, REG_SZ,
318                                        (const BYTE *)buf,
319                                        (lstrlenW(buf)+1)*sizeof(WCHAR));
320                     }
321 		}
322 		RegCloseKey(key);
323 	}
324 }
325 
326 
327 /******************************************************************************
328  * CloseEncryptedFileRaw   (ADVAPI32.@)
329  *
330  * Close encrypted files
331  *
332  * PARAMS
333  *  context    [I] pointer to the context
334  * RETURNS
335  *  Success: ERROR_SUCCESS
336  *  Failure: NTSTATUS error code
337  */
338 void WINAPI CloseEncryptedFileRaw(PVOID context)
339 {
340     FIXME("(%p): stub\n", context);
341 }
342 
343 /******************************************************************************
344  * CryptAcquireContextW (ADVAPI32.@)
345  *
346  * Acquire a crypto provider context handle.
347  *
348  * PARAMS
349  *  phProv       [O] Pointer to HCRYPTPROV for the output.
350  *  pszContainer [I] Key Container Name
351  *  pszProvider  [I] Cryptographic Service Provider Name
352  *  dwProvType   [I] Crypto provider type to get a handle.
353  *  dwFlags      [I] flags for the operation
354  *
355  * RETURNS
356  *  TRUE on success, FALSE on failure.
357  */
358 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
359 		LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
360 {
361 	PCRYPTPROV pProv = NULL;
362 	HKEY key;
363 	PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
364 	PSTR provnameA = NULL, pszContainerA = NULL;
365 	DWORD keytype, type, len;
366 	ULONG r;
367 	static const WCHAR nameW[] = {'N','a','m','e',0};
368 	static const WCHAR typeW[] = {'T','y','p','e',0};
369 	static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
370 
371 	TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_w(pszContainer),
372 		debugstr_w(pszProvider), dwProvType, dwFlags);
373 
374 	if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
375 	{
376 		SetLastError(NTE_BAD_PROV_TYPE);
377 		return FALSE;
378 	}
379 
380 	if (!phProv)
381 	{
382 		SetLastError(ERROR_INVALID_PARAMETER);
383 		return FALSE;
384 	}
385 
386 	/* Make sure the MachineGuid value exists */
387 	CRYPT_CreateMachineGuid();
388 
389 	if (!pszProvider || !*pszProvider)
390 	{
391 		/* No CSP name specified so try the user default CSP first
392 		 * then try the machine default CSP
393 		 */
394 		if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
395 			TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
396 			SetLastError(NTE_PROV_TYPE_NOT_DEF);
397 			return FALSE;
398 		}
399 		if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
400 		{
401 			CRYPT_Free(keyname);
402 			if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
403 				TRACE("No type registered for crypto provider type %d.\n", dwProvType);
404 				RegCloseKey(key);
405 				SetLastError(NTE_PROV_TYPE_NOT_DEF);
406 				goto error;
407 			}
408 			if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
409 				TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
410 				CRYPT_Free(keyname);
411 				RegCloseKey(key);
412 				SetLastError(NTE_PROV_TYPE_NOT_DEF);
413 				goto error;
414 			}
415 		}
416 		CRYPT_Free(keyname);
417 		r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
418 		if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
419 		{
420 			TRACE("error %d reading size of 'Name' from registry\n", r );
421 			RegCloseKey(key);
422 			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
423 			goto error;
424 		}
425 		if(!(provname = CRYPT_Alloc(len)))
426 		{
427 			RegCloseKey(key);
428 			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
429 			goto error;
430 		}
431 		r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
432 		if( r != ERROR_SUCCESS )
433 		{
434 			TRACE("error %d reading 'Name' from registry\n", r );
435 			RegCloseKey(key);
436 			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
437 			goto error;
438 		}
439 		RegCloseKey(key);
440 	} else {
441 		if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
442 		{
443 			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
444 			goto error;
445 		}
446 		strcpyW(provname, pszProvider);
447 	}
448 
449 	keyname = CRYPT_GetProvKeyName(provname);
450 	r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
451 	CRYPT_Free(keyname);
452 	if (r != ERROR_SUCCESS)
453 	{
454 		SetLastError(NTE_KEYSET_NOT_DEF);
455 		goto error;
456 	}
457 	len = sizeof(DWORD);
458 	r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
459 	if (r != ERROR_SUCCESS)
460 	{
461 		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
462 		goto error;
463 	}
464 	if (type != dwProvType)
465 	{
466 		TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
467 		SetLastError(NTE_PROV_TYPE_NO_MATCH);
468 		goto error;
469 	}
470 
471 	r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
472 	if ( r != ERROR_SUCCESS || keytype != REG_SZ)
473 	{
474 		TRACE("error %d reading size of 'Image Path' from registry\n", r );
475 		RegCloseKey(key);
476 		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
477 		goto error;
478 	}
479 	if (!(temp = CRYPT_Alloc(len)))
480 	{
481 		RegCloseKey(key);
482 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
483 		goto error;
484 	}
485 	r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
486 	if( r != ERROR_SUCCESS )
487 	{
488 		TRACE("error %d reading 'Image Path' from registry\n", r );
489 		RegCloseKey(key);
490 		SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
491 		goto error;
492 	}
493 	RegCloseKey(key);
494 	len = ExpandEnvironmentStringsW(temp, NULL, 0);
495 	if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
496 	{
497 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
498 		goto error;
499 	}
500 	if (!ExpandEnvironmentStringsW(temp, imagepath, len))
501 	{
502 		/* ExpandEnvironmentStrings will call SetLastError */
503 		goto error;
504 	}
505 	pProv = CRYPT_LoadProvider(imagepath);
506 	if (!pProv) {
507 		/* CRYPT_LoadProvider calls SetLastError */
508 		goto error;
509 	}
510 	pProv->pVTable->dwProvType = dwProvType;
511 	if(!CRYPT_UnicodeToANSI(provname, &provnameA, 0))
512 	{
513 		/* CRYPT_UnicodeToANSI calls SetLastError */
514 		goto error;
515 	}
516 	pProv->pVTable->pszProvName = provnameA;
517 	if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, 0))
518 	{
519 		/* CRYPT_UnicodeToANSI calls SetLastError */
520 		goto error;
521 	}
522 	if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
523 	{
524 		/* MSDN: When this flag is set, the value returned in phProv is undefined,
525 		 *       and thus, the CryptReleaseContext function need not be called afterwards.
526 		 *       Therefore, we must clean up everything now.
527 		 */
528 		if (dwFlags & CRYPT_DELETEKEYSET)
529 		{
530 			pProv->dwMagic = 0;
531 			FreeLibrary(pProv->hModule);
532 			CRYPT_Free(provnameA);
533 			CRYPT_Free(pProv->pVTable);
534 			CRYPT_Free(pProv->pFuncs);
535 			CRYPT_Free(pProv);
536 		} else {
537 			*phProv = (HCRYPTPROV)pProv;
538 		}
539 		CRYPT_Free(pszContainerA);
540 		CRYPT_Free(provname);
541 		CRYPT_Free(temp);
542 		CRYPT_Free(imagepath);
543 		return TRUE;
544 	}
545 	/* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
546 error:
547 	if (pProv)
548 	{
549 		pProv->dwMagic = 0;
550 		if (pProv->hModule)
551 			FreeLibrary(pProv->hModule);
552 		CRYPT_Free(pProv->pVTable);
553 		CRYPT_Free(pProv->pFuncs);
554 		CRYPT_Free(pProv);
555 	}
556 	CRYPT_Free(pszContainerA);
557 	CRYPT_Free(provnameA);
558 	CRYPT_Free(provname);
559 	CRYPT_Free(temp);
560 	CRYPT_Free(imagepath);
561 	return FALSE;
562 }
563 
564 /******************************************************************************
565  * CryptAcquireContextA (ADVAPI32.@)
566  *
567  * See CryptAcquireContextW.
568  */
569 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
570 		LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
571 {
572 	PWSTR pProvider = NULL, pContainer = NULL;
573 	BOOL ret = FALSE;
574 
575 	TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_a(pszContainer),
576               debugstr_a(pszProvider), dwProvType, dwFlags);
577 
578 	if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
579 	{
580 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
581 		return FALSE;
582 	}
583 	if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
584 	{
585 		CRYPT_Free(pContainer);
586 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
587 		return FALSE;
588 	}
589 
590 	ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
591 
592 	CRYPT_Free(pContainer);
593 	CRYPT_Free(pProvider);
594 
595 	return ret;
596 }
597 
598 /******************************************************************************
599  * CryptContextAddRef (ADVAPI32.@)
600  *
601  * Increases reference count of a cryptographic service provider handle
602  * by one.
603  *
604  * PARAMS
605  *  hProv       [I] Handle to the CSP whose reference is being incremented.
606  *  pdwReserved [IN] Reserved for future use and must be NULL.
607  *  dwFlags     [I] Reserved for future use and must be 0.
608  *
609  * RETURNS
610  *  Success: TRUE
611  *  Failure: FALSE
612  */
613 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
614 {
615 	PCRYPTPROV pProv = (PCRYPTPROV)hProv;
616 
617 	TRACE("(0x%lx, %p, %08x)\n", hProv, pdwReserved, dwFlags);
618 
619 	if (!pProv)
620 	{
621 		SetLastError(NTE_BAD_UID);
622 		return FALSE;
623 	}
624 
625 	if (pProv->dwMagic != MAGIC_CRYPTPROV)
626 	{
627 		SetLastError(ERROR_INVALID_PARAMETER);
628 		return FALSE;
629 	}
630 
631 	InterlockedIncrement(&pProv->refcount);
632 	return TRUE;
633 }
634 
635 /******************************************************************************
636  * CryptReleaseContext (ADVAPI32.@)
637  *
638  * Releases the handle of a CSP.  Reference count is decreased.
639  *
640  * PARAMS
641  *  hProv   [I] Handle of a CSP.
642  *  dwFlags [I] Reserved for future use and must be 0.
643  *
644  * RETURNS
645  *  Success: TRUE
646  *  Failure: FALSE
647  */
648 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
649 {
650 	PCRYPTPROV pProv = (PCRYPTPROV)hProv;
651 	BOOL ret = TRUE;
652 
653 	TRACE("(0x%lx, %08x)\n", hProv, dwFlags);
654 
655 	if (!pProv)
656 	{
657 		SetLastError(ERROR_INVALID_PARAMETER);
658 		return FALSE;
659 	}
660 
661 	if (pProv->dwMagic != MAGIC_CRYPTPROV)
662 	{
663 		SetLastError(ERROR_INVALID_PARAMETER);
664 		return FALSE;
665 	}
666 
667 	if (InterlockedDecrement(&pProv->refcount) == 0)
668 	{
669 		ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
670 		pProv->dwMagic = 0;
671 		FreeLibrary(pProv->hModule);
672 #if 0
673 		CRYPT_Free(pProv->pVTable->pContextInfo);
674 #endif
675 		CRYPT_Free(pProv->pVTable->pszProvName);
676 		CRYPT_Free(pProv->pVTable);
677 		CRYPT_Free(pProv->pFuncs);
678 		CRYPT_Free(pProv);
679 	}
680 	return ret;
681 }
682 
683 /******************************************************************************
684  * CryptGenRandom (ADVAPI32.@)
685  *
686  * Fills a buffer with cryptographically random bytes.
687  *
688  * PARAMS
689  *  hProv    [I] Handle of a CSP.
690  *  dwLen    [I] Number of bytes to generate.
691  *  pbBuffer [I/O] Buffer to contain random bytes.
692  *
693  * RETURNS
694  *  Success: TRUE
695  *  Failure: FALSE
696  *
697  * NOTES
698  *  pdBuffer must be at least dwLen bytes long.
699  */
700 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
701 {
702 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
703 
704 	TRACE("(0x%lx, %d, %p)\n", hProv, dwLen, pbBuffer);
705 
706 	if (!hProv)
707 	{
708 		SetLastError(ERROR_INVALID_HANDLE);
709 		return FALSE;
710 	}
711 
712 	if (prov->dwMagic != MAGIC_CRYPTPROV)
713 	{
714 		SetLastError(ERROR_INVALID_PARAMETER);
715 		return FALSE;
716 	}
717 
718 	return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
719 }
720 
721 /******************************************************************************
722  * CryptCreateHash (ADVAPI32.@)
723  *
724  * Initiates the hashing of a stream of data.
725  *
726  * PARAMS
727  *  hProv   [I] Handle of a CSP.
728  *  Algid   [I] Identifies the hash algorithm to use.
729  *  hKey    [I] Key for the hash (if required).
730  *  dwFlags [I] Reserved for future use and must be 0.
731  *  phHash  [O] Address of the future handle to the new hash object.
732  *
733  * RETURNS
734  *  Success: TRUE
735  *  Failure: FALSE
736  *
737  * NOTES
738  *  If the algorithm is a keyed hash, hKey is the key.
739  */
740 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
741 		DWORD dwFlags, HCRYPTHASH *phHash)
742 {
743 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
744 	PCRYPTKEY key = (PCRYPTKEY)hKey;
745 	PCRYPTHASH hash;
746 
747 	TRACE("(0x%lx, 0x%x, 0x%lx, %08x, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
748 
749 	if (!prov || !phHash || prov->dwMagic != MAGIC_CRYPTPROV ||
750 		(key && key->dwMagic != MAGIC_CRYPTKEY))
751 	{
752 		SetLastError(ERROR_INVALID_PARAMETER);
753 		return FALSE;
754 	}
755 	if (dwFlags)
756 	{
757 		SetLastError(NTE_BAD_FLAGS);
758 		return FALSE;
759 	}
760 	if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
761 	{
762 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
763 		return FALSE;
764 	}
765 
766 	hash->pProvider = prov;
767 	hash->dwMagic = MAGIC_CRYPTHASH;
768 	if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
769 			key ? key->hPrivate : 0, 0, &hash->hPrivate))
770         {
771             *phHash = (HCRYPTHASH)hash;
772             return TRUE;
773         }
774 
775 	/* CSP error! */
776 	hash->dwMagic = 0;
777 	CRYPT_Free(hash);
778 	*phHash = 0;
779 	return FALSE;
780 }
781 
782 /******************************************************************************
783  * CryptDecrypt (ADVAPI32.@)
784  *
785  * Decrypts data encrypted by CryptEncrypt.
786  *
787  * PARAMS
788  *  hKey       [I] Handle to the decryption key.
789  *  hHash      [I] Handle to a hash object.
790  *  Final      [I] TRUE if this is the last section to be decrypted.
791  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
792  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
793  *                   data on return
794  *  pdwDataLen [I/O] Length of pbData before and after the call.
795  *
796  *  RETURNS
797  *   Success: TRUE
798  *   Failure: FALSE
799  */
800 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
801 		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
802 {
803 	PCRYPTPROV prov;
804 	PCRYPTKEY key = (PCRYPTKEY)hKey;
805 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
806 
807 	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
808 
809 	if (!key || !pbData || !pdwDataLen ||
810 		!key->pProvider || key->dwMagic != MAGIC_CRYPTKEY ||
811 		key->pProvider->dwMagic != MAGIC_CRYPTPROV)
812 	{
813 		SetLastError(ERROR_INVALID_PARAMETER);
814 		return FALSE;
815 	}
816 
817 	prov = key->pProvider;
818 	return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
819 			Final, dwFlags, pbData, pdwDataLen);
820 }
821 
822 /******************************************************************************
823  * CryptDeriveKey (ADVAPI32.@)
824  *
825  * Generates session keys derived from a base data value.
826  *
827  * PARAMS
828  *  hProv     [I] Handle to a CSP.
829  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
830  *  hBaseData [I] Handle to a hash object.
831  *  dwFlags   [I] Type of key to generate.
832  *  phKey     [I/O] Address of the newly generated key.
833  *
834  * RETURNS
835  *  Success: TRUE
836  *  Failure: FALSE
837  */
838 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
839 		DWORD dwFlags, HCRYPTKEY *phKey)
840 {
841 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
842 	PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
843 	PCRYPTKEY key;
844 
845 	TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08x, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
846 
847 	if (!prov || !hash)
848 	{
849 		SetLastError(ERROR_INVALID_HANDLE);
850 		return FALSE;
851 	}
852 	if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV || hash->dwMagic != MAGIC_CRYPTHASH)
853 	{
854 		SetLastError(ERROR_INVALID_PARAMETER);
855 		return FALSE;
856 	}
857 	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
858 	{
859 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
860 		return FALSE;
861 	}
862 
863 	key->pProvider = prov;
864 	key->dwMagic = MAGIC_CRYPTKEY;
865 	if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
866         {
867             *phKey = (HCRYPTKEY)key;
868             return TRUE;
869         }
870 
871 	/* CSP error! */
872 	key->dwMagic = 0;
873 	CRYPT_Free(key);
874 	*phKey = 0;
875 	return FALSE;
876 }
877 
878 /******************************************************************************
879  * CryptDestroyHash (ADVAPI32.@)
880  *
881  * Destroys the hash object referenced by hHash.
882  *
883  * PARAMS
884  *  hHash [I] Handle of the hash object to be destroyed.
885  *
886  * RETURNS
887  *  Success: TRUE
888  *  Failure: FALSE
889  */
890 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
891 {
892 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
893 	PCRYPTPROV prov;
894 	BOOL ret;
895 
896 	TRACE("(0x%lx)\n", hHash);
897 
898 	if (!hash)
899 	{
900 		SetLastError(ERROR_INVALID_HANDLE);
901 		return FALSE;
902 	}
903 
904 	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
905 		hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
906 	{
907 		SetLastError(ERROR_INVALID_PARAMETER);
908 		return FALSE;
909 	}
910 
911 	prov = hash->pProvider;
912 	ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
913 	hash->dwMagic = 0;
914 	CRYPT_Free(hash);
915 	return ret;
916 }
917 
918 /******************************************************************************
919  * CryptDestroyKey (ADVAPI32.@)
920  *
921  * Releases the handle referenced by hKey.
922  *
923  * PARAMS
924  *  hKey [I] Handle of the key to be destroyed.
925  *
926  * RETURNS
927  *  Success: TRUE
928  *  Failure: FALSE
929  */
930 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
931 {
932 	PCRYPTKEY key = (PCRYPTKEY)hKey;
933 	PCRYPTPROV prov;
934 	BOOL ret;
935 
936 	TRACE("(0x%lx)\n", hKey);
937 
938 	if (!key)
939 	{
940 		SetLastError(ERROR_INVALID_HANDLE);
941 		return FALSE;
942 	}
943 
944 	if (!key->pProvider || key->dwMagic != MAGIC_CRYPTKEY ||
945 		key->pProvider->dwMagic != MAGIC_CRYPTPROV)
946 	{
947 		SetLastError(ERROR_INVALID_PARAMETER);
948 		return FALSE;
949 	}
950 
951 	prov = key->pProvider;
952 	ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
953 	key->dwMagic = 0;
954 	CRYPT_Free(key);
955 	return ret;
956 }
957 
958 /******************************************************************************
959  * CryptDuplicateHash (ADVAPI32.@)
960  *
961  * Duplicates a hash.
962  *
963  * PARAMS
964  *  hHash       [I] Handle to the hash to be copied.
965  *  pdwReserved [I] Reserved for future use and must be NULL.
966  *  dwFlags     [I] Reserved for future use and must be zero.
967  *  phHash      [O] Address of the handle to receive the copy.
968  *
969  * RETURNS
970  *  Success: TRUE
971  *  Failure: FALSE
972  */
973 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
974 		DWORD dwFlags, HCRYPTHASH *phHash)
975 {
976 	PCRYPTPROV prov;
977 	PCRYPTHASH orghash, newhash;
978 
979 	TRACE("(0x%lx, %p, %08x, %p)\n", hHash, pdwReserved, dwFlags, phHash);
980 
981 	orghash = (PCRYPTHASH)hHash;
982 	if (!orghash || pdwReserved || !phHash || !orghash->pProvider ||
983 		orghash->dwMagic != MAGIC_CRYPTHASH || orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
984 	{
985 		SetLastError(ERROR_INVALID_PARAMETER);
986 		return FALSE;
987 	}
988 
989 	prov = orghash->pProvider;
990 	if (!prov->pFuncs->pCPDuplicateHash)
991 	{
992 		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
993 		return FALSE;
994 	}
995 
996 	if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
997 	{
998 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
999 		return FALSE;
1000 	}
1001 
1002 	newhash->pProvider = prov;
1003 	newhash->dwMagic = MAGIC_CRYPTHASH;
1004 	if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
1005 	{
1006 		*phHash = (HCRYPTHASH)newhash;
1007 		return TRUE;
1008 	}
1009 	newhash->dwMagic = 0;
1010 	CRYPT_Free(newhash);
1011 	return FALSE;
1012 }
1013 
1014 /******************************************************************************
1015  * CryptDuplicateKey (ADVAPI32.@)
1016  *
1017  * Duplicate a key and the key's state.
1018  *
1019  * PARAMS
1020  *  hKey        [I] Handle of the key to copy.
1021  *  pdwReserved [I] Reserved for future use and must be NULL.
1022  *  dwFlags     [I] Reserved for future use and must be zero.
1023  *  phKey       [I] Address of the handle to the duplicated key.
1024  *
1025  * RETURNS
1026  *  Success: TRUE
1027  *  Failure: FALSE
1028  */
1029 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
1030 {
1031 	PCRYPTPROV prov;
1032 	PCRYPTKEY orgkey, newkey;
1033 
1034 	TRACE("(0x%lx, %p, %08x, %p)\n", hKey, pdwReserved, dwFlags, phKey);
1035 
1036 	orgkey = (PCRYPTKEY)hKey;
1037 	if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider ||
1038 		orgkey->dwMagic != MAGIC_CRYPTKEY ||
1039 		orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
1040 	{
1041 		SetLastError(ERROR_INVALID_PARAMETER);
1042 		return FALSE;
1043 	}
1044 
1045 	prov = orgkey->pProvider;
1046 	if (!prov->pFuncs->pCPDuplicateKey)
1047 	{
1048 		SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1049 		return FALSE;
1050 	}
1051 
1052 	if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1053 	{
1054 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1055 		return FALSE;
1056 	}
1057 
1058 	newkey->pProvider = prov;
1059 	newkey->dwMagic = MAGIC_CRYPTKEY;
1060 	if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
1061 	{
1062 		*phKey = (HCRYPTKEY)newkey;
1063 		return TRUE;
1064 	}
1065 	newkey->dwMagic = 0;
1066 	CRYPT_Free(newkey);
1067 	return FALSE;
1068 }
1069 
1070 /******************************************************************************
1071  * CryptEncrypt (ADVAPI32.@)
1072  *
1073  * Encrypts data.
1074  *
1075  * PARAMS
1076  *  hKey       [I] Handle to the encryption key.
1077  *  hHash      [I] Handle to a hash object.
1078  *  Final      [I] TRUE if this is the last section to encrypt.
1079  *  dwFlags    [I] Can be CRYPT_OAEP.
1080  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
1081  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
1082  *                   encrypted data after call.
1083  *  dwBufLen   [I] Length of the input pbData buffer.
1084  *
1085  * RETURNS
1086  *  Success: TRUE
1087  *  Failure: FALSE
1088  *
1089  *  NOTES
1090  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
1091  *   required for the returned data in pdwDataLen.
1092  */
1093 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1094 		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1095 {
1096 	PCRYPTPROV prov;
1097 	PCRYPTKEY key = (PCRYPTKEY)hKey;
1098 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1099 
1100 	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p, %d)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1101 
1102 	if (!key || !pdwDataLen || !key->pProvider ||
1103 		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1104 	{
1105 		SetLastError(ERROR_INVALID_PARAMETER);
1106 		return FALSE;
1107 	}
1108 
1109 	prov = key->pProvider;
1110 	return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
1111 			Final, dwFlags, pbData, pdwDataLen, dwBufLen);
1112 }
1113 
1114 /******************************************************************************
1115  * CryptEnumProvidersW (ADVAPI32.@)
1116  *
1117  * Returns the next available CSP.
1118  *
1119  * PARAMS
1120  *  dwIndex     [I] Index of the next provider to be enumerated.
1121  *  pdwReserved [I] Reserved for future use and must be NULL.
1122  *  dwFlags     [I] Reserved for future use and must be zero.
1123  *  pdwProvType [O] DWORD designating the type of the provider.
1124  *  pszProvName [O] Buffer that receives data from the provider.
1125  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
1126  *                    of bytes stored in the buffer on return.
1127  *
1128  *  RETURNS
1129  *   Success: TRUE
1130  *   Failure: FALSE
1131  *
1132  *  NOTES
1133  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
1134  *   for memory allocation purposes.
1135  */
1136 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
1137 		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
1138 {
1139 	HKEY hKey;
1140 	static const WCHAR providerW[] = {
1141                 'S','o','f','t','w','a','r','e','\\',
1142                 'M','i','c','r','o','s','o','f','t','\\',
1143                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1144                 'D','e','f','a','u','l','t','s','\\',
1145                 'P','r','o','v','i','d','e','r',0
1146         };
1147 	static const WCHAR typeW[] = {'T','y','p','e',0};
1148 	BOOL ret;
1149 
1150 	TRACE("(%d, %p, %d, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1151 			pdwProvType, pszProvName, pcbProvName);
1152 
1153 	if (pdwReserved || !pcbProvName)
1154 	{
1155 		SetLastError(ERROR_INVALID_PARAMETER);
1156 		return FALSE;
1157 	}
1158 	if (dwFlags)
1159 	{
1160 		SetLastError(NTE_BAD_FLAGS);
1161 		return FALSE;
1162 	}
1163 
1164 	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
1165 	{
1166 		SetLastError(NTE_FAIL);
1167 		return FALSE;
1168 	}
1169 
1170 	ret = TRUE;
1171 	if (!pszProvName)
1172 	{
1173 		DWORD numkeys;
1174 		WCHAR *provNameW;
1175 
1176 		RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
1177 				 NULL, NULL, NULL, NULL, NULL, NULL);
1178 
1179 		if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
1180 		{
1181 			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1182 			RegCloseKey(hKey);
1183 			return FALSE;
1184 		}
1185 
1186 		RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
1187 		CRYPT_Free(provNameW);
1188 		(*pcbProvName)++;
1189 		*pcbProvName *= sizeof(WCHAR);
1190 
1191 		if (dwIndex >= numkeys)
1192 		{
1193 			SetLastError(ERROR_NO_MORE_ITEMS);
1194 			ret = FALSE;
1195 		}
1196 	} else {
1197 		DWORD size = sizeof(DWORD);
1198 		DWORD result;
1199 		HKEY subkey;
1200 
1201 		result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
1202 		if (result)
1203 		{
1204 			SetLastError(result);
1205 			RegCloseKey(hKey);
1206 			return FALSE;
1207 		}
1208 		if (RegOpenKeyW(hKey, pszProvName, &subkey))
1209 		{
1210 			RegCloseKey(hKey);
1211 			return FALSE;
1212 		}
1213 
1214 		if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
1215 			ret = FALSE;
1216 
1217 		RegCloseKey(subkey);
1218 	}
1219 	RegCloseKey(hKey);
1220 	return ret;
1221 }
1222 
1223 /******************************************************************************
1224  * CryptEnumProvidersA (ADVAPI32.@)
1225  *
1226  * See CryptEnumProvidersW.
1227  */
1228 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
1229 		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
1230 {
1231 	PWSTR str = NULL;
1232 	DWORD bufsize;
1233 	BOOL ret;
1234 
1235 	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1236 			pdwProvType, pszProvName, pcbProvName);
1237 
1238 	if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1239 		return FALSE;
1240 	if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1241 	{
1242 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1243 		return FALSE;
1244 	}
1245 	ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1246 	if (str)
1247 		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1248 	*pcbProvName = bufsize / sizeof(WCHAR);  /* FIXME: not correct */
1249 	if (str)
1250 	{
1251 		CRYPT_Free(str);
1252 		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1253 		{
1254 			SetLastError(ERROR_MORE_DATA);
1255 			return FALSE;
1256 		}
1257 	}
1258 	return ret;
1259 }
1260 
1261 /******************************************************************************
1262  * CryptEnumProviderTypesW (ADVAPI32.@)
1263  *
1264  * Retrieves the next type of CSP supported.
1265  *
1266  * PARAMS
1267  *  dwIndex     [I] Index of the next provider to be enumerated.
1268  *  pdwReserved [I] Reserved for future use and must be NULL.
1269  *  dwFlags     [I] Reserved for future use and must be zero.
1270  *  pdwProvType [O] DWORD designating the type of the provider.
1271  *  pszTypeName [O] Buffer that receives data from the provider type.
1272  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1273  *                    of bytes stored in the buffer on return.
1274  *
1275  *  RETURNS
1276  *   Success: TRUE
1277  *   Failure: FALSE
1278  *
1279  *  NOTES
1280  *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
1281  *   for memory allocation purposes.
1282  */
1283 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1284 		DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1285 {
1286 	HKEY hKey, hSubkey;
1287 	DWORD keylen, numkeys, dwType;
1288 	PWSTR keyname, ch;
1289 	DWORD result;
1290 	static const WCHAR KEYSTR[] = {
1291                 'S','o','f','t','w','a','r','e','\\',
1292                 'M','i','c','r','o','s','o','f','t','\\',
1293                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
1294                 'D','e','f','a','u','l','t','s','\\',
1295                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
1296 	};
1297 	static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
1298 
1299 	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved,
1300 		dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1301 
1302 	if (pdwReserved || !pdwProvType || !pcbTypeName)
1303 	{
1304 		SetLastError(ERROR_INVALID_PARAMETER);
1305 		return FALSE;
1306 	}
1307 	if (dwFlags)
1308 	{
1309 		SetLastError(NTE_BAD_FLAGS);
1310 		return FALSE;
1311 	}
1312 
1313 	if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
1314 		return FALSE;
1315 
1316 	RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1317 	if (dwIndex >= numkeys)
1318 	{
1319 		SetLastError(ERROR_NO_MORE_ITEMS);
1320 		RegCloseKey(hKey);
1321 		return FALSE;
1322 	}
1323 	keylen++;
1324 	if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
1325 	{
1326 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1327 		RegCloseKey(hKey);
1328 		return FALSE;
1329 	}
1330 	if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
1331                 CRYPT_Free(keyname);
1332 		RegCloseKey(hKey);
1333 		return FALSE;
1334         }
1335 	RegOpenKeyW(hKey, keyname, &hSubkey);
1336 	RegCloseKey(hKey);
1337 
1338 	ch = keyname + strlenW(keyname);
1339 	/* Convert "Type 000" to 0, etc/ */
1340 	*pdwProvType = *(--ch) - '0';
1341 	*pdwProvType += (*(--ch) - '0') * 10;
1342 	*pdwProvType += (*(--ch) - '0') * 100;
1343 	CRYPT_Free(keyname);
1344 
1345 	result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
1346 	if (result)
1347 	{
1348 		SetLastError(result);
1349 		RegCloseKey(hSubkey);
1350 		return FALSE;
1351 	}
1352 
1353 	RegCloseKey(hSubkey);
1354 	return TRUE;
1355 }
1356 
1357 /******************************************************************************
1358  * CryptEnumProviderTypesA (ADVAPI32.@)
1359  *
1360  * See CryptEnumProviderTypesW.
1361  */
1362 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1363 		DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1364 {
1365 	PWSTR str = NULL;
1366 	DWORD bufsize;
1367 	BOOL ret;
1368 
1369 	TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1370 			pdwProvType, pszTypeName, pcbTypeName);
1371 
1372 	if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
1373 		return FALSE;
1374 	if ( pszTypeName && !(str = CRYPT_Alloc(bufsize)) )
1375 	{
1376 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1377 		return FALSE;
1378 	}
1379 	ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
1380 	if (str)
1381 		CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
1382 	*pcbTypeName = bufsize / sizeof(WCHAR);
1383 	if (str)
1384 	{
1385 		CRYPT_Free(str);
1386 		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1387 		{
1388 			SetLastError(ERROR_MORE_DATA);
1389 			return FALSE;
1390 		}
1391 	}
1392 	return ret;
1393 }
1394 
1395 /******************************************************************************
1396  * CryptExportKey (ADVAPI32.@)
1397  *
1398  * Exports a cryptographic key from a CSP.
1399  *
1400  * PARAMS
1401  *  hKey       [I] Handle to the key to export.
1402  *  hExpKey    [I] Handle to a cryptographic key of the end user.
1403  *  dwBlobType [I] Type of BLOB to be exported.
1404  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1405  *  pbData     [O] Buffer to receive BLOB data.
1406  *  pdwDataLen [I/O] Specifies the size of pbData.
1407  *
1408  * RETURNS
1409  *  Success: TRUE
1410  *  Failure: FALSE
1411  *
1412  * NOTES
1413  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1414  *  buffer needed to hold the BLOB.
1415  */
1416 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1417 		DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1418 {
1419 	PCRYPTPROV prov;
1420 	PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1421 
1422 	TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1423 
1424 	if (!key || !pdwDataLen || !key->pProvider ||
1425 		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1426 	{
1427 		SetLastError(ERROR_INVALID_PARAMETER);
1428 		return FALSE;
1429 	}
1430 
1431 	prov = key->pProvider;
1432 	return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1433 			dwBlobType, dwFlags, pbData, pdwDataLen);
1434 }
1435 
1436 /******************************************************************************
1437  * CryptGenKey (ADVAPI32.@)
1438  *
1439  * Generates a random cryptographic session key or a pub/priv key pair.
1440  *
1441  * PARAMS
1442  *  hProv   [I] Handle to a CSP.
1443  *  Algid   [I] Algorithm to use to make key.
1444  *  dwFlags [I] Specifies type of key to make.
1445  *  phKey   [I] Address of the handle to which the new key is copied.
1446  *
1447  *  RETURNS
1448  *   Success: TRUE
1449  *   Failure: FALSE
1450  */
1451 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1452 {
1453 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
1454 	PCRYPTKEY key;
1455 
1456 	TRACE("(0x%lx, %d, %08x, %p)\n", hProv, Algid, dwFlags, phKey);
1457 
1458 	if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
1459 	{
1460 		SetLastError(ERROR_INVALID_PARAMETER);
1461 		return FALSE;
1462 	}
1463 	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1464 	{
1465 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1466 		return FALSE;
1467 	}
1468 
1469 	key->pProvider = prov;
1470 	key->dwMagic = MAGIC_CRYPTKEY;
1471 	if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1472         {
1473             *phKey = (HCRYPTKEY)key;
1474             return TRUE;
1475         }
1476 
1477 	/* CSP error! */
1478 	key->dwMagic = 0;
1479 	CRYPT_Free(key);
1480 	return FALSE;
1481 }
1482 
1483 /******************************************************************************
1484  * CryptGetDefaultProviderW (ADVAPI32.@)
1485  *
1486  * Finds the default CSP of a certain provider type.
1487  *
1488  * PARAMS
1489  *  dwProvType  [I] Provider type to look for.
1490  *  pdwReserved [I] Reserved for future use and must be NULL.
1491  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1492  *  pszProvName [O] Name of the default CSP.
1493  *  pcbProvName [I/O] Size of pszProvName
1494  *
1495  * RETURNS
1496  *  Success: TRUE
1497  *  Failure: FALSE
1498  *
1499  * NOTES
1500  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1501  *  memory allocation purposes on return.
1502  */
1503 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1504 		DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1505 {
1506 	HKEY hKey;
1507 	PWSTR keyname;
1508 	DWORD result;
1509 	static const WCHAR nameW[] = {'N','a','m','e',0};
1510 
1511 	if (pdwReserved || !pcbProvName)
1512 	{
1513 		SetLastError(ERROR_INVALID_PARAMETER);
1514 		return FALSE;
1515 	}
1516 	if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1517 	{
1518 		SetLastError(NTE_BAD_FLAGS);
1519 		return FALSE;
1520 	}
1521 	if (dwProvType > 999)
1522 	{
1523 		SetLastError(NTE_BAD_PROV_TYPE);
1524 		return FALSE;
1525 	}
1526 	if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1527 	{
1528 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1529 		return FALSE;
1530 	}
1531 	if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1532 	{
1533 		CRYPT_Free(keyname);
1534 		SetLastError(NTE_PROV_TYPE_NOT_DEF);
1535 		return FALSE;
1536 	}
1537 	CRYPT_Free(keyname);
1538 
1539 	result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName);
1540 	RegCloseKey(hKey);
1541 
1542 	if (result)
1543 	{
1544 		if (result != ERROR_MORE_DATA)
1545 			SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1546 		else
1547 			SetLastError(result);
1548 
1549 		return FALSE;
1550 	}
1551 
1552 	return TRUE;
1553 }
1554 
1555 /******************************************************************************
1556  * CryptGetDefaultProviderA (ADVAPI32.@)
1557  *
1558  * See CryptGetDefaultProviderW.
1559  */
1560 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1561 		DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1562 {
1563 	PWSTR str = NULL;
1564 	DWORD bufsize;
1565 	BOOL ret;
1566 
1567 	TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1568 
1569 	CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &bufsize);
1570 	if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
1571 	{
1572 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1573 		return FALSE;
1574 	}
1575 	ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &bufsize);
1576 	if (str)
1577 		CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
1578 	*pcbProvName = bufsize / sizeof(WCHAR);
1579 	if (str)
1580 	{
1581 		CRYPT_Free(str);
1582 		if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1583 		{
1584 			SetLastError(ERROR_MORE_DATA);
1585 			return FALSE;
1586 		}
1587 	}
1588 	return ret;
1589 }
1590 
1591 /******************************************************************************
1592  * CryptGetHashParam (ADVAPI32.@)
1593  *
1594  * Retrieves data that controls the operations of a hash object.
1595  *
1596  * PARAMS
1597  *  hHash      [I] Handle of the hash object to question.
1598  *  dwParam    [I] Query type.
1599  *  pbData     [O] Buffer that receives the value data.
1600  *  pdwDataLen [I/O] Size of the pbData buffer.
1601  *  dwFlags    [I] Reserved for future use and must be zero.
1602  *
1603  * RETURNS
1604  *  Success: TRUE
1605  *  Failure: FALSE
1606  *
1607  * NOTES
1608  *  If pbData is NULL, pdwDataLen will contain the length required.
1609  */
1610 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1611 		DWORD *pdwDataLen, DWORD dwFlags)
1612 {
1613 	PCRYPTPROV prov;
1614 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1615 
1616 	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1617 
1618 	if (!hash || !pdwDataLen || !hash->pProvider ||
1619 		hash->dwMagic != MAGIC_CRYPTHASH || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1620 	{
1621 		SetLastError(ERROR_INVALID_PARAMETER);
1622 		return FALSE;
1623 	}
1624 
1625 	prov = hash->pProvider;
1626 	return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1627 			pbData, pdwDataLen, dwFlags);
1628 }
1629 
1630 /******************************************************************************
1631  * CryptGetKeyParam (ADVAPI32.@)
1632  *
1633  * Retrieves data that controls the operations of a key.
1634  *
1635  * PARAMS
1636  *  hKey       [I] Handle to they key in question.
1637  *  dwParam    [I] Specifies query type.
1638  *  pbData     [O] Sequence of bytes to receive data.
1639  *  pdwDataLen [I/O] Size of pbData.
1640  *  dwFlags    [I] Reserved for future use and must be zero.
1641  *
1642  * RETURNS
1643  *  Success: TRUE
1644  *  Failure: FALSE
1645  *
1646  * NOTES
1647  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1648  */
1649 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1650 		DWORD *pdwDataLen, DWORD dwFlags)
1651 {
1652 	PCRYPTPROV prov;
1653 	PCRYPTKEY key = (PCRYPTKEY)hKey;
1654 
1655 	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1656 
1657 	if (!key || !pdwDataLen || !key->pProvider ||
1658 		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
1659 	{
1660 		SetLastError(ERROR_INVALID_PARAMETER);
1661 		return FALSE;
1662 	}
1663 
1664 	prov = key->pProvider;
1665 	return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1666 			pbData, pdwDataLen, dwFlags);
1667 }
1668 
1669 /******************************************************************************
1670  * CryptGetProvParam (ADVAPI32.@)
1671  *
1672  * Retrieves parameters that control the operations of a CSP.
1673  *
1674  * PARAMS
1675  *  hProv      [I] Handle of the CSP in question.
1676  *  dwParam    [I] Specifies query type.
1677  *  pbData     [O] Buffer to receive the data.
1678  *  pdwDataLen [I/O] Size of pbData.
1679  *  dwFlags    [I] see MSDN Docs.
1680  *
1681  * RETURNS
1682  *  Success: TRUE
1683  *  Failure: FALSE
1684  *
1685  * NOTES
1686  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
1687  */
1688 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1689 		DWORD *pdwDataLen, DWORD dwFlags)
1690 {
1691 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
1692 
1693 	TRACE("(0x%lx, %d, %p, %p, %08x)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1694 
1695 	if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
1696 	{
1697 		SetLastError(ERROR_INVALID_PARAMETER);
1698 		return FALSE;
1699 	}
1700 
1701 	return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1702 }
1703 
1704 /******************************************************************************
1705  * CryptGetUserKey (ADVAPI32.@)
1706  *
1707  * Gets a handle of one of a user's two public/private key pairs.
1708  *
1709  * PARAMS
1710  *  hProv     [I] Handle of a CSP.
1711  *  dwKeySpec [I] Private key to use.
1712  *  phUserKey [O] Pointer to the handle of the retrieved keys.
1713  *
1714  * RETURNS
1715  *  Success: TRUE
1716  *  Failure: FALSE
1717  */
1718 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1719 {
1720 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
1721 	PCRYPTKEY key;
1722 
1723 	TRACE("(0x%lx, %d, %p)\n", hProv, dwKeySpec, phUserKey);
1724 
1725 	if (!prov)
1726 	{
1727 		SetLastError(ERROR_INVALID_HANDLE);
1728 		return FALSE;
1729 	}
1730 	if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
1731 	{
1732 		SetLastError(ERROR_INVALID_PARAMETER);
1733 		return FALSE;
1734 	}
1735 	if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1736 	{
1737 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1738 		return FALSE;
1739 	}
1740 
1741 	key->pProvider = prov;
1742 	key->dwMagic = MAGIC_CRYPTKEY;
1743 	if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1744         {
1745             *phUserKey = (HCRYPTKEY)key;
1746             return TRUE;
1747         }
1748 
1749 	/* CSP Error */
1750 	key->dwMagic = 0;
1751 	CRYPT_Free(key);
1752 	*phUserKey = 0;
1753 	return FALSE;
1754 }
1755 
1756 /******************************************************************************
1757  * CryptHashData (ADVAPI32.@)
1758  *
1759  * Adds data to a hash object.
1760  *
1761  * PARAMS
1762  *  hHash     [I] Handle of the hash object.
1763  *  pbData    [I] Buffer of data to be hashed.
1764  *  dwDataLen [I] Number of bytes to add.
1765  *  dwFlags   [I] Can be CRYPT_USERDATA
1766  *
1767  * RETURNS
1768  *  Success: TRUE
1769  *  Failure: FALSE
1770  */
1771 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1772 {
1773 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1774 	PCRYPTPROV prov;
1775 
1776 	TRACE("(0x%lx, %p, %d, %08x)\n", hHash, pbData, dwDataLen, dwFlags);
1777 
1778 	if (!hash)
1779 	{
1780 		SetLastError(ERROR_INVALID_HANDLE);
1781 		return FALSE;
1782 	}
1783 	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
1784 		hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1785 	{
1786 		SetLastError(ERROR_INVALID_PARAMETER);
1787 		return FALSE;
1788 	}
1789 
1790 	prov = hash->pProvider;
1791 	return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1792 }
1793 
1794 /******************************************************************************
1795  * CryptHashSessionKey (ADVAPI32.@)
1796  *
1797  * Compute the cryptographic hash of a session key object.
1798  *
1799  * PARAMS
1800  *  hHash   [I] Handle to the hash object.
1801  *  hKey    [I] Handle to the key to be hashed.
1802  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1803  *
1804  * RETURNS
1805  *  Success: TRUE
1806  *  Failure: FALSE
1807  */
1808 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1809 {
1810 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1811 	PCRYPTKEY key = (PCRYPTKEY)hKey;
1812 	PCRYPTPROV prov;
1813 
1814 	TRACE("(0x%lx, 0x%lx, %08x)\n", hHash, hKey, dwFlags);
1815 
1816 	if (!hash || !key)
1817 	{
1818 		SetLastError(ERROR_INVALID_HANDLE);
1819 		return FALSE;
1820 	}
1821 
1822 	if (!hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
1823 		hash->pProvider->dwMagic != MAGIC_CRYPTPROV || key->dwMagic != MAGIC_CRYPTKEY)
1824 	{
1825 		SetLastError(ERROR_INVALID_PARAMETER);
1826 		return FALSE;
1827 	}
1828 
1829 	prov = hash->pProvider;
1830 	return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1831 }
1832 
1833 /******************************************************************************
1834  * CryptImportKey (ADVAPI32.@)
1835  *
1836  * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
1837  *
1838  * PARAMS
1839  *  hProv     [I] Handle of a CSP.
1840  *  pbData    [I] Contains the key to be imported.
1841  *  dwDataLen [I] Length of the key.
1842  *  hPubKey   [I] Cryptographic key that decrypts pdData
1843  *  dwFlags   [I] Used only with a public/private key pair.
1844  *  phKey     [O] Imported key.
1845  *
1846  * RETURNS
1847  *  Success: TRUE
1848  *  Failure: FALSE
1849  */
1850 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, const BYTE *pbData, DWORD dwDataLen,
1851 		HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1852 {
1853 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
1854 	PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1855 
1856 	TRACE("(0x%lx, %p, %d, 0x%lx, %08x, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1857 
1858 	if (!prov || !pbData || !dwDataLen || !phKey ||
1859 		prov->dwMagic != MAGIC_CRYPTPROV ||
1860 		(pubkey && pubkey->dwMagic != MAGIC_CRYPTKEY))
1861 	{
1862 		SetLastError(ERROR_INVALID_PARAMETER);
1863 		return FALSE;
1864 	}
1865 
1866 	if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1867 	{
1868 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1869 		return FALSE;
1870 	}
1871 
1872 	importkey->pProvider = prov;
1873 	importkey->dwMagic = MAGIC_CRYPTKEY;
1874 	if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1875 			pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1876 	{
1877 		*phKey = (HCRYPTKEY)importkey;
1878 		return TRUE;
1879 	}
1880 
1881 	importkey->dwMagic = 0;
1882 	CRYPT_Free(importkey);
1883 	return FALSE;
1884 }
1885 
1886 /******************************************************************************
1887  * CryptSignHashW (ADVAPI32.@)
1888  *
1889  * Signs data.
1890  *
1891  * PARAMS
1892  *  hHash        [I] Handle of the hash object to be signed.
1893  *  dwKeySpec    [I] Private key to use.
1894  *  sDescription [I] Should be NULL.
1895  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
1896  *  pbSignature  [O] Buffer of the signature data.
1897  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
1898  *
1899  * RETURNS
1900  *  Success: TRUE
1901  *  Failure: FALSE
1902  *
1903  * NOTES
1904  *  Because of security flaws sDescription should not be used and should thus be
1905  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
1906  *  Providers.
1907  */
1908 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
1909 		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1910 {
1911 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1912 	PCRYPTPROV prov;
1913 
1914 	TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n",
1915 		hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
1916 
1917 	if (!hash)
1918 	{
1919 		SetLastError(ERROR_INVALID_HANDLE);
1920 		return FALSE;
1921 	}
1922 	if (!pdwSigLen || !hash->pProvider || hash->dwMagic != MAGIC_CRYPTHASH ||
1923 		 hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1924 	{
1925 		SetLastError(ERROR_INVALID_PARAMETER);
1926 		return FALSE;
1927 	}
1928 
1929 	prov = hash->pProvider;
1930 	return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
1931 		dwFlags, pbSignature, pdwSigLen);
1932 }
1933 
1934 /******************************************************************************
1935  * CryptSignHashA (ADVAPI32.@)
1936  *
1937  * See CryptSignHashW.
1938  */
1939 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1940 		DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1941 {
1942 	LPWSTR wsDescription;
1943 	BOOL result;
1944 
1945 	TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n",
1946 		hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
1947 
1948 	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
1949 	result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
1950 	CRYPT_Free(wsDescription);
1951 
1952 	return result;
1953 }
1954 
1955 /******************************************************************************
1956  * CryptSetHashParam (ADVAPI32.@)
1957  *
1958  * Customizes the operations of a hash object.
1959  *
1960  * PARAMS
1961  *  hHash   [I] Handle of the hash object to set parameters.
1962  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
1963  *  pbData  [I] Value data buffer.
1964  *  dwFlags [I] Reserved for future use and must be zero.
1965  *
1966  * RETURNS
1967  *  Success: TRUE
1968  *  Failure: FALSE
1969  */
1970 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
1971 {
1972 	PCRYPTPROV prov;
1973 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
1974 
1975 	TRACE("(0x%lx, %d, %p, %08x)\n", hHash, dwParam, pbData, dwFlags);
1976 
1977 	if (!hash || !pbData || !hash->pProvider ||
1978 		hash->dwMagic != MAGIC_CRYPTHASH || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
1979 	{
1980 		SetLastError(ERROR_INVALID_PARAMETER);
1981 		return FALSE;
1982 	}
1983 
1984 	prov = hash->pProvider;
1985 	return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1986 			dwParam, pbData, dwFlags);
1987 }
1988 
1989 /******************************************************************************
1990  * CryptSetKeyParam (ADVAPI32.@)
1991  *
1992  * Customizes a session key's operations.
1993  *
1994  * PARAMS
1995  *  hKey    [I] Handle to the key to set values.
1996  *  dwParam [I] See MSDN Doc.
1997  *  pbData  [I] Buffer of values to set.
1998  *  dwFlags [I] Only used when dwParam == KP_ALGID.
1999  *
2000  * RETURNS
2001  *  Success: TRUE
2002  *  Failure: FALSE
2003  */
2004 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
2005 {
2006 	PCRYPTPROV prov;
2007 	PCRYPTKEY key = (PCRYPTKEY)hKey;
2008 
2009 	TRACE("(0x%lx, %d, %p, %08x)\n", hKey, dwParam, pbData, dwFlags);
2010 
2011 	if (!key || !pbData || !key->pProvider ||
2012 		key->dwMagic != MAGIC_CRYPTKEY || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2013 	{
2014 		SetLastError(ERROR_INVALID_PARAMETER);
2015 		return FALSE;
2016 	}
2017 
2018 	prov = key->pProvider;
2019 	return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
2020 			dwParam, pbData, dwFlags);
2021 }
2022 
2023 /******************************************************************************
2024  * CryptSetProviderA (ADVAPI32.@)
2025  *
2026  * Specifies the current user's default CSP.
2027  *
2028  * PARAMS
2029  *  pszProvName [I] Name of the new default CSP.
2030  *  dwProvType  [I] Provider type of the CSP.
2031  *
2032  * RETURNS
2033  *  Success: TRUE
2034  *  Failure: FALSE
2035  */
2036 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
2037 {
2038 	TRACE("(%s, %d)\n", pszProvName, dwProvType);
2039 	return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2040 }
2041 
2042 /******************************************************************************
2043  * CryptSetProviderW (ADVAPI32.@)
2044  *
2045  * See CryptSetProviderA.
2046  */
2047 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
2048 {
2049 	TRACE("(%s, %d)\n", debugstr_w(pszProvName), dwProvType);
2050 	return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
2051 }
2052 
2053 /******************************************************************************
2054  * CryptSetProviderExW (ADVAPI32.@)
2055  *
2056  * Specifies the default CSP.
2057  *
2058  * PARAMS
2059  *  pszProvName [I] Name of the new default CSP.
2060  *  dwProvType  [I] Provider type of the CSP.
2061  *  pdwReserved [I] Reserved for future use and must be NULL.
2062  *  dwFlags     [I] See MSDN Doc.
2063  *
2064  * RETURNS
2065  *  Success: TRUE
2066  *  Failure: FALSE
2067  */
2068 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2069 {
2070 	HKEY hProvKey, hTypeKey;
2071 	PWSTR keyname;
2072 	static const WCHAR nameW[] = {'N','a','m','e',0};
2073 
2074 	TRACE("(%s, %d, %p, %08x)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
2075 
2076 	if (!pszProvName || pdwReserved)
2077 	{
2078 		SetLastError(ERROR_INVALID_PARAMETER);
2079 		return FALSE;
2080 	}
2081 	if (dwProvType > MAXPROVTYPES)
2082 	{
2083 		SetLastError(NTE_BAD_PROV_TYPE);
2084 		return FALSE;
2085 	}
2086 	if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
2087 			|| dwFlags == CRYPT_DELETE_DEFAULT)
2088 	{
2089 		SetLastError(NTE_BAD_FLAGS);
2090 		return FALSE;
2091 	}
2092 
2093 	if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
2094 	{
2095 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2096 		return FALSE;
2097 	}
2098 	if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2099 		keyname, &hTypeKey))
2100 	{
2101 		CRYPT_Free(keyname);
2102 		SetLastError(NTE_BAD_PROVIDER);
2103 		return FALSE;
2104 	}
2105 	CRYPT_Free(keyname);
2106 
2107 	if (dwFlags & CRYPT_DELETE_DEFAULT)
2108 	{
2109 		RegDeleteValueW(hTypeKey, nameW);
2110 	}
2111 	else
2112 	{
2113 		if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
2114 		{
2115 			RegCloseKey(hTypeKey);
2116 			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2117 			return FALSE;
2118 		}
2119 		if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
2120 			keyname, &hProvKey))
2121 		{
2122 			CRYPT_Free(keyname);
2123 			RegCloseKey(hTypeKey);
2124 			SetLastError(NTE_BAD_PROVIDER);
2125 			return FALSE;
2126 		}
2127 		CRYPT_Free(keyname);
2128 
2129 		if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (const BYTE *)pszProvName,
2130 			(strlenW(pszProvName) + 1)*sizeof(WCHAR)))
2131 		{
2132 			RegCloseKey(hTypeKey);
2133 			RegCloseKey(hProvKey);
2134 			return FALSE;
2135 		}
2136 
2137 		RegCloseKey(hProvKey);
2138 	}
2139 	RegCloseKey(hTypeKey);
2140 
2141 	return TRUE;
2142 }
2143 
2144 /******************************************************************************
2145  * CryptSetProviderExA (ADVAPI32.@)
2146  *
2147  * See CryptSetProviderExW.
2148  */
2149 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
2150 {
2151 	BOOL ret = FALSE;
2152 	PWSTR str = NULL;
2153 
2154 	TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
2155 
2156 	if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
2157 	{
2158 		ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
2159 		CRYPT_Free(str);
2160 	}
2161 	return ret;
2162 }
2163 
2164 /******************************************************************************
2165  * CryptSetProvParam (ADVAPI32.@)
2166  *
2167  * Customizes the operations of a CSP.
2168  *
2169  * PARAMS
2170  *  hProv   [I] Handle of a CSP.
2171  *  dwParam [I] See MSDN Doc.
2172  *  pbData  [I] Buffer that contains a value to set as a parameter.
2173  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
2174  *
2175  * RETURNS
2176  *  Success: TRUE
2177  *  Failure: FALSE
2178  */
2179 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, const BYTE *pbData, DWORD dwFlags)
2180 {
2181 	PCRYPTPROV prov = (PCRYPTPROV)hProv;
2182 
2183 	TRACE("(0x%lx, %d, %p, %08x)\n", hProv, dwParam, pbData, dwFlags);
2184 
2185 	if (!prov)
2186 	{
2187 		SetLastError(ERROR_INVALID_HANDLE);
2188 		return FALSE;
2189 	}
2190 	if (prov->dwMagic != MAGIC_CRYPTPROV)
2191 	{
2192 		SetLastError(ERROR_INVALID_PARAMETER);
2193 		return FALSE;
2194 	}
2195 	if (dwParam == PP_USE_HARDWARE_RNG)
2196 	{
2197 		FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
2198 		FIXME("\tLetting the CSP decide.\n");
2199 	}
2200 	if (dwFlags & PP_CLIENT_HWND)
2201 	{
2202 		/* FIXME: Should verify the parameter */
2203 		if (pbData /* && IsWindow((HWND)pbData) */)
2204 		{
2205 			crypt_hWindow = (HWND)(pbData);
2206 			return TRUE;
2207 		} else {
2208 			SetLastError(ERROR_INVALID_PARAMETER);
2209 			return FALSE;
2210 		}
2211 	}
2212 	/* All other flags go to the CSP */
2213 	return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
2214 }
2215 
2216 /******************************************************************************
2217  * CryptVerifySignatureW (ADVAPI32.@)
2218  *
2219  * Verifies the signature of a hash object.
2220  *
2221  * PARAMS
2222  *  hHash        [I] Handle of the hash object to verify.
2223  *  pbSignature  [I] Signature data to verify.
2224  *  dwSigLen     [I] Size of pbSignature.
2225  *  hPubKey      [I] Handle to the public key to authenticate signature.
2226  *  sDescription [I] Should be NULL.
2227  *  dwFlags      [I] See MSDN doc.
2228  *
2229  * RETURNS
2230  *  Success: TRUE
2231  *  Failure: FALSE
2232  *
2233  * NOTES
2234  *  Because of security flaws sDescription should not be used and should thus be
2235  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
2236  *  Providers.
2237  */
2238 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2239 		HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
2240 {
2241 	PCRYPTHASH hash = (PCRYPTHASH)hHash;
2242 	PCRYPTKEY key = (PCRYPTKEY)hPubKey;
2243 	PCRYPTPROV prov;
2244 
2245 	TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2246 			dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
2247 
2248 	if (!hash || !key || key->dwMagic != MAGIC_CRYPTKEY || hash->dwMagic != MAGIC_CRYPTHASH ||
2249 	    !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
2250 	    !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
2251 	{
2252 		SetLastError(ERROR_INVALID_PARAMETER);
2253 		return FALSE;
2254 	}
2255 
2256 	prov = hash->pProvider;
2257 	return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
2258 		key->hPrivate, sDescription, dwFlags);
2259 }
2260 
2261 /******************************************************************************
2262  * CryptVerifySignatureA (ADVAPI32.@)
2263  *
2264  * See CryptVerifySignatureW.
2265  */
2266 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, const BYTE *pbSignature, DWORD dwSigLen,
2267 		HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
2268 {
2269 	LPWSTR wsDescription;
2270 	BOOL result;
2271 
2272 	TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
2273 			dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
2274 
2275 	CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
2276 	result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
2277 	CRYPT_Free(wsDescription);
2278 
2279 	return result;
2280 }
2281 
2282 /******************************************************************************
2283  * OpenEncryptedFileRawA   (ADVAPI32.@)
2284  *
2285  * See OpenEncryptedFileRawW
2286  */
2287 DWORD WINAPI OpenEncryptedFileRawA(LPCSTR filename, ULONG flags, PVOID *context)
2288 {
2289     FIXME("(%s, %x, %p): stub\n", debugstr_a(filename), flags, context);
2290     return ERROR_CALL_NOT_IMPLEMENTED;
2291 }
2292 
2293 /******************************************************************************
2294  * OpenEncryptedFileRawW   (ADVAPI32.@)
2295  *
2296  * Opens an EFS encrypted file for backup/restore
2297  *
2298  * PARAMS
2299  *  filename   [I] Filename to operate on
2300  *  flags     [I] Operation to perform
2301  *  context    [I] Handle to the context (out)
2302  * RETURNS
2303  *  Success: ERROR_SUCCESS
2304  *  Failure: NTSTATUS error code
2305  */
2306 DWORD WINAPI OpenEncryptedFileRawW(LPCWSTR filename, ULONG flags, PVOID *context)
2307 {
2308     FIXME("(%s, %x, %p): stub\n", debugstr_w(filename), flags, context);
2309     return ERROR_CALL_NOT_IMPLEMENTED;
2310 }
2311 
2312 /******************************************************************************
2313  * ReadEncryptedFileRaw   (ADVAPI32.@)
2314  *
2315  * Export encrypted files
2316  *
2317  * PARAMS
2318  *  export   [I] pointer to the export callback function
2319  *  callback     [I] pointer to the application defined context
2320  *  context    [I] pointer to the system context
2321  * RETURNS
2322  *  Success: ERROR_SUCCESS
2323  *  Failure: NTSTATUS error code
2324  */
2325 DWORD WINAPI ReadEncryptedFileRaw(PFE_EXPORT_FUNC export, PVOID callback, PVOID context)
2326 {
2327     FIXME("(%p, %p, %p): stub\n", export, callback, context);
2328     return ERROR_CALL_NOT_IMPLEMENTED;
2329 }
2330 
2331 #ifndef __REACTOS__
2332 /******************************************************************************
2333  * SystemFunction030   (ADVAPI32.@)
2334  *
2335  * Tests if two blocks of 16 bytes are equal
2336  *
2337  * PARAMS
2338  *  b1,b2   [I] block of 16 bytes
2339  *
2340  * RETURNS
2341  *  TRUE  if blocks are the same
2342  *  FALSE if blocks are different
2343  */
2344 BOOL WINAPI SystemFunction030(LPCVOID b1, LPCVOID b2)
2345 {
2346     return !memcmp(b1, b2, 0x10);
2347 }
2348 
2349 /******************************************************************************
2350  * SystemFunction035   (ADVAPI32.@)
2351  *
2352  * Described here:
2353 http://disc.server.com/discussion.cgi?disc=148775;article=942;title=Coding%2FASM%2FSystem
2354  *
2355  * NOTES
2356  *  Stub, always return TRUE.
2357  */
2358 BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
2359 {
2360     FIXME("%s: stub\n", debugstr_a(lpszDllFilePath));
2361     return TRUE;
2362 }
2363 
2364 /******************************************************************************
2365  * SystemFunction036   (ADVAPI32.@)
2366  *
2367  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
2368  *
2369  * PARAMS
2370  *  pbBuffer [O] Pointer to memory to receive random bytes.
2371  *  dwLen   [I] Number of random bytes to fetch.
2372  *
2373  * RETURNS
2374  *  Success: TRUE
2375  *  Failure: FALSE
2376  */
2377 
2378 BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
2379 {
2380     int dev_random;
2381 
2382     dev_random = open("/dev/urandom", O_RDONLY);
2383     if (dev_random != -1)
2384     {
2385         if (!IsBadWritePtr( pbBuffer, dwLen ) &&
2386             read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
2387         {
2388             close(dev_random);
2389             return TRUE;
2390         }
2391         close(dev_random);
2392     }
2393     else
2394         FIXME("couldn't open /dev/urandom\n");
2395     SetLastError(NTE_FAIL);
2396     return FALSE;
2397 }
2398 
2399 /*
2400    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
2401    in crypt32.dll.
2402  */
2403 
2404 /******************************************************************************
2405  * SystemFunction040   (ADVAPI32.@)
2406  *
2407  * MSDN documents this function as RtlEncryptMemory and declares it in ntsecapi.h.
2408  *
2409  * PARAMS
2410  *  memory [I/O] Pointer to memory to encrypt.
2411  *  length [I] Length of region to encrypt in bytes.
2412  *  flags  [I] Control whether other processes are able to decrypt the memory.
2413  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
2414  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
2415  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2416  *
2417  * RETURNS
2418  *  Success: STATUS_SUCCESS
2419  *  Failure: NTSTATUS error code
2420  *
2421  * NOTES
2422  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2423  *  If flags are specified when encrypting, the same flag value must be given
2424  *  when decrypting the memory.
2425  */
2426 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
2427 {
2428 	FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
2429 	return STATUS_SUCCESS;
2430 }
2431 
2432 /******************************************************************************
2433  * SystemFunction041  (ADVAPI32.@)
2434  *
2435  * MSDN documents this function as RtlDecryptMemory and declares it in ntsecapi.h.
2436  *
2437  * PARAMS
2438  *  memory [I/O] Pointer to memory to decrypt.
2439  *  length [I] Length of region to decrypt in bytes.
2440  *  flags  [I] Control whether other processes are able to decrypt the memory.
2441  *    RTL_ENCRYPT_OPTION_SAME_PROCESS
2442  *    RTL_ENCRYPT_OPTION_CROSS_PROCESS
2443  *    RTL_ENCRYPT_OPTION_SAME_LOGON
2444  *
2445  * RETURNS
2446  *  Success: STATUS_SUCCESS
2447  *  Failure: NTSTATUS error code
2448  *
2449  * NOTES
2450  *  length must be a multiple of RTL_ENCRYPT_MEMORY_SIZE.
2451  *  If flags are specified when encrypting, the same flag value must be given
2452  *  when decrypting the memory.
2453  */
2454 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
2455 {
2456 	FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
2457 	return STATUS_SUCCESS;
2458 }
2459 #endif /* !__REACTOS __ */
2460 
2461 /******************************************************************************
2462  * WriteEncryptedFileRaw   (ADVAPI32.@)
2463  *
2464  * Import encrypted files
2465  *
2466  * PARAMS
2467  *  import   [I] pointer to the import callback function
2468  *  callback     [I] pointer to the application defined context
2469  *  context    [I] pointer to the system context
2470  * RETURNS
2471  *  Success: ERROR_SUCCESS
2472  *  Failure: NTSTATUS error code
2473  */
2474 DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC import, PVOID callback, PVOID context)
2475 {
2476     FIXME("(%p, %p, %p): stub\n", import, callback, context);
2477     return ERROR_CALL_NOT_IMPLEMENTED;
2478 }
2479