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

  1. // CardCtx.cpp -- Card ConTeXt class definition
  2. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  3. // 1999. This computer program includes Confidential, Proprietary
  4. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  5. // use, disclosure, and/or reproduction is prohibited unless authorized
  6. // in writing. All Rights Reserved.
  7. // Don't allow the min & max macros in WINDEF.H to be defined so the
  8. // min/max methods declared in limits are accessible.
  9. #define NOMINMAX
  10. #include "NoWarning.h"
  11. #include "ForceLib.h"
  12. #include <limits>
  13. #include <algorithm>
  14. #include <numeric>
  15. #include <scuOsExc.h>
  16. #include <scuCast.h>
  17. #include "HCardCtx.h"
  18. #include "LoginCtx.h"
  19. #include "Procedural.h"
  20. #include "HAdptvCntr.h"
  21. #include "Guarded.h"
  22. #include <scarderr.h> // always last for now
  23. using namespace std;
  24. using namespace cci;
  25. /////////////////////////// LOCAL/HELPER /////////////////////////////////
  26. namespace
  27. {
  28. class StaleContainerKeyAccumulator
  29. : public binary_function<vector<AdaptiveContainerRegistrar::EnrolleeType>,
  30. AdaptiveContainerRegistrar::RegistryType::CollectionType::value_type,
  31. vector<AdaptiveContainerRegistrar::EnrolleeType> >
  32. {
  33. public:
  34. explicit
  35. StaleContainerKeyAccumulator(HCardContext const &rhcardctx)
  36. : m_rhcardctx(rhcardctx)
  37. {}
  38. result_type
  39. operator()(first_argument_type &rvStaleCntrs,
  40. second_argument_type const &rvt) const
  41. {
  42. if (rvt.second->CardContext(false) == m_rhcardctx)
  43. rvStaleCntrs.push_back(rvt.second);
  44. return rvStaleCntrs;
  45. }
  46. private:
  47. HCardContext const &m_rhcardctx;
  48. };
  49. void
  50. ClearAdaptiveContainerCache(AdaptiveContainerRegistrar::EnrolleeType enrollee,
  51. HCardContext hcardctx)
  52. {
  53. if (enrollee->CardContext(false) == hcardctx)
  54. {
  55. enrollee->ClearCache();
  56. }
  57. }
  58. void
  59. DeleteAdaptiveContainerCache(AdaptiveContainerRegistrar::EnrolleeType enrollee,
  60. HCardContext hcardctx)
  61. {
  62. if (enrollee->CardContext(false) == hcardctx)
  63. enrollee->DeleteCache();
  64. }
  65. void
  66. DeactivateLoginContext(auto_ptr<LoginContext> const &raplc)
  67. {
  68. raplc->Deactivate();
  69. }
  70. }
  71. /////////////////////////// PUBLIC /////////////////////////////////
  72. // Types
  73. // C'tors/D'tors
  74. CardContext::CardContext(std::string const &rsReaderName)
  75. : RCObject(),
  76. Lockable(),
  77. Securable(),
  78. CachingObject(),
  79. CardContextRegistrar(rsReaderName),
  80. m_stkapGuards(),
  81. m_aptwCard(),
  82. m_cSecurers(0),
  83. m_card(CCard(rsReaderName)),
  84. m_mloginctx(),
  85. m_mrkLastWrite(iop::CMarker::WriteMarker),
  86. m_mrkLastChvChange(iop::CMarker::PinMarker)
  87. {}
  88. CardContext::~CardContext() throw()
  89. {}
  90. // Operators
  91. // Operations
  92. void
  93. CardContext::ClearLogin(LoginIdentity const &rlid)
  94. {
  95. Guarded<CardContext *> guard(this);
  96. auto_ptr<LoginContext> &raplc = m_mloginctx[rlid];
  97. if (raplc.get())
  98. raplc = auto_ptr<LoginContext>(0);
  99. }
  100. void
  101. CardContext::Login(LoginIdentity const &rlid,
  102. LoginTask &rlt,
  103. bool fForceLogin)
  104. {
  105. Guarded<CardContext *> guard(this);
  106. auto_ptr<LoginContext> &raplc = m_mloginctx[rlid];
  107. if (!raplc.get())
  108. raplc = auto_ptr<LoginContext>(new LoginContext(HCardContext(this),
  109. rlid));
  110. if (fForceLogin || !raplc->IsActive())
  111. raplc->Activate(rlt);
  112. }
  113. void
  114. CardContext::Logout()
  115. {
  116. ForEachMappedValue(m_mloginctx.begin(), m_mloginctx.end(),
  117. DeactivateLoginContext);
  118. }
  119. // Access
  120. CCard
  121. CardContext::Card()
  122. {
  123. return m_card;
  124. }
  125. // Predicates
  126. // Static Variables
  127. /////////////////////////// PROTECTED /////////////////////////////////
  128. // C'tors/D'tors
  129. // Operators
  130. // Operations
  131. void
  132. CardContext::DiscardHook()
  133. {
  134. DeleteCache();
  135. RemoveReference();
  136. }
  137. CardContext *
  138. CardContext::DoInstantiation(std::string const &rsReaderName)
  139. {
  140. return new CardContext(rsReaderName);
  141. }
  142. void
  143. CardContext::EnrollHook()
  144. {
  145. AddReference();
  146. }
  147. // Access
  148. // Predicates
  149. bool
  150. CardContext::KeepEnrolled()
  151. {
  152. return (m_card && m_card->IsAvailable())
  153. ? true
  154. : false;
  155. }
  156. // Static Variables
  157. /////////////////////////// PRIVATE /////////////////////////////////
  158. // C'tors/D'tors
  159. // Operators
  160. // Operations
  161. void
  162. CardContext::Abandon()
  163. {
  164. // Simplifying assumptions: (1) Abandon is only called by the
  165. // Secured destructor, (2) once the object is constructed, Secure
  166. // and Abandon are the only routines that access the count, and
  167. // (3) Abandon is called by a thread within the scope of a Retain
  168. // (e.g. using Retained) which the Secured class enforces.
  169. // Because of (1) and (2), an underflow check on the count is not
  170. // necessary since Secure will have already been called. Because
  171. // of (3), protection against race conditions accessing count
  172. // isn't necessary since Retain acts as a lock.
  173. --m_cSecurers;
  174. if (0 == m_cSecurers)
  175. Logout();
  176. }
  177. // Optionally clear the cached info
  178. void
  179. CardContext::ClearCache()
  180. {
  181. if (Card()->Marker(iop::CMarker::WriteMarker) != m_mrkLastWrite)
  182. {
  183. ForEachEnrollee(AdaptiveContainerRegistrar::Registry(),
  184. ProcedureBind2nd(PointerProcedure(ClearAdaptiveContainerCache),
  185. HCardContext(this)));
  186. Card()->InvalidateCache();
  187. }
  188. if (Card()->Marker(iop::CMarker::PinMarker) != m_mrkLastChvChange)
  189. m_mloginctx.clear();
  190. }
  191. // Delete any cached info, never to be refreshed
  192. void
  193. CardContext::DeleteCache()
  194. {
  195. m_mloginctx.clear();
  196. Guarded<Lockable *> guard(&AdaptiveContainerRegistrar::Registry()); // serialize registry access
  197. AdaptiveContainerRegistrar::ConstRegistryType &rRegistry =
  198. AdaptiveContainerRegistrar::Registry();
  199. AdaptiveContainerRegistrar::ConstRegistryType::CollectionType
  200. &rcollection = rRegistry();
  201. HCardContext hcardctx(this);
  202. // Any containers associated with this card should be marked stale
  203. // now because on Whistler (W2K Upgrade) trying to access them
  204. // later when another context has a begin transaction on the same
  205. // reader will cause a wait. On earlier platforms, the RM would
  206. // return an error (e.g. card removed) when attempting to access
  207. // the container.
  208. vector<AdaptiveContainerRegistrar::EnrolleeType>
  209. vStaleCntrs(accumulate(rcollection.begin(), rcollection.end(),
  210. vector<AdaptiveContainerRegistrar::EnrolleeType>(),
  211. StaleContainerKeyAccumulator(hcardctx)));
  212. for (vector<AdaptiveContainerRegistrar::EnrolleeType>::iterator iCurrent(vStaleCntrs.begin());
  213. iCurrent != vStaleCntrs.end(); ++iCurrent)
  214. {
  215. (*iCurrent)->NullifyCard();
  216. }
  217. }
  218. void
  219. CardContext::Relinquish()
  220. {
  221. // Simplifying assumptions: (1) Relinquish is only called by the
  222. // Retained destructor and (2) once the object is constructed,
  223. // Retain and Relinquish are the only routines that access the
  224. // m_stkapGuards and m_aptwCard. Because of (1) and (2), an
  225. // underflow check on m_stkRetainedCardContexts is not necessary
  226. // since Retain will have already been called.
  227. // Protect against exceptions by fist assigning the newly acquired
  228. // "locks" to temporary variables until all the actions necessary
  229. // are successfully completed before assigning transfering
  230. // ownership of the locks to the associated member variables.
  231. auto_ptr<Guarded<CardContext *> > apgcardctx(m_stkapGuards.front());
  232. m_stkapGuards.pop_front();
  233. if (m_stkapGuards.empty())
  234. {
  235. try
  236. {
  237. m_aptwCard = auto_ptr<CTransactionWrap>(0);
  238. }
  239. catch (...)
  240. {
  241. }
  242. // Notify any changes to this card during this transaction
  243. // before letting someone else have access.
  244. UpdateMarkers();
  245. }
  246. }
  247. void
  248. CardContext::Retain()
  249. {
  250. // Simplifying assumptions: (1) Retain is only called by the
  251. // Retained constructor and (2) once the object is constructed,
  252. // Retain and Relinquish are the only routines that access the
  253. // m_stkapGuards and m_aptwCard. Because of (1) and (2), an
  254. // underflow check on m_stkRetainedCardContexts is not necessary
  255. // since Retain will have already been called.
  256. // Protect against exceptions by fist assigning the newly acquired
  257. // "locks" to temporary variables until all the actions necessary
  258. // are successfully completed before assigning transfering
  259. // ownership of the locks to the associated member variables.
  260. auto_ptr<Guarded<CardContext *> > apgcardctx(new Guarded<CardContext *>(this));
  261. auto_ptr<CTransactionWrap> aptwCard;
  262. if (m_stkapGuards.empty())
  263. {
  264. aptwCard = auto_ptr<CTransactionWrap>(new CTransactionWrap(m_card));
  265. ClearCache();
  266. }
  267. m_stkapGuards.push_front(apgcardctx);
  268. if (aptwCard.get())
  269. m_aptwCard = aptwCard;
  270. }
  271. void
  272. CardContext::UpdateMarkers()
  273. {
  274. m_mrkLastWrite = Card()->Marker(iop::CMarker::WriteMarker);
  275. m_mrkLastChvChange = Card()->Marker(iop::CMarker::PinMarker);
  276. }
  277. void
  278. CardContext::Secure()
  279. {
  280. // Simplifying assumptions: (1) Secure is always called by a thread
  281. // within the scope of a Retain (e.g. using Retained). The
  282. // Secured template enforces this allowing Retain to act as a lock
  283. // to prevent race conditions updating m_cSecurers. (2) Once the
  284. // object is constructed, Secure and Abandon are the only routines
  285. // that access m_cSecurers.
  286. if (0 >= (m_cSecurers + 1))
  287. throw scu::OsException(ERROR_INVALID_HANDLE_STATE);
  288. ++m_cSecurers;
  289. }
  290. // Access
  291. // Predicates
  292. // Static Variables