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.

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