push 378fe7a60681a28e8b22f62dcfe122d585b92570
[wine/hacks.git] / dlls / wintrust / wintrust_main.c
blobd6800b85f3402d82b45680cf6d93e56b226b1b46
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 = 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 = 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 = data->pSIPClientData;
258 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
260 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
261 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
262 fileInfo.pcwszFilePath = subjectFile->lpPath;
263 fileInfo.hFile = subjectFile->hFile;
264 wintrust_data.u.pFile = &fileInfo;
265 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
266 wintrust_data.dwUIChoice = WTD_UI_NONE;
268 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
271 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
272 * action is not stored in the registry and is located in wintrust, not in
273 * cryptdlg along with the rest of the implementation (verified by running the
274 * action with a native wintrust.dll.)
276 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
278 BOOL ret;
280 TRACE("(%p)\n", data);
282 if (!data->padwTrustStepErrors)
283 return S_FALSE;
285 switch (data->pWintrustData->dwUnionChoice)
287 case WTD_CHOICE_BLOB:
288 if (data->pWintrustData->u.pBlob &&
289 data->pWintrustData->u.pBlob->cbStruct == sizeof(WINTRUST_BLOB_INFO) &&
290 data->pWintrustData->u.pBlob->cbMemObject ==
291 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
292 data->pWintrustData->u.pBlob->pbMemObject)
294 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
295 (CERT_VERIFY_CERTIFICATE_TRUST *)
296 data->pWintrustData->u.pBlob->pbMemObject;
298 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
299 pCert->pccert)
301 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
302 DWORD i;
303 SYSTEMTIME sysTime;
305 /* Add a signer with nothing but the time to verify, so we can
306 * add a cert to it
308 GetSystemTime(&sysTime);
309 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
310 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
311 if (!ret)
312 goto error;
313 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
314 pCert->pccert);
315 if (!ret)
316 goto error;
317 for (i = 0; ret && i < pCert->cRootStores; i++)
318 ret = data->psPfns->pfnAddStore2Chain(data,
319 pCert->rghstoreRoots[i]);
320 for (i = 0; ret && i < pCert->cStores; i++)
321 ret = data->psPfns->pfnAddStore2Chain(data,
322 pCert->rghstoreCAs[i]);
323 for (i = 0; ret && i < pCert->cTrustStores; i++)
324 ret = data->psPfns->pfnAddStore2Chain(data,
325 pCert->rghstoreTrust[i]);
327 else
329 SetLastError(ERROR_INVALID_PARAMETER);
330 ret = FALSE;
333 else
335 SetLastError(ERROR_INVALID_PARAMETER);
336 ret = FALSE;
338 break;
339 default:
340 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
341 SetLastError(ERROR_INVALID_PARAMETER);
342 ret = FALSE;
345 error:
346 if (!ret)
347 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
348 GetLastError();
349 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
350 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
351 return ret ? S_OK : S_FALSE;
354 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
355 WINTRUST_DATA *data)
357 DWORD err = ERROR_SUCCESS, numSteps = 0;
358 CRYPT_PROVIDER_DATA *provData;
359 BOOL ret;
360 struct wintrust_step verifySteps[5];
362 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
364 provData = WINTRUST_AllocateProviderData();
365 if (!provData)
366 return ERROR_OUTOFMEMORY;
368 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
369 if (!ret)
371 err = GetLastError();
372 goto error;
374 if (!provData->psPfns->pfnObjectTrust)
375 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
376 /* Not sure why, but native skips the policy check */
377 provData->psPfns->pfnCertCheckPolicy = NULL;
379 data->hWVTStateData = provData;
380 provData->pWintrustData = data;
381 if (hwnd == INVALID_HANDLE_VALUE)
382 provData->hWndParent = GetDesktopWindow();
383 else
384 provData->hWndParent = hwnd;
385 provData->pgActionID = actionID;
386 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
388 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
389 provData->psPfns);
390 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
391 goto done;
393 error:
394 if (provData)
396 WINTRUST_Free(provData->padwTrustStepErrors);
397 WINTRUST_Free(provData->u.pPDSip);
398 WINTRUST_Free(provData->psPfns);
399 WINTRUST_Free(provData);
401 done:
402 TRACE("returning %08x\n", err);
403 return err;
406 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
407 WINTRUST_DATA *data)
409 LONG err;
411 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
413 err = WINTRUST_CertVerify(hwnd, actionID, data);
414 WINTRUST_DefaultClose(hwnd, actionID, data);
415 TRACE("returning %08x\n", err);
416 return err;
419 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
420 WINTRUST_DATA *data)
422 DWORD stateAction;
423 LONG err = ERROR_SUCCESS;
425 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
426 stateAction = data->dwStateAction;
427 else
429 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
430 stateAction = WTD_STATEACTION_IGNORE;
432 switch (stateAction)
434 case WTD_STATEACTION_IGNORE:
435 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
436 break;
437 case WTD_STATEACTION_VERIFY:
438 err = WINTRUST_CertVerify(hwnd, actionID, data);
439 break;
440 case WTD_STATEACTION_CLOSE:
441 err = WINTRUST_DefaultClose(hwnd, actionID, data);
442 break;
443 default:
444 FIXME("unimplemented for %d\n", data->dwStateAction);
446 return err;
449 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
451 TRACE("%p\n", pFile);
452 if (pFile)
454 TRACE("cbStruct: %d\n", pFile->cbStruct);
455 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
456 TRACE("hFile: %p\n", pFile->hFile);
457 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
461 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
463 TRACE("%p\n", catalog);
464 if (catalog)
466 TRACE("cbStruct: %d\n", catalog->cbStruct);
467 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
468 TRACE("pcwszCatalogFilePath: %s\n",
469 debugstr_w(catalog->pcwszCatalogFilePath));
470 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
471 TRACE("pcwszMemberFilePath: %s\n",
472 debugstr_w(catalog->pcwszMemberFilePath));
473 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
474 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
475 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
476 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
480 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
482 TRACE("%p\n", blob);
483 if (blob)
485 TRACE("cbStruct: %d\n", blob->cbStruct);
486 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
487 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
488 TRACE("cbMemObject: %d\n", blob->cbMemObject);
489 TRACE("pbMemObject: %p\n", blob->pbMemObject);
490 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
491 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
495 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
497 TRACE("%p\n", sgnr);
498 if (sgnr)
500 TRACE("cbStruct: %d\n", sgnr->cbStruct);
501 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
502 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
503 TRACE("chStores: %d\n", sgnr->chStores);
507 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
509 TRACE("%p\n", cert);
510 if (cert)
512 TRACE("cbStruct: %d\n", cert->cbStruct);
513 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
514 TRACE("psCertContext: %p\n", cert->psCertContext);
515 TRACE("chStores: %d\n", cert->chStores);
516 TRACE("dwFlags: %08x\n", cert->dwFlags);
517 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
521 static void dump_wintrust_data(WINTRUST_DATA *data)
523 TRACE("%p\n", data);
524 if (data)
526 TRACE("cbStruct: %d\n", data->cbStruct);
527 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
528 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
529 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
530 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
531 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
532 switch (data->dwUnionChoice)
534 case WTD_CHOICE_FILE:
535 dump_file_info(data->u.pFile);
536 break;
537 case WTD_CHOICE_CATALOG:
538 dump_catalog_info(data->u.pCatalog);
539 break;
540 case WTD_CHOICE_BLOB:
541 dump_blob_info(data->u.pBlob);
542 break;
543 case WTD_CHOICE_SIGNER:
544 dump_sgnr_info(data->u.pSgnr);
545 break;
546 case WTD_CHOICE_CERT:
547 dump_cert_info(data->u.pCert);
548 break;
550 TRACE("dwStateAction: %d\n", data->dwStateAction);
551 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
552 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
553 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
554 TRACE("dwUIContext: %d\n", data->dwUIContext);
558 /***********************************************************************
559 * WinVerifyTrust (WINTRUST.@)
561 * Verifies an object by calling the specified trust provider.
563 * PARAMS
564 * hwnd [I] Handle to a caller window.
565 * ActionID [I] Pointer to a GUID that identifies the action to perform.
566 * ActionData [I] Information used by the trust provider to verify the object.
568 * RETURNS
569 * Success: Zero.
570 * Failure: A TRUST_E_* error code.
572 * NOTES
573 * Trust providers can be found at:
574 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
576 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
578 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
579 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
580 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
581 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
582 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
583 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
584 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
585 LONG err = ERROR_SUCCESS;
586 WINTRUST_DATA *actionData = ActionData;
588 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
589 dump_wintrust_data(ActionData);
591 /* Support for known old-style callers: */
592 if (IsEqualGUID(ActionID, &published_software))
593 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
594 else if (IsEqualGUID(ActionID, &cert_action_verify))
595 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
596 else
598 DWORD stateAction;
600 /* Check known actions to warn of possible problems */
601 if (!IsEqualGUID(ActionID, &unknown) &&
602 !IsEqualGUID(ActionID, &generic_verify_v2) &&
603 !IsEqualGUID(ActionID, &generic_cert_verify) &&
604 !IsEqualGUID(ActionID, &generic_chain_verify))
605 WARN("unknown action %s, default behavior may not be right\n",
606 debugstr_guid(ActionID));
607 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
608 stateAction = actionData->dwStateAction;
609 else
611 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
612 stateAction = WTD_STATEACTION_IGNORE;
614 switch (stateAction)
616 case WTD_STATEACTION_IGNORE:
617 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
618 break;
619 case WTD_STATEACTION_VERIFY:
620 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
621 break;
622 case WTD_STATEACTION_CLOSE:
623 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
624 break;
625 default:
626 FIXME("unimplemented for %d\n", actionData->dwStateAction);
630 TRACE("returning %08x\n", err);
631 return err;
634 /***********************************************************************
635 * WinVerifyTrustEx (WINTRUST.@)
637 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
638 WINTRUST_DATA* ActionData )
640 return WinVerifyTrust(hwnd, ActionID, ActionData);
643 /***********************************************************************
644 * WTHelperGetProvSignerFromChain (WINTRUST.@)
646 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
647 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
648 DWORD idxCounterSigner)
650 CRYPT_PROVIDER_SGNR *sgnr;
652 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
653 idxCounterSigner);
655 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
656 return NULL;
657 sgnr = &pProvData->pasSigners[idxSigner];
658 if (fCounterSigner)
660 if (idxCounterSigner >= sgnr->csCounterSigners ||
661 !sgnr->pasCounterSigners)
662 return NULL;
663 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
665 TRACE("returning %p\n", sgnr);
666 return sgnr;
669 /***********************************************************************
670 * WTHelperGetProvCertFromChain (WINTRUST.@)
672 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
673 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
675 CRYPT_PROVIDER_CERT *cert;
677 TRACE("(%p %d)\n", pSgnr, idxCert);
679 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
680 return NULL;
681 cert = &pSgnr->pasCertChain[idxCert];
682 TRACE("returning %p\n", cert);
683 return cert;
686 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
687 CRYPT_PROVIDER_DATA* pProvData,
688 GUID* pgProviderID)
690 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
691 DWORD i;
693 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
695 for (i = 0; i < pProvData->csProvPrivData; i++)
696 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
698 privdata = &pProvData->pasProvPrivData[i];
699 break;
702 return privdata;
705 /***********************************************************************
706 * WTHelperProvDataFromStateData (WINTRUST.@)
708 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
710 TRACE("%p\n", hStateData);
711 return hStateData;
714 /***********************************************************************
715 * WTHelperGetFileName(WINTRUST.@)
717 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
719 TRACE("%p\n",data);
720 if (data->dwUnionChoice == WTD_CHOICE_FILE)
721 return data->u.pFile->pcwszFilePath;
722 else
723 return NULL;
726 /***********************************************************************
727 * WTHelperGetFileHandle(WINTRUST.@)
729 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
731 TRACE("%p\n",data);
732 if (data->dwUnionChoice == WTD_CHOICE_FILE)
733 return data->u.pFile->hFile;
734 else
735 return INVALID_HANDLE_VALUE;
738 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
740 PCCRYPT_OID_INFO **usages = pvArg;
741 DWORD cUsages;
742 BOOL ret;
744 if (!*usages)
746 cUsages = 0;
747 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
749 else
751 PCCRYPT_OID_INFO *ptr;
753 /* Count the existing usages.
754 * FIXME: make sure the new usage doesn't duplicate any in the list?
756 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
758 *usages = WINTRUST_ReAlloc(*usages,
759 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
761 if (*usages)
763 (*usages)[cUsages] = pInfo;
764 (*usages)[cUsages + 1] = NULL;
765 ret = TRUE;
767 else
769 SetLastError(ERROR_OUTOFMEMORY);
770 ret = FALSE;
772 return ret;
775 /***********************************************************************
776 * WTHelperGetKnownUsages(WINTRUST.@)
778 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
780 * PARAMS
781 * action [In] 1 => allocate and return known usages, 2 => free previously
782 * allocated usages.
783 * usages [In/Out] If action == 1, *usages is set to an array of
784 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
785 * pointer.
786 * If action == 2, *usages is freed.
788 * RETURNS
789 * TRUE on success, FALSE on failure.
791 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
793 BOOL ret;
795 TRACE("(%d, %p)\n", action, usages);
797 if (!usages)
799 SetLastError(ERROR_INVALID_PARAMETER);
800 return FALSE;
803 if (action == 1)
805 *usages = NULL;
806 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
807 WINTRUST_enumUsages);
809 else if (action == 2)
811 WINTRUST_Free(*usages);
812 *usages = NULL;
813 ret = TRUE;
815 else
817 WARN("unknown action %d\n", action);
818 SetLastError(ERROR_INVALID_PARAMETER);
819 ret = FALSE;
821 return ret;
824 static const WCHAR Software_Publishing[] = {
825 'S','o','f','t','w','a','r','e','\\',
826 'M','i','c','r','o','s','o','f','t','\\',
827 'W','i','n','d','o','w','s','\\',
828 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
829 'W','i','n','t','r','u','s','t','\\',
830 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
831 'S','o','f','t','w','a','r','e',' ',
832 'P','u','b','l','i','s','h','i','n','g',0 };
833 static const WCHAR State[] = { 'S','t','a','t','e',0 };
835 /***********************************************************************
836 * WintrustGetRegPolicyFlags (WINTRUST.@)
838 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
840 HKEY key;
841 LONG r;
843 TRACE("%p\n", pdwPolicyFlags);
845 *pdwPolicyFlags = 0;
846 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
847 KEY_READ, NULL, &key, NULL);
848 if (!r)
850 DWORD size = sizeof(DWORD);
852 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
853 &size);
854 RegCloseKey(key);
855 if (r)
857 /* Failed to query, create and return default value */
858 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
859 WTPF_OFFLINEOKNBU_COM |
860 WTPF_OFFLINEOKNBU_IND |
861 WTPF_OFFLINEOK_COM |
862 WTPF_OFFLINEOK_IND;
863 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
868 /***********************************************************************
869 * WintrustSetRegPolicyFlags (WINTRUST.@)
871 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
873 HKEY key;
874 LONG r;
876 TRACE("%x\n", dwPolicyFlags);
878 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
879 NULL, 0, KEY_WRITE, NULL, &key, NULL);
880 if (!r)
882 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
883 sizeof(DWORD));
884 RegCloseKey(key);
886 if (r) SetLastError(r);
887 return r == ERROR_SUCCESS;
890 /* Utility functions */
891 void * WINAPI WINTRUST_Alloc(DWORD cb)
893 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
896 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
898 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
901 void WINAPI WINTRUST_Free(void *p)
903 HeapFree(GetProcessHeap(), 0, p);
906 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
908 BOOL ret = FALSE;
910 TRACE("(%p, %p)\n", data, store);
912 if (data->chStores)
913 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
914 (data->chStores + 1) * sizeof(HCERTSTORE));
915 else
917 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
918 data->chStores = 0;
920 if (data->pahStores)
922 data->pahStores[data->chStores++] = CertDuplicateStore(store);
923 ret = TRUE;
925 else
926 SetLastError(ERROR_OUTOFMEMORY);
927 return ret;
930 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
931 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
933 BOOL ret = FALSE;
935 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
937 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
939 SetLastError(ERROR_INVALID_PARAMETER);
940 return FALSE;
942 if (fCounterSigner)
944 FIXME("unimplemented for counter signers\n");
945 SetLastError(ERROR_INVALID_PARAMETER);
946 return FALSE;
948 if (data->csSigners)
949 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
950 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
951 else
953 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
954 data->csSigners = 0;
956 if (data->pasSigners)
958 if (idxSigner < data->csSigners)
959 memmove(&data->pasSigners[idxSigner],
960 &data->pasSigners[idxSigner + 1],
961 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
962 ret = TRUE;
963 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
965 /* The PSDK says psSigner should be allocated using pfnAlloc, but
966 * it doesn't say anything about ownership. Since callers are
967 * internal, assume ownership is passed, and just store the
968 * pointer.
970 memcpy(&data->pasSigners[idxSigner], sgnr,
971 sizeof(CRYPT_PROVIDER_SGNR));
973 else
974 memset(&data->pasSigners[idxSigner], 0,
975 sizeof(CRYPT_PROVIDER_SGNR));
976 data->csSigners++;
978 else
979 SetLastError(ERROR_OUTOFMEMORY);
980 return ret;
983 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
984 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
986 BOOL ret = FALSE;
988 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
989 idxSigner, pCert2Add);
991 if (fCounterSigner)
993 FIXME("unimplemented for counter signers\n");
994 SetLastError(ERROR_INVALID_PARAMETER);
995 return FALSE;
997 if (data->pasSigners[idxSigner].csCertChain)
998 data->pasSigners[idxSigner].pasCertChain =
999 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1000 (data->pasSigners[idxSigner].csCertChain + 1) *
1001 sizeof(CRYPT_PROVIDER_CERT));
1002 else
1004 data->pasSigners[idxSigner].pasCertChain =
1005 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1006 data->pasSigners[idxSigner].csCertChain = 0;
1008 if (data->pasSigners[idxSigner].pasCertChain)
1010 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1011 data->pasSigners[idxSigner].csCertChain];
1013 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1014 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1015 data->pasSigners[idxSigner].csCertChain++;
1016 ret = TRUE;
1018 else
1019 SetLastError(ERROR_OUTOFMEMORY);
1020 return ret;
1023 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1024 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1026 BOOL ret = FALSE;
1028 TRACE("(%p, %p)\n", data, pPrivData2Add);
1030 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1032 SetLastError(ERROR_INVALID_PARAMETER);
1033 WARN("invalid struct size\n");
1034 return FALSE;
1036 if (data->csProvPrivData)
1037 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1038 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1039 else
1041 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1042 data->csProvPrivData = 0;
1044 if (data->pasProvPrivData)
1046 DWORD i;
1048 for (i = 0; i < data->csProvPrivData; i++)
1049 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1050 break;
1052 data->pasProvPrivData[i] = *pPrivData2Add;
1053 if (i == data->csProvPrivData)
1054 data->csProvPrivData++;
1056 else
1057 SetLastError(ERROR_OUTOFMEMORY);
1058 return ret;
1061 /***********************************************************************
1062 * OpenPersonalTrustDBDialog (WINTRUST.@)
1064 * Opens the certificate manager dialog, showing only the stores that
1065 * contain trusted software publishers.
1067 * PARAMS
1068 * hwnd [I] handle of parent window
1070 * RETURNS
1071 * TRUE if the dialog could be opened, FALSE if not.
1073 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1075 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1077 uiCertMgr.dwSize = sizeof(uiCertMgr);
1078 uiCertMgr.hwndParent = hwnd;
1079 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1080 uiCertMgr.pwszTitle = NULL;
1081 uiCertMgr.pszInitUsageOID = NULL;
1082 return CryptUIDlgCertMgr(&uiCertMgr);