cfgmgr32: Forward CM_Locate_DevNodeA/W to setupapi.
[wine] / dlls / crypt32 / ctl.c
CommitLineData
429b1e1b
JL
1/*
2 * Copyright 2008 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20#include <assert.h>
21#include <stdarg.h>
22
23#define NONAMELESSUNION
24#include "windef.h"
25#include "winbase.h"
26#include "wincrypt.h"
27#include "wine/debug.h"
28#include "crypt32_private.h"
29
30WINE_DEFAULT_DEBUG_CHANNEL(crypt);
31
07de224b
JL
32#define CtlContext_CopyProperties(to, from) \
33 Context_CopyProperties((to), (from), sizeof(CTL_CONTEXT))
34
35BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
36 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
37 PCCTL_CONTEXT* ppStoreContext)
38{
39 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
40 BOOL ret = TRUE;
41 PCCTL_CONTEXT toAdd = NULL, existing = NULL;
42
43 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCtlContext, dwAddDisposition,
44 ppStoreContext);
45
46 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
47 {
48 existing = CertFindCTLInStore(hCertStore, 0, 0, CTL_FIND_EXISTING,
49 pCtlContext, NULL);
50 }
51
52 switch (dwAddDisposition)
53 {
54 case CERT_STORE_ADD_ALWAYS:
55 toAdd = CertDuplicateCTLContext(pCtlContext);
56 break;
57 case CERT_STORE_ADD_NEW:
58 if (existing)
59 {
60 TRACE("found matching CTL, not adding\n");
61 SetLastError(CRYPT_E_EXISTS);
62 ret = FALSE;
63 }
64 else
65 toAdd = CertDuplicateCTLContext(pCtlContext);
66 break;
67 case CERT_STORE_ADD_NEWER:
68 if (existing)
69 {
70 LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate,
71 &pCtlContext->pCtlInfo->ThisUpdate);
72
73 if (newer < 0)
74 toAdd = CertDuplicateCTLContext(pCtlContext);
75 else
76 {
77 TRACE("existing CTL is newer, not adding\n");
78 SetLastError(CRYPT_E_EXISTS);
79 ret = FALSE;
cefe8820
JL
80 }
81 }
82 else
83 toAdd = CertDuplicateCTLContext(pCtlContext);
84 break;
85 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
86 if (existing)
87 {
88 LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate,
89 &pCtlContext->pCtlInfo->ThisUpdate);
90
91 if (newer < 0)
92 {
93 toAdd = CertDuplicateCTLContext(pCtlContext);
94 CtlContext_CopyProperties(existing, pCtlContext);
95 }
96 else
97 {
98 TRACE("existing CTL is newer, not adding\n");
99 SetLastError(CRYPT_E_EXISTS);
100 ret = FALSE;
07de224b
JL
101 }
102 }
103 else
104 toAdd = CertDuplicateCTLContext(pCtlContext);
105 break;
106 case CERT_STORE_ADD_REPLACE_EXISTING:
107 toAdd = CertDuplicateCTLContext(pCtlContext);
108 break;
109 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
110 toAdd = CertDuplicateCTLContext(pCtlContext);
111 if (existing)
112 CtlContext_CopyProperties(toAdd, existing);
113 break;
114 case CERT_STORE_ADD_USE_EXISTING:
115 if (existing)
116 CtlContext_CopyProperties(existing, pCtlContext);
117 break;
118 default:
119 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
120 ret = FALSE;
121 }
122
123 if (toAdd)
124 {
125 if (store)
126 ret = store->ctls.addContext(store, (void *)toAdd,
127 (void *)existing, (const void **)ppStoreContext);
128 else if (ppStoreContext)
129 *ppStoreContext = CertDuplicateCTLContext(toAdd);
130 CertFreeCTLContext(toAdd);
131 }
132 CertFreeCTLContext(existing);
133
134 TRACE("returning %d\n", ret);
135 return ret;
136}
137
aebb9372
JL
138BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
139 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
140 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
141{
142 PCCTL_CONTEXT ctl = CertCreateCTLContext(dwMsgAndCertEncodingType,
143 pbCtlEncoded, cbCtlEncoded);
144 BOOL ret;
145
146 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore,
147 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
148 ppCtlContext);
149
150 if (ctl)
151 {
152 ret = CertAddCTLContextToStore(hCertStore, ctl, dwAddDisposition,
153 ppCtlContext);
154 CertFreeCTLContext(ctl);
155 }
156 else
157 ret = FALSE;
158 return ret;
159}
160
7572f61f
JL
161PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
162 PCCTL_CONTEXT pPrev)
163{
164 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
165 PCCTL_CONTEXT ret;
166
167 TRACE("(%p, %p)\n", hCertStore, pPrev);
168 if (!hCertStore)
169 ret = NULL;
170 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
171 ret = NULL;
172 else
173 ret = (PCCTL_CONTEXT)hcs->ctls.enumContext(hcs, (void *)pPrev);
174 return ret;
175}
176
4f62230e
JL
177typedef BOOL (*CtlCompareFunc)(PCCTL_CONTEXT pCtlContext, DWORD dwType,
178 DWORD dwFlags, const void *pvPara);
179
180static BOOL compare_ctl_any(PCCTL_CONTEXT pCtlContext, DWORD dwType,
181 DWORD dwFlags, const void *pvPara)
182{
183 return TRUE;
184}
185
186static BOOL compare_ctl_by_md5_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType,
187 DWORD dwFlags, const void *pvPara)
188{
189 BOOL ret;
190 BYTE hash[16];
191 DWORD size = sizeof(hash);
192
193 ret = CertGetCTLContextProperty(pCtlContext, CERT_MD5_HASH_PROP_ID, hash,
194 &size);
195 if (ret)
196 {
197 const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara;
198
199 if (size == pHash->cbData)
200 ret = !memcmp(pHash->pbData, hash, size);
201 else
202 ret = FALSE;
203 }
204 return ret;
205}
206
207static BOOL compare_ctl_by_sha1_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType,
208 DWORD dwFlags, const void *pvPara)
209{
210 BOOL ret;
211 BYTE hash[20];
212 DWORD size = sizeof(hash);
213
214 ret = CertGetCTLContextProperty(pCtlContext, CERT_SHA1_HASH_PROP_ID, hash,
215 &size);
216 if (ret)
217 {
218 const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara;
219
220 if (size == pHash->cbData)
221 ret = !memcmp(pHash->pbData, hash, size);
222 else
223 ret = FALSE;
224 }
225 return ret;
226}
227
228static BOOL compare_ctl_existing(PCCTL_CONTEXT pCtlContext, DWORD dwType,
229 DWORD dwFlags, const void *pvPara)
230{
231 BOOL ret;
232
233 if (pvPara)
234 {
235 PCCTL_CONTEXT ctl = (PCCTL_CONTEXT)pvPara;
236
237 if (pCtlContext->cbCtlContext == ctl->cbCtlContext)
238 {
239 if (ctl->cbCtlContext)
240 ret = !memcmp(pCtlContext->pbCtlContext, ctl->pbCtlContext,
241 ctl->cbCtlContext);
242 else
243 ret = TRUE;
244 }
245 else
246 ret = FALSE;
247 }
248 else
249 ret = FALSE;
250 return ret;
251}
252
253PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore,
254 DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
255 const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext)
256{
257 PCCTL_CONTEXT ret;
258 CtlCompareFunc compare;
259
260 TRACE("(%p, %d, %d, %d, %p, %p)\n", hCertStore, dwCertEncodingType,
261 dwFindFlags, dwFindType, pvFindPara, pPrevCtlContext);
262
263 switch (dwFindType)
264 {
265 case CTL_FIND_ANY:
266 compare = compare_ctl_any;
267 break;
268 case CTL_FIND_SHA1_HASH:
269 compare = compare_ctl_by_sha1_hash;
270 break;
271 case CTL_FIND_MD5_HASH:
272 compare = compare_ctl_by_md5_hash;
273 break;
274 case CTL_FIND_EXISTING:
275 compare = compare_ctl_existing;
276 break;
277 default:
278 FIXME("find type %08x unimplemented\n", dwFindType);
279 compare = NULL;
280 }
281
282 if (compare)
283 {
284 BOOL matches = FALSE;
285
286 ret = pPrevCtlContext;
287 do {
288 ret = CertEnumCTLsInStore(hCertStore, ret);
289 if (ret)
290 matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
291 } while (ret != NULL && !matches);
292 if (!ret)
293 SetLastError(CRYPT_E_NOT_FOUND);
294 }
295 else
296 {
297 SetLastError(CRYPT_E_NOT_FOUND);
298 ret = NULL;
299 }
300 return ret;
301}
302
7a2cedad
JL
303BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
304{
305 BOOL ret;
306
307 TRACE("(%p)\n", pCtlContext);
308
309 if (!pCtlContext)
310 ret = TRUE;
311 else if (!pCtlContext->hCertStore)
312 {
313 ret = TRUE;
314 CertFreeCTLContext(pCtlContext);
315 }
316 else
317 {
318 PWINECRYPT_CERTSTORE hcs =
319 (PWINECRYPT_CERTSTORE)pCtlContext->hCertStore;
320
321 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
322 ret = FALSE;
323 else
324 ret = hcs->ctls.deleteContext(hcs, (void *)pCtlContext);
325 CertFreeCTLContext(pCtlContext);
326 }
327 return ret;
328}
329
429b1e1b
JL
330PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
331 const BYTE *pbCtlEncoded, DWORD cbCtlEncoded)
332{
333 PCTL_CONTEXT ctl = NULL;
334 HCRYPTMSG msg;
335 BOOL ret;
336 BYTE *content = NULL;
337 DWORD contentSize = 0, size;
338 PCTL_INFO ctlInfo = NULL;
339
340 TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded,
341 cbCtlEncoded);
342
343 if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING)
344 {
345 SetLastError(E_INVALIDARG);
346 return NULL;
347 }
348 if (!pbCtlEncoded || !cbCtlEncoded)
349 {
350 SetLastError(ERROR_INVALID_DATA);
351 return NULL;
352 }
353 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0,
354 0, NULL, NULL);
355 if (!msg)
356 return NULL;
357 ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE);
358 if (!ret)
359 {
360 SetLastError(ERROR_INVALID_DATA);
361 goto end;
362 }
363 /* Check that it's really a CTL */
364 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size);
365 if (ret)
366 {
367 char *innerContent = CryptMemAlloc(size);
368
369 if (innerContent)
370 {
371 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0,
372 innerContent, &size);
373 if (ret)
374 {
375 if (strcmp(innerContent, szOID_CTL))
376 {
377 SetLastError(ERROR_INVALID_DATA);
378 ret = FALSE;
379 }
380 }
381 CryptMemFree(innerContent);
382 }
383 else
384 {
385 SetLastError(ERROR_OUTOFMEMORY);
386 ret = FALSE;
387 }
388 }
389 if (!ret)
390 goto end;
391 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize);
392 if (!ret)
393 goto end;
394 content = CryptMemAlloc(contentSize);
395 if (content)
396 {
397 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content,
398 &contentSize);
399 if (ret)
400 {
401 ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL,
402 content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL,
403 (BYTE *)&ctlInfo, &size);
404 if (ret)
405 {
7589715c 406 ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT));
429b1e1b
JL
407 if (ctl)
408 {
409 BYTE *data = CryptMemAlloc(cbCtlEncoded);
410
411 if (data)
412 {
413 memcpy(data, pbCtlEncoded, cbCtlEncoded);
414 ctl->dwMsgAndCertEncodingType =
415 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
416 ctl->pbCtlEncoded = data;
417 ctl->cbCtlEncoded = cbCtlEncoded;
418 ctl->pCtlInfo = ctlInfo;
419 ctl->hCertStore = NULL;
420 ctl->hCryptMsg = msg;
421 ctl->pbCtlContext = content;
422 ctl->cbCtlContext = contentSize;
423 }
424 else
425 {
426 SetLastError(ERROR_OUTOFMEMORY);
427 ret = FALSE;
428 }
429 }
430 else
431 {
432 SetLastError(ERROR_OUTOFMEMORY);
433 ret = FALSE;
434 }
435 }
436 }
437 }
438 else
439 {
440 SetLastError(ERROR_OUTOFMEMORY);
441 ret = FALSE;
442 }
443
444end:
445 if (!ret)
446 {
447 CryptMemFree(ctl);
448 ctl = NULL;
449 LocalFree(ctlInfo);
450 CryptMemFree(content);
451 CryptMsgClose(msg);
452 }
453 return (PCCTL_CONTEXT)ctl;
454}
455
3eb62ad6
JL
456PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
457{
458 TRACE("(%p)\n", pCtlContext);
459 Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
460 return pCtlContext;
461}
462
429b1e1b
JL
463static void CTLDataContext_Free(void *context)
464{
465 PCTL_CONTEXT ctlContext = (PCTL_CONTEXT)context;
466
467 CryptMsgClose(ctlContext->hCryptMsg);
468 CryptMemFree(ctlContext->pbCtlEncoded);
469 CryptMemFree(ctlContext->pbCtlContext);
470 LocalFree(ctlContext->pCtlInfo);
471}
472
473BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext)
474{
475 TRACE("(%p)\n", pCTLContext);
476
477 if (pCTLContext)
478 Context_Release((void *)pCTLContext, sizeof(CTL_CONTEXT),
479 CTLDataContext_Free);
480 return TRUE;
481}
0ada2b93
JL
482
483DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
484 DWORD dwPropId)
485{
486 PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
487 (void *)pCTLContext, sizeof(CTL_CONTEXT));
488 DWORD ret;
489
490 TRACE("(%p, %d)\n", pCTLContext, dwPropId);
491
492 if (properties)
493 ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
494 else
495 ret = 0;
496 return ret;
497}
498
499static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
500 DWORD dwFlags, const void *pvData);
501
502static BOOL CTLContext_GetHashProp(PCCTL_CONTEXT context, DWORD dwPropId,
503 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
504 DWORD *pcbData)
505{
506 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
507 pcbData);
00c50a67 508 if (ret && pvData)
0ada2b93
JL
509 {
510 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
511
512 ret = CTLContext_SetProperty(context, dwPropId, 0, &blob);
513 }
514 return ret;
515}
516
517static BOOL CTLContext_GetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
518 void *pvData, DWORD *pcbData)
519{
520 PCONTEXT_PROPERTY_LIST properties =
521 Context_GetProperties(context, sizeof(CTL_CONTEXT));
522 BOOL ret;
523 CRYPT_DATA_BLOB blob;
524
525 TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
526
527 if (properties)
528 ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
529 else
530 ret = FALSE;
531 if (ret)
532 {
533 if (!pvData)
534 *pcbData = blob.cbData;
535 else if (*pcbData < blob.cbData)
536 {
537 SetLastError(ERROR_MORE_DATA);
538 *pcbData = blob.cbData;
539 ret = FALSE;
540 }
541 else
542 {
543 memcpy(pvData, blob.pbData, blob.cbData);
544 *pcbData = blob.cbData;
545 }
546 }
547 else
548 {
549 /* Implicit properties */
550 switch (dwPropId)
551 {
552 case CERT_SHA1_HASH_PROP_ID:
553 ret = CTLContext_GetHashProp(context, dwPropId, CALG_SHA1,
554 context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
555 break;
556 case CERT_MD5_HASH_PROP_ID:
557 ret = CTLContext_GetHashProp(context, dwPropId, CALG_MD5,
558 context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
559 break;
560 default:
561 SetLastError(CRYPT_E_NOT_FOUND);
562 }
563 }
564 TRACE("returning %d\n", ret);
565 return ret;
566}
567
568BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
569 DWORD dwPropId, void *pvData, DWORD *pcbData)
570{
571 BOOL ret;
572
573 TRACE("(%p, %d, %p, %p)\n", pCTLContext, dwPropId, pvData, pcbData);
574
575 switch (dwPropId)
576 {
577 case 0:
578 case CERT_CERT_PROP_ID:
579 case CERT_CRL_PROP_ID:
580 case CERT_CTL_PROP_ID:
581 SetLastError(E_INVALIDARG);
582 ret = FALSE;
583 break;
584 case CERT_ACCESS_STATE_PROP_ID:
585 if (!pvData)
586 {
587 *pcbData = sizeof(DWORD);
588 ret = TRUE;
589 }
590 else if (*pcbData < sizeof(DWORD))
591 {
592 SetLastError(ERROR_MORE_DATA);
593 *pcbData = sizeof(DWORD);
594 ret = FALSE;
595 }
596 else
597 {
598 if (pCTLContext->hCertStore)
599 ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId,
600 pvData, pcbData);
601 else
602 *(DWORD *)pvData = 0;
603 ret = TRUE;
604 }
605 break;
606 default:
607 ret = CTLContext_GetProperty(pCTLContext, dwPropId, pvData,
608 pcbData);
609 }
610 return ret;
611}
612
613static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
614 DWORD dwFlags, const void *pvData)
615{
616 PCONTEXT_PROPERTY_LIST properties =
617 Context_GetProperties(context, sizeof(CTL_CONTEXT));
618 BOOL ret;
619
620 TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
621
622 if (!properties)
623 ret = FALSE;
624 else if (!pvData)
625 {
626 ContextPropertyList_RemoveProperty(properties, dwPropId);
627 ret = TRUE;
628 }
629 else
630 {
631 switch (dwPropId)
632 {
633 case CERT_AUTO_ENROLL_PROP_ID:
634 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
635 case CERT_DESCRIPTION_PROP_ID:
636 case CERT_FRIENDLY_NAME_PROP_ID:
637 case CERT_HASH_PROP_ID:
638 case CERT_KEY_IDENTIFIER_PROP_ID:
639 case CERT_MD5_HASH_PROP_ID:
640 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
641 case CERT_PUBKEY_ALG_PARA_PROP_ID:
642 case CERT_PVK_FILE_PROP_ID:
643 case CERT_SIGNATURE_HASH_PROP_ID:
644 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
645 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
646 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
647 case CERT_ENROLLMENT_PROP_ID:
648 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
649 case CERT_RENEWAL_PROP_ID:
650 {
651 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
652
653 ret = ContextPropertyList_SetProperty(properties, dwPropId,
654 blob->pbData, blob->cbData);
655 break;
656 }
657 case CERT_DATE_STAMP_PROP_ID:
658 ret = ContextPropertyList_SetProperty(properties, dwPropId,
659 (const BYTE *)pvData, sizeof(FILETIME));
660 break;
661 default:
662 FIXME("%d: stub\n", dwPropId);
663 ret = FALSE;
664 }
665 }
666 TRACE("returning %d\n", ret);
667 return ret;
668}
669
670BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
671 DWORD dwPropId, DWORD dwFlags, const void *pvData)
672{
673 BOOL ret;
674
675 TRACE("(%p, %d, %08x, %p)\n", pCTLContext, dwPropId, dwFlags, pvData);
676
677 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
678 * crashes on most of these, I'll be safer.
679 */
680 switch (dwPropId)
681 {
682 case 0:
683 case CERT_ACCESS_STATE_PROP_ID:
684 case CERT_CERT_PROP_ID:
685 case CERT_CRL_PROP_ID:
686 case CERT_CTL_PROP_ID:
687 SetLastError(E_INVALIDARG);
688 return FALSE;
689 }
690 ret = CTLContext_SetProperty(pCTLContext, dwPropId, dwFlags, pvData);
691 TRACE("returning %d\n", ret);
692 return ret;
693}