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.

1557 lines
31 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. SEnv
  5. Abstract:
  6. This file contains the outline implementation of the Smartcard Common
  7. dialog CSCardEnv class. This class encapsulates current Smartcard
  8. environment information (i.e. given groups, readers, cards, etc.)
  9. Author:
  10. Chris Dudley 3/3/1997
  11. Environment:
  12. Win32, C++ w/Exceptions, MFC
  13. Revision History:
  14. Chris Dudley (cdudley) 4/15/97
  15. Amanda Matlosz (amatlosz) 1/29/98 Combined CSCardEnv and CSCardGroup,
  16. added unicode support
  17. Notes:
  18. --*/
  19. /////////////////////////////////////////////////////////////////////////////
  20. //
  21. // Includes
  22. //
  23. #include "stdafx.h"
  24. #include "senv.h"
  25. #include <querydb.h>
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. // local macros
  32. #ifdef _DEBUG
  33. #define TRACE_STR(name,sz) \
  34. TRACE(_T("CmnUILb.lib: %s: %s\n"), name, sz)
  35. #define TRACE_CODE(name,code) \
  36. TRACE(_T("CmnUILb.lib: %s: error = 0x%x\n"), name, code)
  37. #define TRACE_CATCH(name,code) TRACE_CODE(name,code)
  38. #define TRACE_CATCH_UNKNOWN(name) TRACE_STR(name,_T("An unidentified exception has occurred!"))
  39. #else
  40. #define TRACE_STR(name,sz) ((void)0)
  41. #define TRACE_CODE(name,code) ((void)0)
  42. #define TRACE_CATCH(name,code) ((void)0)
  43. #define TRACE_CATCH_UNKNOWN(name) ((void)0)
  44. #endif // _DEBUG
  45. /////////////////////////////////////////////////////////////////////////////
  46. //
  47. // CSCardEnv Implementation
  48. //
  49. /*++
  50. GetDialogTitle:
  51. Routine returns a new title for the dialog if needed
  52. Arguments:
  53. pstzTitle -- pointer to a CTextString to contain the dialog's title
  54. Return Value:
  55. A CTextString object containing the new dialog text or empty string
  56. if no new title required.
  57. Author:
  58. Chris Dudley 3/3/1997
  59. Revisions:
  60. Amanda Matlosz 1/28/98 Add unicode support/code cleanup
  61. Notes:
  62. --*/
  63. void CSCardEnv::GetDialogTitle( CTextString *pstzTitle )
  64. {
  65. // check & empty params
  66. ASSERT(NULL != pstzTitle);
  67. pstzTitle->Clear();
  68. *pstzTitle = m_strTitle;
  69. }
  70. /*++
  71. LONG CardMeetsSearchCriteria:
  72. Routine determines if a selected reader has a card inserted which
  73. meets the search criteria defined by the caller.
  74. Arguments:
  75. dwSelectedReader - index used to select which reader to query.
  76. Return Value:
  77. A BOOL value indicating whether or not the card meets the search criteria.
  78. Author:
  79. Amanda Matlosz 3/16/1998 created
  80. Revisions:
  81. --*/
  82. BOOL CSCardEnv::CardMeetsSearchCriteria(DWORD dwSelectedReader)
  83. {
  84. BOOL fReturn = FALSE;
  85. CSCardReaderState* pReaderState = NULL;
  86. SCARD_READERINFO ReaderInfo;
  87. try
  88. {
  89. // check params
  90. if(dwSelectedReader >= (DWORD)NumberOfReaders())
  91. {
  92. throw (LONG)SCARD_E_INVALID_PARAMETER;
  93. }
  94. if (!IsContextValid())
  95. {
  96. throw (LONG)SCARD_E_INVALID_PARAMETER;
  97. }
  98. // get the reader object
  99. pReaderState = m_rgReaders[dwSelectedReader];
  100. // is it valid, matches the search list, and passes the check?
  101. if (NULL != pReaderState)
  102. {
  103. ReaderInfo.fCardLookup = FALSE;
  104. ReaderInfo.fChecked = FALSE;
  105. pReaderState->GetReaderInfo(&ReaderInfo);
  106. fReturn = (ReaderInfo.fCardLookup && ReaderInfo.fChecked);
  107. }
  108. }
  109. catch(LONG lErr)
  110. {
  111. TRACE_CATCH(_T("CardMeetsSearchCriteria"), lErr);
  112. }
  113. catch(...)
  114. {
  115. TRACE_CATCH_UNKNOWN(_T("CardMeetsSearchCriteria"));
  116. }
  117. return fReturn;
  118. }
  119. /*++
  120. LONG ConnectToReader:
  121. Routine connects to a selected reader, and sets the user-provided structs
  122. to contain the reader&cardname. returns an error if the user-provided struct's
  123. buffers aren't long enough.
  124. Arguments:
  125. dwSelectedReader - index used to select which reader to connect to.
  126. Return Value:
  127. A LONG value indicating the status of the requested action.
  128. See the Smartcard header files for additional information.
  129. Author:
  130. Chris Dudley 3/3/1997
  131. Revisions:
  132. Amanda Matlosz 1/28/1998 code cleanup
  133. --*/
  134. LONG CSCardEnv::ConnectToReader(DWORD dwSelectedReader)
  135. {
  136. LONG lReturn = SCARD_S_SUCCESS;
  137. LPSTR szName = NULL;
  138. LPWSTR wszName = NULL;
  139. try
  140. {
  141. if (!IsContextValid())
  142. {
  143. throw (LONG)E_FAIL;
  144. }
  145. //
  146. // If user has indicated to make a connection, do so
  147. // through callbacks or internally.
  148. // m_strReader and m_strCard are set as a side effect of these connect calls
  149. //
  150. if(IsCallbackValid())
  151. {
  152. lReturn = ConnectUser( dwSelectedReader,
  153. &m_hCardHandle,
  154. &m_strReader,
  155. &m_strCard);
  156. }
  157. else
  158. {
  159. if (0 != m_dwShareMode)
  160. {
  161. lReturn = ConnectInternal( dwSelectedReader,
  162. &m_hCardHandle,
  163. m_dwShareMode,
  164. m_dwPreferredProtocols,
  165. &m_dwActiveProtocol,
  166. &m_strReader,
  167. &m_strCard);
  168. }
  169. else
  170. {
  171. //
  172. // MUST set m_strReader and m_strCard manually
  173. //
  174. CSCardReaderState* pReaderState = NULL;
  175. pReaderState = m_rgReaders[dwSelectedReader];
  176. if (NULL != pReaderState)
  177. {
  178. lReturn = pReaderState->GetReaderCardInfo( &m_strReader,
  179. &m_strCard);
  180. }
  181. }
  182. }
  183. if (SCARDFAILED(lReturn))
  184. {
  185. throw (lReturn);
  186. }
  187. //
  188. // Set the user's OCN struct to contain return information
  189. //
  190. if(NULL != m_pOCNW)
  191. {
  192. m_pOCNW->hCardHandle = m_hCardHandle;
  193. m_pOCNW->dwActiveProtocol = m_dwActiveProtocol;
  194. wszName = (LPWSTR)(LPCWSTR)m_strReader;
  195. if (m_pOCNW->nMaxRdr >= m_strReader.Length()+1)
  196. {
  197. ::CopyMemory( (LPVOID) m_pOCNW->lpstrRdr,
  198. (CONST LPVOID)wszName,
  199. ((m_strReader.Length()+1) * sizeof(WCHAR)) );
  200. }
  201. else
  202. {
  203. m_pOCNW->nMaxRdr = m_strReader.Length()+1;
  204. throw (LONG)SCARD_E_NO_MEMORY;
  205. };
  206. wszName = (LPWSTR)(LPCWSTR)m_strCard;
  207. if (m_pOCNW->nMaxCard >= m_strCard.Length()+1)
  208. {
  209. ::CopyMemory( (LPVOID) m_pOCNW->lpstrCard,
  210. (CONST LPVOID)wszName,
  211. ((m_strCard.Length()+1) * sizeof(WCHAR)) );
  212. }
  213. else
  214. {
  215. m_pOCNW->nMaxCard = m_strCard.Length()+1;
  216. throw (LONG)SCARD_E_NO_MEMORY;
  217. };
  218. }
  219. else if (NULL != m_pOCNA)
  220. {
  221. m_pOCNA->hCardHandle = m_hCardHandle;
  222. m_pOCNA->dwActiveProtocol = m_dwActiveProtocol;
  223. szName = (LPSTR)(LPCSTR)m_strReader;
  224. if (m_pOCNA->nMaxRdr >= m_strReader.Length()+1)
  225. {
  226. ::CopyMemory( (LPVOID) m_pOCNA->lpstrRdr,
  227. (CONST LPVOID)szName,
  228. m_strReader.Length()+1);
  229. }
  230. else
  231. {
  232. m_pOCNA->nMaxRdr = m_strReader.Length()+1;
  233. throw (LONG)SCARD_E_NO_MEMORY;
  234. }
  235. szName = (LPSTR)(LPCSTR)m_strCard;
  236. if (m_pOCNA->nMaxCard >= m_strCard.Length()+1)
  237. {
  238. ::CopyMemory( (LPVOID) m_pOCNA->lpstrCard,
  239. (CONST LPVOID)szName,
  240. m_strCard.Length()+1);
  241. }
  242. else
  243. {
  244. m_pOCNA->nMaxCard = m_strCard.Length()+1;
  245. throw (LONG)SCARD_E_NO_MEMORY;
  246. }
  247. }
  248. else
  249. {
  250. // Error! One of them must be valid!
  251. throw (LONG)SCARD_F_INTERNAL_ERROR;
  252. }
  253. }
  254. catch(LONG lErr)
  255. {
  256. lReturn = lErr;
  257. TRACE_CATCH(_T("ConnectToReader"), lErr);
  258. }
  259. catch(...)
  260. {
  261. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  262. TRACE_CATCH_UNKNOWN(_T("ConnectToReader"));
  263. }
  264. return lReturn;
  265. }
  266. /*++
  267. LONG Search:
  268. This routine is called to search for a card when the calling application
  269. requests SC_DLG_NO_UI or SC_DLG_MINIMAL_UI.
  270. Arguments:
  271. pcMatches - pointer to a counter containing the number of matches found for
  272. the given searched for card.
  273. pdwIndex - index of the first card found that matches the search criteria.
  274. Return Value:
  275. A LONG value indicating the status of the requested action.
  276. See the Smartcard header files for additional information.
  277. Author:
  278. Chris Dudley (cdudley) 4/15/97
  279. --*/
  280. LONG CSCardEnv::Search(int *pcMatches, DWORD *pdwIndex)
  281. {
  282. // Locals
  283. LONG lReturn = SCARD_S_SUCCESS;
  284. LONG lMoreReaders = SCARD_S_SUCCESS;
  285. int cMatches = 0;
  286. DWORD dwIndex = 0;
  287. BOOL fIndexStored = FALSE;
  288. SCARD_READERINFO ReaderInfo;
  289. try
  290. {
  291. // Check params
  292. if(pcMatches == NULL || pdwIndex == NULL)
  293. {
  294. throw (LONG)SCARD_E_INVALID_VALUE;
  295. }
  296. // Initialize reader array
  297. lReturn = UpdateReaders();
  298. if(SCARDFAILED(lReturn))
  299. {
  300. throw lReturn;
  301. }
  302. //
  303. // Walk through cards testing if this is a seached for card
  304. //
  305. lMoreReaders = FirstReader(&ReaderInfo);
  306. while (SCARD_NO_MORE_READERS != lMoreReaders)
  307. {
  308. // Check card search status
  309. if((ReaderInfo.fCardLookup) && (ReaderInfo.fChecked))
  310. {
  311. // We've found a card being searched for...Update
  312. cMatches++;
  313. // Save the index of this card
  314. if (!fIndexStored)
  315. {
  316. dwIndex = ReaderInfo.dwInternalIndex;
  317. fIndexStored = TRUE;
  318. }
  319. }
  320. // Must clean up CTextString members before calling again
  321. ReaderInfo.sReaderName.Clear();
  322. ReaderInfo.sCardName.Clear();
  323. // Get Next struct
  324. lMoreReaders = NextReader( &ReaderInfo );
  325. }
  326. // Package for return
  327. *pcMatches = cMatches;
  328. *pdwIndex = dwIndex;
  329. }
  330. catch(LONG lErr)
  331. {
  332. lReturn = lErr;
  333. TRACE_CATCH(_T("Search"), lReturn);
  334. }
  335. catch(...)
  336. {
  337. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  338. TRACE_CATCH_UNKNOWN(_T("Search"));
  339. }
  340. return lReturn;
  341. }
  342. /*++
  343. InitializeAllPossibleCardNames:
  344. Stores all known card names matching the ATRs of the cardnames provided by
  345. the OPENCARDNAME struct to search for.
  346. */
  347. void CSCardEnv::InitializeAllPossibleCardNames( void )
  348. {
  349. LPCSTR szCards = NULL;
  350. LONG lResult = SCARD_S_SUCCESS;
  351. CBuffer bfAtr, bfAtrMask, bfInterfaces, bfProvider;
  352. if (0 == MStringCount(m_strCardNames))
  353. {
  354. // No card names to check
  355. m_strAllPossibleCardNames = m_strCardNames;
  356. return;
  357. }
  358. szCards = m_strCardNames;
  359. szCards = FirstString(szCards);
  360. while (szCards != NULL)
  361. {
  362. //
  363. // get all possible names for this card's ATR
  364. //
  365. if (! GetCardInfo(
  366. SCARD_SCOPE_USER,
  367. szCards,
  368. &bfAtr,
  369. &bfAtrMask,
  370. &bfInterfaces,
  371. &bfProvider ) )
  372. {
  373. // it's weird that this failed, but assume that the name is still OK
  374. m_strAllPossibleCardNames += szCards;
  375. }
  376. else
  377. {
  378. LPTSTR szListCards = NULL;
  379. DWORD dwCards = SCARD_AUTOALLOCATE;
  380. lResult = SCardListCards(
  381. m_hContext,
  382. bfAtr,
  383. NULL,
  384. 0,
  385. (LPTSTR)&szListCards,
  386. &dwCards);
  387. if (SCARD_S_SUCCESS == lResult)
  388. {
  389. // append them to the list of all possible card names
  390. m_strAllPossibleCardNames += szListCards;
  391. }
  392. else
  393. {
  394. // it's weird that this failed, but assume that the name is still OK
  395. m_strAllPossibleCardNames += szCards;
  396. }
  397. if (NULL != szListCards)
  398. {
  399. SCardFreeMemory(m_hContext, (PVOID)szListCards);
  400. }
  401. }
  402. szCards = NextString(szCards);
  403. }
  404. }
  405. /*++
  406. LONG SetOCN:
  407. Stores the user OpenCardName info in the encapsulated data for UNICODE and
  408. ANSI.
  409. Arguments:
  410. LPOPENCARDNAMEA - pointer to ANSI Open card name data.
  411. LPOPENCARDNAMEW - pointer to UNICODE Open card name data.
  412. Return Value:
  413. A LONG value indicating the status of the requested action. Please
  414. see the Smartcard header files for additional information.
  415. Author:
  416. Chris Dudley 3/3/1997
  417. Revisions:
  418. Amanda Matlosz 1/28/98 code cleanup, use charset-generic m_OCN,
  419. move EnableUI code to separate function
  420. --*/
  421. LONG CSCardEnv::SetOCN(LPOPENCARDNAMEA pOCNA)
  422. {
  423. // Locals
  424. LONG lReturn = SCARD_S_SUCCESS;
  425. int cMatches = 0;
  426. DWORD dwIndex = 0;
  427. try
  428. {
  429. // Check params
  430. if(NULL == pOCNA)
  431. {
  432. throw (LONG)SCARD_E_INVALID_VALUE;
  433. }
  434. if( pOCNA->dwStructSize != sizeof (OPENCARDNAMEA) )
  435. {
  436. throw (LONG)SCARD_E_INVALID_VALUE;
  437. }
  438. // TODO: ?? remove this test when Interfaces search is implemented ??
  439. if( (pOCNA->rgguidInterfaces != NULL) || (pOCNA->cguidInterfaces != 0) )
  440. {
  441. throw (LONG)SCARD_E_INVALID_VALUE; // NYI
  442. }
  443. //
  444. // Set UNICODE-specific members to NULL!
  445. //
  446. m_pOCNW = NULL;
  447. m_lpfnConnectW = NULL;
  448. //
  449. // Set appropriate charset-correct member, and copy to charset-generic
  450. //
  451. m_pOCNA = pOCNA;
  452. m_hwndOwner = m_pOCNA->hwndOwner;
  453. m_hContext = m_pOCNA->hSCardContext;
  454. m_strCardNames = m_pOCNA->lpstrCardNames;
  455. m_rgguidInterfaces = m_pOCNA->rgguidInterfaces;
  456. m_cguidInterfaces = m_pOCNA->cguidInterfaces;
  457. m_strReader = m_pOCNA->lpstrRdr;
  458. m_strCard = m_pOCNA->lpstrCard;
  459. m_strTitle = m_pOCNA->lpstrTitle;
  460. m_dwFlags = m_pOCNA->dwFlags;
  461. m_pvUserData = m_pOCNA->pvUserData;
  462. m_dwShareMode = m_pOCNA->dwShareMode;
  463. m_dwPreferredProtocols = m_pOCNA->dwPreferredProtocols;
  464. m_dwActiveProtocol = m_pOCNA->dwActiveProtocol;
  465. m_lpfnConnectA = m_pOCNA->lpfnConnect;
  466. m_lpfnCheck = m_pOCNA->lpfnCheck;
  467. m_lpfnDisconnect = m_pOCNA->lpfnDisconnect;
  468. m_lpUserData = m_pOCNA->pvUserData;
  469. m_hCardHandle = m_pOCNA->hCardHandle;
  470. // special case: lpstrGroupNames==NULL -> use default
  471. if (NULL != m_pOCNA->lpstrGroupNames)
  472. {
  473. m_strGroupNames = m_pOCNA->lpstrGroupNames;
  474. }
  475. else
  476. {
  477. m_strGroupNames = "SCard$DefaultReaders";
  478. }
  479. InitializeAllPossibleCardNames();
  480. }
  481. catch(LONG lErr)
  482. {
  483. lReturn = lErr;
  484. TRACE_CATCH(_T("SetOCN - ANSI"),lReturn);
  485. }
  486. catch(...)
  487. {
  488. lReturn = (LONG)SCARD_F_UNKNOWN_ERROR;
  489. TRACE_CATCH_UNKNOWN(_T("SetOCN - ANSI"));
  490. }
  491. // Release memory if required
  492. RemoveReaders();
  493. return lReturn;
  494. }
  495. // UNICODE
  496. LONG CSCardEnv::SetOCN(LPOPENCARDNAMEW pOCNW)
  497. {
  498. LONG lReturn = SCARD_S_SUCCESS;
  499. try
  500. {
  501. // Check params
  502. if (NULL == pOCNW)
  503. {
  504. throw (LONG)SCARD_E_INVALID_VALUE;
  505. }
  506. if (pOCNW->dwStructSize != sizeof(OPENCARDNAMEW) )
  507. {
  508. throw (LONG)SCARD_E_INVALID_VALUE;
  509. }
  510. if ((pOCNW->rgguidInterfaces != NULL) || (pOCNW->cguidInterfaces != 0))
  511. {
  512. throw (LONG)SCARD_E_INVALID_VALUE; // NYI
  513. }
  514. //
  515. // Set ANSI-specific members to NULL!
  516. //
  517. m_pOCNA = NULL;
  518. m_lpfnConnectA = NULL;
  519. //
  520. // Set appropriate charset-correct member, and copy to charset-generic
  521. //
  522. m_pOCNW = pOCNW;
  523. m_hwndOwner = m_pOCNW->hwndOwner;
  524. m_hContext = m_pOCNW->hSCardContext;
  525. m_strCardNames = m_pOCNW->lpstrCardNames;
  526. m_rgguidInterfaces = m_pOCNW->rgguidInterfaces;
  527. m_cguidInterfaces = m_pOCNW->cguidInterfaces;
  528. m_strReader = m_pOCNW->lpstrRdr;
  529. m_strCard = m_pOCNW->lpstrCard;
  530. m_strTitle = m_pOCNW->lpstrTitle;
  531. m_dwFlags = m_pOCNW->dwFlags;
  532. m_pvUserData = m_pOCNW->pvUserData;
  533. m_dwShareMode = m_pOCNW->dwShareMode;
  534. m_dwPreferredProtocols = m_pOCNW->dwPreferredProtocols;
  535. m_dwActiveProtocol = m_pOCNW->dwActiveProtocol;
  536. m_lpfnConnectW = m_pOCNW->lpfnConnect;
  537. m_lpfnCheck = m_pOCNW->lpfnCheck;
  538. m_lpfnDisconnect = m_pOCNW->lpfnDisconnect;
  539. m_lpUserData = m_pOCNW->pvUserData;
  540. m_hCardHandle = m_pOCNW->hCardHandle;
  541. // special case: lpstrGroupNames=="" -> use default
  542. if (NULL != m_pOCNW->lpstrGroupNames && 0 != *(m_pOCNW->lpstrGroupNames))
  543. {
  544. m_strGroupNames = m_pOCNW->lpstrGroupNames;
  545. }
  546. else
  547. {
  548. m_strGroupNames = L"SCard$DefaultReaders";
  549. }
  550. InitializeAllPossibleCardNames();
  551. }
  552. catch(LONG lErr)
  553. {
  554. lReturn = lErr;
  555. TRACE_CATCH(_T("SetOCN - UNICODE"),lReturn);
  556. }
  557. catch(...)
  558. {
  559. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  560. TRACE_CATCH_UNKNOWN(_T("SetOCN - UNICODE"));
  561. }
  562. return lReturn;
  563. }
  564. /*++
  565. LONG NoUISearch:
  566. If the user has not set SC_DLG_FORCE_UI, perform a search for all
  567. possible cards. If only one card is the result, then the search has
  568. succeeded and no UI is necessary.
  569. Arguments:
  570. BOOL* pfEnableUI.
  571. Return Value:
  572. A LONG indicating the success of the search. If SC_DLG_FORCE_UI is set,
  573. pfEnableUI is always TRUE; if SC_DLG_NO_UI is set, the pfEnableUI is always
  574. FALSE.
  575. Author:
  576. Amanda Matlosz 02/01/1998
  577. Revisions:
  578. --*/
  579. LONG CSCardEnv::NoUISearch(BOOL* pfEnableUI)
  580. {
  581. //
  582. // Must search so we can check all the cards, even if we have to show UI
  583. //
  584. *pfEnableUI = FALSE;
  585. long lResult = SCARD_S_SUCCESS;
  586. int cMatches = 0;
  587. DWORD dwIndex = 0;
  588. try
  589. {
  590. // Search for the card
  591. lResult = Search(&cMatches, &dwIndex);
  592. if(SCARDFAILED(lResult))
  593. {
  594. throw lResult;
  595. }
  596. // Determine if UI should be used...
  597. if(m_dwFlags & SC_DLG_FORCE_UI)
  598. {
  599. *pfEnableUI = TRUE;
  600. }
  601. else if((m_dwFlags & SC_DLG_MINIMAL_UI) && (cMatches != 1))
  602. {
  603. *pfEnableUI = TRUE;
  604. }
  605. // Connect to the reader if 1 matching card found
  606. if(cMatches == 1)
  607. {
  608. lResult = ConnectToReader(dwIndex);
  609. if (SCARDFAILED(lResult))
  610. {
  611. *pfEnableUI = TRUE; // an error occurred with the reader? eep.
  612. throw lResult;
  613. }
  614. }
  615. }
  616. catch(LONG lErr)
  617. {
  618. TRACE_CATCH(_T("NoUISearch"),lErr);
  619. }
  620. catch(...)
  621. {
  622. TRACE_CATCH_UNKNOWN(_T("NoUISearch"));
  623. lResult = SCARD_F_UNKNOWN_ERROR;
  624. }
  625. // Release memory if required
  626. RemoveReaders();
  627. return lResult;
  628. }
  629. /*++
  630. LONG BuildReaderArray:
  631. Builds an array of CSCardReader objects. 1 object per reader.
  632. Arguments:
  633. szReaderNames - an LPTSTR (A/W) multistring containing a list of readers.
  634. Return Value:
  635. A LONG value indicating the status of the requested action.
  636. See the Smartcard header files for additional information.
  637. Author:
  638. Chris Dudley 3/5/1997
  639. Revisions:
  640. Amanda Matlosz 1/29/98 added unicode support
  641. --*/
  642. LONG CSCardEnv::BuildReaderArray( LPTSTR szReaderNames )
  643. {
  644. LONG lReturn = SCARD_S_SUCCESS;
  645. LPCTSTR szReaderName = szReaderNames;
  646. CSCardReaderState* pReaderState = NULL;
  647. try
  648. {
  649. // Check Params
  650. if (NULL == szReaderNames || NULL == *szReaderNames)
  651. {
  652. throw (LONG)SCARD_E_INVALID_VALUE;
  653. }
  654. //
  655. // Store a reader object in the array for each reader
  656. //
  657. szReaderName = FirstString( szReaderName );
  658. while (NULL != szReaderName)
  659. {
  660. pReaderState = new CSCardReaderState;
  661. if (NULL == pReaderState)
  662. {
  663. throw (LONG)SCARD_E_NO_MEMORY;
  664. }
  665. pReaderState->SetContext(m_hContext);
  666. pReaderState->StoreName(szReaderName);
  667. if (NULL != m_pOCNA)
  668. {
  669. lReturn = pReaderState->SetReaderState( m_lpfnConnectA,
  670. m_lpfnCheck,
  671. m_lpfnDisconnect,
  672. m_lpUserData);
  673. }
  674. else if (NULL != m_pOCNW)
  675. {
  676. lReturn = pReaderState->SetReaderState( m_lpfnConnectW,
  677. m_lpfnCheck,
  678. m_lpfnDisconnect,
  679. m_lpUserData);
  680. }
  681. else
  682. {
  683. // Either m_pOCNA or m_pOCNW *must* be valid!
  684. throw (long)SCARD_F_INTERNAL_ERROR;
  685. }
  686. if (SCARDFAILED(lReturn))
  687. {
  688. throw (lReturn);
  689. }
  690. // Check if card inserted and set flag if it contains the search card
  691. if (pReaderState->IsCardInserted())
  692. {
  693. // TODO: ?? fix readerstate so it's nicer w/ W ??
  694. lReturn = pReaderState->CheckCard(m_strAllPossibleCardNames);
  695. if (SCARDFAILED(lReturn))
  696. {
  697. throw (lReturn);
  698. }
  699. }
  700. m_rgReaders.Add(pReaderState);
  701. szReaderName = NextString(szReaderName);
  702. }
  703. }
  704. catch(LONG lErr)
  705. {
  706. lReturn = lErr;
  707. TRACE_CATCH(_T("BuildReaderArray"), lReturn);
  708. }
  709. catch(...)
  710. {
  711. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  712. TRACE_CATCH_UNKNOWN(_T("BuildReaderArray"));
  713. }
  714. return lReturn;
  715. }
  716. /*++
  717. LONG ConnectInternal:
  718. Connect internally to the reader
  719. Arguments:
  720. dwSelectedIndex - index used to select which reader to connect to.
  721. pHandle - pointer to an SCARDHANDLE that will be set on return.
  722. dwShareMode - contains share mode to use when connecting
  723. dwProtocols - contains requested protocol(s) to use when connecting
  724. pdwActiveProtocl - returns active protocol on successful connection
  725. szReaderName - returned name of the reader being connected
  726. Return Value:
  727. A LONG value indicating the status of the requested action. Please
  728. see the Smartcard header files for additional information.
  729. Author:
  730. Chris Dudley 3/11/1997
  731. Revisions:
  732. Amanda Matlosz 1/30/98 code cleanup
  733. --*/
  734. LONG CSCardEnv::ConnectInternal( DWORD dwSelectedReader,
  735. SCARDHANDLE *pHandle,
  736. DWORD dwShareMode,
  737. DWORD dwProtocols,
  738. DWORD *pdwActiveProtocol,
  739. CTextString *pszReaderName,//=NULL
  740. CTextString *pszCardName//=NULL
  741. )
  742. {
  743. LONG lReturn = SCARD_S_SUCCESS;
  744. CSCardReaderState* pReaderState = NULL;
  745. try
  746. {
  747. // Check Params
  748. if (NULL == pHandle)
  749. {
  750. throw (LONG)SCARD_E_INVALID_PARAMETER;
  751. }
  752. if (NULL == pdwActiveProtocol)
  753. {
  754. throw (LONG)SCARD_E_INVALID_PARAMETER;
  755. }
  756. if (dwSelectedReader >= (DWORD)NumberOfReaders())
  757. {
  758. throw (LONG)SCARD_E_INVALID_PARAMETER;
  759. }
  760. if (!IsContextValid())
  761. {
  762. throw (LONG)SCARD_F_INTERNAL_ERROR;
  763. }
  764. // Clear handle
  765. *pHandle = NULL;
  766. // get the object & connect
  767. pReaderState = m_rgReaders[dwSelectedReader];
  768. lReturn = pReaderState->Connect(pHandle,
  769. dwShareMode,
  770. dwProtocols,
  771. pdwActiveProtocol,
  772. pszReaderName,
  773. pszCardName);
  774. if (SCARDFAILED(lReturn))
  775. {
  776. throw lReturn;
  777. }
  778. }
  779. catch(LONG lErr)
  780. {
  781. lReturn = lErr;
  782. TRACE_CATCH(_T("ConnectInternal"), lReturn);
  783. }
  784. catch(...)
  785. {
  786. lReturn = SCARD_F_UNKNOWN_ERROR;
  787. TRACE_CATCH_UNKNOWN(_T("ConnectInternal"));
  788. }
  789. return lReturn;
  790. }
  791. /*++
  792. LONG ConnectUser:
  793. Connect to the reader using user supplied callback
  794. Arguments:
  795. dwSelectedReader - index to reader to connect
  796. lpfnConnect - user supplied callback function.
  797. pHandle - pointer to an SCARDHANDLE that will be set on return.
  798. lpUserData - pointer to user data.
  799. Return Value:
  800. A LONG value indicating the status of the requested action. Please
  801. see the Smartcard header files for additional information.
  802. Author:
  803. Chris Dudley 3/11/1997
  804. Revisions:
  805. Amanda Matlosz 1//30/98 code cleanup
  806. --*/
  807. LONG CSCardEnv::ConnectUser( DWORD dwSelectedReader,
  808. SCARDHANDLE *pHandle,
  809. CTextString *pszReaderName, //=NULL
  810. CTextString *pszCardName //=NULL
  811. )
  812. {
  813. LONG lReturn = SCARD_S_SUCCESS;
  814. CSCardReaderState* pReaderState = NULL;
  815. try
  816. {
  817. // Check Params
  818. if(NULL == pHandle)
  819. {
  820. throw (LONG)SCARD_E_INVALID_PARAMETER;
  821. }
  822. if(dwSelectedReader >= (DWORD)NumberOfReaders())
  823. {
  824. throw (LONG)SCARD_E_INVALID_PARAMETER;
  825. }
  826. if (!IsContextValid())
  827. {
  828. throw (LONG)SCARD_E_INVALID_PARAMETER;
  829. }
  830. // Clear handle
  831. *pHandle = NULL;
  832. // get the reader object & connect
  833. pReaderState = m_rgReaders[dwSelectedReader];
  834. lReturn = pReaderState->UserConnect(pHandle,
  835. pszReaderName,
  836. pszCardName);
  837. if (SCARDFAILED(lReturn))
  838. {
  839. throw (lReturn);
  840. }
  841. }
  842. catch(LONG lErr)
  843. {
  844. lReturn = lErr;
  845. TRACE_CATCH(_T("ConnectUser"), lReturn);
  846. }
  847. catch(...)
  848. {
  849. lReturn = SCARD_F_UNKNOWN_ERROR;
  850. TRACE_CATCH_UNKNOWN(_T("ConnectUser"));
  851. }
  852. return lReturn;
  853. }
  854. /*++
  855. void GetCardList:
  856. Returns a multistring containing the list cards being searched for.
  857. Arguments:
  858. LPCTSTR* - pointer->pointer for the list
  859. Return Value:
  860. none
  861. Author:
  862. Chris Dudley 3/7/1997
  863. Notes:
  864. --*/
  865. void CSCardEnv::GetCardList( LPCTSTR* pszCardList )
  866. {
  867. // Check params
  868. if (NULL != pszCardList)
  869. {
  870. *pszCardList = m_strCardNames;
  871. }
  872. }
  873. /*++
  874. BOOL IsCallbackValid:
  875. This routine checks the user callback functions.
  876. Arguments:
  877. None
  878. Return Value:
  879. TRUE if calbacks are valid. FALSE otherwise.
  880. Author:
  881. Chris Dudley 3/15/1997
  882. --*/
  883. BOOL CSCardEnv::IsCallbackValid ( void )
  884. {
  885. BOOL fValid = FALSE;
  886. fValid = ((NULL != m_lpfnConnectA || NULL != m_lpfnConnectW) &&
  887. (m_lpfnCheck != NULL) && (m_lpfnDisconnect != NULL));
  888. return fValid;
  889. }
  890. /*++
  891. LONG CreateReaderStateArray:
  892. Returns an array of SCARD_READERSTATE structs.
  893. Arguments:
  894. LPSCARD_READERSTATE* - pointer->pointer to an SCARDREADERSTATE struct
  895. Return Value:
  896. A LONG value indicating the status of the requested action. Please
  897. see the Smartcard header files for additional information.
  898. Author:
  899. Chris Dudley 3/7/1997
  900. Revisions:
  901. Amanda Matlosz 1/30/98 added unicode support, code cleanup
  902. --*/
  903. LONG CSCardEnv::CreateReaderStateArray( LPSCARD_READERSTATE* prgReaderStates )
  904. {
  905. // Locals
  906. LONG lReturn = SCARD_S_SUCCESS;
  907. CSCardReaderState* pReaderState = NULL;
  908. LPSCARD_READERSTATE rgReader;
  909. try
  910. {
  911. // Check params, etc.
  912. if (prgReaderStates == NULL)
  913. {
  914. throw (LONG)SCARD_E_INVALID_PARAMETER;
  915. }
  916. if (!IsArrayValid())
  917. {
  918. throw (LONG)SCARD_F_INTERNAL_ERROR;
  919. }
  920. // Clean up the destination
  921. DeleteReaderStateArray(prgReaderStates);
  922. // Build a temp array, set the destination array
  923. rgReader = new SCARD_READERSTATE[(size_t)m_rgReaders.GetSize()];
  924. if (rgReader == NULL)
  925. {
  926. throw (LONG)SCARD_E_NO_MEMORY;
  927. }
  928. for (int ix =0; ix < m_rgReaders.GetSize(); ix++)
  929. {
  930. pReaderState = m_rgReaders[ix];
  931. pReaderState->GetReaderState(&(rgReader[ix])); // TODO: ?? looks funny ??
  932. }
  933. // Asign the pointer
  934. *prgReaderStates = rgReader;
  935. }
  936. catch (LONG err) {
  937. lReturn = err;
  938. TRACE_CATCH(_T("GetReaderStateArray"),err);
  939. }
  940. catch (...) {
  941. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  942. TRACE_CATCH_UNKNOWN(_T("GetReaderStateArray"));
  943. }
  944. return lReturn;
  945. }
  946. /*++
  947. void DeleteReaderStateArray:
  948. Frees the memory associated with a previously created SCARD_READERSTATE
  949. array.
  950. Arguments:
  951. rgReaderStateArray - pointer to the array.
  952. Return Value:
  953. None.
  954. Author:
  955. Chris Dudley 3/7/1997
  956. --*/
  957. void CSCardEnv::DeleteReaderStateArray(LPSCARD_READERSTATE* prgReaderStateArray)
  958. {
  959. if (NULL != *prgReaderStateArray)
  960. {
  961. delete [] (*prgReaderStateArray);
  962. *prgReaderStateArray = NULL;
  963. }
  964. }
  965. /*++
  966. LONG FirstReader:
  967. Retrieves information on the first reader in the reader array.
  968. Arguments:
  969. None
  970. Return Value:
  971. A LONG value indicating the status of the requested action. Please
  972. see the Smartcard header files for additional information.
  973. A return value of SCARD_NO_MORE_READERS means no readers available.
  974. Author:
  975. Chris Dudley 3/7/1997
  976. Notes:
  977. 1. This routine 0's the memory pointed to by pReaderInfo. The calling app should be
  978. careful (i.e. clean up LSCARD_READERINFO struct) before each call to this routine.
  979. --*/
  980. LONG CSCardEnv::FirstReader(LPSCARD_READERINFO pReaderInfo)
  981. {
  982. // Locals
  983. LONG lResult = SCARD_S_SUCCESS;
  984. CSCardReaderState* pReaderState = NULL;
  985. try
  986. {
  987. if (NULL == pReaderInfo)
  988. {
  989. throw (LONG)SCARD_E_INVALID_PARAMETER;
  990. }
  991. // Give up if there are no readers
  992. if (m_rgReaders.GetSize() <= 0)
  993. {
  994. throw (LONG)SCARD_NO_MORE_READERS;
  995. }
  996. // Get the first reader
  997. m_dwReaderIndex = 0;
  998. pReaderState = m_rgReaders[m_dwReaderIndex];
  999. if (!pReaderState->IsStateValid())
  1000. {
  1001. throw (LONG)SCARD_F_INTERNAL_ERROR;
  1002. }
  1003. // Prepare the return struct
  1004. ::ZeroMemory( (LPVOID)pReaderInfo, (DWORD)sizeof(SCARD_READERINFO));
  1005. lResult = pReaderState->GetReaderInfo(pReaderInfo);
  1006. if (SCARDFAILED(lResult))
  1007. {
  1008. throw (lResult);
  1009. }
  1010. // Update the index
  1011. pReaderInfo->dwInternalIndex = m_dwReaderIndex;
  1012. }
  1013. catch(LONG lErr)
  1014. {
  1015. lResult = lErr;
  1016. TRACE_CATCH(_T("FirstReader"), lResult);
  1017. }
  1018. catch(...)
  1019. {
  1020. lResult = SCARD_F_UNKNOWN_ERROR;
  1021. TRACE_CATCH_UNKNOWN(_T("FirstReader"));
  1022. }
  1023. return lResult;
  1024. }
  1025. /*++
  1026. LONG NextReader:
  1027. Retrieves information on the next reader (using internal index) in the
  1028. reader array.
  1029. Arguments:
  1030. None
  1031. Return Value:
  1032. A LONG value indicating the status of the requested action.
  1033. See the Smartcard header files for additional information.
  1034. A return value of SCARD_NO_MORE_READERS means no readers available.
  1035. Author:
  1036. Chris Dudley 3/7/1997
  1037. Notes:
  1038. 1. This routine 0's the memory pointed to by pReaderInfo. The calling app should be
  1039. careful (i.e. clean up LSCARD_READERINFO struct) before each call to this routine.
  1040. --*/
  1041. LONG CSCardEnv::NextReader(LPSCARD_READERINFO pReaderInfo)
  1042. {
  1043. LONG lResult = SCARD_S_SUCCESS;
  1044. CSCardReaderState* pReaderState = NULL;
  1045. DWORD dwTotalReaders = (DWORD)m_rgReaders.GetUpperBound();
  1046. try
  1047. {
  1048. // Check params
  1049. if (NULL == pReaderInfo)
  1050. {
  1051. throw (LONG)SCARD_E_INVALID_PARAMETER;
  1052. }
  1053. // Is there a next reader to retrieve?
  1054. m_dwReaderIndex++;
  1055. if (m_dwReaderIndex > dwTotalReaders)
  1056. {
  1057. throw (LONG)SCARD_NO_MORE_READERS;
  1058. }
  1059. // Fetch the reader state from our array
  1060. pReaderState = m_rgReaders[m_dwReaderIndex];
  1061. if (!pReaderState->IsStateValid())
  1062. {
  1063. throw (LONG)SCARD_F_INTERNAL_ERROR;
  1064. }
  1065. // Setup the struct to return
  1066. ::ZeroMemory((LPVOID)pReaderInfo, (DWORD)sizeof(SCARD_READERINFO));
  1067. lResult = pReaderState->GetReaderInfo(pReaderInfo);
  1068. if (SCARDFAILED(lResult))
  1069. {
  1070. throw (lResult);
  1071. }
  1072. // Update the index
  1073. pReaderInfo->dwInternalIndex = m_dwReaderIndex;
  1074. }
  1075. catch(LONG lErr)
  1076. {
  1077. lResult = lErr;
  1078. TRACE_CATCH(_T("NextReader"), lResult);
  1079. }
  1080. catch(...)
  1081. {
  1082. lResult = (LONG) SCARD_F_UNKNOWN_ERROR;
  1083. TRACE_CATCH_UNKNOWN(_T("NextReader"));
  1084. }
  1085. return lResult;
  1086. }
  1087. /*++
  1088. void RemoveReaderArray:
  1089. Deletes the array of CSCardReader objects.
  1090. Arguments:
  1091. None
  1092. Return Value:
  1093. None
  1094. Author:
  1095. Chris Dudley 3/5/1997
  1096. Revisions:
  1097. Amanda Matlosz 1/29/98 code cleanup
  1098. --*/
  1099. void CSCardEnv::RemoveReaders( void )
  1100. {
  1101. if (IsArrayValid())
  1102. {
  1103. // Delete the attached reader objects
  1104. for (int ix=0; ix <= m_rgReaders.GetUpperBound(); ix++)
  1105. {
  1106. delete m_rgReaders[ix];
  1107. }
  1108. // Free array memory
  1109. m_rgReaders.RemoveAll();
  1110. }
  1111. }
  1112. /*++
  1113. void SetContext:
  1114. Sets the card context, performs no checking.
  1115. Arguments:
  1116. hContext - card context handle
  1117. Return Value:
  1118. None.
  1119. Author:
  1120. Chris Dudley 3/3/1997
  1121. --*/
  1122. void CSCardEnv::SetContext(SCARDCONTEXT hContext)
  1123. {
  1124. m_hContext = hContext;
  1125. }
  1126. /*++
  1127. LONG UpdateReaders:
  1128. Updates the reader array using m_GroupName member.
  1129. Arguments:
  1130. None.
  1131. Return Value:
  1132. A LONG value indicating the status of the requested action. Please
  1133. see the Smartcard header files for additional information.
  1134. Author:
  1135. Chris Dudley 3/3/1997
  1136. Revisions:
  1137. Amanda Matlosz 1/29/98 added Unicode support
  1138. Note:
  1139. --*/
  1140. LONG CSCardEnv::UpdateReaders( void )
  1141. {
  1142. TRACE("\tCSCardEnv::UpdateReaders\r\n"); // TODO: ?? remove this ??
  1143. LONG lReturn = SCARD_S_SUCCESS;
  1144. LPTSTR szReaderNames = NULL;
  1145. DWORD dwNameLength = SCARD_AUTOALLOCATE;
  1146. if (!IsContextValid())
  1147. {
  1148. TRACE_CODE(_T("UpdateReaders"),E_FAIL);
  1149. return (LONG)E_FAIL;
  1150. }
  1151. RemoveReaders(); // deletes current array if required
  1152. try
  1153. {
  1154. // Call Resource manager for list of readers
  1155. lReturn = SCardListReaders(m_hContext,
  1156. m_strGroupNames,
  1157. (LPTSTR)&szReaderNames,
  1158. &dwNameLength);
  1159. if(SCARDFAILED(lReturn))
  1160. {
  1161. throw (lReturn);
  1162. }
  1163. // SCardListReaders will succeed in a PnP world even if there are currently no
  1164. // readers for this group.
  1165. _ASSERTE(NULL != szReaderNames && NULL != *szReaderNames);
  1166. lReturn = BuildReaderArray(szReaderNames);
  1167. if (SCARDFAILED(lReturn))
  1168. {
  1169. throw (lReturn);
  1170. }
  1171. }
  1172. catch(LONG lErr)
  1173. {
  1174. lReturn = lErr;
  1175. TRACE_CATCH(_T("UpdateReaders"),lReturn);
  1176. }
  1177. catch(...)
  1178. {
  1179. lReturn = (LONG) SCARD_F_UNKNOWN_ERROR;
  1180. TRACE_CATCH_UNKNOWN(_T("UpdateReaders"));
  1181. }
  1182. // Clean Up
  1183. if(NULL != szReaderNames)
  1184. {
  1185. SCardFreeMemory(m_hContext, (LPVOID)szReaderNames);
  1186. }
  1187. return lReturn;
  1188. }