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.

2135 lines
58 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. addrmap.c
  5. ABSTRACT
  6. Address attributes database routines shared between
  7. the automatic connection driver, the registry, and
  8. the automatic connection service.
  9. AUTHOR
  10. Anthony Discolo (adiscolo) 01-Sep-1995
  11. REVISION HISTORY
  12. --*/
  13. #define UNICODE
  14. #define _UNICODE
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <stdlib.h>
  19. #include <windows.h>
  20. #include <tchar.h>
  21. #include <stdio.h>
  22. #include <npapi.h>
  23. #include <acd.h>
  24. #include <ras.h>
  25. #include <raserror.h>
  26. #include <rasman.h>
  27. #include <debug.h>
  28. #include <time.h>
  29. #include <wchar.h>
  30. #include "table.h"
  31. #include "reg.h"
  32. #include "imperson.h"
  33. #include "misc.h"
  34. #include "addrmap.h"
  35. #include "netmap.h"
  36. #include "rasprocs.h"
  37. #include "tapiproc.h"
  38. #define DAYSECONDS (60*60*24)
  39. extern HKEY hkeyCUG;
  40. extern LONG g_lRasAutoRunning;
  41. extern DWORD g_dwCritSecFlags;
  42. //
  43. // All the information we cache about
  44. // an address is below. The ulAttributes
  45. // field is written to the automatic connection
  46. // driver, and the rest of the fields are written
  47. // to the registry.
  48. //
  49. #define ADDRESS_MAP_FIELD_DIALINGLOC 0x00000001 // locationList changed
  50. #define ADDRESS_MAP_FIELD_PARAMS 0x00000002 // params
  51. typedef struct _ADDRESS_DIALING_ENTRY {
  52. LIST_ENTRY ListEntry;
  53. BOOLEAN fChanged; // modified bit
  54. ADDRESS_LOCATION_INFORMATION location;
  55. } ADDRESS_DIALING_ENTRY, *PADDRESS_DIALING_ENTRY;
  56. typedef struct _ADDRESS_MAP_ENTRY {
  57. LPTSTR pszNetwork; // the remote network this address is on
  58. ULONG ulModifiedMask; // which fields have been changed
  59. BOOLEAN fDisabled; // disabled for connection attempts
  60. DWORD dwFailedConnectTicks; // last failed connect time
  61. ADDRESS_PARAMS params; // used to garbage collect unref addresses
  62. LIST_ENTRY locationHead; // list of ADDRESS_DIALING_ENTRYs
  63. BOOLEAN fPruned; // removed by the list writer
  64. LIST_ENTRY writerList; // list writer links
  65. } ADDRESS_MAP_ENTRY, *PADDRESS_MAP_ENTRY;
  66. //
  67. // The address map head.
  68. //
  69. typedef struct _ADDRESS_MAP {
  70. CRITICAL_SECTION csLock;
  71. PHASH_TABLE pTable;
  72. } ADDRESS_MAP, *PADDRESS_MAP;
  73. //
  74. // Information needed by the address
  75. // enumerator procedure.
  76. //
  77. typedef struct _ADDRESS_ENUM_INFO {
  78. ULONG ulIndex;
  79. LPTSTR *pAddresses;
  80. } ADDRESS_ENUM_INFO, *PADDRESS_ENUM_INFO;
  81. //
  82. // Information needed by the address map list
  83. // builder enumerator procedure.
  84. //
  85. typedef struct _ADDRESS_LIST_INFO {
  86. LIST_ENTRY tagHead[3]; // one per ADDRMAP_TAG_*
  87. } ADDRESS_LIST_INFO, *PADDRESS_LIST_INFO;
  88. //
  89. // Structure shared by GetOrganizationDialingLocationEntry()
  90. // and FindOrganization() when looking for an address that
  91. // has the same organization name.
  92. //
  93. typedef struct _MATCH_INFO {
  94. BOOLEAN fWww; // look for www-style address
  95. BOOLEAN fOrg; // look for organization
  96. DWORD dwLocationID; // current dialing location
  97. BOOLEAN bFound; // TRUE if success
  98. WCHAR szOrganization[ACD_ADDR_INET_LEN]; // organization we're looking for
  99. WCHAR szAddress[ACD_ADDR_INET_LEN]; // matching address, if found
  100. PADDRESS_DIALING_ENTRY pDialingEntry; // dialing location entry pointer
  101. } MATCH_INFO, *PMATCH_INFO;
  102. //
  103. // Default permanently disabled addresses.
  104. //
  105. #define MAX_DISABLED_ADDRESSES 5
  106. TCHAR *szDisabledAddresses[MAX_DISABLED_ADDRESSES] = {
  107. TEXT("0.0.0.0"),
  108. TEXT("255.255.255.255"),
  109. TEXT("127.0.0.0"),
  110. TEXT("127.0.0.1"),
  111. TEXT("dialin_gateway")
  112. };
  113. //
  114. // Global variables
  115. //
  116. ADDRESS_MAP AddressMapG;
  117. HANDLE hAutodialRegChangeG = NULL;
  118. DWORD dwLearnedAddressIndexG;
  119. PHASH_TABLE pDisabledAddressesG;
  120. CRITICAL_SECTION csDisabledAddressesLockG;
  121. //
  122. // External variables
  123. //
  124. extern HANDLE hAcdG;
  125. extern HANDLE hNewLogonUserG;
  126. extern HANDLE hNewFusG; // Fast user switching
  127. extern HANDLE hPnpEventG;
  128. extern HANDLE hLogoffUserG;
  129. extern HANDLE hLogoffUserDoneG;
  130. extern HANDLE hTapiChangeG;
  131. extern HANDLE hTerminatingG;
  132. extern IMPERSONATION_INFO ImpersonationInfoG;
  133. PADDRESS_MAP_ENTRY
  134. NewAddressMapEntry()
  135. {
  136. PADDRESS_MAP_ENTRY pAddressMapEntry;
  137. pAddressMapEntry = LocalAlloc(LPTR, sizeof (ADDRESS_MAP_ENTRY));
  138. if (pAddressMapEntry == NULL) {
  139. RASAUTO_TRACE("NewAddressMapEntry: LocalAlloc failed");
  140. return NULL;
  141. }
  142. pAddressMapEntry->pszNetwork = NULL;
  143. pAddressMapEntry->ulModifiedMask = 0;
  144. InitializeListHead(&pAddressMapEntry->locationHead);
  145. pAddressMapEntry->params.dwTag = 0xffffffff;
  146. pAddressMapEntry->params.dwModifiedTime = (DWORD)time(0);
  147. return pAddressMapEntry;
  148. } // NewAddressMapEntry
  149. PADDRESS_MAP_ENTRY
  150. GetAddressMapEntry(
  151. IN LPTSTR pszAddress,
  152. IN BOOLEAN fAllocate
  153. )
  154. {
  155. PADDRESS_MAP_ENTRY pAddressMapEntry = NULL;
  156. if (pszAddress == NULL)
  157. return NULL;
  158. if (GetTableEntry(
  159. AddressMapG.pTable,
  160. pszAddress,
  161. &pAddressMapEntry))
  162. {
  163. goto done;
  164. }
  165. if (fAllocate) {
  166. pAddressMapEntry = NewAddressMapEntry();
  167. if (pAddressMapEntry == NULL) {
  168. RASAUTO_TRACE("GetAddressMapEntry: NewAddressMapEntry failed");
  169. goto done;
  170. }
  171. if (!PutTableEntry(AddressMapG.pTable, pszAddress, pAddressMapEntry))
  172. {
  173. RASAUTO_TRACE("GetAddressMapEntry: PutTableEntry failed");
  174. LocalFree(pAddressMapEntry);
  175. pAddressMapEntry = NULL;
  176. goto done;
  177. }
  178. }
  179. done:
  180. return pAddressMapEntry;
  181. } // GetAddressMapEntry
  182. VOID
  183. FreeAddressMapEntry(
  184. IN PADDRESS_MAP_ENTRY pAddressMapEntry
  185. )
  186. {
  187. PLIST_ENTRY pEntry;
  188. PADDRESS_DIALING_ENTRY pDialingEntry;
  189. //
  190. // Free all dynamically allocated strings.
  191. //
  192. if (pAddressMapEntry->pszNetwork != NULL)
  193. LocalFree(pAddressMapEntry->pszNetwork);
  194. while (!IsListEmpty(&pAddressMapEntry->locationHead)) {
  195. pEntry = RemoveHeadList(&pAddressMapEntry->locationHead);
  196. pDialingEntry =
  197. CONTAINING_RECORD(pEntry, ADDRESS_DIALING_ENTRY, ListEntry);
  198. LocalFree(pDialingEntry);
  199. }
  200. //
  201. }
  202. BOOLEAN
  203. ResetDriver()
  204. {
  205. NTSTATUS status;
  206. IO_STATUS_BLOCK ioStatusBlock;
  207. status = NtDeviceIoControlFile(
  208. hAcdG,
  209. NULL,
  210. NULL,
  211. NULL,
  212. &ioStatusBlock,
  213. IOCTL_ACD_RESET,
  214. NULL,
  215. 0,
  216. NULL,
  217. 0);
  218. if (status != STATUS_SUCCESS) {
  219. RASAUTO_TRACE1(
  220. "ResetDriver: NtDeviceIoControlFile failed (status=0x%x)",
  221. status);
  222. return FALSE;
  223. }
  224. return TRUE;
  225. } // ResetDriver
  226. BOOLEAN
  227. EnableDriver()
  228. {
  229. NTSTATUS status;
  230. DWORD dwErr;
  231. IO_STATUS_BLOCK ioStatusBlock;
  232. BOOLEAN fEnable = TRUE;
  233. dwErr = AutoDialEnabled(&fEnable);
  234. RASAUTO_TRACE1("EnableDriver: fEnable=%d", fEnable);
  235. status = NtDeviceIoControlFile(
  236. hAcdG,
  237. NULL,
  238. NULL,
  239. NULL,
  240. &ioStatusBlock,
  241. IOCTL_ACD_ENABLE,
  242. &fEnable,
  243. sizeof (fEnable),
  244. NULL,
  245. 0);
  246. if (status != STATUS_SUCCESS) {
  247. RASAUTO_TRACE1(
  248. "ResetDriver: NtDeviceIoControlFile failed (status=0x%x)",
  249. status);
  250. return FALSE;
  251. }
  252. return TRUE;
  253. } // EnableDriver
  254. PADDRESS_DIALING_ENTRY
  255. FindAddressDialingEntry(
  256. IN PADDRESS_MAP_ENTRY pAddressMapEntry,
  257. IN DWORD dwLocation
  258. )
  259. {
  260. PLIST_ENTRY pEntry;
  261. PADDRESS_DIALING_ENTRY pDialingEntry;
  262. for (pEntry = pAddressMapEntry->locationHead.Flink;
  263. pEntry != &pAddressMapEntry->locationHead;
  264. pEntry = pEntry->Flink)
  265. {
  266. pDialingEntry = CONTAINING_RECORD(
  267. pEntry,
  268. ADDRESS_DIALING_ENTRY,
  269. ListEntry);
  270. if (pDialingEntry->location.dwLocation == dwLocation)
  271. return pDialingEntry;
  272. }
  273. return NULL;
  274. } // FindAddressDialingEntry
  275. BOOLEAN
  276. ClearAddressMapEntry(
  277. IN PVOID pArg,
  278. IN LPTSTR pszAddress,
  279. IN PVOID pData
  280. )
  281. {
  282. PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
  283. FreeAddressMapEntry(pAddressMapEntry);
  284. return TRUE;
  285. } // ClearAddressMapEntry
  286. VOID
  287. ClearAddressMap(VOID)
  288. {
  289. EnumTable(AddressMapG.pTable, ClearAddressMapEntry, NULL);
  290. ClearTable(AddressMapG.pTable);
  291. } // ClearAddressMap
  292. VOID
  293. ResetAddressMapAddress(
  294. IN LPTSTR pszAddress
  295. )
  296. {
  297. DWORD dwErr, dwcb, dwcAddresses, dwcEntries;
  298. DWORD i, j;
  299. PADDRESS_MAP_ENTRY pAddressMapEntry = NULL;
  300. PADDRESS_LOCATION_INFORMATION pLocationInfo = NULL;
  301. RASAUTO_TRACE1("ResetAddressMapAddress(%S)", pszAddress);
  302. dwErr = GetAddressDialingLocationInfo(
  303. pszAddress,
  304. &pLocationInfo,
  305. &dwcEntries);
  306. if (dwErr || !dwcEntries)
  307. return;
  308. //
  309. // Enter this address into the address map
  310. // if it doesn't already exist.
  311. //
  312. if (!GetTableEntry(AddressMapG.pTable, pszAddress, &pAddressMapEntry)) {
  313. pAddressMapEntry = NewAddressMapEntry();
  314. if (pAddressMapEntry == NULL) {
  315. RASAUTO_TRACE("ResetAddressMapAddress: NewAddressMapEntry failed");
  316. goto done;
  317. }
  318. pAddressMapEntry->fDisabled = FALSE;
  319. RASAUTO_TRACE1(
  320. "ResetAddressMap: inserting pszAddress=%S",
  321. RASAUTO_TRACESTRW(pszAddress));
  322. if (!PutTableEntry(
  323. AddressMapG.pTable,
  324. pszAddress,
  325. pAddressMapEntry))
  326. {
  327. RASAUTO_TRACE("ResetAddressMapAddress: PutTableEntry failed");
  328. goto done;
  329. }
  330. }
  331. //
  332. // Get the network for this address.
  333. //
  334. if (pAddressMapEntry->pszNetwork == NULL) {
  335. pAddressMapEntry->pszNetwork = AddressToNetwork(pszAddress);
  336. if (pAddressMapEntry->pszNetwork == NULL) {
  337. RASAUTO_TRACE1(
  338. "ResetAddressMapAddress: AddressToNetwork(%S) failed",
  339. pszAddress);
  340. LocalFree(pAddressMapEntry);
  341. goto done;
  342. }
  343. }
  344. //
  345. // Read the Autodial parameters for this address.
  346. //
  347. GetAddressParams(pszAddress, &pAddressMapEntry->params);
  348. //
  349. // Add this address to the associated
  350. // network map.
  351. //
  352. LockNetworkMap();
  353. AddNetworkAddress(
  354. pAddressMapEntry->pszNetwork,
  355. pszAddress,
  356. pAddressMapEntry->params.dwTag);
  357. UnlockNetworkMap();
  358. //
  359. // Add each dialing location onto
  360. // the address's list.
  361. //
  362. for (j = 0; j < dwcEntries; j++) {
  363. PADDRESS_DIALING_ENTRY pDialingEntry;
  364. pDialingEntry = FindAddressDialingEntry(
  365. pAddressMapEntry,
  366. pLocationInfo[j].dwLocation);
  367. if (pDialingEntry == NULL) {
  368. //
  369. // The dialing entry doesn't exist.
  370. // We need to create it.
  371. //
  372. pDialingEntry = LocalAlloc(LPTR, sizeof (ADDRESS_DIALING_ENTRY));
  373. if (pDialingEntry == NULL) {
  374. RASAUTO_TRACE("ResetAddressMapAddress: LocalAlloc failed");
  375. goto done;
  376. }
  377. RASAUTO_TRACE1(
  378. "ResetAddressMapAddress: inserting dwLocationID=%d",
  379. pLocationInfo[j].dwLocation);
  380. pDialingEntry->fChanged = FALSE;
  381. pDialingEntry->location = pLocationInfo[j];
  382. InsertTailList(&pAddressMapEntry->locationHead, &pDialingEntry->ListEntry);
  383. }
  384. else if (_wcsicmp(
  385. pDialingEntry->location.pszEntryName,
  386. pLocationInfo[j].pszEntryName))
  387. {
  388. //
  389. // The dialing entry does exist, but
  390. // the phonebook entry has changed.
  391. //
  392. RASAUTO_TRACE2(
  393. "ResetAddressMapAddress: updating dwLocationID=%d with %S",
  394. pLocationInfo[j].dwLocation,
  395. RASAUTO_TRACESTRW(pLocationInfo[j].pszEntryName));
  396. pDialingEntry->location.pszEntryName =
  397. pLocationInfo[j].pszEntryName;
  398. }
  399. else {
  400. //
  401. // The dialing entry exists, and we
  402. // already have it loaded.
  403. //
  404. RASAUTO_TRACE1(
  405. "ResetAddressMapAddress: no changes for dwLocationID=%d",
  406. pLocationInfo[j].dwLocation);
  407. LocalFree(pLocationInfo[j].pszEntryName);
  408. }
  409. }
  410. done:
  411. LocalFree(pLocationInfo);
  412. } // ResetAddressMapAddress
  413. BOOLEAN
  414. ResetAddressMap(
  415. IN BOOLEAN fClear
  416. )
  417. {
  418. BOOLEAN fSuccess = FALSE;
  419. DWORD dwErr, i, dwcb, dwcAddresses;
  420. LPTSTR *ppAddresses = NULL;
  421. //
  422. // Clear the current addresses from the table.
  423. // and reset the driver.
  424. //
  425. if (fClear) {
  426. LockAddressMap();
  427. ClearAddressMap();
  428. UnlockAddressMap();
  429. if (!ResetDriver())
  430. return FALSE;
  431. }
  432. //
  433. // Enumerate the Autodial addresses.
  434. //
  435. dwErr = EnumAutodialAddresses(NULL, &dwcb, &dwcAddresses);
  436. if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL) {
  437. RASAUTO_TRACE1(
  438. "ResetAddressMap: RasEnumAutodialAddresses failed (dwErr=%d)",
  439. dwErr);
  440. return FALSE;
  441. }
  442. if (!dwcAddresses)
  443. return TRUE;
  444. ppAddresses = LocalAlloc(LPTR, dwcb);
  445. if (ppAddresses == NULL) {
  446. RASAUTO_TRACE("ResetAddressMap: LocalAlloc failed");
  447. return FALSE;
  448. }
  449. dwErr = EnumAutodialAddresses(
  450. ppAddresses,
  451. &dwcb,
  452. &dwcAddresses);
  453. if (dwErr) {
  454. RASAUTO_TRACE1(
  455. "ResetAddressMap: RasEnumAutodialAddresses failed (dwErr=%d)",
  456. dwErr);
  457. goto done;
  458. }
  459. //
  460. // Get the Autodial information for
  461. // each of the addresses.
  462. //
  463. LockAddressMap();
  464. for (i = 0; i < dwcAddresses; i++)
  465. ResetAddressMapAddress(ppAddresses[i]);
  466. UnlockAddressMap();
  467. LocalFree(ppAddresses);
  468. ppAddresses = NULL;
  469. fSuccess = TRUE;
  470. done:
  471. //
  472. // Free resources.
  473. //
  474. if (ppAddresses != NULL)
  475. LocalFree(ppAddresses);
  476. return fSuccess;
  477. } // ResetAddressMap
  478. BOOLEAN
  479. InitializeAddressMap()
  480. {
  481. DWORD dwErr;
  482. RasInitializeCriticalSection(&AddressMapG.csLock, &dwErr);
  483. if(dwErr != ERROR_SUCCESS)
  484. {
  485. return FALSE;
  486. }
  487. g_dwCritSecFlags |= RASAUTO_CRITSEC_ADDRMAP;
  488. AddressMapG.pTable = NewTable();
  489. if (AddressMapG.pTable == NULL) {
  490. RASAUTO_TRACE("InitializeAddressMap: NewTable failed");
  491. DeleteCriticalSection(&AddressMapG.csLock);
  492. g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_ADDRMAP);
  493. return FALSE;
  494. }
  495. return TRUE;
  496. } // InitializeAddressMap
  497. VOID
  498. UninitializeAddressMap()
  499. {
  500. if(g_dwCritSecFlags & RASAUTO_CRITSEC_ADDRMAP)
  501. {
  502. DeleteCriticalSection(&AddressMapG.csLock);
  503. g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_ADDRMAP);
  504. }
  505. }
  506. VOID
  507. LockAddressMap()
  508. {
  509. EnterCriticalSection(&AddressMapG.csLock);
  510. } // LockAddressMap
  511. VOID
  512. UnlockAddressMap()
  513. {
  514. LeaveCriticalSection(&AddressMapG.csLock);
  515. } // UnlockAddressMap
  516. VOID
  517. LockDisabledAddresses()
  518. {
  519. EnterCriticalSection(&csDisabledAddressesLockG);
  520. }
  521. VOID
  522. UnlockDisabledAddresses()
  523. {
  524. LeaveCriticalSection(&csDisabledAddressesLockG);
  525. }
  526. BOOLEAN
  527. WriteRegistryFields(
  528. IN LPTSTR pszAddress,
  529. IN PADDRESS_MAP_ENTRY pAddressMapEntry
  530. )
  531. {
  532. DWORD dwErr;
  533. PLIST_ENTRY pEntry;
  534. PADDRESS_DIALING_ENTRY pDialingEntry;
  535. //
  536. // Write the address garbage-collection params.
  537. //
  538. if (pAddressMapEntry->ulModifiedMask & ADDRESS_MAP_FIELD_PARAMS) {
  539. dwErr = SetAddressParams(pszAddress, &pAddressMapEntry->params);
  540. if (dwErr)
  541. return FALSE;
  542. pAddressMapEntry->ulModifiedMask &= ~ADDRESS_MAP_FIELD_PARAMS;
  543. }
  544. //
  545. // Write the dialing location information.
  546. //
  547. if (pAddressMapEntry->ulModifiedMask & ADDRESS_MAP_FIELD_DIALINGLOC) {
  548. for (pEntry = pAddressMapEntry->locationHead.Flink;
  549. pEntry != &pAddressMapEntry->locationHead;
  550. pEntry = pEntry->Flink)
  551. {
  552. LPTSTR pszPhonebook, pszEntry;
  553. pDialingEntry = CONTAINING_RECORD(
  554. pEntry,
  555. ADDRESS_DIALING_ENTRY,
  556. ListEntry);
  557. if (!pDialingEntry->fChanged)
  558. continue;
  559. RASAUTO_TRACE3(
  560. "WriteRegistryFields: writing %S=%d/%S",
  561. RASAUTO_TRACESTRW(pszAddress),
  562. pDialingEntry->location.dwLocation,
  563. pDialingEntry->location.pszEntryName);
  564. dwErr = SetAddressDialingLocationInfo(
  565. pszAddress,
  566. &pDialingEntry->location);
  567. if (dwErr)
  568. return FALSE;
  569. pDialingEntry->fChanged = FALSE;
  570. }
  571. //
  572. // If the network value for this address
  573. // is NULL, read it now from the registry.
  574. //
  575. if (pAddressMapEntry->pszNetwork == NULL) {
  576. pAddressMapEntry->pszNetwork = AddressToNetwork(pszAddress);
  577. if (pAddressMapEntry->pszNetwork == NULL) {
  578. RASAUTO_TRACE1(
  579. "WriteRegistryFields: AddressToNetwork(%S) failed",
  580. RASAUTO_TRACESTRW(pszAddress));
  581. }
  582. }
  583. //
  584. // Clear the modified field mask.
  585. //
  586. pAddressMapEntry->ulModifiedMask &= ~ADDRESS_MAP_FIELD_DIALINGLOC;
  587. }
  588. return TRUE;
  589. } // WriteRegistryFields
  590. BOOLEAN
  591. BuildAddressList(
  592. IN PVOID pArg,
  593. IN LPTSTR pszAddress,
  594. IN PVOID pData
  595. )
  596. {
  597. PADDRESS_LIST_INFO pAddressListInfo = (PADDRESS_LIST_INFO)pArg;
  598. PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
  599. PADDRESS_MAP_ENTRY pAddrMapEntry;
  600. PLIST_ENTRY pPrevEntry, pEntry;
  601. DWORD dwTag = pAddressMapEntry->params.dwTag;
  602. //
  603. // If the address does not have any
  604. // dialing location information, then
  605. // skip it.
  606. //
  607. if (IsListEmpty(&pAddressMapEntry->locationHead)) {
  608. pAddressMapEntry->fPruned = TRUE;
  609. RASAUTO_TRACE1("BuildAddressList: %S has no location info", pszAddress);
  610. return TRUE;
  611. }
  612. dwTag = pAddressMapEntry->params.dwTag < ADDRMAP_TAG_LEARNED ?
  613. pAddressMapEntry->params.dwTag :
  614. ADDRMAP_TAG_LEARNED;
  615. //
  616. // If the list is empty, insert it at the head.
  617. // Otherwise sort the items in descending order
  618. // by last modified time per tag. There is no order
  619. // for ADDRMAP_TAG_NONE addresses, so we insert them
  620. // all at the head of the list.
  621. //
  622. if (dwTag == ADDRMAP_TAG_NONE ||
  623. IsListEmpty(&pAddressListInfo->tagHead[dwTag]))
  624. {
  625. InsertHeadList(&pAddressListInfo->tagHead[dwTag], &pAddressMapEntry->writerList);
  626. }
  627. else {
  628. BOOLEAN fInserted = FALSE;
  629. pPrevEntry = &pAddressListInfo->tagHead[dwTag];
  630. for (pEntry = pAddressListInfo->tagHead[dwTag].Flink;
  631. pEntry != &pAddressListInfo->tagHead[dwTag];
  632. pEntry = pEntry->Flink)
  633. {
  634. pAddrMapEntry = CONTAINING_RECORD(pEntry, ADDRESS_MAP_ENTRY, writerList);
  635. //
  636. // There are two cases to skip to the next
  637. // entry:
  638. //
  639. // (1) If the tag is either ADDRMAP_TAG_NONE or
  640. // ADDRMAP_TAG_USED, then we insert sorted
  641. // by dwModifiedTime.
  642. // (2) If the tag is ADDRMAP_TAG_LEARNED, then
  643. // we insert sorted by dwTag, and then by
  644. // dwModifiedTime.
  645. // dwTag.
  646. //
  647. if ((dwTag < ADDRMAP_TAG_LEARNED &&
  648. pAddressMapEntry->params.dwModifiedTime <=
  649. pAddrMapEntry->params.dwModifiedTime) ||
  650. (dwTag == ADDRMAP_TAG_LEARNED &&
  651. (pAddressMapEntry->params.dwTag >
  652. pAddrMapEntry->params.dwTag) ||
  653. (pAddressMapEntry->params.dwTag ==
  654. pAddrMapEntry->params.dwTag &&
  655. (pAddressMapEntry->params.dwModifiedTime <=
  656. pAddrMapEntry->params.dwModifiedTime))))
  657. {
  658. pPrevEntry = pEntry;
  659. continue;
  660. }
  661. InsertHeadList(pPrevEntry, &pAddressMapEntry->writerList);
  662. fInserted = TRUE;
  663. break;
  664. }
  665. if (!fInserted) {
  666. InsertTailList(
  667. &pAddressListInfo->tagHead[dwTag],
  668. &pAddressMapEntry->writerList);
  669. }
  670. }
  671. return TRUE;
  672. } // BuildAddressList
  673. VOID
  674. MarkAddressList(
  675. IN PADDRESS_LIST_INFO pAddressListInfo
  676. )
  677. {
  678. DWORD i, dwcAddresses = 0;
  679. DWORD dwMaxAddresses = GetAutodialParam(RASADP_SavedAddressesLimit);
  680. PLIST_ENTRY pEntry;
  681. PADDRESS_MAP_ENTRY pAddressMapEntry;
  682. RASAUTO_TRACE1("MarkAddressList: RASADP_SavedAddressesLimit=%d", dwMaxAddresses);
  683. //
  684. // Enumerate the entries in the list in order,
  685. // and mark the fPruned bit if its order in the
  686. // list exceeds the maximum set by the user.
  687. // We do not include the ADDRMAP_TAG_NONE address
  688. // in the address count. All of these addresses
  689. // always get written.
  690. //
  691. for (i = 0; i < 3; i++) {
  692. for (pEntry = pAddressListInfo->tagHead[i].Flink;
  693. pEntry != &pAddressListInfo->tagHead[i];
  694. pEntry = pEntry->Flink)
  695. {
  696. pAddressMapEntry = CONTAINING_RECORD(pEntry, ADDRESS_MAP_ENTRY, writerList);
  697. //
  698. // If we exceed the limit of addresses in the
  699. // registry, we have to delete it.
  700. //
  701. if (i == ADDRMAP_TAG_NONE)
  702. pAddressMapEntry->fPruned = FALSE;
  703. else
  704. pAddressMapEntry->fPruned = (++dwcAddresses > dwMaxAddresses);
  705. }
  706. }
  707. } // MarkAddressList
  708. BOOLEAN
  709. PruneAddressList(
  710. IN PVOID pArg,
  711. IN LPTSTR pszAddress,
  712. IN PVOID pData
  713. )
  714. {
  715. PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
  716. if (pAddressMapEntry->fPruned) {
  717. RASAUTO_TRACE1("PruneAddressList: NEED TO DELETE ADDRESS %S in the driver!", pszAddress);
  718. ClearAddressDialingLocationInfo(pszAddress);
  719. FreeAddressMapEntry(pAddressMapEntry);
  720. DeleteTableEntry(AddressMapG.pTable, pszAddress);
  721. }
  722. return TRUE;
  723. } // PruneAddressList
  724. BOOLEAN
  725. WriteAddressMap(
  726. IN PVOID pArg,
  727. IN LPTSTR pszAddress,
  728. IN PVOID pData
  729. )
  730. {
  731. PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
  732. if (pAddressMapEntry->ulModifiedMask) {
  733. if (!WriteRegistryFields(
  734. pszAddress,
  735. pAddressMapEntry))
  736. {
  737. RASAUTO_TRACE("WriteAddressMap: WriteRegistryFields failed");
  738. }
  739. }
  740. return TRUE;
  741. } // WriteAddressMap
  742. BOOLEAN
  743. FlushAddressMap()
  744. {
  745. ADDRESS_LIST_INFO addressListInfo;
  746. //
  747. // Build a new list sorted by address tag and modified
  748. // date.
  749. //
  750. InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_LEARNED]);
  751. InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_USED]);
  752. InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_NONE]);
  753. EnumTable(AddressMapG.pTable, BuildAddressList, &addressListInfo);
  754. MarkAddressList(&addressListInfo);
  755. EnumTable(AddressMapG.pTable, PruneAddressList, NULL);
  756. //
  757. // Turn off registry change notifications
  758. // while we are doing this.
  759. //
  760. EnableAutoDialChangeEvent(hAutodialRegChangeG, FALSE);
  761. EnumTable(AddressMapG.pTable, WriteAddressMap, NULL);
  762. //
  763. // Enable registry change events again.
  764. //
  765. EnableAutoDialChangeEvent(hAutodialRegChangeG, TRUE);
  766. return TRUE;
  767. } // FlushAddressMap
  768. ULONG
  769. AddressMapSize()
  770. {
  771. return AddressMapG.pTable->ulSize;
  772. } // AddressMapSize;
  773. BOOLEAN
  774. EnumAddresses(
  775. IN PVOID pArg,
  776. IN LPTSTR pszAddress,
  777. IN PVOID pData
  778. )
  779. {
  780. PADDRESS_ENUM_INFO pEnumInfo = (PADDRESS_ENUM_INFO)pArg;
  781. pEnumInfo->pAddresses[pEnumInfo->ulIndex++] = CopyString(pszAddress);
  782. return TRUE;
  783. } // EnumAddresses
  784. BOOLEAN
  785. ListAddressMapAddresses(
  786. OUT LPTSTR **ppszAddresses,
  787. OUT PULONG pulcAddresses
  788. )
  789. {
  790. ADDRESS_ENUM_INFO enumInfo;
  791. //
  792. // Check for an empty list.
  793. //
  794. *pulcAddresses = AddressMapG.pTable->ulSize;
  795. if (!*pulcAddresses) {
  796. *ppszAddresses = NULL;
  797. return TRUE;
  798. }
  799. //
  800. // Allocate a list large enough to hold all
  801. // the addresses.
  802. //
  803. *ppszAddresses = LocalAlloc(LPTR, *pulcAddresses * sizeof (LPTSTR));
  804. if (*ppszAddresses == NULL) {
  805. RASAUTO_TRACE("ListAddressMapAddresses: LocalAlloc failed");
  806. return FALSE;
  807. }
  808. //
  809. // Set up the structure for the enumerator
  810. // procedure.
  811. //
  812. enumInfo.ulIndex = 0;
  813. enumInfo.pAddresses = *ppszAddresses;
  814. EnumTable(AddressMapG.pTable, EnumAddresses, &enumInfo);
  815. return TRUE;
  816. } // ListAddressMapAddresses
  817. VOID
  818. EnumAddressMap(
  819. IN PHASH_TABLE_ENUM_PROC pProc,
  820. IN PVOID pArg
  821. )
  822. {
  823. EnumTable(AddressMapG.pTable, pProc, pArg);
  824. } // EnumAddressMap
  825. BOOLEAN
  826. GetAddressDisabled(
  827. IN LPTSTR pszAddress,
  828. OUT PBOOLEAN pfDisabled
  829. )
  830. {
  831. PADDRESS_MAP_ENTRY pAddressMapEntry;
  832. {
  833. DWORD i;
  834. LPTSTR pszDisabled[] =
  835. {
  836. TEXT("wpad"),
  837. TEXT("pnptriage"),
  838. TEXT("nttriage"),
  839. TEXT("ntcore2"),
  840. TEXT("liveraid")
  841. };
  842. for (i = 0; i < sizeof(pszDisabled)/sizeof(LPTSTR); i++)
  843. {
  844. if( (0 == (lstrcmpi(pszDisabled[i], pszAddress)))
  845. || (wcsstr(_wcslwr(pszAddress), pszDisabled[i])
  846. == pszAddress))
  847. {
  848. *pfDisabled = TRUE;
  849. return TRUE;
  850. }
  851. }
  852. }
  853. pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
  854. if (pAddressMapEntry == NULL) {
  855. *pfDisabled = FALSE;
  856. return FALSE;
  857. }
  858. *pfDisabled = pAddressMapEntry->fDisabled;
  859. return TRUE;
  860. } // GetAddressDisabled
  861. BOOLEAN
  862. SetAddressDisabled(
  863. IN LPTSTR pszAddress,
  864. IN BOOLEAN fDisabled
  865. )
  866. {
  867. PADDRESS_MAP_ENTRY pAddressMapEntry;
  868. pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
  869. if (pAddressMapEntry == NULL) {
  870. RASAUTO_TRACE("SetAddressDisabled: GetAddressMapEntry failed");
  871. return FALSE;
  872. }
  873. pAddressMapEntry->fDisabled = fDisabled;
  874. return TRUE;
  875. } // SetAddressDisabled
  876. BOOLEAN
  877. SetAddressDisabledEx(
  878. IN LPTSTR pszAddress,
  879. IN BOOLEAN fDisable
  880. )
  881. {
  882. LONG l;
  883. IO_STATUS_BLOCK ioStatusBlock;
  884. ACD_ENABLE_ADDRESS *pEnableAddress;
  885. //
  886. // .NET bug# 514423 new verbose RASAUTO/RASAUTOU prefast warnings
  887. //
  888. if (!pszAddress)
  889. {
  890. return FALSE;
  891. }
  892. l = InterlockedIncrement(&g_lRasAutoRunning);
  893. InterlockedDecrement(&g_lRasAutoRunning);
  894. if(l == 1)
  895. {
  896. //
  897. // rasauto isn't running. Bail.
  898. //
  899. return TRUE;
  900. }
  901. //
  902. // Also set this address as disabled in the driver
  903. //
  904. pEnableAddress = LocalAlloc(LPTR, sizeof(ACD_ENABLE_ADDRESS));
  905. if(NULL != pEnableAddress)
  906. {
  907. NTSTATUS status;
  908. CHAR *pszNew;
  909. DWORD cb;
  910. cb = WideCharToMultiByte(CP_ACP, 0, pszAddress,
  911. -1, NULL, 0, NULL, NULL);
  912. pszNew = (CHAR*)LocalAlloc(LPTR, cb);
  913. if (pszNew == NULL) {
  914. return FALSE;
  915. }
  916. cb = WideCharToMultiByte(CP_ACP, 0, pszAddress,
  917. -1, pszNew, cb, NULL, NULL);
  918. if (!cb) {
  919. LocalFree(pszNew);
  920. return FALSE;
  921. }
  922. _strlwr(pszNew);
  923. pEnableAddress->fDisable = fDisable;
  924. RtlCopyMemory(pEnableAddress->addr.szInet,
  925. pszNew,
  926. cb);
  927. status = NtDeviceIoControlFile(
  928. hAcdG,
  929. NULL,
  930. NULL,
  931. NULL,
  932. &ioStatusBlock,
  933. IOCTL_ACD_ENABLE_ADDRESS,
  934. pEnableAddress,
  935. sizeof (ACD_ENABLE_ADDRESS),
  936. NULL,
  937. 0);
  938. if (status != STATUS_SUCCESS)
  939. {
  940. RASAUTO_TRACE("SetAddressDisabledEx: ioctl failed");
  941. }
  942. LocalFree(pEnableAddress);
  943. }
  944. return TRUE;
  945. } // SetAddressDisabled
  946. BOOLEAN
  947. GetAddressDialingLocationEntry(
  948. IN LPTSTR pszAddress,
  949. OUT LPTSTR *ppszEntryName
  950. )
  951. {
  952. DWORD dwErr, dwLocationID;
  953. PLIST_ENTRY pEntry;
  954. PADDRESS_MAP_ENTRY pAddressMapEntry;
  955. PADDRESS_DIALING_ENTRY pDialingEntry;
  956. dwErr = TapiCurrentDialingLocation(&dwLocationID);
  957. if (dwErr)
  958. return FALSE;
  959. pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
  960. if (pAddressMapEntry == NULL || IsListEmpty(&pAddressMapEntry->locationHead))
  961. return FALSE;
  962. //
  963. // Search for the dialing information
  964. // that maps to the current dialing
  965. // location.
  966. //
  967. for (pEntry = pAddressMapEntry->locationHead.Flink;
  968. pEntry != &pAddressMapEntry->locationHead;
  969. pEntry = pEntry->Flink)
  970. {
  971. pDialingEntry = CONTAINING_RECORD(
  972. pEntry,
  973. ADDRESS_DIALING_ENTRY,
  974. ListEntry);
  975. if (pDialingEntry->location.dwLocation == dwLocationID) {
  976. *ppszEntryName = CopyString(pDialingEntry->location.pszEntryName);
  977. return TRUE;
  978. }
  979. }
  980. return FALSE;
  981. } // GetAddressDialingLocationEntry
  982. BOOLEAN
  983. IsAWwwAddress(
  984. IN LPTSTR pszAddr
  985. )
  986. {
  987. DWORD dwcbAddress;
  988. DWORD i;
  989. BOOLEAN fDot = FALSE, fIsAWwwAddress = FALSE;
  990. //
  991. // See if this address starts with "www*.".
  992. //
  993. if (!_wcsnicmp(pszAddr, L"www", 3)) {
  994. dwcbAddress = wcslen(pszAddr);
  995. //
  996. // Search for a '.' and something else
  997. // after the '.'.
  998. //
  999. for (i = 3; i < dwcbAddress; i++) {
  1000. if (!fDot)
  1001. fDot = (pszAddr[i] == L'.');
  1002. fIsAWwwAddress = fDot && (pszAddr[i] != L'.');
  1003. if (fIsAWwwAddress)
  1004. break;
  1005. }
  1006. }
  1007. return fIsAWwwAddress;
  1008. } // IsAWwwAddress
  1009. BOOLEAN
  1010. FindSimilarAddress(
  1011. IN PVOID pArg,
  1012. IN LPTSTR pszAddr,
  1013. IN PVOID pData
  1014. )
  1015. /*++
  1016. DESCRIPTION
  1017. This is a table enumerator procedure that searches
  1018. for address with a www-style name or the same
  1019. organization name. For example, it will consider
  1020. "www1.netscape.com" and "www2.netscape.com" equal
  1021. since they share the same organization and domain
  1022. address components.
  1023. ARGUMENTS
  1024. pArg: a pointer to a MATCH_INFO structure
  1025. pszAddr: a pointer to the enumerated address
  1026. ulData: the address's data value
  1027. RETURN VALUE
  1028. TRUE if the enumeration should continue (match
  1029. not found), or FALSE when the enumerations should
  1030. terminate (match found).
  1031. --*/
  1032. {
  1033. BOOLEAN fIsWww = FALSE, fHasOrg = FALSE;
  1034. BOOLEAN fDialingLocationFound;
  1035. PMATCH_INFO pMatchInfo = (PMATCH_INFO)pArg;
  1036. PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
  1037. PLIST_ENTRY pEntry;
  1038. PADDRESS_DIALING_ENTRY pDialingEntry;
  1039. WCHAR szOrganization[ACD_ADDR_INET_LEN];
  1040. if (pMatchInfo->fWww)
  1041. fIsWww = IsAWwwAddress(pszAddr);
  1042. else if (pMatchInfo->fOrg)
  1043. fHasOrg = GetOrganization(pszAddr, szOrganization);
  1044. //
  1045. // If it has neither a www-style address nor
  1046. // it has an organization, then return
  1047. // immediately.
  1048. //
  1049. if ((pMatchInfo->fWww && !fIsWww) ||
  1050. (pMatchInfo->fOrg && !fHasOrg))
  1051. {
  1052. return TRUE;
  1053. }
  1054. if (fIsWww)
  1055. RASAUTO_TRACE1("FindSimilarAddress: fIsWww=1, %S", pszAddr);
  1056. else {
  1057. RASAUTO_TRACE2(
  1058. "FindSimilarAddress: fHasOrg=1, comparing (%S, %S)",
  1059. pMatchInfo->szOrganization,
  1060. szOrganization);
  1061. }
  1062. //
  1063. // If we're looking for an organization,
  1064. // and the organization's don't match,
  1065. // then return.
  1066. //
  1067. if (fHasOrg && _wcsicmp(pMatchInfo->szOrganization, szOrganization))
  1068. {
  1069. return TRUE;
  1070. }
  1071. //
  1072. // Search for the dialing information
  1073. // that maps to the current dialing
  1074. // location.
  1075. //
  1076. fDialingLocationFound = FALSE;
  1077. for (pEntry = pAddressMapEntry->locationHead.Flink;
  1078. pEntry != &pAddressMapEntry->locationHead;
  1079. pEntry = pEntry->Flink)
  1080. {
  1081. pDialingEntry = CONTAINING_RECORD(
  1082. pEntry,
  1083. ADDRESS_DIALING_ENTRY,
  1084. ListEntry);
  1085. if (pDialingEntry->location.dwLocation == pMatchInfo->dwLocationID) {
  1086. fDialingLocationFound = TRUE;
  1087. break;
  1088. }
  1089. }
  1090. if (!fDialingLocationFound) {
  1091. RASAUTO_TRACE1("FindSimilarAddress: dialing location %d not found", pMatchInfo->dwLocationID);
  1092. return TRUE;
  1093. }
  1094. //
  1095. // If we already have found a match,
  1096. // then make sure the network is the
  1097. // same for all the matching addresses.
  1098. // If not terminate the enumeration.
  1099. //
  1100. if (pMatchInfo->bFound &&
  1101. pDialingEntry->location.pszEntryName != NULL &&
  1102. pMatchInfo->pDialingEntry->location.pszEntryName != NULL &&
  1103. _wcsicmp(
  1104. pMatchInfo->pDialingEntry->location.pszEntryName,
  1105. pDialingEntry->location.pszEntryName))
  1106. {
  1107. pMatchInfo->bFound = FALSE;
  1108. RASAUTO_TRACE("FindSimilarAddress: returning FALSE");
  1109. return FALSE;
  1110. }
  1111. //
  1112. // Update the closure and continue
  1113. // the enumeration.
  1114. //
  1115. if (!pMatchInfo->bFound) {
  1116. pMatchInfo->bFound = TRUE;
  1117. wcscpy(pMatchInfo->szAddress, pszAddr);
  1118. pMatchInfo->pDialingEntry = pDialingEntry;
  1119. }
  1120. return TRUE;
  1121. } // FindSimilarAddress
  1122. BOOLEAN
  1123. GetSimilarDialingLocationEntry(
  1124. IN LPTSTR pszAddress,
  1125. OUT LPTSTR *ppszEntryName
  1126. )
  1127. /*++
  1128. DESCRIPTION
  1129. Parse the organization name from the Internet
  1130. address, and look for an address that we know
  1131. about with the same organization name. If we
  1132. find it, make that address our target address.
  1133. This enables us to treat addresses like
  1134. "www1.netscape.com" and "www2.netscape.com"
  1135. equivalently without having to have all
  1136. combinations in our address map.
  1137. ARGUMENTS
  1138. pszAddress: a pointer to the original address
  1139. ppszEntryName: a pointer to the phonebook entry of
  1140. a similar address
  1141. RETURN VALUE
  1142. TRUE if there is a unique phonebook entry;
  1143. FALSE otherwise.
  1144. --*/
  1145. {
  1146. DWORD dwErr;
  1147. MATCH_INFO matchInfo;
  1148. BOOLEAN fIsAWwwAddress = FALSE;
  1149. //
  1150. // Check to see if this is "www*." style address.
  1151. //
  1152. matchInfo.fWww = IsAWwwAddress(pszAddress);
  1153. //
  1154. // Get the organization for the specified address.
  1155. //
  1156. if (!matchInfo.fWww)
  1157. matchInfo.fOrg = GetOrganization(pszAddress, (LPTSTR)&matchInfo.szOrganization);
  1158. else
  1159. matchInfo.fOrg = FALSE;
  1160. if (!matchInfo.fWww && !matchInfo.fOrg) {
  1161. RASAUTO_TRACE1(
  1162. "GetSimilarDialingLocationEntry: %S is not www and has no organization",
  1163. pszAddress);
  1164. return FALSE;
  1165. }
  1166. RASAUTO_TRACE4(
  1167. "GetSimilarDialingLocationEntry: %S: fWww=%d, fOrg=%d, org is %S",
  1168. pszAddress,
  1169. matchInfo.fWww,
  1170. matchInfo.fOrg,
  1171. matchInfo.szOrganization);
  1172. //
  1173. // Search the table.
  1174. //
  1175. dwErr = TapiCurrentDialingLocation(&matchInfo.dwLocationID);
  1176. if (dwErr) {
  1177. RASAUTO_TRACE1(
  1178. "GetSimilarDialingLocationEntry: TapiCurrentDialingLocation failed (dwErr=%d)",
  1179. dwErr);
  1180. return FALSE;
  1181. }
  1182. matchInfo.bFound = FALSE;
  1183. RtlZeroMemory(&matchInfo.szAddress, sizeof (matchInfo.szAddress));
  1184. matchInfo.pDialingEntry = NULL;
  1185. EnumTable(AddressMapG.pTable, FindSimilarAddress, &matchInfo);
  1186. //
  1187. // If we didn't find it, then return.
  1188. //
  1189. if (!matchInfo.bFound) {
  1190. RASAUTO_TRACE1(
  1191. "GetSimilarDialingLocationEntry: %S: did not find matching org",
  1192. pszAddress);
  1193. return FALSE;
  1194. }
  1195. RASAUTO_TRACE2(
  1196. "GetSimilarDialingLocationEntry: %S: matching address is %S",
  1197. pszAddress,
  1198. matchInfo.szAddress);
  1199. //
  1200. // Return the dialing location entry for
  1201. // the matching address.
  1202. //
  1203. return GetAddressDialingLocationEntry(matchInfo.szAddress, ppszEntryName);
  1204. } // GetSimilarDialingLocationEntry
  1205. BOOLEAN
  1206. SetAddressLastFailedConnectTime(
  1207. IN LPTSTR pszAddress
  1208. )
  1209. {
  1210. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1211. pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
  1212. if (pAddressMapEntry == NULL) {
  1213. RASAUTO_TRACE("SetAddressLastFailedConnectTime: GetAddressMapEntry failed");
  1214. return FALSE;
  1215. }
  1216. pAddressMapEntry->dwFailedConnectTicks = GetTickCount();
  1217. return TRUE;
  1218. } // SetAddressLastFailedConnectTime
  1219. BOOLEAN
  1220. GetAddressLastFailedConnectTime(
  1221. IN LPTSTR pszAddress,
  1222. OUT LPDWORD lpdwTicks
  1223. )
  1224. {
  1225. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1226. pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
  1227. if (pAddressMapEntry == NULL) {
  1228. RASAUTO_TRACE("GetAddressLastFailedConnectTime: GetAddressMapEntry failed");
  1229. return FALSE;
  1230. }
  1231. *lpdwTicks = pAddressMapEntry->dwFailedConnectTicks;
  1232. return (*lpdwTicks != 0);
  1233. } // GetAddressLastFailedConnectTime
  1234. BOOLEAN
  1235. SetAddressTag(
  1236. IN LPTSTR pszAddress,
  1237. IN DWORD dwTag
  1238. )
  1239. {
  1240. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1241. time_t clock = time(0);
  1242. pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
  1243. if (pAddressMapEntry == NULL) {
  1244. RASAUTO_TRACE("SetAddressWeight: GetAddressMapEntry failed");
  1245. return FALSE;
  1246. }
  1247. if (dwTag == ADDRMAP_TAG_LEARNED) {
  1248. LockNetworkMap();
  1249. dwTag =
  1250. ADDRMAP_TAG_LEARNED +
  1251. GetNetworkConnectionTag(
  1252. pAddressMapEntry->pszNetwork,
  1253. FALSE);
  1254. if (dwTag < pAddressMapEntry->params.dwTag) {
  1255. //
  1256. // We want to use this tag. Call
  1257. // GetNetworkConnectionTag(TRUE) to
  1258. // increment the next tag.
  1259. //
  1260. (void)GetNetworkConnectionTag(pAddressMapEntry->pszNetwork, TRUE);
  1261. }
  1262. UnlockNetworkMap();
  1263. }
  1264. //
  1265. // If there is no modified time associated with this
  1266. // address then it can only have a tag of ADDR_TAG_NONE.
  1267. //
  1268. if (!pAddressMapEntry->params.dwModifiedTime ||
  1269. dwTag >= pAddressMapEntry->params.dwTag)
  1270. {
  1271. return TRUE;
  1272. }
  1273. pAddressMapEntry->params.dwTag = dwTag;
  1274. pAddressMapEntry->params.dwModifiedTime = (DWORD)clock;
  1275. pAddressMapEntry->ulModifiedMask |= ADDRESS_MAP_FIELD_PARAMS;
  1276. return TRUE;
  1277. } // SetAddressTag
  1278. BOOLEAN
  1279. GetAddressTag(
  1280. IN LPTSTR pszAddress,
  1281. OUT LPDWORD lpdwTag
  1282. )
  1283. {
  1284. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1285. pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
  1286. if (pAddressMapEntry == NULL) {
  1287. RASAUTO_TRACE("GetAddressWeight: GetAddressMapEntry failed");
  1288. return FALSE;
  1289. }
  1290. *lpdwTag = pAddressMapEntry->params.dwTag;
  1291. return TRUE;
  1292. } // GetAddressWeight
  1293. VOID
  1294. ResetLearnedAddressIndex()
  1295. {
  1296. dwLearnedAddressIndexG = 0;
  1297. } // ResetLearnedAddressIndex
  1298. BOOLEAN
  1299. GetAddressNetwork(
  1300. IN LPTSTR pszAddress,
  1301. OUT LPTSTR *ppszNetwork
  1302. )
  1303. {
  1304. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1305. pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
  1306. if (pAddressMapEntry == NULL || pAddressMapEntry->pszNetwork == NULL)
  1307. return FALSE;
  1308. *ppszNetwork = CopyString(pAddressMapEntry->pszNetwork);
  1309. return TRUE;
  1310. } // GetAddressNetwork
  1311. BOOLEAN
  1312. SetAddressDialingLocationEntry(
  1313. IN LPTSTR pszAddress,
  1314. IN LPTSTR pszEntryName
  1315. )
  1316. {
  1317. DWORD dwErr, dwLocationID;
  1318. BOOLEAN fFound = FALSE;
  1319. PLIST_ENTRY pEntry;
  1320. PADDRESS_MAP_ENTRY pAddressMapEntry;
  1321. PADDRESS_DIALING_ENTRY pDialingEntry;
  1322. //
  1323. // Get the current dialing location.
  1324. //
  1325. dwErr = TapiCurrentDialingLocation(&dwLocationID);
  1326. if (dwErr)
  1327. return FALSE;
  1328. //
  1329. // Find the address map entry that
  1330. // corresponds to the address.
  1331. //
  1332. pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
  1333. if (pAddressMapEntry == NULL) {
  1334. RASAUTO_TRACE("SetAddressDialingLocationEntry: GetAddressMapEntry failed");
  1335. return FALSE;
  1336. }
  1337. //
  1338. // Search for the existing dialing
  1339. // information that maps to the current
  1340. // dialing location.
  1341. //
  1342. for (pEntry = pAddressMapEntry->locationHead.Flink;
  1343. pEntry != &pAddressMapEntry->locationHead;
  1344. pEntry = pEntry->Flink)
  1345. {
  1346. pDialingEntry = CONTAINING_RECORD(
  1347. pEntry,
  1348. ADDRESS_DIALING_ENTRY,
  1349. ListEntry);
  1350. if (pDialingEntry->location.dwLocation == dwLocationID) {
  1351. fFound = TRUE;
  1352. break;
  1353. }
  1354. }
  1355. //
  1356. // If we didn't find one, then
  1357. // create a new one.
  1358. //
  1359. if (!fFound) {
  1360. pDialingEntry = LocalAlloc(LPTR, sizeof (ADDRESS_DIALING_ENTRY));
  1361. if (pDialingEntry == NULL) {
  1362. RASAUTO_TRACE("SetAddressDialingLocationEntry: LocalAlloc failed");
  1363. return FALSE;
  1364. }
  1365. pDialingEntry->location.dwLocation = dwLocationID;
  1366. InsertTailList(&pAddressMapEntry->locationHead, &pDialingEntry->ListEntry);
  1367. }
  1368. //
  1369. // Update the dialing location structure
  1370. // with the new values.
  1371. //
  1372. pDialingEntry->fChanged = TRUE;
  1373. if (pDialingEntry->location.pszEntryName != NULL)
  1374. LocalFree(pDialingEntry->location.pszEntryName);
  1375. pDialingEntry->location.pszEntryName = CopyString(pszEntryName);
  1376. pAddressMapEntry->ulModifiedMask |= ADDRESS_MAP_FIELD_DIALINGLOC;
  1377. return TRUE;
  1378. } // SetAddressDialingLocationEntry
  1379. VOID
  1380. ResetDisabledAddresses(VOID)
  1381. {
  1382. HKEY hkey = NULL;
  1383. DWORD dwErr, i, dwi, dwLength, dwDisp, dwcbDisabledAddresses, dwType;
  1384. LPTSTR pszStart, pszNull, pszDisabledAddresses;
  1385. RASAUTO_TRACE("resetting disabled addresses");
  1386. ClearTable(pDisabledAddressesG);
  1387. //
  1388. // Hold the impersonation lock because otherwise
  1389. // hkeycug may be free from under this function.
  1390. //
  1391. LockImpersonation();
  1392. //
  1393. // Make sure that we have hkcu
  1394. //
  1395. dwErr = DwGetHkcu();
  1396. if(ERROR_SUCCESS != dwErr)
  1397. {
  1398. goto done;
  1399. }
  1400. dwErr = RegCreateKeyEx(
  1401. hkeyCUG,
  1402. AUTODIAL_REGCONTROLBASE,
  1403. 0,
  1404. NULL,
  1405. REG_OPTION_NON_VOLATILE,
  1406. KEY_ALL_ACCESS,
  1407. NULL,
  1408. &hkey,
  1409. &dwDisp);
  1410. if (dwErr) {
  1411. RASAUTO_TRACE1("ResetDisabledAddresses: RegCreateKey failed (dwErr=%d)", dwErr);
  1412. goto done;
  1413. }
  1414. if (RegGetValue(
  1415. hkey,
  1416. AUTODIAL_REGDISABLEDADDRVALUE,
  1417. &pszDisabledAddresses,
  1418. &dwcbDisabledAddresses,
  1419. &dwType) &&
  1420. (REG_MULTI_SZ == dwType) &&
  1421. dwcbDisabledAddresses)
  1422. {
  1423. //
  1424. // The registry key exists. Load only the addresses
  1425. // found in the registry into the table.
  1426. //
  1427. pszStart = pszDisabledAddresses;
  1428. for (;;) {
  1429. if (*pszStart == TEXT('\0'))
  1430. break;
  1431. pszNull = _tcschr(pszStart, '\0');
  1432. RASAUTO_TRACE1(
  1433. "ResetDisabledAddresses: adding %S as a disabled address",
  1434. pszStart);
  1435. PutTableEntry(pDisabledAddressesG, pszStart, NULL);
  1436. pszStart = pszNull + 1;
  1437. }
  1438. LocalFree(pszDisabledAddresses);
  1439. }
  1440. else {
  1441. //
  1442. // Initialize the disabled address table
  1443. // with the list of default disabled addresses.
  1444. //
  1445. dwcbDisabledAddresses = 1; // account for extra NULL at the end
  1446. for (i = 0; i < MAX_DISABLED_ADDRESSES; i++) {
  1447. RASAUTO_TRACE1(
  1448. "ResetDisabledAddresses: adding %S as a disabled address",
  1449. szDisabledAddresses[i]);
  1450. PutTableEntry(pDisabledAddressesG, szDisabledAddresses[i], NULL);
  1451. dwcbDisabledAddresses += _tcslen(szDisabledAddresses[i]) + 1;
  1452. }
  1453. pszDisabledAddresses = LocalAlloc(
  1454. LPTR,
  1455. dwcbDisabledAddresses * sizeof (TCHAR));
  1456. if (pszDisabledAddresses != NULL) {
  1457. *pszDisabledAddresses = TEXT('\0');
  1458. //
  1459. // A REG_MULTI_SZ has the strings separated by
  1460. // a NULL character and two NULL characters at
  1461. // the end.
  1462. //
  1463. for (i = 0, dwi = 0; i < MAX_DISABLED_ADDRESSES; i++) {
  1464. _tcscpy(&pszDisabledAddresses[dwi], szDisabledAddresses[i]);
  1465. dwi += _tcslen(szDisabledAddresses[i]) + 1;
  1466. }
  1467. dwErr = RegSetValueEx(
  1468. hkey,
  1469. AUTODIAL_REGDISABLEDADDRVALUE,
  1470. 0,
  1471. REG_MULTI_SZ,
  1472. (PVOID)pszDisabledAddresses,
  1473. dwcbDisabledAddresses * sizeof (TCHAR));
  1474. if (dwErr)
  1475. RASAUTO_TRACE1("ResetDisabledAddresses: RegSetValue failed (dwErr=%d)", dwErr);
  1476. LocalFree(pszDisabledAddresses);
  1477. }
  1478. }
  1479. done:
  1480. if(NULL != hkey)
  1481. {
  1482. RegCloseKey(hkey);
  1483. }
  1484. UnlockImpersonation();
  1485. } // ResetDisabledAddresses
  1486. //
  1487. // Handles a new user coming active in the system (either by logging in or by
  1488. // FUS.
  1489. //
  1490. DWORD
  1491. AcsHandleNewUser(
  1492. IN HANDLE* phProcess)
  1493. {
  1494. DWORD dwErr = NO_ERROR;
  1495. HANDLE hProcess = *phProcess;
  1496. DWORD i;
  1497. do
  1498. {
  1499. //
  1500. // make sure that we think there is no user currently
  1501. // active.
  1502. //
  1503. if (hProcess != NULL)
  1504. {
  1505. RASAUTO_TRACE(
  1506. "AcsHandleNewUser: spurious signal of RasAutodialNewLogonUser event!");
  1507. break;
  1508. }
  1509. RASAUTO_TRACE("AcsHandleNewUser: new user came active");
  1510. //
  1511. // Refresh the impersonation token for this thread with that of the
  1512. // newly logged-in user. You may have to wait for the shell to
  1513. // start up.
  1514. //
  1515. for (i = 0; i < 15; i++)
  1516. {
  1517. Sleep(1000);
  1518. hProcess = RefreshImpersonation(hProcess);
  1519. if (hProcess != NULL)
  1520. {
  1521. break;
  1522. }
  1523. RASAUTO_TRACE("AcsHandleNewUser: waiting for shell startup");
  1524. }
  1525. if (hProcess == NULL)
  1526. {
  1527. RASAUTO_TRACE("AcsHandleNewUser: wait for shell startup failed!");
  1528. dwErr = ERROR_CAN_NOT_COMPLETE;
  1529. break;
  1530. }
  1531. //
  1532. // Load in the list of permanently disabled addresses.
  1533. //
  1534. LockDisabledAddresses();
  1535. ResetDisabledAddresses();
  1536. UnlockDisabledAddresses();
  1537. //
  1538. // Load in the address map from the registry.
  1539. //
  1540. if (!ResetAddressMap(TRUE))
  1541. {
  1542. RASAUTO_TRACE("AcsHandleNewUser: ResetAddressMap failed");
  1543. dwErr = ERROR_CAN_NOT_COMPLETE;
  1544. break;
  1545. }
  1546. //
  1547. // Calculate the initial network connectivity.
  1548. //
  1549. if (!UpdateNetworkMap(TRUE))
  1550. {
  1551. RASAUTO_TRACE("AcsHandleNewUser: UpdateNetworkMap failed");
  1552. dwErr = ERROR_CAN_NOT_COMPLETE;
  1553. break;
  1554. }
  1555. //
  1556. // Reset the "disable autodial for this login session" flag.
  1557. //
  1558. SetAutodialParam(RASADP_LoginSessionDisable, 0);
  1559. //
  1560. // Create an event to monitor AutoDial
  1561. // registry changes.
  1562. //
  1563. dwErr = CreateAutoDialChangeEvent(&hAutodialRegChangeG);
  1564. if (dwErr)
  1565. {
  1566. RASAUTO_TRACE1("AcsHandleNewUser: CreateAutoDialChangeEvent failed (dwErr=%d)", dwErr);
  1567. break;
  1568. }
  1569. //
  1570. // Enable the driver for notifications.
  1571. //
  1572. if (!EnableDriver())
  1573. {
  1574. RASAUTO_TRACE("AcsHandleNewUser: EnableDriver failed!");
  1575. dwErr = ERROR_CAN_NOT_COMPLETE;
  1576. break;
  1577. }
  1578. }while (FALSE);
  1579. // Cleanup
  1580. {
  1581. *phProcess = hProcess;
  1582. }
  1583. return dwErr;
  1584. }
  1585. DWORD
  1586. AcsAddressMapThread(
  1587. LPVOID lpArg
  1588. )
  1589. /*++
  1590. DESCRIPTION
  1591. Periodically enumerate the disabled address list and
  1592. age-out (enable) old disabled addresses.
  1593. ARGUMENTS
  1594. None.
  1595. RETURN VALUE
  1596. None.
  1597. --*/
  1598. {
  1599. NTSTATUS status;
  1600. BOOLEAN bStatus;
  1601. DWORD dwNow, dwLastFlushTicks = 0, dwLastAgeTicks = 0;
  1602. DWORD dwFlushFlags, dwErr, dwTimeout, dwcEvents;
  1603. HANDLE hProcess = NULL;
  1604. HANDLE hEvents[8];
  1605. //
  1606. // Create the table that contains the disabled addresses
  1607. // for the user. These are addresses that never cause
  1608. // Autodial attempts.
  1609. //
  1610. LockDisabledAddresses();
  1611. pDisabledAddressesG = NewTable();
  1612. UnlockDisabledAddresses();
  1613. if (pDisabledAddressesG == NULL) {
  1614. RASAUTO_TRACE("AcsAddressMapThread: NewTable failed");
  1615. return GetLastError();
  1616. }
  1617. //
  1618. // We can't load the RAS DLLs in the main line
  1619. // of this system service's initialization, or
  1620. // we will cause a deadlock in the service
  1621. // controller, so we do it here.
  1622. //
  1623. if (!LoadRasDlls()) {
  1624. RASAUTO_TRACE("AcsAddressMapThread: LoadRasDlls failed");
  1625. return GetLastError();
  1626. }
  1627. //
  1628. // Initialize the first entry of our
  1629. // event array for WaitForMutlipleObjects
  1630. // below.
  1631. //
  1632. hEvents[0] = hTerminatingG;
  1633. hEvents[1] = hNewLogonUserG;
  1634. hEvents[2] = hNewFusG;
  1635. hEvents[3] = hPnpEventG;
  1636. hEvents[4] = hConnectionEventG;
  1637. //
  1638. // Manually set hNewLogonUserG before we
  1639. // start to force us to check for a user
  1640. // logged into the workstation. We need
  1641. // to do this because userinit.exe signals
  1642. // this event upon logon, but it may
  1643. // run before this service is started
  1644. // after boot.
  1645. //
  1646. if (RefreshImpersonation(NULL) != NULL)
  1647. SetEvent(hNewLogonUserG);
  1648. //
  1649. // Periodically write changes to the registry,
  1650. // and age timeout addresses.
  1651. //
  1652. for (;;) {
  1653. //
  1654. // Unload any user-based resources before
  1655. // a potentially long-term wait.
  1656. //
  1657. // PrepareForLongWait();
  1658. //
  1659. // Construct the event array for
  1660. // WaitForMultipleObjects.
  1661. //
  1662. if (hProcess != NULL) {
  1663. hEvents[5] = hTapiChangeG;
  1664. hEvents[6] = hAutodialRegChangeG;
  1665. hEvents[7] = hLogoffUserG;
  1666. dwcEvents = 8;
  1667. }
  1668. else {
  1669. hEvents[5] = NULL;
  1670. hEvents[6] = NULL;
  1671. hEvents[7] = NULL;
  1672. dwcEvents = 5;
  1673. }
  1674. RASAUTO_TRACE1("AcsAddressMapThread: waiting for events..dwcEvents = %d", dwcEvents);
  1675. status = WaitForMultipleObjects(
  1676. dwcEvents,
  1677. hEvents,
  1678. FALSE,
  1679. INFINITE);
  1680. RASAUTO_TRACE1(
  1681. "AcsAddressMapThread: WaitForMultipleObjects returned %d",
  1682. status);
  1683. //
  1684. // RASAUTO_TRACE() who we think the currently
  1685. // impersonated user is.
  1686. //
  1687. TraceCurrentUser();
  1688. //
  1689. // Process the WaitForMultipleObjects() results.
  1690. //
  1691. if (status == WAIT_OBJECT_0 || status == WAIT_FAILED) {
  1692. RASAUTO_TRACE1("AcsAddressMapThread: status=%d: shutting down", status);
  1693. break;
  1694. }
  1695. else if (status == WAIT_OBJECT_0 + 1)
  1696. {
  1697. AcsHandleNewUser(&hProcess);
  1698. }
  1699. else if (status == WAIT_OBJECT_0 + 2)
  1700. {
  1701. //
  1702. // A new user has fast-user-switched to the console.
  1703. //
  1704. // XP 353082
  1705. //
  1706. // The service control handler will have set the
  1707. // new active session id so we just need to refresh
  1708. // impersonation.
  1709. //
  1710. RevertImpersonation();
  1711. hProcess = NULL;
  1712. AcsHandleNewUser(&hProcess);
  1713. }
  1714. else if (status == WAIT_OBJECT_0 + 3)
  1715. {
  1716. //
  1717. // A pnp event has occured that may affect network
  1718. // connectivity
  1719. //
  1720. // XP 364593
  1721. //
  1722. // Recalculate what networks are up/down.
  1723. //
  1724. RASAUTO_TRACE("AcsAddressMapThread: pnp event signaled");
  1725. if (!ResetAddressMap(TRUE))
  1726. {
  1727. RASAUTO_TRACE("AcsAddressMapThread: ResetAddressMap failed");
  1728. continue;
  1729. }
  1730. //
  1731. // Calculate the initial network connectivity.
  1732. //
  1733. if (!UpdateNetworkMap(TRUE))
  1734. {
  1735. RASAUTO_TRACE("AcsAddressMapThread: UpdateNetworkMap failed");
  1736. continue;
  1737. }
  1738. if (!EnableDriver()) {
  1739. RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
  1740. continue;
  1741. }
  1742. }
  1743. else if (status == WAIT_OBJECT_0 + 4) {
  1744. //
  1745. // A RAS connection has been created
  1746. // or destroyed. Flush the address
  1747. // map to the registry.
  1748. //
  1749. RASAUTO_TRACE("AcsAddressMapThread: RAS connection change");
  1750. if (hProcess != NULL) {
  1751. LockAddressMap();
  1752. FlushAddressMap();
  1753. UnlockAddressMap();
  1754. ResetAddressMap(FALSE);
  1755. if (!UpdateNetworkMap(FALSE))
  1756. RASAUTO_TRACE("AcsAddressMapThread: UpdateNetworkMap failed");
  1757. }
  1758. }
  1759. else if (status == WAIT_OBJECT_0 + 5) {
  1760. //
  1761. // Process the TAPI event that just ocurred.
  1762. //
  1763. RASAUTO_TRACE("AcsAddressMapThread: TAPI changed");
  1764. ProcessTapiChangeEvent();
  1765. //
  1766. // Enable the driver for notifications
  1767. // for possibly a new dialing location.
  1768. //
  1769. if (!EnableDriver()) {
  1770. RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
  1771. continue;
  1772. }
  1773. }
  1774. else if (status == WAIT_OBJECT_0 + 6) {
  1775. //
  1776. // The Autodial registry changed. Reset the
  1777. // address map.
  1778. //
  1779. RASAUTO_TRACE("AcsAddressMapThread: registry changed");
  1780. if (ExternalAutoDialChangeEvent()) {
  1781. //
  1782. // We fake this today by making it appear
  1783. // a new user has logged in. We definitely
  1784. // could be smarter about how we do this
  1785. // in the future.
  1786. //
  1787. if (!ResetAddressMap(FALSE)) {
  1788. RASAUTO_TRACE("AcsAddressMapThread: ResetAddressMap failed");
  1789. continue;
  1790. }
  1791. }
  1792. //
  1793. // Re-register the change notification.
  1794. //
  1795. NotifyAutoDialChangeEvent(hAutodialRegChangeG);
  1796. //
  1797. // Enable the driver for notifications
  1798. // for possibly a new enabled value for
  1799. // the current dialing location.
  1800. //
  1801. if (!EnableDriver()) {
  1802. RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
  1803. continue;
  1804. }
  1805. }
  1806. else if (status == WAIT_OBJECT_0 + 7) {
  1807. //
  1808. // The user is logging out.
  1809. //
  1810. RASAUTO_TRACE("AcsAddressThread: user is logging out");
  1811. //
  1812. // Write out the address map to the registry
  1813. // before we reset.
  1814. //
  1815. LockAddressMap();
  1816. FlushAddressMap();
  1817. ClearAddressMap();
  1818. UnlockAddressMap();
  1819. //
  1820. // Clear the network database.
  1821. //
  1822. LockNetworkMap();
  1823. ClearNetworkMap();
  1824. UnlockNetworkMap();
  1825. //
  1826. // Remove our registry change event.
  1827. //
  1828. CloseAutoDialChangeEvent(hAutodialRegChangeG);
  1829. hAutodialRegChangeG = NULL;
  1830. //
  1831. // Clear out the user tokens.
  1832. //
  1833. RevertImpersonation();
  1834. hProcess = NULL;
  1835. //
  1836. // Reset the driver.
  1837. //
  1838. ResetDriver();
  1839. //
  1840. // Unload HKEY_CURRENT_USER.
  1841. //
  1842. // PrepareForLongWait();
  1843. //
  1844. // Signal winlogon that we have flushed
  1845. // HKEY_CURRENT_USER.
  1846. //
  1847. SetEvent(hLogoffUserDoneG);
  1848. }
  1849. }
  1850. RASAUTO_TRACE("AcsAddressMapThread: exiting");
  1851. return 0;
  1852. } // AcsAddressMapThread