Added some more API docs.
[wine/multimedia.git] / dlls / advapi32 / crypt.c
blob4d02ff439c44600a2dad2422f9bcc10925e0a548
1 /*
2 * Copyright 1999 Ian Schmidt
3 * Copyright 2001 Travis Michielsen
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.
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.
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
20 /***********************************************************************
22 * TODO:
23 * - Reference counting
24 * - Thread-safing
25 * - Signature checking
28 #include <time.h>
29 #include <stdlib.h>
30 #include <stdio.h>
32 #include "wine/unicode.h"
33 #include "crypt.h"
34 #include "winnls.h"
35 #include "wincrypt.h"
36 #include "windef.h"
37 #include "winerror.h"
38 #include "winreg.h"
39 #include "winbase.h"
40 #include "winuser.h"
41 #include "wine/debug.h"
42 #include "winternl.h"
43 #include "ntstatus.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
47 HWND crypt_hWindow = 0;
49 #define CRYPT_ReturnLastError(err) {SetLastError(err); return FALSE;}
51 #define CRYPT_Alloc(size) ((LPVOID)LocalAlloc(LMEM_ZEROINIT, size))
52 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
54 static inline PSTR CRYPT_GetProvKeyName(PCSTR pProvName)
56 PCSTR KEYSTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider\\";
57 PSTR keyname;
59 keyname = CRYPT_Alloc(strlen(KEYSTR) + strlen(pProvName) +1);
60 if (keyname)
62 strcpy(keyname, KEYSTR);
63 strcpy(keyname + strlen(KEYSTR), pProvName);
64 } else
65 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
66 return keyname;
69 static inline PSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
71 PCSTR MACHINESTR = "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type XXX";
72 PCSTR USERSTR = "Software\\Microsoft\\Cryptography\\Provider Type XXX";
73 PSTR keyname;
74 PSTR ptr;
76 keyname = CRYPT_Alloc( (user ? strlen(USERSTR) : strlen(MACHINESTR)) +1);
77 if (keyname)
79 user ? strcpy(keyname, USERSTR) : strcpy(keyname, MACHINESTR);
80 ptr = keyname + strlen(keyname);
81 *(--ptr) = (dwType % 10) + '0';
82 *(--ptr) = (dwType / 10) + '0';
83 *(--ptr) = (dwType / 100) + '0';
84 } else
85 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
86 return keyname;
89 /* CRYPT_UnicodeTOANSI
90 * wstr - unicode string
91 * str - pointer to ANSI string
92 * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
94 * returns TRUE if unsuccessfull, FALSE otherwise.
95 * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
97 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
99 int count;
101 if (!wstr)
103 *str = NULL;
104 return TRUE;
106 count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
107 count = count < strsize ? count : strsize;
108 if (strsize == -1)
109 *str = CRYPT_Alloc(count * sizeof(CHAR));
110 if (*str)
112 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
113 return TRUE;
115 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
116 return FALSE;
119 /* CRYPT_ANSITOUnicode
120 * str - ANSI string
121 * wstr - pointer to unicode string
122 * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
124 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
126 int wcount;
128 if (!str)
130 *wstr = NULL;
131 return TRUE;
133 wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
134 wcount = wcount < wstrsize/sizeof(WCHAR) ? wcount : wstrsize/sizeof(WCHAR);
135 if (wstrsize == -1)
136 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
137 if (*wstr)
139 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
140 return TRUE;
142 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
143 return FALSE;
146 /* These next 2 functions are used by the VTableProvStruc structure */
147 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
149 if (!lpszImage || !pData)
151 SetLastError(ERROR_INVALID_PARAMETER);
152 return FALSE;
155 FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
157 return TRUE;
160 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
162 if (!phWnd)
163 return FALSE;
164 *phWnd = crypt_hWindow;
165 return TRUE;
168 #define CRYPT_GetProvFunc(name) \
169 if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
170 #define CRYPT_GetProvFuncOpt(name) \
171 provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
172 PCRYPTPROV CRYPT_LoadProvider(PSTR pImage)
174 PCRYPTPROV provider;
175 DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
177 if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
178 if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
179 if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
180 if ( !(provider->hModule = LoadLibraryA(pImage)) )
182 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
183 FIXME("Failed to load dll %s\n", debugstr_a(pImage));
184 goto error;
187 errorcode = NTE_PROVIDER_DLL_FAIL;
188 CRYPT_GetProvFunc(CPAcquireContext);
189 CRYPT_GetProvFunc(CPCreateHash);
190 CRYPT_GetProvFunc(CPDecrypt);
191 CRYPT_GetProvFunc(CPDeriveKey);
192 CRYPT_GetProvFunc(CPDestroyHash);
193 CRYPT_GetProvFunc(CPDestroyKey);
194 CRYPT_GetProvFuncOpt(CPDuplicateHash);
195 CRYPT_GetProvFuncOpt(CPDuplicateKey);
196 CRYPT_GetProvFunc(CPEncrypt);
197 CRYPT_GetProvFunc(CPExportKey);
198 CRYPT_GetProvFunc(CPGenKey);
199 CRYPT_GetProvFunc(CPGenRandom);
200 CRYPT_GetProvFunc(CPGetHashParam);
201 CRYPT_GetProvFunc(CPGetKeyParam);
202 CRYPT_GetProvFunc(CPGetProvParam);
203 CRYPT_GetProvFunc(CPGetUserKey);
204 CRYPT_GetProvFunc(CPHashData);
205 CRYPT_GetProvFunc(CPHashSessionKey);
206 CRYPT_GetProvFunc(CPImportKey);
207 CRYPT_GetProvFunc(CPReleaseContext);
208 CRYPT_GetProvFunc(CPSetHashParam);
209 CRYPT_GetProvFunc(CPSetKeyParam);
210 CRYPT_GetProvFunc(CPSetProvParam);
211 CRYPT_GetProvFunc(CPSignHash);
212 CRYPT_GetProvFunc(CPVerifySignature);
214 /* FIXME: Not sure what the pbContextInfo field is for.
215 * Does it need memory allocation?
217 provider->pVTable->Version = 3;
218 provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
219 provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
220 provider->pVTable->dwProvType = 0;
221 provider->pVTable->pbContextInfo = NULL;
222 provider->pVTable->cbContextInfo = 0;
223 provider->pVTable->pszProvName = NULL;
224 return provider;
226 error:
227 SetLastError(errorcode);
228 if (provider)
230 if (provider->hModule)
231 FreeLibrary(provider->hModule);
232 CRYPT_Free(provider->pVTable);
233 CRYPT_Free(provider->pFuncs);
234 CRYPT_Free(provider);
236 return NULL;
238 #undef CRYPT_GetProvFunc
239 #undef CRYPT_GetProvFuncOpt
242 /******************************************************************************
243 * CryptAcquireContextA (ADVAPI32.@)
244 * Acquire a crypto provider context handle.
246 * PARAMS
247 * phProv: Pointer to HCRYPTPROV for the output.
248 * pszContainer: Key Container Name
249 * pszProvider: Cryptographic Service Provider Name
250 * dwProvType: Crypto provider type to get a handle.
251 * dwFlags: flags for the operation
253 * RETURNS TRUE on success, FALSE on failure.
255 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
256 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
258 PCRYPTPROV pProv = NULL;
259 HKEY key;
260 PSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
261 BYTE* signature;
262 DWORD keytype, type, len;
263 ULONG r;
265 TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, pszContainer,
266 pszProvider, dwProvType, dwFlags);
268 if (!phProv || !dwProvType)
270 SetLastError(ERROR_INVALID_PARAMETER);
271 return FALSE;
273 if (dwProvType > MAXPROVTYPES)
275 SetLastError(NTE_BAD_PROV_TYPE);
276 return FALSE;
279 if (!pszProvider)
281 /* No CSP name specified so try the user default CSP first
282 * then try the machine default CSP
284 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
285 FIXME("No provider registered for crypto provider type %ld.\n", dwProvType);
286 SetLastError(NTE_PROV_TYPE_NOT_DEF);
287 return FALSE;
289 if (RegOpenKeyA(HKEY_CURRENT_USER, keyname, &key))
291 CRYPT_Free(keyname);
292 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
293 FIXME("No type registered for crypto provider type %ld.\n", dwProvType);
294 RegCloseKey(key);
295 SetLastError(NTE_PROV_TYPE_NOT_DEF);
296 goto error;
298 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) {
299 FIXME("Did not find registry entry of crypto provider for %s.\n", debugstr_a(keyname));
300 RegCloseKey(key);
301 SetLastError(NTE_PROV_TYPE_NOT_DEF);
302 goto error;
305 CRYPT_Free(keyname);
306 r = RegQueryValueExA(key, "Name", NULL, &keytype, NULL, &len);
307 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
309 TRACE("error %ld reading size of 'Name' from registry\n", r );
310 RegCloseKey(key);
311 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
312 goto error;
314 if(!(provname = CRYPT_Alloc(len)))
316 RegCloseKey(key);
317 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
318 goto error;
320 r = RegQueryValueExA(key, "Name", NULL, NULL, provname, &len);
321 if( r != ERROR_SUCCESS )
323 TRACE("error %ld reading 'Name' from registry\n", r );
324 RegCloseKey(key);
325 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
326 goto error;
328 RegCloseKey(key);
329 } else {
330 if ( !(provname = CRYPT_Alloc(strlen(pszProvider) +1)) )
332 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
333 goto error;
335 strcpy(provname, pszProvider);
338 keyname = CRYPT_GetProvKeyName(provname);
339 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &key)) goto error;
340 CRYPT_Free(keyname);
341 len = sizeof(DWORD);
342 r = RegQueryValueExA(key, "Type", NULL, NULL, (BYTE*)&type, &len);
343 if (r != ERROR_SUCCESS || type != dwProvType)
345 FIXME("Crypto provider has wrong type (%ld vs expected %ld).\n", type, dwProvType);
346 SetLastError(NTE_BAD_PROV_TYPE);
347 goto error;
350 r = RegQueryValueExA(key, "Image Path", NULL, &keytype, NULL, &len);
351 if ( r != ERROR_SUCCESS || keytype != REG_SZ)
353 TRACE("error %ld reading size of 'Image Path' from registry\n", r );
354 RegCloseKey(key);
355 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
356 goto error;
358 if (!(temp = CRYPT_Alloc(len)))
360 RegCloseKey(key);
361 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
362 goto error;
364 r = RegQueryValueExA(key, "Image Path", NULL, NULL, temp, &len);
365 if( r != ERROR_SUCCESS )
367 TRACE("error %ld reading 'Image Path' from registry\n", r );
368 RegCloseKey(key);
369 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
370 goto error;
373 r = RegQueryValueExA(key, "Signature", NULL, &keytype, NULL, &len);
374 if ( r == ERROR_SUCCESS && keytype == REG_BINARY )
376 if (!(signature = CRYPT_Alloc(len)))
378 RegCloseKey(key);
379 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
380 goto error;
382 r = RegQueryValueExA(key, "Signature", NULL, NULL, signature, &len);
383 if ( r != ERROR_SUCCESS )
385 TRACE("error %ld reading 'Signature'\n", r );
386 RegCloseKey(key);
387 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
388 goto error;
391 else
393 r = RegQueryValueExA(key, "SigInFile", NULL, &keytype, NULL, &len);
394 if (r != ERROR_SUCCESS)
396 TRACE("error %ld reading size of 'SigInFile'\n", r );
397 RegCloseKey(key);
398 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
399 goto error;
401 else
403 /* FIXME: The presence of the SigInFile value indicates the
404 * provider's signature is in its resources, so need to read it.
405 * But since CRYPT_VerifyImage is stubbed, provide any old thing
406 * for now.
408 if (!(signature = CRYPT_Alloc(1)))
410 RegCloseKey(key);
411 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
412 goto error;
416 RegCloseKey(key);
417 len = ExpandEnvironmentStringsA(temp, NULL, 0);
418 if ( !(imagepath = CRYPT_Alloc(len)) )
420 CRYPT_Free(signature);
421 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
422 goto error;
424 if (!ExpandEnvironmentStringsA(temp, imagepath, len))
426 CRYPT_Free(signature);
427 /* ExpandEnvironmentStrings will call SetLastError */
428 goto error;
431 if (!CRYPT_VerifyImage(imagepath, signature))
433 CRYPT_Free(signature);
434 SetLastError(NTE_SIGNATURE_FILE_BAD);
435 goto error;
437 pProv = CRYPT_LoadProvider(imagepath);
438 CRYPT_Free(temp);
439 CRYPT_Free(signature);
440 if (!pProv) {
441 /* CRYPT_LoadProvider calls SetLastError */
442 goto error;
444 pProv->pVTable->dwProvType = dwProvType;
445 pProv->pVTable->pszProvName = provname;
446 if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, (CHAR*)pszContainer, dwFlags, pProv->pVTable))
448 /* MSDN: When this flag is set, the value returned in phProv is undefined,
449 * and thus, the CryptReleaseContext function need not be called afterwards.
450 * Therefore, we must clean up everything now.
452 if (dwFlags & CRYPT_DELETEKEYSET)
454 FreeLibrary(pProv->hModule);
455 CRYPT_Free(provname);
456 CRYPT_Free(pProv->pFuncs);
457 CRYPT_Free(pProv);
458 } else {
459 *phProv = (HCRYPTPROV)pProv;
461 return TRUE;
463 /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
464 error:
465 if (pProv)
467 FreeLibrary(pProv->hModule);
468 CRYPT_Free(pProv->pVTable);
469 CRYPT_Free(pProv->pFuncs);
470 CRYPT_Free(pProv);
472 CRYPT_Free(provname);
473 CRYPT_Free(temp);
474 CRYPT_Free(imagepath);
475 CRYPT_Free(keyname);
476 return FALSE;
479 /******************************************************************************
480 * CryptAcquireContextW (ADVAPI32.@)
482 * see CryptAcquireContextA
484 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
485 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
487 PSTR pProvider = NULL, pContainer = NULL;
488 BOOL ret = FALSE;
490 TRACE("(%p, %s, %s, %ld, %08lx)\n", phProv, debugstr_w(pszContainer),
491 debugstr_w(pszProvider), dwProvType, dwFlags);
493 if ( !CRYPT_UnicodeToANSI(pszContainer, &pContainer, -1) )
494 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
495 if ( !CRYPT_UnicodeToANSI(pszProvider, &pProvider, -1) )
497 CRYPT_Free(pContainer);
498 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
501 ret = CryptAcquireContextA(phProv, pContainer, pProvider, dwProvType, dwFlags);
503 if (pContainer)
504 CRYPT_Free(pContainer);
505 if (pProvider)
506 CRYPT_Free(pProvider);
508 return ret;
511 /******************************************************************************
512 * CryptContextAddRef (ADVAPI32.@)
514 * Increases reference count of a cryptographic service provider handle
515 * by one.
517 * PARAMS
518 * hProv [I] Handle to the CSP whose reference is being incremented.
519 * pdwReserved [IN] Reserved for future use and must be NULL.
520 * dwFlags [I] Reserved for future use and must be NULL.
522 * RETURNS
523 * Success: TRUE
524 * Failure: FALSE
526 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
528 FIXME("(0x%lx, %p, %08lx): stub!\n", hProv, pdwReserved, dwFlags);
529 return FALSE;
530 /* InterlockIncrement?? */
533 /******************************************************************************
534 * CryptReleaseContext (ADVAPI32.@)
536 * Releases the handle of a CSP. Reference count is decreased.
538 * PARAMS
539 * hProv [I] Handle of a CSP.
540 * dwFlags [I] Reserved for future use and must be NULL.
542 * RETURNS
543 * Success: TRUE
544 * Failure: FALSE
546 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
548 PCRYPTPROV pProv = (PCRYPTPROV)hProv;
549 BOOL ret;
551 TRACE("(0x%lx, %08ld)\n", hProv, dwFlags);
553 if (!pProv)
555 SetLastError(NTE_BAD_UID);
556 return FALSE;
558 /* FIXME: Decrement the counter here first if possible */
559 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
560 FreeLibrary(pProv->hModule);
561 #if 0
562 CRYPT_Free(pProv->pVTable->pContextInfo);
563 #endif
564 CRYPT_Free(pProv->pVTable->pszProvName);
565 CRYPT_Free(pProv->pVTable);
566 CRYPT_Free(pProv->pFuncs);
567 CRYPT_Free(pProv);
568 return ret;
571 /******************************************************************************
572 * CryptGenRandom (ADVAPI32.@)
574 * Fills a buffer with cryptographically random bytes.
576 * PARAMS
577 * hProv [I] Handle of a CSP.
578 * dwLen [I] Number of bytes to generate.
579 * pbBuffer [I/O] Buffer to contain random bytes.
581 * RETURNS
582 * Success: TRUE
583 * Failure: FALSE
585 * NOTES
586 * pdBuffer must be at least dwLen bytes long.
588 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
590 PCRYPTPROV prov = (PCRYPTPROV)hProv;
592 TRACE("(0x%lx, %ld, %p)\n", hProv, dwLen, pbBuffer);
594 if (!hProv)
595 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
597 return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
600 /******************************************************************************
601 * CryptCreateHash (ADVAPI32.@)
603 * Initiates the hashing of a stream of data.
605 * PARAMS
606 * hProv [I] Handle of a CSP.
607 * Algid [I] Identifies the hash algorithm to use.
608 * hKey [I] Key for the hash (if required).
609 * dwFlags [I] Reserved for future use and must be NULL.
610 * phHash [O] Address of the future handle to the new hash object.
612 * RETURNS
613 * Success: TRUE
614 * Failure: FALSE
616 * NOTES
617 * If the algorithm is a keyed hash, hKey is the key.
619 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
620 DWORD dwFlags, HCRYPTHASH *phHash)
622 PCRYPTPROV prov = (PCRYPTPROV)hProv;
623 PCRYPTKEY key = (PCRYPTKEY)hKey;
624 PCRYPTHASH hash;
626 TRACE("(0x%lx, 0x%x, 0x%lx, %08lx, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
628 if (!prov)
629 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
630 if (!phHash)
631 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
632 if (dwFlags)
633 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
634 if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
635 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
637 hash->pProvider = prov;
639 if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
640 key ? key->hPrivate : 0, 0, &hash->hPrivate))
642 *phHash = (HCRYPTHASH)hash;
643 return TRUE;
646 /* CSP error! */
647 CRYPT_Free(hash);
648 return FALSE;
651 /******************************************************************************
652 * CryptDecrypt (ADVAPI32.@)
654 * Decrypts data encrypted by CryptEncrypt.
656 * PARAMS
657 * hKey [I] Handle to the decryption key.
658 * hHash [I] Handle to a hash object.
659 * Final [I] TRUE if this is the last section to be decrypted.
660 * dwFlags [I] Reserved for future use. Can be CRYPT_OAEP.
661 * pbData [I/O] Buffer that holds the encrypted data. Holds decrypted
662 * data on return
663 * pdwDataLen [I/O] Length of pbData before and after the call.
665 * RETURNS
666 * Success: TRUE
667 * Failure: FALSE
669 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
670 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
672 PCRYPTPROV prov;
673 PCRYPTKEY key = (PCRYPTKEY)hKey;
674 PCRYPTHASH hash = (PCRYPTHASH)hHash;
676 TRACE("(0x%lx, 0x%lx, %d, %08lx, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
678 if (!key || !pbData || !pdwDataLen)
679 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
681 prov = key->pProvider;
682 return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
683 Final, dwFlags, pbData, pdwDataLen);
686 /******************************************************************************
687 * CryptDeriveKey (ADVAPI32.@)
689 * Generates session keys derived from a base data value.
691 * PARAMS
692 * hProv [I] Handle to a CSP.
693 * Algid [I] Identifies the symmetric encryption algorithm to use.
694 * hBaseData [I] Handle to a hash object.
695 * dwFlags [I] Type of key to generate.
696 * phKey [I/O] Address of the newly generated key.
698 * RETURNS
699 * Success: TRUE
700 * Failure: FALSE
702 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
703 DWORD dwFlags, HCRYPTKEY *phKey)
705 PCRYPTPROV prov = (PCRYPTPROV)hProv;
706 PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
707 PCRYPTKEY key;
709 TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08lx, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
711 if (!prov || !hash)
712 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
713 if (!phKey)
714 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
715 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
716 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
718 key->pProvider = prov;
719 if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
721 *phKey = (HCRYPTKEY)key;
722 return TRUE;
725 /* CSP error! */
726 CRYPT_Free(key);
727 return FALSE;
730 /******************************************************************************
731 * CryptDestroyHash (ADVAPI32.@)
733 * Destroys the hash object referenced by hHash.
735 * PARAMS
736 * hHash [I] Handle of the hash object to be destroyed.
738 * RETURNS
739 * Success: TRUE
740 * Failure: FALSE
742 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
744 PCRYPTHASH hash = (PCRYPTHASH)hHash;
745 PCRYPTPROV prov;
746 BOOL ret;
748 TRACE("(0x%lx)\n", hHash);
750 if (!hash)
751 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
753 prov = hash->pProvider;
754 ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
755 CRYPT_Free(hash);
756 return ret;
759 /******************************************************************************
760 * CryptDestroyKey (ADVAPI32.@)
762 * Releases the handle referenced by hKey.
764 * PARAMS
765 * hKey [I] Handle of the key to be destroyed.
767 * RETURNS
768 * Success: TRUE
769 * Failure: FALSE
771 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
773 PCRYPTKEY key = (PCRYPTKEY)hKey;
774 PCRYPTPROV prov;
775 BOOL ret;
777 TRACE("(0x%lx)\n", hKey);
779 if (!key)
780 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
782 prov = key->pProvider;
783 ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
784 CRYPT_Free(key);
785 return ret;
788 /******************************************************************************
789 * CryptDuplicateHash (ADVAPI32.@)
791 * Duplicates a hash.
793 * PARAMS
794 * hHash [I] Handle to the hash to be copied.
795 * pdwReserved [I] Reserved for future use and must be zero.
796 * dwFlags [I] Reserved for future use and must be zero.
797 * phHash [O] Address of the handle to receive the copy.
799 * RETURNS
800 * Success: TRUE
801 * Failure: FALSE
803 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
804 DWORD dwFlags, HCRYPTHASH *phHash)
806 PCRYPTPROV prov;
807 PCRYPTHASH orghash, newhash;
809 TRACE("(0x%lx, %p, %08ld, %p)\n", hHash, pdwReserved, dwFlags, phHash);
811 orghash = (PCRYPTHASH)hHash;
812 if (!orghash || pdwReserved || !phHash)
813 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
815 prov = orghash->pProvider;
816 if (!prov->pFuncs->pCPDuplicateHash)
817 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
819 if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
820 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
822 newhash->pProvider = prov;
823 if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
825 *phHash = (HCRYPTHASH)newhash;
826 return TRUE;
828 CRYPT_Free(newhash);
829 return FALSE;
832 /******************************************************************************
833 * CryptDuplicateKey (ADVAPI32.@)
835 * Duplicate a key and the key's state.
837 * PARAMS
838 * hKey [I] Handle of the key to copy.
839 * pdwReserved [I] Reserved for future use and must be NULL.
840 * dwFlags [I] Reserved for future use and must be zero.
841 * phKey [I] Address of the handle to the duplicated key.
843 * RETURNS
844 * Success: TRUE
845 * Failure: FALSE
847 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
849 PCRYPTPROV prov;
850 PCRYPTKEY orgkey, newkey;
852 TRACE("(0x%lx, %p, %08ld, %p)\n", hKey, pdwReserved, dwFlags, phKey);
854 orgkey = (PCRYPTKEY)hKey;
855 if (!orgkey || pdwReserved || !phKey)
856 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
858 prov = orgkey->pProvider;
859 if (!prov->pFuncs->pCPDuplicateKey)
860 CRYPT_ReturnLastError(ERROR_CALL_NOT_IMPLEMENTED);
862 if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
863 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
865 newkey->pProvider = prov;
866 if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
868 *phKey = (HCRYPTKEY)newkey;
869 return TRUE;
871 CRYPT_Free(newkey);
872 return FALSE;
875 /******************************************************************************
876 * CryptEncrypt (ADVAPI32.@)
878 * Encrypts data.
880 * PARAMS
881 * hKey [I] Handle to the enryption key.
882 * hHash [I] Handle to a hash object.
883 * Final [I] TRUE if this is the last section to encrypt.
884 * dwFlags [I] Can be CRYPT_OAEP.
885 * pbData [I/O] Data to be encrypted. Contains encrypted data after call.
886 * pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
887 * encrypted data after call.
888 * dwBufLen [I] Length of the input pbData buffer.
890 * RETURNS
891 * Success: TRUE
892 * Failure: FALSE
894 * NOTES
895 * If pbData is NULL, CryptEncrypt determines stores the number of bytes
896 * required for the returned data in pdwDataLen.
898 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
899 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
901 PCRYPTPROV prov;
902 PCRYPTKEY key = (PCRYPTKEY)hKey;
903 PCRYPTHASH hash = (PCRYPTHASH)hHash;
905 TRACE("(0x%lx, 0x%lx, %d, %08ld, %p, %p, %ld)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
907 if (!key || !pdwDataLen)
908 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
910 prov = key->pProvider;
911 return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
912 Final, dwFlags, pbData, pdwDataLen, dwBufLen);
915 /******************************************************************************
916 * CryptEnumProvidersA (ADVAPI32.@)
918 * Returns the next availabe CPS.
920 * PARAMS
921 * dwIndex [I] Index of the next provider to be enumerated.
922 * pdwReserved [I] Reserved for future use and must be NULL.
923 * dwFlags [I] Reserved for future use and must be zero.
924 * pdwProvType [O] DWORD designating the type of the provider.
925 * pszProvName [O] Buffer that receives data from the provider.
926 * pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
927 * of bytes stored in the buffer no return.
929 * RETURNS
930 * Success: TRUE
931 * Failure: FALSE
933 * NOTES
934 * If pszProvName is NULL, CryptEnumProvidersA sets the size of the name
935 * for memory allocation purposes.
937 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
938 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
940 HKEY hKey;
942 TRACE("(%ld, %p, %ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
943 pdwProvType, pszProvName, pcbProvName);
945 if (pdwReserved || !pcbProvName) CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
946 if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
948 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider", &hKey))
949 CRYPT_ReturnLastError(NTE_FAIL);
951 if (!pszProvName)
953 DWORD numkeys;
954 RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, pcbProvName, NULL, NULL, NULL, NULL, NULL, NULL);
955 (*pcbProvName)++;
956 if (dwIndex >= numkeys)
957 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
958 } else {
959 DWORD size = sizeof(DWORD);
960 HKEY subkey;
961 if (RegEnumKeyA(hKey, dwIndex, pszProvName, *pcbProvName))
962 return FALSE;
963 if (RegOpenKeyA(hKey, pszProvName, &subkey))
964 return FALSE;
965 if (RegQueryValueExA(subkey, "Type", NULL, NULL, (BYTE*)pdwProvType, &size))
966 return FALSE;
967 RegCloseKey(subkey);
969 RegCloseKey(hKey);
970 return TRUE;
973 /******************************************************************************
974 * CryptEnumProvidersW (ADVAPI32.@)
976 * see CryptEnumProvidersA
978 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
979 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
981 PSTR str = NULL;
982 DWORD strlen;
983 BOOL ret; /* = FALSE; */
985 TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
986 pdwProvType, pszProvName, pcbProvName);
988 strlen = *pcbProvName / sizeof(WCHAR);
989 if ( pszProvName && (str = CRYPT_Alloc(strlen)) )
990 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
991 ret = CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
992 if (str)
994 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
995 CRYPT_Free(str);
997 *pcbProvName = strlen * sizeof(WCHAR);
998 return ret;
1001 /******************************************************************************
1002 * CryptEnumProviderTypesA (ADVAPI32i.@)
1004 * Retrieves the next type of CSP supported.
1006 * PARAMS
1007 * dwIndex [I] Index of the next provider to be enumerated.
1008 * pdwReserved [I] Reserved for future use and must be NULL.
1009 * dwFlags [I] Reserved for future use and must be zero.
1010 * pdwProvType [O] DWORD designating the type of the provider.
1011 * pszTypeName [O] Buffer that receives data from the provider type.
1012 * pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
1013 * of bytes stored in the buffer no return.
1015 * RETURNS
1016 * Success: TRUE
1017 * Failure: FALSE
1019 * NOTES
1020 * If pszTypeName is NULL, CryptEnumProviderTypesA sets the size of the name
1021 * for memory allocation purposes.
1023 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
1024 DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
1026 HKEY hKey, hSubkey;
1027 DWORD keylen, numkeys;
1028 PSTR keyname, ch;
1030 TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved,
1031 dwFlags, pdwProvType, pszTypeName, pcbTypeName);
1033 if (pdwReserved || !pdwProvType || !pcbTypeName)
1034 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1035 if (dwFlags) CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1037 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Cryptography\\Defaults\\Provider Types", &hKey))
1038 return FALSE;
1040 RegQueryInfoKeyA(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
1041 if (dwIndex >= numkeys)
1042 CRYPT_ReturnLastError(ERROR_NO_MORE_ITEMS);
1043 keylen++;
1044 if ( !(keyname = CRYPT_Alloc(keylen)) )
1045 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1046 if ( RegEnumKeyA(hKey, dwIndex, keyname, keylen) ) {
1047 CRYPT_Free(keyname);
1048 return FALSE;
1050 RegOpenKeyA(hKey, keyname, &hSubkey);
1051 ch = keyname + strlen(keyname);
1052 /* Convert "Type 000" to 0, etc/ */
1053 *pdwProvType = *(--ch) - '0';
1054 *pdwProvType += (*(--ch) - '0') * 10;
1055 *pdwProvType += (*(--ch) - '0') * 100;
1056 CRYPT_Free(keyname);
1057 RegQueryValueA(hSubkey, "TypeName", pszTypeName, pcbTypeName);
1058 RegCloseKey(hSubkey);
1059 RegCloseKey(hKey);
1060 return TRUE;
1063 /******************************************************************************
1064 * CryptEnumProviderTypesW (ADVAPI32.@)
1066 * see CryptEnumProviderTypesA
1068 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
1069 DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
1071 PSTR str = NULL;
1072 DWORD strlen;
1073 BOOL ret;
1075 TRACE("(%ld, %p, %08ld, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
1076 pdwProvType, pszTypeName, pcbTypeName);
1077 strlen = *pcbTypeName / sizeof(WCHAR);
1078 if ( pszTypeName && (str = CRYPT_Alloc(strlen)) )
1079 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1080 ret = CryptEnumProviderTypesA(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &strlen);
1081 if (str)
1083 CRYPT_ANSIToUnicode(str, &pszTypeName, *pcbTypeName);
1084 CRYPT_Free(str);
1086 *pcbTypeName = strlen * sizeof(WCHAR);
1087 return ret;
1090 /******************************************************************************
1091 * CryptExportKey (ADVAPI32.@)
1093 * Exports a cryptographic key from a CSP.
1095 * PARAMS
1096 * hKey [I] Handle to the key to export.
1097 * hExpKey [I] Handle to a cryptographic key of the end user.
1098 * dwBlobType [I] Type of BLOB to be exported.
1099 * dwFlags [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
1100 * pbData [O] Buffer to receive BLOB data.
1101 * pdwDataLen [I/O] Specifies the size of pbData.
1103 * RETURNS
1104 * Success: TRUE
1105 * Failure: FALSE
1107 * NOTES
1108 * if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
1109 * buffer needed to hold the BLOB.
1111 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
1112 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1114 PCRYPTPROV prov;
1115 PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
1117 TRACE("(0x%lx, 0x%lx, %ld, %08ld, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
1119 if (!key || pdwDataLen)
1120 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1122 prov = key->pProvider;
1123 return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
1124 dwBlobType, dwFlags, pbData, pdwDataLen);
1127 /******************************************************************************
1128 * CryptGenKey (ADVAPI32.@)
1130 * Generates a random cryptographic session key or a pub/priv key pair.
1132 * PARAMS
1133 * hProv [I] Handle to a CSP.
1134 * Algid [I] Algorithm to use to make key.
1135 * dwFlags [I] Specifies type of key to make.
1136 * phKey [I] Address of the handle to which the new key is copied.
1138 * RETURNS
1139 * Success: TRUE
1140 * Failure: FALSE
1142 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
1144 PCRYPTPROV prov = (PCRYPTPROV)hProv;
1145 PCRYPTKEY key;
1147 TRACE("(0x%lx, %d, %08ld, %p)\n", hProv, Algid, dwFlags, phKey);
1149 if (!prov)
1150 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1151 if (!phKey)
1152 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1153 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1154 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1156 key->pProvider = prov;
1158 if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
1160 *phKey = (HCRYPTKEY)key;
1161 return TRUE;
1164 /* CSP error! */
1165 CRYPT_Free(key);
1166 return FALSE;
1169 /******************************************************************************
1170 * CryptGetDefaultProviderA (ADVAPI32.@)
1172 * Finds the default CSP of a certain provider type.
1174 * PARAMS
1175 * dwProvType [I] Provider type to look for.
1176 * pdwReserved [I] Reserved for future use and must be NULL.
1177 * dwFlags [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
1178 * pszProvName [O] Name of the default CSP.
1179 * pcbProvName [I/O] Size of pszProvName
1181 * RETURNS
1182 * Success: TRUE
1183 * Failure: FALSE
1185 * NOTES
1186 * If pszProvName is NULL, pcbProvName will hold the size of the buffer for
1187 * memory allocation purposes on return.
1189 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
1190 DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
1192 HKEY hKey;
1193 PSTR keyname;
1195 if (pdwReserved || !pcbProvName)
1196 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1197 if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
1198 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1199 if (dwProvType > 999)
1200 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1201 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1202 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1203 if (RegOpenKeyA((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
1205 CRYPT_Free(keyname);
1206 CRYPT_ReturnLastError(NTE_PROV_TYPE_NOT_DEF);
1208 CRYPT_Free(keyname);
1209 if (RegQueryValueExA(hKey, "Name", NULL, NULL, pszProvName, pcbProvName))
1211 if (GetLastError() != ERROR_MORE_DATA)
1212 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
1213 return FALSE;
1215 RegCloseKey(hKey);
1216 return TRUE;
1219 /******************************************************************************
1220 * CryptGetDefaultProviderW (ADVAPI32.@)
1222 * see CryptGetDefaultProviderA
1224 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
1225 DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
1227 PSTR str = NULL;
1228 DWORD strlen;
1229 BOOL ret = FALSE;
1231 TRACE("(%ld, %p, %08ld, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
1233 strlen = *pcbProvName / sizeof(WCHAR);
1234 if ( pszProvName && !(str = CRYPT_Alloc(strlen)) )
1235 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1236 ret = CryptGetDefaultProviderA(dwProvType, pdwReserved, dwFlags, str, &strlen);
1237 if (str)
1239 CRYPT_ANSIToUnicode(str, &pszProvName, *pcbProvName);
1240 CRYPT_Free(str);
1242 *pcbProvName = strlen * sizeof(WCHAR);
1243 return ret;
1246 /******************************************************************************
1247 * CryptGetHashParam (ADVAPI32.@)
1249 * Retrieves data that controls the operations of a hash object.
1251 * PARAMS
1252 * hHash [I] Handle of the hash object to question.
1253 * dwParam [I] Query type.
1254 * pbData [O] Buffer that receives the value data.
1255 * pdwDataLen [I/O] Size of the pbData buffer.
1256 * dwFlags [I] Reserved for future use and must be zero.
1258 * RETURNS
1259 * Success: TRUE
1260 * Failure: FALSE
1262 * NOTES
1263 * If pbData is NULL, pdwDataLen will contain the length required.
1265 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
1266 DWORD *pdwDataLen, DWORD dwFlags)
1268 PCRYPTPROV prov;
1269 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1271 TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
1273 if (!hash || !pdwDataLen)
1274 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1276 prov = hash->pProvider;
1277 return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
1278 pbData, pdwDataLen, dwFlags);
1281 /******************************************************************************
1282 * CryptGetKeyParam (ADVAPI32.@)
1284 * Retrieves data that controls the operations of a key.
1286 * PARAMS
1287 * hKey [I] Handle to they key in question.
1288 * dwParam [I] Specifies query type.
1289 * pbData [O] Sequence of bytes to receive data.
1290 * pdwDataLen [I/O] Size of pbData.
1291 * dwFlags [I] Reserved for future use and must be zero.
1293 * RETURNS
1294 * Success: TRUE
1295 * Failure: FALSE
1297 * NOTES
1298 * If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
1300 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
1301 DWORD *pdwDataLen, DWORD dwFlags)
1303 PCRYPTPROV prov;
1304 PCRYPTKEY key = (PCRYPTKEY)hKey;
1306 TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
1308 if (!key || !pdwDataLen)
1309 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1311 prov = key->pProvider;
1312 return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
1313 pbData, pdwDataLen, dwFlags);
1316 /******************************************************************************
1317 * CryptGetProvParam (ADVAPI32.@)
1319 * Retrieves parameters that control the operations of a CSP.
1321 * PARAMS
1322 * hProv [I] Handle of the CSP in question.
1323 * dwParam [I] Specifies query type.
1324 * pbData [O] Buffer to receive the data.
1325 * pdwDataLen [I/O] Size of pbData.
1326 * dwFlags [I] see MSDN Docs.
1328 * RETURNS
1329 * Success: TRUE
1330 * Failure: FALSE
1332 * NOTES
1333 * If pbData is NULL, pdwDataLen is set to the needed buffer length.
1335 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
1336 DWORD *pdwDataLen, DWORD dwFlags)
1338 PCRYPTPROV prov = (PCRYPTPROV)hProv;
1340 TRACE("(0x%lx, %ld, %p, %p, %08ld)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
1342 return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
1345 /******************************************************************************
1346 * CryptGetUserKey (ADVAPI32.@)
1348 * Gets a handle of one of a user's two public/private key pairs.
1350 * PARAMS
1351 * hProv [I] Handle of a CSP.
1352 * dwKeySpec [I] Private key to use.
1353 * phUserKey [O] Pointer to the handle of the retrieved keys.
1355 * RETURNS
1356 * Success: TRUE
1357 * Failure: FALSE
1359 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
1361 PCRYPTPROV prov = (PCRYPTPROV)hProv;
1362 PCRYPTKEY key;
1364 TRACE("(0x%lx, %ld, %p)\n", hProv, dwKeySpec, phUserKey);
1366 if (!prov)
1367 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1368 if (!phUserKey)
1369 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1370 if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1371 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1373 key->pProvider = prov;
1375 if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
1377 *phUserKey = (HCRYPTKEY)key;
1378 return TRUE;
1381 /* CSP Error */
1382 CRYPT_Free(key);
1383 return FALSE;
1386 /******************************************************************************
1387 * CryptHashData (ADVAPI32.@)
1389 * Adds data to a hash object.
1391 * PARAMS
1392 * hHash [I] Handle of the hash object.
1393 * pbData [I] Buffer of data to be hashed.
1394 * dwDataLen [I] Number of bytes to add.
1395 * dwFlags [I] Can be CRYPT_USERDATA
1397 * RETURNS
1398 * Success: TRUE
1399 * Failure: FALSE
1401 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
1403 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1404 PCRYPTPROV prov;
1406 TRACE("(0x%lx, %p, %ld, %08ld)\n", hHash, pbData, dwDataLen, dwFlags);
1408 if (!hash)
1409 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1410 if (!pbData || !dwDataLen)
1411 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1413 prov = hash->pProvider;
1414 return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
1417 /******************************************************************************
1418 * CryptHashSessionKey (ADVAPI32.@)
1420 * PARAMS
1421 * hHash [I] Handle to the hash object.
1422 * hKey [I] Handle to the key to be hashed.
1423 * dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
1425 * RETURNS
1426 * Success: TRUE
1427 * Failure: FALSE
1429 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
1431 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1432 PCRYPTKEY key = (PCRYPTKEY)hKey;
1433 PCRYPTPROV prov;
1435 TRACE("(0x%lx, 0x%lx, %08ld)\n", hHash, hKey, dwFlags);
1437 if (!hash || !key)
1438 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1440 prov = hash->pProvider;
1441 return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
1444 /******************************************************************************
1445 * CryptImportKey (ADVAPI32.@)
1447 * PARAMS
1448 * hProv [I] Handle of a CSP.
1449 * pbData [I] Contains the key to be imported.
1450 * dwDataLen [I] Length of the key.
1451 * hPubKey [I] Cryptographic key that decrypts pdData
1452 * dwFlags [I] Used only with a public/private key pair.
1453 * phKey [O] Imported key.
1455 * RETURNS
1456 * Success: TRUE
1457 * Failure: FALSE
1459 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
1460 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
1462 PCRYPTPROV prov = (PCRYPTPROV)hProv;
1463 PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
1465 TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
1467 if (!prov || !pbData || !dwDataLen || !phKey)
1468 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1470 if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
1471 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1473 importkey->pProvider = prov;
1474 if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
1475 pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
1477 *phKey = (HCRYPTKEY)importkey;
1478 return TRUE;
1481 CRYPT_Free(importkey);
1482 return FALSE;
1485 /******************************************************************************
1486 * CryptSignHashA
1488 * Note: Since the sDesciption (string) is supposed to be NULL and
1489 * is only retained for compatibility no string conversions are required
1490 * and only one implementation is required for both ANSI and Unicode.
1491 * We still need to export both:
1493 * CryptSignHashA (ADVAPI32.@)
1494 * CryptSignHashW (ADVAPI32.@)
1496 * Signs data.
1498 * PARAMS
1499 * hHash [I] Handle of the hash object to be signed.
1500 * dwKeySpec [I] Private key to use.
1501 * sDescription [I] Must be NULL.
1502 * dwFlags [I] CRYPT_NOHASHOID/X931_FORMAT.
1503 * pbSignature [O] Buffer of the signature data.
1504 * pdwSigLen [I/O] Size of the pbSignature buffer.
1506 * RETURNS
1507 * Success: TRUE
1508 * Failure: FALSE
1510 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
1511 DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
1513 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1514 PCRYPTPROV prov;
1516 TRACE("(0x%lx, %ld, %08ld, %p, %p)\n", hHash, dwKeySpec, dwFlags, pbSignature, pdwSigLen);
1517 if (sDescription)
1518 WARN("The sDescription parameter is not supported (and no longer used). Ignoring.\n");
1520 if (!hash)
1521 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1522 if (!pdwSigLen)
1523 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1525 prov = hash->pProvider;
1526 return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, NULL,
1527 dwFlags, pbSignature, pdwSigLen);
1530 /******************************************************************************
1531 * CryptSetHashParam (ADVAPI32.@)
1533 * Customizes the operations of a hash object.
1535 * PARAMS
1536 * hHash [I] Handle of the hash object to set parameters.
1537 * dwParam [I] HP_HMAC_INFO/HASHVAL.
1538 * pbData [I] Value data buffer.
1539 * dwFlags [I] Reserved for future use and must be zero.
1541 * RETURNS
1542 * Success: TRUE
1543 * Failure: FALSE
1545 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1547 PCRYPTPROV prov;
1548 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1550 TRACE("(0x%lx, %ld, %p, %08ld)\n", hHash, dwParam, pbData, dwFlags);
1552 if (!hash || !pbData)
1553 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1555 prov = hash->pProvider;
1556 return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
1557 dwParam, pbData, dwFlags);
1560 /******************************************************************************
1561 * CryptSetKeyParam (ADVAPI32.@)
1563 * Customizes a session key's operations.
1565 * PARAMS
1566 * hKey [I] Handle to the key to set values.
1567 * dwParam [I] See MSDN Doc.
1568 * pbData [I] Buffer of values to set.
1569 * dwFlags [I] Only used when dwParam == KP_ALGID.
1571 * RETURNS
1572 * Success: TRUE
1573 * Failure: FALSE
1575 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1577 PCRYPTPROV prov;
1578 PCRYPTKEY key = (PCRYPTKEY)hKey;
1580 TRACE("(0x%lx, %ld, %p, %08ld)\n", hKey, dwParam, pbData, dwFlags);
1582 if (!key || !pbData)
1583 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1585 prov = key->pProvider;
1586 return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
1587 dwParam, pbData, dwFlags);
1590 /******************************************************************************
1591 * CryptSetProviderA (ADVAPI32.@)
1593 * Specifies the current user's default CSP.
1595 * PARAMS
1596 * pszProvName [I] Name of the new default CSP.
1597 * dwProvType [I] Provider type of the CSP.
1599 * RETURNS
1600 * Success: TRUE
1601 * Failure: FALSE
1603 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
1605 TRACE("(%s, %ld)\n", pszProvName, dwProvType);
1606 return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1609 /******************************************************************************
1610 * CryptSetProviderW (ADVAPI32.@)
1612 * See CryptSetProviderA
1614 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
1616 TRACE("(%s, %ld)\n", debugstr_w(pszProvName), dwProvType);
1617 return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
1620 /******************************************************************************
1621 * CryptSetProviderExA (ADVAPI32.@)
1623 * Specifies the default CSP.
1625 * PARAMS
1626 * pszProvName [I] Name of the new default CSP.
1627 * dwProvType [I] Provider type of the CSP.
1628 * pdwReserved [I] Reserved for future use and must be NULL.
1629 * dwFlags [I] See MSDN Doc.
1631 * RETURNS
1632 * Success: TRUE
1633 * Failure: FALSE
1635 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1637 HKEY hKey;
1638 PSTR keyname;
1640 TRACE("(%s, %ld, %p, %08ld)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
1642 if (!pszProvName || pdwReserved)
1643 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1644 if (dwProvType > MAXPROVTYPES)
1645 CRYPT_ReturnLastError(NTE_BAD_PROV_TYPE);
1646 if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
1647 || dwFlags == CRYPT_DELETE_DEFAULT)
1648 CRYPT_ReturnLastError(NTE_BAD_FLAGS);
1650 if (dwFlags & CRYPT_DELETE_DEFAULT)
1652 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1653 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1654 RegDeleteKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname);
1655 CRYPT_Free(keyname);
1656 return TRUE;
1659 if ( !(keyname = CRYPT_GetProvKeyName(pszProvName)) )
1660 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1661 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, keyname, &hKey))
1663 CRYPT_Free(keyname);
1664 CRYPT_ReturnLastError(NTE_BAD_PROVIDER);
1666 CRYPT_Free(keyname);
1667 RegCloseKey(hKey);
1668 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
1669 CRYPT_ReturnLastError(ERROR_NOT_ENOUGH_MEMORY);
1670 RegCreateKeyA( (dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, keyname, &hKey);
1671 CRYPT_Free(keyname);
1672 if (RegSetValueExA(hKey, "Name", 0, REG_SZ, pszProvName, strlen(pszProvName) +1))
1673 return FALSE;
1674 return TRUE;
1677 /******************************************************************************
1678 * CryptSetProviderExW (ADVAPI32.@)
1680 * See CryptSetProviderExA
1682 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
1684 BOOL ret = FALSE;
1685 PSTR str = NULL;
1687 TRACE("(%s, %ld, %p, %08ld)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
1689 if (CRYPT_UnicodeToANSI(pszProvName, &str, -1))
1691 ret = CryptSetProviderExA(str, dwProvType, pdwReserved, dwFlags);
1692 CRYPT_Free(str);
1694 return ret;
1697 /******************************************************************************
1698 * CryptSetProvParam (ADVAPI32.@)
1700 * Customizes the operations of a CSP.
1702 * PARAMS
1703 * hProv [I] Handle of a CSP.
1704 * dwParam [I] See MSDN Doc.
1705 * pbData [I] Buffer that contains a value to set as a parameter.
1706 * dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
1708 * RETURNS
1709 * Success: TRUE
1710 * Failure: FALSE
1712 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
1714 PCRYPTPROV prov = (PCRYPTPROV)hProv;
1716 TRACE("(0x%lx, %ld, %p, %08ld)\n", hProv, dwParam, pbData, dwFlags);
1718 if (!prov)
1719 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1720 if (dwFlags & PP_USE_HARDWARE_RNG)
1722 FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
1723 FIXME("\tLetting the CSP decide.\n");
1725 if (dwFlags & PP_CLIENT_HWND)
1727 /* FIXME: Should verify the parameter */
1728 if (pbData /* && IsWindow((HWND)pbData) */)
1730 crypt_hWindow = (HWND)(pbData);
1731 return TRUE;
1732 } else {
1733 SetLastError(ERROR_INVALID_PARAMETER);
1734 return FALSE;
1737 /* All other flags go to the CSP */
1738 return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
1741 /******************************************************************************
1742 * CryptVerifySignatureA
1744 * Note: Since the sDesciption (string) is supposed to be NULL and
1745 * is only retained for compatibility no string conversions are required
1746 * and only one implementation is required for both ANSI and Unicode.
1747 * We still need to export both:
1749 * CryptVerifySignatureA (ADVAPI32.@)
1750 * CryptVerifySignatureW (ADVAPI32.@)
1752 * Verifies the signature of a hash object.
1754 * PARAMS
1755 * hHash [I] Handle of the hash object to verify.
1756 * pbSignature [I] Signature data to verify.
1757 * dwSigLen [I] Size of pbSignature.
1758 * hPubKey [I] Handle to the public key to authenticate signature.
1759 * sDescription [I] Must be set to NULL.
1760 * dwFlags [I] See MSDN doc.
1762 * RETURNS
1763 * Success: TRUE
1764 * Failure: FALSE
1766 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
1767 HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
1769 PCRYPTHASH hash = (PCRYPTHASH)hHash;
1770 PCRYPTKEY key = (PCRYPTKEY)hPubKey;
1771 PCRYPTPROV prov;
1773 TRACE("(0x%lx, %p, %ld, 0x%lx, %08ld)\n", hHash, pbSignature,
1774 dwSigLen, hPubKey, dwFlags);
1775 if (sDescription)
1776 WARN("The sDescription parameter is not supported (and no longer used). Ignoring.\n");
1778 if (!hash || !key)
1779 CRYPT_ReturnLastError(ERROR_INVALID_HANDLE);
1780 if (!pbSignature || !dwSigLen)
1781 CRYPT_ReturnLastError(ERROR_INVALID_PARAMETER);
1783 prov = hash->pProvider;
1784 return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
1785 key->hPrivate, NULL, dwFlags);
1790 These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
1791 in crypt32.dll.
1794 /******************************************************************************
1795 * SystemFunction040 (ADVAPI32.@)
1797 * PARAMS:
1798 * memory : pointer to memory to encrypt
1799 * length : length of region to encrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
1800 * flags : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
1801 * control whether other processes are able to decrypt the memory. The same value must be given
1802 * when decrypting the memory.
1804 NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags) /* RtlEncryptMemory */
1806 FIXME("(%p, %lx, %lx): stub [RtlEncryptMemory]\n", memory, length, flags);
1807 return STATUS_SUCCESS;
1810 /******************************************************************************
1811 * SystemFunction041 (ADVAPI32.@)
1813 * PARAMS:
1814 * memory : pointer to memory to decrypt
1815 * length : length of region to decrypt, in bytes. must be multiple of RTL_ENCRYPT_MEMORY_SIZE
1816 * flags : RTL_ENCRYPT_OPTION_SAME_PROCESS | RTL_ENCRYPT_OPTION_CROSS_PROCESS, | RTL_ENCRYPT_OPTION_SAME_LOGON
1817 * control whether other processes are able to decrypt the memory. The same value must be given
1818 * when encrypting the memory.
1820 NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags) /* RtlDecryptMemory */
1822 FIXME("(%p, %lx, %lx): stub [RtlDecryptMemory]\n", memory, length, flags);
1823 return STATUS_SUCCESS;