2007-08-10 20:15:39 +02:00
|
|
|
/* Unit test suite for wintrust asn functions
|
|
|
|
*
|
|
|
|
* Copyright 2007 Juan Lang
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winerror.h"
|
|
|
|
#include "wincrypt.h"
|
|
|
|
#include "wintrust.h"
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
|
|
|
|
2008-03-01 21:13:39 +01:00
|
|
|
static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
|
|
|
|
static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
|
|
|
|
|
2008-11-03 23:54:46 +01:00
|
|
|
static const BYTE falseCriteria[] = { 0x30,0x06,0x01,0x01,0x00,0x01,0x01,0x00 };
|
|
|
|
static const BYTE trueCriteria[] = { 0x30,0x06,0x01,0x01,0xff,0x01,0x01,0xff };
|
|
|
|
|
|
|
|
static void test_encodeSPCFinancialCriteria(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size = 0;
|
|
|
|
LPBYTE buf;
|
|
|
|
SPC_FINANCIAL_CRITERIA criteria = { FALSE, FALSE };
|
|
|
|
|
|
|
|
if (!pCryptEncodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptEncodeObjectEx() is not available. Skipping the encodeFinancialCriteria tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_FINANCIAL_CRITERIA_STRUCT,
|
|
|
|
&criteria, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(falseCriteria), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, falseCriteria, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
criteria.fFinancialInfoAvailable = criteria.fMeetsCriteria = TRUE;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_FINANCIAL_CRITERIA_STRUCT,
|
|
|
|
&criteria, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(trueCriteria), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, trueCriteria, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
|
2008-11-04 00:04:57 +01:00
|
|
|
static void test_decodeSPCFinancialCriteria(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
SPC_FINANCIAL_CRITERIA criteria;
|
|
|
|
DWORD size = sizeof(criteria);
|
|
|
|
|
|
|
|
if (!pCryptDecodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptDecodeObjectEx() is not available. Skipping the decodeSPCFinancialCriteria tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_FINANCIAL_CRITERIA_STRUCT,
|
|
|
|
falseCriteria, sizeof(falseCriteria), 0, NULL, &criteria, &size);
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(!criteria.fFinancialInfoAvailable, "expected FALSE\n");
|
|
|
|
ok(!criteria.fMeetsCriteria, "expected FALSE\n");
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_FINANCIAL_CRITERIA_STRUCT,
|
|
|
|
trueCriteria, sizeof(trueCriteria), 0, NULL, &criteria, &size);
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(criteria.fFinancialInfoAvailable, "expected TRUE\n");
|
|
|
|
ok(criteria.fMeetsCriteria, "expected TRUE\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-10 20:15:39 +02:00
|
|
|
static WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.',
|
|
|
|
'o','r','g',0 };
|
|
|
|
static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
|
|
|
|
0x575b, 0 };
|
|
|
|
static const BYTE emptyURLSPCLink[] = { 0x80,0x00 };
|
|
|
|
static const BYTE urlSPCLink[] = {
|
|
|
|
0x80,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,
|
|
|
|
0x2e,0x6f,0x72,0x67};
|
|
|
|
static const BYTE fileSPCLink[] = {
|
|
|
|
0xa2,0x14,0x80,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
|
|
|
|
0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
|
|
|
|
static const BYTE emptyMonikerSPCLink[] = {
|
|
|
|
0xa1,0x14,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x04,0x00 };
|
|
|
|
static BYTE data[] = { 0xba, 0xad, 0xf0, 0x0d };
|
|
|
|
static const BYTE monikerSPCLink[] = {
|
|
|
|
0xa1,0x18,0x04,0x10,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,
|
|
|
|
0xea,0xea,0xea,0xea,0xea,0x04,0x04,0xba,0xad,0xf0,0x0d };
|
|
|
|
|
|
|
|
static void test_encodeSPCLink(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size = 0;
|
|
|
|
LPBYTE buf;
|
|
|
|
SPC_LINK link = { 0 };
|
|
|
|
|
2008-03-01 21:13:39 +01:00
|
|
|
if (!pCryptEncodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptEncodeObjectEx() is not available. Skipping the encodeSPCLink tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-10 20:15:39 +02:00
|
|
|
SetLastError(0xdeadbeef);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
|
|
link.dwLinkChoice = SPC_URL_LINK_CHOICE;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptyURLSPCLink), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptyURLSPCLink, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* With an invalid char: */
|
2007-09-11 16:37:44 +02:00
|
|
|
U(link).pwszUrl = (LPWSTR)nihongoURL;
|
2007-08-10 20:15:39 +02:00
|
|
|
size = 1;
|
|
|
|
SetLastError(0xdeadbeef);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-09 00:06:28 +02:00
|
|
|
ok(!ret &&
|
|
|
|
(GetLastError() == CRYPT_E_INVALID_IA5_STRING ||
|
|
|
|
GetLastError() == OSS_BAD_PTR /* Win9x */),
|
2007-08-10 20:15:39 +02:00
|
|
|
"Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
|
|
|
|
/* Unlike the crypt32 string encoding routines, size is not set to the
|
|
|
|
* index of the first invalid character.
|
|
|
|
*/
|
|
|
|
ok(size == 0, "Expected size 0, got %d\n", size);
|
2007-09-11 16:37:44 +02:00
|
|
|
U(link).pwszUrl = url;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(urlSPCLink), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, urlSPCLink, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
link.dwLinkChoice = SPC_FILE_LINK_CHOICE;
|
2007-09-11 16:37:44 +02:00
|
|
|
U(link).pwszFile = (LPWSTR)nihongoURL;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(fileSPCLink), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, fileSPCLink, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
link.dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
|
2007-09-11 16:37:44 +02:00
|
|
|
memset(&U(link).Moniker, 0, sizeof(U(link).Moniker));
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptyMonikerSPCLink), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptyMonikerSPCLink, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2007-09-11 16:37:44 +02:00
|
|
|
memset(&U(link).Moniker.ClassId, 0xea, sizeof(U(link).Moniker.ClassId));
|
|
|
|
U(link).Moniker.SerializedData.pbData = data;
|
|
|
|
U(link).Moniker.SerializedData.cbData = sizeof(data);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
2007-08-10 20:15:39 +02:00
|
|
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(monikerSPCLink), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, monikerSPCLink, size), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const BYTE badMonikerSPCLink[] = {
|
|
|
|
0xa1,0x19,0x04,0x11,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,
|
|
|
|
0xea,0xea,0xea,0xea,0xea,0xea,0x04,0x04,0xba,0xad,0xf0,0x0d };
|
|
|
|
|
|
|
|
static void test_decodeSPCLink(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf = NULL;
|
|
|
|
DWORD size = 0;
|
|
|
|
SPC_LINK *link;
|
|
|
|
|
2008-03-01 21:13:39 +01:00
|
|
|
if (!pCryptDecodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptDecodeObjectEx() is not available. Skipping the decodeSPCLink tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
emptyURLSPCLink, sizeof(emptyURLSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
2009-01-13 10:54:56 +01:00
|
|
|
&buf, &size);
|
2007-08-10 20:15:39 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
link = (SPC_LINK *)buf;
|
|
|
|
ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE,
|
|
|
|
"Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(lstrlenW(U(*link).pwszUrl) == 0, "Expected empty string\n");
|
2007-08-10 20:15:39 +02:00
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
urlSPCLink, sizeof(urlSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
2009-01-13 10:54:56 +01:00
|
|
|
&buf, &size);
|
2007-08-10 20:15:39 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
link = (SPC_LINK *)buf;
|
|
|
|
ok(link->dwLinkChoice == SPC_URL_LINK_CHOICE,
|
|
|
|
"Expected SPC_URL_LINK_CHOICE, got %d\n", link->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!lstrcmpW(U(*link).pwszUrl, url), "Unexpected URL\n");
|
2007-08-10 20:15:39 +02:00
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
fileSPCLink, sizeof(fileSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
2009-01-13 10:54:56 +01:00
|
|
|
&buf, &size);
|
2007-08-10 20:15:39 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
link = (SPC_LINK *)buf;
|
|
|
|
ok(link->dwLinkChoice == SPC_FILE_LINK_CHOICE,
|
|
|
|
"Expected SPC_FILE_LINK_CHOICE, got %d\n", link->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!lstrcmpW(U(*link).pwszFile, nihongoURL), "Unexpected file\n");
|
2007-08-10 20:15:39 +02:00
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
emptyMonikerSPCLink, sizeof(emptyMonikerSPCLink), CRYPT_DECODE_ALLOC_FLAG,
|
2009-01-13 10:54:56 +01:00
|
|
|
NULL, &buf, &size);
|
2007-08-10 20:15:39 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
SPC_SERIALIZED_OBJECT emptyMoniker = { { 0 } };
|
|
|
|
|
|
|
|
link = (SPC_LINK *)buf;
|
|
|
|
ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE,
|
|
|
|
"Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!memcmp(&U(*link).Moniker.ClassId, &emptyMoniker.ClassId,
|
2007-08-10 20:23:55 +02:00
|
|
|
sizeof(emptyMoniker.ClassId)), "Unexpected value\n");
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(U(*link).Moniker.SerializedData.cbData == 0,
|
2007-08-10 20:23:55 +02:00
|
|
|
"Expected no serialized data\n");
|
2007-08-10 20:15:39 +02:00
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
monikerSPCLink, sizeof(monikerSPCLink), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
2009-01-13 10:54:56 +01:00
|
|
|
&buf, &size);
|
2007-08-10 20:15:39 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
SPC_UUID id;
|
|
|
|
|
|
|
|
link = (SPC_LINK *)buf;
|
|
|
|
ok(link->dwLinkChoice == SPC_MONIKER_LINK_CHOICE,
|
|
|
|
"Expected SPC_MONIKER_LINK_CHOICE, got %d\n", link->dwLinkChoice);
|
|
|
|
memset(&id, 0xea, sizeof(id));
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!memcmp(&U(*link).Moniker.ClassId, &id, sizeof(id)),
|
2007-08-10 20:15:39 +02:00
|
|
|
"Unexpected value\n");
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(U(*link).Moniker.SerializedData.cbData == sizeof(data),
|
|
|
|
"Unexpected data size %d\n", U(*link).Moniker.SerializedData.cbData);
|
|
|
|
ok(!memcmp(U(*link).Moniker.SerializedData.pbData, data, sizeof(data)),
|
2007-08-10 20:15:39 +02:00
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
SetLastError(0xdeadbeef);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT,
|
2007-08-10 20:15:39 +02:00
|
|
|
badMonikerSPCLink, sizeof(badMonikerSPCLink), CRYPT_DECODE_ALLOC_FLAG,
|
2009-01-13 10:54:56 +01:00
|
|
|
NULL, &buf, &size);
|
2008-10-09 00:06:28 +02:00
|
|
|
ok(!ret &&
|
|
|
|
(GetLastError() == CRYPT_E_BAD_ENCODE ||
|
|
|
|
GetLastError() == OSS_DATA_ERROR /* Win9x */),
|
2007-08-10 20:15:39 +02:00
|
|
|
"Expected CRYPT_E_BAD_ENCODE, got %08x\n", GetLastError());
|
|
|
|
}
|
|
|
|
|
2007-08-10 23:35:36 +02:00
|
|
|
static const BYTE emptySequence[] = { 0x30,0x00 };
|
|
|
|
static BYTE flags[] = { 1 };
|
|
|
|
static const BYTE onlyFlagsPEImage[] = { 0x30,0x04,0x03,0x02,0x00,0x01 };
|
|
|
|
static const BYTE moreFlagsPEImage[] = {
|
|
|
|
0x30,0x06,0x03,0x04,0x04,0xff,0x80,0x10 };
|
|
|
|
static const BYTE onlyEmptyFilePEImage[] = {
|
|
|
|
0x30,0x06,0xa0,0x04,0xa2,0x02,0x80,0x00 };
|
|
|
|
static const BYTE flagsAndEmptyFilePEImage[] = {
|
|
|
|
0x30,0x0a,0x03,0x02,0x00,0x01,0xa0,0x04,0xa2,0x02,0x80,0x00 };
|
|
|
|
static const BYTE flagsAndFilePEImage[] = {
|
|
|
|
0x30,0x1c,0x03,0x02,0x00,0x01,0xa0,0x16,0xa2,0x14,0x80,0x12,0x00,0x68,0x00,
|
|
|
|
0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
|
|
|
|
|
|
|
|
static void test_encodeSPCPEImage(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size = 0;
|
|
|
|
LPBYTE buf;
|
|
|
|
SPC_PE_IMAGE_DATA imageData = { { 0 } };
|
|
|
|
SPC_LINK link = { 0 };
|
|
|
|
|
2008-03-01 21:13:39 +01:00
|
|
|
if (!pCryptEncodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptEncodeObjectEx() is not available. Skipping the encodeSPCPEImage tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* With an invalid link: */
|
|
|
|
imageData.pFile = &link;
|
|
|
|
SetLastError(0xdeadbeef);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(!ret && GetLastError () == E_INVALIDARG,
|
|
|
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
|
|
/* With just unused bits field set: */
|
|
|
|
imageData.pFile = NULL;
|
|
|
|
imageData.Flags.cUnusedBits = 1;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* With flags set: */
|
|
|
|
imageData.Flags.cUnusedBits = 0;
|
|
|
|
imageData.Flags.pbData = flags;
|
|
|
|
imageData.Flags.cbData = sizeof(flags);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-09 00:06:28 +02:00
|
|
|
if (!ret && GetLastError() == OSS_TOO_LONG)
|
|
|
|
{
|
|
|
|
skip("SPC_PE_IMAGE_DATA_STRUCT not supported\n");
|
|
|
|
return;
|
|
|
|
}
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(onlyFlagsPEImage), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, onlyFlagsPEImage, sizeof(onlyFlagsPEImage)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* With just an empty file: */
|
|
|
|
imageData.Flags.cbData = 0;
|
|
|
|
link.dwLinkChoice = SPC_FILE_LINK_CHOICE;
|
|
|
|
imageData.pFile = &link;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(onlyEmptyFilePEImage), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, onlyEmptyFilePEImage, sizeof(onlyEmptyFilePEImage)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* With flags and an empty file: */
|
|
|
|
imageData.Flags.pbData = flags;
|
|
|
|
imageData.Flags.cbData = sizeof(flags);
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(flagsAndEmptyFilePEImage), "Unexpected size %d\n",
|
|
|
|
size);
|
|
|
|
ok(!memcmp(buf, flagsAndEmptyFilePEImage,
|
|
|
|
sizeof(flagsAndEmptyFilePEImage)), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
/* Finally, a non-empty file: */
|
2007-09-11 16:37:44 +02:00
|
|
|
U(link).pwszFile = (LPWSTR)nihongoURL;
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(flagsAndFilePEImage), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, flagsAndFilePEImage, sizeof(flagsAndFilePEImage)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_decodeSPCPEImage(void)
|
|
|
|
{
|
|
|
|
static const WCHAR emptyString[] = { 0 };
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf = NULL;
|
|
|
|
DWORD size = 0;
|
|
|
|
SPC_PE_IMAGE_DATA *imageData;
|
|
|
|
|
2008-03-01 21:13:39 +01:00
|
|
|
if (!pCryptDecodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptDecodeObjectEx() is not available. Skipping the decodeSPCPEImage tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
emptySequence, sizeof(emptySequence),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
imageData = (SPC_PE_IMAGE_DATA *)buf;
|
|
|
|
ok(imageData->Flags.cbData == 0, "Expected empty flags, got %d\n",
|
|
|
|
imageData->Flags.cbData);
|
|
|
|
ok(imageData->pFile == NULL, "Expected no file\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
onlyFlagsPEImage, sizeof(onlyFlagsPEImage),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
imageData = (SPC_PE_IMAGE_DATA *)buf;
|
|
|
|
ok(imageData->Flags.cbData == sizeof(flags),
|
|
|
|
"Unexpected flags size %d\n", imageData->Flags.cbData);
|
|
|
|
if (imageData->Flags.cbData)
|
|
|
|
ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
|
|
|
|
"Unexpected flags\n");
|
|
|
|
ok(imageData->pFile == NULL, "Expected no file\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
onlyEmptyFilePEImage, sizeof(onlyEmptyFilePEImage),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
imageData = (SPC_PE_IMAGE_DATA *)buf;
|
|
|
|
ok(imageData->Flags.cbData == 0, "Expected empty flags, got %d\n",
|
|
|
|
imageData->Flags.cbData);
|
|
|
|
ok(imageData->pFile != NULL, "Expected a file\n");
|
|
|
|
if (imageData->pFile)
|
|
|
|
{
|
|
|
|
ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
|
|
|
|
"Expected SPC_FILE_LINK_CHOICE, got %d\n",
|
|
|
|
imageData->pFile->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString),
|
2007-08-10 23:35:36 +02:00
|
|
|
"Unexpected file\n");
|
|
|
|
}
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
flagsAndEmptyFilePEImage, sizeof(flagsAndEmptyFilePEImage),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
imageData = (SPC_PE_IMAGE_DATA *)buf;
|
|
|
|
ok(imageData->Flags.cbData == sizeof(flags),
|
|
|
|
"Unexpected flags size %d\n", imageData->Flags.cbData);
|
|
|
|
if (imageData->Flags.cbData)
|
|
|
|
ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
|
|
|
|
"Unexpected flags\n");
|
|
|
|
ok(imageData->pFile != NULL, "Expected a file\n");
|
|
|
|
if (imageData->pFile)
|
|
|
|
{
|
|
|
|
ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
|
|
|
|
"Expected SPC_FILE_LINK_CHOICE, got %d\n",
|
|
|
|
imageData->pFile->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!lstrcmpW(U(*imageData->pFile).pwszFile, emptyString),
|
2007-08-10 23:35:36 +02:00
|
|
|
"Unexpected file\n");
|
|
|
|
}
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
2008-03-01 21:13:39 +01:00
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
|
2007-08-10 23:35:36 +02:00
|
|
|
flagsAndFilePEImage, sizeof(flagsAndFilePEImage),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2007-08-10 23:35:36 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
imageData = (SPC_PE_IMAGE_DATA *)buf;
|
|
|
|
ok(imageData->Flags.cbData == sizeof(flags),
|
|
|
|
"Unexpected flags size %d\n", imageData->Flags.cbData);
|
|
|
|
if (imageData->Flags.cbData)
|
|
|
|
ok(!memcmp(imageData->Flags.pbData, flags, sizeof(flags)),
|
|
|
|
"Unexpected flags\n");
|
|
|
|
ok(imageData->pFile != NULL, "Expected a file\n");
|
|
|
|
if (imageData->pFile)
|
|
|
|
{
|
|
|
|
ok(imageData->pFile->dwLinkChoice == SPC_FILE_LINK_CHOICE,
|
|
|
|
"Expected SPC_FILE_LINK_CHOICE, got %d\n",
|
|
|
|
imageData->pFile->dwLinkChoice);
|
2007-09-11 16:37:44 +02:00
|
|
|
ok(!lstrcmpW(U(*imageData->pFile).pwszFile, nihongoURL),
|
2007-08-10 23:35:36 +02:00
|
|
|
"Unexpected file\n");
|
|
|
|
}
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-17 23:06:26 +02:00
|
|
|
static WCHAR foo[] = { 'f','o','o',0 };
|
|
|
|
static WCHAR guidStr[] = { '{','8','b','c','9','6','b','0','0','-',
|
|
|
|
'8','d','a','1','-','1','1','c','f','-','8','7','3','6','-','0','0',
|
|
|
|
'a','a','0','0','a','4','8','5','e','b','}',0 };
|
|
|
|
|
|
|
|
static const BYTE emptyCatMemberInfo[] = { 0x30,0x05,0x1e,0x00,0x02,0x01,0x00 };
|
|
|
|
static const BYTE catMemberInfoWithSillyGuid[] = {
|
|
|
|
0x30,0x0b,0x1e,0x06,0x00,0x66,0x00,0x6f,0x00,0x6f,0x02,0x01,0x00 };
|
|
|
|
static const BYTE catMemberInfoWithGuid[] = {
|
|
|
|
0x30,0x51,0x1e,0x4c,0x00,0x7b,0x00,0x38,0x00,0x62,0x00,0x63,0x00,0x39,0x00,0x36,
|
|
|
|
0x00,0x62,0x00,0x30,0x00,0x30,0x00,0x2d,0x00,0x38,0x00,0x64,0x00,0x61,0x00,0x31,
|
|
|
|
0x00,0x2d,0x00,0x31,0x00,0x31,0x00,0x63,0x00,0x66,0x00,0x2d,0x00,0x38,0x00,0x37,
|
|
|
|
0x00,0x33,0x00,0x36,0x00,0x2d,0x00,0x30,0x00,0x30,0x00,0x61,0x00,0x61,0x00,0x30,
|
|
|
|
0x00,0x30,0x00,0x61,0x00,0x34,0x00,0x38,0x00,0x35,0x00,0x65,0x00,0x62,0x00,0x7d,
|
|
|
|
0x02,0x01,0x00 };
|
|
|
|
|
|
|
|
static void test_encodeCatMemberInfo(void)
|
|
|
|
{
|
|
|
|
CAT_MEMBERINFO info;
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size = 0;
|
|
|
|
LPBYTE buf;
|
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
|
|
|
if (!pCryptEncodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptEncodeObjectEx() is not available. Skipping the encodeCatMemberInfo tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptyCatMemberInfo), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptyCatMemberInfo, sizeof(emptyCatMemberInfo)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
info.pwszSubjGuid = foo;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:06:26 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(catMemberInfoWithSillyGuid), "Unexpected size %d\n",
|
|
|
|
size);
|
|
|
|
ok(!memcmp(buf, catMemberInfoWithSillyGuid,
|
|
|
|
sizeof(catMemberInfoWithSillyGuid)), "Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
info.pwszSubjGuid = guidStr;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:06:26 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(catMemberInfoWithGuid), "Unexpected size %d\n",
|
|
|
|
size);
|
|
|
|
ok(!memcmp(buf, catMemberInfoWithGuid, sizeof(catMemberInfoWithGuid)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-17 23:12:55 +02:00
|
|
|
static void test_decodeCatMemberInfo(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf;
|
|
|
|
DWORD size;
|
|
|
|
CAT_MEMBERINFO *info;
|
|
|
|
|
|
|
|
if (!pCryptDecodeObjectEx)
|
|
|
|
{
|
|
|
|
skip("CryptDecodeObjectEx() is not available. Skipping the decodeCatMemberInfo tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
|
|
|
emptyCatMemberInfo, sizeof(emptyCatMemberInfo),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:12:55 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
info = (CAT_MEMBERINFO *)buf;
|
|
|
|
ok(!info->pwszSubjGuid || !info->pwszSubjGuid[0],
|
|
|
|
"expected empty pwszSubjGuid\n");
|
|
|
|
ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
|
|
|
|
info->dwCertVersion);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
|
|
|
catMemberInfoWithSillyGuid, sizeof(catMemberInfoWithSillyGuid),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:12:55 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
info = (CAT_MEMBERINFO *)buf;
|
|
|
|
ok(info->pwszSubjGuid && !lstrcmpW(info->pwszSubjGuid, foo),
|
|
|
|
"unexpected pwszSubjGuid\n");
|
|
|
|
ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
|
|
|
|
info->dwCertVersion);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_MEMBERINFO_STRUCT,
|
|
|
|
catMemberInfoWithGuid, sizeof(catMemberInfoWithGuid),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:12:55 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
info = (CAT_MEMBERINFO *)buf;
|
|
|
|
ok(info->pwszSubjGuid && !lstrcmpW(info->pwszSubjGuid, guidStr),
|
|
|
|
"unexpected pwszSubjGuid\n");
|
|
|
|
ok(info->dwCertVersion == 0, "expected dwCertVersion == 0, got %d\n",
|
|
|
|
info->dwCertVersion);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-17 23:43:05 +02:00
|
|
|
static const BYTE emptyCatNameValue[] = {
|
|
|
|
0x30,0x07,0x1e,0x00,0x02,0x01,0x00,0x04,0x00 };
|
|
|
|
static const BYTE catNameValueWithTag[] = {
|
|
|
|
0x30,0x0d,0x1e,0x06,0x00,0x66,0x00,0x6f,0x00,0x6f,0x02,0x01,0x00,0x04,0x00 };
|
|
|
|
static const BYTE catNameValueWithFlags[] = {
|
|
|
|
0x30,0x0a,0x1e,0x00,0x02,0x04,0xf0,0x0d,0xd0,0x0d,0x04,0x00 };
|
|
|
|
static const BYTE catNameValueWithValue[] = {
|
|
|
|
0x30,0x0b,0x1e,0x00,0x02,0x01,0x00,0x04,0x04,0x01,0x02,0x03,0x04 };
|
|
|
|
|
|
|
|
static BYTE aVal[] = { 1,2,3,4 };
|
|
|
|
|
|
|
|
static void test_encodeCatNameValue(void)
|
|
|
|
{
|
|
|
|
static WCHAR foo[] = { 'f','o','o',0 };
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf;
|
|
|
|
DWORD size;
|
|
|
|
CAT_NAMEVALUE value;
|
|
|
|
|
|
|
|
memset(&value, 0, sizeof(value));
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:43:05 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptyCatNameValue), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptyCatNameValue, sizeof(emptyCatNameValue)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
value.pwszTag = foo;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:43:05 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(catNameValueWithTag), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, catNameValueWithTag, sizeof(catNameValueWithTag)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
value.pwszTag = NULL;
|
|
|
|
value.fdwFlags = 0xf00dd00d;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:43:05 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(catNameValueWithFlags), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, catNameValueWithFlags, sizeof(catNameValueWithFlags)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
value.fdwFlags = 0;
|
|
|
|
value.Value.cbData = sizeof(aVal);
|
|
|
|
value.Value.pbData = aVal;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-17 23:43:05 +02:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(catNameValueWithValue), "Unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, catNameValueWithValue, sizeof(catNameValueWithValue)),
|
|
|
|
"Unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-18 00:33:46 +02:00
|
|
|
static void test_decodeCatNameValue(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf;
|
|
|
|
DWORD size;
|
|
|
|
CAT_NAMEVALUE *value;
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
|
|
|
emptyCatNameValue, sizeof(emptyCatNameValue),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-18 00:33:46 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
value = (CAT_NAMEVALUE *)buf;
|
|
|
|
ok(!value->pwszTag || !value->pwszTag[0], "expected empty pwszTag\n");
|
|
|
|
ok(value->fdwFlags == 0, "expected fdwFlags == 0, got %08x\n",
|
|
|
|
value->fdwFlags);
|
|
|
|
ok(value->Value.cbData == 0, "expected 0-length value, got %d\n",
|
|
|
|
value->Value.cbData);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
|
|
|
catNameValueWithTag, sizeof(catNameValueWithTag),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-18 00:33:46 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
value = (CAT_NAMEVALUE *)buf;
|
|
|
|
ok(value->pwszTag && !lstrcmpW(value->pwszTag, foo),
|
|
|
|
"unexpected pwszTag\n");
|
|
|
|
ok(value->fdwFlags == 0, "expected fdwFlags == 0, got %08x\n",
|
|
|
|
value->fdwFlags);
|
|
|
|
ok(value->Value.cbData == 0, "expected 0-length value, got %d\n",
|
|
|
|
value->Value.cbData);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
|
|
|
catNameValueWithFlags, sizeof(catNameValueWithFlags),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-18 00:33:46 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
value = (CAT_NAMEVALUE *)buf;
|
|
|
|
ok(!value->pwszTag || !value->pwszTag[0], "expected empty pwszTag\n");
|
|
|
|
ok(value->fdwFlags == 0xf00dd00d,
|
|
|
|
"expected fdwFlags == 0xf00dd00d, got %08x\n", value->fdwFlags);
|
|
|
|
ok(value->Value.cbData == 0, "expected 0-length value, got %d\n",
|
|
|
|
value->Value.cbData);
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, CAT_NAMEVALUE_STRUCT,
|
|
|
|
catNameValueWithValue, sizeof(catNameValueWithValue),
|
2009-01-13 10:54:56 +01:00
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-10-18 00:33:46 +02:00
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
value = (CAT_NAMEVALUE *)buf;
|
|
|
|
ok(!value->pwszTag || !value->pwszTag[0], "expected empty pwszTag\n");
|
|
|
|
ok(value->fdwFlags == 0, "expected fdwFlags == 0, got %08x\n",
|
|
|
|
value->fdwFlags);
|
|
|
|
ok(value->Value.cbData == sizeof(aVal), "unexpected size %d\n",
|
|
|
|
value->Value.cbData);
|
|
|
|
ok(!memcmp(value->Value.pbData, aVal, value->Value.cbData),
|
|
|
|
"unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-10 00:59:56 +01:00
|
|
|
static const WCHAR progName[] = { 'A',' ','p','r','o','g','r','a','m',0 };
|
|
|
|
static const BYTE spOpusInfoWithProgramName[] = {
|
|
|
|
0x30,0x16,0xa0,0x14,0x80,0x12,0x00,0x41,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,
|
|
|
|
0x00,0x67,0x00,0x72,0x00,0x61,0x00,0x6d };
|
|
|
|
static WCHAR winehq[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q',
|
|
|
|
'.','o','r','g','/',0 };
|
|
|
|
static const BYTE spOpusInfoWithMoreInfo[] = {
|
|
|
|
0x30,0x16,0xa1,0x14,0x80,0x12,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,
|
|
|
|
0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x2f };
|
|
|
|
static const BYTE spOpusInfoWithPublisherInfo[] = {
|
|
|
|
0x30,0x16,0xa2,0x14,0x80,0x12,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,
|
|
|
|
0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x2f };
|
|
|
|
|
|
|
|
static void test_encodeSpOpusInfo(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
LPBYTE buf;
|
|
|
|
DWORD size;
|
|
|
|
SPC_SP_OPUS_INFO info;
|
|
|
|
SPC_LINK moreInfo;
|
|
|
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-12-10 00:59:56 +01:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
info.pwszProgramName = progName;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-12-10 00:59:56 +01:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(spOpusInfoWithProgramName), "unexpected size %d\n",
|
|
|
|
size);
|
|
|
|
ok(!memcmp(buf, spOpusInfoWithProgramName, size),
|
|
|
|
"unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
info.pwszProgramName = NULL;
|
|
|
|
memset(&moreInfo, 0, sizeof(moreInfo));
|
|
|
|
info.pMoreInfo = &moreInfo;
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-12-10 00:59:56 +01:00
|
|
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
|
|
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
|
|
|
moreInfo.dwLinkChoice = SPC_URL_LINK_CHOICE;
|
|
|
|
moreInfo.pwszUrl = winehq;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-12-10 00:59:56 +01:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(spOpusInfoWithMoreInfo),
|
|
|
|
"unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, spOpusInfoWithMoreInfo, size),
|
|
|
|
"unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
info.pMoreInfo = NULL;
|
|
|
|
info.pPublisherInfo = &moreInfo;
|
|
|
|
ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
2009-01-13 10:54:56 +01:00
|
|
|
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
2008-12-10 00:59:56 +01:00
|
|
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(size == sizeof(spOpusInfoWithPublisherInfo),
|
|
|
|
"unexpected size %d\n", size);
|
|
|
|
ok(!memcmp(buf, spOpusInfoWithPublisherInfo, size),
|
|
|
|
"unexpected value\n");
|
|
|
|
LocalFree(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-10 01:42:32 +01:00
|
|
|
static void test_decodeSpOpusInfo(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size;
|
|
|
|
SPC_SP_OPUS_INFO *info;
|
|
|
|
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
|
|
|
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
|
|
|
&info, &size);
|
|
|
|
todo_wine
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(!info->pwszProgramName, "expected NULL\n");
|
|
|
|
ok(!info->pMoreInfo, "expected NULL\n");
|
|
|
|
ok(!info->pPublisherInfo, "expected NULL\n");
|
|
|
|
LocalFree(info);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
|
|
|
spOpusInfoWithProgramName, sizeof(spOpusInfoWithProgramName),
|
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
|
|
|
todo_wine
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(info->pwszProgramName && !lstrcmpW(info->pwszProgramName,
|
|
|
|
progName), "unexpected program name\n");
|
|
|
|
ok(!info->pMoreInfo, "expected NULL\n");
|
|
|
|
ok(!info->pPublisherInfo, "expected NULL\n");
|
|
|
|
LocalFree(info);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
|
|
|
spOpusInfoWithMoreInfo, sizeof(spOpusInfoWithMoreInfo),
|
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
|
|
|
todo_wine
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(!info->pwszProgramName, "expected NULL\n");
|
|
|
|
ok(info->pMoreInfo != NULL, "expected a value for pMoreInfo\n");
|
|
|
|
if (info->pMoreInfo)
|
|
|
|
{
|
|
|
|
ok(info->pMoreInfo->dwLinkChoice == SPC_URL_LINK_CHOICE,
|
|
|
|
"unexpected link choice %d\n", info->pMoreInfo->dwLinkChoice);
|
|
|
|
ok(!lstrcmpW(info->pMoreInfo->pwszUrl, winehq),
|
|
|
|
"unexpected link value\n");
|
|
|
|
}
|
|
|
|
ok(!info->pPublisherInfo, "expected NULL\n");
|
|
|
|
LocalFree(info);
|
|
|
|
}
|
|
|
|
ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, SPC_SP_OPUS_INFO_STRUCT,
|
|
|
|
spOpusInfoWithPublisherInfo, sizeof(spOpusInfoWithPublisherInfo),
|
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
|
|
|
todo_wine
|
|
|
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ok(!info->pwszProgramName, "expected NULL\n");
|
|
|
|
ok(!info->pMoreInfo, "expected NULL\n");
|
|
|
|
ok(info->pPublisherInfo != NULL,
|
|
|
|
"expected a value for pPublisherInfo\n");
|
|
|
|
if (info->pPublisherInfo)
|
|
|
|
{
|
|
|
|
ok(info->pPublisherInfo->dwLinkChoice == SPC_URL_LINK_CHOICE,
|
|
|
|
"unexpected link choice %d\n",
|
|
|
|
info->pPublisherInfo->dwLinkChoice);
|
|
|
|
ok(!lstrcmpW(info->pPublisherInfo->pwszUrl, winehq),
|
|
|
|
"unexpected link value\n");
|
|
|
|
}
|
|
|
|
LocalFree(info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-10 20:15:39 +02:00
|
|
|
START_TEST(asn)
|
|
|
|
{
|
2008-03-01 21:13:39 +01:00
|
|
|
HMODULE hCrypt32 = LoadLibraryA("crypt32.dll");
|
|
|
|
pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
|
|
|
|
pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
|
|
|
|
|
2008-11-03 23:54:46 +01:00
|
|
|
test_encodeSPCFinancialCriteria();
|
2008-11-04 00:04:57 +01:00
|
|
|
test_decodeSPCFinancialCriteria();
|
2007-08-10 20:15:39 +02:00
|
|
|
test_encodeSPCLink();
|
|
|
|
test_decodeSPCLink();
|
2007-08-10 23:35:36 +02:00
|
|
|
test_encodeSPCPEImage();
|
|
|
|
test_decodeSPCPEImage();
|
2008-10-17 23:06:26 +02:00
|
|
|
test_encodeCatMemberInfo();
|
2008-10-17 23:12:55 +02:00
|
|
|
test_decodeCatMemberInfo();
|
2008-10-17 23:43:05 +02:00
|
|
|
test_encodeCatNameValue();
|
2008-10-18 00:33:46 +02:00
|
|
|
test_decodeCatNameValue();
|
2008-12-10 00:59:56 +01:00
|
|
|
test_encodeSpOpusInfo();
|
2008-12-10 01:42:32 +01:00
|
|
|
test_decodeSpOpusInfo();
|
2008-09-05 16:14:56 +02:00
|
|
|
|
|
|
|
FreeLibrary(hCrypt32);
|
2007-08-10 20:15:39 +02:00
|
|
|
}
|