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