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.

1590 lines
43 KiB

  1. /****************************************************************************
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name: card.cpp
  4. Abstract: Calling Card Object implementation
  5. Author: noela - 09/11/98
  6. Notes:
  7. Rev History:
  8. ****************************************************************************/
  9. #include <windows.h>
  10. #include <windowsx.h>
  11. #if WINNT
  12. #else
  13. #include <help.h>
  14. #endif
  15. #include <tchar.h>
  16. #include <prsht.h>
  17. #include <stdlib.h>
  18. #include "tapi.h"
  19. #include "tspi.h"
  20. #include "utils.h"
  21. #include "cplResource.h"
  22. #include "client.h"
  23. #include "clntprivate.h"
  24. #include "card.h"
  25. #include "location.h"
  26. #include <shlwapi.h>
  27. #include <shlwapip.h>
  28. #include "rules.h"
  29. #include "tregupr2.h"
  30. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  31. #ifdef DBG
  32. #define assert(condition) if(condition);else \
  33. { DebugAssertFailure (__FILE__, __LINE__, #condition); }
  34. static void DebugAssertFailure (LPCSTR file, DWORD line, LPCSTR condition);
  35. #else
  36. #define assert(condition)
  37. #endif
  38. #define CLIENT_FREE(x) \
  39. if (x) { ClientFree(x); (x)=NULL;} else;
  40. #define TRACE_DWERROR() LOG((TL_ERROR, "Error %x at line %d in file %hs", dwError, __LINE__, __FILE__))
  41. #define TRACE_HRESULT() LOG((TL_ERROR, "Error %x at line %d in file %hs", Result, __LINE__, __FILE__))
  42. #define EXIT_IF_DWERROR() \
  43. if(dwError !=ERROR_SUCCESS) \
  44. { \
  45. TRACE_DWERROR(); \
  46. goto forced_exit; \
  47. }
  48. #define EXIT_IF_FAILED() \
  49. if(FAILED(Result)) \
  50. { \
  51. TRACE_HRESULT(); \
  52. goto forced_exit; \
  53. }
  54. #define MAX_NUMBER_LEN 15
  55. const TCHAR gszCardsPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards");
  56. const TCHAR gszTelephonyPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony");
  57. const TCHAR gszCardW[] = TEXT("Card");
  58. const TCHAR gszCardNameW[] = TEXT("Name");
  59. const TCHAR gszLocalRuleW[] = TEXT("LocalRule");
  60. const TCHAR gszLDRuleW[] = TEXT("LDRule");
  61. const TCHAR gszInternationalRuleW[] = TEXT("InternationalRule");
  62. const TCHAR gszLocalAccessNumberW[] = TEXT("LocalAccessNumber");
  63. const TCHAR gszLDAccessNumberW[] = TEXT("LDAccessNumber");
  64. const TCHAR gszInternationalAccessNumberW[] = TEXT("InternationalAccessNumber");
  65. const TCHAR gszAccountNumberW[] = TEXT("AccountNumber");
  66. const TCHAR gszPinW[] = TEXT("Pin");
  67. const TCHAR gszFlags[] = TEXT("Flags");
  68. const TCHAR gszCard[] = TEXT("Card");
  69. const TCHAR gszCards[] = TEXT("Cards");
  70. const TCHAR gszNextID[] = TEXT("NextID");
  71. const TCHAR gszCardListVersion[] = TEXT("CardListVersion");
  72. const TCHAR gszResourceLibrary[] = TEXT("TAPIUI.DLL");
  73. const TCHAR gszSystemSetupPath[] = TEXT("System\\Setup");
  74. const TCHAR gszSystemSetupInProgress[] = TEXT("SystemSetupInProgress");
  75. static BOOL ValidValue(PWSTR);
  76. /****************************************************************************
  77. Class : CCallingCard
  78. Method : Constructor
  79. ****************************************************************************/
  80. CCallingCard::CCallingCard()
  81. {
  82. m_dwCardID = 0;
  83. m_pszCardName = NULL;;
  84. m_pszPIN = NULL;
  85. m_pszEncryptedPIN = NULL;
  86. m_pszAccountNumber = NULL;
  87. m_pszLocalAccessNumber = NULL;
  88. m_pszLongDistanceAccessNumber = NULL;
  89. m_pszInternationalAccessNumber = NULL;
  90. m_pszCardPath = NULL;
  91. m_hCard = NULL;
  92. m_bDirty = FALSE;
  93. m_bDeleted = FALSE;
  94. m_dwFlags = 0; // by default
  95. m_dwCryptInitResult = TapiCryptInitialize();
  96. }
  97. /****************************************************************************
  98. Class : CCallingCard
  99. Method : Destructor
  100. ****************************************************************************/
  101. CCallingCard::~CCallingCard()
  102. {
  103. CleanUp();
  104. TapiCryptUninitialize();
  105. }
  106. /****************************************************************************
  107. Class : CCallingCard
  108. Method : CleanUp
  109. Clean up memory allocations
  110. ****************************************************************************/
  111. void CCallingCard::CleanUp(void)
  112. {
  113. CLIENT_FREE(m_pszCardName);
  114. CLIENT_FREE(m_pszPIN);
  115. CLIENT_FREE(m_pszEncryptedPIN);
  116. CLIENT_FREE(m_pszAccountNumber);
  117. CLIENT_FREE(m_pszLocalAccessNumber);
  118. CLIENT_FREE(m_pszLongDistanceAccessNumber);
  119. CLIENT_FREE(m_pszInternationalAccessNumber);
  120. CLIENT_FREE(m_Rules.m_pszInternationalRule);
  121. CLIENT_FREE(m_Rules.m_pszLongDistanceRule);
  122. CLIENT_FREE(m_Rules.m_pszLocalRule);
  123. CLIENT_FREE(m_pszCardPath);
  124. CloseCardKey();
  125. }
  126. /****************************************************************************
  127. Class : CCallingCard
  128. Method : Initialize - external parameters
  129. Only for new calling cards (not present in registry)
  130. ****************************************************************************/
  131. HRESULT CCallingCard::Initialize
  132. (
  133. DWORD dwCardID,
  134. PWSTR pszCardName,
  135. DWORD dwFlags,
  136. PWSTR pszPIN,
  137. PWSTR pszAccountNumber,
  138. PWSTR pszInternationalRule,
  139. PWSTR pszLongDistanceRule,
  140. PWSTR pszLocalRule,
  141. PWSTR pszInternationalAccessNumber,
  142. PWSTR pszLongDistanceAccessNumber,
  143. PWSTR pszLocalAccessNumber
  144. )
  145. {
  146. HRESULT Result = S_OK;
  147. #define CALLING_CARD_INIT(param) \
  148. m_##param = ClientAllocString(param); \
  149. if(m_##param == NULL) \
  150. { \
  151. LOG((TL_ERROR, "Initialize create m_%s failed", _T(#param))); \
  152. CleanUp(); \
  153. return E_OUTOFMEMORY; \
  154. }
  155. CALLING_CARD_INIT(pszCardName)
  156. CALLING_CARD_INIT(pszPIN)
  157. CALLING_CARD_INIT(pszAccountNumber)
  158. CALLING_CARD_INIT(pszInternationalAccessNumber)
  159. CALLING_CARD_INIT(pszLongDistanceAccessNumber)
  160. CALLING_CARD_INIT(pszLocalAccessNumber)
  161. #undef CALLING_CARD_INIT
  162. //////////////////////////////////////////////////
  163. // copy the set of three Rules
  164. //
  165. Result = m_Rules.Initialize( pszInternationalRule,
  166. pszLongDistanceRule,
  167. pszLocalRule );
  168. if(FAILED(Result))
  169. {
  170. LOG((TL_ERROR, "Initialize create m_Rules failed" ));
  171. CleanUp();
  172. return Result;
  173. }
  174. m_dwCardID = dwCardID;
  175. m_dwFlags = dwFlags;
  176. m_bDirty = TRUE;
  177. return Result;
  178. }
  179. /****************************************************************************
  180. Class : CCallingCard
  181. Method : Initialize - from registry
  182. ****************************************************************************/
  183. HRESULT CCallingCard::Initialize
  184. (
  185. DWORD dwCardID
  186. )
  187. {
  188. DWORD dwError;
  189. DWORD dwType;
  190. DWORD dwLength;
  191. m_dwCardID = dwCardID;
  192. // open the registry key
  193. dwError = OpenCardKey(FALSE);
  194. if(dwError != ERROR_SUCCESS)
  195. {
  196. // If the key does not exist, it will be created at the first save
  197. if(dwError==ERROR_FILE_NOT_FOUND)
  198. {
  199. m_bDirty = TRUE;
  200. }
  201. return(HRESULT_FROM_WIN32(dwError));
  202. }
  203. #define READ_CARD_VAL(Member, Name) \
  204. dwError = ReadOneStringValue(&##Member, Name); \
  205. if(dwError != ERROR_SUCCESS) \
  206. { \
  207. TRACE_DWERROR(); \
  208. CleanUp(); \
  209. return HRESULT_FROM_WIN32(dwError); \
  210. }
  211. READ_CARD_VAL(m_pszCardName, gszCardNameW);
  212. READ_CARD_VAL(m_pszEncryptedPIN, gszPinW);
  213. // READ_CARD_VAL(m_pszPIN, gszPinW);
  214. READ_CARD_VAL(m_pszAccountNumber, gszAccountNumberW);
  215. READ_CARD_VAL(m_pszLocalAccessNumber, gszLocalAccessNumberW);
  216. READ_CARD_VAL(m_pszLongDistanceAccessNumber, gszLDAccessNumberW);
  217. READ_CARD_VAL(m_pszInternationalAccessNumber, gszInternationalAccessNumberW);
  218. READ_CARD_VAL(m_Rules.m_pszLocalRule, gszLocalRuleW);
  219. READ_CARD_VAL(m_Rules.m_pszLongDistanceRule, gszLDRuleW);
  220. READ_CARD_VAL(m_Rules.m_pszInternationalRule, gszInternationalRuleW);
  221. #undef READ_CARD_VAL
  222. // Decrypt the PIN number
  223. dwError = DecryptPIN();
  224. if(dwError != ERROR_SUCCESS)
  225. {
  226. TRACE_DWERROR();
  227. CleanUp();
  228. return HRESULT_FACILITY(dwError)==0 ? HRESULT_FROM_WIN32(dwError) : dwError;
  229. }
  230. dwLength = sizeof(m_dwFlags);
  231. dwError = RegQueryValueEx ( m_hCard,
  232. gszFlags,
  233. NULL,
  234. &dwType,
  235. (PBYTE)&m_dwFlags,
  236. &dwLength
  237. );
  238. if(dwError != ERROR_SUCCESS)
  239. {
  240. TRACE_DWERROR();
  241. CleanUp();
  242. return HRESULT_FROM_WIN32(dwError);
  243. }
  244. CloseCardKey();
  245. return S_OK;
  246. }
  247. /****************************************************************************
  248. Class : CCallingCard
  249. Method : SaveToRegistry
  250. ****************************************************************************/
  251. HRESULT CCallingCard::SaveToRegistry(void)
  252. {
  253. DWORD dwError;
  254. if(!m_bDirty)
  255. // nothing to save
  256. return S_OK;
  257. //open/create the registry key
  258. dwError = OpenCardKey(TRUE);
  259. if(dwError != ERROR_SUCCESS)
  260. return HRESULT_FROM_WIN32(dwError);
  261. assert(m_hCard);
  262. assert(m_pszCardPath);
  263. if(m_bDeleted)
  264. {
  265. CloseCardKey();
  266. dwError = RegDeleteKey (HKEY_CURRENT_USER,
  267. m_pszCardPath);
  268. if(dwError != ERROR_SUCCESS)
  269. return HRESULT_FROM_WIN32(dwError);
  270. m_bDirty = FALSE;
  271. return S_OK;
  272. }
  273. // Encrypt the PIN number
  274. dwError = EncryptPIN();
  275. if(dwError != ERROR_SUCCESS)
  276. {
  277. TRACE_DWERROR();
  278. return HRESULT_FACILITY(dwError)==0 ? HRESULT_FROM_WIN32(dwError) : dwError;
  279. }
  280. // Save !
  281. #define CARD_SAVE_STRING(Member, Name) \
  282. dwError = TAPIRegSetValueExW( m_hCard, \
  283. Name, \
  284. 0, \
  285. REG_SZ, \
  286. (PBYTE) Member, \
  287. (wcslen(Member)+1)*sizeof(WCHAR) \
  288. ) ; \
  289. if(dwError != ERROR_SUCCESS) \
  290. { \
  291. TRACE_DWERROR(); \
  292. CloseCardKey(); \
  293. return HRESULT_FROM_WIN32(dwError); \
  294. }
  295. CARD_SAVE_STRING(m_pszCardName, gszCardNameW);
  296. CARD_SAVE_STRING(m_pszEncryptedPIN, gszPinW);
  297. CARD_SAVE_STRING(m_pszAccountNumber, gszAccountNumberW);
  298. CARD_SAVE_STRING(m_pszLocalAccessNumber, gszLocalAccessNumberW);
  299. CARD_SAVE_STRING(m_pszLongDistanceAccessNumber, gszLDAccessNumberW);
  300. CARD_SAVE_STRING(m_pszInternationalAccessNumber, gszInternationalAccessNumberW);
  301. CARD_SAVE_STRING(m_Rules.m_pszLocalRule, gszLocalRuleW);
  302. CARD_SAVE_STRING(m_Rules.m_pszLongDistanceRule, gszLDRuleW);
  303. CARD_SAVE_STRING(m_Rules.m_pszInternationalRule, gszInternationalRuleW);
  304. #undef CARD_SAVE_STRING
  305. dwError = RegSetValueEx ( m_hCard,
  306. gszFlags,
  307. 0,
  308. REG_DWORD,
  309. (PBYTE)&m_dwFlags,
  310. sizeof(m_dwFlags)
  311. );
  312. if(dwError != ERROR_SUCCESS)
  313. {
  314. TRACE_DWERROR();
  315. CloseCardKey();
  316. return HRESULT_FROM_WIN32(dwError);
  317. }
  318. m_bDirty = FALSE;
  319. CloseCardKey();
  320. return S_OK;
  321. }
  322. /****************************************************************************
  323. Class : CCallingCard
  324. Method : MarkDeleted
  325. Mark the card as deleted
  326. ****************************************************************************/
  327. HRESULT CCallingCard::MarkDeleted(void)
  328. {
  329. m_bDirty = TRUE;
  330. if (m_dwFlags & CARD_BUILTIN)
  331. {
  332. // a builtin card is only hidden, not deleted
  333. m_dwFlags |= CARD_HIDE;
  334. return S_OK;
  335. }
  336. m_bDeleted = TRUE;
  337. return S_OK;
  338. }
  339. /****************************************************************************
  340. Class : CCallingCard
  341. Method : Validate
  342. Returns 0 if the card contains complete and valid rules, or
  343. a series of flags if the card is missing any required data.
  344. ****************************************************************************/
  345. DWORD CCallingCard::Validate(void)
  346. {
  347. DWORD dwResult = 0;
  348. // Does the card have a name?
  349. if (!*m_pszCardName)
  350. {
  351. dwResult |= CCVF_NOCARDNAME;
  352. }
  353. // Does the card have any rules?
  354. if (!*(m_Rules.m_pszInternationalRule) &&
  355. !*(m_Rules.m_pszLocalRule) &&
  356. !*(m_Rules.m_pszLongDistanceRule) )
  357. {
  358. dwResult |= CCVF_NOCARDRULES;
  359. }
  360. else
  361. {
  362. DWORD dwFieldsToCheck = 0;;
  363. struct
  364. {
  365. PWSTR pwszRule;
  366. DWORD dwAccesFlag;
  367. }
  368. aData[] =
  369. {
  370. {m_Rules.m_pszInternationalRule, CCVF_NOINTERNATIONALACCESSNUMBER},
  371. {m_Rules.m_pszLocalRule, CCVF_NOLOCALACCESSNUMBER},
  372. {m_Rules.m_pszLongDistanceRule, CCVF_NOLONGDISTANCEACCESSNUMBER},
  373. };
  374. // Foreach rule, is the required rule data available? We need to check
  375. // for use of the PIN number, CardNumber, and all three access numbers.
  376. // If any of these fields is used, then we need to verify that data has
  377. // been entered for those fields. The data is only required if it is
  378. // actually used in a rule.
  379. for (int i=0; i<ARRAYSIZE(aData); i++)
  380. {
  381. if (StrChrW(aData[i].pwszRule, L'K'))
  382. {
  383. dwFieldsToCheck |= CCVF_NOCARDNUMBER;
  384. }
  385. if (StrChrW(aData[i].pwszRule, L'H'))
  386. {
  387. dwFieldsToCheck |= CCVF_NOPINNUMBER;
  388. }
  389. if (StrChrW(aData[i].pwszRule, L'J'))
  390. {
  391. dwFieldsToCheck |= aData[i].dwAccesFlag;
  392. }
  393. }
  394. if (dwFieldsToCheck & CCVF_NOCARDNUMBER)
  395. {
  396. if (!ValidValue(m_pszAccountNumber))
  397. {
  398. dwResult |= CCVF_NOCARDNUMBER;
  399. }
  400. }
  401. if (dwFieldsToCheck & CCVF_NOPINNUMBER)
  402. {
  403. if (!ValidValue(m_pszPIN))
  404. {
  405. dwResult |= CCVF_NOPINNUMBER;
  406. }
  407. }
  408. if (dwFieldsToCheck & CCVF_NOINTERNATIONALACCESSNUMBER)
  409. {
  410. if (!ValidValue(m_pszInternationalAccessNumber))
  411. {
  412. dwResult |= CCVF_NOINTERNATIONALACCESSNUMBER;
  413. }
  414. }
  415. if (dwFieldsToCheck & CCVF_NOLOCALACCESSNUMBER)
  416. {
  417. if (!ValidValue(m_pszLocalAccessNumber))
  418. {
  419. dwResult |= CCVF_NOLOCALACCESSNUMBER;
  420. }
  421. }
  422. if (dwFieldsToCheck & CCVF_NOLONGDISTANCEACCESSNUMBER)
  423. {
  424. if (!ValidValue(m_pszLongDistanceAccessNumber))
  425. {
  426. dwResult |= CCVF_NOLONGDISTANCEACCESSNUMBER;
  427. }
  428. }
  429. }
  430. return dwResult;
  431. }
  432. /****************************************************************************
  433. Class : CCallingCard
  434. Method : Set##Member
  435. ****************************************************************************/
  436. #define SET_METHOD(Member) \
  437. HRESULT CCallingCard::Set##Member(PWSTR Value) \
  438. { \
  439. PWSTR pszTemp = NULL; \
  440. \
  441. if(Value == NULL) \
  442. return E_INVALIDARG; \
  443. \
  444. pszTemp = ClientAllocString(Value); \
  445. if(pszTemp==NULL) \
  446. { \
  447. return E_OUTOFMEMORY; \
  448. } \
  449. \
  450. CLIENT_FREE(m_psz##Member); \
  451. m_psz##Member = pszTemp; \
  452. \
  453. m_bDirty = TRUE; \
  454. \
  455. return S_OK; \
  456. }
  457. SET_METHOD(CardName);
  458. SET_METHOD(PIN);
  459. SET_METHOD(AccountNumber);
  460. SET_METHOD(InternationalAccessNumber);
  461. SET_METHOD(LongDistanceAccessNumber);
  462. SET_METHOD(LocalAccessNumber);
  463. #define m_pszInternationalRule m_Rules.m_pszInternationalRule
  464. #define m_pszLongDistanceRule m_Rules.m_pszLongDistanceRule
  465. #define m_pszLocalRule m_Rules.m_pszLocalRule
  466. SET_METHOD(InternationalRule);
  467. SET_METHOD(LongDistanceRule);
  468. SET_METHOD(LocalRule);
  469. #undef m_pszInternationalRule
  470. #undef m_pszLongDistanceRule
  471. #undef m_pszLocalRule
  472. #undef SET_METHOD
  473. /****************************************************************************
  474. Class : CCallingCard
  475. Method : OpenCardKey
  476. Opens the registry key for the card
  477. ****************************************************************************/
  478. DWORD CCallingCard::OpenCardKey(BOOL bWrite)
  479. {
  480. DWORD dwDisp;
  481. DWORD dwError;
  482. if(m_pszCardPath==NULL)
  483. {
  484. DWORD dwLength;
  485. // Absolute path: Software.....Cards\CardX
  486. dwLength = ARRAYSIZE(gszCardsPath)+ARRAYSIZE(gszCard)+MAX_NUMBER_LEN;
  487. m_pszCardPath = (PTSTR)ClientAlloc(dwLength*sizeof(TCHAR));
  488. if (m_pszCardPath==NULL)
  489. return ERROR_OUTOFMEMORY;
  490. wsprintf(m_pszCardPath, TEXT("%s\\%s%d"), gszCardsPath, gszCard, m_dwCardID);
  491. }
  492. if(bWrite)
  493. {
  494. // Creates the key if it does not exist
  495. dwError = RegCreateKeyEx ( HKEY_CURRENT_USER,
  496. m_pszCardPath,
  497. 0,
  498. NULL,
  499. REG_OPTION_NON_VOLATILE,
  500. KEY_QUERY_VALUE | KEY_SET_VALUE,
  501. NULL,
  502. &m_hCard,
  503. &dwDisp
  504. );
  505. }
  506. else
  507. {
  508. dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
  509. m_pszCardPath,
  510. 0,
  511. KEY_QUERY_VALUE,
  512. &m_hCard
  513. );
  514. }
  515. return dwError;
  516. }
  517. /****************************************************************************
  518. Class : CCallingCard
  519. Method : CloseCardKey
  520. Opens the registry key for the card
  521. ****************************************************************************/
  522. DWORD CCallingCard::CloseCardKey(void)
  523. {
  524. if(m_hCard)
  525. {
  526. RegCloseKey(m_hCard);
  527. m_hCard = NULL;
  528. }
  529. return ERROR_SUCCESS;
  530. }
  531. /****************************************************************************
  532. Class : CCallingCard
  533. Method : ReadOneStringValue
  534. Read and allocates a string value
  535. ****************************************************************************/
  536. DWORD CCallingCard::ReadOneStringValue(PWSTR *pMember, const TCHAR *pszName)
  537. {
  538. DWORD dwError;
  539. DWORD dwLength;
  540. DWORD dwType;
  541. PTSTR pszBuffer;
  542. assert(m_hCard);
  543. assert(pMember);
  544. assert(pszName);
  545. // find the length needed
  546. dwError = RegQueryValueEx ( m_hCard,
  547. pszName,
  548. NULL,
  549. &dwType,
  550. NULL,
  551. &dwLength
  552. );
  553. if (dwError != ERROR_SUCCESS)
  554. return dwError;
  555. if (dwType != REG_SZ)
  556. return ERROR_INVALID_DATA;
  557. pszBuffer = (PTSTR)ClientAlloc(dwLength);
  558. if (pszBuffer == NULL)
  559. return ERROR_OUTOFMEMORY;
  560. dwError = RegQueryValueEx ( m_hCard,
  561. pszName,
  562. NULL,
  563. &dwType,
  564. (PBYTE)(pszBuffer),
  565. &dwLength
  566. );
  567. if(dwError != ERROR_SUCCESS)
  568. {
  569. ClientFree(pszBuffer);
  570. return dwError;
  571. }
  572. // convert the required bytes for the TCHAR string into the number of characters in the string.
  573. dwLength = dwLength / sizeof(TCHAR);
  574. *pMember = (PWSTR)ClientAlloc( dwLength * sizeof(WCHAR) );
  575. if ( NULL == *pMember )
  576. {
  577. ClientFree(pszBuffer);
  578. return ERROR_OUTOFMEMORY;
  579. }
  580. SHTCharToUnicode(pszBuffer, *pMember, dwLength);
  581. ClientFree(pszBuffer);
  582. return ERROR_SUCCESS;
  583. }
  584. /****************************************************************************
  585. Class : CCallingCard
  586. Method : EncryptPIN
  587. Encrypts the PIN
  588. ****************************************************************************/
  589. DWORD CCallingCard::EncryptPIN(void)
  590. {
  591. DWORD dwError;
  592. DWORD dwLength;
  593. PWSTR pszTemp = NULL;
  594. // free any existing encrypted string
  595. CLIENT_FREE(m_pszEncryptedPIN);
  596. dwError = TapiEncrypt(m_pszPIN, m_dwCardID, NULL, &dwLength);
  597. if(dwError != ERROR_SUCCESS)
  598. {
  599. LOG((TL_ERROR, "EncryptPIN: TapiEncrypt (1) failed"));
  600. return dwError;
  601. }
  602. pszTemp = (PWSTR)ClientAlloc(dwLength*sizeof(WCHAR));
  603. if(pszTemp==NULL)
  604. {
  605. return ERROR_OUTOFMEMORY;
  606. }
  607. dwError = TapiEncrypt(m_pszPIN, m_dwCardID, pszTemp, &dwLength);
  608. if(dwError != ERROR_SUCCESS)
  609. {
  610. LOG((TL_ERROR, "EncryptPIN: TapiEncrypt (2) failed"));
  611. ClientFree(pszTemp);
  612. return dwError;
  613. }
  614. m_pszEncryptedPIN = pszTemp;
  615. return dwError;
  616. }
  617. /****************************************************************************
  618. Class : CCallingCard
  619. Method : DecryptPIN
  620. Decrypts the PIN
  621. ****************************************************************************/
  622. DWORD CCallingCard::DecryptPIN(void)
  623. {
  624. DWORD dwError;
  625. DWORD dwLength;
  626. PWSTR pszTemp = NULL;
  627. // free any existing string
  628. CLIENT_FREE(m_pszPIN);
  629. dwError = TapiDecrypt(m_pszEncryptedPIN, m_dwCardID, NULL, &dwLength);
  630. if(dwError != ERROR_SUCCESS)
  631. {
  632. LOG((TL_ERROR, "DecryptPIN: TapiDecrypt (1) failed"));
  633. return dwError;
  634. }
  635. pszTemp = (PWSTR)ClientAlloc(dwLength*sizeof(WCHAR));
  636. if(pszTemp==NULL)
  637. {
  638. return ERROR_OUTOFMEMORY;
  639. }
  640. dwError = TapiDecrypt(m_pszEncryptedPIN, m_dwCardID, pszTemp, &dwLength);
  641. if(dwError != ERROR_SUCCESS)
  642. {
  643. LOG((TL_ERROR, "DecryptPIN: TapiDecrypt (2) failed"));
  644. // return a NULL PIN
  645. *pszTemp = L'\0';
  646. dwError = ERROR_SUCCESS;
  647. }
  648. m_pszPIN = pszTemp;
  649. return dwError;
  650. }
  651. /****************************************************************************
  652. Class : CCallingCards
  653. Method : Constructor
  654. ****************************************************************************/
  655. CCallingCards::CCallingCards()
  656. {
  657. m_dwNumEntries = 0;
  658. m_dwNextID = 0;
  659. m_hCards = NULL;
  660. m_hEnumNode = m_CallingCardList.head();
  661. }
  662. /****************************************************************************
  663. Class : CCallingCards
  664. Method : Destructor
  665. ****************************************************************************/
  666. CCallingCards::~CCallingCards()
  667. {
  668. CCallingCardNode *node;
  669. node = m_CallingCardList.head();
  670. while( !node->beyond_tail() )
  671. {
  672. delete node->value();
  673. node = node->next();
  674. }
  675. m_CallingCardList.flush();
  676. node = m_DeletedCallingCardList.head();
  677. while( !node->beyond_tail() )
  678. {
  679. delete node->value();
  680. node = node->next();
  681. }
  682. m_DeletedCallingCardList.flush();
  683. if(m_hCards)
  684. RegCloseKey(m_hCards);
  685. }
  686. /****************************************************************************
  687. Class : CCallingCards
  688. Method : Initialize
  689. Checks the presence of the Cards key. If not present, it creates
  690. and populates it from string resources.
  691. Verify the format of the registry config. If it is the old
  692. one, it converts it to the new one.
  693. Reads the cards from registry
  694. ****************************************************************************/
  695. HRESULT CCallingCards::Initialize(void)
  696. {
  697. DWORD dwError;
  698. DWORD dwDisp;
  699. BOOL bNewCards = FALSE;
  700. DWORD dwIndex;
  701. DWORD dwLength;
  702. DWORD dwType;
  703. CCallingCard *pCard = NULL;
  704. HRESULT Result = S_OK;
  705. BOOL bNeedToConvert = FALSE;
  706. BOOL bNeedToGenerateDefault = FALSE;
  707. // Test the presence of the Cards key
  708. dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
  709. gszCardsPath,
  710. 0,
  711. KEY_READ,
  712. &m_hCards
  713. );
  714. if(dwError==ERROR_SUCCESS)
  715. {
  716. // Read the NextID value
  717. dwLength = sizeof(m_dwNextID);
  718. dwError = RegQueryValueEx ( m_hCards,
  719. gszNextID,
  720. NULL,
  721. &dwType,
  722. (PBYTE)&m_dwNextID,
  723. &dwLength
  724. );
  725. if(dwError==ERROR_SUCCESS)
  726. {
  727. if(dwType == REG_DWORD)
  728. {
  729. // Test the registry format and upgrade if necessary
  730. if(IsCardListInOldFormat(m_hCards))
  731. {
  732. bNeedToConvert = TRUE;
  733. }
  734. }
  735. else
  736. {
  737. dwError = ERROR_INVALID_DATA;
  738. }
  739. }
  740. }
  741. if(dwError != ERROR_SUCCESS)
  742. bNeedToGenerateDefault = TRUE;
  743. if(bNeedToGenerateDefault || bNeedToConvert)
  744. {
  745. // If the Cards key is missing or it has bad info, so we create a fresh, default set of cards.
  746. // If the cards key is in the old format, it have to be converted.
  747. // There's an excepted case, though: during the system setup no cards should be created or converted.
  748. // So detect setup case first:
  749. //
  750. //
  751. HKEY hSetupKey;
  752. DWORD dwSetupValue;
  753. // close the cards key handle
  754. if(m_hCards)
  755. {
  756. RegCloseKey(m_hCards);
  757. m_hCards = NULL;
  758. }
  759. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  760. gszSystemSetupPath,
  761. 0,
  762. KEY_QUERY_VALUE,
  763. &hSetupKey
  764. );
  765. if(dwError == ERROR_SUCCESS)
  766. {
  767. dwLength = sizeof(dwSetupValue);
  768. dwSetupValue = 0;
  769. dwError = RegQueryValueEx( hSetupKey,
  770. gszSystemSetupInProgress,
  771. NULL,
  772. &dwType,
  773. (PBYTE)&dwSetupValue,
  774. &dwLength
  775. );
  776. RegCloseKey(hSetupKey);
  777. if(dwError == ERROR_SUCCESS && dwType == REG_DWORD)
  778. {
  779. if(dwSetupValue == 1)
  780. {
  781. // Setup time !
  782. dwError = ERROR_SUCCESS;
  783. goto forced_exit;
  784. }
  785. }
  786. }
  787. if(dwError != ERROR_SUCCESS)
  788. {
  789. // Hmm, cannot open the key or read the value...
  790. TRACE_DWERROR();
  791. }
  792. if(bNeedToConvert)
  793. {
  794. dwError = ConvertCallingCards(HKEY_CURRENT_USER);
  795. if(dwError!=ERROR_SUCCESS)
  796. {
  797. // fallback to default cards
  798. bNeedToGenerateDefault = TRUE;
  799. }
  800. }
  801. if(bNeedToGenerateDefault)
  802. {
  803. dwError = CreateFreshCards();
  804. EXIT_IF_DWERROR();
  805. }
  806. // Reopen Cards key
  807. dwError = RegOpenKeyEx( HKEY_CURRENT_USER,
  808. gszCardsPath,
  809. 0,
  810. KEY_READ,
  811. &m_hCards
  812. );
  813. EXIT_IF_DWERROR();
  814. // ReRead the NextID value
  815. dwLength = sizeof(m_dwNextID);
  816. dwError = RegQueryValueEx ( m_hCards,
  817. gszNextID,
  818. NULL,
  819. &dwType,
  820. (PBYTE)&m_dwNextID,
  821. &dwLength
  822. );
  823. EXIT_IF_DWERROR();
  824. }
  825. // Read all entries
  826. dwIndex = 0;
  827. while(TRUE)
  828. {
  829. TCHAR szKeyName[ARRAYSIZE(gszCard)+MAX_NUMBER_LEN];
  830. DWORD dwKeyLength;
  831. DWORD dwCardID;
  832. // Enumerate next entry
  833. dwKeyLength = sizeof(szKeyName)/sizeof(TCHAR);
  834. dwError = RegEnumKeyEx (m_hCards,
  835. dwIndex,
  836. szKeyName,
  837. &dwKeyLength,
  838. NULL,
  839. NULL,
  840. NULL,
  841. NULL
  842. );
  843. if(dwError == ERROR_NO_MORE_ITEMS)
  844. {
  845. m_dwNumEntries = dwIndex;
  846. dwError = ERROR_SUCCESS;
  847. break;
  848. }
  849. EXIT_IF_DWERROR();
  850. // Create a CCallingCard object
  851. dwCardID = StrToInt(szKeyName+ARRAYSIZE(gszCard)-1);
  852. pCard = new CCallingCard;
  853. if(pCard != NULL)
  854. {
  855. // Read the card information from registry
  856. Result = pCard->Initialize(dwCardID);
  857. if(SUCCEEDED(Result))
  858. {
  859. // Add it to the list
  860. m_CallingCardList.tail()->insert_after(pCard);
  861. }
  862. else
  863. {
  864. LOG((TL_ERROR, "Error %x reading card %d", Result, dwCardID));
  865. delete pCard;
  866. pCard=NULL;
  867. }
  868. }
  869. dwIndex++;
  870. }
  871. forced_exit:
  872. if(m_hCards)
  873. {
  874. RegCloseKey(m_hCards);
  875. m_hCards = NULL;
  876. }
  877. if(dwError != ERROR_SUCCESS)
  878. Result = HRESULT_FROM_WIN32(dwError);
  879. return Result;
  880. }
  881. /****************************************************************************
  882. Class : CCallingCards
  883. Method : RemoveCard
  884. ****************************************************************************/
  885. void CCallingCards::RemoveCard(CCallingCard *pCard)
  886. {
  887. CCallingCardNode *node = m_CallingCardList.head();
  888. while( !node->beyond_tail() )
  889. {
  890. if ( pCard == node->value() )
  891. {
  892. InternalDeleteCard(node);
  893. return;
  894. }
  895. node = node->next();
  896. }
  897. assert(FALSE);
  898. }
  899. /****************************************************************************
  900. Class : CCallingCards
  901. Method : RemoveCard
  902. ****************************************************************************/
  903. void CCallingCards::RemoveCard(DWORD dwID)
  904. {
  905. CCallingCardNode *node = m_CallingCardList.head();
  906. while( !node->beyond_tail() )
  907. {
  908. if ( dwID == (node->value())->GetCardID() )
  909. {
  910. InternalDeleteCard(node);
  911. return;
  912. }
  913. node = node->next();
  914. }
  915. assert(FALSE);
  916. }
  917. /****************************************************************************
  918. Class : CCallingCards
  919. Method : GetCallingCard
  920. ****************************************************************************/
  921. CCallingCard * CCallingCards::GetCallingCard(DWORD dwID)
  922. {
  923. CCallingCardNode *node = m_CallingCardList.head();
  924. while( !node->beyond_tail() )
  925. {
  926. if ( dwID == (node->value())->GetCardID() )
  927. {
  928. return node->value();
  929. }
  930. node = node->next();
  931. }
  932. return NULL;
  933. }
  934. /****************************************************************************
  935. Class : CCallingCards
  936. Method : SaveToRegistry
  937. ****************************************************************************/
  938. HRESULT CCallingCards::SaveToRegistry(void)
  939. {
  940. DWORD dwError = ERROR_SUCCESS;
  941. HRESULT Result = S_OK;
  942. CCallingCardNode *node;
  943. // Open the Cards key
  944. dwError = RegOpenKeyEx (HKEY_CURRENT_USER,
  945. gszCardsPath,
  946. 0,
  947. KEY_SET_VALUE,
  948. &m_hCards);
  949. EXIT_IF_DWERROR();
  950. //first - save the next ID
  951. dwError = RegSetValueEx ( m_hCards,
  952. gszNextID,
  953. 0,
  954. REG_DWORD,
  955. (PBYTE)&m_dwNextID,
  956. sizeof(m_dwNextID)
  957. );
  958. EXIT_IF_DWERROR();
  959. // save all cards (from both lists)
  960. node = m_CallingCardList.head();
  961. while( !node->beyond_tail() )
  962. {
  963. Result = node->value()->SaveToRegistry();
  964. EXIT_IF_FAILED();
  965. node = node->next();
  966. }
  967. node = m_DeletedCallingCardList.head();
  968. while( !node->beyond_tail() )
  969. {
  970. Result = node->value()->SaveToRegistry();
  971. EXIT_IF_FAILED();
  972. node = node->next();
  973. }
  974. forced_exit:
  975. if(m_hCards)
  976. {
  977. RegCloseKey(m_hCards);
  978. m_hCards = NULL;
  979. }
  980. if(dwError != ERROR_SUCCESS)
  981. Result = HRESULT_FROM_WIN32(dwError);
  982. return Result;
  983. }
  984. /****************************************************************************
  985. Class : CCallingCards
  986. Method : Reset
  987. ****************************************************************************/
  988. HRESULT CCallingCards::Reset(BOOL bInclHidden)
  989. {
  990. m_hEnumNode = m_CallingCardList.head();
  991. m_bEnumInclHidden = bInclHidden;
  992. return S_OK;
  993. }
  994. /****************************************************************************
  995. Class : CCallingCards
  996. Method : Next
  997. ****************************************************************************/
  998. HRESULT CCallingCards::Next(DWORD NrElem, CCallingCard **ppCard, DWORD *pNrElemFetched)
  999. {
  1000. DWORD dwIndex = 0;
  1001. if(pNrElemFetched == NULL && NrElem != 1)
  1002. return E_INVALIDARG;
  1003. if(ppCard==NULL)
  1004. return E_INVALIDARG;
  1005. while( !m_hEnumNode->beyond_tail() && dwIndex<NrElem )
  1006. {
  1007. CCallingCard *pCard;
  1008. pCard = m_hEnumNode->value();
  1009. if(m_bEnumInclHidden || !pCard->IsMarkedHidden())
  1010. {
  1011. *ppCard++ = pCard;
  1012. dwIndex++;
  1013. }
  1014. m_hEnumNode = m_hEnumNode->next();
  1015. }
  1016. if(pNrElemFetched!=NULL)
  1017. *pNrElemFetched = dwIndex;
  1018. return dwIndex<NrElem ? S_FALSE : S_OK;
  1019. }
  1020. /****************************************************************************
  1021. Class : CCallingCards
  1022. Method : Skip
  1023. ****************************************************************************/
  1024. HRESULT CCallingCards::Skip(DWORD NrElem)
  1025. {
  1026. DWORD dwIndex = 0;
  1027. while( !m_hEnumNode->beyond_tail() && dwIndex<NrElem )
  1028. {
  1029. if(m_bEnumInclHidden || !m_hEnumNode->value()->IsMarkedHidden())
  1030. {
  1031. dwIndex++;
  1032. }
  1033. m_hEnumNode = m_hEnumNode->next();
  1034. }
  1035. return dwIndex<NrElem ? S_FALSE : S_OK;
  1036. }
  1037. /****************************************************************************
  1038. Class : CCallingCards
  1039. Method : CreateFreshCards
  1040. ****************************************************************************/
  1041. DWORD CCallingCards::CreateFreshCards(void)
  1042. {
  1043. DWORD dwError = ERROR_SUCCESS;
  1044. HRESULT Result = S_OK;
  1045. HKEY hTelephony = NULL;
  1046. HINSTANCE hTapiui = NULL;
  1047. int iNrChars;
  1048. DWORD dwNumCards;
  1049. DWORD dwDisp;
  1050. DWORD dwIndex;
  1051. DWORD dwValue;
  1052. WCHAR wBuffer[512];
  1053. PWSTR pTemp;
  1054. CCallingCard *pCard = NULL;
  1055. // Open/Create the Telephony key
  1056. dwError = RegCreateKeyEx( HKEY_CURRENT_USER,
  1057. gszTelephonyPath,
  1058. 0,
  1059. NULL,
  1060. REG_OPTION_NON_VOLATILE,
  1061. KEY_WRITE,
  1062. NULL,
  1063. &hTelephony,
  1064. &dwDisp
  1065. );
  1066. EXIT_IF_DWERROR();
  1067. // Delete any existing tree
  1068. RegDeleteKeyRecursive( hTelephony, gszCards);
  1069. // Open/Create the Cards key
  1070. dwError = RegCreateKeyEx( hTelephony,
  1071. gszCards,
  1072. 0,
  1073. NULL,
  1074. REG_OPTION_NON_VOLATILE,
  1075. KEY_SET_VALUE | KEY_READ,
  1076. NULL,
  1077. &m_hCards,
  1078. &dwDisp
  1079. );
  1080. EXIT_IF_DWERROR();
  1081. // Write the version
  1082. dwValue = TAPI_CARD_LIST_VERSION;
  1083. dwError = RegSetValueEx ( m_hCards,
  1084. gszCardListVersion,
  1085. 0,
  1086. REG_DWORD,
  1087. (PBYTE)&dwValue,
  1088. sizeof(dwValue)
  1089. );
  1090. EXIT_IF_DWERROR();
  1091. // Load the TAPIUI.DLL resource library
  1092. hTapiui = LoadLibrary(gszResourceLibrary);
  1093. if(hTapiui==NULL)
  1094. dwError = GetLastError();
  1095. EXIT_IF_DWERROR();
  1096. // Load the number of cards. Use wBuffer as a temporary space
  1097. assert( MAX_NUMBER_LEN <= ARRAYSIZE(wBuffer) );
  1098. iNrChars = LoadString( hTapiui, RC_CARD_ID_BASE, (PTSTR)wBuffer, MAX_NUMBER_LEN);
  1099. if(iNrChars==0)
  1100. dwError = GetLastError();
  1101. EXIT_IF_DWERROR();
  1102. dwNumCards = StrToInt( (PTSTR)wBuffer );
  1103. //Read cards from string resources and write them to registry
  1104. for(dwIndex = 0; dwIndex<dwNumCards; dwIndex++)
  1105. {
  1106. PWSTR pszName;
  1107. PWSTR pszPin;
  1108. PWSTR pszLocalRule;
  1109. PWSTR pszLDRule;
  1110. PWSTR pszInternationalRule;
  1111. PWSTR pszAccountNumber;
  1112. PWSTR pszLocalAccessNumber;
  1113. PWSTR pszLDAccessNumber;
  1114. PWSTR pszInternationalAccessNumber;
  1115. DWORD dwFlags;
  1116. // read the card description
  1117. iNrChars = TAPILoadStringW( hTapiui,
  1118. RC_CARD_ID_BASE + dwIndex + 1,
  1119. wBuffer,
  1120. ARRAYSIZE(wBuffer)
  1121. );
  1122. if(iNrChars==0)
  1123. dwError = GetLastError();
  1124. EXIT_IF_DWERROR();
  1125. // tokenize it
  1126. #define TOKENIZE(Pointer) \
  1127. Pointer = (wcschr(pTemp+1, L'"'))+1; \
  1128. pTemp = wcschr(Pointer, L'"'); \
  1129. *pTemp = L'\0';
  1130. pTemp = wBuffer-1;
  1131. TOKENIZE(pszName);
  1132. TOKENIZE(pszPin);
  1133. TOKENIZE(pszLocalRule);
  1134. TOKENIZE(pszLDRule);
  1135. TOKENIZE(pszInternationalRule);
  1136. TOKENIZE(pszAccountNumber);
  1137. TOKENIZE(pszLocalAccessNumber);
  1138. TOKENIZE(pszLDAccessNumber);
  1139. TOKENIZE(pszInternationalAccessNumber);
  1140. #undef TOKENIZE
  1141. // don't forget the flags
  1142. dwFlags = _wtoi(pTemp+2);
  1143. // create the card object
  1144. pCard = new CCallingCard();
  1145. if(pCard==NULL)
  1146. dwError = ERROR_OUTOFMEMORY;
  1147. EXIT_IF_DWERROR();
  1148. Result = pCard->Initialize( dwIndex,
  1149. pszName,
  1150. dwFlags,
  1151. pszPin,
  1152. pszAccountNumber,
  1153. pszInternationalRule,
  1154. pszLDRule,
  1155. pszLocalRule,
  1156. pszInternationalAccessNumber,
  1157. pszLDAccessNumber,
  1158. pszLocalAccessNumber
  1159. );
  1160. EXIT_IF_FAILED();
  1161. // save it
  1162. Result = pCard->SaveToRegistry();
  1163. EXIT_IF_FAILED();
  1164. delete pCard;
  1165. pCard = NULL;
  1166. }
  1167. // Write NextID value
  1168. dwError = RegSetValueEx ( m_hCards,
  1169. gszNextID,
  1170. 0,
  1171. REG_DWORD,
  1172. (PBYTE)&dwNumCards,
  1173. sizeof(dwNumCards)
  1174. );
  1175. EXIT_IF_DWERROR();
  1176. forced_exit:
  1177. if(hTelephony)
  1178. RegCloseKey(hTelephony);
  1179. if(m_hCards)
  1180. {
  1181. RegCloseKey(m_hCards);
  1182. m_hCards = NULL;
  1183. }
  1184. if(pCard)
  1185. delete pCard;
  1186. if(hTapiui)
  1187. FreeLibrary(hTapiui);
  1188. if(FAILED(Result))
  1189. dwError = HRESULT_CODE(Result);
  1190. return dwError;
  1191. }
  1192. /****************************************************************************
  1193. Class : CCallingCards
  1194. Method : InternalDeleteCard
  1195. ****************************************************************************/
  1196. void CCallingCards::InternalDeleteCard(CCallingCardNode *pNode)
  1197. {
  1198. CCallingCard *pCard = pNode->value();
  1199. pCard->MarkDeleted();
  1200. if(!pCard->IsMarkedHidden())
  1201. {
  1202. pNode->remove();
  1203. m_dwNumEntries--;
  1204. m_DeletedCallingCardList.tail()->insert_after(pCard);
  1205. }
  1206. }
  1207. /****************************************************************************
  1208. Helpers
  1209. ****************************************************************************/
  1210. BOOL ValidValue(PWSTR pwszString)
  1211. {
  1212. // An empty string or with spaces only is not valid
  1213. WCHAR const * pwcCrt = pwszString;
  1214. while(*pwcCrt)
  1215. if(*pwcCrt++ != L' ')
  1216. return TRUE;
  1217. return FALSE;
  1218. }
  1219. #ifdef DBG
  1220. static void DebugAssertFailure (LPCSTR file, DWORD line, LPCSTR condition)
  1221. {
  1222. DbgPrt (0, TEXT("%hs(%d) : Assertion failed, condition: %hs\n"), file, line, condition);
  1223. DebugBreak();
  1224. }
  1225. #endif