push e1d8a1293d44015bb0894687d02c5c53339996f7
[wine/hacks.git] / dlls / wintrust / wintrust_main.c
blob0a40fbab6f82986fcc41623249bb4156ffce9788
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 WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO,
307 data->pWintrustData->u.pBlob->cbStruct, pbMemObject) &&
308 data->pWintrustData->u.pBlob->cbMemObject ==
309 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
310 data->pWintrustData->u.pBlob->pbMemObject)
312 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
313 (CERT_VERIFY_CERTIFICATE_TRUST *)
314 data->pWintrustData->u.pBlob->pbMemObject;
316 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
317 pCert->pccert)
319 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
320 DWORD i;
321 SYSTEMTIME sysTime;
323 /* Add a signer with nothing but the time to verify, so we can
324 * add a cert to it
326 GetSystemTime(&sysTime);
327 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
328 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
329 if (!ret)
330 goto error;
331 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
332 pCert->pccert);
333 if (!ret)
334 goto error;
335 for (i = 0; ret && i < pCert->cRootStores; i++)
336 ret = data->psPfns->pfnAddStore2Chain(data,
337 pCert->rghstoreRoots[i]);
338 for (i = 0; ret && i < pCert->cStores; i++)
339 ret = data->psPfns->pfnAddStore2Chain(data,
340 pCert->rghstoreCAs[i]);
341 for (i = 0; ret && i < pCert->cTrustStores; i++)
342 ret = data->psPfns->pfnAddStore2Chain(data,
343 pCert->rghstoreTrust[i]);
345 else
347 SetLastError(ERROR_INVALID_PARAMETER);
348 ret = FALSE;
351 else
353 SetLastError(ERROR_INVALID_PARAMETER);
354 ret = FALSE;
356 break;
357 default:
358 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
359 SetLastError(ERROR_INVALID_PARAMETER);
360 ret = FALSE;
363 error:
364 if (!ret)
365 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
366 GetLastError();
367 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
368 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
369 return ret ? S_OK : S_FALSE;
372 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
373 WINTRUST_DATA *data)
375 DWORD err = ERROR_SUCCESS, numSteps = 0;
376 CRYPT_PROVIDER_DATA *provData;
377 BOOL ret;
378 struct wintrust_step verifySteps[5];
380 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
382 provData = WINTRUST_AllocateProviderData();
383 if (!provData)
384 return ERROR_OUTOFMEMORY;
386 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
387 if (!ret)
389 err = GetLastError();
390 goto error;
392 if (!provData->psPfns->pfnObjectTrust)
393 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
394 /* Not sure why, but native skips the policy check */
395 provData->psPfns->pfnCertCheckPolicy = NULL;
397 data->hWVTStateData = provData;
398 provData->pWintrustData = data;
399 if (hwnd == INVALID_HANDLE_VALUE)
400 provData->hWndParent = GetDesktopWindow();
401 else
402 provData->hWndParent = hwnd;
403 provData->pgActionID = actionID;
404 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
406 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
407 provData->psPfns);
408 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
409 goto done;
411 error:
412 if (provData)
414 WINTRUST_Free(provData->padwTrustStepErrors);
415 WINTRUST_Free(provData->u.pPDSip);
416 WINTRUST_Free(provData->psPfns);
417 WINTRUST_Free(provData);
419 done:
420 TRACE("returning %08x\n", err);
421 return err;
424 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
425 WINTRUST_DATA *data)
427 LONG err;
429 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
431 err = WINTRUST_CertVerify(hwnd, actionID, data);
432 WINTRUST_DefaultClose(hwnd, actionID, data);
433 TRACE("returning %08x\n", err);
434 return err;
437 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
438 WINTRUST_DATA *data)
440 DWORD stateAction;
441 LONG err = ERROR_SUCCESS;
443 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
444 stateAction = data->dwStateAction;
445 else
447 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
448 stateAction = WTD_STATEACTION_IGNORE;
450 switch (stateAction)
452 case WTD_STATEACTION_IGNORE:
453 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
454 break;
455 case WTD_STATEACTION_VERIFY:
456 err = WINTRUST_CertVerify(hwnd, actionID, data);
457 break;
458 case WTD_STATEACTION_CLOSE:
459 err = WINTRUST_DefaultClose(hwnd, actionID, data);
460 break;
461 default:
462 FIXME("unimplemented for %d\n", data->dwStateAction);
464 return err;
467 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
469 TRACE("%p\n", pFile);
470 if (pFile)
472 TRACE("cbStruct: %d\n", pFile->cbStruct);
473 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
474 TRACE("hFile: %p\n", pFile->hFile);
475 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
479 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
481 TRACE("%p\n", catalog);
482 if (catalog)
484 TRACE("cbStruct: %d\n", catalog->cbStruct);
485 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
486 TRACE("pcwszCatalogFilePath: %s\n",
487 debugstr_w(catalog->pcwszCatalogFilePath));
488 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
489 TRACE("pcwszMemberFilePath: %s\n",
490 debugstr_w(catalog->pcwszMemberFilePath));
491 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
492 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
493 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
494 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
498 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
500 TRACE("%p\n", blob);
501 if (blob)
503 TRACE("cbStruct: %d\n", blob->cbStruct);
504 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
505 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
506 TRACE("cbMemObject: %d\n", blob->cbMemObject);
507 TRACE("pbMemObject: %p\n", blob->pbMemObject);
508 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
509 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
513 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
515 TRACE("%p\n", sgnr);
516 if (sgnr)
518 TRACE("cbStruct: %d\n", sgnr->cbStruct);
519 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
520 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
521 TRACE("chStores: %d\n", sgnr->chStores);
525 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
527 TRACE("%p\n", cert);
528 if (cert)
530 TRACE("cbStruct: %d\n", cert->cbStruct);
531 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
532 TRACE("psCertContext: %p\n", cert->psCertContext);
533 TRACE("chStores: %d\n", cert->chStores);
534 TRACE("dwFlags: %08x\n", cert->dwFlags);
535 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
539 static void dump_wintrust_data(WINTRUST_DATA *data)
541 TRACE("%p\n", data);
542 if (data)
544 TRACE("cbStruct: %d\n", data->cbStruct);
545 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
546 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
547 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
548 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
549 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
550 switch (data->dwUnionChoice)
552 case WTD_CHOICE_FILE:
553 dump_file_info(data->u.pFile);
554 break;
555 case WTD_CHOICE_CATALOG:
556 dump_catalog_info(data->u.pCatalog);
557 break;
558 case WTD_CHOICE_BLOB:
559 dump_blob_info(data->u.pBlob);
560 break;
561 case WTD_CHOICE_SIGNER:
562 dump_sgnr_info(data->u.pSgnr);
563 break;
564 case WTD_CHOICE_CERT:
565 dump_cert_info(data->u.pCert);
566 break;
568 TRACE("dwStateAction: %d\n", data->dwStateAction);
569 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
570 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
571 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
572 TRACE("dwUIContext: %d\n", data->dwUIContext);
576 /***********************************************************************
577 * WinVerifyTrust (WINTRUST.@)
579 * Verifies an object by calling the specified trust provider.
581 * PARAMS
582 * hwnd [I] Handle to a caller window.
583 * ActionID [I] Pointer to a GUID that identifies the action to perform.
584 * ActionData [I] Information used by the trust provider to verify the object.
586 * RETURNS
587 * Success: Zero.
588 * Failure: A TRUST_E_* error code.
590 * NOTES
591 * Trust providers can be found at:
592 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
594 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
596 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
597 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
598 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
599 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
600 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
601 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
602 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
603 LONG err = ERROR_SUCCESS;
604 WINTRUST_DATA *actionData = ActionData;
606 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
607 dump_wintrust_data(ActionData);
609 /* Support for known old-style callers: */
610 if (IsEqualGUID(ActionID, &published_software))
611 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
612 else if (IsEqualGUID(ActionID, &cert_action_verify))
613 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
614 else
616 DWORD stateAction;
618 /* Check known actions to warn of possible problems */
619 if (!IsEqualGUID(ActionID, &unknown) &&
620 !IsEqualGUID(ActionID, &generic_verify_v2) &&
621 !IsEqualGUID(ActionID, &generic_cert_verify) &&
622 !IsEqualGUID(ActionID, &generic_chain_verify))
623 WARN("unknown action %s, default behavior may not be right\n",
624 debugstr_guid(ActionID));
625 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
626 stateAction = actionData->dwStateAction;
627 else
629 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
630 stateAction = WTD_STATEACTION_IGNORE;
632 switch (stateAction)
634 case WTD_STATEACTION_IGNORE:
635 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
636 break;
637 case WTD_STATEACTION_VERIFY:
638 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
639 break;
640 case WTD_STATEACTION_CLOSE:
641 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
642 break;
643 default:
644 FIXME("unimplemented for %d\n", actionData->dwStateAction);
648 TRACE("returning %08x\n", err);
649 return err;
652 /***********************************************************************
653 * WinVerifyTrustEx (WINTRUST.@)
655 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
656 WINTRUST_DATA* ActionData )
658 return WinVerifyTrust(hwnd, ActionID, ActionData);
661 /***********************************************************************
662 * WTHelperGetProvSignerFromChain (WINTRUST.@)
664 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
665 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
666 DWORD idxCounterSigner)
668 CRYPT_PROVIDER_SGNR *sgnr;
670 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
671 idxCounterSigner);
673 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
674 return NULL;
675 sgnr = &pProvData->pasSigners[idxSigner];
676 if (fCounterSigner)
678 if (idxCounterSigner >= sgnr->csCounterSigners ||
679 !sgnr->pasCounterSigners)
680 return NULL;
681 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
683 TRACE("returning %p\n", sgnr);
684 return sgnr;
687 /***********************************************************************
688 * WTHelperGetProvCertFromChain (WINTRUST.@)
690 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
691 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
693 CRYPT_PROVIDER_CERT *cert;
695 TRACE("(%p %d)\n", pSgnr, idxCert);
697 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
698 return NULL;
699 cert = &pSgnr->pasCertChain[idxCert];
700 TRACE("returning %p\n", cert);
701 return cert;
704 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
705 CRYPT_PROVIDER_DATA* pProvData,
706 GUID* pgProviderID)
708 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
709 DWORD i;
711 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
713 for (i = 0; i < pProvData->csProvPrivData; i++)
714 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
716 privdata = &pProvData->pasProvPrivData[i];
717 break;
720 return privdata;
723 /***********************************************************************
724 * WTHelperProvDataFromStateData (WINTRUST.@)
726 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
728 TRACE("%p\n", hStateData);
729 return hStateData;
732 /***********************************************************************
733 * WTHelperGetFileName(WINTRUST.@)
735 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
737 TRACE("%p\n",data);
738 if (data->dwUnionChoice == WTD_CHOICE_FILE)
739 return data->u.pFile->pcwszFilePath;
740 else
741 return NULL;
744 /***********************************************************************
745 * WTHelperGetFileHandle(WINTRUST.@)
747 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
749 TRACE("%p\n",data);
750 if (data->dwUnionChoice == WTD_CHOICE_FILE)
751 return data->u.pFile->hFile;
752 else
753 return INVALID_HANDLE_VALUE;
756 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
758 PCCRYPT_OID_INFO **usages = pvArg;
759 DWORD cUsages;
760 BOOL ret;
762 if (!*usages)
764 cUsages = 0;
765 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
767 else
769 PCCRYPT_OID_INFO *ptr;
771 /* Count the existing usages.
772 * FIXME: make sure the new usage doesn't duplicate any in the list?
774 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
776 *usages = WINTRUST_ReAlloc(*usages,
777 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
779 if (*usages)
781 (*usages)[cUsages] = pInfo;
782 (*usages)[cUsages + 1] = NULL;
783 ret = TRUE;
785 else
787 SetLastError(ERROR_OUTOFMEMORY);
788 ret = FALSE;
790 return ret;
793 /***********************************************************************
794 * WTHelperGetKnownUsages(WINTRUST.@)
796 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
798 * PARAMS
799 * action [In] 1 => allocate and return known usages, 2 => free previously
800 * allocated usages.
801 * usages [In/Out] If action == 1, *usages is set to an array of
802 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
803 * pointer.
804 * If action == 2, *usages is freed.
806 * RETURNS
807 * TRUE on success, FALSE on failure.
809 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
811 BOOL ret;
813 TRACE("(%d, %p)\n", action, usages);
815 if (!usages)
817 SetLastError(ERROR_INVALID_PARAMETER);
818 return FALSE;
821 if (action == 1)
823 *usages = NULL;
824 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
825 WINTRUST_enumUsages);
827 else if (action == 2)
829 WINTRUST_Free(*usages);
830 *usages = NULL;
831 ret = TRUE;
833 else
835 WARN("unknown action %d\n", action);
836 SetLastError(ERROR_INVALID_PARAMETER);
837 ret = FALSE;
839 return ret;
842 static const WCHAR Software_Publishing[] = {
843 'S','o','f','t','w','a','r','e','\\',
844 'M','i','c','r','o','s','o','f','t','\\',
845 'W','i','n','d','o','w','s','\\',
846 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
847 'W','i','n','t','r','u','s','t','\\',
848 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
849 'S','o','f','t','w','a','r','e',' ',
850 'P','u','b','l','i','s','h','i','n','g',0 };
851 static const WCHAR State[] = { 'S','t','a','t','e',0 };
853 /***********************************************************************
854 * WintrustGetRegPolicyFlags (WINTRUST.@)
856 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
858 HKEY key;
859 LONG r;
861 TRACE("%p\n", pdwPolicyFlags);
863 *pdwPolicyFlags = 0;
864 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
865 KEY_READ, NULL, &key, NULL);
866 if (!r)
868 DWORD size = sizeof(DWORD);
870 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
871 &size);
872 RegCloseKey(key);
873 if (r)
875 /* Failed to query, create and return default value */
876 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
877 WTPF_OFFLINEOKNBU_COM |
878 WTPF_OFFLINEOKNBU_IND |
879 WTPF_OFFLINEOK_COM |
880 WTPF_OFFLINEOK_IND;
881 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
886 /***********************************************************************
887 * WintrustSetRegPolicyFlags (WINTRUST.@)
889 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
891 HKEY key;
892 LONG r;
894 TRACE("%x\n", dwPolicyFlags);
896 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
897 NULL, 0, KEY_WRITE, NULL, &key, NULL);
898 if (!r)
900 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
901 sizeof(DWORD));
902 RegCloseKey(key);
904 if (r) SetLastError(r);
905 return r == ERROR_SUCCESS;
908 /* Utility functions */
910 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
912 BOOL ret = FALSE;
914 TRACE("(%p, %p)\n", data, store);
916 if (data->chStores)
917 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
918 (data->chStores + 1) * sizeof(HCERTSTORE));
919 else
921 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
922 data->chStores = 0;
924 if (data->pahStores)
926 data->pahStores[data->chStores++] = CertDuplicateStore(store);
927 ret = TRUE;
929 else
930 SetLastError(ERROR_OUTOFMEMORY);
931 return ret;
934 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
935 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
937 BOOL ret = FALSE;
939 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
941 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
943 SetLastError(ERROR_INVALID_PARAMETER);
944 return FALSE;
946 if (fCounterSigner)
948 FIXME("unimplemented for counter signers\n");
949 SetLastError(ERROR_INVALID_PARAMETER);
950 return FALSE;
952 if (data->csSigners)
953 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
954 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
955 else
957 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
958 data->csSigners = 0;
960 if (data->pasSigners)
962 if (idxSigner < data->csSigners)
963 memmove(&data->pasSigners[idxSigner],
964 &data->pasSigners[idxSigner + 1],
965 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
966 ret = TRUE;
967 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
969 /* The PSDK says psSigner should be allocated using pfnAlloc, but
970 * it doesn't say anything about ownership. Since callers are
971 * internal, assume ownership is passed, and just store the
972 * pointer.
974 memcpy(&data->pasSigners[idxSigner], sgnr,
975 sizeof(CRYPT_PROVIDER_SGNR));
977 else
978 memset(&data->pasSigners[idxSigner], 0,
979 sizeof(CRYPT_PROVIDER_SGNR));
980 data->csSigners++;
982 else
983 SetLastError(ERROR_OUTOFMEMORY);
984 return ret;
987 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
988 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
990 BOOL ret = FALSE;
992 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
993 idxSigner, pCert2Add);
995 if (fCounterSigner)
997 FIXME("unimplemented for counter signers\n");
998 SetLastError(ERROR_INVALID_PARAMETER);
999 return FALSE;
1001 if (data->pasSigners[idxSigner].csCertChain)
1002 data->pasSigners[idxSigner].pasCertChain =
1003 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1004 (data->pasSigners[idxSigner].csCertChain + 1) *
1005 sizeof(CRYPT_PROVIDER_CERT));
1006 else
1008 data->pasSigners[idxSigner].pasCertChain =
1009 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1010 data->pasSigners[idxSigner].csCertChain = 0;
1012 if (data->pasSigners[idxSigner].pasCertChain)
1014 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1015 data->pasSigners[idxSigner].csCertChain];
1017 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1018 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1019 data->pasSigners[idxSigner].csCertChain++;
1020 ret = TRUE;
1022 else
1023 SetLastError(ERROR_OUTOFMEMORY);
1024 return ret;
1027 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1028 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1030 BOOL ret = FALSE;
1032 TRACE("(%p, %p)\n", data, pPrivData2Add);
1034 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1036 SetLastError(ERROR_INVALID_PARAMETER);
1037 WARN("invalid struct size\n");
1038 return FALSE;
1040 if (data->csProvPrivData)
1041 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1042 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1043 else
1045 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1046 data->csProvPrivData = 0;
1048 if (data->pasProvPrivData)
1050 DWORD i;
1052 for (i = 0; i < data->csProvPrivData; i++)
1053 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1054 break;
1056 data->pasProvPrivData[i] = *pPrivData2Add;
1057 if (i == data->csProvPrivData)
1058 data->csProvPrivData++;
1060 else
1061 SetLastError(ERROR_OUTOFMEMORY);
1062 return ret;
1065 /***********************************************************************
1066 * OpenPersonalTrustDBDialog (WINTRUST.@)
1068 * Opens the certificate manager dialog, showing only the stores that
1069 * contain trusted software publishers.
1071 * PARAMS
1072 * hwnd [I] handle of parent window
1074 * RETURNS
1075 * TRUE if the dialog could be opened, FALSE if not.
1077 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1079 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1081 uiCertMgr.dwSize = sizeof(uiCertMgr);
1082 uiCertMgr.hwndParent = hwnd;
1083 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1084 uiCertMgr.pwszTitle = NULL;
1085 uiCertMgr.pszInitUsageOID = NULL;
1086 return CryptUIDlgCertMgr(&uiCertMgr);