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
|
|||
|
|
|||
|
|
|||
|
|