1148 lines
27 KiB
C++
1148 lines
27 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
QueryDB
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module provides simple access to the Calais Registry Database.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 11/25/1996
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Win32, C++ w/ Exceptions
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
?Notes?
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#endif
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <tchar.h>
|
||
|
#include <winscard.h>
|
||
|
#include <CalaisLb.h>
|
||
|
|
||
|
// Keep this in sync with ChangeDB.cpp
|
||
|
typedef struct {
|
||
|
DWORD dwScope;
|
||
|
HKEY hKey;
|
||
|
} RegMap;
|
||
|
|
||
|
#if SCARD_SCOPE_SYSTEM < SCARD_SCOPE_USER
|
||
|
#error Invalid ordering to SCARD_SCOPE definitions
|
||
|
#endif
|
||
|
|
||
|
static const RegMap l_rgRegMap[]
|
||
|
= {
|
||
|
{ SCARD_SCOPE_USER, HKEY_CURRENT_USER },
|
||
|
// { SCARD_SCOPE_TERMINAL, Not implemented yet }, // ?Hydra?
|
||
|
{ SCARD_SCOPE_SYSTEM, HKEY_LOCAL_MACHINE }
|
||
|
};
|
||
|
static const DWORD l_dwRegMapMax = sizeof(l_rgRegMap) / sizeof(RegMap);
|
||
|
|
||
|
static const LPCTSTR l_szrgProvMap[]
|
||
|
= {
|
||
|
NULL, // Zero value
|
||
|
SCARD_REG_PPV,
|
||
|
SCARD_REG_CSP
|
||
|
};
|
||
|
static const DWORD l_dwProvMapMax = sizeof(l_szrgProvMap) / sizeof(LPCTSTR);
|
||
|
|
||
|
static BOOL
|
||
|
ListKnownKeys(
|
||
|
IN DWORD dwScope,
|
||
|
OUT CBuffer &bfKeys,
|
||
|
IN LPCTSTR szUserList,
|
||
|
IN LPCTSTR szSystemList = NULL);
|
||
|
static void
|
||
|
FindKey(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szKey,
|
||
|
OUT CRegistry ®Key,
|
||
|
IN LPCTSTR szUserList,
|
||
|
IN LPCTSTR szSystemList = NULL);
|
||
|
|
||
|
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Calais Database Query Services
|
||
|
//
|
||
|
// These services all are oriented towards reading the Calais database.
|
||
|
//
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ListReaderGroups:
|
||
|
|
||
|
This service provides the list of named card reader groups that have
|
||
|
previously been defined to the system.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
For V1, this value is ignored, and assumed to be SCARD_SCOPE_SYSTEM.
|
||
|
|
||
|
bfGroups receives a multi-string listing the reader groups defined within
|
||
|
the supplied scope.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 10/23/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
ListReaderGroups(
|
||
|
IN DWORD dwScope,
|
||
|
OUT CBuffer &bfGroups)
|
||
|
{
|
||
|
CBuffer bfReaders;
|
||
|
CRegistry regReader;
|
||
|
LPCTSTR szReader, mszGroups;
|
||
|
CBuffer bfTmp;
|
||
|
DWORD cchGroups;
|
||
|
|
||
|
ListKnownKeys(dwScope, bfReaders, SCARD_REG_READERS);
|
||
|
for (szReader = FirstString(bfReaders);
|
||
|
NULL != szReader;
|
||
|
szReader = NextString(szReader))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
FindKey(dwScope, szReader, regReader, SCARD_REG_READERS);
|
||
|
mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
|
||
|
cchGroups = regReader.GetValueLength() / sizeof(TCHAR);
|
||
|
while (0 == mszGroups[cchGroups - 1])
|
||
|
cchGroups -= 1;
|
||
|
bfTmp.Append(
|
||
|
(LPBYTE)mszGroups,
|
||
|
cchGroups * sizeof(TCHAR));
|
||
|
bfTmp.Append((LPBYTE)TEXT("\000"), sizeof(TCHAR));
|
||
|
}
|
||
|
catch (...) {}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Sort the list, and remove duplicates.
|
||
|
//
|
||
|
|
||
|
bfTmp.Append((LPCBYTE)TEXT("\000"), 2 * sizeof(TCHAR));
|
||
|
MStringSort(bfTmp, bfGroups);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ListReaders:
|
||
|
|
||
|
This service provides the list of readers within a set of named reader
|
||
|
groups, eliminating duplicates. The caller supplies a multistring listing
|
||
|
the name of a set of pre-defined group of readers, and receives the list of
|
||
|
smartcard readers within the named groups. Unrecognized group names are
|
||
|
ignored.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
mszGroups supplies the names of the reader groups defined to the system, as
|
||
|
a multi-string. If this parameter is null, all readers are returned.
|
||
|
|
||
|
bfReaders receives a multi-string listing the card readers within the
|
||
|
supplied reader groups.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 10/23/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
ListReaders(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR mszGroups,
|
||
|
OUT CBuffer &bfReaders)
|
||
|
{
|
||
|
CRegistry regReader;
|
||
|
LPCTSTR szReader, mszRdrGroups;
|
||
|
CBuffer bfRdrs, bfCmn;
|
||
|
DWORD dwCmnCount;
|
||
|
|
||
|
dwCmnCount = MStringCommon(mszGroups, SCARD_ALL_READERS, bfCmn);
|
||
|
if (0 == dwCmnCount)
|
||
|
{
|
||
|
if ((NULL == mszGroups) || (0 == *mszGroups))
|
||
|
mszGroups = SCARD_DEFAULT_READERS;
|
||
|
bfReaders.Reset();
|
||
|
ListKnownKeys(dwScope, bfRdrs, SCARD_REG_READERS);
|
||
|
for (szReader = FirstString(bfRdrs);
|
||
|
NULL != szReader;
|
||
|
szReader = NextString(szReader))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
FindKey(dwScope, szReader, regReader, SCARD_REG_READERS);
|
||
|
mszRdrGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
|
||
|
dwCmnCount = MStringCommon(mszGroups, mszRdrGroups, bfCmn);
|
||
|
if (0 < dwCmnCount)
|
||
|
bfReaders.Append(
|
||
|
(LPCBYTE)szReader,
|
||
|
(lstrlen(szReader) + 1) * sizeof(TCHAR));
|
||
|
}
|
||
|
catch (...) {}
|
||
|
}
|
||
|
bfReaders.Append((LPBYTE)TEXT("\000"), 2 * sizeof(TCHAR));
|
||
|
bfReaders.Resize(MStrLen((LPCTSTR)bfReaders.Access()), TRUE);
|
||
|
}
|
||
|
else
|
||
|
ListKnownKeys(dwScope, bfReaders, SCARD_REG_READERS);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ListReaderNames:
|
||
|
|
||
|
This routine returns the list of names corresponding to a given reader
|
||
|
device.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
For V1, this value is ignored, and assumed to be SCARD_SCOPE_SYSTEM.
|
||
|
|
||
|
szDevice supplies the reader device name.
|
||
|
|
||
|
bfNames receives a multistring of the names given to that device, if any.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors as DWORD status codes
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 2/13/1997
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
ListReaderNames(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szDevice,
|
||
|
OUT CBuffer &bfNames)
|
||
|
{
|
||
|
CRegistry regReader;
|
||
|
LPCTSTR szReader, szDev;
|
||
|
CBuffer bfRdrs;
|
||
|
|
||
|
bfNames.Reset();
|
||
|
ListKnownKeys(dwScope, bfRdrs, SCARD_REG_READERS);
|
||
|
for (szReader = FirstString(bfRdrs);
|
||
|
NULL != szReader;
|
||
|
szReader = NextString(szReader))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
FindKey(dwScope, szReader, regReader, SCARD_REG_READERS);
|
||
|
szDev = regReader.GetStringValue(SCARD_REG_DEVICE);
|
||
|
if (0 == lstrcmpi(szDev, szDevice))
|
||
|
MStrAdd(bfNames, szReader);
|
||
|
}
|
||
|
catch (...) {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ListCards:
|
||
|
|
||
|
This service provides a list of named cards previously introduced to the
|
||
|
system by this user which match an optionally supplied ATR string and/or
|
||
|
supply a set of given interfaces.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
pbAtr supplies the address of an ATR string to compare to known cards, or
|
||
|
NULL if all card names are to be returned.
|
||
|
|
||
|
rgguidInterfaces supplies an array of GUIDs, or the value NULL. When an
|
||
|
array is supplied, a card name will be returned only if this set of
|
||
|
GUIDs is a (possibly improper) subset of the set of GUIDs supported by
|
||
|
the card.
|
||
|
|
||
|
cguidInterfaceCount supplies the number of entries in the rgguidInterfaces
|
||
|
array. If rgguidInterfaces is NULL, then this value is ignored.
|
||
|
|
||
|
bfCards receives a multi-string listing the smartcards introduced to the
|
||
|
system by this user which match the supplied ATR string.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 10/23/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
ListCards(
|
||
|
DWORD dwScope,
|
||
|
IN LPCBYTE pbAtr,
|
||
|
IN LPCGUID rgquidInterfaces,
|
||
|
IN DWORD cguidInterfaceCount,
|
||
|
OUT CBuffer &bfCards)
|
||
|
{
|
||
|
CRegistry regCard;
|
||
|
LPCTSTR szCard;
|
||
|
CBuffer bfCardAtr;
|
||
|
CBuffer bfCardList;
|
||
|
|
||
|
bfCards.Reset();
|
||
|
ListKnownKeys(dwScope, bfCardList, SCARD_REG_CARDS, SCARD_REG_TEMPLATES);
|
||
|
for (szCard = FirstString(bfCardList);
|
||
|
NULL != szCard;
|
||
|
szCard = NextString(szCard))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
FindKey(
|
||
|
dwScope,
|
||
|
szCard,
|
||
|
regCard,
|
||
|
SCARD_REG_CARDS,
|
||
|
SCARD_REG_TEMPLATES);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Does this card match the supplied ATR?
|
||
|
//
|
||
|
|
||
|
if ((NULL != pbAtr) && (0 != *pbAtr))
|
||
|
{
|
||
|
LPCBYTE pbCardAtr, pbCardMask;
|
||
|
DWORD cbCardAtr, cbCardMask;
|
||
|
|
||
|
pbCardAtr = regCard.GetBinaryValue(
|
||
|
SCARD_REG_ATR,
|
||
|
&cbCardAtr);
|
||
|
bfCardAtr.Set(pbCardAtr, cbCardAtr);
|
||
|
try
|
||
|
{
|
||
|
pbCardMask = regCard.GetBinaryValue(
|
||
|
SCARD_REG_ATRMASK,
|
||
|
&cbCardMask);
|
||
|
if (cbCardAtr != cbCardMask)
|
||
|
continue; // Invalid ATR/Mask combination.
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbCardMask = NULL; // No mask.
|
||
|
}
|
||
|
|
||
|
if (!AtrCompare(pbAtr, bfCardAtr, pbCardMask, cbCardAtr))
|
||
|
continue; // ATRs invalid or don't match.
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Does this card support the given interfaces?
|
||
|
//
|
||
|
|
||
|
if ((NULL != rgquidInterfaces) && (0 < cguidInterfaceCount))
|
||
|
{
|
||
|
DWORD cguidCrd;
|
||
|
DWORD ix, jx;
|
||
|
BOOL fAllInterfacesFound = TRUE;
|
||
|
LPCGUID rgCrdInfs = (LPCGUID)regCard.GetBinaryValue(
|
||
|
SCARD_REG_GUIDS,
|
||
|
&cguidCrd);
|
||
|
if ((0 != (cguidCrd % sizeof(GUID)))
|
||
|
|| (0 == cguidCrd))
|
||
|
continue; // Invalid GUID list.
|
||
|
cguidCrd /= sizeof(GUID);
|
||
|
for (ix = 0; ix < cguidInterfaceCount; ix += 1)
|
||
|
{
|
||
|
for (jx = 0; jx < cguidCrd; jx += 1)
|
||
|
{
|
||
|
if (0 == MemCompare(
|
||
|
(LPCBYTE)&rgCrdInfs[jx],
|
||
|
(LPCBYTE)&rgquidInterfaces[ix],
|
||
|
sizeof(GUID)))
|
||
|
break;
|
||
|
}
|
||
|
if (jx == cguidCrd)
|
||
|
{
|
||
|
fAllInterfacesFound = FALSE; // Unsupported interface
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!fAllInterfacesFound)
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// This card passes all the tests -- Include it.
|
||
|
//
|
||
|
|
||
|
MStrAdd(bfCards, szCard);
|
||
|
}
|
||
|
catch (...) {}
|
||
|
}
|
||
|
if (0 == bfCards.Length())
|
||
|
bfCards.Set((LPCBYTE)TEXT("\000"), 2 * sizeof(TCHAR));
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetCardTypeProviderName:
|
||
|
|
||
|
This routine returns the value of a given Provider Name, by Id number, for
|
||
|
the identified card type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
szCardName supplies the name of the card type with which this provider name
|
||
|
is associated.
|
||
|
|
||
|
dwProviderId supplies the identifier for the provider associated with this
|
||
|
card type. Possible values are:
|
||
|
|
||
|
SCARD_PROVIDER_SSP - The SSP identifier, as a GUID string.
|
||
|
SCARD_PROVIDER_CSP - The CSP name.
|
||
|
|
||
|
Other values < 0x80000000 are reserved for use by Microsoft. Values
|
||
|
over 0x80000000 are available for use by the smart card vendors, and
|
||
|
are card-specific.
|
||
|
|
||
|
bfProvider receives the string identifying the provider.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors as DWORD status codes
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/19/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
GetCardTypeProviderName(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szCardName,
|
||
|
IN DWORD dwProviderId,
|
||
|
OUT CBuffer &bfProvider)
|
||
|
{
|
||
|
LPCTSTR szProvValue;
|
||
|
TCHAR szNumeric[36];
|
||
|
CRegistry regCard;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Find the Card definition closest to the caller.
|
||
|
//
|
||
|
|
||
|
FindKey(
|
||
|
dwScope,
|
||
|
szCardName,
|
||
|
regCard,
|
||
|
SCARD_REG_CARDS,
|
||
|
SCARD_REG_TEMPLATES);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Derive the Provider Value Name.
|
||
|
//
|
||
|
|
||
|
if (dwProviderId < l_dwProvMapMax)
|
||
|
{
|
||
|
szProvValue = l_szrgProvMap[dwProviderId];
|
||
|
if (NULL == szProvValue)
|
||
|
throw (DWORD)SCARD_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
else if (0x80000000 <= dwProviderId)
|
||
|
{
|
||
|
_ultot(dwProviderId, szNumeric, 16);
|
||
|
szProvValue = szNumeric;
|
||
|
}
|
||
|
else
|
||
|
throw (DWORD)SCARD_E_INVALID_PARAMETER;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the provider value.
|
||
|
//
|
||
|
|
||
|
switch (dwProviderId)
|
||
|
{
|
||
|
case 1: // SCARD_PROVIDER_SSP
|
||
|
{
|
||
|
CBuffer bfGuid(sizeof(GUID));
|
||
|
|
||
|
bfProvider.Presize(40 * sizeof(TCHAR));
|
||
|
regCard.GetValue(szProvValue, bfGuid);
|
||
|
StringFromGuid(
|
||
|
(LPCGUID)bfGuid.Access(),
|
||
|
(LPTSTR)bfProvider.Access());
|
||
|
bfProvider.Resize(
|
||
|
(lstrlen((LPCTSTR)bfProvider.Access()) + 1) * sizeof(TCHAR),
|
||
|
TRUE);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
regCard.GetValue(szProvValue, bfProvider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetReaderInfo:
|
||
|
|
||
|
This routine returns all stored information regarding a given reader.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
szReader supplies the name of the reader of which info is to be extracted.
|
||
|
|
||
|
pbfGroups receives the list of groups as a multistring.
|
||
|
|
||
|
pbfDevice receives the device name.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - Reader found
|
||
|
FALSE - Reader not found
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 12/2/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
GetReaderInfo(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szReader,
|
||
|
OUT CBuffer *pbfGroups,
|
||
|
OUT CBuffer *pbfDevice)
|
||
|
{
|
||
|
CRegistry regReader;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Find the reader definition closest to the caller.
|
||
|
//
|
||
|
|
||
|
try
|
||
|
{
|
||
|
FindKey(dwScope, szReader, regReader, SCARD_REG_READERS);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Look up all it's values.
|
||
|
//
|
||
|
|
||
|
if (NULL != pbfDevice)
|
||
|
{
|
||
|
// Device name
|
||
|
try
|
||
|
{
|
||
|
regReader.GetValue(SCARD_REG_DEVICE, *pbfDevice);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfDevice->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != pbfGroups)
|
||
|
{
|
||
|
// Group list
|
||
|
try
|
||
|
{
|
||
|
regReader.GetValue(SCARD_REG_GROUPS, *pbfGroups);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfGroups->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetCardInfo:
|
||
|
|
||
|
This routine finds the given card under the given scope, and returns all
|
||
|
information associated with it.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
szCard supplies the name of the card for which info is to be extracted.
|
||
|
|
||
|
pbfAtr receives the ATR string of the given card. This parameter may be
|
||
|
NULL if the ATR is not desired.
|
||
|
|
||
|
pbfAtrMask receives the ATR mask of the given card, if any. This parameter
|
||
|
may be NULL if the value is not desired.
|
||
|
|
||
|
pbfInterfaces receives the list of interfaces as an array of GUIDs for the
|
||
|
given card, if any. This parameter may be NULL if the value is not
|
||
|
desired.
|
||
|
|
||
|
pbfProvider receives the Primary Provider of the given card, if any. This
|
||
|
parameter may be NULL if the value is not desired.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - The card was found, the returned data is valid.
|
||
|
FALSE - The supplied card was not found.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
None
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 12/3/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
GetCardInfo(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szCard,
|
||
|
OUT CBuffer *pbfAtr,
|
||
|
OUT CBuffer *pbfAtrMask,
|
||
|
OUT CBuffer *pbfInterfaces,
|
||
|
OUT CBuffer *pbfProvider)
|
||
|
{
|
||
|
CRegistry regCard;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Find the Card definition closest to the caller.
|
||
|
//
|
||
|
|
||
|
try
|
||
|
{
|
||
|
FindKey(
|
||
|
dwScope,
|
||
|
szCard,
|
||
|
regCard,
|
||
|
SCARD_REG_CARDS,
|
||
|
SCARD_REG_TEMPLATES);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Look up all it's values.
|
||
|
//
|
||
|
|
||
|
if (NULL != pbfAtr)
|
||
|
{
|
||
|
// Card ATR String
|
||
|
try
|
||
|
{
|
||
|
regCard.GetValue(SCARD_REG_ATR, *pbfAtr);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfAtr->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != pbfAtrMask)
|
||
|
{
|
||
|
// Card ATR Comparison Mask
|
||
|
try
|
||
|
{
|
||
|
regCard.GetValue(SCARD_REG_ATRMASK, *pbfAtrMask);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfAtrMask->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != pbfInterfaces)
|
||
|
{
|
||
|
// Supported Interface List
|
||
|
try
|
||
|
{
|
||
|
regCard.GetValue(SCARD_REG_GUIDS, *pbfInterfaces);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfInterfaces->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL != pbfProvider)
|
||
|
{
|
||
|
// Card Primary Provider
|
||
|
try
|
||
|
{
|
||
|
regCard.GetValue(SCARD_REG_PPV, *pbfProvider);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbfProvider->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef ENABLE_SCARD_TEMPLATES
|
||
|
/*++
|
||
|
|
||
|
ListCardTypeTemplates:
|
||
|
|
||
|
This routine searches the template database looking for previously defined
|
||
|
smart card templates against which the given card ATR matches. If the ATR
|
||
|
parameter is NULL, it returns a list of all templates.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
pbAtr supplies the ATR of a card to be matched against the known templates.
|
||
|
|
||
|
bfTemplates receives a list of matching template names, as a multistring.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - At least one template was found.
|
||
|
FALSE - No matching templates were found.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/16/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
ListCardTypeTemplates(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCBYTE pbAtr,
|
||
|
OUT CBuffer &bfTemplates)
|
||
|
{
|
||
|
CRegistry regCard;
|
||
|
LPCTSTR szCard;
|
||
|
CBuffer bfCardAtr;
|
||
|
CBuffer bfCardList;
|
||
|
|
||
|
bfTemplates.Reset();
|
||
|
ListKnownKeys(dwScope, bfCardList, SCARD_REG_TEMPLATES);
|
||
|
for (szCard = FirstString(bfCardList);
|
||
|
NULL != szCard;
|
||
|
szCard = NextString(szCard))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
FindKey(dwScope, szCard, regCard, SCARD_REG_TEMPLATES);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Does this card match the supplied ATR?
|
||
|
//
|
||
|
|
||
|
if ((NULL != pbAtr) && (0 != *pbAtr))
|
||
|
{
|
||
|
LPCBYTE pbCardAtr, pbCardMask;
|
||
|
DWORD cbCardAtr, cbCardMask;
|
||
|
|
||
|
pbCardAtr = regCard.GetBinaryValue(
|
||
|
SCARD_REG_ATR,
|
||
|
&cbCardAtr);
|
||
|
bfCardAtr.Set(pbCardAtr, cbCardAtr);
|
||
|
try
|
||
|
{
|
||
|
pbCardMask = regCard.GetBinaryValue(
|
||
|
SCARD_REG_ATRMASK,
|
||
|
&cbCardMask);
|
||
|
if (cbCardAtr != cbCardMask)
|
||
|
continue; // Invalid ATR/Mask combination.
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
pbCardMask = NULL; // No mask.
|
||
|
}
|
||
|
|
||
|
if (!AtrCompare(pbAtr, bfCardAtr, pbCardMask, cbCardAtr))
|
||
|
continue; // ATRs invalid or don't match.
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// This card passes all the tests -- Include it.
|
||
|
//
|
||
|
|
||
|
MStrAdd(bfTemplates, szCard);
|
||
|
}
|
||
|
catch (...) {}
|
||
|
}
|
||
|
if (0 == bfTemplates.Length())
|
||
|
{
|
||
|
bfTemplates.Set((LPCBYTE)TEXT("\000"), 2 * sizeof(TCHAR));
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif // ENABLE_SCARD_TEMPLATES
|
||
|
|
||
|
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Support Routines
|
||
|
//
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ListKnownKeys:
|
||
|
|
||
|
This routine lists all known keys of a given type within the current
|
||
|
caller's scope.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
bfKeys receives a multistring of existing key names, sorted and stripped
|
||
|
of duplicates.
|
||
|
|
||
|
szUserList supplies the primary registry path from which key names are to
|
||
|
be returned.
|
||
|
|
||
|
szSystemList supplies an optional secondary path from which key names can
|
||
|
be returned if the caller is running at system scope.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - At least one was found
|
||
|
FALSE - None were found.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors are thrown as DWORD status codes.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/22/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
static BOOL
|
||
|
ListKnownKeys(
|
||
|
IN DWORD dwScope,
|
||
|
OUT CBuffer &bfKeys,
|
||
|
IN LPCTSTR szUserList,
|
||
|
IN LPCTSTR szSystemList)
|
||
|
{
|
||
|
DWORD dwSpace, dwIndex, dwCount;
|
||
|
CRegistry regScopeKey;
|
||
|
CBuffer bfMyList;
|
||
|
LPCTSTR rgszLists[2];
|
||
|
|
||
|
|
||
|
//
|
||
|
// Loop through introduced space, then if appropriate, template space.
|
||
|
//
|
||
|
|
||
|
rgszLists[0] = szUserList;
|
||
|
rgszLists[1] = szSystemList;
|
||
|
for (dwSpace = 0; 2 > dwSpace; dwSpace += 1)
|
||
|
{
|
||
|
if (NULL == rgszLists[dwSpace])
|
||
|
continue;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Loop through all the possible scopes, from highest to lowest.
|
||
|
//
|
||
|
|
||
|
for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
|
||
|
{
|
||
|
if (l_rgRegMap[dwIndex].dwScope >= dwScope)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// If the caller is under this scope, then look for existing
|
||
|
// Keys.
|
||
|
//
|
||
|
|
||
|
regScopeKey.Open(
|
||
|
l_rgRegMap[dwIndex].hKey,
|
||
|
rgszLists[dwSpace],
|
||
|
KEY_READ);
|
||
|
if (SCARD_S_SUCCESS != regScopeKey.Status(TRUE))
|
||
|
continue;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Pull out all it's subkey names.
|
||
|
//
|
||
|
|
||
|
for (dwCount = 0;; dwCount += 1)
|
||
|
{
|
||
|
LPCTSTR szKey;
|
||
|
|
||
|
szKey = regScopeKey.Subkey(dwCount);
|
||
|
if (NULL == szKey)
|
||
|
break;
|
||
|
|
||
|
bfMyList.Append(
|
||
|
(LPBYTE)szKey,
|
||
|
(lstrlen(szKey) + 1) * sizeof(TCHAR));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Don't go on to the system list unless we're at system scope.
|
||
|
//
|
||
|
|
||
|
if (SCARD_SCOPE_SYSTEM != dwScope)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Sort the list, and remove duplicates.
|
||
|
//
|
||
|
|
||
|
bfMyList.Append((LPBYTE)TEXT("\000"), 2 * sizeof(TCHAR));
|
||
|
MStringSort(bfMyList, bfKeys);
|
||
|
return (2 * sizeof(TCHAR) < bfKeys.Length());
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
FindKey:
|
||
|
|
||
|
This routine finds the named key closest in scope to the caller.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwScope supplies an indicator of the scope of the operation. Possible
|
||
|
values are:
|
||
|
|
||
|
SCARD_SCOPE_USER - The current user's definitions are used.
|
||
|
SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
|
||
|
SCARD_SCOPE_SYSTEM - The system's definitions are used.
|
||
|
|
||
|
szKey supplies the name of the key to be found.
|
||
|
|
||
|
regKey receives initialization to reference the named key.
|
||
|
|
||
|
szUserList supplies the primary registry path from which key names are to
|
||
|
be returned.
|
||
|
|
||
|
szSystemList supplies an optional secondary path from which key names can
|
||
|
be returned if the caller is running at system scope.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - The key was found.
|
||
|
FALSE - No such key was found.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors are thrown as DWORD status codes.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/22/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
static void
|
||
|
FindKey(
|
||
|
IN DWORD dwScope,
|
||
|
IN LPCTSTR szKey,
|
||
|
OUT CRegistry ®Key,
|
||
|
IN LPCTSTR szUserList,
|
||
|
IN LPCTSTR szSystemList)
|
||
|
{
|
||
|
DWORD dwSpace, dwIndex;
|
||
|
CRegistry regScopeKey;
|
||
|
LPCTSTR rgszLists[2];
|
||
|
|
||
|
|
||
|
//
|
||
|
// Loop through introduced space, then if appropriate, template space.
|
||
|
//
|
||
|
|
||
|
rgszLists[0] = szUserList;
|
||
|
rgszLists[1] = szSystemList;
|
||
|
for (dwSpace = 0; 2 > dwSpace; dwSpace += 1)
|
||
|
{
|
||
|
if (NULL == rgszLists[dwSpace])
|
||
|
continue;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Loop through all the possible scopes, from highest to lowest.
|
||
|
//
|
||
|
|
||
|
for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
|
||
|
{
|
||
|
if (l_rgRegMap[dwIndex].dwScope >= dwScope)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// If the caller is under this scope, then look for an
|
||
|
// existing Key.
|
||
|
//
|
||
|
|
||
|
regScopeKey.Open(
|
||
|
l_rgRegMap[dwIndex].hKey,
|
||
|
rgszLists[dwSpace],
|
||
|
KEY_READ);
|
||
|
if (SCARD_S_SUCCESS != regScopeKey.Status(TRUE))
|
||
|
continue;
|
||
|
|
||
|
regKey.Open(regScopeKey, szKey, KEY_READ);
|
||
|
if (SCARD_S_SUCCESS != regKey.Status(TRUE))
|
||
|
continue;
|
||
|
|
||
|
//
|
||
|
// We've found such a key. Return immediately.
|
||
|
//
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Don't go on to the system list unless we're at system scope.
|
||
|
//
|
||
|
|
||
|
if (SCARD_SCOPE_SYSTEM != dwScope)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// We didn't find any such key.
|
||
|
//
|
||
|
|
||
|
throw (DWORD)ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
|