quartz: Make some functions and variables static.
[wine] / dlls / 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 "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg);
38
39 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
40 {
41     TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
42
43     switch (fdwReason)
44     {
45         case DLL_WINE_PREATTACH:
46             return FALSE;    /* prefer native version */
47         case DLL_PROCESS_ATTACH:
48             DisableThreadLibraryCalls(hinstDLL);
49             break;
50         case DLL_PROCESS_DETACH:
51             break;
52         default:
53             break;
54     }
55     return TRUE;
56 }
57
58 /***********************************************************************
59  *              GetFriendlyNameOfCertA (CRYPTDLG.@)
60  */
61 DWORD WINAPI GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pchBuffer,
62                              DWORD cchBuffer)
63 {
64     return CertGetNameStringA(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
65      pchBuffer, cchBuffer);
66 }
67
68 /***********************************************************************
69  *              GetFriendlyNameOfCertW (CRYPTDLG.@)
70  */
71 DWORD WINAPI GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pchBuffer,
72                              DWORD cchBuffer)
73 {
74     return CertGetNameStringW(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
75      pchBuffer, cchBuffer);
76 }
77
78 /***********************************************************************
79  *              CertTrustInit (CRYPTDLG.@)
80  */
81 HRESULT WINAPI CertTrustInit(CRYPT_PROVIDER_DATA *pProvData)
82 {
83     HRESULT ret = S_FALSE;
84
85     TRACE("(%p)\n", pProvData);
86
87     if (pProvData->padwTrustStepErrors &&
88      !pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
89         ret = S_OK;
90     TRACE("returning %08x\n", ret);
91     return ret;
92 }
93
94 /***********************************************************************
95  *              CertTrustCertPolicy (CRYPTDLG.@)
96  */
97 BOOL WINAPI CertTrustCertPolicy(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSignerChain, DWORD idxCounterSigner)
98 {
99     FIXME("(%p, %d, %s, %d)\n", pProvData, idxSigner, fCounterSignerChain ? "TRUE" : "FALSE", idxCounterSigner);
100     return FALSE;
101 }
102
103 /***********************************************************************
104  *              CertTrustCleanup (CRYPTDLG.@)
105  */
106 HRESULT WINAPI CertTrustCleanup(CRYPT_PROVIDER_DATA *pProvData)
107 {
108     FIXME("(%p)\n", pProvData);
109     return E_NOTIMPL;
110 }
111
112 static BOOL CRYPTDLG_CheckOnlineCRL(void)
113 {
114     static const WCHAR policyFlagsKey[] = { 'S','o','f','t','w','a','r','e',
115      '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
116      'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
117      '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
118      '7','9','3','8','7','e','a','}',0 };
119     static const WCHAR policyFlags[] = { 'P','o','l','i','c','y','F','l','a',
120      'g','s',0 };
121     HKEY key;
122     BOOL ret = FALSE;
123
124     if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, policyFlagsKey, 0, KEY_READ, &key))
125     {
126         DWORD type, flags, size = sizeof(flags);
127
128         if (!RegQueryValueExW(key, policyFlags, NULL, &type, (BYTE *)&flags,
129          &size) && type == REG_DWORD)
130         {
131             /* The flag values aren't defined in any header I'm aware of, but
132              * this value is well documented on the net.
133              */
134             if (flags & 0x00010000)
135                 ret = TRUE;
136         }
137         RegCloseKey(key);
138     }
139     return ret;
140 }
141
142 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
143  * is.
144  */
145 static BOOL CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert)
146 {
147     BOOL ret;
148     BYTE hash[20];
149     DWORD size = sizeof(hash);
150
151     if ((ret = CertGetCertificateContextProperty(pCert,
152      CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
153     {
154         static const WCHAR disallowedW[] =
155          { 'D','i','s','a','l','l','o','w','e','d',0 };
156         HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
157          X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, disallowedW);
158
159         if (disallowed)
160         {
161             PCCERT_CONTEXT found = CertFindCertificateInStore(disallowed,
162              X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH, hash, NULL);
163
164             if (found)
165             {
166                 ret = FALSE;
167                 CertFreeCertificateContext(found);
168             }
169             CertCloseStore(disallowed, 0);
170         }
171     }
172     return ret;
173 }
174
175 static DWORD CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus)
176 {
177     DWORD confidence = 0;
178
179     confidence = 0;
180     if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
181         confidence |= CERT_CONFIDENCE_SIG;
182     if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID))
183         confidence |= CERT_CONFIDENCE_TIME;
184     if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED))
185         confidence |= CERT_CONFIDENCE_TIMENEST;
186     return confidence;
187 }
188
189 static BOOL CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA *data,
190  PCCERT_CHAIN_CONTEXT chain)
191 {
192     BOOL ret;
193     CRYPT_PROVIDER_SGNR signer;
194     PCERT_SIMPLE_CHAIN simpleChain = chain->rgpChain[0];
195     DWORD i;
196
197     memset(&signer, 0, sizeof(signer));
198     signer.cbStruct = sizeof(signer);
199     ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
200     if (ret)
201     {
202         CRYPT_PROVIDER_SGNR *sgnr = WTHelperGetProvSignerFromChain(data, 0,
203          FALSE, 0);
204
205         if (sgnr)
206         {
207             sgnr->dwError = simpleChain->TrustStatus.dwErrorStatus;
208             sgnr->pChainContext = CertDuplicateCertificateChain(chain);
209         }
210         else
211             ret = FALSE;
212         for (i = 0; ret && i < simpleChain->cElement; i++)
213         {
214             ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
215              simpleChain->rgpElement[i]->pCertContext);
216             if (ret)
217             {
218                 CRYPT_PROVIDER_CERT *cert;
219
220                 if ((cert = WTHelperGetProvCertFromChain(sgnr, i)))
221                 {
222                     CERT_CHAIN_ELEMENT *element = simpleChain->rgpElement[i];
223
224                     cert->dwConfidence = CRYPTDLG_TrustStatusToConfidence(
225                      element->TrustStatus.dwErrorStatus);
226                     cert->dwError = element->TrustStatus.dwErrorStatus;
227                     cert->pChainElement = element;
228                 }
229                 else
230                     ret = FALSE;
231             }
232         }
233     }
234     return ret;
235 }
236
237 static CERT_VERIFY_CERTIFICATE_TRUST *CRYPTDLG_GetVerifyData(
238  CRYPT_PROVIDER_DATA *data)
239 {
240     CERT_VERIFY_CERTIFICATE_TRUST *pCert = NULL;
241
242     /* This should always be true, but just in case the calling function is
243      * called directly:
244      */
245     if (data->pWintrustData->dwUnionChoice == WTD_CHOICE_BLOB &&
246      data->pWintrustData->u.pBlob && data->pWintrustData->u.pBlob->cbMemObject ==
247      sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
248      data->pWintrustData->u.pBlob->pbMemObject)
249          pCert = (CERT_VERIFY_CERTIFICATE_TRUST *)
250           data->pWintrustData->u.pBlob->pbMemObject;
251     return pCert;
252 }
253
254 static HCERTCHAINENGINE CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST *cert)
255 {
256     HCERTCHAINENGINE engine = NULL;
257     HCERTSTORE root = NULL, trust = NULL;
258     DWORD i;
259
260     if (cert->cRootStores)
261     {
262         root = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
263          CERT_STORE_CREATE_NEW_FLAG, NULL);
264         if (root)
265         {
266             for (i = 0; i < cert->cRootStores; i++)
267                 CertAddStoreToCollection(root, cert->rghstoreRoots[i], 0, 0);
268         }
269     }
270     if (cert->cTrustStores)
271     {
272         trust = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
273          CERT_STORE_CREATE_NEW_FLAG, NULL);
274         if (root)
275         {
276             for (i = 0; i < cert->cTrustStores; i++)
277                 CertAddStoreToCollection(trust, cert->rghstoreTrust[i], 0, 0);
278         }
279     }
280     if (cert->cRootStores || cert->cStores || cert->cTrustStores)
281     {
282         CERT_CHAIN_ENGINE_CONFIG config;
283
284         memset(&config, 0, sizeof(config));
285         config.cbSize = sizeof(config);
286         config.hRestrictedRoot = root;
287         config.hRestrictedTrust = trust;
288         config.cAdditionalStore = cert->cStores;
289         config.rghAdditionalStore = cert->rghstoreCAs;
290         config.hRestrictedRoot = root;
291         CertCreateCertificateChainEngine(&config, &engine);
292         CertCloseStore(root, 0);
293         CertCloseStore(trust, 0);
294     }
295     return engine;
296 }
297
298 /***********************************************************************
299  *              CertTrustFinalPolicy (CRYPTDLG.@)
300  */
301 HRESULT WINAPI CertTrustFinalPolicy(CRYPT_PROVIDER_DATA *data)
302 {
303     BOOL ret;
304     DWORD err = S_OK;
305     CERT_VERIFY_CERTIFICATE_TRUST *pCert = CRYPTDLG_GetVerifyData(data);
306
307     TRACE("(%p)\n", data);
308
309     if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
310         FIXME("unimplemented for UI choice %d\n",
311          data->pWintrustData->dwUIChoice);
312     if (pCert)
313     {
314         DWORD flags = 0;
315         CERT_CHAIN_PARA chainPara;
316         HCERTCHAINENGINE engine;
317
318         memset(&chainPara, 0, sizeof(chainPara));
319         chainPara.cbSize = sizeof(chainPara);
320         if (CRYPTDLG_CheckOnlineCRL())
321             flags |= CERT_CHAIN_REVOCATION_CHECK_END_CERT;
322         engine = CRYPTDLG_MakeEngine(pCert);
323         GetSystemTimeAsFileTime(&data->sftSystemTime);
324         ret = CRYPTDLG_IsCertAllowed(pCert->pccert);
325         if (ret)
326         {
327             PCCERT_CHAIN_CONTEXT chain;
328
329             ret = CertGetCertificateChain(engine, pCert->pccert,
330              &data->sftSystemTime, NULL, &chainPara, flags, NULL, &chain);
331             if (ret)
332             {
333                 if (chain->cChain != 1)
334                 {
335                     FIXME("unimplemented for more than 1 simple chain\n");
336                     err = TRUST_E_SUBJECT_FORM_UNKNOWN;
337                     ret = FALSE;
338                 }
339                 else if ((ret = CRYPTDLG_CopyChain(data, chain)))
340                 {
341                     if (CertVerifyTimeValidity(&data->sftSystemTime,
342                      pCert->pccert->pCertInfo))
343                     {
344                         ret = FALSE;
345                         err = CERT_E_EXPIRED;
346                     }
347                 }
348                 else
349                     err = TRUST_E_SYSTEM_ERROR;
350                 CertFreeCertificateChain(chain);
351             }
352             else
353                 err = TRUST_E_SUBJECT_NOT_TRUSTED;
354         }
355         CertFreeCertificateChainEngine(engine);
356     }
357     else
358     {
359         ret = FALSE;
360         err = TRUST_E_NOSIGNATURE;
361     }
362     /* Oddly, native doesn't set the error in the trust step error location,
363      * probably because this action is more advisory than anything else.
364      * Instead it stores it as the final error, but the function "succeeds" in
365      * any case.
366      */
367     if (!ret)
368         data->dwFinalError = err;
369     TRACE("returning %d (%08x)\n", S_OK, data->dwFinalError);
370     return S_OK;
371 }
372
373 /***********************************************************************
374  *              CertViewPropertiesA (CRYPTDLG.@)
375  */
376 BOOL WINAPI CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A *info)
377 {
378     CERT_VIEWPROPERTIES_STRUCT_W infoW;
379     LPWSTR title = NULL;
380     BOOL ret;
381
382     TRACE("(%p)\n", info);
383
384     memcpy(&infoW, info, sizeof(infoW));
385     if (info->szTitle)
386     {
387         int len = MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, NULL, 0);
388
389         title = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
390         if (title)
391         {
392             MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, title, len);
393             infoW.szTitle = title;
394         }
395         else
396         {
397             ret = FALSE;
398             goto error;
399         }
400     }
401     ret = CertViewPropertiesW(&infoW);
402     HeapFree(GetProcessHeap(), 0, title);
403 error:
404     return ret;
405 }
406
407 /***********************************************************************
408  *              CertViewPropertiesW (CRYPTDLG.@)
409  */
410 BOOL WINAPI CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W *info)
411 {
412     static GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
413     CERT_VERIFY_CERTIFICATE_TRUST trust;
414     WINTRUST_BLOB_INFO blob;
415     WINTRUST_DATA wtd;
416     LONG err;
417     BOOL ret;
418
419     TRACE("(%p)\n", info);
420
421     memset(&trust, 0, sizeof(trust));
422     trust.cbSize = sizeof(trust);
423     trust.pccert = info->pCertContext;
424     trust.cRootStores = info->cRootStores;
425     trust.rghstoreRoots = info->rghstoreRoots;
426     trust.cStores = info->cStores;
427     trust.rghstoreCAs = info->rghstoreCAs;
428     trust.cTrustStores = info->cTrustStores;
429     trust.rghstoreTrust = info->rghstoreTrust;
430     memset(&blob, 0, sizeof(blob));
431     blob.cbStruct = sizeof(blob);
432     blob.cbMemObject = sizeof(trust);
433     blob.pbMemObject = (BYTE *)&trust;
434     memset(&wtd, 0, sizeof(wtd));
435     wtd.cbStruct = sizeof(wtd);
436     wtd.dwUIChoice = WTD_UI_NONE;
437     wtd.dwUnionChoice = WTD_CHOICE_BLOB;
438     wtd.u.pBlob = &blob;
439     wtd.dwStateAction = WTD_STATEACTION_VERIFY;
440     err = WinVerifyTrust(NULL, &cert_action_verify, &wtd);
441     if (err == ERROR_SUCCESS)
442     {
443         CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo;
444         BOOL propsChanged = FALSE;
445
446         memset(&uiInfo, 0, sizeof(uiInfo));
447         uiInfo.dwSize = sizeof(uiInfo);
448         uiInfo.hwndParent = info->hwndParent;
449         uiInfo.dwFlags =
450          CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_EDITPROPERTIES;
451         uiInfo.szTitle = info->szTitle;
452         uiInfo.pCertContext = info->pCertContext;
453         uiInfo.cPurposes = info->cArrayPurposes;
454         uiInfo.rgszPurposes = (LPCSTR *)info->arrayPurposes;
455         uiInfo.u.hWVTStateData = wtd.hWVTStateData;
456         uiInfo.fpCryptProviderDataTrustedUsage = TRUE;
457         uiInfo.cPropSheetPages = info->cArrayPropSheetPages;
458         uiInfo.rgPropSheetPages = info->arrayPropSheetPages;
459         uiInfo.nStartPage = info->nStartPage;
460         ret = CryptUIDlgViewCertificateW(&uiInfo, &propsChanged);
461         wtd.dwStateAction = WTD_STATEACTION_CLOSE;
462         WinVerifyTrust(NULL, &cert_action_verify, &wtd);
463     }
464     else
465         ret = FALSE;
466     return ret;
467 }
468
469 #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
470
471 /***********************************************************************
472  *              DllRegisterServer (CRYPTDLG.@)
473  */
474 HRESULT WINAPI DllRegisterServer(void)
475 {
476     static WCHAR cryptdlg[] = { 'c','r','y','p','t','d','l','g','.',
477      'd','l','l',0 };
478     static WCHAR wintrust[] = { 'w','i','n','t','r','u','s','t','.',
479      'd','l','l',0 };
480     static WCHAR certTrustInit[] = { 'C','e','r','t','T','r','u','s','t',
481      'I','n','i','t',0 };
482     static WCHAR wintrustCertificateTrust[] = { 'W','i','n','t','r','u','s','t',
483      'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
484     static WCHAR certTrustCertPolicy[] = { 'C','e','r','t','T','r','u','s','t',
485      'C','e','r','t','P','o','l','i','c','y',0 };
486     static WCHAR certTrustFinalPolicy[] = { 'C','e','r','t','T','r','u','s','t',
487      'F','i','n','a','l','P','o','l','i','c','y',0 };
488     static WCHAR certTrustCleanup[] = { 'C','e','r','t','T','r','u','s','t',
489      'C','l','e','a','n','u','p',0 };
490     static const WCHAR cryptDlg[] = { 'c','r','y','p','t','d','l','g','.',
491        'd','l','l',0 };
492     CRYPT_REGISTER_ACTIONID reg;
493     GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
494     HRESULT hr = S_OK;
495
496     memset(&reg, 0, sizeof(reg));
497     reg.cbStruct = sizeof(reg);
498     reg.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
499     reg.sInitProvider.pwszDLLName = cryptdlg;
500     reg.sInitProvider.pwszFunctionName = certTrustInit;
501     reg.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
502     reg.sCertificateProvider.pwszDLLName = wintrust;
503     reg.sCertificateProvider.pwszFunctionName = wintrustCertificateTrust;
504     reg.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
505     reg.sCertificatePolicyProvider.pwszDLLName = cryptdlg;
506     reg.sCertificatePolicyProvider.pwszFunctionName = certTrustCertPolicy;
507     reg.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
508     reg.sFinalPolicyProvider.pwszDLLName = cryptdlg;
509     reg.sFinalPolicyProvider.pwszFunctionName = certTrustFinalPolicy;
510     reg.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
511     reg.sCleanupProvider.pwszDLLName = cryptdlg;
512     reg.sCleanupProvider.pwszFunctionName = certTrustCleanup;
513     if (!WintrustAddActionID(&guid, WT_ADD_ACTION_ID_RET_RESULT_FLAG, &reg))
514         hr = GetLastError();
515     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
516      "1.3.6.1.4.1.311.16.1.1", cryptDlg, "EncodeAttrSequence");
517     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
518      szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "EncodeRecipientID");
519     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
520      "1.3.6.1.4.1.311.16.1.1", cryptDlg, "DecodeAttrSequence");
521     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
522      szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "DecodeRecipientID");
523     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
524      szOID_PKIX_KP_EMAIL_PROTECTION, cryptDlg, "FormatPKIXEmailProtection");
525     CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
526      szOID_CERT_POLICIES, cryptDlg, "FormatVerisignExtension");
527     return hr;
528 }
529
530 /***********************************************************************
531  *              DllUnregisterServer (CRYPTDLG.@)
532  */
533 HRESULT WINAPI DllUnregisterServer(void)
534 {
535     GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
536
537     WintrustRemoveActionID(&guid);
538     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
539      "1.3.6.1.4.1.311.16.1.1");
540     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
541      szOID_MICROSOFT_Encryption_Key_Preference);
542     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
543      "1.3.6.1.4.1.311.16.1.1");
544     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
545      szOID_MICROSOFT_Encryption_Key_Preference);
546     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
547      szOID_PKIX_KP_EMAIL_PROTECTION);
548     CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
549      szOID_CERT_POLICIES);
550     return S_OK;
551 }