Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2320 lines
66 KiB

/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
WinSCard
Abstract:
This module supplies the UNICODE version of the API for the Calais Smartcard
Service Manager.
The Calais Service Manager does the work of coordinating the protocols,
readers, drivers, and smartcards on behalf of the application. The
following services are provided as part of a library to simplify access to
the Service Manager. These routines are the documented, exposed APIs.
These routines merely package the requests and forward them to the Calais
Service Manager, allowing the actual implementation of Calais to vary over
time.
At no time does the API library make security decisions. All
security-related functions must be performed by the Service Manager, running
in its own address space, or in the operating system kernel. However, some
utility routines may be implemented in the API library for speed, as long as
they do not involve security decisions.
Author:
Doug Barlow (dbarlow) 10/23/1996
Environment:
Win32, C++ w/ Exceptions
Notes:
?Notes?
--*/
#define __SUBROUTINE__
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "client.h"
#include "redirect.h"
extern HANDLE g_hUnifiedStartedEvent;
//
////////////////////////////////////////////////////////////////////////////////
//
// Calais Database Query Services
//
// These services all are oriented towards reading the Calais database.
// They provide the option for listing a Smartcard Context (see Section
// 4.1.1), but do not require one. Note that without a context, some or
// all information may be inaccessable due to security restrictions.
//
/*++
SCardListReaderGroups:
This service provides the list of named card reader groups that have
previously been defined to the system. The group 'SCard$DefaultReaders' is
only returned if it contains at least one reader. The group
'SCard$AllReaders' is not returned, as it implicitly exists.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
mszGroups receives a multi-string listing the reader groups defined to this
system and available to the current user on the current terminal. If
this value is NULL, the supplied buffer length in pcchGroups is ignored,
the length of the buffer that would have been returned had this
parameter not been null is written to pcchGroups, and a success code is
returned.
pcchGroups supplies the length of the mszGroups buffer in characters, and
receives the actual length of the multi-string structure, including all
trailing Null characters. If the buffer length is specified as
SCARD_AUTOALLOCATE, then szGroups is converted to a pointer to a string
pointer, and receives the address of a block of memory containing the
multi-string structure. This block of memory must be deallocated via
the SCardFreeMemory() service.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardListReaderGroupsW")
WINSCARDAPI LONG WINAPI
SCardListReaderGroupsW(
IN SCARDCONTEXT hContext,
OUT LPWSTR mszGroups,
IN OUT LPDWORD pcchGroups)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
CBuffer bfGroups;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardListReaderGroupsW(hRedirContext, mszGroups, pcchGroups);
}
else
{
ListReaderGroups(dwScope, bfGroups);
PlaceMultiResult(pCtx, bfGroups, mszGroups, pcchGroups);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardListReaders:
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:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
mszGroups supplies the names of the reader groups defined to the system, as
a multi-string. A NULL value is used to indicate that all readers in
the system be listed (i.e., the SCard$AllReaders group).
mszReaders receives a multi-string listing the card readers within the
supplied reader groups. If this value is NULL, the supplied buffer
length in pcchReaders is ignored, the length of the buffer that would
have been returned had this parameter not been null is written to
pcchReaders, and a success code is returned.
pcchReaders supplies the length of the mszReaders buffer in characters, and
receives the actual length of the multi-string structure, including all
trailing Null characters. If the buffer length is specified as
SCARD_AUTOALLOCATE, then mszReaders is converted to a pointer to a
string pointer, and receives the address of a block of memory containing
the multi-string structure. This block of memory must be deallocated
via the SCardFreeMemory() service.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardListReadersW")
WINSCARDAPI LONG WINAPI
SCardListReadersW(
IN SCARDCONTEXT hContext,
IN LPCWSTR mszGroups,
OUT LPWSTR mszReaders,
IN OUT LPDWORD pcchReaders)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
CBuffer bfReaders;
CTextMultistring mtzGroups;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardListReadersW(hRedirContext, mszGroups, mszReaders, pcchReaders);
}
else
{
mtzGroups = mszGroups;
ListReaders(dwScope, mtzGroups, bfReaders);
if (NULL != pCtx)
pCtx->StripInactiveReaders(bfReaders);
PlaceMultiResult(pCtx, bfReaders, mszReaders, pcchReaders);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardListCards:
This service provides a list of named cards previously introduced to the
system by this user which match an optionally supplied ATR string.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
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.
mszCards receives a multi-string listing the smartcards introduced to the
system by this user which match the supplied ATR string. If this value
is NULL, the supplied buffer length in pcchCards is ignored, the length
of the buffer that would have been returned had this parameter not been
null is written to pcchCards, and a success code is returned.
pcchCards supplies the length of the mszCards buffer in characters, and
receives the actual length of the multi-string structure, including all
trailing Null characters. If the buffer length is specified as
SCARD_AUTOALLOCATE, then mszCards is converted to a pointer to a string
pointer, and receives the address of a block of memory containing the
multi-string structure. This block of memory must be deallocated via he
SCardFreeMemory() service.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardListCardsW")
WINSCARDAPI LONG WINAPI
SCardListCardsW(
IN SCARDCONTEXT hContext,
IN LPCBYTE pbAtr,
IN LPCGUID rgquidInterfaces,
IN DWORD cguidInterfaceCount,
OUT LPWSTR mszCards,
IN OUT LPDWORD pcchCards)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
DWORD dwScope = SCARD_SCOPE_SYSTEM;
CBuffer bfCards;
CSCardUserContext *pCtx = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
ListCards(
dwScope,
pbAtr,
rgquidInterfaces,
cguidInterfaceCount,
bfCards);
PlaceMultiResult(pCtx, bfCards, mszCards, pcchCards);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardListInterfaces:
This service provides a list of interfaces known to be supplied by a given
card. The caller supplies the name of a smartcard previously introduced to
the system, and receives the list of interfaces supported by the card.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
szCard supplies the name of the card defined to the system.
pguidInterfaces receives an array of GUIDs indicating the interfaces
supported by the named smartcard. If this value is NULL, the supplied
array length in pcguidInterfaces is ignored, the size of the array that
would have been returned had this parameter not been null is written to
pcguidInterfaces, and a success code is returned.
pcguidInterfaces supplies the size of the pguidInterfaces array, and
receives the actual size of the returned array. If the array size is
specified as SCARD_AUTOALLOCATE, then pguidInterfaces is converted to a
pointer to a GUID pointer, and receives the address of a block of memory
containing the array. This block of memory must be deallocated via he
SCardFreeMemory() service.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardListInterfacesW")
WINSCARDAPI LONG WINAPI
SCardListInterfacesW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCard,
OUT LPGUID pguidInterfaces,
IN OUT LPDWORD pcguidInterfaces)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
BOOL fSts;
CTextString tzCard;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
DWORD cbInterfaces;
CBuffer bfInterfaces;
CSCardUserContext *pCtx = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCard = szCard;
fSts = GetCardInfo(
dwScope,
tzCard,
NULL,
NULL,
&bfInterfaces,
NULL);
if (!fSts)
throw (DWORD)SCARD_E_UNKNOWN_CARD;
if (SCARD_AUTOALLOCATE == *pcguidInterfaces)
cbInterfaces = SCARD_AUTOALLOCATE;
else
cbInterfaces = *pcguidInterfaces * sizeof(GUID);
PlaceResult(
pCtx,
bfInterfaces,
(LPBYTE)pguidInterfaces,
&cbInterfaces);
*pcguidInterfaces = cbInterfaces / sizeof(GUID);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardGetProviderId:
This service returns the GUID of the Primary Service Provider for the given
card. The caller supplies the name of a smartcard previously introduced to
the system, and receives the registered Primary Service Provider GUID, if
any.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
szCard supplies the name of the card defined to the system.
pguidInterfaces receives the GUID of the Primary Service Provider of the
indicated card. This provider may be activated via COM, and will supply
access to other services in the card.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardGetProviderIdW")
WINSCARDAPI LONG WINAPI
SCardGetProviderIdW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCard,
OUT LPGUID pguidProviderId)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
BOOL fSts;
CTextString tzCard;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
CBuffer bfProvider;
if (NULL != hContext)
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCard = szCard;
fSts = GetCardInfo(
dwScope,
tzCard,
NULL,
NULL,
NULL,
&bfProvider);
if (!fSts)
throw (DWORD)SCARD_E_UNKNOWN_CARD;
if (sizeof(GUID) != bfProvider.Length())
throw (DWORD)SCARD_E_INVALID_TARGET;
CopyMemory(pguidProviderId, bfProvider.Access(), bfProvider.Length());
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardGetCardTypeProviderName:
This service returns the value of a given Provider Name, by Id number, for
the identified card type. The caller supplies the name of a smartcard
previously introduced to the system, and receives the registered Service
Provider of that type, if any, as a string.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service, or is
NULL if this query is not directed towards a specific context.
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 Primary 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.
szProvider receives the string identifying the provider.
pcchProvider supplies the length of the szProvider buffer in characters,
and receives the actual length of the returned string, including the
trailing null character. If the buffer length is specified as
SCARD_AUTOALLOCATE, then szProvider is converted to a pointer to a
string pointer, and receives the address of a block of memory
containing the string. This block of memory must be deallocated via
the SCardFreeMemory() service.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Throws:
Errors as DWORD status codes
Author:
Doug Barlow (dbarlow) 1/19/1998
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardGetCardTypeProviderNameW")
WINSCARDAPI LONG WINAPI
SCardGetCardTypeProviderNameW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCardName,
IN DWORD dwProviderId,
OUT LPWSTR szProvider,
IN OUT LPDWORD pcchProvider)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
DWORD dwScope = SCARD_SCOPE_SYSTEM;
CTextString tzCardName;
CBuffer bfProvider;
CSCardUserContext *pCtx = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCardName = szCardName;
GetCardTypeProviderName(
dwScope,
tzCardName,
dwProviderId,
bfProvider);
PlaceResult(pCtx, bfProvider, szProvider, pcchProvider);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
//
////////////////////////////////////////////////////////////////////////////////
//
// Calais Database Management Services
//
// The following services provide for managing the Calais Database. These
// services actually update the database, and require a smartcard context.
//
/*++
SCardIntroduceReaderGroup:
This service provides means for introducing a new smartcard reader group to
Calais.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szGroupName supplies the friendly name to be assigned to the new reader
group.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardIntroduceReaderGroupW")
WINSCARDAPI LONG WINAPI
SCardIntroduceReaderGroupW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szGroupName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzGroupName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardIntroduceReaderGroupW(hRedirContext, szGroupName);
}
else
{
tzGroupName = szGroupName;
IntroduceReaderGroup(
dwScope,
tzGroupName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardForgetReaderGroup:
This service provides means for removing a previously defined smartcard
reader group from the Calais Subsystem. This service automatically clears
all readers from the group before forgetting it. It does not affect the
existence of the readers in the database.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szGroupName supplies the friendly name of the reader group to be
forgotten. The Calais-defined default reader groups may not be
forgotten.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardForgetReaderGroupW")
WINSCARDAPI LONG WINAPI
SCardForgetReaderGroupW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szGroupName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzGroupName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardForgetReaderGroupW(hRedirContext, szGroupName);
}
else
{
tzGroupName = szGroupName;
ForgetReaderGroup(
dwScope,
tzGroupName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardIntroduceReader:
This service provides means for introducing an existing smartcard reader
device to Calais. Once introduced, Calais will assume responsibility for
managing access to that reader.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szReaderName supplies the friendly name to be assigned to the reader.
SzDeviceName supplies the system name of the smartcard reader device.
(Example: "VendorX ModelY Z".)
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardIntroduceReaderW")
WINSCARDAPI LONG WINAPI
SCardIntroduceReaderW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szReaderName,
IN LPCWSTR szDeviceName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzReaderName;
CTextString tzDeviceName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardIntroduceReaderW(hRedirContext, szReaderName, szDeviceName);
}
else
{
tzReaderName = szReaderName;
tzDeviceName = szDeviceName;
IntroduceReader(
dwScope,
tzReaderName,
tzDeviceName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardForgetReader:
This service provides means for removing previously defined smartcard
readers from control by the Calais Subsystem. It is automatically removed
from any groups it may have been added to.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szReaderName supplies the friendly name of the reader to be forgotten.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardForgetReaderW")
WINSCARDAPI LONG WINAPI
SCardForgetReaderW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szReaderName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzReaderName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardForgetReaderW(hRedirContext, szReaderName);
}
else
{
tzReaderName = szReaderName;
ForgetReader(
dwScope,
tzReaderName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardAddReaderToGroup:
This service provides means for adding existing an reader into an existing
reader group.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szReaderName supplies the friendly name of the reader to be added.
szGroupName supplies the friendly name of the group to which the reader
should be added.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardAddReaderToGroupW")
WINSCARDAPI LONG WINAPI
SCardAddReaderToGroupW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szReaderName,
IN LPCWSTR szGroupName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzReaderName;
CTextString tzGroupName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardAddReaderToGroupW(hRedirContext, szReaderName, szGroupName);
}
else
{
tzReaderName = szReaderName;
tzGroupName = szGroupName;
AddReaderToGroup(
dwScope,
tzReaderName,
tzGroupName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardRemoveReaderFromGroup:
This service provides means for removing an existing reader from an existing
reader group. It does not affect the existence of either the reader or the
group in the Calais database.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szReaderName supplies the friendly name of the reader to be removed.
szGroupName supplies the friendly name of the group to which the reader
should be removed.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/25/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardRemoveReaderFromGroupW")
WINSCARDAPI LONG WINAPI
SCardRemoveReaderFromGroupW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szReaderName,
IN LPCWSTR szGroupName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzReaderName;
CTextString tzGroupName;
CSCardUserContext *pCtx = NULL;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
SCARDCONTEXT hRedirContext = NULL;
if (NULL != hContext)
{
pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
hRedirContext = pCtx->GetRedirContext();
}
if (hRedirContext || InTSRedirectMode()) {
if (!TS_REDIRECT_READY)
{
throw (DWORD)SCARD_E_NO_SERVICE;
}
nReturn = pfnSCardRemoveReaderFromGroupW(hRedirContext, szReaderName, szGroupName);
}
else
{
tzReaderName = szReaderName;
tzGroupName = szGroupName;
RemoveReaderFromGroup(
dwScope,
tzReaderName,
tzGroupName);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardIntroduceCardType:
This service provides means for introducing new smartcards to the Calais
Subsystem for the active user.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szCardName supplies the name by which the user can recognize this card.
PguidPrimaryProvider supplies a pointer to a GUID used to identify the
Primary Service Provider for the card.
rgguidInterfaces supplies an array of GUIDs identifying the smartcard
interfaces supported by this card.
dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
pbAtr supplies a string against which card ATRs will be compared to
determine a possible match for this card. The length of this string is
determined by normal ATR parsing.
pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
must point to a string of bytes the same length as the ATR string
supplied in pbAtr. Then when a given ATR A is compared to the ATR
supplied in pbAtr B, it matches if and only if A & M = B, where M is the
supplied mask, and & represents bitwise logical AND.
cbAtrLen supplies the length of the ATR and Mask. This value may be zero
if the lentgh is obvious from the ATR. However, it may be required if
there is a Mask value that obscures the actual ATR.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardIntroduceCardTypeW")
WINSCARDAPI LONG WINAPI
SCardIntroduceCardTypeW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCardName,
IN LPCGUID pguidPrimaryProvider,
IN LPCGUID rgguidInterfaces,
IN DWORD dwInterfaceCount,
IN LPCBYTE pbAtr,
IN LPCBYTE pbAtrMask,
IN DWORD cbAtrLen)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzCardName;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
if (NULL != hContext)
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCardName = szCardName;
IntroduceCard(
dwScope,
tzCardName,
pguidPrimaryProvider,
rgguidInterfaces,
dwInterfaceCount,
pbAtr,
pbAtrMask,
cbAtrLen);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardSetCardTypeProviderName:
This service provides means for adding additional service providers to a
specified card type.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szCardName supplies the name of the card type with which this provider
name is to be associated.
dwProviderId supplies the identifier for the provider to be associated with
this card type. Possible values are:
SCARD_PROVIDER_SSP - The Primary 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.
szProvider supplies the string identifying the provider.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 1/19/1998
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardSetCardTypeProviderNameW")
WINSCARDAPI LONG WINAPI
SCardSetCardTypeProviderNameW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCardName,
IN DWORD dwProviderId,
IN LPCWSTR szProvider)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzCardName;
CTextString tzProvider;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
if (NULL != hContext)
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCardName = szCardName;
tzProvider = szProvider;
SetCardTypeProviderName(
dwScope,
tzCardName,
dwProviderId,
tzProvider);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardForgetCardType:
This service provides means for removing previously defined smartcards from
the Calais Subsystem.
Arguments:
hContext supplies the handle identifying the Service Manager Context, which
must have been previously established via the SCardEstablishContext()
service.
szCardName supplies the friendly name of the card to be forgotten.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardForgetCardTypeW")
WINSCARDAPI LONG WINAPI
SCardForgetCardTypeW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szCardName)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CTextString tzCardName;
DWORD dwScope = SCARD_SCOPE_SYSTEM;
if (NULL != hContext)
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
dwScope = pCtx->Scope();
}
tzCardName = szCardName;
ForgetCard(
dwScope,
tzCardName);
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
//
////////////////////////////////////////////////////////////////////////////////
//
// Reader Services
//
// The following services supply means for tracking cards within readers.
//
/*++
SCardLocateCards:
This service searches the readers listed in the lpReaderStates parameter for
any containing a card with an ATR string matching one of the card supplied
names. This service returns immediately with the result. If no matching
cards are found, the calling application may use the SCardGetStatusChange
service to wait for card availability changes.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service.
mszCards supplies the names of the cards to search for, as a multi-string.
rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
the search, and receives the result.
cReaders supplies the number of elements in the rgReaderStates array.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardLocateCardsW")
WINSCARDAPI LONG WINAPI
SCardLocateCardsW(
IN SCARDCONTEXT hContext,
IN LPCWSTR mszCards,
IN OUT LPSCARD_READERSTATE_W rgReaderStates,
IN DWORD cReaders)
{
LONG nReturn = SCARD_S_SUCCESS;
LPSCARD_ATRMASK rgAtrMasks = NULL;
try
{
LPCSTR szCard;
CTextMultistring mtzCards;
DWORD dwIndex;
DWORD dwScope;
CBuffer bfXlate1(36), bfXlate2(36); // Rough guess of name & ATR lengths
BOOL fSts;
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
dwScope = pCtx->Scope();
if (0 == *mszCards)
throw (DWORD)SCARD_E_INVALID_VALUE;
mtzCards = mszCards;
rgAtrMasks = new SCARD_ATRMASK[MStringCount(mtzCards)];
if (rgAtrMasks == NULL)
{
CalaisWarning(
__SUBROUTINE__,
DBGT("WinSCard Client has no memory"));
throw (DWORD)SCARD_E_NO_MEMORY;
}
dwIndex = 0;
for (szCard = FirstString(mtzCards);
NULL != szCard;
szCard = NextString(szCard))
{
fSts = GetCardInfo(
dwScope,
szCard,
&bfXlate1, // ATR
&bfXlate2, // Mask
NULL,
NULL);
if (!fSts)
throw (DWORD)SCARD_E_UNKNOWN_CARD;
ASSERT(33 >= bfXlate1.Length()); // Biggest an ATR can be.
rgAtrMasks[dwIndex].cbAtr = bfXlate1.Length();
memcpy(rgAtrMasks[dwIndex].rgbAtr, bfXlate1.Access(), rgAtrMasks[dwIndex].cbAtr);
ASSERT(rgAtrMasks[dwIndex].cbAtr == bfXlate2.Length());
memcpy(rgAtrMasks[dwIndex].rgbMask, bfXlate2.Access(), rgAtrMasks[dwIndex].cbAtr);
dwIndex ++;
}
nReturn = SCardLocateCardsByATRW(
hContext,
rgAtrMasks,
dwIndex,
rgReaderStates,
cReaders);
// If the remote client does not implement the new API
// retry with the old one. it might succeed if its DB is good enough
if ((nReturn == ERROR_CALL_NOT_IMPLEMENTED) && (pCtx->GetRedirContext()))
{
nReturn = pfnSCardLocateCardsW(pCtx->GetRedirContext(), mszCards, rgReaderStates, cReaders);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
if (rgAtrMasks != NULL)
{
try
{
delete[] rgAtrMasks;
}
catch (...)
{
}
}
return nReturn;
}
/*++
SCardLocateCardsByATR:
This service searches the readers listed in the lpReaderStates parameter for
any containing a card with an ATR string matching one of the supplied ATRs
This service returns immediately with the result. If no matching
cards are found, the calling application may use the SCardGetStatusChange
service to wait for card availability changes.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service.
rgAtrMasks supplies the ATRs to search for, as an array of structs.
cAtrs supplies the number of elements in the rgAtrMasks array.
rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
the search, and receives the result.
cReaders supplies the number of elements in the rgReaderStates array.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardLocateCardsByATRW")
WINSCARDAPI LONG WINAPI
SCardLocateCardsByATRW(
IN SCARDCONTEXT hContext,
IN LPSCARD_ATRMASK rgAtrMasks,
IN DWORD cAtrs,
IN OUT LPSCARD_READERSTATE_W rgReaderStates,
IN DWORD cReaders)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
if (pCtx->GetRedirContext())
{
nReturn = pfnSCardLocateCardsByATRW(pCtx->GetRedirContext(), rgAtrMasks, cAtrs, rgReaderStates, cReaders);
}
else
{
CBuffer bfReaders;
DWORD dwIndex;
for (dwIndex = 0; dwIndex < cReaders; dwIndex += 1)
MStrAdd(bfReaders, rgReaderStates[dwIndex].szReader);
pCtx->LocateCards(
bfReaders,
rgAtrMasks,
cAtrs,
(LPSCARD_READERSTATE)rgReaderStates,
cReaders);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardGetStatusChange:
This service is used to block execution until such time as the current
availability of cards in a given set of readers changes. The caller
supplies a list of readers to be monitored via an SCARD_READERSTATE array,
and the maximum amount of time, in seconds, that it is willing to wait for
an action to occur on one of the listed readers. Zero in this parameter
indicates that no timeout is specified. The service returns when there is a
change in availability, having filled in the dwEventState fields of the
rgReaderStates parameter appropriately.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service.
dwTimeOut supplies the maximum amount of time to wait for an action, in
seconds. A zero value implies that the wait will never timeout.
rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
the wait, and receives the result.
cReaders supplies the number of elements in the rgReaderStates array.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardGetStatusChangeW")
BOOL
SetStartedEventAfterTestingConnectedState();
WINSCARDAPI LONG WINAPI
SCardGetStatusChangeW(
IN SCARDCONTEXT hContext,
IN DWORD dwTimeout,
IN OUT LPSCARD_READERSTATE_W rgReaderStates,
IN DWORD cReaders)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
if (pCtx->GetRedirContext())
{
nReturn = pfnSCardGetStatusChangeW(pCtx->GetRedirContext(), dwTimeout, rgReaderStates, cReaders);
//
// See if there is an indication that the client's scardsvr service was shutdown
//
if (SCARD_E_SYSTEM_CANCELLED == nReturn)
{
//OutputDebugString("WINSCARD: SCardEstablishContext: got E_NO_SERVICE!\n");
SetStartedEventAfterTestingConnectedState();
}
}
else
{
CBuffer bfReaders;
DWORD dwIndex;
for (dwIndex = 0; dwIndex < cReaders; dwIndex += 1)
MStrAdd(bfReaders, rgReaderStates[dwIndex].szReader);
pCtx->GetStatusChange(
bfReaders,
(LPSCARD_READERSTATE)rgReaderStates,
cReaders,
dwTimeout);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
if (SCARD_E_SYSTEM_CANCELLED == nReturn)
{
ResetEvent(g_hUnifiedStartedEvent);
}
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
//
////////////////////////////////////////////////////////////////////////////////
//
// Card/Reader Access Services
//
// The following services provide means for establishing communication with
// the card.
//
/*++
SCardConnect:
This service establishes a connection from the calling application to the
smartcard in the designated reader. If no card exists in the specified
reader, an error is returned.
Arguments:
hContext supplies the handle identifying the Service Manager Context
established previously via the SCardEstablishContext() service.
szReader supplies the name of the reader containing the target card.
DwShareMode supplies a flag indicating whether or not other applications may
form connections to this card. Possible values are:
SCARD_SHARE_SHARED - This application is willing to share this card with
other applications.
SCARD_SHARE_EXCLUSIVE - This application is not willing to share this
card with other applications.
SCARD_SHARE_DIRECT - This application is taking control of the reader.
DwPreferredProtocols supplies a bit mask of acceptable protocols for this
connection. Possible values, which may be combined via the OR
operation, are:
SCARD_PROTOCOL_T0 - T=0 is an acceptable protocol.
SCARD_PROTOCOL_T1 - T=1 is an acceptable protocol.
phCard receives a handle identifying the connection to the smartcard in the
designated reader.
pdwActiveProtocol receives a flag indicating the established active
protocol. Possible values are:
SCARD_PROTOCOL_T0 - T=0 is the active protocol.
SCARD_PROTOCOL_T1 - T=1 is the active protocol.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardConnectW")
WINSCARDAPI LONG WINAPI
SCardConnectW(
IN SCARDCONTEXT hContext,
IN LPCWSTR szReader,
IN DWORD dwShareMode,
IN DWORD dwPreferredProtocols,
OUT LPSCARDHANDLE phCard,
OUT LPDWORD pdwActiveProtocol)
{
LONG nReturn = SCARD_S_SUCCESS;
CReaderContext *pRdr = NULL;
CSCardSubcontext *pSubCtx = NULL;
try
{
*phCard = NULL; // Touch it to be sure it's real.
CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
CTextString tzReader;
if (pCtx->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
tzReader = szReader;
pRdr = new CReaderContext;
if (NULL == pRdr)
{
CalaisWarning(
__SUBROUTINE__,
DBGT("WinSCard Client has no memory"));
throw (DWORD)SCARD_E_NO_MEMORY;
}
SCARDCONTEXT hRedirContext = pCtx->GetRedirContext();
if (hRedirContext)
{
SCARDHANDLE hCard = g_phlReaders->Add(pRdr); // do it first to avoid out of memory condition
nReturn = pfnSCardConnectW(hRedirContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
if (nReturn == SCARD_S_SUCCESS)
{
pRdr->SetRedirCard(*phCard);
*phCard = hCard;
}
else
{
g_phlReaders->Close(hCard);
delete pRdr;
}
}
else
{
pSubCtx = pCtx->AcquireSubcontext(TRUE);
pRdr->Connect(
pSubCtx,
tzReader,
dwShareMode,
dwPreferredProtocols);
pSubCtx = NULL;
pRdr->Context()->ReleaseSubcontext();
if (NULL != pdwActiveProtocol)
*pdwActiveProtocol = pRdr->Protocol();
pRdr->Context()->m_hReaderHandle = g_phlReaders->Add(pRdr);
*phCard = pRdr->Context()->m_hReaderHandle;
}
}
catch (DWORD dwStatus)
{
if (NULL != pSubCtx)
{
pSubCtx->Deallocate();
pSubCtx->ReleaseSubcontext();
}
if (NULL != pRdr)
delete pRdr;
nReturn = (LONG)dwStatus;
}
catch (...)
{
if (NULL != pSubCtx)
{
pSubCtx->Deallocate();
pSubCtx->ReleaseSubcontext();
}
if (NULL != pRdr)
delete pRdr;
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
/*++
SCardStatus:
This routine provides the current status of the reader. It may be used at
any time following a successful call to SCardConnect or SCardOpenReader, and
prior to a successful call to SCardDisconnect. It does not effect the state
of the reader or driver.
Arguments:
hCard - This is the reference value returned from the SCardConnect or
SCardOpenReader service.
mszReaderNames - This receives a list of friendly names by which the
currently connected reader is known. This list is returned as a
multistring.
pcchReaderLen - This supplies the length of the mszReader buffer, in
characters, and receives the actual returned length of the reader
friendly name list, in characters, including the trailing NULL
characters.
pdwState - This receives the current state of the reader. Upon success, it
receives one of the following state indicators:
SCARD_ABSENT - This value implies there is no card in the reader.
SCARD_PRESENT - This value implies there is a card is present in the
reader, but that it has not been moved into position for use.
SCARD_SWALLOWED - This value implies there is a card in the reader in
position for use. The card is not powered.
SCARD_POWERED - This value implies there is power is being provided to
the card, but the Reader Driver is unaware of the mode of the card.
SCARD_NEGOTIABLEMODE - This value implies the card has been reset and is
awaiting PTS negotiation.
SCARD_SPECIFICMODE - This value implies the card has been reset and
specific communication protocols have been established.
pdwProtocol - This receives the current protocol, if any. Possible returned
values are listed below. Other values may be added in the future. The
returned value is only meaningful if the returned state is
SCARD_SPECIFICMODE.
SCARD_PROTOCOL_RAW - The Raw Transfer Protocol is in use.
SCARD_PROTOCOL_T0 - The ISO 7816/3 T=0 Protocol is in use.
SCARD_PROTOCOL_T1 - The ISO 7816/3 T=1 Protocol is in use.
pbAtr - This parameter points to a 32-byte buffer which receives the ATR
string from the currently inserted card, if available.
pbcAtrLen - This points to a DWORD which supplies the length of the pbAtr
buffer, and receives the actual number of bytes in the ATR string.
Return Value:
A 32-bit value indicating whether or not the service completed successfully.
SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
represents an error condition.
Author:
Doug Barlow (dbarlow) 10/23/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("SCardStatusW")
WINSCARDAPI LONG WINAPI
SCardStatusW(
IN SCARDHANDLE hCard,
OUT LPWSTR mszReaderNames,
IN OUT LPDWORD pcchReaderLen,
OUT LPDWORD pdwState,
OUT LPDWORD pdwProtocol,
OUT LPBYTE pbAtr,
IN OUT LPDWORD pcbAtrLen)
{
LONG nReturn = SCARD_S_SUCCESS;
try
{
CReaderContext *pRdr = (CReaderContext *)((*g_phlReaders)[hCard]);
if (pRdr->IsBad())
{
throw (DWORD)SCARD_E_SERVICE_STOPPED;
}
if (pRdr->GetRedirCard())
{
nReturn = pfnSCardStatusW(pRdr->GetRedirCard(), mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
}
else
{
CBuffer bfAtr, bfReader;
DWORD dwLocalState, dwLocalProtocol;
pRdr->Status(&dwLocalState, &dwLocalProtocol, bfAtr, bfReader);
if (NULL != pdwState)
*pdwState = dwLocalState;
if (NULL != pdwProtocol)
*pdwProtocol = dwLocalProtocol;
if (NULL != pcchReaderLen)
PlaceMultiResult(
pRdr->Context()->Parent(),
bfReader,
mszReaderNames,
pcchReaderLen);
if (NULL != pcbAtrLen)
PlaceResult(pRdr->Context()->Parent(), bfAtr, pbAtr, pcbAtrLen);
}
}
catch (DWORD dwStatus)
{
nReturn = (LONG)dwStatus;
}
catch (...)
{
nReturn = SCARD_E_INVALID_PARAMETER;
}
return nReturn;
}
//
///////////////////////////////////////////////////////////////////////////////
//
// Utility Routines
//
/*++
PlaceResult:
This set of routines places the result of an operation into the user's
output buffer, supporting SCARD_AUTO_ALLOCATE, invalid buffer sizes, etc.
Arguments:
pCtx supplies the context under which this operation is being performed.
bfResult supplies the result to be returned to the user.
pbOutput receives the result for the user, as a byte stream.
szOutput receives the result as an ANSI or UNICODE string.
pcbLength supplies the length of the user's output buffer in bytes, and
receives how much of it was used.
pcchLength supplies the length of the user's output buffer in characters,
and receives how much of it was used.
Return Value:
None
Throws:
Error conditions are thrown as DWORD status codes.
Author:
Doug Barlow (dbarlow) 12/7/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("PlaceResult")
void
PlaceResult(
CSCardUserContext *pCtx,
CBuffer &bfResult,
LPWSTR szOutput,
LPDWORD pcchLength)
{
LPWSTR szForUser = NULL;
LPWSTR szOutBuf = szOutput;
DWORD cchSrcLength = bfResult.Length() / sizeof(TCHAR);
try
{
if (NULL == szOutput)
*pcchLength = 0;
switch (*pcchLength)
{
case 0: // They just want the length.
*pcchLength = cchSrcLength;
break;
case SCARD_AUTOALLOCATE:
if (0 < cchSrcLength)
{
if (NULL == pCtx)
{
szForUser = (LPWSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
cchSrcLength * sizeof(WCHAR));
}
else
szForUser = (LPWSTR)pCtx->AllocateMemory(
cchSrcLength * sizeof(WCHAR));
if (NULL == szForUser)
{
CalaisWarning(
__SUBROUTINE__,
DBGT("Client can't get return memory"));
throw (DWORD)SCARD_E_NO_MEMORY;
}
*(LPWSTR *)szOutput = szForUser;
szOutBuf = szForUser;
// Fall through intentionally
}
else
{
*pcchLength = cchSrcLength;
*(LPWSTR *)szOutput = (LPWSTR)g_wszBlank;
break; // Do terminate the case now.
}
default:
if (*pcchLength < cchSrcLength)
{
*pcchLength = cchSrcLength;
throw (DWORD)SCARD_E_INSUFFICIENT_BUFFER;
}
MoveToUnicodeString(
szOutBuf,
(LPCTSTR)bfResult.Access(),
cchSrcLength);
*pcchLength = cchSrcLength;
break;
}
}
catch (...)
{
if (NULL != szForUser)
{
if (NULL == pCtx)
HeapFree(GetProcessHeap(), 0, szForUser);
else
pCtx->FreeMemory(szForUser);
}
throw;
}
}
/*++
PlaceMultiResult:
This set of routines places a Multistring result of an operation into the
user's output buffer, supporting SCARD_AUTO_ALLOCATE, invalid buffer sizes,
etc.
Arguments:
pCtx supplies the context under which this operation is being performed.
bfResult supplies the TCHAR multistring result to be returned to the user.
mszOutput receives the result as an ANSI or UNICODE multistring.
pcchLength supplies the length of the user's output buffer in characters,
and receives how much of it was used.
Return Value:
None
Throws:
Error conditions are thrown as DWORD status codes.
Author:
Doug Barlow (dbarlow) 12/7/1996
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ DBGT("PlaceMultiResult")
void
PlaceMultiResult(
CSCardUserContext *pCtx,
CBuffer &bfResult,
LPWSTR mszOutput,
LPDWORD pcchLength)
{
LPWSTR mszForUser = NULL;
LPWSTR mszOutBuf = mszOutput;
DWORD cchSrcLength = bfResult.Length() / sizeof(TCHAR);
try
{
if (NULL == mszOutput)
*pcchLength = 0;
switch (*pcchLength)
{
case 0: // They just want the length.
*pcchLength = cchSrcLength;
break;
case SCARD_AUTOALLOCATE:
if (0 < cchSrcLength)
{
if (NULL == pCtx)
{
mszForUser = (LPWSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
cchSrcLength * sizeof(WCHAR));
}
else
mszForUser = (LPWSTR)pCtx->AllocateMemory(
cchSrcLength * sizeof(WCHAR));
if (NULL == mszForUser)
{
CalaisWarning(
__SUBROUTINE__,
DBGT("Client can't get return memory"));
throw (DWORD)SCARD_E_NO_MEMORY;
}
*(LPWSTR *)mszOutput = mszForUser;
mszOutBuf = mszForUser;
// Fall through intentionally
}
else
{
*pcchLength = cchSrcLength;
*(LPWSTR *)mszOutput = (LPWSTR)g_wszBlank;
break; // Do terminate the case now.
}
default:
if (*pcchLength < cchSrcLength)
{
*pcchLength = cchSrcLength;
throw (DWORD)SCARD_E_INSUFFICIENT_BUFFER;
}
MoveToUnicodeMultiString(
mszOutBuf,
(LPCTSTR)bfResult.Access(),
cchSrcLength);
*pcchLength = cchSrcLength;
break;
}
}
catch (...)
{
if (NULL != mszForUser)
{
if (NULL == pCtx)
HeapFree(GetProcessHeap(), 0, mszForUser);
else
pCtx->FreeMemory(mszForUser);
}
throw;
}
}