ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

crypt.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1999 Ian Schmidt
00003  * Copyright 2001 Travis Michielsen
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  */
00019 
00020 /***********************************************************************
00021  *
00022  *  TODO:
00023  *  - Reference counting
00024  *  - Thread-safing
00025   */
00026 
00027 #include <advapi32.h>
00028 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
00029 
00030 
00031 /*
00032  * Note: this code is harmless on little-endian machines.
00033  */
00034 VOID byteReverse(unsigned char *buf, unsigned longs)
00035 {
00036     unsigned int t;
00037 
00038     do
00039     {
00040         t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 |
00041             ((unsigned)buf[1] << 8 | buf[0]);
00042         *(unsigned int *)buf = t;
00043         buf += 4;
00044     } while (--longs);
00045 }
00046 
00047 static HWND crypt_hWindow ;
00048 
00049 #define CRYPT_Alloc(size) (LocalAlloc(LMEM_ZEROINIT, size))
00050 #define CRYPT_Free(buffer) (LocalFree(buffer))
00051 
00052 static inline PWSTR CRYPT_GetProvKeyName(PCWSTR pProvName)
00053 {
00054     static const WCHAR KEYSTR[] = {
00055                 'S','o','f','t','w','a','r','e','\\',
00056                 'M','i','c','r','o','s','o','f','t','\\',
00057                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
00058                 'D','e','f','a','u','l','t','s','\\',
00059                 'P','r','o','v','i','d','e','r','\\',0
00060     };
00061     PWSTR keyname;
00062 
00063     keyname = CRYPT_Alloc((strlenW(KEYSTR) + strlenW(pProvName) +1)*sizeof(WCHAR));
00064     if (keyname)
00065     {
00066         strcpyW(keyname, KEYSTR);
00067         strcpyW(keyname + strlenW(KEYSTR), pProvName);
00068     } else
00069         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00070     return keyname;
00071 }
00072 
00073 static inline PWSTR CRYPT_GetTypeKeyName(DWORD dwType, BOOL user)
00074 {
00075     static const WCHAR MACHINESTR[] = {
00076                 'S','o','f','t','w','a','r','e','\\',
00077                 'M','i','c','r','o','s','o','f','t','\\',
00078                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
00079                 'D','e','f','a','u','l','t','s','\\',
00080                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s','\\',
00081                 'T','y','p','e',' ','X','X','X',0
00082     };
00083     static const WCHAR USERSTR[] = {
00084                 'S','o','f','t','w','a','r','e','\\',
00085                 'M','i','c','r','o','s','o','f','t','\\',
00086                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
00087                 'P','r','o','v','i','d','e','r',' ','T','y','p','e',' ','X','X','X',0
00088     };
00089     PWSTR keyname;
00090     PWSTR ptr;
00091 
00092     keyname = CRYPT_Alloc( ((user ? strlenW(USERSTR) : strlenW(MACHINESTR)) +1)*sizeof(WCHAR));
00093     if (keyname)
00094     {
00095         user ? strcpyW(keyname, USERSTR) : strcpyW(keyname, MACHINESTR);
00096         ptr = keyname + strlenW(keyname);
00097         *(--ptr) = (dwType % 10) + '0';
00098         *(--ptr) = ((dwType / 10) % 10) + '0';
00099         *(--ptr) = (dwType / 100) + '0';
00100     } else
00101         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00102     return keyname;
00103 }
00104 
00105 /* CRYPT_UnicodeTOANSI
00106  * wstr - unicode string
00107  * str - pointer to ANSI string
00108  * strsize - size of buffer pointed to by str or -1 if we have to do the allocation
00109  *
00110  * returns TRUE if unsuccessful, FALSE otherwise.
00111  * if wstr is NULL, returns TRUE and sets str to NULL! Value of str should be checked after call
00112  */
00113 static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize)
00114 {
00115     int count;
00116 
00117     if (!wstr)
00118     {
00119         *str = NULL;
00120         return TRUE;
00121     }
00122     count = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
00123     if (strsize == -1)
00124         *str = CRYPT_Alloc(count * sizeof(CHAR));
00125     else
00126         count = min( count, strsize );
00127     if (*str)
00128     {
00129         WideCharToMultiByte(CP_ACP, 0, wstr, -1, *str, count, NULL, NULL);
00130         return TRUE;
00131     }
00132     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00133     return FALSE;
00134 }
00135 
00136 /* CRYPT_ANSITOUnicode
00137  * str - ANSI string
00138  * wstr - pointer to unicode string
00139  * wstrsize - size of buffer pointed to by wstr or -1 if we have to do the allocation
00140  */
00141 static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize)
00142 {
00143     unsigned int wcount;
00144 
00145     if (!str)
00146     {
00147         *wstr = NULL;
00148         return TRUE;
00149     }
00150     wcount = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
00151     if (wstrsize == -1)
00152         *wstr = CRYPT_Alloc(wcount * sizeof(WCHAR));
00153     else
00154         wcount = min( wcount, wstrsize/sizeof(WCHAR) );
00155     if (*wstr)
00156     {
00157         MultiByteToWideChar(CP_ACP, 0, str, -1, *wstr, wcount);
00158         return TRUE;
00159     }
00160     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00161     return FALSE;
00162 }
00163 
00164 /* These next 2 functions are used by the VTableProvStruc structure */
00165 static BOOL CALLBACK CRYPT_VerifyImage(LPCSTR lpszImage, BYTE* pData)
00166 {
00167     if (!lpszImage || !pData)
00168     {
00169         SetLastError(ERROR_INVALID_PARAMETER);
00170         return FALSE;
00171     }
00172 
00173     FIXME("(%s, %p): not verifying image\n", lpszImage, pData);
00174 
00175     return TRUE;
00176 }
00177 
00178 static BOOL CALLBACK CRYPT_ReturnhWnd(HWND *phWnd)
00179 {
00180     if (!phWnd)
00181         return FALSE;
00182     *phWnd = crypt_hWindow;
00183     return TRUE;
00184 }
00185 
00186 #define CRYPT_GetProvFunc(name) \
00187     if ( !(provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)) ) goto error
00188 #define CRYPT_GetProvFuncOpt(name) \
00189     provider->pFuncs->p##name = (void*)GetProcAddress(provider->hModule, #name)
00190 static PCRYPTPROV CRYPT_LoadProvider(PCWSTR pImage)
00191 {
00192     PCRYPTPROV provider;
00193     DWORD errorcode = ERROR_NOT_ENOUGH_MEMORY;
00194 
00195     if ( !(provider = CRYPT_Alloc(sizeof(CRYPTPROV))) ) goto error;
00196     if ( !(provider->pFuncs = CRYPT_Alloc(sizeof(PROVFUNCS))) ) goto error;
00197     if ( !(provider->pVTable = CRYPT_Alloc(sizeof(VTableProvStruc))) ) goto error;
00198     if ( !(provider->hModule = LoadLibraryW(pImage)) )
00199     {
00200         errorcode = (GetLastError() == ERROR_FILE_NOT_FOUND) ? NTE_PROV_DLL_NOT_FOUND : NTE_PROVIDER_DLL_FAIL;
00201         FIXME("Failed to load dll %s\n", debugstr_w(pImage));
00202         goto error;
00203     }
00204     provider->dwMagic = MAGIC_CRYPTPROV;
00205     provider->refcount = 1;
00206 
00207     errorcode = NTE_PROVIDER_DLL_FAIL;
00208     CRYPT_GetProvFunc(CPAcquireContext);
00209     CRYPT_GetProvFunc(CPCreateHash);
00210     CRYPT_GetProvFunc(CPDecrypt);
00211     CRYPT_GetProvFunc(CPDeriveKey);
00212     CRYPT_GetProvFunc(CPDestroyHash);
00213     CRYPT_GetProvFunc(CPDestroyKey);
00214     CRYPT_GetProvFuncOpt(CPDuplicateHash);
00215     CRYPT_GetProvFuncOpt(CPDuplicateKey);
00216     CRYPT_GetProvFunc(CPEncrypt);
00217     CRYPT_GetProvFunc(CPExportKey);
00218     CRYPT_GetProvFunc(CPGenKey);
00219     CRYPT_GetProvFunc(CPGenRandom);
00220     CRYPT_GetProvFunc(CPGetHashParam);
00221     CRYPT_GetProvFunc(CPGetKeyParam);
00222     CRYPT_GetProvFunc(CPGetProvParam);
00223     CRYPT_GetProvFunc(CPGetUserKey);
00224     CRYPT_GetProvFunc(CPHashData);
00225     CRYPT_GetProvFunc(CPHashSessionKey);
00226     CRYPT_GetProvFunc(CPImportKey);
00227     CRYPT_GetProvFunc(CPReleaseContext);
00228     CRYPT_GetProvFunc(CPSetHashParam);
00229     CRYPT_GetProvFunc(CPSetKeyParam);
00230     CRYPT_GetProvFunc(CPSetProvParam);
00231     CRYPT_GetProvFunc(CPSignHash);
00232     CRYPT_GetProvFunc(CPVerifySignature);
00233 
00234     /* FIXME: Not sure what the pbContextInfo field is for.
00235      *        Does it need memory allocation?
00236      */
00237     provider->pVTable->Version = 3;
00238     provider->pVTable->FuncVerifyImage = CRYPT_VerifyImage;
00239     provider->pVTable->FuncReturnhWnd = CRYPT_ReturnhWnd;
00240     provider->pVTable->dwProvType = 0;
00241     provider->pVTable->pbContextInfo = NULL;
00242     provider->pVTable->cbContextInfo = 0;
00243     provider->pVTable->pszProvName = NULL;
00244     return provider;
00245 
00246 error:
00247     SetLastError(errorcode);
00248     if (provider)
00249     {
00250         provider->dwMagic = 0;
00251         if (provider->hModule)
00252             FreeLibrary(provider->hModule);
00253         CRYPT_Free(provider->pVTable);
00254         CRYPT_Free(provider->pFuncs);
00255         CRYPT_Free(provider);
00256     }
00257     return NULL;
00258 }
00259 #undef CRYPT_GetProvFunc
00260 #undef CRYPT_GetProvFuncOpt
00261 
00262 
00263 static void CRYPT_CreateMachineGuid(void)
00264 {
00265     static const WCHAR cryptographyW[] = {
00266                 'S','o','f','t','w','a','r','e','\\',
00267                 'M','i','c','r','o','s','o','f','t','\\',
00268                 'C','r','y','p','t','o','g','r','a','p','h','y',0 };
00269     static const WCHAR machineGuidW[] = {
00270         'M','a','c','h','i','n','e','G','u','i','d',0 };
00271     LONG r;
00272     HKEY key;
00273 
00274     r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, cryptographyW, 0, KEY_ALL_ACCESS,
00275               &key);
00276     if (!r)
00277     {
00278         DWORD size;
00279 
00280         r = RegQueryValueExW(key, machineGuidW, NULL, NULL, NULL, &size);
00281         if (r == ERROR_FILE_NOT_FOUND)
00282         {
00283                     UUID uuid;
00284                     WCHAR buf[37];
00285                     RPC_STATUS rs;
00286                     static const WCHAR uuidFmt[] = {
00287                         '%','0','8','x','-','%','0','4','x','-',
00288                         '%','0','4','x','-','%','0','2','x',
00289                         '%','0','2','x','-','%','0','2','x',
00290                         '%','0','2','x','%','0','2','x',
00291                         '%','0','2','x','%','0','2','x',
00292                         '%','0','2','x',0 };
00293 
00294                     rs = UuidCreate(&uuid);
00295                     if (rs == S_OK)
00296                     {
00297                         sprintfW(buf, uuidFmt,
00298                                  uuid.Data1, uuid.Data2, uuid.Data3,
00299                                  uuid.Data4[0], uuid.Data4[1],
00300                                  uuid.Data4[2], uuid.Data4[3],
00301                                  uuid.Data4[4], uuid.Data4[5],
00302                                  uuid.Data4[6], uuid.Data4[7] );
00303                         RegSetValueExW(key, machineGuidW, 0, REG_SZ,
00304                                        (const BYTE *)buf,
00305                                        (lstrlenW(buf)+1)*sizeof(WCHAR));
00306                     }
00307         }
00308         RegCloseKey(key);
00309     }
00310 }
00311 
00312 /******************************************************************************
00313  * CryptAcquireContextW (ADVAPI32.@)
00314  *
00315  * Acquire a crypto provider context handle.
00316  *
00317  * PARAMS
00318  *  phProv       [O] Pointer to HCRYPTPROV for the output.
00319  *  pszContainer [I] Key Container Name
00320  *  pszProvider  [I] Cryptographic Service Provider Name
00321  *  dwProvType   [I] Crypto provider type to get a handle.
00322  *  dwFlags      [I] flags for the operation
00323  *
00324  * RETURNS 
00325  *  TRUE on success, FALSE on failure.
00326  */
00327 BOOL WINAPI CryptAcquireContextW (HCRYPTPROV *phProv, LPCWSTR pszContainer,
00328         LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
00329 {
00330     PCRYPTPROV pProv = NULL;
00331     HKEY key;
00332     PWSTR imagepath = NULL, keyname = NULL, provname = NULL, temp = NULL;
00333     PSTR provnameA = NULL, pszContainerA = NULL;
00334     DWORD keytype, type, len;
00335     ULONG r;
00336     static const WCHAR nameW[] = {'N','a','m','e',0};
00337     static const WCHAR typeW[] = {'T','y','p','e',0};
00338     static const WCHAR imagepathW[] = {'I','m','a','g','e',' ','P','a','t','h',0};
00339 
00340     TRACE("(%p, %s, %s, %d, %08x)\n", phProv, debugstr_w(pszContainer),
00341         debugstr_w(pszProvider), dwProvType, dwFlags);
00342 
00343     if (dwProvType < 1 || dwProvType > MAXPROVTYPES)
00344     {
00345         SetLastError(NTE_BAD_PROV_TYPE);
00346         return FALSE;
00347     }
00348     
00349     if (!phProv)
00350     {
00351         SetLastError(ERROR_INVALID_PARAMETER);
00352         return FALSE;
00353     }
00354 
00355     /* Make sure the MachineGuid value exists */
00356     CRYPT_CreateMachineGuid();
00357 
00358     if (!pszProvider || !*pszProvider)
00359     {
00360         /* No CSP name specified so try the user default CSP first
00361          * then try the machine default CSP
00362          */
00363         if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, TRUE)) ) {
00364             TRACE("No provider registered for crypto provider type %d.\n", dwProvType);
00365             SetLastError(NTE_PROV_TYPE_NOT_DEF);
00366             return FALSE;
00367         }
00368         if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &key))
00369         {
00370             CRYPT_Free(keyname);
00371             if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, FALSE)) ) {
00372                 TRACE("No type registered for crypto provider type %d.\n", dwProvType);
00373                 RegCloseKey(key);
00374                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
00375                 goto error;
00376             }
00377             if (RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key)) {
00378                 TRACE("Did not find registry entry of crypto provider for %s.\n", debugstr_w(keyname));
00379                 CRYPT_Free(keyname);
00380                 RegCloseKey(key);
00381                 SetLastError(NTE_PROV_TYPE_NOT_DEF);
00382                 goto error;
00383             }
00384         }
00385         CRYPT_Free(keyname);
00386         r = RegQueryValueExW(key, nameW, NULL, &keytype, NULL, &len);
00387         if( r != ERROR_SUCCESS || !len || keytype != REG_SZ)
00388         {
00389             TRACE("error %d reading size of 'Name' from registry\n", r );
00390             RegCloseKey(key);
00391             SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
00392             goto error;
00393         }
00394         if(!(provname = CRYPT_Alloc(len)))
00395         {
00396             RegCloseKey(key);
00397             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00398             goto error;
00399         }
00400         r = RegQueryValueExW(key, nameW, NULL, NULL, (LPBYTE)provname, &len);
00401         if( r != ERROR_SUCCESS )
00402         {
00403             TRACE("error %d reading 'Name' from registry\n", r );
00404             RegCloseKey(key);
00405             SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
00406             goto error;
00407         }
00408         RegCloseKey(key);
00409     } else {
00410         if ( !(provname = CRYPT_Alloc((strlenW(pszProvider) +1)*sizeof(WCHAR))) )
00411         {
00412             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00413             goto error;
00414         }
00415         strcpyW(provname, pszProvider);
00416     }
00417 
00418     keyname = CRYPT_GetProvKeyName(provname);
00419     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyname, &key);
00420     CRYPT_Free(keyname);
00421     if (r != ERROR_SUCCESS)
00422     {
00423         SetLastError(NTE_KEYSET_NOT_DEF);
00424         goto error;
00425     }
00426     len = sizeof(DWORD);
00427     r = RegQueryValueExW(key, typeW, NULL, NULL, (BYTE*)&type, &len);
00428     if (r != ERROR_SUCCESS)
00429     {
00430         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
00431         goto error;
00432     }
00433     if (type != dwProvType)
00434     {
00435         TRACE("Crypto provider has wrong type (%d vs expected %d).\n", type, dwProvType);
00436         SetLastError(NTE_PROV_TYPE_NO_MATCH);
00437         goto error;
00438     }
00439 
00440     r = RegQueryValueExW(key, imagepathW, NULL, &keytype, NULL, &len);
00441     if ( r != ERROR_SUCCESS || keytype != REG_SZ)
00442     {
00443         TRACE("error %d reading size of 'Image Path' from registry\n", r );
00444         RegCloseKey(key);
00445         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
00446         goto error;
00447     }
00448     if (!(temp = CRYPT_Alloc(len)))
00449     {
00450         RegCloseKey(key);
00451         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00452         goto error;
00453     }
00454     r = RegQueryValueExW(key, imagepathW, NULL, NULL, (LPBYTE)temp, &len);
00455     if( r != ERROR_SUCCESS )
00456     {
00457         TRACE("error %d reading 'Image Path' from registry\n", r );
00458         RegCloseKey(key);
00459         SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
00460         goto error;
00461     }
00462     RegCloseKey(key);
00463     len = ExpandEnvironmentStringsW(temp, NULL, 0);
00464     if ( !(imagepath = CRYPT_Alloc(len*sizeof(WCHAR))) )
00465     {
00466         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00467         goto error;
00468     }
00469     if (!ExpandEnvironmentStringsW(temp, imagepath, len))
00470     {
00471         /* ExpandEnvironmentStrings will call SetLastError */
00472         goto error;
00473     }
00474     pProv = CRYPT_LoadProvider(imagepath);
00475     if (!pProv) {
00476         /* CRYPT_LoadProvider calls SetLastError */
00477         goto error;
00478     }
00479     pProv->pVTable->dwProvType = dwProvType;
00480     if(!CRYPT_UnicodeToANSI(provname, &provnameA, -1))
00481     {
00482         /* CRYPT_UnicodeToANSI calls SetLastError */
00483         goto error;
00484     }
00485     pProv->pVTable->pszProvName = provnameA;
00486     if(!CRYPT_UnicodeToANSI(pszContainer, &pszContainerA, -1))
00487     {
00488         /* CRYPT_UnicodeToANSI calls SetLastError */
00489         goto error;
00490     }
00491     if (pProv->pFuncs->pCPAcquireContext(&pProv->hPrivate, pszContainerA, dwFlags, pProv->pVTable))
00492     {
00493         /* MSDN: When this flag is set, the value returned in phProv is undefined,
00494          *       and thus, the CryptReleaseContext function need not be called afterwards.
00495          *       Therefore, we must clean up everything now.
00496          */
00497         if (dwFlags & CRYPT_DELETEKEYSET)
00498         {
00499             pProv->dwMagic = 0;
00500             FreeLibrary(pProv->hModule);
00501             CRYPT_Free(provnameA);
00502             CRYPT_Free(pProv->pVTable);
00503             CRYPT_Free(pProv->pFuncs);
00504             CRYPT_Free(pProv);
00505         } else {
00506             *phProv = (HCRYPTPROV)pProv;
00507         }
00508         CRYPT_Free(pszContainerA);
00509         CRYPT_Free(provname);
00510         CRYPT_Free(temp);
00511         CRYPT_Free(imagepath);
00512         return TRUE;
00513     }
00514     /* FALLTHROUGH TO ERROR IF FALSE - CSP internal error! */
00515 error:
00516     if (pProv)
00517     {
00518         pProv->dwMagic = 0;
00519         if (pProv->hModule)
00520             FreeLibrary(pProv->hModule);
00521         CRYPT_Free(pProv->pVTable);
00522         CRYPT_Free(pProv->pFuncs);
00523         CRYPT_Free(pProv);
00524     }
00525     CRYPT_Free(pszContainerA);
00526     CRYPT_Free(provnameA);
00527     CRYPT_Free(provname);
00528     CRYPT_Free(temp);
00529     CRYPT_Free(imagepath);
00530     return FALSE;
00531 }
00532 
00533 /******************************************************************************
00534  * CryptAcquireContextA (ADVAPI32.@)
00535  *
00536  * See CryptAcquireContextW.
00537  */
00538 BOOL WINAPI CryptAcquireContextA (HCRYPTPROV *phProv, LPCSTR pszContainer,
00539         LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
00540 {
00541     PWSTR pProvider = NULL, pContainer = NULL;
00542     BOOL ret = FALSE;
00543 
00544     TRACE("(%p, %s, %s, %d, %08x)\n", phProv, pszContainer,
00545         pszProvider, dwProvType, dwFlags);
00546 
00547     if ( !CRYPT_ANSIToUnicode(pszContainer, &pContainer, -1) )
00548     {
00549         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00550         return FALSE;
00551     }
00552     if ( !CRYPT_ANSIToUnicode(pszProvider, &pProvider, -1) )
00553     {
00554         CRYPT_Free(pContainer);
00555         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00556         return FALSE;
00557     }
00558 
00559     ret = CryptAcquireContextW(phProv, pContainer, pProvider, dwProvType, dwFlags);
00560 
00561     CRYPT_Free(pContainer);
00562     CRYPT_Free(pProvider);
00563 
00564     return ret;
00565 }
00566 
00567 /******************************************************************************
00568  * CryptContextAddRef (ADVAPI32.@)
00569  *
00570  * Increases reference count of a cryptographic service provider handle
00571  * by one.
00572  *
00573  * PARAMS
00574  *  hProv       [I] Handle to the CSP whose reference is being incremented.
00575  *  pdwReserved [IN] Reserved for future use and must be NULL.
00576  *  dwFlags     [I] Reserved for future use and must be NULL.
00577  *
00578  * RETURNS
00579  *  Success: TRUE
00580  *  Failure: FALSE
00581  */
00582 BOOL WINAPI CryptContextAddRef (HCRYPTPROV hProv, DWORD *pdwReserved, DWORD dwFlags)
00583 {
00584     PCRYPTPROV pProv = (PCRYPTPROV)hProv;   
00585 
00586     TRACE("(0x%lx, %p, %08x)\n", hProv, pdwReserved, dwFlags);
00587 
00588     if (!pProv)
00589     {
00590         SetLastError(NTE_BAD_UID);
00591         return FALSE;
00592     }
00593 
00594     if (pProv->dwMagic != MAGIC_CRYPTPROV)
00595     {
00596         SetLastError(ERROR_INVALID_PARAMETER);
00597         return FALSE;
00598     }
00599 
00600     pProv->refcount++;
00601     return TRUE;
00602 }
00603 
00604 /******************************************************************************
00605  * CryptReleaseContext (ADVAPI32.@)
00606  *
00607  * Releases the handle of a CSP.  Reference count is decreased.
00608  *
00609  * PARAMS
00610  *  hProv   [I] Handle of a CSP.
00611  *  dwFlags [I] Reserved for future use and must be NULL.
00612  *
00613  * RETURNS
00614  *  Success: TRUE
00615  *  Failure: FALSE
00616  */
00617 BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags)
00618 {
00619     PCRYPTPROV pProv = (PCRYPTPROV)hProv;
00620     BOOL ret = TRUE;
00621 
00622     TRACE("(0x%lx, %08lx)\n", hProv, dwFlags);
00623 
00624     if (!pProv)
00625     {
00626         SetLastError(NTE_BAD_UID);
00627         return FALSE;
00628     }
00629 
00630     if (pProv->dwMagic != MAGIC_CRYPTPROV)
00631     {
00632         SetLastError(ERROR_INVALID_PARAMETER);
00633         return FALSE;
00634     }
00635 
00636     pProv->refcount--;
00637     if (pProv->refcount <= 0) 
00638     {
00639         ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
00640         pProv->dwMagic = 0;
00641         FreeLibrary(pProv->hModule);
00642 #if 0
00643         CRYPT_Free(pProv->pVTable->pContextInfo);
00644 #endif
00645         CRYPT_Free(pProv->pVTable->pszProvName);
00646         CRYPT_Free(pProv->pVTable);
00647         CRYPT_Free(pProv->pFuncs);
00648         CRYPT_Free(pProv);
00649     }
00650     return ret;
00651 }
00652 
00653 /******************************************************************************
00654  * CryptGenRandom (ADVAPI32.@)
00655  *
00656  * Fills a buffer with cryptographically random bytes.
00657  *
00658  * PARAMS
00659  *  hProv    [I] Handle of a CSP.
00660  *  dwLen    [I] Number of bytes to generate.
00661  *  pbBuffer [I/O] Buffer to contain random bytes.
00662  *
00663  * RETURNS
00664  *  Success: TRUE
00665  *  Failure: FALSE
00666  *
00667  * NOTES
00668  *  pdBuffer must be at least dwLen bytes long.
00669  */
00670 BOOL WINAPI CryptGenRandom (HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
00671 {
00672     PCRYPTPROV prov = (PCRYPTPROV)hProv;
00673 
00674     TRACE("(0x%lx, %d, %p)\n", hProv, dwLen, pbBuffer);
00675 
00676     if (!hProv)
00677     {
00678         SetLastError(ERROR_INVALID_HANDLE);
00679         return FALSE;
00680     }
00681 
00682     if (prov->dwMagic != MAGIC_CRYPTPROV)
00683     {
00684         SetLastError(ERROR_INVALID_PARAMETER);
00685         return FALSE;
00686     }
00687 
00688     return prov->pFuncs->pCPGenRandom(prov->hPrivate, dwLen, pbBuffer);
00689 }
00690 
00691 /******************************************************************************
00692  * CryptCreateHash (ADVAPI32.@)
00693  *
00694  * Initiates the hashing of a stream of data.
00695  *
00696  * PARAMS
00697  *  hProv   [I] Handle of a CSP.
00698  *  Algid   [I] Identifies the hash algorithm to use.
00699  *  hKey    [I] Key for the hash (if required).
00700  *  dwFlags [I] Reserved for future use and must be NULL.
00701  *  phHash  [O] Address of the future handle to the new hash object.
00702  *
00703  * RETURNS
00704  *  Success: TRUE
00705  *  Failure: FALSE
00706  *
00707  * NOTES
00708  *  If the algorithm is a keyed hash, hKey is the key.
00709  */
00710 BOOL WINAPI CryptCreateHash (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
00711         DWORD dwFlags, HCRYPTHASH *phHash)
00712 {
00713     PCRYPTPROV prov = (PCRYPTPROV)hProv;
00714     PCRYPTKEY key = (PCRYPTKEY)hKey;
00715     PCRYPTHASH hash;
00716 
00717     TRACE("(0x%lx, 0x%x, 0x%lx, %08x, %p)\n", hProv, Algid, hKey, dwFlags, phHash);
00718 
00719     if (!prov)
00720     {
00721         SetLastError(ERROR_INVALID_HANDLE);
00722         return FALSE;
00723     }
00724     if (!phHash || prov->dwMagic != MAGIC_CRYPTPROV)
00725     {
00726         SetLastError(ERROR_INVALID_PARAMETER);
00727         return FALSE;
00728     }
00729     if (dwFlags)
00730     {
00731         SetLastError(NTE_BAD_FLAGS);
00732         return FALSE;
00733     }
00734     if ( !(hash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
00735     {
00736         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00737         return FALSE;
00738     }
00739 
00740     hash->pProvider = prov;
00741 
00742     if (prov->pFuncs->pCPCreateHash(prov->hPrivate, Algid,
00743             key ? key->hPrivate : 0, 0, &hash->hPrivate))
00744         {
00745             *phHash = (HCRYPTHASH)hash;
00746             return TRUE;
00747         }
00748 
00749     /* CSP error! */
00750     CRYPT_Free(hash);
00751     *phHash = 0;
00752     return FALSE;
00753 }
00754 
00755 /******************************************************************************
00756  * CryptDecrypt (ADVAPI32.@)
00757  *
00758  * Decrypts data encrypted by CryptEncrypt.
00759  *
00760  * PARAMS
00761  *  hKey       [I] Handle to the decryption key.
00762  *  hHash      [I] Handle to a hash object.
00763  *  Final      [I] TRUE if this is the last section to be decrypted.
00764  *  dwFlags    [I] Reserved for future use. Can be CRYPT_OAEP.
00765  *  pbData     [I/O] Buffer that holds the encrypted data. Holds decrypted
00766  *                   data on return
00767  *  pdwDataLen [I/O] Length of pbData before and after the call.
00768  *
00769  *  RETURNS
00770  *   Success: TRUE
00771  *   Failure: FALSE
00772  */
00773 BOOL WINAPI CryptDecrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
00774         DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
00775 {
00776     PCRYPTPROV prov;
00777     PCRYPTKEY key = (PCRYPTKEY)hKey;
00778     PCRYPTHASH hash = (PCRYPTHASH)hHash;
00779 
00780     TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
00781 
00782     if (!key || !pbData || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
00783     {
00784         SetLastError(ERROR_INVALID_PARAMETER);
00785         return FALSE;
00786     }
00787 
00788     prov = key->pProvider;
00789     return prov->pFuncs->pCPDecrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
00790             Final, dwFlags, pbData, pdwDataLen);
00791 }
00792 
00793 /******************************************************************************
00794  * CryptDeriveKey (ADVAPI32.@)
00795  *
00796  * Generates session keys derived from a base data value.
00797  *
00798  * PARAMS
00799  *  hProv     [I] Handle to a CSP.
00800  *  Algid     [I] Identifies the symmetric encryption algorithm to use.
00801  *  hBaseData [I] Handle to a hash object.
00802  *  dwFlags   [I] Type of key to generate.
00803  *  phKey     [I/O] Address of the newly generated key.
00804  *
00805  * RETURNS
00806  *  Success: TRUE
00807  *  Failure: FALSE
00808  */
00809 BOOL WINAPI CryptDeriveKey (HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
00810         DWORD dwFlags, HCRYPTKEY *phKey)
00811 {
00812     PCRYPTPROV prov = (PCRYPTPROV)hProv;
00813     PCRYPTHASH hash = (PCRYPTHASH)hBaseData;
00814     PCRYPTKEY key;
00815 
00816     TRACE("(0x%lx, 0x%08x, 0x%lx, 0x%08x, %p)\n", hProv, Algid, hBaseData, dwFlags, phKey);
00817 
00818     if (!prov || !hash)
00819     {
00820         SetLastError(ERROR_INVALID_HANDLE);
00821         return FALSE;
00822     }
00823     if (!phKey || prov->dwMagic != MAGIC_CRYPTPROV)
00824     {
00825         SetLastError(ERROR_INVALID_PARAMETER);
00826         return FALSE;
00827     }
00828     if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
00829     {
00830         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00831         return FALSE;
00832     }
00833 
00834     key->pProvider = prov;
00835     if (prov->pFuncs->pCPDeriveKey(prov->hPrivate, Algid, hash->hPrivate, dwFlags, &key->hPrivate))
00836         {
00837             *phKey = (HCRYPTKEY)key;
00838             return TRUE;
00839         }
00840 
00841     /* CSP error! */
00842     CRYPT_Free(key);
00843     *phKey = 0;
00844     return FALSE;
00845 }
00846 
00847 /******************************************************************************
00848  * CryptDestroyHash (ADVAPI32.@)
00849  *
00850  * Destroys the hash object referenced by hHash.
00851  *
00852  * PARAMS
00853  *  hHash [I] Handle of the hash object to be destroyed.
00854  *
00855  * RETURNS
00856  *  Success: TRUE
00857  *  Failure: FALSE
00858  */
00859 BOOL WINAPI CryptDestroyHash (HCRYPTHASH hHash)
00860 {
00861     PCRYPTHASH hash = (PCRYPTHASH)hHash;
00862     PCRYPTPROV prov;
00863     BOOL ret;
00864 
00865     TRACE("(0x%lx)\n", hHash);
00866 
00867     if (!hash)
00868     {
00869         SetLastError(ERROR_INVALID_HANDLE);
00870         return FALSE;
00871     }
00872 
00873     if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
00874     {
00875         SetLastError(ERROR_INVALID_PARAMETER);
00876         return FALSE;
00877     }
00878 
00879     prov = hash->pProvider;
00880     ret = prov->pFuncs->pCPDestroyHash(prov->hPrivate, hash->hPrivate);
00881     CRYPT_Free(hash);
00882     return ret;
00883 }
00884 
00885 /******************************************************************************
00886  * CryptDestroyKey (ADVAPI32.@)
00887  *
00888  * Releases the handle referenced by hKey.
00889  *
00890  * PARAMS
00891  *  hKey [I] Handle of the key to be destroyed.
00892  *
00893  * RETURNS
00894  *  Success: TRUE
00895  *  Failure: FALSE
00896  */
00897 BOOL WINAPI CryptDestroyKey (HCRYPTKEY hKey)
00898 {
00899     PCRYPTKEY key = (PCRYPTKEY)hKey;
00900     PCRYPTPROV prov;
00901     BOOL ret;
00902 
00903     TRACE("(0x%lx)\n", hKey);
00904 
00905     if (!key)
00906     {
00907         SetLastError(ERROR_INVALID_HANDLE);
00908         return FALSE;
00909     }
00910 
00911     if (!key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
00912     {
00913         SetLastError(ERROR_INVALID_PARAMETER);
00914         return FALSE;
00915     }
00916 
00917     prov = key->pProvider;
00918     ret = prov->pFuncs->pCPDestroyKey(prov->hPrivate, key->hPrivate);
00919     CRYPT_Free(key);
00920     return ret;
00921 }
00922 
00923 /******************************************************************************
00924  * CryptDuplicateHash (ADVAPI32.@)
00925  *
00926  * Duplicates a hash.
00927  *
00928  * PARAMS
00929  *  hHash       [I] Handle to the hash to be copied.
00930  *  pdwReserved [I] Reserved for future use and must be zero.
00931  *  dwFlags     [I] Reserved for future use and must be zero.
00932  *  phHash      [O] Address of the handle to receive the copy.
00933  *
00934  * RETURNS
00935  *  Success: TRUE
00936  *  Failure: FALSE
00937  */
00938 BOOL WINAPI CryptDuplicateHash (HCRYPTHASH hHash, DWORD *pdwReserved,
00939         DWORD dwFlags, HCRYPTHASH *phHash)
00940 {
00941     PCRYPTPROV prov;
00942     PCRYPTHASH orghash, newhash;
00943 
00944     TRACE("(0x%lx, %p, %08x, %p)\n", hHash, pdwReserved, dwFlags, phHash);
00945 
00946     orghash = (PCRYPTHASH)hHash;
00947     if (!orghash || pdwReserved || !phHash || !orghash->pProvider || 
00948         orghash->pProvider->dwMagic != MAGIC_CRYPTPROV)
00949     {
00950         SetLastError(ERROR_INVALID_PARAMETER);
00951         return FALSE;
00952     }
00953 
00954     prov = orghash->pProvider;
00955     if (!prov->pFuncs->pCPDuplicateHash)
00956     {
00957         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00958         return FALSE;
00959     }
00960 
00961     if ( !(newhash = CRYPT_Alloc(sizeof(CRYPTHASH))) )
00962     {
00963         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00964         return FALSE;
00965     }
00966 
00967     newhash->pProvider = prov;
00968     if (prov->pFuncs->pCPDuplicateHash(prov->hPrivate, orghash->hPrivate, pdwReserved, dwFlags, &newhash->hPrivate))
00969     {
00970         *phHash = (HCRYPTHASH)newhash;
00971         return TRUE;
00972     }
00973     CRYPT_Free(newhash);
00974     return FALSE;
00975 }
00976 
00977 /******************************************************************************
00978  * CryptDuplicateKey (ADVAPI32.@)
00979  *
00980  * Duplicate a key and the key's state.
00981  *
00982  * PARAMS
00983  *  hKey        [I] Handle of the key to copy.
00984  *  pdwReserved [I] Reserved for future use and must be NULL.
00985  *  dwFlags     [I] Reserved for future use and must be zero.
00986  *  phKey       [I] Address of the handle to the duplicated key.
00987  *
00988  * RETURNS
00989  *  Success: TRUE
00990  *  Failure: FALSE
00991  */
00992 BOOL WINAPI CryptDuplicateKey (HCRYPTKEY hKey, DWORD *pdwReserved, DWORD dwFlags, HCRYPTKEY *phKey)
00993 {
00994     PCRYPTPROV prov;
00995     PCRYPTKEY orgkey, newkey;
00996 
00997     TRACE("(0x%lx, %p, %08x, %p)\n", hKey, pdwReserved, dwFlags, phKey);
00998 
00999     orgkey = (PCRYPTKEY)hKey;
01000     if (!orgkey || pdwReserved || !phKey || !orgkey->pProvider || 
01001         orgkey->pProvider->dwMagic != MAGIC_CRYPTPROV)
01002     {
01003         SetLastError(ERROR_INVALID_PARAMETER);
01004         return FALSE;
01005     }
01006 
01007     prov = orgkey->pProvider;
01008     if (!prov->pFuncs->pCPDuplicateKey)
01009     {
01010         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01011         return FALSE;
01012     }
01013 
01014     if ( !(newkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
01015     {
01016         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01017         return FALSE;
01018     }
01019 
01020     newkey->pProvider = prov;
01021     if (prov->pFuncs->pCPDuplicateKey(prov->hPrivate, orgkey->hPrivate, pdwReserved, dwFlags, &newkey->hPrivate))
01022     {
01023         *phKey = (HCRYPTKEY)newkey;
01024         return TRUE;
01025     }
01026     CRYPT_Free(newkey);
01027     return FALSE;
01028 }
01029 
01030 /******************************************************************************
01031  * CryptEncrypt (ADVAPI32.@)
01032  *
01033  * Encrypts data.
01034  *
01035  * PARAMS
01036  *  hKey       [I] Handle to the encryption key.
01037  *  hHash      [I] Handle to a hash object.
01038  *  Final      [I] TRUE if this is the last section to encrypt.
01039  *  dwFlags    [I] Can be CRYPT_OAEP.
01040  *  pbData     [I/O] Data to be encrypted. Contains encrypted data after call.
01041  *  pdwDataLen [I/O] Length of the data to encrypt. Contains the length of the
01042  *                   encrypted data after call.
01043  *  dwBufLen   [I] Length of the input pbData buffer.
01044  *
01045  * RETURNS
01046  *  Success: TRUE
01047  *  Failure: FALSE
01048  *
01049  *  NOTES
01050  *   If pbData is NULL, CryptEncrypt determines stores the number of bytes
01051  *   required for the returned data in pdwDataLen.
01052  */
01053 BOOL WINAPI CryptEncrypt (HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
01054         DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
01055 {
01056     PCRYPTPROV prov;
01057     PCRYPTKEY key = (PCRYPTKEY)hKey;
01058     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01059 
01060     TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p, %d)\n", hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
01061 
01062     if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
01063     {
01064         SetLastError(ERROR_INVALID_PARAMETER);
01065         return FALSE;
01066     }
01067 
01068     prov = key->pProvider;
01069     return prov->pFuncs->pCPEncrypt(prov->hPrivate, key->hPrivate, hash ? hash->hPrivate : 0,
01070             Final, dwFlags, pbData, pdwDataLen, dwBufLen);
01071 }
01072 
01073 /******************************************************************************
01074  * CryptEnumProvidersW (ADVAPI32.@)
01075  *
01076  * Returns the next available CSP.
01077  *
01078  * PARAMS
01079  *  dwIndex     [I] Index of the next provider to be enumerated.
01080  *  pdwReserved [I] Reserved for future use and must be NULL.
01081  *  dwFlags     [I] Reserved for future use and must be zero.
01082  *  pdwProvType [O] DWORD designating the type of the provider.
01083  *  pszProvName [O] Buffer that receives data from the provider.
01084  *  pcbProvName [I/O] Specifies the size of pszProvName. Contains the number
01085  *                    of bytes stored in the buffer on return.
01086  *
01087  *  RETURNS
01088  *   Success: TRUE
01089  *   Failure: FALSE
01090  *
01091  *  NOTES
01092  *   If pszProvName is NULL, CryptEnumProvidersW sets the size of the name
01093  *   for memory allocation purposes.
01094  */
01095 BOOL WINAPI CryptEnumProvidersW (DWORD dwIndex, DWORD *pdwReserved,
01096         DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszProvName, DWORD *pcbProvName)
01097 {
01098     HKEY hKey;
01099     static const WCHAR providerW[] = {
01100                 'S','o','f','t','w','a','r','e','\\',
01101                 'M','i','c','r','o','s','o','f','t','\\',
01102                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
01103                 'D','e','f','a','u','l','t','s','\\',
01104                 'P','r','o','v','i','d','e','r',0
01105         };
01106     static const WCHAR typeW[] = {'T','y','p','e',0};
01107     BOOL ret;
01108 
01109     TRACE("(%d, %p, %d, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
01110             pdwProvType, pszProvName, pcbProvName);
01111 
01112     if (pdwReserved || !pcbProvName)
01113     {
01114         SetLastError(ERROR_INVALID_PARAMETER);
01115         return FALSE;
01116     }
01117     if (dwFlags)
01118     {
01119         SetLastError(NTE_BAD_FLAGS);
01120         return FALSE;
01121     }
01122 
01123     if (RegOpenKeyW(HKEY_LOCAL_MACHINE, providerW, &hKey))
01124     {
01125         SetLastError(NTE_FAIL);
01126         return FALSE;
01127     }
01128 
01129     ret = TRUE;
01130     if (!pszProvName)
01131     {
01132         DWORD numkeys;
01133         WCHAR *provNameW;
01134         
01135         RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, pcbProvName,
01136                  NULL, NULL, NULL, NULL, NULL, NULL);
01137         
01138         if (!(provNameW = CRYPT_Alloc(*pcbProvName * sizeof(WCHAR))))
01139         {
01140             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01141             RegCloseKey(hKey);
01142             return FALSE;
01143         }
01144 
01145         RegEnumKeyExW(hKey, dwIndex, provNameW, pcbProvName, NULL, NULL, NULL, NULL);
01146         CRYPT_Free(provNameW);
01147         (*pcbProvName)++;
01148         *pcbProvName *= sizeof(WCHAR);
01149 
01150         if (dwIndex >= numkeys)
01151         {
01152             SetLastError(ERROR_NO_MORE_ITEMS);
01153             ret = FALSE;
01154         }
01155     } else {
01156         DWORD size = sizeof(DWORD);
01157         DWORD result;
01158         HKEY subkey;
01159         
01160         result = RegEnumKeyW(hKey, dwIndex, pszProvName, *pcbProvName / sizeof(WCHAR));
01161         if (result)
01162         {
01163             SetLastError(result);
01164             RegCloseKey(hKey);
01165             return FALSE;
01166         }
01167         if (RegOpenKeyW(hKey, pszProvName, &subkey))
01168         {
01169             RegCloseKey(hKey);
01170             return FALSE;
01171         }
01172 
01173         if (RegQueryValueExW(subkey, typeW, NULL, NULL, (BYTE*)pdwProvType, &size))
01174             ret = FALSE;
01175 
01176         RegCloseKey(subkey);
01177     }
01178     RegCloseKey(hKey);
01179     return ret;
01180 }
01181 
01182 /******************************************************************************
01183  * CryptEnumProvidersA (ADVAPI32.@)
01184  *
01185  * See CryptEnumProvidersW.
01186  */
01187 BOOL WINAPI CryptEnumProvidersA (DWORD dwIndex, DWORD *pdwReserved,
01188         DWORD dwFlags, DWORD *pdwProvType, LPSTR pszProvName, DWORD *pcbProvName)
01189 {
01190     PWSTR str = NULL;
01191     DWORD bufsize;
01192     BOOL ret; /* = FALSE; */
01193 
01194     TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
01195             pdwProvType, pszProvName, pcbProvName);
01196 
01197     if(!CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
01198         return FALSE;
01199     if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
01200     {
01201         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01202         return FALSE;
01203     }
01204     ret = CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
01205     if (str)
01206         CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
01207     *pcbProvName = bufsize / sizeof(WCHAR);  /* FIXME: not correct */
01208     if (str)
01209     {
01210         CRYPT_Free(str);
01211         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
01212         {
01213             SetLastError(ERROR_MORE_DATA);
01214             return FALSE;
01215         }
01216     }
01217     return ret;
01218 }
01219 
01220 /******************************************************************************
01221  * CryptEnumProviderTypesW (ADVAPI32.@)
01222  *
01223  * Retrieves the next type of CSP supported.
01224  *
01225  * PARAMS
01226  *  dwIndex     [I] Index of the next provider to be enumerated.
01227  *  pdwReserved [I] Reserved for future use and must be NULL.
01228  *  dwFlags     [I] Reserved for future use and must be zero.
01229  *  pdwProvType [O] DWORD designating the type of the provider.
01230  *  pszTypeName [O] Buffer that receives data from the provider type.
01231  *  pcbTypeName [I/O] Specifies the size of pszTypeName. Contains the number
01232  *                    of bytes stored in the buffer on return.
01233  *
01234  *  RETURNS
01235  *   Success: TRUE
01236  *   Failure: FALSE
01237  *
01238  *  NOTES
01239  *   If pszTypeName is NULL, CryptEnumProviderTypesW sets the size of the name
01240  *   for memory allocation purposes.
01241  */
01242 BOOL WINAPI CryptEnumProviderTypesW (DWORD dwIndex, DWORD *pdwReserved,
01243         DWORD dwFlags, DWORD *pdwProvType, LPWSTR pszTypeName, DWORD *pcbTypeName)
01244 {
01245     HKEY hKey, hSubkey;
01246     DWORD keylen, numkeys, dwType;
01247     PWSTR keyname, ch;
01248     DWORD result;
01249     static const WCHAR KEYSTR[] = {
01250                 'S','o','f','t','w','a','r','e','\\',
01251                 'M','i','c','r','o','s','o','f','t','\\',
01252                 'C','r','y','p','t','o','g','r','a','p','h','y','\\',
01253                 'D','e','f','a','u','l','t','s','\\',
01254                 'P','r','o','v','i','d','e','r',' ','T','y','p','e','s',0
01255     };
01256     static const WCHAR typenameW[] = {'T','y','p','e','N','a','m','e',0};
01257 
01258     TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved,
01259         dwFlags, pdwProvType, pszTypeName, pcbTypeName);
01260 
01261     if (pdwReserved || !pdwProvType || !pcbTypeName)
01262     {
01263         SetLastError(ERROR_INVALID_PARAMETER);
01264         return FALSE;
01265     }
01266     if (dwFlags)
01267     {
01268         SetLastError(NTE_BAD_FLAGS);
01269         return FALSE;
01270     }
01271 
01272     if (RegOpenKeyW(HKEY_LOCAL_MACHINE, KEYSTR, &hKey))
01273         return FALSE;
01274 
01275     RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numkeys, &keylen, NULL, NULL, NULL, NULL, NULL, NULL);
01276     if (dwIndex >= numkeys)
01277     {
01278         SetLastError(ERROR_NO_MORE_ITEMS);
01279         return FALSE;
01280     }
01281     keylen++;
01282     if ( !(keyname = CRYPT_Alloc(keylen*sizeof(WCHAR))) )
01283     {
01284         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01285         return FALSE;
01286     }
01287     if ( RegEnumKeyW(hKey, dwIndex, keyname, keylen) ) {
01288                 CRYPT_Free(keyname);
01289         return FALSE;
01290         }
01291     RegOpenKeyW(hKey, keyname, &hSubkey);
01292     ch = keyname + strlenW(keyname);
01293     /* Convert "Type 000" to 0, etc/ */
01294     *pdwProvType = *(--ch) - '0';
01295     *pdwProvType += (*(--ch) - '0') * 10;
01296     *pdwProvType += (*(--ch) - '0') * 100;
01297     CRYPT_Free(keyname);
01298     
01299     result = RegQueryValueExW(hSubkey, typenameW, NULL, &dwType, (LPBYTE)pszTypeName, pcbTypeName);
01300     if (result)
01301     {
01302         SetLastError(result);
01303         return FALSE;
01304     }
01305 
01306     RegCloseKey(hSubkey);
01307     RegCloseKey(hKey);
01308     return TRUE;
01309 }
01310 
01311 /******************************************************************************
01312  * CryptEnumProviderTypesA (ADVAPI32.@)
01313  *
01314  * See CryptEnumProviderTypesW.
01315  */
01316 BOOL WINAPI CryptEnumProviderTypesA (DWORD dwIndex, DWORD *pdwReserved,
01317         DWORD dwFlags, DWORD *pdwProvType, LPSTR pszTypeName, DWORD *pcbTypeName)
01318 {
01319     PWSTR str = NULL;
01320     DWORD bufsize;
01321     BOOL ret;
01322 
01323     TRACE("(%d, %p, %08x, %p, %p, %p)\n", dwIndex, pdwReserved, dwFlags,
01324             pdwProvType, pszTypeName, pcbTypeName);
01325 
01326     if(!CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, NULL, &bufsize))
01327         return FALSE;
01328     if ( pszTypeName && !(str = CRYPT_Alloc(bufsize)) )
01329     {
01330         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01331         return FALSE;
01332     }
01333     ret = CryptEnumProviderTypesW(dwIndex, pdwReserved, dwFlags, pdwProvType, str, &bufsize);
01334     if (str)
01335         CRYPT_UnicodeToANSI(str, &pszTypeName, *pcbTypeName);
01336     *pcbTypeName = bufsize / sizeof(WCHAR);
01337     if (str)
01338     {
01339         CRYPT_Free(str);
01340         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
01341         {
01342             SetLastError(ERROR_MORE_DATA);
01343             return FALSE;
01344         }
01345     }
01346     return ret;
01347 }
01348 
01349 /******************************************************************************
01350  * CryptExportKey (ADVAPI32.@)
01351  * 
01352  * Exports a cryptographic key from a CSP.
01353  *
01354  * PARAMS
01355  *  hKey       [I] Handle to the key to export.
01356  *  hExpKey    [I] Handle to a cryptographic key of the end user.
01357  *  dwBlobType [I] Type of BLOB to be exported.
01358  *  dwFlags    [I] CRYPT_DESTROYKEY/SSL2_FALLBACK/OAEP.
01359  *  pbData     [O] Buffer to receive BLOB data.
01360  *  pdwDataLen [I/O] Specifies the size of pbData.
01361  *
01362  * RETURNS
01363  *  Success: TRUE
01364  *  Failure: FALSE
01365  *
01366  * NOTES
01367  *  if pbData is NULL, CryptExportKey sets pdwDataLen as the size of the
01368  *  buffer needed to hold the BLOB.
01369  */
01370 BOOL WINAPI CryptExportKey (HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType,
01371         DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
01372 {
01373     PCRYPTPROV prov;
01374     PCRYPTKEY key = (PCRYPTKEY)hKey, expkey = (PCRYPTKEY)hExpKey;
01375 
01376     TRACE("(0x%lx, 0x%lx, %d, %08x, %p, %p)\n", hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
01377 
01378     if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
01379     {
01380         SetLastError(ERROR_INVALID_PARAMETER);
01381         return FALSE;
01382     }
01383 
01384     prov = key->pProvider;
01385     return prov->pFuncs->pCPExportKey(prov->hPrivate, key->hPrivate, expkey ? expkey->hPrivate : 0,
01386             dwBlobType, dwFlags, pbData, pdwDataLen);
01387 }
01388 
01389 /******************************************************************************
01390  * CryptGenKey (ADVAPI32.@)
01391  *
01392  * Generates a random cryptographic session key or a pub/priv key pair.
01393  *
01394  * PARAMS
01395  *  hProv   [I] Handle to a CSP.
01396  *  Algid   [I] Algorithm to use to make key.
01397  *  dwFlags [I] Specifies type of key to make.
01398  *  phKey   [I] Address of the handle to which the new key is copied.
01399  *
01400  *  RETURNS
01401  *   Success: TRUE
01402  *   Failure: FALSE
01403  */
01404 BOOL WINAPI CryptGenKey (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
01405 {
01406     PCRYPTPROV prov = (PCRYPTPROV)hProv;
01407     PCRYPTKEY key;
01408 
01409     TRACE("(0x%lx, %d, %08x, %p)\n", hProv, Algid, dwFlags, phKey);
01410 
01411     if (!prov)
01412     {
01413         SetLastError(ERROR_INVALID_HANDLE);
01414         return FALSE;
01415     }
01416     if (!phKey || !prov || prov->dwMagic != MAGIC_CRYPTPROV)
01417     {
01418         SetLastError(ERROR_INVALID_PARAMETER);
01419         return FALSE;
01420     }
01421     if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
01422     {
01423         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01424         return FALSE;
01425     }
01426 
01427     key->pProvider = prov;
01428 
01429     if (prov->pFuncs->pCPGenKey(prov->hPrivate, Algid, dwFlags, &key->hPrivate))
01430         {
01431             *phKey = (HCRYPTKEY)key;
01432             return TRUE;
01433         }
01434 
01435     /* CSP error! */
01436     CRYPT_Free(key);
01437     return FALSE;
01438 }
01439 
01440 /******************************************************************************
01441  * CryptGetDefaultProviderW (ADVAPI32.@)
01442  *
01443  * Finds the default CSP of a certain provider type.
01444  *
01445  * PARAMS
01446  *  dwProvType  [I] Provider type to look for.
01447  *  pdwReserved [I] Reserved for future use and must be NULL.
01448  *  dwFlags     [I] CRYPT_MACHINE_DEFAULT/USER_DEFAULT
01449  *  pszProvName [O] Name of the default CSP.
01450  *  pcbProvName [I/O] Size of pszProvName
01451  *
01452  * RETURNS
01453  *  Success: TRUE
01454  *  Failure: FALSE
01455  *
01456  * NOTES
01457  *  If pszProvName is NULL, pcbProvName will hold the size of the buffer for
01458  *  memory allocation purposes on return.
01459  */
01460 BOOL WINAPI CryptGetDefaultProviderW (DWORD dwProvType, DWORD *pdwReserved,
01461         DWORD dwFlags, LPWSTR pszProvName, DWORD *pcbProvName)
01462 {
01463     HKEY hKey;
01464     PWSTR keyname;
01465     DWORD result;
01466     static const WCHAR nameW[] = {'N','a','m','e',0};
01467 
01468     if (pdwReserved || !pcbProvName)
01469     {
01470         SetLastError(ERROR_INVALID_PARAMETER);
01471         return FALSE;
01472     }
01473     if (dwFlags & ~(CRYPT_USER_DEFAULT | CRYPT_MACHINE_DEFAULT))
01474     {
01475         SetLastError(NTE_BAD_FLAGS);
01476         return FALSE;
01477     }
01478     if (dwProvType > 999)
01479     {
01480         SetLastError(NTE_BAD_PROV_TYPE);
01481         return FALSE;
01482     }
01483     if ( !(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)) )
01484     {
01485         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01486         return FALSE;
01487     }
01488     if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ?  HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE ,keyname, &hKey))
01489     {
01490         CRYPT_Free(keyname);
01491         SetLastError(NTE_PROV_TYPE_NOT_DEF);
01492         return FALSE;
01493     }
01494     CRYPT_Free(keyname);
01495     
01496     result = RegQueryValueExW(hKey, nameW, NULL, NULL, (LPBYTE)pszProvName, pcbProvName); 
01497     if (result)
01498     {
01499         if (result != ERROR_MORE_DATA)
01500             SetLastError(NTE_PROV_TYPE_ENTRY_BAD);
01501         else
01502             SetLastError(result);
01503         
01504         return FALSE;
01505     }
01506     
01507     RegCloseKey(hKey);
01508     return TRUE;
01509 }
01510 
01511 /******************************************************************************
01512  * CryptGetDefaultProviderA (ADVAPI32.@)
01513  *
01514  * See CryptGetDefaultProviderW.
01515  */
01516 BOOL WINAPI CryptGetDefaultProviderA (DWORD dwProvType, DWORD *pdwReserved,
01517         DWORD dwFlags, LPSTR pszProvName, DWORD *pcbProvName)
01518 {
01519     PWSTR str = NULL;
01520     DWORD bufsize;
01521     BOOL ret = FALSE;
01522 
01523     TRACE("(%d, %p, %08x, %p, %p)\n", dwProvType, pdwReserved, dwFlags, pszProvName, pcbProvName);
01524 
01525     CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, NULL, &bufsize);
01526     if ( pszProvName && !(str = CRYPT_Alloc(bufsize)) )
01527     {
01528         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01529         return FALSE;
01530     }
01531     ret = CryptGetDefaultProviderW(dwProvType, pdwReserved, dwFlags, str, &bufsize);
01532     if (str)
01533         CRYPT_UnicodeToANSI(str, &pszProvName, *pcbProvName);
01534     *pcbProvName = bufsize / sizeof(WCHAR);
01535     if (str)
01536     {
01537         CRYPT_Free(str);
01538         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
01539         {
01540             SetLastError(ERROR_MORE_DATA);
01541             return FALSE;
01542         }
01543     }
01544     return ret;
01545 }
01546 
01547 /******************************************************************************
01548  * CryptGetHashParam (ADVAPI32.@)
01549  *
01550  * Retrieves data that controls the operations of a hash object.
01551  *
01552  * PARAMS
01553  *  hHash      [I] Handle of the hash object to question.
01554  *  dwParam    [I] Query type.
01555  *  pbData     [O] Buffer that receives the value data.
01556  *  pdwDataLen [I/O] Size of the pbData buffer.
01557  *  dwFlags    [I] Reserved for future use and must be zero.
01558  *
01559  * RETURNS
01560  *  Success: TRUE
01561  *  Failure: FALSE
01562  *
01563  * NOTES
01564  *  If pbData is NULL, pdwDataLen will contain the length required.
01565  */
01566 BOOL WINAPI CryptGetHashParam (HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
01567         DWORD *pdwDataLen, DWORD dwFlags)
01568 {
01569     PCRYPTPROV prov;
01570     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01571 
01572     TRACE("(0x%lx, %d, %p, %p, %08x)\n", hHash, dwParam, pbData, pdwDataLen, dwFlags);
01573 
01574     if (!hash || !pdwDataLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
01575     {
01576         SetLastError(ERROR_INVALID_PARAMETER);
01577         return FALSE;
01578     }
01579 
01580     prov = hash->pProvider;
01581     return prov->pFuncs->pCPGetHashParam(prov->hPrivate, hash->hPrivate, dwParam,
01582             pbData, pdwDataLen, dwFlags);
01583 }
01584 
01585 /******************************************************************************
01586  * CryptGetKeyParam (ADVAPI32.@)
01587  *
01588  * Retrieves data that controls the operations of a key.
01589  *
01590  * PARAMS
01591  *  hKey       [I] Handle to they key in question.
01592  *  dwParam    [I] Specifies query type.
01593  *  pbData     [O] Sequence of bytes to receive data.
01594  *  pdwDataLen [I/O] Size of pbData.
01595  *  dwFlags    [I] Reserved for future use and must be zero.
01596  *
01597  * RETURNS
01598  *  Success: TRUE
01599  *  Failure: FALSE
01600  *
01601  * NOTES
01602  *  If pbData is NULL, pdwDataLen is set to the needed length of the buffer.
01603  */
01604 BOOL WINAPI CryptGetKeyParam (HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
01605         DWORD *pdwDataLen, DWORD dwFlags)
01606 {
01607     PCRYPTPROV prov;
01608     PCRYPTKEY key = (PCRYPTKEY)hKey;
01609 
01610     TRACE("(0x%lx, %d, %p, %p, %08x)\n", hKey, dwParam, pbData, pdwDataLen, dwFlags);
01611 
01612     if (!key || !pdwDataLen || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
01613     {
01614         SetLastError(ERROR_INVALID_PARAMETER);
01615         return FALSE;
01616     }
01617 
01618     prov = key->pProvider;
01619     return prov->pFuncs->pCPGetKeyParam(prov->hPrivate, key->hPrivate, dwParam,
01620             pbData, pdwDataLen, dwFlags);
01621 }
01622 
01623 /******************************************************************************
01624  * CryptGetProvParam (ADVAPI32.@)
01625  *
01626  * Retrieves parameters that control the operations of a CSP.
01627  *
01628  * PARAMS
01629  *  hProv      [I] Handle of the CSP in question.
01630  *  dwParam    [I] Specifies query type.
01631  *  pbData     [O] Buffer to receive the data.
01632  *  pdwDataLen [I/O] Size of pbData.
01633  *  dwFlags    [I] see MSDN Docs.
01634  *
01635  * RETURNS
01636  *  Success: TRUE
01637  *  Failure: FALSE
01638  *
01639  * NOTES
01640  *  If pbData is NULL, pdwDataLen is set to the needed buffer length.
01641  */
01642 BOOL WINAPI CryptGetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
01643         DWORD *pdwDataLen, DWORD dwFlags)
01644 {
01645     PCRYPTPROV prov = (PCRYPTPROV)hProv;
01646 
01647     TRACE("(0x%lx, %d, %p, %p, %08x)\n", hProv, dwParam, pbData, pdwDataLen, dwFlags);
01648 
01649     if (!prov || prov->dwMagic != MAGIC_CRYPTPROV)
01650     {
01651         SetLastError(ERROR_INVALID_PARAMETER);
01652         return FALSE;
01653     }
01654 
01655     return prov->pFuncs->pCPGetProvParam(prov->hPrivate, dwParam, pbData, pdwDataLen, dwFlags);
01656 }
01657 
01658 /******************************************************************************
01659  * CryptGetUserKey (ADVAPI32.@)
01660  *
01661  * Gets a handle of one of a user's two public/private key pairs.
01662  *
01663  * PARAMS
01664  *  hProv     [I] Handle of a CSP.
01665  *  dwKeySpec [I] Private key to use.
01666  *  phUserKey [O] Pointer to the handle of the retrieved keys.
01667  *
01668  * RETURNS
01669  *  Success: TRUE
01670  *  Failure: FALSE
01671  */
01672 BOOL WINAPI CryptGetUserKey (HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
01673 {
01674     PCRYPTPROV prov = (PCRYPTPROV)hProv;
01675     PCRYPTKEY key;
01676 
01677     TRACE("(0x%lx, %d, %p)\n", hProv, dwKeySpec, phUserKey);
01678 
01679     if (!prov)
01680     {
01681         SetLastError(ERROR_INVALID_HANDLE);
01682         return FALSE;
01683     }
01684     if (!phUserKey || prov->dwMagic != MAGIC_CRYPTPROV)
01685     {
01686         SetLastError(ERROR_INVALID_PARAMETER);
01687         return FALSE;
01688     }
01689     if ( !(key = CRYPT_Alloc(sizeof(CRYPTKEY))) )
01690     {
01691         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01692         return FALSE;
01693     }
01694 
01695     key->pProvider = prov;
01696 
01697     if (prov->pFuncs->pCPGetUserKey(prov->hPrivate, dwKeySpec, &key->hPrivate))
01698         {
01699             *phUserKey = (HCRYPTKEY)key;
01700             return TRUE;
01701         }
01702 
01703     /* CSP Error */
01704     CRYPT_Free(key);
01705     *phUserKey = 0;
01706     return FALSE;
01707 }
01708 
01709 /******************************************************************************
01710  * CryptHashData (ADVAPI32.@)
01711  *
01712  * Adds data to a hash object.
01713  *
01714  * PARAMS
01715  *  hHash     [I] Handle of the hash object.
01716  *  pbData    [I] Buffer of data to be hashed.
01717  *  dwDataLen [I] Number of bytes to add.
01718  *  dwFlags   [I] Can be CRYPT_USERDATA
01719  *
01720  * RETURNS
01721  *  Success: TRUE
01722  *  Failure: FALSE
01723  */
01724 BOOL WINAPI CryptHashData (HCRYPTHASH hHash, const BYTE *pbData, DWORD dwDataLen, DWORD dwFlags)
01725 {
01726     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01727     PCRYPTPROV prov;
01728 
01729     TRACE("(0x%lx, %p, %d, %08x)\n", hHash, pbData, dwDataLen, dwFlags);
01730 
01731     if (!hash)
01732     {
01733         SetLastError(ERROR_INVALID_HANDLE);
01734         return FALSE;
01735     }
01736     if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
01737     {
01738         SetLastError(ERROR_INVALID_PARAMETER);
01739         return FALSE;
01740     }
01741 
01742     prov = hash->pProvider;
01743     return prov->pFuncs->pCPHashData(prov->hPrivate, hash->hPrivate, pbData, dwDataLen, dwFlags);
01744 }
01745 
01746 /******************************************************************************
01747  * CryptHashSessionKey (ADVAPI32.@)
01748  *
01749  * Compute the cryptographic hash of a session key object.
01750  *
01751  * PARAMS 
01752  *  hHash   [I] Handle to the hash object.
01753  *  hKey    [I] Handle to the key to be hashed.
01754  *  dwFlags [I] Can be CRYPT_LITTLE_ENDIAN.
01755  *
01756  * RETURNS
01757  *  Success: TRUE
01758  *  Failure: FALSE
01759  */
01760 BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
01761 {
01762     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01763     PCRYPTKEY key = (PCRYPTKEY)hKey;
01764     PCRYPTPROV prov;
01765 
01766     TRACE("(0x%lx, 0x%lx, %08x)\n", hHash, hKey, dwFlags);
01767 
01768     if (!hash || !key)
01769     {
01770         SetLastError(ERROR_INVALID_HANDLE);
01771         return FALSE;
01772     }
01773 
01774     if (!hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
01775     {
01776         SetLastError(ERROR_INVALID_PARAMETER);
01777         return FALSE;
01778     }
01779 
01780     prov = hash->pProvider;
01781     return prov->pFuncs->pCPHashSessionKey(prov->hPrivate, hash->hPrivate, key->hPrivate, dwFlags);
01782 }
01783 
01784 /******************************************************************************
01785  * CryptImportKey (ADVAPI32.@)
01786  *
01787  * Transfer a cryptographic key from a key BLOB into a cryptographic service provider (CSP).
01788  *
01789  * PARAMS
01790  *  hProv     [I] Handle of a CSP.
01791  *  pbData    [I] Contains the key to be imported.
01792  *  dwDataLen [I] Length of the key.
01793  *  hPubKey   [I] Cryptographic key that decrypts pdData
01794  *  dwFlags   [I] Used only with a public/private key pair.
01795  *  phKey     [O] Imported key.
01796  *
01797  * RETURNS
01798  *  Success: TRUE
01799  *  Failure: FALSE
01800  */
01801 BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
01802         HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
01803 {
01804     PCRYPTPROV prov = (PCRYPTPROV)hProv;
01805     PCRYPTKEY pubkey = (PCRYPTKEY)hPubKey, importkey;
01806 
01807     TRACE("(0x%lx, %p, %d, 0x%lx, %08x, %p)\n", hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
01808 
01809     if (!prov || !pbData || !dwDataLen || !phKey || prov->dwMagic != MAGIC_CRYPTPROV)
01810     {
01811         SetLastError(ERROR_INVALID_PARAMETER);
01812         return FALSE;
01813     }
01814 
01815     if ( !(importkey = CRYPT_Alloc(sizeof(CRYPTKEY))) )
01816     {
01817         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01818         return FALSE;
01819     }
01820 
01821     importkey->pProvider = prov;
01822     if (prov->pFuncs->pCPImportKey(prov->hPrivate, pbData, dwDataLen,
01823             pubkey ? pubkey->hPrivate : 0, dwFlags, &importkey->hPrivate))
01824     {
01825         *phKey = (HCRYPTKEY)importkey;
01826         return TRUE;
01827     }
01828 
01829     CRYPT_Free(importkey);
01830     return FALSE;
01831 }
01832 
01833 /******************************************************************************
01834  * CryptSignHashW (ADVAPI32.@)
01835  *
01836  * Signs data.
01837  *
01838  * PARAMS
01839  *  hHash        [I] Handle of the hash object to be signed.
01840  *  dwKeySpec    [I] Private key to use.
01841  *  sDescription [I] Should be NULL.
01842  *  dwFlags      [I] CRYPT_NOHASHOID/X931_FORMAT.
01843  *  pbSignature  [O] Buffer of the signature data.
01844  *  pdwSigLen    [I/O] Size of the pbSignature buffer.
01845  *
01846  * RETURNS
01847  *  Success: TRUE
01848  *  Failure: FALSE
01849  *
01850  * NOTES
01851  *  Because of security flaws sDescription should not be used and should thus be
01852  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
01853  *  Providers.
01854  */
01855 BOOL WINAPI CryptSignHashW (HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription,
01856         DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
01857 {
01858     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01859     PCRYPTPROV prov;
01860 
01861     TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
01862         hHash, dwKeySpec, debugstr_w(sDescription), dwFlags, pbSignature, pdwSigLen);
01863 
01864     if (!hash)
01865     {
01866         SetLastError(ERROR_INVALID_HANDLE);
01867         return FALSE;
01868     }
01869     if (!pdwSigLen || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
01870     {
01871         SetLastError(ERROR_INVALID_PARAMETER);
01872         return FALSE;
01873     }
01874 
01875     prov = hash->pProvider;
01876     return prov->pFuncs->pCPSignHash(prov->hPrivate, hash->hPrivate, dwKeySpec, sDescription,
01877         dwFlags, pbSignature, pdwSigLen);
01878 }
01879 
01880 /******************************************************************************
01881  * CryptSignHashA (ADVAPI32.@)
01882  *
01883  * See CryptSignHashW.
01884  */
01885 BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
01886         DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen)
01887 {
01888     LPWSTR wsDescription;
01889     BOOL result;
01890 
01891     TRACE("(0x%lx, %d, %s, %08x, %p, %p)\n", 
01892         hHash, dwKeySpec, debugstr_a(sDescription), dwFlags, pbSignature, pdwSigLen);
01893 
01894     CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
01895     result = CryptSignHashW(hHash, dwKeySpec, wsDescription, dwFlags, pbSignature, pdwSigLen);
01896     CRYPT_Free(wsDescription);
01897 
01898     return result;
01899 }
01900 
01901 /******************************************************************************
01902  * CryptSetHashParam (ADVAPI32.@)
01903  *
01904  * Customizes the operations of a hash object.
01905  *
01906  * PARAMS
01907  *  hHash   [I] Handle of the hash object to set parameters.
01908  *  dwParam [I] HP_HMAC_INFO/HASHVAL.
01909  *  pbData  [I] Value data buffer.
01910  *  dwFlags [I] Reserved for future use and must be zero.
01911  *
01912  * RETURNS
01913  *  Success: TRUE
01914  *  Failure: FALSE
01915  */
01916 BOOL WINAPI CryptSetHashParam (HCRYPTHASH hHash, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
01917 {
01918     PCRYPTPROV prov;
01919     PCRYPTHASH hash = (PCRYPTHASH)hHash;
01920 
01921     TRACE("(0x%lx, %d, %p, %08x)\n", hHash, dwParam, pbData, dwFlags);
01922 
01923     if (!hash || !pbData || !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV)
01924     {
01925         SetLastError(ERROR_INVALID_PARAMETER);
01926         return FALSE;
01927     }
01928 
01929     prov = hash->pProvider;
01930     return prov->pFuncs->pCPSetHashParam(prov->hPrivate, hash->hPrivate,
01931             dwParam, pbData, dwFlags);
01932 }
01933 
01934 /******************************************************************************
01935  * CryptSetKeyParam (ADVAPI32.@)
01936  *
01937  * Customizes a session key's operations.
01938  *
01939  * PARAMS
01940  *  hKey    [I] Handle to the key to set values.
01941  *  dwParam [I] See MSDN Doc.
01942  *  pbData  [I] Buffer of values to set.
01943  *  dwFlags [I] Only used when dwParam == KP_ALGID.
01944  *
01945  * RETURNS
01946  *  Success: TRUE
01947  *  Failure: FALSE
01948  */
01949 BOOL WINAPI CryptSetKeyParam (HCRYPTKEY hKey, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
01950 {
01951     PCRYPTPROV prov;
01952     PCRYPTKEY key = (PCRYPTKEY)hKey;
01953 
01954     TRACE("(0x%lx, %d, %p, %08x)\n", hKey, dwParam, pbData, dwFlags);
01955 
01956     if (!key || !pbData || !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
01957     {
01958         SetLastError(ERROR_INVALID_PARAMETER);
01959         return FALSE;
01960     }
01961 
01962     prov = key->pProvider;
01963     return prov->pFuncs->pCPSetKeyParam(prov->hPrivate, key->hPrivate,
01964             dwParam, pbData, dwFlags);
01965 }
01966 
01967 /******************************************************************************
01968  * CryptSetProviderA (ADVAPI32.@)
01969  *
01970  * Specifies the current user's default CSP.
01971  *
01972  * PARAMS
01973  *  pszProvName [I] Name of the new default CSP.
01974  *  dwProvType  [I] Provider type of the CSP.
01975  *
01976  * RETURNS
01977  *  Success: TRUE
01978  *  Failure: FALSE
01979  */
01980 BOOL WINAPI CryptSetProviderA (LPCSTR pszProvName, DWORD dwProvType)
01981 {
01982     TRACE("(%s, %d)\n", pszProvName, dwProvType);
01983     return CryptSetProviderExA(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
01984 }
01985 
01986 /******************************************************************************
01987  * CryptSetProviderW (ADVAPI32.@)
01988  *
01989  * See CryptSetProviderA.
01990  */
01991 BOOL WINAPI CryptSetProviderW (LPCWSTR pszProvName, DWORD dwProvType)
01992 {
01993     TRACE("(%s, %d)\n", debugstr_w(pszProvName), dwProvType);
01994     return CryptSetProviderExW(pszProvName, dwProvType, NULL, CRYPT_USER_DEFAULT);
01995 }
01996 
01997 /******************************************************************************
01998  * CryptSetProviderExW (ADVAPI32.@)
01999  *
02000  * Specifies the default CSP.
02001  *
02002  * PARAMS
02003  *  pszProvName [I] Name of the new default CSP.
02004  *  dwProvType  [I] Provider type of the CSP.
02005  *  pdwReserved [I] Reserved for future use and must be NULL.
02006  *  dwFlags     [I] See MSDN Doc.
02007  *
02008  * RETURNS
02009  *  Success: TRUE
02010  *  Failure: FALSE
02011  */
02012 BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
02013 {
02014     HKEY hProvKey, hTypeKey;
02015     PWSTR keyname;
02016     static const WCHAR nameW[] = {'N','a','m','e',0};
02017 
02018     TRACE("(%s, %d, %p, %08x)\n", debugstr_w(pszProvName), dwProvType, pdwReserved, dwFlags);
02019 
02020     if (!pszProvName || pdwReserved)
02021     {
02022         SetLastError(ERROR_INVALID_PARAMETER);
02023         return FALSE;
02024     }
02025     if (dwProvType > MAXPROVTYPES)
02026     {
02027         SetLastError(NTE_BAD_PROV_TYPE);
02028         return FALSE;
02029     }
02030     if (dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)
02031             || dwFlags == CRYPT_DELETE_DEFAULT)
02032     {
02033         SetLastError(NTE_BAD_FLAGS);
02034         return FALSE;
02035     }
02036 
02037     if (!(keyname = CRYPT_GetTypeKeyName(dwProvType, dwFlags & CRYPT_USER_DEFAULT)))
02038     {
02039         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
02040         return FALSE;
02041     }
02042     if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
02043         keyname, &hTypeKey))
02044     {
02045         CRYPT_Free(keyname);
02046         SetLastError(NTE_BAD_PROVIDER);
02047         return FALSE;
02048     }
02049     CRYPT_Free(keyname);
02050     
02051     if (dwFlags & CRYPT_DELETE_DEFAULT)
02052     {
02053         RegDeleteValueW(hTypeKey, nameW);
02054     }
02055     else
02056     {
02057         if (!(keyname = CRYPT_GetProvKeyName(pszProvName)))
02058         {
02059             RegCloseKey(hTypeKey);
02060             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
02061             return FALSE;
02062         }
02063         if (RegOpenKeyW((dwFlags & CRYPT_USER_DEFAULT) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
02064             keyname, &hProvKey))
02065         {
02066             CRYPT_Free(keyname);
02067             RegCloseKey(hTypeKey);
02068             SetLastError(NTE_BAD_PROVIDER);
02069             return FALSE;
02070         }
02071         CRYPT_Free(keyname);
02072         
02073         if (RegSetValueExW(hTypeKey, nameW, 0, REG_SZ, (const BYTE *)pszProvName,
02074             (strlenW(pszProvName) + 1)*sizeof(WCHAR)))
02075         {
02076             RegCloseKey(hTypeKey);
02077             RegCloseKey(hProvKey);
02078             return FALSE;
02079         }
02080         
02081         RegCloseKey(hProvKey);
02082     }
02083     RegCloseKey(hTypeKey);
02084 
02085     return TRUE;
02086 }
02087 
02088 /******************************************************************************
02089  * CryptSetProviderExA (ADVAPI32.@)
02090  *
02091  * See CryptSetProviderExW.
02092  */
02093 BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags)
02094 {
02095     BOOL ret = FALSE;
02096     PWSTR str = NULL;
02097 
02098     TRACE("(%s, %d, %p, %08x)\n", pszProvName, dwProvType, pdwReserved, dwFlags);
02099 
02100     if (CRYPT_ANSIToUnicode(pszProvName, &str, -1))
02101     {
02102         ret = CryptSetProviderExW(str, dwProvType, pdwReserved, dwFlags);
02103         CRYPT_Free(str);
02104     }
02105     return ret;
02106 }
02107 
02108 /******************************************************************************
02109  * CryptSetProvParam (ADVAPI32.@)
02110  *
02111  * Customizes the operations of a CSP.
02112  *
02113  * PARAMS
02114  *  hProv   [I] Handle of a CSP.
02115  *  dwParam [I] See MSDN Doc.
02116  *  pbData  [I] Buffer that contains a value to set as a parameter.
02117  *  dwFlags [I] if dwParam is PP_USE_HARDWARE_RNG, dwFlags must be zero.
02118  *
02119  * RETURNS
02120  *  Success: TRUE
02121  *  Failure: FALSE
02122  */
02123 BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, CONST BYTE *pbData, DWORD dwFlags)
02124 {
02125     PCRYPTPROV prov = (PCRYPTPROV)hProv;
02126 
02127     TRACE("(0x%lx, %d, %p, %08x)\n", hProv, dwParam, pbData, dwFlags);
02128 
02129     if (!prov)
02130     {
02131         SetLastError(ERROR_INVALID_HANDLE);
02132         return FALSE;
02133     }
02134     if (prov->dwMagic != MAGIC_CRYPTPROV)
02135     {
02136         SetLastError(ERROR_INVALID_PARAMETER);
02137         return FALSE;
02138     }
02139     if (dwFlags & PP_USE_HARDWARE_RNG)
02140     {
02141         FIXME("PP_USE_HARDWARE_RNG: What do I do with this?\n");
02142         FIXME("\tLetting the CSP decide.\n");
02143     }
02144     if (dwFlags & PP_CLIENT_HWND)
02145     {
02146         /* FIXME: Should verify the parameter */
02147         if (pbData /* && IsWindow((HWND)pbData) */)
02148         {
02149             crypt_hWindow = (HWND)(pbData);
02150             return TRUE;
02151         } else {
02152             SetLastError(ERROR_INVALID_PARAMETER);
02153             return FALSE;
02154         }
02155     }
02156     /* All other flags go to the CSP */
02157     return prov->pFuncs->pCPSetProvParam(prov->hPrivate, dwParam, pbData, dwFlags);
02158 }
02159 
02160 /******************************************************************************
02161  * CryptVerifySignatureW (ADVAPI32.@)
02162  *
02163  * Verifies the signature of a hash object.
02164  *
02165  * PARAMS
02166  *  hHash        [I] Handle of the hash object to verify.
02167  *  pbSignature  [I] Signature data to verify.
02168  *  dwSigLen     [I] Size of pbSignature.
02169  *  hPubKey      [I] Handle to the public key to authenticate signature.
02170  *  sDescription [I] Should be NULL.
02171  *  dwFlags      [I] See MSDN doc.
02172  *
02173  * RETURNS
02174  *  Success: TRUE
02175  *  Failure: FALSE
02176  * 
02177  * NOTES
02178  *  Because of security flaws sDescription should not be used and should thus be
02179  *  NULL. It is supported only for compatibility with Microsoft's Cryptographic
02180  *  Providers.
02181  */
02182 BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
02183         HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
02184 {
02185     PCRYPTHASH hash = (PCRYPTHASH)hHash;
02186     PCRYPTKEY key = (PCRYPTKEY)hPubKey;
02187     PCRYPTPROV prov;
02188 
02189     TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
02190             dwSigLen, hPubKey, debugstr_w(sDescription), dwFlags);
02191 
02192     if (!hash || !key ||
02193         !hash->pProvider || hash->pProvider->dwMagic != MAGIC_CRYPTPROV ||
02194         !key->pProvider || key->pProvider->dwMagic != MAGIC_CRYPTPROV)
02195     {
02196         SetLastError(ERROR_INVALID_PARAMETER);
02197         return FALSE;
02198     }
02199         
02200     prov = hash->pProvider;
02201     return prov->pFuncs->pCPVerifySignature(prov->hPrivate, hash->hPrivate, pbSignature, dwSigLen,
02202         key->hPrivate, sDescription, dwFlags);
02203 }
02204 
02205 /******************************************************************************
02206  * CryptVerifySignatureA (ADVAPI32.@)
02207  *
02208  * See CryptVerifySignatureW.
02209  */
02210 BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, CONST BYTE *pbSignature, DWORD dwSigLen,
02211         HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags)
02212 {
02213     LPWSTR wsDescription;
02214     BOOL result;
02215 
02216     TRACE("(0x%lx, %p, %d, 0x%lx, %s, %08x)\n", hHash, pbSignature,
02217             dwSigLen, hPubKey, debugstr_a(sDescription), dwFlags);
02218 
02219     CRYPT_ANSIToUnicode(sDescription, &wsDescription, -1);
02220     result = CryptVerifySignatureW(hHash, pbSignature, dwSigLen, hPubKey, wsDescription, dwFlags);
02221     CRYPT_Free(wsDescription);
02222 
02223     return result;
02224 }

Generated on Sat May 26 2012 04:21:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.