|
|
/*++
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); }
|