push 07a2b33f792746135ccf34a3b3e1dfb2a3c1e823
[wine/hacks.git] / dlls / wintrust / wintrust_main.c
blobf9d33293f5dbf478a3011cd85de5e4135f3719d9
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 /***********************************************************************
45 * DllMain (WINTRUST.@)
47 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
49 switch(reason)
51 case DLL_PROCESS_ATTACH:
52 DisableThreadLibraryCalls( inst );
53 break;
55 return TRUE;
58 /***********************************************************************
59 * TrustIsCertificateSelfSigned (WINTRUST.@)
61 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
63 BOOL ret;
65 TRACE("%p\n", cert);
66 ret = CertCompareCertificateName(cert->dwCertEncodingType,
67 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
68 return ret;
71 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
73 struct wintrust_step
75 wintrust_step_func func;
76 DWORD error_index;
79 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
80 DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
82 DWORD i, err = ERROR_SUCCESS;
84 for (i = 0; !err && i < numSteps; i++)
86 err = steps[i].func(provData);
87 if (err)
88 err = provData->padwTrustStepErrors[steps[i].error_index];
90 return err;
93 static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
95 CRYPT_PROVIDER_DATA *provData;
97 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
98 if (!provData)
99 goto oom;
100 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
102 provData->padwTrustStepErrors =
103 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
104 if (!provData->padwTrustStepErrors)
105 goto oom;
106 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
108 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
109 if (!provData->u.pPDSip)
110 goto oom;
111 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
113 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
114 if (!provData->psPfns)
115 goto oom;
116 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
117 return provData;
119 oom:
120 if (provData)
122 WINTRUST_Free(provData->padwTrustStepErrors);
123 WINTRUST_Free(provData->u.pPDSip);
124 WINTRUST_Free(provData->psPfns);
125 WINTRUST_Free(provData);
127 return NULL;
130 /* Adds trust steps for each function in psPfns. Assumes steps has at least
131 * 5 entries. Returns the number of steps added.
133 static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
134 const CRYPT_PROVIDER_FUNCTIONS *psPfns)
136 DWORD numSteps = 0;
138 if (psPfns->pfnInitialize)
140 steps[numSteps].func = psPfns->pfnInitialize;
141 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
143 if (psPfns->pfnObjectTrust)
145 steps[numSteps].func = psPfns->pfnObjectTrust;
146 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
148 if (psPfns->pfnSignatureTrust)
150 steps[numSteps].func = psPfns->pfnSignatureTrust;
151 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
153 if (psPfns->pfnCertificateTrust)
155 steps[numSteps].func = psPfns->pfnCertificateTrust;
156 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
158 if (psPfns->pfnFinalPolicy)
160 steps[numSteps].func = psPfns->pfnFinalPolicy;
161 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
163 return numSteps;
166 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
167 WINTRUST_DATA *data)
169 DWORD err = ERROR_SUCCESS, numSteps = 0;
170 CRYPT_PROVIDER_DATA *provData;
171 BOOL ret;
172 struct wintrust_step verifySteps[5];
174 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
176 provData = WINTRUST_AllocateProviderData();
177 if (!provData)
178 return ERROR_OUTOFMEMORY;
180 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
181 if (!ret)
183 err = GetLastError();
184 goto error;
187 data->hWVTStateData = (HANDLE)provData;
188 provData->pWintrustData = data;
189 if (hwnd == INVALID_HANDLE_VALUE)
190 provData->hWndParent = GetDesktopWindow();
191 else
192 provData->hWndParent = hwnd;
193 provData->pgActionID = actionID;
194 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
196 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
197 provData->psPfns);
198 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
199 goto done;
201 error:
202 if (provData)
204 WINTRUST_Free(provData->padwTrustStepErrors);
205 WINTRUST_Free(provData->u.pPDSip);
206 WINTRUST_Free(provData->psPfns);
207 WINTRUST_Free(provData);
209 done:
210 TRACE("returning %08x\n", err);
211 return err;
214 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
215 WINTRUST_DATA *data)
217 DWORD err = ERROR_SUCCESS;
218 CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
220 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
222 if (provData)
224 if (provData->psPfns->pfnCleanupPolicy)
225 err = provData->psPfns->pfnCleanupPolicy(provData);
227 WINTRUST_Free(provData->padwTrustStepErrors);
228 WINTRUST_Free(provData->u.pPDSip);
229 WINTRUST_Free(provData->psPfns);
230 WINTRUST_Free(provData);
231 data->hWVTStateData = NULL;
233 TRACE("returning %08x\n", err);
234 return err;
237 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
238 WINTRUST_DATA *data)
240 LONG err;
242 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
244 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
245 WINTRUST_DefaultClose(hwnd, actionID, data);
246 TRACE("returning %08x\n", err);
247 return err;
250 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
251 WINTRUST_DATA *data)
253 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
254 /* Undocumented: the published software action is passed a path,
255 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
257 LPWIN_TRUST_SUBJECT_FILE subjectFile =
258 (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
259 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
261 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
262 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
263 fileInfo.pcwszFilePath = subjectFile->lpPath;
264 fileInfo.hFile = subjectFile->hFile;
265 wintrust_data.u.pFile = &fileInfo;
266 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
267 wintrust_data.dwUIChoice = WTD_UI_NONE;
269 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
272 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
273 * action is not stored in the registry and is located in wintrust, not in
274 * cryptdlg along with the rest of the implementation (verified by running the
275 * action with a native wintrust.dll.)
277 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
279 BOOL ret;
281 TRACE("(%p)\n", data);
283 if (!data->padwTrustStepErrors)
284 return S_FALSE;
286 switch (data->pWintrustData->dwUnionChoice)
288 case WTD_CHOICE_BLOB:
289 if (data->pWintrustData->u.pBlob &&
290 data->pWintrustData->u.pBlob->cbStruct == sizeof(WINTRUST_BLOB_INFO) &&
291 data->pWintrustData->u.pBlob->cbMemObject ==
292 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
293 data->pWintrustData->u.pBlob->pbMemObject)
295 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
296 (CERT_VERIFY_CERTIFICATE_TRUST *)
297 data->pWintrustData->u.pBlob->pbMemObject;
299 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
300 pCert->pccert)
302 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
303 DWORD i;
304 SYSTEMTIME sysTime;
306 /* Add a signer with nothing but the time to verify, so we can
307 * add a cert to it
309 GetSystemTime(&sysTime);
310 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
311 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
312 if (!ret)
313 goto error;
314 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
315 pCert->pccert);
316 if (!ret)
317 goto error;
318 for (i = 0; ret && i < pCert->cRootStores; i++)
319 ret = data->psPfns->pfnAddStore2Chain(data,
320 pCert->rghstoreRoots[i]);
321 for (i = 0; ret && i < pCert->cStores; i++)
322 ret = data->psPfns->pfnAddStore2Chain(data,
323 pCert->rghstoreCAs[i]);
324 for (i = 0; ret && i < pCert->cTrustStores; i++)
325 ret = data->psPfns->pfnAddStore2Chain(data,
326 pCert->rghstoreTrust[i]);
328 else
330 SetLastError(ERROR_INVALID_PARAMETER);
331 ret = FALSE;
334 else
336 SetLastError(ERROR_INVALID_PARAMETER);
337 ret = FALSE;
339 break;
340 default:
341 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
342 SetLastError(ERROR_INVALID_PARAMETER);
343 ret = FALSE;
346 error:
347 if (!ret)
348 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
349 GetLastError();
350 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
351 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
352 return ret ? S_OK : S_FALSE;
355 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
356 WINTRUST_DATA *data)
358 DWORD err = ERROR_SUCCESS, numSteps = 0;
359 CRYPT_PROVIDER_DATA *provData;
360 BOOL ret;
361 struct wintrust_step verifySteps[5];
363 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
365 provData = WINTRUST_AllocateProviderData();
366 if (!provData)
367 return ERROR_OUTOFMEMORY;
369 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
370 if (!ret)
372 err = GetLastError();
373 goto error;
375 if (!provData->psPfns->pfnObjectTrust)
376 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
377 /* Not sure why, but native skips the policy check */
378 provData->psPfns->pfnCertCheckPolicy = NULL;
380 data->hWVTStateData = (HANDLE)provData;
381 provData->pWintrustData = data;
382 if (hwnd == INVALID_HANDLE_VALUE)
383 provData->hWndParent = GetDesktopWindow();
384 else
385 provData->hWndParent = hwnd;
386 provData->pgActionID = actionID;
387 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
389 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
390 provData->psPfns);
391 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
392 goto done;
394 error:
395 if (provData)
397 WINTRUST_Free(provData->padwTrustStepErrors);
398 WINTRUST_Free(provData->u.pPDSip);
399 WINTRUST_Free(provData->psPfns);
400 WINTRUST_Free(provData);
402 done:
403 TRACE("returning %08x\n", err);
404 return err;
407 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
408 WINTRUST_DATA *data)
410 LONG err;
412 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
414 err = WINTRUST_CertVerify(hwnd, actionID, data);
415 WINTRUST_DefaultClose(hwnd, actionID, data);
416 TRACE("returning %08x\n", err);
417 return err;
420 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
421 WINTRUST_DATA *data)
423 DWORD stateAction;
424 LONG err = ERROR_SUCCESS;
426 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
427 stateAction = data->dwStateAction;
428 else
430 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
431 stateAction = WTD_STATEACTION_IGNORE;
433 switch (stateAction)
435 case WTD_STATEACTION_IGNORE:
436 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
437 break;
438 case WTD_STATEACTION_VERIFY:
439 err = WINTRUST_CertVerify(hwnd, actionID, data);
440 break;
441 case WTD_STATEACTION_CLOSE:
442 err = WINTRUST_DefaultClose(hwnd, actionID, data);
443 break;
444 default:
445 FIXME("unimplemented for %d\n", data->dwStateAction);
447 return err;
450 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
452 TRACE("%p\n", pFile);
453 if (pFile)
455 TRACE("cbStruct: %d\n", pFile->cbStruct);
456 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
457 TRACE("hFile: %p\n", pFile->hFile);
458 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
462 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
464 TRACE("%p\n", catalog);
465 if (catalog)
467 TRACE("cbStruct: %d\n", catalog->cbStruct);
468 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
469 TRACE("pcwszCatalogFilePath: %s\n",
470 debugstr_w(catalog->pcwszCatalogFilePath));
471 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
472 TRACE("pcwszMemberFilePath: %s\n",
473 debugstr_w(catalog->pcwszMemberFilePath));
474 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
475 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
476 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
477 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
481 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
483 TRACE("%p\n", blob);
484 if (blob)
486 TRACE("cbStruct: %d\n", blob->cbStruct);
487 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
488 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
489 TRACE("cbMemObject: %d\n", blob->cbMemObject);
490 TRACE("pbMemObject: %p\n", blob->pbMemObject);
491 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
492 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
496 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
498 TRACE("%p\n", sgnr);
499 if (sgnr)
501 TRACE("cbStruct: %d\n", sgnr->cbStruct);
502 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
503 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
504 TRACE("chStores: %d\n", sgnr->chStores);
508 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
510 TRACE("%p\n", cert);
511 if (cert)
513 TRACE("cbStruct: %d\n", cert->cbStruct);
514 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
515 TRACE("psCertContext: %p\n", cert->psCertContext);
516 TRACE("chStores: %d\n", cert->chStores);
517 TRACE("dwFlags: %08x\n", cert->dwFlags);
518 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
522 static void dump_wintrust_data(WINTRUST_DATA *data)
524 TRACE("%p\n", data);
525 if (data)
527 TRACE("cbStruct: %d\n", data->cbStruct);
528 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
529 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
530 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
531 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
532 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
533 switch (data->dwUnionChoice)
535 case WTD_CHOICE_FILE:
536 dump_file_info(data->u.pFile);
537 break;
538 case WTD_CHOICE_CATALOG:
539 dump_catalog_info(data->u.pCatalog);
540 break;
541 case WTD_CHOICE_BLOB:
542 dump_blob_info(data->u.pBlob);
543 break;
544 case WTD_CHOICE_SIGNER:
545 dump_sgnr_info(data->u.pSgnr);
546 break;
547 case WTD_CHOICE_CERT:
548 dump_cert_info(data->u.pCert);
549 break;
551 TRACE("dwStateAction: %d\n", data->dwStateAction);
552 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
553 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
554 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
555 TRACE("dwUIContext: %d\n", data->dwUIContext);
559 /***********************************************************************
560 * WinVerifyTrust (WINTRUST.@)
562 * Verifies an object by calling the specified trust provider.
564 * PARAMS
565 * hwnd [I] Handle to a caller window.
566 * ActionID [I] Pointer to a GUID that identifies the action to perform.
567 * ActionData [I] Information used by the trust provider to verify the object.
569 * RETURNS
570 * Success: Zero.
571 * Failure: A TRUST_E_* error code.
573 * NOTES
574 * Trust providers can be found at:
575 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
577 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
579 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
580 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
581 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
582 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
583 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
584 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
585 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
586 LONG err = ERROR_SUCCESS;
587 WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
589 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
590 dump_wintrust_data(ActionData);
592 /* Support for known old-style callers: */
593 if (IsEqualGUID(ActionID, &published_software))
594 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
595 else if (IsEqualGUID(ActionID, &cert_action_verify))
596 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
597 else
599 DWORD stateAction;
601 /* Check known actions to warn of possible problems */
602 if (!IsEqualGUID(ActionID, &unknown) &&
603 !IsEqualGUID(ActionID, &generic_verify_v2) &&
604 !IsEqualGUID(ActionID, &generic_cert_verify) &&
605 !IsEqualGUID(ActionID, &generic_chain_verify))
606 WARN("unknown action %s, default behavior may not be right\n",
607 debugstr_guid(ActionID));
608 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
609 stateAction = actionData->dwStateAction;
610 else
612 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
613 stateAction = WTD_STATEACTION_IGNORE;
615 switch (stateAction)
617 case WTD_STATEACTION_IGNORE:
618 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
619 break;
620 case WTD_STATEACTION_VERIFY:
621 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
622 break;
623 case WTD_STATEACTION_CLOSE:
624 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
625 break;
626 default:
627 FIXME("unimplemented for %d\n", actionData->dwStateAction);
631 TRACE("returning %08x\n", err);
632 return err;
635 /***********************************************************************
636 * WinVerifyTrustEx (WINTRUST.@)
638 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
639 WINTRUST_DATA* ActionData )
641 return WinVerifyTrust(hwnd, ActionID, ActionData);
644 /***********************************************************************
645 * WTHelperGetProvSignerFromChain (WINTRUST.@)
647 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
648 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
649 DWORD idxCounterSigner)
651 CRYPT_PROVIDER_SGNR *sgnr;
653 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
654 idxCounterSigner);
656 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
657 return NULL;
658 sgnr = &pProvData->pasSigners[idxSigner];
659 if (fCounterSigner)
661 if (idxCounterSigner >= sgnr->csCounterSigners ||
662 !sgnr->pasCounterSigners)
663 return NULL;
664 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
666 TRACE("returning %p\n", sgnr);
667 return sgnr;
670 /***********************************************************************
671 * WTHelperGetProvCertFromChain (WINTRUST.@)
673 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
674 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
676 CRYPT_PROVIDER_CERT *cert;
678 TRACE("(%p %d)\n", pSgnr, idxCert);
680 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
681 return NULL;
682 cert = &pSgnr->pasCertChain[idxCert];
683 TRACE("returning %p\n", cert);
684 return cert;
687 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
688 CRYPT_PROVIDER_DATA* pProvData,
689 GUID* pgProviderID)
691 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
692 DWORD i;
694 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
696 for (i = 0; i < pProvData->csProvPrivData; i++)
697 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
699 privdata = &pProvData->pasProvPrivData[i];
700 break;
703 return privdata;
706 /***********************************************************************
707 * WTHelperProvDataFromStateData (WINTRUST.@)
709 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
711 TRACE("%p\n", hStateData);
712 return (CRYPT_PROVIDER_DATA *)hStateData;
715 /***********************************************************************
716 * WTHelperGetFileName(WINTRUST.@)
718 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
720 TRACE("%p\n",data);
721 if (data->dwUnionChoice == WTD_CHOICE_FILE)
722 return data->u.pFile->pcwszFilePath;
723 else
724 return NULL;
727 /***********************************************************************
728 * WTHelperGetFileHandle(WINTRUST.@)
730 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
732 TRACE("%p\n",data);
733 if (data->dwUnionChoice == WTD_CHOICE_FILE)
734 return data->u.pFile->hFile;
735 else
736 return INVALID_HANDLE_VALUE;
739 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
741 PCCRYPT_OID_INFO **usages = (PCCRYPT_OID_INFO **)pvArg;
742 DWORD cUsages;
743 BOOL ret;
745 if (!*usages)
747 cUsages = 0;
748 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
750 else
752 PCCRYPT_OID_INFO *ptr;
754 /* Count the existing usages.
755 * FIXME: make sure the new usage doesn't duplicate any in the list?
757 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
759 *usages = WINTRUST_ReAlloc((CRYPT_OID_INFO *)*usages,
760 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
762 if (*usages)
764 (*usages)[cUsages] = pInfo;
765 (*usages)[cUsages + 1] = NULL;
766 ret = TRUE;
768 else
770 SetLastError(ERROR_OUTOFMEMORY);
771 ret = FALSE;
773 return ret;
776 /***********************************************************************
777 * WTHelperGetKnownUsages(WINTRUST.@)
779 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
781 * PARAMS
782 * action [In] 1 => allocate and return known usages, 2 => free previously
783 * allocated usages.
784 * usages [In/Out] If action == 1, *usages is set to an array of
785 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
786 * pointer.
787 * If action == 2, *usages is freed.
789 * RETURNS
790 * TRUE on success, FALSE on failure.
792 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
794 BOOL ret;
796 TRACE("(%d, %p)\n", action, usages);
798 if (!usages)
800 SetLastError(ERROR_INVALID_PARAMETER);
801 return FALSE;
804 if (action == 1)
806 *usages = NULL;
807 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
808 WINTRUST_enumUsages);
810 else if (action == 2)
812 WINTRUST_Free((CRYPT_OID_INFO *)*usages);
813 *usages = NULL;
814 ret = TRUE;
816 else
818 WARN("unknown action %d\n", action);
819 SetLastError(ERROR_INVALID_PARAMETER);
820 ret = FALSE;
822 return ret;
825 static const WCHAR Software_Publishing[] = {
826 'S','o','f','t','w','a','r','e','\\',
827 'M','i','c','r','o','s','o','f','t','\\',
828 'W','i','n','d','o','w','s','\\',
829 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
830 'W','i','n','t','r','u','s','t','\\',
831 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
832 'S','o','f','t','w','a','r','e',' ',
833 'P','u','b','l','i','s','h','i','n','g',0 };
834 static const WCHAR State[] = { 'S','t','a','t','e',0 };
836 /***********************************************************************
837 * WintrustGetRegPolicyFlags (WINTRUST.@)
839 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
841 HKEY key;
842 LONG r;
844 TRACE("%p\n", pdwPolicyFlags);
846 *pdwPolicyFlags = 0;
847 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
848 KEY_READ, NULL, &key, NULL);
849 if (!r)
851 DWORD size = sizeof(DWORD);
853 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
854 &size);
855 RegCloseKey(key);
856 if (r)
858 /* Failed to query, create and return default value */
859 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
860 WTPF_OFFLINEOKNBU_COM |
861 WTPF_OFFLINEOKNBU_IND |
862 WTPF_OFFLINEOK_COM |
863 WTPF_OFFLINEOK_IND;
864 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
869 /***********************************************************************
870 * WintrustSetRegPolicyFlags (WINTRUST.@)
872 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
874 HKEY key;
875 LONG r;
877 TRACE("%x\n", dwPolicyFlags);
879 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
880 NULL, 0, KEY_WRITE, NULL, &key, NULL);
881 if (!r)
883 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
884 sizeof(DWORD));
885 RegCloseKey(key);
887 if (r) SetLastError(r);
888 return r == ERROR_SUCCESS;
891 /* Utility functions */
892 void * WINAPI WINTRUST_Alloc(DWORD cb)
894 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
897 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
899 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
902 void WINAPI WINTRUST_Free(void *p)
904 HeapFree(GetProcessHeap(), 0, p);
907 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
909 BOOL ret = FALSE;
911 TRACE("(%p, %p)\n", data, store);
913 if (data->chStores)
914 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
915 (data->chStores + 1) * sizeof(HCERTSTORE));
916 else
918 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
919 data->chStores = 0;
921 if (data->pahStores)
923 data->pahStores[data->chStores++] = CertDuplicateStore(store);
924 ret = TRUE;
926 else
927 SetLastError(ERROR_OUTOFMEMORY);
928 return ret;
931 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
932 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
934 BOOL ret = FALSE;
936 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
938 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
940 SetLastError(ERROR_INVALID_PARAMETER);
941 return FALSE;
943 if (fCounterSigner)
945 FIXME("unimplemented for counter signers\n");
946 SetLastError(ERROR_INVALID_PARAMETER);
947 return FALSE;
949 if (data->csSigners)
950 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
951 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
952 else
954 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
955 data->csSigners = 0;
957 if (data->pasSigners)
959 if (idxSigner < data->csSigners)
960 memmove(&data->pasSigners[idxSigner],
961 &data->pasSigners[idxSigner + 1],
962 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
963 ret = TRUE;
964 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
966 /* The PSDK says psSigner should be allocated using pfnAlloc, but
967 * it doesn't say anything about ownership. Since callers are
968 * internal, assume ownership is passed, and just store the
969 * pointer.
971 memcpy(&data->pasSigners[idxSigner], sgnr,
972 sizeof(CRYPT_PROVIDER_SGNR));
974 else
975 memset(&data->pasSigners[idxSigner], 0,
976 sizeof(CRYPT_PROVIDER_SGNR));
977 data->csSigners++;
979 else
980 SetLastError(ERROR_OUTOFMEMORY);
981 return ret;
984 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
985 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
987 BOOL ret = FALSE;
989 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
990 idxSigner, pCert2Add);
992 if (fCounterSigner)
994 FIXME("unimplemented for counter signers\n");
995 SetLastError(ERROR_INVALID_PARAMETER);
996 return FALSE;
998 if (data->pasSigners[idxSigner].csCertChain)
999 data->pasSigners[idxSigner].pasCertChain =
1000 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1001 (data->pasSigners[idxSigner].csCertChain + 1) *
1002 sizeof(CRYPT_PROVIDER_CERT));
1003 else
1005 data->pasSigners[idxSigner].pasCertChain =
1006 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1007 data->pasSigners[idxSigner].csCertChain = 0;
1009 if (data->pasSigners[idxSigner].pasCertChain)
1011 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1012 data->pasSigners[idxSigner].csCertChain];
1014 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1015 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1016 data->pasSigners[idxSigner].csCertChain++;
1017 ret = TRUE;
1019 else
1020 SetLastError(ERROR_OUTOFMEMORY);
1021 return ret;
1024 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1025 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1027 BOOL ret = FALSE;
1029 TRACE("(%p, %p)\n", data, pPrivData2Add);
1031 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1033 SetLastError(ERROR_INVALID_PARAMETER);
1034 WARN("invalid struct size\n");
1035 return FALSE;
1037 if (data->csProvPrivData)
1038 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1039 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1040 else
1042 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1043 data->csProvPrivData = 0;
1045 if (data->pasProvPrivData)
1047 DWORD i;
1049 for (i = 0; i < data->csProvPrivData; i++)
1050 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1051 break;
1053 data->pasProvPrivData[i] = *pPrivData2Add;
1054 if (i == data->csProvPrivData)
1055 data->csProvPrivData++;
1057 else
1058 SetLastError(ERROR_OUTOFMEMORY);
1059 return ret;
1062 /***********************************************************************
1063 * OpenPersonalTrustDBDialog (WINTRUST.@)
1065 * Opens the certificate manager dialog, showing only the stores that
1066 * contain trusted software publishers.
1068 * PARAMS
1069 * hwnd [I] handle of parent window
1071 * RETURNS
1072 * TRUE if the dialog could be opened, FALSE if not.
1074 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1076 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1078 uiCertMgr.dwSize = sizeof(uiCertMgr);
1079 uiCertMgr.hwndParent = hwnd;
1080 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1081 uiCertMgr.pwszTitle = NULL;
1082 uiCertMgr.pszInitUsageOID = NULL;
1083 return CryptUIDlgCertMgr(&uiCertMgr);