~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/advapi32/crypt.c

Version: ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 #include "config.h"
 28 #include "wine/port.h"
 29 
 30 #include <time.h>
 31 #include <stdlib.h>
 32 #include <stdio.h>
 33 #include <sys/types.h>
 34 #ifdef HAVE_SYS_STAT_H
 35 # include <sys/stat.h>
 36 #endif
 37 #include <fcntl.h>
 38 #ifdef HAVE_UNISTD_H
 39 # include <unistd.h>
 40 #endif
 41 
 42 #include "ntstatus.h"
 43 #define WIN32_NO_STATUS
 44 #include "crypt.h"
 45 #include "winnls.h"
 46 #include "winreg.h"
 47 #include "rpc.h"
 48 #include "wine/debug.h"
 49 #include "wine/unicode.h"
 50 #include "winternl.h"
 51 
 52 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 53 
 54 static HWND crypt_hWindow;
 55 
 56 #define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
 57 #define CRYPT_Free(buffer) (LocalFree((HLOCAL)buffer))
 58 
 59 static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
 60 {
 61         static const WCHAR KEYSTR[] = {
 62                 'S','o','f','t','w','a','r','e','\\',
 63                 'M','i','c','r','o','s','o','f','t','\\',
 64                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
 65                 'D','e','f','a','u','l','t','s','\\',
 66                 'P','r','o','v','i','d','e','r','\\',0
 67         };
 68         PWSTR keyname;
 69 
 70         keyname = CRYPT_Alloc((strlenW(KEYSTR) + strlenW(pProvName) +1)*sizeof(WCHAR));
 71         if (keyname)
 72         {
 73                 strcpyW(keyname, KEYSTR);
 74                 strcpyW(keyname + strlenW(KEYSTR), pProvName);
 75         } else
 76                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 77         return keyname;
 78 }
 79 
 80 static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
 81 {
 82         static const WCHAR MACHINESTR[] = {
 83                 'S','o','f','t','w','a','r','e','\\',
 84                 'M','i','c','r','o','s','o','f','t','\\',
 85                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
 86                 'D','e','f','a','u','l','t','s','\\',
 87                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s','\\',
 88                 'T','y','p','e',' ','X','X','X',0
 89         };
 90         static const WCHAR USERSTR[] = {
 91                 'S','o','f','t','w','a','r','e','\\',
 92                 'M','i','c','r','o','s','o','f','t','\\',
 93                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
 94                 'P','r','o','v','i','d','e','r',' ','T','y','p','e',' ','X','X','X',0
 95         };
 96         PWSTR keyname;
 97         PWSTR ptr;
 98 
 99         keyname = CRYPT_Alloc( ((user ? strlenW(USERSTR) : strlenW(MACHINESTR)) +1)*sizeof(WCHAR));
100         if (keyname)
101         {
102                 user ? strcpyW(keyname, USERSTR) : strcpyW(keyname, MACHINESTR);
103                 ptr = keyname + strlenW(keyname);
104                 *(--ptr) = (dwType % 10) + '';
105                 *(--ptr) = ((dwType / 10) % 10) + '';
106                 *(--ptr) = (dwType / 100) + '';
107         } else
108                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
109         return keyname;
110 }
111 
112 /* CRYPT_UnicodeTOANSI
113  * wstr - unicode string
114  * str - pointer to ANSI string
115  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
116  *
117  * returns TRUE if unsuccessful, FALSE otherwise.
118  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
119  */
120 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
121 {
122         int count;
123 
124         if (!wstr)
125         {
126                 *str = NULL;
127                 return TRUE;
128         }
129         count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
130         if (strsize == -1)
131                 *str = CRYPT_Alloc(count * sizeof(CHAR));
132         else
133                 count = min( count, strsize );
134         if (*str)
135         {
136                 WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
137                 return TRUE;
138         }
139         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
140         return FALSE;
141 }
142 
143 /* CRYPT_ANSITOUnicode
144  * str - ANSI string
145  * wstr - pointer to unicode string
146  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
147  */
148 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
149 {
150         unsigned int wcount;
151 
152         if (!str)
153         {
154                 *wstr = NULL;
155                 return TRUE;
156         }
157         wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
158         if (wstrsize == -1)
159                 *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
160         else
161                 wcount = min( wcount, wstrsize/sizeof(WCHAR) );
162         if (*wstr)
163         {
164                 MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
165                 return TRUE;
166         }
167         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
168         return FALSE;
169 }
170 
171 /* These next 2 functions are used by the VTableProvStruc structure */
172 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
173 {
174         if (!lpszImage || !pData)
175         {
176                 SetLastError(ERROR_INVALID_PARAMETER);
177                 return FALSE;
178         }
179 
180         FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
181 
182         return TRUE;
183 }
184 
185 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
186 {
187         if (!phWnd)
188                 return FALSE;
189         *phWnd = crypt_hWindow;
190         return TRUE;
191 }
192 
193 #define CRYPT_GetProvFunc(name) \
194         if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
195 #define CRYPT_GetProvFuncOpt(name) \
196         provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
197 static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
198 {
199         PCRYPTPROV provider;
200         DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
201 
202         if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
203         if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
204         if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
205         if ( !(provider->hModule = LoadLibraryW(pImage)) )
206         {
207                 errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
208                 FIXME("Failed to load dll %s\n", debugstr_w(pImage));
209                 goto error;
210         }
211         provider->dwMagic = MAGIC_CRYPTPROV;
212         provider->refcount = 1;
213 
214         errorcode = NTE_PROVIDER_DLL_FAIL;
215         CRYPT_GetProvFunc(CPAcquireContext);
216         CRYPT_GetProvFunc(CPCreateHash);
217         CRYPT_GetProvFunc(CPDecrypt);
218         CRYPT_GetProvFunc(CPDeriveKey);
219         CRYPT_GetProvFunc(CPDestroyHash);
220         CRYPT_GetProvFunc(CPDestroyKey);
221         CRYPT_GetProvFuncOpt(CPDuplicateHash);
222         CRYPT_GetProvFuncOpt(CPDuplicateKey);
223         CRYPT_GetProvFunc(CPEncrypt);
224         CRYPT_GetProvFunc(CPExportKey);
225         CRYPT_GetProvFunc(CPGenKey);
226         CRYPT_GetProvFunc(CPGenRandom);
227         CRYPT_GetProvFunc(CPGetHashParam);
228         CRYPT_GetProvFunc(CPGetKeyParam);
229         CRYPT_GetProvFunc(CPGetProvParam);
230         CRYPT_GetProvFunc(CPGetUserKey);
231         CRYPT_GetProvFunc(CPHashData);
232         CRYPT_GetProvFunc(CPHashSessionKey);
233         CRYPT_GetProvFunc(CPImportKey);
234         CRYPT_GetProvFunc(CPReleaseContext);
235         CRYPT_GetProvFunc(CPSetHashParam);
236         CRYPT_GetProvFunc(CPSetKeyParam);
237         CRYPT_GetProvFunc(CPSetProvParam);
238         CRYPT_GetProvFunc(CPSignHash);
239         CRYPT_GetProvFunc(CPVerifySignature);
240 
241         /* FIXME: Not sure what the pbContextInfo field is for.
242          *        Does it need memory allocation?
243          */
244         provider->pVTable->Version = 3;
245         provider->pVTable->pFuncVerifyImage = (FARPROC)CRYPT_VerifyImage;
246         provider->pVTable->pFuncReturnhWnd = (FARPROC)CRYPT_ReturnhWnd;
247         provider->pVTable->dwProvType = 0;
248         provider->pVTable->pbContextInfo = NULL;
249         provider->pVTable->cbContextInfo = 0;
250         provider->pVTable->pszProvName = NULL;
251         return provider;
252 
253 error:
254         SetLastError(errorcode);
255         if (provider)
256         {
257                 provider->dwMagic = 0;
258                 if (provider->hModule)
259                         FreeLibrary(provider->hModule);
260                 CRYPT_Free(provider->pVTable);
261                 CRYPT_Free(provider->pFuncs);
262                 CRYPT_Free(provider);
263         }
264         return NULL;
265 }
266 #undef CRYPT_GetProvFunc
267 #undef CRYPT_GetProvFuncOpt
268 
269 
270 static void CRYPT_CreateMachineGuid(void)
271 {
272         static const WCHAR cryptographyW[] = {
273                 'S','o','f','t','w','a','r','e','\\',
274                 'M','i','c','r','o','s','o','f','t','\\',
275                 'C','r','y','p','t','o','g','r','a','p','h','y',0 };
276         static const WCHAR machineGuidW[] = {
277                 'M','a','c','h','i','n','e','G','u','i','d',0 };
278         LONG r;
279         HKEY key;
280 
281         r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cryptographyW, 0, KEY_ALL_ACCESS,
282                           &key);
283         if (!r)
284         {
285                 DWORD size;
286 
287                 r = RegQueryValueExW(key, machineGuidW, NULL, NULL, NULL, &size);
288                 if (r == ERROR_FILE_NOT_FOUND)
289                 {
290                         static const WCHAR rpcrt4[] = {
291                                 'r','p','c','r','t','4',0 };
292                         HMODULE lib = LoadLibraryW(rpcrt4);
293 
294                         if (lib)
295                         {
296                                 RPC_STATUS (RPC_ENTRY *pUuidCreate)(UUID *);
297                                 UUID uuid;
298                                 WCHAR buf[37];
299                                 RPC_STATUS rs;
300                                 static const WCHAR uuidFmt[] = {
301                                     '%','','8','x','-','%','','4','x','-',
302                                     '%','','4','x','-','%','','2','x',
303                                     '%','','2','x','-','%','','2','x',
304                                     '%','','2','x','%','','2','x',
305                                     '%','','2','x','%','','2','x',
306                                     '%','','2','x',0 };
307 
308                                 pUuidCreate = GetProcAddress(lib, "UuidCreate");
309                                 rs = pUuidCreate(&uuid);
310                                 if (rs == S_OK)
311                                 {
312                                     sprintfW(buf, uuidFmt,
313                                              uuid.Data1, uuid.Data2, uuid.Data3,
314                                              uuid.Data4[0], uuid.Data4[1],
315                                              uuid.Data4[2], uuid.Data4[3],
316                                              uuid.Data4[4], uuid.Data4[5],
317                                              uuid.Data4[6], uuid.Data4[7] );
318                                     RegSetValueExW(key, machineGuidW, 0, REG_SZ,
319                                                    (const BYTE *)buf,
320                                                    (lstrlenW(buf)+1)*sizeof(WCHAR));
321                                 }
322                                 FreeLibrary(lib);
323                         }
324                 }
325                 RegCloseKey(key);
326         }
327 }
328 
329 /******************************************************************************
330  * CryptAcquireContextW (ADVAPI32.@)
331  *
332  * Acquire a crypto provider context handle.
333  *
334  * PARAMS
335  *  phProv       [O] Pointer to HCRYPTPROV for the output.
336  *  pszContainer [I] Key Container Name
337  *  pszProvider  [I] Cryptographic Service Provider Name
338  *  dwProvType   [I] Crypto provider type to get a handle.
339  *  dwFlags      [I] flags for the operation
340  *
341  * RETURNS 
342  *  TRUE on success, FALSE on failure.
343  */
344 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
345                 LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
346 {
347         PCRYPTPROV pProv = NULL;
348         HKEY key;
349         PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
350         PSTR provnameA = NULL, pszContainerA = NULL;
351         DWORD keytype, type, len;
352         ULONG r;
353         static const WCHAR nameW[] = {'N','a','m','e',0};
354         static const WCHAR typeW[] = {'T','y','p','e',0};
355         static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
356 
357         TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_w(pszContainer),
358                 debugstr_w(pszProvider), dwProvType, dwFlags);
359 
360         if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
361         {
362                 SetLastError(NTE_BAD_PROV_TYPE);
363                 return FALSE;
364         }
365         
366         if (!phProv)
367         {
368                 SetLastError(ERROR_INVALID_PARAMETER);
369                 return FALSE;
370         }
371 
372         /* Make sure the MachineGuid value exists */
373         CRYPT_CreateMachineGuid();
374 
375         if (!pszProvider || !*pszProvider)
376         {
377                 /* No CSP name specified so try the user default CSP first
378                  * then try the machine default CSP
379                  */
380                 if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
381                         TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
382                         SetLastError(NTE_PROV_TYPE_NOT_DEF);
383                         return FALSE;
384                 }
385                 if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
386                 {
387                         CRYPT_Free(keyname);
388                         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
389                                 TRACE("No type registered for crypto provider type %d.\n", dwProvType);
390                                 RegCloseKey(key);
391                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
392                                 goto error;
393                         }
394                         if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
395                                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
396                                 CRYPT_Free(keyname);
397                                 RegCloseKey(key);
398                                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
399                                 goto error;
400                         }
401                 }
402                 CRYPT_Free(keyname);
403                 r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
404                 if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
405                 {
406                         TRACE("error %d reading size of 'Name' from registry\n", r );
407                         RegCloseKey(key);
408                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
409                         goto error;
410                 }
411                 if(!(provname = CRYPT_Alloc(len)))
412                 {
413                         RegCloseKey(key);
414                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
415                         goto error;
416                 }
417                 r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
418                 if( r != ERROR_SUCCESS )
419                 {
420                         TRACE("error %d reading 'Name' from registry\n", r );
421                         RegCloseKey(key);
422                         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
423                         goto error;
424                 }
425                 RegCloseKey(key);
426         } else {
427                 if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
428                 {
429                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
430                         goto error;
431                 }
432                 strcpyW(provname, pszProvider);
433         }
434 
435         keyname = CRYPT_GetProvKeyName(provname);
436         r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
437         CRYPT_Free(keyname);
438         if (r != ERROR_SUCCESS)
439         {
440                 SetLastError(NTE_KEYSET_NOT_DEF);
441                 goto error;
442         }
443         len = sizeof(DWORD);
444         r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
445         if (r != ERROR_SUCCESS)
446         {
447                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
448                 goto error;
449         }
450         if (type != dwProvType)
451         {
452                 TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
453                 SetLastError(NTE_PROV_TYPE_NO_MATCH);
454                 goto error;
455         }
456 
457         r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
458         if ( r != ERROR_SUCCESS || keytype != REG_SZ)
459         {
460                 TRACE("error %d reading size of 'Image Path' from registry\n", r );
461                 RegCloseKey(key);
462                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
463                 goto error;
464         }
465         if (!(temp = CRYPT_Alloc(len)))
466         {
467                 RegCloseKey(key);
468                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
469                 goto error;
470         }
471         r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
472         if( r != ERROR_SUCCESS )
473         {
474                 TRACE("error %d reading 'Image Path' from registry\n", r );
475                 RegCloseKey(key);
476                 SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
477                 goto error;
478         }
479         RegCloseKey(key);
480         len = ExpandEnvironmentStringsW(temp, NULL, 0);
481         if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
482         {
483                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
484                 goto error;
485         }
486         if (!ExpandEnvironmentStringsW(temp, imagepath, len))
487         {
488                 /* ExpandEnvironmentStrings will call SetLastError */
489                 goto error;
490         }
491         pProv = CRYPT_LoadProvider(imagepath);
492         if (!pProv) {
493                 /* CRYPT_LoadProvider calls SetLastError */
494                 goto error;
495         }
496         pProv->pVTable->dwProvType = dwProvType;
497         if(!CRYPT_UnicodeToANSI(provname, &provnameA, -1))
498         {
499                 /* CRYPT_UnicodeToANSI calls SetLastError */
500                 goto error;
501         }
502         pProv->pVTable->pszProvName = provnameA;
503         if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, -1))
504         {
505                 /* CRYPT_UnicodeToANSI calls SetLastError */
506                 goto error;
507         }
508         if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
509         {
510                 /* MSDN: When this flag is set, the value returned in phProv is undefined,
511                  *       and thus, the CryptReleaseContext function need not be called afterwards.
512                  *       Therefore, we must clean up everything now.
513                  */
514                 if (dwFlags & CRYPT_DELETEKEYSET)
515                 {
516                         pProv->dwMagic = 0;
517                         FreeLibrary(pProv->hModule);
518                         CRYPT_Free(provnameA);
519                         CRYPT_Free(pProv->pVTable);
520                         CRYPT_Free(pProv->pFuncs);
521                         CRYPT_Free(pProv);
522                 } else {
523                         *phProv = (HCRYPTPROV)pProv;
524                 }
525                 CRYPT_Free(pszContainerA);
526                 CRYPT_Free(provname);
527                 CRYPT_Free(temp);
528                 CRYPT_Free(imagepath);
529                 return TRUE;
530         }
531         /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
532 error:
533         if (pProv)
534         {
535                 pProv->dwMagic = 0;
536                 if (pProv->hModule)
537                         FreeLibrary(pProv->hModule);
538                 CRYPT_Free(pProv->pVTable);
539                 CRYPT_Free(pProv->pFuncs);
540                 CRYPT_Free(pProv);
541         }
542         CRYPT_Free(pszContainerA);
543         CRYPT_Free(provnameA);
544         CRYPT_Free(provname);
545         CRYPT_Free(temp);
546         CRYPT_Free(imagepath);
547         return FALSE;
548 }
549 
550 /******************************************************************************
551  * CryptAcquireContextA (ADVAPI32.@)
552  *
553  * See CryptAcquireContextW.
554  */
555 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
556                 LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
557 {
558         PWSTR pProvider = NULL, pContainer = NULL;
559         BOOL ret = FALSE;
560 
561         TRACE("(%p, %s, %s, %d, %08x)\n", phProv, pszContainer,
562                 pszProvider, dwProvType, dwFlags);
563 
564         if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
565         {
566                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
567                 return FALSE;
568         }
569         if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
570         {
571                 CRYPT_Free(pContainer);
572                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
573                 return FALSE;
574         }
575 
576         ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
577 
578         CRYPT_Free(pContainer);
579         CRYPT_Free(pProvider);
580 
581         return ret;
582 }
583 
584 /******************************************************************************
585  * CryptContextAddRef (ADVAPI32.@)
586  *
587  * Increases reference count of a cryptographic service provider handle
588  * by one.
589  *
590  * PARAMS
591  *  hProv       [I] Handle to the CSP whose reference is being incremented.
592  *  pdwReserved [IN] Reserved for future use and must be NULL.
593  *  dwFlags     [I] Reserved for future use and must be NULL.
594  *
595  * RETURNS
596  *  Success: TRUE
597  *  Failure: FALSE
598  */
599 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
600 {
601         PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
602 
603         TRACE("(0x%lx, %p, %08x)\n", hProv, pdwReserved, dwFlags);
604 
605         if (!pProv)
606         {
607                 SetLastError(NTE_BAD_UID);
608                 return FALSE;
609         }
610 
611         if (pProv->dwMagic != MAGIC_CRYPTPROV)
612         {
613                 SetLastError(ERROR_INVALID_PARAMETER);
614                 return FALSE;
615         }
616 
617         pProv->refcount++;
618         return TRUE;
619 }
620 
621 /******************************************************************************
622  * CryptReleaseContext (ADVAPI32.@)
623  *
624  * Releases the handle of a CSP.  Reference count is decreased.
625  *
626  * PARAMS
627  *  hProv   [I] Handle of a CSP.
628  *  dwFlags [I] Reserved for future use and must be NULL.
629  *
630  * RETURNS
631  *  Success: TRUE
632  *  Failure: FALSE
633  */
634 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, ULONG_PTR dwFlags)
635 {
636         PCRYPTPROV pProv = (PCRYPTPROV)hProv;
637         BOOL ret = TRUE;
638 
639         TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
640 
641         if (!pProv)
642         {
643                 SetLastError(NTE_BAD_UID);
644                 return FALSE;
645         }
646 
647         if (pProv->dwMagic != MAGIC_CRYPTPROV)
648         {
649                 SetLastError(ERROR_INVALID_PARAMETER);
650                 return FALSE;
651         }
652 
653         pProv->refcount--;
654         if (pProv->refcount <= 0) 
655         {
656                 ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
657                 pProv->dwMagic = 0;
658                 FreeLibrary(pProv->hModule);
659 #if 0
660                 CRYPT_Free(pProv->pVTable->pContextInfo);
661 #endif
662                 CRYPT_Free(pProv->pVTable->pszProvName);
663                 CRYPT_Free(pProv->pVTable);
664                 CRYPT_Free(pProv->pFuncs);
665                 CRYPT_Free(pProv);
666         }
667         return ret;
668 }
669 
670 /******************************************************************************
671  * CryptGenRandom (ADVAPI32.@)
672  *
673  * Fills a buffer with cryptographically random bytes.
674  *
675  * PARAMS
676  *  hProv    [I] Handle of a CSP.
677  *  dwLen    [I] Number of bytes to generate.
678  *  pbBuffer [I/O] Buffer to contain random bytes.
679  *
680  * RETURNS
681  *  Success: TRUE
682  *  Failure: FALSE
683  *
684  * NOTES
685  *  pdBuffer must be at least dwLen bytes long.
686  */
687 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
688 {
689         PCRYPTPROV prov = (PCRYPTPROV)hProv;
690 
691         TRACE("(0x%lx, %d, %p)\n", hProv, dwLen, pbBuffer);
692 
693         if (!hProv)
694         {
695                 SetLastError(ERROR_INVALID_HANDLE);
696                 return FALSE;
697         }
698 
699         if (prov->dwMagic != MAGIC_CRYPTPROV)
700         {
701                 SetLastError(ERROR_INVALID_PARAMETER);
702                 return FALSE;
703         }
704 
705         return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
706 }
707 
708 /******************************************************************************
709  * CryptCreateHash (ADVAPI32.@)
710  *
711  * Initiates the hashing of a stream of data.
712  *
713  * PARAMS
714  *  hProv   [I] Handle of a CSP.
715  *  Algid   [I] Identifies the hash algorithm to use.
716  *  hKey    [I] Key for the hash (if required).
717  *  dwFlags [I] Reserved for future use and must be NULL.
718  *  phHash  [O] Address of the future handle to the new hash object.
719  *
720  * RETURNS
721  *  Success: TRUE
722  *  Failure: FALSE
723  *
724  * NOTES
725  *  If the algorithm is a keyed hash, hKey is the key.
726  */
727 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
728                 DWORD dwFlags, HCRYPTHASH *phHash)
729 {
730         PCRYPTPROV prov = (PCRYPTPROV)hProv;
731         PCRYPTKEY key = (PCRYPTKEY)hKey;
732         PCRYPTHASH hash;
733 
734         TRACE("(0x%lx, 0x%x, 0x%lx, %08x, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
735 
736         if (!prov)
737         {
738                 SetLastError(ERROR_INVALID_HANDLE);
739                 return FALSE;
740         }
741         if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
742         {
743                 SetLastError(ERROR_INVALID_PARAMETER);
744                 return FALSE;
745         }
746         if (dwFlags)
747         {
748                 SetLastError(NTE_BAD_FLAGS);
749                 return FALSE;
750         }
751         if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
752         {
753                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
754                 return FALSE;
755         }
756 
757         hash->pProvider = prov;
758 
759         if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
760                         key ? key->hPrivate : 0, 0, &hash->hPrivate))
761         {
762             *phHash = (HCRYPTHASH)hash;
763             return TRUE;
764         }
765 
766         /* CSP error! */
767         CRYPT_Free(hash);
768         *phHash = 0;
769         return FALSE;
770 }
771 
772 /******************************************************************************
773  * CryptDecrypt (ADVAPI32.@)
774  *
775  * Decrypts data encrypted by CryptEncrypt.
776  *
777  * PARAMS
778  *  hKey       [I] Handle to the decryption key.
779  *  hHash      [I] Handle to a hash object.
780  *  Final      [I] TRUE if this is the last section to be decrypted.
781  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
782  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
783  *                   data on return
784  *  pdwDataLen [I/O] Length of pbData before and after the call.
785  *
786  *  RETURNS
787  *   Success: TRUE
788  *   Failure: FALSE
789  */
790 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
791                 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
792 {
793         PCRYPTPROV prov;
794         PCRYPTKEY key = (PCRYPTKEY)hKey;
795         PCRYPTHASH hash = (PCRYPTHASH)hHash;
796 
797         TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
798 
799         if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
800         {
801                 SetLastError(ERROR_INVALID_PARAMETER);
802                 return FALSE;
803         }
804 
805         prov = key->pProvider;
806         return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
807                         Final, dwFlags, pbData, pdwDataLen);
808 }
809 
810 /******************************************************************************
811  * CryptDeriveKey (ADVAPI32.@)
812  *
813  * Generates session keys derived from a base data value.
814  *
815  * PARAMS
816  *  hProv     [I] Handle to a CSP.
817  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
818  *  hBaseData [I] Handle to a hash object.
819  *  dwFlags   [I] Type of key to generate.
820  *  phKey     [I/O] Address of the newly generated key.
821  *
822  * RETURNS
823  *  Success: TRUE
824  *  Failure: FALSE
825  */
826 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
827                 DWORD dwFlags, HCRYPTKEY *phKey)
828 {
829         PCRYPTPROV prov = (PCRYPTPROV)hProv;
830         PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
831         PCRYPTKEY key;
832 
833         TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08x, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
834 
835         if (!prov || !hash)
836         {
837                 SetLastError(ERROR_INVALID_HANDLE);
838                 return FALSE;
839         }
840         if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
841         {
842                 SetLastError(ERROR_INVALID_PARAMETER);
843                 return FALSE;
844         }
845         if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
846         {
847                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
848                 return FALSE;
849         }
850 
851         key->pProvider = prov;
852         if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
853         {
854             *phKey = (HCRYPTKEY)key;
855             return TRUE;
856         }
857 
858         /* CSP error! */
859         CRYPT_Free(key);
860         *phKey = 0;
861         return FALSE;
862 }
863 
864 /******************************************************************************
865  * CryptDestroyHash (ADVAPI32.@)
866  *
867  * Destroys the hash object referenced by hHash.
868  *
869  * PARAMS
870  *  hHash [I] Handle of the hash object to be destroyed.
871  *
872  * RETURNS
873  *  Success: TRUE
874  *  Failure: FALSE
875  */
876 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
877 {
878         PCRYPTHASH hash = (PCRYPTHASH)hHash;
879         PCRYPTPROV prov;
880         BOOL ret;
881 
882         TRACE("(0x%lx)\n", hHash);
883 
884         if (!hash)
885         {
886                 SetLastError(ERROR_INVALID_HANDLE);
887                 return FALSE;
888         }
889 
890         if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
891         {
892                 SetLastError(ERROR_INVALID_PARAMETER);
893                 return FALSE;
894         }
895 
896         prov = hash->pProvider;
897         ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
898         CRYPT_Free(hash);
899         return ret;
900 }
901 
902 /******************************************************************************
903  * CryptDestroyKey (ADVAPI32.@)
904  *
905  * Releases the handle referenced by hKey.
906  *
907  * PARAMS
908  *  hKey [I] Handle of the key to be destroyed.
909  *
910  * RETURNS
911  *  Success: TRUE
912  *  Failure: FALSE
913  */
914 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
915 {
916         PCRYPTKEY key = (PCRYPTKEY)hKey;
917         PCRYPTPROV prov;
918         BOOL ret;
919 
920         TRACE("(0x%lx)\n", hKey);
921 
922         if (!key)
923         {
924                 SetLastError(ERROR_INVALID_HANDLE);
925                 return FALSE;
926         }
927 
928         if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
929         {
930                 SetLastError(ERROR_INVALID_PARAMETER);
931                 return FALSE;
932         }
933 
934         prov = key->pProvider;
935         ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
936         CRYPT_Free(key);
937         return ret;
938 }
939