1 /* 2 * Copyright 2002 Mike McCormack for CodeWeavers 3 * Copyright 2005-2008 Juan Lang 4 * Copyright 2006 Paul Vriens 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "crypt32_private.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 24 25 static const WCHAR szOID[] = { 26 'S','o','f','t','w','a','r','e','\\', 27 'M','i','c','r','o','s','o','f','t','\\', 28 'C','r','y','p','t','o','g','r','a','p','h','y','\\', 29 'O','I','D','\\', 30 'E','n','c','o','d','i','n','g','T','y','p','e',' ','0','\\', 31 'C','r','y','p','t','S','I','P','D','l','l', 0 }; 32 33 static const WCHAR szPutSigned[] = { 34 'P','u','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 35 static const WCHAR szGetSigned[] = { 36 'G','e','t','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 37 static const WCHAR szRemoveSigned[] = { 38 'R','e','m','o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g','\\',0}; 39 static const WCHAR szCreate[] = { 40 'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a','\\',0}; 41 static const WCHAR szVerify[] = { 42 'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a','\\',0}; 43 static const WCHAR szIsMyFile[] = { 44 'I','s','M','y','F','i','l','e','T','y','p','e','\\',0}; 45 static const WCHAR szIsMyFile2[] = { 46 'I','s','M','y','F','i','l','e','T','y','p','e','2','\\',0}; 47 48 static const WCHAR szDllName[] = { 'D','l','l',0 }; 49 static const WCHAR szFuncName[] = { 'F','u','n','c','N','a','m','e',0 }; 50 51 /* convert a guid to a wide character string */ 52 static void CRYPT_guid2wstr( const GUID *guid, LPWSTR wstr ) 53 { 54 char str[40]; 55 56 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 57 guid->Data1, guid->Data2, guid->Data3, 58 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 59 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); 60 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, 40 ); 61 } 62 63 /*********************************************************************** 64 * CRYPT_SIPDeleteFunction 65 * 66 * Helper function for CryptSIPRemoveProvider 67 */ 68 static LONG CRYPT_SIPDeleteFunction( const GUID *guid, LPCWSTR szKey ) 69 { 70 WCHAR szFullKey[ 0x100 ]; 71 LONG r = ERROR_SUCCESS; 72 73 /* max length of szFullKey depends on our code only, so we won't overrun */ 74 lstrcpyW( szFullKey, szOID ); 75 lstrcatW( szFullKey, szKey ); 76 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] ); 77 78 r = RegDeleteKeyW(HKEY_LOCAL_MACHINE, szFullKey); 79 80 return r; 81 } 82 83 /*********************************************************************** 84 * CryptSIPRemoveProvider (CRYPT32.@) 85 * 86 * Remove a SIP provider and its functions from the registry. 87 * 88 * PARAMS 89 * pgProv [I] Pointer to a GUID for this SIP provider 90 * 91 * RETURNS 92 * Success: TRUE. 93 * Failure: FALSE. (Look at GetLastError()). 94 * 95 * NOTES 96 * Registry errors are always reported via SetLastError(). Every registry 97 * deletion will be tried. 98 */ 99 BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv) 100 { 101 LONG r = ERROR_SUCCESS; 102 LONG remove_error = ERROR_SUCCESS; 103 104 TRACE("%s\n", debugstr_guid(pgProv)); 105 106 if (!pgProv) 107 { 108 SetLastError(ERROR_INVALID_PARAMETER); 109 return FALSE; 110 } 111 112 113 #define CRYPT_SIPREMOVEPROV( key ) \ 114 r = CRYPT_SIPDeleteFunction( pgProv, key); \ 115 if (r != ERROR_SUCCESS) remove_error = r 116 117 CRYPT_SIPREMOVEPROV( szPutSigned); 118 CRYPT_SIPREMOVEPROV( szGetSigned); 119 CRYPT_SIPREMOVEPROV( szRemoveSigned); 120 CRYPT_SIPREMOVEPROV( szCreate); 121 CRYPT_SIPREMOVEPROV( szVerify); 122 CRYPT_SIPREMOVEPROV( szIsMyFile); 123 CRYPT_SIPREMOVEPROV( szIsMyFile2); 124 125 #undef CRYPT_SIPREMOVEPROV 126 127 if (remove_error != ERROR_SUCCESS) 128 { 129 SetLastError(remove_error); 130 return FALSE; 131 } 132 133 return TRUE; 134 } 135 136 /* 137 * Helper for CryptSIPAddProvider 138 * 139 * Add a registry key containing a dll name and function under 140 * "Software\\Microsoft\\Cryptography\\OID\\EncodingType 0\\<func>\\<guid>" 141 */ 142 static LONG CRYPT_SIPWriteFunction( const GUID *guid, LPCWSTR szKey, 143 LPCWSTR szDll, LPCWSTR szFunction ) 144 { 145 WCHAR szFullKey[ 0x100 ]; 146 LONG r = ERROR_SUCCESS; 147 HKEY hKey; 148 149 if( !szFunction ) 150 return ERROR_SUCCESS; 151 152 /* max length of szFullKey depends on our code only, so we won't overrun */ 153 lstrcpyW( szFullKey, szOID ); 154 lstrcatW( szFullKey, szKey ); 155 CRYPT_guid2wstr( guid, &szFullKey[ lstrlenW( szFullKey ) ] ); 156 157 TRACE("key is %s\n", debugstr_w( szFullKey ) ); 158 159 r = RegCreateKeyW( HKEY_LOCAL_MACHINE, szFullKey, &hKey ); 160 if( r != ERROR_SUCCESS ) goto error_close_key; 161 162 /* write the values */ 163 r = RegSetValueExW( hKey, szFuncName, 0, REG_SZ, (const BYTE*) szFunction, 164 ( lstrlenW( szFunction ) + 1 ) * sizeof (WCHAR) ); 165 if( r != ERROR_SUCCESS ) goto error_close_key; 166 r = RegSetValueExW( hKey, szDllName, 0, REG_SZ, (const BYTE*) szDll, 167 ( lstrlenW( szDll ) + 1) * sizeof (WCHAR) ); 168 169 error_close_key: 170 171 RegCloseKey( hKey ); 172 173 return r; 174 } 175 176 /*********************************************************************** 177 * CryptSIPAddProvider (CRYPT32.@) 178 * 179 * Add a SIP provider and its functions to the registry. 180 * 181 * PARAMS 182 * psNewProv [I] Pointer to a structure with information about 183 * the functions this SIP provider can perform. 184 * 185 * RETURNS 186 * Success: TRUE. 187 * Failure: FALSE. (Look at GetLastError()). 188 * 189 * NOTES 190 * Registry errors are always reported via SetLastError(). If a 191 * registry error occurs the rest of the registry write operations 192 * will be skipped. 193 */ 194 BOOL WINAPI CryptSIPAddProvider(SIP_ADD_NEWPROVIDER *psNewProv) 195 { 196 LONG r = ERROR_SUCCESS; 197 198 TRACE("%p\n", psNewProv); 199 200 if (!psNewProv || 201 psNewProv->cbStruct < FIELD_OFFSET(SIP_ADD_NEWPROVIDER, pwszGetCapFuncName) || 202 !psNewProv->pwszGetFuncName || 203 !psNewProv->pwszPutFuncName || 204 !psNewProv->pwszCreateFuncName || 205 !psNewProv->pwszVerifyFuncName || 206 !psNewProv->pwszRemoveFuncName) 207 { 208 SetLastError(ERROR_INVALID_PARAMETER); 209 return FALSE; 210 } 211 212 TRACE("%s %s %s %s %s\n", 213 debugstr_guid( psNewProv->pgSubject ), 214 debugstr_w( psNewProv->pwszDLLFileName ), 215 debugstr_w( psNewProv->pwszMagicNumber ), 216 debugstr_w( psNewProv->pwszIsFunctionName ), 217 debugstr_w( psNewProv->pwszIsFunctionNameFmt2 ) ); 218 219 #define CRYPT_SIPADDPROV( key, field ) \ 220 r = CRYPT_SIPWriteFunction( psNewProv->pgSubject, key, \ 221 psNewProv->pwszDLLFileName, psNewProv->field); \ 222 if (r != ERROR_SUCCESS) goto end_function 223 224 CRYPT_SIPADDPROV( szPutSigned, pwszPutFuncName ); 225 CRYPT_SIPADDPROV( szGetSigned, pwszGetFuncName ); 226 CRYPT_SIPADDPROV( szRemoveSigned, pwszRemoveFuncName ); 227 CRYPT_SIPADDPROV( szCreate, pwszCreateFuncName ); 228 CRYPT_SIPADDPROV( szVerify, pwszVerifyFuncName ); 229 CRYPT_SIPADDPROV( szIsMyFile, pwszIsFunctionName ); 230 CRYPT_SIPADDPROV( szIsMyFile2, pwszIsFunctionNameFmt2 ); 231 232 #undef CRYPT_SIPADDPROV 233 234 end_function: 235 236 if (r != ERROR_SUCCESS) 237 { 238 SetLastError(r); 239 return FALSE; 240 } 241 242 return TRUE; 243 } 244 245 static void *CRYPT_LoadSIPFuncFromKey(HKEY key, HMODULE *pLib) 246 { 247 LONG r; 248 DWORD size; 249 WCHAR dllName[MAX_PATH]; 250 char functionName[MAX_PATH]; 251 HMODULE lib; 252 void *func = NULL; 253 254 /* Read the DLL entry */ 255 size = sizeof(dllName); 256 r = RegQueryValueExW(key, szDllName, NULL, NULL, (LPBYTE)dllName, &size); 257 if (r) goto end; 258 259 /* Read the Function entry */ 260 size = sizeof(functionName); 261 r = RegQueryValueExA(key, "FuncName", NULL, NULL, (LPBYTE)functionName, 262 &size); 263 if (r) goto end; 264 265 lib = LoadLibraryW(dllName); 266 if (!lib) 267 goto end; 268 func = GetProcAddress(lib, functionName); 269 if (func) 270 *pLib = lib; 271 else 272 FreeLibrary(lib); 273 274 end: 275 return func; 276 } 277 278 /*********************************************************************** 279 * CryptSIPRetrieveSubjectGuid (CRYPT32.@) 280 * 281 * Determine the right SIP GUID for the given file. 282 * 283 * PARAMS 284 * FileName [I] Filename. 285 * hFileIn [I] Optional handle to the file. 286 * pgSubject [O] The SIP's GUID. 287 * 288 * RETURNS 289 * Success: TRUE. pgSubject contains the SIP GUID. 290 * Failure: FALSE. (Look at GetLastError()). 291 * 292 * NOTES 293 * On failure pgSubject will contain a NULL GUID. 294 * The handle is always preferred above the filename. 295 */ 296 BOOL WINAPI CryptSIPRetrieveSubjectGuid 297 (LPCWSTR FileName, HANDLE hFileIn, GUID *pgSubject) 298 { 299 HANDLE hFile; 300 BOOL bRet = FALSE; 301 DWORD count; 302 LARGE_INTEGER zero, oldPos; 303 /* FIXME, find out if there is a name for this GUID */ 304 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 305 static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }}; 306 static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 307 static const WORD dosHdr = IMAGE_DOS_SIGNATURE; 308 static const BYTE cabHdr[] = { 'M','S','C','F' }; 309 BYTE hdr[SIP_MAX_MAGIC_NUMBER]; 310 WCHAR szFullKey[ 0x100 ]; 311 LONG r = ERROR_SUCCESS; 312 HKEY key; 313 314 TRACE("(%s %p %p)\n", wine_dbgstr_w(FileName), hFileIn, pgSubject); 315 316 if (!pgSubject || (!FileName && !hFileIn)) 317 { 318 SetLastError(ERROR_INVALID_PARAMETER); 319 return FALSE; 320 } 321 322 /* Set pgSubject to zero's */ 323 memset(pgSubject, 0 , sizeof(GUID)); 324 325 if (hFileIn) 326 /* Use the given handle, make sure not to close this one ourselves */ 327 hFile = hFileIn; 328 else 329 { 330 hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 331 /* Last error is set by CreateFile */ 332 if (hFile == INVALID_HANDLE_VALUE) return FALSE; 333 } 334 335 zero.QuadPart = 0; 336 SetFilePointerEx(hFile, zero, &oldPos, FILE_CURRENT); 337 SetFilePointer(hFile, 0, NULL, FILE_BEGIN); 338 if (!ReadFile(hFile, hdr, sizeof(hdr), &count, NULL)) 339 goto cleanup; 340 341 if (count < SIP_MAX_MAGIC_NUMBER) 342 { 343 SetLastError(ERROR_INVALID_PARAMETER); 344 goto cleanup; 345 } 346 347 TRACE("file magic = 0x%02x%02x%02x%02x\n", hdr[0], hdr[1], hdr[2], hdr[3]); 348 /* As everything is in place now we start looking at the file header */ 349 if (!memcmp(hdr, &dosHdr, sizeof(dosHdr))) 350 { 351 *pgSubject = unknown; 352 SetLastError(S_OK); 353 bRet = TRUE; 354 goto cleanup; 355 } 356 /* Quick-n-dirty check for a cab file. */ 357 if (!memcmp(hdr, cabHdr, sizeof(cabHdr))) 358 { 359 *pgSubject = cabGUID; 360 SetLastError(S_OK); 361 bRet = TRUE; 362 goto cleanup; 363 } 364 /* If it's asn.1-encoded, it's probably a .cat file. */ 365 if (hdr[0] == 0x30) 366 { 367 DWORD fileLen = GetFileSize(hFile, NULL); 368 369 TRACE("fileLen = %d\n", fileLen); 370 /* Sanity-check length */ 371 if (hdr[1] < 0x80 && fileLen == 2 + hdr[1]) 372 { 373 *pgSubject = catGUID; 374 SetLastError(S_OK); 375 bRet = TRUE; 376 goto cleanup; 377 } 378 else if (hdr[1] == 0x80) 379 { 380 /* Indefinite length, can't verify with just the header, assume it 381 * is. 382 */ 383 *pgSubject = catGUID; 384 SetLastError(S_OK); 385 bRet = TRUE; 386 goto cleanup; 387 } 388 else 389 { 390 BYTE lenBytes = hdr[1] & 0x7f; 391 392 if (lenBytes == 1 && fileLen == 2 + lenBytes + hdr[2]) 393 { 394 *pgSubject = catGUID; 395 SetLastError(S_OK); 396 bRet = TRUE; 397 goto cleanup; 398 } 399 else if (lenBytes == 2 && fileLen == 2 + lenBytes + 400 (hdr[2] << 8 | hdr[3])) 401 { 402 *pgSubject = catGUID; 403 SetLastError(S_OK); 404 bRet = TRUE; 405 goto cleanup; 406 } 407 else if (fileLen > 0xffff) 408 { 409 /* The file size must be greater than 2 bytes in length, so 410 * assume it is a .cat file 411 */ 412 *pgSubject = catGUID; 413 SetLastError(S_OK); 414 bRet = TRUE; 415 goto cleanup; 416 } 417 } 418 } 419 420 /* Check for supported functions using CryptSIPDllIsMyFileType */ 421 /* max length of szFullKey depends on our code only, so we won't overrun */ 422 lstrcpyW(szFullKey, szOID); 423 lstrcatW(szFullKey, szIsMyFile); 424 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key); 425 if (r == ERROR_SUCCESS) 426 { 427 DWORD index = 0, size; 428 WCHAR subKeyName[MAX_PATH]; 429 430 do { 431 size = sizeof(subKeyName) / sizeof(subKeyName[0]); 432 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, 433 NULL, NULL); 434 if (r == ERROR_SUCCESS) 435 { 436 HKEY subKey; 437 438 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); 439 if (r == ERROR_SUCCESS) 440 { 441 HMODULE lib; 442 pfnIsFileSupported isMy = CRYPT_LoadSIPFuncFromKey(subKey, 443 &lib); 444 445 if (isMy) 446 { 447 bRet = isMy(hFile, pgSubject); 448 FreeLibrary(lib); 449 } 450 RegCloseKey(subKey); 451 } 452 } 453 } while (!bRet && r == ERROR_SUCCESS); 454 RegCloseKey(key); 455 } 456 457 /* Check for supported functions using CryptSIPDllIsMyFileType2 */ 458 if (!bRet) 459 { 460 lstrcpyW(szFullKey, szOID); 461 lstrcatW(szFullKey, szIsMyFile2); 462 r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &key); 463 if (r == ERROR_SUCCESS) 464 { 465 DWORD index = 0, size; 466 WCHAR subKeyName[MAX_PATH]; 467 468 do { 469 size = sizeof(subKeyName) / sizeof(subKeyName[0]); 470 r = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, 471 NULL, NULL); 472 if (r == ERROR_SUCCESS) 473 { 474 HKEY subKey; 475 476 r = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); 477 if (r == ERROR_SUCCESS) 478 { 479 HMODULE lib; 480 pfnIsFileSupportedName isMy2 = 481 CRYPT_LoadSIPFuncFromKey(subKey, &lib); 482 483 if (isMy2) 484 { 485 bRet = isMy2((LPWSTR)FileName, pgSubject); 486 FreeLibrary(lib); 487 } 488 RegCloseKey(subKey); 489 } 490 } 491 } while (!bRet && r == ERROR_SUCCESS); 492 RegCloseKey(key); 493 } 494 } 495 496 if (!bRet) 497 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN); 498 499 cleanup: 500 /* If we didn't open this one we shouldn't close it (hFile is a copy), 501 * but we should reset the file pointer to its original position. 502 */ 503 if (!hFileIn) 504 CloseHandle(hFile); 505 else 506 SetFilePointerEx(hFile, oldPos, NULL, FILE_BEGIN); 507 508 return bRet; 509 } 510 511 static LONG CRYPT_OpenSIPFunctionKey(const GUID *guid, LPCWSTR function, 512 HKEY *key) 513 { 514 WCHAR szFullKey[ 0x100 ]; 515 516 lstrcpyW(szFullKey, szOID); 517 lstrcatW(szFullKey, function); 518 CRYPT_guid2wstr(guid, &szFullKey[lstrlenW(szFullKey)]); 519 return RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, key); 520 } 521 522 /* Loads the function named function for the SIP specified by pgSubject, and 523 * returns it if found. Returns NULL on error. If the function is loaded, 524 * *pLib is set to the library in which it is found. 525 */ 526 static void *CRYPT_LoadSIPFunc(const GUID *pgSubject, LPCWSTR function, 527 HMODULE *pLib) 528 { 529 LONG r; 530 HKEY key; 531 void *func = NULL; 532 533 TRACE("(%s, %s)\n", debugstr_guid(pgSubject), debugstr_w(function)); 534 535 r = CRYPT_OpenSIPFunctionKey(pgSubject, function, &key); 536 if (!r) 537 { 538 func = CRYPT_LoadSIPFuncFromKey(key, pLib); 539 RegCloseKey(key); 540 } 541 TRACE("returning %p\n", func); 542 return func; 543 } 544 545 typedef struct _WINE_SIP_PROVIDER { 546 GUID subject; 547 SIP_DISPATCH_INFO info; 548 struct list entry; 549 } WINE_SIP_PROVIDER; 550 551 static struct list providers = { &providers, &providers }; 552 static CRITICAL_SECTION providers_cs; 553 static CRITICAL_SECTION_DEBUG providers_cs_debug = 554 { 555 0, 0, &providers_cs, 556 { &providers_cs_debug.ProcessLocksList, 557 &providers_cs_debug.ProcessLocksList }, 558 0, 0, { (DWORD_PTR)(__FILE__ ": providers_cs") } 559 }; 560 static CRITICAL_SECTION providers_cs = { &providers_cs_debug, -1, 0, 0, 0, 0 }; 561 562 static void CRYPT_CacheSIP(const GUID *pgSubject, SIP_DISPATCH_INFO *info) 563 { 564 WINE_SIP_PROVIDER *prov = CryptMemAlloc(sizeof(WINE_SIP_PROVIDER)); 565 566 if (prov) 567 { 568 prov->subject = *pgSubject; 569 prov->info = *info; 570 EnterCriticalSection(&providers_cs); 571 list_add_tail(&providers, &prov->entry); 572 LeaveCriticalSection(&providers_cs); 573 } 574 } 575 576 static WINE_SIP_PROVIDER *CRYPT_GetCachedSIP(const GUID *pgSubject) 577 { 578 WINE_SIP_PROVIDER *provider = NULL, *ret = NULL; 579 580 EnterCriticalSection(&providers_cs); 581 LIST_FOR_EACH_ENTRY(provider, &providers, WINE_SIP_PROVIDER, entry) 582 { 583 if (IsEqualGUID(pgSubject, &provider->subject)) 584 break; 585 } 586 if (provider && IsEqualGUID(pgSubject, &provider->subject)) 587 ret = provider; 588 LeaveCriticalSection(&providers_cs); 589 return ret; 590 } 591 592 static inline BOOL CRYPT_IsSIPCached(const GUID *pgSubject) 593 { 594 return CRYPT_GetCachedSIP(pgSubject) != NULL; 595 } 596 597 void crypt_sip_free(void) 598 { 599 WINE_SIP_PROVIDER *prov, *next; 600 601 LIST_FOR_EACH_ENTRY_SAFE(prov, next, &providers, WINE_SIP_PROVIDER, entry) 602 { 603 list_remove(&prov->entry); 604 FreeLibrary(prov->info.hSIP); 605 CryptMemFree(prov); 606 } 607 DeleteCriticalSection(&providers_cs); 608 } 609 610 /* Loads the SIP for pgSubject into the global cache. Returns FALSE if the 611 * SIP isn't registered or is invalid. 612 */ 613 static BOOL CRYPT_LoadSIP(const GUID *pgSubject) 614 { 615 SIP_DISPATCH_INFO sip = { 0 }; 616 HMODULE lib = NULL, temp = NULL; 617 618 sip.pfGet = CRYPT_LoadSIPFunc(pgSubject, szGetSigned, &lib); 619 if (!sip.pfGet) 620 goto error; 621 sip.pfPut = CRYPT_LoadSIPFunc(pgSubject, szPutSigned, &temp); 622 if (!sip.pfPut || temp != lib) 623 goto error; 624 FreeLibrary(temp); 625 temp = NULL; 626 sip.pfCreate = CRYPT_LoadSIPFunc(pgSubject, szCreate, &temp); 627 if (!sip.pfCreate || temp != lib) 628 goto error; 629 FreeLibrary(temp); 630 temp = NULL; 631 sip.pfVerify = CRYPT_LoadSIPFunc(pgSubject, szVerify, &temp); 632 if (!sip.pfVerify || temp != lib) 633 goto error; 634 FreeLibrary(temp); 635 temp = NULL; 636 sip.pfRemove = CRYPT_LoadSIPFunc(pgSubject, szRemoveSigned, &temp); 637 if (!sip.pfRemove || temp != lib) 638 goto error; 639 FreeLibrary(temp); 640 sip.hSIP = lib; 641 CRYPT_CacheSIP(pgSubject, &sip); 642 return TRUE; 643 644 error: 645 FreeLibrary(lib); 646 FreeLibrary(temp); 647 SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN); 648 return FALSE; 649 } 650 651 /*********************************************************************** 652 * CryptSIPLoad (CRYPT32.@) 653 * 654 * Load some internal crypt32 functions into a SIP_DISPATCH_INFO structure. 655 * 656 * PARAMS 657 * pgSubject [I] The GUID. 658 * dwFlags [I] Flags. 659 * pSipDispatch [I] The loaded functions. 660 * 661 * RETURNS 662 * Success: TRUE. pSipDispatch contains the functions. 663 * Failure: FALSE. (Look at GetLastError()). 664 * 665 * NOTES 666 * CryptSIPLoad uses caching for the list of GUIDs and whether a SIP is 667 * already loaded. 668 * 669 * An application calls CryptSipLoad which will return a structure with the 670 * function addresses of some internal crypt32 functions. The application will 671 * then call these functions which will be forwarded to the appropriate SIP. 672 * 673 * CryptSIPLoad will load the needed SIP but doesn't unload this dll. The unloading 674 * is done when crypt32 is unloaded. 675 */ 676 BOOL WINAPI CryptSIPLoad 677 (const GUID *pgSubject, DWORD dwFlags, SIP_DISPATCH_INFO *pSipDispatch) 678 { 679 TRACE("(%s %d %p)\n", debugstr_guid(pgSubject), dwFlags, pSipDispatch); 680 681 if (!pgSubject || dwFlags != 0 || !pSipDispatch) 682 { 683 SetLastError(ERROR_INVALID_PARAMETER); 684 return FALSE; 685 } 686 if (!CRYPT_IsSIPCached(pgSubject) && !CRYPT_LoadSIP(pgSubject)) 687 return FALSE; 688 689 pSipDispatch->hSIP = NULL; 690 pSipDispatch->pfGet = CryptSIPGetSignedDataMsg; 691 pSipDispatch->pfPut = CryptSIPPutSignedDataMsg; 692 pSipDispatch->pfCreate = CryptSIPCreateIndirectData; 693 pSipDispatch->pfVerify = CryptSIPVerifyIndirectData; 694 pSipDispatch->pfRemove = CryptSIPRemoveSignedDataMsg; 695 696 return TRUE; 697 } 698 699 /*********************************************************************** 700 * CryptSIPCreateIndirectData (CRYPT32.@) 701 */ 702 BOOL WINAPI CryptSIPCreateIndirectData(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pcbIndirectData, 703 SIP_INDIRECT_DATA* pIndirectData) 704 { 705 WINE_SIP_PROVIDER *sip; 706 BOOL ret = FALSE; 707 708 TRACE("(%p %p %p)\n", pSubjectInfo, pcbIndirectData, pIndirectData); 709 710 if (!pSubjectInfo || !pSubjectInfo->pgSubjectType || !pcbIndirectData) 711 { 712 SetLastError(ERROR_INVALID_PARAMETER); 713 return FALSE; 714 } 715 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 716 ret = sip->info.pfCreate(pSubjectInfo, pcbIndirectData, pIndirectData); 717 TRACE("returning %d\n", ret); 718 return ret; 719 } 720 721 /*********************************************************************** 722 * CryptSIPGetSignedDataMsg (CRYPT32.@) 723 */ 724 BOOL WINAPI CryptSIPGetSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD* pdwEncodingType, 725 DWORD dwIndex, DWORD* pcbSignedDataMsg, BYTE* pbSignedDataMsg) 726 { 727 WINE_SIP_PROVIDER *sip; 728 BOOL ret = FALSE; 729 730 TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, 731 pcbSignedDataMsg, pbSignedDataMsg); 732 733 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 734 ret = sip->info.pfGet(pSubjectInfo, pdwEncodingType, dwIndex, 735 pcbSignedDataMsg, pbSignedDataMsg); 736 TRACE("returning %d\n", ret); 737 return ret; 738 } 739 740 /*********************************************************************** 741 * CryptSIPPutSignedDataMsg (CRYPT32.@) 742 */ 743 BOOL WINAPI CryptSIPPutSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, DWORD pdwEncodingType, 744 DWORD* pdwIndex, DWORD cbSignedDataMsg, BYTE* pbSignedDataMsg) 745 { 746 WINE_SIP_PROVIDER *sip; 747 BOOL ret = FALSE; 748 749 TRACE("(%p %d %p %d %p)\n", pSubjectInfo, pdwEncodingType, pdwIndex, 750 cbSignedDataMsg, pbSignedDataMsg); 751 752 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 753 ret = sip->info.pfPut(pSubjectInfo, pdwEncodingType, pdwIndex, 754 cbSignedDataMsg, pbSignedDataMsg); 755 TRACE("returning %d\n", ret); 756 return ret; 757 } 758 759 /*********************************************************************** 760 * CryptSIPRemoveSignedDataMsg (CRYPT32.@) 761 */ 762 BOOL WINAPI CryptSIPRemoveSignedDataMsg(SIP_SUBJECTINFO* pSubjectInfo, 763 DWORD dwIndex) 764 { 765 WINE_SIP_PROVIDER *sip; 766 BOOL ret = FALSE; 767 768 TRACE("(%p %d)\n", pSubjectInfo, dwIndex); 769 770 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 771 ret = sip->info.pfRemove(pSubjectInfo, dwIndex); 772 TRACE("returning %d\n", ret); 773 return ret; 774 } 775 776 /*********************************************************************** 777 * CryptSIPVerifyIndirectData (CRYPT32.@) 778 */ 779 BOOL WINAPI CryptSIPVerifyIndirectData(SIP_SUBJECTINFO* pSubjectInfo, 780 SIP_INDIRECT_DATA* pIndirectData) 781 { 782 WINE_SIP_PROVIDER *sip; 783 BOOL ret = FALSE; 784 785 TRACE("(%p %p)\n", pSubjectInfo, pIndirectData); 786 787 if ((sip = CRYPT_GetCachedSIP(pSubjectInfo->pgSubjectType))) 788 ret = sip->info.pfVerify(pSubjectInfo, pIndirectData); 789 TRACE("returning %d\n", ret); 790 return ret; 791 } 792