Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4413 lines
136 KiB

//+----------------------------------------------------------------------------
//
// 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
//
// 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: 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[11] = NULL; //RasDeleteSubEntry
c_ArrayOfRasFuncsW[12] = NULL; //RasSetCustomAuthData
c_ArrayOfRasFuncsW[13] = NULL; //RasGetEapUserIdentity
c_ArrayOfRasFuncsW[14] = NULL; //RasFreeEapUserIdentity
c_ArrayOfRasFuncsW[15] = NULL; //RasInvokeEapUI
c_ArrayOfRasFuncsW[16] = NULL; //pfnGetCredentials
c_ArrayOfRasFuncsW[17] = NULL; //pfnSetCredentials
}
else if (OS_W2K)
{
//
// Special-casing for APIs that changed after Windows2000 shipped
//
c_ArrayOfRasFuncsW[11] = "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[10] = NULL; //RasSetSubEntryProperties
c_ArrayOfRasFuncsUA[11] = 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
// uNumCharsInDeviceType [IN] - number of chars of memory available in pszDeviceType
// pszDeviceName[IN] - device name
//
// Returns: TRUE on success, FALSE otherwise
//
// History: byao Created 03/21/97
//-----------------------------------------------------------------------------
BOOL GetDeviceType(ArgsStruct *pArgs, LPTSTR pszDeviceType, UINT uNumCharsInDeviceType, 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)
{
lstrcpynU(pszDeviceType, prdiModems[dwIdx].szDeviceType, uNumCharsInDeviceType);
break;
}
}
CmFree(prdiModems);
if (dwIdx == dwCnt) // not found in the modem list -- strange things happened
{
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function PickTunnelDevice
//
// Synopsis pick a tunnel device used to dial out
//
// Arguments
// pszDeviceType Tunnel device type. -- RASDT_Vpn
// pszDeviceName Tunnel device name
// prdiModems Pointer to a list of modems
// dwCnt Total number of modems available in the system
//
// Returns TRUE succeed
// FALSE otherwise
//
// History 3/1/97 byao Created
//
//-----------------------------------------------------------------------------
BOOL PickTunnelDevice(LPTSTR pszDeviceType,
LPTSTR pszDeviceName,
LPRASDEVINFO prdiModems,
DWORD dwCnt)
{
DWORD dwIdx;
if (dwCnt == 0)
{
return (FALSE);
}
for (dwIdx=0;dwIdx<dwCnt;dwIdx++)
{
if (lstrcmpiU(pszDeviceType,prdiModems[dwIdx].szDeviceType) == 0)
{
break;
}
}
if (dwIdx == dwCnt)
{
return (FALSE);
}
if (pszDeviceType)
{
lstrcpyU(pszDeviceType,prdiModems[dwIdx].szDeviceType);
}
if (pszDeviceName)
{
lstrcpyU(pszDeviceName,prdiModems[dwIdx].szDeviceName);
}
return (TRUE);
}
//+----------------------------------------------------------------------------
//
// 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 3/1/97 byao Created
//
//-----------------------------------------------------------------------------
BOOL PickTunnelDevice(ArgsStruct *pArgs,
LPTSTR pszDeviceType,
LPTSTR pszDeviceName)
{
LPRASDEVINFO prdiModems;
DWORD dwCnt;
BOOL bRes;
// first, get a list of modems from RAS
if (!GetRasModems(&pArgs->rlsRasLink,&prdiModems,&dwCnt))
{
return (FALSE);
}
// then, pick up the one used for tunneling
bRes = PickTunnelDevice(pszDeviceType,pszDeviceName,prdiModems,dwCnt);
CmFree(prdiModems);
return (bRes);
}
//+----------------------------------------------------------------------------
//
// 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
return FALSE;
break;
case ERROR_NO_ANSWER:
{
//
// For ISDN (Whistler bug#384223) we want to make sure CM displays the correct ras error (same as TAPI)
// thus we have to treat this error as a fatal error.
// This should return TRUE for the first time we are dialing and only dual-channel mode
//
if (0 == lstrcmpiU(pArgs->szDeviceType, RASDT_Isdn) && (pArgs->nMaxRedials == pArgs->nRedialCnt))
{
if (CM_ISDN_MODE_DUALCHANNEL_ONLY == pArgs->dwIsdnDialMode)
{
return TRUE;
}
}
return FALSE;
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);
}
}
}
//
// Special check for tunneling to verify that we have a device name
//
if (IsDialingTunnel(pArgs))
{
//
// Check whether the tunnel device name is valid
//
if (!PickTunnelDevice(pArgs,pArgs->szTunnelDeviceType,pArgs->szTunnelDeviceName))
{
pArgs->szTunnelDeviceName[0]= TEXT('\0');
pArgs->piniProfile->WPPS(c_pszCmSection, c_pszCmEntryTunnelDevice, TEXT(""));
pszMsg = CmLoadString(g_hInst, GetPPTPMsgId());
dwIdMsg = 0;
}
pArgs->piniProfile->WPPS(c_pszCmSection, c_pszCmEntryTunnelDevice, pArgs->szTunnelDeviceName);
}
//
// 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;
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;
SECURITY_ATTRIBUTES sa = {0};
PSECURITY_ATTRIBUTES pSA = NULL;
PSECURITY_DESCRIPTOR pSd = NULL;
if (OS_NT5 && pArgs->fAllUser)
{
//
// Be sure to create it with a security descriptor that
// allows it to be read by any authenticated user. If we don't it may
// prevent other users from being able to read it. We didn't want to
// change the old behavior downlevel so this fix is just for Whistler+.
//
DWORD dwErr = AllocateSecurityDescriptorAllowAccessToWorld(&pSd);
if ((ERROR_SUCCESS == dwErr) && pSd)
{
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSd;
sa.bInheritHandle = TRUE;
pSA = &sa;
}
}
hFile = CreateFileU(pszHiddenPbkPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
pSA, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CmFree(pSd);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwLastError = GetLastError();
MYDBGASSERT(hFile != INVALID_HANDLE_VALUE);
CMTRACE1(TEXT("CreateRasPrivatePbk - CreateFileU failed. GetLastError = %d"), dwLastError);
}
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.
//
// 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)
{
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;
MYDBGASSERT(pIni);
MYDBGASSERT(ppbEapData);
MYDBGASSERT(pdwEapSize);
if (NULL == pIni || NULL == ppbEapData || NULL == pdwEapSize)
{
return FALSE;
}
//
// 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
pbEapBytes = (BYTE *) CmMalloc(nTotal + 1);
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:
CmFree(pchBuf);
CmFree(pszLoadSection);
CmFree(pszSection);
CmFree(pszFile);
CmFree(pbEapBytes);
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) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireEAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireEAP;
}
//
// PAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequirePap,
(BOOL) preRas->dwfOptions & RASEO_RequirePAP))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequirePAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequirePAP;
}
//
// SPAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireSpap,
(BOOL) preRas->dwfOptions & RASEO_RequireSPAP))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireSPAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireSPAP;
}
//
// CHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireChap,
(BOOL) preRas->dwfOptions & RASEO_RequireCHAP))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireCHAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireCHAP;
}
//
// MSCHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap,
(BOOL) preRas->dwfOptions & RASEO_RequireMsCHAP))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireMsCHAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireMsCHAP;
}
//
// MSCHAP2 required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireMsChap2,
(BOOL) preRas->dwfOptions & RASEO_RequireMsCHAP2))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireMsCHAP2;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireMsCHAP2;
}
//
// W95 MSCHAP required
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerRequireW95MsChap,
(BOOL) preRas->dwfOptions & RASEO_RequireW95MSCHAP))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_RequireW95MSCHAP;
}
else
{
preRas->dwfOptions &= ~RASEO_RequireW95MSCHAP;
}
//
// Custom Security configuration
//
if (iniFile.GPPB(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomSecurity,
(BOOL) preRas->dwfOptions & RASEO_Custom))
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
preRas->dwfOptions |= RASEO_Custom;
}
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) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
//
// We have an ID and its NT5, read the EAP config data
//
((LPRASENTRY_V500)preRas)->dwCustomAuthKey = nTmp;
ReadDunSettingsEapData(&iniFile, ppbEapData, pdwEapSize, nTmp);
}
//
// Get and apply the Networking section entries.
//
nTmp = iniFile.GPPI(c_pszCmSectionDunNetworking, c_pszCmEntryDunNetworkingVpnStrategy, -1);
if (-1 != nTmp)
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
((LPRASENTRY_V500)preRas)->dwVpnStrategy = nTmp;
}
//
// See if the profile calls for using a Pre-Shared Key for L2TP. Note that we currently don't
// provide a mechanism to set the Pre-Shared Key through RasSetCredentials but that could easily
// be done through a custom action or a post install action.
//
if (OS_NT51)
{
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;
}
}
//
// 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_pszCmEntryDunNetworkingSecureFileAndPrint, -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)
{
if (!(OS_NT5) && bEnforceCustomSecurity)
{
return (ERROR_INVALID_DATA);
}
((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_pszCmEntryDunNetworkingSecureClientForMSNet,
(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_pszCmEntryDunNetworkingDontNegotiateMultilink,
(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_pszCmEntryDunNetworkingDontUseRasCredentials,
(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+ then we may need to invoke a terminal window
//
if (OS_NT51 && !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: 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_NT51);
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;
}
}
//
// 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)
{
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(""));
}
}
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)
{
dwRes = pArgs->dwExitCode;
}
else
{
dwRes = ERROR_AUTHENTICATION_FAILURE;
}
}
CMTRACE1(TEXT("OnPauseRasDial() - RetryAuthentication"), dwRes);
break;
}
case RASCS_Interactive: // Terminal/script pause state
if (OS_NT51)
{
if (pArgs->dwFlags & FL_UNATTENDED)
{
dwRes = ERROR_INTERACTIVE_MODE;
goto OnPauseRasDialExit;
}
dwRes = InvokeTerminalWindow(pszRasPbk, pArgs->szServiceName, pArgs->pRasDialParams, pArgs->hwndMainDlg, hRasConn);
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)
{
//
// 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);
CmEncodePassword(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;
}
}
//+----------------------------------------------------------------------------
//
// Function: AllocateSecurityDescriptorAllowAccessToWorld
//
// Synopsis: This function allocates a security descriptor for all users.
// This function was taken directly from RAS when they create their
// phonebook. This has to be before GetPhoneBookPath otherwise it
// causes compile errors in other components since we don't have a
// function prototype anywhere and cmcfg just includes this (getpbk.cpp)
// file. This function is also in common\source\getpbk.cpp
//
// Arguments: PSECURITY_DESCRIPTOR *ppSd - Pointer to a pointer to the SD struct
//
// Returns: DWORD - returns ERROR_SUCCESS if successfull
//
// History: 06/27/2001 tomkel Taken from RAS ui\common\pbk\file.c
//
//+----------------------------------------------------------------------------
#define SIZE_ALIGNED_FOR_TYPE(_size, _type) \
(((_size) + sizeof(_type)-1) & ~(sizeof(_type)-1))
DWORD AllocateSecurityDescriptorAllowAccessToWorld(PSECURITY_DESCRIPTOR *ppSd)
{
PSECURITY_DESCRIPTOR pSd;
PSID pSid;
PACL pDacl;
DWORD dwErr = ERROR_SUCCESS;
DWORD dwAlignSdSize;
DWORD dwAlignDaclSize;
DWORD dwSidSize;
PVOID pvBuffer;
DWORD dwAcls = 0;
// Here is the buffer we are building.
//
// |<- a ->|<- b ->|<- c ->|
// +-------+--------+------+
// | p| p| |
// | SD a| DACL a| SID |
// | d| d| |
// +-------+-------+-------+
// ^ ^ ^
// | | |
// | | +--pSid
// | |
// | +--pDacl
// |
// +--pSd (this is returned via *ppSd)
//
// pad is so that pDacl and pSid are aligned properly.
//
// a = dwAlignSdSize
// b = dwAlignDaclSize
// c = dwSidSize
//
if (NULL == ppSd)
{
return ERROR_INVALID_PARAMETER;
}
// Initialize output parameter.
//
*ppSd = NULL;
// Compute the size of the SID. The SID is the well-known SID for World
// (S-1-1-0).
//
dwSidSize = GetSidLengthRequired(1);
// Compute the size of the DACL. It has an inherent copy of SID within
// it so add enough room for it. It also must sized properly so that
// a pointer to a SID structure can come after it. Hence, we use
// SIZE_ALIGNED_FOR_TYPE.
//
dwAlignDaclSize = SIZE_ALIGNED_FOR_TYPE(
sizeof(ACCESS_ALLOWED_ACE) + sizeof(ACL) + dwSidSize,
PSID);
// Compute the size of the SD. It must be sized propertly so that a
// pointer to a DACL structure can come after it. Hence, we use
// SIZE_ALIGNED_FOR_TYPE.
//
dwAlignSdSize = SIZE_ALIGNED_FOR_TYPE(
sizeof(SECURITY_DESCRIPTOR),
PACL);
// Allocate the buffer big enough for all.
//
dwErr = ERROR_OUTOFMEMORY;
pvBuffer = CmMalloc(dwSidSize + dwAlignDaclSize + dwAlignSdSize);
if (pvBuffer)
{
SID_IDENTIFIER_AUTHORITY SidIdentifierWorldAuth
= SECURITY_WORLD_SID_AUTHORITY;
PULONG pSubAuthority;
dwErr = NOERROR;
// Setup the pointers into the buffer.
//
pSd = pvBuffer;
pDacl = (PACL)((PBYTE)pvBuffer + dwAlignSdSize);
pSid = (PSID)((PBYTE)pDacl + dwAlignDaclSize);
// Initialize pSid as S-1-1-0.
//
if (!InitializeSid(
pSid,
&SidIdentifierWorldAuth,
1)) // 1 sub-authority
{
dwErr = GetLastError();
goto finish;
}
pSubAuthority = GetSidSubAuthority(pSid, 0);
*pSubAuthority = SECURITY_WORLD_RID;
// Initialize pDacl.
//
if (!InitializeAcl(
pDacl,
dwAlignDaclSize,
ACL_REVISION))
{
dwErr = GetLastError();
goto finish;
}
dwAcls = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
dwAcls &= ~(WRITE_DAC | WRITE_OWNER);
if(!AddAccessAllowedAce(
pDacl,
ACL_REVISION,
dwAcls,
pSid))
{
dwErr = GetLastError();
goto finish;
}
// Initialize pSd.
//
if (!InitializeSecurityDescriptor(
pSd,
SECURITY_DESCRIPTOR_REVISION))
{
dwErr = GetLastError();
goto finish;
}
// Set pSd to use pDacl.
//
if (!SetSecurityDescriptorDacl(
pSd,
TRUE,
pDacl,
FALSE))
{
dwErr = GetLastError();
goto finish;
}
// Set the owner for pSd.
//
if (!SetSecurityDescriptorOwner(
pSd,
NULL,
TRUE))
{
dwErr = GetLastError();
goto finish;
}
// Set the group for pSd.
//
if (!SetSecurityDescriptorGroup(
pSd,
NULL,
FALSE))
{
dwErr = GetLastError();
goto finish;
}
finish:
if (!dwErr)
{
*ppSd = pSd;
}
else
{
CmFree(pvBuffer);
}
}
return dwErr;
}