wineconsole: Leave room for wide characters only when using a DBCS codepage.
[wine.git] / dlls / wintrust / wintrust_main.c
blob58e3ac39c007cfc876ebb814bc1c77ff45fbd6db
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 * TrustIsCertificateSelfSigned (WINTRUST.@)
64 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
66 PCERT_EXTENSION ext;
67 DWORD size;
68 BOOL ret;
70 TRACE("%p\n", cert);
71 if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2,
72 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
74 CERT_AUTHORITY_KEY_ID2_INFO *info;
76 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
77 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
78 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
79 &info, &size);
80 if (ret)
82 if (info->AuthorityCertIssuer.cAltEntry &&
83 info->AuthorityCertSerialNumber.cbData)
85 PCERT_ALT_NAME_ENTRY directoryName = NULL;
86 DWORD i;
88 for (i = 0; !directoryName &&
89 i < info->AuthorityCertIssuer.cAltEntry; i++)
90 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
91 == CERT_ALT_NAME_DIRECTORY_NAME)
92 directoryName =
93 &info->AuthorityCertIssuer.rgAltEntry[i];
94 if (directoryName)
96 ret = CertCompareCertificateName(cert->dwCertEncodingType,
97 &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer)
98 && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber,
99 &cert->pCertInfo->SerialNumber);
101 else
103 FIXME("no supported name type in authority key id2\n");
104 ret = FALSE;
107 else if (info->KeyId.cbData)
109 ret = CertGetCertificateContextProperty(cert,
110 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
111 if (ret && size == info->KeyId.cbData)
113 LPBYTE buf = CryptMemAlloc(size);
115 if (buf)
117 CertGetCertificateContextProperty(cert,
118 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
119 ret = !memcmp(buf, info->KeyId.pbData, size);
120 CryptMemFree(buf);
122 else
123 ret = FALSE;
125 else
126 ret = FALSE;
128 LocalFree(info);
131 else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER,
132 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
134 CERT_AUTHORITY_KEY_ID_INFO *info;
136 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
137 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
138 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
139 &info, &size);
140 if (ret)
142 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
144 ret = CertCompareCertificateName(cert->dwCertEncodingType,
145 &info->CertIssuer, &cert->pCertInfo->Issuer) &&
146 CertCompareIntegerBlob(&info->CertSerialNumber,
147 &cert->pCertInfo->SerialNumber);
149 else if (info->KeyId.cbData)
151 ret = CertGetCertificateContextProperty(cert,
152 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
153 if (ret && size == info->KeyId.cbData)
155 LPBYTE buf = CryptMemAlloc(size);
157 if (buf)
159 CertGetCertificateContextProperty(cert,
160 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
161 ret = !memcmp(buf, info->KeyId.pbData, size);
162 CryptMemFree(buf);
164 else
165 ret = FALSE;
167 else
168 ret = FALSE;
170 else
171 ret = FALSE;
172 LocalFree(info);
175 else
176 ret = CertCompareCertificateName(cert->dwCertEncodingType,
177 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
178 return ret;
181 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
183 struct wintrust_step
185 wintrust_step_func func;
186 DWORD error_index;
189 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
190 DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
192 DWORD i, err = ERROR_SUCCESS;
194 for (i = 0; !err && i < numSteps; i++)
196 err = steps[i].func(provData);
197 if (err)
198 err = provData->padwTrustStepErrors[steps[i].error_index];
200 return err;
203 static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
205 CRYPT_PROVIDER_DATA *provData;
207 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
208 if (!provData)
209 goto oom;
210 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
212 provData->padwTrustStepErrors =
213 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
214 if (!provData->padwTrustStepErrors)
215 goto oom;
216 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
218 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
219 if (!provData->u.pPDSip)
220 goto oom;
221 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
223 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
224 if (!provData->psPfns)
225 goto oom;
226 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
227 return provData;
229 oom:
230 if (provData)
232 WINTRUST_Free(provData->padwTrustStepErrors);
233 WINTRUST_Free(provData->u.pPDSip);
234 WINTRUST_Free(provData->psPfns);
235 WINTRUST_Free(provData);
237 return NULL;
240 /* Adds trust steps for each function in psPfns. Assumes steps has at least
241 * 5 entries. Returns the number of steps added.
243 static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
244 const CRYPT_PROVIDER_FUNCTIONS *psPfns)
246 DWORD numSteps = 0;
248 if (psPfns->pfnInitialize)
250 steps[numSteps].func = psPfns->pfnInitialize;
251 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
253 if (psPfns->pfnObjectTrust)
255 steps[numSteps].func = psPfns->pfnObjectTrust;
256 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
258 if (psPfns->pfnSignatureTrust)
260 steps[numSteps].func = psPfns->pfnSignatureTrust;
261 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
263 if (psPfns->pfnCertificateTrust)
265 steps[numSteps].func = psPfns->pfnCertificateTrust;
266 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
268 if (psPfns->pfnFinalPolicy)
270 steps[numSteps].func = psPfns->pfnFinalPolicy;
271 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
273 return numSteps;
276 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
277 WINTRUST_DATA *data)
279 DWORD err = ERROR_SUCCESS, numSteps = 0;
280 CRYPT_PROVIDER_DATA *provData;
281 BOOL ret;
282 struct wintrust_step verifySteps[5];
284 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
286 provData = WINTRUST_AllocateProviderData();
287 if (!provData)
288 return ERROR_OUTOFMEMORY;
290 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
291 if (!ret)
293 err = GetLastError();
294 goto error;
297 data->hWVTStateData = provData;
298 provData->pWintrustData = data;
299 if (hwnd == INVALID_HANDLE_VALUE)
300 provData->hWndParent = GetDesktopWindow();
301 else
302 provData->hWndParent = hwnd;
303 provData->pgActionID = actionID;
304 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
306 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
307 provData->psPfns);
308 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
309 goto done;
311 error:
312 if (provData)
314 WINTRUST_Free(provData->padwTrustStepErrors);
315 WINTRUST_Free(provData->u.pPDSip);
316 WINTRUST_Free(provData->psPfns);
317 WINTRUST_Free(provData);
319 done:
320 TRACE("returning %08x\n", err);
321 return err;
324 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
325 WINTRUST_DATA *data)
327 DWORD err = ERROR_SUCCESS;
328 CRYPT_PROVIDER_DATA *provData = data->hWVTStateData;
330 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
332 if (provData)
334 if (provData->psPfns->pfnCleanupPolicy)
335 err = provData->psPfns->pfnCleanupPolicy(provData);
337 WINTRUST_Free(provData->padwTrustStepErrors);
338 WINTRUST_Free(provData->u.pPDSip);
339 WINTRUST_Free(provData->psPfns);
340 WINTRUST_Free(provData);
341 data->hWVTStateData = NULL;
343 TRACE("returning %08x\n", err);
344 return err;
347 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
348 WINTRUST_DATA *data)
350 LONG err;
352 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
354 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
355 WINTRUST_DefaultClose(hwnd, actionID, data);
356 TRACE("returning %08x\n", err);
357 return err;
360 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
361 WINTRUST_DATA *data)
363 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
364 /* Undocumented: the published software action is passed a path,
365 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
367 LPWIN_TRUST_SUBJECT_FILE subjectFile = data->pSIPClientData;
368 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
370 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
371 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
372 fileInfo.pcwszFilePath = subjectFile->lpPath;
373 fileInfo.hFile = subjectFile->hFile;
374 wintrust_data.u.pFile = &fileInfo;
375 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
376 wintrust_data.dwUIChoice = WTD_UI_NONE;
378 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
381 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
382 * action is not stored in the registry and is located in wintrust, not in
383 * cryptdlg along with the rest of the implementation (verified by running the
384 * action with a native wintrust.dll.)
386 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
388 BOOL ret;
390 TRACE("(%p)\n", data);
392 if (!data->padwTrustStepErrors)
393 return S_FALSE;
395 switch (data->pWintrustData->dwUnionChoice)
397 case WTD_CHOICE_BLOB:
398 if (data->pWintrustData->u.pBlob &&
399 WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO,
400 data->pWintrustData->u.pBlob->cbStruct, pbMemObject) &&
401 data->pWintrustData->u.pBlob->cbMemObject ==
402 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
403 data->pWintrustData->u.pBlob->pbMemObject)
405 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
406 (CERT_VERIFY_CERTIFICATE_TRUST *)
407 data->pWintrustData->u.pBlob->pbMemObject;
409 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
410 pCert->pccert)
412 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
413 DWORD i;
414 SYSTEMTIME sysTime;
416 /* Add a signer with nothing but the time to verify, so we can
417 * add a cert to it
419 GetSystemTime(&sysTime);
420 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
421 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
422 if (!ret)
423 goto error;
424 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
425 pCert->pccert);
426 if (!ret)
427 goto error;
428 for (i = 0; ret && i < pCert->cRootStores; i++)
429 ret = data->psPfns->pfnAddStore2Chain(data,
430 pCert->rghstoreRoots[i]);
431 for (i = 0; ret && i < pCert->cStores; i++)
432 ret = data->psPfns->pfnAddStore2Chain(data,
433 pCert->rghstoreCAs[i]);
434 for (i = 0; ret && i < pCert->cTrustStores; i++)
435 ret = data->psPfns->pfnAddStore2Chain(data,
436 pCert->rghstoreTrust[i]);
438 else
440 SetLastError(ERROR_INVALID_PARAMETER);
441 ret = FALSE;
444 else
446 SetLastError(ERROR_INVALID_PARAMETER);
447 ret = FALSE;
449 break;
450 default:
451 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
452 SetLastError(ERROR_INVALID_PARAMETER);
453 ret = FALSE;
456 error:
457 if (!ret)
458 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
459 GetLastError();
460 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
461 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
462 return ret ? S_OK : S_FALSE;
465 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
466 WINTRUST_DATA *data)
468 DWORD err = ERROR_SUCCESS, numSteps = 0;
469 CRYPT_PROVIDER_DATA *provData;
470 BOOL ret;
471 struct wintrust_step verifySteps[5];
473 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
475 provData = WINTRUST_AllocateProviderData();
476 if (!provData)
477 return ERROR_OUTOFMEMORY;
479 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
480 if (!ret)
482 err = GetLastError();
483 goto error;
485 if (!provData->psPfns->pfnObjectTrust)
486 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
487 /* Not sure why, but native skips the policy check */
488 provData->psPfns->pfnCertCheckPolicy = NULL;
490 data->hWVTStateData = provData;
491 provData->pWintrustData = data;
492 if (hwnd == INVALID_HANDLE_VALUE)
493 provData->hWndParent = GetDesktopWindow();
494 else
495 provData->hWndParent = hwnd;
496 provData->pgActionID = actionID;
497 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
499 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
500 provData->psPfns);
501 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
502 goto done;
504 error:
505 if (provData)
507 WINTRUST_Free(provData->padwTrustStepErrors);
508 WINTRUST_Free(provData->u.pPDSip);
509 WINTRUST_Free(provData->psPfns);
510 WINTRUST_Free(provData);
512 done:
513 TRACE("returning %08x\n", err);
514 return err;
517 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
518 WINTRUST_DATA *data)
520 LONG err;
522 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
524 err = WINTRUST_CertVerify(hwnd, actionID, data);
525 WINTRUST_DefaultClose(hwnd, actionID, data);
526 TRACE("returning %08x\n", err);
527 return err;
530 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
531 WINTRUST_DATA *data)
533 DWORD stateAction;
534 LONG err = ERROR_SUCCESS;
536 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
537 stateAction = data->dwStateAction;
538 else
540 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
541 stateAction = WTD_STATEACTION_IGNORE;
543 switch (stateAction)
545 case WTD_STATEACTION_IGNORE:
546 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
547 break;
548 case WTD_STATEACTION_VERIFY:
549 err = WINTRUST_CertVerify(hwnd, actionID, data);
550 break;
551 case WTD_STATEACTION_CLOSE:
552 err = WINTRUST_DefaultClose(hwnd, actionID, data);
553 break;
554 default:
555 FIXME("unimplemented for %d\n", data->dwStateAction);
557 return err;
560 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
562 TRACE("%p\n", pFile);
563 if (pFile)
565 TRACE("cbStruct: %d\n", pFile->cbStruct);
566 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
567 TRACE("hFile: %p\n", pFile->hFile);
568 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
572 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
574 TRACE("%p\n", catalog);
575 if (catalog)
577 TRACE("cbStruct: %d\n", catalog->cbStruct);
578 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
579 TRACE("pcwszCatalogFilePath: %s\n",
580 debugstr_w(catalog->pcwszCatalogFilePath));
581 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
582 TRACE("pcwszMemberFilePath: %s\n",
583 debugstr_w(catalog->pcwszMemberFilePath));
584 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
585 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
586 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
587 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
591 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
593 TRACE("%p\n", blob);
594 if (blob)
596 TRACE("cbStruct: %d\n", blob->cbStruct);
597 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
598 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
599 TRACE("cbMemObject: %d\n", blob->cbMemObject);
600 TRACE("pbMemObject: %p\n", blob->pbMemObject);
601 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
602 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
606 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
608 TRACE("%p\n", sgnr);
609 if (sgnr)
611 TRACE("cbStruct: %d\n", sgnr->cbStruct);
612 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
613 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
614 TRACE("chStores: %d\n", sgnr->chStores);
618 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
620 TRACE("%p\n", cert);
621 if (cert)
623 TRACE("cbStruct: %d\n", cert->cbStruct);
624 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
625 TRACE("psCertContext: %p\n", cert->psCertContext);
626 TRACE("chStores: %d\n", cert->chStores);
627 TRACE("dwFlags: %08x\n", cert->dwFlags);
628 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
632 static void dump_wintrust_data(WINTRUST_DATA *data)
634 TRACE("%p\n", data);
635 if (data)
637 TRACE("cbStruct: %d\n", data->cbStruct);
638 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
639 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
640 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
641 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
642 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
643 switch (data->dwUnionChoice)
645 case WTD_CHOICE_FILE:
646 dump_file_info(data->u.pFile);
647 break;
648 case WTD_CHOICE_CATALOG:
649 dump_catalog_info(data->u.pCatalog);
650 break;
651 case WTD_CHOICE_BLOB:
652 dump_blob_info(data->u.pBlob);
653 break;
654 case WTD_CHOICE_SIGNER:
655 dump_sgnr_info(data->u.pSgnr);
656 break;
657 case WTD_CHOICE_CERT:
658 dump_cert_info(data->u.pCert);
659 break;
661 TRACE("dwStateAction: %d\n", data->dwStateAction);
662 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
663 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
664 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
665 TRACE("dwUIContext: %d\n", data->dwUIContext);
669 /***********************************************************************
670 * WinVerifyTrust (WINTRUST.@)
672 * Verifies an object by calling the specified trust provider.
674 * PARAMS
675 * hwnd [I] Handle to a caller window.
676 * ActionID [I] Pointer to a GUID that identifies the action to perform.
677 * ActionData [I] Information used by the trust provider to verify the object.
679 * RETURNS
680 * Success: Zero.
681 * Failure: A TRUST_E_* error code.
683 * NOTES
684 * Trust providers can be found at:
685 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
687 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
689 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
690 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
691 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
692 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
693 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
694 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
695 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
696 LONG err = ERROR_SUCCESS;
697 WINTRUST_DATA *actionData = ActionData;
699 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
700 dump_wintrust_data(ActionData);
702 /* Support for known old-style callers: */
703 if (IsEqualGUID(ActionID, &published_software))
704 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
705 else if (IsEqualGUID(ActionID, &cert_action_verify))
706 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
707 else
709 DWORD stateAction;
711 /* Check known actions to warn of possible problems */
712 if (!IsEqualGUID(ActionID, &unknown) &&
713 !IsEqualGUID(ActionID, &generic_verify_v2) &&
714 !IsEqualGUID(ActionID, &generic_cert_verify) &&
715 !IsEqualGUID(ActionID, &generic_chain_verify))
716 WARN("unknown action %s, default behavior may not be right\n",
717 debugstr_guid(ActionID));
718 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
719 stateAction = actionData->dwStateAction;
720 else
722 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
723 stateAction = WTD_STATEACTION_IGNORE;
725 switch (stateAction)
727 case WTD_STATEACTION_IGNORE:
728 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
729 break;
730 case WTD_STATEACTION_VERIFY:
731 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
732 break;
733 case WTD_STATEACTION_CLOSE:
734 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
735 break;
736 default:
737 FIXME("unimplemented for %d\n", actionData->dwStateAction);
741 TRACE("returning %08x\n", err);
742 return err;
745 /***********************************************************************
746 * WinVerifyTrustEx (WINTRUST.@)
748 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
749 WINTRUST_DATA* ActionData )
751 return WinVerifyTrust(hwnd, ActionID, ActionData);
754 /***********************************************************************
755 * WTHelperGetProvSignerFromChain (WINTRUST.@)
757 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
758 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
759 DWORD idxCounterSigner)
761 CRYPT_PROVIDER_SGNR *sgnr;
763 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
764 idxCounterSigner);
766 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
767 return NULL;
768 sgnr = &pProvData->pasSigners[idxSigner];
769 if (fCounterSigner)
771 if (idxCounterSigner >= sgnr->csCounterSigners ||
772 !sgnr->pasCounterSigners)
773 return NULL;
774 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
776 TRACE("returning %p\n", sgnr);
777 return sgnr;
780 /***********************************************************************
781 * WTHelperGetProvCertFromChain (WINTRUST.@)
783 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
784 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
786 CRYPT_PROVIDER_CERT *cert;
788 TRACE("(%p %d)\n", pSgnr, idxCert);
790 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
791 return NULL;
792 cert = &pSgnr->pasCertChain[idxCert];
793 TRACE("returning %p\n", cert);
794 return cert;
797 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
798 CRYPT_PROVIDER_DATA* pProvData,
799 GUID* pgProviderID)
801 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
802 DWORD i;
804 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
806 for (i = 0; i < pProvData->csProvPrivData; i++)
807 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
809 privdata = &pProvData->pasProvPrivData[i];
810 break;
813 return privdata;
816 /***********************************************************************
817 * WTHelperProvDataFromStateData (WINTRUST.@)
819 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
821 TRACE("%p\n", hStateData);
822 return hStateData;
825 /***********************************************************************
826 * WTHelperGetFileName(WINTRUST.@)
828 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
830 TRACE("%p\n",data);
831 if (data->dwUnionChoice == WTD_CHOICE_FILE)
832 return data->u.pFile->pcwszFilePath;
833 else
834 return NULL;
837 /***********************************************************************
838 * WTHelperGetFileHandle(WINTRUST.@)
840 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
842 TRACE("%p\n",data);
843 if (data->dwUnionChoice == WTD_CHOICE_FILE)
844 return data->u.pFile->hFile;
845 else
846 return INVALID_HANDLE_VALUE;
849 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
851 PCCRYPT_OID_INFO **usages = pvArg;
852 DWORD cUsages;
853 BOOL ret;
855 if (!*usages)
857 cUsages = 0;
858 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
860 else
862 PCCRYPT_OID_INFO *ptr;
864 /* Count the existing usages.
865 * FIXME: make sure the new usage doesn't duplicate any in the list?
867 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
869 *usages = WINTRUST_ReAlloc(*usages,
870 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
872 if (*usages)
874 (*usages)[cUsages] = pInfo;
875 (*usages)[cUsages + 1] = NULL;
876 ret = TRUE;
878 else
880 SetLastError(ERROR_OUTOFMEMORY);
881 ret = FALSE;
883 return ret;
886 /***********************************************************************
887 * WTHelperGetKnownUsages(WINTRUST.@)
889 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
891 * PARAMS
892 * action [In] 1 => allocate and return known usages, 2 => free previously
893 * allocated usages.
894 * usages [In/Out] If action == 1, *usages is set to an array of
895 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
896 * pointer.
897 * If action == 2, *usages is freed.
899 * RETURNS
900 * TRUE on success, FALSE on failure.
902 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
904 BOOL ret;
906 TRACE("(%d, %p)\n", action, usages);
908 if (!usages)
910 SetLastError(ERROR_INVALID_PARAMETER);
911 return FALSE;
914 if (action == 1)
916 *usages = NULL;
917 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
918 WINTRUST_enumUsages);
920 else if (action == 2)
922 WINTRUST_Free(*usages);
923 *usages = NULL;
924 ret = TRUE;
926 else
928 WARN("unknown action %d\n", action);
929 SetLastError(ERROR_INVALID_PARAMETER);
930 ret = FALSE;
932 return ret;
935 static const WCHAR Software_Publishing[] = {
936 'S','o','f','t','w','a','r','e','\\',
937 'M','i','c','r','o','s','o','f','t','\\',
938 'W','i','n','d','o','w','s','\\',
939 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
940 'W','i','n','t','r','u','s','t','\\',
941 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
942 'S','o','f','t','w','a','r','e',' ',
943 'P','u','b','l','i','s','h','i','n','g',0 };
944 static const WCHAR State[] = { 'S','t','a','t','e',0 };
946 /***********************************************************************
947 * WintrustGetRegPolicyFlags (WINTRUST.@)
949 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
951 HKEY key;
952 LONG r;
954 TRACE("%p\n", pdwPolicyFlags);
956 *pdwPolicyFlags = 0;
957 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
958 KEY_READ, NULL, &key, NULL);
959 if (!r)
961 DWORD size = sizeof(DWORD);
963 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
964 &size);
965 RegCloseKey(key);
966 if (r)
968 /* Failed to query, create and return default value */
969 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
970 WTPF_OFFLINEOKNBU_COM |
971 WTPF_OFFLINEOKNBU_IND |
972 WTPF_OFFLINEOK_COM |
973 WTPF_OFFLINEOK_IND;
974 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
979 /***********************************************************************
980 * WintrustSetRegPolicyFlags (WINTRUST.@)
982 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
984 HKEY key;
985 LONG r;
987 TRACE("%x\n", dwPolicyFlags);
989 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
990 NULL, 0, KEY_WRITE, NULL, &key, NULL);
991 if (!r)
993 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
994 sizeof(DWORD));
995 RegCloseKey(key);
997 if (r) SetLastError(r);
998 return r == ERROR_SUCCESS;
1001 /* Utility functions */
1003 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
1005 BOOL ret = FALSE;
1007 TRACE("(%p, %p)\n", data, store);
1009 if (data->chStores)
1010 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
1011 (data->chStores + 1) * sizeof(HCERTSTORE));
1012 else
1014 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
1015 data->chStores = 0;
1017 if (data->pahStores)
1019 data->pahStores[data->chStores++] = CertDuplicateStore(store);
1020 ret = TRUE;
1022 else
1023 SetLastError(ERROR_OUTOFMEMORY);
1024 return ret;
1027 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
1028 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
1030 BOOL ret = FALSE;
1032 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
1034 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
1036 SetLastError(ERROR_INVALID_PARAMETER);
1037 return FALSE;
1039 if (fCounterSigner)
1041 FIXME("unimplemented for counter signers\n");
1042 SetLastError(ERROR_INVALID_PARAMETER);
1043 return FALSE;
1045 if (data->csSigners)
1046 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
1047 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1048 else
1050 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1051 data->csSigners = 0;
1053 if (data->pasSigners)
1055 if (idxSigner < data->csSigners)
1056 memmove(&data->pasSigners[idxSigner],
1057 &data->pasSigners[idxSigner + 1],
1058 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
1059 ret = TRUE;
1060 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
1062 /* The PSDK says psSigner should be allocated using pfnAlloc, but
1063 * it doesn't say anything about ownership. Since callers are
1064 * internal, assume ownership is passed, and just store the
1065 * pointer.
1067 memcpy(&data->pasSigners[idxSigner], sgnr,
1068 sizeof(CRYPT_PROVIDER_SGNR));
1070 else
1071 memset(&data->pasSigners[idxSigner], 0,
1072 sizeof(CRYPT_PROVIDER_SGNR));
1073 data->csSigners++;
1075 else
1076 SetLastError(ERROR_OUTOFMEMORY);
1077 return ret;
1080 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
1081 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
1083 BOOL ret = FALSE;
1085 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
1086 idxSigner, pCert2Add);
1088 if (fCounterSigner)
1090 FIXME("unimplemented for counter signers\n");
1091 SetLastError(ERROR_INVALID_PARAMETER);
1092 return FALSE;
1094 if (data->pasSigners[idxSigner].csCertChain)
1095 data->pasSigners[idxSigner].pasCertChain =
1096 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1097 (data->pasSigners[idxSigner].csCertChain + 1) *
1098 sizeof(CRYPT_PROVIDER_CERT));
1099 else
1101 data->pasSigners[idxSigner].pasCertChain =
1102 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1103 data->pasSigners[idxSigner].csCertChain = 0;
1105 if (data->pasSigners[idxSigner].pasCertChain)
1107 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1108 data->pasSigners[idxSigner].csCertChain];
1110 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1111 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1112 data->pasSigners[idxSigner].csCertChain++;
1113 ret = TRUE;
1115 else
1116 SetLastError(ERROR_OUTOFMEMORY);
1117 return ret;
1120 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1121 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1123 BOOL ret = FALSE;
1125 TRACE("(%p, %p)\n", data, pPrivData2Add);
1127 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1129 SetLastError(ERROR_INVALID_PARAMETER);
1130 WARN("invalid struct size\n");
1131 return FALSE;
1133 if (data->csProvPrivData)
1134 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1135 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1136 else
1138 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1139 data->csProvPrivData = 0;
1141 if (data->pasProvPrivData)
1143 DWORD i;
1145 for (i = 0; i < data->csProvPrivData; i++)
1146 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1147 break;
1149 data->pasProvPrivData[i] = *pPrivData2Add;
1150 if (i == data->csProvPrivData)
1151 data->csProvPrivData++;
1153 else
1154 SetLastError(ERROR_OUTOFMEMORY);
1155 return ret;
1158 /***********************************************************************
1159 * OpenPersonalTrustDBDialog (WINTRUST.@)
1161 * Opens the certificate manager dialog, showing only the stores that
1162 * contain trusted software publishers.
1164 * PARAMS
1165 * hwnd [I] handle of parent window
1167 * RETURNS
1168 * TRUE if the dialog could be opened, FALSE if not.
1170 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1172 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1174 uiCertMgr.dwSize = sizeof(uiCertMgr);
1175 uiCertMgr.hwndParent = hwnd;
1176 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1177 uiCertMgr.pwszTitle = NULL;
1178 uiCertMgr.pszInitUsageOID = NULL;
1179 return CryptUIDlgCertMgr(&uiCertMgr);
1182 /***********************************************************************
1183 * WTHelperCertCheckValidSignature
1185 HRESULT WINAPI WTHelperCertCheckValidSignature(CRYPT_PROVIDER_DATA *pProvData)
1187 FIXME("Stub\n");
1188 return S_OK;
1191 /***********************************************************************
1192 * IsCatalogFile
1194 BOOL WINAPI IsCatalogFile(HANDLE hFile, WCHAR *pwszFileName)
1196 static const GUID catGUID = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
1197 GUID guid;
1199 TRACE("(%p, %s)\n", hFile, debugstr_w(pwszFileName));
1201 if (!CryptSIPRetrieveSubjectGuid(pwszFileName, hFile, &guid))
1202 return FALSE;
1203 return IsEqualGUID(&guid, &catGUID);
1206 /***********************************************************************
1207 * FindCertsByIssuer
1209 HRESULT WINAPI FindCertsByIssuer(PCERT_CHAIN pCertChains, DWORD *pcbCertChains,
1210 DWORD *pcCertChains, BYTE* pbEncodedIssuerName, DWORD cbEncodedIssuerName,
1211 LPCWSTR pwszPurpose, DWORD dwKeySpec)
1213 FIXME("(%p, %p, %p, %p, %d, %s, %d): stub\n", pCertChains, pcbCertChains,
1214 pcCertChains, pbEncodedIssuerName, cbEncodedIssuerName,
1215 debugstr_w(pwszPurpose), dwKeySpec);
1216 return E_FAIL;