push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / wintrust / wintrust_main.c
blobc5b1612d93bdc51c70a940e1de6f2d8a50e5e1dc
1 /*
2 * Copyright 2001 Rein Klazes
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
22 #include <stdarg.h>
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "winreg.h"
30 #include "guiddef.h"
31 #include "wintrust.h"
32 #include "softpub.h"
33 #include "mscat.h"
34 #include "objbase.h"
35 #include "winuser.h"
36 #include "wintrust_priv.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
42 /***********************************************************************
43 * DllMain (WINTRUST.@)
45 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
47 switch(reason)
49 case DLL_PROCESS_ATTACH:
50 DisableThreadLibraryCalls( inst );
51 break;
53 return TRUE;
56 /***********************************************************************
57 * TrustIsCertificateSelfSigned (WINTRUST.@)
59 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
61 BOOL ret;
63 TRACE("%p\n", cert);
64 ret = CertCompareCertificateName(cert->dwCertEncodingType,
65 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
66 return ret;
69 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
70 WINTRUST_DATA *data)
72 DWORD err = ERROR_SUCCESS;
73 CRYPT_PROVIDER_DATA *provData;
74 BOOL ret;
76 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
78 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
79 if (!provData)
80 goto oom;
81 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
83 provData->padwTrustStepErrors =
84 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
85 if (!provData->padwTrustStepErrors)
86 goto oom;
87 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
89 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
90 if (!provData->u.pPDSip)
91 goto oom;
92 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
94 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
95 if (!provData->psPfns)
96 goto oom;
97 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
98 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
99 if (!ret)
101 err = GetLastError();
102 goto error;
105 data->hWVTStateData = (HANDLE)provData;
106 provData->pWintrustData = data;
107 if (hwnd == INVALID_HANDLE_VALUE)
108 provData->hWndParent = GetDesktopWindow();
109 else
110 provData->hWndParent = hwnd;
111 provData->pgActionID = actionID;
112 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
114 err = provData->psPfns->pfnInitialize(provData);
115 if (err)
116 goto done;
117 err = provData->psPfns->pfnObjectTrust(provData);
118 if (err)
119 goto done;
120 err = provData->psPfns->pfnSignatureTrust(provData);
121 if (err)
122 goto done;
123 err = provData->psPfns->pfnCertificateTrust(provData);
124 if (err)
125 goto done;
126 err = provData->psPfns->pfnFinalPolicy(provData);
127 goto done;
129 oom:
130 err = ERROR_OUTOFMEMORY;
131 error:
132 if (provData)
134 WINTRUST_Free(provData->padwTrustStepErrors);
135 WINTRUST_Free(provData->u.pPDSip);
136 WINTRUST_Free(provData->psPfns);
137 WINTRUST_Free(provData);
139 done:
140 TRACE("returning %08x\n", err);
141 return err;
144 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
145 WINTRUST_DATA *data)
147 DWORD err = ERROR_SUCCESS;
148 CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
150 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
152 if (provData)
154 if (provData->psPfns->pfnCleanupPolicy)
155 err = provData->psPfns->pfnCleanupPolicy(provData);
157 WINTRUST_Free(provData->padwTrustStepErrors);
158 WINTRUST_Free(provData->u.pPDSip);
159 WINTRUST_Free(provData->psPfns);
160 WINTRUST_Free(provData);
161 data->hWVTStateData = NULL;
163 TRACE("returning %08x\n", err);
164 return err;
167 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
168 WINTRUST_DATA *data)
170 LONG err;
172 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
174 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
175 WINTRUST_DefaultClose(hwnd, actionID, data);
176 TRACE("returning %08x\n", err);
177 return err;
180 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
181 WINTRUST_DATA *data)
183 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
184 /* Undocumented: the published software action is passed a path,
185 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
187 LPCWSTR path = (LPCWSTR)data->u.pFile;
188 LPWIN_TRUST_SUBJECT_FILE subjectFile =
189 (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
190 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
192 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
193 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
194 fileInfo.pcwszFilePath = path;
195 fileInfo.hFile = subjectFile->hFile;
196 wintrust_data.u.pFile = &fileInfo;
197 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
198 wintrust_data.dwUIChoice = WTD_UI_NONE;
200 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
203 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
205 TRACE("%p\n", pFile);
206 if (pFile)
208 TRACE("cbStruct: %d\n", pFile->cbStruct);
209 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
210 TRACE("hFile: %p\n", pFile->hFile);
211 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
215 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
217 TRACE("%p\n", catalog);
218 if (catalog)
220 TRACE("cbStruct: %d\n", catalog->cbStruct);
221 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
222 TRACE("pcwszCatalogFilePath: %s\n",
223 debugstr_w(catalog->pcwszCatalogFilePath));
224 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
225 TRACE("pcwszMemberFilePath: %s\n",
226 debugstr_w(catalog->pcwszMemberFilePath));
227 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
228 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
229 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
230 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
234 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
236 TRACE("%p\n", blob);
237 if (blob)
239 TRACE("cbStruct: %d\n", blob->cbStruct);
240 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
241 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
242 TRACE("cbMemObject: %d\n", blob->cbMemObject);
243 TRACE("pbMemObject: %p\n", blob->pbMemObject);
244 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
245 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
249 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
251 TRACE("%p\n", sgnr);
252 if (sgnr)
254 TRACE("cbStruct: %d\n", sgnr->cbStruct);
255 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
256 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
257 TRACE("chStores: %d\n", sgnr->chStores);
261 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
263 TRACE("%p\n", cert);
264 if (cert)
266 TRACE("cbStruct: %d\n", cert->cbStruct);
267 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
268 TRACE("psCertContext: %p\n", cert->psCertContext);
269 TRACE("chStores: %d\n", cert->chStores);
270 TRACE("dwFlags: %08x\n", cert->dwFlags);
271 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
275 static void dump_wintrust_data(WINTRUST_DATA *data)
277 TRACE("%p\n", data);
278 if (data)
280 TRACE("cbStruct: %d\n", data->cbStruct);
281 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
282 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
283 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
284 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
285 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
286 switch (data->dwUnionChoice)
288 case WTD_CHOICE_FILE:
289 dump_file_info(data->u.pFile);
290 break;
291 case WTD_CHOICE_CATALOG:
292 dump_catalog_info(data->u.pCatalog);
293 break;
294 case WTD_CHOICE_BLOB:
295 dump_blob_info(data->u.pBlob);
296 break;
297 case WTD_CHOICE_SIGNER:
298 dump_sgnr_info(data->u.pSgnr);
299 break;
300 case WTD_CHOICE_CERT:
301 dump_cert_info(data->u.pCert);
302 break;
304 TRACE("dwStateAction: %d\n", data->dwStateAction);
305 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
306 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
307 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
308 TRACE("dwUIContext: %d\n", data->dwUIContext);
312 /***********************************************************************
313 * WinVerifyTrust (WINTRUST.@)
315 * Verifies an object by calling the specified trust provider.
317 * PARAMS
318 * hwnd [I] Handle to a caller window.
319 * ActionID [I] Pointer to a GUID that identifies the action to perform.
320 * ActionData [I] Information used by the trust provider to verify the object.
322 * RETURNS
323 * Success: Zero.
324 * Failure: A TRUST_E_* error code.
326 * NOTES
327 * Trust providers can be found at:
328 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
330 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
332 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
333 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
334 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
335 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
336 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
337 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
338 LONG err = ERROR_SUCCESS;
339 WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
341 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
342 dump_wintrust_data(ActionData);
344 /* Support for known old-style callers: */
345 if (IsEqualGUID(ActionID, &published_software))
346 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
347 else
349 /* Check known actions to warn of possible problems */
350 if (!IsEqualGUID(ActionID, &unknown) &&
351 !IsEqualGUID(ActionID, &generic_verify_v2) &&
352 !IsEqualGUID(ActionID, &generic_cert_verify) &&
353 !IsEqualGUID(ActionID, &generic_chain_verify))
354 WARN("unknown action %s, default behavior may not be right\n",
355 debugstr_guid(ActionID));
356 switch (actionData->dwStateAction)
358 case WTD_STATEACTION_IGNORE:
359 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
360 break;
361 case WTD_STATEACTION_VERIFY:
362 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
363 break;
364 case WTD_STATEACTION_CLOSE:
365 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
366 break;
367 default:
368 FIXME("unimplemented for %d\n", actionData->dwStateAction);
372 TRACE("returning %08x\n", err);
373 return err;
376 /***********************************************************************
377 * WinVerifyTrustEx (WINTRUST.@)
379 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
380 WINTRUST_DATA* ActionData )
382 return WinVerifyTrust(hwnd, ActionID, ActionData);
385 /***********************************************************************
386 * WTHelperGetProvSignerFromChain (WINTRUST.@)
388 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
389 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
390 DWORD idxCounterSigner)
392 CRYPT_PROVIDER_SGNR *sgnr;
394 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
395 idxCounterSigner);
397 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
398 return NULL;
399 sgnr = &pProvData->pasSigners[idxSigner];
400 if (fCounterSigner)
402 if (idxCounterSigner >= sgnr->csCounterSigners ||
403 !sgnr->pasCounterSigners)
404 return NULL;
405 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
407 TRACE("returning %p\n", sgnr);
408 return sgnr;
411 /***********************************************************************
412 * WTHelperGetProvCertFromChain (WINTRUST.@)
414 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
415 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
417 CRYPT_PROVIDER_CERT *cert;
419 TRACE("(%p %d)\n", pSgnr, idxCert);
421 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
422 return NULL;
423 cert = &pSgnr->pasCertChain[idxCert];
424 TRACE("returning %p\n", cert);
425 return cert;
428 /***********************************************************************
429 * WTHelperProvDataFromStateData (WINTRUST.@)
431 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
433 TRACE("%p\n", hStateData);
434 return (CRYPT_PROVIDER_DATA *)hStateData;
437 /***********************************************************************
438 * WTHelperGetFileName(WINTRUST.@)
440 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
442 TRACE("%p\n",data);
443 if (data->dwUnionChoice == WTD_CHOICE_FILE)
444 return data->u.pFile->pcwszFilePath;
445 else
446 return NULL;
449 /***********************************************************************
450 * WTHelperGetFileHandle(WINTRUST.@)
452 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
454 TRACE("%p\n",data);
455 if (data->dwUnionChoice == WTD_CHOICE_FILE)
456 return data->u.pFile->hFile;
457 else
458 return INVALID_HANDLE_VALUE;
461 static const WCHAR Software_Publishing[] = {
462 'S','o','f','t','w','a','r','e','\\',
463 'M','i','c','r','o','s','o','f','t','\\',
464 'W','i','n','d','o','w','s','\\',
465 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
466 'W','i','n','t','r','u','s','t','\\',
467 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
468 'S','o','f','t','w','a','r','e',' ',
469 'P','u','b','l','i','s','h','i','n','g',0 };
470 static const WCHAR State[] = { 'S','t','a','t','e',0 };
472 /***********************************************************************
473 * WintrustGetRegPolicyFlags (WINTRUST.@)
475 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
477 HKEY key;
478 LONG r;
480 TRACE("%p\n", pdwPolicyFlags);
482 *pdwPolicyFlags = 0;
483 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
484 KEY_READ, NULL, &key, NULL);
485 if (!r)
487 DWORD size = sizeof(DWORD);
489 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
490 &size);
491 RegCloseKey(key);
492 if (r)
494 /* Failed to query, create and return default value */
495 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
496 WTPF_OFFLINEOKNBU_COM |
497 WTPF_OFFLINEOKNBU_IND |
498 WTPF_OFFLINEOK_COM |
499 WTPF_OFFLINEOK_IND;
500 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
505 /***********************************************************************
506 * WintrustSetRegPolicyFlags (WINTRUST.@)
508 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
510 HKEY key;
511 LONG r;
513 TRACE("%x\n", dwPolicyFlags);
515 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
516 NULL, 0, KEY_WRITE, NULL, &key, NULL);
517 if (!r)
519 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
520 sizeof(DWORD));
521 RegCloseKey(key);
523 if (r) SetLastError(r);
524 return r == ERROR_SUCCESS;
527 /* Utility functions */
528 void * WINAPI WINTRUST_Alloc(DWORD cb)
530 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
533 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
535 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
538 void WINAPI WINTRUST_Free(void *p)
540 HeapFree(GetProcessHeap(), 0, p);
543 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
545 BOOL ret = FALSE;
547 if (data->chStores)
548 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
549 (data->chStores + 1) * sizeof(HCERTSTORE));
550 else
552 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
553 data->chStores = 0;
555 if (data->pahStores)
557 data->pahStores[data->chStores++] = CertDuplicateStore(store);
558 ret = TRUE;
560 else
561 SetLastError(ERROR_OUTOFMEMORY);
562 return ret;
565 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
566 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
568 BOOL ret = FALSE;
570 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
572 SetLastError(ERROR_INVALID_PARAMETER);
573 return FALSE;
575 if (fCounterSigner)
577 FIXME("unimplemented for counter signers\n");
578 SetLastError(ERROR_INVALID_PARAMETER);
579 return FALSE;
581 if (data->csSigners)
582 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
583 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
584 else
586 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
587 data->csSigners = 0;
589 if (data->pasSigners)
591 if (idxSigner < data->csSigners)
592 memmove(&data->pasSigners[idxSigner],
593 &data->pasSigners[idxSigner + 1],
594 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
595 ret = TRUE;
596 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
598 /* The PSDK says psSigner should be allocated using pfnAlloc, but
599 * it doesn't say anything about ownership. Since callers are
600 * internal, assume ownership is passed, and just store the
601 * pointer.
603 memcpy(&data->pasSigners[idxSigner], sgnr,
604 sizeof(CRYPT_PROVIDER_SGNR));
606 else
607 memset(&data->pasSigners[idxSigner], 0,
608 sizeof(CRYPT_PROVIDER_SGNR));
609 data->csSigners++;
611 else
612 SetLastError(ERROR_OUTOFMEMORY);
613 return ret;
616 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
617 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
619 BOOL ret = FALSE;
621 if (fCounterSigner)
623 FIXME("unimplemented for counter signers\n");
624 SetLastError(ERROR_INVALID_PARAMETER);
625 return FALSE;
627 if (data->pasSigners[idxSigner].csCertChain)
628 data->pasSigners[idxSigner].pasCertChain =
629 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
630 (data->pasSigners[idxSigner].csCertChain + 1) *
631 sizeof(CRYPT_PROVIDER_CERT));
632 else
634 data->pasSigners[idxSigner].pasCertChain =
635 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
636 data->pasSigners[idxSigner].csCertChain = 0;
638 if (data->pasSigners[idxSigner].pasCertChain)
640 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
641 data->pasSigners[idxSigner].csCertChain];
643 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
644 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
645 data->pasSigners[idxSigner].csCertChain++;
646 ret = TRUE;
648 else
649 SetLastError(ERROR_OUTOFMEMORY);
650 return ret;