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