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.

1951 lines
59 KiB

  1. /****************************************************************************
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name: tregupr2.c
  4. Abstract: Upgrades the telephony registry settings to the post NT5b2 format
  5. Author: radus - 09/11/98
  6. Notes: stolen from \Nt\Private\tapi\dev\apps\tapiupr\tapiupr.c
  7. Rev History:
  8. ****************************************************************************/
  9. #define STRICT
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <tchar.h>
  13. #include <stdlib.h>
  14. // from the old version of loc_comn.h
  15. #define MAXLEN_AREACODE 16
  16. #define OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE 0x00000008
  17. //
  18. #include "tregupr2.h"
  19. #include "debug.h"
  20. #define BACKUP_OLD_KEYS
  21. #define BACKUP_FILE_LOCATIONS _T("REGLOCS.OLD")
  22. #define BACKUP_FILE_USER_LOCATIONS _T("REGULOCS.OLD")
  23. #define BACKUP_FILE_CARDS _T("REGCARDS.OLD")
  24. #define AREACODERULE_INCLUDEALLPREFIXES 0x00000001
  25. #define AREACODERULE_DIALAREACODE 0x00000002
  26. #define AREACODERULE_DIALNUMBERTODIAL 0x00000004
  27. #define US_COUNTRY_CODE(x) ((x) == 1 || \
  28. (x >= 100 && x < 200))
  29. #define MAXLEN_NUMBER_LEN 12
  30. #define MAXLEN_RULE 128
  31. #define MAXLEN_ACCESS_NUMBER 128
  32. #define MAXLEN_PIN 128
  33. #define TEMPORARY_ID_FLAG 0x80000000
  34. #define PRIVATE static
  35. PRIVATE DWORD ConvertOneLocation( HKEY hLocation);
  36. PRIVATE DWORD CreateAreaCodeRule( HKEY hParent,
  37. int iRuleNumber,
  38. LPCTSTR pszAreaCodeToCall,
  39. LPCTSTR pszNumberToDial,
  40. LPBYTE pbPrefixes,
  41. DWORD dwPrefixesLength,
  42. DWORD dwFlags
  43. );
  44. PRIVATE DWORD ConvertOneCard(HKEY hCard, DWORD);
  45. PRIVATE DWORD ConvertPIN(HKEY hCard, DWORD);
  46. PRIVATE BOOL IsTelephonyDigit(TCHAR );
  47. PRIVATE DWORD SplitCallingCardRule(HKEY hCard, LPCTSTR pszRuleName, LPCTSTR pszAccessNumberName);
  48. PRIVATE DWORD RegRenameKey( HKEY hParentKey,
  49. LPCTSTR pszOldName,
  50. LPCTSTR pszNewName);
  51. PRIVATE DWORD RegCopyKeyRecursive(HKEY hSrcParentKey, LPCTSTR pszSrcName,
  52. HKEY hDestParentKey, LPCTSTR pszDestName);
  53. #ifdef BACKUP_OLD_KEYS
  54. #ifdef WINNT
  55. PRIVATE
  56. BOOL
  57. EnablePrivilege(
  58. PTSTR PrivilegeName,
  59. BOOL Enable,
  60. BOOL *Old
  61. );
  62. #endif // WINNT
  63. PRIVATE
  64. BOOL
  65. SaveKey(
  66. HKEY hKey,
  67. LPCTSTR pszFileName
  68. );
  69. #endif // BACKUP_OLD_KEYS
  70. PRIVATE const TCHAR gszName[] = _T("Name");
  71. PRIVATE const TCHAR gszID[] = _T("ID");
  72. PRIVATE const TCHAR gszAreaCode[] = _T("AreaCode");
  73. PRIVATE const TCHAR gszAreaCodeRules[] = _T("AreaCodeRules");
  74. PRIVATE const TCHAR gszCountry[] = _T("Country");
  75. PRIVATE const TCHAR gszFlags[] = _T("Flags");
  76. PRIVATE const TCHAR gszDisableCallWaiting[] = _T("DisableCallWaiting");
  77. PRIVATE const TCHAR gszTollList[] = _T("TollList");
  78. PRIVATE const TCHAR gszNoPrefAC[] = _T("NoPrefAC");
  79. PRIVATE const TCHAR gszPrefixes[] = _T("Prefixes");
  80. PRIVATE const TCHAR gszRules[] = _T("Rules");
  81. PRIVATE const TCHAR gszRule[] = _T("Rule");
  82. PRIVATE const TCHAR gszAreaCodeToCall[] = _T("AreaCodeToCall");
  83. PRIVATE const TCHAR gszNumberToDial[] = _T("NumberToDial");
  84. PRIVATE const TCHAR gszCard[] = _T("Card");
  85. PRIVATE const TCHAR gszCards[] = _T("Cards");
  86. PRIVATE const TCHAR gszLocalRule[] = _T("LocalRule");
  87. PRIVATE const TCHAR gszLDRule[] = _T("LDRule");
  88. PRIVATE const TCHAR gszInternationalRule[] = _T("InternationalRule");
  89. PRIVATE const TCHAR gszLocalAccessNumber[] = _T("LocalAccessNumber");
  90. PRIVATE const TCHAR gszLDAccessNumber[] = _T("LDAccessNumber");
  91. PRIVATE const TCHAR gszInternationalAccessNumber[] = _T("InternationalAccessNumber");
  92. PRIVATE const TCHAR gszAccountNumber[] = _T("AccountNumber");
  93. PRIVATE const WCHAR gwszPIN[] = L"PIN";
  94. PRIVATE const TCHAR gszNumEntries[] = _T("NumEntries");
  95. PRIVATE const TCHAR gszEmpty[] = _T("");
  96. PRIVATE const TCHAR gszMultiEmpty[] = _T("\0");
  97. PRIVATE const TCHAR gszLocations[] = _T("Locations");
  98. PRIVATE const TCHAR gszLocation[] = _T("Location");
  99. PRIVATE const TCHAR gszLocationsPath[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations");
  100. PRIVATE const TCHAR gszCardsPath[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards");
  101. PRIVATE const TCHAR gszUSLDSpecifier[] = _T("1");
  102. PRIVATE const TCHAR gszLocationListVersion[] = _T("LocationListVersion");
  103. PRIVATE const TCHAR gszCardListVersion[] = _T("CardListVersion");
  104. PRIVATE const TCHAR gszKeyRenameHistory[] = _T("KeyRenameHistory");
  105. #pragma check_stack ( off )
  106. //***************************************************************************
  107. //***************************************************************************
  108. //***************************************************************************
  109. //
  110. // ConvertLocations - convert the telephony locations to the new format.
  111. // see nt\private\tapi\dev\docs\dialrules.doc
  112. //
  113. DWORD ConvertLocations(void)
  114. {
  115. TCHAR Location[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  116. TCHAR NewLocation[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  117. DWORD dwError = ERROR_SUCCESS;
  118. HKEY hLocations = NULL;
  119. HKEY hLocation = NULL;
  120. DWORD dwNumEntries;
  121. DWORD dwCount;
  122. DWORD dwRenameEntryCount;
  123. DWORD dwCountPhase1;
  124. DWORD dwLength;
  125. DWORD dwType;
  126. DWORD dwLocationID;
  127. DWORD dwLocationIDTmp;
  128. DWORD dwValue;
  129. PDWORD pdwRenameList = NULL;
  130. PDWORD pdwRenameEntry;
  131. PDWORD pdwRenameEntryPhase1;
  132. #ifdef BACKUP_OLD_KEYS
  133. TCHAR szPath[MAX_PATH+1];
  134. #endif
  135. DBGOUT((9, "ConvertLocations - Enter"));
  136. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  137. gszLocationsPath,
  138. 0,
  139. KEY_READ | KEY_WRITE,
  140. &hLocations
  141. );
  142. if(dwError == ERROR_FILE_NOT_FOUND)
  143. {
  144. DBGOUT((1, "Locations key not present, so there's nothing to convert"));
  145. //Nothing to convert
  146. return ERROR_SUCCESS;
  147. }
  148. EXIT_IF_DWERROR();
  149. // Version check
  150. if(!IsLocationListInOldFormat(hLocations))
  151. {
  152. //Nothing to convert
  153. DBGOUT((1, "Locations key is already in the new format"));
  154. RegCloseKey(hLocations);
  155. return ERROR_SUCCESS;
  156. }
  157. #ifdef BACKUP_OLD_KEYS
  158. // Try to save the old key
  159. dwError = GetWindowsDirectory(szPath, MAX_PATH - 12); // a 8+3 name
  160. if(dwError)
  161. {
  162. if(szPath[3] != _T('\0'))
  163. lstrcat(szPath, _T("\\"));
  164. lstrcat(szPath, BACKUP_FILE_LOCATIONS);
  165. SaveKey(hLocations, szPath);
  166. }
  167. else
  168. DBGOUT((1, "Cannot get windows directory (?!?)"));
  169. dwError = ERROR_SUCCESS;
  170. #endif
  171. // Read number of entries
  172. dwLength = sizeof(dwNumEntries);
  173. dwError = RegQueryValueEx( hLocations,
  174. gszNumEntries,
  175. NULL,
  176. &dwType,
  177. (BYTE *)&dwNumEntries,
  178. &dwLength
  179. );
  180. if(dwError==ERROR_SUCCESS && dwType != REG_DWORD)
  181. {
  182. dwError = ERROR_INVALID_DATA;
  183. assert(FALSE);
  184. }
  185. // The value could be missing in an empty key
  186. if(dwError != ERROR_SUCCESS)
  187. dwNumEntries = 0;
  188. // Alloc a rename list for the worst case (all key to be renamed using temporary IDs)
  189. if(dwNumEntries>0)
  190. {
  191. pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwNumEntries*4*sizeof(DWORD) );
  192. if(pdwRenameList==NULL)
  193. {
  194. DBGOUT((1, "Cannot allocate the Rename List"));
  195. dwError = ERROR_OUTOFMEMORY;
  196. goto forced_exit;
  197. }
  198. }
  199. pdwRenameEntry = pdwRenameList;
  200. dwRenameEntryCount = 0;
  201. // Convert from end to the begining in order to avoid name conflicts during the key renames
  202. for(dwCount = dwNumEntries-1; (LONG)dwCount>=0; dwCount--)
  203. {
  204. wsprintf(Location, _T("%s%d"), gszLocation, dwCount);
  205. dwError = RegOpenKeyEx( hLocations,
  206. Location,
  207. 0,
  208. KEY_READ | KEY_WRITE,
  209. &hLocation
  210. );
  211. if(dwError == ERROR_FILE_NOT_FOUND)
  212. {
  213. DBGOUT((1, "Cannot open old %s", Location));
  214. // Try to recover - skip to the next entry
  215. continue;
  216. }
  217. EXIT_IF_DWERROR();
  218. // Read the ID for later usage
  219. dwLength = sizeof(dwLocationID);
  220. dwError = RegQueryValueEx( hLocation,
  221. gszID,
  222. NULL,
  223. &dwType,
  224. (LPBYTE)&dwLocationID,
  225. &dwLength
  226. );
  227. if(dwError == ERROR_SUCCESS)
  228. {
  229. // Convert the location to the new format
  230. dwError = ConvertOneLocation(hLocation);
  231. if(dwError != ERROR_SUCCESS)
  232. {
  233. DBGOUT((1, "%s conversion failed with error %d. Trying to continue...", Location, dwError));
  234. }
  235. RegCloseKey(hLocation);
  236. hLocation = NULL;
  237. // Rename the key if it is necessary
  238. if(dwLocationID != dwCount)
  239. {
  240. wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationID);
  241. // Check the destination for an old key still present. It may be possible to find one if
  242. // the original TAPI version was TELEPHON.INI-based.
  243. assert(!(dwLocationID & TEMPORARY_ID_FLAG));
  244. dwLocationIDTmp = dwLocationID;
  245. dwError = RegOpenKeyEx( hLocations,
  246. NewLocation,
  247. 0,
  248. KEY_READ,
  249. &hLocation
  250. );
  251. if(dwError==ERROR_SUCCESS)
  252. {
  253. // use a temporary ID
  254. dwLocationIDTmp |= TEMPORARY_ID_FLAG;
  255. wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationIDTmp);
  256. }
  257. if(hLocation)
  258. {
  259. RegCloseKey(hLocation);
  260. hLocation = NULL;
  261. }
  262. dwError = RegRenameKey( hLocations,
  263. Location,
  264. NewLocation
  265. );
  266. EXIT_IF_DWERROR();
  267. // trace the rename. It will be useful when we try to upgrade the HKEY_CURRENT_USER/../Locations key
  268. *pdwRenameEntry++ = dwCount;
  269. *pdwRenameEntry++ = dwLocationIDTmp;
  270. dwRenameEntryCount++;
  271. }
  272. DBGOUT ((9, "Converted location %d (ID %d)", dwCount, dwLocationID));
  273. }
  274. }
  275. dwError = ERROR_SUCCESS;
  276. // Rewalk the list for renaming the keys with temporary IDs
  277. pdwRenameEntryPhase1 = pdwRenameList;
  278. dwCountPhase1 = dwRenameEntryCount;
  279. for(dwCount=0; dwCount<dwCountPhase1; dwCount++)
  280. {
  281. pdwRenameEntryPhase1++;
  282. dwLocationIDTmp = *pdwRenameEntryPhase1++;
  283. if(dwLocationIDTmp & TEMPORARY_ID_FLAG)
  284. {
  285. wsprintf(Location, _T("%s%d"), gszLocation, dwLocationIDTmp);
  286. dwLocationID = dwLocationIDTmp & ~TEMPORARY_ID_FLAG;
  287. wsprintf(NewLocation, _T("%s%d"), gszLocation, dwLocationID);
  288. dwError = RegRenameKey( hLocations,
  289. Location,
  290. NewLocation
  291. );
  292. EXIT_IF_DWERROR();
  293. *pdwRenameEntry++ = dwLocationIDTmp;
  294. *pdwRenameEntry++ = dwLocationID;
  295. dwRenameEntryCount++;
  296. DBGOUT ((9, "Renamed to permanent ID %d", dwLocationID));
  297. }
  298. }
  299. // delete the DisableCallWaiting value
  300. RegDeleteValue( hLocations,
  301. gszDisableCallWaiting
  302. );
  303. // delete the NumEntries value. We don't need it any more
  304. RegDeleteValue( hLocations,
  305. gszNumEntries);
  306. // add the rename history
  307. dwError = RegSetValueEx( hLocations,
  308. gszKeyRenameHistory,
  309. 0,
  310. REG_BINARY,
  311. (PBYTE)pdwRenameList,
  312. dwRenameEntryCount*2*sizeof(DWORD)
  313. );
  314. EXIT_IF_DWERROR();
  315. // add the versioning value
  316. dwValue = TAPI_LOCATION_LIST_VERSION;
  317. dwError = RegSetValueEx( hLocations,
  318. gszLocationListVersion,
  319. 0,
  320. REG_DWORD,
  321. (PBYTE)&dwValue,
  322. sizeof(dwValue)
  323. );
  324. EXIT_IF_DWERROR();
  325. forced_exit:
  326. if(hLocation)
  327. RegCloseKey(hLocation);
  328. if(hLocations)
  329. RegCloseKey(hLocations);
  330. if(pdwRenameList)
  331. GlobalFree(pdwRenameList);
  332. DBGOUT((9, "ConvertLocations - Exit %xh", dwError));
  333. return dwError;
  334. }
  335. //***************************************************************************
  336. //
  337. // ConvertOneLocation - convert one location
  338. // hLocation is the handle of the LocationX key
  339. // Note The key rename according to location ID is executed in ConvertLocations
  340. PRIVATE DWORD ConvertOneLocation( HKEY hLocation)
  341. {
  342. DWORD dwError = ERROR_SUCCESS;
  343. LPTSTR pTollList = NULL;
  344. LPBYTE pNoPrefAC = NULL;
  345. TCHAR *pCrt;
  346. TCHAR AreaCode[MAXLEN_AREACODE];
  347. DWORD dwFlags;
  348. DWORD dwCountryID;
  349. DWORD dwType;
  350. DWORD dwLength;
  351. DWORD dwTollListLength;
  352. DWORD dwDisp;
  353. HKEY hAreaCodeRules = NULL;
  354. int iRuleNumber;
  355. DBGOUT((9, "ConvertOneLocation - Enter"));
  356. assert(hLocation);
  357. // Read the current location flags
  358. dwLength = sizeof(dwFlags);
  359. dwError = RegQueryValueEx( hLocation,
  360. gszFlags,
  361. NULL,
  362. &dwType,
  363. (BYTE *)&dwFlags,
  364. &dwLength
  365. );
  366. if(dwError==ERROR_SUCCESS && dwType != REG_DWORD)
  367. {
  368. dwError=ERROR_INVALID_DATA;
  369. assert(FALSE);
  370. }
  371. EXIT_IF_DWERROR();
  372. //Read the current Area Code
  373. dwLength = sizeof(AreaCode);
  374. dwError = RegQueryValueEx( hLocation,
  375. gszAreaCode,
  376. NULL,
  377. &dwType,
  378. (BYTE *)AreaCode,
  379. &dwLength
  380. );
  381. if(dwError==ERROR_SUCCESS && dwType != REG_SZ)
  382. {
  383. dwError=ERROR_INVALID_DATA;
  384. assert(FALSE);
  385. }
  386. EXIT_IF_DWERROR();
  387. //Read the current Country ID
  388. dwLength = sizeof(dwCountryID);
  389. dwError = RegQueryValueEx( hLocation,
  390. gszCountry,
  391. NULL,
  392. &dwType,
  393. (BYTE *)&dwCountryID,
  394. &dwLength
  395. );
  396. if(dwError==ERROR_SUCCESS && dwType != REG_DWORD)
  397. {
  398. dwError=ERROR_INVALID_DATA;
  399. assert(FALSE);
  400. }
  401. EXIT_IF_DWERROR();
  402. // create the AreaCodeRules subkey
  403. dwError = RegCreateKeyEx( hLocation,
  404. gszAreaCodeRules,
  405. 0,
  406. NULL,
  407. REG_OPTION_NON_VOLATILE,
  408. KEY_WRITE,
  409. NULL,
  410. &hAreaCodeRules,
  411. &dwDisp
  412. );
  413. if(dwError==ERROR_SUCCESS && dwDisp != REG_CREATED_NEW_KEY)
  414. {
  415. dwError=ERROR_INVALID_DATA;
  416. assert(FALSE);
  417. }
  418. EXIT_IF_DWERROR();
  419. iRuleNumber = 0;
  420. // Create a rule for "Always Include Area Code" flag..
  421. if(dwFlags & OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE)
  422. {
  423. dwError = CreateAreaCodeRule( hAreaCodeRules,
  424. iRuleNumber++,
  425. AreaCode,
  426. gszEmpty,
  427. (LPBYTE)gszMultiEmpty,
  428. sizeof(gszMultiEmpty),
  429. AREACODERULE_DIALAREACODE | AREACODERULE_INCLUDEALLPREFIXES
  430. );
  431. EXIT_IF_DWERROR();
  432. // update the location flag
  433. dwFlags &= ~OLDFLAG_LOCATION_ALWAYSINCLUDEAREACODE;
  434. dwLength = sizeof(dwFlags);
  435. dwError = RegSetValueEx( hLocation,
  436. gszFlags,
  437. 0,
  438. REG_DWORD,
  439. (CONST BYTE *)&dwFlags,
  440. dwLength
  441. );
  442. EXIT_IF_DWERROR();
  443. }
  444. // The TollList and NoPrefAC were valid only in countries with Country=1 (US, Canada)
  445. // Ignore them if other country
  446. if(US_COUNTRY_CODE(dwCountryID))
  447. {
  448. // Translate TollList
  449. // Length...
  450. dwError = RegQueryValueEx( hLocation,
  451. gszTollList,
  452. NULL,
  453. NULL,
  454. NULL,
  455. &dwTollListLength);
  456. if(dwError == ERROR_SUCCESS)
  457. {
  458. pTollList=GlobalAlloc(GPTR, dwTollListLength+sizeof(TCHAR)); // We'll convert in place to a
  459. // REG_MULTI_SZ, so reserve an extra space for safety
  460. dwError = pTollList!=NULL ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  461. EXIT_IF_DWERROR();
  462. // ..and read
  463. dwError = RegQueryValueEx( hLocation,
  464. gszTollList,
  465. NULL,
  466. &dwType,
  467. (BYTE *)pTollList,
  468. &dwTollListLength
  469. );
  470. if(dwError == ERROR_SUCCESS && dwType != REG_SZ)
  471. {
  472. dwError = ERROR_INVALID_DATA;
  473. assert(FALSE);
  474. }
  475. EXIT_IF_DWERROR();
  476. // try to find one toll prefix
  477. pCrt = pTollList;
  478. //skip any unwanted commas
  479. while(*pCrt==_T(','))
  480. {
  481. pCrt++;
  482. dwTollListLength -= sizeof(TCHAR);
  483. }
  484. if(*pCrt)
  485. {
  486. TCHAR * pOut = pCrt;
  487. // convert inplace to a REG_MULTI_SZ
  488. while(*pCrt)
  489. {
  490. while(*pCrt && *pCrt!=_T(','))
  491. {
  492. pCrt++;
  493. }
  494. if(!*pCrt)
  495. {
  496. // incorrect string (does not end with a comma)
  497. pCrt++;
  498. *pCrt = _T('\0');
  499. dwTollListLength+=sizeof(TCHAR);
  500. }
  501. else
  502. *pCrt++ = _T('\0');
  503. }
  504. // Create one rule for all the prefixes
  505. dwError = CreateAreaCodeRule( hAreaCodeRules,
  506. iRuleNumber++,
  507. AreaCode,
  508. gszUSLDSpecifier,
  509. (BYTE *)pOut,
  510. dwTollListLength,
  511. AREACODERULE_DIALAREACODE | AREACODERULE_DIALNUMBERTODIAL
  512. );
  513. EXIT_IF_DWERROR();
  514. }
  515. }
  516. DBGOUT((9, "ConvertOneLocation - Success TollList"));
  517. // Translate NoPrefAC
  518. // Length...
  519. dwError = RegQueryValueEx( hLocation,
  520. gszNoPrefAC,
  521. NULL,
  522. NULL,
  523. NULL,
  524. &dwLength);
  525. if(dwError== ERROR_SUCCESS && dwLength>0)
  526. {
  527. int iCount;
  528. DWORD *pValue;
  529. TCHAR AreaCodeToCall[MAXLEN_NUMBER_LEN];
  530. pNoPrefAC=GlobalAlloc(GPTR, dwLength);
  531. dwError = pNoPrefAC!=NULL ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  532. EXIT_IF_DWERROR();
  533. // ..and read
  534. dwError = RegQueryValueEx( hLocation,
  535. gszNoPrefAC,
  536. NULL,
  537. &dwType,
  538. pNoPrefAC,
  539. &dwLength
  540. );
  541. if(dwError == ERROR_SUCCESS && dwType != REG_BINARY)
  542. {
  543. dwError = ERROR_INVALID_DATA;
  544. assert(FALSE);
  545. }
  546. EXIT_IF_DWERROR();
  547. iCount = dwLength/4;
  548. pValue = (DWORD *)pNoPrefAC;
  549. while(iCount--)
  550. {
  551. // Create one rule for each area code
  552. _itot(*pValue, AreaCodeToCall, 10);
  553. dwError = CreateAreaCodeRule( hAreaCodeRules,
  554. iRuleNumber++,
  555. AreaCodeToCall,
  556. gszEmpty,
  557. (LPBYTE)gszMultiEmpty,
  558. sizeof(gszMultiEmpty),
  559. AREACODERULE_DIALAREACODE | AREACODERULE_INCLUDEALLPREFIXES
  560. );
  561. EXIT_IF_DWERROR();
  562. pValue++;
  563. }
  564. }
  565. DBGOUT((9, "ConvertOneLocation - Success NoPrefAC"));
  566. }
  567. dwError = ERROR_SUCCESS;
  568. // delete the TollList Value
  569. RegDeleteValue( hLocation,
  570. gszTollList
  571. );
  572. // delete the NoPrefAC Value
  573. RegDeleteValue( hLocation,
  574. gszNoPrefAC
  575. );
  576. // delete the ID Value
  577. RegDeleteValue( hLocation,
  578. gszID
  579. );
  580. forced_exit:
  581. if(hAreaCodeRules)
  582. RegCloseKey(hAreaCodeRules);
  583. if(pTollList)
  584. GlobalFree(pTollList);
  585. if(pNoPrefAC)
  586. GlobalFree(pNoPrefAC);
  587. DBGOUT((9, "ConvertOneLocation - Exit %xh", dwError));
  588. return dwError;
  589. }
  590. //***************************************************************************
  591. //
  592. // CreateAreaCodeRule - creates an area code rule key
  593. // hParent = handle of the AreaCodeRules key
  594. // iRuleNumber = rule number
  595. // pszAreaCodeToCall, pszNumberToDial & dwFlags = rule values
  596. // pbPrefixes - prefixes
  597. // dwPrefixesLength - length of the prefixes in bytes (including the NULL characters)
  598. PRIVATE DWORD CreateAreaCodeRule( HKEY hParent,
  599. int iRuleNumber,
  600. LPCTSTR pszAreaCodeToCall,
  601. LPCTSTR pszNumberToDial,
  602. LPBYTE pbPrefixes,
  603. DWORD dwPrefixesLength,
  604. DWORD dwFlags
  605. )
  606. {
  607. TCHAR szBuffer[MAXLEN_NUMBER_LEN + sizeof(gszRule)/sizeof(TCHAR)];
  608. DWORD dwError = ERROR_SUCCESS;
  609. DWORD dwDisp;
  610. DWORD dwLength;
  611. HKEY hRule = NULL;
  612. DBGOUT((10, "CreateAreaCodeRule - Enter"));
  613. assert(hParent);
  614. assert(pszNumberToDial);
  615. assert(pszAreaCodeToCall);
  616. assert(pbPrefixes);
  617. // Find the rule key name
  618. wsprintf(szBuffer, _T("%s%d"), gszRule, iRuleNumber);
  619. // Create the key
  620. dwError = RegCreateKeyEx( hParent,
  621. szBuffer,
  622. 0,
  623. NULL,
  624. REG_OPTION_NON_VOLATILE,
  625. KEY_WRITE,
  626. NULL,
  627. &hRule,
  628. &dwDisp
  629. );
  630. EXIT_IF_DWERROR();
  631. assert(dwDisp==REG_CREATED_NEW_KEY);
  632. // AreaCodeToCall value
  633. dwLength = (_tcslen(pszAreaCodeToCall)+1)*sizeof(TCHAR);
  634. dwError = RegSetValueEx( hRule,
  635. gszAreaCodeToCall,
  636. 0,
  637. REG_SZ,
  638. (CONST BYTE *)pszAreaCodeToCall,
  639. dwLength
  640. );
  641. EXIT_IF_DWERROR();
  642. // NumberToDial value
  643. dwLength = (_tcslen(pszNumberToDial)+1)*sizeof(TCHAR);
  644. dwError = RegSetValueEx( hRule,
  645. gszNumberToDial,
  646. 0,
  647. REG_SZ,
  648. (CONST BYTE *)pszNumberToDial,
  649. dwLength
  650. );
  651. EXIT_IF_DWERROR();
  652. // Flags value
  653. dwLength = sizeof(dwFlags);
  654. dwError = RegSetValueEx( hRule,
  655. gszFlags,
  656. 0,
  657. REG_DWORD,
  658. (CONST BYTE *)&dwFlags,
  659. dwLength
  660. );
  661. EXIT_IF_DWERROR();
  662. // Prefixes value
  663. dwError = RegSetValueEx( hRule,
  664. gszPrefixes,
  665. 0,
  666. REG_MULTI_SZ,
  667. (CONST BYTE *)pbPrefixes,
  668. dwPrefixesLength
  669. );
  670. EXIT_IF_DWERROR();
  671. forced_exit:
  672. if(hRule)
  673. RegCloseKey(hRule);
  674. DBGOUT((10, "CreateAreaCodeRule - Exit %xh", dwError));
  675. return dwError;
  676. }
  677. //***************************************************************************
  678. //***************************************************************************
  679. //***************************************************************************
  680. //
  681. // ConvertUserLocations - convert the telephony locations stored in a per user way
  682. // The parameter should be HKEY_CURRENT_USER
  683. //
  684. //
  685. //
  686. DWORD ConvertUserLocations(HKEY hUser)
  687. {
  688. TCHAR Location[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  689. TCHAR NewLocation[sizeof(gszLocation)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  690. DWORD dwError = ERROR_SUCCESS;
  691. HKEY hMachineLocations = NULL;
  692. HKEY hLocations = NULL;
  693. DWORD dwOldID;
  694. DWORD dwNewID;
  695. DWORD dwCount;
  696. DWORD dwLength;
  697. DWORD dwType;
  698. DWORD dwValue;
  699. PDWORD pdwRenameList = NULL;
  700. PDWORD pdwRenameEntry;
  701. #ifdef BACKUP_OLD_KEYS
  702. TCHAR szPath[MAX_PATH+1];
  703. #endif
  704. DBGOUT((8, "ConvertUserLocations - Enter"));
  705. assert(hUser);
  706. dwError = RegOpenKeyEx( hUser,
  707. gszLocationsPath,
  708. 0,
  709. KEY_READ | KEY_WRITE,
  710. &hLocations
  711. );
  712. if(dwError == ERROR_FILE_NOT_FOUND)
  713. {
  714. DBGOUT((1, "Locations key not present, so there's nothing to convert"));
  715. //Nothing to convert
  716. return ERROR_SUCCESS;
  717. }
  718. EXIT_IF_DWERROR();
  719. #ifdef BACKUP_OLD_KEYS
  720. // Try to save the old key
  721. // We DON'T use different files for different users
  722. dwError = GetWindowsDirectory(szPath, MAX_PATH - 12); // a 8+3 name
  723. if(dwError)
  724. {
  725. if(szPath[3] != _T('\0'))
  726. lstrcat(szPath, _T("\\"));
  727. lstrcat(szPath, BACKUP_FILE_USER_LOCATIONS);
  728. SaveKey(hLocations, szPath);
  729. }
  730. else
  731. DBGOUT((1, "Cannot get windows directory (?!?)"));
  732. dwError = ERROR_SUCCESS;
  733. #endif
  734. // Version check
  735. if(!IsLocationListInOldFormat(hLocations))
  736. {
  737. //Nothing to convert
  738. DBGOUT((1, "User Locations key is already in the new format"));
  739. RegCloseKey(hLocations);
  740. return ERROR_SUCCESS;
  741. }
  742. // Open the Machine Locations key
  743. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  744. gszLocationsPath,
  745. 0,
  746. KEY_QUERY_VALUE,
  747. &hMachineLocations
  748. );
  749. if(dwError == ERROR_FILE_NOT_FOUND)
  750. {
  751. DBGOUT((1, "Locations key not present, so there's nothing to convert in User Locations"));
  752. //Nothing to convert
  753. return ERROR_SUCCESS;
  754. }
  755. EXIT_IF_DWERROR();
  756. // query info about the rename history value
  757. dwError = RegQueryValueEx( hMachineLocations,
  758. gszKeyRenameHistory,
  759. NULL,
  760. &dwType,
  761. NULL,
  762. &dwLength
  763. );
  764. if(dwError==ERROR_SUCCESS && dwType!=REG_BINARY)
  765. {
  766. // strange value
  767. dwError = ERROR_INVALID_DATA;
  768. }
  769. if(dwError==ERROR_FILE_NOT_FOUND)
  770. {
  771. dwError = ERROR_SUCCESS;
  772. dwLength = 0;
  773. }
  774. EXIT_IF_DWERROR();
  775. if(dwLength>0)
  776. {
  777. pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwLength);
  778. if(pdwRenameList == NULL)
  779. {
  780. DBGOUT((1, "Cannot allocate the Rename List"));
  781. dwError = ERROR_OUTOFMEMORY;
  782. goto forced_exit;
  783. }
  784. // Read the list
  785. dwError = RegQueryValueEx( hMachineLocations,
  786. gszKeyRenameHistory,
  787. NULL,
  788. NULL,
  789. (PBYTE)pdwRenameList,
  790. &dwLength);
  791. EXIT_IF_DWERROR();
  792. //
  793. RegCloseKey(hMachineLocations);
  794. hMachineLocations = NULL;
  795. // convert dwLength to the number of entries
  796. dwLength /= 2*sizeof(DWORD);
  797. pdwRenameEntry = pdwRenameList;
  798. for(dwCount = 0; dwCount<dwLength; dwCount++)
  799. {
  800. dwOldID = *pdwRenameEntry++;
  801. dwNewID = *pdwRenameEntry++;
  802. if(dwNewID != dwOldID)
  803. {
  804. wsprintf(Location, _T("%s%d"), gszLocation, dwOldID);
  805. wsprintf(NewLocation, _T("%s%d"), gszLocation, dwNewID);
  806. dwError = RegRenameKey( hLocations,
  807. Location,
  808. NewLocation );
  809. if(dwError==ERROR_SUCCESS)
  810. {
  811. DBGOUT ((8, "Renamed user location number from %d to %d", dwOldID, dwNewID));
  812. }
  813. // ignore the errors - the key could be missing
  814. }
  815. }
  816. }
  817. // add the versioning value
  818. dwValue = TAPI_LOCATION_LIST_VERSION;
  819. dwError = RegSetValueEx( hLocations,
  820. gszLocationListVersion,
  821. 0,
  822. REG_DWORD,
  823. (PBYTE)&dwValue,
  824. sizeof(dwValue)
  825. );
  826. EXIT_IF_DWERROR();
  827. forced_exit:
  828. DBGOUT((8, "ConvertUserLocations - Exit %xh", dwError));
  829. if(hMachineLocations)
  830. RegCloseKey(hMachineLocations);
  831. if(hLocations)
  832. RegCloseKey(hLocations);
  833. if(pdwRenameList)
  834. GlobalFree(pdwRenameList);
  835. return dwError;
  836. }
  837. //***************************************************************************
  838. //***************************************************************************
  839. //***************************************************************************
  840. //
  841. // ConvertCallingCards - convert the telephony calling cards to the new format
  842. // The parameter should be HKEY_CURRENT_USER or the handle of HKU\.Default
  843. //
  844. // see nt\private\tapi\dev\docs\dialrules.doc
  845. //
  846. DWORD ConvertCallingCards(HKEY hUser)
  847. {
  848. TCHAR Card[sizeof(gszCard)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  849. TCHAR NewCard[sizeof(gszCard)/sizeof(TCHAR) + MAXLEN_NUMBER_LEN];
  850. DWORD dwError = ERROR_SUCCESS;
  851. HKEY hCards = NULL;
  852. HKEY hCard = NULL;
  853. DWORD dwNumCards;
  854. DWORD dwCardID;
  855. DWORD dwCardIDTmp;
  856. DWORD dwCount;
  857. DWORD dwLength;
  858. DWORD dwType;
  859. DWORD dwValue;
  860. BOOL bCryptInitialized;
  861. PDWORD pdwRenameList = NULL;
  862. PDWORD pdwRenameEntry;
  863. DWORD dwRenameEntryCount;
  864. #ifdef BACKUP_OLD_KEYS
  865. TCHAR szPath[MAX_PATH+1];
  866. #endif
  867. DBGOUT((8, "ConvertCallingCards - Enter"));
  868. assert(hUser);
  869. bCryptInitialized = FALSE;
  870. // Open the key
  871. dwError = RegOpenKeyEx( hUser,
  872. gszCardsPath,
  873. 0,
  874. KEY_READ | KEY_WRITE,
  875. &hCards
  876. );
  877. if(dwError == ERROR_FILE_NOT_FOUND)
  878. {
  879. DBGOUT((1, "Cards key not present, so there's nothing to convert"));
  880. //Nothing to convert
  881. return ERROR_SUCCESS;
  882. }
  883. EXIT_IF_DWERROR();
  884. // Version check
  885. if(!IsCardListInOldFormat(hCards))
  886. {
  887. //Nothing to convert
  888. DBGOUT((1, "Cards key is already in the new format"));
  889. RegCloseKey(hCards);
  890. return ERROR_SUCCESS;
  891. }
  892. #ifdef BACKUP_OLD_KEYS
  893. // Try to save the old key
  894. // We DON'T use different files for different users
  895. dwError = GetWindowsDirectory(szPath, MAX_PATH - 12); // a 8+3 name
  896. if(dwError)
  897. {
  898. if(szPath[3] != _T('\0'))
  899. lstrcat(szPath, _T("\\"));
  900. lstrcat(szPath, BACKUP_FILE_CARDS);
  901. SaveKey(hCards, szPath);
  902. }
  903. else
  904. DBGOUT((1, "Cannot get windows directory (?!?)"));
  905. dwError = ERROR_SUCCESS;
  906. #endif
  907. // Read number of cards
  908. dwLength = sizeof(dwNumCards);
  909. dwError = RegQueryValueEx( hCards,
  910. gszNumEntries,
  911. NULL,
  912. &dwType,
  913. (BYTE *)&dwNumCards,
  914. &dwLength
  915. );
  916. if(dwError==ERROR_SUCCESS && dwType != REG_DWORD)
  917. {
  918. dwError = ERROR_INVALID_DATA;
  919. assert(FALSE);
  920. }
  921. // The value could be missing in an empty key
  922. if(dwError != ERROR_SUCCESS)
  923. dwNumCards = 0;
  924. // Alloc storage for a list of card temp IDs
  925. if(dwNumCards>0)
  926. {
  927. pdwRenameList = (PDWORD)GlobalAlloc(GPTR, dwNumCards*sizeof(DWORD) );
  928. if(pdwRenameList==NULL)
  929. {
  930. DBGOUT((1, "Cannot allocate the temp IDs List"));
  931. dwError = ERROR_OUTOFMEMORY;
  932. goto forced_exit;
  933. }
  934. }
  935. pdwRenameEntry = pdwRenameList;
  936. dwRenameEntryCount = 0;
  937. // Initialize the cryptographic part
  938. dwError = TapiCryptInitialize();
  939. bCryptInitialized = TRUE; // whatever the result was
  940. if(dwError != ERROR_SUCCESS)
  941. {
  942. DBGOUT((8, "ConvertCallingCards - Cannot init Crypt %xh", dwError));
  943. // Make it not fatal
  944. dwError = ERROR_SUCCESS;
  945. }
  946. // Convert from end to the begining in order to avoid name conflicts during the key renames
  947. for(dwCount = dwNumCards-1; (LONG)dwCount>=0; dwCount--)
  948. {
  949. wsprintf(Card, _T("%s%d"), gszCard, dwCount);
  950. dwError = RegOpenKeyEx( hCards,
  951. Card,
  952. 0,
  953. KEY_READ | KEY_WRITE,
  954. &hCard
  955. );
  956. if(dwError == ERROR_FILE_NOT_FOUND)
  957. {
  958. DBGOUT((1, "Cannot open old %s", Card));
  959. // Try to recover - skip to the next entry
  960. continue;
  961. }
  962. EXIT_IF_DWERROR();
  963. // Read the ID for later usage
  964. dwLength = sizeof(dwCardID);
  965. dwError = RegQueryValueEx( hCard,
  966. gszID,
  967. NULL,
  968. &dwType,
  969. (LPBYTE)&dwCardID,
  970. &dwLength
  971. );
  972. if(dwError == ERROR_SUCCESS)
  973. {
  974. // Convert the card to the new format
  975. dwError = ConvertOneCard(hCard, dwCardID);
  976. EXIT_IF_DWERROR();
  977. RegCloseKey(hCard);
  978. hCard = NULL;
  979. // Rename the key if it is necessary
  980. if(dwCardID != dwCount)
  981. {
  982. wsprintf(NewCard, _T("%s%d"), gszCard, dwCardID);
  983. // Check the destination for an old key still present. It may be possible to find one if
  984. // the original TAPI version was TELEPHON.INI-based.
  985. assert(!(dwCardID & TEMPORARY_ID_FLAG));
  986. dwCardIDTmp = dwCardID;
  987. dwError = RegOpenKeyEx( hCards,
  988. NewCard,
  989. 0,
  990. KEY_READ,
  991. &hCard
  992. );
  993. if(dwError==ERROR_SUCCESS)
  994. {
  995. // use a temporary ID
  996. dwCardIDTmp |= TEMPORARY_ID_FLAG;
  997. wsprintf(NewCard, _T("%s%d"), gszCard, dwCardIDTmp);
  998. *pdwRenameEntry++ = dwCardIDTmp;
  999. dwRenameEntryCount++;
  1000. }
  1001. if(hCard)
  1002. {
  1003. RegCloseKey(hCard);
  1004. hCard = NULL;
  1005. }
  1006. dwError = RegRenameKey( hCards,
  1007. Card,
  1008. NewCard
  1009. );
  1010. EXIT_IF_DWERROR();
  1011. }
  1012. DBGOUT ((8, "Converted card %d (ID %d)", dwCount, dwCardID));
  1013. }
  1014. }
  1015. dwError = ERROR_SUCCESS;
  1016. // Rewalk the list for renaming the keys with temporary IDs
  1017. pdwRenameEntry = pdwRenameList;
  1018. for(dwCount=0; dwCount<dwRenameEntryCount; dwCount++)
  1019. {
  1020. dwCardIDTmp = *pdwRenameEntry++;
  1021. wsprintf(Card, _T("%s%d"), gszCard, dwCardIDTmp);
  1022. dwCardID = dwCardIDTmp & ~TEMPORARY_ID_FLAG;
  1023. wsprintf(NewCard, _T("%s%d"), gszCard, dwCardID);
  1024. dwError = RegRenameKey( hCards,
  1025. Card,
  1026. NewCard
  1027. );
  1028. EXIT_IF_DWERROR();
  1029. DBGOUT ((8, "Renamed to permanent ID %d", dwCardID));
  1030. }
  1031. // delete the NumEntries value. We don't need it any more
  1032. RegDeleteValue( hCards,
  1033. gszNumEntries);
  1034. // add the versioning value
  1035. dwValue = TAPI_CARD_LIST_VERSION;
  1036. dwError = RegSetValueEx( hCards,
  1037. gszCardListVersion,
  1038. 0,
  1039. REG_DWORD,
  1040. (PBYTE)&dwValue,
  1041. sizeof(dwValue)
  1042. );
  1043. EXIT_IF_DWERROR();
  1044. forced_exit:
  1045. if(hCard)
  1046. RegCloseKey(hCard);
  1047. if(hCards)
  1048. RegCloseKey(hCards);
  1049. if(bCryptInitialized)
  1050. TapiCryptUninitialize();
  1051. if(pdwRenameList)
  1052. GlobalFree(pdwRenameList);
  1053. DBGOUT((8, "ConvertCallingCards - Exit %xh", dwError));
  1054. return dwError;
  1055. }
  1056. //***************************************************************************
  1057. //
  1058. // ConvertOneCard - convert one calling card
  1059. // hCard is the handle of the CardX key
  1060. // Note The key rename according to card ID is executed in ConvertCallingCards
  1061. DWORD ConvertOneCard(HKEY hCard, DWORD dwCardID)
  1062. {
  1063. DWORD dwError = ERROR_SUCCESS;
  1064. DBGOUT((9, "ConvertOneCard - Enter"));
  1065. assert(hCard);
  1066. dwError = SplitCallingCardRule( hCard,
  1067. gszLocalRule,
  1068. gszLocalAccessNumber);
  1069. // ignore any error
  1070. dwError = SplitCallingCardRule( hCard,
  1071. gszLDRule,
  1072. gszLDAccessNumber);
  1073. // ignore any error
  1074. dwError = SplitCallingCardRule( hCard,
  1075. gszInternationalRule,
  1076. gszInternationalAccessNumber);
  1077. // ignore any error
  1078. dwError = RegSetValueEx( hCard,
  1079. gszAccountNumber,
  1080. 0,
  1081. REG_SZ,
  1082. (BYTE *)gszEmpty,
  1083. sizeof(TCHAR)
  1084. );
  1085. // Converts the PIN number to a better encrypted form
  1086. dwError = ConvertPIN(hCard, dwCardID);
  1087. // delete the ID Value
  1088. RegDeleteValue( hCard,
  1089. gszID
  1090. );
  1091. //forced_exit:
  1092. DBGOUT((9, "ConvertOneCard - Exit %xh", dwError));
  1093. return dwError;
  1094. }
  1095. //***************************************************************************
  1096. //
  1097. // ConvertPIN - better encryption of the PIN number
  1098. // hCard is the handle of the CardX key
  1099. //
  1100. DWORD ConvertPIN(HKEY hCard, DWORD dwCardID)
  1101. {
  1102. WCHAR szOldPIN[MAXLEN_PIN+1];
  1103. PWSTR pszNewPIN = NULL;
  1104. DWORD dwError;
  1105. DWORD dwLength;
  1106. DWORD dwLength2;
  1107. DWORD dwLength3;
  1108. DWORD dwType;
  1109. // Read the old PIN with a UNICODE version of RegQuery..
  1110. dwLength = sizeof(szOldPIN);
  1111. dwError = RegQueryValueExW( hCard,
  1112. gwszPIN,
  1113. NULL,
  1114. &dwType,
  1115. (BYTE *)szOldPIN,
  1116. &dwLength
  1117. );
  1118. if(dwError==ERROR_SUCCESS)
  1119. {
  1120. if(*szOldPIN==L'\0')
  1121. {
  1122. // Nothing to do !
  1123. return ERROR_SUCCESS;
  1124. }
  1125. // Decrypts inplace
  1126. dwError = TapiDecrypt(szOldPIN, dwCardID, szOldPIN, &dwLength2);
  1127. if(dwError==ERROR_SUCCESS)
  1128. {
  1129. assert(dwLength2 == dwLength/sizeof(WCHAR));
  1130. // Find the space needed for the encrypted result
  1131. dwError = TapiEncrypt(szOldPIN, dwCardID, NULL, &dwLength2);
  1132. if(dwError == ERROR_SUCCESS)
  1133. {
  1134. // If the length is the same with the original, we have no conversion
  1135. if(dwLength2 > dwLength/sizeof(WCHAR))
  1136. {
  1137. pszNewPIN = (PWSTR)GlobalAlloc(GMEM_FIXED, dwLength2*sizeof(WCHAR));
  1138. if(pszNewPIN==NULL)
  1139. {
  1140. return ERROR_OUTOFMEMORY;
  1141. }
  1142. dwError = TapiEncrypt(szOldPIN, dwCardID, pszNewPIN, &dwLength3);
  1143. if(dwError == ERROR_SUCCESS)
  1144. {
  1145. assert(dwLength3<=dwLength2);
  1146. // Write the new PIN
  1147. dwError = RegSetValueExW( hCard,
  1148. gwszPIN,
  1149. 0,
  1150. REG_SZ,
  1151. (BYTE *)pszNewPIN,
  1152. dwLength3*sizeof(WCHAR)
  1153. );
  1154. // TEST
  1155. /*
  1156. ZeroMemory(szOldPIN, sizeof(szOldPIN));
  1157. dwError = TapiDecrypt(pszNewPIN, dwCardID, szOldPIN, &dwLength3);
  1158. if(dwError==ERROR_SUCCESS)
  1159. DBGOUT((5, "TEST Decrypt Card %d - PIN # %S, Length=%d", dwCardID, szOldPIN, dwLength3));
  1160. else
  1161. DBGOUT((5, "TEST Decrypt Card %d - Error 0x%x", dwCardID, dwError));
  1162. */
  1163. }
  1164. GlobalFree(pszNewPIN);
  1165. }
  1166. else
  1167. {
  1168. DBGOUT((5, "PIN for card %d not converted", dwCardID));
  1169. }
  1170. }
  1171. }
  1172. else
  1173. {
  1174. // Strange, shouldn't happen
  1175. assert(FALSE);
  1176. }
  1177. }
  1178. return dwError;
  1179. }
  1180. //***************************************************************************
  1181. //
  1182. // Version Check
  1183. BOOL IsLocationListInOldFormat(HKEY hLocations) // for both user & machine
  1184. {
  1185. return (ERROR_SUCCESS != RegQueryValueEx( hLocations,
  1186. gszLocationListVersion,
  1187. NULL,
  1188. NULL,
  1189. NULL,
  1190. NULL
  1191. ));
  1192. }
  1193. BOOL IsCardListInOldFormat(HKEY hCards)
  1194. {
  1195. return (ERROR_SUCCESS != RegQueryValueEx( hCards,
  1196. gszCardListVersion,
  1197. NULL,
  1198. NULL,
  1199. NULL,
  1200. NULL
  1201. ));
  1202. }
  1203. //***************************************************************************
  1204. //
  1205. // IsTelephonyDigit - test range 0123456789#*ABCD
  1206. PRIVATE BOOL IsTelephonyDigit(TCHAR c)
  1207. {
  1208. return _istdigit(c) || c==_T('*') || c==_T('#') || c==_T('A') || c==_T('B') || c==_T('C') || c==_T('D');
  1209. }
  1210. //***************************************************************************
  1211. //
  1212. // SplitCallingCardRule - tries to find the access numbers and updates the coresponding values
  1213. PRIVATE DWORD SplitCallingCardRule(HKEY hCard, LPCTSTR pszRuleName, LPCTSTR pszAccessNumberName)
  1214. {
  1215. TCHAR OldRule[MAXLEN_RULE];
  1216. TCHAR NewRule[MAXLEN_RULE];
  1217. TCHAR AccessNumber[MAXLEN_ACCESS_NUMBER];
  1218. TCHAR * pOld;
  1219. TCHAR * pNew;
  1220. TCHAR * pNr;
  1221. DWORD dwLength;
  1222. DWORD dwError = ERROR_SUCCESS;
  1223. DWORD dwType;
  1224. // read the local rule
  1225. dwLength = sizeof(OldRule);
  1226. dwError = RegQueryValueEx( hCard,
  1227. pszRuleName,
  1228. NULL,
  1229. &dwType,
  1230. (BYTE *)OldRule,
  1231. &dwLength
  1232. );
  1233. if(dwError==ERROR_SUCCESS && dwType != REG_SZ)
  1234. {
  1235. dwError = ERROR_INVALID_DATA;
  1236. assert(FALSE);
  1237. }
  1238. if(dwError==ERROR_SUCCESS)
  1239. {
  1240. // Parse the old rule
  1241. pOld = OldRule;
  1242. pNew = NewRule;
  1243. pNr = AccessNumber;
  1244. while(*pOld && IsTelephonyDigit(*pOld))
  1245. *pNr++ = *pOld++;
  1246. if(pNr!=AccessNumber)
  1247. *pNew++ = _T('J');
  1248. while(*pOld)
  1249. *pNew++ = *pOld++;
  1250. *pNew = _T('\0');
  1251. *pNr = _T('\0');
  1252. dwLength = (_tcslen(AccessNumber)+1)*sizeof(TCHAR);
  1253. dwError = RegSetValueEx( hCard,
  1254. pszAccessNumberName,
  1255. 0,
  1256. REG_SZ,
  1257. (BYTE *)AccessNumber,
  1258. dwLength
  1259. );
  1260. EXIT_IF_DWERROR();
  1261. dwLength = (_tcslen(NewRule)+1)*sizeof(TCHAR);
  1262. dwError = RegSetValueEx( hCard,
  1263. pszRuleName,
  1264. 0,
  1265. REG_SZ,
  1266. (BYTE *)NewRule,
  1267. dwLength
  1268. );
  1269. EXIT_IF_DWERROR();
  1270. }
  1271. forced_exit:
  1272. return dwError;
  1273. }
  1274. //***************************************************************************
  1275. //***************************************************************************
  1276. //***************************************************************************
  1277. // Helper functions for renaming the registry keys
  1278. PRIVATE DWORD RegRenameKey( HKEY hParentKey,
  1279. LPCTSTR pszOldName,
  1280. LPCTSTR pszNewName)
  1281. {
  1282. DWORD dwError;
  1283. assert(pszOldName);
  1284. assert(pszNewName);
  1285. DBGOUT((15, "RegRenameKey - Start, from %s to %s", pszOldName, pszNewName));
  1286. assert(hParentKey);
  1287. assert(_tcscmp(pszOldName, pszNewName)!=0);
  1288. dwError = RegCopyKeyRecursive( hParentKey,
  1289. pszOldName,
  1290. hParentKey,
  1291. pszNewName
  1292. );
  1293. EXIT_IF_DWERROR();
  1294. dwError = RegDeleteKeyRecursive(hParentKey,
  1295. pszOldName);
  1296. EXIT_IF_DWERROR();
  1297. forced_exit:
  1298. DBGOUT((15, "RegRenameKey - Exit %xh", dwError));
  1299. return dwError;
  1300. }
  1301. PRIVATE DWORD RegCopyKeyRecursive(HKEY hSrcParentKey, LPCTSTR pszSrcName,
  1302. HKEY hDestParentKey, LPCTSTR pszDestName)
  1303. {
  1304. HKEY hSrcKey = NULL;
  1305. HKEY hDestKey = NULL;
  1306. DWORD dwError = ERROR_SUCCESS;
  1307. DWORD dwDisp;
  1308. DWORD dwMaxSubkeyLength;
  1309. DWORD dwMaxValueNameLength;
  1310. DWORD dwMaxValueLength;
  1311. DWORD dwNumValues;
  1312. DWORD dwNumSubkeys;
  1313. DWORD dwIndex;
  1314. DWORD dwType;
  1315. DWORD dwValueLength;
  1316. DWORD dwValueNameLength;
  1317. DWORD dwSubkeyLength;
  1318. LPTSTR pszSubkey = NULL;
  1319. LPTSTR pszValueName = NULL;
  1320. LPBYTE pbValue = NULL;
  1321. assert(hSrcParentKey);
  1322. assert(hDestParentKey);
  1323. assert(pszSrcName);
  1324. assert(pszDestName);
  1325. // open source key
  1326. dwError = RegOpenKeyEx( hSrcParentKey,
  1327. pszSrcName,
  1328. 0,
  1329. KEY_READ,
  1330. &hSrcKey
  1331. );
  1332. EXIT_IF_DWERROR();
  1333. // create destination key
  1334. dwError = RegCreateKeyEx( hDestParentKey,
  1335. pszDestName,
  1336. 0,
  1337. NULL,
  1338. REG_OPTION_NON_VOLATILE,
  1339. KEY_READ | KEY_WRITE,
  1340. NULL,
  1341. &hDestKey,
  1342. &dwDisp
  1343. );
  1344. EXIT_IF_DWERROR();
  1345. assert(dwDisp==REG_CREATED_NEW_KEY);
  1346. // query some info about the source key in order to allocate memory
  1347. dwError = RegQueryInfoKey( hSrcKey,
  1348. NULL,
  1349. NULL,
  1350. NULL,
  1351. &dwNumSubkeys,
  1352. &dwMaxSubkeyLength,
  1353. NULL,
  1354. &dwNumValues,
  1355. &dwMaxValueNameLength,
  1356. &dwMaxValueLength,
  1357. NULL,
  1358. NULL
  1359. );
  1360. EXIT_IF_DWERROR();
  1361. pszSubkey = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwMaxSubkeyLength+1)*sizeof(TCHAR));
  1362. if(pszSubkey==NULL)
  1363. dwError = ERROR_OUTOFMEMORY;
  1364. EXIT_IF_DWERROR();
  1365. pszValueName = (LPTSTR)GlobalAlloc(GMEM_FIXED, (dwMaxValueNameLength+1)*sizeof(TCHAR));
  1366. if(pszValueName==NULL)
  1367. dwError = ERROR_OUTOFMEMORY;
  1368. EXIT_IF_DWERROR();
  1369. pbValue = (LPBYTE)GlobalAlloc(GMEM_FIXED, dwMaxValueLength);
  1370. if(pbValue==NULL)
  1371. dwError = ERROR_OUTOFMEMORY;
  1372. EXIT_IF_DWERROR();
  1373. // enumerate and copy the values
  1374. for(dwIndex=0; dwIndex<dwNumValues; dwIndex++)
  1375. {
  1376. // read one value
  1377. dwValueNameLength = dwMaxValueNameLength + 1;
  1378. dwValueLength = dwMaxValueLength;
  1379. dwError = RegEnumValue( hSrcKey,
  1380. dwIndex,
  1381. pszValueName,
  1382. &dwValueNameLength,
  1383. NULL,
  1384. &dwType,
  1385. pbValue,
  1386. &dwValueLength
  1387. );
  1388. EXIT_IF_DWERROR();
  1389. // write it
  1390. dwError = RegSetValueEx(hDestKey,
  1391. pszValueName,
  1392. 0,
  1393. dwType,
  1394. pbValue,
  1395. dwValueLength
  1396. );
  1397. EXIT_IF_DWERROR();
  1398. }
  1399. // enumerate and copy the subkeys
  1400. for(dwIndex=0; dwIndex<dwNumSubkeys; dwIndex++)
  1401. {
  1402. // read a subkey
  1403. dwSubkeyLength = dwMaxSubkeyLength +1;
  1404. dwError = RegEnumKeyEx( hSrcKey,
  1405. dwIndex,
  1406. pszSubkey,
  1407. &dwSubkeyLength,
  1408. NULL,
  1409. NULL,
  1410. NULL,
  1411. NULL
  1412. );
  1413. EXIT_IF_DWERROR();
  1414. // copy it
  1415. dwError = RegCopyKeyRecursive( hSrcKey,
  1416. pszSubkey,
  1417. hDestKey,
  1418. pszSubkey
  1419. );
  1420. EXIT_IF_DWERROR();
  1421. }
  1422. forced_exit:
  1423. if(hSrcKey)
  1424. RegCloseKey(hSrcKey);
  1425. if(hDestKey)
  1426. RegCloseKey(hDestKey);
  1427. if(pszSubkey)
  1428. GlobalFree(pszSubkey);
  1429. if(pszValueName)
  1430. GlobalFree(pszValueName);
  1431. if(pbValue)
  1432. GlobalFree(pbValue);
  1433. return dwError;
  1434. }
  1435. DWORD RegDeleteKeyRecursive (HKEY hParentKey, LPCTSTR pszKeyName)
  1436. {
  1437. HKEY hKey = NULL;
  1438. DWORD dwError;
  1439. DWORD dwIndex;
  1440. DWORD dwSubKeyCount;
  1441. LPTSTR pszSubKeyName;
  1442. DWORD dwSubKeyNameLength; // in characters
  1443. DWORD dwSubKeyNameLengthBytes; // in bytes
  1444. DWORD dwMaxSubKeyLength;;
  1445. dwError = RegOpenKeyEx (hParentKey, pszKeyName, 0, KEY_READ | KEY_WRITE, &hKey);
  1446. if (dwError != ERROR_SUCCESS)
  1447. return dwError;
  1448. dwError = RegQueryInfoKey (
  1449. hKey, // key in question
  1450. NULL, NULL, // class
  1451. NULL, // reserved
  1452. &dwSubKeyCount, // number of subkeys
  1453. &dwMaxSubKeyLength, // maximum length of subkey name
  1454. NULL, // max class length
  1455. NULL, // number of values
  1456. NULL, // max value name len
  1457. NULL, // max value len
  1458. NULL, // security descriptor
  1459. NULL); // last write time
  1460. if (dwError != ERROR_SUCCESS) {
  1461. RegCloseKey (hKey);
  1462. return dwError;
  1463. }
  1464. if (dwSubKeyCount > 0) {
  1465. // at least one subkey
  1466. dwSubKeyNameLengthBytes = sizeof (TCHAR) * (dwMaxSubKeyLength + 1);
  1467. pszSubKeyName = (LPTSTR) GlobalAlloc (GMEM_FIXED, dwSubKeyNameLengthBytes);
  1468. if (pszSubKeyName) {
  1469. // delete from end to beginning, to avoid quadratic performance
  1470. // ignore deletion errors
  1471. for (dwIndex = dwSubKeyCount; dwIndex > 0; dwIndex--) {
  1472. dwSubKeyNameLength = dwMaxSubKeyLength + 1;
  1473. dwError = RegEnumKeyEx (hKey, dwIndex - 1, pszSubKeyName, &dwSubKeyNameLength, NULL, NULL, NULL, NULL);
  1474. if (dwError == ERROR_SUCCESS) {
  1475. RegDeleteKeyRecursive (hKey, pszSubKeyName);
  1476. }
  1477. }
  1478. // clean up any stragglers
  1479. for (;;) {
  1480. dwSubKeyNameLength = dwMaxSubKeyLength + 1;
  1481. dwError = RegEnumKeyEx (hKey, 0, pszSubKeyName, &dwSubKeyNameLength, NULL, NULL, NULL, NULL);
  1482. if (dwError == ERROR_SUCCESS)
  1483. RegDeleteKeyRecursive (hKey, pszSubKeyName);
  1484. else
  1485. break;
  1486. }
  1487. GlobalFree (pszSubKeyName);
  1488. }
  1489. }
  1490. RegCloseKey (hKey);
  1491. return RegDeleteKey (hParentKey, pszKeyName);
  1492. }
  1493. #ifdef BACKUP_OLD_KEYS
  1494. #ifdef WINNT
  1495. PRIVATE
  1496. BOOL
  1497. EnablePrivilege(
  1498. PTSTR PrivilegeName,
  1499. BOOL Enable,
  1500. BOOL *Old
  1501. )
  1502. {
  1503. HANDLE Token;
  1504. BOOL b;
  1505. TOKEN_PRIVILEGES NewPrivileges, OldPrivileges; // place for one priv
  1506. LUID Luid;
  1507. DWORD Length;
  1508. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,&Token)) {
  1509. return(FALSE);
  1510. }
  1511. if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) {
  1512. CloseHandle(Token);
  1513. return(FALSE);
  1514. }
  1515. NewPrivileges.PrivilegeCount = 1;
  1516. NewPrivileges.Privileges[0].Luid = Luid;
  1517. NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
  1518. b = AdjustTokenPrivileges(
  1519. Token,
  1520. FALSE,
  1521. &NewPrivileges,
  1522. sizeof(OldPrivileges), // it has a place for one luid
  1523. &OldPrivileges,
  1524. &Length
  1525. );
  1526. CloseHandle(Token);
  1527. if(b)
  1528. {
  1529. if(OldPrivileges.PrivilegeCount==0)
  1530. *Old = Enable;
  1531. else
  1532. *Old = (OldPrivileges.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED)
  1533. ? TRUE : FALSE;
  1534. }
  1535. else
  1536. DBGOUT((1, "Cannot change SeBackupPrivilege - Error %d", GetLastError()));
  1537. return(b);
  1538. }
  1539. #endif // WINNT
  1540. PRIVATE
  1541. BOOL
  1542. SaveKey(
  1543. HKEY hKey,
  1544. LPCTSTR pszFileName
  1545. )
  1546. {
  1547. DWORD dwError;
  1548. #ifdef WINNT
  1549. BOOL bOldBackupPriv = FALSE;
  1550. #endif
  1551. // Delete the file if exists (ignore errors)
  1552. DeleteFile(pszFileName);
  1553. #ifdef WINNT
  1554. // Enable the BACKUP privilege (ignore errors)
  1555. EnablePrivilege(SE_BACKUP_NAME, TRUE, &bOldBackupPriv);
  1556. #endif
  1557. // Save the key
  1558. dwError = RegSaveKey( hKey,
  1559. pszFileName,
  1560. NULL
  1561. );
  1562. if(dwError==ERROR_SUCCESS)
  1563. DBGOUT((9, "Old Telephony key saved")) ;
  1564. else
  1565. DBGOUT((1, "Cannot save old Telephony key - Error %d", dwError));
  1566. #ifdef WINNT
  1567. // Restore the BACKUP privilege (ignore errors)
  1568. EnablePrivilege(SE_BACKUP_NAME, bOldBackupPriv, &bOldBackupPriv);
  1569. #endif
  1570. return (dwError == ERROR_SUCCESS);
  1571. }
  1572. #endif // BACKUP_OLD_KEYS