mirror of https://github.com/tongzx/nt5src
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
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
|