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.

1418 lines
36 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. ScSearch
  5. Abstract:
  6. This file contains the outline implementation of
  7. miscellaneous smart card search and check functions
  8. for the Microsoft Smart Card Common Dialog
  9. Author:
  10. Amanda Matlosz 5/7/98
  11. Environment:
  12. Win32, C++ w/Exceptions, MFC
  13. Revision History:
  14. Notes:
  15. --*/
  16. /////////////////////////////////////////////////////////////////////////////
  17. //
  18. // Includes
  19. //
  20. #include "stdafx.h"
  21. // #include <atlconv.cpp>
  22. #include <winscard.h>
  23. #include "ScSearch.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. /////////////////////////////////////////////////////////////////////////////
  30. //
  31. // Helpers
  32. //
  33. LPSTR GetCardNameA(SCARDCONTEXT hSCardContext, LPBYTE pbAtr)
  34. {
  35. LPSTR szCard = NULL;
  36. DWORD dwNameLength = SCARD_AUTOALLOCATE;
  37. LONG lReturn = SCardListCardsA(
  38. hSCardContext,
  39. pbAtr,
  40. NULL,
  41. 0,
  42. (LPSTR)&szCard,
  43. &dwNameLength);
  44. if (SCARD_S_SUCCESS != lReturn)
  45. {
  46. if (NULL != szCard)
  47. {
  48. SCardFreeMemory(hSCardContext, (PVOID)szCard);
  49. szCard = NULL;
  50. }
  51. }
  52. return szCard;
  53. }
  54. LPWSTR GetCardNameW(SCARDCONTEXT hSCardContext, LPBYTE pbAtr)
  55. {
  56. LPWSTR szCard = NULL;
  57. DWORD dwNameLength = SCARD_AUTOALLOCATE;
  58. LONG lReturn = SCardListCardsW(
  59. hSCardContext,
  60. pbAtr,
  61. NULL,
  62. 0,
  63. (LPWSTR)&szCard,
  64. &dwNameLength);
  65. if (SCARD_S_SUCCESS != lReturn)
  66. {
  67. if (NULL != szCard)
  68. {
  69. SCardFreeMemory(hSCardContext, (PVOID)szCard);
  70. szCard = NULL;
  71. }
  72. }
  73. return szCard;
  74. }
  75. DWORD AnsiMStringCount(LPCSTR msz)
  76. {
  77. DWORD dwRet = 0;
  78. while (NULL != msz)
  79. {
  80. if (NULL == *msz)
  81. {
  82. msz = NULL;
  83. }
  84. else
  85. {
  86. DWORD cchLen = strlen(msz);
  87. msz = msz+(sizeof(CHAR)*(cchLen+1));
  88. dwRet++;
  89. }
  90. }
  91. return dwRet;
  92. }
  93. void
  94. MatchInterfacesW(
  95. SCARDCONTEXT hSCardContext,
  96. LPCGUID pGUIDInterfaces,
  97. DWORD cGUIDInterfaces,
  98. CTextMultistring& mstrAllCards)
  99. {
  100. //
  101. // Append all cards that support the requested guidInterfaces
  102. //
  103. if (NULL != pGUIDInterfaces && 0 < cGUIDInterfaces)
  104. {
  105. LONG lResult = SCARD_S_SUCCESS;
  106. LPWSTR szListCards = NULL;
  107. DWORD dwCards = SCARD_AUTOALLOCATE;
  108. lResult = SCardListCardsW(
  109. hSCardContext,
  110. NULL,
  111. pGUIDInterfaces,
  112. cGUIDInterfaces,
  113. (LPWSTR) &szListCards,
  114. &dwCards);
  115. if (SCARD_S_SUCCESS == lResult)
  116. {
  117. // append them to the list of all possible card names
  118. mstrAllCards += szListCards;
  119. }
  120. if (NULL != szListCards)
  121. {
  122. SCardFreeMemory(hSCardContext, (PVOID)szListCards);
  123. }
  124. }
  125. }
  126. /////////////////////////////////////////////////////////////////////////////
  127. //
  128. // Methods
  129. //
  130. __inline BOOL CheckProtocols(
  131. IN DWORD dwProtocols)
  132. {
  133. return
  134. SCARD_PROTOCOL_T0 == (SCARD_PROTOCOL_T0 & dwProtocols) ||
  135. SCARD_PROTOCOL_T1 == (SCARD_PROTOCOL_T1 & dwProtocols) ||
  136. (SCARD_PROTOCOL_Tx) == ((SCARD_PROTOCOL_Tx) & dwProtocols) ||
  137. SCARD_PROTOCOL_RAW == (SCARD_PROTOCOL_RAW & dwProtocols) ||
  138. SCARD_PROTOCOL_DEFAULT == (SCARD_PROTOCOL_DEFAULT & dwProtocols) ||
  139. SCARD_PROTOCOL_OPTIMAL == (SCARD_PROTOCOL_OPTIMAL & dwProtocols);
  140. }
  141. /*++
  142. BOOL CheckOCN:
  143. Routine performs simple parameter checks on OPENCARDNAME and
  144. OPENCARD_SEARCH_CRITERIA structs
  145. Return Value:
  146. FALSE if invalid parameter, otherwise TRUE.
  147. Author:
  148. Amanda Matlosz 09/16/1998
  149. --*/
  150. BOOL CheckOCN(LPOPENCARDNAMEA_EX pOCNA)
  151. {
  152. if (NULL == pOCNA)
  153. {
  154. return FALSE;
  155. }
  156. if (pOCNA->dwStructSize != sizeof(OPENCARDNAMEA_EX))
  157. {
  158. return FALSE;
  159. }
  160. if (NULL == pOCNA->hSCardContext)
  161. {
  162. return FALSE;
  163. }
  164. if (0 == pOCNA->nMaxRdr || NULL == pOCNA->lpstrRdr)
  165. {
  166. return FALSE;
  167. }
  168. if (0 == pOCNA->nMaxCard || NULL == pOCNA->lpstrCard)
  169. {
  170. return FALSE;
  171. }
  172. BOOL fOneFlagOnly = FALSE;
  173. if (0 != (pOCNA->dwFlags & SC_DLG_MINIMAL_UI))
  174. {
  175. fOneFlagOnly = TRUE;
  176. }
  177. if (0 != (pOCNA->dwFlags & SC_DLG_FORCE_UI))
  178. {
  179. if (fOneFlagOnly)
  180. {
  181. return FALSE;
  182. }
  183. fOneFlagOnly = TRUE;
  184. }
  185. if (0 != (pOCNA->dwFlags & SC_DLG_NO_UI))
  186. {
  187. if (fOneFlagOnly)
  188. {
  189. return FALSE;
  190. }
  191. fOneFlagOnly = TRUE;
  192. }
  193. // Now check POPENCARD_SEARCH_CRITERIAA, if applicable
  194. if (NULL != pOCNA->pOpenCardSearchCriteria)
  195. {
  196. DWORD dwShareMode = pOCNA->pOpenCardSearchCriteria->dwShareMode;
  197. DWORD dwPreferredProtocols = pOCNA->pOpenCardSearchCriteria->dwPreferredProtocols;
  198. if (NULL != pOCNA->pOpenCardSearchCriteria->lpfnCheck)
  199. {
  200. // either lpfnConnect and lpfnDisconnect must be set
  201. if ( (NULL != pOCNA->pOpenCardSearchCriteria->lpfnConnect) &&
  202. (NULL != pOCNA->pOpenCardSearchCriteria->lpfnDisconnect) )
  203. {
  204. return TRUE;
  205. }
  206. if ( ( SCARD_SHARE_EXCLUSIVE == dwShareMode ||
  207. SCARD_SHARE_SHARED == dwShareMode ||
  208. SCARD_SHARE_DIRECT == dwShareMode ) &&
  209. CheckProtocols(dwPreferredProtocols)
  210. )
  211. {
  212. return TRUE;
  213. }
  214. return FALSE;
  215. }
  216. }
  217. // if all the tests have passed, it must be OK.
  218. return TRUE;
  219. }
  220. BOOL CheckOCN(LPOPENCARDNAMEW_EX pOCNW)
  221. {
  222. if (NULL == pOCNW)
  223. {
  224. return FALSE;
  225. }
  226. if (pOCNW->dwStructSize != sizeof(OPENCARDNAMEW_EX))
  227. {
  228. return FALSE;
  229. }
  230. if (NULL == pOCNW->hSCardContext)
  231. {
  232. return FALSE;
  233. }
  234. if (0 == pOCNW->nMaxRdr || NULL == pOCNW->lpstrRdr)
  235. {
  236. return FALSE;
  237. }
  238. if (0 == pOCNW->nMaxCard || NULL == pOCNW->lpstrCard)
  239. {
  240. return FALSE;
  241. }
  242. BOOL fOneFlagOnly = FALSE;
  243. if (0 != (pOCNW->dwFlags & SC_DLG_MINIMAL_UI))
  244. {
  245. fOneFlagOnly = TRUE;
  246. }
  247. if (0 != (pOCNW->dwFlags & SC_DLG_FORCE_UI))
  248. {
  249. if (fOneFlagOnly)
  250. {
  251. return FALSE;
  252. }
  253. fOneFlagOnly = TRUE;
  254. }
  255. if (0 != (pOCNW->dwFlags & SC_DLG_NO_UI))
  256. {
  257. if (fOneFlagOnly)
  258. {
  259. return FALSE;
  260. }
  261. fOneFlagOnly = TRUE;
  262. }
  263. // Now check POPENCARD_SEARCH_CRITERIAW, if applicable
  264. if (NULL != pOCNW->pOpenCardSearchCriteria)
  265. {
  266. DWORD dwShareMode = pOCNW->pOpenCardSearchCriteria->dwShareMode;
  267. DWORD dwPreferredProtocols = pOCNW->pOpenCardSearchCriteria->dwPreferredProtocols;
  268. if (NULL != pOCNW->pOpenCardSearchCriteria->lpfnCheck)
  269. {
  270. // either lpfnConnect and lpfnDisconnect must be set
  271. if ( (NULL != pOCNW->pOpenCardSearchCriteria->lpfnConnect) &&
  272. (NULL != pOCNW->pOpenCardSearchCriteria->lpfnDisconnect) )
  273. {
  274. return TRUE;
  275. }
  276. if ( ( SCARD_SHARE_EXCLUSIVE == dwShareMode ||
  277. SCARD_SHARE_SHARED == dwShareMode ||
  278. SCARD_SHARE_DIRECT == dwShareMode ) &&
  279. CheckProtocols(dwPreferredProtocols)
  280. )
  281. {
  282. return TRUE;
  283. }
  284. return FALSE;
  285. }
  286. }
  287. // if all the tests have passed, it must be OK.
  288. return TRUE;
  289. }
  290. /*++
  291. void ListAllOKCardNames:
  292. Routine creates a multistring list of card names that match the
  293. search criteria for both ATR (as determined by the list of card
  294. names) and supported interfaces. This list of card names is not
  295. displayed to the user, but is used internally.
  296. This is a complete list of possible cards. Note that the list of
  297. supported interfaces is an _additive_ criteria, not a restrictive
  298. one.
  299. TODO: ?? recheck that assumption re: additive vs. restrictive. ??
  300. Arguments:
  301. pOCSC - POPENCARD_SEARCH_CRITERIAA
  302. mstrAllCards - referece to a CTextMultistring to take list of all OK cards
  303. Return Value:
  304. None.
  305. Author:
  306. Amanda Matlosz 09/16/1998
  307. --*/
  308. void ListAllOKCardNames(LPOPENCARDNAMEA_EX pOCNA, CTextMultistring& mstrAllCards) // ANSI
  309. {
  310. POPENCARD_SEARCH_CRITERIAA pOCSC = pOCNA->pOpenCardSearchCriteria;
  311. if ((NULL == pOCSC) || (NULL == pOCSC->lpstrCardNames))
  312. {
  313. // No cards specified
  314. return;
  315. }
  316. mstrAllCards = pOCSC->lpstrCardNames;
  317. //
  318. // List all cards that support the requested guidInterfaces
  319. //
  320. MatchInterfacesW(
  321. pOCNA->hSCardContext,
  322. pOCSC->rgguidInterfaces,
  323. pOCSC->cguidInterfaces,
  324. mstrAllCards);
  325. }
  326. void ListAllOKCardNames(LPOPENCARDNAMEW_EX pOCNW, CTextMultistring& mstrAllCards) // UNICODE
  327. {
  328. POPENCARD_SEARCH_CRITERIAW pOCSC = pOCNW->pOpenCardSearchCriteria;
  329. if ((NULL == pOCSC) || (NULL == pOCSC->lpstrCardNames))
  330. {
  331. // No cards specified
  332. return;
  333. }
  334. mstrAllCards = pOCSC->lpstrCardNames;
  335. //
  336. // List all cards that support the requested guidInterfaces
  337. //
  338. MatchInterfacesW(
  339. pOCNW->hSCardContext,
  340. pOCSC->rgguidInterfaces,
  341. pOCSC->cguidInterfaces,
  342. mstrAllCards);
  343. }
  344. // pdwOKCards is used so the caller can decide what additional actions to take
  345. // based on how many suitable cards were found
  346. LONG NoUISearch(OPENCARDNAMEA_EX* pOCN, DWORD* pdwOKCards, LPCSTR mszCards) // ansi-only
  347. {
  348. USES_CONVERSION;
  349. _ASSERTE(pOCN != NULL);
  350. *pdwOKCards = 0;
  351. LONG lReturn = SCARD_S_SUCCESS;
  352. SCARD_READERSTATEA* pReaderStatus = NULL;
  353. DWORD dwReaders = 0;
  354. const DWORD dwMeetsCriteria = 1;
  355. LPSTR szGroupNames = NULL;
  356. LPSTR szReaderNames = NULL;
  357. DWORD dw=0;
  358. DWORD dwNameLength = SCARD_AUTOALLOCATE;
  359. //
  360. // get list of readers we'll consider
  361. //
  362. if (NULL != pOCN->pOpenCardSearchCriteria &&
  363. NULL != pOCN->pOpenCardSearchCriteria->lpstrGroupNames)
  364. {
  365. szGroupNames = pOCN->pOpenCardSearchCriteria->lpstrGroupNames;
  366. }
  367. else
  368. {
  369. szGroupNames = W2A(SCARD_DEFAULT_READERS);
  370. }
  371. lReturn = SCardListReadersA(pOCN->hSCardContext,
  372. szGroupNames,
  373. (LPSTR)&szReaderNames,
  374. &dwNameLength);
  375. if(SCARD_S_SUCCESS == lReturn)
  376. {
  377. //
  378. // use the list of readers to build a readerstate array
  379. //
  380. dwReaders = AnsiMStringCount(szReaderNames);
  381. _ASSERTE(0 != dwReaders);
  382. pReaderStatus = new SCARD_READERSTATEA[dwReaders];
  383. if (NULL != pReaderStatus)
  384. {
  385. LPCSTR pchReader = szReaderNames;
  386. int nIndex = 0;
  387. memset(pReaderStatus, 0, sizeof(SCARD_READERSTATEA) * dwReaders);
  388. while(0 != *pchReader)
  389. {
  390. pReaderStatus[nIndex].szReader = pchReader;
  391. pReaderStatus[nIndex].dwCurrentState = SCARD_STATE_UNAWARE;
  392. pchReader += strlen(pchReader)+1;
  393. nIndex++;
  394. }
  395. }
  396. else
  397. {
  398. lReturn = SCARD_E_NO_MEMORY;
  399. }
  400. }
  401. //
  402. // If there are no readers, there's no point to go on.
  403. //
  404. if (0 == dwReaders || SCARD_S_SUCCESS != lReturn)
  405. {
  406. goto CleanUp;
  407. }
  408. //
  409. // Search for cards: use SCardLocateCards to find cards that match
  410. // ATR & interfaces supported if mszCards is not empty,
  411. // otherwise use SCardGetStatusChange() to look for any card
  412. //
  413. if (0 < AnsiMStringCount(mszCards))
  414. {
  415. lReturn = SCardLocateCardsA(pOCN->hSCardContext,
  416. mszCards,
  417. pReaderStatus,
  418. dwReaders);
  419. if (SCARD_S_SUCCESS == lReturn)
  420. {
  421. // for any that have SCARD_STATE_ATRMATCH set & don't have SCARD_STATE_EXCLUSIVE,
  422. // set pvUserData to dwMeetsCriteria
  423. for (dw=0; dw<dwReaders; dw++)
  424. {
  425. if ((pReaderStatus[dw].dwEventState & SCARD_STATE_ATRMATCH) &&
  426. !(pReaderStatus[dw].dwEventState & SCARD_STATE_EXCLUSIVE))
  427. {
  428. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  429. }
  430. }
  431. }
  432. }
  433. else
  434. {
  435. lReturn = SCardGetStatusChangeA(
  436. pOCN->hSCardContext,
  437. 0,
  438. pReaderStatus,
  439. dwReaders);
  440. if (SCARD_S_SUCCESS == lReturn)
  441. {
  442. // for any that have SCARD_STATE_PRESENT & don't have SCARD_STATE_EXCLUSIVE,
  443. // set pvUserData to dwMeetsCriteria
  444. for (dw=0; dw<dwReaders; dw++)
  445. {
  446. if ((pReaderStatus[dw].dwEventState & SCARD_STATE_PRESENT) &&
  447. !(pReaderStatus[dw].dwEventState & SCARD_STATE_EXCLUSIVE))
  448. {
  449. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  450. }
  451. }
  452. }
  453. }
  454. //
  455. // check each card to see if it's OK (meets callback criteria)
  456. //
  457. for (dw=0; dw<dwReaders; dw++)
  458. {
  459. if (dwMeetsCriteria == (DWORD)((DWORD_PTR)pReaderStatus[dw].pvUserData))
  460. {
  461. pReaderStatus[dw].pvUserData = NULL;
  462. // get the card name for CheckCardCallback;
  463. // if there's no name, don't accept it
  464. LPSTR szCard = NULL;
  465. szCard = GetCardNameA(pOCN->hSCardContext, pReaderStatus[dw].rgbAtr);
  466. if (NULL != szCard && NULL != *szCard)
  467. {
  468. if (CheckCardCallback((LPSTR)pReaderStatus[dw].szReader, szCard, pOCN))
  469. {
  470. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  471. (*pdwOKCards)++;
  472. }
  473. }
  474. if (NULL != szCard)
  475. {
  476. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szCard);
  477. }
  478. }
  479. }
  480. //
  481. // if SC_DLG_MIN_UI and only found one OK card, connect to that one
  482. // if SC_DLG_NO_UI and found one or more OK card, connect to the first
  483. //
  484. if ((0 != (pOCN->dwFlags & SC_DLG_MINIMAL_UI) && 1 == *pdwOKCards) ||
  485. (0 != (pOCN->dwFlags & SC_DLG_NO_UI) && 1 <= *pdwOKCards))
  486. {
  487. DWORD dwSel = 0;
  488. while (dwSel < dwReaders)
  489. {
  490. if (dwMeetsCriteria == (DWORD)((DWORD_PTR)pReaderStatus[dwSel].pvUserData))
  491. {
  492. break;
  493. }
  494. dwSel++;
  495. }
  496. _ASSERTE(dwSel<dwReaders); // Why didn't it find any OK cards?
  497. // get the card name for SetFinalCardSelection; can be NULL
  498. LPSTR szCard = NULL;
  499. szCard = GetCardNameA(pOCN->hSCardContext, pReaderStatus[dwSel].rgbAtr);
  500. lReturn = SetFinalCardSelection((LPSTR)(pReaderStatus[dwSel].szReader), szCard, pOCN);
  501. // let go of CardName
  502. if (NULL != szCard)
  503. {
  504. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szCard);
  505. }
  506. }
  507. else
  508. {
  509. if (SCARD_S_SUCCESS == lReturn)
  510. {
  511. lReturn = SCARD_E_CANCELLED; // any non-SCARD_S_SUCCESS return val will do
  512. }
  513. }
  514. CleanUp:
  515. //
  516. // Clean up
  517. //
  518. if (NULL != pReaderStatus)
  519. {
  520. delete [] pReaderStatus;
  521. }
  522. if (NULL != szReaderNames)
  523. {
  524. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szReaderNames);
  525. }
  526. return lReturn;
  527. }
  528. LONG NoUISearch(OPENCARDNAMEW_EX* pOCN, DWORD* pdwOKCards, LPCWSTR mszCards) // UNICODE
  529. {
  530. _ASSERTE(pOCN != NULL);
  531. *pdwOKCards = 0;
  532. LONG lReturn = SCARD_S_SUCCESS;
  533. SCARD_READERSTATEW* pReaderStatus = NULL;
  534. DWORD dwReaders = 0;
  535. const DWORD dwMeetsCriteria = 1;
  536. LPWSTR szGroupNames = NULL;
  537. LPWSTR szReaderNames = NULL;
  538. DWORD dw=0;
  539. DWORD dwNameLength = SCARD_AUTOALLOCATE;
  540. //
  541. // get list of readers we'll consider
  542. //
  543. if (NULL != pOCN->pOpenCardSearchCriteria &&
  544. NULL != pOCN->pOpenCardSearchCriteria->lpstrGroupNames)
  545. {
  546. szGroupNames = pOCN->pOpenCardSearchCriteria->lpstrGroupNames;
  547. }
  548. else
  549. {
  550. szGroupNames = SCARD_DEFAULT_READERS;
  551. }
  552. lReturn = SCardListReadersW(pOCN->hSCardContext,
  553. szGroupNames,
  554. (LPWSTR)&szReaderNames,
  555. &dwNameLength);
  556. if(SCARD_S_SUCCESS == lReturn)
  557. {
  558. //
  559. // use the list of readers to build a readerstate array
  560. //
  561. dwReaders = MStringCount(szReaderNames);
  562. _ASSERTE(0 != dwReaders);
  563. pReaderStatus = new SCARD_READERSTATEW[dwReaders];
  564. if (NULL != pReaderStatus)
  565. {
  566. LPCWSTR pchReader = szReaderNames;
  567. int nIndex = 0;
  568. memset(pReaderStatus, 0, sizeof(SCARD_READERSTATEW) * dwReaders);
  569. while(0 != *pchReader)
  570. {
  571. pReaderStatus[nIndex].szReader = pchReader;
  572. pReaderStatus[nIndex].dwCurrentState = SCARD_STATE_UNAWARE;
  573. pchReader += lstrlen(pchReader)+1;
  574. nIndex++;
  575. }
  576. }
  577. else
  578. {
  579. lReturn = SCARD_E_NO_MEMORY;
  580. }
  581. }
  582. //
  583. // If there are no readers, there's no point to go on.
  584. //
  585. if (0 == dwReaders)
  586. {
  587. goto CleanUp;
  588. }
  589. //
  590. // Search for cards: use SCardLocateCards to find cards that match
  591. // ATR & interfaces supported if mszCards is not empty,
  592. // otherwise use SCardGetStatusChange() to look for any card
  593. //
  594. if (0 < MStringCount(mszCards))
  595. {
  596. lReturn = SCardLocateCardsW(pOCN->hSCardContext,
  597. mszCards,
  598. pReaderStatus,
  599. dwReaders);
  600. if (SCARD_S_SUCCESS == lReturn)
  601. {
  602. // for any that have SCARD_STATE_ATRMATCH set & don't have SCARD_STATE_EXCLUSIVE,
  603. // set pvUserData to dwMeetsCriteria
  604. for (dw=0; dw<dwReaders; dw++)
  605. {
  606. if ((pReaderStatus[dw].dwEventState & SCARD_STATE_ATRMATCH) &&
  607. !(pReaderStatus[dw].dwEventState & SCARD_STATE_EXCLUSIVE))
  608. {
  609. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  610. }
  611. }
  612. }
  613. }
  614. else
  615. {
  616. lReturn = SCardGetStatusChangeW(
  617. pOCN->hSCardContext,
  618. 0,
  619. pReaderStatus,
  620. dwReaders);
  621. if (SCARD_S_SUCCESS == lReturn)
  622. {
  623. // for any that have SCARD_STATE_PRESENT & don't have SCARD_STATE_EXCLUSIVE,
  624. // set pvUserData to dwMeetsCriteria
  625. for (dw=0; dw<dwReaders; dw++)
  626. {
  627. if ((pReaderStatus[dw].dwEventState & SCARD_STATE_PRESENT) &&
  628. !(pReaderStatus[dw].dwEventState & SCARD_STATE_EXCLUSIVE))
  629. {
  630. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  631. }
  632. }
  633. }
  634. }
  635. //
  636. // check each card to see if it's OK (meets callback criteria)
  637. //
  638. for (dw=0; dw<dwReaders; dw++)
  639. {
  640. if (dwMeetsCriteria == (DWORD)((DWORD_PTR)pReaderStatus[dw].pvUserData))
  641. {
  642. pReaderStatus[dw].pvUserData = NULL;
  643. // get the card name for CheckCardCallback;
  644. // if there's no name, don't accept it
  645. LPWSTR szCard = NULL;
  646. szCard = GetCardNameW(pOCN->hSCardContext, pReaderStatus[dw].rgbAtr);
  647. if (NULL != szCard && 0 != lstrlen(szCard))
  648. {
  649. if (CheckCardCallback((LPWSTR)pReaderStatus[dw].szReader, szCard, pOCN))
  650. {
  651. pReaderStatus[dw].pvUserData = ULongToHandle(dwMeetsCriteria);
  652. (*pdwOKCards)++;
  653. }
  654. }
  655. // let go of CardName
  656. if (NULL != szCard)
  657. {
  658. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szCard);
  659. }
  660. }
  661. }
  662. //
  663. // if SC_DLG_MIN_UI and only found one OK card, connect to that one
  664. // if SC_DLG_NO_UI and found one or more OK card, connect to the first
  665. //
  666. if ((0 != (pOCN->dwFlags & SC_DLG_MINIMAL_UI) && 1 == *pdwOKCards) ||
  667. (0 != (pOCN->dwFlags & SC_DLG_NO_UI) && 1 <= *pdwOKCards))
  668. {
  669. DWORD dwSel = 0;
  670. while (dwSel < dwReaders)
  671. {
  672. if (dwMeetsCriteria == (DWORD)((DWORD_PTR)pReaderStatus[dwSel].pvUserData))
  673. {
  674. break;
  675. }
  676. dwSel++;
  677. }
  678. _ASSERTE(dwSel<dwReaders); // Why didn't it find any OK cards?
  679. // get the card name for SetFinalCardSelection; can be NULL
  680. LPWSTR szCard = NULL;
  681. szCard = GetCardNameW(pOCN->hSCardContext, pReaderStatus[dwSel].rgbAtr);
  682. lReturn = SetFinalCardSelection((LPWSTR)(pReaderStatus[dwSel].szReader), szCard, pOCN);
  683. // let go of CardName
  684. if (NULL != szCard)
  685. {
  686. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szCard);
  687. }
  688. }
  689. else
  690. {
  691. if (SCARD_S_SUCCESS == lReturn)
  692. {
  693. lReturn = SCARD_E_CANCELLED; // any non-SCARD_S_SUCCESS return val will do
  694. }
  695. }
  696. CleanUp:
  697. //
  698. // Clean up
  699. //
  700. if (NULL != pReaderStatus)
  701. {
  702. delete [] pReaderStatus;
  703. }
  704. if (NULL != szReaderNames)
  705. {
  706. SCardFreeMemory(pOCN->hSCardContext, (PVOID)szReaderNames);
  707. }
  708. return lReturn;
  709. }
  710. /*++
  711. BOOL CheckCardCallback:
  712. Routine connects to the indicated card/reader, calls user-
  713. supplied "check" function, and disconnects from card
  714. according to search criteria members.
  715. Arguments:
  716. szReader - indicated reader.
  717. szCard - indicated card name.
  718. pOCN - OPENCARDNAME_EX struct containing search criteria
  719. Return Value:
  720. TRUE if connection, check, and disconnection succeeds, otherwise
  721. FALSE.
  722. Author:
  723. Amanda Matlosz 07/09/1998
  724. --*/
  725. BOOL CheckCardCallback(LPSTR szReader, LPSTR szCard, OPENCARDNAMEA_EX* pOCN)
  726. {
  727. BOOL fReturn = FALSE;
  728. //
  729. // Check parameters
  730. //
  731. // if no check callback, succeed by default
  732. if (!(NULL != pOCN->pOpenCardSearchCriteria &&
  733. NULL != pOCN->pOpenCardSearchCriteria->lpfnCheck))
  734. {
  735. return TRUE;
  736. }
  737. // in order to connect, we either need to have dwShareMode set to non-0
  738. // or both the conenct and disconnect callbacks have to be valid.
  739. // This should have been caught in SetOCN()!
  740. if (0 == pOCN->pOpenCardSearchCriteria->dwShareMode &&
  741. (NULL == pOCN->pOpenCardSearchCriteria->lpfnConnect
  742. || NULL == pOCN->pOpenCardSearchCriteria->lpfnDisconnect))
  743. {
  744. return FALSE;
  745. }
  746. LPOCNCONNPROCA lpfnConnect = pOCN->pOpenCardSearchCriteria->lpfnConnect;
  747. LPOCNCHKPROC lpfnCheck = pOCN->pOpenCardSearchCriteria->lpfnCheck;
  748. LPOCNDSCPROC lpfnDisconnect = pOCN->pOpenCardSearchCriteria->lpfnDisconnect;
  749. PVOID pvUserData = pOCN->pOpenCardSearchCriteria->pvUserData;
  750. //
  751. // Connect, preferably through the callback
  752. //
  753. SCARDHANDLE hCard = NULL;
  754. if (NULL != lpfnConnect)
  755. {
  756. hCard = lpfnConnect(pOCN->hSCardContext,
  757. szReader,
  758. szCard,
  759. pvUserData);
  760. }
  761. else
  762. {
  763. DWORD dw = 0; // Don't need to know the active protocol
  764. LONG lReturn = SCardConnectA(pOCN->hSCardContext,
  765. (LPCSTR)szReader,
  766. pOCN->pOpenCardSearchCriteria->dwShareMode,
  767. pOCN->pOpenCardSearchCriteria->dwPreferredProtocols,
  768. &hCard,
  769. &dw);
  770. // TODO: ?? maybe want to trace failure of lReturn... ??
  771. }
  772. // if the connect failed, there's no way we can check the card!
  773. if (NULL == hCard)
  774. {
  775. return fReturn;
  776. }
  777. //
  778. // Check the card
  779. //
  780. fReturn = lpfnCheck(pOCN->hSCardContext,
  781. hCard,
  782. pvUserData);
  783. //
  784. // Disconnect from the card and clean up.
  785. //
  786. if (NULL != lpfnDisconnect)
  787. {
  788. lpfnDisconnect(pOCN->hSCardContext,
  789. hCard,
  790. pvUserData);
  791. }
  792. else
  793. {
  794. SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  795. }
  796. return fReturn;
  797. }
  798. BOOL CheckCardCallback(LPWSTR szReader, LPWSTR szCard, OPENCARDNAMEW_EX* pOCN)
  799. {
  800. BOOL fReturn = FALSE;
  801. //
  802. // Check parameters
  803. //
  804. // if no check callback, succeed by default
  805. if (!(NULL != pOCN->pOpenCardSearchCriteria &&
  806. NULL != pOCN->pOpenCardSearchCriteria->lpfnCheck))
  807. {
  808. return TRUE;
  809. }
  810. // in order to connect, we either need to have dwShareMode set to non-0
  811. // or both the conenct and disconnect callbacks have to be valid.
  812. // This should have been caught in SetOCN()!
  813. if (0 == pOCN->pOpenCardSearchCriteria->dwShareMode &&
  814. (NULL == pOCN->pOpenCardSearchCriteria->lpfnConnect
  815. || NULL == pOCN->pOpenCardSearchCriteria->lpfnDisconnect))
  816. {
  817. return FALSE;
  818. }
  819. LPOCNCONNPROCW lpfnConnect = pOCN->pOpenCardSearchCriteria->lpfnConnect;
  820. LPOCNCHKPROC lpfnCheck = pOCN->pOpenCardSearchCriteria->lpfnCheck;
  821. LPOCNDSCPROC lpfnDisconnect = pOCN->pOpenCardSearchCriteria->lpfnDisconnect;
  822. PVOID pvUserData = pOCN->pOpenCardSearchCriteria->pvUserData;
  823. //
  824. // Connect, preferably through the callback
  825. //
  826. SCARDHANDLE hCard = NULL;
  827. if (NULL != lpfnConnect)
  828. {
  829. hCard = lpfnConnect(pOCN->hSCardContext,
  830. szReader,
  831. szCard,
  832. pvUserData);
  833. }
  834. else
  835. {
  836. DWORD dw = 0; // Don't need to know the active protocol
  837. LONG lReturn = SCardConnectW(pOCN->hSCardContext,
  838. (LPCWSTR)szReader,
  839. pOCN->pOpenCardSearchCriteria->dwShareMode,
  840. pOCN->pOpenCardSearchCriteria->dwPreferredProtocols,
  841. &hCard,
  842. &dw);
  843. // TODO: ?? maybe want to trace failure of lReturn... ??
  844. }
  845. // if the connect failed, there's no way we can check the card!
  846. if (NULL == hCard)
  847. {
  848. return fReturn;
  849. }
  850. //
  851. // Check the card
  852. //
  853. fReturn = lpfnCheck(pOCN->hSCardContext,
  854. hCard,
  855. pvUserData);
  856. //
  857. // Disconnect from the card and clean up.
  858. //
  859. if (NULL != lpfnDisconnect)
  860. {
  861. lpfnDisconnect(pOCN->hSCardContext,
  862. hCard,
  863. pvUserData);
  864. }
  865. else
  866. {
  867. SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  868. }
  869. return fReturn;
  870. }
  871. /*++
  872. BOOL CheckCardAll:
  873. Routine checks to see whether or not the indicated card meets
  874. the search criteria. ATR, supported interfaces, and callbacks
  875. are all checked.
  876. Arguments:
  877. pReader - Reader containing card to check acceptability of
  878. pOCN - OPENCARDNAME[A|W]_EX struct containing search criteria, etc.
  879. mszCards - a multistring containing names of ALL acceptable cards
  880. Return Value:
  881. A BOOL value indicating the acceptibility of the given card.
  882. Author:
  883. Amanda Matlosz 07/09/1998
  884. --*/
  885. BOOL CheckCardAll(CSCardReaderState* pReader, OPENCARDNAMEA_EX* pOCN, LPCWSTR mszCards) // ANSI
  886. {
  887. USES_CONVERSION;
  888. BOOL fReturn = FALSE; // assume no match
  889. _ASSERTE(NULL != pReader && NULL != pOCN);
  890. if (NULL == pReader || NULL == pOCN)
  891. {
  892. return FALSE;
  893. }
  894. // Check Name & interfaces
  895. if (!pReader->strCard.IsEmpty())
  896. {
  897. LPCWSTR msz = mszCards;
  898. if (0 < MStringCount(msz))
  899. {
  900. msz = FirstString(mszCards);
  901. while (!fReturn && msz != NULL)
  902. {
  903. // compare if OK fReturn = TRUE;
  904. if (0 == pReader->strCard.Compare(msz) || 0==lstrlen(msz))
  905. {
  906. fReturn = TRUE;
  907. }
  908. else
  909. {
  910. msz = NextString(msz);
  911. }
  912. }
  913. }
  914. else
  915. {
  916. fReturn = TRUE;
  917. }
  918. }
  919. // Check Callback
  920. if (fReturn)
  921. {
  922. // turn CStrings into LPSTRs
  923. LPSTR szReader = W2A(pReader->strReader);
  924. LPSTR szCard = W2A(pReader->strCard);
  925. fReturn = CheckCardCallback(szReader, szCard, pOCN);
  926. }
  927. // note in readerstate whether or not the card passed all tests
  928. pReader->fOK = fReturn;
  929. return fReturn;
  930. }
  931. BOOL CheckCardAll(CSCardReaderState* pReader, OPENCARDNAMEW_EX* pOCN, LPCWSTR mszCards) // UNICODE
  932. {
  933. BOOL fReturn = FALSE; // assume no match
  934. _ASSERTE(NULL != pReader && NULL != pOCN);
  935. if (NULL == pReader || NULL == pOCN)
  936. {
  937. return FALSE;
  938. }
  939. // Check Name & interfaces
  940. if (!pReader->strCard.IsEmpty())
  941. {
  942. LPCWSTR msz = mszCards;
  943. if (0 < MStringCount(msz))
  944. {
  945. msz = FirstString(mszCards);
  946. while (!fReturn && msz != NULL)
  947. {
  948. // compare if OK fReturn = TRUE;
  949. if (0 == pReader->strCard.Compare(msz) || 0==lstrlen(msz))
  950. {
  951. fReturn = TRUE;
  952. }
  953. else
  954. {
  955. msz = NextString(msz);
  956. }
  957. }
  958. }
  959. else
  960. {
  961. fReturn = TRUE;
  962. }
  963. }
  964. // Check Callback
  965. if (fReturn)
  966. {
  967. // turn CStrings into LPSTRs
  968. LPWSTR szReader = pReader->strReader.GetBuffer(1);
  969. LPWSTR szCard = pReader->strCard.GetBuffer(1);
  970. fReturn = CheckCardCallback(szReader, szCard, pOCN);
  971. pReader->strReader.ReleaseBuffer();
  972. pReader->strCard.ReleaseBuffer();
  973. }
  974. // note in readerstate whether or not the card passed all tests
  975. pReader->fOK = fReturn;
  976. return fReturn;
  977. }
  978. /*++
  979. LONG SetFinalCardSelection:
  980. Routine connects to a selected reader, and sets the user-provided structs
  981. to contain the reader&cardname. Returns an error if the user-provided struct's
  982. buffers aren't long enough.
  983. Arguments:
  984. dwSelectedReader - index used to select which reader to connect to.
  985. Return Value:
  986. A LONG value indicating the status of the requested action.
  987. See the Smartcard header files for additional information.
  988. Author:
  989. Amanda Matlosz 07/09/1998
  990. --*/
  991. LONG SetFinalCardSelection(LPSTR szReader, LPSTR szCard, OPENCARDNAMEA_EX* pOCN) // ANSI
  992. {
  993. _ASSERTE(NULL != pOCN);
  994. pOCN->hCardHandle = NULL;
  995. LONG lReturn = SCARD_S_SUCCESS;
  996. //
  997. // Set return values in OCN
  998. //
  999. if (NULL == szReader)
  1000. {
  1001. lReturn = SCARD_F_INTERNAL_ERROR;
  1002. }
  1003. else
  1004. {
  1005. if (pOCN->nMaxRdr >= strlen(szReader)+1)
  1006. {
  1007. ::CopyMemory( (LPVOID)pOCN->lpstrRdr,
  1008. (CONST LPVOID)szReader,
  1009. strlen(szReader)+1);
  1010. }
  1011. else
  1012. {
  1013. pOCN->nMaxRdr = strlen(szReader)+1;
  1014. lReturn = SCARD_E_NO_MEMORY;
  1015. }
  1016. }
  1017. if (SCARD_S_SUCCESS == lReturn)
  1018. {
  1019. if (NULL == szCard)
  1020. {
  1021. lReturn = SCARD_F_INTERNAL_ERROR;
  1022. }
  1023. else
  1024. {
  1025. if (pOCN->nMaxCard >= strlen(szCard)+1)
  1026. {
  1027. ::CopyMemory( (LPVOID)pOCN->lpstrCard,
  1028. (CONST LPVOID)szCard,
  1029. strlen(szCard)+1);
  1030. }
  1031. else
  1032. {
  1033. pOCN->nMaxCard = strlen(szCard)+1;
  1034. lReturn = SCARD_E_NO_MEMORY;
  1035. }
  1036. }
  1037. }
  1038. //
  1039. // Connect to card only if we're still in a successful state,
  1040. //
  1041. if (SCARD_S_SUCCESS == lReturn)
  1042. {
  1043. if(NULL != pOCN->lpfnConnect)
  1044. {
  1045. pOCN->hCardHandle = pOCN->lpfnConnect(
  1046. pOCN->hSCardContext,
  1047. szReader,
  1048. szCard,
  1049. pOCN->pvUserData);
  1050. }
  1051. else if (0 != pOCN->dwShareMode)
  1052. {
  1053. lReturn = SCardConnectA(pOCN->hSCardContext,
  1054. (LPCSTR)szReader,
  1055. pOCN->dwShareMode,
  1056. pOCN->dwPreferredProtocols,
  1057. &pOCN->hCardHandle,
  1058. &pOCN->dwActiveProtocol);
  1059. if (SCARD_S_SUCCESS != lReturn)
  1060. {
  1061. // must return hCardHandle of NULL
  1062. pOCN->hCardHandle = NULL;
  1063. }
  1064. }
  1065. }
  1066. return lReturn;
  1067. }
  1068. LONG SetFinalCardSelection(LPWSTR szReader, LPWSTR szCard, OPENCARDNAMEW_EX* pOCN) // UNICODE
  1069. {
  1070. _ASSERTE(NULL != pOCN);
  1071. pOCN->hCardHandle = NULL;
  1072. LONG lReturn = SCARD_S_SUCCESS;
  1073. //
  1074. // Set return values in OCN
  1075. //
  1076. if (NULL == szReader)
  1077. {
  1078. lReturn = SCARD_F_INTERNAL_ERROR;
  1079. }
  1080. else
  1081. {
  1082. if (pOCN->nMaxRdr >= (DWORD)lstrlen(szReader)+1)
  1083. {
  1084. ::CopyMemory( (LPVOID)pOCN->lpstrRdr,
  1085. (CONST LPVOID)szReader,
  1086. sizeof(WCHAR)*(lstrlen(szReader)+1));
  1087. }
  1088. else
  1089. {
  1090. pOCN->nMaxRdr = lstrlen(szReader)+1;
  1091. lReturn = SCARD_E_NO_MEMORY;
  1092. }
  1093. }
  1094. if (SCARD_S_SUCCESS == lReturn)
  1095. {
  1096. if (NULL == szCard)
  1097. {
  1098. lReturn = SCARD_F_INTERNAL_ERROR;
  1099. }
  1100. else
  1101. {
  1102. if (pOCN->nMaxCard >= (DWORD)lstrlen(szCard)+1)
  1103. {
  1104. ::CopyMemory( (LPVOID)pOCN->lpstrCard,
  1105. (CONST LPVOID)szCard,
  1106. sizeof(WCHAR)*(lstrlen(szCard)+1));
  1107. }
  1108. else
  1109. {
  1110. pOCN->nMaxCard = lstrlen(szCard)+1;
  1111. lReturn = SCARD_E_NO_MEMORY;
  1112. }
  1113. }
  1114. }
  1115. //
  1116. // Connect to card only if we're still in a successful state,
  1117. //
  1118. if (SCARD_S_SUCCESS == lReturn)
  1119. {
  1120. if(NULL != pOCN->lpfnConnect)
  1121. {
  1122. pOCN->hCardHandle = pOCN->lpfnConnect(
  1123. pOCN->hSCardContext,
  1124. szReader,
  1125. szCard,
  1126. pOCN->pvUserData);
  1127. }
  1128. else if (0 != pOCN->dwShareMode)
  1129. {
  1130. lReturn = SCardConnectW(pOCN->hSCardContext,
  1131. (LPCWSTR)szReader,
  1132. pOCN->dwShareMode,
  1133. pOCN->dwPreferredProtocols,
  1134. &pOCN->hCardHandle,
  1135. &pOCN->dwActiveProtocol);
  1136. if (SCARD_S_SUCCESS != lReturn)
  1137. {
  1138. // must return hCardHandle of NULL
  1139. pOCN->hCardHandle = NULL;
  1140. }
  1141. }
  1142. }
  1143. return lReturn;
  1144. }