Source code of Windows XP (NT5)
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.

1395 lines
34 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. changedb
  5. Abstract:
  6. This file provides the implementation of the Calais Database management
  7. utilities which modify the Calais database.
  8. Author:
  9. Doug Barlow (dbarlow) 1/29/1997
  10. Environment:
  11. Win32, C++ w/ Exceptions
  12. Notes:
  13. ?Notes?
  14. --*/
  15. #ifndef WIN32_LEAN_AND_MEAN
  16. #define WIN32_LEAN_AND_MEAN
  17. #endif
  18. #include <windows.h>
  19. #include <stdlib.h>
  20. #include <tchar.h>
  21. #include <winscard.h>
  22. #include <CalaisLb.h>
  23. // Keep this in sync with QueryDB.cpp
  24. typedef struct {
  25. DWORD dwScope;
  26. HKEY hKey;
  27. } RegMap;
  28. #if SCARD_SCOPE_SYSTEM < SCARD_SCOPE_USER
  29. #error Invalid ordering to SCARD_SCOPE definitions
  30. #endif
  31. static TCHAR l_szInvalidChars[] = TEXT("\\?");
  32. static const RegMap l_rgRegMap[]
  33. = {
  34. { SCARD_SCOPE_USER, HKEY_CURRENT_USER },
  35. // { SCARD_SCOPE_TERMINAL, Not implemented yet }, // ?Hydra?
  36. { SCARD_SCOPE_SYSTEM, HKEY_LOCAL_MACHINE }
  37. };
  38. static const DWORD l_dwRegMapMax = sizeof(l_rgRegMap) / sizeof(RegMap);
  39. static const LPCTSTR l_szrgProvMap[]
  40. = {
  41. NULL, // Zero value
  42. SCARD_REG_PPV,
  43. SCARD_REG_CSP
  44. };
  45. static const DWORD l_dwProvMapMax = sizeof(l_szrgProvMap) / sizeof(LPCTSTR);
  46. static void
  47. GuidFromString(
  48. IN LPCTSTR szGuid,
  49. OUT LPGUID pguidResult);
  50. //
  51. ////////////////////////////////////////////////////////////////////////////////
  52. //
  53. // Calais Database Management Services
  54. //
  55. // The following services provide for managing the Calais Database. These
  56. // services actually update the database, and require a smartcard context.
  57. //
  58. /*++
  59. IntroduceReaderGroup:
  60. This service provides means for introducing a new smartcard reader group to
  61. Calais.
  62. Arguments:
  63. dwScope supplies an indicator of the scope of the operation. Possible
  64. values are:
  65. SCARD_SCOPE_USER - The current user's definitions are used.
  66. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  67. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  68. For V1, SCARD_SCOPE_TERMINAL is not supported..
  69. szGroupName supplies the friendly name to be assigned to the new reader
  70. group.
  71. Return Value:
  72. None
  73. Author:
  74. Doug Barlow (dbarlow) 1/29/1007
  75. --*/
  76. void
  77. IntroduceReaderGroup(
  78. IN DWORD dwScope,
  79. IN LPCTSTR szGroupName)
  80. {
  81. //
  82. // In this implementation, groups need not be pre-declared.
  83. //
  84. if (0 == *szGroupName)
  85. throw (DWORD)SCARD_E_INVALID_VALUE;
  86. if (NULL != _tcspbrk(szGroupName, l_szInvalidChars))
  87. throw (DWORD)SCARD_E_INVALID_VALUE;
  88. return;
  89. }
  90. /*++
  91. ForgetReaderGroup:
  92. This service provides means for removing a previously defined smartcard
  93. reader group from the Calais Subsystem. This service automatically clears
  94. all readers from the group before forgetting it. It does not affect the
  95. existence of the readers in the database.
  96. Arguments:
  97. dwScope supplies an indicator of the scope of the operation. Possible
  98. values are:
  99. SCARD_SCOPE_USER - The current user's definitions are used.
  100. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  101. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  102. For V1, SCARD_SCOPE_TERMINAL is not supported.
  103. szGroupName supplies the friendly name of the reader group to be
  104. forgotten. The Calais-defined default reader groups may not be
  105. forgotten.
  106. Return Value:
  107. None
  108. Author:
  109. Doug Barlow (dbarlow) 1/29/1007
  110. --*/
  111. void
  112. ForgetReaderGroup(
  113. IN DWORD dwScope,
  114. IN LPCTSTR szGroupName)
  115. {
  116. DWORD dwCount, dwLen;
  117. LPCTSTR mszGroups;
  118. CBuffer bfTmp;
  119. CBuffer bfGroup;
  120. DWORD dwIndex;
  121. CRegistry regReaders;
  122. LPCTSTR szReader;
  123. if (0 == *szGroupName)
  124. throw (DWORD)SCARD_E_INVALID_VALUE;
  125. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  126. {
  127. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  128. break;
  129. }
  130. if (l_dwRegMapMax <= dwIndex)
  131. throw (DWORD)SCARD_E_INVALID_VALUE;
  132. regReaders.Open(
  133. l_rgRegMap[dwIndex].hKey,
  134. SCARD_REG_READERS,
  135. KEY_ALL_ACCESS);
  136. regReaders.Status();
  137. MStrAdd(bfGroup, szGroupName);
  138. for (dwIndex = 0;; dwIndex += 1)
  139. {
  140. try
  141. {
  142. try
  143. {
  144. szReader = regReaders.Subkey(dwIndex);
  145. }
  146. catch (...)
  147. {
  148. szReader = NULL;
  149. }
  150. if (NULL == szReader)
  151. break;
  152. CRegistry regReader(regReaders, szReader, KEY_ALL_ACCESS);
  153. mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
  154. dwCount = MStringCount(mszGroups);
  155. dwLen = MStringRemove(mszGroups, bfGroup, bfTmp);
  156. if (dwCount != dwLen)
  157. regReader.SetMultiStringValue(SCARD_REG_GROUPS, bfTmp);
  158. }
  159. catch (...) {}
  160. }
  161. }
  162. /*++
  163. IntroduceReader:
  164. This service provides means for introducing an existing smartcard reader
  165. device to Calais. Once introduced, Calais will assume responsibility for
  166. managing access to that reader.
  167. Arguments:
  168. dwScope supplies an indicator of the scope of the operation. Possible
  169. values are:
  170. SCARD_SCOPE_USER - The current user's definitions are used.
  171. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  172. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  173. For V1, SCARD_SCOPE_TERMINAL is not supported.
  174. szReaderName supplies the friendly name to be assigned to the reader.
  175. SzDeviceName supplies the system name of the smartcard reader device.
  176. (Example: "Smartcard0".)
  177. Return Value:
  178. None
  179. Author:
  180. Doug Barlow (dbarlow) 1/29/1007
  181. --*/
  182. void
  183. IntroduceReader(
  184. IN DWORD dwScope,
  185. IN LPCTSTR szReaderName,
  186. IN LPCTSTR szDeviceName)
  187. {
  188. CRegistry regReaders;
  189. DWORD dwIndex;
  190. //
  191. // Verify the reader name, so that it doesn't include any
  192. // disallowed characters.
  193. //
  194. if (0 == *szReaderName)
  195. throw (DWORD)SCARD_E_INVALID_VALUE;
  196. if (NULL != _tcspbrk(szReaderName, l_szInvalidChars))
  197. throw (DWORD)SCARD_E_INVALID_VALUE;
  198. //
  199. // Translate the caller's scope.
  200. //
  201. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  202. {
  203. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  204. break;
  205. }
  206. if (l_dwRegMapMax <= dwIndex)
  207. throw (DWORD)SCARD_E_INVALID_VALUE;
  208. regReaders.Open(
  209. l_rgRegMap[dwIndex].hKey,
  210. SCARD_REG_READERS,
  211. KEY_CREATE_SUB_KEY,
  212. REG_OPTION_NON_VOLATILE,
  213. NULL); // Inherit
  214. CRegistry regReader(
  215. regReaders,
  216. szReaderName,
  217. KEY_SET_VALUE,
  218. REG_OPTION_NON_VOLATILE,
  219. NULL); // Create it & inherit
  220. if (REG_OPENED_EXISTING_KEY == regReader.GetDisposition())
  221. throw (DWORD)SCARD_E_DUPLICATE_READER;
  222. regReader.SetValue(SCARD_REG_DEVICE, szDeviceName);
  223. // regReader.SetValue(SCARD_REG_OEMCFG, ?what?);
  224. regReader.SetMultiStringValue(SCARD_REG_GROUPS, SCARD_DEFAULT_READERS);
  225. }
  226. /*++
  227. ForgetReader:
  228. This service provides means for removing previously defined smartcard
  229. readers from control by the Calais Subsystem. It is automatically removed
  230. from any groups it may have been added to.
  231. Arguments:
  232. dwScope supplies an indicator of the scope of the operation. Possible
  233. values are:
  234. SCARD_SCOPE_USER - The current user's definitions are used.
  235. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  236. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  237. For V1, SCARD_SCOPE_TERMINAL is not supported.
  238. szReaderName supplies the friendly name of the reader to be forgotten.
  239. Return Value:
  240. None
  241. Author:
  242. Doug Barlow (dbarlow) 1/29/1007
  243. --*/
  244. void
  245. ForgetReader(
  246. IN DWORD dwScope,
  247. IN LPCTSTR szReaderName)
  248. {
  249. CRegistry regReaders;
  250. DWORD dwIndex;
  251. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  252. {
  253. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  254. break;
  255. }
  256. if (l_dwRegMapMax <= dwIndex)
  257. throw (DWORD)SCARD_E_INVALID_VALUE;
  258. regReaders.Open(
  259. l_rgRegMap[dwIndex].hKey,
  260. SCARD_REG_READERS,
  261. KEY_ALL_ACCESS);
  262. regReaders.DeleteKey(szReaderName);
  263. }
  264. /*++
  265. AddReaderToGroup:
  266. This service provides means for adding existing an reader into an existing
  267. reader group.
  268. Arguments:
  269. dwScope supplies an indicator of the scope of the operation. Possible
  270. values are:
  271. SCARD_SCOPE_USER - The current user's definitions are used.
  272. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  273. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  274. For V1, SCARD_SCOPE_TERMINAL is not supported.
  275. szReaderName supplies the friendly name of the reader to be added.
  276. szGroupName supplies the friendly name of the group to which the reader
  277. should be added.
  278. Return Value:
  279. None
  280. Author:
  281. Doug Barlow (dbarlow) 1/29/1007
  282. --*/
  283. void
  284. AddReaderToGroup(
  285. IN DWORD dwScope,
  286. IN LPCTSTR szReaderName,
  287. IN LPCTSTR szGroupName)
  288. {
  289. DWORD dwCount, dwLen;
  290. LPCTSTR mszGroups;
  291. CBuffer bfTmp;
  292. CBuffer bfGroup;
  293. CRegistry regReaders;
  294. DWORD dwIndex;
  295. if (0 == *szGroupName)
  296. throw (DWORD)SCARD_E_INVALID_VALUE;
  297. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  298. {
  299. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  300. break;
  301. }
  302. if (l_dwRegMapMax <= dwIndex)
  303. throw (DWORD)SCARD_E_INVALID_VALUE;
  304. regReaders.Open(
  305. l_rgRegMap[dwIndex].hKey,
  306. SCARD_REG_READERS,
  307. KEY_ALL_ACCESS);
  308. CRegistry regReader(
  309. regReaders,
  310. szReaderName,
  311. KEY_ALL_ACCESS);
  312. MStrAdd(bfGroup, szGroupName);
  313. mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
  314. dwCount = MStringCount(mszGroups);
  315. dwLen = MStringMerge(mszGroups, bfGroup, bfTmp);
  316. if (dwCount != dwLen)
  317. regReader.SetMultiStringValue(SCARD_REG_GROUPS, bfTmp);
  318. }
  319. /*++
  320. RemoveReaderFromGroup:
  321. This service provides means for removing an existing reader from an existing
  322. reader group. It does not affect the existence of either the reader or the
  323. group in the Calais database.
  324. Arguments:
  325. dwScope supplies an indicator of the scope of the operation. Possible
  326. values are:
  327. SCARD_SCOPE_USER - The current user's definitions are used.
  328. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  329. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  330. For V1, SCARD_SCOPE_TERMINAL is not supported.
  331. szReaderName supplies the friendly name of the reader to be removed.
  332. szGroupName supplies the friendly name of the group to which the reader
  333. should be removed.
  334. Return Value:
  335. A 32-bit value indicating whether or not the service completed successfully.
  336. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  337. represents an error condition.
  338. Author:
  339. Doug Barlow (dbarlow) 1/29/1007
  340. --*/
  341. void
  342. RemoveReaderFromGroup(
  343. IN DWORD dwScope,
  344. IN LPCTSTR szReaderName,
  345. IN LPCTSTR szGroupName)
  346. {
  347. DWORD dwCount, dwLen;
  348. LPCTSTR mszGroups;
  349. CBuffer bfTmp;
  350. CBuffer bfGroup;
  351. CRegistry regReaders;
  352. DWORD dwIndex;
  353. if (0 == *szGroupName)
  354. throw (DWORD)SCARD_E_INVALID_VALUE;
  355. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  356. {
  357. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  358. break;
  359. }
  360. if (l_dwRegMapMax <= dwIndex)
  361. throw (DWORD)SCARD_E_INVALID_VALUE;
  362. regReaders.Open(
  363. l_rgRegMap[dwIndex].hKey,
  364. SCARD_REG_READERS,
  365. KEY_ALL_ACCESS);
  366. CRegistry regReader(
  367. regReaders,
  368. szReaderName,
  369. KEY_ALL_ACCESS);
  370. MStrAdd(bfGroup, szGroupName);
  371. mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
  372. dwCount = MStringCount(mszGroups);
  373. dwLen = MStringRemove(mszGroups, bfGroup, bfTmp);
  374. if (dwCount != dwLen)
  375. regReader.SetMultiStringValue(SCARD_REG_GROUPS, bfTmp);
  376. }
  377. /*++
  378. IntroduceCard:
  379. This service provides means for introducing new smartcards to the Calais
  380. Subsystem for the active user.
  381. Arguments:
  382. dwScope supplies an indicator of the scope of the operation. Possible
  383. values are:
  384. SCARD_SCOPE_USER - The current user's definitions are used.
  385. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  386. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  387. For V1, SCARD_SCOPE_TERMINAL is not supported.
  388. szCardName supplies the friendly name by which this card should be known.
  389. PguidPrimaryProvider supplies a pointer to a GUID used to identify the
  390. Primary Service Provider for the card.
  391. rgguidInterfaces supplies an array of GUIDs identifying the smartcard
  392. interfaces supported by this card.
  393. dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
  394. pbAtr supplies a string against which card ATRs will be compared to
  395. determine a possible match for this card. The length of this string is
  396. determined by normal ATR parsing.
  397. pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
  398. smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
  399. must point to a string of bytes the same length as the ATR string
  400. supplied in pbAtr. Then when a given ATR A is compared to the ATR
  401. supplied in pbAtr B, it matches if and only if A & M = B, where M is the
  402. supplied mask, and & represents bitwise logical AND.
  403. cbAtrLen supplies the length of the ATR and Mask. This value may be zero
  404. if the lentgh is obvious from the ATR. However, it may be required if
  405. there is a Mask value that obscures the actual ATR.
  406. Return Value:
  407. None
  408. Author:
  409. Doug Barlow (dbarlow) 10/23/1996
  410. --*/
  411. void
  412. IntroduceCard(
  413. IN DWORD dwScope,
  414. IN LPCTSTR szCardName,
  415. IN LPCGUID pguidPrimaryProvider,
  416. IN LPCGUID rgguidInterfaces,
  417. IN DWORD dwInterfaceCount,
  418. IN LPCBYTE pbAtr,
  419. IN LPCBYTE pbAtrMask,
  420. IN DWORD cbAtrLen)
  421. {
  422. DWORD dwIndex, dwReg, dwAtrLen;
  423. //
  424. // Verify the card name, so that it doesn't include any
  425. // disallowed characters.
  426. //
  427. if (0 == *szCardName)
  428. throw (DWORD)SCARD_E_INVALID_VALUE;
  429. if (NULL != _tcspbrk(szCardName, l_szInvalidChars))
  430. throw (DWORD)SCARD_E_INVALID_VALUE;
  431. //
  432. // Translate the caller's scope.
  433. //
  434. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  435. {
  436. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  437. break;
  438. }
  439. if (l_dwRegMapMax == dwIndex)
  440. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  441. dwReg = dwIndex;
  442. if (NULL == pbAtrMask)
  443. {
  444. if (!ParseAtr(pbAtr, &dwAtrLen))
  445. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  446. if ((0 != cbAtrLen) && (dwAtrLen != cbAtrLen))
  447. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  448. }
  449. else
  450. {
  451. if ((2 > cbAtrLen) || (33 < cbAtrLen))
  452. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  453. for (dwIndex = 0; dwIndex < cbAtrLen; dwIndex += 1)
  454. {
  455. if (pbAtr[dwIndex] != (pbAtr[dwIndex] & pbAtrMask[dwIndex]))
  456. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  457. }
  458. dwAtrLen = cbAtrLen;
  459. }
  460. CRegistry regCards(
  461. l_rgRegMap[dwReg].hKey,
  462. SCARD_REG_CARDS,
  463. KEY_ALL_ACCESS,
  464. REG_OPTION_NON_VOLATILE,
  465. NULL); // Inherit
  466. CRegistry regCard(
  467. regCards,
  468. szCardName,
  469. KEY_ALL_ACCESS,
  470. REG_OPTION_NON_VOLATILE,
  471. NULL); // Create it & inherit
  472. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  473. throw (DWORD)ERROR_ALREADY_EXISTS;
  474. regCard.SetValue(
  475. SCARD_REG_ATR,
  476. pbAtr,
  477. dwAtrLen);
  478. if (NULL != pbAtrMask)
  479. regCard.SetValue(
  480. SCARD_REG_ATRMASK,
  481. pbAtrMask,
  482. dwAtrLen);
  483. if (NULL != pguidPrimaryProvider)
  484. regCard.SetValue(
  485. SCARD_REG_PPV,
  486. (LPBYTE)pguidPrimaryProvider,
  487. sizeof(GUID));
  488. if ((NULL != rgguidInterfaces) && (0 < dwInterfaceCount))
  489. regCard.SetValue(
  490. SCARD_REG_GUIDS,
  491. (LPBYTE)rgguidInterfaces,
  492. sizeof(GUID) * dwInterfaceCount);
  493. }
  494. /*++
  495. SetCardTypeProviderName:
  496. This routine sets the value of a given Provider Name, by Id number, for the
  497. identified card type.
  498. Arguments:
  499. dwScope supplies an indicator of the scope of the operation. Possible
  500. values are:
  501. SCARD_SCOPE_USER - The current user's definitions are used.
  502. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  503. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  504. For V1, SCARD_SCOPE_TERMINAL and SCARD_SCOPE_USER are not supported.
  505. szCardName supplies the name of the card type with which this provider
  506. name is to be associated.
  507. dwProviderId supplies the identifier for the provider to be associated with
  508. this card type. Possible values are:
  509. SCARD_PROVIDER_SSP - The SSP identifier, as a GUID string.
  510. SCARD_PROVIDER_CSP - The CSP name.
  511. Other values < 0x80000000 are reserved for use by Microsoft. Values
  512. over 0x80000000 are available for use by the smart card vendors, and
  513. are card-specific.
  514. szProvider supplies the string identifying the provider.
  515. Return Value:
  516. None.
  517. Author:
  518. Doug Barlow (dbarlow) 1/19/1998
  519. --*/
  520. void
  521. SetCardTypeProviderName(
  522. IN DWORD dwScope,
  523. IN LPCTSTR szCardName,
  524. IN DWORD dwProviderId,
  525. IN LPCTSTR szProvider)
  526. {
  527. DWORD dwIndex;
  528. LPCTSTR szProvValue;
  529. TCHAR szNumeric[36];
  530. //
  531. // Validate the request.
  532. //
  533. if (0 == *szCardName)
  534. throw (DWORD)SCARD_E_INVALID_VALUE;
  535. if (0 == *szProvider)
  536. throw (DWORD)SCARD_E_INVALID_VALUE;
  537. //
  538. // Find the Card definition.
  539. //
  540. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  541. {
  542. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  543. break;
  544. }
  545. if (l_dwRegMapMax == dwIndex)
  546. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  547. CRegistry regCardTypes(
  548. l_rgRegMap[dwIndex].hKey,
  549. SCARD_REG_CARDS,
  550. KEY_ALL_ACCESS);
  551. CRegistry regCard(
  552. regCardTypes,
  553. szCardName,
  554. KEY_ALL_ACCESS);
  555. regCard.Status();
  556. //
  557. // Derive the Provider Value Name.
  558. //
  559. if (dwProviderId < l_dwProvMapMax)
  560. {
  561. szProvValue = l_szrgProvMap[dwProviderId];
  562. if (NULL == szProvValue)
  563. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  564. }
  565. else if (0x80000000 <= dwProviderId)
  566. {
  567. _ultot(dwProviderId, szNumeric, 16);
  568. szProvValue = szNumeric;
  569. }
  570. else
  571. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  572. //
  573. // Write the provider value.
  574. //
  575. switch (dwProviderId)
  576. {
  577. case 1: // SCARD_PROVIDER_SSP
  578. {
  579. GUID guidProvider;
  580. GuidFromString(szProvider, &guidProvider);
  581. regCard.SetValue(szProvValue, (LPCBYTE)&guidProvider, sizeof(GUID));
  582. break;
  583. }
  584. default:
  585. regCard.SetValue(szProvValue, szProvider);
  586. }
  587. }
  588. /*++
  589. ForgetCard:
  590. This service provides means for removing previously defined smartcards from
  591. the Calais Subsystem.
  592. Arguments:
  593. dwScope supplies an indicator of the scope of the operation. Possible
  594. values are:
  595. SCARD_SCOPE_USER - The current user's definitions are used.
  596. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  597. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  598. For V1, SCARD_SCOPE_TERMINAL is not supported.
  599. szCardName supplies the friendly name of the card to be forgotten.
  600. Return Value:
  601. None
  602. Author:
  603. Doug Barlow (dbarlow) 10/23/1996
  604. --*/
  605. void
  606. ForgetCard(
  607. IN DWORD dwScope,
  608. IN LPCTSTR szCardName)
  609. {
  610. DWORD dwIndex;
  611. if (0 == *szCardName)
  612. throw (DWORD)SCARD_E_INVALID_VALUE;
  613. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  614. {
  615. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  616. break;
  617. }
  618. if (l_dwRegMapMax == dwIndex)
  619. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  620. CRegistry regCards(
  621. l_rgRegMap[dwIndex].hKey,
  622. SCARD_REG_CARDS,
  623. KEY_ALL_ACCESS);
  624. regCards.DeleteKey(szCardName);
  625. }
  626. #ifdef ENABLE_SCARD_TEMPLATES
  627. /*++
  628. IntroduceCardTypeTemplate:
  629. This service provides means for introducing a new smartcard template to the
  630. Calais Subsystem. A card tye template is a known card type that hasn't
  631. been formally introduced.
  632. Arguments:
  633. dwScope supplies an indicator of the scope of the operation. Possible
  634. values are:
  635. SCARD_SCOPE_USER - The current user's definitions are used.
  636. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  637. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  638. For V1, SCARD_SCOPE_USER and SCARD_SCOPE_TERMINAL is not supported.
  639. szVendorName supplies the manufacturer name by which this card should be
  640. recognized.
  641. PguidPrimaryProvider supplies a pointer to a GUID used to identify the
  642. Primary Service Provider for the card.
  643. rgguidInterfaces supplies an array of GUIDs identifying the smartcard
  644. interfaces supported by this card.
  645. dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
  646. pbAtr supplies a string against which card ATRs will be compared to
  647. determine a possible match for this card. The length of this string is
  648. determined by normal ATR parsing.
  649. pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
  650. smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
  651. must point to a string of bytes the same length as the ATR string
  652. supplied in pbAtr. Then when a given ATR A is compared to the ATR
  653. supplied in pbAtr B, it matches if and only if A & M = B, where M is the
  654. supplied mask, and & represents bitwise logical AND.
  655. cbAtrLen supplies the length of the ATR and Mask. This value may be zero
  656. if the lentgh is obvious from the ATR. However, it may be required if
  657. there is a Mask value that obscures the actual ATR.
  658. Return Value:
  659. None
  660. Author:
  661. Doug Barlow (dbarlow) 1/16/1998
  662. --*/
  663. void
  664. IntroduceCardTypeTemplate(
  665. IN DWORD dwScope,
  666. IN LPCTSTR szVendorName,
  667. IN LPCGUID pguidPrimaryProvider,
  668. IN LPCGUID rgguidInterfaces,
  669. IN DWORD dwInterfaceCount,
  670. IN LPCBYTE pbAtr,
  671. IN LPCBYTE pbAtrMask,
  672. IN DWORD cbAtrLen)
  673. {
  674. DWORD dwIndex, dwReg, dwAtrLen;
  675. //
  676. // Verify the template name, so that it doesn't include any
  677. // disallowed characters.
  678. //
  679. if (NULL != _tcspbrk(szVendorName, l_szInvalidChars))
  680. throw (DWORD)SCARD_E_INVALID_VALUE;
  681. //
  682. // Translate the caller's scope.
  683. //
  684. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  685. {
  686. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  687. break;
  688. }
  689. if (l_dwRegMapMax == dwIndex)
  690. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  691. dwReg = dwIndex;
  692. if (NULL == pbAtrMask)
  693. {
  694. if (!ParseAtr(pbAtr, &dwAtrLen))
  695. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  696. if ((0 != cbAtrLen) && (dwAtrLen != cbAtrLen))
  697. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  698. }
  699. else
  700. {
  701. if ((2 > cbAtrLen) || (33 < cbAtrLen))
  702. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  703. for (dwIndex = 0; dwIndex < cbAtrLen; dwIndex += 1)
  704. {
  705. if (pbAtr[dwIndex] != (pbAtr[dwIndex] & pbAtrMask[dwIndex]))
  706. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  707. }
  708. dwAtrLen = cbAtrLen;
  709. }
  710. CRegistry regCards(
  711. l_rgRegMap[dwReg].hKey,
  712. SCARD_REG_TEMPLATES,
  713. KEY_ALL_ACCESS,
  714. REG_OPTION_NON_VOLATILE,
  715. NULL);
  716. CRegistry regCard(
  717. regCards,
  718. szVendorName,
  719. KEY_ALL_ACCESS,
  720. REG_OPTION_NON_VOLATILE,
  721. NULL); // Create it.
  722. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  723. throw (DWORD)ERROR_ALREADY_EXISTS;
  724. regCard.SetValue(
  725. SCARD_REG_ATR,
  726. pbAtr,
  727. dwAtrLen);
  728. if (NULL != pbAtrMask)
  729. regCard.SetValue(
  730. SCARD_REG_ATRMASK,
  731. pbAtrMask,
  732. dwAtrLen);
  733. if (NULL != pguidPrimaryProvider)
  734. regCard.SetValue(
  735. SCARD_REG_PPV,
  736. (LPBYTE)pguidPrimaryProvider,
  737. sizeof(GUID));
  738. if ((NULL != rgguidInterfaces) && (0 < dwInterfaceCount))
  739. regCard.SetValue(
  740. SCARD_REG_GUIDS,
  741. (LPBYTE)rgguidInterfaces,
  742. sizeof(GUID) * dwInterfaceCount);
  743. }
  744. /*++
  745. SetCardTypeTemplateProviderName:
  746. This routine sets the value of a given Provider Name, by Id number, for the
  747. identified card type template.
  748. Arguments:
  749. dwScope supplies an indicator of the scope of the operation. Possible
  750. values are:
  751. SCARD_SCOPE_USER - The current user's definitions are used.
  752. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  753. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  754. For V1, SCARD_SCOPE_TERMINAL and SCARD_SCOPE_USER are not supported.
  755. szTemplateName supplies the name of the card type template with which this
  756. provider name is to be associated.
  757. dwProviderId supplies the identifier for the provider to be associated with
  758. this card type template. Possible values are:
  759. SCARD_PROVIDER_SSP - The SSP identifier, as a GUID string.
  760. SCARD_PROVIDER_CSP - The CSP name.
  761. Other values < 0x80000000 are reserved for use by Microsoft. Values
  762. over 0x80000000 are available for use by the smart card vendors, and
  763. are card-specific.
  764. szProvider supplies the string identifying the provider.
  765. Return Value:
  766. None.
  767. Author:
  768. Doug Barlow (dbarlow) 1/19/1998
  769. --*/
  770. void
  771. SetCardTypeTemplateProviderName(
  772. IN DWORD dwScope,
  773. IN LPCTSTR szTemplateName,
  774. IN DWORD dwProviderId,
  775. IN LPCTSTR szProvider)
  776. {
  777. DWORD dwIndex;
  778. LPCTSTR szProvValue;
  779. TCHAR szNumeric[36];
  780. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  781. {
  782. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  783. break;
  784. }
  785. if (l_dwRegMapMax == dwIndex)
  786. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  787. //
  788. // Make sure the template exists.
  789. //
  790. CRegistry regTemplates(
  791. l_rgRegMap[dwIndex].hKey,
  792. SCARD_REG_TEMPLATES,
  793. KEY_ALL_ACCESS);
  794. CRegistry regTempl(
  795. regTemplates,
  796. szTemplateName,
  797. KEY_ALL_ACCESS);
  798. regTempl.Status();
  799. //
  800. // Derive the Provider Value Name.
  801. //
  802. if (dwProviderId < l_dwProvMapMax)
  803. {
  804. szProvValue = l_szrgProvMap[dwProviderId];
  805. if (NULL == szProvValue)
  806. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  807. }
  808. else if (0x80000000 <= dwProviderId)
  809. {
  810. _ultot(dwProviderId, szNumeric, 16);
  811. szProvValue = szNumeric;
  812. }
  813. else
  814. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  815. //
  816. // Write the provider value.
  817. //
  818. switch (dwProviderId)
  819. {
  820. case 1: // SCARD_PROVIDER_SSP
  821. {
  822. GUID guidProvider;
  823. GuidFromString(szProvider, &guidProvider);
  824. regTempl.SetValue(szProvValue, (LPCBYTE)&guidProvider, sizeof(GUID));
  825. break;
  826. }
  827. default:
  828. regTempl.SetValue(szProvValue, szProvider);
  829. }
  830. }
  831. /*++
  832. ForgetCardTypeTemplate:
  833. This service provides means for removing previously defined smart card type
  834. templates from the Calais Subsystem.
  835. Arguments:
  836. dwScope supplies an indicator of the scope of the operation. Possible
  837. values are:
  838. SCARD_SCOPE_USER - The current user's definitions are used.
  839. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  840. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  841. For V1, SCARD_SCOPE_USER and SCARD_SCOPE_TERMINAL are not supported.
  842. szVendorName supplies the manufacturer's name of the card to be forgotten.
  843. Return Value:
  844. None
  845. Author:
  846. Doug Barlow (dbarlow) 1/16/1998
  847. --*/
  848. void
  849. ForgetCardTypeTemplate(
  850. IN DWORD dwScope,
  851. IN LPCTSTR szVendorName)
  852. {
  853. DWORD dwIndex;
  854. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  855. {
  856. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  857. break;
  858. }
  859. if (l_dwRegMapMax == dwIndex)
  860. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  861. CRegistry regTemplates(
  862. l_rgRegMap[dwIndex].hKey,
  863. SCARD_REG_TEMPLATES,
  864. KEY_ALL_ACCESS);
  865. regTemplates.DeleteKey(szVendorName);
  866. }
  867. /*++
  868. IntroduceCardTypeFromTemplate:
  869. This service provides means for introducing new smartcards to the Calais
  870. Subsystem for the active user, based on a stored card template.
  871. Arguments:
  872. dwScope supplies an indicator of the scope of the operation. Possible
  873. values are:
  874. SCARD_SCOPE_USER - The current user's definitions are used.
  875. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  876. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  877. For V1, SCARD_SCOPE_TERMINAL is not supported.
  878. szVendorName supplies the vendor name by which this card type is known,
  879. identifying the template to use.
  880. szFriendlyName supplies the friendly name by which this card should be
  881. known. If this value is NULL, the vendor name is used as the friendly
  882. name,
  883. Return Value:
  884. None
  885. Author:
  886. Doug Barlow (dbarlow) 1/16/1998
  887. --*/
  888. void
  889. IntroduceCardTypeFromTemplate(
  890. IN DWORD dwScope,
  891. IN LPCTSTR szVendorName,
  892. IN LPCTSTR szFriendlyName /* = NULL */ )
  893. {
  894. DWORD dwIndex;
  895. HKEY hCardTypeKey;
  896. CRegistry regTemplates, regTmpl;
  897. //
  898. // Verify the reader name, so that it doesn't include any
  899. // disallowed characters.
  900. //
  901. if (NULL == szFriendlyName)
  902. szFriendlyName = szVendorName;
  903. else
  904. {
  905. if (NULL != _tcspbrk(szFriendlyName, l_szInvalidChars))
  906. throw (DWORD)SCARD_E_INVALID_VALUE;
  907. }
  908. //
  909. // Identify the card type scope.
  910. //
  911. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  912. {
  913. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  914. break;
  915. }
  916. if (l_dwRegMapMax == dwIndex)
  917. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  918. hCardTypeKey = l_rgRegMap[dwIndex].hKey;
  919. //
  920. // Find the Template definition closest to the caller.
  921. //
  922. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  923. {
  924. if (l_rgRegMap[dwIndex].dwScope >= dwScope)
  925. {
  926. regTemplates.Open(
  927. l_rgRegMap[dwIndex].hKey,
  928. SCARD_REG_TEMPLATES,
  929. KEY_READ);
  930. try
  931. {
  932. regTmpl.Open(regTemplates, szVendorName, KEY_READ);
  933. regTmpl.Status();
  934. break;
  935. }
  936. catch (...)
  937. {
  938. regTmpl.Close();
  939. }
  940. regTemplates.Close();
  941. }
  942. }
  943. if (l_dwRegMapMax <= dwIndex)
  944. throw (DWORD)ERROR_FILE_NOT_FOUND;
  945. //
  946. // Create the CardType Entry.
  947. //
  948. CRegistry regCards(
  949. hCardTypeKey,
  950. SCARD_REG_CARDS,
  951. KEY_ALL_ACCESS,
  952. REG_OPTION_NON_VOLATILE,
  953. NULL);
  954. CRegistry regCard(
  955. regCards,
  956. szFriendlyName,
  957. KEY_ALL_ACCESS,
  958. REG_OPTION_NON_VOLATILE,
  959. NULL); // Create it.
  960. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  961. throw (DWORD)ERROR_ALREADY_EXISTS;
  962. //
  963. // Copy the entries.
  964. //
  965. regCard.Copy(regTmpl);
  966. }
  967. #endif // ENABLE_SCARD_TEMPLATES
  968. //
  969. ////////////////////////////////////////////////////////////////////////////////
  970. //
  971. // Support Routines
  972. //
  973. /*++
  974. GuidFromString:
  975. This routine converts a string representation of a GUID into an actual GUID.
  976. It tries not to be picky about the systax, as long as it can get a GUID out
  977. of the string. It's here so that it's not necessary to link all of OleBase
  978. into WinSCard. Otherwise, we'd just use CLSIDFromString.
  979. Arguments:
  980. szGuid supplies the GUID as a string. For this routine, a GUID consists of
  981. hex digits, and some collection of braces and dashes.
  982. pguidResult receives the converted GUID. If an error occurs during
  983. conversion, the contents of this parameter are indeterminant.
  984. Return Value:
  985. None
  986. Throws:
  987. Errors are thrown as DWORD status codes.
  988. Author:
  989. Doug Barlow (dbarlow) 1/20/1998
  990. --*/
  991. static void
  992. GuidFromString(
  993. IN LPCTSTR szGuid,
  994. OUT LPGUID pguidResult)
  995. {
  996. // The following placement assumes Little Endianness.
  997. static const WORD wPlace[sizeof(GUID)]
  998. = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
  999. DWORD dwI, dwJ;
  1000. LPCTSTR pch = szGuid;
  1001. LPBYTE pbGuid = (LPBYTE)pguidResult;
  1002. BYTE bVal;
  1003. for (dwI = 0; dwI < sizeof(GUID); dwI += 1)
  1004. {
  1005. bVal = 0;
  1006. for (dwJ = 0; dwJ < 2;)
  1007. {
  1008. switch (*pch)
  1009. {
  1010. case TEXT('0'):
  1011. case TEXT('1'):
  1012. case TEXT('2'):
  1013. case TEXT('3'):
  1014. case TEXT('4'):
  1015. case TEXT('5'):
  1016. case TEXT('6'):
  1017. case TEXT('7'):
  1018. case TEXT('8'):
  1019. case TEXT('9'):
  1020. bVal = (bVal << 4) + (*pch - TEXT('0'));
  1021. dwJ += 1;
  1022. break;
  1023. case TEXT('A'):
  1024. case TEXT('B'):
  1025. case TEXT('C'):
  1026. case TEXT('D'):
  1027. case TEXT('E'):
  1028. case TEXT('F'):
  1029. bVal = (bVal << 4) + (10 + *pch - TEXT('A'));
  1030. dwJ += 1;
  1031. break;
  1032. case TEXT('a'):
  1033. case TEXT('b'):
  1034. case TEXT('c'):
  1035. case TEXT('d'):
  1036. case TEXT('e'):
  1037. case TEXT('f'):
  1038. bVal = (bVal << 4) + (10 + *pch - TEXT('a'));
  1039. dwJ += 1;
  1040. break;
  1041. case TEXT('['):
  1042. case TEXT(']'):
  1043. case TEXT('{'):
  1044. case TEXT('}'):
  1045. case TEXT('-'):
  1046. break;
  1047. default:
  1048. throw (DWORD)SCARD_E_INVALID_VALUE;
  1049. }
  1050. pch += 1;
  1051. }
  1052. pbGuid[wPlace[dwI]] = bVal;
  1053. }
  1054. }