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.

1649 lines
29 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 1999
  3. Module Name:
  4. SCardCmd
  5. Abstract:
  6. The ISCardCmd interface provides the methods needed to construct and manage
  7. a smart card Application Protocol Data Unit (APDU ). This interface
  8. encapsulates two buffers:
  9. The APDU buffer contains the command sequence that will be sent to the
  10. card.
  11. The APDUReply buffer contains data returned from the card after execution
  12. of the APDU command (this data is also referred to as the return ADPU).
  13. The following example shows a typical use of the ISCardCmd interface. The
  14. ISCardCmd interface is used to build the an ADPU.
  15. To submit a transaction to a specific card
  16. 1) Create an ISCard interface and connect to a smart card.
  17. 2) Create an ISCardCmd interface.
  18. 3) Build a smart card APDU command using the ISCardISO7816 interface or
  19. one of ISCardCmd's build methods).
  20. 4) Execute the command on the smart card by calling the appropriate ISCard
  21. interface method.
  22. 5) Evaluate the returned response.
  23. 6) Repeat the procedure as needed.
  24. 7) Release the ISCardCmd interface and others as needed.
  25. Author:
  26. Doug Barlow (dbarlow) 6/24/1999
  27. Notes:
  28. ?Notes?
  29. --*/
  30. #ifndef WIN32_LEAN_AND_MEAN
  31. #define WIN32_LEAN_AND_MEAN
  32. #endif
  33. #include "stdafx.h"
  34. #include "scardssp.h"
  35. #include "ByteBuffer.h"
  36. #include "SCardCmd.h"
  37. #include "Conversion.h"
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CSCardCmd
  40. /*++
  41. CSCardCmd::get_Apdu:
  42. The get_Apdu method retrieves the raw APDU.
  43. Arguments:
  44. ppApdu [out, retval] Pointer to the byte buffer mapped through an IStream
  45. that contains the APDU message on return.
  46. Return Value:
  47. The return value is an HRESULT. A value of S_OK indicates the call was
  48. successful.
  49. Remarks:
  50. To copy the APDU from an IByteBuffer (IStream) object into the APDU
  51. wrapped in this interface object, call put_Apdu.
  52. To determine the length of the APDU, call get_ApduLength.
  53. Author:
  54. Doug Barlow (dbarlow) 6/24/1999
  55. --*/
  56. #undef __SUBROUTINE__
  57. #define __SUBROUTINE__ TEXT("CSCardCmd::get_Apdu")
  58. STDMETHODIMP
  59. CSCardCmd::get_Apdu(
  60. /* [retval][out] */ LPBYTEBUFFER __RPC_FAR *ppApdu)
  61. {
  62. HRESULT hReturn = S_OK;
  63. CByteBuffer *pMyBuffer = NULL;
  64. try
  65. {
  66. CBuffer bfApdu(m_bfRequestData.Length() + 4 + 3 + 3);
  67. if (NULL == *ppApdu)
  68. {
  69. *ppApdu = pMyBuffer = NewByteBuffer();
  70. if (NULL == pMyBuffer)
  71. throw (HRESULT)E_OUTOFMEMORY;
  72. }
  73. ConstructRequest(
  74. m_bCla,
  75. m_bIns,
  76. m_bP1,
  77. m_bP2,
  78. m_bfRequestData,
  79. m_wLe,
  80. m_dwFlags,
  81. bfApdu);
  82. BufferToByteBuffer(bfApdu, ppApdu);
  83. pMyBuffer = NULL;
  84. }
  85. catch (HRESULT hError)
  86. {
  87. hReturn = hError;
  88. }
  89. catch (...)
  90. {
  91. hReturn = E_INVALIDARG;
  92. }
  93. if (NULL != pMyBuffer)
  94. {
  95. pMyBuffer->Release();
  96. *ppApdu = NULL;
  97. }
  98. return hReturn;
  99. }
  100. /*++
  101. CSCardCmd::put_Apdu:
  102. The put_Apdu method copies the APDU from the IByteBuffer (IStream) object
  103. into the APDU wrapped in this interface object.
  104. Arguments:
  105. pApdu [in] Pointer to the ISO 7816-4 APDU to be copied in.
  106. Return Value:
  107. The return value is an HRESULT. A value of S_OK indicates the call was
  108. successful.
  109. Remarks:
  110. To retrieve the raw APDU from the byte buffer mapped through an IStream
  111. that contains the APDU message, call get_Apdu.
  112. Author:
  113. Doug Barlow (dbarlow) 6/24/1999
  114. --*/
  115. #undef __SUBROUTINE__
  116. #define __SUBROUTINE__ TEXT("CSCardCmd::put_Apdu")
  117. STDMETHODIMP
  118. CSCardCmd::put_Apdu(
  119. /* [in] */ LPBYTEBUFFER pApdu)
  120. {
  121. HRESULT hReturn = S_OK;
  122. try
  123. {
  124. CBuffer bfApdu;
  125. LPCBYTE pbData;
  126. WORD wLc;
  127. ByteBufferToBuffer(pApdu, bfApdu);
  128. ParseRequest(
  129. bfApdu.Access(),
  130. bfApdu.Length(),
  131. &m_bCla,
  132. &m_bIns,
  133. &m_bP1,
  134. &m_bP2,
  135. &pbData,
  136. &wLc,
  137. &m_wLe,
  138. &m_dwFlags);
  139. m_bfRequestData.Set(pbData, wLc);
  140. }
  141. catch (HRESULT hError)
  142. {
  143. hReturn = hError;
  144. }
  145. catch (...)
  146. {
  147. hReturn = E_INVALIDARG;
  148. }
  149. return hReturn;
  150. }
  151. /*++
  152. CSCardCmd::get_ApduLength:
  153. The get_ApduLength method determines the length (in bytes) of the APDU.
  154. Arguments:
  155. plSize [out, retval] Pointer to the length of the APDU.
  156. Return Value:
  157. The return value is an HRESULT. A value of S_OK indicates the call was
  158. successful.
  159. Remarks:
  160. To retrieve the raw APDU from the byte buffer mapped through an IStream
  161. that contains the APDU message, call get_Apdu.
  162. Author:
  163. Doug Barlow (dbarlow) 6/24/1999
  164. --*/
  165. #undef __SUBROUTINE__
  166. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ApduLength")
  167. STDMETHODIMP
  168. CSCardCmd::get_ApduLength(
  169. /* [retval][out] */ LONG __RPC_FAR *plSize)
  170. {
  171. HRESULT hReturn = S_OK;
  172. try
  173. {
  174. CBuffer bfApdu;
  175. ConstructRequest(
  176. m_bCla,
  177. m_bIns,
  178. m_bP1,
  179. m_bP2,
  180. m_bfRequestData,
  181. m_wLe,
  182. m_dwFlags,
  183. bfApdu);
  184. *plSize = (LONG)bfApdu.Length();
  185. }
  186. catch (HRESULT hError)
  187. {
  188. hReturn = hError;
  189. }
  190. catch (...)
  191. {
  192. hReturn = E_INVALIDARG;
  193. }
  194. return hReturn;
  195. }
  196. /*++
  197. CSCardCmd::get_ApduReply:
  198. The get_ApduReply retrieves the reply APDU, placing it in a specific byte
  199. buffer. The reply may be NULL if no transaction has been performed on the
  200. command APDU.
  201. Arguments:
  202. ppReplyApdu [out, retval] Pointer to the byte buffer (mapped through an
  203. IStream) that contains the APDU reply message on return.
  204. Return Value:
  205. The return value is an HRESULT. A value of S_OK indicates the call was
  206. successful.
  207. Remarks:
  208. Author:
  209. Doug Barlow (dbarlow) 6/24/1999
  210. --*/
  211. #undef __SUBROUTINE__
  212. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ApduReply")
  213. STDMETHODIMP
  214. CSCardCmd::get_ApduReply(
  215. /* [retval][out] */ LPBYTEBUFFER __RPC_FAR *ppReplyApdu)
  216. {
  217. HRESULT hReturn = S_OK;
  218. LPBYTEBUFFER pMyBuffer = NULL;
  219. try
  220. {
  221. if (NULL == *ppReplyApdu)
  222. {
  223. *ppReplyApdu = pMyBuffer = NewByteBuffer();
  224. if (NULL == pMyBuffer)
  225. throw (HRESULT)E_OUTOFMEMORY;
  226. }
  227. BufferToByteBuffer(m_bfResponseApdu, ppReplyApdu);
  228. pMyBuffer = NULL;
  229. }
  230. catch (HRESULT hError)
  231. {
  232. hReturn = hError;
  233. }
  234. catch (...)
  235. {
  236. hReturn = E_INVALIDARG;
  237. }
  238. if (NULL != pMyBuffer)
  239. {
  240. pMyBuffer->Release();
  241. *ppReplyApdu = NULL;
  242. }
  243. return hReturn;
  244. }
  245. /*++
  246. CSCardCmd::put_ApduReply:
  247. The put_ApduReply method sets a new reply APDU.
  248. Arguments:
  249. pReplyApdu [in] Pointer to the byte buffer (mapped through an IStream) that
  250. contains the replay APDU message on return.
  251. Return Value:
  252. The return value is an HRESULT. A value of S_OK indicates the call was
  253. successful.
  254. Remarks:
  255. Author:
  256. Doug Barlow (dbarlow) 6/24/1999
  257. --*/
  258. #undef __SUBROUTINE__
  259. #define __SUBROUTINE__ TEXT("CSCardCmd::put_ApduReply")
  260. STDMETHODIMP
  261. CSCardCmd::put_ApduReply(
  262. /* [in] */ LPBYTEBUFFER pReplyApdu)
  263. {
  264. HRESULT hReturn = S_OK;
  265. try
  266. {
  267. ByteBufferToBuffer(pReplyApdu, m_bfResponseApdu);
  268. }
  269. catch (HRESULT hError)
  270. {
  271. hReturn = hError;
  272. }
  273. catch (...)
  274. {
  275. hReturn = E_INVALIDARG;
  276. }
  277. return hReturn;
  278. }
  279. /*++
  280. CSCardCmd::get_ApduReplyLength:
  281. The get_ApduReplyLength method determines the length (in bytes) of the
  282. reply APDU.
  283. Arguments:
  284. plSize [out, retval] Pointer to the size of the reply APDU message.
  285. Return Value:
  286. The return value is an HRESULT. A value of S_OK indicates the call was
  287. successful.
  288. Remarks:
  289. Author:
  290. Doug Barlow (dbarlow) 6/24/1999
  291. --*/
  292. #undef __SUBROUTINE__
  293. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ApduReplyLength")
  294. STDMETHODIMP
  295. CSCardCmd::get_ApduReplyLength(
  296. /* [retval][out] */ LONG __RPC_FAR *plSize)
  297. {
  298. HRESULT hReturn = S_OK;
  299. try
  300. {
  301. *plSize = (LONG)m_bfResponseApdu.Length();
  302. }
  303. catch (...)
  304. {
  305. hReturn = E_INVALIDARG;
  306. }
  307. return hReturn;
  308. }
  309. STDMETHODIMP
  310. CSCardCmd::put_ApduReplyLength(
  311. /* [in] */ LONG lSize)
  312. {
  313. HRESULT hReturn = S_OK;
  314. try
  315. {
  316. m_bfResponseApdu.Resize((DWORD)lSize, TRUE);
  317. }
  318. catch (...)
  319. {
  320. hReturn = E_INVALIDARG;
  321. }
  322. return hReturn;
  323. }
  324. /*++
  325. CSCardCmd::get_ClassId:
  326. The get_ClassId method retrieves the class identifier from the APDU.
  327. Arguments:
  328. pbyClass [out, retval] Pointer to the byte that represents the class
  329. identifier.
  330. Return Value:
  331. The return value is an HRESULT. A value of S_OK indicates the call was
  332. successful.
  333. Remarks:
  334. Author:
  335. Doug Barlow (dbarlow) 6/24/1999
  336. --*/
  337. #undef __SUBROUTINE__
  338. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ClassId")
  339. STDMETHODIMP
  340. CSCardCmd::get_ClassId(
  341. /* [retval][out] */ BYTE __RPC_FAR *pbyClass)
  342. {
  343. HRESULT hReturn = S_OK;
  344. try
  345. {
  346. *pbyClass = m_bCla;
  347. }
  348. catch (...)
  349. {
  350. hReturn = E_INVALIDARG;
  351. }
  352. return hReturn;
  353. }
  354. /*++
  355. CSCardCmd::put_ClassId:
  356. The put_ClassId method sets a new class identifier in the APDU.
  357. Arguments:
  358. byClass [in, defaultvalue(0)] The byte that represents the class identifier.
  359. Return Value:
  360. The return value is an HRESULT. A value of S_OK indicates the call was
  361. successful.
  362. Remarks:
  363. Author:
  364. Doug Barlow (dbarlow) 6/24/1999
  365. --*/
  366. #undef __SUBROUTINE__
  367. #define __SUBROUTINE__ TEXT("CSCardCmd::put_ClassId")
  368. STDMETHODIMP
  369. CSCardCmd::put_ClassId(
  370. /* [defaultvalue][in] */ BYTE byClass)
  371. {
  372. HRESULT hReturn = S_OK;
  373. try
  374. {
  375. m_bCla = byClass;
  376. }
  377. catch (...)
  378. {
  379. hReturn = E_INVALIDARG;
  380. }
  381. return hReturn;
  382. }
  383. /*++
  384. CSCardCmd::get_Data:
  385. The get_Data method retrieves the data field from the APDU, placing it in a
  386. byte buffer object.
  387. Arguments:
  388. ppData [out, retval] Pointer to the byte buffer object (IStream) that holds
  389. the APDU's data field on return.
  390. Return Value:
  391. The return value is an HRESULT. A value of S_OK indicates the call was
  392. successful.
  393. Remarks:
  394. Author:
  395. Doug Barlow (dbarlow) 6/24/1999
  396. --*/
  397. #undef __SUBROUTINE__
  398. #define __SUBROUTINE__ TEXT("CSCardCmd::get_Data")
  399. STDMETHODIMP
  400. CSCardCmd::get_Data(
  401. /* [retval][out] */ LPBYTEBUFFER __RPC_FAR *ppData)
  402. {
  403. HRESULT hReturn = S_OK;
  404. CByteBuffer *pMyBuffer = NULL;
  405. try
  406. {
  407. if (NULL == *ppData)
  408. {
  409. *ppData = pMyBuffer = NewByteBuffer();
  410. if (NULL == pMyBuffer)
  411. throw (HRESULT)E_OUTOFMEMORY;
  412. }
  413. BufferToByteBuffer(m_bfRequestData, ppData);
  414. pMyBuffer = NULL;
  415. }
  416. catch (HRESULT hError)
  417. {
  418. hReturn = hError;
  419. }
  420. catch (...)
  421. {
  422. hReturn = E_INVALIDARG;
  423. }
  424. if (NULL != pMyBuffer)
  425. {
  426. pMyBuffer->Release();
  427. *ppData = NULL;
  428. }
  429. return hReturn;
  430. }
  431. /*++
  432. CSCardCmd::put_Data:
  433. The put_Data method sets the data field in the APDU.
  434. Arguments:
  435. pData [in] Pointer to the byte buffer object (IStream) to be copied into
  436. the APDU's data field.
  437. Return Value:
  438. The return value is an HRESULT. A value of S_OK indicates the call was
  439. successful.
  440. Remarks:
  441. Author:
  442. Doug Barlow (dbarlow) 6/24/1999
  443. --*/
  444. #undef __SUBROUTINE__
  445. #define __SUBROUTINE__ TEXT("CSCardCmd::put_Data")
  446. STDMETHODIMP
  447. CSCardCmd::put_Data(
  448. /* [in] */ LPBYTEBUFFER pData)
  449. {
  450. HRESULT hReturn = S_OK;
  451. try
  452. {
  453. ByteBufferToBuffer(pData, m_bfRequestData);
  454. }
  455. catch (HRESULT hError)
  456. {
  457. hReturn = hError;
  458. }
  459. catch (...)
  460. {
  461. hReturn = E_INVALIDARG;
  462. }
  463. return hReturn;
  464. }
  465. /*++
  466. CSCardCmd::get_InstructionId:
  467. The get_InstructionId method retrieves the instruction identifier byte from
  468. the APDU.
  469. Arguments:
  470. pbyIns [out, retval] Pointer to the byte that is the instruction ID from
  471. the APDU on return.
  472. Return Value:
  473. The return value is an HRESULT. A value of S_OK indicates the call was
  474. successful.
  475. Remarks:
  476. Author:
  477. Doug Barlow (dbarlow) 6/24/1999
  478. --*/
  479. #undef __SUBROUTINE__
  480. #define __SUBROUTINE__ TEXT("CSCardCmd::get_InstructionId")
  481. STDMETHODIMP
  482. CSCardCmd::get_InstructionId(
  483. /* [retval][out] */ BYTE __RPC_FAR *pbyIns)
  484. {
  485. HRESULT hReturn = S_OK;
  486. try
  487. {
  488. *pbyIns = m_bIns;
  489. }
  490. catch (...)
  491. {
  492. hReturn = E_INVALIDARG;
  493. }
  494. return hReturn;
  495. }
  496. /*++
  497. CSCardCmd::put_InstructionId:
  498. The put_InstructionId sets the given instruction identifier in the APDU.
  499. Arguments:
  500. byIns [in] The byte that is the instruction identifier.
  501. Return Value:
  502. The return value is an HRESULT. A value of S_OK indicates the call was
  503. successful.
  504. Remarks:
  505. Author:
  506. Doug Barlow (dbarlow) 6/24/1999
  507. --*/
  508. #undef __SUBROUTINE__
  509. #define __SUBROUTINE__ TEXT("CSCardCmd::put_InstructionId")
  510. STDMETHODIMP
  511. CSCardCmd::put_InstructionId(
  512. /* [in] */ BYTE byIns)
  513. {
  514. HRESULT hReturn = S_OK;
  515. try
  516. {
  517. m_bIns = byIns;
  518. }
  519. catch (...)
  520. {
  521. hReturn = E_INVALIDARG;
  522. }
  523. return hReturn;
  524. }
  525. STDMETHODIMP
  526. CSCardCmd::get_LeField(
  527. /* [retval][out] */ LONG __RPC_FAR *plSize)
  528. {
  529. HRESULT hReturn = S_OK;
  530. try
  531. {
  532. *plSize = m_wLe;
  533. }
  534. catch (...)
  535. {
  536. hReturn = E_INVALIDARG;
  537. }
  538. return hReturn;
  539. }
  540. /*++
  541. CSCardCmd::get_P1:
  542. The get_P1 method retrieves the first parameter (P1) byte from the APDU.
  543. Arguments:
  544. pbyP1 [out, retval] Pointer to the P1 byte in the APDU on return.
  545. Return Value:
  546. The return value is an HRESULT. A value of S_OK indicates the call was
  547. successful.
  548. Remarks:
  549. Author:
  550. Doug Barlow (dbarlow) 6/24/1999
  551. --*/
  552. #undef __SUBROUTINE__
  553. #define __SUBROUTINE__ TEXT("CSCardCmd::get_P1")
  554. STDMETHODIMP
  555. CSCardCmd::get_P1(
  556. /* [retval][out] */ BYTE __RPC_FAR *pbyP1)
  557. {
  558. HRESULT hReturn = S_OK;
  559. try
  560. {
  561. *pbyP1 = m_bP1;
  562. }
  563. catch (...)
  564. {
  565. hReturn = E_INVALIDARG;
  566. }
  567. return hReturn;
  568. }
  569. /*++
  570. CSCardCmd::put_P1:
  571. The put_P1 method sets the first parameter (P1) byte of the APDU.
  572. Arguments:
  573. byP1 [in] The byte that is the P1 field.
  574. Return Value:
  575. The return value is an HRESULT. A value of S_OK indicates the call was
  576. successful.
  577. Remarks:
  578. Author:
  579. Doug Barlow (dbarlow) 6/24/1999
  580. --*/
  581. #undef __SUBROUTINE__
  582. #define __SUBROUTINE__ TEXT("CSCardCmd::put_P1")
  583. STDMETHODIMP
  584. CSCardCmd::put_P1(
  585. /* [in] */ BYTE byP1)
  586. {
  587. HRESULT hReturn = S_OK;
  588. try
  589. {
  590. m_bP1 = byP1;
  591. }
  592. catch (...)
  593. {
  594. hReturn = E_INVALIDARG;
  595. }
  596. return hReturn;
  597. }
  598. /*++
  599. CSCardCmd::get_P2:
  600. The get_P2 method retrieves the second parameter (P2) byte from the APDU
  601. Arguments:
  602. pbyP2 [out, retval] Pointer to the byte that is the P2 from the APDU on
  603. return.
  604. Return Value:
  605. The return value is an HRESULT. A value of S_OK indicates the call was
  606. successful.
  607. Remarks:
  608. Author:
  609. Doug Barlow (dbarlow) 6/24/1999
  610. --*/
  611. #undef __SUBROUTINE__
  612. #define __SUBROUTINE__ TEXT("CSCardCmd::get_P2")
  613. STDMETHODIMP
  614. CSCardCmd::get_P2(
  615. /* [retval][out] */ BYTE __RPC_FAR *pbyP2)
  616. {
  617. HRESULT hReturn = S_OK;
  618. try
  619. {
  620. *pbyP2 = m_bP2;
  621. }
  622. catch (...)
  623. {
  624. hReturn = E_INVALIDARG;
  625. }
  626. return hReturn;
  627. }
  628. /*++
  629. CSCardCmd::put_P2:
  630. The put_P2 method sets the second parameter (P2) byte in the APDU.
  631. Arguments:
  632. byP2 [in] The byte that is the P2 field.
  633. Return Value:
  634. The return value is an HRESULT. A value of S_OK indicates the call was
  635. successful.
  636. Remarks:
  637. Author:
  638. Doug Barlow (dbarlow) 6/24/1999
  639. --*/
  640. #undef __SUBROUTINE__
  641. #define __SUBROUTINE__ TEXT("CSCardCmd::put_P2")
  642. STDMETHODIMP
  643. CSCardCmd::put_P2(
  644. /* [in] */ BYTE byP2)
  645. {
  646. HRESULT hReturn = S_OK;
  647. try
  648. {
  649. m_bP2 = byP2;
  650. }
  651. catch (...)
  652. {
  653. hReturn = E_INVALIDARG;
  654. }
  655. return hReturn;
  656. }
  657. /*++
  658. CSCardCmd::get_P3:
  659. The get_P3 method retrieves the third parameter (P3) byte from the APDU.
  660. This read-only byte value represents the size of the data portion of the
  661. APDU.
  662. Arguments:
  663. pbyP3 [out, retval] Pointer to the byte that is the P3 from the APDU on
  664. return.
  665. Return Value:
  666. The return value is an HRESULT. A value of S_OK indicates the call was
  667. successful.
  668. Remarks:
  669. Author:
  670. Doug Barlow (dbarlow) 6/24/1999
  671. --*/
  672. #undef __SUBROUTINE__
  673. #define __SUBROUTINE__ TEXT("CSCardCmd::get_P3")
  674. STDMETHODIMP
  675. CSCardCmd::get_P3(
  676. /* [retval][out] */ BYTE __RPC_FAR *pbyP3)
  677. {
  678. HRESULT hReturn = S_OK;
  679. try
  680. {
  681. *pbyP3 = (BYTE)m_bfRequestData.Length();
  682. }
  683. catch (...)
  684. {
  685. hReturn = E_INVALIDARG;
  686. }
  687. return hReturn;
  688. }
  689. /*++
  690. CSCardCmd::get_ReplyStatus:
  691. The get_ReplyStatus method retrieves the reply APDU's message status word.
  692. Arguments:
  693. pwStatus [out, retval] Pointer to the word that is the status on return.
  694. Return Value:
  695. The return value is an HRESULT. A value of S_OK indicates the call was
  696. successful.
  697. Remarks:
  698. Author:
  699. Doug Barlow (dbarlow) 6/24/1999
  700. --*/
  701. #undef __SUBROUTINE__
  702. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ReplyStatus")
  703. STDMETHODIMP
  704. CSCardCmd::get_ReplyStatus(
  705. /* [retval][out] */ LPWORD pwStatus)
  706. {
  707. HRESULT hReturn = S_OK;
  708. try
  709. {
  710. DWORD dwLen = m_bfResponseApdu.Length();
  711. if (2 <= dwLen)
  712. *pwStatus = NetToLocal(m_bfResponseApdu.Access(dwLen - 2));
  713. else
  714. *pwStatus = 0;
  715. }
  716. catch (...)
  717. {
  718. hReturn = E_INVALIDARG;
  719. }
  720. return hReturn;
  721. }
  722. /*++
  723. CSCardCmd::put_ReplyStatus:
  724. The put_ReplyStatus sets a new reply APDU's message status word.
  725. Arguments:
  726. wStatus [in] The word that is the status.
  727. Return Value:
  728. The return value is an HRESULT. A value of S_OK indicates the call was
  729. successful.
  730. Remarks:
  731. Author:
  732. Doug Barlow (dbarlow) 6/24/1999
  733. --*/
  734. #undef __SUBROUTINE__
  735. #define __SUBROUTINE__ TEXT("CSCardCmd::put_ReplyStatus")
  736. STDMETHODIMP
  737. CSCardCmd::put_ReplyStatus(
  738. /* [in] */ WORD wStatus)
  739. {
  740. HRESULT hReturn = S_OK;
  741. try
  742. {
  743. DWORD dwLen = m_bfResponseApdu.Length();
  744. if (2 <= dwLen)
  745. CopyMemory(m_bfResponseApdu.Access(dwLen - 2), &wStatus, 2);
  746. else
  747. m_bfResponseApdu.Set((LPCBYTE)&wStatus, 2);
  748. }
  749. catch (...)
  750. {
  751. hReturn = E_INVALIDARG;
  752. }
  753. return hReturn;
  754. }
  755. /*++
  756. CSCardCmd::get_ReplyStatusSW1:
  757. The get_ReplyStatusSW1 method retrieves the reply APDU's SW1 status byte.
  758. Arguments:
  759. pbySW1 [out, retval] Pointer to the byte that contains the value of the SW1
  760. byte on return.
  761. Return Value:
  762. The return value is an HRESULT. A value of S_OK indicates the call was
  763. successful.
  764. Remarks:
  765. Author:
  766. Doug Barlow (dbarlow) 6/24/1999
  767. --*/
  768. #undef __SUBROUTINE__
  769. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ReplyStatusSW1")
  770. STDMETHODIMP
  771. CSCardCmd::get_ReplyStatusSW1(
  772. /* [retval][out] */ BYTE __RPC_FAR *pbySW1)
  773. {
  774. HRESULT hReturn = S_OK;
  775. try
  776. {
  777. DWORD dwLen = m_bfResponseApdu.Length();
  778. if (2 <= dwLen)
  779. *pbySW1 = *m_bfResponseApdu.Access(dwLen - 2);
  780. else
  781. *pbySW1 = 0;
  782. }
  783. catch (HRESULT hError)
  784. {
  785. hReturn = hError;
  786. }
  787. catch (...)
  788. {
  789. hReturn = E_INVALIDARG;
  790. }
  791. return hReturn;
  792. }
  793. /*++
  794. CSCardCmd::get_ReplyStatusSW2:
  795. The get_ReplyStatusSW2 method retrieves the reply APDU's SW2 status byte.
  796. Arguments:
  797. pbySW2 [out, retval] Pointer to the byte that contains the value of the SW2
  798. byte on return.
  799. Return Value:
  800. The return value is an HRESULT. A value of S_OK indicates the call was
  801. successful.
  802. Remarks:
  803. Author:
  804. Doug Barlow (dbarlow) 6/24/1999
  805. --*/
  806. #undef __SUBROUTINE__
  807. #define __SUBROUTINE__ TEXT("CSCardCmd::get_ReplyStatusSW2")
  808. STDMETHODIMP
  809. CSCardCmd::get_ReplyStatusSW2(
  810. /* [retval][out] */ BYTE __RPC_FAR *pbySW2)
  811. {
  812. HRESULT hReturn = S_OK;
  813. try
  814. {
  815. DWORD dwLen = m_bfResponseApdu.Length();
  816. if (2 <= dwLen)
  817. *pbySW2 = *m_bfResponseApdu.Access(dwLen - 1);
  818. else
  819. *pbySW2 = 0;
  820. }
  821. catch (...)
  822. {
  823. hReturn = E_INVALIDARG;
  824. }
  825. return hReturn;
  826. }
  827. #undef __SUBROUTINE__
  828. #define __SUBROUTINE__ TEXT("CSCardCmd::get_Type")
  829. STDMETHODIMP
  830. CSCardCmd::get_Type(
  831. /* [retval][out] */ ISO_APDU_TYPE __RPC_FAR *pType)
  832. {
  833. HRESULT hReturn = S_OK;
  834. try
  835. {
  836. // ?todo?
  837. breakpoint;
  838. hReturn = E_NOTIMPL;
  839. }
  840. catch (HRESULT hError)
  841. {
  842. hReturn = hError;
  843. }
  844. catch (...)
  845. {
  846. hReturn = E_INVALIDARG;
  847. }
  848. return hReturn;
  849. }
  850. STDMETHODIMP
  851. CSCardCmd::get_Nad(
  852. /* [retval][out] */ BYTE __RPC_FAR *pbNad)
  853. {
  854. HRESULT hReturn = S_OK;
  855. try
  856. {
  857. if (0 != (m_dwFlags & APDU_REQNAD_VALID))
  858. *pbNad = m_bRequestNad;
  859. else
  860. hReturn = E_ACCESSDENIED;
  861. }
  862. catch (...)
  863. {
  864. hReturn = E_INVALIDARG;
  865. }
  866. return hReturn;
  867. }
  868. STDMETHODIMP
  869. CSCardCmd::put_Nad(
  870. /* [in] */ BYTE bNad)
  871. {
  872. HRESULT hReturn = S_OK;
  873. try
  874. {
  875. m_bRequestNad = bNad;
  876. m_dwFlags |= APDU_REQNAD_VALID;
  877. }
  878. catch (...)
  879. {
  880. hReturn = E_INVALIDARG;
  881. }
  882. return hReturn;
  883. }
  884. STDMETHODIMP
  885. CSCardCmd::get_ReplyNad(
  886. /* [retval][out] */ BYTE __RPC_FAR *pbNad)
  887. {
  888. HRESULT hReturn = S_OK;
  889. try
  890. {
  891. if (0 != (APDU_RSPNAD_VALID & m_dwFlags))
  892. *pbNad = m_bResponseNad;
  893. else
  894. hReturn = E_ACCESSDENIED;
  895. }
  896. catch (...)
  897. {
  898. hReturn = E_INVALIDARG;
  899. }
  900. return hReturn;
  901. }
  902. STDMETHODIMP
  903. CSCardCmd::put_ReplyNad(
  904. /* [in] */ BYTE bNad)
  905. {
  906. HRESULT hReturn = S_OK;
  907. try
  908. {
  909. m_bResponseNad = bNad;
  910. m_dwFlags |= APDU_RSPNAD_VALID;
  911. }
  912. catch (...)
  913. {
  914. hReturn = E_INVALIDARG;
  915. }
  916. return hReturn;
  917. }
  918. /*++
  919. CSCardCmd::get_AlternateClassId:
  920. The get_AlternateClassId method retrieves the alternate class identifier
  921. from the APDU. The Alternate Class Id is used for automatically generated
  922. GetResponse and Envelope commands when T=0 is used.
  923. Arguments:
  924. pbyClass [out, retval] Pointer to the byte that represents the alternate
  925. class identifier.
  926. Return Value:
  927. The return value is an HRESULT. A value of S_OK indicates the call was
  928. successful.
  929. Remarks:
  930. Author:
  931. Doug Barlow (dbarlow) 6/24/1999
  932. --*/
  933. #undef __SUBROUTINE__
  934. #define __SUBROUTINE__ TEXT("CSCardCmd::get_AlternateClassId")
  935. STDMETHODIMP
  936. CSCardCmd::get_AlternateClassId(
  937. /* [retval][out] */ BYTE __RPC_FAR *pbyClass)
  938. {
  939. HRESULT hReturn = S_OK;
  940. try
  941. {
  942. if (0 != (m_dwFlags & APDU_ALTCLA_VALID))
  943. *pbyClass = m_bAltCla;
  944. else
  945. hReturn = E_ACCESSDENIED;
  946. }
  947. catch (...)
  948. {
  949. hReturn = E_INVALIDARG;
  950. }
  951. return hReturn;
  952. }
  953. /*++
  954. CSCardCmd::put_AlternateClassId:
  955. The put_AlternateClassId method sets a new alternate class identifier in
  956. the APDU. The Alternate Class Id is used for automatically generated
  957. GetResponse and Envelope commands when T=0 is used. If no alternate class
  958. identifier is set, then the CLA of the original command is used.
  959. Arguments:
  960. byClass [in, defaultvalue(0)] The byte that represents the alternate class
  961. identifier.
  962. Return Value:
  963. The return value is an HRESULT. A value of S_OK indicates the call was
  964. successful.
  965. Remarks:
  966. Author:
  967. Doug Barlow (dbarlow) 6/24/1999
  968. --*/
  969. #undef __SUBROUTINE__
  970. #define __SUBROUTINE__ TEXT("CSCardCmd::put_AlternateClassId")
  971. STDMETHODIMP
  972. CSCardCmd::put_AlternateClassId(
  973. /* [defaultvalue][in] */ BYTE byClass)
  974. {
  975. HRESULT hReturn = S_OK;
  976. try
  977. {
  978. m_bAltCla = byClass;
  979. m_dwFlags |= APDU_ALTCLA_VALID;
  980. }
  981. catch (...)
  982. {
  983. hReturn = E_INVALIDARG;
  984. }
  985. return hReturn;
  986. }
  987. /*++
  988. CSCardCmd::BuildCmd:
  989. The BuildCmd method constructs a valid command APDU for transmission to a
  990. smart card.
  991. Arguments:
  992. byClassId [in] Command class identifier.
  993. byInsId [in] Command instruction identifier.
  994. byP1 [in, defaultvalue(0)] Command's first parameter.
  995. byP2 [in, defaultvalue(0)] Command's second parameter.
  996. pbyData [in, defaultvalue(NULL)] Pointer to the data portion of the
  997. command.
  998. p1Le [in, defaultvalue(NULL)] Pointer to a LONG integer containing the
  999. expected length of the returned data.
  1000. Return Value:
  1001. The return value is an HRESULT. A value of S_OK indicates the call was
  1002. successful.
  1003. Remarks:
  1004. Author:
  1005. Doug Barlow (dbarlow) 6/24/1999
  1006. --*/
  1007. #undef __SUBROUTINE__
  1008. #define __SUBROUTINE__ TEXT("CSCardCmd::BuildCmd")
  1009. STDMETHODIMP
  1010. CSCardCmd::BuildCmd(
  1011. /* [in] */ BYTE byClassId,
  1012. /* [in] */ BYTE byInsId,
  1013. /* [defaultvalue][in] */ BYTE byP1,
  1014. /* [defaultvalue][in] */ BYTE byP2,
  1015. /* [defaultvalue][in] */ LPBYTEBUFFER pbyData,
  1016. /* [defaultvalue][in] */ LONG __RPC_FAR *plLe)
  1017. {
  1018. HRESULT hReturn = S_OK;
  1019. try
  1020. {
  1021. ByteBufferToBuffer(pbyData, m_bfRequestData);
  1022. m_bCla = byClassId;
  1023. m_bIns = byInsId;
  1024. m_bP1 = byP1;
  1025. m_bP2 = byP2;
  1026. m_dwFlags = 0;
  1027. if (NULL != plLe)
  1028. {
  1029. switch (*plLe)
  1030. {
  1031. case 0x10000:
  1032. m_dwFlags |= APDU_EXTENDED_LENGTH;
  1033. // Fall through intentionally
  1034. case 0x100:
  1035. case 0:
  1036. m_dwFlags |= APDU_MAXIMUM_LE;
  1037. m_wLe = 0;
  1038. break;
  1039. default:
  1040. if (0x10000 < *plLe)
  1041. throw (HRESULT)E_INVALIDARG;
  1042. if (0x100 < *plLe)
  1043. m_dwFlags |= APDU_EXTENDED_LENGTH;
  1044. m_wLe = (WORD)(*plLe);
  1045. }
  1046. }
  1047. }
  1048. catch (HRESULT hError)
  1049. {
  1050. hReturn = hError;
  1051. }
  1052. catch (...)
  1053. {
  1054. hReturn = E_INVALIDARG;
  1055. }
  1056. return hReturn;
  1057. }
  1058. /*++
  1059. CSCardCmd::Clear:
  1060. The Clear method clears the APDU and reply APDU message buffers.
  1061. Arguments:
  1062. None
  1063. Return Value:
  1064. The return value is an HRESULT. A value of S_OK indicates the call was
  1065. successful.
  1066. Remarks:
  1067. Author:
  1068. Doug Barlow (dbarlow) 6/24/1999
  1069. --*/
  1070. #undef __SUBROUTINE__
  1071. #define __SUBROUTINE__ TEXT("CSCardCmd::Clear")
  1072. STDMETHODIMP
  1073. CSCardCmd::Clear(
  1074. void)
  1075. {
  1076. HRESULT hReturn = S_OK;
  1077. try
  1078. {
  1079. m_bfRequestData.Reset();
  1080. m_bfResponseApdu.Reset();
  1081. }
  1082. catch (...)
  1083. {
  1084. hReturn = E_INVALIDARG;
  1085. }
  1086. return hReturn;
  1087. }
  1088. /*++
  1089. CSCardCmd::Encapsulate:
  1090. The Encapsulate method encapsulates the given command APDU into another
  1091. command APDU for transmission to a smart card.
  1092. Arguments:
  1093. pApdu [in] Pointer to the APDU to be encapsulated.
  1094. ApduType [in] Specifies the ISO 7816-4 case for T0 transmissions. Possible
  1095. values are:
  1096. ISO_CASE_1
  1097. ISO_CASE_2
  1098. ISO_CASE_3
  1099. ISO_CASE_4
  1100. Return Value:
  1101. The return value is an HRESULT. A value of S_OK indicates the call was
  1102. successful.
  1103. Remarks:
  1104. Author:
  1105. Doug Barlow (dbarlow) 6/24/1999
  1106. --*/
  1107. #undef __SUBROUTINE__
  1108. #define __SUBROUTINE__ TEXT("CSCardCmd::Encapsulate")
  1109. STDMETHODIMP
  1110. CSCardCmd::Encapsulate(
  1111. /* [in] */ LPBYTEBUFFER pApdu,
  1112. /* [in] */ ISO_APDU_TYPE ApduType)
  1113. {
  1114. HRESULT hReturn = S_OK;
  1115. try
  1116. {
  1117. WORD wLe;
  1118. DWORD dwFlags;
  1119. //
  1120. // Get the APDU to be encapsulated.
  1121. //
  1122. ByteBufferToBuffer(pApdu, m_bfRequestData);
  1123. //
  1124. // Parse it.
  1125. //
  1126. ParseRequest(
  1127. m_bfRequestData.Access(),
  1128. m_bfRequestData.Length(),
  1129. NULL,
  1130. NULL,
  1131. NULL,
  1132. NULL,
  1133. NULL,
  1134. NULL,
  1135. &wLe,
  1136. &dwFlags);
  1137. m_bIns = 0xc2;
  1138. m_bP1 = 0x00;
  1139. m_bP2 = 0x00;
  1140. m_wLe = wLe;
  1141. m_dwFlags = dwFlags;
  1142. // ?todo? -- support ApduType
  1143. }
  1144. catch (HRESULT hError)
  1145. {
  1146. hReturn = hError;
  1147. }
  1148. catch (...)
  1149. {
  1150. hReturn = E_INVALIDARG;
  1151. }
  1152. return hReturn;
  1153. }