source: trunk/src/crypt32/sip.c@ 22020

Last change on this file since 22020 was 22020, checked in by dmik, 13 years ago

Disable debug fields of RTL_CRITICAL_SECTION_DEBUG.

Odin uses the DebugInfo ptr in CRITICAL_SECTION for its own purposes
which are incompatible with NT. For this reason any NT-style usage must
be disabled.

This in particular fixes debug assertions and crashes in CRYPT32.DLL (due to
misinterpretation of the structure fields) which happened e.g. during playback of
some Flash content.

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