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.
 
 
 
 
 
 

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;
}