You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2498 lines
70 KiB
2498 lines
70 KiB
/*++
|
|
|
|
Copyright(c) 1995 Microsoft Corporation
|
|
|
|
MODULE NAME
|
|
rasprocs.c
|
|
|
|
ABSTRACT
|
|
RAS utility routines.
|
|
|
|
AUTHOR
|
|
Anthony Discolo (adiscolo) 23-Mar-1995
|
|
|
|
REVISION HISTORY
|
|
Original version from Gurdeep
|
|
|
|
--*/
|
|
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <npapi.h>
|
|
#include <ras.h>
|
|
#include <raserror.h>
|
|
#include <rasman.h>
|
|
#include <winsock.h>
|
|
#include <acd.h>
|
|
#include <tapi.h>
|
|
#include <debug.h>
|
|
#include <userenv.h>
|
|
|
|
#include "reg.h"
|
|
#include "table.h"
|
|
#include "addrmap.h"
|
|
#include "access.h"
|
|
#include "misc.h"
|
|
#include "process.h"
|
|
#include "rasprocs.h"
|
|
#include "tapiproc.h"
|
|
#include "imperson.h"
|
|
|
|
extern HKEY hkeyCUG;
|
|
|
|
extern PHASH_TABLE pDisabledAddressesG;
|
|
|
|
//
|
|
// rasdlui command line strings.
|
|
//
|
|
#define RASAUTOUI_EXE L"rasautou.exe" // .exe name
|
|
#define RASAUTOUI_NOENTRY L"rasautou -a \"%s\""
|
|
#define RASAUTOUI_CUSTOMDIALENTRY L"rasautou -d \"%s\" -p \"%s\" -e \"%s\""
|
|
#define RASAUTOUI_DEFAULTDIALENTRY L"rasautou -a \"%s\" -e \"%s\""
|
|
#define RASAUTOUI_DEFAULTDIALENTRY2 L"rasautou -q -a \"%s\" -e \"%s\""
|
|
#define RASAUTOUI_REDIALENTRY L"rasautou -r -f \"%s\" -e \"%s\""
|
|
|
|
//
|
|
// DLL module handles for rasapi32.dll and rasman.dll.
|
|
//
|
|
#define RASAPI_MODULE L"RASAPI32"
|
|
HANDLE hRasApiG;
|
|
|
|
#define RASMAN_MODULE L"RASMAN"
|
|
HANDLE hRasManG;
|
|
|
|
//
|
|
// DLL entrypoints for rasapi32.dll.
|
|
//
|
|
#define RASDIAL "RasDialW"
|
|
FARPROC lpfnRasDialG;
|
|
|
|
#define RASENUMCONNECTIONS "RasEnumConnectionsW"
|
|
FARPROC lpfnRasEnumConnectionsG;
|
|
|
|
#define RASENUMENTRIES "RasEnumEntriesW"
|
|
FARPROC lpfnRasEnumEntriesG;
|
|
|
|
#define RASGETCONNECTSTATUS "RasGetConnectStatusW"
|
|
FARPROC lpfnRasGetConnectStatusG;
|
|
|
|
#define RASGETHPORT "RasGetHport"
|
|
FARPROC lpfnRasGetHportG;
|
|
|
|
#define RASGETPROJECTIONINFO "RasGetProjectionInfoW"
|
|
FARPROC lpfnRasGetProjectionInfoG;
|
|
|
|
#define RASGETENTRYPROPERTIES "RasGetEntryPropertiesW"
|
|
FARPROC lpfnRasGetEntryPropertiesG;
|
|
|
|
#define RASGETAUTODIALADDRESS "RasGetAutodialAddressW"
|
|
FARPROC lpfnRasGetAutodialAddressG;
|
|
|
|
#define RASSETAUTODIALADDRESS "RasSetAutodialAddressW"
|
|
FARPROC lpfnRasSetAutodialAddressG;
|
|
|
|
#define RASENUMAUTODIALADDRESSES "RasEnumAutodialAddressesW"
|
|
FARPROC lpfnRasEnumAutodialAddressesG;
|
|
|
|
#define RASGETAUTODIALENABLE "RasGetAutodialEnableW"
|
|
FARPROC lpfnRasGetAutodialEnableG;
|
|
|
|
#define RASSETAUTODIALENABLE "RasSetAutodialEnableW"
|
|
FARPROC lpfnRasSetAutodialEnableG;
|
|
|
|
#define RASAUTODIALADDRESSTONETWORK "RasAutodialAddressToNetwork"
|
|
FARPROC lpfnRasAutodialAddressToNetworkG;
|
|
|
|
#define RASAUTODIALENTRYTONETWORK "RasAutodialEntryToNetwork"
|
|
FARPROC lpfnRasAutodialEntryToNetworkG;
|
|
|
|
#define RASCONNECTIONNOTIFICATION "RasConnectionNotificationW"
|
|
FARPROC lpfnRasConnectionNotificationG;
|
|
|
|
#define RASGETAUTODIALPARAM "RasGetAutodialParamW"
|
|
FARPROC lpfnRasGetAutodialParamG;
|
|
|
|
#define RASSETAUTODIALPARAM "RasSetAutodialParamW"
|
|
FARPROC lpfnRasSetAutodialParamG;
|
|
|
|
#define RASQUERYSHAREDAUTODIAL "RasQuerySharedAutoDial"
|
|
FARPROC lpfnRasQuerySharedAutoDialG;
|
|
|
|
#define RASQUERYSHAREDCONNECTION "RasQuerySharedConnection"
|
|
FARPROC lpfnRasQuerySharedConnectionG;
|
|
|
|
#define RASQUERYREDIALONLINKFAILURE "RasQueryRedialOnLinkFailure"
|
|
FARPROC lpfnRasQueryRedialOnLinkFailureG;
|
|
|
|
#define RASGETCREDENTIALS "RasGetCredentialsW"
|
|
FARPROC lpfnRasGetCredentialsG;
|
|
|
|
#define RASHANGUP "RasHangUpW"
|
|
FARPROC lpfnRasHangUpG;
|
|
|
|
//
|
|
// DLL entrypoints for rasman.dll.
|
|
//
|
|
#define RASPORTRETRIEVEUSERDATA "RasPortRetrieveUserData"
|
|
FARPROC lpfnRasPortRetrieveUserDataG;
|
|
|
|
#define RASPORTENUMPROTOCOLS "RasPortEnumProtocols"
|
|
FARPROC lpfnRasPortEnumProtocolsG;
|
|
|
|
#define RASPORTENUM "RasPortEnum"
|
|
FARPROC lpfnRasPortEnumG;
|
|
|
|
#define RASINITIALIZE "RasInitialize"
|
|
FARPROC lpfnRasInitializeG;
|
|
|
|
#define RASREFERENCERASMAN "RasReferenceRasman"
|
|
FARPROC lpfnRasReferenceRasmanG;
|
|
|
|
#define RASPORTOPEN "RasPortOpen"
|
|
FARPROC lpfnRasPortOpenG;
|
|
|
|
#define RASPORTCLOSE "RasPortClose"
|
|
FARPROC lpfnRasPortCloseG;
|
|
|
|
#define RASGETINFO "RasGetInfo"
|
|
FARPROC lpfnRasGetInfoG;
|
|
|
|
#define RASGETPORTUSERDATA "RasGetPortUserData"
|
|
FARPROC lpfnRasGetPortUserDataG;
|
|
|
|
#define RASREGISTERREDIALCALLBACK "RasRegisterRedialCallback"
|
|
FARPROC lpfnRasRegisterRedialCallbackG;
|
|
|
|
//
|
|
// Hostent cache.
|
|
//
|
|
#define HOSTENTCACHESIZ 10
|
|
|
|
typedef struct _HOSTENT_CACHE {
|
|
CHAR szDns[ACD_ADDR_INET_LEN];
|
|
ULONG ulIpaddr;
|
|
} HOSTENT_CACHE, *PHOSTENT_CACHE;
|
|
|
|
//
|
|
// External definitions
|
|
//
|
|
VOID
|
|
AcsRedialOnLinkFailure(
|
|
LPSTR lpszPhonebook,
|
|
LPSTR lpszEntry);
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
CRITICAL_SECTION csRasG;
|
|
INT nRasReferencesG;
|
|
BOOLEAN fAutoDialRegChangeG;
|
|
HKEY hkeyAutoDialRegChangeG;
|
|
HANDLE hConnectionEventG = NULL;
|
|
|
|
HOSTENT_CACHE hostentCacheG[HOSTENTCACHESIZ];
|
|
INT iHostentCacheG = 0;
|
|
|
|
//
|
|
// Private structure returned by
|
|
// RasPortRetrieveUserData().
|
|
//
|
|
typedef struct _StoredData {
|
|
DWORD arg;
|
|
BOOLEAN fAuthenticated;
|
|
} StoredData;
|
|
|
|
//
|
|
// External variables
|
|
//
|
|
extern HANDLE hAcdG;
|
|
extern HANDLE hTerminatingG;
|
|
|
|
|
|
|
|
BOOLEAN
|
|
LoadRasDlls()
|
|
{
|
|
BOOLEAN fSuccess = FALSE;
|
|
SC_HANDLE hSCManager, hService;
|
|
SERVICE_STATUS status;
|
|
DWORD dwErr, dwcDevices, dwDisp;
|
|
|
|
//
|
|
// Since these DLLs will be loaded/unloaded
|
|
// by multiple threads, we must do this under
|
|
// a mutex.
|
|
//
|
|
EnterCriticalSection(&csRasG);
|
|
//
|
|
// If the DLLs have already been successfully
|
|
// loaded, no further processing is necessary.
|
|
//
|
|
if (nRasReferencesG) {
|
|
fSuccess = TRUE;
|
|
goto done;
|
|
}
|
|
#ifdef notdef
|
|
//
|
|
// Get a service controller handle on
|
|
// the rasman service.
|
|
//
|
|
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
if (hSCManager == NULL)
|
|
goto done;
|
|
hService = OpenService(
|
|
hSCManager,
|
|
TEXT(RASMAN_SERVICE_NAME),
|
|
SERVICE_START|SERVICE_QUERY_STATUS);
|
|
if (hService == NULL) {
|
|
CloseServiceHandle(hSCManager);
|
|
goto done;
|
|
}
|
|
//
|
|
// Start the rasman service if necessary.
|
|
//
|
|
do {
|
|
if (!QueryServiceStatus(hService, &status))
|
|
break;
|
|
switch (status.dwCurrentState) {
|
|
case SERVICE_STOP_PENDING:
|
|
case SERVICE_START_PENDING:
|
|
Sleep(500);
|
|
break;
|
|
case SERVICE_STOPPED:
|
|
StartService(hService, 0, NULL);
|
|
break;
|
|
case SERVICE_RUNNING:
|
|
break;
|
|
}
|
|
} while (status.dwCurrentState != SERVICE_RUNNING);
|
|
CloseServiceHandle(hService);
|
|
CloseServiceHandle(hSCManager);
|
|
if (status.dwCurrentState != SERVICE_RUNNING) {
|
|
RASAUTO_TRACE("LoadRasDlls: Could not start rasman service");
|
|
goto done;
|
|
}
|
|
#endif
|
|
//
|
|
// Load rasapi32.dll.
|
|
//
|
|
hRasApiG = LoadLibrary(RASAPI_MODULE);
|
|
if (hRasApiG == NULL) {
|
|
RASAUTO_TRACE("LoadRasDlls: couldn't load rasapi32.dll");
|
|
goto done;
|
|
}
|
|
lpfnRasDialG = GetProcAddress(hRasApiG, RASDIAL);
|
|
lpfnRasEnumConnectionsG = GetProcAddress(hRasApiG, RASENUMCONNECTIONS);
|
|
lpfnRasEnumEntriesG = GetProcAddress(hRasApiG, RASENUMENTRIES);
|
|
lpfnRasGetConnectStatusG = GetProcAddress(hRasApiG, RASGETCONNECTSTATUS );
|
|
lpfnRasGetHportG = GetProcAddress(hRasApiG, RASGETHPORT);
|
|
lpfnRasGetProjectionInfoG = GetProcAddress(hRasApiG, RASGETPROJECTIONINFO);
|
|
lpfnRasGetEntryPropertiesG = GetProcAddress(hRasApiG, RASGETENTRYPROPERTIES);
|
|
lpfnRasGetAutodialAddressG = GetProcAddress(hRasApiG, RASGETAUTODIALADDRESS);
|
|
lpfnRasSetAutodialAddressG = GetProcAddress(hRasApiG, RASSETAUTODIALADDRESS);
|
|
lpfnRasEnumAutodialAddressesG = GetProcAddress(hRasApiG, RASENUMAUTODIALADDRESSES);
|
|
lpfnRasGetAutodialEnableG = GetProcAddress(hRasApiG, RASGETAUTODIALENABLE);
|
|
lpfnRasSetAutodialEnableG = GetProcAddress(hRasApiG, RASSETAUTODIALENABLE);
|
|
lpfnRasAutodialAddressToNetworkG =
|
|
GetProcAddress(hRasApiG, RASAUTODIALADDRESSTONETWORK);
|
|
lpfnRasAutodialEntryToNetworkG =
|
|
GetProcAddress(hRasApiG, RASAUTODIALENTRYTONETWORK);
|
|
lpfnRasConnectionNotificationG =
|
|
GetProcAddress(hRasApiG, RASCONNECTIONNOTIFICATION);
|
|
lpfnRasGetAutodialParamG = GetProcAddress(hRasApiG, RASGETAUTODIALPARAM);
|
|
lpfnRasSetAutodialParamG = GetProcAddress(hRasApiG, RASSETAUTODIALPARAM);
|
|
lpfnRasQuerySharedAutoDialG = GetProcAddress(hRasApiG, RASQUERYSHAREDAUTODIAL);
|
|
lpfnRasQuerySharedConnectionG = GetProcAddress(hRasApiG, RASQUERYSHAREDCONNECTION);
|
|
lpfnRasQueryRedialOnLinkFailureG = GetProcAddress(hRasApiG, RASQUERYREDIALONLINKFAILURE);
|
|
lpfnRasGetCredentialsG = GetProcAddress(hRasApiG, RASGETCREDENTIALS);
|
|
lpfnRasHangUpG = GetProcAddress(hRasApiG, RASHANGUP);
|
|
if (!lpfnRasEnumConnectionsG || !lpfnRasEnumEntriesG ||
|
|
!lpfnRasGetConnectStatusG || !lpfnRasGetHportG ||
|
|
!lpfnRasGetProjectionInfoG || !lpfnRasGetAutodialAddressG ||
|
|
!lpfnRasSetAutodialAddressG || !lpfnRasEnumAutodialAddressesG ||
|
|
!lpfnRasGetAutodialEnableG || !lpfnRasSetAutodialEnableG ||
|
|
!lpfnRasAutodialAddressToNetworkG || !lpfnRasAutodialEntryToNetworkG ||
|
|
!lpfnRasConnectionNotificationG || !lpfnRasGetAutodialParamG ||
|
|
!lpfnRasSetAutodialParamG || !lpfnRasQuerySharedConnectionG ||
|
|
!lpfnRasQuerySharedAutoDialG || !lpfnRasQueryRedialOnLinkFailureG ||
|
|
!lpfnRasGetCredentialsG || !lpfnRasHangUpG)
|
|
{
|
|
RASAUTO_TRACE("LoadRasDlls: couldn't find entrypoints in rasapi32.dll");
|
|
goto done;
|
|
}
|
|
//
|
|
// Load rasman.dll.
|
|
//
|
|
hRasManG = LoadLibrary(RASMAN_MODULE);
|
|
if (hRasManG == NULL) {
|
|
RASAUTO_TRACE("LoadRasDlls: couldn't load rasman.dll");
|
|
goto done;
|
|
}
|
|
lpfnRasPortRetrieveUserDataG = GetProcAddress(
|
|
hRasManG,
|
|
RASPORTRETRIEVEUSERDATA);
|
|
lpfnRasPortEnumProtocolsG = GetProcAddress(hRasManG, RASPORTENUMPROTOCOLS);
|
|
lpfnRasPortEnumG = GetProcAddress(hRasManG, RASPORTENUM);
|
|
lpfnRasInitializeG = GetProcAddress(hRasManG, RASINITIALIZE);
|
|
lpfnRasReferenceRasmanG = GetProcAddress(hRasManG, RASREFERENCERASMAN);
|
|
lpfnRasPortOpenG = GetProcAddress(hRasManG, RASPORTOPEN);
|
|
lpfnRasPortCloseG = GetProcAddress(hRasManG, RASPORTCLOSE);
|
|
lpfnRasGetInfoG = GetProcAddress(hRasManG, RASGETINFO);
|
|
lpfnRasGetPortUserDataG = GetProcAddress(hRasManG, RASGETPORTUSERDATA);
|
|
lpfnRasRegisterRedialCallbackG = GetProcAddress(
|
|
hRasManG,
|
|
RASREGISTERREDIALCALLBACK);
|
|
if (!lpfnRasPortRetrieveUserDataG ||
|
|
!lpfnRasPortEnumProtocolsG ||
|
|
!lpfnRasPortEnumG ||
|
|
!lpfnRasInitializeG ||
|
|
!lpfnRasReferenceRasmanG ||
|
|
!lpfnRasPortOpenG ||
|
|
!lpfnRasPortCloseG ||
|
|
!lpfnRasGetInfoG ||
|
|
!lpfnRasGetPortUserDataG ||
|
|
!lpfnRasRegisterRedialCallbackG ||
|
|
(*lpfnRasInitializeG)() ||
|
|
(*lpfnRasReferenceRasmanG)(TRUE))
|
|
{
|
|
RASAUTO_TRACE("LoadRasDlls: couldn't find entrypoints in rasman.dll");
|
|
goto done;
|
|
}
|
|
//
|
|
// rasman will let us know when to invoke redial-on-link-failure
|
|
// and for which phonebook entry.
|
|
//
|
|
SetRedialOnLinkFailureHandler((FARPROC)AcsRedialOnLinkFailure);
|
|
RASAUTO_TRACE("LoadRasDlls: set redial-on-link-failure handler");
|
|
//
|
|
// rasapi32 will let us when new RAS connections
|
|
// are created or destroyed by signaling our
|
|
// event.
|
|
//
|
|
dwErr = (DWORD)(*lpfnRasConnectionNotificationG)(
|
|
INVALID_HANDLE_VALUE,
|
|
hConnectionEventG,
|
|
RASCN_Connection|RASCN_Disconnection);
|
|
RASAUTO_TRACE1("LoadRasDlls: RasConnectionNotification returned dwErr=%d", dwErr);
|
|
fSuccess = !dwErr;
|
|
|
|
done:
|
|
if (fSuccess) {
|
|
#ifdef notdef
|
|
// for now, we don't need multiple references
|
|
nRasReferencesG++;
|
|
#endif
|
|
nRasReferencesG = 1;
|
|
}
|
|
else {
|
|
if (hRasManG != NULL)
|
|
FreeLibrary(hRasManG);
|
|
if (hRasApiG != NULL)
|
|
FreeLibrary(hRasApiG);
|
|
hRasManG = hRasApiG = NULL;
|
|
}
|
|
LeaveCriticalSection(&csRasG);
|
|
|
|
return fSuccess;
|
|
} // LoadRasDlls
|
|
|
|
|
|
|
|
VOID
|
|
UnloadRasDlls()
|
|
{
|
|
DWORD dwErr;
|
|
|
|
//
|
|
// Since these DLLs will be loaded/unloaded
|
|
// by multiple threads, we must do this under
|
|
// a mutex.
|
|
//
|
|
EnterCriticalSection(&csRasG);
|
|
if (nRasReferencesG) {
|
|
//
|
|
// Unregister the callback function for
|
|
// redial on link failure
|
|
//
|
|
(void)(*lpfnRasRegisterRedialCallbackG)(NULL);
|
|
//
|
|
// Inform rasman.dll we are unloading it.
|
|
//
|
|
(void)(*lpfnRasReferenceRasmanG)(FALSE);
|
|
if (hRasApiG != NULL)
|
|
FreeLibrary(hRasApiG);
|
|
if (hRasManG != NULL)
|
|
FreeLibrary(hRasManG);
|
|
nRasReferencesG--;
|
|
}
|
|
|
|
LeaveCriticalSection(&csRasG);
|
|
} // UnloadRasDlls
|
|
|
|
|
|
|
|
BOOLEAN
|
|
RasDllsLoaded()
|
|
{
|
|
BOOLEAN fLoaded;
|
|
|
|
EnterCriticalSection(&csRasG);
|
|
fLoaded = (BOOLEAN)nRasReferencesG;
|
|
LeaveCriticalSection(&csRasG);
|
|
|
|
return fLoaded;
|
|
} // RasDllsLoaded
|
|
|
|
|
|
|
|
DWORD
|
|
ActiveConnections(
|
|
IN BOOLEAN fAuthenticated,
|
|
OUT LPTSTR **lppEntryNames,
|
|
OUT HRASCONN **lpphRasConn
|
|
)
|
|
|
|
/*++
|
|
|
|
DESCRIPTION
|
|
Enumerate the list of active RAS connections, and put the
|
|
phone book entry names in lppEntryNames. Return the number
|
|
of entries in the list.
|
|
|
|
ARGUMENTS
|
|
fAuthenticated: TRUE if the resulting arrays should contain
|
|
only authenticated entries.
|
|
|
|
lppEntryNames: a pointer which is set to the allocated array
|
|
of phone book entry names.
|
|
|
|
lpphRasConn: a pointer which is set to the allocated array
|
|
of RASCONN descriptors corresponding to the phone book
|
|
entries.
|
|
|
|
RETURN VALUE
|
|
The number of entries in lppEntryNames.
|
|
|
|
--*/
|
|
|
|
{
|
|
RASCONN RasCon;
|
|
RASCONN *lpRasCon = NULL;
|
|
DWORD dwStatus;
|
|
DWORD dwSize;
|
|
DWORD dwConnections;
|
|
DWORD dwRealConnections = 0;
|
|
DWORD dwIndex;
|
|
RASCONNSTATUS RasConStatus;
|
|
HPORT hPort;
|
|
PBYTE lpUserData = NULL;
|
|
BOOLEAN fEntryAuthenticated;
|
|
|
|
//
|
|
// Initialize return values.
|
|
//
|
|
if (lppEntryNames != NULL)
|
|
*lppEntryNames = NULL;
|
|
if (lpphRasConn != NULL)
|
|
*lpphRasConn = NULL;
|
|
//
|
|
// Allow this routine to be called
|
|
// even when the RAS dlls are not loaded.
|
|
//
|
|
if (!RasDllsLoaded())
|
|
goto done;
|
|
//
|
|
// Get the number of active connections. We
|
|
// allocate a buffer large enough for one connection
|
|
// initially, and reallocate it if it's too small.
|
|
//
|
|
lpRasCon = LocalAlloc(LPTR, sizeof (RASCONN));
|
|
if (lpRasCon == NULL) {
|
|
RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
lpRasCon[0].dwSize = sizeof (RASCONN);
|
|
dwSize = sizeof (RASCONN);
|
|
dwStatus = (DWORD)(*lpfnRasEnumConnectionsG)(lpRasCon, &dwSize, &dwConnections);
|
|
if (dwStatus == ERROR_BUFFER_TOO_SMALL) {
|
|
//
|
|
// Buffer's too small. Reallocate and try again.
|
|
//
|
|
LocalFree(lpRasCon);
|
|
lpRasCon = LocalAlloc(LPTR, dwSize);
|
|
if (lpRasCon == NULL) {
|
|
RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
lpRasCon[0].dwSize = sizeof (RASCONN);
|
|
dwStatus = (DWORD)(*lpfnRasEnumConnectionsG)(
|
|
lpRasCon,
|
|
&dwSize,
|
|
&dwConnections);
|
|
}
|
|
if (dwStatus) {
|
|
RASAUTO_TRACE1(
|
|
"ActiveConnections: RasEnumConnections failed (dwStatus=0x%x)",
|
|
dwStatus);
|
|
goto done;
|
|
}
|
|
//
|
|
// Short-circuit the rest if there
|
|
// are no connections.
|
|
//
|
|
if (!dwConnections)
|
|
goto done;
|
|
//
|
|
// Allocate the user's return buffers,
|
|
// if necessary.
|
|
//
|
|
if (lppEntryNames != NULL) {
|
|
*lppEntryNames = LocalAlloc(LPTR, (dwConnections+1) * sizeof (LPTSTR));
|
|
if (*lppEntryNames == NULL) {
|
|
RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
}
|
|
if (lpphRasConn != NULL) {
|
|
*lpphRasConn = LocalAlloc(LPTR, (dwConnections+1) * sizeof (HRASCONN));
|
|
if (*lpphRasConn == NULL) {
|
|
RASAUTO_TRACE("ActiveConnections: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
}
|
|
//
|
|
// Go through each connection, and
|
|
// check to see if the connection's
|
|
// passed the authentication phase yet.
|
|
//
|
|
for (dwIndex = 0; dwIndex < dwConnections; dwIndex++) {
|
|
RasConStatus.dwSize = sizeof (RASCONNSTATUS);
|
|
dwStatus = (DWORD)(*lpfnRasGetConnectStatusG)(
|
|
lpRasCon[dwIndex].hrasconn,
|
|
&RasConStatus);
|
|
if (dwStatus) {
|
|
RASAUTO_TRACE2(
|
|
"ActiveConnections: RasGetConnectStatus(%S) failed (dwStatus=0x%x)",
|
|
lpRasCon[dwIndex].szEntryName,
|
|
dwStatus);
|
|
continue;
|
|
}
|
|
//
|
|
// If the connection is not connected,
|
|
// then skip it.
|
|
//
|
|
RASAUTO_TRACE2("ActiveConnections: state for hrasconn 0x%x is %d",
|
|
lpRasCon[dwIndex].hrasconn,
|
|
RasConStatus.rasconnstate);
|
|
//
|
|
// If the caller specified only authenticated entries
|
|
// and the entry is not yet connected, then skip it.
|
|
//
|
|
if (fAuthenticated && RasConStatus.rasconnstate != RASCS_Connected)
|
|
continue;
|
|
if (lppEntryNames != NULL) {
|
|
(*lppEntryNames)[dwRealConnections] =
|
|
CopyString(lpRasCon[dwIndex].szEntryName);
|
|
}
|
|
if (lpphRasConn != NULL)
|
|
(*lpphRasConn)[dwRealConnections] = lpRasCon[dwIndex].hrasconn;
|
|
RASAUTO_TRACE2(
|
|
"ActiveConnections: (%S, 0x%x)",
|
|
lpRasCon[dwIndex].szEntryName,
|
|
lpRasCon[dwIndex].hrasconn);
|
|
dwRealConnections++;
|
|
}
|
|
|
|
done:
|
|
if (lpRasCon != NULL)
|
|
LocalFree(lpRasCon);
|
|
if (lpUserData != NULL)
|
|
LocalFree(lpUserData);
|
|
if (!dwRealConnections) {
|
|
if (lppEntryNames != NULL) {
|
|
if (*lppEntryNames != NULL) {
|
|
LocalFree(*lppEntryNames);
|
|
*lppEntryNames = NULL;
|
|
}
|
|
}
|
|
if (lpphRasConn != NULL) {
|
|
if (*lpphRasConn != NULL) {
|
|
LocalFree(*lpphRasConn);
|
|
*lpphRasConn = NULL;
|
|
}
|
|
}
|
|
}
|
|
return dwRealConnections;
|
|
} // ActiveConnections
|
|
|
|
|
|
|
|
LPTSTR
|
|
AddressToNetwork(
|
|
LPTSTR pszAddress
|
|
)
|
|
{
|
|
DWORD dwErr, dwSize;
|
|
LPTSTR pszNetwork = NULL;
|
|
|
|
//
|
|
// Map an address to a network name
|
|
// by calling a (currently) private rasapi32 API.
|
|
//
|
|
dwSize = 0;
|
|
dwErr = (DWORD)(*lpfnRasAutodialAddressToNetworkG)(pszAddress, NULL, &dwSize);
|
|
if (dwErr)
|
|
goto done;
|
|
pszNetwork = LocalAlloc(LPTR, dwSize);
|
|
if (pszNetwork == NULL) {
|
|
dwErr = GetLastError();
|
|
goto done;
|
|
}
|
|
dwErr = (DWORD)(*lpfnRasAutodialAddressToNetworkG)(
|
|
pszAddress,
|
|
pszNetwork,
|
|
&dwSize);
|
|
|
|
done:
|
|
return (!dwErr ? pszNetwork : NULL);
|
|
} // AddressToNetwork
|
|
|
|
|
|
|
|
LPTSTR
|
|
EntryToNetwork(
|
|
LPTSTR pszEntry
|
|
)
|
|
{
|
|
DWORD dwErr, dwSize;
|
|
LPTSTR pszNetwork = NULL;
|
|
|
|
//
|
|
// Map an address to a network name
|
|
// by calling a (currently) private rasapi32 API.
|
|
//
|
|
dwSize = 0;
|
|
dwErr = (DWORD)(*lpfnRasAutodialEntryToNetworkG)(pszEntry, NULL, &dwSize);
|
|
if (dwErr)
|
|
goto done;
|
|
pszNetwork = LocalAlloc(LPTR, dwSize);
|
|
if (pszNetwork == NULL) {
|
|
dwErr = GetLastError();
|
|
goto done;
|
|
}
|
|
dwErr = (DWORD)(*lpfnRasAutodialEntryToNetworkG)(
|
|
pszEntry,
|
|
pszNetwork,
|
|
&dwSize);
|
|
|
|
done:
|
|
return (!dwErr ? pszNetwork : NULL);
|
|
} // EntryToNetwork
|
|
|
|
|
|
|
|
DWORD
|
|
AutoDialEnabled(
|
|
IN PBOOLEAN lpfEnabled
|
|
)
|
|
{
|
|
DWORD dwErr, dwLocationID;
|
|
BOOL fEnabled;
|
|
|
|
//
|
|
// If there is no dialing location
|
|
// defined, then return FALSE.
|
|
//
|
|
dwErr = TapiCurrentDialingLocation(&dwLocationID);
|
|
if (dwErr) {
|
|
*lpfEnabled = FALSE;
|
|
return 0;
|
|
}
|
|
dwErr = (DWORD)(*lpfnRasGetAutodialEnableG)(dwLocationID, &fEnabled);
|
|
if (dwErr)
|
|
return dwErr;
|
|
*lpfEnabled = (BOOLEAN)fEnabled;
|
|
|
|
return 0;
|
|
} // AutoDialEnabled
|
|
|
|
|
|
|
|
DWORD
|
|
DisableAutoDial()
|
|
{
|
|
DWORD dwErr, dwLocationID;
|
|
|
|
dwErr = TapiCurrentDialingLocation(&dwLocationID);
|
|
if (dwErr)
|
|
return dwErr;
|
|
|
|
return (DWORD)(*lpfnRasSetAutodialEnableG)(dwLocationID, (BOOL)FALSE);
|
|
} // DisableAutoDial
|
|
|
|
|
|
|
|
BOOLEAN
|
|
PortAvailable(
|
|
IN LPTSTR lpszDeviceType,
|
|
IN LPTSTR lpszDeviceName
|
|
)
|
|
|
|
/*++
|
|
|
|
DESCRIPTION
|
|
Determines whether there is a free port
|
|
available to dial the specified entry.
|
|
|
|
ARGUMENTS
|
|
lpszDeviceType: a pointer to the device type string
|
|
|
|
lpszDeviceName: a pointer to the device name string
|
|
|
|
RETURN VALUE
|
|
TRUE if one or more of the correct port
|
|
type is free; FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwErr;
|
|
DWORD dwSize = 0,
|
|
dwEntries, i;
|
|
RASMAN_PORT *pPorts = NULL;
|
|
BOOLEAN fFound = FALSE,
|
|
fOtherType;
|
|
BOOLEAN fTypeMatch, fNameMatch;
|
|
LPSTR lpszAnsiDeviceType = NULL,
|
|
lpszAnsiDeviceName = NULL;
|
|
|
|
//
|
|
// If fOtherType is TRUE, then we compare
|
|
// the RASMAN media type with the device type.
|
|
//
|
|
fOtherType = (_wcsicmp(lpszDeviceType, RASDT_Modem) &&
|
|
_wcsicmp(lpszDeviceType, RASDT_Isdn) &&
|
|
_wcsicmp(lpszDeviceType, RASDT_X25) &&
|
|
_wcsicmp(lpszDeviceType, L"VPN"));
|
|
//
|
|
// Convert lpszDeviceType to Ansi so
|
|
// we can compare with rasman's version.
|
|
//
|
|
lpszAnsiDeviceType = UnicodeStringToAnsiString(
|
|
lpszDeviceType,
|
|
NULL,
|
|
0);
|
|
if (lpszAnsiDeviceType == NULL)
|
|
goto done;
|
|
lpszAnsiDeviceName = UnicodeStringToAnsiString(
|
|
lpszDeviceName,
|
|
NULL,
|
|
0);
|
|
if (lpszAnsiDeviceName == NULL)
|
|
goto done;
|
|
//
|
|
// Get a list of ports.
|
|
//
|
|
dwErr = (DWORD)(*lpfnRasPortEnumG)(NULL, NULL, &dwSize, &dwEntries);
|
|
if (!dwErr || dwErr != ERROR_BUFFER_TOO_SMALL) {
|
|
RASAUTO_TRACE1("PortAvailable: RasPortEnum failed (dwErr=%d)", dwErr);
|
|
goto done;
|
|
}
|
|
pPorts = LocalAlloc(LPTR, dwSize);
|
|
if (pPorts == NULL) {
|
|
RASAUTO_TRACE("PortAvailable: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
dwErr = (DWORD)(*lpfnRasPortEnumG)(NULL, pPorts, &dwSize, &dwEntries);
|
|
if (dwErr) {
|
|
RASAUTO_TRACE1("PortAvailable: RasPortEnum failed (dwErr=%d)", dwErr);
|
|
goto done;
|
|
}
|
|
for (i = 0; i < dwEntries; i++) {
|
|
RASMAN_INFO info;
|
|
|
|
RASAUTO_TRACE6(
|
|
"PortAvailable: lpszAnsiDeviceType=%s, lpszAnsiDeviceName=%s, "
|
|
"media=%s, type=%s, name=%s, usage=%d",
|
|
lpszAnsiDeviceType,
|
|
lpszAnsiDeviceName,
|
|
pPorts[i].P_MediaName,
|
|
pPorts[i].P_DeviceType,
|
|
pPorts[i].P_DeviceName,
|
|
pPorts[i].P_ConfiguredUsage);
|
|
RASAUTO_TRACE2("PortAvailable: status=%d, current usage=%d",
|
|
pPorts[i].P_Status,
|
|
pPorts[i].P_CurrentUsage);
|
|
//
|
|
// Only interested in dial-out and biplex ports.
|
|
//
|
|
if (!(pPorts[i].P_ConfiguredUsage & CALL_OUT)
|
|
&& !(pPorts[i].P_ConfiguredUsage & CALL_OUT_ONLY))
|
|
continue;
|
|
RtlZeroMemory(&info, sizeof (info));
|
|
|
|
//
|
|
// If the port has already been opened for call out
|
|
// fail the call.
|
|
//
|
|
ZeroMemory(&info, sizeof(RASMAN_INFO));
|
|
|
|
dwErr = RasGetInfo(NULL,
|
|
pPorts[i].P_Handle,
|
|
&info);
|
|
|
|
if(NO_ERROR == dwErr)
|
|
{
|
|
if(info.RI_dwFlags & RASMAN_OPEN_CALLOUT)
|
|
{
|
|
RASAUTO_TRACE("Port already open for call out");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (pPorts[i].P_Status == OPEN) {
|
|
dwErr = (DWORD)(*lpfnRasGetInfoG)(NULL, pPorts[i].P_Handle, &info);
|
|
if (dwErr) {
|
|
RASAUTO_TRACE1("PortAvailable: RasGetInfo failed (dwErr=%d)", dwErr);
|
|
goto statecheck;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// Determine if the connection associated with a
|
|
// disconnected port has gone away. In this case,
|
|
// we can close the port and attempt to reopen
|
|
// it. This is essentially what rasapi32/RasDial()
|
|
// when it determines if a port is available for
|
|
// dialing out.
|
|
//
|
|
if (pPorts[i].P_Status == OPEN &&
|
|
info.RI_ConnState == DISCONNECTED &&
|
|
info.RI_ConnectionHandle)
|
|
{
|
|
RASCONNSTATE connstate;
|
|
DWORD dwSize = sizeof (RASCONNSTATE);
|
|
|
|
RASAUTO_TRACE1(
|
|
"PortAvailable: Open disconnected port %d found",
|
|
pPorts[i].P_Handle);
|
|
dwErr = (DWORD)(*lpfnRasGetPortUserDataG)(
|
|
pPorts[i].P_Handle,
|
|
3, // PORT_CONNSTATE_INDEX
|
|
&connstate,
|
|
&dwSize);
|
|
RASAUTO_TRACE2(
|
|
"PortAvailable: RasGetPortUserData(%d), connstate=%d",
|
|
dwErr,
|
|
connstate);
|
|
if (!dwErr &&
|
|
(connstate < RASCS_PrepareForCallback ||
|
|
connstate > RASCS_WaitForCallback))
|
|
{
|
|
RASAUTO_TRACE1(
|
|
"PortAvailable: RasPortClose(%d)...",
|
|
pPorts[i].P_Handle);
|
|
dwErr = (DWORD)(*lpfnRasPortCloseG)(pPorts[i].P_Handle);
|
|
RASAUTO_TRACE1("PortAvailable: RasPortClose done(%d)", dwErr);
|
|
//
|
|
// Since we've closed the port,
|
|
// update the P_Status field manually.
|
|
//
|
|
if (!dwErr)
|
|
pPorts[i].P_Status = CLOSED;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
//
|
|
// Only interested in dial-out ports if the port
|
|
// is closed. Biplex port opens, on the other
|
|
// hand, may succeed even if the port is
|
|
// open.
|
|
//
|
|
statecheck:
|
|
if (pPorts[i].P_ConfiguredUsage == CALL_OUT
|
|
&& pPorts[i].P_Status != CLOSED)
|
|
{
|
|
RASAUTO_TRACE("Port is not available for call_out");
|
|
continue;
|
|
}
|
|
|
|
fTypeMatch =
|
|
(!_stricmp(lpszAnsiDeviceType, pPorts[i].P_DeviceType)) ||
|
|
(fOtherType && !_stricmp(lpszAnsiDeviceType, pPorts[i].P_MediaName));
|
|
fNameMatch = !_stricmp(lpszAnsiDeviceName, pPorts[i].P_DeviceName);
|
|
if (fTypeMatch && fNameMatch) {
|
|
|
|
fFound = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
done:
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (lpszAnsiDeviceType != NULL)
|
|
LocalFree(lpszAnsiDeviceType);
|
|
if (lpszAnsiDeviceName != NULL)
|
|
LocalFree(lpszAnsiDeviceName);
|
|
if (pPorts != NULL)
|
|
LocalFree(pPorts);
|
|
return fFound;
|
|
} // PortAvailable
|
|
|
|
DWORD
|
|
DisableAddress(PACD_ADDR pAddr)
|
|
{
|
|
DWORD retcode = SUCCESS;
|
|
LPTSTR pszAddress = NULL;
|
|
|
|
LockDisabledAddresses();
|
|
ASSERT(NULL != pDisabledAddressesG);
|
|
|
|
pszAddress = AddressToUnicodeString(pAddr);
|
|
|
|
if(NULL == pszAddress)
|
|
{
|
|
retcode = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto done;
|
|
}
|
|
|
|
PutTableEntry(pDisabledAddressesG, pszAddress, NULL);
|
|
|
|
done:
|
|
|
|
if(NULL != pszAddress)
|
|
{
|
|
LocalFree(pszAddress);
|
|
}
|
|
|
|
UnlockDisabledAddresses();
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
StartAutoDialer(
|
|
IN HANDLE hProcess,
|
|
IN PACD_ADDR pAddr,
|
|
IN LPTSTR lpAddress,
|
|
IN LPTSTR lpEntryName,
|
|
IN BOOLEAN fSharedAccess,
|
|
OUT PBOOLEAN pfInvalidEntry
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
BOOLEAN fSuccess = FALSE, fEntryFound = FALSE;
|
|
BOOLEAN fUseRasDial, fDialerPresent, fDialerKilled;
|
|
DWORD dwStatus, dwSize, dwIndex, dwEntries, dwCount = 0;
|
|
TCHAR *pszCmdLine = NULL;
|
|
STARTUPINFO StartupInfo;
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
DWORD dwPreConnections, dwConnections;
|
|
DWORD dwExitCode = STILL_ACTIVE;
|
|
HANDLE hToken;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
ACD_STATUS connStatus;
|
|
DWORD dwErr;
|
|
BOOL fDisableAddress = FALSE;
|
|
PVOID pEnvBlock = NULL;
|
|
|
|
//
|
|
// Initialization of various variables.
|
|
//
|
|
*pfInvalidEntry = FALSE;
|
|
memset(&StartupInfo, 0, sizeof (StartupInfo));
|
|
memset(&ProcessInfo, 0, sizeof (ProcessInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
|
|
StartupInfo.lpDesktop = TEXT("winsta0\\default");
|
|
//
|
|
// Read the phonebook entry to determine whether
|
|
// we need to load a custom AutoDial UI.
|
|
//
|
|
if (lpEntryName != NULL) {
|
|
DWORD dwIgnore;
|
|
LPRASENTRY lpEntry;
|
|
|
|
dwErr = (DWORD)(*lpfnRasGetEntryPropertiesG)(
|
|
NULL,
|
|
lpEntryName,
|
|
NULL,
|
|
&dwSize,
|
|
NULL,
|
|
&dwIgnore);
|
|
if (dwErr == ERROR_CANNOT_FIND_PHONEBOOK_ENTRY) {
|
|
//
|
|
// If the phonebook entry has been renamed
|
|
// or deleted, then ask again for an entry.
|
|
//
|
|
lpEntryName = NULL;
|
|
dwErr = 0;
|
|
goto fmtcmd;
|
|
}
|
|
else if (dwErr != ERROR_BUFFER_TOO_SMALL) {
|
|
*pfInvalidEntry = TRUE;
|
|
RASAUTO_TRACE2(
|
|
"StartAutoDialer: RasGetEntryProperties(%S) failed (dwErr=%d)",
|
|
RASAUTO_TRACESTRW(lpEntryName),
|
|
dwErr);
|
|
goto done;
|
|
}
|
|
lpEntry = LocalAlloc(LPTR, dwSize);
|
|
if (lpEntry == NULL) {
|
|
RASAUTO_TRACE("StartAutoDialer: LocalAlloc failed");
|
|
goto done;
|
|
}
|
|
lpEntry->dwSize = sizeof (RASENTRY);
|
|
dwErr = (DWORD)(*lpfnRasGetEntryPropertiesG)(
|
|
NULL,
|
|
lpEntryName,
|
|
lpEntry,
|
|
&dwSize,
|
|
NULL,
|
|
&dwIgnore);
|
|
if (dwErr) {
|
|
*pfInvalidEntry = TRUE;
|
|
RASAUTO_TRACE2(
|
|
"StartAutoDialer: RasGetEntryProperties(%S) failed (dwErr=%d)",
|
|
RASAUTO_TRACESTRW(lpEntryName),
|
|
dwErr);
|
|
LocalFree(lpEntry);
|
|
lpEntry = NULL;
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// While we have the phonebook entry
|
|
// verify there is an available port
|
|
// to dial.
|
|
//
|
|
if (!PortAvailable(lpEntry->szDeviceType, lpEntry->szDeviceName)) {
|
|
RASAUTO_TRACE("StartAutoDialer: no port available");
|
|
LocalFree(lpEntry);
|
|
goto done;
|
|
}
|
|
if (*lpEntry->szAutodialDll != L'\0' &&
|
|
*lpEntry->szAutodialFunc != L'\0')
|
|
{
|
|
//
|
|
// Allocate pszCmdLine
|
|
//
|
|
pszCmdLine = LocalAlloc(
|
|
LPTR,
|
|
( lstrlen(RASAUTOUI_CUSTOMDIALENTRY)
|
|
+ lstrlen(lpEntry->szAutodialDll)
|
|
+ lstrlen(lpEntry->szAutodialFunc)
|
|
+ lstrlen(lpEntryName)
|
|
+ 1) * sizeof(TCHAR));
|
|
|
|
if(NULL == pszCmdLine)
|
|
{
|
|
RASAUTO_TRACE1("StartAutoDialer: Failed to allocate pszcmdline. 0x%x",
|
|
dwErr);
|
|
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Run a special program that loads the
|
|
// AutoDial DLL and calls the correct
|
|
// DLL entrypoint.
|
|
//
|
|
wsprintf(
|
|
pszCmdLine,
|
|
RASAUTOUI_CUSTOMDIALENTRY,
|
|
lpEntry->szAutodialDll,
|
|
lpEntry->szAutodialFunc,
|
|
lpEntryName);
|
|
}
|
|
LocalFree(lpEntry);
|
|
}
|
|
fmtcmd:
|
|
//
|
|
// Ping the driver before we start
|
|
// the dialing dialer to make sure
|
|
// the connection is still valid.
|
|
//
|
|
if (pAddr)
|
|
{
|
|
connStatus.fSuccess = FALSE;
|
|
RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
|
|
status = NtDeviceIoControlFile(
|
|
hAcdG,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
IOCTL_ACD_KEEPALIVE,
|
|
&connStatus,
|
|
sizeof (connStatus),
|
|
NULL,
|
|
0);
|
|
if (status != STATUS_SUCCESS) {
|
|
RASAUTO_TRACE1(
|
|
"StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_KEEPALIVE) failed (status=0x%x)",
|
|
status);
|
|
goto done;
|
|
}
|
|
}
|
|
if (NULL == pszCmdLine)
|
|
{
|
|
//
|
|
// Construct the command line when there
|
|
// is not a custom dial DLL.
|
|
//
|
|
if (lpEntryName != NULL)
|
|
{
|
|
pszCmdLine = LocalAlloc(
|
|
LPTR,
|
|
( lstrlen(RASAUTOUI_DEFAULTDIALENTRY2)
|
|
+ lstrlen(lpAddress)
|
|
+ lstrlen(lpEntryName)
|
|
+ 1) * sizeof(TCHAR));
|
|
|
|
if(NULL == pszCmdLine)
|
|
{
|
|
dwErr = GetLastError();
|
|
goto done;
|
|
}
|
|
|
|
if (fSharedAccess)
|
|
wsprintf(pszCmdLine, RASAUTOUI_DEFAULTDIALENTRY2, lpAddress, lpEntryName);
|
|
else
|
|
wsprintf(pszCmdLine, RASAUTOUI_DEFAULTDIALENTRY, lpAddress, lpEntryName);
|
|
}
|
|
else
|
|
{
|
|
pszCmdLine = LocalAlloc(
|
|
LPTR,
|
|
( lstrlen(RASAUTOUI_NOENTRY)
|
|
+ lstrlen(lpAddress)
|
|
+ 1) * sizeof(TCHAR));
|
|
|
|
if(NULL == pszCmdLine)
|
|
{
|
|
dwErr = GetLastError();
|
|
goto done;
|
|
}
|
|
|
|
wsprintf(pszCmdLine, RASAUTOUI_NOENTRY, lpAddress);
|
|
}
|
|
}
|
|
|
|
RASAUTO_TRACE1("StartAutoDialer: szCmdLine=%S", pszCmdLine);
|
|
//
|
|
// Exec the process.
|
|
//
|
|
if (!OpenProcessToken(
|
|
hProcess,
|
|
TOKEN_ALL_ACCESS,
|
|
&hToken))
|
|
{
|
|
RASAUTO_TRACE1(
|
|
"StartAutoDialer: OpenProcessToken failed (dwErr=%d)",
|
|
GetLastError());
|
|
goto done;
|
|
}
|
|
|
|
if (!CreateEnvironmentBlock(
|
|
&pEnvBlock,
|
|
hToken,
|
|
FALSE))
|
|
{
|
|
TRACE1(
|
|
"StartAutoDialer: CreateEnvironmentBlock failed (dwErr=%d)",
|
|
GetLastError());
|
|
goto done;
|
|
}
|
|
|
|
if (!CreateProcessAsUser(
|
|
hToken,
|
|
NULL,
|
|
pszCmdLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS|DETACHED_PROCESS|CREATE_UNICODE_ENVIRONMENT,
|
|
pEnvBlock,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInfo))
|
|
{
|
|
RASAUTO_TRACE2(
|
|
"StartAutoDialer: CreateProcessAsUser(%S) failed (error=0x%x)",
|
|
pszCmdLine,
|
|
GetLastError());
|
|
CloseHandle(hToken);
|
|
goto done;
|
|
}
|
|
RASAUTO_TRACE1("StartAutoDialer: started pid %d", ProcessInfo.dwProcessId);
|
|
CloseHandle(hToken);
|
|
CloseHandle(ProcessInfo.hThread);
|
|
//
|
|
// Now that we've started the process, we need to
|
|
// wait until we think the connection has
|
|
// been made.
|
|
//
|
|
fDialerPresent = TRUE;
|
|
dwPreConnections = ActiveConnections(TRUE, NULL, NULL);
|
|
while (dwCount++ < 0xffffffff) {
|
|
//
|
|
// Sleep for one second.
|
|
//
|
|
status = WaitForSingleObject(hTerminatingG, 1000);
|
|
if (status == WAIT_OBJECT_0)
|
|
goto done;
|
|
//
|
|
// Ping the driver to let it
|
|
// know we are working on the
|
|
// request.
|
|
//
|
|
if (pAddr)
|
|
{
|
|
connStatus.fSuccess = FALSE;
|
|
RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
|
|
status = NtDeviceIoControlFile(
|
|
hAcdG,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
IOCTL_ACD_KEEPALIVE,
|
|
&connStatus,
|
|
sizeof (connStatus),
|
|
NULL,
|
|
0);
|
|
if (status != STATUS_SUCCESS) {
|
|
RASAUTO_TRACE1(
|
|
"StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_KEEPALIVE) failed (status=0x%x)",
|
|
status);
|
|
// goto done;
|
|
}
|
|
}
|
|
//
|
|
// Check to see if there are any connections yet.
|
|
// If there are, then we are done.
|
|
//
|
|
dwConnections = ActiveConnections(TRUE, NULL, NULL);
|
|
if (dwConnections > dwPreConnections) {
|
|
RASAUTO_TRACE("StartAutoDialer: connection started");
|
|
fSuccess = TRUE;
|
|
goto done;
|
|
}
|
|
//
|
|
// After we have determined there are
|
|
// no active connections, check to see
|
|
// if the dialer is still present. This
|
|
// was calculated on the *previous* iteration
|
|
// of the loop. We do this to avoid a race
|
|
// condition of having the dialer go away
|
|
// after we call ActiveConnections().
|
|
//
|
|
if (!fDialerPresent) {
|
|
BOOLEAN fFound = FALSE;
|
|
LPTSTR *lpConnections;
|
|
|
|
RASAUTO_TRACE("StartAutoDialer: dialer went away!");
|
|
if (lpEntryName != NULL) {
|
|
//
|
|
// Make absolutely sure if an entry was specified,
|
|
// it is not connected before we return FALSE.
|
|
// It's possible a connection could have been
|
|
// in progress before we started the dialer.
|
|
//
|
|
dwConnections = ActiveConnections(TRUE, &lpConnections, NULL);
|
|
if (dwConnections) {
|
|
for (dwIndex = 0; dwIndex < dwConnections; dwIndex++) {
|
|
if (!_wcsicmp(lpConnections[dwIndex], lpEntryName)) {
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
FreeStringArray(lpConnections, dwConnections);
|
|
if (fFound) {
|
|
RASAUTO_TRACE1(
|
|
"StartAutoDialer: found %S on final check!",
|
|
RASAUTO_TRACESTRW(lpEntryName));
|
|
}
|
|
}
|
|
}
|
|
fSuccess = fFound;
|
|
goto done;
|
|
}
|
|
//
|
|
// After 5 seconds, check to see if
|
|
// the dialer has terminated.
|
|
//
|
|
if (dwCount > 5) {
|
|
fDialerPresent =
|
|
GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode) &&
|
|
dwExitCode == STILL_ACTIVE;
|
|
RASAUTO_TRACE2(
|
|
"StartAutoDialer: GetExitCodeProcess returned %d, dwExitCode=%d",
|
|
fDialerPresent,
|
|
dwExitCode);
|
|
|
|
if(ERROR_CANCELLED == dwExitCode)
|
|
{
|
|
RASAUTO_TRACE("User cancelled the connection attempt");
|
|
fDisableAddress = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
//
|
|
// We timed out waiting for a connection.
|
|
// If the dialer is still running kill it.
|
|
//
|
|
if (ProcessInfo.hProcess != NULL)
|
|
CloseHandle(ProcessInfo.hProcess);
|
|
//
|
|
// Complete the connection request
|
|
// in the driver.
|
|
//
|
|
if (pAddr)
|
|
{
|
|
connStatus.fSuccess = fSuccess;
|
|
RtlCopyMemory(&connStatus.addr, pAddr, sizeof (ACD_ADDR));
|
|
status = NtDeviceIoControlFile(
|
|
hAcdG,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
IOCTL_ACD_COMPLETION,
|
|
&connStatus,
|
|
sizeof (connStatus),
|
|
NULL,
|
|
0);
|
|
if (status != STATUS_SUCCESS) {
|
|
RASAUTO_TRACE1(
|
|
"StartAutoDialer: NtDeviceIoControlFile(IOCTL_ACD_COMPLETION) failed (status=0x%x)",
|
|
status);
|
|
}
|
|
|
|
if(fDisableAddress)
|
|
{
|
|
DWORD retcode;
|
|
|
|
retcode = DisableAddress(pAddr);
|
|
|
|
RASAUTO_TRACE2("StartAutodialer: Disabled %S. rc=0x%x",
|
|
RASAUTO_TRACESTRW(lpAddress),
|
|
retcode);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
if (NULL != pEnvBlock)
|
|
{
|
|
DestroyEnvironmentBlock(pEnvBlock);
|
|
}
|
|
|
|
if(NULL != pszCmdLine)
|
|
{
|
|
LocalFree(pszCmdLine);
|
|
}
|
|
|
|
return fSuccess;
|
|
} // StartAutoDialer
|
|
|
|
|
|
|
|
BOOLEAN
|
|
StartReDialer(
|
|
IN HANDLE hProcess,
|
|
IN LPTSTR lpPhonebook,
|
|
IN LPTSTR lpEntry
|
|
)
|
|
{
|
|
TCHAR szCmdLine[100];
|
|
TCHAR *pszCmdLine = NULL;
|
|
STARTUPINFO StartupInfo;
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
HANDLE hToken;
|
|
PVOID pEnvBlock = NULL;
|
|
|
|
//
|
|
// Initialization of various variables.
|
|
//
|
|
memset(&StartupInfo, 0, sizeof (StartupInfo));
|
|
memset(&ProcessInfo, 0, sizeof (ProcessInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
//
|
|
// Construct the command line when there
|
|
// is not a custom dial DLL.
|
|
//
|
|
pszCmdLine = LocalAlloc(
|
|
LPTR,
|
|
( lstrlen(RASAUTOUI_REDIALENTRY)
|
|
+ lstrlen(lpPhonebook)
|
|
+ lstrlen(lpEntry)
|
|
+ 1) * sizeof(TCHAR));
|
|
|
|
if(NULL == pszCmdLine)
|
|
{
|
|
RASAUTO_TRACE1("StartReDialer: failed to allocate pszCmdLine. 0x%x",
|
|
GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
wsprintf(pszCmdLine, RASAUTOUI_REDIALENTRY, lpPhonebook, lpEntry);
|
|
RASAUTO_TRACE1("StartReDialer: szCmdLine=%S", pszCmdLine);
|
|
//
|
|
// Exec the process.
|
|
//
|
|
if (!OpenProcessToken(
|
|
hProcess,
|
|
TOKEN_ALL_ACCESS,
|
|
&hToken))
|
|
{
|
|
RASAUTO_TRACE1(
|
|
"StartReDialer: OpenProcessToken failed (dwErr=%d)",
|
|
GetLastError());
|
|
|
|
LocalFree(pszCmdLine);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateEnvironmentBlock(
|
|
&pEnvBlock,
|
|
hToken,
|
|
FALSE))
|
|
{
|
|
TRACE1(
|
|
"StartReDialer: CreateEnvironmentBlock failed (dwErr=%d)",
|
|
GetLastError());
|
|
|
|
LocalFree(pszCmdLine);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateProcessAsUser(
|
|
hToken,
|
|
NULL,
|
|
pszCmdLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS|DETACHED_PROCESS|CREATE_UNICODE_ENVIRONMENT,
|
|
pEnvBlock,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInfo))
|
|
{
|
|
RASAUTO_TRACE2(
|
|
"StartReDialer: CreateProcessAsUser(%S) failed (error=0x%x)",
|
|
pszCmdLine,
|
|
GetLastError());
|
|
CloseHandle(hToken);
|
|
|
|
LocalFree(pszCmdLine);
|
|
|
|
if (pEnvBlock)
|
|
{
|
|
DestroyEnvironmentBlock(pEnvBlock);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
RASAUTO_TRACE1("StartReDialer: started pid %d", ProcessInfo.dwProcessId);
|
|
CloseHandle(hToken);
|
|
CloseHandle(ProcessInfo.hThread);
|
|
|
|
LocalFree(pszCmdLine);
|
|
|
|
if (pEnvBlock)
|
|
{
|
|
DestroyEnvironmentBlock(pEnvBlock);
|
|
}
|
|
|
|
return TRUE;
|
|
} // StartReDialer
|
|
|
|
|
|
|
|
DWORD
|
|
GetAddressDialingLocationInfo(
|
|
IN LPTSTR pszAddress,
|
|
OUT PADDRESS_LOCATION_INFORMATION *lppDialingInfo,
|
|
OUT LPDWORD lpdwcDialingInfo
|
|
)
|
|
{
|
|
DWORD dwErr, dwcb, dwcEntries, i;
|
|
LPRASAUTODIALENTRY lpAutoDialEntries;
|
|
PADDRESS_LOCATION_INFORMATION lpDialingInfo;
|
|
|
|
//
|
|
// Call RAS to find out how many
|
|
// dialing location entries there are.
|
|
//
|
|
dwcb = 0;
|
|
dwErr = (DWORD)(*lpfnRasGetAutodialAddressG)(
|
|
pszAddress,
|
|
NULL,
|
|
NULL,
|
|
&dwcb,
|
|
&dwcEntries);
|
|
if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL)
|
|
return dwErr;
|
|
if (!dwcEntries) {
|
|
*lppDialingInfo = NULL;
|
|
*lpdwcDialingInfo = 0;
|
|
return 0;
|
|
}
|
|
lpAutoDialEntries = LocalAlloc(LPTR, dwcb);
|
|
if (lpAutoDialEntries == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
lpAutoDialEntries->dwSize = sizeof (RASAUTODIALENTRY);
|
|
dwErr = (DWORD)(*lpfnRasGetAutodialAddressG)(
|
|
pszAddress,
|
|
NULL,
|
|
lpAutoDialEntries,
|
|
&dwcb,
|
|
&dwcEntries);
|
|
if (dwErr || (0 == dwcEntries)) {
|
|
LocalFree(lpAutoDialEntries);
|
|
if(0 == dwcEntries)
|
|
{
|
|
dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
|
|
}
|
|
return dwErr;
|
|
}
|
|
//
|
|
// Allocate our buffer.
|
|
//
|
|
lpDialingInfo = LocalAlloc(
|
|
LPTR,
|
|
dwcEntries * sizeof (ADDRESS_LOCATION_INFORMATION));
|
|
if (lpDialingInfo == NULL) {
|
|
LocalFree(lpAutoDialEntries);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
//
|
|
// Copy this information over to our
|
|
// buffer.
|
|
//
|
|
for (i = 0; i < dwcEntries; i++) {
|
|
lpDialingInfo[i].dwLocation = lpAutoDialEntries[i].dwDialingLocation;
|
|
lpDialingInfo[i].pszEntryName =
|
|
CopyString(lpAutoDialEntries[i].szEntry);
|
|
}
|
|
//
|
|
// Free the RAS buffer.
|
|
//
|
|
LocalFree(lpAutoDialEntries);
|
|
//
|
|
// Set return values.
|
|
//
|
|
*lppDialingInfo = lpDialingInfo;
|
|
*lpdwcDialingInfo = dwcEntries;
|
|
|
|
return 0;
|
|
} // GetAddressDialingLocationInfo
|
|
|
|
|
|
|
|
DWORD
|
|
SetAddressDialingLocationInfo(
|
|
IN LPTSTR pszAddress,
|
|
IN PADDRESS_LOCATION_INFORMATION lpDialingInfo
|
|
)
|
|
{
|
|
RASAUTODIALENTRY rasAutoDialEntry;
|
|
|
|
//
|
|
// Copy the caller's buffer over
|
|
// to the RAS buffer.
|
|
//
|
|
rasAutoDialEntry.dwSize = sizeof (RASAUTODIALENTRY);
|
|
rasAutoDialEntry.dwDialingLocation = lpDialingInfo->dwLocation;
|
|
wcscpy(rasAutoDialEntry.szEntry, lpDialingInfo->pszEntryName);
|
|
|
|
return (DWORD)(*lpfnRasSetAutodialAddressG)(
|
|
pszAddress,
|
|
0,
|
|
&rasAutoDialEntry,
|
|
sizeof (RASAUTODIALENTRY),
|
|
1);
|
|
} // SetAddressDialingLocationInfo
|
|
|
|
|
|
|
|
DWORD
|
|
ClearAddressDialingLocationInfo(
|
|
IN LPTSTR pszAddress
|
|
)
|
|
{
|
|
return (DWORD)(*lpfnRasSetAutodialAddressG)(pszAddress, 0, NULL, 0, 0);
|
|
} // ClearAddressDialingLocationInfo
|
|
|
|
|
|
|
|
DWORD
|
|
GetAddressParams(
|
|
IN LPTSTR pszAddress,
|
|
IN PADDRESS_PARAMS lpParams
|
|
)
|
|
{
|
|
HKEY hkey;
|
|
DWORD dwErr, dwSize, dwType;
|
|
LPTSTR lpszAddressKey;
|
|
|
|
//
|
|
// Initialize address map fields.
|
|
//
|
|
lpParams->dwTag = ADDRMAP_TAG_NONE;
|
|
lpParams->dwModifiedTime = 0;
|
|
//
|
|
// Read the values from the registry.
|
|
//
|
|
lpszAddressKey = LocalAlloc(
|
|
LPTR,
|
|
(lstrlen(AUTODIAL_REGADDRESSBASE) +
|
|
lstrlen(pszAddress) + 2) * sizeof (TCHAR));
|
|
if (lpszAddressKey == NULL)
|
|
return 0;
|
|
wsprintf(lpszAddressKey, L"%s\\%s", AUTODIAL_REGADDRESSBASE, pszAddress);
|
|
|
|
LockImpersonation();
|
|
|
|
//
|
|
// Make sure we have hkcu
|
|
//
|
|
|
|
dwErr = DwGetHkcu();
|
|
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
dwErr = RegOpenKeyEx(
|
|
hkeyCUG,
|
|
lpszAddressKey,
|
|
0,
|
|
KEY_READ,
|
|
&hkey);
|
|
if (dwErr) {
|
|
LocalFree(lpszAddressKey);
|
|
goto done;
|
|
}
|
|
dwSize = sizeof (DWORD);
|
|
dwErr = RegQueryValueEx(
|
|
hkey,
|
|
AUTODIAL_REGTAGVALUE,
|
|
NULL,
|
|
&dwType,
|
|
(PVOID)&lpParams->dwTag,
|
|
&dwSize);
|
|
if (dwErr || dwType != REG_DWORD)
|
|
lpParams->dwTag = ADDRMAP_TAG_NONE;
|
|
dwSize = sizeof (DWORD);
|
|
dwErr = RegQueryValueEx(
|
|
hkey,
|
|
AUTODIAL_REGMTIMEVALUE,
|
|
NULL,
|
|
&dwType,
|
|
(PVOID)&lpParams->dwModifiedTime,
|
|
&dwSize);
|
|
if (dwErr || dwType != REG_DWORD)
|
|
lpParams->dwModifiedTime = 0;
|
|
RegCloseKey(hkey);
|
|
LocalFree(lpszAddressKey);
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
done:
|
|
|
|
UnlockImpersonation();
|
|
return dwErr;
|
|
} // GetAddressParams
|
|
|
|
|
|
|
|
DWORD
|
|
SetAddressParams(
|
|
IN LPTSTR pszAddress,
|
|
IN PADDRESS_PARAMS lpParams
|
|
)
|
|
{
|
|
HKEY hkey;
|
|
DWORD dwErr, dwSize, dwDisp;
|
|
LPTSTR lpszAddressKey;
|
|
|
|
//
|
|
// Write the values to the registry.
|
|
//
|
|
lpszAddressKey = LocalAlloc(
|
|
LPTR,
|
|
(lstrlen(AUTODIAL_REGADDRESSBASE) +
|
|
lstrlen(pszAddress) + 2) * sizeof (TCHAR));
|
|
if (lpszAddressKey == NULL)
|
|
return 0;
|
|
wsprintf(lpszAddressKey, L"%s\\%s", AUTODIAL_REGADDRESSBASE, pszAddress);
|
|
|
|
|
|
LockImpersonation();
|
|
|
|
//
|
|
// Make sure we have hkcu
|
|
//
|
|
|
|
dwErr = DwGetHkcu();
|
|
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
|
|
dwErr = RegCreateKeyEx(
|
|
hkeyCUG,
|
|
lpszAddressKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hkey,
|
|
&dwDisp);
|
|
if (dwErr) {
|
|
LocalFree(lpszAddressKey);
|
|
goto done;
|
|
}
|
|
dwErr = RegSetValueEx(
|
|
hkey,
|
|
AUTODIAL_REGTAGVALUE,
|
|
0,
|
|
REG_DWORD,
|
|
(PVOID)&lpParams->dwTag,
|
|
sizeof (DWORD));
|
|
dwErr = RegSetValueEx(
|
|
hkey,
|
|
AUTODIAL_REGMTIMEVALUE,
|
|
0,
|
|
REG_DWORD,
|
|
(PVOID)&lpParams->dwModifiedTime,
|
|
sizeof (DWORD));
|
|
RegCloseKey(hkey);
|
|
LocalFree(lpszAddressKey);
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
done:
|
|
UnlockImpersonation();
|
|
return dwErr;
|
|
} // SetAddressParams
|
|
|
|
|
|
|
|
DWORD
|
|
EnumAutodialAddresses(
|
|
IN LPTSTR *ppAddresses,
|
|
IN LPDWORD lpdwcbAddresses,
|
|
IN LPDWORD lpdwcAddresses
|
|
)
|
|
{
|
|
return (DWORD)(*lpfnRasEnumAutodialAddressesG)(
|
|
ppAddresses,
|
|
lpdwcbAddresses,
|
|
lpdwcAddresses);
|
|
} // EnumAutodialAddresses
|
|
|
|
|
|
|
|
DWORD
|
|
GetAutodialParam(
|
|
IN DWORD dwKey
|
|
)
|
|
{
|
|
DWORD dwValue, dwcb = sizeof (DWORD);
|
|
|
|
(void)(*lpfnRasGetAutodialParamG)(dwKey, &dwValue, &dwcb);
|
|
return dwValue;
|
|
} // GetAutodialParam
|
|
|
|
|
|
|
|
VOID
|
|
SetAutodialParam(
|
|
IN DWORD dwKey,
|
|
IN DWORD dwValue
|
|
)
|
|
{
|
|
(void)(*lpfnRasSetAutodialParamG)(dwKey, &dwValue, sizeof (DWORD));
|
|
} // SetAutodialParam
|
|
|
|
|
|
|
|
DWORD
|
|
NotifyAutoDialChangeEvent(
|
|
IN HANDLE hEvent
|
|
)
|
|
{
|
|
DWORD dwErr, dwDisp;
|
|
|
|
//
|
|
// Make sure we have hkcu
|
|
//
|
|
|
|
LockImpersonation();
|
|
|
|
dwErr = DwGetHkcu();
|
|
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Open the AutoDial registry key.
|
|
//
|
|
if (hkeyAutoDialRegChangeG == NULL) {
|
|
dwErr = RegCreateKeyEx(
|
|
hkeyCUG,
|
|
L"Software\\Microsoft\\RAS AutoDial",
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_NOTIFY,
|
|
NULL,
|
|
&hkeyAutoDialRegChangeG,
|
|
&dwDisp);
|
|
if (dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
//
|
|
// Set the notification change.
|
|
//
|
|
dwErr = RegNotifyChangeKeyValue(
|
|
hkeyAutoDialRegChangeG,
|
|
TRUE,
|
|
REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_ATTRIBUTES|REG_NOTIFY_CHANGE_LAST_SET|REG_NOTIFY_CHANGE_SECURITY,
|
|
hEvent,
|
|
TRUE);
|
|
|
|
done:
|
|
UnlockImpersonation();
|
|
return dwErr;
|
|
} // NotifyAutoDialChangeEvent
|
|
|
|
|
|
|
|
DWORD
|
|
CreateAutoDialChangeEvent(
|
|
IN PHANDLE phEvent
|
|
)
|
|
{
|
|
//
|
|
// Reset the internal change flag.
|
|
//
|
|
fAutoDialRegChangeG = TRUE;
|
|
//
|
|
// Create the event.
|
|
//
|
|
*phEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (*phEvent == NULL)
|
|
return GetLastError();
|
|
//
|
|
// Register it.
|
|
//
|
|
return NotifyAutoDialChangeEvent(*phEvent);
|
|
} // CreateAutoDialChangeEvent
|
|
|
|
|
|
|
|
VOID
|
|
EnableAutoDialChangeEvent(
|
|
IN HANDLE hEvent,
|
|
IN BOOLEAN fEnabled
|
|
)
|
|
{
|
|
EnterCriticalSection(&csRasG);
|
|
//
|
|
// If the event was disabled, and now
|
|
// it is being enabled, then we reset
|
|
// the event.
|
|
//
|
|
if (!fAutoDialRegChangeG && fEnabled)
|
|
ResetEvent(hEvent);
|
|
fAutoDialRegChangeG = fEnabled;
|
|
LeaveCriticalSection(&csRasG);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
ExternalAutoDialChangeEvent()
|
|
{
|
|
BOOLEAN fChanged;
|
|
|
|
EnterCriticalSection(&csRasG);
|
|
fChanged = fAutoDialRegChangeG;
|
|
LeaveCriticalSection(&csRasG);
|
|
|
|
return fChanged;
|
|
} // ExternalAutoDialChangeEvent
|
|
|
|
|
|
|
|
VOID
|
|
CloseAutoDialChangeEvent(
|
|
IN HANDLE hEvent
|
|
)
|
|
{
|
|
if (hkeyAutoDialRegChangeG != NULL) {
|
|
RegCloseKey(hkeyAutoDialRegChangeG);
|
|
hkeyAutoDialRegChangeG = NULL;
|
|
}
|
|
CloseHandle(hEvent);
|
|
} // CloseAutoDialChangeEvent
|
|
|
|
|
|
|
|
VOID
|
|
SetHostentCache(
|
|
IN PCHAR pszDns,
|
|
IN ULONG ulIpaddr
|
|
)
|
|
{
|
|
EnterCriticalSection(&csRasG);
|
|
lstrcpynA(
|
|
(PCHAR)&hostentCacheG[iHostentCacheG].szDns,
|
|
pszDns,
|
|
ACD_ADDR_INET_LEN);
|
|
hostentCacheG[iHostentCacheG].ulIpaddr = ulIpaddr;
|
|
iHostentCacheG = (iHostentCacheG + 1) % HOSTENTCACHESIZ;
|
|
LeaveCriticalSection(&csRasG);
|
|
} // SetHostentCache
|
|
|
|
|
|
|
|
PCHAR
|
|
GetHostentCache(
|
|
IN ULONG ulIpaddr
|
|
)
|
|
{
|
|
PCHAR pszDns = NULL;
|
|
INT i;
|
|
|
|
EnterCriticalSection(&csRasG);
|
|
for (i = 0; i < HOSTENTCACHESIZ; i++) {
|
|
if (hostentCacheG[i].ulIpaddr == ulIpaddr) {
|
|
pszDns = hostentCacheG[i].szDns;
|
|
break;
|
|
}
|
|
}
|
|
LeaveCriticalSection(&csRasG);
|
|
|
|
return pszDns;
|
|
} // GetHostentCache
|
|
|
|
|
|
|
|
LPTSTR
|
|
GetNetbiosDevice(
|
|
IN HRASCONN hrasconn
|
|
)
|
|
{
|
|
INT i, nProtocols;
|
|
RAS_PROTOCOLS Protocols;
|
|
HPORT hPort;
|
|
RASMAN_ROUTEINFO *pRoute;
|
|
WCHAR szDevice[MAX_DEVICE_NAME + 1];
|
|
DWORD dwErr;
|
|
|
|
nProtocols = 0;
|
|
hPort = (HPORT) (*lpfnRasGetHportG)(hrasconn);
|
|
|
|
if(INVALID_HPORT == hPort)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if(ERROR_SUCCESS != (dwErr = (DWORD)(*lpfnRasPortEnumProtocolsG)(
|
|
NULL, hPort,
|
|
&Protocols, &nProtocols)))
|
|
{
|
|
RASAUTO_TRACE1("GetNetbiosDevice: RasPortEnumProtocolsG failed"
|
|
" and returned 0x%x", dwErr);
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < nProtocols; i++) {
|
|
pRoute = &Protocols.RP_ProtocolInfo[i];
|
|
RASAUTO_TRACE3(
|
|
"GetNetbiosDevice: lana=%d, xport=%S, adapter=%S",
|
|
pRoute->RI_LanaNum,
|
|
pRoute->RI_XportName,
|
|
pRoute->RI_AdapterName);
|
|
switch (pRoute->RI_Type) {
|
|
case IPX:
|
|
return CopyString(L"\\Device\\Nwlnknb");
|
|
case IP:
|
|
wsprintf(szDevice, L"\\Device\\NetBT_Tcpip%s", &pRoute->RI_AdapterName[8]);
|
|
return CopyString(szDevice);
|
|
case ASYBEUI:
|
|
wsprintf(szDevice, L"\\Device\\Nbf_%s", &pRoute->RI_AdapterName[8]);
|
|
return CopyString(szDevice);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
} // GetNetbiosDevice
|
|
|
|
|
|
DWORD
|
|
DwGetDefaultEntryName(LPTSTR *ppszEntryName)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
DWORD dwcb = sizeof(RASAUTODIALENTRY);
|
|
RASAUTODIALENTRY Entry;
|
|
DWORD dwEntries = 0;
|
|
LPTSTR pszEntryName = NULL;
|
|
|
|
if(NULL == ppszEntryName)
|
|
{
|
|
dwErr = E_INVALIDARG;
|
|
goto done;
|
|
}
|
|
|
|
ZeroMemory(&Entry, sizeof(RASAUTODIALENTRY));
|
|
|
|
Entry.dwSize = sizeof(RASAUTODIALENTRY);
|
|
dwErr = (DWORD) (*lpfnRasGetAutodialAddressG)(
|
|
NULL, NULL, &Entry,
|
|
&dwcb, &dwEntries);
|
|
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if(0 != dwEntries)
|
|
{
|
|
pszEntryName = LocalAlloc(LPTR,
|
|
sizeof(TCHAR) * (lstrlen(Entry.szEntry) + 1));
|
|
|
|
if(NULL != pszEntryName)
|
|
{
|
|
//
|
|
// Got a default entry.
|
|
//
|
|
lstrcpy(pszEntryName, Entry.szEntry);
|
|
}
|
|
else
|
|
{
|
|
dwErr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RASAUTO_TRACE("No default connection defined");
|
|
dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
|
|
}
|
|
|
|
*ppszEntryName = pszEntryName;
|
|
|
|
done:
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
VOID
|
|
ProcessLearnedAddress(
|
|
IN ACD_ADDR_TYPE fType,
|
|
IN LPTSTR pszAddress,
|
|
IN PACD_ADAPTER pAdapter
|
|
)
|
|
{
|
|
BOOLEAN fStatus;
|
|
DWORD dwConn, dwConnections, dwSize;
|
|
LPTSTR *pEntryNames, pszEntryName = NULL;
|
|
HRASCONN *phRasConn;
|
|
union {
|
|
RASPPPNBF pppNbf;
|
|
RASPPPIP pppIp;
|
|
RASPPPIPX pppIpx;
|
|
} projBuf;
|
|
RASPROJECTION fProjection;
|
|
INT i, nProtocols;
|
|
RAS_PROTOCOLS Protocols;
|
|
RASMAN_ROUTEINFO *pRoute;
|
|
HPORT hPort;
|
|
PCHAR pszIpAddr, pszMac = NULL;
|
|
WCHAR szIpAddr[17], *p, *pwszMac;
|
|
UCHAR cMac[6];
|
|
struct in_addr in;
|
|
LPTSTR pszDefaultEntry = NULL;
|
|
|
|
|
|
RASAUTO_TRACE2("ProcessLearnedAddress(%S,%d)", RASAUTO_TRACESTRW(pszAddress), pAdapter->fType);
|
|
dwConnections = ActiveConnections(TRUE, &pEntryNames, &phRasConn);
|
|
if (!dwConnections)
|
|
return;
|
|
|
|
(VOID) DwGetDefaultEntryName(&pszDefaultEntry);
|
|
|
|
if(NULL != pszDefaultEntry)
|
|
{
|
|
//
|
|
// Check to see if we have default entries as one of the
|
|
// connected entries. If it is we don't learn the address
|
|
//
|
|
for(dwConn = 0; dwConn < dwConnections; dwConn++)
|
|
{
|
|
if(0 == lstrcmpi(pEntryNames[dwConn], pszDefaultEntry))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
LocalFree(pszDefaultEntry);
|
|
if(dwConn != dwConnections)
|
|
{
|
|
RASAUTO_TRACE("ProcessLearnedAddress: not processing the address since"
|
|
" its learned over the default connection");
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this is a DNS-to-IP address mapping,
|
|
// then simply enter it into the hostent
|
|
// cache and return.
|
|
//
|
|
if (fType == ACD_ADDR_INET && pAdapter->fType == ACD_ADAPTER_IP) {
|
|
PCHAR pszDns = UnicodeStringToAnsiString(pszAddress, NULL, 0);
|
|
|
|
if (pszDns != NULL)
|
|
{
|
|
SetHostentCache(pszDns, pAdapter->ulIpaddr);
|
|
LocalFree(pszDns);
|
|
}
|
|
// return;
|
|
}
|
|
//
|
|
// Set the buffer size according to the
|
|
// adapter's type.
|
|
//
|
|
switch (pAdapter->fType) {
|
|
case ACD_ADAPTER_LANA:
|
|
RASAUTO_TRACE1(
|
|
"ProcessLearnedAddress: ACD_ADAPTER_LANA: bLana=%d",
|
|
pAdapter->bLana);
|
|
fProjection = RASP_PppNbf;
|
|
dwSize = sizeof (RASPPPNBF);
|
|
break;
|
|
case ACD_ADAPTER_IP:
|
|
fProjection = RASP_PppIp;
|
|
dwSize = sizeof (RASPPPIP);
|
|
//
|
|
// Convert the ULONG into a formatted IP address.
|
|
//
|
|
in.s_addr = pAdapter->ulIpaddr;
|
|
pszIpAddr = inet_ntoa(in);
|
|
RASAUTO_TRACE1(
|
|
"ProcessLearnedAddress: ACD_ADAPTER_IPADDR: %s",
|
|
pszIpAddr);
|
|
AnsiStringToUnicodeString(
|
|
pszIpAddr,
|
|
szIpAddr,
|
|
sizeof (szIpAddr) / sizeof(WCHAR));
|
|
break;
|
|
case ACD_ADAPTER_NAME:
|
|
RASAUTO_TRACE1(
|
|
"ProcessLearnedAddress: ACD_ADAPTER_NAME: %S",
|
|
pAdapter->szName);
|
|
dwSize = 0;
|
|
break;
|
|
case ACD_ADAPTER_MAC:
|
|
RASAUTO_TRACE6(
|
|
"ProcessLearnedAddress: ACD_ADAPTER_MAC: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
pAdapter->cMac[0],
|
|
pAdapter->cMac[1],
|
|
pAdapter->cMac[2],
|
|
pAdapter->cMac[3],
|
|
pAdapter->cMac[4],
|
|
pAdapter->cMac[5]);
|
|
fProjection = RASP_PppIpx;
|
|
dwSize = sizeof (RASPPPIPX);
|
|
break;
|
|
}
|
|
for (dwConn = 0; dwConn < dwConnections; dwConn++) {
|
|
//
|
|
// If we are looking for a device name,
|
|
// we have to use RasPortEnumProtocols(),
|
|
// otherwise it's easier to use
|
|
// RasGetProjectionInfo.
|
|
//
|
|
if (pAdapter->fType != ACD_ADAPTER_NAME) {
|
|
//
|
|
// Note: the following statement assumes the
|
|
// dwSize field is at the same offset for
|
|
// all members of the union.
|
|
//
|
|
projBuf.pppNbf.dwSize = dwSize;
|
|
if ((*lpfnRasGetProjectionInfoG)(
|
|
phRasConn[dwConn],
|
|
fProjection,
|
|
&projBuf,
|
|
&dwSize))
|
|
{
|
|
RASAUTO_TRACE1(
|
|
"ProcessLearnedAddress: RasGetProjectionInfo(%S) failed",
|
|
RASAUTO_TRACESTRW(pEntryNames[dwConn]));
|
|
continue;
|
|
}
|
|
RASAUTO_TRACE3(
|
|
"ProcessLearnedAddress: RasGetProjectionInfo returned dwSize=%d, dwError=%d, szIpAddress=%S",
|
|
projBuf.pppIp.dwSize,
|
|
projBuf.pppIp.dwError,
|
|
projBuf.pppIp.szIpAddress);
|
|
//
|
|
// Note: the following statement assumes the
|
|
// dwError field is at the same offset for
|
|
// all members of the union.
|
|
//
|
|
if (projBuf.pppNbf.dwError) {
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: %S: dwError=0x%x",
|
|
RASAUTO_TRACESTRW(pEntryNames[dwConn]),
|
|
projBuf.pppNbf.dwError);
|
|
continue;
|
|
}
|
|
switch (pAdapter->fType) {
|
|
case ACD_ADAPTER_LANA:
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: comparing lanas (%d, %d)",
|
|
pAdapter->bLana,
|
|
projBuf.pppNbf.bLana);
|
|
if (pAdapter->bLana == projBuf.pppNbf.bLana) {
|
|
pszEntryName = CopyString(pEntryNames[dwConn]);
|
|
goto done;
|
|
}
|
|
break;
|
|
case ACD_ADAPTER_IP:
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: comparing ipaddrs (%S, %S)",
|
|
szIpAddr,
|
|
projBuf.pppIp.szIpAddress);
|
|
// if (!_wcsicmp(szIpAddr, projBuf.pppIp.szIpAddress)) {
|
|
pszEntryName = CopyString(pEntryNames[dwConn]);
|
|
goto done;
|
|
//}
|
|
break;
|
|
case ACD_ADAPTER_MAC:
|
|
//
|
|
// Terminate IPX address after network number.
|
|
//
|
|
pwszMac = wcschr(projBuf.pppIpx.szIpxAddress, '.');
|
|
if (pwszMac == NULL)
|
|
goto done;
|
|
pszMac = UnicodeStringToAnsiString(pwszMac + 1, NULL, 0);
|
|
if (pszMac == NULL)
|
|
goto done;
|
|
StringToNodeNumber(pszMac, cMac);
|
|
RASAUTO_TRACE6(
|
|
"ProcessLearnedAddress: mac addr #1: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
pAdapter->cMac[0],
|
|
pAdapter->cMac[1],
|
|
pAdapter->cMac[2],
|
|
pAdapter->cMac[3],
|
|
pAdapter->cMac[4],
|
|
pAdapter->cMac[5]);
|
|
RASAUTO_TRACE6(
|
|
"ProcessLearnedAddress: mac addr #2: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
cMac[0],
|
|
cMac[1],
|
|
cMac[2],
|
|
cMac[3],
|
|
cMac[4],
|
|
cMac[5]);
|
|
if (RtlEqualMemory(pAdapter->cMac, cMac, sizeof (cMac)))
|
|
{
|
|
pszEntryName = CopyString(pEntryNames[dwConn]);
|
|
goto done;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
nProtocols = 0;
|
|
hPort = (HPORT)(*lpfnRasGetHportG)(phRasConn[dwConn]);
|
|
(*lpfnRasPortEnumProtocolsG)(NULL, hPort, &Protocols, &nProtocols);
|
|
for (i = 0; i < nProtocols; i++) {
|
|
pRoute = &Protocols.RP_ProtocolInfo[i];
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: comparing (%S, %S)",
|
|
pAdapter->szName,
|
|
&pRoute->RI_AdapterName[8]);
|
|
//
|
|
// Skip the "/Device/" prefix in
|
|
// RI_AdapterName for the comparison.
|
|
//
|
|
if (!_wcsicmp(
|
|
pAdapter->szName,
|
|
&pRoute->RI_AdapterName[8]))
|
|
{
|
|
pszEntryName = CopyString(pEntryNames[dwConn]);
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
//
|
|
// Create a mapping for the original address
|
|
// if we found one.
|
|
//
|
|
if (pszEntryName != NULL) {
|
|
LPTSTR pszNetbiosName, pszAlias = NULL;
|
|
CHAR szIpAddress[17], *psz;
|
|
ULONG inaddr;
|
|
struct hostent *hp;
|
|
|
|
switch (fType) {
|
|
case ACD_ADDR_IP:
|
|
//
|
|
// Get the Netbios name from the IP address,
|
|
// if any.
|
|
//
|
|
hPort = (HPORT)(*lpfnRasGetHportG)(phRasConn[dwConn]);
|
|
pszNetbiosName = IpAddressToNetbiosName(pszAddress, hPort);
|
|
if (pszNetbiosName != NULL) {
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: ipaddr %S maps to Netbios name %S",
|
|
pszAddress,
|
|
pszNetbiosName);
|
|
LockAddressMap();
|
|
fStatus = SetAddressDialingLocationEntry(
|
|
pszNetbiosName,
|
|
pszEntryName);
|
|
fStatus = SetAddressTag(
|
|
pszNetbiosName,
|
|
ADDRMAP_TAG_LEARNED);
|
|
UnlockAddressMap();
|
|
LocalFree(pszNetbiosName);
|
|
}
|
|
//
|
|
// Get the DNS name from the IP address,
|
|
// if any.
|
|
//
|
|
UnicodeStringToAnsiString(
|
|
pszAddress,
|
|
szIpAddress,
|
|
sizeof (szIpAddress));
|
|
inaddr = inet_addr(szIpAddress);
|
|
psz = GetHostentCache(inaddr);
|
|
if (psz != NULL)
|
|
pszAlias = AnsiStringToUnicodeString(psz, NULL, 0);
|
|
if (pszAlias != NULL) {
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: ipaddr %S maps to DNS %S",
|
|
pszAddress,
|
|
pszAlias);
|
|
LockAddressMap();
|
|
fStatus = SetAddressDialingLocationEntry(
|
|
pszAlias,
|
|
pszEntryName);
|
|
fStatus = SetAddressTag(
|
|
pszAlias,
|
|
ADDRMAP_TAG_LEARNED);
|
|
UnlockAddressMap();
|
|
LocalFree(pszAlias);
|
|
}
|
|
break;
|
|
case ACD_ADDR_IPX:
|
|
//
|
|
// Get the Netbios name from the IPX address,
|
|
// if any.
|
|
//
|
|
pszNetbiosName = IpxAddressToNetbiosName(pszAddress);
|
|
if (pszNetbiosName != NULL) {
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: ipaddr %S maps to Netbios name %S",
|
|
pszAddress,
|
|
pszNetbiosName);
|
|
LockAddressMap();
|
|
fStatus = SetAddressDialingLocationEntry(
|
|
pszNetbiosName,
|
|
pszEntryName);
|
|
fStatus = SetAddressTag(
|
|
pszNetbiosName,
|
|
ADDRMAP_TAG_LEARNED);
|
|
UnlockAddressMap();
|
|
LocalFree(pszNetbiosName);
|
|
}
|
|
break;
|
|
}
|
|
RASAUTO_TRACE2(
|
|
"ProcessLearnedAddress: learned %S->%S",
|
|
pszAddress,
|
|
pszEntryName);
|
|
LockAddressMap();
|
|
fStatus = SetAddressDialingLocationEntry(
|
|
pszAddress,
|
|
pszEntryName);
|
|
fStatus = SetAddressTag(
|
|
pszAddress,
|
|
ADDRMAP_TAG_LEARNED);
|
|
UnlockAddressMap();
|
|
LocalFree(pszEntryName);
|
|
}
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (dwConnections) {
|
|
FreeStringArray(pEntryNames, dwConnections);
|
|
LocalFree(phRasConn);
|
|
}
|
|
|
|
if(NULL != pszMac)
|
|
{
|
|
LocalFree(pszMac);
|
|
}
|
|
} // ProcessLearnedAddress
|
|
|
|
|
|
|
|
VOID
|
|
SetRedialOnLinkFailureHandler(
|
|
IN FARPROC lpProc
|
|
)
|
|
{
|
|
(*lpfnRasRegisterRedialCallbackG)(lpProc);
|
|
} // SetRedialOnLinkFailureHandler
|
|
|
|
|
|
VOID
|
|
GetPortProtocols(
|
|
IN HPORT hPort,
|
|
IN RAS_PROTOCOLS *pProtocols,
|
|
IN LPDWORD lpdwcProtocols
|
|
)
|
|
{
|
|
(*lpfnRasPortEnumProtocolsG)(NULL, hPort, pProtocols, lpdwcProtocols);
|
|
}
|