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