|
|
/*++
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; }
|