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
24 #define NONAMELESSUNION
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 )
49 case DLL_PROCESS_ATTACH:
50 DisableThreadLibraryCalls( inst );
56 /***********************************************************************
57 * TrustIsCertificateSelfSigned (WINTRUST.@)
59 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
64 ret = CertCompareCertificateName(cert->dwCertEncodingType,
65 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
69 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
73 wintrust_step_func func;
77 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
78 DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
80 DWORD i, err = ERROR_SUCCESS;
82 for (i = 0; !err && i < numSteps; i++)
84 err = steps[i].func(provData);
86 err = provData->padwTrustStepErrors[steps[i].error_index];
91 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
94 DWORD err = ERROR_SUCCESS, numSteps = 0;
95 CRYPT_PROVIDER_DATA *provData;
97 struct wintrust_step verifySteps[5];
99 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
101 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
104 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
106 provData->padwTrustStepErrors =
107 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
108 if (!provData->padwTrustStepErrors)
110 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
112 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
113 if (!provData->u.pPDSip)
115 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
117 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
118 if (!provData->psPfns)
120 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
121 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
124 err = GetLastError();
128 data->hWVTStateData = (HANDLE)provData;
129 provData->pWintrustData = data;
130 if (hwnd == INVALID_HANDLE_VALUE)
131 provData->hWndParent = GetDesktopWindow();
133 provData->hWndParent = hwnd;
134 provData->pgActionID = actionID;
135 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
137 if (provData->psPfns->pfnInitialize)
139 verifySteps[numSteps].func = provData->psPfns->pfnInitialize;
140 verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
142 if (provData->psPfns->pfnObjectTrust)
144 verifySteps[numSteps].func = provData->psPfns->pfnObjectTrust;
145 verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
147 if (provData->psPfns->pfnSignatureTrust)
149 verifySteps[numSteps].func = provData->psPfns->pfnSignatureTrust;
150 verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
152 if (provData->psPfns->pfnCertificateTrust)
154 verifySteps[numSteps].func = provData->psPfns->pfnCertificateTrust;
155 verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
157 if (provData->psPfns->pfnFinalPolicy)
159 verifySteps[numSteps].func = provData->psPfns->pfnFinalPolicy;
160 verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
162 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
166 err = ERROR_OUTOFMEMORY;
170 WINTRUST_Free(provData->padwTrustStepErrors);
171 WINTRUST_Free(provData->u.pPDSip);
172 WINTRUST_Free(provData->psPfns);
173 WINTRUST_Free(provData);
176 TRACE("returning %08x\n", err);
180 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
183 DWORD err = ERROR_SUCCESS;
184 CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
186 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
190 if (provData->psPfns->pfnCleanupPolicy)
191 err = provData->psPfns->pfnCleanupPolicy(provData);
193 WINTRUST_Free(provData->padwTrustStepErrors);
194 WINTRUST_Free(provData->u.pPDSip);
195 WINTRUST_Free(provData->psPfns);
196 WINTRUST_Free(provData);
197 data->hWVTStateData = NULL;
199 TRACE("returning %08x\n", err);
203 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
208 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
210 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
211 WINTRUST_DefaultClose(hwnd, actionID, data);
212 TRACE("returning %08x\n", err);
216 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
219 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
220 /* Undocumented: the published software action is passed a path,
221 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
223 LPWIN_TRUST_SUBJECT_FILE subjectFile =
224 (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
225 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
227 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
228 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
229 fileInfo.pcwszFilePath = subjectFile->lpPath;
230 fileInfo.hFile = subjectFile->hFile;
231 wintrust_data.u.pFile = &fileInfo;
232 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
233 wintrust_data.dwUIChoice = WTD_UI_NONE;
235 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
238 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
240 TRACE("%p\n", pFile);
243 TRACE("cbStruct: %d\n", pFile->cbStruct);
244 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
245 TRACE("hFile: %p\n", pFile->hFile);
246 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
250 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
252 TRACE("%p\n", catalog);
255 TRACE("cbStruct: %d\n", catalog->cbStruct);
256 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
257 TRACE("pcwszCatalogFilePath: %s\n",
258 debugstr_w(catalog->pcwszCatalogFilePath));
259 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
260 TRACE("pcwszMemberFilePath: %s\n",
261 debugstr_w(catalog->pcwszMemberFilePath));
262 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
263 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
264 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
265 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
269 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
274 TRACE("cbStruct: %d\n", blob->cbStruct);
275 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
276 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
277 TRACE("cbMemObject: %d\n", blob->cbMemObject);
278 TRACE("pbMemObject: %p\n", blob->pbMemObject);
279 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
280 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
284 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
289 TRACE("cbStruct: %d\n", sgnr->cbStruct);
290 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
291 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
292 TRACE("chStores: %d\n", sgnr->chStores);
296 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
301 TRACE("cbStruct: %d\n", cert->cbStruct);
302 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
303 TRACE("psCertContext: %p\n", cert->psCertContext);
304 TRACE("chStores: %d\n", cert->chStores);
305 TRACE("dwFlags: %08x\n", cert->dwFlags);
306 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
310 static void dump_wintrust_data(WINTRUST_DATA *data)
315 TRACE("cbStruct: %d\n", data->cbStruct);
316 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
317 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
318 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
319 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
320 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
321 switch (data->dwUnionChoice)
323 case WTD_CHOICE_FILE:
324 dump_file_info(data->u.pFile);
326 case WTD_CHOICE_CATALOG:
327 dump_catalog_info(data->u.pCatalog);
329 case WTD_CHOICE_BLOB:
330 dump_blob_info(data->u.pBlob);
332 case WTD_CHOICE_SIGNER:
333 dump_sgnr_info(data->u.pSgnr);
335 case WTD_CHOICE_CERT:
336 dump_cert_info(data->u.pCert);
339 TRACE("dwStateAction: %d\n", data->dwStateAction);
340 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
341 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
342 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
343 TRACE("dwUIContext: %d\n", data->dwUIContext);
347 /***********************************************************************
348 * WinVerifyTrust (WINTRUST.@)
350 * Verifies an object by calling the specified trust provider.
353 * hwnd [I] Handle to a caller window.
354 * ActionID [I] Pointer to a GUID that identifies the action to perform.
355 * ActionData [I] Information used by the trust provider to verify the object.
359 * Failure: A TRUST_E_* error code.
362 * Trust providers can be found at:
363 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
365 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
367 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
368 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
369 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
370 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
371 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
372 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
373 LONG err = ERROR_SUCCESS;
374 WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
376 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
377 dump_wintrust_data(ActionData);
379 /* Support for known old-style callers: */
380 if (IsEqualGUID(ActionID, &published_software))
381 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
384 /* Check known actions to warn of possible problems */
385 if (!IsEqualGUID(ActionID, &unknown) &&
386 !IsEqualGUID(ActionID, &generic_verify_v2) &&
387 !IsEqualGUID(ActionID, &generic_cert_verify) &&
388 !IsEqualGUID(ActionID, &generic_chain_verify))
389 WARN("unknown action %s, default behavior may not be right\n",
390 debugstr_guid(ActionID));
391 switch (actionData->dwStateAction)
393 case WTD_STATEACTION_IGNORE:
394 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
396 case WTD_STATEACTION_VERIFY:
397 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
399 case WTD_STATEACTION_CLOSE:
400 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
403 FIXME("unimplemented for %d\n", actionData->dwStateAction);
407 TRACE("returning %08x\n", err);
411 /***********************************************************************
412 * WinVerifyTrustEx (WINTRUST.@)
414 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
415 WINTRUST_DATA* ActionData )
417 return WinVerifyTrust(hwnd, ActionID, ActionData);
420 /***********************************************************************
421 * WTHelperGetProvSignerFromChain (WINTRUST.@)
423 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
424 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
425 DWORD idxCounterSigner)
427 CRYPT_PROVIDER_SGNR *sgnr;
429 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
432 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
434 sgnr = &pProvData->pasSigners[idxSigner];
437 if (idxCounterSigner >= sgnr->csCounterSigners ||
438 !sgnr->pasCounterSigners)
440 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
442 TRACE("returning %p\n", sgnr);
446 /***********************************************************************
447 * WTHelperGetProvCertFromChain (WINTRUST.@)
449 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
450 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
452 CRYPT_PROVIDER_CERT *cert;
454 TRACE("(%p %d)\n", pSgnr, idxCert);
456 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
458 cert = &pSgnr->pasCertChain[idxCert];
459 TRACE("returning %p\n", cert);
463 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
464 CRYPT_PROVIDER_DATA* pProvData,
467 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
470 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
472 for (i = 0; i < pProvData->csProvPrivData; i++)
473 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
475 privdata = &pProvData->pasProvPrivData[i];
482 /***********************************************************************
483 * WTHelperProvDataFromStateData (WINTRUST.@)
485 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
487 TRACE("%p\n", hStateData);
488 return (CRYPT_PROVIDER_DATA *)hStateData;
491 /***********************************************************************
492 * WTHelperGetFileName(WINTRUST.@)
494 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
497 if (data->dwUnionChoice == WTD_CHOICE_FILE)
498 return data->u.pFile->pcwszFilePath;
503 /***********************************************************************
504 * WTHelperGetFileHandle(WINTRUST.@)
506 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
509 if (data->dwUnionChoice == WTD_CHOICE_FILE)
510 return data->u.pFile->hFile;
512 return INVALID_HANDLE_VALUE;
515 static const WCHAR Software_Publishing[] = {
516 'S','o','f','t','w','a','r','e','\\',
517 'M','i','c','r','o','s','o','f','t','\\',
518 'W','i','n','d','o','w','s','\\',
519 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
520 'W','i','n','t','r','u','s','t','\\',
521 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
522 'S','o','f','t','w','a','r','e',' ',
523 'P','u','b','l','i','s','h','i','n','g',0 };
524 static const WCHAR State[] = { 'S','t','a','t','e',0 };
526 /***********************************************************************
527 * WintrustGetRegPolicyFlags (WINTRUST.@)
529 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
534 TRACE("%p\n", pdwPolicyFlags);
537 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
538 KEY_READ, NULL, &key, NULL);
541 DWORD size = sizeof(DWORD);
543 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
548 /* Failed to query, create and return default value */
549 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
550 WTPF_OFFLINEOKNBU_COM |
551 WTPF_OFFLINEOKNBU_IND |
554 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
559 /***********************************************************************
560 * WintrustSetRegPolicyFlags (WINTRUST.@)
562 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
567 TRACE("%x\n", dwPolicyFlags);
569 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
570 NULL, 0, KEY_WRITE, NULL, &key, NULL);
573 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
577 if (r) SetLastError(r);
578 return r == ERROR_SUCCESS;
581 /* Utility functions */
582 void * WINAPI WINTRUST_Alloc(DWORD cb)
584 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
587 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
589 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
592 void WINAPI WINTRUST_Free(void *p)
594 HeapFree(GetProcessHeap(), 0, p);
597 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
602 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
603 (data->chStores + 1) * sizeof(HCERTSTORE));
606 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
611 data->pahStores[data->chStores++] = CertDuplicateStore(store);
615 SetLastError(ERROR_OUTOFMEMORY);
619 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
620 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
624 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
626 SetLastError(ERROR_INVALID_PARAMETER);
631 FIXME("unimplemented for counter signers\n");
632 SetLastError(ERROR_INVALID_PARAMETER);
636 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
637 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
640 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
643 if (data->pasSigners)
645 if (idxSigner < data->csSigners)
646 memmove(&data->pasSigners[idxSigner],
647 &data->pasSigners[idxSigner + 1],
648 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
650 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
652 /* The PSDK says psSigner should be allocated using pfnAlloc, but
653 * it doesn't say anything about ownership. Since callers are
654 * internal, assume ownership is passed, and just store the
657 memcpy(&data->pasSigners[idxSigner], sgnr,
658 sizeof(CRYPT_PROVIDER_SGNR));
661 memset(&data->pasSigners[idxSigner], 0,
662 sizeof(CRYPT_PROVIDER_SGNR));
666 SetLastError(ERROR_OUTOFMEMORY);
670 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
671 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
677 FIXME("unimplemented for counter signers\n");
678 SetLastError(ERROR_INVALID_PARAMETER);
681 if (data->pasSigners[idxSigner].csCertChain)
682 data->pasSigners[idxSigner].pasCertChain =
683 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
684 (data->pasSigners[idxSigner].csCertChain + 1) *
685 sizeof(CRYPT_PROVIDER_CERT));
688 data->pasSigners[idxSigner].pasCertChain =
689 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
690 data->pasSigners[idxSigner].csCertChain = 0;
692 if (data->pasSigners[idxSigner].pasCertChain)
694 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
695 data->pasSigners[idxSigner].csCertChain];
697 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
698 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
699 data->pasSigners[idxSigner].csCertChain++;
703 SetLastError(ERROR_OUTOFMEMORY);
707 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
708 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
712 TRACE("(%p, %p)\n", data, pPrivData2Add);
714 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
716 SetLastError(ERROR_INVALID_PARAMETER);
717 WARN("invalid struct size\n");
720 if (data->csProvPrivData)
721 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
722 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
725 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
726 data->csProvPrivData = 0;
728 if (data->pasProvPrivData)
732 for (i = 0; i < data->csProvPrivData; i++)
733 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
736 data->pasProvPrivData[i] = *pPrivData2Add;
737 if (i == data->csProvPrivData)
738 data->csProvPrivData++;
741 SetLastError(ERROR_OUTOFMEMORY);