wintrust: Fix a test failure on Win2008.
[wine] / dlls / wintrust / wintrust_main.c
1 /*
2  * Copyright 2001 Rein Klazes
3  * Copyright 2007 Juan Lang
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include "config.h"
21
22 #include <stdarg.h>
23
24 #define NONAMELESSUNION
25
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"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
42
43
44 /* Utility functions */
45 void * WINAPI WINTRUST_Alloc(DWORD cb)
46 {
47     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
48 }
49
50 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb) __WINE_ALLOC_SIZE(2);
51 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb)
52 {
53     return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
54 }
55
56 void WINAPI WINTRUST_Free(void *p)
57 {
58     HeapFree(GetProcessHeap(), 0, p);
59 }
60
61 /***********************************************************************
62  *              DllMain  (WINTRUST.@)
63  */
64 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
65 {
66     switch(reason)
67     {
68     case DLL_PROCESS_ATTACH:
69         DisableThreadLibraryCalls( inst );
70         break;
71     }
72     return TRUE;
73 }
74
75 /***********************************************************************
76  *              TrustIsCertificateSelfSigned (WINTRUST.@)
77  */
78 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
79 {
80     BOOL ret;
81
82     TRACE("%p\n", cert);
83     ret = CertCompareCertificateName(cert->dwCertEncodingType,
84      &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
85     return ret;
86 }
87
88 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
89
90 struct wintrust_step
91 {
92     wintrust_step_func func;
93     DWORD              error_index;
94 };
95
96 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
97  DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
98 {
99     DWORD i, err = ERROR_SUCCESS;
100
101     for (i = 0; !err && i < numSteps; i++)
102     {
103         err = steps[i].func(provData);
104         if (err)
105             err = provData->padwTrustStepErrors[steps[i].error_index];
106     }
107     return err;
108 }
109
110 static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
111 {
112     CRYPT_PROVIDER_DATA *provData;
113
114     provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
115     if (!provData)
116         goto oom;
117     provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
118
119     provData->padwTrustStepErrors =
120      WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
121     if (!provData->padwTrustStepErrors)
122         goto oom;
123     provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
124
125     provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
126     if (!provData->u.pPDSip)
127         goto oom;
128     provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
129
130     provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
131     if (!provData->psPfns)
132         goto oom;
133     provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
134     return provData;
135
136 oom:
137     if (provData)
138     {
139         WINTRUST_Free(provData->padwTrustStepErrors);
140         WINTRUST_Free(provData->u.pPDSip);
141         WINTRUST_Free(provData->psPfns);
142         WINTRUST_Free(provData);
143     }
144     return NULL;
145 }
146
147 /* Adds trust steps for each function in psPfns.  Assumes steps has at least
148  * 5 entries.  Returns the number of steps added.
149  */
150 static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
151  const CRYPT_PROVIDER_FUNCTIONS *psPfns)
152 {
153     DWORD numSteps = 0;
154
155     if (psPfns->pfnInitialize)
156     {
157         steps[numSteps].func = psPfns->pfnInitialize;
158         steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
159     }
160     if (psPfns->pfnObjectTrust)
161     {
162         steps[numSteps].func = psPfns->pfnObjectTrust;
163         steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
164     }
165     if (psPfns->pfnSignatureTrust)
166     {
167         steps[numSteps].func = psPfns->pfnSignatureTrust;
168         steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
169     }
170     if (psPfns->pfnCertificateTrust)
171     {
172         steps[numSteps].func = psPfns->pfnCertificateTrust;
173         steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
174     }
175     if (psPfns->pfnFinalPolicy)
176     {
177         steps[numSteps].func = psPfns->pfnFinalPolicy;
178         steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
179     }
180     return numSteps;
181 }
182
183 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
184  WINTRUST_DATA *data)
185 {
186     DWORD err = ERROR_SUCCESS, numSteps = 0;
187     CRYPT_PROVIDER_DATA *provData;
188     BOOL ret;
189     struct wintrust_step verifySteps[5];
190
191     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
192
193     provData = WINTRUST_AllocateProviderData();
194     if (!provData)
195         return ERROR_OUTOFMEMORY;
196
197     ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
198     if (!ret)
199     {
200         err = GetLastError();
201         goto error;
202     }
203
204     data->hWVTStateData = provData;
205     provData->pWintrustData = data;
206     if (hwnd == INVALID_HANDLE_VALUE)
207         provData->hWndParent = GetDesktopWindow();
208     else
209         provData->hWndParent = hwnd;
210     provData->pgActionID = actionID;
211     WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
212
213     numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
214      provData->psPfns);
215     err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
216     goto done;
217
218 error:
219     if (provData)
220     {
221         WINTRUST_Free(provData->padwTrustStepErrors);
222         WINTRUST_Free(provData->u.pPDSip);
223         WINTRUST_Free(provData->psPfns);
224         WINTRUST_Free(provData);
225     }
226 done:
227     TRACE("returning %08x\n", err);
228     return err;
229 }
230
231 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
232  WINTRUST_DATA *data)
233 {
234     DWORD err = ERROR_SUCCESS;
235     CRYPT_PROVIDER_DATA *provData = data->hWVTStateData;
236
237     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
238
239     if (provData)
240     {
241         if (provData->psPfns->pfnCleanupPolicy)
242             err = provData->psPfns->pfnCleanupPolicy(provData);
243
244         WINTRUST_Free(provData->padwTrustStepErrors);
245         WINTRUST_Free(provData->u.pPDSip);
246         WINTRUST_Free(provData->psPfns);
247         WINTRUST_Free(provData);
248         data->hWVTStateData = NULL;
249     }
250     TRACE("returning %08x\n", err);
251     return err;
252 }
253
254 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
255  WINTRUST_DATA *data)
256 {
257     LONG err;
258
259     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
260
261     err = WINTRUST_DefaultVerify(hwnd, actionID, data);
262     WINTRUST_DefaultClose(hwnd, actionID, data);
263     TRACE("returning %08x\n", err);
264     return err;
265 }
266
267 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
268  WINTRUST_DATA *data)
269 {
270     WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
271     /* Undocumented: the published software action is passed a path,
272      * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
273      */
274     LPWIN_TRUST_SUBJECT_FILE subjectFile = data->pSIPClientData;
275     WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
276
277     TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
278     TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
279     fileInfo.pcwszFilePath = subjectFile->lpPath;
280     fileInfo.hFile = subjectFile->hFile;
281     wintrust_data.u.pFile = &fileInfo;
282     wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
283     wintrust_data.dwUIChoice = WTD_UI_NONE;
284
285     return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
286 }
287
288 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
289  * action is not stored in the registry and is located in wintrust, not in
290  * cryptdlg along with the rest of the implementation (verified by running the
291  * action with a native wintrust.dll.)
292  */
293 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
294 {
295     BOOL ret;
296
297     TRACE("(%p)\n", data);
298
299     if (!data->padwTrustStepErrors)
300         return S_FALSE;
301
302     switch (data->pWintrustData->dwUnionChoice)
303     {
304     case WTD_CHOICE_BLOB:
305         if (data->pWintrustData->u.pBlob &&
306          WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO,
307          data->pWintrustData->u.pBlob->cbStruct, pbMemObject) &&
308          data->pWintrustData->u.pBlob->cbMemObject ==
309          sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
310          data->pWintrustData->u.pBlob->pbMemObject)
311         {
312             CERT_VERIFY_CERTIFICATE_TRUST *pCert =
313              (CERT_VERIFY_CERTIFICATE_TRUST *)
314              data->pWintrustData->u.pBlob->pbMemObject;
315
316             if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
317              pCert->pccert)
318             {
319                 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
320                 DWORD i;
321                 SYSTEMTIME sysTime;
322
323                 /* Add a signer with nothing but the time to verify, so we can
324                  * add a cert to it
325                  */
326                 GetSystemTime(&sysTime);
327                 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
328                 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
329                 if (!ret)
330                     goto error;
331                 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
332                  pCert->pccert);
333                 if (!ret)
334                     goto error;
335                 for (i = 0; ret && i < pCert->cRootStores; i++)
336                     ret = data->psPfns->pfnAddStore2Chain(data,
337                      pCert->rghstoreRoots[i]);
338                 for (i = 0; ret && i < pCert->cStores; i++)
339                     ret = data->psPfns->pfnAddStore2Chain(data,
340                      pCert->rghstoreCAs[i]);
341                 for (i = 0; ret && i < pCert->cTrustStores; i++)
342                     ret = data->psPfns->pfnAddStore2Chain(data,
343                      pCert->rghstoreTrust[i]);
344             }
345             else
346             {
347                 SetLastError(ERROR_INVALID_PARAMETER);
348                 ret = FALSE;
349             }
350         }
351         else
352         {
353             SetLastError(ERROR_INVALID_PARAMETER);
354             ret = FALSE;
355         }
356         break;
357     default:
358         FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
359         SetLastError(ERROR_INVALID_PARAMETER);
360         ret = FALSE;
361     }
362
363 error:
364     if (!ret)
365         data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
366          GetLastError();
367     TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
368      data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
369     return ret ? S_OK : S_FALSE;
370 }
371
372 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
373  WINTRUST_DATA *data)
374 {
375     DWORD err = ERROR_SUCCESS, numSteps = 0;
376     CRYPT_PROVIDER_DATA *provData;
377     BOOL ret;
378     struct wintrust_step verifySteps[5];
379
380     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
381
382     provData = WINTRUST_AllocateProviderData();
383     if (!provData)
384         return ERROR_OUTOFMEMORY;
385
386     ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
387     if (!ret)
388     {
389         err = GetLastError();
390         goto error;
391     }
392     if (!provData->psPfns->pfnObjectTrust)
393         provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
394     /* Not sure why, but native skips the policy check */
395     provData->psPfns->pfnCertCheckPolicy = NULL;
396
397     data->hWVTStateData = provData;
398     provData->pWintrustData = data;
399     if (hwnd == INVALID_HANDLE_VALUE)
400         provData->hWndParent = GetDesktopWindow();
401     else
402         provData->hWndParent = hwnd;
403     provData->pgActionID = actionID;
404     WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
405
406     numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
407      provData->psPfns);
408     err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
409     goto done;
410
411 error:
412     if (provData)
413     {
414         WINTRUST_Free(provData->padwTrustStepErrors);
415         WINTRUST_Free(provData->u.pPDSip);
416         WINTRUST_Free(provData->psPfns);
417         WINTRUST_Free(provData);
418     }
419 done:
420     TRACE("returning %08x\n", err);
421     return err;
422 }
423
424 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
425  WINTRUST_DATA *data)
426 {
427     LONG err;
428
429     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
430
431     err = WINTRUST_CertVerify(hwnd, actionID, data);
432     WINTRUST_DefaultClose(hwnd, actionID, data);
433     TRACE("returning %08x\n", err);
434     return err;
435 }
436
437 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
438  WINTRUST_DATA *data)
439 {
440     DWORD stateAction;
441     LONG err = ERROR_SUCCESS;
442
443     if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
444         stateAction = data->dwStateAction;
445     else
446     {
447         TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
448         stateAction = WTD_STATEACTION_IGNORE;
449     }
450     switch (stateAction)
451     {
452     case WTD_STATEACTION_IGNORE:
453         err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
454         break;
455     case WTD_STATEACTION_VERIFY:
456         err = WINTRUST_CertVerify(hwnd, actionID, data);
457         break;
458     case WTD_STATEACTION_CLOSE:
459         err = WINTRUST_DefaultClose(hwnd, actionID, data);
460         break;
461     default:
462         FIXME("unimplemented for %d\n", data->dwStateAction);
463     }
464     return err;
465 }
466
467 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
468 {
469     TRACE("%p\n", pFile);
470     if (pFile)
471     {
472         TRACE("cbStruct: %d\n", pFile->cbStruct);
473         TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
474         TRACE("hFile: %p\n", pFile->hFile);
475         TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
476     }
477 }
478
479 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
480 {
481     TRACE("%p\n", catalog);
482     if (catalog)
483     {
484         TRACE("cbStruct: %d\n", catalog->cbStruct);
485         TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
486         TRACE("pcwszCatalogFilePath: %s\n",
487          debugstr_w(catalog->pcwszCatalogFilePath));
488         TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
489         TRACE("pcwszMemberFilePath: %s\n",
490          debugstr_w(catalog->pcwszMemberFilePath));
491         TRACE("hMemberFile: %p\n", catalog->hMemberFile);
492         TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
493         TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
494         TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
495     }
496 }
497
498 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
499 {
500     TRACE("%p\n", blob);
501     if (blob)
502     {
503         TRACE("cbStruct: %d\n", blob->cbStruct);
504         TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
505         TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
506         TRACE("cbMemObject: %d\n", blob->cbMemObject);
507         TRACE("pbMemObject: %p\n", blob->pbMemObject);
508         TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
509         TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
510     }
511 }
512
513 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
514 {
515     TRACE("%p\n", sgnr);
516     if (sgnr)
517     {
518         TRACE("cbStruct: %d\n", sgnr->cbStruct);
519         TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
520         TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
521         TRACE("chStores: %d\n", sgnr->chStores);
522     }
523 }
524
525 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
526 {
527     TRACE("%p\n", cert);
528     if (cert)
529     {
530         TRACE("cbStruct: %d\n", cert->cbStruct);
531         TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
532         TRACE("psCertContext: %p\n", cert->psCertContext);
533         TRACE("chStores: %d\n", cert->chStores);
534         TRACE("dwFlags: %08x\n", cert->dwFlags);
535         TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
536     }
537 }
538
539 static void dump_wintrust_data(WINTRUST_DATA *data)
540 {
541     TRACE("%p\n", data);
542     if (data)
543     {
544         TRACE("cbStruct: %d\n", data->cbStruct);
545         TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
546         TRACE("pSIPClientData: %p\n", data->pSIPClientData);
547         TRACE("dwUIChoice: %d\n", data->dwUIChoice);
548         TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
549         TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
550         switch (data->dwUnionChoice)
551         {
552         case WTD_CHOICE_FILE:
553             dump_file_info(data->u.pFile);
554             break;
555         case WTD_CHOICE_CATALOG:
556             dump_catalog_info(data->u.pCatalog);
557             break;
558         case WTD_CHOICE_BLOB:
559             dump_blob_info(data->u.pBlob);
560             break;
561         case WTD_CHOICE_SIGNER:
562             dump_sgnr_info(data->u.pSgnr);
563             break;
564         case WTD_CHOICE_CERT:
565             dump_cert_info(data->u.pCert);
566             break;
567         }
568         TRACE("dwStateAction: %d\n", data->dwStateAction);
569         TRACE("hWVTStateData: %p\n", data->hWVTStateData);
570         TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
571         TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
572         TRACE("dwUIContext: %d\n", data->dwUIContext);
573     }
574 }
575
576 /***********************************************************************
577  *              WinVerifyTrust (WINTRUST.@)
578  *
579  * Verifies an object by calling the specified trust provider.
580  *
581  * PARAMS
582  *   hwnd       [I] Handle to a caller window.
583  *   ActionID   [I] Pointer to a GUID that identifies the action to perform.
584  *   ActionData [I] Information used by the trust provider to verify the object.
585  *
586  * RETURNS
587  *   Success: Zero.
588  *   Failure: A TRUST_E_* error code.
589  *
590  * NOTES
591  *   Trust providers can be found at:
592  *   HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
593  */
594 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
595 {
596     static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
597      0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
598     static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
599     static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
600     static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
601     static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
602     static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
603     LONG err = ERROR_SUCCESS;
604     WINTRUST_DATA *actionData = ActionData;
605
606     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
607     dump_wintrust_data(ActionData);
608
609     /* Support for known old-style callers: */
610     if (IsEqualGUID(ActionID, &published_software))
611         err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
612     else if (IsEqualGUID(ActionID, &cert_action_verify))
613         err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
614     else
615     {
616         DWORD stateAction;
617
618         /* Check known actions to warn of possible problems */
619         if (!IsEqualGUID(ActionID, &unknown) &&
620          !IsEqualGUID(ActionID, &generic_verify_v2) &&
621          !IsEqualGUID(ActionID, &generic_cert_verify) &&
622          !IsEqualGUID(ActionID, &generic_chain_verify))
623             WARN("unknown action %s, default behavior may not be right\n",
624              debugstr_guid(ActionID));
625         if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
626             stateAction = actionData->dwStateAction;
627         else
628         {
629             TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
630             stateAction = WTD_STATEACTION_IGNORE;
631         }
632         switch (stateAction)
633         {
634         case WTD_STATEACTION_IGNORE:
635             err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
636             break;
637         case WTD_STATEACTION_VERIFY:
638             err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
639             break;
640         case WTD_STATEACTION_CLOSE:
641             err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
642             break;
643         default:
644             FIXME("unimplemented for %d\n", actionData->dwStateAction);
645         }
646     }
647
648     TRACE("returning %08x\n", err);
649     return err;
650 }
651
652 /***********************************************************************
653  *              WinVerifyTrustEx (WINTRUST.@)
654  */
655 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
656  WINTRUST_DATA* ActionData )
657 {
658     return WinVerifyTrust(hwnd, ActionID, ActionData);
659 }
660
661 /***********************************************************************
662  *              WTHelperGetProvSignerFromChain (WINTRUST.@)
663  */
664 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
665  CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
666  DWORD idxCounterSigner)
667 {
668     CRYPT_PROVIDER_SGNR *sgnr;
669
670     TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
671      idxCounterSigner);
672
673     if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
674         return NULL;
675     sgnr = &pProvData->pasSigners[idxSigner];
676     if (fCounterSigner)
677     {
678         if (idxCounterSigner >= sgnr->csCounterSigners ||
679          !sgnr->pasCounterSigners)
680             return NULL;
681         sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
682     }
683     TRACE("returning %p\n", sgnr);
684     return sgnr;
685 }
686
687 /***********************************************************************
688  *              WTHelperGetProvCertFromChain (WINTRUST.@)
689  */
690 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
691  CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
692 {
693     CRYPT_PROVIDER_CERT *cert;
694
695     TRACE("(%p %d)\n", pSgnr, idxCert);
696
697     if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
698         return NULL;
699     cert = &pSgnr->pasCertChain[idxCert];
700     TRACE("returning %p\n", cert);
701     return cert;
702 }
703
704 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
705  CRYPT_PROVIDER_DATA* pProvData,
706  GUID* pgProviderID)
707 {
708     CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
709     DWORD i;
710
711     TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
712
713     for (i = 0; i < pProvData->csProvPrivData; i++)
714         if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
715         {
716             privdata = &pProvData->pasProvPrivData[i];
717             break;
718         }
719
720     return privdata;
721 }
722
723 /***********************************************************************
724  *              WTHelperProvDataFromStateData (WINTRUST.@)
725  */
726 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
727 {
728     TRACE("%p\n", hStateData);
729     return hStateData;
730 }
731
732 /***********************************************************************
733  *              WTHelperGetFileName(WINTRUST.@)
734  */
735 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
736 {
737     TRACE("%p\n",data);
738     if (data->dwUnionChoice == WTD_CHOICE_FILE)
739         return data->u.pFile->pcwszFilePath;
740     else
741         return NULL;
742 }
743
744 /***********************************************************************
745  *              WTHelperGetFileHandle(WINTRUST.@)
746  */
747 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
748 {
749     TRACE("%p\n",data);
750     if (data->dwUnionChoice == WTD_CHOICE_FILE)
751         return data->u.pFile->hFile;
752     else
753         return INVALID_HANDLE_VALUE;
754 }
755
756 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
757 {
758     PCCRYPT_OID_INFO **usages = pvArg;
759     DWORD cUsages;
760     BOOL ret;
761
762     if (!*usages)
763     {
764         cUsages = 0;
765         *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
766     }
767     else
768     {
769         PCCRYPT_OID_INFO *ptr;
770
771         /* Count the existing usages.
772          * FIXME: make sure the new usage doesn't duplicate any in the list?
773          */
774         for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
775             ;
776         *usages = WINTRUST_ReAlloc(*usages,
777          (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
778     }
779     if (*usages)
780     {
781         (*usages)[cUsages] = pInfo;
782         (*usages)[cUsages + 1] = NULL;
783         ret = TRUE;
784     }
785     else
786     {
787         SetLastError(ERROR_OUTOFMEMORY);
788         ret = FALSE;
789     }
790     return ret;
791 }
792
793 /***********************************************************************
794  *              WTHelperGetKnownUsages(WINTRUST.@)
795  *
796  * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
797  *
798  * PARAMS
799  *  action      [In]     1 => allocate and return known usages, 2 => free previously
800  *                       allocated usages.
801  *  usages      [In/Out] If action == 1, *usages is set to an array of
802  *                       PCCRYPT_OID_INFO *.  The array is terminated with a NULL
803  *                       pointer.
804  *                       If action == 2, *usages is freed.
805  *
806  * RETURNS
807  *  TRUE on success, FALSE on failure.
808  */
809 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
810 {
811     BOOL ret;
812
813     TRACE("(%d, %p)\n", action, usages);
814
815     if (!usages)
816     {
817         SetLastError(ERROR_INVALID_PARAMETER);
818         return FALSE;
819     }
820
821     if (action == 1)
822     {
823         *usages = NULL;
824         ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
825          WINTRUST_enumUsages);
826     }
827     else if (action == 2)
828     {
829         WINTRUST_Free(*usages);
830         *usages = NULL;
831         ret = TRUE;
832     }
833     else
834     {
835         WARN("unknown action %d\n", action);
836         SetLastError(ERROR_INVALID_PARAMETER);
837         ret = FALSE;
838     }
839     return ret;
840 }
841
842 static const WCHAR Software_Publishing[] = {
843  'S','o','f','t','w','a','r','e','\\',
844  'M','i','c','r','o','s','o','f','t','\\',
845  'W','i','n','d','o','w','s','\\',
846  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
847  'W','i','n','t','r','u','s','t','\\',
848  'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
849  'S','o','f','t','w','a','r','e',' ',
850  'P','u','b','l','i','s','h','i','n','g',0 };
851 static const WCHAR State[] = { 'S','t','a','t','e',0 };
852
853 /***********************************************************************
854  *              WintrustGetRegPolicyFlags (WINTRUST.@)
855  */
856 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
857 {
858     HKEY key;
859     LONG r;
860
861     TRACE("%p\n", pdwPolicyFlags);
862
863     *pdwPolicyFlags = 0;
864     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
865      KEY_READ, NULL, &key, NULL);
866     if (!r)
867     {
868         DWORD size = sizeof(DWORD);
869
870         r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
871          &size);
872         RegCloseKey(key);
873         if (r)
874         {
875             /* Failed to query, create and return default value */
876             *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
877              WTPF_OFFLINEOKNBU_COM |
878              WTPF_OFFLINEOKNBU_IND |
879              WTPF_OFFLINEOK_COM |
880              WTPF_OFFLINEOK_IND;
881             WintrustSetRegPolicyFlags(*pdwPolicyFlags);
882         }
883     }
884 }
885
886 /***********************************************************************
887  *              WintrustSetRegPolicyFlags (WINTRUST.@)
888  */
889 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
890 {
891     HKEY key;
892     LONG r;
893
894     TRACE("%x\n", dwPolicyFlags);
895
896     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
897      NULL, 0, KEY_WRITE, NULL, &key, NULL);
898     if (!r)
899     {
900         r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
901          sizeof(DWORD));
902         RegCloseKey(key);
903     }
904     if (r) SetLastError(r);
905     return r == ERROR_SUCCESS;
906 }
907
908 /* Utility functions */
909
910 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
911 {
912     BOOL ret = FALSE;
913
914     TRACE("(%p, %p)\n", data, store);
915
916     if (data->chStores)
917         data->pahStores = WINTRUST_ReAlloc(data->pahStores,
918          (data->chStores + 1) * sizeof(HCERTSTORE));
919     else
920     {
921         data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
922         data->chStores = 0;
923     }
924     if (data->pahStores)
925     {
926         data->pahStores[data->chStores++] = CertDuplicateStore(store);
927         ret = TRUE;
928     }
929     else
930         SetLastError(ERROR_OUTOFMEMORY);
931     return ret;
932 }
933
934 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
935  BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
936 {
937     BOOL ret = FALSE;
938
939     TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
940
941     if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
942     {
943         SetLastError(ERROR_INVALID_PARAMETER);
944         return FALSE;
945     }
946     if (fCounterSigner)
947     {
948         FIXME("unimplemented for counter signers\n");
949         SetLastError(ERROR_INVALID_PARAMETER);
950         return FALSE;
951     }
952     if (data->csSigners)
953         data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
954          (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
955     else
956     {
957         data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
958         data->csSigners = 0;
959     }
960     if (data->pasSigners)
961     {
962         if (idxSigner < data->csSigners)
963             memmove(&data->pasSigners[idxSigner],
964              &data->pasSigners[idxSigner + 1],
965              (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
966         ret = TRUE;
967         if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
968         {
969             /* The PSDK says psSigner should be allocated using pfnAlloc, but
970              * it doesn't say anything about ownership.  Since callers are
971              * internal, assume ownership is passed, and just store the
972              * pointer.
973              */
974             memcpy(&data->pasSigners[idxSigner], sgnr,
975              sizeof(CRYPT_PROVIDER_SGNR));
976         }
977         else
978             memset(&data->pasSigners[idxSigner], 0,
979              sizeof(CRYPT_PROVIDER_SGNR));
980         data->csSigners++;
981     }
982     else
983         SetLastError(ERROR_OUTOFMEMORY);
984     return ret;
985 }
986
987 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
988  BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
989 {
990     BOOL ret = FALSE;
991
992     TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
993      idxSigner, pCert2Add);
994
995     if (fCounterSigner)
996     {
997         FIXME("unimplemented for counter signers\n");
998         SetLastError(ERROR_INVALID_PARAMETER);
999         return FALSE;
1000     }
1001     if (data->pasSigners[idxSigner].csCertChain)
1002         data->pasSigners[idxSigner].pasCertChain =
1003          WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1004          (data->pasSigners[idxSigner].csCertChain + 1) *
1005          sizeof(CRYPT_PROVIDER_CERT));
1006     else
1007     {
1008         data->pasSigners[idxSigner].pasCertChain =
1009          WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1010         data->pasSigners[idxSigner].csCertChain = 0;
1011     }
1012     if (data->pasSigners[idxSigner].pasCertChain)
1013     {
1014         CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1015          data->pasSigners[idxSigner].csCertChain];
1016
1017         cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1018         cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1019         data->pasSigners[idxSigner].csCertChain++;
1020         ret = TRUE;
1021     }
1022     else
1023         SetLastError(ERROR_OUTOFMEMORY);
1024     return ret;
1025 }
1026
1027 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1028  CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1029 {
1030     BOOL ret = FALSE;
1031
1032     TRACE("(%p, %p)\n", data, pPrivData2Add);
1033
1034     if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1035     {
1036         SetLastError(ERROR_INVALID_PARAMETER);
1037         WARN("invalid struct size\n");
1038         return FALSE;
1039     }
1040     if (data->csProvPrivData)
1041         data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1042          (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1043     else
1044     {
1045         data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1046         data->csProvPrivData = 0;
1047     }
1048     if (data->pasProvPrivData)
1049     {
1050         DWORD i;
1051
1052         for (i = 0; i < data->csProvPrivData; i++)
1053             if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1054                 break;
1055
1056         data->pasProvPrivData[i] = *pPrivData2Add;
1057         if (i == data->csProvPrivData)
1058             data->csProvPrivData++;
1059     }
1060     else
1061         SetLastError(ERROR_OUTOFMEMORY);
1062     return ret;
1063 }
1064
1065 /***********************************************************************
1066  *              OpenPersonalTrustDBDialog (WINTRUST.@)
1067  *
1068  * Opens the certificate manager dialog, showing only the stores that
1069  * contain trusted software publishers.
1070  *
1071  * PARAMS
1072  *  hwnd [I] handle of parent window
1073  *
1074  * RETURNS
1075  *  TRUE if the dialog could be opened, FALSE if not.
1076  */
1077 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1078 {
1079     CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1080
1081     uiCertMgr.dwSize = sizeof(uiCertMgr);
1082     uiCertMgr.hwndParent = hwnd;
1083     uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1084     uiCertMgr.pwszTitle = NULL;
1085     uiCertMgr.pszInitUsageOID = NULL;
1086     return CryptUIDlgCertMgr(&uiCertMgr);
1087 }
1088
1089 /***********************************************************************
1090  *              WTHelperCertCheckValidSignature
1091  */
1092 HRESULT WINAPI WTHelperCertCheckValidSignature(CRYPT_PROVIDER_DATA *pProvData)
1093 {
1094     FIXME("Stub\n");
1095     return S_OK;
1096 }