crypt32: Improve error checking for the base policy.
[wine] / dlls / crypt32 / tests / oid.c
1 /*
2  * Unit test suite for crypt32.dll's OID support functions.
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26 #include <winreg.h>
27
28 #include "wine/test.h"
29
30
31 static BOOL (WINAPI *pCryptEnumOIDInfo)(DWORD,DWORD,void*,PFN_CRYPT_ENUM_OID_INFO);
32
33
34 struct OIDToAlgID
35 {
36     LPCSTR oid;
37     LPCSTR altOid;
38     DWORD algID;
39 };
40
41 static const struct OIDToAlgID oidToAlgID[] = {
42  { szOID_RSA_RSA, NULL, CALG_RSA_KEYX },
43  { szOID_RSA_MD2RSA, NULL, CALG_MD2 },
44  { szOID_RSA_MD4RSA, NULL, CALG_MD4 },
45  { szOID_RSA_MD5RSA, NULL, CALG_MD5 },
46  { szOID_RSA_SHA1RSA, NULL, CALG_SHA },
47  { szOID_RSA_DH, NULL, CALG_DH_SF },
48  { szOID_RSA_SMIMEalgESDH, NULL, CALG_DH_EPHEM },
49  { szOID_RSA_SMIMEalgCMS3DESwrap, NULL, CALG_3DES },
50  { szOID_RSA_SMIMEalgCMSRC2wrap, NULL, CALG_RC2 },
51  { szOID_RSA_MD2, NULL, CALG_MD2 },
52  { szOID_RSA_MD4, NULL, CALG_MD4 },
53  { szOID_RSA_MD5, NULL, CALG_MD5 },
54  { szOID_RSA_RC2CBC, NULL, CALG_RC2 },
55  { szOID_RSA_RC4, NULL, CALG_RC4 },
56  { szOID_RSA_DES_EDE3_CBC, NULL, CALG_3DES },
57  { szOID_ANSI_X942_DH, NULL, CALG_DH_SF },
58  { szOID_X957_DSA, NULL, CALG_DSS_SIGN },
59  { szOID_X957_SHA1DSA, NULL, CALG_SHA },
60  { szOID_OIWSEC_md4RSA, NULL, CALG_MD4 },
61  { szOID_OIWSEC_md5RSA, NULL, CALG_MD5 },
62  { szOID_OIWSEC_md4RSA2, NULL, CALG_MD4 },
63  { szOID_OIWSEC_desCBC, NULL, CALG_DES },
64  { szOID_OIWSEC_dsa, NULL, CALG_DSS_SIGN },
65  { szOID_OIWSEC_shaDSA, NULL, CALG_SHA },
66  { szOID_OIWSEC_shaRSA, NULL, CALG_SHA },
67  { szOID_OIWSEC_sha, NULL, CALG_SHA },
68  { szOID_OIWSEC_rsaXchg, NULL, CALG_RSA_KEYX },
69  { szOID_OIWSEC_sha1, NULL, CALG_SHA },
70  { szOID_OIWSEC_dsaSHA1, NULL, CALG_SHA },
71  { szOID_OIWSEC_sha1RSASign, NULL, CALG_SHA },
72  { szOID_OIWDIR_md2RSA, NULL, CALG_MD2 },
73  { szOID_INFOSEC_mosaicUpdatedSig, NULL, CALG_SHA },
74  { szOID_INFOSEC_mosaicKMandUpdSig, NULL, CALG_DSS_SIGN },
75 };
76
77 static const struct OIDToAlgID algIDToOID[] = {
78  { szOID_RSA_RSA, NULL, CALG_RSA_KEYX },
79  { szOID_RSA_SMIMEalgESDH, NULL, CALG_DH_EPHEM },
80  { szOID_RSA_MD2, NULL, CALG_MD2 },
81  { szOID_RSA_MD4, NULL, CALG_MD4 },
82  { szOID_RSA_MD5, NULL, CALG_MD5 },
83  { szOID_RSA_RC2CBC, NULL, CALG_RC2 },
84  { szOID_RSA_RC4, NULL, CALG_RC4 },
85  { szOID_RSA_DES_EDE3_CBC, NULL, CALG_3DES },
86  { szOID_ANSI_X942_DH, NULL, CALG_DH_SF },
87  { szOID_X957_DSA, szOID_OIWSEC_dsa /* some Win98 */, CALG_DSS_SIGN },
88  { szOID_OIWSEC_desCBC, NULL, CALG_DES },
89  { szOID_OIWSEC_sha1, NULL, CALG_SHA },
90 };
91
92 static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
93 static const WCHAR bogus2Dll[] = { 'b','o','g','u','s','2','.','d','l','l',0 };
94
95 static void testOIDToAlgID(void)
96 {
97     int i;
98     DWORD alg;
99
100     /* Test with a bogus one */
101     alg = CertOIDToAlgId("1.2.3");
102     ok(!alg, "Expected failure, got %d\n", alg);
103
104     for (i = 0; i < sizeof(oidToAlgID) / sizeof(oidToAlgID[0]); i++)
105     {
106         alg = CertOIDToAlgId(oidToAlgID[i].oid);
107         /* Not all Windows installations support all these, so make sure it's
108          * at least not the wrong one.
109          */
110         ok(alg == 0 || alg == oidToAlgID[i].algID,
111          "Expected %d, got %d\n", oidToAlgID[i].algID, alg);
112     }
113 }
114
115 static void testAlgIDToOID(void)
116 {
117     int i;
118     LPCSTR oid;
119
120     /* Test with a bogus one */
121     SetLastError(0xdeadbeef);
122     oid = CertAlgIdToOID(ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | 80);
123     ok(!oid && GetLastError() == 0xdeadbeef,
124      "Didn't expect last error (%08x) to be set\n", GetLastError());
125     for (i = 0; i < sizeof(algIDToOID) / sizeof(algIDToOID[0]); i++)
126     {
127         oid = CertAlgIdToOID(algIDToOID[i].algID);
128         /* Allow failure, not every version of Windows supports every algo */
129         if (oid)
130         {
131             if (strcmp(oid, algIDToOID[i].oid))
132             {
133                 if (algIDToOID[i].altOid)
134                     ok(!strcmp(oid, algIDToOID[i].altOid),
135                      "Expected %s or %s, got %s\n", algIDToOID[i].oid,
136                      algIDToOID[i].altOid, oid);
137                 else
138                 {
139                     /* No need to rerun the test, we already know it failed. */
140                     ok(0, "Expected %s, got %s\n", algIDToOID[i].oid, oid);
141                 }
142             }
143             else
144             {
145                 /* No need to rerun the test, we already know it succeeded. */
146                 ok(1, "Expected %s, got %s\n", algIDToOID[i].oid, oid);
147             }
148         }
149     }
150 }
151
152 static void test_oidFunctionSet(void)
153 {
154     HCRYPTOIDFUNCSET set1, set2;
155     BOOL ret;
156     LPWSTR buf = NULL;
157     DWORD size;
158
159     /* This crashes
160     set = CryptInitOIDFunctionSet(NULL, 0);
161      */
162
163     /* The name doesn't mean much */
164     set1 = CryptInitOIDFunctionSet("funky", 0);
165     ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
166     if (set1)
167     {
168         /* These crash
169         ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, NULL);
170         ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, &size);
171          */
172         size = 0;
173         ret = CryptGetDefaultOIDDllList(set1, 0, NULL, &size);
174         ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n", GetLastError());
175         if (ret)
176         {
177             buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
178             if (buf)
179             {
180                 ret = CryptGetDefaultOIDDllList(set1, 0, buf, &size);
181                 ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n",
182                  GetLastError());
183                 ok(!*buf, "Expected empty DLL list\n");
184                 HeapFree(GetProcessHeap(), 0, buf);
185             }
186         }
187     }
188
189     /* MSDN says flags must be 0, but it's not checked */
190     set1 = CryptInitOIDFunctionSet("", 1);
191     ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
192     set2 = CryptInitOIDFunctionSet("", 0);
193     ok(set2 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
194     /* There isn't a free function, so there must be only one set per name to
195      * limit leaks.  (I guess the sets are freed when crypt32 is unloaded.)
196      */
197     ok(set1 == set2, "Expected identical sets\n");
198     if (set1)
199     {
200         /* The empty name function set used here seems to correspond to
201          * DEFAULT.
202          */
203     }
204
205     /* There's no installed function for a built-in encoding. */
206     set1 = CryptInitOIDFunctionSet("CryptDllEncodeObject", 0);
207     ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
208     if (set1)
209     {
210         void *funcAddr;
211         HCRYPTOIDFUNCADDR hFuncAddr;
212
213         ret = CryptGetOIDFunctionAddress(set1, X509_ASN_ENCODING, X509_CERT, 0,
214          &funcAddr, &hFuncAddr);
215         ok((!ret && GetLastError() == ERROR_FILE_NOT_FOUND) ||
216          broken(ret) /* some Win98 */,
217          "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
218     }
219 }
220
221 typedef int (*funcY)(int);
222
223 static int funky(int x)
224 {
225     return x;
226 }
227
228 static void test_installOIDFunctionAddress(void)
229 {
230     BOOL ret;
231     CRYPT_OID_FUNC_ENTRY entry = { CRYPT_DEFAULT_OID, funky };
232     HCRYPTOIDFUNCSET set;
233
234     /* This crashes
235     ret = CryptInstallOIDFunctionAddress(NULL, 0, NULL, 0, NULL, 0);
236      */
237
238     /* Installing zero functions should work */
239     SetLastError(0xdeadbeef);
240     ret = CryptInstallOIDFunctionAddress(NULL, 0, "CryptDllEncodeObject", 0,
241      NULL, 0);
242     ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
243      GetLastError());
244
245     /* The function name doesn't much matter */
246     SetLastError(0xdeadbeef);
247     ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 0, NULL, 0);
248     ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
249      GetLastError());
250     SetLastError(0xdeadbeef);
251     entry.pszOID = X509_CERT;
252     ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 1, &entry, 0);
253     ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
254      GetLastError());
255     set = CryptInitOIDFunctionSet("OhSoFunky", 0);
256     ok(set != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
257     if (set)
258     {
259         funcY funcAddr = NULL;
260         HCRYPTOIDFUNCADDR hFuncAddr = NULL;
261
262         /* This crashes
263         ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0, NULL,
264          NULL);
265          */
266         ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0,
267          (void **)&funcAddr, &hFuncAddr);
268         ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
269          GetLastError() == E_INVALIDARG /* some Win98 */),
270          "Expected ERROR_FILE_NOT_FOUND or E_INVALIDARG, got %d\n",
271          GetLastError());
272         ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, X509_CERT, 0,
273          (void **)&funcAddr, &hFuncAddr);
274         ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
275          "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
276         ret = CryptGetOIDFunctionAddress(set, 0, X509_CERT, 0,
277          (void **)&funcAddr, &hFuncAddr);
278         ok(ret, "CryptGetOIDFunctionAddress failed: %d\n", GetLastError());
279         if (funcAddr)
280         {
281             int y = funcAddr(0xabadc0da);
282
283             ok(y == 0xabadc0da, "Unexpected return (%d) from function\n", y);
284             CryptFreeOIDFunctionAddress(hFuncAddr, 0);
285         }
286     }
287 }
288
289 static void test_registerOIDFunction(void)
290 {
291     BOOL ret;
292
293     /* oddly, this succeeds under WinXP; the function name key is merely
294      * omitted.  This may be a side effect of the registry code, I don't know.
295      * I don't check it because I doubt anyone would depend on it.
296     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
297      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
298      */
299     /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
300      * E_INVALIDARG
301      */
302     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
303      NULL);
304     ok(!ret && GetLastError() == E_INVALIDARG,
305      "Expected E_INVALIDARG: %d\n", GetLastError());
306     /* This has no effect, but "succeeds" on XP */
307     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
308      "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
309     ok(ret, "Expected pseudo-success, got %d\n", GetLastError());
310     SetLastError(0xdeadbeef);
311     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
312      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
313     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
314     {
315         skip("Need admin rights\n");
316         return;
317     }
318     ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
319     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
320      "1.2.3.4.5.6.7.8.9.10");
321     ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
322     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
323      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
324     ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
325     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
326      "1.2.3.4.5.6.7.8.9.10");
327     ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
328     /* Unwanted Cryptography\OID\EncodingType 1\bogus\ will still be there */
329     ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
330      "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 1\\bogus"),
331      "Could not delete bogus key\n");
332     /* Shouldn't have effect but registry keys are created */
333     ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
334      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
335     ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
336     ret = CryptUnregisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
337      "1.2.3.4.5.6.7.8.9.10");
338     ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
339     /* Check with bogus encoding type. Registry keys are still created */
340     ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
341      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
342     ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
343     ret = CryptUnregisterOIDFunction(0, "CryptDllEncodeObject",
344      "1.2.3.4.5.6.7.8.9.10");
345     ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
346     /* Unwanted Cryptography\OID\EncodingType 0\CryptDllEncodeObject\
347      * will still be there
348      */
349     ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
350      "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllEncodeObject"),
351      "Could not delete CryptDllEncodeObject key\n");
352     /* This is written with value 3 verbatim.  Thus, the encoding type isn't
353      * (for now) treated as a mask. Registry keys are created.
354      */
355     ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
356      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
357     ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
358     ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
359      "1.2.3.4.5.6.7.8.9.10");
360     ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
361     /* Unwanted Cryptography\OID\EncodingType 3\CryptDllEncodeObject
362      * will still be there.
363      */
364     ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
365      "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3\\CryptDllEncodeObject"),
366      "Could not delete CryptDllEncodeObject key\n");
367     ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
368      "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3"),
369      "Could not delete 'EncodingType 3' key\n");
370 }
371
372 static void test_registerDefaultOIDFunction(void)
373 {
374     static const char fmt[] =
375      "Software\\Microsoft\\Cryptography\\OID\\EncodingType %d\\%s\\DEFAULT";
376     static const char func[] = "CertDllOpenStoreProv";
377     char buf[MAX_PATH];
378     BOOL ret;
379     LSTATUS rc;
380     HKEY key;
381
382     ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, NULL);
383     ok(!ret && GetLastError() == E_INVALIDARG,
384      "Expected E_INVALIDARG, got %08x\n", GetLastError());
385     /* This succeeds on WinXP, although the bogus entry is unusable.
386     ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, bogusDll);
387      */
388     /* Register one at index 0 */
389     SetLastError(0xdeadbeef);
390     ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
391      bogusDll);
392     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
393     {
394         skip("Need admin rights\n");
395         return;
396     }
397     ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
398     /* Reregistering should fail */
399     ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
400      bogusDll);
401     ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
402      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
403     /* Registering the same one at index 1 should also fail */
404     ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1,
405      bogusDll);
406     ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
407      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
408     /* Registering a different one at index 1 succeeds */
409     ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1,
410      bogus2Dll);
411     ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
412     sprintf(buf, fmt, 0, func);
413     rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, buf, &key);
414     ok(rc == 0, "Expected key to exist, RegOpenKeyA failed: %d\n", rc);
415     if (rc == 0)
416     {
417         static const CHAR dllA[] = "Dll";
418         static const CHAR bogusDll_A[] = "bogus.dll";
419         static const CHAR bogus2Dll_A[] = "bogus2.dll";
420         CHAR dllBuf[MAX_PATH];
421         DWORD type, size;
422         LPSTR ptr;
423
424         size = sizeof(dllBuf) / sizeof(dllBuf[0]);
425         rc = RegQueryValueExA(key, dllA, NULL, &type, (LPBYTE)dllBuf, &size);
426         ok(rc == 0,
427          "Expected Dll value to exist, RegQueryValueExA failed: %d\n", rc);
428         ok(type == REG_MULTI_SZ, "Expected type REG_MULTI_SZ, got %d\n", type);
429         /* bogusDll was registered first, so that should be first */
430         ptr = dllBuf;
431         ok(!lstrcmpiA(ptr, bogusDll_A), "Unexpected dll\n");
432         ptr += lstrlenA(ptr) + 1;
433         ok(!lstrcmpiA(ptr, bogus2Dll_A), "Unexpected dll\n");
434         RegCloseKey(key);
435     }
436     /* Unregister both of them */
437     ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
438      bogusDll);
439     ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n",
440      GetLastError());
441     ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
442      bogus2Dll);
443     ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n",
444      GetLastError());
445     /* Now that they're both unregistered, unregistering should fail */
446     ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
447      bogusDll);
448     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
449      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
450
451     /* Repeat a few tests on the normal encoding type */
452     ret = CryptRegisterDefaultOIDFunction(X509_ASN_ENCODING,
453      "CertDllOpenStoreProv", 0, bogusDll);
454     ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING,
455      "CertDllOpenStoreProv", bogusDll);
456     ok(ret, "CryptUnregisterDefaultOIDFunction failed\n");
457     ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING,
458      "CertDllOpenStoreProv", bogusDll);
459     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
460      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
461 }
462
463 static void test_getDefaultOIDFunctionAddress(void)
464 {
465     BOOL ret;
466     HCRYPTOIDFUNCSET set;
467     void *funcAddr;
468     HCRYPTOIDFUNCADDR hFuncAddr;
469
470     /* Crash
471     ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, NULL);
472     ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr, NULL);
473     ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, &hFuncAddr);
474     ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr,
475      &hFuncAddr);
476      */
477     set = CryptInitOIDFunctionSet("CertDllOpenStoreProv", 0);
478     ok(set != 0, "CryptInitOIDFunctionSet failed: %d\n", GetLastError());
479     /* This crashes if hFuncAddr is not 0 to begin with */
480     hFuncAddr = 0;
481     ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr,
482      &hFuncAddr);
483     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
484      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
485     /* This fails with the normal encoding too, so built-in functions aren't
486      * returned.
487      */
488     ret = CryptGetDefaultOIDFunctionAddress(set, X509_ASN_ENCODING, NULL, 0,
489      &funcAddr, &hFuncAddr);
490     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
491      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
492
493     /* Even with a registered dll, this fails (since the dll doesn't exist) */
494     SetLastError(0xdeadbeef);
495     ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
496      bogusDll);
497     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
498         skip("Need admin rights\n");
499     else
500         ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
501     ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr,
502      &hFuncAddr);
503     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
504      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
505     CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", bogusDll);
506 }
507
508 static BOOL WINAPI countOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg)
509 {
510     (*(DWORD *)pvArg)++;
511     return TRUE;
512 }
513
514 static BOOL WINAPI noOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg)
515 {
516     return FALSE;
517 }
518
519 static void test_enumOIDInfo(void)
520 {
521     BOOL ret;
522     DWORD count = 0;
523
524     if (!pCryptEnumOIDInfo)
525     {
526         win_skip("CryptEnumOIDInfo() is not available\n");
527         return;
528     }
529
530     /* This crashes
531     ret = pCryptEnumOIDInfo(7, 0, NULL, NULL);
532      */
533
534     /* Silly tests, check that more than one thing is enumerated */
535     ret = pCryptEnumOIDInfo(0, 0, &count, countOidInfo);
536     ok(ret && count > 0, "Expected more than item enumerated\n");
537     ret = pCryptEnumOIDInfo(0, 0, NULL, noOidInfo);
538     ok(!ret, "Expected FALSE\n");
539 }
540
541 static void test_findOIDInfo(void)
542 {
543     static WCHAR sha1[] = { 's','h','a','1',0 };
544     static CHAR oid_rsa_md5[] = szOID_RSA_MD5;
545     ALG_ID alg = CALG_SHA1;
546     ALG_ID algs[2] = { CALG_MD5, CALG_RSA_SIGN };
547     PCCRYPT_OID_INFO info;
548
549     info = CryptFindOIDInfo(0, NULL, 0);
550     ok(info == NULL, "Expected NULL\n");
551     info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_rsa_md5, 0);
552     ok(info != NULL, "Expected to find szOID_RSA_MD5\n");
553     if (info)
554     {
555         ok(!strcmp(info->pszOID, szOID_RSA_MD5), "Expected %s, got %s\n",
556          szOID_RSA_MD5, info->pszOID);
557         ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
558            U(*info).Algid);
559     }
560     info = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, sha1, 0);
561     ok(info != NULL, "Expected to find sha1\n");
562     if (info)
563     {
564         ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
565          szOID_OIWSEC_sha1, info->pszOID);
566         ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
567            U(*info).Algid);
568     }
569     info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &alg, 0);
570     ok(info != NULL, "Expected to find sha1\n");
571     if (info)
572     {
573         ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
574          szOID_OIWSEC_sha1, info->pszOID);
575         ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
576            U(*info).Algid);
577     }
578     info = CryptFindOIDInfo(CRYPT_OID_INFO_SIGN_KEY, algs, 0);
579     ok(info != NULL, "Expected to find md5RSA\n");
580     if (info)
581     {
582         ok(!strcmp(info->pszOID, szOID_RSA_MD5RSA), "Expected %s, got %s\n",
583          szOID_RSA_MD5RSA, info->pszOID);
584         ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
585            U(*info).Algid);
586     }
587 }
588
589 START_TEST(oid)
590 {
591     HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
592     pCryptEnumOIDInfo = (void*)GetProcAddress(hCrypt32, "CryptEnumOIDInfo");
593
594     testOIDToAlgID();
595     testAlgIDToOID();
596     test_enumOIDInfo();
597     test_findOIDInfo();
598     test_oidFunctionSet();
599     test_installOIDFunctionAddress();
600     test_registerOIDFunction();
601     test_registerDefaultOIDFunction();
602     test_getDefaultOIDFunctionAddress();
603 }