wintrust: Implement WVTAsn1CatNameValueEncode.
[wine] / dlls / wintrust / tests / asn.c
1 /* Unit test suite for wintrust asn functions
2  *
3  * Copyright 2007 Juan Lang
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winerror.h"
24 #include "wincrypt.h"
25 #include "wintrust.h"
26
27 #include "wine/test.h"
28
29 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
30 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
31
32
33 static WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.',
34  'o','r','g',0 };
35 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
36  0x575b, 0 };
37 static const BYTE emptyURLSPCLink[] = { 0x80,0x00 };
38 static const BYTE urlSPCLink[] = {
39 0x80,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,
40 0x2e,0x6f,0x72,0x67};
41 static const BYTE fileSPCLink[] = {
42 0xa2,0x14,0x80,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
43 0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
44 static const BYTE emptyMonikerSPCLink[] = {
45 0xa1,0x14,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
46 0x00,0x00,0x00,0x00,0x00,0x04,0x00 };
47 static BYTE data[] = { 0xba, 0xad, 0xf0, 0x0d };
48 static const BYTE monikerSPCLink[] = {
49 0xa1,0x18,0x04,0x10,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,
50 0xea,0xea,0xea,0xea,0xea,0x04,0x04,0xba,0xad,0xf0,0x0d };
51
52 static void test_encodeSPCLink(void)
53 {
54     BOOL ret;
55     DWORD size = 0;
56     LPBYTE buf;
57     SPC_LINK link = { 0 };
58
59     if (!pCryptEncodeObjectEx)
60     {
61         skip("CryptEncodeObjectEx() is not available. Skipping the encodeSPCLink tests\n");
62         return;
63     }
64
65     SetLastError(0xdeadbeef);
66     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
67      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
68     ok(!ret && GetLastError() == E_INVALIDARG,
69      "Expected E_INVALIDARG, got %08x\n", GetLastError());
70     link.dwLinkChoice = SPC_URL_LINK_CHOICE;
71     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
72      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
73     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
74     if (ret)
75     {
76         ok(size == sizeof(emptyURLSPCLink), "Unexpected size %d\n", size);
77         ok(!memcmp(buf, emptyURLSPCLink, size), "Unexpected value\n");
78         LocalFree(buf);
79     }
80     /* With an invalid char: */
81     U(link).pwszUrl = (LPWSTR)nihongoURL;
82     size = 1;
83     SetLastError(0xdeadbeef);
84     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
85      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
86     ok(!ret &&
87      (GetLastError() == CRYPT_E_INVALID_IA5_STRING ||
88      GetLastError() == OSS_BAD_PTR /* Win9x */),
89      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
90     /* Unlike the crypt32 string encoding routines, size is not set to the
91      * index of the first invalid character.
92      */
93     ok(size == 0, "Expected size 0, got %d\n", size);
94     U(link).pwszUrl = url;
95     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
96      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
97     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
98     if (ret)
99     {
100         ok(size == sizeof(urlSPCLink), "Unexpected size %d\n", size);
101         ok(!memcmp(buf, urlSPCLink, size), "Unexpected value\n");
102         LocalFree(buf);
103     }
104     link.dwLinkChoice = SPC_FILE_LINK_CHOICE;
105     U(link).pwszFile = (LPWSTR)nihongoURL;
106     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
107      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
108     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
109     if (ret)
110     {
111         ok(size == sizeof(fileSPCLink), "Unexpected size %d\n", size);
112         ok(!memcmp(buf, fileSPCLink, size), "Unexpected value\n");
113         LocalFree(buf);
114     }
115     link.dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
116     memset(&U(link).Moniker, 0, sizeof(U(link).Moniker));
117     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
120     if (ret)
121     {
122         ok(size == sizeof(emptyMonikerSPCLink), "Unexpected size %d\n", size);
123         ok(!memcmp(buf, emptyMonikerSPCLink, size), "Unexpected value\n");
124         LocalFree(buf);
125     }
126     memset(&U(link).Moniker.ClassId, 0xea, sizeof(U(link).Moniker.ClassId));
127     U(link).Moniker.SerializedData.pbData = data;
128     U(link).Moniker.SerializedData.cbData = sizeof(data);
129     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
130      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
131     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
132     if (ret)
133     {
134         ok(size == sizeof(monikerSPCLink), "Unexpected size %d\n", size);
135         ok(!memcmp(buf, monikerSPCLink, size), "Unexpected value\n");
136         LocalFree(buf);
137     }
138 }
139
140 static const BYTE badMonikerSPCLink[] = {
141 0xa1,0x19,0x04,0x11,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,
142 0xea,0xea,0xea,0xea,0xea,0xea,0x04,0x04,0xba,0xad,0xf0,0x0d };
143
144 static void test_decodeSPCLink(void)
145 {
146     BOOL ret;
147     LPBYTE buf = NULL;
148     DWORD size = 0;
149     SPC_LINK *link;
150
151     if (!pCryptDecodeObjectEx)
152     {
153         skip("CryptDecodeObjectEx() is not available. Skipping the decodeSPCLink tests\n");
154         return;
155     }
156
157     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
158      emptyURLSPCLink, sizeof(emptyURLSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
159      (BYTE *)&buf, &size);
160     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
161     if (ret)
162     {
163         link = (SPC_LINK *)buf;
164         ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE,
165          "Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice);
166         ok(lstrlenW(U(*link).pwszUrl) == 0, "Expected empty string\n");
167         LocalFree(buf);
168     }
169     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
170      urlSPCLink, sizeof(urlSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
171      (BYTE *)&buf, &size);
172     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
173     if (ret)
174     {
175         link = (SPC_LINK *)buf;
176         ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE,
177          "Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice);
178         ok(!lstrcmpW(U(*link).pwszUrl, url), "Unexpected URL\n");
179         LocalFree(buf);
180     }
181     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
182      fileSPCLink, sizeof(fileSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
183      (BYTE *)&buf, &size);
184     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
185     if (ret)
186     {
187         link = (SPC_LINK *)buf;
188         ok(link->dwLinkChoice == SPC_FILE_LINK_CHOICE,
189          "Expected SPC_FILE_LINK_CHOICE, got %d\n", link->dwLinkChoice);
190         ok(!lstrcmpW(U(*link).pwszFile, nihongoURL), "Unexpected file\n");
191         LocalFree(buf);
192     }
193     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
194      emptyMonikerSPCLink, sizeof(emptyMonikerSPCLink), CRYPT_DECODE_ALLOC_FLAG,
195      NULL, (BYTE *)&buf, &size);
196     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
197     if (ret)
198     {
199         SPC_SERIALIZED_OBJECT emptyMoniker = { { 0 } };
200
201         link = (SPC_LINK *)buf;
202         ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE,
203          "Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice);
204         ok(!memcmp(&U(*link).Moniker.ClassId, &emptyMoniker.ClassId,
205          sizeof(emptyMoniker.ClassId)), "Unexpected value\n");
206         ok(U(*link).Moniker.SerializedData.cbData == 0,
207          "Expected no serialized data\n");
208         LocalFree(buf);
209     }
210     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
211      monikerSPCLink, sizeof(monikerSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
212      (BYTE *)&buf, &size);
213     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
214     if (ret)
215     {
216         SPC_UUID id;
217
218         link = (SPC_LINK *)buf;
219         ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE,
220          "Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice);
221         memset(&id, 0xea, sizeof(id));
222         ok(!memcmp(&U(*link).Moniker.ClassId, &id, sizeof(id)),
223          "Unexpected value\n");
224         ok(U(*link).Moniker.SerializedData.cbData == sizeof(data),
225            "Unexpected data size %d\n", U(*link).Moniker.SerializedData.cbData);
226         ok(!memcmp(U(*link).Moniker.SerializedData.pbData, data, sizeof(data)),
227          "Unexpected value\n");
228         LocalFree(buf);
229     }
230     SetLastError(0xdeadbeef);
231     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
232      badMonikerSPCLink, sizeof(badMonikerSPCLink), CRYPT_DECODE_ALLOC_FLAG,
233      NULL, (BYTE *)&buf, &size);
234     ok(!ret &&
235      (GetLastError() == CRYPT_E_BAD_ENCODE ||
236      GetLastError() == OSS_DATA_ERROR /* Win9x */),
237      "Expected CRYPT_E_BAD_ENCODE, got %08x\n", GetLastError());
238 }
239
240 static const BYTE emptySequence[] = { 0x30,0x00 };
241 static BYTE flags[] = { 1 };
242 static const BYTE onlyFlagsPEImage[] = { 0x30,0x04,0x03,0x02,0x00,0x01 };
243 static const BYTE moreFlagsPEImage[] = {
244 0x30,0x06,0x03,0x04,0x04,0xff,0x80,0x10 };
245 static const BYTE onlyEmptyFilePEImage[] = {
246 0x30,0x06,0xa0,0x04,0xa2,0x02,0x80,0x00 };
247 static const BYTE flagsAndEmptyFilePEImage[] = {
248 0x30,0x0a,0x03,0x02,0x00,0x01,0xa0,0x04,0xa2,0x02,0x80,0x00 };
249 static const BYTE flagsAndFilePEImage[] = {
250 0x30,0x1c,0x03,0x02,0x00,0x01,0xa0,0x16,0xa2,0x14,0x80,0x12,0x00,0x68,0x00,
251 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
252
253 static void test_encodeSPCPEImage(void)
254 {
255     BOOL ret;
256     DWORD size = 0;
257     LPBYTE buf;
258     SPC_PE_IMAGE_DATA imageData = { { 0 } };
259     SPC_LINK link = { 0 };
260
261     if (!pCryptEncodeObjectEx)
262     {
263         skip("CryptEncodeObjectEx() is not available. Skipping the encodeSPCPEImage tests\n");
264         return;
265     }
266
267     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
268      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
269     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
270     if (ret)
271     {
272         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
273         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
274          "Unexpected value\n");
275         LocalFree(buf);
276     }
277     /* With an invalid link: */
278     imageData.pFile = &link;
279     SetLastError(0xdeadbeef);
280     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
281      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
282     ok(!ret && GetLastError () == E_INVALIDARG,
283      "Expected E_INVALIDARG, got %08x\n", GetLastError());
284     /* With just unused bits field set: */
285     imageData.pFile = NULL;
286     imageData.Flags.cUnusedBits = 1;
287     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
288      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
289     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
290     if (ret)
291     {
292         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
293         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
294          "Unexpected value\n");
295         LocalFree(buf);
296     }
297     /* With flags set: */
298     imageData.Flags.cUnusedBits = 0;
299     imageData.Flags.pbData = flags;
300     imageData.Flags.cbData = sizeof(flags);
301     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
302      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
303     if (!ret && GetLastError() == OSS_TOO_LONG)
304     {
305         skip("SPC_PE_IMAGE_DATA_STRUCT not supported\n");
306         return;
307     }
308     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
309     if (ret)
310     {
311         ok(size == sizeof(onlyFlagsPEImage), "Unexpected size %d\n", size);
312         ok(!memcmp(buf, onlyFlagsPEImage, sizeof(onlyFlagsPEImage)),
313          "Unexpected value\n");
314         LocalFree(buf);
315     }
316     /* With just an empty file: */
317     imageData.Flags.cbData = 0;
318     link.dwLinkChoice = SPC_FILE_LINK_CHOICE;
319     imageData.pFile = &link;
320     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
321      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
322     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
323     if (ret)
324     {
325         ok(size == sizeof(onlyEmptyFilePEImage), "Unexpected size %d\n", size);
326         ok(!memcmp(buf, onlyEmptyFilePEImage, sizeof(onlyEmptyFilePEImage)),
327          "Unexpected value\n");
328         LocalFree(buf);
329     }
330     /* With flags and an empty file: */
331     imageData.Flags.pbData = flags;
332     imageData.Flags.cbData = sizeof(flags);
333     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
334      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
335     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
336     if (ret)
337     {
338         ok(size == sizeof(flagsAndEmptyFilePEImage), "Unexpected size %d\n",
339          size);
340         ok(!memcmp(buf, flagsAndEmptyFilePEImage,
341          sizeof(flagsAndEmptyFilePEImage)), "Unexpected value\n");
342         LocalFree(buf);
343     }
344     /* Finally, a non-empty file: */
345     U(link).pwszFile = (LPWSTR)nihongoURL;
346     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
347      &imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
348     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
349     if (ret)
350     {
351         ok(size == sizeof(flagsAndFilePEImage), "Unexpected size %d\n", size);
352         ok(!memcmp(buf, flagsAndFilePEImage, sizeof(flagsAndFilePEImage)),
353          "Unexpected value\n");
354         LocalFree(buf);
355     }
356 }
357
358 static void test_decodeSPCPEImage(void)
359 {
360     static const WCHAR emptyString[] = { 0 };
361     BOOL ret;
362     LPBYTE buf = NULL;
363     DWORD size = 0;
364     SPC_PE_IMAGE_DATA *imageData;
365
366     if (!pCryptDecodeObjectEx)
367     {
368         skip("CryptDecodeObjectEx() is not available. Skipping the decodeSPCPEImage tests\n");
369         return;
370     }
371
372     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
373      emptySequence, sizeof(emptySequence),
374      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
375     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
376     if (ret)
377     {
378         imageData = (SPC_PE_IMAGE_DATA *)buf;
379         ok(imageData->Flags.cbData == 0, "Expected empty flags, got %d\n",
380          imageData->Flags.cbData);
381         ok(imageData->pFile == NULL, "Expected no file\n");
382         LocalFree(buf);
383     }
384     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
385      onlyFlagsPEImage, sizeof(onlyFlagsPEImage),
386      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
387     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
388     if (ret)
389     {
390         imageData = (SPC_PE_IMAGE_DATA *)buf;
391         ok(imageData->Flags.cbData == sizeof(flags),
392          "Unexpected flags size %d\n", imageData->Flags.cbData);
393         if (imageData->Flags.cbData)
394             ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
395              "Unexpected flags\n");
396         ok(imageData->pFile == NULL, "Expected no file\n");
397         LocalFree(buf);
398     }
399     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
400      onlyEmptyFilePEImage, sizeof(onlyEmptyFilePEImage),
401      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
402     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
403     if (ret)
404     {
405         imageData = (SPC_PE_IMAGE_DATA *)buf;
406         ok(imageData->Flags.cbData == 0, "Expected empty flags, got %d\n",
407          imageData->Flags.cbData);
408         ok(imageData->pFile != NULL, "Expected a file\n");
409         if (imageData->pFile)
410         {
411             ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
412              "Expected SPC_FILE_LINK_CHOICE, got %d\n",
413              imageData->pFile->dwLinkChoice);
414             ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString),
415              "Unexpected file\n");
416         }
417         LocalFree(buf);
418     }
419     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
420      flagsAndEmptyFilePEImage, sizeof(flagsAndEmptyFilePEImage),
421      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
422     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
423     if (ret)
424     {
425         imageData = (SPC_PE_IMAGE_DATA *)buf;
426         ok(imageData->Flags.cbData == sizeof(flags),
427          "Unexpected flags size %d\n", imageData->Flags.cbData);
428         if (imageData->Flags.cbData)
429             ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
430              "Unexpected flags\n");
431         ok(imageData->pFile != NULL, "Expected a file\n");
432         if (imageData->pFile)
433         {
434             ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
435              "Expected SPC_FILE_LINK_CHOICE, got %d\n",
436              imageData->pFile->dwLinkChoice);
437             ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString),
438              "Unexpected file\n");
439         }
440         LocalFree(buf);
441     }
442     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
443      flagsAndFilePEImage, sizeof(flagsAndFilePEImage),
444      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
445     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
446     if (ret)
447     {
448         imageData = (SPC_PE_IMAGE_DATA *)buf;
449         ok(imageData->Flags.cbData == sizeof(flags),
450          "Unexpected flags size %d\n", imageData->Flags.cbData);
451         if (imageData->Flags.cbData)
452             ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
453              "Unexpected flags\n");
454         ok(imageData->pFile != NULL, "Expected a file\n");
455         if (imageData->pFile)
456         {
457             ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
458              "Expected SPC_FILE_LINK_CHOICE, got %d\n",
459              imageData->pFile->dwLinkChoice);
460             ok(!lstrcmpW(U(*imageData->pFile).pwszFile, nihongoURL),
461              "Unexpected file\n");
462         }
463         LocalFree(buf);
464     }
465 }
466
467 static WCHAR foo[] = { 'f','o','o',0 };
468 static WCHAR guidStr[] = { '{','8','b','c','9','6','b','0','0','-',
469  '8','d','a','1','-','1','1','c','f','-','8','7','3','6','-','0','0',
470  'a','a','0','0','a','4','8','5','e','b','}',0 };
471
472 static const BYTE emptyCatMemberInfo[] = { 0x30,0x05,0x1e,0x00,0x02,0x01,0x00 };
473 static const BYTE catMemberInfoWithSillyGuid[] = {
474 0x30,0x0b,0x1e,0x06,0x00,0x66,0x00,0x6f,0x00,0x6f,0x02,0x01,0x00 };
475 static const BYTE catMemberInfoWithGuid[] = {
476 0x30,0x51,0x1e,0x4c,0x00,0x7b,0x00,0x38,0x00,0x62,0x00,0x63,0x00,0x39,0x00,0x36,
477 0x00,0x62,0x00,0x30,0x00,0x30,0x00,0x2d,0x00,0x38,0x00,0x64,0x00,0x61,0x00,0x31,
478 0x00,0x2d,0x00,0x31,0x00,0x31,0x00,0x63,0x00,0x66,0x00,0x2d,0x00,0x38,0x00,0x37,
479 0x00,0x33,0x00,0x36,0x00,0x2d,0x00,0x30,0x00,0x30,0x00,0x61,0x00,0x61,0x00,0x30,
480 0x00,0x30,0x00,0x61,0x00,0x34,0x00,0x38,0x00,0x35,0x00,0x65,0x00,0x62,0x00,0x7d,
481 0x02,0x01,0x00 };
482
483 static void test_encodeCatMemberInfo(void)
484 {
485     CAT_MEMBERINFO info;
486     BOOL ret;
487     DWORD size = 0;
488     LPBYTE buf;
489
490     memset(&info, 0, sizeof(info));
491
492     if (!pCryptEncodeObjectEx)
493     {
494         skip("CryptEncodeObjectEx() is not available. Skipping the encodeCatMemberInfo tests\n");
495         return;
496     }
497
498     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
499      &info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
500     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
501     if (ret)
502     {
503         ok(size == sizeof(emptyCatMemberInfo), "Unexpected size %d\n", size);
504         ok(!memcmp(buf, emptyCatMemberInfo, sizeof(emptyCatMemberInfo)),
505          "Unexpected value\n");
506         LocalFree(buf);
507     }
508     info.pwszSubjGuid = foo;
509     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
510      (LPBYTE)&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
511     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
512     if (ret)
513     {
514         ok(size == sizeof(catMemberInfoWithSillyGuid), "Unexpected size %d\n",
515          size);
516         ok(!memcmp(buf, catMemberInfoWithSillyGuid,
517          sizeof(catMemberInfoWithSillyGuid)), "Unexpected value\n");
518         LocalFree(buf);
519     }
520     info.pwszSubjGuid = guidStr;
521     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
522      (LPBYTE)&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
523     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
524     if (ret)
525     {
526         ok(size == sizeof(catMemberInfoWithGuid), "Unexpected size %d\n",
527          size);
528         ok(!memcmp(buf, catMemberInfoWithGuid, sizeof(catMemberInfoWithGuid)),
529          "Unexpected value\n");
530         LocalFree(buf);
531     }
532 }
533
534 static void test_decodeCatMemberInfo(void)
535 {
536    BOOL ret;
537    LPBYTE buf;
538    DWORD size;
539    CAT_MEMBERINFO *info;
540
541     if (!pCryptDecodeObjectEx)
542     {
543         skip("CryptDecodeObjectEx() is not available. Skipping the decodeCatMemberInfo tests\n");
544         return;
545     }
546
547     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
548      emptyCatMemberInfo, sizeof(emptyCatMemberInfo),
549      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
550     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
551     if (ret)
552     {
553         info = (CAT_MEMBERINFO *)buf;
554         ok(!info->pwszSubjGuid || !info->pwszSubjGuid[0],
555          "expected empty pwszSubjGuid\n");
556         ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
557          info->dwCertVersion);
558         LocalFree(buf);
559     }
560     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
561      catMemberInfoWithSillyGuid, sizeof(catMemberInfoWithSillyGuid),
562      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
563     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
564     if (ret)
565     {
566         info = (CAT_MEMBERINFO *)buf;
567         ok(info->pwszSubjGuid && !lstrcmpW(info->pwszSubjGuid, foo),
568          "unexpected pwszSubjGuid\n");
569         ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
570          info->dwCertVersion);
571         LocalFree(buf);
572     }
573     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
574      catMemberInfoWithGuid, sizeof(catMemberInfoWithGuid),
575      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
576     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
577     if (ret)
578     {
579         info = (CAT_MEMBERINFO *)buf;
580         ok(info->pwszSubjGuid && !lstrcmpW(info->pwszSubjGuid, guidStr),
581          "unexpected pwszSubjGuid\n");
582         ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
583          info->dwCertVersion);
584         LocalFree(buf);
585     }
586 }
587
588 static const BYTE emptyCatNameValue[] = {
589 0x30,0x07,0x1e,0x00,0x02,0x01,0x00,0x04,0x00 };
590 static const BYTE catNameValueWithTag[] = {
591 0x30,0x0d,0x1e,0x06,0x00,0x66,0x00,0x6f,0x00,0x6f,0x02,0x01,0x00,0x04,0x00 };
592 static const BYTE catNameValueWithFlags[] = {
593 0x30,0x0a,0x1e,0x00,0x02,0x04,0xf0,0x0d,0xd0,0x0d,0x04,0x00 };
594 static const BYTE catNameValueWithValue[] = {
595 0x30,0x0b,0x1e,0x00,0x02,0x01,0x00,0x04,0x04,0x01,0x02,0x03,0x04 };
596
597 static BYTE aVal[] = { 1,2,3,4 };
598
599 static void test_encodeCatNameValue(void)
600 {
601     static WCHAR foo[] = { 'f','o','o',0 };
602     BOOL ret;
603     LPBYTE buf;
604     DWORD size;
605     CAT_NAMEVALUE value;
606
607     memset(&value, 0, sizeof(value));
608     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
609      (LPBYTE)&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
610     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
611     if (ret)
612     {
613         ok(size == sizeof(emptyCatNameValue), "Unexpected size %d\n", size);
614         ok(!memcmp(buf, emptyCatNameValue, sizeof(emptyCatNameValue)),
615          "Unexpected value\n");
616         LocalFree(buf);
617     }
618     value.pwszTag = foo;
619     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
620      (LPBYTE)&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
621     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
622     if (ret)
623     {
624         ok(size == sizeof(catNameValueWithTag), "Unexpected size %d\n", size);
625         ok(!memcmp(buf, catNameValueWithTag, sizeof(catNameValueWithTag)),
626          "Unexpected value\n");
627         LocalFree(buf);
628     }
629     value.pwszTag = NULL;
630     value.fdwFlags = 0xf00dd00d;
631     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
632      (LPBYTE)&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
633     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
634     if (ret)
635     {
636         ok(size == sizeof(catNameValueWithFlags), "Unexpected size %d\n", size);
637         ok(!memcmp(buf, catNameValueWithFlags, sizeof(catNameValueWithFlags)),
638          "Unexpected value\n");
639         LocalFree(buf);
640     }
641     value.fdwFlags = 0;
642     value.Value.cbData = sizeof(aVal);
643     value.Value.pbData = aVal;
644     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
645      (LPBYTE)&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
646     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
647     if (ret)
648     {
649         ok(size == sizeof(catNameValueWithValue), "Unexpected size %d\n", size);
650         ok(!memcmp(buf, catNameValueWithValue, sizeof(catNameValueWithValue)),
651          "Unexpected value\n");
652         LocalFree(buf);
653     }
654 }
655
656 START_TEST(asn)
657 {
658     HMODULE hCrypt32 = LoadLibraryA("crypt32.dll");
659     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
660     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
661
662     test_encodeSPCLink();
663     test_decodeSPCLink();
664     test_encodeSPCPEImage();
665     test_decodeSPCPEImage();
666     test_encodeCatMemberInfo();
667     test_decodeCatMemberInfo();
668     test_encodeCatNameValue();
669
670     FreeLibrary(hCrypt32);
671 }