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.
1557 lines
31 KiB
1557 lines
31 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
|
|
Module Name:
|
|
|
|
SEnv
|
|
|
|
Abstract:
|
|
|
|
This file contains the outline implementation of the Smartcard Common
|
|
dialog CSCardEnv class. This class encapsulates current Smartcard
|
|
environment information (i.e. given groups, readers, cards, etc.)
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
Environment:
|
|
|
|
Win32, C++ w/Exceptions, MFC
|
|
|
|
Revision History:
|
|
|
|
Chris Dudley (cdudley) 4/15/97
|
|
Amanda Matlosz (amatlosz) 1/29/98 Combined CSCardEnv and CSCardGroup,
|
|
added unicode support
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Includes
|
|
//
|
|
#include "stdafx.h"
|
|
#include "senv.h"
|
|
#include <querydb.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// local macros
|
|
#ifdef _DEBUG
|
|
#define TRACE_STR(name,sz) \
|
|
TRACE(_T("CmnUILb.lib: %s: %s\n"), name, sz)
|
|
#define TRACE_CODE(name,code) \
|
|
TRACE(_T("CmnUILb.lib: %s: error = 0x%x\n"), name, code)
|
|
#define TRACE_CATCH(name,code) TRACE_CODE(name,code)
|
|
#define TRACE_CATCH_UNKNOWN(name) TRACE_STR(name,_T("An unidentified exception has occurred!"))
|
|
#else
|
|
#define TRACE_STR(name,sz) ((void)0)
|
|
#define TRACE_CODE(name,code) ((void)0)
|
|
#define TRACE_CATCH(name,code) ((void)0)
|
|
#define TRACE_CATCH_UNKNOWN(name) ((void)0)
|
|
#endif // _DEBUG
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSCardEnv Implementation
|
|
//
|
|
|
|
|
|
/*++
|
|
GetDialogTitle:
|
|
|
|
Routine returns a new title for the dialog if needed
|
|
|
|
Arguments:
|
|
|
|
pstzTitle -- pointer to a CTextString to contain the dialog's title
|
|
|
|
Return Value:
|
|
|
|
A CTextString object containing the new dialog text or empty string
|
|
if no new title required.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/28/98 Add unicode support/code cleanup
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
void CSCardEnv::GetDialogTitle( CTextString *pstzTitle )
|
|
{
|
|
// check & empty params
|
|
|
|
ASSERT(NULL != pstzTitle);
|
|
pstzTitle->Clear();
|
|
|
|
*pstzTitle = m_strTitle;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG CardMeetsSearchCriteria:
|
|
|
|
Routine determines if a selected reader has a card inserted which
|
|
meets the search criteria defined by the caller.
|
|
|
|
Arguments:
|
|
|
|
dwSelectedReader - index used to select which reader to query.
|
|
|
|
Return Value:
|
|
|
|
A BOOL value indicating whether or not the card meets the search criteria.
|
|
|
|
Author:
|
|
|
|
Amanda Matlosz 3/16/1998 created
|
|
|
|
Revisions:
|
|
|
|
|
|
--*/
|
|
BOOL CSCardEnv::CardMeetsSearchCriteria(DWORD dwSelectedReader)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
SCARD_READERINFO ReaderInfo;
|
|
|
|
try
|
|
{
|
|
// check params
|
|
if(dwSelectedReader >= (DWORD)NumberOfReaders())
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!IsContextValid())
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// get the reader object
|
|
pReaderState = m_rgReaders[dwSelectedReader];
|
|
|
|
// is it valid, matches the search list, and passes the check?
|
|
if (NULL != pReaderState)
|
|
{
|
|
ReaderInfo.fCardLookup = FALSE;
|
|
ReaderInfo.fChecked = FALSE;
|
|
|
|
pReaderState->GetReaderInfo(&ReaderInfo);
|
|
|
|
fReturn = (ReaderInfo.fCardLookup && ReaderInfo.fChecked);
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
TRACE_CATCH(_T("CardMeetsSearchCriteria"), lErr);
|
|
}
|
|
catch(...)
|
|
{
|
|
TRACE_CATCH_UNKNOWN(_T("CardMeetsSearchCriteria"));
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
/*++
|
|
|
|
LONG ConnectToReader:
|
|
|
|
Routine connects to a selected reader, and sets the user-provided structs
|
|
to contain the reader&cardname. returns an error if the user-provided struct's
|
|
buffers aren't long enough.
|
|
|
|
Arguments:
|
|
|
|
dwSelectedReader - index used to select which reader to connect to.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action.
|
|
See the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/28/1998 code cleanup
|
|
|
|
--*/
|
|
LONG CSCardEnv::ConnectToReader(DWORD dwSelectedReader)
|
|
{
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
LPSTR szName = NULL;
|
|
LPWSTR wszName = NULL;
|
|
|
|
try
|
|
{
|
|
if (!IsContextValid())
|
|
{
|
|
throw (LONG)E_FAIL;
|
|
}
|
|
|
|
//
|
|
// If user has indicated to make a connection, do so
|
|
// through callbacks or internally.
|
|
// m_strReader and m_strCard are set as a side effect of these connect calls
|
|
//
|
|
|
|
if(IsCallbackValid())
|
|
{
|
|
lReturn = ConnectUser( dwSelectedReader,
|
|
&m_hCardHandle,
|
|
&m_strReader,
|
|
&m_strCard);
|
|
}
|
|
else
|
|
{
|
|
if (0 != m_dwShareMode)
|
|
{
|
|
lReturn = ConnectInternal( dwSelectedReader,
|
|
&m_hCardHandle,
|
|
m_dwShareMode,
|
|
m_dwPreferredProtocols,
|
|
&m_dwActiveProtocol,
|
|
&m_strReader,
|
|
&m_strCard);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// MUST set m_strReader and m_strCard manually
|
|
//
|
|
CSCardReaderState* pReaderState = NULL;
|
|
pReaderState = m_rgReaders[dwSelectedReader];
|
|
if (NULL != pReaderState)
|
|
{
|
|
lReturn = pReaderState->GetReaderCardInfo( &m_strReader,
|
|
&m_strCard);
|
|
}
|
|
}
|
|
}
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
|
|
//
|
|
// Set the user's OCN struct to contain return information
|
|
//
|
|
|
|
if(NULL != m_pOCNW)
|
|
{
|
|
m_pOCNW->hCardHandle = m_hCardHandle;
|
|
m_pOCNW->dwActiveProtocol = m_dwActiveProtocol;
|
|
|
|
wszName = (LPWSTR)(LPCWSTR)m_strReader;
|
|
if (m_pOCNW->nMaxRdr >= m_strReader.Length()+1)
|
|
{
|
|
::CopyMemory( (LPVOID) m_pOCNW->lpstrRdr,
|
|
(CONST LPVOID)wszName,
|
|
((m_strReader.Length()+1) * sizeof(WCHAR)) );
|
|
}
|
|
else
|
|
{
|
|
m_pOCNW->nMaxRdr = m_strReader.Length()+1;
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
};
|
|
|
|
wszName = (LPWSTR)(LPCWSTR)m_strCard;
|
|
if (m_pOCNW->nMaxCard >= m_strCard.Length()+1)
|
|
{
|
|
::CopyMemory( (LPVOID) m_pOCNW->lpstrCard,
|
|
(CONST LPVOID)wszName,
|
|
((m_strCard.Length()+1) * sizeof(WCHAR)) );
|
|
}
|
|
else
|
|
{
|
|
m_pOCNW->nMaxCard = m_strCard.Length()+1;
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
};
|
|
}
|
|
else if (NULL != m_pOCNA)
|
|
{
|
|
m_pOCNA->hCardHandle = m_hCardHandle;
|
|
m_pOCNA->dwActiveProtocol = m_dwActiveProtocol;
|
|
|
|
szName = (LPSTR)(LPCSTR)m_strReader;
|
|
if (m_pOCNA->nMaxRdr >= m_strReader.Length()+1)
|
|
{
|
|
::CopyMemory( (LPVOID) m_pOCNA->lpstrRdr,
|
|
(CONST LPVOID)szName,
|
|
m_strReader.Length()+1);
|
|
}
|
|
else
|
|
{
|
|
m_pOCNA->nMaxRdr = m_strReader.Length()+1;
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
}
|
|
|
|
szName = (LPSTR)(LPCSTR)m_strCard;
|
|
if (m_pOCNA->nMaxCard >= m_strCard.Length()+1)
|
|
{
|
|
::CopyMemory( (LPVOID) m_pOCNA->lpstrCard,
|
|
(CONST LPVOID)szName,
|
|
m_strCard.Length()+1);
|
|
}
|
|
else
|
|
{
|
|
m_pOCNA->nMaxCard = m_strCard.Length()+1;
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Error! One of them must be valid!
|
|
throw (LONG)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("ConnectToReader"), lErr);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("ConnectToReader"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG Search:
|
|
|
|
This routine is called to search for a card when the calling application
|
|
requests SC_DLG_NO_UI or SC_DLG_MINIMAL_UI.
|
|
|
|
Arguments:
|
|
|
|
pcMatches - pointer to a counter containing the number of matches found for
|
|
the given searched for card.
|
|
|
|
pdwIndex - index of the first card found that matches the search criteria.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action.
|
|
See the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley (cdudley) 4/15/97
|
|
|
|
--*/
|
|
LONG CSCardEnv::Search(int *pcMatches, DWORD *pdwIndex)
|
|
{
|
|
// Locals
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
LONG lMoreReaders = SCARD_S_SUCCESS;
|
|
int cMatches = 0;
|
|
DWORD dwIndex = 0;
|
|
BOOL fIndexStored = FALSE;
|
|
SCARD_READERINFO ReaderInfo;
|
|
|
|
try
|
|
{
|
|
// Check params
|
|
if(pcMatches == NULL || pdwIndex == NULL)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
|
|
// Initialize reader array
|
|
lReturn = UpdateReaders();
|
|
if(SCARDFAILED(lReturn))
|
|
{
|
|
throw lReturn;
|
|
}
|
|
|
|
//
|
|
// Walk through cards testing if this is a seached for card
|
|
//
|
|
|
|
lMoreReaders = FirstReader(&ReaderInfo);
|
|
while (SCARD_NO_MORE_READERS != lMoreReaders)
|
|
{
|
|
// Check card search status
|
|
if((ReaderInfo.fCardLookup) && (ReaderInfo.fChecked))
|
|
{
|
|
// We've found a card being searched for...Update
|
|
cMatches++;
|
|
|
|
// Save the index of this card
|
|
if (!fIndexStored)
|
|
{
|
|
dwIndex = ReaderInfo.dwInternalIndex;
|
|
fIndexStored = TRUE;
|
|
}
|
|
}
|
|
|
|
// Must clean up CTextString members before calling again
|
|
ReaderInfo.sReaderName.Clear();
|
|
ReaderInfo.sCardName.Clear();
|
|
|
|
// Get Next struct
|
|
lMoreReaders = NextReader( &ReaderInfo );
|
|
}
|
|
|
|
// Package for return
|
|
*pcMatches = cMatches;
|
|
*pdwIndex = dwIndex;
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("Search"), lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("Search"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
InitializeAllPossibleCardNames:
|
|
|
|
Stores all known card names matching the ATRs of the cardnames provided by
|
|
the OPENCARDNAME struct to search for.
|
|
*/
|
|
void CSCardEnv::InitializeAllPossibleCardNames( void )
|
|
{
|
|
LPCSTR szCards = NULL;
|
|
LONG lResult = SCARD_S_SUCCESS;
|
|
CBuffer bfAtr, bfAtrMask, bfInterfaces, bfProvider;
|
|
|
|
if (0 == MStringCount(m_strCardNames))
|
|
{
|
|
// No card names to check
|
|
m_strAllPossibleCardNames = m_strCardNames;
|
|
return;
|
|
}
|
|
|
|
szCards = m_strCardNames;
|
|
|
|
szCards = FirstString(szCards);
|
|
while (szCards != NULL)
|
|
{
|
|
//
|
|
// get all possible names for this card's ATR
|
|
//
|
|
|
|
if (! GetCardInfo(
|
|
SCARD_SCOPE_USER,
|
|
szCards,
|
|
&bfAtr,
|
|
&bfAtrMask,
|
|
&bfInterfaces,
|
|
&bfProvider ) )
|
|
{
|
|
// it's weird that this failed, but assume that the name is still OK
|
|
m_strAllPossibleCardNames += szCards;
|
|
}
|
|
else
|
|
{
|
|
LPTSTR szListCards = NULL;
|
|
DWORD dwCards = SCARD_AUTOALLOCATE;
|
|
|
|
lResult = SCardListCards(
|
|
m_hContext,
|
|
bfAtr,
|
|
NULL,
|
|
0,
|
|
(LPTSTR)&szListCards,
|
|
&dwCards);
|
|
|
|
if (SCARD_S_SUCCESS == lResult)
|
|
{
|
|
// append them to the list of all possible card names
|
|
m_strAllPossibleCardNames += szListCards;
|
|
}
|
|
else
|
|
{
|
|
// it's weird that this failed, but assume that the name is still OK
|
|
m_strAllPossibleCardNames += szCards;
|
|
}
|
|
|
|
if (NULL != szListCards)
|
|
{
|
|
SCardFreeMemory(m_hContext, (PVOID)szListCards);
|
|
}
|
|
}
|
|
|
|
szCards = NextString(szCards);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG SetOCN:
|
|
|
|
Stores the user OpenCardName info in the encapsulated data for UNICODE and
|
|
ANSI.
|
|
|
|
Arguments:
|
|
|
|
LPOPENCARDNAMEA - pointer to ANSI Open card name data.
|
|
LPOPENCARDNAMEW - pointer to UNICODE Open card name data.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/28/98 code cleanup, use charset-generic m_OCN,
|
|
move EnableUI code to separate function
|
|
|
|
--*/
|
|
LONG CSCardEnv::SetOCN(LPOPENCARDNAMEA pOCNA)
|
|
{
|
|
// Locals
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
int cMatches = 0;
|
|
DWORD dwIndex = 0;
|
|
|
|
try
|
|
{
|
|
// Check params
|
|
if(NULL == pOCNA)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
if( pOCNA->dwStructSize != sizeof (OPENCARDNAMEA) )
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
|
|
// TODO: ?? remove this test when Interfaces search is implemented ??
|
|
if( (pOCNA->rgguidInterfaces != NULL) || (pOCNA->cguidInterfaces != 0) )
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE; // NYI
|
|
}
|
|
|
|
//
|
|
// Set UNICODE-specific members to NULL!
|
|
//
|
|
|
|
m_pOCNW = NULL;
|
|
m_lpfnConnectW = NULL;
|
|
|
|
//
|
|
// Set appropriate charset-correct member, and copy to charset-generic
|
|
//
|
|
|
|
m_pOCNA = pOCNA;
|
|
|
|
m_hwndOwner = m_pOCNA->hwndOwner;
|
|
m_hContext = m_pOCNA->hSCardContext;
|
|
m_strCardNames = m_pOCNA->lpstrCardNames;
|
|
m_rgguidInterfaces = m_pOCNA->rgguidInterfaces;
|
|
m_cguidInterfaces = m_pOCNA->cguidInterfaces;
|
|
m_strReader = m_pOCNA->lpstrRdr;
|
|
m_strCard = m_pOCNA->lpstrCard;
|
|
m_strTitle = m_pOCNA->lpstrTitle;
|
|
m_dwFlags = m_pOCNA->dwFlags;
|
|
m_pvUserData = m_pOCNA->pvUserData;
|
|
m_dwShareMode = m_pOCNA->dwShareMode;
|
|
m_dwPreferredProtocols = m_pOCNA->dwPreferredProtocols;
|
|
m_dwActiveProtocol = m_pOCNA->dwActiveProtocol;
|
|
m_lpfnConnectA = m_pOCNA->lpfnConnect;
|
|
m_lpfnCheck = m_pOCNA->lpfnCheck;
|
|
m_lpfnDisconnect = m_pOCNA->lpfnDisconnect;
|
|
m_lpUserData = m_pOCNA->pvUserData;
|
|
m_hCardHandle = m_pOCNA->hCardHandle;
|
|
|
|
// special case: lpstrGroupNames==NULL -> use default
|
|
if (NULL != m_pOCNA->lpstrGroupNames)
|
|
{
|
|
m_strGroupNames = m_pOCNA->lpstrGroupNames;
|
|
}
|
|
else
|
|
{
|
|
m_strGroupNames = "SCard$DefaultReaders";
|
|
}
|
|
|
|
InitializeAllPossibleCardNames();
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("SetOCN - ANSI"),lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG)SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("SetOCN - ANSI"));
|
|
}
|
|
|
|
|
|
// Release memory if required
|
|
RemoveReaders();
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
// UNICODE
|
|
LONG CSCardEnv::SetOCN(LPOPENCARDNAMEW pOCNW)
|
|
{
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
|
|
try
|
|
{
|
|
// Check params
|
|
if (NULL == pOCNW)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
if (pOCNW->dwStructSize != sizeof(OPENCARDNAMEW) )
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
if ((pOCNW->rgguidInterfaces != NULL) || (pOCNW->cguidInterfaces != 0))
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE; // NYI
|
|
}
|
|
|
|
//
|
|
// Set ANSI-specific members to NULL!
|
|
//
|
|
|
|
m_pOCNA = NULL;
|
|
m_lpfnConnectA = NULL;
|
|
|
|
//
|
|
// Set appropriate charset-correct member, and copy to charset-generic
|
|
//
|
|
|
|
m_pOCNW = pOCNW;
|
|
|
|
m_hwndOwner = m_pOCNW->hwndOwner;
|
|
m_hContext = m_pOCNW->hSCardContext;
|
|
m_strCardNames = m_pOCNW->lpstrCardNames;
|
|
m_rgguidInterfaces = m_pOCNW->rgguidInterfaces;
|
|
m_cguidInterfaces = m_pOCNW->cguidInterfaces;
|
|
m_strReader = m_pOCNW->lpstrRdr;
|
|
m_strCard = m_pOCNW->lpstrCard;
|
|
m_strTitle = m_pOCNW->lpstrTitle;
|
|
m_dwFlags = m_pOCNW->dwFlags;
|
|
m_pvUserData = m_pOCNW->pvUserData;
|
|
m_dwShareMode = m_pOCNW->dwShareMode;
|
|
m_dwPreferredProtocols = m_pOCNW->dwPreferredProtocols;
|
|
m_dwActiveProtocol = m_pOCNW->dwActiveProtocol;
|
|
m_lpfnConnectW = m_pOCNW->lpfnConnect;
|
|
m_lpfnCheck = m_pOCNW->lpfnCheck;
|
|
m_lpfnDisconnect = m_pOCNW->lpfnDisconnect;
|
|
m_lpUserData = m_pOCNW->pvUserData;
|
|
m_hCardHandle = m_pOCNW->hCardHandle;
|
|
|
|
// special case: lpstrGroupNames=="" -> use default
|
|
if (NULL != m_pOCNW->lpstrGroupNames && 0 != *(m_pOCNW->lpstrGroupNames))
|
|
{
|
|
m_strGroupNames = m_pOCNW->lpstrGroupNames;
|
|
}
|
|
else
|
|
{
|
|
m_strGroupNames = L"SCard$DefaultReaders";
|
|
}
|
|
|
|
InitializeAllPossibleCardNames();
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("SetOCN - UNICODE"),lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("SetOCN - UNICODE"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG NoUISearch:
|
|
|
|
If the user has not set SC_DLG_FORCE_UI, perform a search for all
|
|
possible cards. If only one card is the result, then the search has
|
|
succeeded and no UI is necessary.
|
|
|
|
|
|
Arguments:
|
|
|
|
BOOL* pfEnableUI.
|
|
|
|
Return Value:
|
|
|
|
A LONG indicating the success of the search. If SC_DLG_FORCE_UI is set,
|
|
pfEnableUI is always TRUE; if SC_DLG_NO_UI is set, the pfEnableUI is always
|
|
FALSE.
|
|
|
|
Author:
|
|
|
|
Amanda Matlosz 02/01/1998
|
|
|
|
Revisions:
|
|
|
|
--*/
|
|
LONG CSCardEnv::NoUISearch(BOOL* pfEnableUI)
|
|
{
|
|
//
|
|
// Must search so we can check all the cards, even if we have to show UI
|
|
//
|
|
|
|
*pfEnableUI = FALSE;
|
|
long lResult = SCARD_S_SUCCESS;
|
|
int cMatches = 0;
|
|
DWORD dwIndex = 0;
|
|
|
|
try
|
|
{
|
|
// Search for the card
|
|
lResult = Search(&cMatches, &dwIndex);
|
|
if(SCARDFAILED(lResult))
|
|
{
|
|
throw lResult;
|
|
}
|
|
|
|
// Determine if UI should be used...
|
|
|
|
if(m_dwFlags & SC_DLG_FORCE_UI)
|
|
{
|
|
*pfEnableUI = TRUE;
|
|
}
|
|
else if((m_dwFlags & SC_DLG_MINIMAL_UI) && (cMatches != 1))
|
|
{
|
|
*pfEnableUI = TRUE;
|
|
}
|
|
|
|
// Connect to the reader if 1 matching card found
|
|
|
|
if(cMatches == 1)
|
|
{
|
|
lResult = ConnectToReader(dwIndex);
|
|
if (SCARDFAILED(lResult))
|
|
{
|
|
*pfEnableUI = TRUE; // an error occurred with the reader? eep.
|
|
throw lResult;
|
|
}
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
TRACE_CATCH(_T("NoUISearch"),lErr);
|
|
}
|
|
catch(...)
|
|
{
|
|
TRACE_CATCH_UNKNOWN(_T("NoUISearch"));
|
|
lResult = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
|
|
// Release memory if required
|
|
RemoveReaders();
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG BuildReaderArray:
|
|
|
|
Builds an array of CSCardReader objects. 1 object per reader.
|
|
|
|
Arguments:
|
|
|
|
szReaderNames - an LPTSTR (A/W) multistring containing a list of readers.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action.
|
|
See the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/5/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/29/98 added unicode support
|
|
--*/
|
|
LONG CSCardEnv::BuildReaderArray( LPTSTR szReaderNames )
|
|
{
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
LPCTSTR szReaderName = szReaderNames;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
|
|
try
|
|
{
|
|
// Check Params
|
|
if (NULL == szReaderNames || NULL == *szReaderNames)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_VALUE;
|
|
}
|
|
|
|
//
|
|
// Store a reader object in the array for each reader
|
|
//
|
|
|
|
szReaderName = FirstString( szReaderName );
|
|
while (NULL != szReaderName)
|
|
{
|
|
pReaderState = new CSCardReaderState;
|
|
if (NULL == pReaderState)
|
|
{
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
}
|
|
|
|
pReaderState->SetContext(m_hContext);
|
|
pReaderState->StoreName(szReaderName);
|
|
|
|
if (NULL != m_pOCNA)
|
|
{
|
|
lReturn = pReaderState->SetReaderState( m_lpfnConnectA,
|
|
m_lpfnCheck,
|
|
m_lpfnDisconnect,
|
|
m_lpUserData);
|
|
}
|
|
else if (NULL != m_pOCNW)
|
|
{
|
|
lReturn = pReaderState->SetReaderState( m_lpfnConnectW,
|
|
m_lpfnCheck,
|
|
m_lpfnDisconnect,
|
|
m_lpUserData);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Either m_pOCNA or m_pOCNW *must* be valid!
|
|
throw (long)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
|
|
// Check if card inserted and set flag if it contains the search card
|
|
if (pReaderState->IsCardInserted())
|
|
{
|
|
// TODO: ?? fix readerstate so it's nicer w/ W ??
|
|
lReturn = pReaderState->CheckCard(m_strAllPossibleCardNames);
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
}
|
|
|
|
m_rgReaders.Add(pReaderState);
|
|
szReaderName = NextString(szReaderName);
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("BuildReaderArray"), lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("BuildReaderArray"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG ConnectInternal:
|
|
|
|
Connect internally to the reader
|
|
|
|
Arguments:
|
|
|
|
dwSelectedIndex - index used to select which reader to connect to.
|
|
pHandle - pointer to an SCARDHANDLE that will be set on return.
|
|
dwShareMode - contains share mode to use when connecting
|
|
dwProtocols - contains requested protocol(s) to use when connecting
|
|
pdwActiveProtocl - returns active protocol on successful connection
|
|
szReaderName - returned name of the reader being connected
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/11/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/30/98 code cleanup
|
|
--*/
|
|
LONG CSCardEnv::ConnectInternal( DWORD dwSelectedReader,
|
|
SCARDHANDLE *pHandle,
|
|
DWORD dwShareMode,
|
|
DWORD dwProtocols,
|
|
DWORD *pdwActiveProtocol,
|
|
CTextString *pszReaderName,//=NULL
|
|
CTextString *pszCardName//=NULL
|
|
)
|
|
{
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
|
|
try
|
|
{
|
|
// Check Params
|
|
if (NULL == pHandle)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
if (NULL == pdwActiveProtocol)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
if (dwSelectedReader >= (DWORD)NumberOfReaders())
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!IsContextValid())
|
|
{
|
|
throw (LONG)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Clear handle
|
|
*pHandle = NULL;
|
|
|
|
// get the object & connect
|
|
pReaderState = m_rgReaders[dwSelectedReader];
|
|
lReturn = pReaderState->Connect(pHandle,
|
|
dwShareMode,
|
|
dwProtocols,
|
|
pdwActiveProtocol,
|
|
pszReaderName,
|
|
pszCardName);
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw lReturn;
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("ConnectInternal"), lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("ConnectInternal"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG ConnectUser:
|
|
|
|
Connect to the reader using user supplied callback
|
|
|
|
Arguments:
|
|
|
|
dwSelectedReader - index to reader to connect
|
|
lpfnConnect - user supplied callback function.
|
|
pHandle - pointer to an SCARDHANDLE that will be set on return.
|
|
lpUserData - pointer to user data.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/11/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1//30/98 code cleanup
|
|
|
|
--*/
|
|
LONG CSCardEnv::ConnectUser( DWORD dwSelectedReader,
|
|
SCARDHANDLE *pHandle,
|
|
CTextString *pszReaderName, //=NULL
|
|
CTextString *pszCardName //=NULL
|
|
)
|
|
{
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
|
|
try
|
|
{
|
|
// Check Params
|
|
if(NULL == pHandle)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
if(dwSelectedReader >= (DWORD)NumberOfReaders())
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!IsContextValid())
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Clear handle
|
|
*pHandle = NULL;
|
|
|
|
// get the reader object & connect
|
|
pReaderState = m_rgReaders[dwSelectedReader];
|
|
lReturn = pReaderState->UserConnect(pHandle,
|
|
pszReaderName,
|
|
pszCardName);
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("ConnectUser"), lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("ConnectUser"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
void GetCardList:
|
|
|
|
Returns a multistring containing the list cards being searched for.
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR* - pointer->pointer for the list
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/7/1997
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
void CSCardEnv::GetCardList( LPCTSTR* pszCardList )
|
|
{
|
|
// Check params
|
|
if (NULL != pszCardList)
|
|
{
|
|
*pszCardList = m_strCardNames;
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
BOOL IsCallbackValid:
|
|
|
|
This routine checks the user callback functions.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if calbacks are valid. FALSE otherwise.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/15/1997
|
|
|
|
--*/
|
|
BOOL CSCardEnv::IsCallbackValid ( void )
|
|
{
|
|
BOOL fValid = FALSE;
|
|
|
|
fValid = ((NULL != m_lpfnConnectA || NULL != m_lpfnConnectW) &&
|
|
(m_lpfnCheck != NULL) && (m_lpfnDisconnect != NULL));
|
|
|
|
return fValid;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG CreateReaderStateArray:
|
|
|
|
Returns an array of SCARD_READERSTATE structs.
|
|
|
|
Arguments:
|
|
|
|
LPSCARD_READERSTATE* - pointer->pointer to an SCARDREADERSTATE struct
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/7/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/30/98 added unicode support, code cleanup
|
|
|
|
--*/
|
|
LONG CSCardEnv::CreateReaderStateArray( LPSCARD_READERSTATE* prgReaderStates )
|
|
{
|
|
// Locals
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
LPSCARD_READERSTATE rgReader;
|
|
|
|
try
|
|
{
|
|
// Check params, etc.
|
|
if (prgReaderStates == NULL)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!IsArrayValid())
|
|
{
|
|
throw (LONG)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Clean up the destination
|
|
DeleteReaderStateArray(prgReaderStates);
|
|
|
|
// Build a temp array, set the destination array
|
|
rgReader = new SCARD_READERSTATE[(size_t)m_rgReaders.GetSize()];
|
|
if (rgReader == NULL)
|
|
{
|
|
throw (LONG)SCARD_E_NO_MEMORY;
|
|
}
|
|
|
|
for (int ix =0; ix < m_rgReaders.GetSize(); ix++)
|
|
{
|
|
pReaderState = m_rgReaders[ix];
|
|
pReaderState->GetReaderState(&(rgReader[ix])); // TODO: ?? looks funny ??
|
|
}
|
|
|
|
// Asign the pointer
|
|
*prgReaderStates = rgReader;
|
|
}
|
|
|
|
catch (LONG err) {
|
|
lReturn = err;
|
|
TRACE_CATCH(_T("GetReaderStateArray"),err);
|
|
}
|
|
|
|
catch (...) {
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("GetReaderStateArray"));
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
void DeleteReaderStateArray:
|
|
|
|
Frees the memory associated with a previously created SCARD_READERSTATE
|
|
array.
|
|
|
|
Arguments:
|
|
|
|
rgReaderStateArray - pointer to the array.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/7/1997
|
|
|
|
--*/
|
|
void CSCardEnv::DeleteReaderStateArray(LPSCARD_READERSTATE* prgReaderStateArray)
|
|
{
|
|
if (NULL != *prgReaderStateArray)
|
|
{
|
|
delete [] (*prgReaderStateArray);
|
|
*prgReaderStateArray = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG FirstReader:
|
|
|
|
Retrieves information on the first reader in the reader array.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
A return value of SCARD_NO_MORE_READERS means no readers available.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/7/1997
|
|
|
|
Notes:
|
|
|
|
1. This routine 0's the memory pointed to by pReaderInfo. The calling app should be
|
|
careful (i.e. clean up LSCARD_READERINFO struct) before each call to this routine.
|
|
|
|
--*/
|
|
LONG CSCardEnv::FirstReader(LPSCARD_READERINFO pReaderInfo)
|
|
{
|
|
// Locals
|
|
LONG lResult = SCARD_S_SUCCESS;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
|
|
try
|
|
{
|
|
if (NULL == pReaderInfo)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Give up if there are no readers
|
|
if (m_rgReaders.GetSize() <= 0)
|
|
{
|
|
throw (LONG)SCARD_NO_MORE_READERS;
|
|
}
|
|
|
|
// Get the first reader
|
|
m_dwReaderIndex = 0;
|
|
pReaderState = m_rgReaders[m_dwReaderIndex];
|
|
if (!pReaderState->IsStateValid())
|
|
{
|
|
throw (LONG)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Prepare the return struct
|
|
::ZeroMemory( (LPVOID)pReaderInfo, (DWORD)sizeof(SCARD_READERINFO));
|
|
lResult = pReaderState->GetReaderInfo(pReaderInfo);
|
|
if (SCARDFAILED(lResult))
|
|
{
|
|
throw (lResult);
|
|
}
|
|
// Update the index
|
|
pReaderInfo->dwInternalIndex = m_dwReaderIndex;
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lResult = lErr;
|
|
TRACE_CATCH(_T("FirstReader"), lResult);
|
|
}
|
|
catch(...)
|
|
{
|
|
lResult = SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("FirstReader"));
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG NextReader:
|
|
|
|
Retrieves information on the next reader (using internal index) in the
|
|
reader array.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action.
|
|
See the Smartcard header files for additional information.
|
|
|
|
A return value of SCARD_NO_MORE_READERS means no readers available.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/7/1997
|
|
|
|
Notes:
|
|
|
|
1. This routine 0's the memory pointed to by pReaderInfo. The calling app should be
|
|
careful (i.e. clean up LSCARD_READERINFO struct) before each call to this routine.
|
|
|
|
--*/
|
|
LONG CSCardEnv::NextReader(LPSCARD_READERINFO pReaderInfo)
|
|
{
|
|
LONG lResult = SCARD_S_SUCCESS;
|
|
CSCardReaderState* pReaderState = NULL;
|
|
DWORD dwTotalReaders = (DWORD)m_rgReaders.GetUpperBound();
|
|
|
|
try
|
|
{
|
|
// Check params
|
|
if (NULL == pReaderInfo)
|
|
{
|
|
throw (LONG)SCARD_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Is there a next reader to retrieve?
|
|
m_dwReaderIndex++;
|
|
if (m_dwReaderIndex > dwTotalReaders)
|
|
{
|
|
throw (LONG)SCARD_NO_MORE_READERS;
|
|
}
|
|
|
|
// Fetch the reader state from our array
|
|
pReaderState = m_rgReaders[m_dwReaderIndex];
|
|
if (!pReaderState->IsStateValid())
|
|
{
|
|
throw (LONG)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Setup the struct to return
|
|
|
|
::ZeroMemory((LPVOID)pReaderInfo, (DWORD)sizeof(SCARD_READERINFO));
|
|
lResult = pReaderState->GetReaderInfo(pReaderInfo);
|
|
if (SCARDFAILED(lResult))
|
|
{
|
|
throw (lResult);
|
|
}
|
|
|
|
// Update the index
|
|
pReaderInfo->dwInternalIndex = m_dwReaderIndex;
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lResult = lErr;
|
|
TRACE_CATCH(_T("NextReader"), lResult);
|
|
}
|
|
catch(...)
|
|
{
|
|
lResult = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("NextReader"));
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
void RemoveReaderArray:
|
|
|
|
Deletes the array of CSCardReader objects.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/5/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/29/98 code cleanup
|
|
|
|
--*/
|
|
void CSCardEnv::RemoveReaders( void )
|
|
{
|
|
if (IsArrayValid())
|
|
{
|
|
// Delete the attached reader objects
|
|
for (int ix=0; ix <= m_rgReaders.GetUpperBound(); ix++)
|
|
{
|
|
delete m_rgReaders[ix];
|
|
}
|
|
|
|
// Free array memory
|
|
m_rgReaders.RemoveAll();
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
void SetContext:
|
|
|
|
Sets the card context, performs no checking.
|
|
|
|
Arguments:
|
|
|
|
hContext - card context handle
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
--*/
|
|
void CSCardEnv::SetContext(SCARDCONTEXT hContext)
|
|
{
|
|
m_hContext = hContext;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
LONG UpdateReaders:
|
|
|
|
Updates the reader array using m_GroupName member.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
A LONG value indicating the status of the requested action. Please
|
|
see the Smartcard header files for additional information.
|
|
|
|
Author:
|
|
|
|
Chris Dudley 3/3/1997
|
|
|
|
Revisions:
|
|
|
|
Amanda Matlosz 1/29/98 added Unicode support
|
|
|
|
Note:
|
|
|
|
--*/
|
|
LONG CSCardEnv::UpdateReaders( void )
|
|
{
|
|
TRACE("\tCSCardEnv::UpdateReaders\r\n"); // TODO: ?? remove this ??
|
|
|
|
LONG lReturn = SCARD_S_SUCCESS;
|
|
LPTSTR szReaderNames = NULL;
|
|
DWORD dwNameLength = SCARD_AUTOALLOCATE;
|
|
|
|
if (!IsContextValid())
|
|
{
|
|
TRACE_CODE(_T("UpdateReaders"),E_FAIL);
|
|
return (LONG)E_FAIL;
|
|
}
|
|
|
|
RemoveReaders(); // deletes current array if required
|
|
|
|
try
|
|
{
|
|
// Call Resource manager for list of readers
|
|
lReturn = SCardListReaders(m_hContext,
|
|
m_strGroupNames,
|
|
(LPTSTR)&szReaderNames,
|
|
&dwNameLength);
|
|
|
|
if(SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
|
|
// SCardListReaders will succeed in a PnP world even if there are currently no
|
|
// readers for this group.
|
|
_ASSERTE(NULL != szReaderNames && NULL != *szReaderNames);
|
|
|
|
lReturn = BuildReaderArray(szReaderNames);
|
|
if (SCARDFAILED(lReturn))
|
|
{
|
|
throw (lReturn);
|
|
}
|
|
}
|
|
catch(LONG lErr)
|
|
{
|
|
lReturn = lErr;
|
|
TRACE_CATCH(_T("UpdateReaders"),lReturn);
|
|
}
|
|
catch(...)
|
|
{
|
|
lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
|
|
TRACE_CATCH_UNKNOWN(_T("UpdateReaders"));
|
|
}
|
|
|
|
// Clean Up
|
|
if(NULL != szReaderNames)
|
|
{
|
|
SCardFreeMemory(m_hContext, (LPVOID)szReaderNames);
|
|
}
|
|
|
|
return lReturn;
|
|
}
|
|
|