1. //  Copyright(C):      Advanced Card Systems Ltd
  2. //
  3. //  File:              SLE4432_4442Dlg.pas
  4. //
  5. //  Description:       This sample program outlines the steps on how to
  6. //                     program SLE4432/4442 memory cards using ACS readers
  7. //                     in PC/SC platform.
  8. //
  9. //  Author:            Jose Isagani R. Mission
  10. //
  11. //  Date:              June 25, 2004
  12. //
  13. //  Revision Trail:   (Date/Author/Description)
  14. //
  15. //======================================================================
  16. // SLE4432_4442Dlg.cpp : implementation file
  17. //
  18.  
  19. #include "stdafx.h"
  20. #include "SLE4432_4442.h"
  21. #include "SLE4432_4442Dlg.h"
  22.  
  23. // ==========================================================================
  24. // SLE4432_4442Dlg include file
  25. #include "Winscard.h"
  26.  
  27. // SLE4432_4442Dlg GlobalVariables
  28.     SCARDCONTEXT            hContext;
  29.     SCARDHANDLE             hCard;
  30.     unsigned long           dwActProtocol;
  31.     LPCBYTE                 pbSend;
  32.     DWORD                   dwSend, dwRecv, size = 64;
  33.     LPBYTE                  pbRecv;
  34.     SCARD_IO_REQUEST        ioRequest;
  35.     int                     retCode;
  36.     char                    readerName [256];
  37.     DWORD                   SendLen,
  38.                             RecvLen,
  39.                             nBytesRet;
  40.     CmdBytes                apdu;
  41.     BYTE                    SendBuff[262],
  42.                             RecvBuff[262];
  43.     BOOL                    connActive;
  44.     CSLE4432_4442Dlg        *pThis=NULL;
  45. // ==========================================================================
  46.  
  47. #ifdef _DEBUG
  48. #define new DEBUG_NEW
  49. #undef THIS_FILE
  50. static char THIS_FILE[] = __FILE__;
  51. #endif
  52.  
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CAboutDlg dialog used for App About
  55.  
  56. class CAboutDlg : public CDialog
  57. {
  58. public:
  59.     CAboutDlg();
  60.  
  61. // Dialog Data
  62.     //{{AFX_DATA(CAboutDlg)
  63.     enum { IDD = IDD_ABOUTBOX };
  64.     //}}AFX_DATA
  65.  
  66.     // ClassWizard generated virtual function overrides
  67.     //{{AFX_VIRTUAL(CAboutDlg)
  68.     protected:
  69.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  70.     //}}AFX_VIRTUAL
  71.  
  72. // Implementation
  73. protected:
  74.     //{{AFX_MSG(CAboutDlg)
  75.     //}}AFX_MSG
  76.     DECLARE_MESSAGE_MAP()
  77. };
  78.  
  79. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  80. {
  81.     //{{AFX_DATA_INIT(CAboutDlg)
  82.     //}}AFX_DATA_INIT
  83. }
  84.  
  85. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  86. {
  87.     CDialog::DoDataExchange(pDX);
  88.     //{{AFX_DATA_MAP(CAboutDlg)
  89.     //}}AFX_DATA_MAP
  90. }
  91.  
  92. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  93.     //{{AFX_MSG_MAP(CAboutDlg)
  94.         // No message handlers
  95.     //}}AFX_MSG_MAP
  96. END_MESSAGE_MAP()
  97.  
  98. /////////////////////////////////////////////////////////////////////////////
  99. // CSLE4432_4442Dlg dialog
  100.  
  101. CSLE4432_4442Dlg::CSLE4432_4442Dlg(CWnd* pParent /*=NULL*/)
  102.     : CDialog(CSLE4432_4442Dlg::IDD, pParent)
  103. {
  104.     //{{AFX_DATA_INIT(CSLE4432_4442Dlg)
  105.     //}}AFX_DATA_INIT
  106.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  107.     m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
  108. }
  109.  
  110. void CSLE4432_4442Dlg::DoDataExchange(CDataExchange* pDX)
  111. {
  112.     CDialog::DoDataExchange(pDX);
  113.     //{{AFX_DATA_MAP(CSLE4432_4442Dlg)
  114.     DDX_Control(pDX, IDC_BUTTON4, bChange);
  115.     DDX_Control(pDX, IDC_BUTTON6, bWriteProt);
  116.     DDX_Control(pDX, IDC_EDIT1, tAdd);
  117.     DDX_Control(pDX, IDC_RADIO1, rbSLE4432);
  118.     DDX_Control(pDX, IDC_COMBO1, cbReader);
  119.     DDX_Control(pDX, IDC_LIST1, mMsg);
  120.     DDX_Control(pDX, IDC_EDIT4, tData);
  121.     DDX_Control(pDX, IDC_EDIT3, tLen);
  122.     DDX_Control(pDX, IDC_BUTTON9, bReset);
  123.     DDX_Control(pDX, IDC_BUTTON8, bErrCtr);
  124.     DDX_Control(pDX, IDC_BUTTON7, bSubmit);
  125.     DDX_Control(pDX, IDC_BUTTON5, bWrite);
  126.     DDX_Control(pDX, IDC_BUTTON3, bRead);
  127.     DDX_Control(pDX, IDC_BUTTON2, bConnect);
  128.     DDX_Control(pDX, IDC_BUTTON10, bQuit);
  129.     DDX_Control(pDX, IDC_BUTTON1, bInit);
  130.     //}}AFX_DATA_MAP
  131. }
  132.  
  133. BEGIN_MESSAGE_MAP(CSLE4432_4442Dlg, CDialog)
  134.     //{{AFX_MSG_MAP(CSLE4432_4442Dlg)
  135.     ON_WM_SYSCOMMAND()
  136.     ON_WM_PAINT()
  137.     ON_WM_QUERYDRAGICON()
  138.     ON_BN_CLICKED(IDC_BUTTON1, OnInit)
  139.     ON_BN_CLICKED(IDC_BUTTON9, OnReset)
  140.     ON_BN_CLICKED(IDC_BUTTON10, OnQuit)
  141.     ON_BN_CLICKED(IDC_BUTTON2, OnConnect)
  142.     ON_BN_CLICKED(IDC_RADIO1, OnSLE4418)
  143.     ON_CBN_EDITCHANGE(IDC_COMBO1, OnEditchangeCombo1)
  144.     ON_BN_CLICKED(IDC_RADIO2, OnSLE4428)
  145.     ON_BN_CLICKED(IDC_BUTTON3, OnRead)
  146.     ON_BN_CLICKED(IDC_BUTTON4, OnReadProt)
  147.     ON_BN_CLICKED(IDC_BUTTON5, OnWrite)
  148.     ON_BN_CLICKED(IDC_BUTTON7, OnSubmit)
  149.     ON_BN_CLICKED(IDC_BUTTON8, OnErrCtr)
  150.     ON_BN_CLICKED(IDC_BUTTON6, OnWriteProt)
  151.     ON_CBN_SELCHANGE(IDC_COMBO1, OnSelchangeCombo1)
  152.     //}}AFX_MSG_MAP
  153. END_MESSAGE_MAP()
  154.  
  155. // ==========================================================================
  156. // SLE4432_4442Dlg internal routines
  157.  
  158. static CString GetScardErrMsg(int code)
  159. {
  160.     switch(code)
  161.     {
  162.     // Smartcard Reader interface errors
  163.     case SCARD_E_CANCELLED:
  164.         return ("The action was canceled by an SCardCancel request.");
  165.         break;
  166.     case SCARD_E_CANT_DISPOSE:
  167.         return ("The system could not dispose of the media in the requested manner.");
  168.         break;
  169.     case SCARD_E_CARD_UNSUPPORTED:
  170.         return ("The smart card does not meet minimal requirements for support.");
  171.         break;
  172.     case SCARD_E_DUPLICATE_READER:
  173.         return ("The reader driver didn't produce a unique reader name.");
  174.         break;
  175.     case SCARD_E_INSUFFICIENT_BUFFER:
  176.         return ("The data buffer for returned data is too small for the returned data.");
  177.         break;
  178.     case SCARD_E_INVALID_ATR:
  179.         return ("An ATR string obtained from the registry is not a valid ATR string.");
  180.         break;
  181.     case SCARD_E_INVALID_HANDLE:
  182.         return ("The supplied handle was invalid.");
  183.         break;
  184.     case SCARD_E_INVALID_PARAMETER:
  185.         return ("One or more of the supplied parameters could not be properly interpreted.");
  186.         break;
  187.     case SCARD_E_INVALID_TARGET:
  188.         return ("Registry startup information is missing or invalid.");
  189.         break;
  190.     case SCARD_E_INVALID_VALUE:
  191.         return ("One or more of the supplied parameter values could not be properly interpreted.");
  192.         break;
  193.     case SCARD_E_NOT_READY:
  194.         return ("The reader or card is not ready to accept commands.");
  195.         break;
  196.     case SCARD_E_NOT_TRANSACTED:
  197.         return ("An attempt was made to end a non-existent transaction.");
  198.         break;
  199.     case SCARD_E_NO_MEMORY:
  200.         return ("Not enough memory available to complete this command.");
  201.         break;
  202.     case SCARD_E_NO_SERVICE:
  203.         return ("The smart card resource manager is not running.");
  204.         break;
  205.     case SCARD_E_NO_SMARTCARD:
  206.         return ("The operation requires a smart card, but no smart card is currently in the device.");
  207.         break;
  208.     case SCARD_E_PCI_TOO_SMALL:
  209.         return ("The PCI receive buffer was too small.");
  210.         break;
  211.     case SCARD_E_PROTO_MISMATCH:
  212.         return ("The requested protocols are incompatible with the protocol currently in use with the card.");
  213.         break;
  214.     case SCARD_E_READER_UNAVAILABLE:
  215.         return ("The specified reader is not currently available for use.");
  216.         break;
  217.     case SCARD_E_READER_UNSUPPORTED:
  218.         return ("The reader driver does not meet minimal requirements for support.");
  219.         break;
  220.     case SCARD_E_SERVICE_STOPPED:
  221.         return ("The smart card resource manager has shut down.");
  222.         break;
  223.     case SCARD_E_SHARING_VIOLATION:
  224.         return ("The smart card cannot be accessed because of other outstanding connections.");
  225.         break;
  226.     case SCARD_E_SYSTEM_CANCELLED:
  227.         return ("The action was canceled by the system, presumably to log off or shut down.");
  228.         break;
  229.     case SCARD_E_TIMEOUT:
  230.         return ("The user-specified timeout value has expired.");
  231.         break;
  232.     case SCARD_E_UNKNOWN_CARD:
  233.         return ("The specified smart card name is not recognized.");
  234.         break;
  235.     case SCARD_E_UNKNOWN_READER:
  236.         return ("The specified reader name is not recognized.");
  237.         break;
  238.     case SCARD_F_COMM_ERROR:
  239.         return ("An internal communications error has been detected.");
  240.         break;
  241.     case SCARD_F_INTERNAL_ERROR:
  242.         return ("An internal consistency check failed.");
  243.         break;
  244.     case SCARD_F_UNKNOWN_ERROR:
  245.         return ("An internal error has been detected, but the source is unknown.");
  246.         break;
  247.     case SCARD_F_WAITED_TOO_LONG:
  248.         return ("An internal consistency timer has expired.");
  249.         break;
  250.     case SCARD_W_REMOVED_CARD:
  251.         return ("The smart card has been removed and no further communication is possible.");
  252.         break;
  253.     case SCARD_W_RESET_CARD:
  254.         return ("The smart card has been reset, so any shared state information is invalid.");
  255.         break;
  256.     case SCARD_W_UNPOWERED_CARD:
  257.         return ("Power has been removed from the smart card and no further communication is possible.");
  258.         break;
  259.     case SCARD_W_UNRESPONSIVE_CARD:
  260.         return ("The smart card is not responding to a reset.");
  261.         break;
  262.     case SCARD_W_UNSUPPORTED_CARD:
  263.         return ("The reader cannot communicate with the card due to ATR string configuration conflicts.");
  264.         break;
  265.     case NO_READER_INSTALLED:
  266.         return ("The smartcard reader is not installed in your system.");
  267.         break;
  268.     }
  269.     return ("Error is not documented.");
  270. }
  271.  
  272. void ClearBuffers()
  273. {
  274.     int indx;
  275.     for (indx = 0;indx<263;indx++)
  276.     {
  277.       SendBuff[indx] = 0x00;
  278.       RecvBuff[indx] = 0x00;
  279.     }
  280. }
  281.  
  282. void ClearFields()
  283. {
  284.  
  285.     pThis->tAdd.SetWindowText("");
  286.     pThis->tLen.SetWindowText("");
  287.     pThis->tData.SetWindowText("");
  288.  
  289. }
  290.  
  291. void EnableFields()
  292. {
  293.     pThis->tAdd.EnableWindow(TRUE);
  294.     pThis->tAdd.SetLimitText(2);
  295.     pThis->tLen.EnableWindow(TRUE);
  296.     pThis->tLen.SetLimitText(2);
  297.     pThis->tData.EnableWindow(TRUE);
  298. }
  299.  
  300. void DisableFields()
  301. {
  302.     pThis->tAdd.EnableWindow(FALSE);
  303.     pThis->tLen.EnableWindow(FALSE);
  304.     pThis->tData.EnableWindow(FALSE);
  305. }
  306.  
  307. void InitMenu()
  308. {
  309.     pThis->cbReader.ResetContent();
  310.     pThis->mMsg.ResetContent();
  311.     pThis->rbSLE4432.SetCheck(0);
  312.     pThis->cbReader.EnableWindow(FALSE);
  313.     pThis->bInit.EnableWindow(TRUE);
  314.     pThis->bConnect.EnableWindow(FALSE);
  315.     pThis->bErrCtr.EnableWindow(FALSE);
  316.     pThis->bRead.EnableWindow(FALSE);
  317.     pThis->bWrite.EnableWindow(FALSE);
  318.     pThis->bWriteProt.EnableWindow(FALSE);
  319.     pThis->bReset.EnableWindow(FALSE);
  320.     pThis->bSubmit.EnableWindow(FALSE);
  321.     pThis->bChange.EnableWindow(FALSE);
  322.     ClearFields();
  323.     DisableFields();
  324. }
  325.  
  326. void DisplayOut(int errType, int retVal, CString prtText)
  327. {
  328.   char buffer[300];
  329.  
  330.   switch (errType){
  331.   case 0:                          // Notifications
  332.       pThis->mMsg.AddString(prtText);
  333.       break;
  334.   case 1:                          // Error Messages
  335.       pThis->mMsg.AddString(GetScardErrMsg(retVal));
  336.       break;
  337.   case 2:                          // Input data
  338.       sprintf(buffer, "< %s", prtText);
  339.       pThis->mMsg.AddString(buffer);
  340.       break;
  341.   case 3:                          // Output data
  342.       sprintf(buffer, "> %s", prtText);
  343.       pThis->mMsg.AddString(buffer);
  344.       break;
  345.   }
  346.  
  347. }
  348.  
  349. void AddButtons()
  350. {
  351.     pThis->bInit.EnableWindow(FALSE);
  352.     pThis->bConnect.EnableWindow(TRUE);
  353.     pThis->bRead.EnableWindow(TRUE);
  354.     pThis->bWrite.EnableWindow(TRUE);
  355.     pThis->bWriteProt.EnableWindow(TRUE);
  356.     pThis->bReset.EnableWindow(TRUE);
  357.     if (pThis->rbSLE4432.GetCheck() == 1){
  358.         pThis->bSubmit.EnableWindow(FALSE);
  359.         pThis->bChange.EnableWindow(FALSE);
  360.         pThis->bErrCtr.EnableWindow(FALSE);
  361.     }
  362.     else{
  363.         pThis->bSubmit.EnableWindow(TRUE);
  364.         pThis->bChange.EnableWindow(TRUE);
  365.         pThis->bErrCtr.EnableWindow(TRUE);
  366.     }
  367.    
  368. }
  369.  
  370. int SendAPDUandDisplay(int sendType, CString apduIn)
  371. {
  372.     char buffer[300], tmpStr[300];
  373.     int  indx;
  374.  
  375.     ioRequest.dwProtocol = dwActProtocol;
  376.     ioRequest.cbPciLength = sizeof(SCARD_IO_REQUEST);
  377.     DisplayOut(2, 0, apduIn);
  378.     retCode = SCardTransmit( hCard,
  379.                         &ioRequest,
  380.                         SendBuff,
  381.                         SendLen,
  382.                         NULL,
  383.                         RecvBuff,
  384.                         &RecvLen);
  385.     if (retCode != SCARD_S_SUCCESS)
  386.     {
  387.         DisplayOut(1, retCode, "");
  388.         return retCode;
  389.     }
  390.  
  391.     switch(sendType){
  392.     case 0:                     // Display SW1/SW2 value
  393.         if (!((RecvBuff[RecvLen-2] == 0x90) && (RecvBuff[RecvLen-1] == 0x00)))
  394.             DisplayOut(1, 0, "Return bytes are not acceptable.");
  395.         else{
  396.             strcpy(tmpStr, "");
  397.             for (indx=RecvLen-2; indx<(RecvLen); indx++){
  398.                 sprintf(buffer, "%02X ", RecvBuff[indx] & 0x00FF);
  399.                 strcat(tmpStr, buffer);
  400.             }
  401.         }
  402.         break;
  403.     case 1:                     // Display ATR after checking SW1/SW2
  404.         if (!((RecvBuff[RecvLen-2] == 0x90) && (RecvBuff[RecvLen-1] == 0x00)))
  405.             DisplayOut(1, 0, "Return bytes are not acceptable.");
  406.         else{
  407.             strcpy(tmpStr, "ATR : ");
  408.             for (indx=0; indx<(RecvLen-2); indx++){
  409.                 sprintf(buffer, "%02X ", RecvBuff[indx] & 0x00FF);
  410.                 strcat(tmpStr, buffer);
  411.             }
  412.             sprintf(tmpStr, "%s", tmpStr);
  413.         }
  414.         break;
  415.     case 2:                     // Display all data after checking SW1/SW2
  416.         if (!((RecvBuff[RecvLen-2] == 0x90) && (RecvBuff[RecvLen-1] == 0x00)))
  417.             DisplayOut(1, 0, "Return bytes are not acceptable.");
  418.         else{
  419.             strcpy(tmpStr, "");
  420.             for (indx=0; indx<(RecvLen); indx++){
  421.                 sprintf(buffer, "%02X ", RecvBuff[indx] & 0x00FF);
  422.                 strcat(tmpStr, buffer);
  423.             }
  424.         }
  425.         break;
  426.     }
  427.     DisplayOut(3, 0, tmpStr);
  428.     return retCode;
  429.  
  430. }
  431.  
  432. BOOL InputOK(int checkType)
  433. {
  434.     char tmpStr[257];
  435.     int tmpLen;
  436.  
  437.     switch(checkType){
  438.     case 0:               // for Read function
  439.         tmpLen = pThis->tAdd.GetWindowText(tmpStr, 3);
  440.         if  (tmpLen != 2){
  441.             pThis->tAdd.SetFocus();
  442.             return 0;
  443.         }
  444.         tmpLen = pThis->tLen.GetWindowText(tmpStr, 3);
  445.         if  (tmpLen != 2){
  446.             pThis->tLen.SetFocus();
  447.             return 0;
  448.         }
  449.         break;
  450.     case 1:               // for Write function
  451.         tmpLen = pThis->tAdd.GetWindowText(tmpStr, 3);
  452.         if  (tmpLen != 2){
  453.             pThis->tAdd.SetFocus();
  454.             return 0;
  455.         }
  456.         tmpLen = pThis->tLen.GetWindowText(tmpStr, 3);
  457.         if  (tmpLen != 2){
  458.             pThis->tLen.SetFocus();
  459.             return 0;
  460.         }
  461.         tmpLen = pThis->tData.GetWindowText(tmpStr, 257);
  462.         if  (tmpStr[0] == 0){
  463.             pThis->tData.SetFocus();
  464.             return 0;
  465.         }
  466.         break;
  467.     case 2:               // for Verify function
  468.         pThis->tAdd.Clear();
  469.         pThis->tLen.Clear();
  470.         tmpLen = pThis->tData.GetWindowText(tmpStr, 257);
  471.         if  (tmpLen < 4){
  472.             pThis->tData.SetFocus();
  473.             return 0;
  474.         }
  475.         break;
  476.     }
  477.  
  478.     return 1;
  479.  
  480. }
  481.  
  482. /////////////////////////////////////////////////////////////////////////////
  483. // CSLE4432_4442Dlg message handlers
  484.  
  485. BOOL CSLE4432_4442Dlg::OnInitDialog()
  486. {
  487.     CDialog::OnInitDialog();
  488.  
  489.     // Add "About..." menu item to system menu.
  490.  
  491.     // IDM_ABOUTBOX must be in the system command range.
  492.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  493.     ASSERT(IDM_ABOUTBOX < 0xF000);
  494.  
  495.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  496.     if (pSysMenu != NULL)
  497.     {
  498.         CString strAboutMenu;
  499.         strAboutMenu.LoadString(IDS_ABOUTBOX);
  500.         if (!strAboutMenu.IsEmpty())
  501.         {
  502.             pSysMenu->AppendMenu(MF_SEPARATOR);
  503.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  504.         }
  505.     }
  506.  
  507.     // Set the icon for this dialog.  The framework does this automatically
  508.     //  when the application's main window is not a dialog
  509.     SetIcon(m_hIcon, TRUE);         // Set big icon
  510.     SetIcon(m_hIcon, FALSE);        // Set small icon
  511.    
  512.     // TODO: Add extra initialization here
  513.     pThis = this;
  514.     InitMenu();
  515.    
  516.     return TRUE;  // return TRUE  unless you set the focus to a control
  517. }
  518.  
  519. void CSLE4432_4442Dlg::OnSysCommand(UINT nID, LPARAM lParam)
  520. {
  521.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  522.     {
  523.         CAboutDlg dlgAbout;
  524.         dlgAbout.DoModal();
  525.     }
  526.     else
  527.     {
  528.         CDialog::OnSysCommand(nID, lParam);
  529.     }
  530. }
  531.  
  532. // If you add a minimize button to your dialog, you will need the code below
  533. //  to draw the icon.  For MFC applications using the document/view model,
  534. //  this is automatically done for you by the framework.
  535.  
  536. void CSLE4432_4442Dlg::OnPaint()
  537. {
  538.     if (IsIconic())
  539.     {
  540.         CPaintDC dc(this); // device context for painting
  541.  
  542.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  543.  
  544.         // Center icon in client rectangle
  545.         int cxIcon = GetSystemMetrics(SM_CXICON);
  546.         int cyIcon = GetSystemMetrics(SM_CYICON);
  547.         CRect rect;
  548.         GetClientRect(&rect);
  549.         int x = (rect.Width() - cxIcon + 1) / 2;
  550.         int y = (rect.Height() - cyIcon + 1) / 2;
  551.  
  552.         // Draw the icon
  553.         dc.DrawIcon(x, y, m_hIcon);
  554.     }
  555.     else
  556.     {
  557.         CDialog::OnPaint();
  558.     }
  559. }
  560.  
  561. // The system calls this to obtain the cursor to display while the user drags
  562. //  the minimized window.
  563. HCURSOR CSLE4432_4442Dlg::OnQueryDragIcon()
  564. {
  565.     return (HCURSOR) m_hIcon;
  566. }
  567.  
  568. void CSLE4432_4442Dlg::OnInit()
  569. {
  570.     int nLength = 64;
  571.    
  572.   // 1. Initialize SC reader
  573.   //  1.1. Establish context
  574.     retCode = SCardEstablishContext (SCARD_SCOPE_USER,
  575.                                 NULL,
  576.                                 NULL,
  577.                                 &hContext);
  578.     if (retCode != SCARD_S_SUCCESS)
  579.     {
  580.         DisplayOut(1, retCode, "");
  581.         return;
  582.     }
  583.  
  584.   //  1.2. List PC/SC readers
  585.     size = 256;
  586.     retCode = SCardListReaders (hContext,
  587.                             NULL,
  588.                             readerName,
  589.                             &size);
  590.     if (retCode != SCARD_S_SUCCESS)
  591.     {
  592.         DisplayOut(1, retCode, "");
  593.         return;
  594.     }
  595.     if (readerName == NULL)
  596.     {
  597.         DisplayOut(0, retCode, "No PC/SC reader is detected in your system.");
  598.         return;
  599.     }
  600.    
  601.     int i = 0;
  602.     cbReader.ResetContent();
  603.     char *p = readerName;
  604.     while (*p)
  605.     {
  606.         for (int i=0;p[i];i++);
  607.           i++;
  608.         if (*p != 0)
  609.         {
  610.             cbReader.AddString(p);
  611.         }
  612.         p = &p[i];
  613.     }
  614.     cbReader.SetCurSel(0);
  615.     DisplayOut(0, retCode, "Select Reader and Card to connect.");
  616.     cbReader.EnableWindow(TRUE);
  617.     rbSLE4432.SetCheck(1);
  618.     bConnect.EnableWindow(TRUE);
  619.     bInit.EnableWindow(FALSE);
  620.     bReset.EnableWindow(TRUE);
  621.    
  622. }
  623.  
  624. void CSLE4432_4442Dlg::OnReset()
  625. {
  626.  
  627.     ClearFields();
  628.  
  629.     // Close SC reader
  630.     if (connActive)
  631.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  632.     retCode = SCardReleaseContext(hContext);
  633.     connActive = FALSE;
  634.     InitMenu();
  635.    
  636. }
  637.  
  638. void CSLE4432_4442Dlg::OnQuit()
  639. {
  640.  
  641.     int tmpResult = 0;
  642.  
  643.     // Close SC reader
  644.     if (connActive)
  645.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  646.     retCode = SCardReleaseContext(hContext);
  647.     this->EndDialog(tmpResult);
  648.    
  649. }
  650.  
  651. void CSLE4432_4442Dlg::OnConnect()
  652. {
  653.     int tmpInt = cbReader.GetCurSel();
  654.     CString rName,cardType;
  655.     char buffer[200];
  656.     char tmpStr[128];
  657.  
  658.     if (connActive){
  659.         DisplayOut(0, 0, "Connection is already active.");
  660.         return;
  661.     }
  662.     cbReader.GetLBText(tmpInt, rName);
  663.  
  664.   // 1. Direct Connection
  665.     retCode = SCardConnect(hContext,
  666.                         rName,
  667.                         SCARD_SHARE_DIRECT,
  668.                         0,
  669.                         &hCard,
  670.                         &dwActProtocol);
  671.     if (retCode != SCARD_S_SUCCESS)
  672.     {
  673.         DisplayOut(1, retCode, "");
  674.         return;
  675.     }
  676.  
  677.     // 2. Select Card Type
  678.     ClearBuffers();
  679.     SendLen = 4;
  680.     if (rbSLE4432.GetCheck() == 1){
  681.         SendBuff[0] = 0x11;      // Card Type for SLE4432
  682.         cardType = "SLE 4432";
  683.     }
  684.     else{
  685.         SendBuff[0] = 0x12;      // Card Type for SLE4442
  686.         cardType = "SLE 4442";
  687.     }
  688.     RecvLen = 262;
  689.     retCode = SCardControl(hCard,
  690.                   IOCTL_SMARTCARD_SET_CARD_TYPE,
  691.                   &SendBuff,
  692.                   SendLen,
  693.                   &RecvBuff,
  694.                   RecvLen,
  695.                   &nBytesRet);
  696.     if (retCode != SCARD_S_SUCCESS)
  697.     {
  698.         DisplayOut(1, retCode, "");
  699.         return;
  700.     }
  701.  
  702.     sprintf(buffer, "%s is selected.", cardType);
  703.     DisplayOut(0, 0, buffer);
  704.  
  705.     // 3. Reconnect using SCARD_SHARE_SHARED and
  706.     //    SCARD_PROTOCOL_T0 parameters
  707.     retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  708.     if (retCode != SCARD_S_SUCCESS)
  709.     {
  710.         DisplayOut(1, retCode, "");
  711.         return;
  712.     }
  713.  
  714.     retCode = SCardConnect(hContext,
  715.                         rName,
  716.                         SCARD_SHARE_SHARED,
  717.                         SCARD_PROTOCOL_T0,
  718.                         &hCard,
  719.                         &dwActProtocol);
  720.     if (retCode != SCARD_S_SUCCESS)
  721.     {
  722.         DisplayOut(1, retCode, "");
  723.         connActive = FALSE;
  724.         return;
  725.     }
  726.     sprintf(buffer, "Connected to %s.", rName);
  727.     DisplayOut(0, 0, buffer);
  728.  
  729.     // 4. Get ATR
  730.     DisplayOut(2, 0, "Get ATR");
  731.     ClearBuffers();
  732.     SendBuff[0] = 0xFF;
  733.     SendBuff[1] = 0xA4;
  734.     SendBuff[2] = 0x00;
  735.     SendBuff[3] = 0x00;
  736.     SendBuff[4] = 0x01;
  737.     SendBuff[5] = 0x06;  // SLE4432/4442 value
  738.     SendLen = 6;
  739.     RecvLen = 6;
  740.     strcpy(tmpStr, "");
  741.     for(int i=0; i<SendLen-1; i++){
  742.         sprintf(buffer, "%02X ", SendBuff[i] & 0x00FF);
  743.         strcat(tmpStr, buffer);
  744.     }
  745.     retCode = SendAPDUandDisplay(1, tmpStr);
  746.     if (retCode != SCARD_S_SUCCESS)
  747.         return;
  748.  
  749.     connActive = TRUE;
  750.     AddButtons();
  751.     EnableFields();
  752.  
  753. }
  754.  
  755. void CSLE4432_4442Dlg::OnSLE4418()
  756. {
  757.     ClearFields();
  758.     DisableFields();
  759.     bRead.EnableWindow(FALSE);
  760.     bWrite.EnableWindow(FALSE);
  761.     bChange.EnableWindow(FALSE);
  762.     bWriteProt.EnableWindow(FALSE);
  763.     bSubmit.EnableWindow(FALSE);
  764.     bErrCtr.EnableWindow(FALSE);
  765.    
  766.     if (connActive)
  767.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  768.     connActive = FALSE;
  769.  
  770. }
  771.  
  772. void CSLE4432_4442Dlg::OnEditchangeCombo1()
  773. {
  774.     ClearFields();
  775.     DisableFields();
  776.     bRead.EnableWindow(FALSE);
  777.     bWrite.EnableWindow(FALSE);
  778.     bChange.EnableWindow(FALSE);
  779.     bWriteProt.EnableWindow(FALSE);
  780.     bSubmit.EnableWindow(FALSE);
  781.     bErrCtr.EnableWindow(FALSE);
  782.    
  783.     if (connActive)
  784.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  785.     connActive = FALSE;
  786.  
  787. }
  788.  
  789. void CSLE4432_4442Dlg::OnSLE4428()
  790. {
  791.     ClearFields();
  792.     DisableFields();
  793.     bRead.EnableWindow(FALSE);
  794.     bWrite.EnableWindow(FALSE);
  795.     bChange.EnableWindow(FALSE);
  796.     bWriteProt.EnableWindow(FALSE);
  797.     bSubmit.EnableWindow(FALSE);
  798.     bErrCtr.EnableWindow(FALSE);
  799.    
  800.     if (connActive)
  801.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  802.     connActive = FALSE;
  803.  
  804. }
  805.  
  806. void CSLE4432_4442Dlg::OnRead()
  807. {
  808.     int tmpInt, indx;
  809.     char buffer[256], tmpStr[256];
  810.  
  811.     // 1. Check for all input fields
  812.     if (!InputOK(0))
  813.         return;
  814.    
  815.     // 2. Read input fields and pass data to card
  816.     tData.Clear();
  817.     ClearBuffers();
  818.     tmpInt = 0;
  819.     SendBuff[0] = 0xFF;
  820.     SendBuff[1] = 0xB0;
  821.     SendBuff[2] = 0x00;
  822.  
  823.     tmpInt = 0;
  824.     tAdd.GetWindowText(buffer, 3);
  825.     sscanf(buffer, "%02X", &tmpInt);
  826.     SendBuff[3] = tmpInt;
  827.  
  828.     tmpInt = 0;
  829.     tLen.GetWindowText(buffer, 3);
  830.     sscanf(buffer, "%02X", &tmpInt);
  831.     SendBuff[4] = tmpInt;
  832.    
  833.     SendLen = 5;
  834.     RecvLen = SendBuff[4]+6;
  835.     strcpy(tmpStr, "");
  836.     for(indx=0; indx<5; indx++){
  837.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  838.         strcat(tmpStr, buffer);
  839.     }
  840.     retCode = SendAPDUandDisplay(2, tmpStr);
  841.     if (retCode != SCARD_S_SUCCESS)
  842.         return;
  843.  
  844.     // 3. Display data read from card into Data textbox
  845.     strcpy(tmpStr, "");
  846.     for(indx=0; indx<SendBuff[4]; indx++){
  847.         sprintf(buffer, "%c", RecvBuff[indx] & 0xFF);
  848.         strcat(tmpStr, buffer);
  849.     }
  850.     tData.SetWindowText(tmpStr);
  851. }
  852.  
  853. void CSLE4432_4442Dlg::OnReadProt()
  854. {
  855.     int tmpInt, indx;
  856.     char buffer[256], tmpStr[256], tmpByte[2];
  857.  
  858.     // 1. Check for all input fields
  859.     if (!InputOK(2))
  860.         return;
  861.    
  862.     // 2. Read input fields and pass data to card
  863.     // 2. Read input fields and pass data to card
  864.     ClearBuffers();
  865.     tmpInt = 0;
  866.     SendBuff[0] = 0xFF;
  867.     SendBuff[1] = 0xD2;
  868.     SendBuff[2] = 0x00;
  869.     SendBuff[3] = 0x01;
  870.     SendBuff[4] = 0x03;
  871.  
  872.     tmpInt = 0;
  873.     tData.GetWindowText(buffer, 7);
  874.     memcpy(tmpByte, buffer, 2);
  875.     sscanf(tmpByte, "%02X", &SendBuff[5]);
  876.     memcpy(tmpByte, buffer+2, 2);
  877.     sscanf(tmpByte, "%02X", &SendBuff[6]);
  878.     memcpy(tmpByte, buffer+4, 2);
  879.     sscanf(tmpByte, "%02X", &SendBuff[7]);
  880.     SendLen = 5 + SendBuff[4];
  881.     RecvLen = 2;
  882.     strcpy(tmpStr, "");
  883.     for(indx=0; indx<SendLen; indx++){
  884.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  885.         strcat(tmpStr, buffer);
  886.     }
  887.     retCode = SendAPDUandDisplay(2, tmpStr);
  888.     if (retCode != SCARD_S_SUCCESS)
  889.         return;
  890.  
  891.     tData.SetWindowText("");
  892.  
  893. }
  894.  
  895. void CSLE4432_4442Dlg::OnWrite()
  896. {
  897.     int tmpInt, indx;
  898.     char buffer[256], tmpStr[256];
  899.  
  900.     // 1. Check for all input fields
  901.     if (!InputOK(1))
  902.         return;
  903.    
  904.     // 2. Read input fields and pass data to card
  905.     ClearBuffers();
  906.     tmpInt = 0;
  907.     SendBuff[0] = 0xFF;
  908.     SendBuff[1] = 0xD0;
  909.     SendBuff[2] = 0x00;
  910.  
  911.     tmpInt = 0;
  912.     tAdd.GetWindowText(buffer, 3);
  913.     sscanf(buffer, "%02X", &tmpInt);
  914.     SendBuff[3] = tmpInt;
  915.  
  916.     tmpInt = 0;
  917.     tLen.GetWindowText(buffer, 3);
  918.     sscanf(buffer, "%02X", &tmpInt);
  919.     SendBuff[4] = tmpInt;
  920.    
  921.     tData.GetWindowText(buffer, SendBuff[4]+1);
  922.     for (indx =0;indx<SendBuff[4];indx++)
  923.         SendBuff[indx + 5] = buffer[indx];
  924.     SendLen = 5 + SendBuff[4];
  925.     RecvLen = 2;
  926.     strcpy(tmpStr, "");
  927.     for(indx=0; indx<SendLen; indx++){
  928.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  929.         strcat(tmpStr, buffer);
  930.     }
  931.     retCode = SendAPDUandDisplay(0, tmpStr);
  932.     if (retCode != SCARD_S_SUCCESS)
  933.         return;
  934.     tData.SetWindowText("");
  935.    
  936. }
  937.  
  938. void CSLE4432_4442Dlg::OnSubmit()
  939. {
  940.  
  941.     int tmpInt, indx;
  942.     char buffer[256], tmpStr[256], tmpByte[2];
  943.  
  944.     // 1. Check for all input fields
  945.     if (!InputOK(2))
  946.         return;
  947.    
  948.     // 2. Read input fields and pass data to card
  949.     ClearBuffers();
  950.     tmpInt = 0;
  951.     SendBuff[0] = 0xFF;
  952.     SendBuff[1] = 0x20;
  953.     SendBuff[2] = 0x00;
  954.     SendBuff[3] = 0x00;
  955.     SendBuff[4] = 0x03;
  956.  
  957.     tmpInt = 0;
  958.     tData.GetWindowText(buffer, 7);
  959.     memcpy(tmpByte, buffer, 2);
  960.     sscanf(tmpByte, "%02X", &SendBuff[5]);
  961.     memcpy(tmpByte, buffer+2, 2);
  962.     sscanf(tmpByte, "%02X", &SendBuff[6]);
  963.     memcpy(tmpByte, buffer+4, 2);
  964.     sscanf(tmpByte, "%02X", &SendBuff[7]);
  965.     SendLen = 5 + SendBuff[4];
  966.     RecvLen = 6;
  967.     strcpy(tmpStr, "");
  968.     for(indx=0; indx<SendLen; indx++){
  969.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  970.         strcat(tmpStr, buffer);
  971.     }
  972.     retCode = SendAPDUandDisplay(2, tmpStr);
  973.     if (retCode != SCARD_S_SUCCESS)
  974.         return;
  975.  
  976.     tData.SetWindowText("");
  977.  
  978. }
  979.  
  980. void CSLE4432_4442Dlg::OnErrCtr()
  981. {
  982.  
  983.     int tmpInt, indx;
  984.     char buffer[256], tmpStr[256];
  985.  
  986.     // 1. Clear all input fields
  987.     ClearFields();
  988.    
  989.   // 2. Send all inputs to the card
  990.     ClearBuffers();
  991.     tmpInt = 0;
  992.     SendBuff[0] = 0xFF;
  993.     SendBuff[1] = 0xB1;
  994.     SendBuff[2] = 0x00;
  995.     SendBuff[3] = 0x00;
  996.     SendBuff[4] = 0x00;
  997.  
  998.     SendLen = 5;
  999.     RecvLen = 6;
  1000.     strcpy(tmpStr, "");
  1001.     for(indx=0; indx<SendLen; indx++){
  1002.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  1003.         strcat(tmpStr, buffer);
  1004.     }
  1005.     retCode = SendAPDUandDisplay(2, tmpStr);
  1006.     if (retCode != SCARD_S_SUCCESS)
  1007.         return;
  1008.  
  1009. }
  1010.  
  1011. void CSLE4432_4442Dlg::OnWriteProt()
  1012. {
  1013.     int tmpInt, indx;
  1014.     char buffer[256], tmpStr[256];
  1015.  
  1016.     // 1. Check for all input fields
  1017.     if (!InputOK(1))
  1018.         return;
  1019.    
  1020.     // 2. Read input fields and pass data to card
  1021.     ClearBuffers();
  1022.     tmpInt = 0;
  1023.     SendBuff[0] = 0xFF;
  1024.     SendBuff[1] = 0xD1;
  1025.     SendBuff[2] = 0x00;
  1026.  
  1027.     tmpInt = 0;
  1028.     tAdd.GetWindowText(buffer, 3);
  1029.     sscanf(buffer, "%02X", &tmpInt);
  1030.     SendBuff[3] = tmpInt;
  1031.  
  1032.     tmpInt = 0;
  1033.     tLen.GetWindowText(buffer, 3);
  1034.     sscanf(buffer, "%02X", &tmpInt);
  1035.     SendBuff[4] = tmpInt;
  1036.    
  1037.     tData.GetWindowText(buffer, SendBuff[4]+1);
  1038.     for (indx =0;indx<SendBuff[4];indx++)
  1039.         SendBuff[indx + 5] = buffer[indx];
  1040.     SendLen = 5 + SendBuff[4];
  1041.     RecvLen = 2;
  1042.     strcpy(tmpStr, "");
  1043.     for(indx=0; indx<SendLen; indx++){
  1044.         sprintf(buffer, "%02X ", SendBuff[indx] & 0x00FF);
  1045.         strcat(tmpStr, buffer);
  1046.     }
  1047.     retCode = SendAPDUandDisplay(0, tmpStr);
  1048.     if (retCode != SCARD_S_SUCCESS)
  1049.         return;
  1050.  
  1051.     tData.SetWindowText("");
  1052.    
  1053. }
  1054.  
  1055. void CSLE4432_4442Dlg::OnSelchangeCombo1()
  1056. {
  1057.     ClearFields();
  1058.     DisableFields();
  1059.     bRead.EnableWindow(FALSE);
  1060.     bWrite.EnableWindow(FALSE);
  1061.     bChange.EnableWindow(FALSE);
  1062.     bWriteProt.EnableWindow(FALSE);
  1063.     bSubmit.EnableWindow(FALSE);
  1064.     bErrCtr.EnableWindow(FALSE);
  1065.    
  1066.     if (connActive)
  1067.         retCode = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  1068.     connActive = FALSE;
  1069.  
  1070. }