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

sip.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2002 Mike McCormack for CodeWeavers
00003  * Copyright 2005-2008 Juan Lang
00004  * Copyright 2006 Paul Vriens
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 
00024 #include "windef.h"
00025 #include "winbase.h"
00026 #include "wincrypt.h"
00027 #include "winreg.h"
00028 #include "winnls.h"
00029 #include "mssip.h"
00030 #include "winuser.h"
00031 
00032 #include "wine/debug.h"
00033 #include "wine/list.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
00036 
00037 static const WCHAR szOID[] = {
00038     'S','o','f','t','w','a','r','e','\\',
00039     'M','i','c','r','o','s','o','f','t','\\',
00040     'C','r','y','p','t','o','g','r','a','p','h','y','\\',
00041     'O','I','D','\\',
00042     'E','n','c','o','d','i','n','g','T','y','p','e',' ','0','\\',
00043     'C','r','y','p','t','S','I','P','D','l','l', 0 };
00044 
00045 static const WCHAR szPutSigned[] = {
00046     'P','u','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
00047 static const WCHAR szGetSigned[] = {
00048     'G','e','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
00049 static const WCHAR szRemoveSigned[] = {
00050     'R','e','m','o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0};
00051 static const WCHAR szCreate[] = {
00052     'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a','\\',0};
00053 static const WCHAR szVerify[] = {
00054     'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a','\\',0};
00055 static const WCHAR szIsMyFile[] = {
00056     'I','s','M','y','F','i','l','e','T','y','p','e','\\',0};
00057 static const WCHAR szIsMyFile2[] = {
00058     'I','s','M','y','F','i','l','e','T','y','p','e','2','\\',0};
00059 
00060 static const WCHAR szDllName[] = { 'D','l','l',0 };
00061 static const WCHAR szFuncName[] = { 'F','u','n','c','N','a','m','e',0 };
00062 
00063 /* convert a guid to a wide character string */
00064 static void CRYPT_guid2wstr( const GUID *guid, LPWSTR wstr )
00065 {
00066     char str[40];
00067 
00068     sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
00069            guid->Data1, guid->Data2, guid->Data3,
00070            guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
00071            guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
00072     MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, 40 );
00073 }
00074 
00075 /***********************************************************************
00076  *              CRYPT_SIPDeleteFunction
00077  *
00078  * Helper function for CryptSIPRemoveProvider
00079  */
00080 static LONG CRYPT_SIPDeleteFunction( const GUID *guid, LPCWSTR szKey )
00081 {
00082     WCHAR szFullKey[ 0x100 ];
00083     LONG r = ERROR_SUCCESS;
00084 
00085     /* max length of szFullKey depends on our code only, so we won't overrun */
00086     lstrcpyW( szFullKey, szOID );
00087     lstrcatW( szFullKey, szKey );
00088     CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] );
00089 
00090     r = RegDeleteKeyW(HKEY_LOCAL_MACHINE, szFullKey);
00091 
00092     return r;
00093 }
00094 
00095 /***********************************************************************
00096  *             CryptSIPRemoveProvider (CRYPT32.@)
00097  *
00098  * Remove a SIP provider and its functions from the registry.
00099  *
00100  * PARAMS
00101  *  pgProv     [I] Pointer to a GUID for this SIP provider
00102  *
00103  * RETURNS
00104  *  Success: TRUE.
00105  *  Failure: FALSE. (Look at GetLastError()).
00106  *
00107  * NOTES
00108  *  Registry errors are always reported via SetLastError(). Every registry
00109  *  deletion will be tried.
00110  */
00111 BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv)
00112 {
00113     LONG r = ERROR_SUCCESS;
00114     LONG remove_error = ERROR_SUCCESS;
00115 
00116     TRACE("%s\n", debugstr_guid(pgProv));
00117 
00118     if (!pgProv)
00119     {
00120         SetLastError(ERROR_INVALID_PARAMETER);
00121         return FALSE;
00122     }
00123 
00124 
00125 #define CRYPT_SIPREMOVEPROV( key ) \
00126     r = CRYPT_SIPDeleteFunction( pgProv, key); \
00127     if (r != ERROR_SUCCESS) remove_error = r
00128 
00129     CRYPT_SIPREMOVEPROV( szPutSigned);
00130     CRYPT_SIPREMOVEPROV( szGetSigned);
00131     CRYPT_SIPREMOVEPROV( szRemoveSigned);
00132     CRYPT_SIPREMOVEPROV( szCreate);
00133     CRYPT_SIPREMOVEPROV( szVerify);
00134     CRYPT_SIPREMOVEPROV( szIsMyFile);
00135     CRYPT_SIPREMOVEPROV( szIsMyFile2);
00136 
00137 #undef CRYPT_SIPREMOVEPROV
00138 
00139     if (remove_error != ERROR_SUCCESS)
00140     {
00141         SetLastError(remove_error);
00142         return FALSE;
00143     }
00144 
00145     return TRUE;
00146 }
00147 
00148 /*
00149  * Helper for CryptSIPAddProvider
00150  *
00151  * Add a registry key containing a dll name and function under
00152  *  "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\<func>\<guid>"
00153  */
00154 static LONG CRYPT_SIPWriteFunction( const GUID *guid, LPCWSTR szKey,
00155               LPCWSTR szDll, LPCWSTR szFunction )
00156 {
00157     WCHAR szFullKey[ 0x100 ];
00158     LONG r = ERROR_SUCCESS;
00159     HKEY hKey;
00160 
00161     if( !szFunction )
00162          return ERROR_SUCCESS;
00163 
00164     /* max length of szFullKey depends on our code only, so we won't overrun */
00165     lstrcpyW( szFullKey, szOID );
00166     lstrcatW( szFullKey, szKey );
00167     CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] );
00168 
00169     TRACE("key is %s\n", debugstr_w( szFullKey ) );
00170 
00171     r = RegCreateKeyW( HKEY_LOCAL_MACHINE, szFullKey, &hKey );
00172     if( r != ERROR_SUCCESS ) goto error_close_key;
00173 
00174     /* write the values */
00175     r = RegSetValueExW( hKey, szFuncName, 0, REG_SZ, (const BYTE*) szFunction,
00176                         ( lstrlenW( szFunction ) + 1 ) * sizeof (WCHAR) );
00177     if( r != ERROR_SUCCESS ) goto error_close_key;
00178     r = RegSetValueExW( hKey, szDllName, 0, REG_SZ, (const BYTE*) szDll,
00179                         ( lstrlenW( szDll ) + 1) * sizeof (WCHAR) );
00180 
00181 error_close_key:
00182 
00183     RegCloseKey( hKey );
00184 
00185     return r;
00186 }
00187 
00188 /***********************************************************************
00189  *             CryptSIPAddProvider (CRYPT32.@)
00190  *
00191  * Add a SIP provider and its functions to the registry.
00192  *
00193  * PARAMS
00194  *  psNewProv       [I] Pointer to a structure with information about
00195  *                      the functions this SIP provider can perform.
00196  *
00197  * RETURNS
00198  *  Success: TRUE.
00199  *  Failure: FALSE. (Look at GetLastError()).
00200  *
00201  * NOTES
00202  *  Registry errors are always reported via SetLastError(). If a
00203  *  registry error occurs the rest of the registry write operations
00204  *  will be skipped.
00205  */
00206 BOOL WINAPI CryptSIPAddProvider(SIP_ADD_NEWPROVIDER *psNewProv)
00207 {
00208     LONG r = ERROR_SUCCESS;
00209 
00210     TRACE("%p\n", psNewProv);
00211 
00212     if (!psNewProv ||
00213         psNewProv->cbStruct != sizeof(SIP_ADD_NEWPROVIDER) ||
00214         !psNewProv->pwszGetFuncName ||
00215         !psNewProv->pwszPutFuncName ||
00216         !psNewProv->pwszCreateFuncName ||
00217         !psNewProv->pwszVerifyFuncName ||
00218         !psNewProv->pwszRemoveFuncName)
00219     {
00220         SetLastError(ERROR_INVALID_PARAMETER);
00221         return FALSE;
00222     }
00223 
00224     TRACE("%s %s %s %s %s\n",
00225           debugstr_guid( psNewProv->pgSubject ),
00226           debugstr_w( psNewProv->pwszDLLFileName ),
00227           debugstr_w( psNewProv->pwszMagicNumber ),
00228           debugstr_w( psNewProv->pwszIsFunctionName ),
00229           debugstr_w( psNewProv->pwszIsFunctionNameFmt2 ) );
00230 
00231 #define CRYPT_SIPADDPROV( key, field ) \
00232     r = CRYPT_SIPWriteFunction( psNewProv->pgSubject, key, \
00233            psNewProv->pwszDLLFileName, psNewProv->field); \
00234     if (r != ERROR_SUCCESS) goto end_function
00235 
00236     CRYPT_SIPADDPROV( szPutSigned, pwszPutFuncName );
00237     CRYPT_SIPADDPROV( szGetSigned, pwszGetFuncName );
00238     CRYPT_SIPADDPROV( szRemoveSigned, pwszRemoveFuncName );
00239     CRYPT_SIPADDPROV( szCreate, pwszCreateFuncName );
00240     CRYPT_SIPADDPROV( szVerify, pwszVerifyFuncName );
00241     CRYPT_SIPADDPROV( szIsMyFile, pwszIsFunctionName );
00242     CRYPT_SIPADDPROV( szIsMyFile2, pwszIsFunctionNameFmt2 );
00243 
00244 #undef CRYPT_SIPADDPROV
00245 
00246 end_function:
00247 
00248     if (r != ERROR_SUCCESS)
00249     {
00250         SetLastError(r);
00251         return FALSE;
00252     }
00253 
00254     return TRUE;
00255 }
00256 
00257 static void *CRYPT_LoadSIPFuncFromKey(HKEY key, HMODULE *pLib)
00258 {
00259     LONG r;
00260     DWORD size;
00261     WCHAR dllName[MAX_PATH];
00262     char functionName[MAX_PATH];
00263     HMODULE lib;
00264     void *func = NULL;
00265 
00266     /* Read the DLL entry */
00267     size = sizeof(dllName);
00268     r = RegQueryValueExW(key, szDllName, NULL, NULL, (LPBYTE)dllName, &size);
00269     if (r) goto end;
00270 
00271     /* Read the Function entry */
00272     size = sizeof(functionName);
00273     r = RegQueryValueExA(key, "FuncName", NULL, NULL, (LPBYTE)functionName,
00274      &size);
00275     if (r) goto end;
00276 
00277     lib = LoadLibraryW(dllName);
00278     if (!lib)
00279         goto end;
00280     func = GetProcAddress(lib, functionName);
00281     if (func)
00282         *pLib = lib;
00283     else
00284         FreeLibrary(lib);
00285 
00286 end:
00287     return func;
00288 }
00289 
00290 /***********************************************************************
00291  *             CryptSIPRetrieveSubjectGuid (CRYPT32.@)
00292  *
00293  * Determine the right SIP GUID for the given file.
00294  *
00295  * PARAMS
00296  *  FileName   [I] Filename.
00297  *  hFileIn    [I] Optional handle to the file.
00298  *  pgSubject  [O] The SIP's GUID.
00299  *
00300  * RETURNS
00301  *  Success: TRUE. pgSubject contains the SIP GUID.
00302  *  Failure: FALSE. (Look at GetLastError()).
00303  *
00304  * NOTES
00305  *  On failure pgSubject will contain a NULL GUID.
00306  *  The handle is always preferred above the filename.
00307  */
00308 BOOL WINAPI CryptSIPRetrieveSubjectGuid
00309       (LPCWSTR FileName, HANDLE hFileIn, GUID *pgSubject)
00310 {
00311     HANDLE hFile;
00312     BOOL   bRet = FALSE;
00313     DWORD  count;
00314     LARGE_INTEGER zero, oldPos;
00315     /* FIXME, find out if there is a name for this GUID */
00316     static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
00317     static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }};
00318     static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
00319     static const WORD dosHdr = IMAGE_DOS_SIGNATURE;
00320     static const BYTE cabHdr[] = { 'M','S','C','F' };
00321     BYTE hdr[SIP_MAX_MAGIC_NUMBER];
00322     WCHAR szFullKey[ 0x100 ];
00323     LONG r = ERROR_SUCCESS;
00324     HKEY key;
00325 
00326     TRACE("(%s %p %p)\n", wine_dbgstr_w(FileName), hFileIn, pgSubject);
00327 
00328     if (!pgSubject || (!FileName && !hFileIn))
00329     {
00330         SetLastError(ERROR_INVALID_PARAMETER);
00331         return FALSE;
00332     }
00333 
00334     /* Set pgSubject to zero's */
00335     memset(pgSubject, 0 , sizeof(GUID));
00336 
00337     if (hFileIn)
00338         /* Use the given handle, make sure not to close this one ourselves */
00339         hFile = hFileIn;
00340     else
00341     {
00342         hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00343         /* Last error is set by CreateFile */
00344         if (hFile == INVALID_HANDLE_VALUE) return FALSE;
00345     }
00346 
00347     zero.QuadPart = 0;
00348     SetFilePointerEx(hFile, zero, &oldPos, FILE_CURRENT);
00349     SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
00350     if (!ReadFile(hFile, hdr, sizeof(hdr), &count, NULL))
00351         goto cleanup;
00352 
00353     if (count < SIP_MAX_MAGIC_NUMBER)
00354     {
00355         SetLastError(ERROR_INVALID_PARAMETER);
00356         goto cleanup;
00357     }
00358 
00359     TRACE("file magic = 0x%02x%02x%02x%02x\n", hdr[0], hdr[1], hdr[2], hdr[3]);
00360     /* As everything is in place now we start looking at the file header */
00361     if (!memcmp(hdr, &dosHdr, sizeof(dosHdr)))
00362     {
00363         *pgSubject = unknown;
00364         SetLastError(S_OK);
00365         bRet = TRUE;
00366         goto cleanup;
00367     }
00368     /* Quick-n-dirty check for a cab file. */
00369     if (!memcmp(hdr, cabHdr, sizeof(cabHdr)))
00370     {
00371         *pgSubject = cabGUID;
00372         SetLastError(S_OK);
00373         bRet = TRUE;
00374         goto cleanup;
00375     }
00376     /* If it's asn.1-encoded, it's probably a .cat file. */
00377     if (hdr[0] == 0x30)
00378     {
00379         DWORD fileLen = GetFileSize(hFile, NULL);
00380 
00381         TRACE("fileLen = %d\n", fileLen);
00382         /* Sanity-check length */
00383         if (hdr[1] < 0x80 && fileLen == 2 + hdr[1])
00384         {
00385             *pgSubject = catGUID;
00386             SetLastError(S_OK);
00387             bRet = TRUE;
00388             goto cleanup;
00389         }
00390         else if (hdr[1] == 0x80)
00391         {
00392             /* Indefinite length, can't verify with just the header, assume it
00393              * is.
00394              */
00395             *pgSubject = catGUID;
00396             SetLastError(S_OK);
00397             bRet = TRUE;
00398             goto cleanup;
00399         }
00400         else
00401         {
00402             BYTE lenBytes = hdr[1] & 0x7f;
00403 
00404             if (lenBytes == 1 && fileLen == 2 + lenBytes + hdr[2])
00405             {
00406                 *pgSubject = catGUID;
00407                 SetLastError(S_OK);
00408                 bRet = TRUE;
00409                 goto cleanup;
00410             }
00411             else if (lenBytes == 2 && fileLen == 2 + lenBytes +
00412              (hdr[2] << 8 | hdr[3]))
00413             {
00414                 *pgSubject = catGUID;
00415                 SetLastError(S_OK);
00416                 bRet = TRUE;
00417                 goto cleanup;
00418             }
00419             else if (fileLen > 0xffff)
00420             {
00421                 /* The file size must be greater than 2 bytes in length, so
00422                  * assume it is a .cat file
00423                  */
00424                 *pgSubject = catGUID;
00425                 SetLastError(S_OK);
00426                 bRet = TRUE;
00427                 goto cleanup;
00428             }
00429         }
00430     }
00431 
00432     /* Check for supported functions using CryptSIPDllIsMyFileType */
00433     /* max length of szFullKey depends on our code only, so we won't overrun */
00434     lstrcpyW(szFullKey, szOID);
00435     lstrcatW(szFullKey, szIsMyFile);
00436     r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key);
00437     if (r == ERROR_SUCCESS)
00438     {
00439         DWORD index = 0, size;
00440         WCHAR subKeyName[MAX_PATH];
00441 
00442         do {
00443             size = sizeof(subKeyName) / sizeof(subKeyName[0]);
00444             r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL,
00445              NULL, NULL);
00446             if (r == ERROR_SUCCESS)
00447             {
00448                 HKEY subKey;
00449 
00450                 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
00451                 if (r == ERROR_SUCCESS)
00452                 {
00453                     HMODULE lib;
00454                     pfnIsFileSupported isMy = CRYPT_LoadSIPFuncFromKey(subKey,
00455                      &lib);
00456 
00457                     if (isMy)
00458                     {
00459                         bRet = isMy(hFile, pgSubject);
00460                         FreeLibrary(lib);
00461                     }
00462                     RegCloseKey(subKey);
00463                 }
00464             }
00465         } while (!bRet && r == ERROR_SUCCESS);
00466         RegCloseKey(key);
00467     }
00468 
00469     /* Check for supported functions using CryptSIPDllIsMyFileType2 */
00470     if (!bRet)
00471     {
00472         lstrcpyW(szFullKey, szOID);
00473         lstrcatW(szFullKey, szIsMyFile2);
00474         r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key);
00475         if (r == ERROR_SUCCESS)
00476         {
00477             DWORD index = 0, size;
00478             WCHAR subKeyName[MAX_PATH];
00479 
00480             do {
00481                 size = sizeof(subKeyName) / sizeof(subKeyName[0]);
00482                 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL,
00483                  NULL, NULL);
00484                 if (r == ERROR_SUCCESS)
00485                 {
00486                     HKEY subKey;
00487 
00488                     r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
00489                     if (r == ERROR_SUCCESS)
00490                     {
00491                         HMODULE lib;
00492                         pfnIsFileSupportedName isMy2 =
00493                          CRYPT_LoadSIPFuncFromKey(subKey, &lib);
00494 
00495                         if (isMy2)
00496                         {
00497                             bRet = isMy2((LPWSTR)FileName, pgSubject);
00498                             FreeLibrary(lib);
00499                         }
00500                         RegCloseKey(subKey);
00501                     }
00502                 }
00503             } while (!bRet && r == ERROR_SUCCESS);
00504             RegCloseKey(key);
00505         }
00506     }
00507 
00508     if (!bRet)
00509         SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
00510 
00511 cleanup:
00512     /* If we didn't open this one we shouldn't close it (hFile is a copy),
00513      * but we should reset the file pointer to its original position.
00514      */
00515     if (!hFileIn)
00516         CloseHandle(hFile);
00517     else
00518         SetFilePointerEx(hFile, oldPos, NULL, FILE_BEGIN);
00519 
00520     return bRet;
00521 }
00522 
00523 static LONG CRYPT_OpenSIPFunctionKey(const GUID *guid, LPCWSTR function,
00524  HKEY *key)
00525 {
00526     WCHAR szFullKey[ 0x100 ];
00527 
00528     lstrcpyW(szFullKey, szOID);
00529     lstrcatW(szFullKey, function);
00530     CRYPT_guid2wstr(guid, &szFullKey[lstrlenW(szFullKey)]);
00531     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, key);
00532 }
00533 
00534 /* Loads the function named function for the SIP specified by pgSubject, and
00535  * returns it if found.  Returns NULL on error.  If the function is loaded,
00536  * *pLib is set to the library in which it is found.
00537  */
00538 static void *CRYPT_LoadSIPFunc(const GUID *pgSubject, LPCWSTR function,
00539  HMODULE *pLib)
00540 {
00541     LONG r;
00542     HKEY key;
00543     void *func = NULL;
00544 
00545     TRACE("(%s, %s)\n", debugstr_guid(pgSubject), debugstr_w(function));
00546 
00547     r = CRYPT_OpenSIPFunctionKey(pgSubject, function, &key);
00548     if (!r)
00549     {
00550         func = CRYPT_LoadSIPFuncFromKey(key, pLib);
00551         RegCloseKey(key);
00552     }
00553     TRACE("returning %p\n", func);
00554     return func;
00555 }
00556 
00557 typedef struct _WINE_SIP_PROVIDER {
00558     GUID              subject;
00559     SIP_DISPATCH_INFO info;
00560     struct list       entry;
00561 } WINE_SIP_PROVIDER;
00562 
00563 static struct list providers = { &providers, &providers };
00564 static CRITICAL_SECTION providers_cs;
00565 static CRITICAL_SECTION_DEBUG providers_cs_debug =
00566 {
00567     0, 0, &providers_cs,
00568     { &providers_cs_debug.ProcessLocksList,
00569     &providers_cs_debug.ProcessLocksList },
00570     0, 0, { (DWORD_PTR)(__FILE__ ": providers_cs") }
00571 };
00572 static CRITICAL_SECTION providers_cs = { &providers_cs_debug, -1, 0, 0, 0, 0 };
00573 
00574 static void CRYPT_CacheSIP(const GUID *pgSubject, SIP_DISPATCH_INFO *info)
00575 {
00576     WINE_SIP_PROVIDER *prov = CryptMemAlloc(sizeof(WINE_SIP_PROVIDER));
00577 
00578     if (prov)
00579     {
00580         prov->subject = *pgSubject;
00581         prov->info = *info;
00582         EnterCriticalSection(&providers_cs);
00583         list_add_tail(&providers, &prov->entry);
00584         LeaveCriticalSection(&providers_cs);
00585     }
00586 }
00587 
00588 static WINE_SIP_PROVIDER *CRYPT_GetCachedSIP(const GUID *pgSubject)
00589 {
00590     WINE_SIP_PROVIDER *provider = NULL, *ret = NULL;
00591 
00592     EnterCriticalSection(&providers_cs);
00593     LIST_FOR_EACH_ENTRY(provider, &providers, WINE_SIP_PROVIDER, entry)
00594     {
00595         if (IsEqualGUID(pgSubject, &provider->subject))
00596             break;
00597     }
00598     if (provider && IsEqualGUID(pgSubject, &provider->subject))
00599         ret = provider;
00600     LeaveCriticalSection(&providers_cs);
00601     return ret;
00602 }
00603 
00604 static inline BOOL CRYPT_IsSIPCached(const GUID *pgSubject)
00605 {
00606     return CRYPT_GetCachedSIP(pgSubject) != NULL;
00607 }
00608 
00609 void crypt_sip_free(void)
00610 {
00611     WINE_SIP_PROVIDER *prov, *next;
00612 
00613     LIST_FOR_EACH_ENTRY_SAFE(prov, next, &providers, WINE_SIP_PROVIDER, entry)
00614     {
00615         list_remove(&prov->entry);
00616         FreeLibrary(prov->info.hSIP);
00617         CryptMemFree(prov);
00618     }
00619     DeleteCriticalSection(&providers_cs);
00620 }
00621 
00622 /* Loads the SIP for pgSubject into the global cache.  Returns FALSE if the
00623  * SIP isn't registered or is invalid.
00624  */
00625 static BOOL CRYPT_LoadSIP(const GUID *pgSubject)
00626 {
00627     SIP_DISPATCH_INFO sip = { 0 };
00628     HMODULE lib = NULL, temp = NULL;
00629 
00630     sip.pfGet = CRYPT_LoadSIPFunc(pgSubject, szGetSigned, &lib);
00631     if (!sip.pfGet)
00632         goto error;
00633     sip.pfPut = CRYPT_LoadSIPFunc(pgSubject, szPutSigned, &temp);
00634     if (!sip.pfPut || temp != lib)
00635         goto error;
00636     FreeLibrary(temp);
00637     sip.pfCreate = CRYPT_LoadSIPFunc(pgSubject, szCreate, &temp);
00638     if (!sip.pfCreate || temp != lib)
00639         goto error;
00640     FreeLibrary(temp);
00641     sip.pfVerify = CRYPT_LoadSIPFunc(pgSubject, szVerify, &temp);
00642     if (!sip.pfVerify || temp != lib)
00643         goto error;
00644     FreeLibrary(temp);
00645     sip.pfRemove = CRYPT_LoadSIPFunc(pgSubject, szRemoveSigned, &temp);
00646     if (!sip.pfRemove || temp != lib)
00647         goto error;
00648     FreeLibrary(temp);
00649     sip.hSIP = lib;
00650     CRYPT_CacheSIP(pgSubject, &sip);
00651     return TRUE;
00652 
00653 error:
00654     FreeLibrary(lib);
00655     FreeLibrary(temp);
00656     SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
00657     return FALSE;
00658 }
00659 
00660 /***********************************************************************
00661  *             CryptSIPLoad (CRYPT32.@)
00662  *
00663  * Load some internal crypt32 functions into a SIP_DISPATCH_INFO structure.
00664  *
00665  * PARAMS
00666  *  pgSubject    [I] The GUID.
00667  *  dwFlags      [I] Flags.
00668  *  pSipDispatch [I] The loaded functions.
00669  *
00670  * RETURNS
00671  *  Success: TRUE. pSipDispatch contains the functions.
00672  *  Failure: FALSE. (Look at GetLastError()).
00673  *
00674  * NOTES
00675  *  CryptSIPLoad uses caching for the list of GUIDs and whether a SIP is
00676  *  already loaded.
00677  *
00678  *  An application calls CryptSipLoad which will return a structure with the
00679  *  function addresses of some internal crypt32 functions. The application will
00680  *  then call these functions which will be forwarded to the appropriate SIP.
00681  *
00682  *  CryptSIPLoad will load the needed SIP but doesn't unload this dll. The unloading
00683  *  is done when crypt32 is unloaded.
00684  */
00685 BOOL WINAPI CryptSIPLoad
00686        (const GUID *pgSubject, DWORD dwFlags, SIP_DISPATCH_INFO *pSipDispatch)
00687 {
00688     TRACE("(%s %d %p)\n", debugstr_guid(pgSubject), dwFlags, pSipDispatch);
00689 
00690     if (!pgSubject || dwFlags != 0 || !pSipDispatch)
00691     {
00692         SetLastError(ERROR_INVALID_PARAMETER);
00693         return FALSE;
00694     }
00695     if (!CRYPT_IsSIPCached(pgSubject) && !CRYPT_LoadSIP(pgSubject))
00696         return FALSE;
00697 
00698     pSipDispatch->hSIP = NULL;
00699     pSipDispatch->pfGet = CryptSIPGetSignedDataMsg;
00700     pSipDispatch->pfPut = CryptSIPPutSignedDataMsg;
00701     pSipDispatch->pfCreate = CryptSIPCreateIndirectData;
00702     pSipDispatch->pfVerify = CryptSIPVerifyIndirectData;
00703     pSipDispatch->pfRemove = CryptSIPRemoveSignedDataMsg;
00704 
00705     return TRUE;
00706 }
00707 
00708 /***********************************************************************
00709  *             CryptSIPCreateIndirectData (CRYPT32.@)
00710  */
00711 BOOL WINAPI CryptSIPCreateIndirectData(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pcbIndirectData,
00712                                        SIP_INDIRECT_DATA* pIndirectData)
00713 {
00714     WINE_SIP_PROVIDER *sip;
00715     BOOL ret = FALSE;
00716 
00717     TRACE("(%p %p %p)\n", pSubjectInfo, pcbIndirectData, pIndirectData);
00718 
00719     if (!pSubjectInfo || !pSubjectInfo->pgSubjectType || !pcbIndirectData)
00720     {
00721         SetLastError(ERROR_INVALID_PARAMETER);
00722         return FALSE;
00723     }
00724     if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
00725         ret = sip->info.pfCreate(pSubjectInfo, pcbIndirectData, pIndirectData);
00726     TRACE("returning %d\n", ret);
00727     return ret;
00728 }
00729 
00730 /***********************************************************************
00731  *             CryptSIPGetSignedDataMsg (CRYPT32.@)
00732  */
00733 BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType,
00734                                        DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg)
00735 {
00736     WINE_SIP_PROVIDER *sip;
00737     BOOL ret = FALSE;
00738 
00739     TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex,
00740           pcbSignedDataMsg, pbSignedDataMsg);
00741 
00742     if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
00743         ret = sip->info.pfGet(pSubjectInfo, pdwEncodingType, dwIndex,
00744          pcbSignedDataMsg, pbSignedDataMsg);
00745     TRACE("returning %d\n", ret);
00746     return ret;
00747 }
00748 
00749 /***********************************************************************
00750  *             CryptSIPPutSignedDataMsg (CRYPT32.@)
00751  */
00752 BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType,
00753                                        DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg)
00754 {
00755     WINE_SIP_PROVIDER *sip;
00756     BOOL ret = FALSE;
00757 
00758     TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex,
00759           cbSignedDataMsg, pbSignedDataMsg);
00760 
00761     if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
00762         ret = sip->info.pfPut(pSubjectInfo, pdwEncodingType, pdwIndex,
00763          cbSignedDataMsg, pbSignedDataMsg);
00764     TRACE("returning %d\n", ret);
00765     return ret;
00766 }
00767 
00768 /***********************************************************************
00769  *             CryptSIPRemoveSignedDataMsg (CRYPT32.@)
00770  */
00771 BOOL WINAPI CryptSIPRemoveSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo,
00772                                        DWORD dwIndex)
00773 {
00774     WINE_SIP_PROVIDER *sip;
00775     BOOL ret = FALSE;
00776 
00777     TRACE("(%p %d)\n", pSubjectInfo, dwIndex);
00778 
00779     if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
00780         ret = sip->info.pfRemove(pSubjectInfo, dwIndex);
00781     TRACE("returning %d\n", ret);
00782     return ret;
00783 }
00784 
00785 /***********************************************************************
00786  *             CryptSIPVerifyIndirectData (CRYPT32.@)
00787  */
00788 BOOL WINAPI CryptSIPVerifyIndirectData(SIP_SUBJECTINFO* pSubjectInfo,
00789                                        SIP_INDIRECT_DATA* pIndirectData)
00790 {
00791     WINE_SIP_PROVIDER *sip;
00792     BOOL ret = FALSE;
00793 
00794     TRACE("(%p %p)\n", pSubjectInfo, pIndirectData);
00795 
00796     if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType)))
00797         ret = sip->info.pfVerify(pSubjectInfo, pIndirectData);
00798     TRACE("returning %d\n", ret);
00799     return ret;
00800 }

Generated on Sat May 26 2012 04:21:55 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.