Sync with trunk r63502.
[reactos.git] / dll / win32 / cryptdlg / main.c
1 /*
2 * Copyright 2008 Maarten Lankhorst
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 #define WIN32_NO_STATUS
20
21 #define NONAMELESSUNION
22
23 #include <config.h>
24
25 #include <stdarg.h>
26
27 #include <windef.h>
28 #include <winbase.h>
29 //#include "winnls.h"
30 #include <winreg.h>
31 #include <wincrypt.h>
32 //#include "wintrust.h"
33 #include <winuser.h>
34 //#include "objbase.h"
35 #include <cryptdlg.h>
36 #include <cryptuiapi.h>
37 #include "cryptres.h"
38 #include <wine/unicode.h>
39 #include <wine/debug.h>
40
41 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg);
42
43 static HINSTANCE hInstance;
44
45 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
46 {
47 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
48
49 switch (fdwReason)
50 {
51 case DLL_WINE_PREATTACH:
52 return FALSE; /* prefer native version */
53 case DLL_PROCESS_ATTACH:
54 DisableThreadLibraryCalls(hinstDLL);
55 hInstance = hinstDLL;
56 break;
57 }
58 return TRUE;
59 }
60
61 /***********************************************************************
62 * GetFriendlyNameOfCertA (CRYPTDLG.@)
63 */
64 DWORD WINAPI GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pchBuffer,
65 DWORD cchBuffer)
66 {
67 return CertGetNameStringA(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
68 pchBuffer, cchBuffer);
69 }
70
71 /***********************************************************************
72 * GetFriendlyNameOfCertW (CRYPTDLG.@)
73 */
74 DWORD WINAPI GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pchBuffer,
75 DWORD cchBuffer)
76 {
77 return CertGetNameStringW(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
78 pchBuffer, cchBuffer);
79 }
80
81 /***********************************************************************
82 * CertTrustInit (CRYPTDLG.@)
83 */
84 HRESULT WINAPI CertTrustInit(CRYPT_PROVIDER_DATA *pProvData)
85 {
86 HRESULT ret = S_FALSE;
87
88 TRACE("(%p)\n", pProvData);
89
90 if (pProvData->padwTrustStepErrors &&
91 !pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
92 ret = S_OK;
93 TRACE("returning %08x\n", ret);
94 return ret;
95 }
96
97 /***********************************************************************
98 * CertTrustCertPolicy (CRYPTDLG.@)
99 */
100 BOOL WINAPI CertTrustCertPolicy(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSignerChain, DWORD idxCounterSigner)
101 {
102 FIXME("(%p, %d, %s, %d)\n", pProvData, idxSigner, fCounterSignerChain ? "TRUE" : "FALSE", idxCounterSigner);
103 return FALSE;
104 }
105
106 /***********************************************************************
107 * CertTrustCleanup (CRYPTDLG.@)
108 */
109 HRESULT WINAPI CertTrustCleanup(CRYPT_PROVIDER_DATA *pProvData)
110 {
111 FIXME("(%p)\n", pProvData);
112 return E_NOTIMPL;
113 }
114
115 static BOOL CRYPTDLG_CheckOnlineCRL(void)
116 {
117 static const WCHAR policyFlagsKey[] = { 'S','o','f','t','w','a','r','e',
118 '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
119 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
120 '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
121 '7','9','3','8','7','e','a','}',0 };
122 static const WCHAR policyFlags[] = { 'P','o','l','i','c','y','F','l','a',
123 'g','s',0 };
124 HKEY key;
125 BOOL ret = FALSE;
126
127 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, policyFlagsKey, 0, KEY_READ, &key))
128 {
129 DWORD type, flags, size = sizeof(flags);
130
131 if (!RegQueryValueExW(key, policyFlags, NULL, &type, (BYTE *)&flags,
132 &size) && type == REG_DWORD)
133 {
134 /* The flag values aren't defined in any header I'm aware of, but
135 * this value is well documented on the net.
136 */
137 if (flags & 0x00010000)
138 ret = TRUE;
139 }
140 RegCloseKey(key);
141 }
142 return ret;
143 }
144
145 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
146 * is.
147 */
148 static BOOL CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert)
149 {
150 BOOL ret;
151 BYTE hash[20];
152 DWORD size = sizeof(hash);
153
154 if ((ret = CertGetCertificateContextProperty(pCert,
155 CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
156 {
157 static const WCHAR disallowedW[] =
158 { 'D','i','s','a','l','l','o','w','e','d',0 };
159 HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
160 X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, disallowedW);
161
162 if (disallowed)
163 {
164 PCCERT_CONTEXT found = CertFindCertificateInStore(disallowed,
165 X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH, hash, NULL);
166
167 if (found)
168 {
169 ret = FALSE;
170 CertFreeCertificateContext(found);
171 }
172 CertCloseStore(disallowed, 0);
173 }
174 }
175 return ret;
176 }
177
178 static DWORD CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus)
179 {
180 DWORD confidence = 0;
181
182 confidence = 0;
183 if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
184 confidence |= CERT_CONFIDENCE_SIG;
185 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID))
186 confidence |= CERT_CONFIDENCE_TIME;
187 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED))
188 confidence |= CERT_CONFIDENCE_TIMENEST;
189 return confidence;
190 }
191
192 static BOOL CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA *data,
193 PCCERT_CHAIN_CONTEXT chain)
194 {
195 BOOL ret;
196 CRYPT_PROVIDER_SGNR signer;
197 PCERT_SIMPLE_CHAIN simpleChain = chain->rgpChain[0];
198 DWORD i;
199
200 memset(&signer, 0, sizeof(signer));
201 signer.cbStruct = sizeof(signer);
202 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
203 if (ret)
204 {
205 CRYPT_PROVIDER_SGNR *sgnr = WTHelperGetProvSignerFromChain(data, 0,
206 FALSE, 0);
207
208 if (sgnr)
209 {
210 sgnr->dwError = simpleChain->TrustStatus.dwErrorStatus;
211 sgnr->pChainContext = CertDuplicateCertificateChain(chain);
212 }
213 else
214 ret = FALSE;
215 for (i = 0; ret && i < simpleChain->cElement; i++)
216 {
217 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
218 simpleChain->rgpElement[i]->pCertContext);
219 if (ret)
220 {
221 CRYPT_PROVIDER_CERT *cert;
222
223 if ((cert = WTHelperGetProvCertFromChain(sgnr, i)))
224 {
225 CERT_CHAIN_ELEMENT *element = simpleChain->rgpElement[i];
226
227 cert->dwConfidence = CRYPTDLG_TrustStatusToConfidence(
228 element->TrustStatus.dwErrorStatus);
229 cert->dwError = element->TrustStatus.dwErrorStatus;
230 cert->pChainElement = element;
231 }
232 else
233 ret = FALSE;
234 }
235 }
236 }
237 return ret;
238 }
239
240 static CERT_VERIFY_CERTIFICATE_TRUST *CRYPTDLG_GetVerifyData(
241 CRYPT_PROVIDER_DATA *data)
242 {
243 CERT_VERIFY_CERTIFICATE_TRUST *pCert = NULL;
244
245 /* This should always be true, but just in case the calling function is
246 * called directly:
247 */
248 if (data->pWintrustData->dwUnionChoice == WTD_CHOICE_BLOB &&
249 data->pWintrustData->u.pBlob && data->pWintrustData->u.pBlob->cbMemObject ==
250 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
251 data->pWintrustData->u.pBlob->pbMemObject)
252 pCert = (CERT_VERIFY_CERTIFICATE_TRUST *)
253 data->pWintrustData->u.pBlob->pbMemObject;
254 return pCert;
255 }
256
257 static HCERTCHAINENGINE CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST *cert)
258 {
259 HCERTCHAINENGINE engine = NULL;
260 HCERTSTORE root = NULL, trust = NULL;
261 DWORD i;
262
263 if (cert->cRootStores)
264 {
265 root = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
266 CERT_STORE_CREATE_NEW_FLAG, NULL);
267 if (root)
268 {
269 for (i = 0; i < cert->cRootStores; i++)
270 CertAddStoreToCollection(root, cert->rghstoreRoots[i], 0, 0);
271 }
272 }
273 if (cert->cTrustStores)
274 {
275 trust = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
276 CERT_STORE_CREATE_NEW_FLAG, NULL);
277 if (trust)
278 {
279 for (i = 0; i < cert->cTrustStores; i++)
280 CertAddStoreToCollection(trust, cert->rghstoreTrust[i], 0, 0);
281 }
282 }
283 if (cert->cRootStores || cert->cStores || cert->cTrustStores)
284 {
285 CERT_CHAIN_ENGINE_CONFIG config;
286
287 memset(&config, 0, sizeof(config));
288 config.cbSize = sizeof(config);
289 config.hRestrictedRoot = root;
290 config.hRestrictedTrust = trust;
291 config.cAdditionalStore = cert->cStores;
292 config.rghAdditionalStore = cert->rghstoreCAs;
293 config.hRestrictedRoot = root;
294 CertCreateCertificateChainEngine(&config, &engine);
295 CertCloseStore(root, 0);
296 CertCloseStore(trust, 0);
297 }
298 return engine;
299 }
300
301 /***********************************************************************
302 * CertTrustFinalPolicy (CRYPTDLG.@)
303 */
304 HRESULT WINAPI CertTrustFinalPolicy(CRYPT_PROVIDER_DATA *data)
305 {
306 BOOL ret;
307 DWORD err = S_OK;
308 CERT_VERIFY_CERTIFICATE_TRUST *pCert = CRYPTDLG_GetVerifyData(data);
309
310 TRACE("(%p)\n", data);
311
312 if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
313 FIXME("unimplemented for UI choice %d\n",
314 data->pWintrustData->dwUIChoice);
315 if (pCert)
316 {
317 DWORD flags = 0;
318 CERT_CHAIN_PARA chainPara;
319 HCERTCHAINENGINE engine;
320
321 memset(&chainPara, 0, sizeof(chainPara));
322 chainPara.cbSize = sizeof(chainPara);
323 if (CRYPTDLG_CheckOnlineCRL())
324 flags |= CERT_CHAIN_REVOCATION_CHECK_END_CERT;
325 engine = CRYPTDLG_MakeEngine(pCert);
326 GetSystemTimeAsFileTime(&data->sftSystemTime);
327 ret = CRYPTDLG_IsCertAllowed(pCert->pccert);
328 if (ret)
329 {
330 PCCERT_CHAIN_CONTEXT chain;
331
332 ret = CertGetCertificateChain(engine, pCert->pccert,
333 &data->sftSystemTime, NULL, &chainPara, flags, NULL, &chain);
334 if (ret)
335 {
336 if (chain->cChain != 1)
337 {
338 FIXME("unimplemented for more than 1 simple chain\n");
339 err = TRUST_E_SUBJECT_FORM_UNKNOWN;
340 ret = FALSE;
341 }
342 else if ((ret = CRYPTDLG_CopyChain(data, chain)))
343 {
344 if (CertVerifyTimeValidity(&data->sftSystemTime,
345 pCert->pccert->pCertInfo))
346 {
347 ret = FALSE;
348 err = CERT_E_EXPIRED;
349 }
350 }
351 else
352 err = TRUST_E_SYSTEM_ERROR;
353 CertFreeCertificateChain(chain);
354 }
355 else
356 err = TRUST_E_SUBJECT_NOT_TRUSTED;
357 }
358 CertFreeCertificateChainEngine(engine);
359 }
360 else
361 {
362 ret = FALSE;
363 err = TRUST_E_NOSIGNATURE;
364 }
365 /* Oddly, native doesn't set the error in the trust step error location,
366 * probably because this action is more advisory than anything else.
367 * Instead it stores it as the final error, but the function "succeeds" in
368 * any case.
369 */
370 if (!ret)
371 data->dwFinalError = err;
372 TRACE("returning %d (%08x)\n", S_OK, data->dwFinalError);
373 return S_OK;
374 }
375
376 /***********************************************************************
377 * CertViewPropertiesA (CRYPTDLG.@)
378 */
379 BOOL WINAPI CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A *info)
380 {
381 CERT_VIEWPROPERTIES_STRUCT_W infoW;
382 LPWSTR title = NULL;
383 BOOL ret;
384
385 TRACE("(%p)\n", info);
386
387 memcpy(&infoW, info, sizeof(infoW));
388 if (info->szTitle)
389 {
390 int len = MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, NULL, 0);
391
392 title = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
393 if (title)
394 {
395 MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, title, len);
396 infoW.szTitle = title;
397 }
398 else
399 {
400 ret = FALSE;
401 goto error;
402 }
403 }
404 ret = CertViewPropertiesW(&infoW);
405 HeapFree(GetProcessHeap(), 0, title);
406 error:
407 return ret;
408 }
409
410 /***********************************************************************
411 * CertViewPropertiesW (CRYPTDLG.@)
412 */
413 BOOL WINAPI CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W *info)
414 {
415 static GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
416 CERT_VERIFY_CERTIFICATE_TRUST trust;
417 WINTRUST_BLOB_INFO blob;
418 WINTRUST_DATA wtd;
419 LONG err;
420 BOOL ret;
421
422 TRACE("(%p)\n", info);
423
424 memset(&trust, 0, sizeof(trust));
425 trust.cbSize = sizeof(trust);
426 trust.pccert = info->pCertContext;
427 trust.cRootStores = info->cRootStores;
428 trust.rghstoreRoots = info->rghstoreRoots;
429 trust.cStores = info->cStores;
430 trust.rghstoreCAs = info->rghstoreCAs;
431 trust.cTrustStores = info->cTrustStores;
432 trust.rghstoreTrust = info->rghstoreTrust;
433 memset(&blob, 0, sizeof(blob));
434 blob.cbStruct = sizeof(blob);
435 blob.cbMemObject = sizeof(trust);
436 blob.pbMemObject = (BYTE *)&trust;
437 memset(&wtd, 0, sizeof(wtd));
438 wtd.cbStruct = sizeof(wtd);
439 wtd.dwUIChoice = WTD_UI_NONE;
440 wtd.dwUnionChoice = WTD_CHOICE_BLOB;
441 wtd.u.pBlob = &blob;
442 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
443 err = WinVerifyTrust(NULL, &cert_action_verify, &wtd);
444 if (err == ERROR_SUCCESS)
445 {
446 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo;
447 BOOL propsChanged = FALSE;
448
449 memset(&uiInfo, 0, sizeof(uiInfo));
450 uiInfo.dwSize = sizeof(uiInfo);
451 uiInfo.hwndParent = info->hwndParent;
452 uiInfo.dwFlags =
453 CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_EDITPROPERTIES;
454 uiInfo.szTitle = info->szTitle;
455 uiInfo.pCertContext = info->pCertContext;
456 uiInfo.cPurposes = info->cArrayPurposes;
457 uiInfo.rgszPurposes = (LPCSTR *)info->arrayPurposes;
458 uiInfo.u.hWVTStateData = wtd.hWVTStateData;
459 uiInfo.fpCryptProviderDataTrustedUsage = TRUE;
460 uiInfo.cPropSheetPages = info->cArrayPropSheetPages;
461 uiInfo.rgPropSheetPages = info->arrayPropSheetPages;
462 uiInfo.nStartPage = info->nStartPage;
463 ret = CryptUIDlgViewCertificateW(&uiInfo, &propsChanged);
464 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
465 WinVerifyTrust(NULL, &cert_action_verify, &wtd);
466 }
467 else
468 ret = FALSE;
469 return ret;
470 }
471
472 static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded,
473 WCHAR *str, DWORD *pcchStr)
474 {
475 BOOL ret;
476 DWORD charsNeeded;
477
478 if (cbEncoded)
479 charsNeeded = (cbEncoded * 3);
480 else
481 charsNeeded = 1;
482 if (!str)
483 {
484 *pcchStr = charsNeeded;
485 ret = TRUE;
486 }
487 else if (*pcchStr < charsNeeded)
488 {
489 *pcchStr = charsNeeded;
490 SetLastError(ERROR_MORE_DATA);
491 ret = FALSE;
492 }
493 else
494 {
495 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
496 static const WCHAR endFmt[] = { '%','0','2','x',0 };
497 DWORD i;
498 LPWSTR ptr = str;
499
500 *pcchStr = charsNeeded;
501 if (cbEncoded)
502 {
503 for (i = 0; i < cbEncoded; i++)
504 {
505 if (i < cbEncoded - 1)
506 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
507 else
508 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
509 }
510 }
511 else
512 *ptr = 0;
513 ret = TRUE;
514 }
515 return ret;
516 }
517
518 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
519 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
520 static const WCHAR colonSpace[] = { ':',' ',0 };
521 static const WCHAR crlf[] = { '\r','\n',0 };
522 static const WCHAR commaSep[] = { ',',' ',0 };
523
524 static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType,
525 DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded,
526 WCHAR *str, DWORD *pcchStr)
527 {
528 BOOL ret;
529 DWORD size, charsNeeded = 1;
530 CERT_NAME_VALUE *cpsValue;
531
532 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
533 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &cpsValue, &size)))
534 {
535 LPCWSTR sep;
536 DWORD sepLen;
537
538 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
539 sep = crlf;
540 else
541 sep = commaSep;
542
543 sepLen = strlenW(sep);
544
545 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
546 {
547 charsNeeded += 3 * strlenW(indent);
548 if (str && *pcchStr >= charsNeeded)
549 {
550 strcpyW(str, indent);
551 str += strlenW(indent);
552 strcpyW(str, indent);
553 str += strlenW(indent);
554 strcpyW(str, indent);
555 str += strlenW(indent);
556 }
557 }
558 charsNeeded += cpsValue->Value.cbData / sizeof(WCHAR);
559 if (str && *pcchStr >= charsNeeded)
560 {
561 strcpyW(str, (LPWSTR)cpsValue->Value.pbData);
562 str += cpsValue->Value.cbData / sizeof(WCHAR);
563 }
564 charsNeeded += sepLen;
565 if (str && *pcchStr >= charsNeeded)
566 {
567 strcpyW(str, sep);
568 str += sepLen;
569 }
570 LocalFree(cpsValue);
571 if (!str)
572 *pcchStr = charsNeeded;
573 else if (*pcchStr < charsNeeded)
574 {
575 *pcchStr = charsNeeded;
576 SetLastError(ERROR_MORE_DATA);
577 ret = FALSE;
578 }
579 else
580 *pcchStr = charsNeeded;
581 }
582 return ret;
583 }
584
585 static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType,
586 DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded,
587 WCHAR *str, DWORD *pcchStr)
588 {
589 BOOL ret;
590 DWORD size, charsNeeded = 1;
591 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
592
593 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
594 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded,
595 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size)))
596 {
597 static const WCHAR numFmt[] = { '%','d',0 };
598 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef =
599 notice->pNoticeReference;
600 LPCWSTR headingSep, sep;
601 DWORD headingSepLen, sepLen;
602 LPWSTR noticeRef, organization, noticeNum, noticeText;
603 DWORD noticeRefLen, organizationLen, noticeNumLen, noticeTextLen;
604 WCHAR noticeNumStr[11];
605
606 noticeRefLen = LoadStringW(hInstance, IDS_NOTICE_REF,
607 (LPWSTR)&noticeRef, 0);
608 organizationLen = LoadStringW(hInstance, IDS_ORGANIZATION,
609 (LPWSTR)&organization, 0);
610 noticeNumLen = LoadStringW(hInstance, IDS_NOTICE_NUM,
611 (LPWSTR)&noticeNum, 0);
612 noticeTextLen = LoadStringW(hInstance, IDS_NOTICE_TEXT,
613 (LPWSTR)&noticeText, 0);
614 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
615 {
616 headingSep = colonCrlf;
617 sep = crlf;
618 }
619 else
620 {
621 headingSep = colonSpace;
622 sep = commaSep;
623 }
624 sepLen = strlenW(sep);
625 headingSepLen = strlenW(headingSep);
626
627 if (pNoticeRef)
628 {
629 DWORD k;
630 LPCSTR src;
631
632 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
633 {
634 charsNeeded += 3 * strlenW(indent);
635 if (str && *pcchStr >= charsNeeded)
636 {
637 strcpyW(str, indent);
638 str += strlenW(indent);
639 strcpyW(str, indent);
640 str += strlenW(indent);
641 strcpyW(str, indent);
642 str += strlenW(indent);
643 }
644 }
645 charsNeeded += noticeRefLen;
646 if (str && *pcchStr >= charsNeeded)
647 {
648 memcpy(str, noticeRef, noticeRefLen * sizeof(WCHAR));
649 str += noticeRefLen;
650 }
651 charsNeeded += headingSepLen;
652 if (str && *pcchStr >= charsNeeded)
653 {
654 strcpyW(str, headingSep);
655 str += headingSepLen;
656 }
657 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
658 {
659 charsNeeded += 4 * strlenW(indent);
660 if (str && *pcchStr >= charsNeeded)
661 {
662 strcpyW(str, indent);
663 str += strlenW(indent);
664 strcpyW(str, indent);
665 str += strlenW(indent);
666 strcpyW(str, indent);
667 str += strlenW(indent);
668 strcpyW(str, indent);
669 str += strlenW(indent);
670 }
671 }
672 charsNeeded += organizationLen;
673 if (str && *pcchStr >= charsNeeded)
674 {
675 memcpy(str, organization, organizationLen * sizeof(WCHAR));
676 str += organizationLen;
677 }
678 charsNeeded += strlen(pNoticeRef->pszOrganization);
679 if (str && *pcchStr >= charsNeeded)
680 for (src = pNoticeRef->pszOrganization; src && *src;
681 src++, str++)
682 *str = *src;
683 charsNeeded += sepLen;
684 if (str && *pcchStr >= charsNeeded)
685 {
686 strcpyW(str, sep);
687 str += sepLen;
688 }
689 for (k = 0; k < pNoticeRef->cNoticeNumbers; k++)
690 {
691 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
692 {
693 charsNeeded += 4 * strlenW(indent);
694 if (str && *pcchStr >= charsNeeded)
695 {
696 strcpyW(str, indent);
697 str += strlenW(indent);
698 strcpyW(str, indent);
699 str += strlenW(indent);
700 strcpyW(str, indent);
701 str += strlenW(indent);
702 strcpyW(str, indent);
703 str += strlenW(indent);
704 }
705 }
706 charsNeeded += noticeNumLen;
707 if (str && *pcchStr >= charsNeeded)
708 {
709 memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR));
710 str += noticeNumLen;
711 }
712 sprintfW(noticeNumStr, numFmt, k + 1);
713 charsNeeded += strlenW(noticeNumStr);
714 if (str && *pcchStr >= charsNeeded)
715 {
716 strcpyW(str, noticeNumStr);
717 str += strlenW(noticeNumStr);
718 }
719 charsNeeded += sepLen;
720 if (str && *pcchStr >= charsNeeded)
721 {
722 strcpyW(str, sep);
723 str += sepLen;
724 }
725 }
726 }
727 if (notice->pszDisplayText)
728 {
729 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
730 {
731 charsNeeded += 3 * strlenW(indent);
732 if (str && *pcchStr >= charsNeeded)
733 {
734 strcpyW(str, indent);
735 str += strlenW(indent);
736 strcpyW(str, indent);
737 str += strlenW(indent);
738 strcpyW(str, indent);
739 str += strlenW(indent);
740 }
741 }
742 charsNeeded += noticeTextLen;
743 if (str && *pcchStr >= charsNeeded)
744 {
745 memcpy(str, noticeText, noticeTextLen * sizeof(WCHAR));
746 str += noticeTextLen;
747 }
748 charsNeeded += strlenW(notice->pszDisplayText);
749 if (str && *pcchStr >= charsNeeded)
750 {
751 strcpyW(str, notice->pszDisplayText);
752 str += strlenW(notice->pszDisplayText);
753 }
754 charsNeeded += sepLen;
755 if (str && *pcchStr >= charsNeeded)
756 {
757 strcpyW(str, sep);
758 str += sepLen;
759 }
760 }
761 LocalFree(notice);
762 if (!str)
763 *pcchStr = charsNeeded;
764 else if (*pcchStr < charsNeeded)
765 {
766 *pcchStr = charsNeeded;
767 SetLastError(ERROR_MORE_DATA);
768 ret = FALSE;
769 }
770 else
771 *pcchStr = charsNeeded;
772 }
773 return ret;
774 }
775
776 /***********************************************************************
777 * FormatVerisignExtension (CRYPTDLG.@)
778 */
779 BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
780 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
782 DWORD *pcbFormat)
783 {
784 CERT_POLICIES_INFO *policies;
785 DWORD size;
786 BOOL ret = FALSE;
787
788 if (!cbEncoded)
789 {
790 SetLastError(E_INVALIDARG);
791 return FALSE;
792 }
793 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES,
794 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size)))
795 {
796 static const WCHAR numFmt[] = { '%','d',0 };
797 DWORD charsNeeded = 1; /* space for NULL terminator */
798 LPCWSTR headingSep, sep;
799 DWORD headingSepLen, sepLen;
800 WCHAR policyNum[11], policyQualifierNum[11];
801 LPWSTR certPolicy, policyId, policyQualifierInfo, policyQualifierId;
802 LPWSTR cps, userNotice, qualifier;
803 DWORD certPolicyLen, policyIdLen, policyQualifierInfoLen;
804 DWORD policyQualifierIdLen, cpsLen, userNoticeLen, qualifierLen;
805 DWORD i;
806 LPWSTR str = pbFormat;
807
808 certPolicyLen = LoadStringW(hInstance, IDS_CERT_POLICY,
809 (LPWSTR)&certPolicy, 0);
810 policyIdLen = LoadStringW(hInstance, IDS_POLICY_ID, (LPWSTR)&policyId,
811 0);
812 policyQualifierInfoLen = LoadStringW(hInstance,
813 IDS_POLICY_QUALIFIER_INFO, (LPWSTR)&policyQualifierInfo, 0);
814 policyQualifierIdLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_ID,
815 (LPWSTR)&policyQualifierId, 0);
816 cpsLen = LoadStringW(hInstance, IDS_CPS, (LPWSTR)&cps, 0);
817 userNoticeLen = LoadStringW(hInstance, IDS_USER_NOTICE,
818 (LPWSTR)&userNotice, 0);
819 qualifierLen = LoadStringW(hInstance, IDS_QUALIFIER,
820 (LPWSTR)&qualifier, 0);
821 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
822 {
823 headingSep = colonCrlf;
824 sep = crlf;
825 }
826 else
827 {
828 headingSep = colonSpace;
829 sep = commaSep;
830 }
831 sepLen = strlenW(sep);
832 headingSepLen = strlenW(headingSep);
833
834 for (i = 0; ret && i < policies->cPolicyInfo; i++)
835 {
836 CERT_POLICY_INFO *policy = &policies->rgPolicyInfo[i];
837 DWORD j;
838 LPCSTR src;
839
840 charsNeeded += 1; /* '['*/
841 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
842 *str++ = '[';
843 sprintfW(policyNum, numFmt, i + 1);
844 charsNeeded += strlenW(policyNum);
845 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
846 {
847 strcpyW(str, policyNum);
848 str += strlenW(policyNum);
849 }
850 charsNeeded += 1; /* ']'*/
851 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
852 *str++ = ']';
853 charsNeeded += certPolicyLen;
854 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
855 {
856 memcpy(str, certPolicy, certPolicyLen * sizeof(WCHAR));
857 str += certPolicyLen;
858 }
859 charsNeeded += headingSepLen;
860 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
861 {
862 strcpyW(str, headingSep);
863 str += headingSepLen;
864 }
865 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
866 {
867 charsNeeded += strlenW(indent);
868 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
869 {
870 strcpyW(str, indent);
871 str += strlenW(indent);
872 }
873 }
874 charsNeeded += policyIdLen;
875 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
876 {
877 memcpy(str, policyId, policyIdLen * sizeof(WCHAR));
878 str += policyIdLen;
879 }
880 charsNeeded += strlen(policy->pszPolicyIdentifier);
881 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
882 {
883 for (src = policy->pszPolicyIdentifier; src && *src;
884 src++, str++)
885 *str = *src;
886 }
887 charsNeeded += sepLen;
888 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
889 {
890 strcpyW(str, sep);
891 str += sepLen;
892 }
893 for (j = 0; j < policy->cPolicyQualifier; j++)
894 {
895 CERT_POLICY_QUALIFIER_INFO *qualifierInfo =
896 &policy->rgPolicyQualifier[j];
897 DWORD sizeRemaining;
898
899 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
900 {
901 charsNeeded += strlenW(indent);
902 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
903 {
904 strcpyW(str, indent);
905 str += strlenW(indent);
906 }
907 }
908 charsNeeded += 1; /* '['*/
909 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
910 *str++ = '[';
911 charsNeeded += strlenW(policyNum);
912 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
913 {
914 strcpyW(str, policyNum);
915 str += strlenW(policyNum);
916 }
917 charsNeeded += 1; /* ','*/
918 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
919 *str++ = ',';
920 sprintfW(policyQualifierNum, numFmt, j + 1);
921 charsNeeded += strlenW(policyQualifierNum);
922 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
923 {
924 strcpyW(str, policyQualifierNum);
925 str += strlenW(policyQualifierNum);
926 }
927 charsNeeded += 1; /* ']'*/
928 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
929 *str++ = ']';
930 charsNeeded += policyQualifierInfoLen;
931 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
932 {
933 memcpy(str, policyQualifierInfo,
934 policyQualifierInfoLen * sizeof(WCHAR));
935 str += policyQualifierInfoLen;
936 }
937 charsNeeded += headingSepLen;
938 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
939 {
940 strcpyW(str, headingSep);
941 str += headingSepLen;
942 }
943 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
944 {
945 charsNeeded += 2 * strlenW(indent);
946 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
947 {
948 strcpyW(str, indent);
949 str += strlenW(indent);
950 strcpyW(str, indent);
951 str += strlenW(indent);
952 }
953 }
954 charsNeeded += policyQualifierIdLen;
955 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
956 {
957 memcpy(str, policyQualifierId,
958 policyQualifierIdLen * sizeof(WCHAR));
959 str += policyQualifierIdLen;
960 }
961 if (!strcmp(qualifierInfo->pszPolicyQualifierId,
962 szOID_PKIX_POLICY_QUALIFIER_CPS))
963 {
964 charsNeeded += cpsLen;
965 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
966 {
967 memcpy(str, cps, cpsLen * sizeof(WCHAR));
968 str += cpsLen;
969 }
970 }
971 else if (!strcmp(qualifierInfo->pszPolicyQualifierId,
972 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
973 {
974 charsNeeded += userNoticeLen;
975 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
976 {
977 memcpy(str, userNotice, userNoticeLen * sizeof(WCHAR));
978 str += userNoticeLen;
979 }
980 }
981 else
982 {
983 charsNeeded += strlen(qualifierInfo->pszPolicyQualifierId);
984 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
985 {
986 for (src = qualifierInfo->pszPolicyQualifierId;
987 src && *src; src++, str++)
988 *str = *src;
989 }
990 }
991 charsNeeded += sepLen;
992 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
993 {
994 strcpyW(str, sep);
995 str += sepLen;
996 }
997 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
998 {
999 charsNeeded += 2 * strlenW(indent);
1000 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
1001 {
1002 strcpyW(str, indent);
1003 str += strlenW(indent);
1004 strcpyW(str, indent);
1005 str += strlenW(indent);
1006 }
1007 }
1008 charsNeeded += qualifierLen;
1009 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
1010 {
1011 memcpy(str, qualifier, qualifierLen * sizeof(WCHAR));
1012 str += qualifierLen;
1013 }
1014 charsNeeded += headingSepLen;
1015 if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
1016 {
1017 strcpyW(str, headingSep);
1018 str += headingSepLen;
1019 }
1020 /* This if block is deliberately redundant with the same if
1021 * block above, in order to keep the code more readable (the
1022 * code flow follows the order in which the strings are output.)
1023 */
1024 if (!strcmp(qualifierInfo->pszPolicyQualifierId,
1025 szOID_PKIX_POLICY_QUALIFIER_CPS))
1026 {
1027 if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
1028 {
1029 /* Insufficient space, determine how much is needed. */
1030 ret = CRYPT_FormatCPS(dwCertEncodingType,
1031 dwFormatStrType, qualifierInfo->Qualifier.pbData,
1032 qualifierInfo->Qualifier.cbData, NULL, &size);
1033 if (ret)
1034 charsNeeded += size - 1;
1035 }
1036 else
1037 {
1038 sizeRemaining = *pcbFormat / sizeof(WCHAR);
1039 sizeRemaining -= str - (LPWSTR)pbFormat;
1040 ret = CRYPT_FormatCPS(dwCertEncodingType,
1041 dwFormatStrType, qualifierInfo->Qualifier.pbData,
1042 qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
1043 if (ret || GetLastError() == ERROR_MORE_DATA)
1044 {
1045 charsNeeded += sizeRemaining - 1;
1046 str += sizeRemaining - 1;
1047 }
1048 }
1049 }
1050 else if (!strcmp(qualifierInfo->pszPolicyQualifierId,
1051 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
1052 {
1053 if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
1054 {
1055 /* Insufficient space, determine how much is needed. */
1056 ret = CRYPT_FormatUserNotice(dwCertEncodingType,
1057 dwFormatStrType, qualifierInfo->Qualifier.pbData,
1058 qualifierInfo->Qualifier.cbData, NULL, &size);
1059 if (ret)
1060 charsNeeded += size - 1;
1061 }
1062 else
1063 {
1064 sizeRemaining = *pcbFormat / sizeof(WCHAR);
1065 sizeRemaining -= str - (LPWSTR)pbFormat;
1066 ret = CRYPT_FormatUserNotice(dwCertEncodingType,
1067 dwFormatStrType, qualifierInfo->Qualifier.pbData,
1068 qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
1069 if (ret || GetLastError() == ERROR_MORE_DATA)
1070 {
1071 charsNeeded += sizeRemaining - 1;
1072 str += sizeRemaining - 1;
1073 }
1074 }
1075 }
1076 else
1077 {
1078 if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
1079 {
1080 /* Insufficient space, determine how much is needed. */
1081 ret = CRYPT_FormatHexString(
1082 qualifierInfo->Qualifier.pbData,
1083 qualifierInfo->Qualifier.cbData, NULL, &size);
1084 if (ret)
1085 charsNeeded += size - 1;
1086 }
1087 else
1088 {
1089 sizeRemaining = *pcbFormat / sizeof(WCHAR);
1090 sizeRemaining -= str - (LPWSTR)pbFormat;
1091 ret = CRYPT_FormatHexString(
1092 qualifierInfo->Qualifier.pbData,
1093 qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
1094 if (ret || GetLastError() == ERROR_MORE_DATA)
1095 {
1096 charsNeeded += sizeRemaining - 1;
1097 str += sizeRemaining - 1;
1098 }
1099 }
1100 }
1101 }
1102 }
1103 LocalFree(policies);
1104 if (ret)
1105 {
1106 if (!pbFormat)
1107 *pcbFormat = charsNeeded * sizeof(WCHAR);
1108 else if (*pcbFormat < charsNeeded * sizeof(WCHAR))
1109 {
1110 *pcbFormat = charsNeeded * sizeof(WCHAR);
1111 SetLastError(ERROR_MORE_DATA);
1112 ret = FALSE;
1113 }
1114 else
1115 *pcbFormat = charsNeeded * sizeof(WCHAR);
1116 }
1117 }
1118 return ret;
1119 }
1120
1121 #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
1122
1123 /***********************************************************************
1124 * DllRegisterServer (CRYPTDLG.@)
1125 */
1126 HRESULT WINAPI DllRegisterServer(void)
1127 {
1128 static WCHAR cryptdlg[] = { 'c','r','y','p','t','d','l','g','.',
1129 'd','l','l',0 };
1130 static WCHAR wintrust[] = { 'w','i','n','t','r','u','s','t','.',
1131 'd','l','l',0 };
1132 static WCHAR certTrustInit[] = { 'C','e','r','t','T','r','u','s','t',
1133 'I','n','i','t',0 };
1134 static WCHAR wintrustCertificateTrust[] = { 'W','i','n','t','r','u','s','t',
1135 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
1136 static WCHAR certTrustCertPolicy[] = { 'C','e','r','t','T','r','u','s','t',
1137 'C','e','r','t','P','o','l','i','c','y',0 };
1138 static WCHAR certTrustFinalPolicy[] = { 'C','e','r','t','T','r','u','s','t',
1139 'F','i','n','a','l','P','o','l','i','c','y',0 };
1140 static WCHAR certTrustCleanup[] = { 'C','e','r','t','T','r','u','s','t',
1141 'C','l','e','a','n','u','p',0 };
1142 static const WCHAR cryptDlg[] = { 'c','r','y','p','t','d','l','g','.',
1143 'd','l','l',0 };
1144 CRYPT_REGISTER_ACTIONID reg;
1145 GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
1146 HRESULT hr = S_OK;
1147
1148 memset(&reg, 0, sizeof(reg));
1149 reg.cbStruct = sizeof(reg);
1150 reg.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
1151 reg.sInitProvider.pwszDLLName = cryptdlg;
1152 reg.sInitProvider.pwszFunctionName = certTrustInit;
1153 reg.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
1154 reg.sCertificateProvider.pwszDLLName = wintrust;
1155 reg.sCertificateProvider.pwszFunctionName = wintrustCertificateTrust;
1156 reg.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
1157 reg.sCertificatePolicyProvider.pwszDLLName = cryptdlg;
1158 reg.sCertificatePolicyProvider.pwszFunctionName = certTrustCertPolicy;
1159 reg.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
1160 reg.sFinalPolicyProvider.pwszDLLName = cryptdlg;
1161 reg.sFinalPolicyProvider.pwszFunctionName = certTrustFinalPolicy;
1162 reg.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
1163 reg.sCleanupProvider.pwszDLLName = cryptdlg;
1164 reg.sCleanupProvider.pwszFunctionName = certTrustCleanup;
1165 if (!WintrustAddActionID(&guid, WT_ADD_ACTION_ID_RET_RESULT_FLAG, &reg))
1166 hr = GetLastError();
1167 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
1168 "1.3.6.1.4.1.311.16.1.1", cryptDlg, "EncodeAttrSequence");
1169 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
1170 szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "EncodeRecipientID");
1171 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
1172 "1.3.6.1.4.1.311.16.1.1", cryptDlg, "DecodeAttrSequence");
1173 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
1174 szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "DecodeRecipientID");
1175 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
1176 szOID_PKIX_KP_EMAIL_PROTECTION, cryptDlg, "FormatPKIXEmailProtection");
1177 CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
1178 szOID_CERT_POLICIES, cryptDlg, "FormatVerisignExtension");
1179 return hr;
1180 }
1181
1182 /***********************************************************************
1183 * DllUnregisterServer (CRYPTDLG.@)
1184 */
1185 HRESULT WINAPI DllUnregisterServer(void)
1186 {
1187 GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
1188
1189 WintrustRemoveActionID(&guid);
1190 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
1191 "1.3.6.1.4.1.311.16.1.1");
1192 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
1193 szOID_MICROSOFT_Encryption_Key_Preference);
1194 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
1195 "1.3.6.1.4.1.311.16.1.1");
1196 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
1197 szOID_MICROSOFT_Encryption_Key_Preference);
1198 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
1199 szOID_PKIX_KP_EMAIL_PROTECTION);
1200 CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
1201 szOID_CERT_POLICIES);
1202 return S_OK;
1203 }