winhttp: Add the remaining completion notifications.
[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 "wintrust_priv.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
40
41
42 /***********************************************************************
43  *              DllMain  (WINTRUST.@)
44  */
45 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
46 {
47     switch(reason)
48     {
49     case DLL_PROCESS_ATTACH:
50         DisableThreadLibraryCalls( inst );
51         break;
52     }
53     return TRUE;
54 }
55
56 /***********************************************************************
57  *              TrustIsCertificateSelfSigned (WINTRUST.@)
58  */
59 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
60 {
61     BOOL ret;
62
63     TRACE("%p\n", cert);
64     ret = CertCompareCertificateName(cert->dwCertEncodingType,
65      &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
66     return ret;
67 }
68
69 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
70
71 struct wintrust_step
72 {
73     wintrust_step_func func;
74     DWORD              error_index;
75 };
76
77 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
78  DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
79 {
80     DWORD i, err = ERROR_SUCCESS;
81
82     for (i = 0; !err && i < numSteps; i++)
83     {
84         err = steps[i].func(provData);
85         if (err)
86             err = provData->padwTrustStepErrors[steps[i].error_index];
87     }
88     return err;
89 }
90
91 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
92  WINTRUST_DATA *data)
93 {
94     DWORD err = ERROR_SUCCESS, numSteps = 0;
95     CRYPT_PROVIDER_DATA *provData;
96     BOOL ret;
97     struct wintrust_step verifySteps[5];
98
99     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
100
101     provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
102     if (!provData)
103         goto oom;
104     provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
105
106     provData->padwTrustStepErrors =
107      WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
108     if (!provData->padwTrustStepErrors)
109         goto oom;
110     provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
111
112     provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
113     if (!provData->u.pPDSip)
114         goto oom;
115     provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
116
117     provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
118     if (!provData->psPfns)
119         goto oom;
120     provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
121     ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
122     if (!ret)
123     {
124         err = GetLastError();
125         goto error;
126     }
127
128     data->hWVTStateData = (HANDLE)provData;
129     provData->pWintrustData = data;
130     if (hwnd == INVALID_HANDLE_VALUE)
131         provData->hWndParent = GetDesktopWindow();
132     else
133         provData->hWndParent = hwnd;
134     provData->pgActionID = actionID;
135     WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
136
137     if (provData->psPfns->pfnInitialize)
138     {
139         verifySteps[numSteps].func = provData->psPfns->pfnInitialize;
140         verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
141     }
142     if (provData->psPfns->pfnObjectTrust)
143     {
144         verifySteps[numSteps].func = provData->psPfns->pfnObjectTrust;
145         verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
146     }
147     if (provData->psPfns->pfnSignatureTrust)
148     {
149         verifySteps[numSteps].func = provData->psPfns->pfnSignatureTrust;
150         verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
151     }
152     if (provData->psPfns->pfnCertificateTrust)
153     {
154         verifySteps[numSteps].func = provData->psPfns->pfnCertificateTrust;
155         verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
156     }
157     if (provData->psPfns->pfnFinalPolicy)
158     {
159         verifySteps[numSteps].func = provData->psPfns->pfnFinalPolicy;
160         verifySteps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
161     }
162     err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
163     goto done;
164
165 oom:
166     err = ERROR_OUTOFMEMORY;
167 error:
168     if (provData)
169     {
170         WINTRUST_Free(provData->padwTrustStepErrors);
171         WINTRUST_Free(provData->u.pPDSip);
172         WINTRUST_Free(provData->psPfns);
173         WINTRUST_Free(provData);
174     }
175 done:
176     TRACE("returning %08x\n", err);
177     return err;
178 }
179
180 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
181  WINTRUST_DATA *data)
182 {
183     DWORD err = ERROR_SUCCESS;
184     CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
185
186     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
187
188     if (provData)
189     {
190         if (provData->psPfns->pfnCleanupPolicy)
191             err = provData->psPfns->pfnCleanupPolicy(provData);
192
193         WINTRUST_Free(provData->padwTrustStepErrors);
194         WINTRUST_Free(provData->u.pPDSip);
195         WINTRUST_Free(provData->psPfns);
196         WINTRUST_Free(provData);
197         data->hWVTStateData = NULL;
198     }
199     TRACE("returning %08x\n", err);
200     return err;
201 }
202
203 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
204  WINTRUST_DATA *data)
205 {
206     LONG err;
207
208     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
209
210     err = WINTRUST_DefaultVerify(hwnd, actionID, data);
211     WINTRUST_DefaultClose(hwnd, actionID, data);
212     TRACE("returning %08x\n", err);
213     return err;
214 }
215
216 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
217  WINTRUST_DATA *data)
218 {
219     WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
220     /* Undocumented: the published software action is passed a path,
221      * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
222      */
223     LPWIN_TRUST_SUBJECT_FILE subjectFile =
224      (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
225     WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
226
227     TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
228     TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
229     fileInfo.pcwszFilePath = subjectFile->lpPath;
230     fileInfo.hFile = subjectFile->hFile;
231     wintrust_data.u.pFile = &fileInfo;
232     wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
233     wintrust_data.dwUIChoice = WTD_UI_NONE;
234
235     return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
236 }
237
238 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
239 {
240     TRACE("%p\n", pFile);
241     if (pFile)
242     {
243         TRACE("cbStruct: %d\n", pFile->cbStruct);
244         TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
245         TRACE("hFile: %p\n", pFile->hFile);
246         TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
247     }
248 }
249
250 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
251 {
252     TRACE("%p\n", catalog);
253     if (catalog)
254     {
255         TRACE("cbStruct: %d\n", catalog->cbStruct);
256         TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
257         TRACE("pcwszCatalogFilePath: %s\n",
258          debugstr_w(catalog->pcwszCatalogFilePath));
259         TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
260         TRACE("pcwszMemberFilePath: %s\n",
261          debugstr_w(catalog->pcwszMemberFilePath));
262         TRACE("hMemberFile: %p\n", catalog->hMemberFile);
263         TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
264         TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
265         TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
266     }
267 }
268
269 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
270 {
271     TRACE("%p\n", blob);
272     if (blob)
273     {
274         TRACE("cbStruct: %d\n", blob->cbStruct);
275         TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
276         TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
277         TRACE("cbMemObject: %d\n", blob->cbMemObject);
278         TRACE("pbMemObject: %p\n", blob->pbMemObject);
279         TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
280         TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
281     }
282 }
283
284 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
285 {
286     TRACE("%p\n", sgnr);
287     if (sgnr)
288     {
289         TRACE("cbStruct: %d\n", sgnr->cbStruct);
290         TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
291         TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
292         TRACE("chStores: %d\n", sgnr->chStores);
293     }
294 }
295
296 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
297 {
298     TRACE("%p\n", cert);
299     if (cert)
300     {
301         TRACE("cbStruct: %d\n", cert->cbStruct);
302         TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
303         TRACE("psCertContext: %p\n", cert->psCertContext);
304         TRACE("chStores: %d\n", cert->chStores);
305         TRACE("dwFlags: %08x\n", cert->dwFlags);
306         TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
307     }
308 }
309
310 static void dump_wintrust_data(WINTRUST_DATA *data)
311 {
312     TRACE("%p\n", data);
313     if (data)
314     {
315         TRACE("cbStruct: %d\n", data->cbStruct);
316         TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
317         TRACE("pSIPClientData: %p\n", data->pSIPClientData);
318         TRACE("dwUIChoice: %d\n", data->dwUIChoice);
319         TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
320         TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
321         switch (data->dwUnionChoice)
322         {
323         case WTD_CHOICE_FILE:
324             dump_file_info(data->u.pFile);
325             break;
326         case WTD_CHOICE_CATALOG:
327             dump_catalog_info(data->u.pCatalog);
328             break;
329         case WTD_CHOICE_BLOB:
330             dump_blob_info(data->u.pBlob);
331             break;
332         case WTD_CHOICE_SIGNER:
333             dump_sgnr_info(data->u.pSgnr);
334             break;
335         case WTD_CHOICE_CERT:
336             dump_cert_info(data->u.pCert);
337             break;
338         }
339         TRACE("dwStateAction: %d\n", data->dwStateAction);
340         TRACE("hWVTStateData: %p\n", data->hWVTStateData);
341         TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
342         TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
343         TRACE("dwUIContext: %d\n", data->dwUIContext);
344     }
345 }
346
347 /***********************************************************************
348  *              WinVerifyTrust (WINTRUST.@)
349  *
350  * Verifies an object by calling the specified trust provider.
351  *
352  * PARAMS
353  *   hwnd       [I] Handle to a caller window.
354  *   ActionID   [I] Pointer to a GUID that identifies the action to perform.
355  *   ActionData [I] Information used by the trust provider to verify the object.
356  *
357  * RETURNS
358  *   Success: Zero.
359  *   Failure: A TRUST_E_* error code.
360  *
361  * NOTES
362  *   Trust providers can be found at:
363  *   HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
364  */
365 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
366 {
367     static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
368      0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
369     static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
370     static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
371     static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
372     static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
373     LONG err = ERROR_SUCCESS;
374     WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
375
376     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
377     dump_wintrust_data(ActionData);
378
379     /* Support for known old-style callers: */
380     if (IsEqualGUID(ActionID, &published_software))
381         err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
382     else
383     {
384         /* Check known actions to warn of possible problems */
385         if (!IsEqualGUID(ActionID, &unknown) &&
386          !IsEqualGUID(ActionID, &generic_verify_v2) &&
387          !IsEqualGUID(ActionID, &generic_cert_verify) &&
388          !IsEqualGUID(ActionID, &generic_chain_verify))
389             WARN("unknown action %s, default behavior may not be right\n",
390              debugstr_guid(ActionID));
391         switch (actionData->dwStateAction)
392         {
393         case WTD_STATEACTION_IGNORE:
394             err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
395             break;
396         case WTD_STATEACTION_VERIFY:
397             err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
398             break;
399         case WTD_STATEACTION_CLOSE:
400             err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
401             break;
402         default:
403             FIXME("unimplemented for %d\n", actionData->dwStateAction);
404         }
405     }
406
407     TRACE("returning %08x\n", err);
408     return err;
409 }
410
411 /***********************************************************************
412  *              WinVerifyTrustEx (WINTRUST.@)
413  */
414 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
415  WINTRUST_DATA* ActionData )
416 {
417     return WinVerifyTrust(hwnd, ActionID, ActionData);
418 }
419
420 /***********************************************************************
421  *              WTHelperGetProvSignerFromChain (WINTRUST.@)
422  */
423 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
424  CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
425  DWORD idxCounterSigner)
426 {
427     CRYPT_PROVIDER_SGNR *sgnr;
428
429     TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
430      idxCounterSigner);
431
432     if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
433         return NULL;
434     sgnr = &pProvData->pasSigners[idxSigner];
435     if (fCounterSigner)
436     {
437         if (idxCounterSigner >= sgnr->csCounterSigners ||
438          !sgnr->pasCounterSigners)
439             return NULL;
440         sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
441     }
442     TRACE("returning %p\n", sgnr);
443     return sgnr;
444 }
445
446 /***********************************************************************
447  *              WTHelperGetProvCertFromChain (WINTRUST.@)
448  */
449 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
450  CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
451 {
452     CRYPT_PROVIDER_CERT *cert;
453
454     TRACE("(%p %d)\n", pSgnr, idxCert);
455
456     if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
457         return NULL;
458     cert = &pSgnr->pasCertChain[idxCert];
459     TRACE("returning %p\n", cert);
460     return cert;
461 }
462
463 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
464  CRYPT_PROVIDER_DATA* pProvData,
465  GUID* pgProviderID)
466 {
467     CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
468     DWORD i;
469
470     TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
471
472     for (i = 0; i < pProvData->csProvPrivData; i++)
473         if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
474         {
475             privdata = &pProvData->pasProvPrivData[i];
476             break;
477         }
478
479     return privdata;
480 }
481
482 /***********************************************************************
483  *              WTHelperProvDataFromStateData (WINTRUST.@)
484  */
485 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
486 {
487     TRACE("%p\n", hStateData);
488     return (CRYPT_PROVIDER_DATA *)hStateData;
489 }
490
491 /***********************************************************************
492  *              WTHelperGetFileName(WINTRUST.@)
493  */
494 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
495 {
496     TRACE("%p\n",data);
497     if (data->dwUnionChoice == WTD_CHOICE_FILE)
498         return data->u.pFile->pcwszFilePath;
499     else
500         return NULL;
501 }
502
503 /***********************************************************************
504  *              WTHelperGetFileHandle(WINTRUST.@)
505  */
506 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
507 {
508     TRACE("%p\n",data);
509     if (data->dwUnionChoice == WTD_CHOICE_FILE)
510         return data->u.pFile->hFile;
511     else
512         return INVALID_HANDLE_VALUE;
513 }
514
515 static const WCHAR Software_Publishing[] = {
516  'S','o','f','t','w','a','r','e','\\',
517  'M','i','c','r','o','s','o','f','t','\\',
518  'W','i','n','d','o','w','s','\\',
519  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
520  'W','i','n','t','r','u','s','t','\\',
521  'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
522  'S','o','f','t','w','a','r','e',' ',
523  'P','u','b','l','i','s','h','i','n','g',0 };
524 static const WCHAR State[] = { 'S','t','a','t','e',0 };
525
526 /***********************************************************************
527  *              WintrustGetRegPolicyFlags (WINTRUST.@)
528  */
529 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
530 {
531     HKEY key;
532     LONG r;
533
534     TRACE("%p\n", pdwPolicyFlags);
535
536     *pdwPolicyFlags = 0;
537     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
538      KEY_READ, NULL, &key, NULL);
539     if (!r)
540     {
541         DWORD size = sizeof(DWORD);
542
543         r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
544          &size);
545         RegCloseKey(key);
546         if (r)
547         {
548             /* Failed to query, create and return default value */
549             *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
550              WTPF_OFFLINEOKNBU_COM |
551              WTPF_OFFLINEOKNBU_IND |
552              WTPF_OFFLINEOK_COM |
553              WTPF_OFFLINEOK_IND;
554             WintrustSetRegPolicyFlags(*pdwPolicyFlags);
555         }
556     }
557 }
558
559 /***********************************************************************
560  *              WintrustSetRegPolicyFlags (WINTRUST.@)
561  */
562 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
563 {
564     HKEY key;
565     LONG r;
566
567     TRACE("%x\n", dwPolicyFlags);
568
569     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
570      NULL, 0, KEY_WRITE, NULL, &key, NULL);
571     if (!r)
572     {
573         r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
574          sizeof(DWORD));
575         RegCloseKey(key);
576     }
577     if (r) SetLastError(r);
578     return r == ERROR_SUCCESS;
579 }
580
581 /* Utility functions */
582 void * WINAPI WINTRUST_Alloc(DWORD cb)
583 {
584     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
585 }
586
587 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
588 {
589     return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
590 }
591
592 void WINAPI WINTRUST_Free(void *p)
593 {
594     HeapFree(GetProcessHeap(), 0, p);
595 }
596
597 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
598 {
599     BOOL ret = FALSE;
600
601     if (data->chStores)
602         data->pahStores = WINTRUST_ReAlloc(data->pahStores,
603          (data->chStores + 1) * sizeof(HCERTSTORE));
604     else
605     {
606         data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
607         data->chStores = 0;
608     }
609     if (data->pahStores)
610     {
611         data->pahStores[data->chStores++] = CertDuplicateStore(store);
612         ret = TRUE;
613     }
614     else
615         SetLastError(ERROR_OUTOFMEMORY);
616     return ret;
617 }
618
619 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
620  BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
621 {
622     BOOL ret = FALSE;
623
624     if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
625     {
626         SetLastError(ERROR_INVALID_PARAMETER);
627         return FALSE;
628     }
629     if (fCounterSigner)
630     {
631         FIXME("unimplemented for counter signers\n");
632         SetLastError(ERROR_INVALID_PARAMETER);
633         return FALSE;
634     }
635     if (data->csSigners)
636         data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
637          (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
638     else
639     {
640         data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
641         data->csSigners = 0;
642     }
643     if (data->pasSigners)
644     {
645         if (idxSigner < data->csSigners)
646             memmove(&data->pasSigners[idxSigner],
647              &data->pasSigners[idxSigner + 1],
648              (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
649         ret = TRUE;
650         if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
651         {
652             /* The PSDK says psSigner should be allocated using pfnAlloc, but
653              * it doesn't say anything about ownership.  Since callers are
654              * internal, assume ownership is passed, and just store the
655              * pointer.
656              */
657             memcpy(&data->pasSigners[idxSigner], sgnr,
658              sizeof(CRYPT_PROVIDER_SGNR));
659         }
660         else
661             memset(&data->pasSigners[idxSigner], 0,
662              sizeof(CRYPT_PROVIDER_SGNR));
663         data->csSigners++;
664     }
665     else
666         SetLastError(ERROR_OUTOFMEMORY);
667     return ret;
668 }
669
670 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
671  BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
672 {
673     BOOL ret = FALSE;
674
675     if (fCounterSigner)
676     {
677         FIXME("unimplemented for counter signers\n");
678         SetLastError(ERROR_INVALID_PARAMETER);
679         return FALSE;
680     }
681     if (data->pasSigners[idxSigner].csCertChain)
682         data->pasSigners[idxSigner].pasCertChain =
683          WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
684          (data->pasSigners[idxSigner].csCertChain + 1) *
685          sizeof(CRYPT_PROVIDER_CERT));
686     else
687     {
688         data->pasSigners[idxSigner].pasCertChain =
689          WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
690         data->pasSigners[idxSigner].csCertChain = 0;
691     }
692     if (data->pasSigners[idxSigner].pasCertChain)
693     {
694         CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
695          data->pasSigners[idxSigner].csCertChain];
696
697         cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
698         cert->pCert = CertDuplicateCertificateContext(pCert2Add);
699         data->pasSigners[idxSigner].csCertChain++;
700         ret = TRUE;
701     }
702     else
703         SetLastError(ERROR_OUTOFMEMORY);
704     return ret;
705 }
706
707 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
708  CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
709 {
710     BOOL ret = FALSE;
711
712     TRACE("(%p, %p)\n", data, pPrivData2Add);
713
714     if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
715     {
716         SetLastError(ERROR_INVALID_PARAMETER);
717         WARN("invalid struct size\n");
718         return FALSE;
719     }
720     if (data->csProvPrivData)
721         data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
722          (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
723     else
724     {
725         data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
726         data->csProvPrivData = 0;
727     }
728     if (data->pasProvPrivData)
729     {
730         DWORD i;
731
732         for (i = 0; i < data->csProvPrivData; i++)
733             if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
734                 break;
735
736         data->pasProvPrivData[i] = *pPrivData2Add;
737         if (i == data->csProvPrivData)
738             data->csProvPrivData++;
739     }
740     else
741         SetLastError(ERROR_OUTOFMEMORY);
742     return ret;
743 }