|
|
//+----------------------------------------------------------------------------
//
// File: ras.cpp
//
// Module: CMDIAL32.DLL
//
// Synopsis: This module contains the functions to allow Connection Manager to
// interact with RAS.
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// Author: byao created 04/29/97
// quintinb created Header 08/16/99
//
//+----------------------------------------------------------------------------
#include "cmmaster.h"
#include "compchck.h"
#include "dial_str.h"
#include "dun_str.h"
#include "tunl_str.h"
#include "stp_str.h"
#include "ras_str.h"
#include "dialogs.h"
#include <cmdefs.h> // located in net\inc
//
// Include the header and code for linking to the SafeNet Config APIs
//
#include "cmsafenet.h"
#include "cmsafenet.cpp"
//
// For AllowAccessToWorld
//
#include "allowaccess.h"
#include "allowaccess.cpp"
//
// CMS flags use to specify DUN settings. These entries are specific
// to this code module, shared entries are stored on dun_str.h
//
const TCHAR* const c_pszCmSectionDunPhone = TEXT("Phone"); const TCHAR* const c_pszCmEntryDunPhoneDialAsIs = TEXT("Dial_As_Is"); const TCHAR* const c_pszCmEntryDunPhonePhoneNumber = TEXT("Phone_Number"); const TCHAR* const c_pszCmEntryDunPhoneAreaCode = TEXT("Area_Code"); const TCHAR* const c_pszCmEntryDunPhoneCountryCode = TEXT("Country_Code"); const TCHAR* const c_pszCmEntryDunPhoneCountryId = TEXT("Country_ID"); const TCHAR* const c_pszCmSectionDunDevice = TEXT("Device"); const TCHAR* const c_pszCmEntryDunDeviceType = TEXT("Type"); const TCHAR* const c_pszCmEntryDunDeviceName = TEXT("Name"); const TCHAR* const c_pszCmEntryHideTrayIcon = TEXT("HideTrayIcon"); const TCHAR* const c_pszCmEntryInternetConnection = TEXT("InternetConnection");
//
// the following reg key and value control whether Dial-Up Networking on Win95
// will start the Wizard. Note that these are explicitly chars instead of TCHARs
//
const CHAR* const c_pszRegRemoteAccess = "RemoteAccess"; const CHAR* const c_pszRegWizard = "wizard";
#define ICM_RAS_REG_WIZARD_VALUE 0x00000080
//
// .CMS flags used only by ras.cpp
//
const TCHAR* const c_pszCmEntryDialExtraPercent = TEXT("DialExtraPercent"); const TCHAR* const c_pszCmEntryDialExtraSampleSeconds = TEXT("DialExtraSampleSeconds"); const TCHAR* const c_pszCmEntryHangUpExtraPercent = TEXT("HangUpExtraPercent"); const TCHAR* const c_pszCmEntryHangUpExtraSampleSeconds = TEXT("HangUpExtraSampleSeconds");
//
// This file includes the definitions of c_ArrayOfRasFuncsW and c_ArrayOfRasFuncsUA below
//
#include "raslink.cpp"
//
// Function prototypes
//
BOOL IsTerminalWindowSupportedOnWin2kPlus();
//+----------------------------------------------------------------------------
//
// Function: LinkToRas
//
// Synopsis: Establishes the RAS linkage by populating the inputted RAS Linkage structure
// with function pointers from Rasapi32.dll (on NT) or from cmutoa.dll (Unicode
// to ANSI wrapper functions used on win9x). Most of the actual work is done
// in LinkToDll, this function just does setup work to make sure the correct
// entry points are searched for and that Cmutoa.dll is initialized properly (since it
// needs to link to rasapi32.dll itself to get the actual ANSI RAS API's to work with).
//
// Arguments: RasLinkageStruct *prlsRasLink - pointer to a RAS Linkage structure. This
// structure contains storage for pointers to
// the RAS dll and all of the needed RAS
// function pointers.
//
// Returns: BOOL - FALSE if *any* entry point is still not resolved.
//
// History: quintinb Created Header 01/04/2000
//
//+----------------------------------------------------------------------------
BOOL LinkToRas(RasLinkageStruct *prlsRasLink) { BOOL bReturn = TRUE;
//
// Check inputs
//
if (NULL == prlsRasLink) { return FALSE; }
if (OS_NT) { //
// On NT we get our RAS APIs from rasapi32.dll and we ask for the W version
// of the API.
//
if (OS_NT4) { c_ArrayOfRasFuncsW[12] = NULL; //RasDeleteSubEntry
c_ArrayOfRasFuncsW[13] = NULL; //RasSetCustomAuthData
c_ArrayOfRasFuncsW[14] = NULL; //RasGetEapUserIdentity
c_ArrayOfRasFuncsW[15] = NULL; //RasFreeEapUserIdentity
c_ArrayOfRasFuncsW[16] = NULL; //RasInvokeEapUI
c_ArrayOfRasFuncsW[17] = NULL; //pfnGetCredentials
c_ArrayOfRasFuncsW[18] = NULL; //pfnSetCredentials
c_ArrayOfRasFuncsW[19] = NULL; //pfnGetCustomAuthData
} else if (OS_W2K) { //
// Special-casing for APIs that changed after Windows2000 shipped
//
c_ArrayOfRasFuncsW[12] = "DwDeleteSubEntry"; //RasDeleteSubEntry is DwDeleteSubEntry on Win2k
}
bReturn = LinkToDll(&prlsRasLink->hInstRas, "RASAPI32.DLL", c_ArrayOfRasFuncsW, prlsRasLink->apvPfnRas); } else { //
// On Win9x we still want the W version of the API but since it isn't available we
// call the wrappers in cmutoa.dll instead. Thus we use cmutoa.dll as our RAS API dll
// and call the UA APIs. We also have an extra step because we want to make sure
// that cmutoa.dll can actually initialize the RAS dll's that it uses for the UA
// conversion functions. Thus we call cmutoa's InitCmRasUtoA function to set up
// its internal RAS linkage. If this function fails, we must fail the RAS link.
typedef BOOL (WINAPI *pfnInitCmRasUtoASpec)(void);
pfnInitCmRasUtoASpec InitCmRasUtoA; HMODULE hCmUtoADll = LoadLibraryExA("cmutoa.DLL", NULL, 0); // REVIEW: this should use getmodulehandle so as not to change the refcount on the dll.
if (!hCmUtoADll) { return FALSE; }
// Get Initialization routine from the DLL
InitCmRasUtoA = (pfnInitCmRasUtoASpec) GetProcAddress(hCmUtoADll, "InitCmRasUtoA") ;
if (InitCmRasUtoA) { bReturn = InitCmRasUtoA(); if (bReturn) { if (!OS_MIL) { c_ArrayOfRasFuncsUA[11] = NULL; //RasSetSubEntryProperties
c_ArrayOfRasFuncsUA[12] = NULL; //RasDeleteSubEntry
}
bReturn = LinkToDll(&prlsRasLink->hInstRas, "CMUTOA.DLL", c_ArrayOfRasFuncsUA, prlsRasLink->apvPfnRas); } }
FreeLibrary(hCmUtoADll); // we want this to stay in memory but the refcount should also be correct
}
return bReturn; }
BOOL IsRasLoaded(const RasLinkageStruct * const prlsRasLink) { UINT uIndex = 0;
//
// Did we get a valid pointer passed in and does that
// struct contain a pointer to a RAS dll?
//
BOOL bReturn = (NULL != prlsRasLink) && (NULL != prlsRasLink->hInstRas);
//
// The list of functions we are checking for is different on NT
// and Win9x. Note that we also assume that LinkToRas has already
// been called so that the list of functions we are expecting will
// have been modified for the exact platform that we are one. If
// LinkToRas hasn't been called then the hInstRas param should be
// NULL.
//
if (OS_NT) { while (bReturn && (NULL != c_ArrayOfRasFuncsW[uIndex])) { //
// Check for a NULL function pointer when we have
// a valid function name.
//
if (NULL == prlsRasLink->apvPfnRas[uIndex]) { bReturn = FALSE; }
uIndex++; } } else { while (bReturn && (NULL != c_ArrayOfRasFuncsUA[uIndex])) { //
// Check for a NULL function pointer when we have
// a valid function name.
//
if (NULL == prlsRasLink->apvPfnRas[uIndex]) { bReturn = FALSE; }
uIndex++; } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: UnlinkFromRas
//
// Synopsis: This function tears down the linkage with RAS by freeing RAS dll's, calling
// the cmutoa unklinkage function (if necessary), and zeroing the RAS Linkage
// structure passed in.
//
// Arguments: RasLinkageStruct *prlsRasLink - pointer to a RAS Linkage structure. This
// structure contains storage for pointers to
// the RAS dll and all of the needed RAS
// function pointers.
//
// Returns: Nothing
//
// History: quintinb Created Header 01/04/2000
//
//+----------------------------------------------------------------------------
void UnlinkFromRas(RasLinkageStruct *prlsRasLink) { if (!OS_NT) { HMODULE hCmUtoADll = LoadLibraryExA("cmutoa.dll", NULL, 0); if (!hCmUtoADll) { CMASSERTMSG(FALSE, TEXT("UnlinkFromRas -- Unable to load cmutoa.")); return; }
FARPROC FreeCmRasUtoA = GetProcAddress(hCmUtoADll, "FreeCmRasUtoA");
if (FreeCmRasUtoA) { FreeCmRasUtoA(); }
FreeLibrary(hCmUtoADll); }
if (prlsRasLink->hInstRas) { FreeLibrary(prlsRasLink->hInstRas); }
memset(prlsRasLink,0,sizeof(RasLinkageStruct)); }
//
// GetRasModems: get a list of modem devices from RAS
//
//+----------------------------------------------------------------------------
//
// Function: GetRasModems
//
// Synopsis: Enumerates the available RAS devices. The device list is allocated and passed
// back to the caller through the pprdiRasDevInfo pointer. This allocated memory
// must be freed by the caller. The count of available devices is stored in the
// pdwCnt input parameter.
//
// Arguments: RasLinkageStruct *prlsRasLink - pointer to the RAS Linkage structure
// LPRASDEVINFO *pprdiRasDevInfo - pointer to hold the RAS device list
// LPDWORD pdwCnt - pointer to hold the count of devices
//
// Returns: BOOL - FALSE if unable to return the enumerated device list.
//
// History: quintinb Created Header 01/04/2000
//
//+----------------------------------------------------------------------------
BOOL GetRasModems(const RasLinkageStruct *prlsRasLink, LPRASDEVINFO *pprdiRasDevInfo, LPDWORD pdwCnt) { DWORD dwLen; DWORD dwRes; DWORD dwCnt;
if (pprdiRasDevInfo) { *pprdiRasDevInfo = NULL; } if (pdwCnt) { *pdwCnt = 0; } if (!prlsRasLink->pfnEnumDevices) { return (FALSE); } dwLen = 0; dwRes = prlsRasLink->pfnEnumDevices(NULL,&dwLen,&dwCnt);
CMTRACE3(TEXT("GetRasModems() RasEnumDevices(NULL,pdwLen,&dwCnt) returns %u, dwLen=%u, dwCnt=%u."), dwRes, dwLen, dwCnt); if (((dwRes != ERROR_SUCCESS) && (dwRes != ERROR_BUFFER_TOO_SMALL)) || (dwLen < sizeof(**pprdiRasDevInfo))) { return (FALSE); }
if (!pprdiRasDevInfo) { if (pdwCnt) { *pdwCnt = dwCnt; } return (TRUE); } *pprdiRasDevInfo = (LPRASDEVINFO) CmMalloc(__max(dwLen,sizeof(**pprdiRasDevInfo)));
if (*pprdiRasDevInfo) { (*pprdiRasDevInfo)->dwSize = sizeof(**pprdiRasDevInfo); dwRes = prlsRasLink->pfnEnumDevices(*pprdiRasDevInfo,&dwLen,&dwCnt);
CMTRACE3(TEXT("GetRasModems() RasEnumDevices(*pprdiRasDevInfo,&dwLen,&dwCnt) returns %u, dwLen=%u, dwCnt=%u."), dwRes, dwLen, dwCnt);
if (dwRes != ERROR_SUCCESS) { CmFree(*pprdiRasDevInfo); *pprdiRasDevInfo = NULL; return (FALSE); } } else { CMASSERTMSG(FALSE, TEXT("GetRasModems -- CmMalloc failed to allocate memory for *pprdiRasDevInfo.")); return (FALSE); } if (pdwCnt) { *pdwCnt = dwCnt; }
return (TRUE); }
//+----------------------------------------------------------------------------
//
// Function: PickModem
//
// Synopsis:
//
// Arguments: const pArgs, the pArgs->pIniProfile contains the modem name
// OUT pszDeviceType, the device type if not NULL
// OUT pszDeviceName, the device name if not NULL
// OUT pfSameModem, Whether the modem found is the same as
// the one in profile
//
// Returns: TRUE, is modem is found
//
// History: fengsun Created Header 10/24/97
//
//+----------------------------------------------------------------------------
BOOL PickModem(IN const ArgsStruct *pArgs, OUT LPTSTR pszDeviceType, OUT LPTSTR pszDeviceName, OUT BOOL* pfSameModem) { LPRASDEVINFO prdiModems; DWORD dwCnt; LPTSTR pszModem; DWORD dwIdx; BOOL bFound = FALSE;
//
// First, get a list of modems from RAS
//
if (!GetRasModems(&pArgs->rlsRasLink,&prdiModems,&dwCnt) || dwCnt == 0) { return (FALSE); }
if (pfSameModem) { *pfSameModem = FALSE; }
//
// Get the name of the current modem from the service profile and
// try to find a match against non-tunnel RAS devices in the list
//
pszModem = pArgs->piniProfile->GPPS(c_pszCmSection, c_pszCmEntryDialDevice);
if (*pszModem) { CMTRACE1(TEXT("PickModem() - looking for match with %s"), pszModem);
for (dwIdx=0; dwIdx < dwCnt; dwIdx++) { CMTRACE2(TEXT("PickModem() - examining device (%s) of type (%s)"), prdiModems[dwIdx].szDeviceName, prdiModems[dwIdx].szDeviceType);
//
// we'll take only ISDN and modem devices
//
if (lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Isdn) && lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Modem) && lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Atm)) { continue; }
//
// If we have a match, we're done here
//
if (lstrcmpiU(pszModem,prdiModems[dwIdx].szDeviceName) == 0) { CMTRACE(TEXT("PickModem() - match found.")); bFound = TRUE; if (pfSameModem) { *pfSameModem = TRUE; } break; } } }
if (FALSE == bFound) { //
// No match, find the first non-tunnel device and use it by default.
//
CMTRACE(TEXT("PickModem() - enumerating devices for default match against type RASDT_Isdn, RASDT_Modem or RASDT_Atm")); for (dwIdx=0; dwIdx < dwCnt; dwIdx++) { CMTRACE2(TEXT("PickModem() - examining device (%s) of type (%s)"), prdiModems[dwIdx].szDeviceName, prdiModems[dwIdx].szDeviceType); //
// we'll take only ISDN and modem devices
//
if (!lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Isdn) || !lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Modem) || !lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Atm)) { CMTRACE2(TEXT("PickModem() - default device (%s) of type (%s) selected."), prdiModems[dwIdx].szDeviceName, prdiModems[dwIdx].szDeviceType); bFound = TRUE; break; } } }
//
// If we have a match, fill device name and device type
//
if (bFound) { if (pszDeviceType) { lstrcpyU(pszDeviceType,prdiModems[dwIdx].szDeviceType); } if (pszDeviceName) { lstrcpyU(pszDeviceName,prdiModems[dwIdx].szDeviceName); } }
CmFree(pszModem); CmFree(prdiModems); return (bFound); }
//+----------------------------------------------------------------------------
//
// Function: GetDeviceType
//
// Synopsis: Get the deviceType for a chosen device name
//
// Arguments: pArgs - Pointer to ArgsStruct
// pszDeviceType[OUT] - pointer to buffer where device
// type will be returned
// pszDeviceName[IN] - device name
//
// Returns: TRUE on success, FALSE otherwise
//
// History: byao Created 03/21/97
//-----------------------------------------------------------------------------
BOOL GetDeviceType(ArgsStruct *pArgs, LPTSTR pszDeviceType, LPTSTR pszDeviceName) { LPRASDEVINFO prdiModems; DWORD dwCnt, dwIdx;
if (!pszDeviceType) { return FALSE; }
// first, get a list of modems from RAS
if (!GetRasModems(&pArgs->rlsRasLink,&prdiModems,&dwCnt)) { return (FALSE); }
// choose the device that has the same name as pszDeviceName
for (dwIdx=0;dwIdx<dwCnt;dwIdx++) { if (lstrcmpiU(pszDeviceName,prdiModems[dwIdx].szDeviceName) == 0) { lstrcpyU(pszDeviceType, prdiModems[dwIdx].szDeviceType); break; } }
CmFree(prdiModems);
if (dwIdx == dwCnt) // not found in the modem list -- strange things happened
{ return FALSE; }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function ConfiguredToDialWithSafeNet
//
// Synopsis Figures out if the current Tunnel DUN setting is configured
// to use the SafeNet client.
//
// Arguments pArgs Pointer to ArgsStruct
//
// Returns TRUE - if the current Tunnel DUN setting should use SafeNet
//
// History 09/24/01 quintinb Created
//
//-----------------------------------------------------------------------------
BOOL ConfiguredToDialWithSafeNet(ArgsStruct *pArgs) { BOOL bUseSafeNet = FALSE;
if (OS_NT4 || OS_W9X) { LPTSTR pszDunSetting = GetDunSettingName(pArgs, -1, TRUE); // -1 for index as not needed, TRUE for is Tunneling
if (pszDunSetting) { //
// Create an Ini File object so that we can access the UseDownLevelL2TP setting
//
CIni iniFile(g_hInst, pArgs->piniService->GetFile());
LPTSTR pszSection = CmStrCpyAlloc(TEXT("&")); if (pszSection) { pszSection = CmStrCatAlloc(&pszSection, pszDunSetting); if (pszSection) { iniFile.SetSection(pszSection); CmFree(pszSection);
//
// If we are supposed to be using the SafeNet downlevel L2TP client, then we need to make
// sure to pick it as the adapter name. We can only use the SafeNet client if it is available,
// however.
//
if (iniFile.GPPB(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingUseDownLevelL2TP)) { bUseSafeNet = pArgs->bSafeNetClientAvailable; } } }
CmFree(pszDunSetting); } }
return bUseSafeNet; }
//+----------------------------------------------------------------------------
//
// Function IsSafeNetDevice
//
// Synopsis Figures out if the passed in device name and device type
// correspond to a SafeNet device.
//
// Arguments LPCTSTR pszDeviceType - type of device to check
// LPCTSTR pszDeviceName - name of device to check
//
// Returns TRUE - if the device is a SafeNet device
//
// History 09/24/01 quintinb Created
//
//-----------------------------------------------------------------------------
BOOL IsSafeNetDevice(LPCTSTR pszDeviceType, LPCTSTR pszDeviceName) { BOOL bReturn = FALSE;
if (pszDeviceType && pszDeviceName) { //
// First check the existing names...
//
if (OS_NT4 && (0 == lstrcmpiU(pszDeviceType, c_pszSafeNetAdapterType_Winnt4_old)) && (0 == lstrcmpiU(pszDeviceName, c_pszSafeNetAdapterName_Winnt4_old))) { bReturn = TRUE; } if (!bReturn && OS_W9X && (0 == lstrcmpiU(pszDeviceType, c_pszSafeNetAdapterType_Win9x_old)) && (0 == lstrcmpiU(pszDeviceName, c_pszSafeNetAdapterName_Win9x_old))) { bReturn = TRUE; }
//
// Now check the names that are supposed to exist in the future...
//
if (!bReturn && OS_NT4 && (0 == lstrcmpiU(pszDeviceType, RASDT_Vpn)) && (0 == lstrcmpiU(pszDeviceName, c_pszSafeNetAdapterName_Winnt4))) { bReturn = TRUE; } if (!bReturn && OS_W9X && (0 == lstrcmpiU(pszDeviceType, RASDT_Vpn))) { //
// If SafeNet doesn't fix the problem on win9x where the adapter is named "XXX 1",
// then we are going to need to match adapters that might or might not have this
// extra suffix. Thus lets check the first lstrlenU(c_pszSafeNetAdapterName_Win9x)
// letters and if we have a match we will call it good.
//
DWORD dwLen = lstrlenU(c_pszSafeNetAdapterName_Win9x);
if (dwLen <= (DWORD)lstrlenU(pszDeviceName)) { LPTSTR pszString = (LPTSTR)CmMalloc((dwLen+1)*sizeof(TCHAR));
if (pszString) { lstrcpynU(pszString, pszDeviceName, dwLen+1);
if (0 == lstrcmpiU(pszString, c_pszSafeNetAdapterName_Win9x)) { bReturn = TRUE; }
CmFree (pszString); } } } }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function PickTunnelDevice
//
// Synopsis pick a tunnel device used to dial out
//
// Arguments pArgs Pointer to ArgsStruct
// pszDeviceType Tunnel device type. -- RASDT_Vpn
// pszDeviceName Tunnel device name
//
// Returns TRUE - scripting has been installed
//
// History 03/01/97 byao Created
// 09/05/01 quintinb Rewrote to handle the SafeNet Adapter
//
//-----------------------------------------------------------------------------
BOOL PickTunnelDevice(ArgsStruct *pArgs, LPTSTR pszDeviceType, LPTSTR pszDeviceName) { //
// Check input parameters
//
if ((NULL == pArgs) || (NULL == pszDeviceType) || (NULL == pszDeviceName)) { CMASSERTMSG(FALSE, TEXT("PickTunnelDevice -- invalid parameters passed!")); return FALSE; }
LPRASDEVINFO prdiModems = NULL; BOOL bReturn = FALSE; DWORD dwCnt; DWORD dwIdx;
//
// Clear the output param
//
pszDeviceName[0] = TEXT('\0'); pszDeviceType[0] = TEXT('\0');
//
// First, get the list of devices from RAS
//
if (GetRasModems(&pArgs->rlsRasLink, &prdiModems, &dwCnt) && dwCnt) { //
// Okay, let's pick an MS tunnel adapter first
//
for (dwIdx = 0; dwIdx < dwCnt; dwIdx++) { if (0 == lstrcmpiU(prdiModems[dwIdx].szDeviceType, RASDT_Vpn)) { //
// Okay, if this is Win2k+ then any VPN device will do. RAS will figure out what
// we mean by looking at the VpnStrategy.
//
if (OS_NT5) { break; } else { //
// For downlevel platforms we either need to pick the SafeNet device or make sure
// we aren't picking it if we are doing PPTP.
//
BOOL bSafeNetDeviceName = IsSafeNetDevice(prdiModems[dwIdx].szDeviceType, prdiModems[dwIdx].szDeviceName);
if (!bSafeNetDeviceName) { break; } } } }
if (dwIdx != dwCnt) { lstrcpyU(pszDeviceName, prdiModems[dwIdx].szDeviceName); lstrcpyU(pszDeviceType, prdiModems[dwIdx].szDeviceType); bReturn = TRUE; }
//
// If we are configured to dial with SafeNet then we actually want to pick
// the SafeNet adapter. However, if we cannot find their adapter then we will
// use the one we picked before...
//
BOOL bUseSafeNet = ConfiguredToDialWithSafeNet(pArgs);
if (bUseSafeNet) { for (dwIdx = 0; dwIdx < dwCnt; dwIdx++) { if (IsSafeNetDevice(prdiModems[dwIdx].szDeviceType, prdiModems[dwIdx].szDeviceName)) { break; } }
//
// Note that if we find a SafeNet device it will override the device we found in the
// first for loop. However, if we don't find a SafeNet device then we will go ahead
// and use the MS adapter assuming we found one...
//
if (dwIdx != dwCnt) { lstrcpyU(pszDeviceName, prdiModems[dwIdx].szDeviceName); lstrcpyU(pszDeviceType, prdiModems[dwIdx].szDeviceType); bReturn = TRUE; } } }
CmFree(prdiModems);
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: CopyAutoDial
//
// Synopsis: Sets the szAutodialDll and szAutodialFunc members of the
// specified RAS entry structure with our module name and
// InetDialHandler repectively. Not on NT5.
//
// Arguments: LPRASENTRY preEntry - Ptr to the Ras entry structure.
//
// Returns: Nothing
//
// History: nickball Created Header 03/16/98
// nickball Removed from NT5 11/17/98
//
//+----------------------------------------------------------------------------
void CopyAutoDial(LPRASENTRY preEntry) { MYDBGASSERT(preEntry);
//
// Don't set these on NT5, they are no longer used by IE and the
// InetDialHandler prototype differs from that used by RAS
//
if (OS_NT5 || NULL == preEntry) { return; }
memset(preEntry->szAutodialDll,0,sizeof(preEntry->szAutodialDll));
//
// Set szAutodialDll with our Module name
//
GetModuleFileNameU(g_hInst, preEntry->szAutodialDll, sizeof(preEntry->szAutodialDll)/sizeof(TCHAR));
//
// Set szAutodialFunc with the mangled form of InetDialHandler
//
memset(preEntry->szAutodialFunc,0,sizeof(preEntry->szAutodialFunc)); lstrcpyU(preEntry->szAutodialFunc, c_pszInetDialHandler); }
//+----------------------------------------------------------------------------
//
// Function MyRGEP
//
// Synopsis Call RasGetEntryProperties()
//
// Arguments
//
// Returns
//
// Histroy Revised to improve performance 08/7/97 fengsun
//-----------------------------------------------------------------------------
LPRASENTRY MyRGEP(LPCTSTR pszRasPbk, LPCTSTR pszEntryName, RasLinkageStruct *prlsRasLink) { LPRASENTRY preRasEntry; DWORD dwRes;
if (!(preRasEntry = AllocateRasEntry())) { MYDBGASSERT(0); return NULL; }
DWORD dwRasEntry = preRasEntry->dwSize;
dwRes = prlsRasLink->pfnGetEntryProperties(pszRasPbk, pszEntryName, preRasEntry, &dwRasEntry, NULL, // lpbDeviceInfo
NULL); // lpdwDeviceInfoSize
CMTRACE2(TEXT("MyRGEP() - dwRasEntry = %u : sizeof(*preRasEntry) = %u"), dwRasEntry, sizeof(*preRasEntry)); if ((dwRes == ERROR_BUFFER_TOO_SMALL) && (dwRasEntry >= sizeof(*preRasEntry))) { //
// If the memory if not large enough, realloc one
//
CmFree(preRasEntry);
preRasEntry = (LPRASENTRY) CmMalloc(dwRasEntry);
if (NULL != preRasEntry) { //
// dwSize has to be set to sizeof(RASENTRY)
// because dwRasEntry contains the additional
// bytes required for this connectoid (alternative
// phone numbers, etc.
//
preRasEntry->dwSize = sizeof(RASENTRY); // Specifies version
dwRes = prlsRasLink->pfnGetEntryProperties (pszRasPbk, pszEntryName, preRasEntry, &dwRasEntry, NULL, NULL); } else { MYDBGASSERT(0); return NULL; } }
if (dwRes != ERROR_SUCCESS) { CMTRACE3(TEXT("MyRGEP(*pszRasPbk=%s, *pszEntryName=%s) RasGetEntryProperties returned %u"), pszRasPbk, pszEntryName, dwRes); CmFree(preRasEntry); preRasEntry = NULL; }
SetLastError(dwRes); return (preRasEntry); }
//+----------------------------------------------------------------------------
//
// Function IsConnectErrorFatal
//
// Synopsis Determine if an error is recoverable, (ie. we should re-dial).
//
// Arguments DWORD dwErr - The RAS error code
// ArgsStruct* pArgs - Ptr to global args struct
//
// Returns TRUE if error is fatal
//
// Histroy nickball Created header 05/21/99
//
//-----------------------------------------------------------------------------
BOOL IsConnectErrorFatal(DWORD dwErr, ArgsStruct *pArgs) { switch (dwErr) { //
// The following cases are W9x ISDN error returns that actually mean
// different things on WinNT. Since we use the NT header files, we don't
// have an include file that contains these errors. We have to special
// case these so that we recognize them as ISDN errors, and reconnect as
// appropriate.
//
// The 9x errors are listed below along with the NT equivalents.
//
case 751: // 9x.ERROR_BAD_DEST_ADDRESS == NT.ERROR_INVALID_CALLBACK_NUMBER
case 752: // 9x.ERROR_UNREACHABLE_DEST == NT.ERROR_SCRIPT_SYNTAX
case 753: // 9x.ERROR_INCOMPATIBLE_DEST == NT.ERROR_HANGUP_FAILED
case 754: // 9x.ERROR_NETWORK_CONGESTION == NT.ERROR_BUNDLE_NOT_FOUND
case 755: // 9x.ERROR_CALL_BLOCKED == NT.ERROR_CANNOT_DO_CUSTOMDIAL
case 756: // 9x.ERROR_NETWORK_TEMPFAILURE == NT.ERROR_DIAL_ALREADY_IN_PROGRESS
if (OS_W9X) { //
// On W9x, if you have an invalid ISDN number, the error codes
// returned by Millennium RAS are different from the NT ones.
// We have to special-case these by number so that we reconnect
//
CMTRACE1(TEXT("IsConnectErrorFatal : handled Win9x ISDN error %d"), dwErr); return FALSE; } break;
case ERROR_PPP_TIMEOUT: // Timed out waiting for a valid response from the remote PPP peer.%0
case ERROR_PPP_REMOTE_TERMINATED: // PPP terminated by remote machine.%0
case ERROR_PPP_INVALID_PACKET: // The PPP packet is invalid.%0
case ERROR_PPP_NO_RESPONSE: // Remote PPP peer is not responding
case ERROR_SERVER_NOT_RESPONDING: case ERROR_LINE_BUSY: case ERROR_NO_CARRIER: case ERROR_REMOTE_DISCONNECTION: case ERROR_BAD_ADDRESS_SPECIFIED: case ERROR_AUTOMATIC_VPN_FAILED: // New ras error for VPN
case ERROR_NO_ANSWER: return FALSE; break;
case ERROR_PORT_DISCONNECTED: { if (0 == lstrcmpiU(pArgs->szDeviceType, RASDT_Isdn)) { if ((CM_ISDN_MODE_DUALCHANNEL_ONLY == pArgs->dwIsdnDialMode) || (CM_ISDN_MODE_DUALCHANNEL_FALLBACK == pArgs->dwIsdnDialMode)) { OutputDebugString(TEXT("IsConnectErrorFatal -- Got a ERROR_PORT_DISCONNECTED error. Ignoring because it is dual channel ISDN.")); CMTRACE(TEXT("IsConnectErrorFatal -- Got a ERROR_PORT_DISCONNECTED error. Ignoring because it is dual channel ISDN.")); return FALSE; } }
return TRUE; break; }
default: break; }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function IsRasError
//
// Synopsis Simple function to determine if an error falls in the RAS range
//
// Arguments DWORD dwErr - The error code
//
// Returns TRUE if error is within RAS range
//
// Histroy nickball Created header 05/21/99
//
//-----------------------------------------------------------------------------
inline BOOL IsRasError(DWORD dwErr) { return ((dwErr >= RASBASE) && (dwErr <= RASBASEEND)); }
//+----------------------------------------------------------------------------
//
// Function CheckConnectionError
//
// Synopsis Determine if a RAS error is recoverable. If not recoverable,
// retrieves the appropriate error message for display.
//
// Arguments DWORD dwErr - The RAS error code
// ArgsStruct* pArgs - Ptr to global args struct
// BOOL fTunneling - Flag indicating whether we're tunneling
// LPTSTR *ppszRasErrMsg - Pointer to pointer for message string
//
// Returns TRUE if error is fatal
//
// Histroy nickball Created header 05/21/99
//
//-----------------------------------------------------------------------------
BOOL CheckConnectionError(HWND hwndDlg, DWORD dwErr, ArgsStruct *pArgs, BOOL fTunneling, LPTSTR *ppszRasErrMsg) { DWORD dwIdMsg = 0; LPTSTR pszMsg = NULL; LPTSTR pszTmp = NULL;
//
// Examine the error more closely. Note: For W2K, we skip RAS
// errors and query RAS for a displayable error string below.
//
if ((!OS_NT5) || (!IsRasError(dwErr))) { switch (dwErr) { case ERROR_PPP_TIMEOUT: // Timed out waiting for a valid response from the remote PPP peer.%0
case ERROR_PPP_REMOTE_TERMINATED: // PPP terminated by remote machine.%0
case ERROR_PPP_INVALID_PACKET: // The PPP packet is invalid.%0
case ERROR_PPP_NO_RESPONSE: // Remote PPP peer is not responding
case ERROR_SERVER_NOT_RESPONDING: dwIdMsg = IDMSG_PPPPROBLEM; break;
case ERROR_LINE_BUSY: if ((pArgs->nDialIdx+1 == MAX_PHONE_NUMBERS || !pArgs->aDialInfo[pArgs->nDialIdx+1].szDialablePhoneNumber[0]) && !pArgs->nRedialCnt) dwIdMsg = IDMSG_LINEBUSY; else dwIdMsg = IDMSG_LINEBUSYREDIAL;
break;
case ERROR_NO_ANSWER: case ERROR_NO_CARRIER: if ((pArgs->nDialIdx+1 == MAX_PHONE_NUMBERS || !pArgs->aDialInfo[pArgs->nDialIdx+1].szDialablePhoneNumber[0]) && !pArgs->nRedialCnt) dwIdMsg = fTunneling ? IDMSG_TUNNEL_NOANSWER : IDMSG_NOANSWER ; else dwIdMsg = fTunneling ? IDMSG_TUNNEL_NOANSWERREDIAL : IDMSG_NOANSWERREDIAL; break;
case ERROR_REMOTE_DISCONNECTION: dwIdMsg = IDMSG_REMOTEDISCONNECTED; break;
case ERROR_BAD_ADDRESS_SPECIFIED: dwIdMsg = IDMSG_TUNNEL_NOANSWERREDIAL; break;
case ERROR_PPP_NO_PROTOCOLS_CONFIGURED: // No PPP control protocols configured.%0
dwIdMsg = IDMSG_TCPIPPROBLEM; break;
case ERROR_PORT_ALREADY_OPEN: dwIdMsg = fTunneling ? IDMSG_TUNNELINUSE : IDMSG_PORTINUSE ; break;
case ERROR_FROM_DEVICE: dwIdMsg = IDMSG_DEVICEERROR; break;
case ERROR_HARDWARE_FAILURE: case ERROR_PORT_OR_DEVICE: //11694
case ERROR_DEVICE_NOT_READY: dwIdMsg = IDMSG_NOTRESPONDING; break;
case ERROR_NO_DIALTONE: dwIdMsg = IDMSG_NODIALTONE; break;
case ERROR_CANCELLED: case ERROR_USER_DISCONNECTION: dwIdMsg = IDMSG_CANCELED; break;
case ERROR_AUTHENTICATION_FAILURE: case ERROR_ACCESS_DENIED: // 13795 // WINDOWS ERROR
dwIdMsg = IDMSG_BADPASSWORD; break;
case ERROR_VOICE_ANSWER: dwIdMsg = IDMSG_VOICEANSWER; break; case ERROR_PORT_NOT_AVAILABLE: if (IsDialingTunnel(pArgs)) { dwIdMsg = IDMSG_TUNNELNOTAVAILABLE; } else { dwIdMsg = IDMSG_PORTNOTAVAILABLE; } break;
case ERROR_PORT_NOT_CONFIGURED: dwIdMsg = IDMSG_PORTNOTCONFIGURED; break;
case ERROR_RESTRICTED_LOGON_HOURS: dwIdMsg = IDMSG_RESTRICTEDLOGONHOURS; break; case ERROR_ACCT_DISABLED: case ERROR_ACCT_EXPIRED: dwIdMsg = IDMSG_ACCTDISABLED; break;
case ERROR_PASSWD_EXPIRED: dwIdMsg = IDMSG_PASSWDEXPIRED; break; case ERROR_NO_DIALIN_PERMISSION: dwIdMsg = IDMSG_NODIALINPERMISSION; break;
case ERROR_PROTOCOL_NOT_CONFIGURED: dwIdMsg = IDMSG_PROTOCOL_NOT_CONFIGURED; break;
case ERROR_INVALID_DATA: // WINDOWS ERROR
//
// The specific case in which we encountered DUN settings
// that aren't supported on the current platform
//
CMTRACE(TEXT("CheckConnectionError - Unsupported DUN setting detected")); dwIdMsg = IDMSG_UNSUPPORTED_SETTING; break; case ERROR_BAD_PHONE_NUMBER: // TBD - drop through to default
default: break; } }
if (0 == dwIdMsg) { //
// If no message ID was picked up, then try to get one from RAS
//
if (pArgs->rlsRasLink.pfnGetErrorString) { DWORD dwRes; DWORD dwFmtMsgId;
pszTmp = (LPTSTR) CmMalloc(256 * sizeof(TCHAR)); // Docs say 256 chars is always enough.
if (pszTmp) { dwRes = pArgs->rlsRasLink.pfnGetErrorString((UINT) dwErr, pszTmp, (DWORD) 256); if (ERROR_SUCCESS == dwRes) { pszMsg = CmFmtMsg(g_hInst, IDMSG_RAS_ERROR, pszTmp, dwErr); } }
CmFree(pszTmp); } if (NULL == pszMsg) { //
// Still no message, try to get description from system (on NT)
// Note: HRESULTS are displayed in Hex, Win errors are decimal.
if (OS_NT) { if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_IGNORE_INSERTS + FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, 0, (LPTSTR) &pszTmp, 1, NULL)) { if (pszTmp) { pszMsg = CmFmtMsg(g_hInst, (dwErr > 0x7FFFFFFF) ? IDMSG_SYS_ERROR_HEX : IDMSG_SYS_ERROR_DEC, pszTmp, dwErr); LocalFree(pszTmp); } else { CMASSERTMSG(FALSE, TEXT("CheckConnectionError -- FormatMessage failed to allocate pszTmp.")); } } } if (NULL == pszMsg) { //
// Still no message, go with default
//
pszMsg = CmFmtMsg(g_hInst, (dwErr > 0x7FFFFFFF) ? IDMSG_CM_ERROR_HEX : IDMSG_CM_ERROR_DEC, dwErr); } } }
//
// If we have a message ID format it for display
//
if (dwIdMsg) { MYDBGASSERT(!pszMsg); pszMsg = CmFmtMsg(g_hInst,dwIdMsg); }
if (pszMsg) { if (!ppszRasErrMsg) { AppendStatusPane(hwndDlg,pszMsg); CmFree(pszMsg); } else { //
// pass the msg to the caller. the caller needs to free it.
//
*ppszRasErrMsg = pszMsg; } }
BOOL bCancel = IsConnectErrorFatal(dwErr, pArgs);
if (bCancel && dwErr != ERROR_CANCELLED && dwErr != ERROR_AUTHENTICATION_FAILURE && dwErr != ERROR_ACCESS_DENIED) { //
// if we're canceling redial, then there might be something
// seriously wrong. We want to recheck our configs the next
// time CM is run.
//
ClearComponentsChecked(); } return (bCancel); }
//+----------------------------------------------------------------------------
//
// Function GetRasConnectoidName
//
// Synopsis Construct a RAS connectoid name.
//
// The connectoid name is "<long service name>-[Primary|Backup]".
// or "<long service name>&Tunnel" for the case of tunnel entry.
//
// Arguments pArgs Pointer to ArgsStruct
// piniService[IN] the service obj
// fTunnelEntry[IN] TRUE: This connectoid is for tunneling
// FALSE: otherwise
//
// Returns LPTSTR The connectoid name.
//
//-----------------------------------------------------------------------------
LPTSTR GetRasConnectoidName( ArgsStruct *pArgs, CIni* piniService, BOOL fTunnelEntry ) { LPTSTR pszConnectoid = GetServiceName(piniService); if (pszConnectoid) { //
// If tunneling 9X connectoid, append the Tunnel
// Suffix - e.g. "Tunnel (for advanced use only)"
//
if (OS_W9X && fTunnelEntry) { LPTSTR pszSuffix = GetTunnelSuffix(); if (pszSuffix) { pszConnectoid = CmStrCatAlloc(&pszConnectoid, pszSuffix); } CmFree(pszSuffix); } }
return pszConnectoid; }
//+----------------------------------------------------------------------------
//
// Function CreateRASEntryStruct
//
// Synopsis Create a connectoid with the settings specified in the cms.
// If a parameter does NOT exist in the cms file, the corresponding
// value is used.
//
// The connectoid name is "<long service name>-[Primary|Backup]".
// or "<long service name>&Tunnel" for the case of tunnel entry.
//
// Arguments pArgs Pointer to ArgsStruct
// pszDUN DUN name
// piniService[IN] the service file obj
// fTunnelEntry[IN] TRUE: This connectoid is for tunneling
// FALSE: otherwise
// pszRasPbk the RAS phonebook in which the connectoid is located
// ppbEapData[OUT] Address of pointer to store EapData, allocated here.
// pdwEapSize[OUT] Ptr to a DWORD to record the size of the data blob.
//
// Returns LPRASENTRY The new RAS connectoid
//
// History 5/12/97 henryt created
// 5/23/97 byao Modified: added fSkipProfile flag
// 6/9/97 byao Modified: use DUN= field when the
// phone number has no DUN name associated
// 7/28/97 byao Added change for #10459
// 4/13/97 nickball Renamed, return LPRASENTRY
//-----------------------------------------------------------------------------
LPRASENTRY CreateRASEntryStruct( ArgsStruct *pArgs, LPCTSTR pszDUN, CIni* piniService, BOOL fTunnelEntry, LPTSTR pszRasPbk, LPBYTE *ppbEapData, LPDWORD pdwEapSize ) { LPTSTR pszDunEntry = NULL; DWORD dwErr = NOERROR; BOOL bTmp;
//
// first we need to create a RAS entry in memory with default values
//
LPRASENTRY preBuffer = AllocateRasEntry();
if (!preBuffer) { return NULL; }
MYDBGASSERT(preBuffer->dwSize >= sizeof(*preBuffer));
//
// Set up the preBuffer to defaults value
//
preBuffer->dwFramingProtocol = RASFP_Ppp;
//
// Allow only TCP/IP by default
//
preBuffer->dwfNetProtocols |= RASNP_Ip;
//
// Set default RASEO settings.
//
if (!fTunnelEntry) { preBuffer->dwfOptions |= RASEO_UseCountryAndAreaCodes | RASEO_IpHeaderCompression | RASEO_RemoteDefaultGateway | RASEO_SwCompression; //RASEO_SecureLocalFiles; // NT 427042
//RASEO_DisableLcpExtensions; //13059 Olympus + 289461 NT
//
// We want to honor the HideTrayIcon flag. If it is not NT5, then
// we always set this flag. If it is NT5, then we should only set
// this flag if HideTrayIcon is false.
//
if (!OS_NT5 || !(pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryHideTrayIcon))) { preBuffer->dwfOptions |= RASEO_ModemLights; }
//
// In order for users to be able to specify device settings on Whistler,
// they have to do it from the control panel and we have to set the
// RASEO2_UseGlobalDeviceSettings flag in dwfOptions2.
//
if (OS_NT51) { ((LPRASENTRY_V501)preBuffer)->dwfOptions2 |= RASEO2_UseGlobalDeviceSettings; }
//
// We should have the devicename/devicetype by now.
// (PickModem should be called)
//
MYDBGASSERT(pArgs->szDeviceType[0]); MYDBGASSERT(pArgs->szDeviceName[0]);
lstrcpynU(preBuffer->szDeviceType, pArgs->szDeviceType, sizeof(preBuffer->szDeviceType)/sizeof(TCHAR)); lstrcpynU(preBuffer->szDeviceName, pArgs->szDeviceName, sizeof(preBuffer->szDeviceName)/sizeof(TCHAR)); } else { preBuffer->dwfOptions = RASEO_IpHeaderCompression | RASEO_RemoteDefaultGateway | RASEO_NetworkLogon | RASEO_SwCompression; //RASEO_SecureLocalFiles // NT 427042
//RASEO_DisableLcpExtensions
//
// Always set Modem lights on direct connection, unless HideTrayIcon
// flag is explicitly set in the .CMS. #262825, #262988
//
if (!(pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryHideTrayIcon))) { preBuffer->dwfOptions |= RASEO_ModemLights; } MYDBGASSERT(pArgs->szTunnelDeviceType[0]); MYDBGASSERT(pArgs->szTunnelDeviceName[0]);
lstrcpynU(preBuffer->szDeviceType, pArgs->szTunnelDeviceType, sizeof(preBuffer->szDeviceType)/sizeof(TCHAR)); lstrcpynU(preBuffer->szDeviceName, pArgs->szTunnelDeviceName, sizeof(preBuffer->szDeviceName)/sizeof(TCHAR));
lstrcpyU(preBuffer->szLocalPhoneNumber, pArgs->GetTunnelAddress()); }
//
// Check to see if we need to tell RAS that this connection has Internet Connectivity or not
//
if (OS_NT51) { //
// Note that we use the top level service profile on purpose here (pArgs->pIniService directly)
// as this is a profile global setting.
//
if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryInternetConnection, (BOOL) ((LPRASENTRY_V501)preBuffer)->dwfOptions2 & RASEO2_Internet)) { ((LPRASENTRY_V501)preBuffer)->dwfOptions2 |= RASEO2_Internet; } else { ((LPRASENTRY_V501)preBuffer)->dwfOptions2 &= ~RASEO2_Internet; } }
//
// If we have a specific DUN name to use, then
// use it instead of the default DUN setting in the .CMS.
//
if (pszDUN && *pszDUN) { pszDunEntry = CmStrCpyAlloc(pszDUN); } else { pszDunEntry = GetDefaultDunSettingName(piniService, fTunnelEntry); }
//
// If we have a DUN setting name, read the settings from cms
//
if (pszDunEntry && *pszDunEntry) { dwErr = (DWORD)ReadDUNSettings(pArgs, piniService->GetFile(), pszDunEntry, preBuffer, ppbEapData ,pdwEapSize, fTunnelEntry);
if (ERROR_SUCCESS != dwErr) { CMTRACE(TEXT("UpdateRASConnectoid: ReadDUNSettings failed")); CmFree(preBuffer); preBuffer = NULL; goto exit; } }
//
// Get autodial information, store in preBuffer
//
CopyAutoDial(preBuffer); //
// disable the RAS wizard on Win95
//
if (OS_W9X) { DisableWin95RasWizard(); }
exit: if (pszDunEntry) { CmFree(pszDunEntry); } SetLastError(dwErr);
return preBuffer; }
//+----------------------------------------------------------------------------
//
// Function CreateRasPrivatePbk
//
// Synopsis Create the private RAS phone book and returns the full path.
//
// Arguments pArgs Pointer to global Args struct
//
// Returns LPTSTR The full path name of the newly created private pbk
//
// History ??/??/97 henryt created
//
// 01/15/99 Jeffspr Changed the GetTempFileName pattern,
// as it was using more than the allowed/
// used 3 chars, plus made the failure
// case use the same pattern (we will
// filter on this in the connection
// enumerator to ignore these entries).
//
// 05/21/99 nickball Added allocation, removed input buf
// 04/10/00 quintinb Removed GetTempFileName as we no longer
// want this file to be temporary. Changed
// the function to create a file named _cmphone.pbk
// in the profile directory.
// Please see Whistler bug 15812 for details.
// 07/05/00 t-urama Changed the path to the hidden pbk to point
// to the RAS pbk.
//
//-----------------------------------------------------------------------------
LPTSTR CreateRasPrivatePbk(ArgsStruct *pArgs) { //
// No private PBK on win9x, everything is in the registry.
//
if (OS_W9X) { return NULL; }
if (NULL == pArgs) { MYDBGASSERT(pArgs); return NULL; }
LPTSTR pszHiddenPbkPath = NULL; LPCTSTR pszCmp = pArgs->piniProfile->GetFile();
//
// This version of the function uses the function GetPathToPbk in connect.cpp to find the path
// to the phone book. The hidden phone book also has to be created in the same directory.
//
if (pszCmp) { LPTSTR pszRasPbkDir = GetPathToPbk(pszCmp, pArgs); MYDBGASSERT(pszRasPbkDir);
if (pszRasPbkDir) { pszHiddenPbkPath = (LPTSTR) CmMalloc((lstrlen(pszRasPbkDir) + lstrlen(CM_PBK_FILTER_PREFIX) + 7) * sizeof(TCHAR));
if (pszHiddenPbkPath) { wsprintfU(pszHiddenPbkPath, TEXT("%s\\%sphone"), pszRasPbkDir, CM_PBK_FILTER_PREFIX); MYDBGASSERT(pszHiddenPbkPath); HANDLE hFile = INVALID_HANDLE_VALUE; hFile = CreateFileU(pszHiddenPbkPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { DWORD dwLastError = GetLastError(); MYDBGASSERT(hFile != INVALID_HANDLE_VALUE); CMTRACE1(TEXT("CreateRasPrivatePbk - CreateFileU failed. GetLastError = %d"), dwLastError); } else if (OS_NT5 && pArgs->fAllUser) { //
// Set the file permissions on the hidden pbk file so that everyone has write access to it.
//
MYVERIFY(AllowAccessToWorld(pszHiddenPbkPath)); }
CloseHandle(hFile); } else { CMASSERTMSG(FALSE, TEXT("CreateRasPrivatePbk -- CmMalloc returned NULL for pszHiddenPbkPath")); }
CmFree(pszRasPbkDir); } } return pszHiddenPbkPath; }
//+----------------------------------------------------------------------------
//
// Function GetPathToPbk
//
// Synopsis This function is a helper function called by
// CheckAccessToCmpAndPbk in connect.cpp and by
// CreateRasPrivatePbk. It returns the path to the RAS
// phonebook.
//
// Arguments LPTSTR pszCmp - The path to the cmp file
// LPTSTR pszRasPbk - The string to store the result
// ArgsStruct *pArgs - pArgs
//
// Returns NONE
//
// History 07/05/00 t-urama created
//-----------------------------------------------------------------------------
LPTSTR GetPathToPbk(LPCTSTR pszCmp, ArgsStruct *pArgs) { MYDBGASSERT(pArgs); if (NULL == pArgs) { return NULL; }
MYDBGASSERT(pszCmp); if (NULL == pszCmp) { return NULL; }
LPTSTR pszRasPbk = NULL;
//
// pszRasPbk could be NULL if we are on NT4 or we are using the
// all user default phonebook.
//
if (NULL == pArgs->pszRasPbk) { if (OS_NT4) { DWORD dwSize = (MAX_PATH + 1); DWORD dwRet; BOOL bExitLoop = TRUE;
do { pszRasPbk = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
if (pszRasPbk) { dwRet = GetSystemDirectoryU(pszRasPbk, dwSize); if (dwRet) { if (dwRet > dwSize) { dwSize = dwRet + 1; bExitLoop = FALSE; // we didn't get all of the string, try again
CmFree(pszRasPbk); } else { bExitLoop = TRUE; CmStrCatAlloc(&pszRasPbk, c_pszRasDirRas); } } else { CmFree(pszRasPbk); pszRasPbk = NULL; } } else { CMASSERTMSG(FALSE, TEXT("GetPathToPbk -- CmMalloc failed!")); return NULL; } } while (!bExitLoop); } else { pszRasPbk = CmStrCpyAlloc(pszCmp);
if (pszRasPbk) { LPTSTR pszSlash = CmStrrchr(pszRasPbk, TEXT('\\')); if (pszSlash) { *pszSlash = TEXT('\0'); // remove <shortservicename>.cmp
pszSlash = CmStrrchr(pszRasPbk, TEXT('\\'));
if (pszSlash) { *pszSlash = TEXT('\0');
CmStrCatAlloc(&pszRasPbk, TEXT("\\")); CmStrCatAlloc(&pszRasPbk, c_pszPbk); } else { CMASSERTMSG(FALSE, TEXT("GetPathToPbk -- unable to convert cmp path to pbk path.")); CmFree(pszRasPbk); pszRasPbk = NULL; }
} else { CMASSERTMSG(FALSE, TEXT("GetPathToPbk -- unable to convert cmp path to pbk path!")); CmFree(pszRasPbk); pszRasPbk = NULL; } } } } else { pszRasPbk = CmStrCpyAlloc(pArgs->pszRasPbk); LPTSTR pszSlash = CmStrrchr(pszRasPbk, TEXT('\\')); if (pszSlash) { *pszSlash = TEXT('\0'); // remove the RAS phonebook name
} else { CMASSERTMSG(FALSE, TEXT("GetPathToPbk -- unable to convert RAS pbk name to pbk path!")); CmFree(pszRasPbk); pszRasPbk = NULL; } }
return pszRasPbk; }
//+----------------------------------------------------------------------------
//
// Function DisableWin95RasWizard
//
// Synopsis This function disable the Win95 Dial-up Networking wizard
// by writing a dword reg value 0x00000080 in the registry.
//
// Arguments NONE
//
// Returns NONE
//
// History 7/1/97 henryt created
//-----------------------------------------------------------------------------
void DisableWin95RasWizard( void) { HKEY hkReg = NULL; LONG lRes; DWORD dwSize; DWORD dwType; DWORD dwValue;
lRes = RegOpenKeyExA(HKEY_CURRENT_USER, c_pszRegRemoteAccess, 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkReg);
if (ERROR_SUCCESS != lRes) { CMTRACE1(TEXT("DisableWin95RasWizard() RegOpenKeyEx() failed, GLE=%u."), lRes); goto exit; } //
// see if we already have a value there.
//
dwSize = sizeof(DWORD); lRes = RegQueryValueExA(hkReg, c_pszRegWizard, NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
if (lRes == ERROR_SUCCESS && dwSize == sizeof(DWORD) && dwType == REG_BINARY && dwValue == ICM_RAS_REG_WIZARD_VALUE) { CMTRACE(TEXT("DisableWin95RasWizard() RegQueryValueEx() - found correct value.")); goto exit; } //
// well, the value is not in reg yet. we need to create the value.
//
dwValue = ICM_RAS_REG_WIZARD_VALUE; lRes = RegSetValueExA(hkReg, c_pszRegWizard, 0, REG_BINARY, (LPBYTE)&dwValue, sizeof(dwValue)); #ifdef DEBUG
if (ERROR_SUCCESS != lRes) { CMTRACE1(TEXT("DisableWin95RasWizard() RegSetValueEx() failed, GLE=%u."), lRes); } #endif
exit:
if (hkReg) { lRes = RegCloseKey(hkReg);
#ifdef DEBUG
if (ERROR_SUCCESS != lRes) { CMTRACE1(TEXT("DisableWin95RasWizard() RegCloseKey() failed, GLE=%u."), lRes); } #endif
} return; }
//+----------------------------------------------------------------------------
//
// Function SetIsdnDualChannelEntries
//
// Synopsis As what the func name says. We prepare the RASENTRY and
// RASSUBENTRY properly. We don't actually make RAS calls to
// save the entries. We'll leave it to the caller(so that the
// can make other changes to the structs for other reasons and
// commit the changes in 1 or 2 RAS calls).
//
// Arguments pArgs [IN] Pointer to ArgsStruct
// pRasEntry [IN/OUT] rasentry to be filled
// ppRasSubEntry [OUT] pointer to be filled with the subentry array
// The buffer is allocated in this function.
// pdwSubEntryCount Number of subentries allocated.
//
// Returns BOOL TRUE = success, FALSE = failure.
//
//-----------------------------------------------------------------------------
BOOL SetIsdnDualChannelEntries(ArgsStruct *pArgs, LPRASENTRY pRasEntry, LPRASSUBENTRY *ppRasSubEntry, PDWORD pdwSubEntryCount) { //
// Lets check the input parameters
//
MYDBGASSERT(pArgs); MYDBGASSERT(pRasEntry); MYDBGASSERT(ppRasSubEntry); MYDBGASSERT(pdwSubEntryCount); if ((NULL == pArgs) || (NULL == pRasEntry) || (NULL == ppRasSubEntry) || (NULL == pdwSubEntryCount)) { return FALSE; } //
// Since we don't support BAP if they called this function they must have wanted
// to do DualChannel ISDN. If the dial mode isn't set for dual channel, we will
// assert an continue. Better to connect the user in dual channel mode then not
// at all if they have a misconfigured profile.
//
MYDBGASSERT(pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL);
//
// Check the size of the passed in RasEntry struct. If it isn't at least
// a 4.01 size struct, then return.
//
MYDBGASSERT(pRasEntry->dwSize >= sizeof(LPRASENTRY_V401)); if (sizeof(LPRASENTRY_V401) > pRasEntry->dwSize) { return FALSE; }
LPRASENTRY_V401 pRasEntry401 = (LPRASENTRY_V401)pRasEntry;
//
// set isdn dial mode to dial both channels
//
pRasEntry401->dwDialMode = RASEDM_DialAll; CMTRACE(TEXT("ISDN Dual Channel Mode On"));
if (OS_NT) { *pdwSubEntryCount = 2; } else if (OS_MIL) { // 112351: 9x only requires one sub entry. We'll keep the device name the same.
// In this case, Win9x will work as follows:
// for the 1st channel, the device name provided works fine.
// for the 2nd channel, 9x sees the device is in use and looks for the
// the closest match (which is the 2nd channel).
//
*pdwSubEntryCount = 1; } else { CMASSERTMSG(FALSE, TEXT("SetIsdnDualChannelEntries -- Function called on a platform other than NT or Millennium.")); return FALSE; }
//
// Allocate the sub entries
//
*ppRasSubEntry = (LPRASSUBENTRY)CmMalloc((*pdwSubEntryCount)*(sizeof(RASSUBENTRY)));
if (NULL == *ppRasSubEntry) { CMASSERTMSG(FALSE, TEXT("SetIsdnDualChannelEntries -- CmMalloc failed to alloc ppRasSubEntry.")); return FALSE; }
//
// Fill in the sub entries with the device and phonenumber information
//
for (DWORD dwIndex=0; dwIndex < (*pdwSubEntryCount); dwIndex++) { (*ppRasSubEntry)[dwIndex].dwSize = sizeof(RASSUBENTRY); lstrcpyU((*ppRasSubEntry)[dwIndex].szDeviceType, pArgs->szDeviceType); lstrcpyU((*ppRasSubEntry)[dwIndex].szDeviceName, pArgs->szDeviceName); lstrcpyU((*ppRasSubEntry)[dwIndex].szLocalPhoneNumber, pRasEntry401->szLocalPhoneNumber); } return TRUE; }
//
// Keep in case we ever want to support BAP
//
/*
BOOL SetIsdnDualChannelEntries( ArgsStruct *pArgs, LPRASENTRY pre, LPRASSUBENTRY *prgrse, PDWORD pdwSubEntryCount ) { LPRASENTRY_V401 pre401;
MYDBGASSERT(pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL);
MYDBGASSERT(pre->dwSize >= sizeof(LPRASENTRY_V401)); pre401 = (LPRASENTRY_V401)pre;
//
// set isdn dial mode
//
if (pArgs->dwIsdnDialMode == CM_ISDN_MODE_DIALALL) { //
// dial both channels
//
pre401->dwDialMode = RASEDM_DialAll; CMTRACE(TEXT("ISDN Dual Channel Mode On")); } else { //
// dial 2nd channel on demand
//
//
// First get the 4 thresholds
//
if (!pArgs->dwDialExtraPercent) { pArgs->dwDialExtraPercent = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDialExtraPercent, DEFAULT_DIALEXTRAPERCENT); if (pArgs->dwDialExtraPercent < 0 || pArgs->dwDialExtraPercent > 100) { pArgs->dwDialExtraPercent = DEFAULT_DIALEXTRAPERCENT; } } if (!pArgs->dwDialExtraSampleSeconds) { pArgs->dwDialExtraSampleSeconds = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDialExtraSampleSeconds, DEFAULT_DIALEXTRASAMPLESECONDS); if (pArgs->dwDialExtraSampleSeconds < 0) { pArgs->dwDialExtraSampleSeconds = DEFAULT_DIALEXTRASAMPLESECONDS; } } if (!pArgs->dwHangUpExtraPercent) { pArgs->dwHangUpExtraPercent = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryHangUpExtraPercent, DEFAULT_HANGUPEXTRAPERCENT); if (pArgs->dwHangUpExtraPercent < 0 || pArgs->dwHangUpExtraPercent > 100) { pArgs->dwHangUpExtraPercent = DEFAULT_HANGUPEXTRAPERCENT; } } if (!pArgs->dwHangUpExtraSampleSeconds) { pArgs->dwHangUpExtraSampleSeconds = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryHangUpExtraSampleSeconds, DEFAULT_HANGUPEXTRASAMPLESECONDS); if (pArgs->dwHangUpExtraSampleSeconds < 0) { pArgs->dwHangUpExtraSampleSeconds = DEFAULT_HANGUPEXTRASAMPLESECONDS; } }
//
// set multilink info
//
pre401->dwDialMode = RASEDM_DialAsNeeded;
pre401->dwDialExtraPercent = pArgs->dwDialExtraPercent; pre401->dwDialExtraSampleSeconds = pArgs->dwDialExtraSampleSeconds; pre401->dwHangUpExtraPercent = pArgs->dwHangUpExtraPercent; pre401->dwHangUpExtraSampleSeconds = pArgs->dwHangUpExtraSampleSeconds;
CMTRACE2(TEXT("ISDN 2nd Channel Dial On Demand: dial extra %u%%, dial extra %u sample secs"), pre401->dwDialExtraPercent, pre401->dwDialExtraSampleSeconds);
CMTRACE2(TEXT("\t\thangup extra %u%%, hangup extra %u sample secs"), pre401->dwHangUpExtraPercent, pre401->dwHangUpExtraSampleSeconds); }
if (OS_NT) { if (!(*prgrse = (LPRASSUBENTRY)CmMalloc(2*sizeof(RASSUBENTRY)))) { CMTRACE(TEXT("SetIsdnDualChannelEntries failed to alloc a ras sub entry")); return FALSE; } ZeroMemory((PVOID)*prgrse, 2*sizeof(RASSUBENTRY));
//
// first channel
//
(*prgrse)[0].dwSize = sizeof(RASSUBENTRY); lstrcpyU((*prgrse)[0].szDeviceType, pArgs->szDeviceType); lstrcpyU((*prgrse)[0].szDeviceName, pArgs->szDeviceName); lstrcpyU((*prgrse)[0].szLocalPhoneNumber, pre401->szLocalPhoneNumber);
//
// the 2nd channel is identical
//
CopyMemory((PVOID)(*prgrse + 1), (PVOID)*prgrse, sizeof(RASSUBENTRY));
*pdwSubEntryCount = 2; } else { MYDBGASSERT(OS_MIL);
CMTRACE(TEXT("doing the Millennium subentry stuff"));
// 112351: 9x only requires one sub entry. We'll keep the device name the same.
// In this case, Win9x will work as follows:
// for the 1st channel, the device name provided works fine.
// for the 2nd channel, 9x sees the device is in use and looks for the
// the closest match (which is the 2nd channel).
//
if (!(*prgrse = (LPRASSUBENTRY)CmMalloc(1*sizeof(RASSUBENTRY)))) { CMTRACE(TEXT("SetIsdnDualChannelEntries failed to alloc a ras sub entry")); return FALSE; }
ZeroMemory((PVOID)*prgrse, 1*sizeof(RASSUBENTRY));
//
// 2nd channel
//
(*prgrse)[0].dwSize = sizeof(RASSUBENTRY); lstrcpyU((*prgrse)[0].szDeviceType, pArgs->szDeviceType); lstrcpyU((*prgrse)[0].szDeviceName, pArgs->szDeviceName); lstrcpyU((*prgrse)[0].szLocalPhoneNumber, pre401->szLocalPhoneNumber);
*pdwSubEntryCount = 1; } return TRUE; } */
//+----------------------------------------------------------------------------
//
// Function SetNtIdleDisconnectInRasEntry
//
// Synopsis As what the func name says. We prepare the RASENTRY and
// RASSUBENTRY properly. We don't actually make RAS calls to
// save the entries. We'll leave it to the caller(so that the
// can make other changes to the structs for other reasons and
// commit the changes in 1 or 2 RAS calls).
//
// Arguments pArgs [IN] Pointer to ArgsStruct
// pre [OUT] Pointer to RASENTRY with the correct size
//
// Returns BOOL TRUE = success, FALSE = failure.
//
//-----------------------------------------------------------------------------
BOOL SetNtIdleDisconnectInRasEntry( ArgsStruct *pArgs, LPRASENTRY pre ) { if (!OS_NT4) { return FALSE; } if ((NULL == pArgs) || (NULL == pre) || (pre->dwSize < sizeof(LPRASENTRY_V401))) { CMASSERTMSG(FALSE, TEXT("SetNtIdleDisconnectInRasEntry -- Invalid parameter")); return FALSE; }
//
// If idle-disconnect is enabled, use the options value otherwise
// pArgs->dwIdleTimeout is in minutes. Note that 0xFFFFFFFF means
// no idle disconnect to RAS but 0 is the value we use to mean never
// idle disconnect in the CMS.
//
DWORD dwIdle = (pArgs->dwIdleTimeout * 60);
if (0 == dwIdle) { dwIdle = (DWORD)-1; }
((LPRASENTRY_V401 )pre)->dwIdleDisconnectSeconds = dwIdle;
CMTRACE1(TEXT("SetNtIdleDisconnect: current idle Timeout is %u seconds."), dwIdle);
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: DisableSystemIdleDisconnect
//
// Synopsis: This function sets the idle timeout value of a RAS connection to
// be disabled.
//
// Arguments: LPRASENTRY pre - pointer to a RASENTRY to disable idle disconnect for
//
// Returns: BOOL TRUE = success, FALSE = failure.
//
//-----------------------------------------------------------------------------
BOOL DisableSystemIdleDisconnect(LPRASENTRY pre) { if ((NULL == pre) || (pre->dwSize < sizeof(LPRASENTRY_V401))) { CMASSERTMSG(FALSE, TEXT("DisableSystemIdleDisconnect -- Invalid parameter")); return FALSE; }
//
// Set the idle time to 0xFFFFFFFF which means no idle disconnect to RAS
//
((LPRASENTRY_V401 )pre)->dwIdleDisconnectSeconds = (DWORD)-1;
CMTRACE(TEXT("DisableSystemIdleDisconnect -- System Idle disconnect disabled"));
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function RasDialFunc2
//
// Synopsis A RAS callback type 2 for RasDial.
//
// Arguments
// ULONG_PTR dwCallbackId,// user-defined value specified in RasDial
// DWORD dwSubEntry, // subentry index in multilink connection
// HRASCONN hrasconn, // handle to RAS connection
// UINT unMsg, // type of event that has occurred
// RASCONNSTATE rascs, // connection state about to be entered
// DWORD dwError, // error that may have occurred
// DWORD dwExtendedError // extended error information for some errors
//
// Returns LPRASENTRY - pointer to the RASENTRY structure allocated
//
//-----------------------------------------------------------------------------
DWORD WINAPI RasDialFunc2( ULONG_PTR dwCallbackId, // user-defined value specified in RasDial
DWORD dwSubEntry, // subentry index in multilink connection
HRASCONN hrasconn, // handle to RAS connection
UINT unMsg, // type of event that has occurred
RASCONNSTATE rascs, // connection state about to be entered
DWORD dwError, // error that may have occurred
DWORD dwExtendedError // extended error information for some errors
) { CMTRACE2(TEXT("RasDialFunc2(): dwSubentry=%u. dwErr=0x%x"), dwSubEntry, dwError); CMTRACE2(TEXT("RasDialFunc2(): dwExtendedErr=0x%x, rascs=%u"), dwExtendedError, rascs);
MYDBGASSERT(dwCallbackId);
if (dwCallbackId) { ArgsStruct *pArgs = (ArgsStruct *) dwCallbackId; pArgs->dwRasSubEntry = dwSubEntry;
//CMTRACE1(TEXT("RasDialFunc2(): pArgs->lInConnectOrCancel=%d"),pArgs->lInConnectOrCancel);
//CMASSERTMSG((NOT_IN_CONNECT_OR_CANCEL == pArgs->lInConnectOrCancel),
// TEXT("RasDialFunc2 - RasDial mutex is NOT NULL..."));
SendMessage(pArgs->hwndMainDlg, pArgs->uMsgId, rascs, dwError); }
return 1; }
//+----------------------------------------------------------------------------
//
// Function: SetRasDialExtensions
//
// Synopsis: Encapsulates initialization and configuration of the
// RasDialExtensions that we use on NT.
//
// Arguments: pArgs - Ptr to global args struct
// fEnablePausedStates - Use Paused states or not
// fEnableCustomScripting - whether to use custom scripting or not
//
// Returns: DWORD - Error code
//
// History: nickball Created 7/22/99
//
//+----------------------------------------------------------------------------
DWORD SetRasDialExtensions(ArgsStruct* pArgs, BOOL fEnablePausedStates, BOOL fEnableCustomScripting) { DWORD dwRes = ERROR_SUCCESS;
MYDBGASSERT(pArgs); if (NULL == pArgs) { return ERROR_INVALID_PARAMETER; }
//
// If not already allocated, we need a RasDialExtensions struct
//
if (!pArgs->pRasDialExtensions) { pArgs->pRasDialExtensions = AllocateAndInitRasDialExtensions();
if (!pArgs->pRasDialExtensions) { dwRes = ERROR_NOT_ENOUGH_MEMORY; } } else { dwRes = InitRasDialExtensions(pArgs->pRasDialExtensions); }
if (ERROR_SUCCESS != dwRes) { goto SetRasDialExtensionsExit; }
//
// Turn on PauseStates for NT
//
if (fEnablePausedStates) { pArgs->pRasDialExtensions->dwfOptions |= RDEOPT_PausedStates; }
//
// Turn on custom scripting if we are running on Whistler+ and the caller
// asked for it.
//
if (fEnableCustomScripting && OS_NT51) { pArgs->pRasDialExtensions->dwfOptions |= RDEOPT_UseCustomScripting; }
//
// RDEOPT_NoUser is required for the WinLogon credential case,
// which we identify by the presence of either lpEapLogonInfo
// or lpRasNoUser. Note that the if statement below is somewhat redundant
// since we should have CM_LOGON_TYPE_WINLOGON set if we get either a NoUser
// struct or an EapLogonInfo struct. However, wanted to point out that on Win2k
// one of the first two will always be true and on Whistler the first two may be
// false but the third true (RAS now sends a flag to tell us when we are at WinLogon on
// whistler as there are Ctrl-Alt-Del with SmartCard cases where it sends neither struct).
//
if (pArgs->lpEapLogonInfo || pArgs->lpRasNoUser || (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType)) { pArgs->pRasDialExtensions->dwfOptions |= RDEOPT_NoUser; }
//
// If the modem speaker is turned off, makes sure that we
// disable it explicitly in RAS, otherwise it will use
// its default and turn the speaker on. These settings
// should be ignored by RAS in the tunnel case.
//
if (pArgs->tlsTapiLink.bModemSpeakerOff) { pArgs->pRasDialExtensions->dwfOptions |= RDEOPT_IgnoreModemSpeaker; pArgs->pRasDialExtensions->dwfOptions &= ~RDEOPT_SetModemSpeaker; }
SetRasDialExtensionsExit:
return dwRes; }
//+----------------------------------------------------------------------------
//
// Function: InitRasDialExtensions
//
// Synopsis: Flushes a previously allocated RasDialExtensions buffer and sets
// size, options for re-use.
//
// Arguments: LPRASDIALEXTENSIONS - Ptr to allocated struct with size set.
//
// Returns: DWORD - Error code
//
// History: nickball Created 5/22/99
//
//+----------------------------------------------------------------------------
DWORD InitRasDialExtensions(LPRASDIALEXTENSIONS lpRasDialExtensions) { MYDBGASSERT(lpRasDialExtensions);
if (NULL == lpRasDialExtensions) { return ERROR_INVALID_PARAMETER; }
//
// First, we determine the size
//
DWORD dwSize = OS_NT5 ? sizeof(RASDIALEXTENSIONS_V500) : sizeof(RASDIALEXTENSIONS);
//
// Flush buffer and reset size.
//
ZeroMemory(lpRasDialExtensions, dwSize);
lpRasDialExtensions->dwSize = dwSize;
//
// Set customdial if needed
//
if (dwSize == sizeof(RASDIALEXTENSIONS_V500)) { //
// Set the CustomDial flag for NT5. We don't set this on NT4
// and 9X as a precaution because the falg isn't defined.
//
lpRasDialExtensions->dwfOptions |= RDEOPT_CustomDial; }
CMTRACE1(TEXT("InitRasDialExtensions() - dwSize is %u"), dwSize);
return ERROR_SUCCESS; }
//+----------------------------------------------------------------------------
//
// Function: AllocateAndInitRasDialExtensions
//
// Synopsis: Encapsulates the allocation of a RASEXTENSION based upon the OS
//
// Arguments: None
//
// Returns: LPRASDIALEXTENSIONS - Ptr to allocated struct with size set.
//
// History: nickball Created 5/13/99
//
//+----------------------------------------------------------------------------
LPRASDIALEXTENSIONS AllocateAndInitRasDialExtensions() { //
// Allocate struct and pre-fill as appropriate
//
LPRASDIALEXTENSIONS prdeNew = (LPRASDIALEXTENSIONS)CmMalloc(OS_NT5 ? sizeof(RASDIALEXTENSIONS_V500) : sizeof(RASDIALEXTENSIONS));
if (!prdeNew) { CMTRACE(TEXT("AllocateAndInitRasDialExtensions: failed to alloc RasDialExtension buffer")); return NULL; } InitRasDialExtensions(prdeNew);
return prdeNew; }
//+----------------------------------------------------------------------------
//
// Function: InitRasDialParams
//
// Synopsis: Flushes a previously allocated RasDialParams buffer and sets
// size, options for re-use.
//
// Arguments: LPRASDIALPARAMS - Ptr to allocated struct with size set.
//
// Returns: DWORD - Error code
//
// History: nickball Created 5/22/99
//
//+----------------------------------------------------------------------------
DWORD InitRasDialParams(LPRASDIALPARAMS lpRasDialParams) { MYDBGASSERT(lpRasDialParams);
if (NULL == lpRasDialParams) { return ERROR_INVALID_PARAMETER; }
//
// First, we determine the size
//
DWORD dwSize = OS_NT ? sizeof(RASDIALPARAMS_V401) : sizeof(RASDIALPARAMS);
//
// Flush buffer and reset size.
//
ZeroMemory(lpRasDialParams, dwSize);
lpRasDialParams->dwSize = dwSize;
CMTRACE1(TEXT("InitRasDialParams() - dwSize is %u"), dwSize);
return ERROR_SUCCESS; }
//+----------------------------------------------------------------------------
//
// Function: AllocateAndInitRasDialParams
//
// Synopsis: Encapsulates the allocation of a RASDIALPARAMS based upon the OS
//
// Arguments: None
//
// Returns: LPRASDIALPARAMS - Ptr to allocated struct with size set.
//
// History: nickball Created 5/22/99
//
//+----------------------------------------------------------------------------
LPRASDIALPARAMS AllocateAndInitRasDialParams() { //
// Allocate struct and pre-fill as appropriate
//
LPRASDIALPARAMS prdpNew = (LPRASDIALPARAMS)CmMalloc(OS_NT ? sizeof(RASDIALPARAMS_V401) : sizeof(RASDIALPARAMS));
if (!prdpNew) { CMTRACE(TEXT("AllocateRasDialParams: failed to alloc RasDialParams buffer")); return NULL; } InitRasDialParams(prdpNew);
return prdpNew; }
//+----------------------------------------------------------------------------
//
// Function: AllocateRasEntry
//
// Synopsis: Encapsulates the allocation of a RASENTRY struct based upon the OS
//
// Arguments: None
//
// Returns: LPRASENTRY - Ptr to allocated struct with size set.
//
// History: nickball Created Header 5/13/99
//
//+----------------------------------------------------------------------------
LPRASENTRY AllocateRasEntry() { static DWORD s_dwRasEntrySize = -1;
//
// first, we determine the size
//
if (s_dwRasEntrySize == -1) { if (OS_NT51) { //
// Whistler
//
s_dwRasEntrySize = sizeof(RASENTRY_V501); } else if (OS_W2K) { //
// nt5
//
s_dwRasEntrySize = sizeof(RASENTRY_V500); } else if (OS_MIL || OS_NT4) { //
// Millennium uses the NT4 structure
//
s_dwRasEntrySize = sizeof(RASENTRY_V401); } else { //
// win9x
//
s_dwRasEntrySize = sizeof(RASENTRY); } }
//
// add 512 bytes since a rasentry can contain alternate phone #'s
// See RASENTRY.dwAlternateOffset
//
LPRASENTRY preNew = (LPRASENTRY)CmMalloc(s_dwRasEntrySize+512);
if (!preNew) { CMTRACE(TEXT("AllocateRasEntry: failed to alloc rasentry buffer")); return NULL; } preNew->dwSize = s_dwRasEntrySize; if (s_dwRasEntrySize >= sizeof(RASENTRY_V500)) { ((LPRASENTRY_V500)preNew)->dwType = RASET_Internet; //
// For NT5, set szCustomDialDll with our Module name. This ensures that our
// custom DialDlg, DialEntry, and Hangup routines will be called by RAS for
// operations on our connectoid. We don't want to tie our path to anything
// machine specific, so we'll use the %windir% environment string.
//
lstrcpyU(((LPRASENTRY_V500)preNew)->szCustomDialDll, c_pszCmDialPath); }
CMTRACE1(TEXT("AllocateRasEntry() - s_dwRasEntrySize is %u"), s_dwRasEntrySize);
return preNew; }
#if 0
/*
//+----------------------------------------------------------------------------
//
// Function: GetRasSystemPhoneBookPath
//
// Synopsis: Builds the conventional path to the RAS system phonebook
//
// Arguments: None
//
// Returns: LPTSTR - The phonebook path
//
// History: nickball Created 8/14/98
//
//+----------------------------------------------------------------------------
LPTSTR GetRasSystemPhoneBookPath() { MYDBGASSERT(OS_NT); TCHAR szTemp[MAX_PATH+1];
GetSystemDirectoryU(szTemp,sizeof(szTemp)); lstrcatU(szTemp, c_pszRasDirRas); lstrcatU(szTemp, c_pszRasPhonePbk); return CmStrCpyAlloc(szTemp); }
//+---------------------------------------------------------------------------
//
// Function: InitDefaultRasPhoneBook
//
// Synopsis: Special case Helper function ensures that there is a default
// ras phonebook when running on NT. We simply attempt to create
// the file which fails if the file already exists, or creates
// an empty file if it does not.
//
// Arguments: None
//
// Returns: Nothing
//
// History: a-nichb - 4/30/97 Created
// VetriV 5/21/97 Changed code to call GetOSVersion()
// instead of using pArgs->dwPlatformID
// for bug #4700
// nickball ??/??/98 Removed as we no longer call RasValidateEntry
// which introduced the requirement of having at
// least an empty phonebook for the API to work.
//
//----------------------------------------------------------------------------
void InitDefaultRasPhoneBook() { //
// NT only. Create empty system phonebook if none exists
//
if (OS_NT) { LPTSTR pszSystemPbk = GetRasSystemPhoneBookPath();
if (pszSystemPbk) { //
// Try to create the phonebook, fails if file already exists
//
HANDLE hInf = CreateFileU(pszSystemPbk, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hInf != INVALID_HANDLE_VALUE) { CloseHandle(hInf); } } CmFree(pszSystemPbk); } } */ #endif
//+----------------------------------------------------------------------------
//
// Function: GetRasPbkFromNT5ProfilePath
//
// Synopsis: Helper function to manufacture a RAS phonebook path from
// a .CMP file path on NT5
//
// Arguments: LPCTSTR pszProfile - The full path to a profile .CMP file.
//
// Returns: LPTSTR - The new phonebook path. NULL on failure
//
// History: nickball Created 8/13/98
//
//+----------------------------------------------------------------------------
LPTSTR GetRasPbkFromNT5ProfilePath(LPCTSTR pszProfile) { MYDBGASSERT(OS_NT5); MYDBGASSERT(pszProfile);
if (NULL == pszProfile) { return NULL; }
//
// We will deduce the phonebook path from our current profile location.
//
LPTSTR pszRasPhonePath = (LPTSTR) CmMalloc(MAX_PATH + 1); MYDBGASSERT(pszRasPhonePath);
if (pszRasPhonePath) { //
// Strip .CMP file name and parent directory
//
LPTSTR pszDir = CmStripFileName(pszProfile, FALSE); MYDBGASSERT(pszDir); if (pszDir) { LPTSTR pszTmp = CmStrrchr(pszDir, TEXT('\\')); MYDBGASSERT(pszTmp);
if (pszTmp) {
*pszTmp = 0; //
// Append \\pbk\\rasphone.pbk
//
lstrcpyU(pszRasPhonePath, pszDir); lstrcatU(pszRasPhonePath, TEXT("\\")); lstrcatU(pszRasPhonePath, c_pszPbk); lstrcatU(pszRasPhonePath, c_pszRasPhonePbk); } CmFree(pszDir); } else { CmFree(pszRasPhonePath); } }
return pszRasPhonePath; }
#define MAX_BLOB_CHARS_PER_LINE 128
//+----------------------------------------------------------------------------
//
// Function: ReadDunSettingsEapData
//
// Synopsis: Retrieves DUN setting for EAP config (opaque blob) data. The
// entry may span several lines and contain several EAP data blocks.
//
// Arguments: CIni *pIni - Ptr to ini object to be used.
// LPBYTE* ppbEapData - Address of pointer to store EapData, allocated here.
// LPDWORD pdwEapSize - Ptr to a DWORD to record the size of the data blob.
// DWORD dwCustomAuthKey - The EAP type that we are interested in.
// LPBYTE* ppbEapStruct - [OUT] used for returning the whole
// EAP_CUSTOM_DATA structure. Can be NULL.
// DWORD* pdwEapStructSize - [OUT] used for returning the size of the
// EAP_CUSTOM_DATA structure. Can be NULL.
//
// Returns: TRUE on success
//
// Note: CM expects blob data to be provided in numbered entries such as:
// CustomAuthData0=, CustomAuthData1=, CustomAuthData2=, etc.
//
// History: nickball Created 08/24/98
// nickball Handle multiple EAP data blocks in blob. 09/11/99
//
//+----------------------------------------------------------------------------
BOOL ReadDunSettingsEapData(CIni *pIni, LPBYTE* ppbEapData, LPDWORD pdwEapSize, const DWORD dwCustomAuthKey, LPBYTE* ppbEapStruct, LPDWORD pdwEapStructSize) { CHAR *pchBuf = NULL; CHAR szTmp[MAX_BLOB_CHARS_PER_LINE + 2]; CHAR szEntry[128]; int nLine = -1; int nRead = -1; int nTotal = 0;
LPBYTE pbEapBytes = NULL; DWORD cbEapBytes = 0;
MYDBGASSERT(pIni); MYDBGASSERT(ppbEapData); MYDBGASSERT(pdwEapSize);
//
// ppbEapStruct && pdwEapStructSize are allowed to be NULL, so if you need to use them, check for NULL first
//
if (NULL == pIni || NULL == ppbEapData || NULL == pdwEapSize) { return FALSE; }
if (ppbEapStruct) { *ppbEapStruct = NULL; }
if (pdwEapStructSize) { *pdwEapStructSize = 0; }
//
// First get the section (it should include &) then the entry.
//
BOOL bRet = FALSE; LPWSTR pszLoadSection = pIni->LoadSection(c_pszCmSectionDunServer); LPSTR pszSection = WzToSzWithAlloc(pszLoadSection); LPSTR pszFile = WzToSzWithAlloc(pIni->GetFile());
if (!pszLoadSection || !pszSection || !pszFile) { bRet = FALSE; goto exit; }
//
// Read numbered entries until there are no more.
// Note: RAS blob doesn't exceed 64 chars, but can wrap over multiple lines
//
while (nRead) { //
// Read CustomAuthDataX where X is the number of entries
//
nLine++; wsprintfA(szEntry, "%s%d", c_pszCmEntryDunServerCustomAuthData, nLine);
nRead = GetPrivateProfileStringA(pszSection, szEntry, "", szTmp, sizeof(szTmp), pszFile);
if (nRead) { //
// If line exceeded 64 chars, it is considered corrupt
//
if (MAX_BLOB_CHARS_PER_LINE < nRead) { nTotal = 0; break; }
//
// Update our local master buffer with the latest fragment
//
if (nLine) { pchBuf = CmStrCatAllocA(&pchBuf, szTmp); } else { pchBuf = CmStrCpyAllocA(szTmp); }
if (!pchBuf) { bRet = FALSE; goto exit; }
nTotal += nRead; } }
//
// At this point we should have the entire entry in pchBuf in HEX format
// Convert the buffer to byte format and store in supplied EAP buffer.
//
if (nTotal && !(nTotal & 1)) { nTotal /= 2; // Only need half the hex char size
cbEapBytes = nTotal + 1; pbEapBytes = (BYTE *) CmMalloc(cbEapBytes);
if (!pbEapBytes) { goto exit; }
CHAR *pch = pchBuf; BYTE *pb = pbEapBytes;
while (*pch != '\0') { *pb = HexValue( *pch++ ) * 16; *pb += HexValue( *pch++ ); ++pb; }
//
// Now we have the bytes, locate and extract the data block that we
// are after. Note: Multiple blocks are arrayed using the following
// header:
//
// typedef struct _EAP_CUSTOM_DATA
// {
// DWORD dwSignature;
// DWORD dwCustomAuthKey;
// DWORD dwSize;
// BYTE abdata[1];
// } EAP_CUSTOM_DATA;
//
EAP_CUSTOM_DATA *pCustomData = (EAP_CUSTOM_DATA *) pbEapBytes;
while (((LPBYTE) pCustomData - pbEapBytes) < nTotal) { if (pCustomData->dwCustomAuthKey == dwCustomAuthKey) { //
// Bingo! We have a match, first make sure that the indicated
// size isn't pointing out into space, then make a copy and
// run for the hills.
//
if (((LPBYTE) pCustomData - pbEapBytes) + sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize > (DWORD) nTotal) { MYDBGASSERT(FALSE); goto exit; }
*ppbEapData = (BYTE *) CmMalloc(pCustomData->dwSize);
if (*ppbEapData) { CopyMemory(*ppbEapData, pCustomData->abdata, pCustomData->dwSize);
*pdwEapSize = pCustomData->dwSize; bRet = TRUE; goto exit; } }
//
// Locate the next data block
//
pCustomData = (EAP_CUSTOM_DATA *) ((LPBYTE) pCustomData + sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize); } }
exit: if (bRet && ppbEapStruct && pdwEapStructSize) { *ppbEapStruct = pbEapBytes; *pdwEapStructSize = cbEapBytes; } else { CmFree(pbEapBytes); } CmFree(pchBuf); CmFree(pszLoadSection); CmFree(pszSection); CmFree(pszFile);
return bRet; }
//+----------------------------------------------------------------------------
//
// Function: ReadDUNSettings
//
// Synopsis: Reads the DUN settings for the specified DUN name and .CMS file
// into a RASENTRY structure. Because some settings are not supported
// on downlevel platforms, this function will potentially display an
// error message to the user.
//
// Arguments: ArgsStruct *pArgs - Ptr to global args struct.
// LPCSTR pszFile - Full path to the .CMS file.
// LPCTSTR pszDunName - The DUN name for the settings.
// LPVOID pvBuffer - Ptr to RASENTRY buffer.
// LPBYTE* ppbEapData - Address of pointer to store EapData
// LPDWORD pdwEapSize - Ptr to a DWORD to record the size of the data blob.
// BOOL fTunnel - are we reading tunnel settings?
//
// Returns: ERROR_SUCCESS on success. Use GetLastError for failure details.
//
// Note: This was formerly the PhoneBookReadDun API in CMPBK.DLL
//
// History: nickball 8/22/98 Created Header
// nickball 02/03/99 Added pArgs :( in order to have access to the
// the top-level service for path conversion.
//
//+----------------------------------------------------------------------------
LRESULT ReadDUNSettings(ArgsStruct *pArgs, LPCTSTR pszFile, LPCTSTR pszDunName, LPVOID pvBuffer, LPBYTE* ppbEapData, LPDWORD pdwEapSize, BOOL fTunnel) { MYDBGASSERT(pszFile); MYDBGASSERT(pszDunName); MYDBGASSERT(pvBuffer);
if (NULL == pszFile || NULL == pszDunName || NULL == pvBuffer) { return (ERROR_INVALID_PARAMETER); }
CMTRACE1(TEXT("ReadDUNSettings -- using DUN setting: %s"), pszDunName); RASENTRYW *preRas = (RASENTRYW *) pvBuffer;
//
// Setup INI object. Prepend pszDunName with "&" for section.
//
CIni iniFile(g_hInst, pszFile); LPTSTR pszSection = CmStrCpyAlloc(TEXT("&")); pszSection = CmStrCatAlloc(&pszSection, pszDunName); iniFile.SetSection(pszSection); CmFree(pszSection);
//
// Get and apply the Phone section entries
//
if (iniFile.GPPB(c_pszCmSectionDunPhone, c_pszCmEntryDunPhoneDialAsIs)) { preRas->dwfOptions &= ~RASEO_UseCountryAndAreaCodes; } CopyGPPS(&iniFile, c_pszCmSectionDunPhone, c_pszCmEntryDunPhonePhoneNumber, preRas->szLocalPhoneNumber, sizeof(preRas->szLocalPhoneNumber)/sizeof(TCHAR)); CopyGPPS(&iniFile,c_pszCmSectionDunPhone, c_pszCmEntryDunPhoneAreaCode, preRas->szAreaCode, sizeof(preRas->szAreaCode)/sizeof(TCHAR)); preRas->dwCountryCode = iniFile.GPPI(c_pszCmSectionDunPhone, c_pszCmEntryDunPhoneCountryCode, preRas->dwCountryCode); preRas->dwCountryID = iniFile.GPPI(c_pszCmSectionDunPhone, c_pszCmEntryDunPhoneCountryId, preRas->dwCountryID); //
// Get and apply the Device section entries
//
CopyGPPS(&iniFile,c_pszCmSectionDunDevice, c_pszCmEntryDunDeviceType, preRas->szDeviceType, sizeof(preRas->szDeviceType)/sizeof(TCHAR)); CopyGPPS(&iniFile,c_pszCmSectionDunDevice, c_pszCmEntryDunDeviceName, preRas->szDeviceName, sizeof(preRas->szDeviceName)/sizeof(TCHAR)); //
// Get and apply the Server section entries
//
LPTSTR pszTmp = iniFile.GPPS(c_pszCmSectionDunServer, c_pszCmEntryDunServerType); if (*pszTmp) { if (0 == lstrcmpiU(pszTmp, c_pszDunPpp)) { preRas->dwFramingProtocol = RASFP_Ppp; } else if (0 == lstrcmpiU(pszTmp, c_pszDunCslip)) { preRas->dwFramingProtocol = RASFP_Slip; preRas->dwfOptions |= RASEO_IpHeaderCompression; } else if (0 == lstrcmpiU(pszTmp, c_pszDunSlip)) { preRas->dwFramingProtocol = RASFP_Slip; if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunTcpIpIpHeaderCompress, (BOOL) preRas->dwfOptions & RASEO_IpHeaderCompression)) { preRas->dwfOptions |= RASEO_IpHeaderCompression; } else { preRas->dwfOptions &= ~RASEO_IpHeaderCompression; } } } CmFree(pszTmp); if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerSwCompress, (BOOL) preRas->dwfOptions & RASEO_SwCompression)) { preRas->dwfOptions |= RASEO_SwCompression; } else { preRas->dwfOptions &= ~RASEO_SwCompression; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerDisableLcp, (BOOL) preRas->dwfOptions & RASEO_DisableLcpExtensions)) { preRas->dwfOptions |= RASEO_DisableLcpExtensions; } else { preRas->dwfOptions &= ~RASEO_DisableLcpExtensions; } if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerNetworkLogon, (BOOL) preRas->dwfOptions & RASEO_NetworkLogon)) { preRas->dwfOptions |= RASEO_NetworkLogon; } else { preRas->dwfOptions &= ~RASEO_NetworkLogon; } if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerNegotiateTcpIp, (BOOL) preRas->dwfNetProtocols & RASNP_Ip)) { preRas->dwfNetProtocols |= RASNP_Ip; } else { preRas->dwfNetProtocols &= ~RASNP_Ip; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerNegotiateIpx, (BOOL) preRas->dwfNetProtocols & RASNP_Ipx)) { preRas->dwfNetProtocols |= RASNP_Ipx; } else { preRas->dwfNetProtocols &= ~RASNP_Ipx; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerNegotiateNetBeui, preRas->dwfNetProtocols&RASNP_NetBEUI)) { preRas->dwfNetProtocols |= RASNP_NetBEUI; } else { preRas->dwfNetProtocols &= ~RASNP_NetBEUI; }
//
// Get the NT5 specific DUN settings. We will error out if we're running
// downlevel when these settings are configured and the EnforceCustomSecurity
// flag has been set.
//
// Note: c_pszCmEntryDunServerEnforceCustomSecurity is a DUN setting and is FALSE by default
//
BOOL bEnforceCustomSecurity = iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerEnforceCustomSecurity, FALSE);
//
// Is EAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireEap, (BOOL) preRas->dwfOptions & RASEO_RequireEAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireEAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireEAP; }
//
// PAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequirePap, (BOOL) preRas->dwfOptions & RASEO_RequirePAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequirePAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequirePAP; }
//
// SPAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireSpap, (BOOL) preRas->dwfOptions & RASEO_RequireSPAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireSPAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireSPAP; }
//
// CHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireChap, (BOOL) preRas->dwfOptions & RASEO_RequireCHAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireCHAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireCHAP; }
//
// MSCHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap, (BOOL) preRas->dwfOptions & RASEO_RequireMsCHAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireMsCHAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireMsCHAP; }
//
// MSCHAP2 required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap2, (BOOL) preRas->dwfOptions & RASEO_RequireMsCHAP2)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireMsCHAP2; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireMsCHAP2; }
//
// W95 MSCHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireW95MsChap, (BOOL) preRas->dwfOptions & RASEO_RequireW95MSCHAP)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_RequireW95MSCHAP; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_RequireW95MSCHAP; }
//
// Custom Security configuration
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomSecurity, (BOOL) preRas->dwfOptions & RASEO_Custom)) { if (OS_NT5) { preRas->dwfOptions |= RASEO_Custom; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } else { preRas->dwfOptions &= ~RASEO_Custom; }
//
// Now get the legacy security settings if we don't already have
// settings specificed from above. By checking for the Win2k specific
// settings first we allow Admins to specify both so that legacy platforms
// can have settings but Win2k can use the more granular settings.
// If we didn't do this the legacy flags could water down the security on Win2k ...
//
const DWORD dwWin2kSecuritySettings = RASEO_RequireEAP | RASEO_RequirePAP | RASEO_RequireSPAP | RASEO_RequireCHAP | RASEO_RequireMsCHAP | RASEO_RequireMsCHAP2 | RASEO_RequireW95MSCHAP;
if (0 == (preRas->dwfOptions & dwWin2kSecuritySettings) || !OS_NT5) { //
// Security settings
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerPwEncrypt, (BOOL) preRas->dwfOptions & RASEO_RequireEncryptedPw)) { preRas->dwfOptions |= RASEO_RequireEncryptedPw; } else { preRas->dwfOptions &= ~RASEO_RequireEncryptedPw; }
//
// MS-CHAP
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerPwEncryptMs, (BOOL) preRas->dwfOptions & RASEO_RequireMsEncryptedPw)) { preRas->dwfOptions |= RASEO_RequireMsEncryptedPw; } else { preRas->dwfOptions &= ~RASEO_RequireMsEncryptedPw; } } else { CMASSERTMSG((preRas->dwfOptions & RASEO_Custom), TEXT("ReadDUNSettings -- Win2k+ security setting configured but RASEO_Custom not specified.")); }
//
// Encrypt Data (legacy setting, same as ET_Require from above)
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerDataEncrypt, (BOOL) preRas->dwfOptions & RASEO_RequireDataEncryption)) { preRas->dwfOptions |= RASEO_RequireDataEncryption; } else { preRas->dwfOptions &= ~RASEO_RequireDataEncryption; }
//
// Encryption type, just a straight int read. (win2k+ setting)
//
int nTmp = iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerEncryptionType, -1);
if (OS_NT5) { //
// We need to set Tunnel encryption type to ET_Require because that's what the ConnFolder does.
// We also set it ET_Require if the user specified RASEO_RequireDataEncryption as a legacy setting
// but didn't specify a specific win2k setting.
//
if (-1 == nTmp) { if (fTunnel || (preRas->dwfOptions & RASEO_RequireDataEncryption)) { nTmp = ET_Require; } else { nTmp = ET_Optional; } } ((LPRASENTRY_V500)preRas)->dwEncryptionType = (DWORD) nTmp; } else { if (-1 != nTmp && bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } } //
// Get the EAP type ID (CustomAuthKey) - The data is stored in the RAS
// pbk via a specific API, just before dialing - SetCustomAuthData().
//
nTmp = iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomAuthKey, -1);
//
// If a type ID for EAP is specified, see if there is any config data
//
if (-1 != nTmp) { if (OS_NT5) { //
// We have an ID and its NT5, read the EAP config data
//
((LPRASENTRY_V500)preRas)->dwCustomAuthKey = nTmp;
//
// Last two params are NULL, NULL since we don't need the whole eap custom auth data structure
//
ReadDunSettingsEapData(&iniFile, ppbEapData, pdwEapSize, nTmp, NULL, NULL); } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } }
//
// Get and apply the Networking section entries.
//
nTmp = iniFile.GPPI(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingVpnStrategy, -1);
if (-1 != nTmp) { if (OS_NT5) { ((LPRASENTRY_V500)preRas)->dwVpnStrategy = nTmp; } else if (bEnforceCustomSecurity) { return (ERROR_INVALID_DATA); } }
//
// See if the profile calls for using a Pre-Shared Key for L2TP.
//
if (OS_NT51 && fTunnel) { if (iniFile.GPPB(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingUsePreSharedKey, (BOOL) ((LPRASENTRY_V501)preRas)->dwfOptions2 & RASEO2_UsePreSharedKey)) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_UsePreSharedKey; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_UsePreSharedKey; } } else if (fTunnel && ConfiguredToDialWithSafeNet(pArgs) && (OS_W9X || OS_NT4)) { //
// Link to SafeNet
//
SafeNetLinkageStruct SnLinkage = {0}; DWORD dwAuthMode;
if (LinkToSafeNet(&SnLinkage)) { //
// First figure out what auth mode we are supposed to be using.
//
if (iniFile.GPPB(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingUsePskDownLevel)) { dwAuthMode = SN_PRESHR; } else { //
// Now get the current authmode of the SafeNet Client. We do this because if the auth mode
// is a specific cert and we are going to set AutoCert then we don't want to change it.
//
DWORD dwSize = sizeof(DWORD); MYVERIFY(SnLinkage.pfnSnPolicyGet(SN_AUTHMODE, (VOID*)&(dwAuthMode), &dwSize));
if (SN_CERT != dwAuthMode) { dwAuthMode = SN_AUTOCERT; } // else leave it SN_CERT
}
//
// Now set the auth mode
//
if (FALSE == SnLinkage.pfnSnPolicySet(SN_AUTHMODE, (VOID*)&dwAuthMode)) { CMTRACE1(TEXT("ReadDUNSettings -- SnPolicySet failed with GLE=%d"), GetLastError()); CMASSERTMSG(FALSE, TEXT("ReadDUNSettings -- unable to set SN_AUTHMODE")); //
// We were unable to set the policy, we must change the adapter to be the MS PPTP adapter instead of
// the SafeNet adapter.
//
pArgs->bSafeNetClientAvailable = FALSE; MYDBGASSERT(PickTunnelDevice(pArgs, preRas->szDeviceType, preRas->szDeviceName)); pArgs->Log.Log(SN_ADAPTER_CHANGE_EVENT, pArgs->szTunnelDeviceName, preRas->szDeviceName); // log the fact we are changing devices
lstrcpynU(pArgs->szTunnelDeviceName, preRas->szDeviceName, sizeof (pArgs->szTunnelDeviceName)/sizeof(TCHAR)); } else { if (FALSE == SnLinkage.pfnSnPolicyReload()) { CMTRACE1(TEXT("ReadDUNSettings -- pfnSnPolicyReload failed with GLE=%d"), GetLastError()); CMASSERTMSG(FALSE, TEXT("ReadDUNSettings -- unable to commit the SafeNet settings to the driver."));
//
// We were unable to commit the changes to the SafeNet driver, we must change
// the adapter to be the MS PPTP adapter instead of the SafeNet adapter.
//
pArgs->bSafeNetClientAvailable = FALSE; MYDBGASSERT(PickTunnelDevice(pArgs, preRas->szDeviceType, preRas->szDeviceName)); pArgs->Log.Log(SN_ADAPTER_CHANGE_EVENT, pArgs->szTunnelDeviceName, preRas->szDeviceName); // log the fact we are changing devices
lstrcpynU(pArgs->szTunnelDeviceName, preRas->szDeviceName, sizeof (pArgs->szTunnelDeviceName)/sizeof(TCHAR)); } }
UnLinkFromSafeNet(&SnLinkage); } else { CMASSERTMSG(FALSE, TEXT("ReadDUNSettings -- SafeNet client wasn't available even though we thought it should be... continuing with PPTP.")); pArgs->bSafeNetClientAvailable = FALSE; } }
//
// File and Print sharing. Note that on systems up to Win2k we only have the traditional RASEO_SecureLocalFiles.
// However, Win2k gave this flag two purposes (enable/disable NetBt and enable/disable file and print sharing).
// In Whistler two separate flags were developed to allow greater granularity. To give legacy profiles the behavior
// they expect while disabling file and print sharing as the default the logic gets a little complicated. Basically
// the new flag overrides the legacy flag and defaults to 1. If the new flag isn't specified then we use the value
// of the legacy flag if it is specified. If neither is specified we set it to 1. On platforms previous to Whistler
// the old flag is the only thing we have and it defaults to 0.
//
int nLegacySecureLocalFiles = iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerSecureLocalFiles, -1); int nSecureFileAndPrint = iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerSecureFileAndPrint, -1);
if (-1 == nSecureFileAndPrint) { nSecureFileAndPrint = nLegacySecureLocalFiles ? 1 : 0; }
if (-1 == nLegacySecureLocalFiles) { nLegacySecureLocalFiles = 0; }
if (OS_NT51) { //
// Set the 501/Options2 style File and Print sharing flag
//
if (nSecureFileAndPrint) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_SecureFileAndPrint; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_SecureFileAndPrint; } } else { if (nLegacySecureLocalFiles) { preRas->dwfOptions |= RASEO_SecureLocalFiles; } else { preRas->dwfOptions &= ~RASEO_SecureLocalFiles; } }
//
// Pick up Whistler specific DUN settings
//
if (OS_NT51) { //
// Get the 501/Options2 style MSNet binding flag
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerSecureClientForMSNet, (BOOL) ((LPRASENTRY_V501)preRas)->dwfOptions2 & RASEO2_SecureClientForMSNet)) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_SecureClientForMSNet; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_SecureClientForMSNet; }
//
// Get the 501/Options2 style Multilink Negotiation flag
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerDontNegotiateMultilink, (BOOL) ((LPRASENTRY_V501)preRas)->dwfOptions2 & RASEO2_DontNegotiateMultilink)) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_DontNegotiateMultilink; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_DontNegotiateMultilink; }
//
// Get the 501/Options2 style DontUseRasCredentials flag
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerDontUseRasCredentials, (BOOL) ((LPRASENTRY_V501)preRas)->dwfOptions2 & RASEO2_DontUseRasCredentials)) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_DontUseRasCredentials; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_DontUseRasCredentials; }
//
// Get the RASEO_CustomScript flag value. Note that this flag existed on Win2k but wasn't
// available for RasDial only RasDialDlg. On Whistler+ it is available to RasDial as well.
// Note that we also have to set the RDEOPT_UseCustomScripting flag in the RASDIALEXTENSIONS
// for this to work.
//
if (iniFile.GPPB(c_pszCmSectionDunScripting, c_pszCmEntryDunScriptingUseRasCustomScriptDll, (BOOL) (preRas->dwfOptions & RASEO_CustomScript))) { preRas->dwfOptions |= RASEO_CustomScript; } else { preRas->dwfOptions &= ~RASEO_CustomScript; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerDisableNbtOverIP, (BOOL) (((LPRASENTRY_V501)preRas)->dwfOptions2 & RASEO2_DisableNbtOverIP))) { ((LPRASENTRY_V501)preRas)->dwfOptions2 |= RASEO2_DisableNbtOverIP; } else { ((LPRASENTRY_V501)preRas)->dwfOptions2 &= ~RASEO2_DisableNbtOverIP; } }
//
// Get and apply the TCP/IP section entries
//
if (iniFile.GPPB(c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpSpecifyIpAddress, (BOOL) preRas->dwfOptions & RASEO_SpecificIpAddr)) { preRas->dwfOptions |= RASEO_SpecificIpAddr; } else { preRas->dwfOptions &= ~RASEO_SpecificIpAddr; } Ip_GPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpIpAddress, &preRas->ipaddr); if (iniFile.GPPB(c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpSpecifyServerAddress, (BOOL) preRas->dwfOptions & RASEO_SpecificNameServers)) { preRas->dwfOptions |= RASEO_SpecificNameServers; } else { preRas->dwfOptions &= ~RASEO_SpecificNameServers; }
if (iniFile.GPPB(c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpIpHeaderCompress, (BOOL) preRas->dwfOptions & RASEO_IpHeaderCompression)) { preRas->dwfOptions |= RASEO_IpHeaderCompression; } else { preRas->dwfOptions &= ~RASEO_IpHeaderCompression; }
Ip_GPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpDnsAddress, &preRas->ipaddrDns); Ip_GPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpDnsAltAddress, &preRas->ipaddrDnsAlt); Ip_GPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpWinsAddress, &preRas->ipaddrWins); Ip_GPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpWinsAltAddress, &preRas->ipaddrWinsAlt); if (iniFile.GPPB(c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpGatewayOnRemote, (BOOL) preRas->dwfOptions & RASEO_RemoteDefaultGateway)) { preRas->dwfOptions |= RASEO_RemoteDefaultGateway; } else { preRas->dwfOptions &= ~RASEO_RemoteDefaultGateway; }
if (OS_NT51) { //
// If the caller specified a DNS suffix then lets read it and add it to the RAS entry
//
CopyGPPS(&iniFile, c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpDnsSuffix, ((LPRASENTRY_V501)preRas)->szDnsSuffix, sizeof(((LPRASENTRY_V501)preRas)->szDnsSuffix)/sizeof(TCHAR)); }
//
// Set the TCP Window size -- the NTT DoCoMo fix for Whistler. The Win2k version of this fix
// must be written through a private RAS API that must be called after the phonebook entry
// exists ie. after we call RasSetEntryProperties ... otherwise it won't work on the first
// dial.
//
if (OS_NT51) { ((LPRASENTRY_V501)preRas)->dwTcpWindowSize = iniFile.GPPI(c_pszCmSectionDunTcpIp, c_pszCmEntryDunTcpIpTcpWindowSize, 0); }
//
// Get and apply the Scripting section entries
//
TCHAR szScript[MAX_PATH + 1] = TEXT(""); CopyGPPS(&iniFile,c_pszCmSectionDunScripting, c_pszCmEntryDunScriptingName, szScript, sizeof(szScript)/sizeof(TCHAR));
//
// The script path from our cms file is a relative path. We need to convert
// it to a full path, but make sure that we use the top-level service for
// the conversion because it is used to derive the short-service name for
// the directory. Note that tunnel dun settings cannot have a script.
//
if (szScript[0] && !fTunnel) { CMTRACE1(TEXT("ReadDunSettings() - Converting script path %s to full path"), szScript); pszTmp = CmConvertRelativePath(pArgs->piniService->GetFile(), szScript);
MYDBGASSERT(pszTmp);
if (pszTmp && *pszTmp) { lstrcpyU(preRas->szScript, pszTmp); CMTRACE1(TEXT("ReadDunSettings() - Script file is %s"), preRas->szScript); }
CmFree(pszTmp); } else { //
// The cms didn't specify a script ==> no script
//
preRas->szScript[0] = TEXT('\0'); }
//
// If this is Whistler+ or Win2k with SP3 then we may need to invoke a terminal window
//
if (OS_NT5 && IsTerminalWindowSupportedOnWin2kPlus() && !fTunnel && iniFile.GPPB(c_pszCmSectionDunScripting, c_pszCmEntryDunScriptingUseTerminalWindow, (BOOL) preRas->dwfOptions & RASEO_TerminalAfterDial)) { preRas->dwfOptions |= RASEO_TerminalAfterDial; } else { preRas->dwfOptions &= ~RASEO_TerminalAfterDial; }
return (ERROR_SUCCESS); }
//+----------------------------------------------------------------------------
//
// Function: ValidateDialupDunSettings
//
// Synopsis: Verifies the DUN settings that the specified .CMS and DUN name are
// supported on the current platform. If we are running on a downlevel
// OS and we encounter any NT specific security settings we error out.
//
// Arguments: LPCTSTR pszCmsFile - The phone # specific .CMS file name.
// LPCTSTR pszDunName - The DUN name, if any for the settings.
// LPCTSTR pszTopLevelCms - The top-level CMS file name.
//
// Returns: BOOL - TRUE on success.
//
// History: nickball Created 8/26/98
//
//+----------------------------------------------------------------------------
BOOL ValidateDialupDunSettings(LPCTSTR pszCmsFile, LPCTSTR pszDunName, LPCTSTR pszTopLevelCms) { MYDBGASSERT(pszCmsFile); MYDBGASSERT(*pszCmsFile); MYDBGASSERT(pszDunName);
if (NULL == pszCmsFile || (!*pszCmsFile) || NULL == pszDunName) { return FALSE; }
//
// On NT5 we currently support all settings, so succeed automatically
//
if (OS_NT5) { return TRUE; }
//
// Determine the DUN name that we are looking for. In the tunnel case we
// always read it from the .CMS. For dial-up, we'll use the specified DUN
// name, and revert to the .CMS if blank.
//
CIni iniFile(g_hInst, pszCmsFile);
//
// Now determine the DUN name to be used when looking up settings.
//
LPTSTR pszEntryName;
//
// If we have a specific DUN name to use, and we're not tunneling
// use it instead of the default DUN setting in the .CMS.
//
if (pszDunName && *pszDunName) { pszEntryName = CmStrCpyAlloc(pszDunName); } else { pszEntryName = GetDefaultDunSettingName(&iniFile, FALSE); // FALSE == not tunnel
}
//
// If no DUN name is specified, then pass validation automatically
//
if (!pszEntryName || (!*pszEntryName)) { CmFree(pszEntryName); CMTRACE1(TEXT("ValidateDunSettings() - No DUN name found in %s"), pszCmsFile); return TRUE; } //
// Include the entryname in the section headers
//
LPTSTR pszSection = CmStrCpyAlloc(TEXT("&")); pszSection = CmStrCatAlloc(&pszSection, pszEntryName); iniFile.SetSection(pszSection);
CmFree(pszSection); CmFree(pszEntryName);
//
// Check to see if the admin wants us to check the custom security settings
// against the platform. By default, we do not enforce this check.
//
//
if (FALSE == iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerEnforceCustomSecurity)) { return TRUE; }
//
// Now check the actual settings if we're still here.
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireEap)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequirePap)) { goto ValidateDunSettingsExit; } if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireSpap)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireChap)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap2)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireW95MsChap)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomSecurity)) { goto ValidateDunSettingsExit; }
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerEncryptionType)) { goto ValidateDunSettingsExit; }
if (-1 != iniFile.GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomAuthKey, -1)) { goto ValidateDunSettingsExit; } if (-1 != iniFile.GPPI(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingVpnStrategy, -1)) { goto ValidateDunSettingsExit; } return TRUE;
ValidateDunSettingsExit:
//
// Get the top-level service name
//
CIni iniTopLevelCms(g_hInst, pszTopLevelCms);
LPTSTR pszTitle = GetServiceName(&iniTopLevelCms); LPTSTR pszTmp = CmFmtMsg(g_hInst,IDMSG_UNSUPPORTED_SETTING_NUM);
MessageBoxEx(NULL, pszTmp, pszTitle, MB_OK|MB_ICONSTOP, LANG_USER_DEFAULT);//13309
CmFree(pszTmp); CmFree(pszTitle);
CMTRACE1(TEXT("ValidateDunSettings() - Unsupported setting detected in %s"), pszCmsFile); return FALSE; }
//+----------------------------------------------------------------------------
//
// Function: IsTerminalWindowSupportedOnWin2kPlus
//
// Synopsis: Detects if the private RAS API in RasDlg.dll to invoke a terminal
// window is available or not. Should exist on win2k with SP3+ or
// on whistler and greater.
//
// Arguments: None
//
// Returns: TRUE if the private API for terminal window support is available
//
// History: quintinb Created 08/06/01
//
//+----------------------------------------------------------------------------
BOOL IsTerminalWindowSupportedOnWin2kPlus() { MYDBGASSERT(OS_NT5); BOOL bReturn = FALSE; typedef DWORD (WINAPI *pfnDwTerminalDlgSpec)(LPCWSTR, LPCWSTR, RASDIALPARAMS *, HWND, HRASCONN);
//
// First call loadlibrary on rasdlg.dll
//
HMODULE hRasDlg = LoadLibraryExU(TEXT("rasdlg.dll"), NULL, 0);
if (hRasDlg) { pfnDwTerminalDlgSpec pfnDwTerminalDlg = (pfnDwTerminalDlgSpec)GetProcAddress(hRasDlg, "DwTerminalDlg");
if (pfnDwTerminalDlg) { bReturn = TRUE; }
FreeLibrary(hRasDlg); }
return bReturn; }
//+----------------------------------------------------------------------------
//
// Function: InvokeTerminalWindow
//
// Synopsis: Allows CM to invoke a terminal window on Whistler or later versions
// of Win2k but calling a private RAS API in RasDlg.dll.
//
// Arguments: LPCWSTR pszPhoneBook - full path to the phonebook file
// LPCWSTR pszEntry - entry name to invoke the terminal window for
// RASDIALPARAMS *pRasDialParams - RasDialParams for the connection
// to invoke the terminal window for
// HWND hWnd - window handle of the parent dialog
// HRASCONN hRasconn - handle to the ras connection
//
// Returns: Windows error message
//
// History: quintinb Created 07/11/00
//
//+----------------------------------------------------------------------------
DWORD InvokeTerminalWindow(LPCWSTR pszPhoneBook, LPCWSTR pszEntry, RASDIALPARAMS *pRasDialParams, HWND hWnd, HRASCONN hRasconn) { //
// Validate the input parameters. Note that pszPhoneBook can be NULL but if it is non-NULL then we cannot have
// an empty string.
//
MYDBGASSERT(OS_NT5); if (((NULL != pszPhoneBook) && (L'\0' == pszPhoneBook[0])) || (NULL == pszEntry) || (L'\0' == pszEntry[0]) || (NULL == pRasDialParams) || (NULL == hWnd) || (NULL == hRasconn)) { CMASSERTMSG(FALSE, TEXT("InvokeTerminalWindow - Invalid parameter passed.")); return ERROR_INVALID_PARAMETER; }
DWORD dwReturn; typedef DWORD (WINAPI *pfnDwTerminalDlgSpec)(LPCWSTR, LPCWSTR, RASDIALPARAMS *, HWND, HRASCONN);
//
// First call loadlibrary on rasdlg.dll
//
HMODULE hRasDlg = LoadLibraryExU(TEXT("rasdlg.dll"), NULL, 0);
if (hRasDlg) { pfnDwTerminalDlgSpec pfnDwTerminalDlg = (pfnDwTerminalDlgSpec)GetProcAddress(hRasDlg, "DwTerminalDlg");
if (pfnDwTerminalDlg) { dwReturn = pfnDwTerminalDlg(pszPhoneBook, pszEntry, pRasDialParams, hWnd, hRasconn); } else { dwReturn = ERROR_PROC_NOT_FOUND; } FreeLibrary(hRasDlg); } else { dwReturn = ERROR_MOD_NOT_FOUND; }
return dwReturn; }
//+----------------------------------------------------------------------------
//
// Function: OnPauseRasDial
//
// Synopsis: Message handler for RasDial pause states. In the pause state, RAS
// is suspended, waiting for us to restart it by calling RasDial after
// performing the appropriate interface with the user.
//
// Arguments: HWND hwndDlg - Window handle of main dialog
// ArgsStruct *pArgs - Ptr to global args struct
// WPARAM wParam - wParam being handled
// LPARAM lParam - lParam being handled
//
// Returns: Windows error message
//
// History: nickball Created 05/19/99
//
//+----------------------------------------------------------------------------
DWORD OnPauseRasDial(HWND hwndDlg, ArgsStruct *pArgs, WPARAM wParam, LPARAM lParam) { CMTRACE2(TEXT("OnPauseRasDial - wParam is %u and lParam is %u."), wParam, lParam);
MYDBGASSERT(pArgs); if (NULL == pArgs) { return ERROR_INVALID_PARAMETER; }
//
// Get connection handle and re-dial
//
HRASCONN hRasConn; DWORD dwRes = ERROR_SUCCESS; LPTSTR pszRasPbk = pArgs->pszRasPbk; //
// Determine the appropriate connection handle and phonebook
// Note: Make an explicit copy or we'll wind up re-dialing
// if the connection drops while the pause UI is invoked.
//
if (IsDialingTunnel(pArgs)) { hRasConn = pArgs->hrcTunnelConn; } else { hRasConn = pArgs->hrcRasConn;
if (pArgs->pszRasHiddenPbk) { pszRasPbk = pArgs->pszRasHiddenPbk; } }
//
// In certain pause states we need to repopulate RASDIALPARAMS
// password because we always wipe it for security reasons
// after using it in RasDial. Thus we need to find out which
// passwords (Inet or regular) to use to repopulate RASDIALPARAMS
//
CSecurePassword *pSecPass = NULL; BOOL fUsingInetCredentials = (!pArgs->fUseSameUserName && !IsDialingTunnel(pArgs) && UseTunneling(pArgs, pArgs->nDialIdx));
//
// Handle the pause
//
switch (wParam) { case (RASCS_PAUSED + 4): // 4100 - RASCS_InvokeEapUI )
//
// If UNATTENDED, just bail out immediately.
//
if (pArgs->dwFlags & FL_UNATTENDED) { dwRes = ERROR_INTERACTIVE_MODE; goto OnPauseRasDialExit; }
//
// If EAP triggered the pause, invoke the EAP UI
//
dwRes = pArgs->rlsRasLink.pfnInvokeEapUI(hRasConn, pArgs->dwRasSubEntry, pArgs->pRasDialExtensions, hwndDlg); CMTRACE1(TEXT("OnPauseRasDial() - InvokeEapUI() returns %u."), dwRes); break;
case RASCS_PasswordExpired: // Domain password has expired
{ //
// If UNATTENDED, just bail out immediately.
//
if (pArgs->dwFlags & FL_UNATTENDED) { dwRes = ERROR_INTERACTIVE_MODE; goto OnPauseRasDialExit; }
CChangePasswordDlg NewPasswordDlg(pArgs); if (IDOK != NewPasswordDlg.DoDialogBox(g_hInst, IDD_CHANGEPASSWORD, pArgs->hwndMainDlg)) { if (pArgs->dwExitCode)// REVIEW: CChangePasswordDlg never sets dwExitCode, why are we doing this? quintinb 8/8/2001
{ dwRes = pArgs->dwExitCode; } else { dwRes = ERROR_CANCELLED; } } CMTRACE1(TEXT("OnPauseRasDial() - Password Expired"), dwRes); break; }
case RASCS_CallbackSetByCaller: // Server wants to call us back
{ //
// Preset dial params and call dialog to retrieve number from user
//
LPTSTR pszTmp = pArgs->piniProfile->GPPS(c_pszCmSection, c_pszCmEntryCallbackNumber); lstrcpyU(pArgs->pRasDialParams->szCallbackNumber, pszTmp); CmFree(pszTmp); //
// If we're running unattended, skip the dialog phase. The
// presumption is that there is no user there to receive it.
//
BOOL bPromptUser = !(pArgs->dwFlags & FL_UNATTENDED); if (bPromptUser) { //
// The above also applies in the case of DialAutomatically
// if we have a phone number, then there is no need to prompt.
//
if (pArgs->fDialAutomatically && TEXT('\0') != pArgs->pRasDialParams->szCallbackNumber[0]) { bPromptUser = FALSE; } }
if (bPromptUser) { CCallbackNumberDlg CallbackNumberDialog(pArgs); if (IDOK != CallbackNumberDialog.DoDialogBox(g_hInst, IDD_CALLBACK_NUMBER, pArgs->hwndMainDlg)) { //
// If the user canceled, clear the number so that RAS wont attempt callback
//
lstrcpyU(pArgs->pRasDialParams->szCallbackNumber, TEXT("")); } } //
// Now make sure the password is in the RASCREDENTAIAL structure.
//
if (fUsingInetCredentials) { pSecPass = &(pArgs->SecureInetPW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Inet - pArgs->szInetUserName = %s"), pArgs->szInetUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Inet - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Inet - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Inet - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
CMASSERTMSG(0 == lstrcmpU(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName), TEXT("OnPauseRasDial() - RASCS_CallbackSetByCaller - Inet - szInetUserName doesn't match RASDIALPARAMS"));
} else { pSecPass = &(pArgs->SecurePW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Corp - pArgs->szUserName = %s"), pArgs->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Corp - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Corp - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_CallbackSetByCaller - Corp - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
CMASSERTMSG(0 == lstrcmpU(pArgs->szUserName, pArgs->pRasDialParams->szUserName), TEXT("OnPauseRasDial() - RASCS_CallbackSetByCaller - Corp - Username doesn't match RASDIALPARAMS")); CMASSERTMSG(0 == lstrcmpU(pArgs->szDomain , pArgs->pRasDialParams->szDomain), TEXT("OnPauseRasDial() - RASCS_CallbackSetByCaller - Corp - domain doesn't match RASDIALPARAMS"));
}
if (FALSE == pSecPass->IsEmptyString()) { LPTSTR pszClearPassword = NULL; DWORD cbClearPassword = 0; BOOL fRetPassword = FALSE;
fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
if (fRetPassword && pszClearPassword) { lstrcpynU(pArgs->pRasDialParams->szPassword, pszClearPassword, lstrlenU(pszClearPassword)+1); CmEncodePassword(pArgs->pRasDialParams->szPassword); //
// Clear and Free the clear-text password
//
pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword); } }
dwRes = ERROR_SUCCESS; CMTRACE1(TEXT("OnPauseRasDial() - CallbackSetByCaller returns %u"), dwRes); break; }
case RASCS_RetryAuthentication: // Credentials aren't correct
{ //
// If UNATTENDED, just bail out immediately.
//
if (pArgs->dwFlags & FL_UNATTENDED) { dwRes = ERROR_INTERACTIVE_MODE; goto OnPauseRasDialExit; }
//
// Creds didn't work, prompt user for new ones.
//
CRetryAuthenticationDlg RetryAuthenticationDialog(pArgs);
if (IDOK != RetryAuthenticationDialog.DoDialogBox(g_hInst, RetryAuthenticationDialog.GetDlgTemplate(), pArgs->hwndMainDlg)) { //
// User canceled, or the call was dropped elsewhere. Use
// existing error code or designate authentication failure.
//
if (pArgs->dwExitCode) // REVIEW: CRetryAuthenticationDlg never sets dwExitCode, why are we doing this? quintinb 8/8/2001
{ dwRes = pArgs->dwExitCode; } else { dwRes = ERROR_AUTHENTICATION_FAILURE; } } CMTRACE1(TEXT("OnPauseRasDial() - RetryAuthentication"), dwRes); break; } case RASCS_Interactive: // Terminal/script pause state
if (OS_NT5 && IsTerminalWindowSupportedOnWin2kPlus()) { if (pArgs->dwFlags & FL_UNATTENDED) { dwRes = ERROR_INTERACTIVE_MODE; goto OnPauseRasDialExit; }
//
// Now make sure the password is in the RASCREDENTAIAL structure before invoking
// Terminal window.
//
if (fUsingInetCredentials) { pSecPass = &(pArgs->SecureInetPW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->szInetUserName = %s"), pArgs->szInetUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
//
// The user names should match.
//
CMASSERTMSG((0 == lstrcmpU(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName)), TEXT("OnPauseRasDial() - RASCS_Interactive - Inet - szInetUserName doesn't match RASDIALPARAMS")); } else { pSecPass = &(pArgs->SecurePW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->szUserName = %s"), pArgs->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
//
// The user names and domains should match since we'll be using the corp password to
// populate RASDIALPARAMS
//
CMASSERTMSG(0 == lstrcmpU(pArgs->szUserName, pArgs->pRasDialParams->szUserName), TEXT("OnPauseRasDial() - RASCS_Interactive - Corp - Username doesn't match RASDIALPARAMS")); CMASSERTMSG(0 == lstrcmpU(pArgs->szDomain , pArgs->pRasDialParams->szDomain), TEXT("OnPauseRasDial() - RASCS_Interactive - Corp - domain doesn't match RASDIALPARAMS")); }
if (FALSE == pSecPass->IsEmptyString()) { LPTSTR pszClearPassword = NULL; DWORD cbClearPassword = 0; BOOL fRetPassword = FALSE;
fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
if (fRetPassword && pszClearPassword) { lstrcpynU(pArgs->pRasDialParams->szPassword, pszClearPassword, lstrlenU(pszClearPassword)+1);
if (!OS_W2K) { //
// We don't want to encode this on Win2K. The RAS TerminalDlg code on Win2K doesn't
// like encoded passwords, thus it fails. On XP/Server 2003 this was changed (254385).
//
CmEncodePassword(pArgs->pRasDialParams->szPassword); } //
// Clear and Free the clear-text password
//
pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword); } }
dwRes = InvokeTerminalWindow(pszRasPbk, pArgs->szServiceName, pArgs->pRasDialParams, pArgs->hwndMainDlg, hRasConn);
//
// Before RasDial (below) the password gets decoded so must encode it here, because for
// Win2K we didn't encoded before calling InvokeTerminalWindow
//
if (OS_W2K) { CmEncodePassword(pArgs->pRasDialParams->szPassword); }
break; } // else fail through to default and error out.
//
// We got a pause state that we don't handle, error out.
//
default: dwRes = ERROR_INTERACTIVE_MODE; CMASSERTMSG(FALSE, TEXT("OnPauseRasDial() - Error, unsupported RAS pause state encountered.")); break; }
//
// On success, call RasDial to resume connection
//
if (ERROR_SUCCESS == dwRes) {
//
// Since these pause states no longer use RASDIALPARAMS to store the password
// we need to get it in the clear and copy it into the structure
//
if ((RASCS_PasswordExpired == wParam) || (RASCS_RetryAuthentication == wParam)) { if (fUsingInetCredentials) { pSecPass = &(pArgs->SecureInetPW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->szInetUserName = %s"), pArgs->szInetUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Inet - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
//
// The Inet user names should match.
//
CMASSERTMSG((0 == lstrcmpU(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName)), TEXT("OnPauseRasDial() - RASCS_Interactive - Inet - szInetUserName doesn't match RASDIALPARAMS")); } else { pSecPass = &(pArgs->SecurePW);
CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->szUserName = %s"), pArgs->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->szDomain = %s"), pArgs->szDomain); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->pRasDialParams->szUserName = %s"), pArgs->pRasDialParams->szUserName); CMTRACE1(TEXT("nPauseRasDial() - RASCS_Interactive - Corp - pArgs->pRasDialParams->szDomain = %s"), pArgs->pRasDialParams->szDomain);
//
// The user names and domains should match since we'll be using the corp password to
// populate RASDIALPARAMS
//
CMASSERTMSG(0 == lstrcmpU(pArgs->szUserName, pArgs->pRasDialParams->szUserName), TEXT("OnPauseRasDial() - RASCS_Interactive - Corp - Username doesn't match RASDIALPARAMS")); CMASSERTMSG(0 == lstrcmpU(pArgs->szDomain , pArgs->pRasDialParams->szDomain), TEXT("OnPauseRasDial() - RASCS_Interactive - Corp - domain doesn't match RASDIALPARAMS")); }
LPTSTR pszClearPassword = NULL; DWORD cbClearPassword = 0; BOOL fRetPassword = FALSE;
fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
if (fRetPassword && pszClearPassword) { lstrcpynU(pArgs->pRasDialParams->szPassword, pszClearPassword, CELEMS(pArgs->pRasDialParams->szPassword)); CmEncodePassword(pArgs->pRasDialParams->szPassword); //
// Clear and Free the clear-text password
//
pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword); }
}
//
// Decode active password, re-call RasDial, then re-encode
//
CmDecodePassword(pArgs->pRasDialParams->szPassword);
CMASSERTMSG((NOT_IN_CONNECT_OR_CANCEL == pArgs->lInConnectOrCancel), TEXT("OnPauseRasDial - RasDial mutex is NOT NULL..."));
dwRes = pArgs->rlsRasLink.pfnDial(pArgs->pRasDialExtensions, pszRasPbk, pArgs->pRasDialParams, GetRasCallBackType(), GetRasCallBack(pArgs), &hRasConn);
CmWipePassword(pArgs->pRasDialParams->szPassword); CMTRACE1(TEXT("OnPauseRasDial() - RasDial() returns %u."), dwRes);
//
// Reset timers, the current action starts now.
//
pArgs->dwStateStartTime = GetTickCount(); pArgs->nLastSecondsDisplay = (UINT) -1; }
OnPauseRasDialExit:
if (ERROR_SUCCESS != dwRes) { OnRasErrorMessage(hwndDlg, pArgs, dwRes); }
return dwRes; }
//+----------------------------------------------------------------------------
//
// Function: GetRasCallBackType
//
// Synopsis: Simple function to return the Callback type that we use for RasDial
// depending upon the OS.
//
// Arguments: None
//
// Returns: DWORD - The callback type
//
// History: nickball Created 05/22/99
//
//+----------------------------------------------------------------------------
DWORD GetRasCallBackType() { if (OS_NT5) { return 2; } else { return -1; } }
//+----------------------------------------------------------------------------
//
// Function: GetRasCallBack
//
// Synopsis: Simple function to return the Callback that we use for RasDial
// depending upon the OS.
//
// Arguments: ArgsStruct *pArgs - Ptr to global args struct
//
// Returns: LPVOID - The callback
//
// History: nickball Created 05/22/99
//
//+----------------------------------------------------------------------------
LPVOID GetRasCallBack(ArgsStruct* pArgs) { MYDBGASSERT(pArgs);
if (NULL == pArgs) { return NULL; }
//
// Now set return the callback func or hwnd according to OS.
//
if (OS_NT5) { //
// Set Callback data in RasDialParams
//
if (pArgs->pRasDialParams->dwSize == sizeof(RASDIALPARAMS_V401)) { ((LPRASDIALPARAMS_V401)pArgs->pRasDialParams)->dwCallbackId = (ULONG_PTR) pArgs; }
return (LPVOID) RasDialFunc2; } else { MYDBGASSERT(pArgs->hwndMainDlg); return (LPVOID) pArgs->hwndMainDlg; } }
|