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.

808 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: ScInsDlg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // ScInsDlg.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include <atlconv.h>
  14. #include "resource.h"
  15. #include "scdlg.h"
  16. #include "ScSearch.h"
  17. #include "ScInsDlg.h"
  18. #include "statmon.h"
  19. #include "scHlpArr.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CScInsertDlg dialog
  27. CScInsertDlg::CScInsertDlg(CWnd* pParent/*=NULL*/)
  28. : CDialog(CScInsertDlg::IDD, pParent)
  29. {
  30. // Member Initialization
  31. m_lLastError = SCARD_S_SUCCESS;
  32. m_ParentHwnd = pParent;
  33. m_pOCNW = NULL;
  34. m_pOCNA = NULL;
  35. m_pSelectedReader = NULL;
  36. m_pSubDlg = NULL;
  37. m_strTitle.Empty();
  38. m_strPrompt.Empty();
  39. m_mstrAllCards = "";
  40. //{{AFX_DATA_INIT(CScInsertDlg)
  41. // NOTE: the ClassWizard will add member initialization here
  42. //}}AFX_DATA_INIT
  43. }
  44. CScInsertDlg::~CScInsertDlg()
  45. {
  46. // Stop status monitor
  47. m_monitor.Stop();
  48. // Clean up status list!
  49. if (0 != m_aReaderState.GetSize())
  50. {
  51. for (int i = (int)m_aReaderState.GetUpperBound(); i>=0; i--)
  52. {
  53. delete m_aReaderState[i];
  54. }
  55. m_aReaderState.RemoveAll();
  56. }
  57. }
  58. void CScInsertDlg::DoDataExchange(CDataExchange* pDX)
  59. {
  60. CDialog::DoDataExchange(pDX);
  61. //{{AFX_DATA_MAP(CScInsertDlg)
  62. DDX_Control(pDX, IDC_DETAILS, m_btnDetails);
  63. //}}AFX_DATA_MAP
  64. }
  65. BEGIN_MESSAGE_MAP(CScInsertDlg, CDialog)
  66. //{{AFX_MSG_MAP(CScInsertDlg)
  67. ON_MESSAGE( WM_READERSTATUSCHANGE, OnReaderStatusChange )
  68. ON_BN_CLICKED(IDC_DETAILS, OnDetails)
  69. ON_WM_HELPINFO()
  70. ON_WM_CONTEXTMENU()
  71. //}}AFX_MSG_MAP
  72. END_MESSAGE_MAP()
  73. /////////////////////////////////////////////////////////////////////////////
  74. // CScInsertDlg data methods
  75. /*++
  76. LONG Initialize:
  77. Stores the open card name pointer in the proper internal struct.
  78. Determines whether to show the dialog in details or brief mode.
  79. Arguments:
  80. pOCN(x) - pointer to an open card name ex struct
  81. Return Value:
  82. A LONG value indicating the status of the requested action. Please
  83. see the Smartcard header files for additional information.
  84. Author:
  85. Amanda Matlosz 07/09/1998
  86. --*/
  87. // ANSI
  88. LONG CScInsertDlg::Initialize(LPOPENCARDNAMEA_EX pOCNA, DWORD dwNumOKCards, LPCSTR mszOKCards)
  89. {
  90. _ASSERTE(NULL != pOCNA);
  91. if (NULL == pOCNA)
  92. {
  93. return SCARD_F_UNKNOWN_ERROR;
  94. }
  95. m_pOCNA = pOCNA;
  96. m_strTitle = m_pOCNA->lpstrTitle;
  97. m_strPrompt = m_pOCNA->lpstrSearchDesc;
  98. m_mstrAllCards = mszOKCards;
  99. m_hIcon = pOCNA->hIcon;
  100. // hide details if no suitable cards available, else show details
  101. m_fDetailsShown = (0==dwNumOKCards) ? FALSE : TRUE;
  102. // prepare critical section for UI routines
  103. m_pCritSec = new CCriticalSection();
  104. if (NULL == m_pCritSec)
  105. {
  106. return ERROR_OUTOFMEMORY; // TODO: is another errorcode more appropriate?
  107. }
  108. // put dialog on top
  109. SetForegroundWindow();
  110. return SCARD_S_SUCCESS;
  111. }
  112. //UNICODE
  113. HRESULT CScInsertDlg::Initialize(LPOPENCARDNAMEW_EX pOCNW, DWORD dwNumOKCards, LPCWSTR mszOKCards)
  114. {
  115. _ASSERTE(NULL != pOCNW);
  116. if (NULL == pOCNW)
  117. {
  118. return SCARD_F_UNKNOWN_ERROR;
  119. }
  120. m_pOCNW = pOCNW;
  121. m_strTitle = m_pOCNW->lpstrTitle;
  122. m_strPrompt = m_pOCNW->lpstrSearchDesc;
  123. m_mstrAllCards = mszOKCards;
  124. m_hIcon = pOCNW->hIcon;
  125. // hide details if no suitable cards available, else show details
  126. m_fDetailsShown = (0==dwNumOKCards) ? FALSE : TRUE;
  127. // prepare critical section for UI routines
  128. m_pCritSec = new CCriticalSection();
  129. if (NULL == m_pCritSec)
  130. {
  131. return ERROR_OUTOFMEMORY; // TODO: is another errorcode more appropriate?
  132. }
  133. // put dialog on top
  134. SetForegroundWindow();
  135. return SCARD_S_SUCCESS;
  136. }
  137. void CScInsertDlg::EnableOK(BOOL fEnabled)
  138. {
  139. CButton* pBtn = (CButton*)GetDlgItem(IDOK);
  140. _ASSERTE(NULL != pBtn);
  141. pBtn->EnableWindow(fEnabled);
  142. //
  143. // Change prompt text accordingly and set the OK button
  144. // to be default if it's enabled
  145. //
  146. CString strPrompt;
  147. if (fEnabled)
  148. {
  149. strPrompt.LoadString(IDS_SC_FOUND);
  150. // set <OK> default, remove <Cancel> default
  151. pBtn->SetButtonStyle(BS_DEFPUSHBUTTON);
  152. pBtn = (CButton*)GetDlgItem(IDCANCEL);
  153. _ASSERTE(NULL != pBtn);
  154. pBtn->SetButtonStyle(BS_PUSHBUTTON);
  155. pBtn = (CButton*)GetDlgItem(IDC_DETAILS); // details can sometimes get set to default
  156. _ASSERTE(NULL != pBtn);
  157. pBtn->SetButtonStyle(BS_PUSHBUTTON);
  158. }
  159. else
  160. {
  161. _ASSERTE(!m_strPrompt.IsEmpty());
  162. strPrompt = m_strPrompt;
  163. // remove <OK> default, set <Cancel> default
  164. pBtn->SetButtonStyle(BS_PUSHBUTTON);
  165. pBtn = (CButton*)GetDlgItem(IDCANCEL);
  166. _ASSERTE(NULL != pBtn);
  167. pBtn->SetButtonStyle(BS_DEFPUSHBUTTON);
  168. pBtn = (CButton*)GetDlgItem(IDC_DETAILS); // details can sometimes get set to default
  169. _ASSERTE(NULL != pBtn);
  170. pBtn->SetButtonStyle(BS_PUSHBUTTON);
  171. }
  172. CWnd* pDlgItem = GetDlgItem(IDC_PROMPT);
  173. _ASSERTE(NULL != pDlgItem);
  174. pDlgItem->SetWindowText(strPrompt);
  175. }
  176. void CScInsertDlg::DisplayError(UINT uiErrorMsg)
  177. {
  178. CString strTitle, strMsg;
  179. strTitle.LoadString(IDS_SC_TITLE_ERROR);
  180. strMsg.LoadString(uiErrorMsg);
  181. MessageBox(strMsg, strTitle, MB_OK | MB_ICONEXCLAMATION);
  182. }
  183. void CScInsertDlg::SetSelection(CSCardReaderState* pRdrSt)
  184. {
  185. m_pSelectedReader = pRdrSt;
  186. EnableOK(IsSelectionOK());
  187. }
  188. BOOL CScInsertDlg::SameCard(CSCardReaderState* p1, CSCardReaderState* p2)
  189. {
  190. _ASSERTE(NULL != p1);
  191. _ASSERTE(NULL != p2);
  192. if ((NULL == p1) && (NULL == p2))
  193. {
  194. return TRUE;
  195. }
  196. if ((NULL == p1) || (NULL == p2))
  197. {
  198. return FALSE;
  199. }
  200. // same reader & card?
  201. if ((0 == p1->strReader.Compare(p2->strReader)) &&
  202. (0 == p1->strCard.Compare(p2->strCard)))
  203. {
  204. // no drastic state change?
  205. if(p1->dwState == p2->dwState)
  206. {
  207. return TRUE;
  208. }
  209. if(((p1->dwState == SC_SATATUS_AVAILABLE) ||
  210. (p1->dwState == SC_STATUS_SHARED) ||
  211. (p1->dwState == SC_STATUS_EXCLUSIVE)) &&
  212. ((p2->dwState == SC_SATATUS_AVAILABLE) ||
  213. (p2->dwState == SC_STATUS_SHARED) ||
  214. (p2->dwState == SC_STATUS_EXCLUSIVE)) )
  215. {
  216. return TRUE;
  217. }
  218. }
  219. return FALSE;
  220. }
  221. /////////////////////////////////////////////////////////////////////////////
  222. // CScInsertDlg message handlers
  223. /*++
  224. void ShowHelp:
  225. Helper function for OnHelpInfo and OnContextMenu.
  226. BOOL OnHelpInfo:
  227. Called by the MFC framework when the user hits F1.
  228. void OnContextMenu
  229. Called by the MFC framework when the user right-clicks.
  230. Author:
  231. Amanda Matlosz 03/04/1999
  232. Note:
  233. These three functions work together to provide context-sensitive
  234. help for the insertdlg. Similar functions are declared for
  235. CScInsertBar
  236. --*/
  237. void CScInsertDlg::ShowHelp(HWND hWnd, UINT nCommand)
  238. {
  239. ::WinHelp(hWnd, _T("SCardDlg.hlp"), nCommand, (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_SCARDDLG1);
  240. }
  241. afx_msg BOOL CScInsertDlg::OnHelpInfo(LPHELPINFO lpHelpInfo)
  242. {
  243. _ASSERTE(NULL != lpHelpInfo);
  244. ShowHelp((HWND)lpHelpInfo->hItemHandle, HELP_WM_HELP);
  245. return TRUE;
  246. }
  247. afx_msg void CScInsertDlg::OnContextMenu(CWnd* pWnd, CPoint pt)
  248. {
  249. _ASSERTE(NULL != pWnd);
  250. ShowHelp(pWnd->m_hWnd, HELP_CONTEXTMENU);
  251. }
  252. /*++
  253. void OnReaderStatusChange:
  254. This message handler is called by the status thread when smartcard status
  255. has changed.
  256. Arguments:
  257. None.
  258. Return Value:
  259. IGNORED BY CALLER. Long indicating status of ResMgr calls.
  260. Author:
  261. Amanda Matlosz 07/09/1998
  262. Note:
  263. No formal parameters are declared. These are not used and
  264. will stop compiler warnings from being generated.
  265. The long param takes the result of no_service or stopped
  266. --*/
  267. LONG CScInsertDlg::OnReaderStatusChange(UINT uint, LONG lParam)
  268. {
  269. // Is monitor still alive?
  270. CScStatusMonitor::status status = m_monitor.GetStatus();
  271. if (CScStatusMonitor::running != status)
  272. {
  273. m_pSubDlg->EnableStatusList(FALSE);
  274. SetSelection(NULL); // JIC
  275. // display appropriate error & set m_lLastError
  276. switch(status)
  277. {
  278. case CScStatusMonitor::no_service:
  279. case CScStatusMonitor::stopped:
  280. m_lLastError = lParam;
  281. DisplayError(IDS_SC_RM_ERR);
  282. break;
  283. case CScStatusMonitor::no_readers:
  284. m_lLastError = SCARD_E_NO_READERS_AVAILABLE;
  285. DisplayError(IDS_SC_NO_READERS);
  286. break;
  287. default:
  288. m_lLastError = SCARD_F_UNKNOWN_ERROR;
  289. DisplayError(IDS_UNKNOWN_ERROR);
  290. break;
  291. }
  292. }
  293. else
  294. {
  295. // crit section around member reader/card status array
  296. _ASSERTE(m_pCritSec);
  297. if (m_pCritSec)
  298. {
  299. m_pCritSec->Lock();
  300. }
  301. // make local copy of recent reader state array,
  302. // so we know which cards have already been checked
  303. CSCardReaderStateArray aPreviousReaderState;
  304. aPreviousReaderState.RemoveAll();
  305. for (int nCopy = (int)m_aReaderState.GetUpperBound(); nCopy>=0; nCopy--)
  306. {
  307. CSCardReaderState* pReader = NULL;
  308. pReader = new CSCardReaderState(m_aReaderState[nCopy]);
  309. if (NULL != pReader)
  310. {
  311. aPreviousReaderState.Add(pReader);
  312. }
  313. }
  314. // udpate array from CStatusMonitor
  315. // check cards that have not been previously checked,
  316. // & update UI
  317. m_monitor.GetReaderStatus(m_aReaderState);
  318. for (int n = (int)m_aReaderState.GetUpperBound(); n>=0; n--)
  319. {
  320. CSCardReaderState* pReader = m_aReaderState[n];
  321. BOOL fAlreadyChecked = FALSE;
  322. // have we checked this card before?
  323. for (int nPrev = (int)aPreviousReaderState.GetUpperBound();
  324. (nPrev>=0 && !fAlreadyChecked);
  325. nPrev--)
  326. {
  327. if (SameCard(pReader, aPreviousReaderState[nPrev]))
  328. {
  329. pReader->fOK = (aPreviousReaderState[nPrev])->fOK;
  330. fAlreadyChecked = TRUE;
  331. }
  332. }
  333. // if this is a new card, or if the card's status has changed
  334. // drastically since we last looked at it, check it again
  335. if (!fAlreadyChecked)
  336. {
  337. if (NULL != m_pOCNW)
  338. {
  339. m_aReaderState[n]->fOK = CheckCardAll(
  340. m_aReaderState[n],
  341. m_pOCNW,
  342. (LPCWSTR)m_mstrAllCards);
  343. }
  344. else
  345. {
  346. _ASSERTE(NULL != m_pOCNA);
  347. m_aReaderState[n]->fOK = CheckCardAll(
  348. m_aReaderState[n],
  349. m_pOCNA,
  350. (LPCWSTR)m_mstrAllCards);
  351. }
  352. }
  353. }
  354. // the subdialog will handle automatic reader selection
  355. m_pSubDlg->UpdateStatusList(&m_aReaderState);
  356. // clean up
  357. for (int nX = (int)aPreviousReaderState.GetUpperBound(); nX>=0; nX--)
  358. {
  359. delete aPreviousReaderState[nX];
  360. }
  361. aPreviousReaderState.RemoveAll();
  362. // end crit section
  363. if (m_pCritSec)
  364. {
  365. m_pCritSec->Unlock();
  366. }
  367. }
  368. return (long)SCARD_S_SUCCESS; // there's no one to receive this.
  369. }
  370. void CScInsertDlg::OnDetails()
  371. {
  372. //
  373. // If the details are currently shown, hide them...
  374. // otherwise, show them.
  375. //
  376. CRect rectWin;
  377. GetWindowRect(&rectWin);
  378. CRect rectButtonBottom;
  379. CString strDetailsCaption;
  380. //
  381. // Determine the new height of the dialog & resize
  382. //
  383. int nNewHeight = 0;
  384. if (m_fDetailsShown)
  385. {
  386. nNewHeight = m_SmallHeight;
  387. strDetailsCaption.LoadString(IDS_DETAILS_SHOW);
  388. }
  389. else
  390. {
  391. nNewHeight = m_BigHeight;
  392. strDetailsCaption.LoadString(IDS_DETAILS_HIDE);
  393. }
  394. ScreenToClient(&rectButtonBottom);
  395. rectWin.bottom = rectWin.top + nNewHeight;
  396. SetWindowPos(NULL,
  397. rectWin.left,
  398. rectWin.top,
  399. rectWin.Width(),
  400. rectWin.Height(),
  401. SWP_NOMOVE | SWP_NOZORDER);
  402. //
  403. // change captions, move buttons, show or hide the details section
  404. //
  405. m_btnDetails.SetWindowText(strDetailsCaption);
  406. MoveButton(IDC_DETAILS, nNewHeight - m_yMargin);
  407. MoveButton(IDOK, nNewHeight - m_yMargin);
  408. MoveButton(IDCANCEL, nNewHeight - m_yMargin);
  409. ToggleSubDialog();
  410. //
  411. // remember our new state
  412. //
  413. m_fDetailsShown = !m_fDetailsShown;
  414. }
  415. BOOL CScInsertDlg::OnInitDialog()
  416. {
  417. CDialog::OnInitDialog();
  418. //
  419. // Initialize bits to query RM; if these fail, there's no point to go on
  420. // but the user should see an error message.
  421. //
  422. // kick off CSCStatusMonitor
  423. m_lLastError = m_monitor.Start(m_hWnd, WM_READERSTATUSCHANGE);
  424. // if not running or no readers available
  425. CScStatusMonitor::status status = m_monitor.GetStatus();
  426. if (SCARD_S_SUCCESS != m_lLastError)
  427. {
  428. switch(status)
  429. {
  430. case CScStatusMonitor::no_service:
  431. DisplayError(IDS_SC_RM_ERR);
  432. break;
  433. case CScStatusMonitor::no_readers:
  434. // DisplayError(IDS_SC_NO_READERS); // Bug 15742 -> will die quietly (no UI)
  435. break;
  436. case CScStatusMonitor::running:
  437. _ASSERTE(FALSE); // How can this be running if an error was returned??????
  438. // no break; go ahead an report an 'unknown error'
  439. default:
  440. DisplayError(IDS_UNKNOWN_ERROR);
  441. break;
  442. }
  443. PostMessage(WM_CLOSE, 0, 0);
  444. return TRUE;
  445. }
  446. _ASSERTE(status == CScStatusMonitor::running);
  447. //
  448. // Determine constant offsets for resizing window (on details)
  449. //
  450. CRect rectWin, rectDlgItem;
  451. GetWindowRect(&rectWin);
  452. m_SmallHeight = rectWin.Height();
  453. CWnd* pDlgItem = GetDlgItem(IDOK);
  454. _ASSERTE(NULL != pDlgItem);
  455. pDlgItem->GetWindowRect(&rectDlgItem);
  456. ScreenToClient(rectDlgItem);
  457. m_yMargin = m_SmallHeight - rectDlgItem.bottom;
  458. pDlgItem = GetDlgItem(IDC_BUTTON_BOTTOM);
  459. _ASSERTE(NULL != pDlgItem);
  460. pDlgItem->GetWindowRect(&rectDlgItem);
  461. ScreenToClient(rectDlgItem);
  462. m_BigHeight = rectDlgItem.bottom + m_yMargin;
  463. //
  464. // Add user-provided or ReaderLoaded icon
  465. //
  466. if (NULL == m_hIcon)
  467. {
  468. m_hIcon = AfxGetApp()->LoadIcon(IDI_SC_READERLOADED_V2);
  469. }
  470. _ASSERTE(NULL != m_hIcon);
  471. pDlgItem = GetDlgItem(IDC_USERICON);
  472. _ASSERTE(NULL != pDlgItem);
  473. pDlgItem->SetIcon(m_hIcon, TRUE); // TRUE: 32x32 icon
  474. //
  475. // Add other User-Customization bits
  476. //
  477. if (!m_strTitle.IsEmpty())
  478. {
  479. SetWindowText(m_strTitle);
  480. }
  481. if (m_strPrompt.IsEmpty())
  482. {
  483. // Use the default prompt text.
  484. m_strPrompt.LoadString(IDS_SC_PROMPT_ANYCARD);
  485. }
  486. pDlgItem = GetDlgItem(IDC_PROMPT);
  487. _ASSERTE(NULL != pDlgItem);
  488. pDlgItem->SetWindowText(m_strPrompt);
  489. // by default, <OK> is not enabled (subdlg's OnInitDlg might change that)
  490. EnableOK(FALSE);
  491. //
  492. // Set HELP ID(s) for context help
  493. //
  494. pDlgItem = GetDlgItem(IDC_DETAILS);
  495. _ASSERTE(NULL != pDlgItem);
  496. pDlgItem->SetWindowContextHelpId(IDH_DLG1_DETAILS_BTN);
  497. //
  498. // Add CScInsertBar (actually, a CDialog-derivative) to our dialog
  499. //
  500. pDlgItem = GetDlgItem(IDC_DLGBAR);
  501. _ASSERTE(NULL != pDlgItem);
  502. pDlgItem->GetWindowRect(&rectDlgItem);
  503. ScreenToClient(rectDlgItem);
  504. m_pSubDlg = new CScInsertBar(this);
  505. _ASSERTE(NULL != m_pSubDlg);
  506. if (NULL == m_pSubDlg)
  507. {
  508. m_lLastError = ERROR_OUTOFMEMORY;
  509. PostMessage(WM_CLOSE, 0, 0);
  510. return TRUE;
  511. }
  512. m_pSubDlg->Create(IDD_SCARDDLG_BAR, this);
  513. m_pSubDlg->SetWindowPos(NULL,
  514. rectDlgItem.left,
  515. rectDlgItem.top,
  516. 0,
  517. 0,
  518. SWP_NOSIZE | SWP_NOACTIVATE); // TODO: SWP_NOZORDER ??
  519. //
  520. // Set the dialog to alter itself to match how it was called
  521. //
  522. m_fDetailsShown = !m_fDetailsShown;
  523. OnDetails();
  524. if (m_fDetailsShown)
  525. {
  526. return FALSE; // focus should be set to list control
  527. }
  528. return TRUE; // return TRUE unless you set the focus to a control
  529. // EXCEPTION: OCX Property Pages should return FALSE
  530. }
  531. void CScInsertDlg::MoveButton(UINT nID, int newBottom)
  532. {
  533. CWnd* pBtn = GetDlgItem(nID);
  534. _ASSERTE(NULL != pBtn);
  535. CRect rect;
  536. pBtn->GetWindowRect(&rect);
  537. ScreenToClient(&rect);
  538. rect.top = newBottom - rect.Height();
  539. pBtn->SetWindowPos(NULL,
  540. rect.left,
  541. rect.top,
  542. 0,
  543. 0,
  544. SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
  545. }
  546. void CScInsertDlg::ToggleSubDialog()
  547. {
  548. //
  549. // All you need to do to toggle the sub dialog's accessibility
  550. // is to hide&disable or show&enable the window.
  551. //
  552. if (m_fDetailsShown)
  553. {
  554. m_pSubDlg->ShowWindow(SW_HIDE);
  555. m_pSubDlg->EnableWindow(FALSE);
  556. }
  557. else
  558. {
  559. m_pSubDlg->ShowWindow(SW_SHOW);
  560. m_pSubDlg->EnableWindow(TRUE);
  561. }
  562. }
  563. BOOL CScInsertDlg::DestroyWindow()
  564. {
  565. if (NULL != m_pSubDlg)
  566. {
  567. m_pSubDlg->DestroyWindow();
  568. delete m_pSubDlg;
  569. }
  570. return CDialog::DestroyWindow();
  571. }
  572. /*++
  573. void OnOK:
  574. Handle user's <OK>, error if can't complete
  575. Arguments:
  576. None.
  577. Return Value:
  578. None
  579. Author:
  580. Amanda Matlosz 4/28/98
  581. --*/
  582. void CScInsertDlg::OnOK()
  583. {
  584. USES_CONVERSION;
  585. // Must have something selected to exit
  586. if (NULL == m_pSelectedReader || m_pSelectedReader->strCard.IsEmpty())
  587. {
  588. DisplayError(IDS_SC_SELECT);
  589. return;
  590. }
  591. // Must have selected something we're looking for...
  592. if (!(m_pSelectedReader->fOK))
  593. {
  594. DisplayError(IDS_SC_NOMATCH);
  595. return;
  596. }
  597. // Call the correct method to set the *real* card selection
  598. if(NULL != m_pOCNA)
  599. {
  600. LPSTR szCard = W2A(m_pSelectedReader->strCard);
  601. LPSTR szReader = W2A(m_pSelectedReader->strReader);
  602. m_lLastError = SetFinalCardSelection(szReader, szCard, m_pOCNA);
  603. }
  604. else
  605. {
  606. _ASSERTE(NULL != m_pOCNW);
  607. LPWSTR szCard = m_pSelectedReader->strCard.GetBuffer(1);
  608. LPWSTR szReader = m_pSelectedReader->strReader.GetBuffer(1);
  609. m_lLastError = SetFinalCardSelection(szReader, szCard, m_pOCNW);
  610. m_pSelectedReader->strCard.ReleaseBuffer();
  611. m_pSelectedReader->strReader.ReleaseBuffer();
  612. }
  613. if (SCARD_S_SUCCESS != m_lLastError)
  614. {
  615. DisplayError(IDS_SC_CONNECT_FAILED); // Either connect failed or out of memory - close enough.
  616. return;
  617. }
  618. CDialog::OnOK();
  619. }