Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

352 lines
11 KiB

// CardCtx.cpp -- Card ConTeXt class definition
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
// 1999. This computer program includes Confidential, Proprietary
// Information and is a Trade Secret of Schlumberger Technology Corp. All
// use, disclosure, and/or reproduction is prohibited unless authorized
// in writing. All Rights Reserved.
// Don't allow the min & max macros in WINDEF.H to be defined so the
// min/max methods declared in limits are accessible.
#define NOMINMAX
#include "NoWarning.h"
#include "ForceLib.h"
#include <limits>
#include <algorithm>
#include <numeric>
#include <scuOsExc.h>
#include <scuCast.h>
#include "HCardCtx.h"
#include "LoginCtx.h"
#include "Procedural.h"
#include "HAdptvCntr.h"
#include "Guarded.h"
#include <scarderr.h> // always last for now
using namespace std;
using namespace cci;
/////////////////////////// LOCAL/HELPER /////////////////////////////////
namespace
{
class StaleContainerKeyAccumulator
: public binary_function<vector<AdaptiveContainerRegistrar::EnrolleeType>,
AdaptiveContainerRegistrar::RegistryType::CollectionType::value_type,
vector<AdaptiveContainerRegistrar::EnrolleeType> >
{
public:
explicit
StaleContainerKeyAccumulator(HCardContext const &rhcardctx)
: m_rhcardctx(rhcardctx)
{}
result_type
operator()(first_argument_type &rvStaleCntrs,
second_argument_type const &rvt) const
{
if (rvt.second->CardContext(false) == m_rhcardctx)
rvStaleCntrs.push_back(rvt.second);
return rvStaleCntrs;
}
private:
HCardContext const &m_rhcardctx;
};
void
ClearAdaptiveContainerCache(AdaptiveContainerRegistrar::EnrolleeType enrollee,
HCardContext hcardctx)
{
if (enrollee->CardContext(false) == hcardctx)
{
enrollee->ClearCache();
}
}
void
DeleteAdaptiveContainerCache(AdaptiveContainerRegistrar::EnrolleeType enrollee,
HCardContext hcardctx)
{
if (enrollee->CardContext(false) == hcardctx)
enrollee->DeleteCache();
}
void
DeactivateLoginContext(auto_ptr<LoginContext> const &raplc)
{
raplc->Deactivate();
}
}
/////////////////////////// PUBLIC /////////////////////////////////
// Types
// C'tors/D'tors
CardContext::CardContext(std::string const &rsReaderName)
: RCObject(),
Lockable(),
Securable(),
CachingObject(),
CardContextRegistrar(rsReaderName),
m_stkapGuards(),
m_aptwCard(),
m_cSecurers(0),
m_card(CCard(rsReaderName)),
m_mloginctx(),
m_mrkLastWrite(iop::CMarker::WriteMarker),
m_mrkLastChvChange(iop::CMarker::PinMarker)
{}
CardContext::~CardContext() throw()
{}
// Operators
// Operations
void
CardContext::ClearLogin(LoginIdentity const &rlid)
{
Guarded<CardContext *> guard(this);
auto_ptr<LoginContext> &raplc = m_mloginctx[rlid];
if (raplc.get())
raplc = auto_ptr<LoginContext>(0);
}
void
CardContext::Login(LoginIdentity const &rlid,
LoginTask &rlt,
bool fForceLogin)
{
Guarded<CardContext *> guard(this);
auto_ptr<LoginContext> &raplc = m_mloginctx[rlid];
if (!raplc.get())
raplc = auto_ptr<LoginContext>(new LoginContext(HCardContext(this),
rlid));
if (fForceLogin || !raplc->IsActive())
raplc->Activate(rlt);
}
void
CardContext::Logout()
{
ForEachMappedValue(m_mloginctx.begin(), m_mloginctx.end(),
DeactivateLoginContext);
}
// Access
CCard
CardContext::Card()
{
return m_card;
}
// Predicates
// Static Variables
/////////////////////////// PROTECTED /////////////////////////////////
// C'tors/D'tors
// Operators
// Operations
void
CardContext::DiscardHook()
{
DeleteCache();
RemoveReference();
}
CardContext *
CardContext::DoInstantiation(std::string const &rsReaderName)
{
return new CardContext(rsReaderName);
}
void
CardContext::EnrollHook()
{
AddReference();
}
// Access
// Predicates
bool
CardContext::KeepEnrolled()
{
return (m_card && m_card->IsAvailable())
? true
: false;
}
// Static Variables
/////////////////////////// PRIVATE /////////////////////////////////
// C'tors/D'tors
// Operators
// Operations
void
CardContext::Abandon()
{
// Simplifying assumptions: (1) Abandon is only called by the
// Secured destructor, (2) once the object is constructed, Secure
// and Abandon are the only routines that access the count, and
// (3) Abandon is called by a thread within the scope of a Retain
// (e.g. using Retained) which the Secured class enforces.
// Because of (1) and (2), an underflow check on the count is not
// necessary since Secure will have already been called. Because
// of (3), protection against race conditions accessing count
// isn't necessary since Retain acts as a lock.
--m_cSecurers;
if (0 == m_cSecurers)
Logout();
}
// Optionally clear the cached info
void
CardContext::ClearCache()
{
if (Card()->Marker(iop::CMarker::WriteMarker) != m_mrkLastWrite)
{
ForEachEnrollee(AdaptiveContainerRegistrar::Registry(),
ProcedureBind2nd(PointerProcedure(ClearAdaptiveContainerCache),
HCardContext(this)));
Card()->InvalidateCache();
}
if (Card()->Marker(iop::CMarker::PinMarker) != m_mrkLastChvChange)
m_mloginctx.clear();
}
// Delete any cached info, never to be refreshed
void
CardContext::DeleteCache()
{
m_mloginctx.clear();
Guarded<Lockable *> guard(&AdaptiveContainerRegistrar::Registry()); // serialize registry access
AdaptiveContainerRegistrar::ConstRegistryType &rRegistry =
AdaptiveContainerRegistrar::Registry();
AdaptiveContainerRegistrar::ConstRegistryType::CollectionType
&rcollection = rRegistry();
HCardContext hcardctx(this);
// Any containers associated with this card should be marked stale
// now because on Whistler (W2K Upgrade) trying to access them
// later when another context has a begin transaction on the same
// reader will cause a wait. On earlier platforms, the RM would
// return an error (e.g. card removed) when attempting to access
// the container.
vector<AdaptiveContainerRegistrar::EnrolleeType>
vStaleCntrs(accumulate(rcollection.begin(), rcollection.end(),
vector<AdaptiveContainerRegistrar::EnrolleeType>(),
StaleContainerKeyAccumulator(hcardctx)));
for (vector<AdaptiveContainerRegistrar::EnrolleeType>::iterator iCurrent(vStaleCntrs.begin());
iCurrent != vStaleCntrs.end(); ++iCurrent)
{
(*iCurrent)->NullifyCard();
}
}
void
CardContext::Relinquish()
{
// Simplifying assumptions: (1) Relinquish is only called by the
// Retained destructor and (2) once the object is constructed,
// Retain and Relinquish are the only routines that access the
// m_stkapGuards and m_aptwCard. Because of (1) and (2), an
// underflow check on m_stkRetainedCardContexts is not necessary
// since Retain will have already been called.
// Protect against exceptions by fist assigning the newly acquired
// "locks" to temporary variables until all the actions necessary
// are successfully completed before assigning transfering
// ownership of the locks to the associated member variables.
auto_ptr<Guarded<CardContext *> > apgcardctx(m_stkapGuards.front());
m_stkapGuards.pop_front();
if (m_stkapGuards.empty())
{
try
{
m_aptwCard = auto_ptr<CTransactionWrap>(0);
}
catch (...)
{
}
// Notify any changes to this card during this transaction
// before letting someone else have access.
UpdateMarkers();
}
}
void
CardContext::Retain()
{
// Simplifying assumptions: (1) Retain is only called by the
// Retained constructor and (2) once the object is constructed,
// Retain and Relinquish are the only routines that access the
// m_stkapGuards and m_aptwCard. Because of (1) and (2), an
// underflow check on m_stkRetainedCardContexts is not necessary
// since Retain will have already been called.
// Protect against exceptions by fist assigning the newly acquired
// "locks" to temporary variables until all the actions necessary
// are successfully completed before assigning transfering
// ownership of the locks to the associated member variables.
auto_ptr<Guarded<CardContext *> > apgcardctx(new Guarded<CardContext *>(this));
auto_ptr<CTransactionWrap> aptwCard;
if (m_stkapGuards.empty())
{
aptwCard = auto_ptr<CTransactionWrap>(new CTransactionWrap(m_card));
ClearCache();
}
m_stkapGuards.push_front(apgcardctx);
if (aptwCard.get())
m_aptwCard = aptwCard;
}
void
CardContext::UpdateMarkers()
{
m_mrkLastWrite = Card()->Marker(iop::CMarker::WriteMarker);
m_mrkLastChvChange = Card()->Marker(iop::CMarker::PinMarker);
}
void
CardContext::Secure()
{
// Simplifying assumptions: (1) Secure is always called by a thread
// within the scope of a Retain (e.g. using Retained). The
// Secured template enforces this allowing Retain to act as a lock
// to prevent race conditions updating m_cSecurers. (2) Once the
// object is constructed, Secure and Abandon are the only routines
// that access m_cSecurers.
if (0 >= (m_cSecurers + 1))
throw scu::OsException(ERROR_INVALID_HANDLE_STATE);
++m_cSecurers;
}
// Access
// Predicates
// Static Variables