2125 lines
56 KiB
C
2125 lines
56 KiB
C
/*++
|
||
|
||
Copyright(c) 1995 Microsoft Corporation
|
||
|
||
MODULE NAME
|
||
addrmap.c
|
||
|
||
ABSTRACT
|
||
Address attributes database routines shared between
|
||
the automatic connection driver, the registry, and
|
||
the automatic connection service.
|
||
|
||
AUTHOR
|
||
Anthony Discolo (adiscolo) 01-Sep-1995
|
||
|
||
REVISION HISTORY
|
||
|
||
--*/
|
||
|
||
#define UNICODE
|
||
#define _UNICODE
|
||
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
|
||
#include <stdlib.h>
|
||
#include <windows.h>
|
||
#include <tchar.h>
|
||
#include <stdio.h>
|
||
#include <npapi.h>
|
||
#include <acd.h>
|
||
#include <ras.h>
|
||
#include <raserror.h>
|
||
#include <rasman.h>
|
||
#include <debug.h>
|
||
#include <time.h>
|
||
#include <wchar.h>
|
||
|
||
#include "table.h"
|
||
#include "reg.h"
|
||
#include "imperson.h"
|
||
#include "misc.h"
|
||
#include "addrmap.h"
|
||
#include "netmap.h"
|
||
#include "rasprocs.h"
|
||
#include "tapiproc.h"
|
||
|
||
#define DAYSECONDS (60*60*24)
|
||
|
||
extern HKEY hkeyCUG;
|
||
|
||
extern LONG g_lRasAutoRunning;
|
||
|
||
//
|
||
// All the information we cache about
|
||
// an address is below. The ulAttributes
|
||
// field is written to the automatic connection
|
||
// driver, and the rest of the fields are written
|
||
// to the registry.
|
||
//
|
||
#define ADDRESS_MAP_FIELD_DIALINGLOC 0x00000001 // locationList changed
|
||
#define ADDRESS_MAP_FIELD_PARAMS 0x00000002 // params
|
||
|
||
typedef struct _ADDRESS_DIALING_ENTRY {
|
||
LIST_ENTRY ListEntry;
|
||
BOOLEAN fChanged; // modified bit
|
||
ADDRESS_LOCATION_INFORMATION location;
|
||
} ADDRESS_DIALING_ENTRY, *PADDRESS_DIALING_ENTRY;
|
||
|
||
typedef struct _ADDRESS_MAP_ENTRY {
|
||
LPTSTR pszNetwork; // the remote network this address is on
|
||
ULONG ulModifiedMask; // which fields have been changed
|
||
BOOLEAN fDisabled; // disabled for connection attempts
|
||
DWORD dwFailedConnectTicks; // last failed connect time
|
||
ADDRESS_PARAMS params; // used to garbage collect unref addresses
|
||
LIST_ENTRY locationHead; // list of ADDRESS_DIALING_ENTRYs
|
||
BOOLEAN fPruned; // removed by the list writer
|
||
LIST_ENTRY writerList; // list writer links
|
||
} ADDRESS_MAP_ENTRY, *PADDRESS_MAP_ENTRY;
|
||
|
||
//
|
||
// The address map head.
|
||
//
|
||
typedef struct _ADDRESS_MAP {
|
||
CRITICAL_SECTION csLock;
|
||
PHASH_TABLE pTable;
|
||
} ADDRESS_MAP, *PADDRESS_MAP;
|
||
|
||
//
|
||
// Information needed by the address
|
||
// enumerator procedure.
|
||
//
|
||
typedef struct _ADDRESS_ENUM_INFO {
|
||
ULONG ulIndex;
|
||
LPTSTR *pAddresses;
|
||
} ADDRESS_ENUM_INFO, *PADDRESS_ENUM_INFO;
|
||
|
||
//
|
||
// Information needed by the address map list
|
||
// builder enumerator procedure.
|
||
//
|
||
typedef struct _ADDRESS_LIST_INFO {
|
||
LIST_ENTRY tagHead[3]; // one per ADDRMAP_TAG_*
|
||
} ADDRESS_LIST_INFO, *PADDRESS_LIST_INFO;
|
||
|
||
//
|
||
// Structure shared by GetOrganizationDialingLocationEntry()
|
||
// and FindOrganization() when looking for an address that
|
||
// has the same organization name.
|
||
//
|
||
typedef struct _MATCH_INFO {
|
||
BOOLEAN fWww; // look for www-style address
|
||
BOOLEAN fOrg; // look for organization
|
||
DWORD dwLocationID; // current dialing location
|
||
BOOLEAN bFound; // TRUE if success
|
||
WCHAR szOrganization[ACD_ADDR_INET_LEN]; // organization we're looking for
|
||
WCHAR szAddress[ACD_ADDR_INET_LEN]; // matching address, if found
|
||
PADDRESS_DIALING_ENTRY pDialingEntry; // dialing location entry pointer
|
||
} MATCH_INFO, *PMATCH_INFO;
|
||
|
||
//
|
||
// Default permanently disabled addresses.
|
||
//
|
||
#define MAX_DISABLED_ADDRESSES 5
|
||
TCHAR *szDisabledAddresses[MAX_DISABLED_ADDRESSES] = {
|
||
TEXT("0.0.0.0"),
|
||
TEXT("255.255.255.255"),
|
||
TEXT("127.0.0.0"),
|
||
TEXT("127.0.0.1"),
|
||
TEXT("dialin_gateway")
|
||
};
|
||
|
||
//
|
||
// Global variables
|
||
//
|
||
ADDRESS_MAP AddressMapG;
|
||
HANDLE hAutodialRegChangeG = NULL;
|
||
DWORD dwLearnedAddressIndexG;
|
||
PHASH_TABLE pDisabledAddressesG;
|
||
CRITICAL_SECTION csDisabledAddressesLockG;
|
||
|
||
//
|
||
// External variables
|
||
//
|
||
extern HANDLE hAcdG;
|
||
extern HANDLE hNewLogonUserG;
|
||
extern HANDLE hNewFusG; // Fast user switching
|
||
extern HANDLE hPnpEventG;
|
||
extern HANDLE hLogoffUserG;
|
||
extern HANDLE hLogoffUserDoneG;
|
||
extern HANDLE hTapiChangeG;
|
||
extern HANDLE hTerminatingG;
|
||
extern IMPERSONATION_INFO ImpersonationInfoG;
|
||
|
||
|
||
|
||
PADDRESS_MAP_ENTRY
|
||
NewAddressMapEntry()
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = LocalAlloc(LPTR, sizeof (ADDRESS_MAP_ENTRY));
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("NewAddressMapEntry: LocalAlloc failed");
|
||
return NULL;
|
||
}
|
||
pAddressMapEntry->pszNetwork = NULL;
|
||
pAddressMapEntry->ulModifiedMask = 0;
|
||
InitializeListHead(&pAddressMapEntry->locationHead);
|
||
pAddressMapEntry->params.dwTag = 0xffffffff;
|
||
pAddressMapEntry->params.dwModifiedTime = (DWORD)time(0);
|
||
|
||
return pAddressMapEntry;
|
||
} // NewAddressMapEntry
|
||
|
||
|
||
|
||
PADDRESS_MAP_ENTRY
|
||
GetAddressMapEntry(
|
||
IN LPTSTR pszAddress,
|
||
IN BOOLEAN fAllocate
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = NULL;
|
||
|
||
if (pszAddress == NULL)
|
||
return NULL;
|
||
|
||
if (GetTableEntry(
|
||
AddressMapG.pTable,
|
||
pszAddress,
|
||
&pAddressMapEntry))
|
||
{
|
||
goto done;
|
||
}
|
||
if (fAllocate) {
|
||
pAddressMapEntry = NewAddressMapEntry();
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("GetAddressMapEntry: NewAddressMapEntry failed");
|
||
goto done;
|
||
}
|
||
if (!PutTableEntry(AddressMapG.pTable, pszAddress, pAddressMapEntry))
|
||
{
|
||
RASAUTO_TRACE("GetAddressMapEntry: PutTableEntry failed");
|
||
LocalFree(pAddressMapEntry);
|
||
pAddressMapEntry = NULL;
|
||
goto done;
|
||
}
|
||
}
|
||
|
||
done:
|
||
return pAddressMapEntry;
|
||
} // GetAddressMapEntry
|
||
|
||
|
||
|
||
VOID
|
||
FreeAddressMapEntry(
|
||
IN PADDRESS_MAP_ENTRY pAddressMapEntry
|
||
)
|
||
{
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
//
|
||
// Free all dynamically allocated strings.
|
||
//
|
||
if (pAddressMapEntry->pszNetwork != NULL)
|
||
LocalFree(pAddressMapEntry->pszNetwork);
|
||
while (!IsListEmpty(&pAddressMapEntry->locationHead)) {
|
||
pEntry = RemoveHeadList(&pAddressMapEntry->locationHead);
|
||
pDialingEntry =
|
||
CONTAINING_RECORD(pEntry, ADDRESS_DIALING_ENTRY, ListEntry);
|
||
|
||
LocalFree(pDialingEntry);
|
||
}
|
||
//
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ResetDriver()
|
||
{
|
||
NTSTATUS status;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
|
||
status = NtDeviceIoControlFile(
|
||
hAcdG,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
IOCTL_ACD_RESET,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
0);
|
||
if (status != STATUS_SUCCESS) {
|
||
RASAUTO_TRACE1(
|
||
"ResetDriver: NtDeviceIoControlFile failed (status=0x%x)",
|
||
status);
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
} // ResetDriver
|
||
|
||
|
||
|
||
BOOLEAN
|
||
EnableDriver()
|
||
{
|
||
NTSTATUS status;
|
||
DWORD dwErr;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
BOOLEAN fEnable = TRUE;
|
||
|
||
dwErr = AutoDialEnabled(&fEnable);
|
||
RASAUTO_TRACE1("EnableDriver: fEnable=%d", fEnable);
|
||
status = NtDeviceIoControlFile(
|
||
hAcdG,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
IOCTL_ACD_ENABLE,
|
||
&fEnable,
|
||
sizeof (fEnable),
|
||
NULL,
|
||
0);
|
||
if (status != STATUS_SUCCESS) {
|
||
RASAUTO_TRACE1(
|
||
"ResetDriver: NtDeviceIoControlFile failed (status=0x%x)",
|
||
status);
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
} // EnableDriver
|
||
|
||
|
||
|
||
PADDRESS_DIALING_ENTRY
|
||
FindAddressDialingEntry(
|
||
IN PADDRESS_MAP_ENTRY pAddressMapEntry,
|
||
IN DWORD dwLocation
|
||
)
|
||
{
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
for (pEntry = pAddressMapEntry->locationHead.Flink;
|
||
pEntry != &pAddressMapEntry->locationHead;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pDialingEntry = CONTAINING_RECORD(
|
||
pEntry,
|
||
ADDRESS_DIALING_ENTRY,
|
||
ListEntry);
|
||
|
||
if (pDialingEntry->location.dwLocation == dwLocation)
|
||
return pDialingEntry;
|
||
}
|
||
|
||
return NULL;
|
||
} // FindAddressDialingEntry
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ClearAddressMapEntry(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddress,
|
||
IN PVOID pData
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
|
||
|
||
FreeAddressMapEntry(pAddressMapEntry);
|
||
|
||
return TRUE;
|
||
} // ClearAddressMapEntry
|
||
|
||
|
||
|
||
VOID
|
||
ClearAddressMap(VOID)
|
||
{
|
||
EnumTable(AddressMapG.pTable, ClearAddressMapEntry, NULL);
|
||
ClearTable(AddressMapG.pTable);
|
||
} // ClearAddressMap
|
||
|
||
|
||
|
||
VOID
|
||
ResetAddressMapAddress(
|
||
IN LPTSTR pszAddress
|
||
)
|
||
{
|
||
DWORD dwErr, dwcb, dwcAddresses, dwcEntries;
|
||
DWORD i, j;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = NULL;
|
||
PADDRESS_LOCATION_INFORMATION pLocationInfo = NULL;
|
||
|
||
RASAUTO_TRACE1("ResetAddressMapAddress(%S)", pszAddress);
|
||
|
||
dwErr = GetAddressDialingLocationInfo(
|
||
pszAddress,
|
||
&pLocationInfo,
|
||
&dwcEntries);
|
||
if (dwErr || !dwcEntries)
|
||
return;
|
||
//
|
||
// Enter this address into the address map
|
||
// if it doesn't already exist.
|
||
//
|
||
if (!GetTableEntry(AddressMapG.pTable, pszAddress, &pAddressMapEntry)) {
|
||
pAddressMapEntry = NewAddressMapEntry();
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("ResetAddressMapAddress: NewAddressMapEntry failed");
|
||
goto done;
|
||
}
|
||
pAddressMapEntry->fDisabled = FALSE;
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMap: inserting pszAddress=%S",
|
||
RASAUTO_TRACESTRW(pszAddress));
|
||
if (!PutTableEntry(
|
||
AddressMapG.pTable,
|
||
pszAddress,
|
||
pAddressMapEntry))
|
||
{
|
||
RASAUTO_TRACE("ResetAddressMapAddress: PutTableEntry failed");
|
||
goto done;
|
||
}
|
||
}
|
||
//
|
||
// Get the network for this address.
|
||
//
|
||
if (pAddressMapEntry->pszNetwork == NULL) {
|
||
pAddressMapEntry->pszNetwork = AddressToNetwork(pszAddress);
|
||
if (pAddressMapEntry->pszNetwork == NULL) {
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMapAddress: AddressToNetwork(%S) failed",
|
||
pszAddress);
|
||
LocalFree(pAddressMapEntry);
|
||
goto done;
|
||
}
|
||
}
|
||
//
|
||
// Read the Autodial parameters for this address.
|
||
//
|
||
GetAddressParams(pszAddress, &pAddressMapEntry->params);
|
||
//
|
||
// Add this address to the associated
|
||
// network map.
|
||
//
|
||
LockNetworkMap();
|
||
AddNetworkAddress(
|
||
pAddressMapEntry->pszNetwork,
|
||
pszAddress,
|
||
pAddressMapEntry->params.dwTag);
|
||
UnlockNetworkMap();
|
||
//
|
||
// Add each dialing location onto
|
||
// the address's list.
|
||
//
|
||
for (j = 0; j < dwcEntries; j++) {
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
pDialingEntry = FindAddressDialingEntry(
|
||
pAddressMapEntry,
|
||
pLocationInfo[j].dwLocation);
|
||
if (pDialingEntry == NULL) {
|
||
//
|
||
// The dialing entry doesn't exist.
|
||
// We need to create it.
|
||
//
|
||
pDialingEntry = LocalAlloc(LPTR, sizeof (ADDRESS_DIALING_ENTRY));
|
||
if (pDialingEntry == NULL) {
|
||
RASAUTO_TRACE("ResetAddressMapAddress: LocalAlloc failed");
|
||
goto done;
|
||
}
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMapAddress: inserting dwLocationID=%d",
|
||
pLocationInfo[j].dwLocation);
|
||
pDialingEntry->fChanged = FALSE;
|
||
pDialingEntry->location = pLocationInfo[j];
|
||
InsertTailList(&pAddressMapEntry->locationHead, &pDialingEntry->ListEntry);
|
||
}
|
||
else if (_wcsicmp(
|
||
pDialingEntry->location.pszEntryName,
|
||
pLocationInfo[j].pszEntryName))
|
||
{
|
||
//
|
||
// The dialing entry does exist, but
|
||
// the phonebook entry has changed.
|
||
//
|
||
RASAUTO_TRACE2(
|
||
"ResetAddressMapAddress: updating dwLocationID=%d with %S",
|
||
pLocationInfo[j].dwLocation,
|
||
RASAUTO_TRACESTRW(pLocationInfo[j].pszEntryName));
|
||
pDialingEntry->location.pszEntryName =
|
||
pLocationInfo[j].pszEntryName;
|
||
}
|
||
else {
|
||
//
|
||
// The dialing entry exists, and we
|
||
// already have it loaded.
|
||
//
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMapAddress: no changes for dwLocationID=%d",
|
||
pLocationInfo[j].dwLocation);
|
||
LocalFree(pLocationInfo[j].pszEntryName);
|
||
}
|
||
}
|
||
|
||
done:
|
||
LocalFree(pLocationInfo);
|
||
} // ResetAddressMapAddress
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ResetAddressMap(
|
||
IN BOOLEAN fClear
|
||
)
|
||
{
|
||
BOOLEAN fSuccess = FALSE;
|
||
DWORD dwErr, i, dwcb, dwcAddresses;
|
||
LPTSTR *ppAddresses = NULL;
|
||
|
||
//
|
||
// Clear the current addresses from the table.
|
||
// and reset the driver.
|
||
//
|
||
if (fClear) {
|
||
LockAddressMap();
|
||
ClearAddressMap();
|
||
UnlockAddressMap();
|
||
if (!ResetDriver())
|
||
return FALSE;
|
||
}
|
||
//
|
||
// Enumerate the Autodial addresses.
|
||
//
|
||
dwErr = EnumAutodialAddresses(NULL, &dwcb, &dwcAddresses);
|
||
if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL) {
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMap: RasEnumAutodialAddresses failed (dwErr=%d)",
|
||
dwErr);
|
||
return FALSE;
|
||
}
|
||
if (!dwcAddresses)
|
||
return TRUE;
|
||
ppAddresses = LocalAlloc(LPTR, dwcb);
|
||
if (ppAddresses == NULL) {
|
||
RASAUTO_TRACE("ResetAddressMap: LocalAlloc failed");
|
||
return FALSE;
|
||
}
|
||
dwErr = EnumAutodialAddresses(
|
||
ppAddresses,
|
||
&dwcb,
|
||
&dwcAddresses);
|
||
if (dwErr) {
|
||
RASAUTO_TRACE1(
|
||
"ResetAddressMap: RasEnumAutodialAddresses failed (dwErr=%d)",
|
||
dwErr);
|
||
goto done;
|
||
}
|
||
//
|
||
// Get the Autodial information for
|
||
// each of the addresses.
|
||
//
|
||
LockAddressMap();
|
||
for (i = 0; i < dwcAddresses; i++)
|
||
ResetAddressMapAddress(ppAddresses[i]);
|
||
UnlockAddressMap();
|
||
LocalFree(ppAddresses);
|
||
ppAddresses = NULL;
|
||
fSuccess = TRUE;
|
||
|
||
done:
|
||
//
|
||
// Free resources.
|
||
//
|
||
if (ppAddresses != NULL)
|
||
LocalFree(ppAddresses);
|
||
|
||
return fSuccess;
|
||
} // ResetAddressMap
|
||
|
||
|
||
|
||
BOOLEAN
|
||
InitializeAddressMap()
|
||
{
|
||
//
|
||
// Create the address map.
|
||
//
|
||
InitializeCriticalSection(&AddressMapG.csLock);
|
||
AddressMapG.pTable = NewTable();
|
||
if (AddressMapG.pTable == NULL) {
|
||
RASAUTO_TRACE("InitializeAddressMap: NewTable failed");
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
} // InitializeAddressMap
|
||
|
||
VOID
|
||
UninitializeAddressMap()
|
||
{
|
||
DeleteCriticalSection(&AddressMapG.csLock);
|
||
}
|
||
|
||
|
||
VOID
|
||
LockAddressMap()
|
||
{
|
||
EnterCriticalSection(&AddressMapG.csLock);
|
||
} // LockAddressMap
|
||
|
||
|
||
|
||
VOID
|
||
UnlockAddressMap()
|
||
{
|
||
LeaveCriticalSection(&AddressMapG.csLock);
|
||
} // UnlockAddressMap
|
||
|
||
|
||
VOID
|
||
LockDisabledAddresses()
|
||
{
|
||
EnterCriticalSection(&csDisabledAddressesLockG);
|
||
}
|
||
|
||
VOID
|
||
UnlockDisabledAddresses()
|
||
{
|
||
LeaveCriticalSection(&csDisabledAddressesLockG);
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
WriteRegistryFields(
|
||
IN LPTSTR pszAddress,
|
||
IN PADDRESS_MAP_ENTRY pAddressMapEntry
|
||
)
|
||
{
|
||
DWORD dwErr;
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
//
|
||
// Write the address garbage-collection params.
|
||
//
|
||
if (pAddressMapEntry->ulModifiedMask & ADDRESS_MAP_FIELD_PARAMS) {
|
||
dwErr = SetAddressParams(pszAddress, &pAddressMapEntry->params);
|
||
if (dwErr)
|
||
return FALSE;
|
||
pAddressMapEntry->ulModifiedMask &= ~ADDRESS_MAP_FIELD_PARAMS;
|
||
}
|
||
//
|
||
// Write the dialing location information.
|
||
//
|
||
if (pAddressMapEntry->ulModifiedMask & ADDRESS_MAP_FIELD_DIALINGLOC) {
|
||
for (pEntry = pAddressMapEntry->locationHead.Flink;
|
||
pEntry != &pAddressMapEntry->locationHead;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
LPTSTR pszPhonebook, pszEntry;
|
||
|
||
pDialingEntry = CONTAINING_RECORD(
|
||
pEntry,
|
||
ADDRESS_DIALING_ENTRY,
|
||
ListEntry);
|
||
|
||
if (!pDialingEntry->fChanged)
|
||
continue;
|
||
RASAUTO_TRACE3(
|
||
"WriteRegistryFields: writing %S=%d/%S",
|
||
RASAUTO_TRACESTRW(pszAddress),
|
||
pDialingEntry->location.dwLocation,
|
||
pDialingEntry->location.pszEntryName);
|
||
dwErr = SetAddressDialingLocationInfo(
|
||
pszAddress,
|
||
&pDialingEntry->location);
|
||
if (dwErr)
|
||
return FALSE;
|
||
pDialingEntry->fChanged = FALSE;
|
||
}
|
||
//
|
||
// If the network value for this address
|
||
// is NULL, read it now from the registry.
|
||
//
|
||
if (pAddressMapEntry->pszNetwork == NULL) {
|
||
pAddressMapEntry->pszNetwork = AddressToNetwork(pszAddress);
|
||
if (pAddressMapEntry->pszNetwork == NULL) {
|
||
RASAUTO_TRACE1(
|
||
"WriteRegistryFields: AddressToNetwork(%S) failed",
|
||
RASAUTO_TRACESTRW(pszAddress));
|
||
}
|
||
}
|
||
//
|
||
// Clear the modified field mask.
|
||
//
|
||
pAddressMapEntry->ulModifiedMask &= ~ADDRESS_MAP_FIELD_DIALINGLOC;
|
||
}
|
||
|
||
return TRUE;
|
||
} // WriteRegistryFields
|
||
|
||
|
||
|
||
BOOLEAN
|
||
BuildAddressList(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddress,
|
||
IN PVOID pData
|
||
)
|
||
{
|
||
PADDRESS_LIST_INFO pAddressListInfo = (PADDRESS_LIST_INFO)pArg;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
|
||
PADDRESS_MAP_ENTRY pAddrMapEntry;
|
||
PLIST_ENTRY pPrevEntry, pEntry;
|
||
DWORD dwTag = pAddressMapEntry->params.dwTag;
|
||
|
||
//
|
||
// If the address does not have any
|
||
// dialing location information, then
|
||
// skip it.
|
||
//
|
||
if (IsListEmpty(&pAddressMapEntry->locationHead)) {
|
||
pAddressMapEntry->fPruned = TRUE;
|
||
RASAUTO_TRACE1("BuildAddressList: %S has no location info", pszAddress);
|
||
return TRUE;
|
||
}
|
||
dwTag = pAddressMapEntry->params.dwTag < ADDRMAP_TAG_LEARNED ?
|
||
pAddressMapEntry->params.dwTag :
|
||
ADDRMAP_TAG_LEARNED;
|
||
//
|
||
// If the list is empty, insert it at the head.
|
||
// Otherwise sort the items in descending order
|
||
// by last modified time per tag. There is no order
|
||
// for ADDRMAP_TAG_NONE addresses, so we insert them
|
||
// all at the head of the list.
|
||
//
|
||
if (dwTag == ADDRMAP_TAG_NONE ||
|
||
IsListEmpty(&pAddressListInfo->tagHead[dwTag]))
|
||
{
|
||
InsertHeadList(&pAddressListInfo->tagHead[dwTag], &pAddressMapEntry->writerList);
|
||
}
|
||
else {
|
||
BOOLEAN fInserted = FALSE;
|
||
|
||
pPrevEntry = &pAddressListInfo->tagHead[dwTag];
|
||
for (pEntry = pAddressListInfo->tagHead[dwTag].Flink;
|
||
pEntry != &pAddressListInfo->tagHead[dwTag];
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pAddrMapEntry = CONTAINING_RECORD(pEntry, ADDRESS_MAP_ENTRY, writerList);
|
||
|
||
//
|
||
// There are two cases to skip to the next
|
||
// entry:
|
||
//
|
||
// (1) If the tag is either ADDRMAP_TAG_NONE or
|
||
// ADDRMAP_TAG_USED, then we insert sorted
|
||
// by dwModifiedTime.
|
||
// (2) If the tag is ADDRMAP_TAG_LEARNED, then
|
||
// we insert sorted by dwTag, and then by
|
||
// dwModifiedTime.
|
||
// dwTag.
|
||
//
|
||
if ((dwTag < ADDRMAP_TAG_LEARNED &&
|
||
pAddressMapEntry->params.dwModifiedTime <=
|
||
pAddrMapEntry->params.dwModifiedTime) ||
|
||
(dwTag == ADDRMAP_TAG_LEARNED &&
|
||
(pAddressMapEntry->params.dwTag >
|
||
pAddrMapEntry->params.dwTag) ||
|
||
(pAddressMapEntry->params.dwTag ==
|
||
pAddrMapEntry->params.dwTag &&
|
||
(pAddressMapEntry->params.dwModifiedTime <=
|
||
pAddrMapEntry->params.dwModifiedTime))))
|
||
{
|
||
pPrevEntry = pEntry;
|
||
continue;
|
||
}
|
||
InsertHeadList(pPrevEntry, &pAddressMapEntry->writerList);
|
||
fInserted = TRUE;
|
||
break;
|
||
}
|
||
if (!fInserted) {
|
||
InsertTailList(
|
||
&pAddressListInfo->tagHead[dwTag],
|
||
&pAddressMapEntry->writerList);
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
} // BuildAddressList
|
||
|
||
|
||
|
||
VOID
|
||
MarkAddressList(
|
||
IN PADDRESS_LIST_INFO pAddressListInfo
|
||
)
|
||
{
|
||
DWORD i, dwcAddresses = 0;
|
||
DWORD dwMaxAddresses = GetAutodialParam(RASADP_SavedAddressesLimit);
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
RASAUTO_TRACE1("MarkAddressList: RASADP_SavedAddressesLimit=%d", dwMaxAddresses);
|
||
//
|
||
// Enumerate the entries in the list in order,
|
||
// and mark the fPruned bit if its order in the
|
||
// list exceeds the maximum set by the user.
|
||
// We do not include the ADDRMAP_TAG_NONE address
|
||
// in the address count. All of these addresses
|
||
// always get written.
|
||
//
|
||
for (i = 0; i < 3; i++) {
|
||
for (pEntry = pAddressListInfo->tagHead[i].Flink;
|
||
pEntry != &pAddressListInfo->tagHead[i];
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pAddressMapEntry = CONTAINING_RECORD(pEntry, ADDRESS_MAP_ENTRY, writerList);
|
||
|
||
//
|
||
// If we exceed the limit of addresses in the
|
||
// registry, we have to delete it.
|
||
//
|
||
if (i == ADDRMAP_TAG_NONE)
|
||
pAddressMapEntry->fPruned = FALSE;
|
||
else
|
||
pAddressMapEntry->fPruned = (++dwcAddresses > dwMaxAddresses);
|
||
}
|
||
}
|
||
} // MarkAddressList
|
||
|
||
|
||
|
||
BOOLEAN
|
||
PruneAddressList(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddress,
|
||
IN PVOID pData
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
|
||
|
||
if (pAddressMapEntry->fPruned) {
|
||
RASAUTO_TRACE1("PruneAddressList: NEED TO DELETE ADDRESS %S in the driver!", pszAddress);
|
||
ClearAddressDialingLocationInfo(pszAddress);
|
||
FreeAddressMapEntry(pAddressMapEntry);
|
||
DeleteTableEntry(AddressMapG.pTable, pszAddress);
|
||
}
|
||
|
||
return TRUE;
|
||
} // PruneAddressList
|
||
|
||
|
||
|
||
BOOLEAN
|
||
WriteAddressMap(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddress,
|
||
IN PVOID pData
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
|
||
|
||
if (pAddressMapEntry->ulModifiedMask) {
|
||
if (!WriteRegistryFields(
|
||
pszAddress,
|
||
pAddressMapEntry))
|
||
{
|
||
RASAUTO_TRACE("WriteAddressMap: WriteRegistryFields failed");
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
} // WriteAddressMap
|
||
|
||
|
||
|
||
BOOLEAN
|
||
FlushAddressMap()
|
||
{
|
||
ADDRESS_LIST_INFO addressListInfo;
|
||
|
||
//
|
||
// Build a new list sorted by address tag and modified
|
||
// date.
|
||
//
|
||
InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_LEARNED]);
|
||
InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_USED]);
|
||
InitializeListHead(&addressListInfo.tagHead[ADDRMAP_TAG_NONE]);
|
||
EnumTable(AddressMapG.pTable, BuildAddressList, &addressListInfo);
|
||
MarkAddressList(&addressListInfo);
|
||
EnumTable(AddressMapG.pTable, PruneAddressList, NULL);
|
||
//
|
||
// Turn off registry change notifications
|
||
// while we are doing this.
|
||
//
|
||
EnableAutoDialChangeEvent(hAutodialRegChangeG, FALSE);
|
||
EnumTable(AddressMapG.pTable, WriteAddressMap, NULL);
|
||
//
|
||
// Enable registry change events again.
|
||
//
|
||
EnableAutoDialChangeEvent(hAutodialRegChangeG, TRUE);
|
||
|
||
return TRUE;
|
||
} // FlushAddressMap
|
||
|
||
|
||
|
||
ULONG
|
||
AddressMapSize()
|
||
{
|
||
return AddressMapG.pTable->ulSize;
|
||
} // AddressMapSize;
|
||
|
||
|
||
|
||
BOOLEAN
|
||
EnumAddresses(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddress,
|
||
IN PVOID pData
|
||
)
|
||
{
|
||
PADDRESS_ENUM_INFO pEnumInfo = (PADDRESS_ENUM_INFO)pArg;
|
||
|
||
pEnumInfo->pAddresses[pEnumInfo->ulIndex++] = CopyString(pszAddress);
|
||
return TRUE;
|
||
} // EnumAddresses
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ListAddressMapAddresses(
|
||
OUT LPTSTR **ppszAddresses,
|
||
OUT PULONG pulcAddresses
|
||
)
|
||
{
|
||
ADDRESS_ENUM_INFO enumInfo;
|
||
|
||
//
|
||
// Check for an empty list.
|
||
//
|
||
*pulcAddresses = AddressMapG.pTable->ulSize;
|
||
if (!*pulcAddresses) {
|
||
*ppszAddresses = NULL;
|
||
return TRUE;
|
||
}
|
||
//
|
||
// Allocate a list large enough to hold all
|
||
// the addresses.
|
||
//
|
||
*ppszAddresses = LocalAlloc(LPTR, *pulcAddresses * sizeof (LPTSTR));
|
||
if (*ppszAddresses == NULL) {
|
||
RASAUTO_TRACE("ListAddressMapAddresses: LocalAlloc failed");
|
||
return FALSE;
|
||
}
|
||
//
|
||
// Set up the structure for the enumerator
|
||
// procedure.
|
||
//
|
||
enumInfo.ulIndex = 0;
|
||
enumInfo.pAddresses = *ppszAddresses;
|
||
EnumTable(AddressMapG.pTable, EnumAddresses, &enumInfo);
|
||
|
||
return TRUE;
|
||
} // ListAddressMapAddresses
|
||
|
||
|
||
|
||
VOID
|
||
EnumAddressMap(
|
||
IN PHASH_TABLE_ENUM_PROC pProc,
|
||
IN PVOID pArg
|
||
)
|
||
{
|
||
EnumTable(AddressMapG.pTable, pProc, pArg);
|
||
} // EnumAddressMap
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetAddressDisabled(
|
||
IN LPTSTR pszAddress,
|
||
OUT PBOOLEAN pfDisabled
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
|
||
{
|
||
DWORD i;
|
||
LPTSTR pszDisabled[] =
|
||
{
|
||
TEXT("wpad"),
|
||
TEXT("pnptriage"),
|
||
TEXT("nttriage"),
|
||
TEXT("ntcore2"),
|
||
TEXT("liveraid")
|
||
};
|
||
|
||
for (i = 0; i < sizeof(pszDisabled)/sizeof(LPTSTR); i++)
|
||
{
|
||
if( (0 == (lstrcmpi(pszDisabled[i], pszAddress)))
|
||
|| (wcsstr(_wcslwr(pszAddress), pszDisabled[i])
|
||
== pszAddress))
|
||
{
|
||
*pfDisabled = TRUE;
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
|
||
if (pAddressMapEntry == NULL) {
|
||
*pfDisabled = FALSE;
|
||
return FALSE;
|
||
}
|
||
*pfDisabled = pAddressMapEntry->fDisabled;
|
||
|
||
return TRUE;
|
||
} // GetAddressDisabled
|
||
|
||
|
||
|
||
BOOLEAN
|
||
SetAddressDisabled(
|
||
IN LPTSTR pszAddress,
|
||
IN BOOLEAN fDisabled
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressDisabled: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
pAddressMapEntry->fDisabled = fDisabled;
|
||
|
||
return TRUE;
|
||
} // SetAddressDisabled
|
||
|
||
BOOLEAN
|
||
SetAddressDisabledEx(
|
||
IN LPTSTR pszAddress,
|
||
IN BOOLEAN fDisable
|
||
)
|
||
{
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
ACD_ENABLE_ADDRESS *pEnableAddress;
|
||
|
||
LONG l = InterlockedIncrement(&g_lRasAutoRunning);
|
||
|
||
InterlockedDecrement(&g_lRasAutoRunning);
|
||
|
||
if(l == 1)
|
||
{
|
||
//
|
||
// rasauto isn't running. Bail.
|
||
//
|
||
return TRUE;
|
||
}
|
||
|
||
#if 0
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressDisabled: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
|
||
#endif
|
||
|
||
//
|
||
// Also set this address as disabled in the driver
|
||
//
|
||
pEnableAddress = LocalAlloc(LPTR, sizeof(ACD_ENABLE_ADDRESS));
|
||
if(NULL != pEnableAddress)
|
||
{
|
||
NTSTATUS status;
|
||
CHAR *pszNew;
|
||
DWORD cb;
|
||
|
||
if (pszAddress != NULL) {
|
||
|
||
cb = WideCharToMultiByte(CP_ACP, 0, pszAddress,
|
||
-1, NULL, 0, NULL, NULL);
|
||
|
||
pszNew = (CHAR*)LocalAlloc(LPTR, cb);
|
||
if (pszNew == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
cb = WideCharToMultiByte(CP_ACP, 0, pszAddress,
|
||
-1, pszNew, cb, NULL, NULL);
|
||
|
||
if (!cb) {
|
||
LocalFree(pszNew);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
_strlwr(pszNew);
|
||
|
||
pEnableAddress->fDisable = fDisable;
|
||
RtlCopyMemory(pEnableAddress->addr.szInet,
|
||
pszNew,
|
||
cb);
|
||
|
||
status = NtDeviceIoControlFile(
|
||
hAcdG,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
IOCTL_ACD_ENABLE_ADDRESS,
|
||
pEnableAddress,
|
||
sizeof (ACD_ENABLE_ADDRESS),
|
||
NULL,
|
||
0);
|
||
if (status != STATUS_SUCCESS)
|
||
{
|
||
RASAUTO_TRACE("SetAddressDisabledEx: ioctl failed");
|
||
}
|
||
|
||
LocalFree(pEnableAddress);
|
||
}
|
||
|
||
return TRUE;
|
||
} // SetAddressDisabled
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetAddressDialingLocationEntry(
|
||
IN LPTSTR pszAddress,
|
||
OUT LPTSTR *ppszEntryName
|
||
)
|
||
{
|
||
DWORD dwErr, dwLocationID;
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
dwErr = TapiCurrentDialingLocation(&dwLocationID);
|
||
if (dwErr)
|
||
return FALSE;
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
|
||
if (pAddressMapEntry == NULL || IsListEmpty(&pAddressMapEntry->locationHead))
|
||
return FALSE;
|
||
//
|
||
// Search for the dialing information
|
||
// that maps to the current dialing
|
||
// location.
|
||
//
|
||
for (pEntry = pAddressMapEntry->locationHead.Flink;
|
||
pEntry != &pAddressMapEntry->locationHead;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pDialingEntry = CONTAINING_RECORD(
|
||
pEntry,
|
||
ADDRESS_DIALING_ENTRY,
|
||
ListEntry);
|
||
|
||
if (pDialingEntry->location.dwLocation == dwLocationID) {
|
||
*ppszEntryName = CopyString(pDialingEntry->location.pszEntryName);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
} // GetAddressDialingLocationEntry
|
||
|
||
|
||
|
||
BOOLEAN
|
||
IsAWwwAddress(
|
||
IN LPTSTR pszAddr
|
||
)
|
||
{
|
||
DWORD dwcbAddress;
|
||
DWORD i;
|
||
BOOLEAN fDot = FALSE, fIsAWwwAddress = FALSE;
|
||
|
||
//
|
||
// See if this address starts with "www*.".
|
||
//
|
||
if (!_wcsnicmp(pszAddr, L"www", 3)) {
|
||
dwcbAddress = wcslen(pszAddr);
|
||
//
|
||
// Search for a '.' and something else
|
||
// after the '.'.
|
||
//
|
||
for (i = 3; i < dwcbAddress; i++) {
|
||
if (!fDot)
|
||
fDot = (pszAddr[i] == L'.');
|
||
fIsAWwwAddress = fDot && (pszAddr[i] != L'.');
|
||
if (fIsAWwwAddress)
|
||
break;
|
||
}
|
||
}
|
||
|
||
return fIsAWwwAddress;
|
||
} // IsAWwwAddress
|
||
|
||
|
||
|
||
BOOLEAN
|
||
FindSimilarAddress(
|
||
IN PVOID pArg,
|
||
IN LPTSTR pszAddr,
|
||
IN PVOID pData
|
||
)
|
||
|
||
/*++
|
||
|
||
DESCRIPTION
|
||
This is a table enumerator procedure that searches
|
||
for address with a www-style name or the same
|
||
organization name. For example, it will consider
|
||
"www1.netscape.com" and "www2.netscape.com" equal
|
||
since they share the same organization and domain
|
||
address components.
|
||
|
||
ARGUMENTS
|
||
pArg: a pointer to a MATCH_INFO structure
|
||
|
||
pszAddr: a pointer to the enumerated address
|
||
|
||
ulData: the address's data value
|
||
|
||
RETURN VALUE
|
||
TRUE if the enumeration should continue (match
|
||
not found), or FALSE when the enumerations should
|
||
terminate (match found).
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOLEAN fIsWww = FALSE, fHasOrg = FALSE;
|
||
BOOLEAN fDialingLocationFound;
|
||
PMATCH_INFO pMatchInfo = (PMATCH_INFO)pArg;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry = (PADDRESS_MAP_ENTRY)pData;
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
WCHAR szOrganization[ACD_ADDR_INET_LEN];
|
||
|
||
if (pMatchInfo->fWww)
|
||
fIsWww = IsAWwwAddress(pszAddr);
|
||
else if (pMatchInfo->fOrg)
|
||
fHasOrg = GetOrganization(pszAddr, (LPTSTR)&szOrganization);
|
||
//
|
||
// If it has neither a www-style address nor
|
||
// it has an organization, then return
|
||
// immediately.
|
||
//
|
||
if ((pMatchInfo->fWww && !fIsWww) ||
|
||
(pMatchInfo->fOrg && !fHasOrg))
|
||
{
|
||
return TRUE;
|
||
}
|
||
if (fIsWww)
|
||
RASAUTO_TRACE1("FindSimilarAddress: fIsWww=1, %S", pszAddr);
|
||
else {
|
||
RASAUTO_TRACE2(
|
||
"FindSimilarAddress: fHasOrg=1, comparing (%S, %S)",
|
||
pMatchInfo->szOrganization,
|
||
szOrganization);
|
||
}
|
||
//
|
||
// If we're looking for an organization,
|
||
// and the organization's don't match,
|
||
// then return.
|
||
//
|
||
if (fHasOrg && _wcsicmp(pMatchInfo->szOrganization, szOrganization))
|
||
{
|
||
return TRUE;
|
||
}
|
||
//
|
||
// Search for the dialing information
|
||
// that maps to the current dialing
|
||
// location.
|
||
//
|
||
fDialingLocationFound = FALSE;
|
||
for (pEntry = pAddressMapEntry->locationHead.Flink;
|
||
pEntry != &pAddressMapEntry->locationHead;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pDialingEntry = CONTAINING_RECORD(
|
||
pEntry,
|
||
ADDRESS_DIALING_ENTRY,
|
||
ListEntry);
|
||
|
||
if (pDialingEntry->location.dwLocation == pMatchInfo->dwLocationID) {
|
||
fDialingLocationFound = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
if (!fDialingLocationFound) {
|
||
RASAUTO_TRACE1("FindSimilarAddress: dialing location %d not found", pMatchInfo->dwLocationID);
|
||
return TRUE;
|
||
}
|
||
//
|
||
// If we already have found a match,
|
||
// then make sure the network is the
|
||
// same for all the matching addresses.
|
||
// If not terminate the enumeration.
|
||
//
|
||
if (pMatchInfo->bFound &&
|
||
pDialingEntry->location.pszEntryName != NULL &&
|
||
pMatchInfo->pDialingEntry->location.pszEntryName != NULL &&
|
||
_wcsicmp(
|
||
pMatchInfo->pDialingEntry->location.pszEntryName,
|
||
pDialingEntry->location.pszEntryName))
|
||
{
|
||
pMatchInfo->bFound = FALSE;
|
||
RASAUTO_TRACE("FindSimilarAddress: returning FALSE");
|
||
return FALSE;
|
||
}
|
||
//
|
||
// Update the closure and continue
|
||
// the enumeration.
|
||
//
|
||
if (!pMatchInfo->bFound) {
|
||
pMatchInfo->bFound = TRUE;
|
||
wcscpy(pMatchInfo->szAddress, pszAddr);
|
||
pMatchInfo->pDialingEntry = pDialingEntry;
|
||
}
|
||
return TRUE;
|
||
} // FindSimilarAddress
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetSimilarDialingLocationEntry(
|
||
IN LPTSTR pszAddress,
|
||
OUT LPTSTR *ppszEntryName
|
||
)
|
||
|
||
/*++
|
||
|
||
DESCRIPTION
|
||
Parse the organization name from the Internet
|
||
address, and look for an address that we know
|
||
about with the same organization name. If we
|
||
find it, make that address our target address.
|
||
This enables us to treat addresses like
|
||
"www1.netscape.com" and "www2.netscape.com"
|
||
equivalently without having to have all
|
||
combinations in our address map.
|
||
|
||
ARGUMENTS
|
||
pszAddress: a pointer to the original address
|
||
|
||
ppszEntryName: a pointer to the phonebook entry of
|
||
a similar address
|
||
|
||
RETURN VALUE
|
||
TRUE if there is a unique phonebook entry;
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwErr;
|
||
MATCH_INFO matchInfo;
|
||
BOOLEAN fIsAWwwAddress = FALSE;
|
||
|
||
//
|
||
// Check to see if this is "www*." style address.
|
||
//
|
||
matchInfo.fWww = IsAWwwAddress(pszAddress);
|
||
//
|
||
// Get the organization for the specified address.
|
||
//
|
||
if (!matchInfo.fWww)
|
||
matchInfo.fOrg = GetOrganization(pszAddress, (LPTSTR)&matchInfo.szOrganization);
|
||
else
|
||
matchInfo.fOrg = FALSE;
|
||
if (!matchInfo.fWww && !matchInfo.fOrg) {
|
||
RASAUTO_TRACE1(
|
||
"GetSimilarDialingLocationEntry: %S is not www and has no organization",
|
||
pszAddress);
|
||
return FALSE;
|
||
}
|
||
RASAUTO_TRACE4(
|
||
"GetSimilarDialingLocationEntry: %S: fWww=%d, fOrg=%d, org is %S",
|
||
pszAddress,
|
||
matchInfo.fWww,
|
||
matchInfo.fOrg,
|
||
matchInfo.szOrganization);
|
||
//
|
||
// Search the table.
|
||
//
|
||
dwErr = TapiCurrentDialingLocation(&matchInfo.dwLocationID);
|
||
if (dwErr) {
|
||
RASAUTO_TRACE1(
|
||
"GetSimilarDialingLocationEntry: TapiCurrentDialingLocation failed (dwErr=%d)",
|
||
dwErr);
|
||
return FALSE;
|
||
}
|
||
matchInfo.bFound = FALSE;
|
||
RtlZeroMemory(&matchInfo.szAddress, sizeof (matchInfo.szAddress));
|
||
matchInfo.pDialingEntry = NULL;
|
||
EnumTable(AddressMapG.pTable, FindSimilarAddress, &matchInfo);
|
||
//
|
||
// If we didn't find it, then return.
|
||
//
|
||
if (!matchInfo.bFound) {
|
||
RASAUTO_TRACE1(
|
||
"GetSimilarDialingLocationEntry: %S: did not find matching org",
|
||
pszAddress);
|
||
return FALSE;
|
||
}
|
||
RASAUTO_TRACE2(
|
||
"GetSimilarDialingLocationEntry: %S: matching address is %S",
|
||
pszAddress,
|
||
matchInfo.szAddress);
|
||
//
|
||
// Return the dialing location entry for
|
||
// the matching address.
|
||
//
|
||
return GetAddressDialingLocationEntry(matchInfo.szAddress, ppszEntryName);
|
||
} // GetSimilarDialingLocationEntry
|
||
|
||
|
||
|
||
BOOLEAN
|
||
SetAddressLastFailedConnectTime(
|
||
IN LPTSTR pszAddress
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressLastFailedConnectTime: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
pAddressMapEntry->dwFailedConnectTicks = GetTickCount();
|
||
|
||
return TRUE;
|
||
} // SetAddressLastFailedConnectTime
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetAddressLastFailedConnectTime(
|
||
IN LPTSTR pszAddress,
|
||
OUT LPDWORD lpdwTicks
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("GetAddressLastFailedConnectTime: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
*lpdwTicks = pAddressMapEntry->dwFailedConnectTicks;
|
||
|
||
return (*lpdwTicks != 0);
|
||
} // GetAddressLastFailedConnectTime
|
||
|
||
|
||
|
||
BOOLEAN
|
||
SetAddressTag(
|
||
IN LPTSTR pszAddress,
|
||
IN DWORD dwTag
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
time_t clock = time(0);
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressWeight: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
if (dwTag == ADDRMAP_TAG_LEARNED) {
|
||
LockNetworkMap();
|
||
dwTag =
|
||
ADDRMAP_TAG_LEARNED +
|
||
GetNetworkConnectionTag(
|
||
pAddressMapEntry->pszNetwork,
|
||
FALSE);
|
||
if (dwTag < pAddressMapEntry->params.dwTag) {
|
||
//
|
||
// We want to use this tag. Call
|
||
// GetNetworkConnectionTag(TRUE) to
|
||
// increment the next tag.
|
||
//
|
||
(void)GetNetworkConnectionTag(pAddressMapEntry->pszNetwork, TRUE);
|
||
}
|
||
UnlockNetworkMap();
|
||
}
|
||
//
|
||
// If there is no modified time associated with this
|
||
// address then it can only have a tag of ADDR_TAG_NONE.
|
||
//
|
||
if (!pAddressMapEntry->params.dwModifiedTime ||
|
||
dwTag >= pAddressMapEntry->params.dwTag)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
pAddressMapEntry->params.dwTag = dwTag;
|
||
pAddressMapEntry->params.dwModifiedTime = (DWORD)clock;
|
||
pAddressMapEntry->ulModifiedMask |= ADDRESS_MAP_FIELD_PARAMS;
|
||
|
||
return TRUE;
|
||
} // SetAddressTag
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetAddressTag(
|
||
IN LPTSTR pszAddress,
|
||
OUT LPDWORD lpdwTag
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("GetAddressWeight: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
*lpdwTag = pAddressMapEntry->params.dwTag;
|
||
|
||
return TRUE;
|
||
} // GetAddressWeight
|
||
|
||
|
||
|
||
VOID
|
||
ResetLearnedAddressIndex()
|
||
{
|
||
dwLearnedAddressIndexG = 0;
|
||
} // ResetLearnedAddressIndex
|
||
|
||
|
||
|
||
BOOLEAN
|
||
GetAddressNetwork(
|
||
IN LPTSTR pszAddress,
|
||
OUT LPTSTR *ppszNetwork
|
||
)
|
||
{
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, FALSE);
|
||
if (pAddressMapEntry == NULL || pAddressMapEntry->pszNetwork == NULL)
|
||
return FALSE;
|
||
*ppszNetwork = CopyString(pAddressMapEntry->pszNetwork);
|
||
|
||
return TRUE;
|
||
} // GetAddressNetwork
|
||
|
||
|
||
|
||
BOOLEAN
|
||
SetAddressDialingLocationEntry(
|
||
IN LPTSTR pszAddress,
|
||
IN LPTSTR pszEntryName
|
||
)
|
||
{
|
||
DWORD dwErr, dwLocationID;
|
||
BOOLEAN fFound = FALSE;
|
||
PLIST_ENTRY pEntry;
|
||
PADDRESS_MAP_ENTRY pAddressMapEntry;
|
||
PADDRESS_DIALING_ENTRY pDialingEntry;
|
||
|
||
//
|
||
// Get the current dialing location.
|
||
//
|
||
dwErr = TapiCurrentDialingLocation(&dwLocationID);
|
||
if (dwErr)
|
||
return FALSE;
|
||
//
|
||
// Find the address map entry that
|
||
// corresponds to the address.
|
||
//
|
||
pAddressMapEntry = GetAddressMapEntry(pszAddress, TRUE);
|
||
if (pAddressMapEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressDialingLocationEntry: GetAddressMapEntry failed");
|
||
return FALSE;
|
||
}
|
||
//
|
||
// Search for the existing dialing
|
||
// information that maps to the current
|
||
// dialing location.
|
||
//
|
||
for (pEntry = pAddressMapEntry->locationHead.Flink;
|
||
pEntry != &pAddressMapEntry->locationHead;
|
||
pEntry = pEntry->Flink)
|
||
{
|
||
pDialingEntry = CONTAINING_RECORD(
|
||
pEntry,
|
||
ADDRESS_DIALING_ENTRY,
|
||
ListEntry);
|
||
|
||
if (pDialingEntry->location.dwLocation == dwLocationID) {
|
||
fFound = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
//
|
||
// If we didn't find one, then
|
||
// create a new one.
|
||
//
|
||
if (!fFound) {
|
||
pDialingEntry = LocalAlloc(LPTR, sizeof (ADDRESS_DIALING_ENTRY));
|
||
if (pDialingEntry == NULL) {
|
||
RASAUTO_TRACE("SetAddressDialingLocationEntry: LocalAlloc failed");
|
||
return FALSE;
|
||
}
|
||
pDialingEntry->location.dwLocation = dwLocationID;
|
||
InsertTailList(&pAddressMapEntry->locationHead, &pDialingEntry->ListEntry);
|
||
}
|
||
//
|
||
// Update the dialing location structure
|
||
// with the new values.
|
||
//
|
||
pDialingEntry->fChanged = TRUE;
|
||
if (pDialingEntry->location.pszEntryName != NULL)
|
||
LocalFree(pDialingEntry->location.pszEntryName);
|
||
pDialingEntry->location.pszEntryName = CopyString(pszEntryName);
|
||
pAddressMapEntry->ulModifiedMask |= ADDRESS_MAP_FIELD_DIALINGLOC;
|
||
|
||
return TRUE;
|
||
} // SetAddressDialingLocationEntry
|
||
|
||
|
||
|
||
VOID
|
||
ResetDisabledAddresses(VOID)
|
||
{
|
||
HKEY hkey = NULL;
|
||
DWORD dwErr, i, dwi, dwLength, dwDisp, dwcbDisabledAddresses, dwType;
|
||
LPTSTR pszStart, pszNull, pszDisabledAddresses;
|
||
|
||
RASAUTO_TRACE("resetting disabled addresses");
|
||
|
||
ClearTable(pDisabledAddressesG);
|
||
|
||
//
|
||
// Hold the impersonation lock because otherwise
|
||
// hkeycug may be free from under this function.
|
||
//
|
||
|
||
LockImpersonation();
|
||
|
||
//
|
||
// Make sure that we have hkcu
|
||
//
|
||
dwErr = DwGetHkcu();
|
||
|
||
if(ERROR_SUCCESS != dwErr)
|
||
{
|
||
goto done;
|
||
}
|
||
|
||
dwErr = RegCreateKeyEx(
|
||
hkeyCUG,
|
||
AUTODIAL_REGCONTROLBASE,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_NON_VOLATILE,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&hkey,
|
||
&dwDisp);
|
||
if (dwErr) {
|
||
RASAUTO_TRACE1("ResetDisabledAddresses: RegCreateKey failed (dwErr=%d)", dwErr);
|
||
goto done;
|
||
}
|
||
if (RegGetValue(
|
||
hkey,
|
||
AUTODIAL_REGDISABLEDADDRVALUE,
|
||
&pszDisabledAddresses,
|
||
&dwcbDisabledAddresses,
|
||
&dwType) &&
|
||
(REG_MULTI_SZ == dwType) &&
|
||
dwcbDisabledAddresses)
|
||
{
|
||
//
|
||
// The registry key exists. Load only the addresses
|
||
// found in the registry into the table.
|
||
//
|
||
pszStart = pszDisabledAddresses;
|
||
for (;;) {
|
||
if (*pszStart == TEXT('\0'))
|
||
break;
|
||
pszNull = _tcschr(pszStart, '\0');
|
||
RASAUTO_TRACE1(
|
||
"ResetDisabledAddresses: adding %S as a disabled address",
|
||
pszStart);
|
||
PutTableEntry(pDisabledAddressesG, pszStart, NULL);
|
||
pszStart = pszNull + 1;
|
||
}
|
||
LocalFree(pszDisabledAddresses);
|
||
}
|
||
else {
|
||
//
|
||
// Initialize the disabled address table
|
||
// with the list of default disabled addresses.
|
||
//
|
||
dwcbDisabledAddresses = 1; // account for extra NULL at the end
|
||
for (i = 0; i < MAX_DISABLED_ADDRESSES; i++) {
|
||
RASAUTO_TRACE1(
|
||
"ResetDisabledAddresses: adding %S as a disabled address",
|
||
szDisabledAddresses[i]);
|
||
PutTableEntry(pDisabledAddressesG, szDisabledAddresses[i], NULL);
|
||
dwcbDisabledAddresses += _tcslen(szDisabledAddresses[i]) + 1;
|
||
}
|
||
pszDisabledAddresses = LocalAlloc(
|
||
LPTR,
|
||
dwcbDisabledAddresses * sizeof (TCHAR));
|
||
if (pszDisabledAddresses != NULL) {
|
||
*pszDisabledAddresses = TEXT('\0');
|
||
//
|
||
// A REG_MULTI_SZ has the strings separated by
|
||
// a NULL character and two NULL characters at
|
||
// the end.
|
||
//
|
||
for (i = 0, dwi = 0; i < MAX_DISABLED_ADDRESSES; i++) {
|
||
_tcscpy(&pszDisabledAddresses[dwi], szDisabledAddresses[i]);
|
||
dwi += _tcslen(szDisabledAddresses[i]) + 1;
|
||
}
|
||
dwErr = RegSetValueEx(
|
||
hkey,
|
||
AUTODIAL_REGDISABLEDADDRVALUE,
|
||
0,
|
||
REG_MULTI_SZ,
|
||
(PVOID)pszDisabledAddresses,
|
||
dwcbDisabledAddresses * sizeof (TCHAR));
|
||
if (dwErr)
|
||
RASAUTO_TRACE1("ResetDisabledAddresses: RegSetValue failed (dwErr=%d)", dwErr);
|
||
LocalFree(pszDisabledAddresses);
|
||
}
|
||
}
|
||
|
||
done:
|
||
|
||
if(NULL != hkey)
|
||
{
|
||
RegCloseKey(hkey);
|
||
}
|
||
|
||
UnlockImpersonation();
|
||
} // ResetDisabledAddresses
|
||
|
||
//
|
||
// Handles a new user coming active in the system (either by logging in or by
|
||
// FUS.
|
||
//
|
||
DWORD
|
||
AcsHandleNewUser(
|
||
IN HANDLE* phProcess)
|
||
{
|
||
DWORD dwErr = NO_ERROR;
|
||
HANDLE hProcess = *phProcess;
|
||
DWORD i;
|
||
|
||
do
|
||
{
|
||
//
|
||
// make sure that we think there is no user currently
|
||
// active.
|
||
//
|
||
if (hProcess != NULL)
|
||
{
|
||
RASAUTO_TRACE(
|
||
"AcsHandleNewUser: spurious signal of RasAutodialNewLogonUser event!");
|
||
break;
|
||
}
|
||
|
||
RASAUTO_TRACE("AcsHandleNewUser: new user came active");
|
||
|
||
//
|
||
// Refresh the impersonation token for this thread with that of the
|
||
// newly logged-in user. You may have to wait for the shell to
|
||
// start up.
|
||
//
|
||
for (i = 0; i < 15; i++)
|
||
{
|
||
Sleep(1000);
|
||
hProcess = RefreshImpersonation(hProcess);
|
||
if (hProcess != NULL)
|
||
{
|
||
break;
|
||
}
|
||
RASAUTO_TRACE("AcsHandleNewUser: waiting for shell startup");
|
||
}
|
||
|
||
if (hProcess == NULL)
|
||
{
|
||
RASAUTO_TRACE("AcsHandleNewUser: wait for shell startup failed!");
|
||
dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Load in the list of permanently disabled addresses.
|
||
//
|
||
LockDisabledAddresses();
|
||
ResetDisabledAddresses();
|
||
UnlockDisabledAddresses();
|
||
|
||
//
|
||
// Load in the address map from the registry.
|
||
//
|
||
if (!ResetAddressMap(TRUE))
|
||
{
|
||
RASAUTO_TRACE("AcsHandleNewUser: ResetAddressMap failed");
|
||
dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Calculate the initial network connectivity.
|
||
//
|
||
if (!UpdateNetworkMap(TRUE))
|
||
{
|
||
RASAUTO_TRACE("AcsHandleNewUser: UpdateNetworkMap failed");
|
||
dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Reset the "disable autodial for this login session" flag.
|
||
//
|
||
SetAutodialParam(RASADP_LoginSessionDisable, 0);
|
||
|
||
//
|
||
// Create an event to monitor AutoDial
|
||
// registry changes.
|
||
//
|
||
dwErr = CreateAutoDialChangeEvent(&hAutodialRegChangeG);
|
||
if (dwErr)
|
||
{
|
||
RASAUTO_TRACE1("AcsHandleNewUser: CreateAutoDialChangeEvent failed (dwErr=%d)", dwErr);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Enable the driver for notifications.
|
||
//
|
||
if (!EnableDriver())
|
||
{
|
||
RASAUTO_TRACE("AcsHandleNewUser: EnableDriver failed!");
|
||
dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
break;
|
||
}
|
||
|
||
}while (FALSE);
|
||
|
||
// Cleanup
|
||
{
|
||
*phProcess = hProcess;
|
||
}
|
||
|
||
return dwErr;
|
||
}
|
||
|
||
DWORD
|
||
AcsAddressMapThread(
|
||
LPVOID lpArg
|
||
)
|
||
|
||
/*++
|
||
|
||
DESCRIPTION
|
||
Periodically enumerate the disabled address list and
|
||
age-out (enable) old disabled addresses.
|
||
|
||
ARGUMENTS
|
||
None.
|
||
|
||
RETURN VALUE
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
BOOLEAN bStatus;
|
||
DWORD dwNow, dwLastFlushTicks = 0, dwLastAgeTicks = 0;
|
||
DWORD dwFlushFlags, dwErr, dwTimeout, dwcEvents;
|
||
HANDLE hProcess = NULL;
|
||
HANDLE hEvents[8];
|
||
|
||
//
|
||
// Create the table that contains the disabled addresses
|
||
// for the user. These are addresses that never cause
|
||
// Autodial attempts.
|
||
//
|
||
LockDisabledAddresses();
|
||
pDisabledAddressesG = NewTable();
|
||
UnlockDisabledAddresses();
|
||
if (pDisabledAddressesG == NULL) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: NewTable failed");
|
||
return GetLastError();
|
||
}
|
||
//
|
||
// We can't load the RAS DLLs in the main line
|
||
// of this system service's initialization, or
|
||
// we will cause a deadlock in the service
|
||
// controller, so we do it here.
|
||
//
|
||
if (!LoadRasDlls()) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: LoadRasDlls failed");
|
||
return GetLastError();
|
||
}
|
||
//
|
||
// Initialize the first entry of our
|
||
// event array for WaitForMutlipleObjects
|
||
// below.
|
||
//
|
||
hEvents[0] = hTerminatingG;
|
||
hEvents[1] = hNewLogonUserG;
|
||
hEvents[2] = hNewFusG;
|
||
hEvents[3] = hPnpEventG;
|
||
hEvents[4] = hConnectionEventG;
|
||
|
||
//
|
||
// Manually set hNewLogonUserG before we
|
||
// start to force us to check for a user
|
||
// logged into the workstation. We need
|
||
// to do this because userinit.exe signals
|
||
// this event upon logon, but it may
|
||
// run before this service is started
|
||
// after boot.
|
||
//
|
||
if (RefreshImpersonation(NULL) != NULL)
|
||
SetEvent(hNewLogonUserG);
|
||
//
|
||
// Periodically write changes to the registry,
|
||
// and age timeout addresses.
|
||
//
|
||
for (;;) {
|
||
//
|
||
// Unload any user-based resources before
|
||
// a potentially long-term wait.
|
||
//
|
||
// PrepareForLongWait();
|
||
//
|
||
// Construct the event array for
|
||
// WaitForMultipleObjects.
|
||
//
|
||
if (hProcess != NULL) {
|
||
hEvents[5] = hTapiChangeG;
|
||
hEvents[6] = hAutodialRegChangeG;
|
||
hEvents[7] = hLogoffUserG;
|
||
dwcEvents = 8;
|
||
}
|
||
else {
|
||
hEvents[5] = NULL;
|
||
hEvents[6] = NULL;
|
||
hEvents[7] = NULL;
|
||
dwcEvents = 5;
|
||
}
|
||
|
||
RASAUTO_TRACE1("AcsAddressMapThread: waiting for events..dwcEvents = %d", dwcEvents);
|
||
status = WaitForMultipleObjects(
|
||
dwcEvents,
|
||
hEvents,
|
||
FALSE,
|
||
INFINITE);
|
||
RASAUTO_TRACE1(
|
||
"AcsAddressMapThread: WaitForMultipleObjects returned %d",
|
||
status);
|
||
//
|
||
// RASAUTO_TRACE() who we think the currently
|
||
// impersonated user is.
|
||
//
|
||
TraceCurrentUser();
|
||
//
|
||
// Process the WaitForMultipleObjects() results.
|
||
//
|
||
if (status == WAIT_OBJECT_0 || status == WAIT_FAILED) {
|
||
RASAUTO_TRACE1("AcsAddressMapThread: status=%d: shutting down", status);
|
||
break;
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 1)
|
||
{
|
||
AcsHandleNewUser(&hProcess);
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 2)
|
||
{
|
||
//
|
||
// A new user has fast-user-switched to the console.
|
||
//
|
||
// XP 353082
|
||
//
|
||
// The service control handler will have set the
|
||
// new active session id so we just need to refresh
|
||
// impersonation.
|
||
//
|
||
RevertImpersonation();
|
||
hProcess = NULL;
|
||
AcsHandleNewUser(&hProcess);
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 3)
|
||
{
|
||
//
|
||
// A pnp event has occured that may affect network
|
||
// connectivity
|
||
//
|
||
// XP 364593
|
||
//
|
||
// Recalculate what networks are up/down.
|
||
//
|
||
RASAUTO_TRACE("AcsAddressMapThread: pnp event signaled");
|
||
if (!ResetAddressMap(TRUE))
|
||
{
|
||
RASAUTO_TRACE("AcsAddressMapThread: ResetAddressMap failed");
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Calculate the initial network connectivity.
|
||
//
|
||
if (!UpdateNetworkMap(TRUE))
|
||
{
|
||
RASAUTO_TRACE("AcsAddressMapThread: UpdateNetworkMap failed");
|
||
continue;
|
||
}
|
||
|
||
if (!EnableDriver()) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
|
||
continue;
|
||
}
|
||
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 4) {
|
||
//
|
||
// A RAS connection has been created
|
||
// or destroyed. Flush the address
|
||
// map to the registry.
|
||
//
|
||
RASAUTO_TRACE("AcsAddressMapThread: RAS connection change");
|
||
if (hProcess != NULL) {
|
||
LockAddressMap();
|
||
FlushAddressMap();
|
||
UnlockAddressMap();
|
||
ResetAddressMap(FALSE);
|
||
|
||
if (!UpdateNetworkMap(FALSE))
|
||
RASAUTO_TRACE("AcsAddressMapThread: UpdateNetworkMap failed");
|
||
}
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 5) {
|
||
//
|
||
// Process the TAPI event that just ocurred.
|
||
//
|
||
RASAUTO_TRACE("AcsAddressMapThread: TAPI changed");
|
||
ProcessTapiChangeEvent();
|
||
//
|
||
// Enable the driver for notifications
|
||
// for possibly a new dialing location.
|
||
//
|
||
if (!EnableDriver()) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
|
||
continue;
|
||
}
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 6) {
|
||
//
|
||
// The Autodial registry changed. Reset the
|
||
// address map.
|
||
//
|
||
RASAUTO_TRACE("AcsAddressMapThread: registry changed");
|
||
if (ExternalAutoDialChangeEvent()) {
|
||
//
|
||
// We fake this today by making it appear
|
||
// a new user has logged in. We definitely
|
||
// could be smarter about how we do this
|
||
// in the future.
|
||
//
|
||
if (!ResetAddressMap(FALSE)) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: ResetAddressMap failed");
|
||
continue;
|
||
}
|
||
}
|
||
//
|
||
// Re-register the change notification.
|
||
//
|
||
NotifyAutoDialChangeEvent(hAutodialRegChangeG);
|
||
//
|
||
// Enable the driver for notifications
|
||
// for possibly a new enabled value for
|
||
// the current dialing location.
|
||
//
|
||
if (!EnableDriver()) {
|
||
RASAUTO_TRACE("AcsAddressMapThread: EnableDriver failed!");
|
||
continue;
|
||
}
|
||
}
|
||
else if (status == WAIT_OBJECT_0 + 7) {
|
||
//
|
||
// The user is logging out.
|
||
//
|
||
RASAUTO_TRACE("AcsAddressThread: user is logging out");
|
||
//
|
||
// Write out the address map to the registry
|
||
// before we reset.
|
||
//
|
||
LockAddressMap();
|
||
FlushAddressMap();
|
||
ClearAddressMap();
|
||
UnlockAddressMap();
|
||
//
|
||
// Clear the network database.
|
||
//
|
||
LockNetworkMap();
|
||
ClearNetworkMap();
|
||
UnlockNetworkMap();
|
||
//
|
||
// Remove our registry change event.
|
||
//
|
||
CloseAutoDialChangeEvent(hAutodialRegChangeG);
|
||
hAutodialRegChangeG = NULL;
|
||
//
|
||
// Clear out the user tokens.
|
||
//
|
||
RevertImpersonation();
|
||
hProcess = NULL;
|
||
//
|
||
// Reset the driver.
|
||
//
|
||
ResetDriver();
|
||
//
|
||
// Unload HKEY_CURRENT_USER.
|
||
//
|
||
// PrepareForLongWait();
|
||
//
|
||
// Signal winlogon that we have flushed
|
||
// HKEY_CURRENT_USER.
|
||
//
|
||
SetEvent(hLogoffUserDoneG);
|
||
}
|
||
}
|
||
|
||
RASAUTO_TRACE("AcsAddressMapThread: exiting");
|
||
return 0;
|
||
} // AcsAddressMapThread
|
||
|
||
|
||
|