crypt32: Fix another test on Win9x.
[wine/wine-gecko.git] / dlls / wintrust / wintrust_main.c
blobfa4da16434ce277fa7fe02e65699214ebd4b2a45
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 "cryptdlg.h"
37 #include "cryptuiapi.h"
38 #include "wintrust_priv.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
44 /* Utility functions */
45 void * WINAPI WINTRUST_Alloc(DWORD cb)
47 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
50 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb) __WINE_ALLOC_SIZE(2);
51 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb)
53 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
56 void WINAPI WINTRUST_Free(void *p)
58 HeapFree(GetProcessHeap(), 0, p);
61 /***********************************************************************
62 * DllMain (WINTRUST.@)
64 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
66 switch(reason)
68 case DLL_PROCESS_ATTACH:
69 DisableThreadLibraryCalls( inst );
70 break;
72 return TRUE;
75 /***********************************************************************
76 * TrustIsCertificateSelfSigned (WINTRUST.@)
78 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
80 BOOL ret;
82 TRACE("%p\n", cert);
83 ret = CertCompareCertificateName(cert->dwCertEncodingType,
84 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
85 return ret;
88 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
90 struct wintrust_step
92 wintrust_step_func func;
93 DWORD error_index;
96 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
97 DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
99 DWORD i, err = ERROR_SUCCESS;
101 for (i = 0; !err && i < numSteps; i++)
103 err = steps[i].func(provData);
104 if (err)
105 err = provData->padwTrustStepErrors[steps[i].error_index];
107 return err;
110 static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
112 CRYPT_PROVIDER_DATA *provData;
114 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
115 if (!provData)
116 goto oom;
117 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
119 provData->padwTrustStepErrors =
120 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
121 if (!provData->padwTrustStepErrors)
122 goto oom;
123 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
125 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
126 if (!provData->u.pPDSip)
127 goto oom;
128 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
130 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
131 if (!provData->psPfns)
132 goto oom;
133 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
134 return provData;
136 oom:
137 if (provData)
139 WINTRUST_Free(provData->padwTrustStepErrors);
140 WINTRUST_Free(provData->u.pPDSip);
141 WINTRUST_Free(provData->psPfns);
142 WINTRUST_Free(provData);
144 return NULL;
147 /* Adds trust steps for each function in psPfns. Assumes steps has at least
148 * 5 entries. Returns the number of steps added.
150 static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
151 const CRYPT_PROVIDER_FUNCTIONS *psPfns)
153 DWORD numSteps = 0;
155 if (psPfns->pfnInitialize)
157 steps[numSteps].func = psPfns->pfnInitialize;
158 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
160 if (psPfns->pfnObjectTrust)
162 steps[numSteps].func = psPfns->pfnObjectTrust;
163 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
165 if (psPfns->pfnSignatureTrust)
167 steps[numSteps].func = psPfns->pfnSignatureTrust;
168 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
170 if (psPfns->pfnCertificateTrust)
172 steps[numSteps].func = psPfns->pfnCertificateTrust;
173 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
175 if (psPfns->pfnFinalPolicy)
177 steps[numSteps].func = psPfns->pfnFinalPolicy;
178 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
180 return numSteps;
183 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
184 WINTRUST_DATA *data)
186 DWORD err = ERROR_SUCCESS, numSteps = 0;
187 CRYPT_PROVIDER_DATA *provData;
188 BOOL ret;
189 struct wintrust_step verifySteps[5];
191 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
193 provData = WINTRUST_AllocateProviderData();
194 if (!provData)
195 return ERROR_OUTOFMEMORY;
197 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
198 if (!ret)
200 err = GetLastError();
201 goto error;
204 data->hWVTStateData = provData;
205 provData->pWintrustData = data;
206 if (hwnd == INVALID_HANDLE_VALUE)
207 provData->hWndParent = GetDesktopWindow();
208 else
209 provData->hWndParent = hwnd;
210 provData->pgActionID = actionID;
211 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
213 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
214 provData->psPfns);
215 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
216 goto done;
218 error:
219 if (provData)
221 WINTRUST_Free(provData->padwTrustStepErrors);
222 WINTRUST_Free(provData->u.pPDSip);
223 WINTRUST_Free(provData->psPfns);
224 WINTRUST_Free(provData);
226 done:
227 TRACE("returning %08x\n", err);
228 return err;
231 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
232 WINTRUST_DATA *data)
234 DWORD err = ERROR_SUCCESS;
235 CRYPT_PROVIDER_DATA *provData = data->hWVTStateData;
237 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
239 if (provData)
241 if (provData->psPfns->pfnCleanupPolicy)
242 err = provData->psPfns->pfnCleanupPolicy(provData);
244 WINTRUST_Free(provData->padwTrustStepErrors);
245 WINTRUST_Free(provData->u.pPDSip);
246 WINTRUST_Free(provData->psPfns);
247 WINTRUST_Free(provData);
248 data->hWVTStateData = NULL;
250 TRACE("returning %08x\n", err);
251 return err;
254 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
255 WINTRUST_DATA *data)
257 LONG err;
259 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
261 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
262 WINTRUST_DefaultClose(hwnd, actionID, data);
263 TRACE("returning %08x\n", err);
264 return err;
267 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
268 WINTRUST_DATA *data)
270 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
271 /* Undocumented: the published software action is passed a path,
272 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
274 LPWIN_TRUST_SUBJECT_FILE subjectFile = data->pSIPClientData;
275 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
277 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
278 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
279 fileInfo.pcwszFilePath = subjectFile->lpPath;
280 fileInfo.hFile = subjectFile->hFile;
281 wintrust_data.u.pFile = &fileInfo;
282 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
283 wintrust_data.dwUIChoice = WTD_UI_NONE;
285 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
288 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
289 * action is not stored in the registry and is located in wintrust, not in
290 * cryptdlg along with the rest of the implementation (verified by running the
291 * action with a native wintrust.dll.)
293 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
295 BOOL ret;
297 TRACE("(%p)\n", data);
299 if (!data->padwTrustStepErrors)
300 return S_FALSE;
302 switch (data->pWintrustData->dwUnionChoice)
304 case WTD_CHOICE_BLOB:
305 if (data->pWintrustData->u.pBlob &&
306 data->pWintrustData->u.pBlob->cbStruct == sizeof(WINTRUST_BLOB_INFO) &&
307 data->pWintrustData->u.pBlob->cbMemObject ==
308 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
309 data->pWintrustData->u.pBlob->pbMemObject)
311 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
312 (CERT_VERIFY_CERTIFICATE_TRUST *)
313 data->pWintrustData->u.pBlob->pbMemObject;
315 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
316 pCert->pccert)
318 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
319 DWORD i;
320 SYSTEMTIME sysTime;
322 /* Add a signer with nothing but the time to verify, so we can
323 * add a cert to it
325 GetSystemTime(&sysTime);
326 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
327 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
328 if (!ret)
329 goto error;
330 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
331 pCert->pccert);
332 if (!ret)
333 goto error;
334 for (i = 0; ret && i < pCert->cRootStores; i++)
335 ret = data->psPfns->pfnAddStore2Chain(data,
336 pCert->rghstoreRoots[i]);
337 for (i = 0; ret && i < pCert->cStores; i++)
338 ret = data->psPfns->pfnAddStore2Chain(data,
339 pCert->rghstoreCAs[i]);
340 for (i = 0; ret && i < pCert->cTrustStores; i++)
341 ret = data->psPfns->pfnAddStore2Chain(data,
342 pCert->rghstoreTrust[i]);
344 else
346 SetLastError(ERROR_INVALID_PARAMETER);
347 ret = FALSE;
350 else
352 SetLastError(ERROR_INVALID_PARAMETER);
353 ret = FALSE;
355 break;
356 default:
357 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
358 SetLastError(ERROR_INVALID_PARAMETER);
359 ret = FALSE;
362 error:
363 if (!ret)
364 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
365 GetLastError();
366 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
367 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
368 return ret ? S_OK : S_FALSE;
371 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
372 WINTRUST_DATA *data)
374 DWORD err = ERROR_SUCCESS, numSteps = 0;
375 CRYPT_PROVIDER_DATA *provData;
376 BOOL ret;
377 struct wintrust_step verifySteps[5];
379 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
381 provData = WINTRUST_AllocateProviderData();
382 if (!provData)
383 return ERROR_OUTOFMEMORY;
385 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
386 if (!ret)
388 err = GetLastError();
389 goto error;
391 if (!provData->psPfns->pfnObjectTrust)
392 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
393 /* Not sure why, but native skips the policy check */
394 provData->psPfns->pfnCertCheckPolicy = NULL;
396 data->hWVTStateData = provData;
397 provData->pWintrustData = data;
398 if (hwnd == INVALID_HANDLE_VALUE)
399 provData->hWndParent = GetDesktopWindow();
400 else
401 provData->hWndParent = hwnd;
402 provData->pgActionID = actionID;
403 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
405 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
406 provData->psPfns);
407 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
408 goto done;
410 error:
411 if (provData)
413 WINTRUST_Free(provData->padwTrustStepErrors);
414 WINTRUST_Free(provData->u.pPDSip);
415 WINTRUST_Free(provData->psPfns);
416 WINTRUST_Free(provData);
418 done:
419 TRACE("returning %08x\n", err);
420 return err;
423 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
424 WINTRUST_DATA *data)
426 LONG err;
428 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
430 err = WINTRUST_CertVerify(hwnd, actionID, data);
431 WINTRUST_DefaultClose(hwnd, actionID, data);
432 TRACE("returning %08x\n", err);
433 return err;
436 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
437 WINTRUST_DATA *data)
439 DWORD stateAction;
440 LONG err = ERROR_SUCCESS;
442 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
443 stateAction = data->dwStateAction;
444 else
446 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
447 stateAction = WTD_STATEACTION_IGNORE;
449 switch (stateAction)
451 case WTD_STATEACTION_IGNORE:
452 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
453 break;
454 case WTD_STATEACTION_VERIFY:
455 err = WINTRUST_CertVerify(hwnd, actionID, data);
456 break;
457 case WTD_STATEACTION_CLOSE:
458 err = WINTRUST_DefaultClose(hwnd, actionID, data);
459 break;
460 default:
461 FIXME("unimplemented for %d\n", data->dwStateAction);
463 return err;
466 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
468 TRACE("%p\n", pFile);
469 if (pFile)
471 TRACE("cbStruct: %d\n", pFile->cbStruct);
472 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
473 TRACE("hFile: %p\n", pFile->hFile);
474 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
478 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
480 TRACE("%p\n", catalog);
481 if (catalog)
483 TRACE("cbStruct: %d\n", catalog->cbStruct);
484 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
485 TRACE("pcwszCatalogFilePath: %s\n",
486 debugstr_w(catalog->pcwszCatalogFilePath));
487 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
488 TRACE("pcwszMemberFilePath: %s\n",
489 debugstr_w(catalog->pcwszMemberFilePath));
490 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
491 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
492 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
493 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
497 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
499 TRACE("%p\n", blob);
500 if (blob)
502 TRACE("cbStruct: %d\n", blob->cbStruct);
503 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
504 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
505 TRACE("cbMemObject: %d\n", blob->cbMemObject);
506 TRACE("pbMemObject: %p\n", blob->pbMemObject);
507 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
508 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
512 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
514 TRACE("%p\n", sgnr);
515 if (sgnr)
517 TRACE("cbStruct: %d\n", sgnr->cbStruct);
518 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
519 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
520 TRACE("chStores: %d\n", sgnr->chStores);
524 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
526 TRACE("%p\n", cert);
527 if (cert)
529 TRACE("cbStruct: %d\n", cert->cbStruct);
530 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
531 TRACE("psCertContext: %p\n", cert->psCertContext);
532 TRACE("chStores: %d\n", cert->chStores);
533 TRACE("dwFlags: %08x\n", cert->dwFlags);
534 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
538 static void dump_wintrust_data(WINTRUST_DATA *data)
540 TRACE("%p\n", data);
541 if (data)
543 TRACE("cbStruct: %d\n", data->cbStruct);
544 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
545 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
546 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
547 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
548 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
549 switch (data->dwUnionChoice)
551 case WTD_CHOICE_FILE:
552 dump_file_info(data->u.pFile);
553 break;
554 case WTD_CHOICE_CATALOG:
555 dump_catalog_info(data->u.pCatalog);
556 break;
557 case WTD_CHOICE_BLOB:
558 dump_blob_info(data->u.pBlob);
559 break;
560 case WTD_CHOICE_SIGNER:
561 dump_sgnr_info(data->u.pSgnr);
562 break;
563 case WTD_CHOICE_CERT:
564 dump_cert_info(data->u.pCert);
565 break;
567 TRACE("dwStateAction: %d\n", data->dwStateAction);
568 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
569 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
570 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
571 TRACE("dwUIContext: %d\n", data->dwUIContext);
575 /***********************************************************************
576 * WinVerifyTrust (WINTRUST.@)
578 * Verifies an object by calling the specified trust provider.
580 * PARAMS
581 * hwnd [I] Handle to a caller window.
582 * ActionID [I] Pointer to a GUID that identifies the action to perform.
583 * ActionData [I] Information used by the trust provider to verify the object.
585 * RETURNS
586 * Success: Zero.
587 * Failure: A TRUST_E_* error code.
589 * NOTES
590 * Trust providers can be found at:
591 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
593 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
595 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
596 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
597 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
598 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
599 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
600 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
601 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
602 LONG err = ERROR_SUCCESS;
603 WINTRUST_DATA *actionData = ActionData;
605 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
606 dump_wintrust_data(ActionData);
608 /* Support for known old-style callers: */
609 if (IsEqualGUID(ActionID, &published_software))
610 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
611 else if (IsEqualGUID(ActionID, &cert_action_verify))
612 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
613 else
615 DWORD stateAction;
617 /* Check known actions to warn of possible problems */
618 if (!IsEqualGUID(ActionID, &unknown) &&
619 !IsEqualGUID(ActionID, &generic_verify_v2) &&
620 !IsEqualGUID(ActionID, &generic_cert_verify) &&
621 !IsEqualGUID(ActionID, &generic_chain_verify))
622 WARN("unknown action %s, default behavior may not be right\n",
623 debugstr_guid(ActionID));
624 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
625 stateAction = actionData->dwStateAction;
626 else
628 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
629 stateAction = WTD_STATEACTION_IGNORE;
631 switch (stateAction)
633 case WTD_STATEACTION_IGNORE:
634 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
635 break;
636 case WTD_STATEACTION_VERIFY:
637 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
638 break;
639 case WTD_STATEACTION_CLOSE:
640 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
641 break;
642 default:
643 FIXME("unimplemented for %d\n", actionData->dwStateAction);
647 TRACE("returning %08x\n", err);
648 return err;
651 /***********************************************************************
652 * WinVerifyTrustEx (WINTRUST.@)
654 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
655 WINTRUST_DATA* ActionData )
657 return WinVerifyTrust(hwnd, ActionID, ActionData);
660 /***********************************************************************
661 * WTHelperGetProvSignerFromChain (WINTRUST.@)
663 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
664 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
665 DWORD idxCounterSigner)
667 CRYPT_PROVIDER_SGNR *sgnr;
669 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
670 idxCounterSigner);
672 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
673 return NULL;
674 sgnr = &pProvData->pasSigners[idxSigner];
675 if (fCounterSigner)
677 if (idxCounterSigner >= sgnr->csCounterSigners ||
678 !sgnr->pasCounterSigners)
679 return NULL;
680 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
682 TRACE("returning %p\n", sgnr);
683 return sgnr;
686 /***********************************************************************
687 * WTHelperGetProvCertFromChain (WINTRUST.@)
689 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
690 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
692 CRYPT_PROVIDER_CERT *cert;
694 TRACE("(%p %d)\n", pSgnr, idxCert);
696 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
697 return NULL;
698 cert = &pSgnr->pasCertChain[idxCert];
699 TRACE("returning %p\n", cert);
700 return cert;
703 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
704 CRYPT_PROVIDER_DATA* pProvData,
705 GUID* pgProviderID)
707 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
708 DWORD i;
710 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
712 for (i = 0; i < pProvData->csProvPrivData; i++)
713 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
715 privdata = &pProvData->pasProvPrivData[i];
716 break;
719 return privdata;
722 /***********************************************************************
723 * WTHelperProvDataFromStateData (WINTRUST.@)
725 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
727 TRACE("%p\n", hStateData);
728 return hStateData;
731 /***********************************************************************
732 * WTHelperGetFileName(WINTRUST.@)
734 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
736 TRACE("%p\n",data);
737 if (data->dwUnionChoice == WTD_CHOICE_FILE)
738 return data->u.pFile->pcwszFilePath;
739 else
740 return NULL;
743 /***********************************************************************
744 * WTHelperGetFileHandle(WINTRUST.@)
746 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
748 TRACE("%p\n",data);
749 if (data->dwUnionChoice == WTD_CHOICE_FILE)
750 return data->u.pFile->hFile;
751 else
752 return INVALID_HANDLE_VALUE;
755 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
757 PCCRYPT_OID_INFO **usages = pvArg;
758 DWORD cUsages;
759 BOOL ret;
761 if (!*usages)
763 cUsages = 0;
764 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
766 else
768 PCCRYPT_OID_INFO *ptr;
770 /* Count the existing usages.
771 * FIXME: make sure the new usage doesn't duplicate any in the list?
773 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
775 *usages = WINTRUST_ReAlloc(*usages,
776 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
778 if (*usages)
780 (*usages)[cUsages] = pInfo;
781 (*usages)[cUsages + 1] = NULL;
782 ret = TRUE;
784 else
786 SetLastError(ERROR_OUTOFMEMORY);
787 ret = FALSE;
789 return ret;
792 /***********************************************************************
793 * WTHelperGetKnownUsages(WINTRUST.@)
795 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
797 * PARAMS
798 * action [In] 1 => allocate and return known usages, 2 => free previously
799 * allocated usages.
800 * usages [In/Out] If action == 1, *usages is set to an array of
801 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
802 * pointer.
803 * If action == 2, *usages is freed.
805 * RETURNS
806 * TRUE on success, FALSE on failure.
808 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
810 BOOL ret;
812 TRACE("(%d, %p)\n", action, usages);
814 if (!usages)
816 SetLastError(ERROR_INVALID_PARAMETER);
817 return FALSE;
820 if (action == 1)
822 *usages = NULL;
823 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
824 WINTRUST_enumUsages);
826 else if (action == 2)
828 WINTRUST_Free(*usages);
829 *usages = NULL;
830 ret = TRUE;
832 else
834 WARN("unknown action %d\n", action);
835 SetLastError(ERROR_INVALID_PARAMETER);
836 ret = FALSE;
838 return ret;
841 static const WCHAR Software_Publishing[] = {
842 'S','o','f','t','w','a','r','e','\\',
843 'M','i','c','r','o','s','o','f','t','\\',
844 'W','i','n','d','o','w','s','\\',
845 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
846 'W','i','n','t','r','u','s','t','\\',
847 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
848 'S','o','f','t','w','a','r','e',' ',
849 'P','u','b','l','i','s','h','i','n','g',0 };
850 static const WCHAR State[] = { 'S','t','a','t','e',0 };
852 /***********************************************************************
853 * WintrustGetRegPolicyFlags (WINTRUST.@)
855 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
857 HKEY key;
858 LONG r;
860 TRACE("%p\n", pdwPolicyFlags);
862 *pdwPolicyFlags = 0;
863 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
864 KEY_READ, NULL, &key, NULL);
865 if (!r)
867 DWORD size = sizeof(DWORD);
869 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
870 &size);
871 RegCloseKey(key);
872 if (r)
874 /* Failed to query, create and return default value */
875 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
876 WTPF_OFFLINEOKNBU_COM |
877 WTPF_OFFLINEOKNBU_IND |
878 WTPF_OFFLINEOK_COM |
879 WTPF_OFFLINEOK_IND;
880 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
885 /***********************************************************************
886 * WintrustSetRegPolicyFlags (WINTRUST.@)
888 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
890 HKEY key;
891 LONG r;
893 TRACE("%x\n", dwPolicyFlags);
895 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
896 NULL, 0, KEY_WRITE, NULL, &key, NULL);
897 if (!r)
899 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
900 sizeof(DWORD));
901 RegCloseKey(key);
903 if (r) SetLastError(r);
904 return r == ERROR_SUCCESS;
907 /* Utility functions */
909 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
911 BOOL ret = FALSE;
913 TRACE("(%p, %p)\n", data, store);
915 if (data->chStores)
916 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
917 (data->chStores + 1) * sizeof(HCERTSTORE));
918 else
920 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
921 data->chStores = 0;
923 if (data->pahStores)
925 data->pahStores[data->chStores++] = CertDuplicateStore(store);
926 ret = TRUE;
928 else
929 SetLastError(ERROR_OUTOFMEMORY);
930 return ret;
933 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
934 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
936 BOOL ret = FALSE;
938 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
940 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
942 SetLastError(ERROR_INVALID_PARAMETER);
943 return FALSE;
945 if (fCounterSigner)
947 FIXME("unimplemented for counter signers\n");
948 SetLastError(ERROR_INVALID_PARAMETER);
949 return FALSE;
951 if (data->csSigners)
952 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
953 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
954 else
956 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
957 data->csSigners = 0;
959 if (data->pasSigners)
961 if (idxSigner < data->csSigners)
962 memmove(&data->pasSigners[idxSigner],
963 &data->pasSigners[idxSigner + 1],
964 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
965 ret = TRUE;
966 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
968 /* The PSDK says psSigner should be allocated using pfnAlloc, but
969 * it doesn't say anything about ownership. Since callers are
970 * internal, assume ownership is passed, and just store the
971 * pointer.
973 memcpy(&data->pasSigners[idxSigner], sgnr,
974 sizeof(CRYPT_PROVIDER_SGNR));
976 else
977 memset(&data->pasSigners[idxSigner], 0,
978 sizeof(CRYPT_PROVIDER_SGNR));
979 data->csSigners++;
981 else
982 SetLastError(ERROR_OUTOFMEMORY);
983 return ret;
986 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
987 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
989 BOOL ret = FALSE;
991 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
992 idxSigner, pCert2Add);
994 if (fCounterSigner)
996 FIXME("unimplemented for counter signers\n");
997 SetLastError(ERROR_INVALID_PARAMETER);
998 return FALSE;
1000 if (data->pasSigners[idxSigner].csCertChain)
1001 data->pasSigners[idxSigner].pasCertChain =
1002 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1003 (data->pasSigners[idxSigner].csCertChain + 1) *
1004 sizeof(CRYPT_PROVIDER_CERT));
1005 else
1007 data->pasSigners[idxSigner].pasCertChain =
1008 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1009 data->pasSigners[idxSigner].csCertChain = 0;
1011 if (data->pasSigners[idxSigner].pasCertChain)
1013 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1014 data->pasSigners[idxSigner].csCertChain];
1016 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1017 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1018 data->pasSigners[idxSigner].csCertChain++;
1019 ret = TRUE;
1021 else
1022 SetLastError(ERROR_OUTOFMEMORY);
1023 return ret;
1026 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1027 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1029 BOOL ret = FALSE;
1031 TRACE("(%p, %p)\n", data, pPrivData2Add);
1033 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1035 SetLastError(ERROR_INVALID_PARAMETER);
1036 WARN("invalid struct size\n");
1037 return FALSE;
1039 if (data->csProvPrivData)
1040 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1041 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1042 else
1044 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1045 data->csProvPrivData = 0;
1047 if (data->pasProvPrivData)
1049 DWORD i;
1051 for (i = 0; i < data->csProvPrivData; i++)
1052 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1053 break;
1055 data->pasProvPrivData[i] = *pPrivData2Add;
1056 if (i == data->csProvPrivData)
1057 data->csProvPrivData++;
1059 else
1060 SetLastError(ERROR_OUTOFMEMORY);
1061 return ret;
1064 /***********************************************************************
1065 * OpenPersonalTrustDBDialog (WINTRUST.@)
1067 * Opens the certificate manager dialog, showing only the stores that
1068 * contain trusted software publishers.
1070 * PARAMS
1071 * hwnd [I] handle of parent window
1073 * RETURNS
1074 * TRUE if the dialog could be opened, FALSE if not.
1076 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1078 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1080 uiCertMgr.dwSize = sizeof(uiCertMgr);
1081 uiCertMgr.hwndParent = hwnd;
1082 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1083 uiCertMgr.pwszTitle = NULL;
1084 uiCertMgr.pszInitUsageOID = NULL;
1085 return CryptUIDlgCertMgr(&uiCertMgr);