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.

2320 lines
66 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. WinSCard
  5. Abstract:
  6. This module supplies the UNICODE version of the API for the Calais Smartcard
  7. Service Manager.
  8. The Calais Service Manager does the work of coordinating the protocols,
  9. readers, drivers, and smartcards on behalf of the application. The
  10. following services are provided as part of a library to simplify access to
  11. the Service Manager. These routines are the documented, exposed APIs.
  12. These routines merely package the requests and forward them to the Calais
  13. Service Manager, allowing the actual implementation of Calais to vary over
  14. time.
  15. At no time does the API library make security decisions. All
  16. security-related functions must be performed by the Service Manager, running
  17. in its own address space, or in the operating system kernel. However, some
  18. utility routines may be implemented in the API library for speed, as long as
  19. they do not involve security decisions.
  20. Author:
  21. Doug Barlow (dbarlow) 10/23/1996
  22. Environment:
  23. Win32, C++ w/ Exceptions
  24. Notes:
  25. ?Notes?
  26. --*/
  27. #define __SUBROUTINE__
  28. #ifndef WIN32_LEAN_AND_MEAN
  29. #define WIN32_LEAN_AND_MEAN
  30. #endif
  31. #include <windows.h>
  32. #include "client.h"
  33. #include "redirect.h"
  34. extern HANDLE g_hUnifiedStartedEvent;
  35. //
  36. ////////////////////////////////////////////////////////////////////////////////
  37. //
  38. // Calais Database Query Services
  39. //
  40. // These services all are oriented towards reading the Calais database.
  41. // They provide the option for listing a Smartcard Context (see Section
  42. // 4.1.1), but do not require one. Note that without a context, some or
  43. // all information may be inaccessable due to security restrictions.
  44. //
  45. /*++
  46. SCardListReaderGroups:
  47. This service provides the list of named card reader groups that have
  48. previously been defined to the system. The group 'SCard$DefaultReaders' is
  49. only returned if it contains at least one reader. The group
  50. 'SCard$AllReaders' is not returned, as it implicitly exists.
  51. Arguments:
  52. hContext supplies the handle identifying the Service Manager Context
  53. established previously via the SCardEstablishContext() service, or is
  54. NULL if this query is not directed towards a specific context.
  55. mszGroups receives a multi-string listing the reader groups defined to this
  56. system and available to the current user on the current terminal. If
  57. this value is NULL, the supplied buffer length in pcchGroups is ignored,
  58. the length of the buffer that would have been returned had this
  59. parameter not been null is written to pcchGroups, and a success code is
  60. returned.
  61. pcchGroups supplies the length of the mszGroups buffer in characters, and
  62. receives the actual length of the multi-string structure, including all
  63. trailing Null characters. If the buffer length is specified as
  64. SCARD_AUTOALLOCATE, then szGroups is converted to a pointer to a string
  65. pointer, and receives the address of a block of memory containing the
  66. multi-string structure. This block of memory must be deallocated via
  67. the SCardFreeMemory() service.
  68. Return Value:
  69. A 32-bit value indicating whether or not the service completed successfully.
  70. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  71. represents an error condition.
  72. Author:
  73. Doug Barlow (dbarlow) 10/23/1996
  74. --*/
  75. #undef __SUBROUTINE__
  76. #define __SUBROUTINE__ DBGT("SCardListReaderGroupsW")
  77. WINSCARDAPI LONG WINAPI
  78. SCardListReaderGroupsW(
  79. IN SCARDCONTEXT hContext,
  80. OUT LPWSTR mszGroups,
  81. IN OUT LPDWORD pcchGroups)
  82. {
  83. LONG nReturn = SCARD_S_SUCCESS;
  84. try
  85. {
  86. CSCardUserContext *pCtx = NULL;
  87. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  88. CBuffer bfGroups;
  89. SCARDCONTEXT hRedirContext = NULL;
  90. if (NULL != hContext)
  91. {
  92. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  93. if (pCtx->IsBad())
  94. {
  95. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  96. }
  97. dwScope = pCtx->Scope();
  98. hRedirContext = pCtx->GetRedirContext();
  99. }
  100. if (hRedirContext || InTSRedirectMode()) {
  101. if (!TS_REDIRECT_READY)
  102. {
  103. throw (DWORD)SCARD_E_NO_SERVICE;
  104. }
  105. nReturn = pfnSCardListReaderGroupsW(hRedirContext, mszGroups, pcchGroups);
  106. }
  107. else
  108. {
  109. ListReaderGroups(dwScope, bfGroups);
  110. PlaceMultiResult(pCtx, bfGroups, mszGroups, pcchGroups);
  111. }
  112. }
  113. catch (DWORD dwStatus)
  114. {
  115. nReturn = (LONG)dwStatus;
  116. }
  117. catch (...)
  118. {
  119. nReturn = SCARD_E_INVALID_PARAMETER;
  120. }
  121. return nReturn;
  122. }
  123. /*++
  124. SCardListReaders:
  125. This service provides the list of readers within a set of named reader
  126. groups, eliminating duplicates. The caller supplies a multistring listing
  127. the name of a set of pre-defined group of readers, and receives the list of
  128. smartcard readers within the named groups. Unrecognized group names are
  129. ignored.
  130. Arguments:
  131. hContext supplies the handle identifying the Service Manager Context
  132. established previously via the SCardEstablishContext() service, or is
  133. NULL if this query is not directed towards a specific context.
  134. mszGroups supplies the names of the reader groups defined to the system, as
  135. a multi-string. A NULL value is used to indicate that all readers in
  136. the system be listed (i.e., the SCard$AllReaders group).
  137. mszReaders receives a multi-string listing the card readers within the
  138. supplied reader groups. If this value is NULL, the supplied buffer
  139. length in pcchReaders is ignored, the length of the buffer that would
  140. have been returned had this parameter not been null is written to
  141. pcchReaders, and a success code is returned.
  142. pcchReaders supplies the length of the mszReaders buffer in characters, and
  143. receives the actual length of the multi-string structure, including all
  144. trailing Null characters. If the buffer length is specified as
  145. SCARD_AUTOALLOCATE, then mszReaders is converted to a pointer to a
  146. string pointer, and receives the address of a block of memory containing
  147. the multi-string structure. This block of memory must be deallocated
  148. via the SCardFreeMemory() service.
  149. Return Value:
  150. A 32-bit value indicating whether or not the service completed successfully.
  151. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  152. represents an error condition.
  153. Author:
  154. Doug Barlow (dbarlow) 10/23/1996
  155. --*/
  156. #undef __SUBROUTINE__
  157. #define __SUBROUTINE__ DBGT("SCardListReadersW")
  158. WINSCARDAPI LONG WINAPI
  159. SCardListReadersW(
  160. IN SCARDCONTEXT hContext,
  161. IN LPCWSTR mszGroups,
  162. OUT LPWSTR mszReaders,
  163. IN OUT LPDWORD pcchReaders)
  164. {
  165. LONG nReturn = SCARD_S_SUCCESS;
  166. try
  167. {
  168. CSCardUserContext *pCtx = NULL;
  169. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  170. CBuffer bfReaders;
  171. CTextMultistring mtzGroups;
  172. SCARDCONTEXT hRedirContext = NULL;
  173. if (NULL != hContext)
  174. {
  175. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  176. if (pCtx->IsBad())
  177. {
  178. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  179. }
  180. dwScope = pCtx->Scope();
  181. hRedirContext = pCtx->GetRedirContext();
  182. }
  183. if (hRedirContext || InTSRedirectMode()) {
  184. if (!TS_REDIRECT_READY)
  185. {
  186. throw (DWORD)SCARD_E_NO_SERVICE;
  187. }
  188. nReturn = pfnSCardListReadersW(hRedirContext, mszGroups, mszReaders, pcchReaders);
  189. }
  190. else
  191. {
  192. mtzGroups = mszGroups;
  193. ListReaders(dwScope, mtzGroups, bfReaders);
  194. if (NULL != pCtx)
  195. pCtx->StripInactiveReaders(bfReaders);
  196. PlaceMultiResult(pCtx, bfReaders, mszReaders, pcchReaders);
  197. }
  198. }
  199. catch (DWORD dwStatus)
  200. {
  201. nReturn = (LONG)dwStatus;
  202. }
  203. catch (...)
  204. {
  205. nReturn = SCARD_E_INVALID_PARAMETER;
  206. }
  207. return nReturn;
  208. }
  209. /*++
  210. SCardListCards:
  211. This service provides a list of named cards previously introduced to the
  212. system by this user which match an optionally supplied ATR string.
  213. Arguments:
  214. hContext supplies the handle identifying the Service Manager Context
  215. established previously via the SCardEstablishContext() service, or is
  216. NULL if this query is not directed towards a specific context.
  217. pbAtr supplies the address of an ATR string to compare to known cards, or
  218. NULL if all card names are to be returned.
  219. rgguidInterfaces supplies an array of GUIDs, or the value NULL. When an
  220. array is supplied, a card name will be returned only if this set of
  221. GUIDs is a (possibly improper) subset of the set of GUIDs supported by
  222. the card.
  223. cguidInterfaceCount supplies the number of entries in the rgguidInterfaces
  224. array. If rgguidInterfaces is NULL, then this value is ignored.
  225. mszCards receives a multi-string listing the smartcards introduced to the
  226. system by this user which match the supplied ATR string. If this value
  227. is NULL, the supplied buffer length in pcchCards is ignored, the length
  228. of the buffer that would have been returned had this parameter not been
  229. null is written to pcchCards, and a success code is returned.
  230. pcchCards supplies the length of the mszCards buffer in characters, and
  231. receives the actual length of the multi-string structure, including all
  232. trailing Null characters. If the buffer length is specified as
  233. SCARD_AUTOALLOCATE, then mszCards is converted to a pointer to a string
  234. pointer, and receives the address of a block of memory containing the
  235. multi-string structure. This block of memory must be deallocated via he
  236. SCardFreeMemory() service.
  237. Return Value:
  238. A 32-bit value indicating whether or not the service completed successfully.
  239. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  240. represents an error condition.
  241. Author:
  242. Doug Barlow (dbarlow) 10/23/1996
  243. --*/
  244. #undef __SUBROUTINE__
  245. #define __SUBROUTINE__ DBGT("SCardListCardsW")
  246. WINSCARDAPI LONG WINAPI
  247. SCardListCardsW(
  248. IN SCARDCONTEXT hContext,
  249. IN LPCBYTE pbAtr,
  250. IN LPCGUID rgquidInterfaces,
  251. IN DWORD cguidInterfaceCount,
  252. OUT LPWSTR mszCards,
  253. IN OUT LPDWORD pcchCards)
  254. {
  255. LONG nReturn = SCARD_S_SUCCESS;
  256. try
  257. {
  258. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  259. CBuffer bfCards;
  260. CSCardUserContext *pCtx = NULL;
  261. if (NULL != hContext)
  262. {
  263. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  264. dwScope = pCtx->Scope();
  265. }
  266. ListCards(
  267. dwScope,
  268. pbAtr,
  269. rgquidInterfaces,
  270. cguidInterfaceCount,
  271. bfCards);
  272. PlaceMultiResult(pCtx, bfCards, mszCards, pcchCards);
  273. }
  274. catch (DWORD dwStatus)
  275. {
  276. nReturn = (LONG)dwStatus;
  277. }
  278. catch (...)
  279. {
  280. nReturn = SCARD_E_INVALID_PARAMETER;
  281. }
  282. return nReturn;
  283. }
  284. /*++
  285. SCardListInterfaces:
  286. This service provides a list of interfaces known to be supplied by a given
  287. card. The caller supplies the name of a smartcard previously introduced to
  288. the system, and receives the list of interfaces supported by the card.
  289. Arguments:
  290. hContext supplies the handle identifying the Service Manager Context
  291. established previously via the SCardEstablishContext() service, or is
  292. NULL if this query is not directed towards a specific context.
  293. szCard supplies the name of the card defined to the system.
  294. pguidInterfaces receives an array of GUIDs indicating the interfaces
  295. supported by the named smartcard. If this value is NULL, the supplied
  296. array length in pcguidInterfaces is ignored, the size of the array that
  297. would have been returned had this parameter not been null is written to
  298. pcguidInterfaces, and a success code is returned.
  299. pcguidInterfaces supplies the size of the pguidInterfaces array, and
  300. receives the actual size of the returned array. If the array size is
  301. specified as SCARD_AUTOALLOCATE, then pguidInterfaces is converted to a
  302. pointer to a GUID pointer, and receives the address of a block of memory
  303. containing the array. This block of memory must be deallocated via he
  304. SCardFreeMemory() service.
  305. Return Value:
  306. A 32-bit value indicating whether or not the service completed successfully.
  307. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  308. represents an error condition.
  309. Author:
  310. Doug Barlow (dbarlow) 10/23/1996
  311. --*/
  312. #undef __SUBROUTINE__
  313. #define __SUBROUTINE__ DBGT("SCardListInterfacesW")
  314. WINSCARDAPI LONG WINAPI
  315. SCardListInterfacesW(
  316. IN SCARDCONTEXT hContext,
  317. IN LPCWSTR szCard,
  318. OUT LPGUID pguidInterfaces,
  319. IN OUT LPDWORD pcguidInterfaces)
  320. {
  321. LONG nReturn = SCARD_S_SUCCESS;
  322. try
  323. {
  324. BOOL fSts;
  325. CTextString tzCard;
  326. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  327. DWORD cbInterfaces;
  328. CBuffer bfInterfaces;
  329. CSCardUserContext *pCtx = NULL;
  330. if (NULL != hContext)
  331. {
  332. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  333. dwScope = pCtx->Scope();
  334. }
  335. tzCard = szCard;
  336. fSts = GetCardInfo(
  337. dwScope,
  338. tzCard,
  339. NULL,
  340. NULL,
  341. &bfInterfaces,
  342. NULL);
  343. if (!fSts)
  344. throw (DWORD)SCARD_E_UNKNOWN_CARD;
  345. if (SCARD_AUTOALLOCATE == *pcguidInterfaces)
  346. cbInterfaces = SCARD_AUTOALLOCATE;
  347. else
  348. cbInterfaces = *pcguidInterfaces * sizeof(GUID);
  349. PlaceResult(
  350. pCtx,
  351. bfInterfaces,
  352. (LPBYTE)pguidInterfaces,
  353. &cbInterfaces);
  354. *pcguidInterfaces = cbInterfaces / sizeof(GUID);
  355. }
  356. catch (DWORD dwStatus)
  357. {
  358. nReturn = (LONG)dwStatus;
  359. }
  360. catch (...)
  361. {
  362. nReturn = SCARD_E_INVALID_PARAMETER;
  363. }
  364. return nReturn;
  365. }
  366. /*++
  367. SCardGetProviderId:
  368. This service returns the GUID of the Primary Service Provider for the given
  369. card. The caller supplies the name of a smartcard previously introduced to
  370. the system, and receives the registered Primary Service Provider GUID, if
  371. any.
  372. Arguments:
  373. hContext supplies the handle identifying the Service Manager Context
  374. established previously via the SCardEstablishContext() service, or is
  375. NULL if this query is not directed towards a specific context.
  376. szCard supplies the name of the card defined to the system.
  377. pguidInterfaces receives the GUID of the Primary Service Provider of the
  378. indicated card. This provider may be activated via COM, and will supply
  379. access to other services in the card.
  380. Return Value:
  381. A 32-bit value indicating whether or not the service completed successfully.
  382. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  383. represents an error condition.
  384. Author:
  385. Doug Barlow (dbarlow) 10/23/1996
  386. --*/
  387. #undef __SUBROUTINE__
  388. #define __SUBROUTINE__ DBGT("SCardGetProviderIdW")
  389. WINSCARDAPI LONG WINAPI
  390. SCardGetProviderIdW(
  391. IN SCARDCONTEXT hContext,
  392. IN LPCWSTR szCard,
  393. OUT LPGUID pguidProviderId)
  394. {
  395. LONG nReturn = SCARD_S_SUCCESS;
  396. try
  397. {
  398. BOOL fSts;
  399. CTextString tzCard;
  400. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  401. CBuffer bfProvider;
  402. if (NULL != hContext)
  403. {
  404. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  405. dwScope = pCtx->Scope();
  406. }
  407. tzCard = szCard;
  408. fSts = GetCardInfo(
  409. dwScope,
  410. tzCard,
  411. NULL,
  412. NULL,
  413. NULL,
  414. &bfProvider);
  415. if (!fSts)
  416. throw (DWORD)SCARD_E_UNKNOWN_CARD;
  417. if (sizeof(GUID) != bfProvider.Length())
  418. throw (DWORD)SCARD_E_INVALID_TARGET;
  419. CopyMemory(pguidProviderId, bfProvider.Access(), bfProvider.Length());
  420. }
  421. catch (DWORD dwStatus)
  422. {
  423. nReturn = (LONG)dwStatus;
  424. }
  425. catch (...)
  426. {
  427. nReturn = SCARD_E_INVALID_PARAMETER;
  428. }
  429. return nReturn;
  430. }
  431. /*++
  432. SCardGetCardTypeProviderName:
  433. This service returns the value of a given Provider Name, by Id number, for
  434. the identified card type. The caller supplies the name of a smartcard
  435. previously introduced to the system, and receives the registered Service
  436. Provider of that type, if any, as a string.
  437. Arguments:
  438. hContext supplies the handle identifying the Service Manager Context
  439. established previously via the SCardEstablishContext() service, or is
  440. NULL if this query is not directed towards a specific context.
  441. szCardName supplies the name of the card type with which this provider name
  442. is associated.
  443. dwProviderId supplies the identifier for the provider associated with this
  444. card type. Possible values are:
  445. SCARD_PROVIDER_SSP - The Primary SSP identifier, as a GUID string.
  446. SCARD_PROVIDER_CSP - The CSP name.
  447. Other values < 0x80000000 are reserved for use by Microsoft. Values
  448. over 0x80000000 are available for use by the smart card vendors, and
  449. are card-specific.
  450. szProvider receives the string identifying the provider.
  451. pcchProvider supplies the length of the szProvider buffer in characters,
  452. and receives the actual length of the returned string, including the
  453. trailing null character. If the buffer length is specified as
  454. SCARD_AUTOALLOCATE, then szProvider is converted to a pointer to a
  455. string pointer, and receives the address of a block of memory
  456. containing the string. This block of memory must be deallocated via
  457. the SCardFreeMemory() service.
  458. Return Value:
  459. A 32-bit value indicating whether or not the service completed successfully.
  460. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  461. represents an error condition.
  462. Throws:
  463. Errors as DWORD status codes
  464. Author:
  465. Doug Barlow (dbarlow) 1/19/1998
  466. --*/
  467. #undef __SUBROUTINE__
  468. #define __SUBROUTINE__ DBGT("SCardGetCardTypeProviderNameW")
  469. WINSCARDAPI LONG WINAPI
  470. SCardGetCardTypeProviderNameW(
  471. IN SCARDCONTEXT hContext,
  472. IN LPCWSTR szCardName,
  473. IN DWORD dwProviderId,
  474. OUT LPWSTR szProvider,
  475. IN OUT LPDWORD pcchProvider)
  476. {
  477. LONG nReturn = SCARD_S_SUCCESS;
  478. try
  479. {
  480. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  481. CTextString tzCardName;
  482. CBuffer bfProvider;
  483. CSCardUserContext *pCtx = NULL;
  484. if (NULL != hContext)
  485. {
  486. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  487. dwScope = pCtx->Scope();
  488. }
  489. tzCardName = szCardName;
  490. GetCardTypeProviderName(
  491. dwScope,
  492. tzCardName,
  493. dwProviderId,
  494. bfProvider);
  495. PlaceResult(pCtx, bfProvider, szProvider, pcchProvider);
  496. }
  497. catch (DWORD dwStatus)
  498. {
  499. nReturn = (LONG)dwStatus;
  500. }
  501. catch (...)
  502. {
  503. nReturn = SCARD_E_INVALID_PARAMETER;
  504. }
  505. return nReturn;
  506. }
  507. //
  508. ////////////////////////////////////////////////////////////////////////////////
  509. //
  510. // Calais Database Management Services
  511. //
  512. // The following services provide for managing the Calais Database. These
  513. // services actually update the database, and require a smartcard context.
  514. //
  515. /*++
  516. SCardIntroduceReaderGroup:
  517. This service provides means for introducing a new smartcard reader group to
  518. Calais.
  519. Arguments:
  520. hContext supplies the handle identifying the Service Manager Context, which
  521. must have been previously established via the SCardEstablishContext()
  522. service.
  523. szGroupName supplies the friendly name to be assigned to the new reader
  524. group.
  525. Return Value:
  526. A 32-bit value indicating whether or not the service completed successfully.
  527. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  528. represents an error condition.
  529. Author:
  530. Doug Barlow (dbarlow) 10/25/1996
  531. --*/
  532. #undef __SUBROUTINE__
  533. #define __SUBROUTINE__ DBGT("SCardIntroduceReaderGroupW")
  534. WINSCARDAPI LONG WINAPI
  535. SCardIntroduceReaderGroupW(
  536. IN SCARDCONTEXT hContext,
  537. IN LPCWSTR szGroupName)
  538. {
  539. LONG nReturn = SCARD_S_SUCCESS;
  540. try
  541. {
  542. CTextString tzGroupName;
  543. CSCardUserContext *pCtx = NULL;
  544. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  545. SCARDCONTEXT hRedirContext = NULL;
  546. if (NULL != hContext)
  547. {
  548. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  549. if (pCtx->IsBad())
  550. {
  551. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  552. }
  553. dwScope = pCtx->Scope();
  554. hRedirContext = pCtx->GetRedirContext();
  555. }
  556. if (hRedirContext || InTSRedirectMode()) {
  557. if (!TS_REDIRECT_READY)
  558. {
  559. throw (DWORD)SCARD_E_NO_SERVICE;
  560. }
  561. nReturn = pfnSCardIntroduceReaderGroupW(hRedirContext, szGroupName);
  562. }
  563. else
  564. {
  565. tzGroupName = szGroupName;
  566. IntroduceReaderGroup(
  567. dwScope,
  568. tzGroupName);
  569. }
  570. }
  571. catch (DWORD dwStatus)
  572. {
  573. nReturn = (LONG)dwStatus;
  574. }
  575. catch (...)
  576. {
  577. nReturn = SCARD_E_INVALID_PARAMETER;
  578. }
  579. return nReturn;
  580. }
  581. /*++
  582. SCardForgetReaderGroup:
  583. This service provides means for removing a previously defined smartcard
  584. reader group from the Calais Subsystem. This service automatically clears
  585. all readers from the group before forgetting it. It does not affect the
  586. existence of the readers in the database.
  587. Arguments:
  588. hContext supplies the handle identifying the Service Manager Context, which
  589. must have been previously established via the SCardEstablishContext()
  590. service.
  591. szGroupName supplies the friendly name of the reader group to be
  592. forgotten. The Calais-defined default reader groups may not be
  593. forgotten.
  594. Return Value:
  595. A 32-bit value indicating whether or not the service completed successfully.
  596. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  597. represents an error condition.
  598. Author:
  599. Doug Barlow (dbarlow) 10/25/1996
  600. --*/
  601. #undef __SUBROUTINE__
  602. #define __SUBROUTINE__ DBGT("SCardForgetReaderGroupW")
  603. WINSCARDAPI LONG WINAPI
  604. SCardForgetReaderGroupW(
  605. IN SCARDCONTEXT hContext,
  606. IN LPCWSTR szGroupName)
  607. {
  608. LONG nReturn = SCARD_S_SUCCESS;
  609. try
  610. {
  611. CTextString tzGroupName;
  612. CSCardUserContext *pCtx = NULL;
  613. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  614. SCARDCONTEXT hRedirContext = NULL;
  615. if (NULL != hContext)
  616. {
  617. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  618. if (pCtx->IsBad())
  619. {
  620. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  621. }
  622. dwScope = pCtx->Scope();
  623. hRedirContext = pCtx->GetRedirContext();
  624. }
  625. if (hRedirContext || InTSRedirectMode()) {
  626. if (!TS_REDIRECT_READY)
  627. {
  628. throw (DWORD)SCARD_E_NO_SERVICE;
  629. }
  630. nReturn = pfnSCardForgetReaderGroupW(hRedirContext, szGroupName);
  631. }
  632. else
  633. {
  634. tzGroupName = szGroupName;
  635. ForgetReaderGroup(
  636. dwScope,
  637. tzGroupName);
  638. }
  639. }
  640. catch (DWORD dwStatus)
  641. {
  642. nReturn = (LONG)dwStatus;
  643. }
  644. catch (...)
  645. {
  646. nReturn = SCARD_E_INVALID_PARAMETER;
  647. }
  648. return nReturn;
  649. }
  650. /*++
  651. SCardIntroduceReader:
  652. This service provides means for introducing an existing smartcard reader
  653. device to Calais. Once introduced, Calais will assume responsibility for
  654. managing access to that reader.
  655. Arguments:
  656. hContext supplies the handle identifying the Service Manager Context, which
  657. must have been previously established via the SCardEstablishContext()
  658. service.
  659. szReaderName supplies the friendly name to be assigned to the reader.
  660. SzDeviceName supplies the system name of the smartcard reader device.
  661. (Example: "VendorX ModelY Z".)
  662. Return Value:
  663. A 32-bit value indicating whether or not the service completed successfully.
  664. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  665. represents an error condition.
  666. Author:
  667. Doug Barlow (dbarlow) 10/25/1996
  668. --*/
  669. #undef __SUBROUTINE__
  670. #define __SUBROUTINE__ DBGT("SCardIntroduceReaderW")
  671. WINSCARDAPI LONG WINAPI
  672. SCardIntroduceReaderW(
  673. IN SCARDCONTEXT hContext,
  674. IN LPCWSTR szReaderName,
  675. IN LPCWSTR szDeviceName)
  676. {
  677. LONG nReturn = SCARD_S_SUCCESS;
  678. try
  679. {
  680. CTextString tzReaderName;
  681. CTextString tzDeviceName;
  682. CSCardUserContext *pCtx = NULL;
  683. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  684. SCARDCONTEXT hRedirContext = NULL;
  685. if (NULL != hContext)
  686. {
  687. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  688. if (pCtx->IsBad())
  689. {
  690. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  691. }
  692. dwScope = pCtx->Scope();
  693. hRedirContext = pCtx->GetRedirContext();
  694. }
  695. if (hRedirContext || InTSRedirectMode()) {
  696. if (!TS_REDIRECT_READY)
  697. {
  698. throw (DWORD)SCARD_E_NO_SERVICE;
  699. }
  700. nReturn = pfnSCardIntroduceReaderW(hRedirContext, szReaderName, szDeviceName);
  701. }
  702. else
  703. {
  704. tzReaderName = szReaderName;
  705. tzDeviceName = szDeviceName;
  706. IntroduceReader(
  707. dwScope,
  708. tzReaderName,
  709. tzDeviceName);
  710. }
  711. }
  712. catch (DWORD dwStatus)
  713. {
  714. nReturn = (LONG)dwStatus;
  715. }
  716. catch (...)
  717. {
  718. nReturn = SCARD_E_INVALID_PARAMETER;
  719. }
  720. return nReturn;
  721. }
  722. /*++
  723. SCardForgetReader:
  724. This service provides means for removing previously defined smartcard
  725. readers from control by the Calais Subsystem. It is automatically removed
  726. from any groups it may have been added to.
  727. Arguments:
  728. hContext supplies the handle identifying the Service Manager Context, which
  729. must have been previously established via the SCardEstablishContext()
  730. service.
  731. szReaderName supplies the friendly name of the reader to be forgotten.
  732. Return Value:
  733. A 32-bit value indicating whether or not the service completed successfully.
  734. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  735. represents an error condition.
  736. Author:
  737. Doug Barlow (dbarlow) 10/25/1996
  738. --*/
  739. #undef __SUBROUTINE__
  740. #define __SUBROUTINE__ DBGT("SCardForgetReaderW")
  741. WINSCARDAPI LONG WINAPI
  742. SCardForgetReaderW(
  743. IN SCARDCONTEXT hContext,
  744. IN LPCWSTR szReaderName)
  745. {
  746. LONG nReturn = SCARD_S_SUCCESS;
  747. try
  748. {
  749. CTextString tzReaderName;
  750. CSCardUserContext *pCtx = NULL;
  751. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  752. SCARDCONTEXT hRedirContext = NULL;
  753. if (NULL != hContext)
  754. {
  755. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  756. if (pCtx->IsBad())
  757. {
  758. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  759. }
  760. dwScope = pCtx->Scope();
  761. hRedirContext = pCtx->GetRedirContext();
  762. }
  763. if (hRedirContext || InTSRedirectMode()) {
  764. if (!TS_REDIRECT_READY)
  765. {
  766. throw (DWORD)SCARD_E_NO_SERVICE;
  767. }
  768. nReturn = pfnSCardForgetReaderW(hRedirContext, szReaderName);
  769. }
  770. else
  771. {
  772. tzReaderName = szReaderName;
  773. ForgetReader(
  774. dwScope,
  775. tzReaderName);
  776. }
  777. }
  778. catch (DWORD dwStatus)
  779. {
  780. nReturn = (LONG)dwStatus;
  781. }
  782. catch (...)
  783. {
  784. nReturn = SCARD_E_INVALID_PARAMETER;
  785. }
  786. return nReturn;
  787. }
  788. /*++
  789. SCardAddReaderToGroup:
  790. This service provides means for adding existing an reader into an existing
  791. reader group.
  792. Arguments:
  793. hContext supplies the handle identifying the Service Manager Context, which
  794. must have been previously established via the SCardEstablishContext()
  795. service.
  796. szReaderName supplies the friendly name of the reader to be added.
  797. szGroupName supplies the friendly name of the group to which the reader
  798. should be added.
  799. Return Value:
  800. A 32-bit value indicating whether or not the service completed successfully.
  801. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  802. represents an error condition.
  803. Author:
  804. Doug Barlow (dbarlow) 10/25/1996
  805. --*/
  806. #undef __SUBROUTINE__
  807. #define __SUBROUTINE__ DBGT("SCardAddReaderToGroupW")
  808. WINSCARDAPI LONG WINAPI
  809. SCardAddReaderToGroupW(
  810. IN SCARDCONTEXT hContext,
  811. IN LPCWSTR szReaderName,
  812. IN LPCWSTR szGroupName)
  813. {
  814. LONG nReturn = SCARD_S_SUCCESS;
  815. try
  816. {
  817. CTextString tzReaderName;
  818. CTextString tzGroupName;
  819. CSCardUserContext *pCtx = NULL;
  820. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  821. SCARDCONTEXT hRedirContext = NULL;
  822. if (NULL != hContext)
  823. {
  824. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  825. if (pCtx->IsBad())
  826. {
  827. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  828. }
  829. dwScope = pCtx->Scope();
  830. hRedirContext = pCtx->GetRedirContext();
  831. }
  832. if (hRedirContext || InTSRedirectMode()) {
  833. if (!TS_REDIRECT_READY)
  834. {
  835. throw (DWORD)SCARD_E_NO_SERVICE;
  836. }
  837. nReturn = pfnSCardAddReaderToGroupW(hRedirContext, szReaderName, szGroupName);
  838. }
  839. else
  840. {
  841. tzReaderName = szReaderName;
  842. tzGroupName = szGroupName;
  843. AddReaderToGroup(
  844. dwScope,
  845. tzReaderName,
  846. tzGroupName);
  847. }
  848. }
  849. catch (DWORD dwStatus)
  850. {
  851. nReturn = (LONG)dwStatus;
  852. }
  853. catch (...)
  854. {
  855. nReturn = SCARD_E_INVALID_PARAMETER;
  856. }
  857. return nReturn;
  858. }
  859. /*++
  860. SCardRemoveReaderFromGroup:
  861. This service provides means for removing an existing reader from an existing
  862. reader group. It does not affect the existence of either the reader or the
  863. group in the Calais database.
  864. Arguments:
  865. hContext supplies the handle identifying the Service Manager Context, which
  866. must have been previously established via the SCardEstablishContext()
  867. service.
  868. szReaderName supplies the friendly name of the reader to be removed.
  869. szGroupName supplies the friendly name of the group to which the reader
  870. should be removed.
  871. Return Value:
  872. A 32-bit value indicating whether or not the service completed successfully.
  873. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  874. represents an error condition.
  875. Author:
  876. Doug Barlow (dbarlow) 10/25/1996
  877. --*/
  878. #undef __SUBROUTINE__
  879. #define __SUBROUTINE__ DBGT("SCardRemoveReaderFromGroupW")
  880. WINSCARDAPI LONG WINAPI
  881. SCardRemoveReaderFromGroupW(
  882. IN SCARDCONTEXT hContext,
  883. IN LPCWSTR szReaderName,
  884. IN LPCWSTR szGroupName)
  885. {
  886. LONG nReturn = SCARD_S_SUCCESS;
  887. try
  888. {
  889. CTextString tzReaderName;
  890. CTextString tzGroupName;
  891. CSCardUserContext *pCtx = NULL;
  892. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  893. SCARDCONTEXT hRedirContext = NULL;
  894. if (NULL != hContext)
  895. {
  896. pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  897. if (pCtx->IsBad())
  898. {
  899. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  900. }
  901. dwScope = pCtx->Scope();
  902. hRedirContext = pCtx->GetRedirContext();
  903. }
  904. if (hRedirContext || InTSRedirectMode()) {
  905. if (!TS_REDIRECT_READY)
  906. {
  907. throw (DWORD)SCARD_E_NO_SERVICE;
  908. }
  909. nReturn = pfnSCardRemoveReaderFromGroupW(hRedirContext, szReaderName, szGroupName);
  910. }
  911. else
  912. {
  913. tzReaderName = szReaderName;
  914. tzGroupName = szGroupName;
  915. RemoveReaderFromGroup(
  916. dwScope,
  917. tzReaderName,
  918. tzGroupName);
  919. }
  920. }
  921. catch (DWORD dwStatus)
  922. {
  923. nReturn = (LONG)dwStatus;
  924. }
  925. catch (...)
  926. {
  927. nReturn = SCARD_E_INVALID_PARAMETER;
  928. }
  929. return nReturn;
  930. }
  931. /*++
  932. SCardIntroduceCardType:
  933. This service provides means for introducing new smartcards to the Calais
  934. Subsystem for the active user.
  935. Arguments:
  936. hContext supplies the handle identifying the Service Manager Context, which
  937. must have been previously established via the SCardEstablishContext()
  938. service.
  939. szCardName supplies the name by which the user can recognize this card.
  940. PguidPrimaryProvider supplies a pointer to a GUID used to identify the
  941. Primary Service Provider for the card.
  942. rgguidInterfaces supplies an array of GUIDs identifying the smartcard
  943. interfaces supported by this card.
  944. dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
  945. pbAtr supplies a string against which card ATRs will be compared to
  946. determine a possible match for this card. The length of this string is
  947. determined by normal ATR parsing.
  948. pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
  949. smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
  950. must point to a string of bytes the same length as the ATR string
  951. supplied in pbAtr. Then when a given ATR A is compared to the ATR
  952. supplied in pbAtr B, it matches if and only if A & M = B, where M is the
  953. supplied mask, and & represents bitwise logical AND.
  954. cbAtrLen supplies the length of the ATR and Mask. This value may be zero
  955. if the lentgh is obvious from the ATR. However, it may be required if
  956. there is a Mask value that obscures the actual ATR.
  957. Return Value:
  958. A 32-bit value indicating whether or not the service completed successfully.
  959. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  960. represents an error condition.
  961. Author:
  962. Doug Barlow (dbarlow) 10/23/1996
  963. --*/
  964. #undef __SUBROUTINE__
  965. #define __SUBROUTINE__ DBGT("SCardIntroduceCardTypeW")
  966. WINSCARDAPI LONG WINAPI
  967. SCardIntroduceCardTypeW(
  968. IN SCARDCONTEXT hContext,
  969. IN LPCWSTR szCardName,
  970. IN LPCGUID pguidPrimaryProvider,
  971. IN LPCGUID rgguidInterfaces,
  972. IN DWORD dwInterfaceCount,
  973. IN LPCBYTE pbAtr,
  974. IN LPCBYTE pbAtrMask,
  975. IN DWORD cbAtrLen)
  976. {
  977. LONG nReturn = SCARD_S_SUCCESS;
  978. try
  979. {
  980. CTextString tzCardName;
  981. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  982. if (NULL != hContext)
  983. {
  984. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  985. dwScope = pCtx->Scope();
  986. }
  987. tzCardName = szCardName;
  988. IntroduceCard(
  989. dwScope,
  990. tzCardName,
  991. pguidPrimaryProvider,
  992. rgguidInterfaces,
  993. dwInterfaceCount,
  994. pbAtr,
  995. pbAtrMask,
  996. cbAtrLen);
  997. }
  998. catch (DWORD dwStatus)
  999. {
  1000. nReturn = (LONG)dwStatus;
  1001. }
  1002. catch (...)
  1003. {
  1004. nReturn = SCARD_E_INVALID_PARAMETER;
  1005. }
  1006. return nReturn;
  1007. }
  1008. /*++
  1009. SCardSetCardTypeProviderName:
  1010. This service provides means for adding additional service providers to a
  1011. specified card type.
  1012. Arguments:
  1013. hContext supplies the handle identifying the Service Manager Context, which
  1014. must have been previously established via the SCardEstablishContext()
  1015. service.
  1016. szCardName supplies the name of the card type with which this provider
  1017. name is to be associated.
  1018. dwProviderId supplies the identifier for the provider to be associated with
  1019. this card type. Possible values are:
  1020. SCARD_PROVIDER_SSP - The Primary SSP identifier, as a GUID string.
  1021. SCARD_PROVIDER_CSP - The CSP name.
  1022. Other values < 0x80000000 are reserved for use by Microsoft. Values
  1023. over 0x80000000 are available for use by the smart card vendors, and
  1024. are card-specific.
  1025. szProvider supplies the string identifying the provider.
  1026. Return Value:
  1027. A 32-bit value indicating whether or not the service completed successfully.
  1028. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1029. represents an error condition.
  1030. Author:
  1031. Doug Barlow (dbarlow) 1/19/1998
  1032. --*/
  1033. #undef __SUBROUTINE__
  1034. #define __SUBROUTINE__ DBGT("SCardSetCardTypeProviderNameW")
  1035. WINSCARDAPI LONG WINAPI
  1036. SCardSetCardTypeProviderNameW(
  1037. IN SCARDCONTEXT hContext,
  1038. IN LPCWSTR szCardName,
  1039. IN DWORD dwProviderId,
  1040. IN LPCWSTR szProvider)
  1041. {
  1042. LONG nReturn = SCARD_S_SUCCESS;
  1043. try
  1044. {
  1045. CTextString tzCardName;
  1046. CTextString tzProvider;
  1047. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  1048. if (NULL != hContext)
  1049. {
  1050. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1051. dwScope = pCtx->Scope();
  1052. }
  1053. tzCardName = szCardName;
  1054. tzProvider = szProvider;
  1055. SetCardTypeProviderName(
  1056. dwScope,
  1057. tzCardName,
  1058. dwProviderId,
  1059. tzProvider);
  1060. }
  1061. catch (DWORD dwStatus)
  1062. {
  1063. nReturn = (LONG)dwStatus;
  1064. }
  1065. catch (...)
  1066. {
  1067. nReturn = SCARD_E_INVALID_PARAMETER;
  1068. }
  1069. return nReturn;
  1070. }
  1071. /*++
  1072. SCardForgetCardType:
  1073. This service provides means for removing previously defined smartcards from
  1074. the Calais Subsystem.
  1075. Arguments:
  1076. hContext supplies the handle identifying the Service Manager Context, which
  1077. must have been previously established via the SCardEstablishContext()
  1078. service.
  1079. szCardName supplies the friendly name of the card to be forgotten.
  1080. Return Value:
  1081. A 32-bit value indicating whether or not the service completed successfully.
  1082. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1083. represents an error condition.
  1084. Author:
  1085. Doug Barlow (dbarlow) 10/23/1996
  1086. --*/
  1087. #undef __SUBROUTINE__
  1088. #define __SUBROUTINE__ DBGT("SCardForgetCardTypeW")
  1089. WINSCARDAPI LONG WINAPI
  1090. SCardForgetCardTypeW(
  1091. IN SCARDCONTEXT hContext,
  1092. IN LPCWSTR szCardName)
  1093. {
  1094. LONG nReturn = SCARD_S_SUCCESS;
  1095. try
  1096. {
  1097. CTextString tzCardName;
  1098. DWORD dwScope = SCARD_SCOPE_SYSTEM;
  1099. if (NULL != hContext)
  1100. {
  1101. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1102. dwScope = pCtx->Scope();
  1103. }
  1104. tzCardName = szCardName;
  1105. ForgetCard(
  1106. dwScope,
  1107. tzCardName);
  1108. }
  1109. catch (DWORD dwStatus)
  1110. {
  1111. nReturn = (LONG)dwStatus;
  1112. }
  1113. catch (...)
  1114. {
  1115. nReturn = SCARD_E_INVALID_PARAMETER;
  1116. }
  1117. return nReturn;
  1118. }
  1119. //
  1120. ////////////////////////////////////////////////////////////////////////////////
  1121. //
  1122. // Reader Services
  1123. //
  1124. // The following services supply means for tracking cards within readers.
  1125. //
  1126. /*++
  1127. SCardLocateCards:
  1128. This service searches the readers listed in the lpReaderStates parameter for
  1129. any containing a card with an ATR string matching one of the card supplied
  1130. names. This service returns immediately with the result. If no matching
  1131. cards are found, the calling application may use the SCardGetStatusChange
  1132. service to wait for card availability changes.
  1133. Arguments:
  1134. hContext supplies the handle identifying the Service Manager Context
  1135. established previously via the SCardEstablishContext() service.
  1136. mszCards supplies the names of the cards to search for, as a multi-string.
  1137. rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
  1138. the search, and receives the result.
  1139. cReaders supplies the number of elements in the rgReaderStates array.
  1140. Return Value:
  1141. A 32-bit value indicating whether or not the service completed successfully.
  1142. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1143. represents an error condition.
  1144. Author:
  1145. Doug Barlow (dbarlow) 10/23/1996
  1146. --*/
  1147. #undef __SUBROUTINE__
  1148. #define __SUBROUTINE__ DBGT("SCardLocateCardsW")
  1149. WINSCARDAPI LONG WINAPI
  1150. SCardLocateCardsW(
  1151. IN SCARDCONTEXT hContext,
  1152. IN LPCWSTR mszCards,
  1153. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  1154. IN DWORD cReaders)
  1155. {
  1156. LONG nReturn = SCARD_S_SUCCESS;
  1157. LPSCARD_ATRMASK rgAtrMasks = NULL;
  1158. try
  1159. {
  1160. LPCSTR szCard;
  1161. CTextMultistring mtzCards;
  1162. DWORD dwIndex;
  1163. DWORD dwScope;
  1164. CBuffer bfXlate1(36), bfXlate2(36); // Rough guess of name & ATR lengths
  1165. BOOL fSts;
  1166. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1167. if (pCtx->IsBad())
  1168. {
  1169. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  1170. }
  1171. dwScope = pCtx->Scope();
  1172. if (0 == *mszCards)
  1173. throw (DWORD)SCARD_E_INVALID_VALUE;
  1174. mtzCards = mszCards;
  1175. rgAtrMasks = new SCARD_ATRMASK[MStringCount(mtzCards)];
  1176. if (rgAtrMasks == NULL)
  1177. {
  1178. CalaisWarning(
  1179. __SUBROUTINE__,
  1180. DBGT("WinSCard Client has no memory"));
  1181. throw (DWORD)SCARD_E_NO_MEMORY;
  1182. }
  1183. dwIndex = 0;
  1184. for (szCard = FirstString(mtzCards);
  1185. NULL != szCard;
  1186. szCard = NextString(szCard))
  1187. {
  1188. fSts = GetCardInfo(
  1189. dwScope,
  1190. szCard,
  1191. &bfXlate1, // ATR
  1192. &bfXlate2, // Mask
  1193. NULL,
  1194. NULL);
  1195. if (!fSts)
  1196. throw (DWORD)SCARD_E_UNKNOWN_CARD;
  1197. ASSERT(33 >= bfXlate1.Length()); // Biggest an ATR can be.
  1198. rgAtrMasks[dwIndex].cbAtr = bfXlate1.Length();
  1199. memcpy(rgAtrMasks[dwIndex].rgbAtr, bfXlate1.Access(), rgAtrMasks[dwIndex].cbAtr);
  1200. ASSERT(rgAtrMasks[dwIndex].cbAtr == bfXlate2.Length());
  1201. memcpy(rgAtrMasks[dwIndex].rgbMask, bfXlate2.Access(), rgAtrMasks[dwIndex].cbAtr);
  1202. dwIndex ++;
  1203. }
  1204. nReturn = SCardLocateCardsByATRW(
  1205. hContext,
  1206. rgAtrMasks,
  1207. dwIndex,
  1208. rgReaderStates,
  1209. cReaders);
  1210. // If the remote client does not implement the new API
  1211. // retry with the old one. it might succeed if its DB is good enough
  1212. if ((nReturn == ERROR_CALL_NOT_IMPLEMENTED) && (pCtx->GetRedirContext()))
  1213. {
  1214. nReturn = pfnSCardLocateCardsW(pCtx->GetRedirContext(), mszCards, rgReaderStates, cReaders);
  1215. }
  1216. }
  1217. catch (DWORD dwStatus)
  1218. {
  1219. nReturn = (LONG)dwStatus;
  1220. }
  1221. catch (...)
  1222. {
  1223. nReturn = SCARD_E_INVALID_PARAMETER;
  1224. }
  1225. if (rgAtrMasks != NULL)
  1226. {
  1227. try
  1228. {
  1229. delete[] rgAtrMasks;
  1230. }
  1231. catch (...)
  1232. {
  1233. }
  1234. }
  1235. return nReturn;
  1236. }
  1237. /*++
  1238. SCardLocateCardsByATR:
  1239. This service searches the readers listed in the lpReaderStates parameter for
  1240. any containing a card with an ATR string matching one of the supplied ATRs
  1241. This service returns immediately with the result. If no matching
  1242. cards are found, the calling application may use the SCardGetStatusChange
  1243. service to wait for card availability changes.
  1244. Arguments:
  1245. hContext supplies the handle identifying the Service Manager Context
  1246. established previously via the SCardEstablishContext() service.
  1247. rgAtrMasks supplies the ATRs to search for, as an array of structs.
  1248. cAtrs supplies the number of elements in the rgAtrMasks array.
  1249. rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
  1250. the search, and receives the result.
  1251. cReaders supplies the number of elements in the rgReaderStates array.
  1252. Return Value:
  1253. A 32-bit value indicating whether or not the service completed successfully.
  1254. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1255. represents an error condition.
  1256. --*/
  1257. #undef __SUBROUTINE__
  1258. #define __SUBROUTINE__ DBGT("SCardLocateCardsByATRW")
  1259. WINSCARDAPI LONG WINAPI
  1260. SCardLocateCardsByATRW(
  1261. IN SCARDCONTEXT hContext,
  1262. IN LPSCARD_ATRMASK rgAtrMasks,
  1263. IN DWORD cAtrs,
  1264. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  1265. IN DWORD cReaders)
  1266. {
  1267. LONG nReturn = SCARD_S_SUCCESS;
  1268. try
  1269. {
  1270. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1271. if (pCtx->IsBad())
  1272. {
  1273. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  1274. }
  1275. if (pCtx->GetRedirContext())
  1276. {
  1277. nReturn = pfnSCardLocateCardsByATRW(pCtx->GetRedirContext(), rgAtrMasks, cAtrs, rgReaderStates, cReaders);
  1278. }
  1279. else
  1280. {
  1281. CBuffer bfReaders;
  1282. DWORD dwIndex;
  1283. for (dwIndex = 0; dwIndex < cReaders; dwIndex += 1)
  1284. MStrAdd(bfReaders, rgReaderStates[dwIndex].szReader);
  1285. pCtx->LocateCards(
  1286. bfReaders,
  1287. rgAtrMasks,
  1288. cAtrs,
  1289. (LPSCARD_READERSTATE)rgReaderStates,
  1290. cReaders);
  1291. }
  1292. }
  1293. catch (DWORD dwStatus)
  1294. {
  1295. nReturn = (LONG)dwStatus;
  1296. }
  1297. catch (...)
  1298. {
  1299. nReturn = SCARD_E_INVALID_PARAMETER;
  1300. }
  1301. return nReturn;
  1302. }
  1303. /*++
  1304. SCardGetStatusChange:
  1305. This service is used to block execution until such time as the current
  1306. availability of cards in a given set of readers changes. The caller
  1307. supplies a list of readers to be monitored via an SCARD_READERSTATE array,
  1308. and the maximum amount of time, in seconds, that it is willing to wait for
  1309. an action to occur on one of the listed readers. Zero in this parameter
  1310. indicates that no timeout is specified. The service returns when there is a
  1311. change in availability, having filled in the dwEventState fields of the
  1312. rgReaderStates parameter appropriately.
  1313. Arguments:
  1314. hContext supplies the handle identifying the Service Manager Context
  1315. established previously via the SCardEstablishContext() service.
  1316. dwTimeOut supplies the maximum amount of time to wait for an action, in
  1317. seconds. A zero value implies that the wait will never timeout.
  1318. rgReaderStates supplies an array of SCARD_READERSTATE structures controlling
  1319. the wait, and receives the result.
  1320. cReaders supplies the number of elements in the rgReaderStates array.
  1321. Return Value:
  1322. A 32-bit value indicating whether or not the service completed successfully.
  1323. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1324. represents an error condition.
  1325. Author:
  1326. Doug Barlow (dbarlow) 10/23/1996
  1327. --*/
  1328. #undef __SUBROUTINE__
  1329. #define __SUBROUTINE__ DBGT("SCardGetStatusChangeW")
  1330. BOOL
  1331. SetStartedEventAfterTestingConnectedState();
  1332. WINSCARDAPI LONG WINAPI
  1333. SCardGetStatusChangeW(
  1334. IN SCARDCONTEXT hContext,
  1335. IN DWORD dwTimeout,
  1336. IN OUT LPSCARD_READERSTATE_W rgReaderStates,
  1337. IN DWORD cReaders)
  1338. {
  1339. LONG nReturn = SCARD_S_SUCCESS;
  1340. try
  1341. {
  1342. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1343. if (pCtx->IsBad())
  1344. {
  1345. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  1346. }
  1347. if (pCtx->GetRedirContext())
  1348. {
  1349. nReturn = pfnSCardGetStatusChangeW(pCtx->GetRedirContext(), dwTimeout, rgReaderStates, cReaders);
  1350. //
  1351. // See if there is an indication that the client's scardsvr service was shutdown
  1352. //
  1353. if (SCARD_E_SYSTEM_CANCELLED == nReturn)
  1354. {
  1355. //OutputDebugString("WINSCARD: SCardEstablishContext: got E_NO_SERVICE!\n");
  1356. SetStartedEventAfterTestingConnectedState();
  1357. }
  1358. }
  1359. else
  1360. {
  1361. CBuffer bfReaders;
  1362. DWORD dwIndex;
  1363. for (dwIndex = 0; dwIndex < cReaders; dwIndex += 1)
  1364. MStrAdd(bfReaders, rgReaderStates[dwIndex].szReader);
  1365. pCtx->GetStatusChange(
  1366. bfReaders,
  1367. (LPSCARD_READERSTATE)rgReaderStates,
  1368. cReaders,
  1369. dwTimeout);
  1370. }
  1371. }
  1372. catch (DWORD dwStatus)
  1373. {
  1374. nReturn = (LONG)dwStatus;
  1375. if (SCARD_E_SYSTEM_CANCELLED == nReturn)
  1376. {
  1377. ResetEvent(g_hUnifiedStartedEvent);
  1378. }
  1379. }
  1380. catch (...)
  1381. {
  1382. nReturn = SCARD_E_INVALID_PARAMETER;
  1383. }
  1384. return nReturn;
  1385. }
  1386. //
  1387. ////////////////////////////////////////////////////////////////////////////////
  1388. //
  1389. // Card/Reader Access Services
  1390. //
  1391. // The following services provide means for establishing communication with
  1392. // the card.
  1393. //
  1394. /*++
  1395. SCardConnect:
  1396. This service establishes a connection from the calling application to the
  1397. smartcard in the designated reader. If no card exists in the specified
  1398. reader, an error is returned.
  1399. Arguments:
  1400. hContext supplies the handle identifying the Service Manager Context
  1401. established previously via the SCardEstablishContext() service.
  1402. szReader supplies the name of the reader containing the target card.
  1403. DwShareMode supplies a flag indicating whether or not other applications may
  1404. form connections to this card. Possible values are:
  1405. SCARD_SHARE_SHARED - This application is willing to share this card with
  1406. other applications.
  1407. SCARD_SHARE_EXCLUSIVE - This application is not willing to share this
  1408. card with other applications.
  1409. SCARD_SHARE_DIRECT - This application is taking control of the reader.
  1410. DwPreferredProtocols supplies a bit mask of acceptable protocols for this
  1411. connection. Possible values, which may be combined via the OR
  1412. operation, are:
  1413. SCARD_PROTOCOL_T0 - T=0 is an acceptable protocol.
  1414. SCARD_PROTOCOL_T1 - T=1 is an acceptable protocol.
  1415. phCard receives a handle identifying the connection to the smartcard in the
  1416. designated reader.
  1417. pdwActiveProtocol receives a flag indicating the established active
  1418. protocol. Possible values are:
  1419. SCARD_PROTOCOL_T0 - T=0 is the active protocol.
  1420. SCARD_PROTOCOL_T1 - T=1 is the active protocol.
  1421. Return Value:
  1422. A 32-bit value indicating whether or not the service completed successfully.
  1423. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1424. represents an error condition.
  1425. Author:
  1426. Doug Barlow (dbarlow) 10/23/1996
  1427. --*/
  1428. #undef __SUBROUTINE__
  1429. #define __SUBROUTINE__ DBGT("SCardConnectW")
  1430. WINSCARDAPI LONG WINAPI
  1431. SCardConnectW(
  1432. IN SCARDCONTEXT hContext,
  1433. IN LPCWSTR szReader,
  1434. IN DWORD dwShareMode,
  1435. IN DWORD dwPreferredProtocols,
  1436. OUT LPSCARDHANDLE phCard,
  1437. OUT LPDWORD pdwActiveProtocol)
  1438. {
  1439. LONG nReturn = SCARD_S_SUCCESS;
  1440. CReaderContext *pRdr = NULL;
  1441. CSCardSubcontext *pSubCtx = NULL;
  1442. try
  1443. {
  1444. *phCard = NULL; // Touch it to be sure it's real.
  1445. CSCardUserContext *pCtx = (CSCardUserContext *)((*g_phlContexts)[hContext]);
  1446. CTextString tzReader;
  1447. if (pCtx->IsBad())
  1448. {
  1449. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  1450. }
  1451. tzReader = szReader;
  1452. pRdr = new CReaderContext;
  1453. if (NULL == pRdr)
  1454. {
  1455. CalaisWarning(
  1456. __SUBROUTINE__,
  1457. DBGT("WinSCard Client has no memory"));
  1458. throw (DWORD)SCARD_E_NO_MEMORY;
  1459. }
  1460. SCARDCONTEXT hRedirContext = pCtx->GetRedirContext();
  1461. if (hRedirContext)
  1462. {
  1463. SCARDHANDLE hCard = g_phlReaders->Add(pRdr); // do it first to avoid out of memory condition
  1464. nReturn = pfnSCardConnectW(hRedirContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
  1465. if (nReturn == SCARD_S_SUCCESS)
  1466. {
  1467. pRdr->SetRedirCard(*phCard);
  1468. *phCard = hCard;
  1469. }
  1470. else
  1471. {
  1472. g_phlReaders->Close(hCard);
  1473. delete pRdr;
  1474. }
  1475. }
  1476. else
  1477. {
  1478. pSubCtx = pCtx->AcquireSubcontext(TRUE);
  1479. pRdr->Connect(
  1480. pSubCtx,
  1481. tzReader,
  1482. dwShareMode,
  1483. dwPreferredProtocols);
  1484. pSubCtx = NULL;
  1485. pRdr->Context()->ReleaseSubcontext();
  1486. if (NULL != pdwActiveProtocol)
  1487. *pdwActiveProtocol = pRdr->Protocol();
  1488. pRdr->Context()->m_hReaderHandle = g_phlReaders->Add(pRdr);
  1489. *phCard = pRdr->Context()->m_hReaderHandle;
  1490. }
  1491. }
  1492. catch (DWORD dwStatus)
  1493. {
  1494. if (NULL != pSubCtx)
  1495. {
  1496. pSubCtx->Deallocate();
  1497. pSubCtx->ReleaseSubcontext();
  1498. }
  1499. if (NULL != pRdr)
  1500. delete pRdr;
  1501. nReturn = (LONG)dwStatus;
  1502. }
  1503. catch (...)
  1504. {
  1505. if (NULL != pSubCtx)
  1506. {
  1507. pSubCtx->Deallocate();
  1508. pSubCtx->ReleaseSubcontext();
  1509. }
  1510. if (NULL != pRdr)
  1511. delete pRdr;
  1512. nReturn = SCARD_E_INVALID_PARAMETER;
  1513. }
  1514. return nReturn;
  1515. }
  1516. /*++
  1517. SCardStatus:
  1518. This routine provides the current status of the reader. It may be used at
  1519. any time following a successful call to SCardConnect or SCardOpenReader, and
  1520. prior to a successful call to SCardDisconnect. It does not effect the state
  1521. of the reader or driver.
  1522. Arguments:
  1523. hCard - This is the reference value returned from the SCardConnect or
  1524. SCardOpenReader service.
  1525. mszReaderNames - This receives a list of friendly names by which the
  1526. currently connected reader is known. This list is returned as a
  1527. multistring.
  1528. pcchReaderLen - This supplies the length of the mszReader buffer, in
  1529. characters, and receives the actual returned length of the reader
  1530. friendly name list, in characters, including the trailing NULL
  1531. characters.
  1532. pdwState - This receives the current state of the reader. Upon success, it
  1533. receives one of the following state indicators:
  1534. SCARD_ABSENT - This value implies there is no card in the reader.
  1535. SCARD_PRESENT - This value implies there is a card is present in the
  1536. reader, but that it has not been moved into position for use.
  1537. SCARD_SWALLOWED - This value implies there is a card in the reader in
  1538. position for use. The card is not powered.
  1539. SCARD_POWERED - This value implies there is power is being provided to
  1540. the card, but the Reader Driver is unaware of the mode of the card.
  1541. SCARD_NEGOTIABLEMODE - This value implies the card has been reset and is
  1542. awaiting PTS negotiation.
  1543. SCARD_SPECIFICMODE - This value implies the card has been reset and
  1544. specific communication protocols have been established.
  1545. pdwProtocol - This receives the current protocol, if any. Possible returned
  1546. values are listed below. Other values may be added in the future. The
  1547. returned value is only meaningful if the returned state is
  1548. SCARD_SPECIFICMODE.
  1549. SCARD_PROTOCOL_RAW - The Raw Transfer Protocol is in use.
  1550. SCARD_PROTOCOL_T0 - The ISO 7816/3 T=0 Protocol is in use.
  1551. SCARD_PROTOCOL_T1 - The ISO 7816/3 T=1 Protocol is in use.
  1552. pbAtr - This parameter points to a 32-byte buffer which receives the ATR
  1553. string from the currently inserted card, if available.
  1554. pbcAtrLen - This points to a DWORD which supplies the length of the pbAtr
  1555. buffer, and receives the actual number of bytes in the ATR string.
  1556. Return Value:
  1557. A 32-bit value indicating whether or not the service completed successfully.
  1558. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  1559. represents an error condition.
  1560. Author:
  1561. Doug Barlow (dbarlow) 10/23/1996
  1562. --*/
  1563. #undef __SUBROUTINE__
  1564. #define __SUBROUTINE__ DBGT("SCardStatusW")
  1565. WINSCARDAPI LONG WINAPI
  1566. SCardStatusW(
  1567. IN SCARDHANDLE hCard,
  1568. OUT LPWSTR mszReaderNames,
  1569. IN OUT LPDWORD pcchReaderLen,
  1570. OUT LPDWORD pdwState,
  1571. OUT LPDWORD pdwProtocol,
  1572. OUT LPBYTE pbAtr,
  1573. IN OUT LPDWORD pcbAtrLen)
  1574. {
  1575. LONG nReturn = SCARD_S_SUCCESS;
  1576. try
  1577. {
  1578. CReaderContext *pRdr = (CReaderContext *)((*g_phlReaders)[hCard]);
  1579. if (pRdr->IsBad())
  1580. {
  1581. throw (DWORD)SCARD_E_SERVICE_STOPPED;
  1582. }
  1583. if (pRdr->GetRedirCard())
  1584. {
  1585. nReturn = pfnSCardStatusW(pRdr->GetRedirCard(), mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
  1586. }
  1587. else
  1588. {
  1589. CBuffer bfAtr, bfReader;
  1590. DWORD dwLocalState, dwLocalProtocol;
  1591. pRdr->Status(&dwLocalState, &dwLocalProtocol, bfAtr, bfReader);
  1592. if (NULL != pdwState)
  1593. *pdwState = dwLocalState;
  1594. if (NULL != pdwProtocol)
  1595. *pdwProtocol = dwLocalProtocol;
  1596. if (NULL != pcchReaderLen)
  1597. PlaceMultiResult(
  1598. pRdr->Context()->Parent(),
  1599. bfReader,
  1600. mszReaderNames,
  1601. pcchReaderLen);
  1602. if (NULL != pcbAtrLen)
  1603. PlaceResult(pRdr->Context()->Parent(), bfAtr, pbAtr, pcbAtrLen);
  1604. }
  1605. }
  1606. catch (DWORD dwStatus)
  1607. {
  1608. nReturn = (LONG)dwStatus;
  1609. }
  1610. catch (...)
  1611. {
  1612. nReturn = SCARD_E_INVALID_PARAMETER;
  1613. }
  1614. return nReturn;
  1615. }
  1616. //
  1617. ///////////////////////////////////////////////////////////////////////////////
  1618. //
  1619. // Utility Routines
  1620. //
  1621. /*++
  1622. PlaceResult:
  1623. This set of routines places the result of an operation into the user's
  1624. output buffer, supporting SCARD_AUTO_ALLOCATE, invalid buffer sizes, etc.
  1625. Arguments:
  1626. pCtx supplies the context under which this operation is being performed.
  1627. bfResult supplies the result to be returned to the user.
  1628. pbOutput receives the result for the user, as a byte stream.
  1629. szOutput receives the result as an ANSI or UNICODE string.
  1630. pcbLength supplies the length of the user's output buffer in bytes, and
  1631. receives how much of it was used.
  1632. pcchLength supplies the length of the user's output buffer in characters,
  1633. and receives how much of it was used.
  1634. Return Value:
  1635. None
  1636. Throws:
  1637. Error conditions are thrown as DWORD status codes.
  1638. Author:
  1639. Doug Barlow (dbarlow) 12/7/1996
  1640. --*/
  1641. #undef __SUBROUTINE__
  1642. #define __SUBROUTINE__ DBGT("PlaceResult")
  1643. void
  1644. PlaceResult(
  1645. CSCardUserContext *pCtx,
  1646. CBuffer &bfResult,
  1647. LPWSTR szOutput,
  1648. LPDWORD pcchLength)
  1649. {
  1650. LPWSTR szForUser = NULL;
  1651. LPWSTR szOutBuf = szOutput;
  1652. DWORD cchSrcLength = bfResult.Length() / sizeof(TCHAR);
  1653. try
  1654. {
  1655. if (NULL == szOutput)
  1656. *pcchLength = 0;
  1657. switch (*pcchLength)
  1658. {
  1659. case 0: // They just want the length.
  1660. *pcchLength = cchSrcLength;
  1661. break;
  1662. case SCARD_AUTOALLOCATE:
  1663. if (0 < cchSrcLength)
  1664. {
  1665. if (NULL == pCtx)
  1666. {
  1667. szForUser = (LPWSTR)HeapAlloc(
  1668. GetProcessHeap(),
  1669. HEAP_ZERO_MEMORY,
  1670. cchSrcLength * sizeof(WCHAR));
  1671. }
  1672. else
  1673. szForUser = (LPWSTR)pCtx->AllocateMemory(
  1674. cchSrcLength * sizeof(WCHAR));
  1675. if (NULL == szForUser)
  1676. {
  1677. CalaisWarning(
  1678. __SUBROUTINE__,
  1679. DBGT("Client can't get return memory"));
  1680. throw (DWORD)SCARD_E_NO_MEMORY;
  1681. }
  1682. *(LPWSTR *)szOutput = szForUser;
  1683. szOutBuf = szForUser;
  1684. // Fall through intentionally
  1685. }
  1686. else
  1687. {
  1688. *pcchLength = cchSrcLength;
  1689. *(LPWSTR *)szOutput = (LPWSTR)g_wszBlank;
  1690. break; // Do terminate the case now.
  1691. }
  1692. default:
  1693. if (*pcchLength < cchSrcLength)
  1694. {
  1695. *pcchLength = cchSrcLength;
  1696. throw (DWORD)SCARD_E_INSUFFICIENT_BUFFER;
  1697. }
  1698. MoveToUnicodeString(
  1699. szOutBuf,
  1700. (LPCTSTR)bfResult.Access(),
  1701. cchSrcLength);
  1702. *pcchLength = cchSrcLength;
  1703. break;
  1704. }
  1705. }
  1706. catch (...)
  1707. {
  1708. if (NULL != szForUser)
  1709. {
  1710. if (NULL == pCtx)
  1711. HeapFree(GetProcessHeap(), 0, szForUser);
  1712. else
  1713. pCtx->FreeMemory(szForUser);
  1714. }
  1715. throw;
  1716. }
  1717. }
  1718. /*++
  1719. PlaceMultiResult:
  1720. This set of routines places a Multistring result of an operation into the
  1721. user's output buffer, supporting SCARD_AUTO_ALLOCATE, invalid buffer sizes,
  1722. etc.
  1723. Arguments:
  1724. pCtx supplies the context under which this operation is being performed.
  1725. bfResult supplies the TCHAR multistring result to be returned to the user.
  1726. mszOutput receives the result as an ANSI or UNICODE multistring.
  1727. pcchLength supplies the length of the user's output buffer in characters,
  1728. and receives how much of it was used.
  1729. Return Value:
  1730. None
  1731. Throws:
  1732. Error conditions are thrown as DWORD status codes.
  1733. Author:
  1734. Doug Barlow (dbarlow) 12/7/1996
  1735. --*/
  1736. #undef __SUBROUTINE__
  1737. #define __SUBROUTINE__ DBGT("PlaceMultiResult")
  1738. void
  1739. PlaceMultiResult(
  1740. CSCardUserContext *pCtx,
  1741. CBuffer &bfResult,
  1742. LPWSTR mszOutput,
  1743. LPDWORD pcchLength)
  1744. {
  1745. LPWSTR mszForUser = NULL;
  1746. LPWSTR mszOutBuf = mszOutput;
  1747. DWORD cchSrcLength = bfResult.Length() / sizeof(TCHAR);
  1748. try
  1749. {
  1750. if (NULL == mszOutput)
  1751. *pcchLength = 0;
  1752. switch (*pcchLength)
  1753. {
  1754. case 0: // They just want the length.
  1755. *pcchLength = cchSrcLength;
  1756. break;
  1757. case SCARD_AUTOALLOCATE:
  1758. if (0 < cchSrcLength)
  1759. {
  1760. if (NULL == pCtx)
  1761. {
  1762. mszForUser = (LPWSTR)HeapAlloc(
  1763. GetProcessHeap(),
  1764. HEAP_ZERO_MEMORY,
  1765. cchSrcLength * sizeof(WCHAR));
  1766. }
  1767. else
  1768. mszForUser = (LPWSTR)pCtx->AllocateMemory(
  1769. cchSrcLength * sizeof(WCHAR));
  1770. if (NULL == mszForUser)
  1771. {
  1772. CalaisWarning(
  1773. __SUBROUTINE__,
  1774. DBGT("Client can't get return memory"));
  1775. throw (DWORD)SCARD_E_NO_MEMORY;
  1776. }
  1777. *(LPWSTR *)mszOutput = mszForUser;
  1778. mszOutBuf = mszForUser;
  1779. // Fall through intentionally
  1780. }
  1781. else
  1782. {
  1783. *pcchLength = cchSrcLength;
  1784. *(LPWSTR *)mszOutput = (LPWSTR)g_wszBlank;
  1785. break; // Do terminate the case now.
  1786. }
  1787. default:
  1788. if (*pcchLength < cchSrcLength)
  1789. {
  1790. *pcchLength = cchSrcLength;
  1791. throw (DWORD)SCARD_E_INSUFFICIENT_BUFFER;
  1792. }
  1793. MoveToUnicodeMultiString(
  1794. mszOutBuf,
  1795. (LPCTSTR)bfResult.Access(),
  1796. cchSrcLength);
  1797. *pcchLength = cchSrcLength;
  1798. break;
  1799. }
  1800. }
  1801. catch (...)
  1802. {
  1803. if (NULL != mszForUser)
  1804. {
  1805. if (NULL == pCtx)
  1806. HeapFree(GetProcessHeap(), 0, mszForUser);
  1807. else
  1808. pCtx->FreeMemory(mszForUser);
  1809. }
  1810. throw;
  1811. }
  1812. }