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.

1400 lines
36 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. // Need to prevent passing a NULL string to DeleteKey, since
  259. // that will cause the whole reader DB to be deleted.
  260. if (NULL == szReaderName || _T('\0') == szReaderName[0])
  261. throw (DWORD)SCARD_E_INVALID_VALUE;
  262. regReaders.Open(
  263. l_rgRegMap[dwIndex].hKey,
  264. SCARD_REG_READERS,
  265. KEY_ALL_ACCESS);
  266. regReaders.DeleteKey(szReaderName);
  267. }
  268. /*++
  269. AddReaderToGroup:
  270. This service provides means for adding existing an reader into an existing
  271. reader group.
  272. Arguments:
  273. dwScope supplies an indicator of the scope of the operation. Possible
  274. values are:
  275. SCARD_SCOPE_USER - The current user's definitions are used.
  276. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  277. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  278. For V1, SCARD_SCOPE_TERMINAL is not supported.
  279. szReaderName supplies the friendly name of the reader to be added.
  280. szGroupName supplies the friendly name of the group to which the reader
  281. should be added.
  282. Return Value:
  283. None
  284. Author:
  285. Doug Barlow (dbarlow) 1/29/1007
  286. --*/
  287. void
  288. AddReaderToGroup(
  289. IN DWORD dwScope,
  290. IN LPCTSTR szReaderName,
  291. IN LPCTSTR szGroupName)
  292. {
  293. DWORD dwCount, dwLen;
  294. LPCTSTR mszGroups;
  295. CBuffer bfTmp;
  296. CBuffer bfGroup;
  297. CRegistry regReaders;
  298. DWORD dwIndex;
  299. if (0 == *szGroupName)
  300. throw (DWORD)SCARD_E_INVALID_VALUE;
  301. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  302. {
  303. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  304. break;
  305. }
  306. if (l_dwRegMapMax <= dwIndex)
  307. throw (DWORD)SCARD_E_INVALID_VALUE;
  308. regReaders.Open(
  309. l_rgRegMap[dwIndex].hKey,
  310. SCARD_REG_READERS,
  311. KEY_ALL_ACCESS);
  312. CRegistry regReader(
  313. regReaders,
  314. szReaderName,
  315. KEY_ALL_ACCESS);
  316. MStrAdd(bfGroup, szGroupName);
  317. mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
  318. dwCount = MStringCount(mszGroups);
  319. dwLen = MStringMerge(mszGroups, bfGroup, bfTmp);
  320. if (dwCount != dwLen)
  321. regReader.SetMultiStringValue(SCARD_REG_GROUPS, bfTmp);
  322. }
  323. /*++
  324. RemoveReaderFromGroup:
  325. This service provides means for removing an existing reader from an existing
  326. reader group. It does not affect the existence of either the reader or the
  327. group in the Calais database.
  328. Arguments:
  329. dwScope supplies an indicator of the scope of the operation. Possible
  330. values are:
  331. SCARD_SCOPE_USER - The current user's definitions are used.
  332. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  333. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  334. For V1, SCARD_SCOPE_TERMINAL is not supported.
  335. szReaderName supplies the friendly name of the reader to be removed.
  336. szGroupName supplies the friendly name of the group to which the reader
  337. should be removed.
  338. Return Value:
  339. A 32-bit value indicating whether or not the service completed successfully.
  340. SCARD_S_SUCCESS is returned on successful completion. Otherwise, the value
  341. represents an error condition.
  342. Author:
  343. Doug Barlow (dbarlow) 1/29/1007
  344. --*/
  345. void
  346. RemoveReaderFromGroup(
  347. IN DWORD dwScope,
  348. IN LPCTSTR szReaderName,
  349. IN LPCTSTR szGroupName)
  350. {
  351. DWORD dwCount, dwLen;
  352. LPCTSTR mszGroups;
  353. CBuffer bfTmp;
  354. CBuffer bfGroup;
  355. CRegistry regReaders;
  356. DWORD dwIndex;
  357. if (0 == *szGroupName)
  358. throw (DWORD)SCARD_E_INVALID_VALUE;
  359. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  360. {
  361. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  362. break;
  363. }
  364. if (l_dwRegMapMax <= dwIndex)
  365. throw (DWORD)SCARD_E_INVALID_VALUE;
  366. regReaders.Open(
  367. l_rgRegMap[dwIndex].hKey,
  368. SCARD_REG_READERS,
  369. KEY_ALL_ACCESS);
  370. CRegistry regReader(
  371. regReaders,
  372. szReaderName,
  373. KEY_ALL_ACCESS);
  374. MStrAdd(bfGroup, szGroupName);
  375. mszGroups = regReader.GetMultiStringValue(SCARD_REG_GROUPS);
  376. dwCount = MStringCount(mszGroups);
  377. dwLen = MStringRemove(mszGroups, bfGroup, bfTmp);
  378. if (dwCount != dwLen)
  379. regReader.SetMultiStringValue(SCARD_REG_GROUPS, bfTmp);
  380. }
  381. /*++
  382. IntroduceCard:
  383. This service provides means for introducing new smartcards to the Calais
  384. Subsystem for the active user.
  385. Arguments:
  386. dwScope supplies an indicator of the scope of the operation. Possible
  387. values are:
  388. SCARD_SCOPE_USER - The current user's definitions are used.
  389. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  390. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  391. For V1, SCARD_SCOPE_TERMINAL is not supported.
  392. szCardName supplies the friendly name by which this card should be known.
  393. PguidPrimaryProvider supplies a pointer to a GUID used to identify the
  394. Primary Service Provider for the card.
  395. rgguidInterfaces supplies an array of GUIDs identifying the smartcard
  396. interfaces supported by this card.
  397. dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
  398. pbAtr supplies a string against which card ATRs will be compared to
  399. determine a possible match for this card. The length of this string is
  400. determined by normal ATR parsing.
  401. pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
  402. smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
  403. must point to a string of bytes the same length as the ATR string
  404. supplied in pbAtr. Then when a given ATR A is compared to the ATR
  405. supplied in pbAtr B, it matches if and only if A & M = B, where M is the
  406. supplied mask, and & represents bitwise logical AND.
  407. cbAtrLen supplies the length of the ATR and Mask. This value may be zero
  408. if the lentgh is obvious from the ATR. However, it may be required if
  409. there is a Mask value that obscures the actual ATR.
  410. Return Value:
  411. None
  412. Author:
  413. Doug Barlow (dbarlow) 10/23/1996
  414. --*/
  415. void
  416. IntroduceCard(
  417. IN DWORD dwScope,
  418. IN LPCTSTR szCardName,
  419. IN LPCGUID pguidPrimaryProvider,
  420. IN LPCGUID rgguidInterfaces,
  421. IN DWORD dwInterfaceCount,
  422. IN LPCBYTE pbAtr,
  423. IN LPCBYTE pbAtrMask,
  424. IN DWORD cbAtrLen)
  425. {
  426. DWORD dwIndex, dwReg, dwAtrLen;
  427. //
  428. // Verify the card name, so that it doesn't include any
  429. // disallowed characters.
  430. //
  431. if (0 == *szCardName)
  432. throw (DWORD)SCARD_E_INVALID_VALUE;
  433. if (NULL != _tcspbrk(szCardName, l_szInvalidChars))
  434. throw (DWORD)SCARD_E_INVALID_VALUE;
  435. //
  436. // Translate the caller's scope.
  437. //
  438. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  439. {
  440. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  441. break;
  442. }
  443. if (l_dwRegMapMax == dwIndex)
  444. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  445. dwReg = dwIndex;
  446. if (NULL == pbAtrMask)
  447. {
  448. if (!ParseAtr(pbAtr, &dwAtrLen))
  449. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  450. if ((0 != cbAtrLen) && (dwAtrLen != cbAtrLen))
  451. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  452. }
  453. else
  454. {
  455. if ((2 > cbAtrLen) || (33 < cbAtrLen))
  456. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  457. for (dwIndex = 0; dwIndex < cbAtrLen; dwIndex += 1)
  458. {
  459. if (pbAtr[dwIndex] != (pbAtr[dwIndex] & pbAtrMask[dwIndex]))
  460. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  461. }
  462. dwAtrLen = cbAtrLen;
  463. }
  464. CRegistry regCards(
  465. l_rgRegMap[dwReg].hKey,
  466. SCARD_REG_CARDS,
  467. KEY_ALL_ACCESS,
  468. REG_OPTION_NON_VOLATILE,
  469. NULL); // Inherit
  470. CRegistry regCard(
  471. regCards,
  472. szCardName,
  473. KEY_ALL_ACCESS,
  474. REG_OPTION_NON_VOLATILE,
  475. NULL); // Create it & inherit
  476. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  477. throw (DWORD)ERROR_ALREADY_EXISTS;
  478. regCard.SetValue(
  479. SCARD_REG_ATR,
  480. pbAtr,
  481. dwAtrLen);
  482. if (NULL != pbAtrMask)
  483. regCard.SetValue(
  484. SCARD_REG_ATRMASK,
  485. pbAtrMask,
  486. dwAtrLen);
  487. if (NULL != pguidPrimaryProvider)
  488. regCard.SetValue(
  489. SCARD_REG_PPV,
  490. (LPBYTE)pguidPrimaryProvider,
  491. sizeof(GUID));
  492. if ((NULL != rgguidInterfaces) && (0 < dwInterfaceCount))
  493. regCard.SetValue(
  494. SCARD_REG_GUIDS,
  495. (LPBYTE)rgguidInterfaces,
  496. sizeof(GUID) * dwInterfaceCount);
  497. }
  498. /*++
  499. SetCardTypeProviderName:
  500. This routine sets the value of a given Provider Name, by Id number, for the
  501. identified card type.
  502. Arguments:
  503. dwScope supplies an indicator of the scope of the operation. Possible
  504. values are:
  505. SCARD_SCOPE_USER - The current user's definitions are used.
  506. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  507. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  508. For V1, SCARD_SCOPE_TERMINAL and SCARD_SCOPE_USER are not supported.
  509. szCardName supplies the name of the card type with which this provider
  510. name is to be associated.
  511. dwProviderId supplies the identifier for the provider to be associated with
  512. this card type. Possible values are:
  513. SCARD_PROVIDER_SSP - The SSP identifier, as a GUID string.
  514. SCARD_PROVIDER_CSP - The CSP name.
  515. Other values < 0x80000000 are reserved for use by Microsoft. Values
  516. over 0x80000000 are available for use by the smart card vendors, and
  517. are card-specific.
  518. szProvider supplies the string identifying the provider.
  519. Return Value:
  520. None.
  521. Author:
  522. Doug Barlow (dbarlow) 1/19/1998
  523. --*/
  524. void
  525. SetCardTypeProviderName(
  526. IN DWORD dwScope,
  527. IN LPCTSTR szCardName,
  528. IN DWORD dwProviderId,
  529. IN LPCTSTR szProvider)
  530. {
  531. DWORD dwIndex;
  532. LPCTSTR szProvValue;
  533. TCHAR szNumeric[36];
  534. //
  535. // Validate the request.
  536. //
  537. if (0 == *szCardName)
  538. throw (DWORD)SCARD_E_INVALID_VALUE;
  539. if (0 == *szProvider)
  540. throw (DWORD)SCARD_E_INVALID_VALUE;
  541. //
  542. // Find the Card definition.
  543. //
  544. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  545. {
  546. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  547. break;
  548. }
  549. if (l_dwRegMapMax == dwIndex)
  550. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  551. CRegistry regCardTypes(
  552. l_rgRegMap[dwIndex].hKey,
  553. SCARD_REG_CARDS,
  554. KEY_ALL_ACCESS);
  555. CRegistry regCard(
  556. regCardTypes,
  557. szCardName,
  558. KEY_ALL_ACCESS);
  559. regCard.Status();
  560. //
  561. // Derive the Provider Value Name.
  562. //
  563. if (dwProviderId < l_dwProvMapMax)
  564. {
  565. szProvValue = l_szrgProvMap[dwProviderId];
  566. if (NULL == szProvValue)
  567. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  568. }
  569. else if (0x80000000 <= dwProviderId)
  570. {
  571. _ultot(dwProviderId, szNumeric, 16);
  572. szProvValue = szNumeric;
  573. }
  574. else
  575. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  576. //
  577. // Write the provider value.
  578. //
  579. switch (dwProviderId)
  580. {
  581. case 1: // SCARD_PROVIDER_SSP
  582. {
  583. GUID guidProvider;
  584. GuidFromString(szProvider, &guidProvider);
  585. regCard.SetValue(szProvValue, (LPCBYTE)&guidProvider, sizeof(GUID));
  586. break;
  587. }
  588. default:
  589. regCard.SetValue(szProvValue, szProvider);
  590. }
  591. }
  592. /*++
  593. ForgetCard:
  594. This service provides means for removing previously defined smartcards from
  595. the Calais Subsystem.
  596. Arguments:
  597. dwScope supplies an indicator of the scope of the operation. Possible
  598. values are:
  599. SCARD_SCOPE_USER - The current user's definitions are used.
  600. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  601. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  602. For V1, SCARD_SCOPE_TERMINAL is not supported.
  603. szCardName supplies the friendly name of the card to be forgotten.
  604. Return Value:
  605. None
  606. Author:
  607. Doug Barlow (dbarlow) 10/23/1996
  608. --*/
  609. void
  610. ForgetCard(
  611. IN DWORD dwScope,
  612. IN LPCTSTR szCardName)
  613. {
  614. DWORD dwIndex;
  615. if (0 == *szCardName)
  616. throw (DWORD)SCARD_E_INVALID_VALUE;
  617. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  618. {
  619. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  620. break;
  621. }
  622. if (l_dwRegMapMax == dwIndex)
  623. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  624. CRegistry regCards(
  625. l_rgRegMap[dwIndex].hKey,
  626. SCARD_REG_CARDS,
  627. KEY_ALL_ACCESS);
  628. regCards.DeleteKey(szCardName);
  629. }
  630. #ifdef ENABLE_SCARD_TEMPLATES
  631. /*++
  632. IntroduceCardTypeTemplate:
  633. This service provides means for introducing a new smartcard template to the
  634. Calais Subsystem. A card tye template is a known card type that hasn't
  635. been formally introduced.
  636. Arguments:
  637. dwScope supplies an indicator of the scope of the operation. Possible
  638. values are:
  639. SCARD_SCOPE_USER - The current user's definitions are used.
  640. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  641. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  642. For V1, SCARD_SCOPE_USER and SCARD_SCOPE_TERMINAL is not supported.
  643. szVendorName supplies the manufacturer name by which this card should be
  644. recognized.
  645. PguidPrimaryProvider supplies a pointer to a GUID used to identify the
  646. Primary Service Provider for the card.
  647. rgguidInterfaces supplies an array of GUIDs identifying the smartcard
  648. interfaces supported by this card.
  649. dwInterfaceCount supplies the number of GUIDs in the pguidInterfaces array.
  650. pbAtr supplies a string against which card ATRs will be compared to
  651. determine a possible match for this card. The length of this string is
  652. determined by normal ATR parsing.
  653. pbAtrMask supplies an optional bitmask to use when comparing the ATRs of
  654. smartcards to the ATR supplied in pbAtr. If this value is non-NULL, it
  655. must point to a string of bytes the same length as the ATR string
  656. supplied in pbAtr. Then when a given ATR A is compared to the ATR
  657. supplied in pbAtr B, it matches if and only if A & M = B, where M is the
  658. supplied mask, and & represents bitwise logical AND.
  659. cbAtrLen supplies the length of the ATR and Mask. This value may be zero
  660. if the lentgh is obvious from the ATR. However, it may be required if
  661. there is a Mask value that obscures the actual ATR.
  662. Return Value:
  663. None
  664. Author:
  665. Doug Barlow (dbarlow) 1/16/1998
  666. --*/
  667. void
  668. IntroduceCardTypeTemplate(
  669. IN DWORD dwScope,
  670. IN LPCTSTR szVendorName,
  671. IN LPCGUID pguidPrimaryProvider,
  672. IN LPCGUID rgguidInterfaces,
  673. IN DWORD dwInterfaceCount,
  674. IN LPCBYTE pbAtr,
  675. IN LPCBYTE pbAtrMask,
  676. IN DWORD cbAtrLen)
  677. {
  678. DWORD dwIndex, dwReg, dwAtrLen;
  679. //
  680. // Verify the template name, so that it doesn't include any
  681. // disallowed characters.
  682. //
  683. if (NULL != _tcspbrk(szVendorName, l_szInvalidChars))
  684. throw (DWORD)SCARD_E_INVALID_VALUE;
  685. //
  686. // Translate the caller's scope.
  687. //
  688. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  689. {
  690. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  691. break;
  692. }
  693. if (l_dwRegMapMax == dwIndex)
  694. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  695. dwReg = dwIndex;
  696. if (NULL == pbAtrMask)
  697. {
  698. if (!ParseAtr(pbAtr, &dwAtrLen))
  699. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  700. if ((0 != cbAtrLen) && (dwAtrLen != cbAtrLen))
  701. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  702. }
  703. else
  704. {
  705. if ((2 > cbAtrLen) || (33 < cbAtrLen))
  706. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  707. for (dwIndex = 0; dwIndex < cbAtrLen; dwIndex += 1)
  708. {
  709. if (pbAtr[dwIndex] != (pbAtr[dwIndex] & pbAtrMask[dwIndex]))
  710. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  711. }
  712. dwAtrLen = cbAtrLen;
  713. }
  714. CRegistry regCards(
  715. l_rgRegMap[dwReg].hKey,
  716. SCARD_REG_TEMPLATES,
  717. KEY_ALL_ACCESS,
  718. REG_OPTION_NON_VOLATILE,
  719. NULL);
  720. CRegistry regCard(
  721. regCards,
  722. szVendorName,
  723. KEY_ALL_ACCESS,
  724. REG_OPTION_NON_VOLATILE,
  725. NULL); // Create it.
  726. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  727. throw (DWORD)ERROR_ALREADY_EXISTS;
  728. regCard.SetValue(
  729. SCARD_REG_ATR,
  730. pbAtr,
  731. dwAtrLen);
  732. if (NULL != pbAtrMask)
  733. regCard.SetValue(
  734. SCARD_REG_ATRMASK,
  735. pbAtrMask,
  736. dwAtrLen);
  737. if (NULL != pguidPrimaryProvider)
  738. regCard.SetValue(
  739. SCARD_REG_PPV,
  740. (LPBYTE)pguidPrimaryProvider,
  741. sizeof(GUID));
  742. if ((NULL != rgguidInterfaces) && (0 < dwInterfaceCount))
  743. regCard.SetValue(
  744. SCARD_REG_GUIDS,
  745. (LPBYTE)rgguidInterfaces,
  746. sizeof(GUID) * dwInterfaceCount);
  747. }
  748. /*++
  749. SetCardTypeTemplateProviderName:
  750. This routine sets the value of a given Provider Name, by Id number, for the
  751. identified card type template.
  752. Arguments:
  753. dwScope supplies an indicator of the scope of the operation. Possible
  754. values are:
  755. SCARD_SCOPE_USER - The current user's definitions are used.
  756. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  757. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  758. For V1, SCARD_SCOPE_TERMINAL and SCARD_SCOPE_USER are not supported.
  759. szTemplateName supplies the name of the card type template with which this
  760. provider name is to be associated.
  761. dwProviderId supplies the identifier for the provider to be associated with
  762. this card type template. Possible values are:
  763. SCARD_PROVIDER_SSP - The SSP identifier, as a GUID string.
  764. SCARD_PROVIDER_CSP - The CSP name.
  765. Other values < 0x80000000 are reserved for use by Microsoft. Values
  766. over 0x80000000 are available for use by the smart card vendors, and
  767. are card-specific.
  768. szProvider supplies the string identifying the provider.
  769. Return Value:
  770. None.
  771. Author:
  772. Doug Barlow (dbarlow) 1/19/1998
  773. --*/
  774. void
  775. SetCardTypeTemplateProviderName(
  776. IN DWORD dwScope,
  777. IN LPCTSTR szTemplateName,
  778. IN DWORD dwProviderId,
  779. IN LPCTSTR szProvider)
  780. {
  781. DWORD dwIndex;
  782. LPCTSTR szProvValue;
  783. TCHAR szNumeric[36];
  784. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  785. {
  786. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  787. break;
  788. }
  789. if (l_dwRegMapMax == dwIndex)
  790. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  791. //
  792. // Make sure the template exists.
  793. //
  794. CRegistry regTemplates(
  795. l_rgRegMap[dwIndex].hKey,
  796. SCARD_REG_TEMPLATES,
  797. KEY_ALL_ACCESS);
  798. CRegistry regTempl(
  799. regTemplates,
  800. szTemplateName,
  801. KEY_ALL_ACCESS);
  802. regTempl.Status();
  803. //
  804. // Derive the Provider Value Name.
  805. //
  806. if (dwProviderId < l_dwProvMapMax)
  807. {
  808. szProvValue = l_szrgProvMap[dwProviderId];
  809. if (NULL == szProvValue)
  810. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  811. }
  812. else if (0x80000000 <= dwProviderId)
  813. {
  814. _ultot(dwProviderId, szNumeric, 16);
  815. szProvValue = szNumeric;
  816. }
  817. else
  818. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  819. //
  820. // Write the provider value.
  821. //
  822. switch (dwProviderId)
  823. {
  824. case 1: // SCARD_PROVIDER_SSP
  825. {
  826. GUID guidProvider;
  827. GuidFromString(szProvider, &guidProvider);
  828. regTempl.SetValue(szProvValue, (LPCBYTE)&guidProvider, sizeof(GUID));
  829. break;
  830. }
  831. default:
  832. regTempl.SetValue(szProvValue, szProvider);
  833. }
  834. }
  835. /*++
  836. ForgetCardTypeTemplate:
  837. This service provides means for removing previously defined smart card type
  838. templates from the Calais Subsystem.
  839. Arguments:
  840. dwScope supplies an indicator of the scope of the operation. Possible
  841. values are:
  842. SCARD_SCOPE_USER - The current user's definitions are used.
  843. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  844. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  845. For V1, SCARD_SCOPE_USER and SCARD_SCOPE_TERMINAL are not supported.
  846. szVendorName supplies the manufacturer's name of the card to be forgotten.
  847. Return Value:
  848. None
  849. Author:
  850. Doug Barlow (dbarlow) 1/16/1998
  851. --*/
  852. void
  853. ForgetCardTypeTemplate(
  854. IN DWORD dwScope,
  855. IN LPCTSTR szVendorName)
  856. {
  857. DWORD dwIndex;
  858. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  859. {
  860. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  861. break;
  862. }
  863. if (l_dwRegMapMax == dwIndex)
  864. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  865. CRegistry regTemplates(
  866. l_rgRegMap[dwIndex].hKey,
  867. SCARD_REG_TEMPLATES,
  868. KEY_ALL_ACCESS);
  869. regTemplates.DeleteKey(szVendorName);
  870. }
  871. /*++
  872. IntroduceCardTypeFromTemplate:
  873. This service provides means for introducing new smartcards to the Calais
  874. Subsystem for the active user, based on a stored card template.
  875. Arguments:
  876. dwScope supplies an indicator of the scope of the operation. Possible
  877. values are:
  878. SCARD_SCOPE_USER - The current user's definitions are used.
  879. SCARD_SCOPE_TERMINAL - The terminal's definitions are used.
  880. SCARD_SCOPE_SYSTEM - The system's definitions are used.
  881. For V1, SCARD_SCOPE_TERMINAL is not supported.
  882. szVendorName supplies the vendor name by which this card type is known,
  883. identifying the template to use.
  884. szFriendlyName supplies the friendly name by which this card should be
  885. known. If this value is NULL, the vendor name is used as the friendly
  886. name,
  887. Return Value:
  888. None
  889. Author:
  890. Doug Barlow (dbarlow) 1/16/1998
  891. --*/
  892. void
  893. IntroduceCardTypeFromTemplate(
  894. IN DWORD dwScope,
  895. IN LPCTSTR szVendorName,
  896. IN LPCTSTR szFriendlyName /* = NULL */ )
  897. {
  898. DWORD dwIndex;
  899. HKEY hCardTypeKey;
  900. CRegistry regTemplates, regTmpl;
  901. //
  902. // Verify the reader name, so that it doesn't include any
  903. // disallowed characters.
  904. //
  905. if (NULL == szFriendlyName)
  906. szFriendlyName = szVendorName;
  907. else
  908. {
  909. if (NULL != _tcspbrk(szFriendlyName, l_szInvalidChars))
  910. throw (DWORD)SCARD_E_INVALID_VALUE;
  911. }
  912. //
  913. // Identify the card type scope.
  914. //
  915. for (dwIndex = 0; dwIndex < l_dwRegMapMax; dwIndex += 1)
  916. {
  917. if (l_rgRegMap[dwIndex].dwScope == dwScope)
  918. break;
  919. }
  920. if (l_dwRegMapMax == dwIndex)
  921. throw (DWORD)SCARD_E_INVALID_PARAMETER;
  922. hCardTypeKey = l_rgRegMap[dwIndex].hKey;
  923. //
  924. // Find the Template definition closest to the caller.
  925. //
  926. for (dwIndex = 0; l_dwRegMapMax > dwIndex; dwIndex += 1)
  927. {
  928. if (l_rgRegMap[dwIndex].dwScope >= dwScope)
  929. {
  930. regTemplates.Open(
  931. l_rgRegMap[dwIndex].hKey,
  932. SCARD_REG_TEMPLATES,
  933. KEY_READ);
  934. try
  935. {
  936. regTmpl.Open(regTemplates, szVendorName, KEY_READ);
  937. regTmpl.Status();
  938. break;
  939. }
  940. catch (...)
  941. {
  942. regTmpl.Close();
  943. }
  944. regTemplates.Close();
  945. }
  946. }
  947. if (l_dwRegMapMax <= dwIndex)
  948. throw (DWORD)ERROR_FILE_NOT_FOUND;
  949. //
  950. // Create the CardType Entry.
  951. //
  952. CRegistry regCards(
  953. hCardTypeKey,
  954. SCARD_REG_CARDS,
  955. KEY_ALL_ACCESS,
  956. REG_OPTION_NON_VOLATILE,
  957. NULL);
  958. CRegistry regCard(
  959. regCards,
  960. szFriendlyName,
  961. KEY_ALL_ACCESS,
  962. REG_OPTION_NON_VOLATILE,
  963. NULL); // Create it.
  964. if (REG_OPENED_EXISTING_KEY == regCard.GetDisposition())
  965. throw (DWORD)ERROR_ALREADY_EXISTS;
  966. //
  967. // Copy the entries.
  968. //
  969. regCard.Copy(regTmpl);
  970. }
  971. #endif // ENABLE_SCARD_TEMPLATES
  972. //
  973. ////////////////////////////////////////////////////////////////////////////////
  974. //
  975. // Support Routines
  976. //
  977. /*++
  978. GuidFromString:
  979. This routine converts a string representation of a GUID into an actual GUID.
  980. It tries not to be picky about the systax, as long as it can get a GUID out
  981. of the string. It's here so that it's not necessary to link all of OleBase
  982. into WinSCard. Otherwise, we'd just use CLSIDFromString.
  983. Arguments:
  984. szGuid supplies the GUID as a string. For this routine, a GUID consists of
  985. hex digits, and some collection of braces and dashes.
  986. pguidResult receives the converted GUID. If an error occurs during
  987. conversion, the contents of this parameter are indeterminant.
  988. Return Value:
  989. None
  990. Throws:
  991. Errors are thrown as DWORD status codes.
  992. Author:
  993. Doug Barlow (dbarlow) 1/20/1998
  994. --*/
  995. static void
  996. GuidFromString(
  997. IN LPCTSTR szGuid,
  998. OUT LPGUID pguidResult)
  999. {
  1000. // The following placement assumes Little Endianness.
  1001. static const WORD wPlace[sizeof(GUID)]
  1002. = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
  1003. DWORD dwI, dwJ;
  1004. LPCTSTR pch = szGuid;
  1005. LPBYTE pbGuid = (LPBYTE)pguidResult;
  1006. BYTE bVal;
  1007. for (dwI = 0; dwI < sizeof(GUID); dwI += 1)
  1008. {
  1009. bVal = 0;
  1010. for (dwJ = 0; dwJ < 2;)
  1011. {
  1012. switch (*pch)
  1013. {
  1014. case TEXT('0'):
  1015. case TEXT('1'):
  1016. case TEXT('2'):
  1017. case TEXT('3'):
  1018. case TEXT('4'):
  1019. case TEXT('5'):
  1020. case TEXT('6'):
  1021. case TEXT('7'):
  1022. case TEXT('8'):
  1023. case TEXT('9'):
  1024. bVal = (bVal << 4) + (*pch - TEXT('0'));
  1025. dwJ += 1;
  1026. break;
  1027. case TEXT('A'):
  1028. case TEXT('B'):
  1029. case TEXT('C'):
  1030. case TEXT('D'):
  1031. case TEXT('E'):
  1032. case TEXT('F'):
  1033. bVal = (bVal << 4) + (10 + *pch - TEXT('A'));
  1034. dwJ += 1;
  1035. break;
  1036. case TEXT('a'):
  1037. case TEXT('b'):
  1038. case TEXT('c'):
  1039. case TEXT('d'):
  1040. case TEXT('e'):
  1041. case TEXT('f'):
  1042. bVal = (bVal << 4) + (10 + *pch - TEXT('a'));
  1043. dwJ += 1;
  1044. break;
  1045. case TEXT('['):
  1046. case TEXT(']'):
  1047. case TEXT('{'):
  1048. case TEXT('}'):
  1049. case TEXT('-'):
  1050. break;
  1051. default:
  1052. throw (DWORD)SCARD_E_INVALID_VALUE;
  1053. }
  1054. pch += 1;
  1055. }
  1056. pbGuid[wPlace[dwI]] = bVal;
  1057. }
  1058. }