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