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