|
|
// Copyright (c) 1995, Microsoft Corporation, all rights reserved
//
// file.c
// Remote Access phonebook library
// File access routines
// Listed alphabetically
//
// 09/21/95 Steve Cobb
//
// About .PBK files:
// -----------------
//
// A phonebook file is an MB ANSI file containing 0-n []ed sections, each
// containing information for a single phonebook entry. The single entry may
// contain multiple link information. Refer to file 'notes.txt' for a
// description of how this format differs from the NT 3.51 format.
//
// [ENTRY]
// Encoding=<encoding> ; New
// Type=<RASET-code> ; New
// Description=<text> ; Used for upgrade only
// AutoLogon=<1/0>
// DialParamsUID=<unique-ID>
// Guid=<16-byte-binary> ; Absence indicates pre-NT5 entry
// BaseProtocol=<BP-code>
// VpnStrategy=<VS-code>
// Authentication=<AS-code>
// ExcludedProtocols=<NP-bits>
// LcpExtensions=<1/0>
// DataEncryption=<DE-code>
// SkipNwcWarning=<1/0>
// SkipDownLevelDialog=<1/0>
// SkipDoubleDialDialog=<1/0>
// SwCompression=<1/0>
// UseCountryAndAreaCodes=<1/0> ; Used for upgrade only
// AreaCode=<string> ; Used for upgrade only
// CountryID=<id> ; Used for upgrade only
// CountryCode=<code> ; Used for upgrade only
// ShowMonitorIconInTaskBar
// CustomAuthKey=<EAP-IANA-code>
// CustomAuthData=<hexdump>
// CustomAuthIdentity=<name>
// AuthRestrictions=<AR-code>
// TypicalAuth=<TA-code>
// ShowMonitorIconInTaskBar=<1/0>
// OverridePref=<RASOR-bits>
// DialMode=<DM-code>
// DialPercent=<0-100>
// DialSeconds=<1-n>
// HangUpPercent=<0-100>
// HangUpSeconds=<1-n>
// RedialAttempts=<n>
// RedialSeconds=<n>
// IdleDisconnectSeconds=<-1,0,1-n>
// RedialOnLinkFailure=<1/0>
// CallbackMode=<CBM-code>
// CustomDialDll=<path>
// CustomDialFunc=<func-name>
// AuthenticateServer=<1/0>
// ShareMsFilePrint=<1/0>
// BindMsNetClient=<1/0>
// SharedPhoneNumbers=<1/0>
// PrerequisiteEntry=<entry-name>
// PrerequisitePbk=<PBK-path>
// PreferredPort=<port name>
// PreferredDevice=<device name>
// PreviewUserPw=<1/0>
// PreviewDomain=<1/0>
// PreviewPhoneNumber=<1/0>
// ShowDialingProgress=<1/0>
// CustomScript=<1/0>
//
// The following single set of IP parameters appear in place of the equivalent
// separate sets of PppXxx or SlipXxx parameters in the previous phonebook.
//
// IpPrioritizeRemote=<1/0>
// IpHeaderCompression=<1/0>
// IpAddress=<a.b.c.d>
// IpDnsAddress=<a.b.c.d>
// IpDns2Address=<a.b.c.d>
// IpWinsAddress=<a.b.c.d>
// IpWins2Address=<a.b.c.d>
// IpAssign=<ASRC-code>
// IpNameAssign=<ASRC-code>
// IpFrameSize=<1006/1500>
// IpDnsFlags=<DNS_ bits>
// IpDnsSuffix=<dns suffix>
//
// Each entry contains a NETCOMPONENT subsection containing a freeform list of
// keys and values representing installed net component parameters.
//
// NETCOMPONENTS=
// <key1>=<value1>
// <key2>=<value2>
// <keyn>=<valuen>
//
// In general each section contains subsections delimited by MEDIA=<something>
// and DEVICE=<something> lines. In NT 3.51 there had to be exactly one MEDIA
// subsection and it had to be the first subsection of the section. There
// could be any number of DEVICE subsections. Now, there can be multiple
// MEDIA/DEVICE sets where the position of the set determines it's sub-entry
// index, the first being 1, the second 2, etc.
//
// For serial media, the program currently expects 1 to 4 DEVICE subsections,
// representing a preconnect switch, modem, X.25 PAD, and postconnect switch
// (often a script). Following is a full serial link:
//
// MEDIA=serial
// Port=<port-name>
// Device=<device-name> ; Absence indicates a 3.51- phonebook
// ConnectBps=<bps>
//
// DEVICE=switch
// Type=<switchname or Terminal> ; Used for upgrade only
// Name=<switchname>
// Terminal=<1/0>
//
// DEVICE=modem
// PhoneNumber=<phonenumber1>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text1>
// PhoneNumber=<phonenumber2>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text2>
// PhoneNumber=<phonenumberN>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-textn>
// LastSelectedPhone=<index>
// PromoteAlternates=<1/0>
// TryNextAlternateOnFail=<1/0>
// TapiBlob=<hexdump>
// HwFlowControl=<1/0>
// Protocol=<1/0>
// Compression=<1/0>
// Speaker=<0/1>
//
// DEVICE=pad
// X25Pad=<padtype>
// X25Address=<X121address>
// UserData=<userdata>
// Facilities=<facilities>
//
// DEVICE=switch
// Type=<switchname or Terminal> ; Used for upgrade only
// Name=<switchname>
// Terminal=<1/0>
//
// In the above, when a "pad" device appears without a modem (local PAD card),
// the X25Pad field is written but is empty, because this is what the old
// library/UI appears to do (though it does not look to be what was intended).
//
// For ISDN media, the program expects exactly 1 DEVICE subsection.
//
// MEDIA=isdn
// Port=<port>
// Device=<device-name>
//
// DEVICE=isdn
// PhoneNumber=<phonenumber1>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text1>
// PhoneNumber=<phonenumber2>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text2>
// PhoneNumber=<phonenumberN>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-textn>
// LastSelectedPhone=<index>
// PromoteAlternates=<1/0>
// TryNextAlternateOnFail=<1/0>
// LineType=<0/1/2>
// Fallback=<1/0>
// EnableCompression=<1/0> ; Old proprietary protocol only
// ChannelAggregation=<channels> ; Old proprietary protocol only
// Proprietary=<1/0> ; Exists only in new, not found is 1.
//
//
// For X.25 media, the program expects exactly 1 DEVICE subsection.
//
// MEDIA=x25
// Port=<port-name>
// Device=<device-name>
//
// DEVICE=x25
// X25Address=<X121address>
// UserData=<userdata>
// Facilities=<facilities>
//
// For other media, the program expects exactly one DEVICE subsection with
// device name matching the media. "Other" media and devices are created for
// entries assigned to all non-serial, non-isdn medias.
//
// MEDIA=<media>
// Port=<port-name>
// Device=<device-name>
//
// DEVICE=<media>
// PhoneNumber=<phonenumber1>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text1>
// PhoneNumber=<phonenumber2>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-text2>
// PhoneNumber=<phonenumberN>
// AreaCode=<area-code1>
// CountryID=<id>
// CountryCode=<country-code>
// UseDialingRules=<1/0>
// Comment=<arbitrary-textn>
// LastSelectedPhone=<index>
// PromoteAlternates=<1/0>
// TryNextAlternateOnFail=<1/0>
//
// The phonebook also supports the concept of "custom" entries, i.e. entries
// that fit the MEDIA followed by DEVICE subsection rules but which do not
// include certain expected key fields. A custom entry is not editable with
// the UI, but may be chosen for connection. This gives us a story for new
// drivers added by 3rd parties or after release and not yet fully supported
// in the UI. (Note: The RAS API support for most the custom entry discussion
// above may be removed for NT SUR)
//
#include <nt.h>
#include <ntrtl.h> // for DbgPrint
#include <nturtl.h>
#include <shlobj.h> // for CSIDL_*
#include "pbkp.h"
// This mutex guards against multiple RASFILE access to any phonebook file
// across processes. Because this is currently a static library there is no
// easy way to protect a single file at a time though this would be adequate.
//
#define PBMUTEXNAME "RasPbFile"
HANDLE g_hmutexPb = NULL;
#define MARK_LastLineToDelete 249
#define MARK_BeginNetComponentsSearch 248
#define IB_BytesPerLine 64
const WCHAR c_pszRegKeySecureVpn[] = L"System\\CurrentControlSet\\Services\\Rasman\\PPP"; const WCHAR c_pszRegValSecureVpn[] = L"SecureVPN"; const WCHAR* c_pszRegKeyForceStrongEncryption = c_pszRegKeySecureVpn; const WCHAR c_pszRegValForceStrongEncryption[] = L"ForceStrongEncryption";
//
// Enumerated values define what encoding was used to store information
// in the phonebook.
//
#define EN_Ansi 0x0 // Ansi encoding
#define EN_Standard 0x1 // Utf8 encoding
//
// pmay: 124594
//
// Defines a function prototype that converts a string from ansi to TCHAR.
//
typedef TCHAR* (* STRDUP_T_FROM_A_FUNC)( IN CHAR* pszAnsi);
//----------------------------------------------------------------------------
// Local prototypes
//----------------------------------------------------------------------------
BOOL DeleteCurrentSection( IN HRASFILE h );
DWORD GetPersonalPhonebookFile( IN TCHAR* pszUser, IN LONG lNum, OUT TCHAR* pszFile );
BOOL GetPhonebookPath( IN PBUSER* pUser, IN DWORD dwFlags, OUT TCHAR** ppszPath, OUT DWORD* pdwPhonebookMode );
DWORD InsertBinary( IN HRASFILE h, IN CHAR* pszKey, IN BYTE* pData, IN DWORD cbData );
DWORD InsertBinaryChunk( IN HRASFILE h, IN CHAR* pszKey, IN BYTE* pData, IN DWORD cbData );
DWORD InsertDeviceList( IN PBFILE *pFile, IN HRASFILE h, IN PBENTRY* ppbentry, IN PBLINK* ppblink );
DWORD InsertFlag( IN HRASFILE h, IN CHAR* pszKey, IN BOOL fValue );
DWORD InsertGroup( IN HRASFILE h, IN CHAR* pszGroupKey, IN TCHAR* pszValue );
DWORD InsertLong( IN HRASFILE h, IN CHAR* pszKey, IN LONG lValue );
DWORD InsertNetComponents( IN HRASFILE h, IN DTLLIST* pdtllist );
DWORD InsertPhoneList( IN HRASFILE h, IN DTLLIST* pdtllist );
DWORD InsertSection( IN HRASFILE h, IN TCHAR* pszSectionName );
DWORD InsertString( IN HRASFILE h, IN CHAR* pszKey, IN TCHAR* pszValue );
DWORD InsertStringA( IN HRASFILE h, IN CHAR* pszKey, IN CHAR* pszValue );
DWORD InsertStringList( IN HRASFILE h, IN CHAR* pszKey, IN DTLLIST* pdtllistValues );
BOOL IsGroup( IN CHAR* pszText );
DWORD ModifyEntryList( IN PBFILE* pFile );
DWORD ReadBinary( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT BYTE** ppResult, OUT DWORD* pcb );
DWORD ReadDeviceList( IN HRASFILE h, IN STRDUP_T_FROM_A_FUNC pStrDupTFromA, IN OUT PBENTRY* ppbentry, IN OUT PBLINK* ppblink, IN BOOL fUnconfiguredPort, IN BOOL* pfSpeaker );
DWORD ReadEntryList( IN OUT PBFILE* pFile, IN DWORD dwFlags, IN LPCTSTR pszSection);
DWORD ReadFlag( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT BOOL* pfResult );
DWORD ReadLong( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT LONG* plResult );
VOID ReadNetComponents( IN HRASFILE h, IN DTLLIST* pdtllist );
DWORD ReadPhoneList( IN HRASFILE h, IN RFSCOPE rfscope, OUT DTLLIST** ppdtllist, OUT BOOL* pfDirty );
DWORD ReadString( IN HRASFILE h, IN STRDUP_T_FROM_A_FUNC pStrDupTFromA, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT TCHAR** ppszResult );
DWORD ReadStringList( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT DTLLIST** ppdtllistResult );
BOOL PbportTypeMatchesEntryType( IN PBPORT * ppbport, IN PBENTRY* ppbentry);
PBPORT* PpbportFromNullModem( IN DTLLIST* pdtllistPorts, IN TCHAR* pszPort, IN TCHAR* pszDevice );
DWORD UpgradeRegistryOptions( IN HANDLE hConnection, IN PBENTRY* pEntry );
//----------------------------------------------------------------------------
// Routines
//----------------------------------------------------------------------------
VOID ClosePhonebookFile( IN OUT PBFILE* pFile )
// Closes the currently open phonebook file for shutdown.
//
{ if (pFile->hrasfile != -1) { RasfileClose( pFile->hrasfile ); pFile->hrasfile = -1; }
if(pFile->pszPath != NULL){ Free0( pFile->pszPath ); pFile->pszPath = NULL; }
if (pFile->pdtllistEntries != NULL) { if (DtlGetListId( pFile->pdtllistEntries ) == RPBF_HeadersOnly) { DtlDestroyList( pFile->pdtllistEntries, DestroyPszNode ); } else if (DtlGetListId(pFile->pdtllistEntries) == RPBF_HeaderType) { DtlDestroyList(pFile->pdtllistEntries, DestroyEntryTypeNode); } else { DtlDestroyList( pFile->pdtllistEntries, DestroyEntryNode ); } pFile->pdtllistEntries = NULL; } }
BOOL DeleteCurrentSection( IN HRASFILE h )
// Delete the section containing the current line from phonebook file 'h'.
//
// Returns true if all lines are deleted successfully, false otherwise.
// False is returned if the current line is not in a section. If
// successful, the current line is set to the line following the deleted
// section. There are no promises about the current line in case of
// failure.
//
{ BOOL fLastLine;
// Mark the last line in the section, then reset the current line to the
// first line of the section.
//
if (!RasfileFindLastLine( h, RFL_ANY, RFS_SECTION ) || !RasfilePutLineMark( h, MARK_LastLineToDelete ) || !RasfileFindFirstLine( h, RFL_ANY, RFS_SECTION )) { return FALSE; }
// Delete lines up to and including the last line of the section.
//
do { fLastLine = (RasfileGetLineMark( h ) == MARK_LastLineToDelete);
if (!RasfileDeleteLine( h )) { return FALSE; } } while (!fLastLine);
return TRUE; }
// (shaunco) DwAllocateSecurityDescriptorAllowAccessToWorld was added when
// it was seen that the old InitSecurityDescriptor code was leaking memory
// like a sieve.
//
#define SIZE_ALIGNED_FOR_TYPE(_size, _type) \
(((_size) + sizeof(_type)-1) & ~(sizeof(_type)-1))
DWORD DwAllocateSecurityDescriptorAllowAccessToWorld ( PSECURITY_DESCRIPTOR* ppSd ) { PSECURITY_DESCRIPTOR pSd; PSID pSid; PACL pDacl; DWORD dwErr = NOERROR; 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
//
// 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 = Malloc(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 { Free(pvBuffer); } }
return dwErr; }
BOOL GetDefaultPhonebookPath( IN DWORD dwFlags, OUT TCHAR** ppszPath )
// Loads caller's 'ppszPath' with the path to the default phonebook
// for the current user, i.e. the phonebook which would be opened
// if 'NULL' were passed as the 'pszPhonebook' argument to any RAS API.
//
// Returns true if successful, or false otherwise.
// It is the caller's responsibility to Free the returned string.
//
{ DWORD dwPhonebookMode; BOOL f; PBUSER user;
if (GetUserPreferences( NULL, &user, FALSE ) != 0) { return FALSE; }
f = GetPhonebookPath( &user, dwFlags, ppszPath, &dwPhonebookMode );
DestroyUserPreferences( &user );
return f; }
#if 0
DWORD GetPersonalPhonebookFile( IN TCHAR* pszUser, IN LONG lNum, OUT TCHAR* pszFile )
// Loads caller's 'pszFile' buffer with the NUL-terminated filename
// corresponding to unique phonebook file name attempt 'lNum' for current
// user 'pszUser'. Caller's 'pszFile' must be at least 13 characters
// long. Attempts go from -1 to 999.
//
// Returns 0 if successful or a non-0 error code.
//
{ TCHAR szNum[ 3 + 1 ];
if (lNum < 0) { lstrcpyn( pszFile, pszUser, 9 ); } else { if (lNum > 999) { return ERROR_PATH_NOT_FOUND; }
lstrcpy( pszFile, TEXT("00000000") ); LToT( lNum, szNum, 10 ); lstrcpy( pszFile + 8 - lstrlen( szNum ), szNum ); CopyMemory( pszFile, pszUser, (min( lstrlen( pszUser ), 5 )) * sizeof(TCHAR) ); }
lstrcat( pszFile, TEXT(".pbk") ); return 0; } #endif
BOOL GetPhonebookDirectory( IN DWORD dwPhonebookMode, OUT TCHAR* pszPathBuf )
// Loads caller's 'pszPathBuf' (should have length MAX_PATH + 1) with the
// path to the directory containing phonebook files for the given mode,
// e.g. c:\nt\system32\ras\" for mode PBM_Router. Note the
// trailing backslash.
//
// Returns true if successful, false otherwise. Caller is guaranteed that
// an 8.3 filename will fit on the end of the directory without exceeding
// MAX_PATH.
//
{ BOOL bSuccess = FALSE; UINT cch;
// 205217: (shaunco) PBM_System also comees from the profile now.
// We pick it up using the command appdata directory returned from
// SHGetFolderPath.
//
if (dwPhonebookMode == PBM_Personal || dwPhonebookMode == PBM_System) { HANDLE hToken = NULL;
if ((OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_IMPERSONATE, TRUE, &hToken) || OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_IMPERSONATE, &hToken))) { HRESULT hr; INT csidl = CSIDL_APPDATA;
if (dwPhonebookMode == PBM_System) { csidl = CSIDL_COMMON_APPDATA; }
hr = SHGetFolderPath(NULL, csidl, hToken, 0, pszPathBuf);
if (SUCCEEDED(hr)) { if(lstrlen(pszPathBuf) <= (MAX_PATH - (lstrlen(TEXT("\\Microsoft\\Network\\Connections\\Pbk\\"))))) { lstrcat(pszPathBuf, TEXT("\\Microsoft\\Network\\Connections\\Pbk\\")); bSuccess = TRUE; } } else { TRACE1("ShGetFolderPath failed. hr=0x%08x", hr); }
CloseHandle(hToken); } } else { // Note: RASDLG uses this case to determine the scripts directory.
//
cch = GetSystemDirectory(pszPathBuf, MAX_PATH + 1);
if (cch != 0 && cch <= (MAX_PATH - (5 + 8 + 1 + 3))) { lstrcat(pszPathBuf, TEXT("\\Ras\\")); bSuccess = TRUE; } }
return bSuccess; }
BOOL GetPhonebookPath( IN PBUSER* pUser, IN DWORD dwFlags, OUT TCHAR** ppszPath, OUT DWORD* pdwPhonebookMode )
// Loads caller's '*ppszPath', with the full path to the user's phonebook
// file. Caller's '*pdwPhonebookMode' is set to the mode, system,
// personal, or alternate. 'PUser' is the current user preferences.
//
// Returns true if successful, false otherwise. It is caller's
// responsibility to Free the returned string.
//
{ TCHAR szPath[ MAX_PATH + 1 ];
*szPath = TEXT('\0'); if (pUser) { if (pUser->dwPhonebookMode == PBM_Personal) { if (!GetPersonalPhonebookPath( pUser->pszPersonalFile, szPath )) { return FALSE; } *ppszPath = StrDup( szPath ); if(NULL == *ppszPath) { return FALSE; } *pdwPhonebookMode = PBM_Personal; return TRUE; } else if (pUser->dwPhonebookMode == PBM_Alternate) { *ppszPath = StrDup( pUser->pszAlternatePath );
if(NULL == *ppszPath) { return FALSE; } *pdwPhonebookMode = PBM_Alternate; return TRUE; } }
// 205217: (shaunco) Admins or power users get to use the public
// phonebook file. Everyone else must use their own phonebook to
// prevent them from adding to/deleting from the public phonebook.
// The exception is the 'no user' case when we are called from winlogon.
// For this case, all edits happen in the public phonebook.
//
if ( (dwFlags & RPBF_NoUser) || (dwFlags & RPBF_AllUserPbk) || // XP 346918
(FIsUserAdminOrPowerUser()) ) { TRACE("User is an admin or power user. (or no user context yet)");
if (!GetPublicPhonebookPath( szPath )) { return FALSE; } *ppszPath = StrDup( szPath );
if(NULL == *ppszPath) { return FALSE; } *pdwPhonebookMode = PBM_System; } else { TRACE("User is NOT an admin or power user.");
if (!GetPersonalPhonebookPath( NULL, szPath )) { return FALSE; } *ppszPath = StrDup( szPath ); if(NULL == *ppszPath) { return FALSE; } *pdwPhonebookMode = PBM_Personal; } return TRUE; }
BOOL GetPersonalPhonebookPath( IN TCHAR* pszFile, OUT TCHAR* pszPathBuf )
// Loads caller's 'pszPathBuf' (should have length MAX_PATH + 1) with the
// path to the personal phonebook, (in the user's profile.)
// 'PszFile' is the filename of the personal phonebook.
//
// Returns true if successful, false otherwise.
//
{ if (!GetPhonebookDirectory( PBM_Personal, pszPathBuf )) { return FALSE; }
// No file means use the default name for a phonebook.
//
if (!pszFile) { pszFile = TEXT("rasphone.pbk"); }
lstrcat( pszPathBuf, pszFile );
return TRUE; }
BOOL GetPublicPhonebookPath( OUT TCHAR* pszPathBuf )
// Loads caller's 'pszPathBuf' (should have length MAX_PATH + 1) with the
// path to the system phonebook, (in the all-user's profile.)
//
// Returns true if successful, false otherwise.
//
{ if (!GetPhonebookDirectory( PBM_System, pszPathBuf )) { return FALSE; }
lstrcat( pszPathBuf, TEXT("rasphone.pbk") );
return TRUE; }
DWORD InitializePbk( void )
// Initialize the PBK library. This routine must be called before any
// other PBK library calls. See also TerminatePbk.
//
{ DWORD dwErr = NO_ERROR; if (!g_hmutexPb) { SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR pSd;
// The mutex must be accessible by everyone, even processes with
// security privilege lower than the creator.
//
dwErr = DwAllocateSecurityDescriptorAllowAccessToWorld(&pSd); if (dwErr != 0) { return dwErr; }
sa.nLength = sizeof(SECURITY_ATTRIBUTES) ; sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = FALSE ;
g_hmutexPb = CreateMutexA( &sa, FALSE, PBMUTEXNAME ); Free(pSd); if (!g_hmutexPb) { dwErr = GetLastError();
if(ERROR_ACCESS_DENIED == dwErr) { dwErr = NO_ERROR; //
// Try to open the mutex for synchronization.
// the mutex must already have been created.
//
g_hmutexPb = OpenMutexA(SYNCHRONIZE, FALSE, PBMUTEXNAME); if(NULL == g_hmutexPb) { return GetLastError(); } } } }
dwErr = PbkPathInfoInit(&g_PbkPathInfo); if( NO_ERROR != dwErr ) { return dwErr; }
#ifdef _PBK_CACHE_
dwErr = PbkCacheInit();
#endif
return dwErr; }
#if 0
DWORD InitPersonalPhonebook( OUT TCHAR** ppszFile )
// Creates a new personal phonebook file and initializes it to the current
// contents of the public phonebook file. Returns the address of the file
// name in caller's '*ppszfile' which is caller's responsibility to Free.
//
// Returns 0 if succesful, otherwise a non-0 error code.
//
{ TCHAR szUser[ UNLEN + 1 ]; DWORD cbUser = UNLEN + 1; TCHAR szPath[ MAX_PATH + 1 ]; TCHAR* pszDirEnd; LONG lTry = -1;
// Find a name for the personal phonebook that is derived from the
// username and does not already exist.
//
if (!GetUserName( szUser, &cbUser )) { return ERROR_NO_SUCH_USER; }
if (!GetPhonebookDirectory( PBM_Personal, szPath )) { return ERROR_PATH_NOT_FOUND; }
pszDirEnd = &szPath[ lstrlen( szPath ) ];
do { DWORD dwErr;
dwErr = GetPersonalPhonebookFile( szUser, lTry++, pszDirEnd ); if (dwErr != 0) { return dwErr; } } while (FFileExists( szPath ));
// Copy the public phonebook to the new personal phonebook.
//
{ TCHAR szPublicPath[ MAX_PATH + 1 ];
if (!GetPublicPhonebookPath( szPublicPath )) { return ERROR_PATH_NOT_FOUND; }
if (!CopyFile( szPublicPath, szPath, TRUE )) { return GetLastError(); } }
*ppszFile = StrDup( pszDirEnd ); if (!*ppszFile) { return ERROR_NOT_ENOUGH_MEMORY; }
return 0; } #endif
DWORD InsertBinary( IN HRASFILE h, IN CHAR* pszKey, IN BYTE* pData, IN DWORD cbData )
// Insert key/value line(s) with key 'pszKey' and value hex dump 'cbData'
// of 'pData' at the current line in file 'h'. The data will be split
// over multiple same-named keys, if necessary.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ DWORD dwErr; BYTE* p; DWORD c;
p = pData; c = 0;
while (cbData) { if (cbData >= IB_BytesPerLine) { c = IB_BytesPerLine; } else { c = cbData; }
dwErr = InsertBinaryChunk( h, pszKey, p, c ); if (dwErr != 0) { return dwErr; }
p += c; cbData -= c; }
return 0; }
DWORD InsertBinaryChunk( IN HRASFILE h, IN CHAR* pszKey, IN BYTE* pData, IN DWORD cbData )
// Insert key/value line(s) with key 'pszKey' and value hex dump 'cbData'
// of 'pData' at the current line in file 'h'. The data will be split
// over multiple same-named keys, if necessary.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ CHAR szBuf[ (IB_BytesPerLine * 2) + 1 ]; CHAR* pszBuf; BOOL fStatus;
ASSERT( cbData<=IB_BytesPerLine );
szBuf[ 0 ] = '\0'; for (pszBuf = szBuf; cbData; ++pData, --cbData) { *pszBuf++ = HexChar( (BYTE )(*pData / 16) ); *pszBuf++ = HexChar( (BYTE )(*pData % 16) ); } *pszBuf = '\0';
return InsertStringA( h, pszKey, szBuf ); }
DWORD InsertDeviceList( IN PBFILE *pFile, IN HRASFILE h, IN PBENTRY* ppbentry, IN PBLINK* ppblink )
// Inserts the list of devices associated with link 'ppblink' of phone
// book entry 'ppbentry' at the current line of file 'h'.
//
// Returns 0 if successful, otherwise a non-zero error code.
//
{ DWORD dwErr, dwFlags = 0; PBDEVICETYPE type;
type = ppblink->pbport.pbdevicetype; dwFlags = ppblink->pbport.dwFlags;
if (type == PBDT_Isdn) { // ISDN ports use a single device with the same name as the media.
//
if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(ISDN_TXT) )) != 0) { return dwErr; }
if ((dwErr = InsertPhoneList( h, ppblink->pdtllistPhones )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_LastSelectedPhone, ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PromoteAlternates, ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_TryNextAlternateOnFail, ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_LineType, ppblink->lLineType )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_Fallback, ppblink->fFallback )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_Compression, ppblink->fCompression )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_Channels, ppblink->lChannels )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_ProprietaryIsdn, ppblink->fProprietaryIsdn )) != 0) { return dwErr; } } else if (type == PBDT_X25) { // Native X.25 ports are assumed to use a single device with the same
// name as the media, i.e. "x25".
//
if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(X25_TXT) )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_X25_Address, ppbentry->pszX25Address )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_X25_UserData, ppbentry->pszX25UserData )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_X25_Facilities, ppbentry->pszX25Facilities )) != 0) { return dwErr; } } else if ( (type == PBDT_Other) || (type == PBDT_Irda) || (type == PBDT_Vpn) || (type == PBDT_Serial) || (type == PBDT_Atm) || (type == PBDT_Parallel) || (type == PBDT_Sonet) || (type == PBDT_Sw56) || (type == PBDT_FrameRelay) || (type == PBDT_PPPoE)) {
//
// If we are looking at a downlevel server (<= win2k) we
// save the device type as media.
//
RAS_RPC *pConnection = (RAS_RPC *) pFile->hConnection; TCHAR *pszDevice = NULL; BOOL bFreeDev = FALSE; if(pFile->hConnection < (HANDLE)VERSION_501) { pszDevice = pszDeviceTypeFromRdt(RdtFromPbdt(type, dwFlags)); } if(NULL == pszDevice) { pszDevice = ppblink->pbport.pszMedia; } else { bFreeDev = TRUE; } // "Other" ports use a single device with the same name as the media.
//
if ((dwErr = InsertGroup( h, GROUPKEY_Device, pszDevice )) != 0) { if (bFreeDev) Free0(pszDevice); return dwErr; }
if ((dwErr = InsertPhoneList( h, ppblink->pdtllistPhones )) != 0) { if (bFreeDev) Free0(pszDevice); return dwErr; }
if ((dwErr = InsertLong( h, KEY_LastSelectedPhone, ppblink->iLastSelectedPhone )) != 0) { if (bFreeDev) Free0(pszDevice); return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PromoteAlternates, ppblink->fPromoteAlternates )) != 0) { if (bFreeDev) Free0(pszDevice); return dwErr; }
if ((dwErr = InsertFlag( h, KEY_TryNextAlternateOnFail, ppblink->fTryNextAlternateOnFail )) != 0) { if (bFreeDev) Free0(pszDevice); return dwErr; }
// For whistler 483290
//
if (bFreeDev) { Free0(pszDevice); } } else { // Serial ports may involve multiple devices, specifically a modem, an
// X.25 dialup PAD, and a post-connect switch. Pre-connect script is
// preserved, though no longer offered by UI.
//
if (ppblink->pbport.fScriptBefore || ppblink->pbport.fScriptBeforeTerminal) { if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(MXS_SWITCH_TXT) )) != 0) { return dwErr; }
if (ppblink->pbport.fScriptBefore) { if ((dwErr = InsertString( h, KEY_Name, ppblink->pbport.pszScriptBefore )) != 0) { return dwErr; } }
if (ppblink->pbport.fScriptBeforeTerminal) { if ((dwErr = InsertFlag( h, KEY_Terminal, ppblink->pbport.fScriptBeforeTerminal )) != 0) { return dwErr; } }
if (ppblink->pbport.fScriptBefore) { if ((dwErr = InsertFlag( h, KEY_Script, ppblink->pbport.fScriptBefore )) != 0) { return dwErr; } } }
if (((type == PBDT_Null) && !(dwFlags & PBP_F_NullModem)) || (type == PBDT_ComPort) ) { if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(MXS_NULL_TXT) )) != 0) { return dwErr; } }
// pmay: 245860
//
// We must save null modems the same way we save modems in
// order to export properties such as connect bps.
//
if ((type == PBDT_Modem) || (dwFlags & PBP_F_NullModem)) { if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(MXS_MODEM_TXT) )) != 0) { return dwErr; }
if ((dwErr = InsertPhoneList( h, ppblink->pdtllistPhones )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_LastSelectedPhone, ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PromoteAlternates, ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_TryNextAlternateOnFail, ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_HwFlow, ppblink->fHwFlow )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_Ec, ppblink->fEc )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_Ecc, ppblink->fEcc )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_Speaker, ppblink->fSpeaker )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_MdmProtocol, ppblink->dwModemProtocol )) != 0) { return dwErr; } }
if (type == PBDT_Pad || (type == PBDT_Modem && ppbentry->pszX25Network)) { if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(MXS_PAD_TXT) )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PAD_Type, ppbentry->pszX25Network )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PAD_Address, ppbentry->pszX25Address )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PAD_UserData, ppbentry->pszX25UserData )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PAD_Facilities, ppbentry->pszX25Facilities )) != 0) { return dwErr; } }
if (ppbentry->fScriptAfter || ppbentry->fScriptAfterTerminal || ppbentry->dwCustomScript) { if ((dwErr = InsertGroup( h, GROUPKEY_Device, TEXT(MXS_SWITCH_TXT) )) != 0) { return dwErr; }
if (ppbentry->fScriptAfter) { if ((dwErr = InsertString( h, KEY_Name, ppbentry->pszScriptAfter )) != 0) { return dwErr; } }
if (ppbentry->fScriptAfterTerminal) { if ((dwErr = InsertFlag( h, KEY_Terminal, ppbentry->fScriptAfterTerminal )) != 0) { return dwErr; } }
if (ppbentry->fScriptAfter) { if ((dwErr = InsertFlag( h, KEY_Script, ppbentry->fScriptAfter )) != 0) { return dwErr; } }
if(ppbentry->dwCustomScript) { if((dwErr = InsertLong( h, KEY_CustomScript, ppbentry->dwCustomScript)) != 0) { return dwErr; } } } }
return 0; }
DWORD InsertFlag( IN HRASFILE h, IN CHAR* pszKey, IN BOOL fValue )
// Insert a key/value line after the current line in file 'h'. The
// inserted line has a key of 'pszKey' and a value of "1" if 'fValue' is
// true or "0" otherwise. If 'pszKey' is NULL a blank line is appended.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ return InsertStringA( h, pszKey, (fValue) ? "1" : "0" ); }
DWORD InsertGroup( IN HRASFILE h, IN CHAR* pszGroupKey, IN TCHAR* pszValue )
// Insert a blank line and a group header with group key 'pszGroupKey' and
// value 'pszValue' after the current line in file 'h'.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the added group header.
//
{ DWORD dwErr;
if ((dwErr = InsertString( h, NULL, NULL )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, pszGroupKey, pszValue )) != 0) { return dwErr; }
return 0; }
DWORD InsertLong( IN HRASFILE h, IN CHAR* pszKey, IN LONG lValue )
// Insert a key/value line after the current line in file 'h'. The
// inserted line has a key of 'pszKey' and a value of 'lValue'. If
// 'pszKey' is NULL a blank line is appended.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ CHAR szNum[ 33 + 1 ];
_ltoa( lValue, szNum, 10 );
return InsertStringA( h, pszKey, szNum ); }
DWORD InsertNetComponents( IN HRASFILE h, IN DTLLIST* pdtllist )
// Inserts the NETCOMPONENTS group and adds lines for the list of net
// component key/value pairs in 'pdtllist' at the current line of file
// 'h'.
//
// Returns 0 if successful, otherwise a non-zero error code.
//
{ DWORD dwErr; DTLNODE* pdtlnode;
// Insert the NETCOMPONENTS group.
//
dwErr = InsertGroup( h, GROUPKEY_NetComponents, TEXT("") ); if (dwErr != 0) { return dwErr; }
// Insert a key/value pair for each listed net component.
//
for (pdtlnode = DtlGetFirstNode( pdtllist ); pdtlnode; pdtlnode = DtlGetNextNode( pdtlnode )) { KEYVALUE* pKv; CHAR* pszKeyA;
pKv = (KEYVALUE* )DtlGetData( pdtlnode ); ASSERT( pKv );
pszKeyA = StrDupAFromT( pKv->pszKey ); if (!pszKeyA) { return ERROR_NOT_ENOUGH_MEMORY; }
dwErr = InsertString( h, pszKeyA, pKv->pszValue ); Free0( pszKeyA ); if (dwErr != 0) { return dwErr; } }
return 0; }
DWORD InsertPhoneList( IN HRASFILE h, IN DTLLIST* pdtllist )
// Insert key/value lines for each PBPHONE node in from 'pdtllist' after
// the current line in file 'h'.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the last one added.
//
{ DWORD dwErr; DTLNODE* pdtlnode;
for (pdtlnode = DtlGetFirstNode( pdtllist ); pdtlnode; pdtlnode = DtlGetNextNode( pdtlnode )) { CHAR* pszValueA; PBPHONE* pPhone;
pPhone = (PBPHONE* )DtlGetData( pdtlnode );
dwErr = InsertString( h, KEY_PhoneNumber, pPhone->pszPhoneNumber ); if (dwErr) { return dwErr; }
dwErr = InsertString( h, KEY_AreaCode, pPhone->pszAreaCode ); if (dwErr) { return dwErr; }
dwErr = InsertLong( h, KEY_CountryCode, pPhone->dwCountryCode ); if (dwErr) { return dwErr; }
dwErr = InsertLong( h, KEY_CountryID, pPhone->dwCountryID ); if (dwErr) { return dwErr; }
dwErr = InsertFlag( h, KEY_UseDialingRules, pPhone->fUseDialingRules ); if (dwErr) { return dwErr; }
dwErr = InsertString( h, KEY_Comment, pPhone->pszComment ); if (dwErr) { return dwErr; } }
return 0; }
DWORD InsertSection( IN HRASFILE h, IN TCHAR* pszSectionName )
// Insert a section header with name 'pszSectionName' and a trailing blank
// line in file 'h' after the current line.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the added section header.
//
{ DWORD dwErr; CHAR* pszSectionNameA; BOOL fStatus;
ASSERT( pszSectionName );
if ((dwErr = InsertString( h, NULL, NULL )) != 0) { return dwErr; }
pszSectionNameA = StrDupAFromT( pszSectionName ); if (!pszSectionNameA) { return ERROR_NOT_ENOUGH_MEMORY; }
fStatus = RasfilePutSectionName( h, pszSectionNameA );
Free( pszSectionNameA );
if (!fStatus) { return ERROR_NOT_ENOUGH_MEMORY; }
if ((dwErr = InsertString( h, NULL, NULL )) != 0) { return dwErr; }
RasfileFindFirstLine( h, RFL_SECTION, RFS_SECTION );
return 0; }
DWORD InsertString( IN HRASFILE h, IN CHAR* pszKey, IN TCHAR* pszValue )
// Insert a key/value line with key 'pszKey' and value 'pszValue' after
// the current line in file 'h'. If 'pszKey' is NULL a blank line is
// appended.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ BOOL fStatus; CHAR* pszValueA;
if (pszValue) { pszValueA = StrDupAFromT( pszValue );
if (!pszValueA) { return ERROR_NOT_ENOUGH_MEMORY; } } else { pszValueA = NULL; }
fStatus = InsertStringA( h, pszKey, pszValueA );
Free0( pszValueA ); return fStatus; }
DWORD InsertStringA( IN HRASFILE h, IN CHAR* pszKey, IN CHAR* pszValue )
// Insert a key/value line with key 'pszKey' and value 'pszValue' after
// the current line in file 'h'. If 'pszKey' is NULL a blank line is
// appended.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the one added.
//
{ if (!RasfileInsertLine( h, "", FALSE )) { return ERROR_NOT_ENOUGH_MEMORY; }
if (!RasfileFindNextLine( h, RFL_ANY, RFS_FILE )) { RasfileFindFirstLine( h, RFL_ANY, RFS_FILE ); }
if (pszKey) { CHAR* pszValueA;
if (!pszValue) { pszValue = ""; }
if (!RasfilePutKeyValueFields( h, pszKey, pszValue )) { return ERROR_NOT_ENOUGH_MEMORY; } }
return 0; }
DWORD InsertStringList( IN HRASFILE h, IN CHAR* pszKey, IN DTLLIST* pdtllistValues )
// Insert key/value lines with key 'pszKey' and values from
// 'pdtllistValues' after the current line in file 'h'.
//
// Returns 0 if successful, otherwise a non-zero error code. The current
// line is the last one added.
//
{ DTLNODE* pdtlnode;
for (pdtlnode = DtlGetFirstNode( pdtllistValues ); pdtlnode; pdtlnode = DtlGetNextNode( pdtlnode )) { CHAR* pszValueA; BOOL fStatus;
if (!RasfileInsertLine( h, "", FALSE )) { return ERROR_NOT_ENOUGH_MEMORY; }
if (!RasfileFindNextLine( h, RFL_ANY, RFS_FILE )) { RasfileFindFirstLine( h, RFL_ANY, RFS_FILE ); }
pszValueA = StrDupAFromT( (TCHAR* )DtlGetData( pdtlnode ) ); if (!pszValueA) { return ERROR_NOT_ENOUGH_MEMORY; }
fStatus = RasfilePutKeyValueFields( h, pszKey, pszValueA );
Free( pszValueA );
if (!fStatus) { return ERROR_NOT_ENOUGH_MEMORY; } }
return 0; }
BOOL IsDeviceLine( IN CHAR* pszText )
// Returns true if the text of the line, 'pszText', indicates the line is
// a DEVICE subsection header, false otherwise.
//
{ return (StrNCmpA( pszText, GROUPID_Device, sizeof(GROUPID_Device) - 1 ) == 0); }
BOOL IsGroup( IN CHAR* pszText )
// Returns true if the text of the line, 'pszText', indicates the line is
// a valid subsection header, false otherwise. The address of this
// routine is passed to the RASFILE library on RasFileLoad.
//
{ return IsMediaLine( pszText ) || IsDeviceLine( pszText ) || IsNetComponentsLine( pszText ); }
BOOL IsMediaLine( IN CHAR* pszText )
// Returns true if the text of the line, 'pszText', indicates the line is
// a MEDIA subsection header, false otherwise.
//
{ return (StrNCmpA( pszText, GROUPID_Media, sizeof(GROUPID_Media) - 1 ) == 0); }
BOOL IsNetComponentsLine( IN CHAR* pszText )
// Returns true if the text of the line, 'pszText', indicates the line is
// a NETCOMPONENTS subsection header, false otherwise.
//
{ return (StrNCmpA( pszText, GROUPID_NetComponents, sizeof(GROUPID_NetComponents) - 1 ) == 0); }
DWORD ModifyEntryList( IN PBFILE* pFile )
// Update all dirty entries in phone book file 'pFile'.
//
// Returns 0 if successful, otherwise a non-zero error code.
//
{ DWORD dwErr = 0; DTLNODE* pdtlnodeEntry; DTLNODE* pdtlnodeLink; HRASFILE h;
h = pFile->hrasfile;
for (pdtlnodeEntry = DtlGetFirstNode( pFile->pdtllistEntries ); pdtlnodeEntry; pdtlnodeEntry = DtlGetNextNode( pdtlnodeEntry )) { PBENTRY* ppbentry = (PBENTRY* )DtlGetData( pdtlnodeEntry );
// if (!ppbentry->fDirty || ppbentry->fCustom)
//for bug 174260
if (!ppbentry->fDirty ) { continue; }
// Delete the current version of the entry, if any.
//
{ CHAR* pszEntryNameA;
ASSERT( ppbentry->pszEntryName ); pszEntryNameA = StrDupAFromT( ppbentry->pszEntryName ); if (!pszEntryNameA) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
if (RasfileFindSectionLine( h, pszEntryNameA, TRUE )) { DeleteCurrentSection( h ); }
Free( pszEntryNameA ); }
// Append a blank line followed by a section header and the entry
// description to the end of the file.
//
RasfileFindLastLine( h, RFL_ANY, RFS_FILE );
if ((dwErr = InsertSection( h, ppbentry->pszEntryName )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_Encoding, (LONG ) EN_Standard )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_Type, (LONG )ppbentry->dwType )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_AutoLogon, ppbentry->fAutoLogon )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_UseRasCredentials, ppbentry->fUseRasCredentials)) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_UID, (LONG )ppbentry->dwDialParamsUID )) != 0) { break; }
if(ppbentry->pGuid) { if ((dwErr = InsertBinary( h, KEY_Guid, (BYTE* )ppbentry->pGuid, sizeof( GUID ) )) != 0) { return dwErr; } }
if ((dwErr = InsertLong( h, KEY_BaseProtocol, (LONG )ppbentry->dwBaseProtocol )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_VpnStrategy, (LONG )ppbentry->dwVpnStrategy )) != 0) { break; }
#if AMB
if ((dwErr = InsertLong( h, KEY_Authentication, (LONG )ppbentry->dwAuthentication )) != 0) { break; } #endif
if ((dwErr = InsertLong( h, KEY_ExcludedProtocols, (LONG )ppbentry->dwfExcludedProtocols )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_LcpExtensions, ppbentry->fLcpExtensions )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_DataEncryption, ppbentry->dwDataEncryption )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_SwCompression, ppbentry->fSwCompression )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_NegotiateMultilinkAlways, ppbentry->fNegotiateMultilinkAlways )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_SkipNwcWarning, ppbentry->fSkipNwcWarning )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_SkipDownLevelDialog, ppbentry->fSkipDownLevelDialog )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_SkipDoubleDialDialog, ppbentry->fSkipDoubleDialDialog )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_DialMode, (LONG )ppbentry->dwDialMode )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_DialPercent, (LONG )ppbentry->dwDialPercent )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_DialSeconds, (LONG )ppbentry->dwDialSeconds )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_HangUpPercent, (LONG )ppbentry->dwHangUpPercent )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_HangUpSeconds, (LONG )ppbentry->dwHangUpSeconds )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_OverridePref, ppbentry->dwfOverridePref )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_RedialAttempts, ppbentry->dwRedialAttempts )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_RedialSeconds, ppbentry->dwRedialSeconds )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_IdleDisconnectSeconds, ppbentry->lIdleDisconnectSeconds )) != 0) { break; }
if ((dwErr = InsertFlag( h, KEY_RedialOnLinkFailure, ppbentry->fRedialOnLinkFailure )) != 0) { break; }
if ((dwErr = InsertLong( h, KEY_CallbackMode, ppbentry->dwCallbackMode )) != 0) { break; }
if ((dwErr = InsertString( h, KEY_CustomDialDll, ppbentry->pszCustomDialDll )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_CustomDialFunc, ppbentry->pszCustomDialFunc )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_CustomDialerName, ppbentry->pszCustomDialerName)) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_AuthenticateServer, ppbentry->fAuthenticateServer )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_ShareMsFilePrint, ppbentry->fShareMsFilePrint )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_BindMsNetClient, ppbentry->fBindMsNetClient )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_SharedPhoneNumbers, ppbentry->fSharedPhoneNumbers )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_GlobalDeviceSettings, ppbentry->fGlobalDeviceSettings)) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PrerequisiteEntry, ppbentry->pszPrerequisiteEntry )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PrerequisitePbk, ppbentry->pszPrerequisitePbk )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_PreferredPort, ppbentry->pszPreferredPort )) != 0) { return dwErr; } if ((dwErr = InsertString( h, KEY_PreferredDevice, ppbentry->pszPreferredDevice )) != 0) { return dwErr; }
//For .Net 639551
if ((dwErr = InsertLong( h, KEY_PreferredBps, ppbentry->dwPreferredBps)) != 0) { return dwErr; } if ((dwErr = InsertFlag( h, KEY_PreferredHwFlow, ppbentry->fPreferredHwFlow)) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PreferredEc, ppbentry->fPreferredEc)) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PreferredEcc, ppbentry->fPreferredEcc)) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_PreferredSpeaker, ppbentry->fPreferredSpeaker)) != 0) { return dwErr; }
//For whistler bug 402522
//
if ((dwErr = InsertLong( h, KEY_PreferredModemProtocol, ppbentry->dwPreferredModemProtocol)) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PreviewUserPw, ppbentry->fPreviewUserPw )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PreviewDomain, ppbentry->fPreviewDomain )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_PreviewPhoneNumber, ppbentry->fPreviewPhoneNumber )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_ShowDialingProgress, ppbentry->fShowDialingProgress )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_ShowMonitorIconInTaskBar, ppbentry->fShowMonitorIconInTaskBar )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_CustomAuthKey, ppbentry->dwCustomAuthKey )) != 0) { return dwErr; }
if(ppbentry->pCustomAuthData) { if ((dwErr = InsertBinary( h, KEY_CustomAuthData, ppbentry->pCustomAuthData, ppbentry->cbCustomAuthData )) != 0) { return dwErr; } }
// Insert the IP addressing parameters for both PPP/SLIP.
//
if ((dwErr = InsertLong( h, KEY_AuthRestrictions, ppbentry->dwAuthRestrictions )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_TypicalAuth, ppbentry->dwTypicalAuth )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_IpPrioritizeRemote, ppbentry->fIpPrioritizeRemote )) != 0) { return dwErr; }
if ((dwErr = InsertFlag( h, KEY_IpHeaderCompression, ppbentry->fIpHeaderCompression )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpAddress, (ppbentry->pszIpAddress) ? ppbentry->pszIpAddress : TEXT("0.0.0.0") )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpDnsAddress, (ppbentry->pszIpDnsAddress) ? ppbentry->pszIpDnsAddress : TEXT("0.0.0.0") )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpDns2Address, (ppbentry->pszIpDns2Address) ? ppbentry->pszIpDns2Address : TEXT("0.0.0.0") )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpWinsAddress, (ppbentry->pszIpWinsAddress) ? ppbentry->pszIpWinsAddress : TEXT("0.0.0.0") )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpWins2Address, (ppbentry->pszIpWins2Address) ? ppbentry->pszIpWins2Address : TEXT("0.0.0.0") )) != 0) { return dwErr; }
// Next two actually used for PPP only.
//
if ((dwErr = InsertLong( h, KEY_IpAddressSource, ppbentry->dwIpAddressSource )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_IpNameSource, ppbentry->dwIpNameSource )) != 0) { return dwErr; }
// Next one actually used for SLIP only.
//
if ((dwErr = InsertLong( h, KEY_IpFrameSize, ppbentry->dwFrameSize )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_IpDnsFlags, ppbentry->dwIpDnsFlags )) != 0) { return dwErr; }
if ((dwErr = InsertLong( h, KEY_IpNbtFlags, ppbentry->dwIpNbtFlags )) != 0) { return dwErr; }
// Whistler bug 300933
//
if ((dwErr = InsertLong( h, KEY_TcpWindowSize, ppbentry->dwTcpWindowSize )) != 0) { return dwErr; }
// Add the use flag
//
if ((dwErr = InsertLong( h, KEY_UseFlags, ppbentry->dwUseFlags )) != 0) { return dwErr; }
// Add IpSec flags for whistler bug 193987 gangz
//
if ((dwErr = InsertLong( h, KEY_IpSecFlags, ppbentry->dwIpSecFlags )) != 0) { return dwErr; }
if ((dwErr = InsertString( h, KEY_IpDnsSuffix, ppbentry->pszIpDnsSuffix)) != 0) { return dwErr; }
// Insert the net components section.
//
InsertNetComponents( h, ppbentry->pdtllistNetComponents );
// Append the MEDIA subsections.
//
for (pdtlnodeLink = DtlGetFirstNode( ppbentry->pdtllistLinks ); pdtlnodeLink; pdtlnodeLink = DtlGetNextNode( pdtlnodeLink )) { PBLINK* ppblink; TCHAR* pszMedia;
ppblink = (PBLINK* )DtlGetData( pdtlnodeLink ); ASSERT( ppblink ); pszMedia = ppblink->pbport.pszMedia;
if ((dwErr = InsertGroup( h, GROUPKEY_Media, pszMedia )) != 0) { break; }
if ((dwErr = InsertString( h, KEY_Port, ppblink->pbport.pszPort )) != 0) { break; }
if (ppblink->pbport.pszDevice) { if ((dwErr = InsertString( h, KEY_Device, ppblink->pbport.pszDevice )) != 0) { break; } }
if ( (ppblink->pbport.pbdevicetype == PBDT_Modem) || (ppblink->pbport.dwFlags & PBP_F_NullModem) ) { if ((dwErr = InsertLong( h, KEY_InitBps, ppblink->dwBps )) != 0) { break; } }
// Append the device subsection lines.
//
RasfileFindLastLine( h, RFL_ANYACTIVE, RFS_GROUP );
if ((dwErr = InsertDeviceList( pFile, h, ppbentry, ppblink )) != 0) { break; }
ppbentry->fDirty = FALSE; } }
return dwErr; }
DWORD ReadBinary( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT BYTE** ppResult, OUT DWORD* pcb )
// Utility routine to read a string value from the next line in the scope
// 'rfscope' with key 'pszKey'. The result is placed in the allocated
// '*ppszResult' buffer. The current line is reset to the start of the
// scope if the call was successful.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case '*ppszResult' is not changed.
// Caller is responsible for freeing the returned '*ppszResult' buffer.
//
{ DWORD cb; DWORD cbLine; CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ] = "\0"; CHAR* pch = NULL; BYTE* pResult = NULL; BYTE* pLineResult = NULL; BYTE* pTmp = NULL;
cb = cbLine = 0;
while (RasfileFindNextKeyLine( h, pszKey, rfscope )) { if (!RasfileGetKeyValueFields( h, NULL, szValue )) { Free0( pResult ); return ERROR_NOT_ENOUGH_MEMORY; }
cbLine = lstrlenA( szValue ); if (cbLine & 1) { Free0( pResult ); return ERROR_CORRUPT_PHONEBOOK; } cbLine /= 2; cb += cbLine;
if (pResult) {
// For whistler 517007
//
pTmp = Realloc( pResult, cb ); if( pTmp ) { pResult = pTmp; } else { Free(pResult); pResult = NULL; } } else { pResult = Malloc( cb ); }
if (!pResult) { return ERROR_NOT_ENOUGH_MEMORY; }
pLineResult = pResult + (cb - cbLine);
pch = szValue; while (*pch != '\0') { *pLineResult = HexValue( *pch++ ) * 16; *pLineResult += HexValue( *pch++ ); ++pLineResult; } }
*ppResult = pResult; *pcb = cb; return 0; }
DWORD ReadDeviceList( IN HRASFILE h, IN STRDUP_T_FROM_A_FUNC pStrDupTFromA, IN OUT PBENTRY* ppbentry, IN OUT PBLINK* ppblink, IN BOOL fUnconfiguredPort, IN BOOL* pfDisableSpeaker )
// Reads all DEVICE subsections the section from the first subsection
// following the current position in phonebook file 'h'. Caller's
// '*ppbentry' and '*ppblink' buffer is loaded with information extracted
// from the subsections. 'FUnconfiguredPort' is true if the port for the
// link was unconfigured. In this case, data found/not-found by this
// routine helps determine whether the link was an MXS modem link.
// 'pfDisableSpeaker' is the address of the old speaker setting or NULL to
// read it from the file.
//
// Returns 0 if successful, ERROR_CORRUPT_PHONEBOOK if any subsection
// other than a DEVICE subsection is encountered, or another non-0 error
// code indicating a fatal error.
//
{ INT i; DWORD dwErr; CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ]; BOOL fPreconnectFound = FALSE; BOOL fModemFound = FALSE; BOOL fPadFound = FALSE; BOOL fPostconnectFound = FALSE; BOOL fDirty = FALSE;
// For each subsection...
//
while (RasfileFindNextLine( h, RFL_GROUP, RFS_SECTION )) { CHAR* pszLine;
pszLine = (CHAR* )RasfileGetLine( h ); if (IsMediaLine( pszLine )) { RasfileFindPrevLine( h, RFL_ANY, RFS_SECTION ); break; }
if (!IsDeviceLine( pszLine )) { return ERROR_CORRUPT_PHONEBOOK; }
RasfileGetKeyValueFields( h, NULL, szValue );
TRACE1( "Reading device group \"%s\"", szValue );
// For whistler 524726
if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, ISDN_TXT, -1, szValue, -1 ) ) { // It's an ISDN device.
//
ppblink->pbport.pbdevicetype = PBDT_Isdn;
if ((dwErr = ReadPhoneList( h, RFS_GROUP, &ppblink->pdtllistPhones, &fDirty )) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_LastSelectedPhone, &ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_PromoteAlternates, &ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_TryNextAlternateOnFail, &ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_LineType, &ppblink->lLineType )) != 0) { return dwErr; }
if (ppblink->lLineType < 0 || ppblink->lLineType > 2) ppblink->lLineType = 0;
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Fallback, &ppblink->fFallback )) != 0) { return dwErr; }
// Default is true if not found. Default for new entry is false,
// so must set this before reading the entry.
//
ppblink->fProprietaryIsdn = TRUE; if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_ProprietaryIsdn, &ppblink->fProprietaryIsdn )) != 0) { return dwErr; }
// If "Channels" is not found assume it's not proprietary. This
// covers a case that never shipped outside the NT group.
//
{ LONG lChannels = -1; if ((dwErr = ReadLong( h, RFS_GROUP, KEY_Channels, &lChannels )) != 0) { return dwErr; }
if (lChannels == -1) { ppblink->fProprietaryIsdn = FALSE; } else { ppblink->lChannels = lChannels; } }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Compression, &ppblink->fCompression )) != 0) { return dwErr; } } else if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, X25_TXT, -1, szValue, -1 ) ) { // It's a native X.25 device.
//
ppblink->pbport.pbdevicetype = PBDT_X25;
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_X25_Address, &ppbentry->pszX25Address )) != 0) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_X25_UserData, &ppbentry->pszX25UserData )) != 0) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_X25_Facilities, &ppbentry->pszX25Facilities )) != 0) { return dwErr; } } else if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, MXS_MODEM_TXT, -1, szValue, -1 ) ) { // It's a MODEM device.
//
ppblink->pbport.pbdevicetype = PBDT_Modem;
if ((dwErr = ReadPhoneList( h, RFS_GROUP, &ppblink->pdtllistPhones, &fDirty )) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_LastSelectedPhone, &ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_PromoteAlternates, &ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_TryNextAlternateOnFail, &ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; }
{ if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_HwFlow, &ppblink->fHwFlow )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Ec, &ppblink->fEc )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Ecc, &ppblink->fEcc )) != 0) { return dwErr; }
if (pfDisableSpeaker) { ppblink->fSpeaker = !*pfDisableSpeaker; } else { if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Speaker, &ppblink->fSpeaker )) != 0) { return dwErr; } } if ((dwErr = ReadLong( h, RFS_GROUP, KEY_MdmProtocol, &ppblink->dwModemProtocol )) != 0) { return dwErr; } }
fModemFound = TRUE; } else if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, MXS_SWITCH_TXT, -1, szValue, -1 ) ) { // It's a SWITCH device.
// Read switch type string.
//
TCHAR* pszSwitch = NULL;
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_Type, &pszSwitch )) != 0) { return dwErr; }
if (pszSwitch) { // It's a pre-NT5 switch.
//
if (!fPreconnectFound && !fModemFound && !fPadFound) { // It's the preconnect switch.
//
if( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, TEXT(SM_TerminalText), -1, pszSwitch, -1 ) ) { ppblink->pbport.fScriptBeforeTerminal = TRUE; Free( pszSwitch ); } else { ppblink->pbport.fScriptBefore = TRUE; ppblink->pbport.pszScriptBefore = pszSwitch; }
fPreconnectFound = TRUE; } else if (!fPostconnectFound) { // It's the postconnect switch, i.e. a login script.
//
if( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, TEXT(SM_TerminalText), -1, pszSwitch, -1 ) ) { ppbentry->fScriptAfterTerminal = TRUE; Free( pszSwitch ); } else { ppbentry->fScriptAfter = TRUE; ppbentry->pszScriptAfter = pszSwitch; }
fPostconnectFound = TRUE; } else { // It's a switch, but it's not in the normal pre- or post-
// connect positions.
//
ppbentry->fCustom = TRUE; Free( pszSwitch ); return 0; } } else { BOOL fTerminal; BOOL fScript; TCHAR* pszName;
// It's an NT5+ switch.
//
fTerminal = FALSE; fScript = FALSE; pszName = NULL;
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Terminal, &fTerminal )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_Script, &fScript )) != 0) { return dwErr; }
if ((dwErr = ReadLong(h, RFS_GROUP, KEY_CustomScript, &ppbentry->dwCustomScript))) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_Name, &pszName )) != 0) { return dwErr; }
if (!fPreconnectFound && !fModemFound && !fPadFound) { // It's the preconnect switch.
//
ppblink->pbport.fScriptBeforeTerminal = fTerminal; ppblink->pbport.fScriptBefore = fScript; ppblink->pbport.pszScriptBefore = pszName;
fPreconnectFound = TRUE; } else if (!fPostconnectFound) { // It's the postconnect switch, i.e. a login script.
//
ppbentry->fScriptAfterTerminal = fTerminal; ppbentry->fScriptAfter = fScript; ppbentry->pszScriptAfter = pszName;
fPostconnectFound = TRUE; } else { // It's a switch, but it's not in the normal pre- or post-
// connect positions.
//
ppbentry->fCustom = TRUE; return 0; } } } else if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, MXS_PAD_TXT, -1, szValue, -1 ) ) { // It's an X.25 PAD device.
//
if (!fModemFound) { ppblink->pbport.pbdevicetype = PBDT_Pad; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_PAD_Type, &ppbentry->pszX25Network )) != 0) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_PAD_Address, &ppbentry->pszX25Address )) != 0) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_PAD_UserData, &ppbentry->pszX25UserData )) != 0) { return dwErr; }
if ((dwErr = ReadString( h, pStrDupTFromA, RFS_GROUP, KEY_PAD_Facilities, &ppbentry->pszX25Facilities )) != 0) { return dwErr; }
fPadFound = TRUE; } else if( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, MXS_NULL_TXT, -1, szValue, -1 ) ) { // It's a null device. Currently, there is no specific null
// information stored.
//
ppblink->pbport.pbdevicetype = PBDT_Null; } else if( (ppblink->pbport.pszDevice[ 0 ] == TEXT('\0')) && ( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, S_WIN9XATM, -1, szValue, -1 ) ) ) { // Whistler 326015 PBK: if ATM device name is NULL, we should seek
// out a device name just like w/serial/ISDN
//
// This section was added to cover a Win9x migration problem. The
// ATM device name is NULL'd during the upgrade because we have no
// way to predict what the name will end up as. We will now use the
// first ATM device name we get from RASMAN, if any.
//
ppblink->pbport.pbdevicetype = PBDT_Atm;
// Read only the phone number strings and hunt flag.
//
if ((dwErr = ReadPhoneList( h, RFS_GROUP, &ppblink->pdtllistPhones, &fDirty )) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_LastSelectedPhone, &ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_PromoteAlternates, &ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_TryNextAlternateOnFail, &ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; } } else { BOOL fSame; CHAR* pszMedia; TCHAR *pszValue;
pszMedia = StrDupAFromT( ppblink->pbport.pszMedia ); if (!pszMedia) { return ERROR_NOT_ENOUGH_MEMORY; }
pszValue = pStrDupTFromA(szValue);
if(!pszValue) { return ERROR_NOT_ENOUGH_MEMORY; }
fSame = ( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, szValue, -1, pszMedia, -1 ) );
Free( pszMedia );
if ( (fSame ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, TEXT("SERIAL"), -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Vpn, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Generic, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_FrameRelay, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Atm, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Sonet, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_SW56, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Irda, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_Parallel, -1, pszValue, -1 ) ) || ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, RASDT_PPPoE, -1, pszValue, -1 ) ) )//end of if()
{ Free(pszValue); // It's an "other" device.
//
if(PBDT_None == ppblink->pbport.pbdevicetype) { ppblink->pbport.pbdevicetype = PBDT_Other; }
// Read only the phone number strings and hunt flag.
//
if ((dwErr = ReadPhoneList( h, RFS_GROUP, &ppblink->pdtllistPhones, &fDirty )) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_LastSelectedPhone, &ppblink->iLastSelectedPhone )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_PromoteAlternates, &ppblink->fPromoteAlternates )) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_GROUP, KEY_TryNextAlternateOnFail, &ppblink->fTryNextAlternateOnFail )) != 0) { return dwErr; } } else { Free(pszValue); // Device name doesn't match media so it's a custom type, i.e.
// it wasn't created by us.
//
ppbentry->fCustom = TRUE; } } }
if (ppblink->pbport.pbdevicetype == PBDT_None) { TRACE( "No device section" ); return ERROR_CORRUPT_PHONEBOOK; }
if (fDirty) { ppbentry->fDirty = TRUE; }
return 0; }
DWORD ReadEntryList( IN OUT PBFILE* pFile, IN DWORD dwFlags, IN LPCTSTR pszSection)
// Creates the entry list 'pFile->pdtllistEntries' from previously loaded
// phonebook file 'pFile.hrasfile'.' 'FRouter' is true if router ports
// should be used for comparison/conversion of devices, false otherwise.
//
// Returns 0 if successful, otherwise a non-0 error code.
//
{ DWORD dwErr = 0; BOOL fDirty = FALSE; DTLNODE* pdtlnodeEntry = NULL; DTLNODE* pdtlnodeLink = NULL; PBENTRY* ppbentry; PBLINK* ppblink; CHAR* szValue; BOOL fStatus; BOOL fFoundMedia; BOOL fSectionDeleted; BOOL fOldPhonebook; BOOL fDisableSwCompression; BOOL fDisableModemSpeaker; BOOL fRouter; HRASFILE h; DTLLIST* pdtllistPorts = NULL; DWORD dwfInstalledProtocols; DWORD dwEncoding; DWORD dwEntryType; STRDUP_T_FROM_A_FUNC pDupTFromA = StrDupTFromA; TCHAR* pszCurEntryName; BOOL fOldPhoneNumberParts; TCHAR* pszOldAreaCode; BOOL fOldUseDialingRules; DWORD dwOldCountryID; DWORD dwOldCountryCode; DWORD dwDialUIDOffset;
fOldPhoneNumberParts = FALSE; pszOldAreaCode = NULL; szValue = NULL; dwOldCountryID = 0; dwOldCountryCode = 0; dwDialUIDOffset = 0;
// Make sure our assumption that ISDN phone number keys are equivalent to
// modem phone number keys is correct.
//
ASSERT( ( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, ISDN_PHONENUMBER_KEY, -1, KEY_PhoneNumber, -1 ) ) ); ASSERT( ( CSTR_EQUAL == CompareStringA( LOCALE_INVARIANT, NORM_IGNORECASE, MXS_PHONENUMBER_KEY, -1, KEY_PhoneNumber, -1 ) ) );
h = pFile->hrasfile; ASSERT( h != -1 );
fRouter = !!(dwFlags & RPBF_Router); if ( fRouter ) { //
// if router bit is set, check for protocols to which RasRtr
// or RasSrv is bound
//
dwfInstalledProtocols = GetInstalledProtocolsEx( NULL, TRUE, FALSE, TRUE ); } else { //
// get protocols to which Dial Up Client is bound
//
dwfInstalledProtocols = GetInstalledProtocolsEx( NULL, FALSE, TRUE, FALSE ); }
// Look up a couple flags in the old global section and, if found, apply
// them to the new per-entry equivalents. This will only find anything on
// phonebook upgrade, since all ".XXX" sections are deleted later.
//
fOldPhonebook = FALSE; if (RasfileFindSectionLine( h, GLOBALSECTIONNAME, TRUE )) { fOldPhonebook = TRUE;
fDisableModemSpeaker = FALSE; if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_DisableModemSpeaker, &fDisableModemSpeaker )) != 0) { return dwErr; }
fDisableSwCompression = FALSE; if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_DisableSwCompression, &fDisableSwCompression )) != 0) { return dwErr; }
TRACE2( "Old phonebook: dms=%d,dsc=%d", fDisableModemSpeaker, fDisableSwCompression ); }
if (!(pFile->pdtllistEntries = DtlCreateList( 0L ))) { return ERROR_NOT_ENOUGH_MEMORY; }
// XP 339346
//
if (! (szValue = (CHAR*)Malloc( (RAS_MAXLINEBUFLEN + 1) * sizeof(CHAR)))) { DtlDestroyList(pFile->pdtllistEntries, NULL); pFile->pdtllistEntries = NULL; return ERROR_NOT_ENOUGH_MEMORY; }
// For each connectoid section in the file...
//
fSectionDeleted = FALSE; for (fStatus = RasfileFindFirstLine( h, RFL_SECTION, RFS_FILE ); fStatus; fSectionDeleted || (fStatus = RasfileFindNextLine( h, RFL_SECTION, RFS_FILE ))) { fSectionDeleted = FALSE;
// Read the entry name (same as section name), skipping over any
// sections beginning with dot. These are reserved for special
// purposes (like the old global section).
//
if (!RasfileGetSectionName( h, szValue )) { // Get here only when the last section in the file is deleted
// within the loop.
//
break; }
TRACE1( "ENTRY: Reading \"%s\"", szValue );
if (szValue[ 0 ] == '.') { TRACE1( "Obsolete section %s deleted", szValue ); DeleteCurrentSection( h ); fSectionDeleted = TRUE; continue; }
// Figure out if this entry was saved with ansi or
// utf8 encoding
//
dwEncoding = EN_Ansi; if ((dwErr = ReadLong( h, RFS_SECTION, KEY_Encoding, (LONG* )&dwEncoding )) != 0) { break; }
// Read in the type
//
dwEntryType = RASET_Phone; if ((dwErr = ReadLong( h, RFS_SECTION, KEY_Type, (LONG* )&dwEntryType )) != 0) { break; }
if (dwEncoding == EN_Ansi) { // We need to write the entry out in UTF8 for localization
// reasons, so mark it dirty since it has the wrong encoding.
//
pDupTFromA = StrDupTFromAUsingAnsiEncoding; } else { pDupTFromA = StrDupTFromA; }
// Get the current entry name
//
pszCurEntryName = pDupTFromA( szValue ); if (pszCurEntryName == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
// Make sure this is the entry that the user requested
//
// for BVT break bug 528488 gangz
// It's my bad!!!
if ( pszSection && ( CSTR_EQUAL != CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, pszCurEntryName, -1, pszSection, -1 ) ) ) { Free(pszCurEntryName); continue; }
// Create the type of node requested in the flags
//
if (dwFlags & RPBF_HeadersOnly) { DtlPutListCode( pFile->pdtllistEntries, RPBF_HeadersOnly ); pdtlnodeEntry = DtlCreateNode( pszCurEntryName, 0L ); if (!pdtlnodeEntry ) { Free( pszCurEntryName ); dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
DtlAddNodeLast( pFile->pdtllistEntries, pdtlnodeEntry );
continue; } else if (dwFlags & RPBF_HeaderType) { RASENTRYHEADER * preh; DtlPutListCode( pFile->pdtllistEntries, RPBF_HeaderType ); pdtlnodeEntry = DtlCreateSizedNode(sizeof(RASENTRYHEADER), 0); if (!pdtlnodeEntry ) { Free( pszCurEntryName ); dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
preh = (RASENTRYHEADER *) DtlGetData(pdtlnodeEntry); lstrcpynW( preh->szEntryName, pszCurEntryName, sizeof(preh->szEntryName) / sizeof(WCHAR)); preh->dwEntryType = dwEntryType; Free( pszCurEntryName );
DtlAddNodeLast( pFile->pdtllistEntries, pdtlnodeEntry ); continue; }
// If we reach this point, we know that all phonebook
// info is being requested.
//
if (!(pdtlnodeEntry = CreateEntryNode( FALSE ))) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } // Initialize the entry, name, and type
//
DtlAddNodeLast( pFile->pdtllistEntries, pdtlnodeEntry ); ppbentry = (PBENTRY* )DtlGetData( pdtlnodeEntry ); ppbentry->pszEntryName = pszCurEntryName; ppbentry->dwType = dwEntryType;
// Change default on "upgrade" to "show domain field". See bug 281673.
//
ppbentry->fPreviewDomain = TRUE;
if ((fOldPhonebook) || (dwEncoding == EN_Ansi)) { // Mark all entries dirty when upgrading old phonebooks because
// they all need to have there DialParamUIDs written out.
//
fDirty = ppbentry->fDirty = TRUE; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_AutoLogon, &ppbentry->fAutoLogon )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_UseRasCredentials, &ppbentry->fUseRasCredentials )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_UID, (LONG* )&ppbentry->dwDialParamsUID )) != 0) { break; }
{ GUID* pGuid; DWORD cb;
pGuid = NULL; if ((dwErr = ReadBinary( h, RFS_SECTION, KEY_Guid, (BYTE** )&pGuid, &cb )) != 0) { break; }
if (cb == sizeof(UUID)) { Free0( ppbentry->pGuid ); ppbentry->pGuid = pGuid; } else { fDirty = ppbentry->fDirty = TRUE; } }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_BaseProtocol, (LONG* )&ppbentry->dwBaseProtocol )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_VpnStrategy, (LONG* )&ppbentry->dwVpnStrategy )) != 0) { break; }
#if AMB
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_Authentication, (LONG* )&ppbentry->dwAuthentication )) != 0) { break; } #endif
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_ExcludedProtocols, (LONG * )&ppbentry->dwfExcludedProtocols )) != 0) { break; }
#if AMB
// Automatically mark all installed protocols on AMB-only entries as
// "excluded for PPP connections".
//
if (ppbentry->dwAuthentication == AS_AmbOnly || (ppbentry->dwBaseProtocol == BP_Ppp && (dwfInstalledProtocols & ~(ppbentry->dwfExcludedProtocols)) == 0)) { ppbentry->dwBaseProtocol = BP_Ras; ppbentry->dwfExcludedProtocols = 0; fDirty = ppbentry->fDirty = TRUE; } #else
// AMB support deprecated, see NarenG. If old AMB entry, set framing
// and authentication strategy back to defaults. If calling a non-PPP
// (NT 3.1 or WFW server) it still won't work, but at least this fixes
// someone who accidently chose AMB.
//
if (ppbentry->dwBaseProtocol == BP_Ras) { ppbentry->dwBaseProtocol = BP_Ppp; }
#endif
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_LcpExtensions, &ppbentry->fLcpExtensions )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_DataEncryption, &ppbentry->dwDataEncryption )) != 0) { break; }
if (fOldPhonebook) { ppbentry->fSwCompression = !fDisableSwCompression; } else { if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SwCompression, &ppbentry->fSwCompression )) != 0) { break; } }
fOldUseDialingRules = (BOOL )-1; if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_UseCountryAndAreaCodes, &fOldUseDialingRules )) != 0) { break; }
if (fOldUseDialingRules != (BOOL )-1) { fOldPhoneNumberParts = TRUE;
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_AreaCode, &pszOldAreaCode )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_CountryID, &dwOldCountryID )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_CountryCode, &dwOldCountryCode )) != 0) { break; } }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_NegotiateMultilinkAlways, &ppbentry->fNegotiateMultilinkAlways )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SkipNwcWarning, &ppbentry->fSkipNwcWarning )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SkipDownLevelDialog, &ppbentry->fSkipDownLevelDialog )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SkipDoubleDialDialog, &ppbentry->fSkipDoubleDialDialog )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_DialMode, (LONG* )&ppbentry->dwDialMode )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_DialPercent, (LONG* )&ppbentry->dwDialPercent )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_DialSeconds, (LONG* )&ppbentry->dwDialSeconds )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_HangUpPercent, (LONG* )&ppbentry->dwHangUpPercent )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_HangUpSeconds, (LONG* )&ppbentry->dwHangUpSeconds )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_OverridePref, (LONG* )&ppbentry->dwfOverridePref )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_RedialAttempts, (LONG* )&ppbentry->dwRedialAttempts )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_RedialSeconds, (LONG* )&ppbentry->dwRedialSeconds )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IdleDisconnectSeconds, &ppbentry->lIdleDisconnectSeconds )) != 0) { break; }
// If this "idle seconds" is non-zero set it's override bit
// explicitly. This is necessary for this field only, because it
// existed in entries created before the override bits were
// implemented.
//
if (ppbentry->lIdleDisconnectSeconds != 0) { ppbentry->dwfOverridePref |= RASOR_IdleDisconnectSeconds; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_RedialOnLinkFailure, &ppbentry->fRedialOnLinkFailure )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_CallbackMode, (LONG* )&ppbentry->dwCallbackMode )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_CustomDialDll, &ppbentry->pszCustomDialDll )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_CustomDialFunc, &ppbentry->pszCustomDialFunc )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_CustomDialerName, &ppbentry->pszCustomDialerName )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_AuthenticateServer, &ppbentry->fAuthenticateServer )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_ShareMsFilePrint, &ppbentry->fShareMsFilePrint )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_BindMsNetClient, &ppbentry->fBindMsNetClient )) != 0) { break; }
{ ppbentry->fSharedPhoneNumbers = (BOOL )-1;
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SharedPhoneNumbers, &ppbentry->fSharedPhoneNumbers )) != 0) { break; } }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_GlobalDeviceSettings, &ppbentry->fGlobalDeviceSettings)) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PrerequisiteEntry, &ppbentry->pszPrerequisiteEntry )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PrerequisitePbk, &ppbentry->pszPrerequisitePbk )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PreferredPort, &ppbentry->pszPreferredPort )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PreferredDevice, &ppbentry->pszPreferredDevice )) != 0) { break; }
//For .Net 639551
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PreferredBps, &ppbentry->dwPreferredBps)) != 0) { return dwErr; } if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreferredHwFlow, &ppbentry->fPreferredHwFlow)) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreferredEc, &ppbentry->fPreferredEc)) != 0) { return dwErr; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreferredEcc, &ppbentry->fPreferredEcc)) != 0) { return dwErr; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PreferredSpeaker, &ppbentry->fPreferredSpeaker)) != 0) { return dwErr; }
//For whistler bug 402522
//
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PreferredModemProtocol, &ppbentry->dwPreferredModemProtocol)) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreviewUserPw, &ppbentry->fPreviewUserPw )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreviewDomain, &ppbentry->fPreviewDomain )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PreviewPhoneNumber, &ppbentry->fPreviewPhoneNumber )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_ShowDialingProgress, &ppbentry->fShowDialingProgress )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_ShowMonitorIconInTaskBar, &ppbentry->fShowMonitorIconInTaskBar )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_CustomAuthKey, (LONG* )&ppbentry->dwCustomAuthKey )) != 0) { break; }
if ((dwErr = ReadBinary( h, RFS_SECTION, KEY_CustomAuthData, &ppbentry->pCustomAuthData, &ppbentry->cbCustomAuthData )) != 0) { break; }
if (fOldPhonebook) { // Look for the old PPP keys.
//
if (ppbentry->dwBaseProtocol == BP_Ppp) { if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PppTextAuthentication, &ppbentry->dwAuthRestrictions )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PppIpPrioritizeRemote, &ppbentry->fIpPrioritizeRemote )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_PppIpVjCompression, &ppbentry->fIpHeaderCompression )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PppIpAddress, &ppbentry->pszIpAddress )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PppIpAddressSource, &ppbentry->dwIpAddressSource )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PppIpDnsAddress, &ppbentry->pszIpDnsAddress )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PppIpDns2Address, &ppbentry->pszIpDns2Address )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PppIpWinsAddress, &ppbentry->pszIpWinsAddress )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_PppIpWins2Address, &ppbentry->pszIpWins2Address )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_PppIpNameSource, &ppbentry->dwIpNameSource )) != 0) { break; } }
// Look for the old SLIP keys.
//
if (ppbentry->dwBaseProtocol == BP_Slip) { if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SlipHeaderCompression, &ppbentry->fIpHeaderCompression )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_SlipPrioritizeRemote, &ppbentry->fIpPrioritizeRemote )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_SlipFrameSize, &ppbentry->dwFrameSize )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_SlipIpAddress, &ppbentry->pszIpAddress )) != 0) { break; } }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_User, &ppbentry->pszOldUser )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_Domain, &ppbentry->pszOldDomain )) != 0) { break; } } else { // Look for the new IP names.
//
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_AuthRestrictions, &ppbentry->dwAuthRestrictions )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_TypicalAuth, &ppbentry->dwTypicalAuth )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_IpPrioritizeRemote, &ppbentry->fIpPrioritizeRemote )) != 0) { break; }
if ((dwErr = ReadFlag( h, RFS_SECTION, KEY_IpHeaderCompression, &ppbentry->fIpHeaderCompression )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpAddress, &ppbentry->pszIpAddress )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpDnsAddress, &ppbentry->pszIpDnsAddress )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpDns2Address, &ppbentry->pszIpDns2Address )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpWinsAddress, &ppbentry->pszIpWinsAddress )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpWins2Address, &ppbentry->pszIpWins2Address )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpAddressSource, &ppbentry->dwIpAddressSource )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpNameSource, &ppbentry->dwIpNameSource )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpFrameSize, &ppbentry->dwFrameSize )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpDnsFlags, &ppbentry->dwIpDnsFlags )) != 0) { break; }
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpNbtFlags, &ppbentry->dwIpNbtFlags )) != 0) { break; }
// Whistler bug 300933
//
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_TcpWindowSize, &ppbentry->dwTcpWindowSize )) != 0) { break; }
// Read the use flags
//
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_UseFlags, (LONG* )&ppbentry->dwUseFlags )) != 0) { break; }
//Add an IPSecFlags for whistler bug 193987 gangz
//
if ((dwErr = ReadLong( h, RFS_SECTION, KEY_IpSecFlags, (LONG* )&ppbentry->dwIpSecFlags )) != 0) { break; }
if ((dwErr = ReadString( h, pDupTFromA, RFS_SECTION, KEY_IpDnsSuffix, &ppbentry->pszIpDnsSuffix )) != 0) { break; } }
// Read the NETCOMPONENTS items.
//
ReadNetComponents( h, ppbentry->pdtllistNetComponents );
// MEDIA subsections.
//
fFoundMedia = FALSE;
//Load system ports into pdtllistPorts
//
if (!pdtllistPorts) { dwErr = LoadPortsList2( (fRouter) ? (pFile->hConnection) : NULL, &pdtllistPorts, fRouter );
if (dwErr != 0) { break; } }
//Loop over each media (media + device) section in a connectoid section
//
for (;;) { TCHAR* pszDevice; PBPORT* ppbport;
if (!RasfileFindNextLine( h, RFL_GROUP, RFS_SECTION ) || !IsMediaLine( (CHAR* )RasfileGetLine( h ) )) { if (fFoundMedia) { // Out of media groups, i.e. "links", but found at least
// one. This is the successful exit case.
//
break; }
// First subsection MUST be a MEDIA subsection. Delete
// non-conforming entries as invalid.
//
TRACE( "No media section?" ); DeleteCurrentSection( h ); fSectionDeleted = TRUE; DtlRemoveNode( pFile->pdtllistEntries, pdtlnodeEntry ); DestroyEntryNode( pdtlnodeEntry ); break; }
// Create a default link node and add it to the list.
//
if (!(pdtlnodeLink = CreateLinkNode())) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
DtlAddNodeLast( ppbentry->pdtllistLinks, pdtlnodeLink ); ppblink = (PBLINK* )DtlGetData( pdtlnodeLink );
RasfileGetKeyValueFields( h, NULL, szValue ); TRACE1( "Reading media group \"%s\"", szValue );
if ((dwErr = ReadString( h, pDupTFromA, RFS_GROUP, KEY_Port, &ppblink->pbport.pszPort )) != 0) { break; }
//
// If this is a Direct Connect Entry default the entry type
// of the port to some direct connect device. We will default
// to Parallel port. In the case of a Broadband entry default
// to PPPoE.
//
if(RASET_Direct == ppbentry->dwType) { ppblink->pbport.pbdevicetype = PBDT_Parallel; } else if (RASET_Broadband == ppbentry->dwType) { ppblink->pbport.pbdevicetype = PBDT_PPPoE; }
if (!ppblink->pbport.pszPort) { // No port. Blow away corrupt section and go on to the next
// one.
//
TRACE( "No port key? (section deleted)" ); dwErr = 0; DeleteCurrentSection( h ); fSectionDeleted = TRUE; DtlRemoveNode( pFile->pdtllistEntries, pdtlnodeEntry ); DestroyEntryNode( pdtlnodeEntry ); break; }
{ pszDevice = NULL; if ((dwErr = ReadString( h, pDupTFromA, RFS_GROUP, KEY_Device, &pszDevice )) != 0) { break; }
ppblink->pbport.pszDevice = pszDevice; TRACE1( "%s link format", (pszDevice) ? "New" : "Old" ); }
TRACEW1( "Port=%s", ppblink->pbport.pszPort );
//
// pmay: 226594
//
// If the device is one of them magic nt4-style null modems,
// upgrade it to a null modem and update the entry type.
//
if ((pszDevice) && (_tcsstr( pszDevice, TEXT("Dial-Up Networking Serial Cable between 2 PCs"))) ) { ppbport = PpbportFromNullModem( pdtllistPorts, ppblink->pbport.pszPort, ppblink->pbport.pszDevice );
if (ppbport != NULL) { ChangeEntryType( ppbentry, RASET_Direct ); fDirty = ppbentry->fDirty = TRUE; } }
//
// Otherwise, match the port up with the device name.
//
else { ppbport = PpbportFromPortAndDeviceName( pdtllistPorts, ppblink->pbport.pszPort, ppblink->pbport.pszDevice ); }
if ( ( ppbport ) && ( PbportTypeMatchesEntryType(ppbport, ppbentry) ) ) { if (lstrcmp( ppbport->pszPort, ppblink->pbport.pszPort ) != 0) { // The phonebook had an old-style port name. Mark the
// entry for update with the new port name format.
//
TRACEW1( "Port=>%s", ppblink->pbport.pszPort ); fDirty = ppbentry->fDirty = TRUE; }
dwErr = CopyToPbport( &ppblink->pbport, ppbport ); if (dwErr != 0) { break; } } else { // If no port is matched, it could be a vpn or isdn from a
// nt4 upgrade We haven't changed anything else in nt5. Check
// for these cases and upgrade the port.
//
ppbport = PpbportFromNT4PortandDevice( pdtllistPorts, ppblink->pbport.pszPort, ppblink->pbport.pszDevice);
if( (NULL != ppbport) && (PbportTypeMatchesEntryType(ppbport, ppbentry))) { fDirty = ppbentry->fDirty = TRUE; dwErr = CopyToPbport(&ppblink->pbport, ppbport);
if(dwErr != 0) { break; } } else {
TRACE( "Port not configured" ); ppblink->pbport.fConfigured = FALSE;
// Assign unconfigured port the media we read earlier.
//
Free0( ppblink->pbport.pszMedia ); ppblink->pbport.pszMedia = pDupTFromA( szValue ); if (!ppblink->pbport.pszMedia) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } } }
if ((!ppbport) || (ppblink->pbport.pbdevicetype == PBDT_Modem) || (ppblink->pbport.dwFlags & PBP_F_NullModem) ) { // pmay: 260579. dwBps has to be initialized to zero in order
// for Rao's fix to 106837 (below) to work.
DWORD dwBps = 0;
SetDefaultModemSettings( ppblink );
if ((dwErr = ReadLong( h, RFS_GROUP, KEY_InitBps, &dwBps )) != 0) { break; }
// If the phonebook returns a 0 value, the case when the entry
// is created programmatically, then we stick with the default
// bps. RAID nt5 106837. (RaoS)
//
if ( 0 != dwBps ) { ppblink->dwBps = dwBps; } }
// DEVICE subsections.
// At this point ppblink->pbport contains information from the
// matching port in the configured port list or defaults with
// pszMedia and pszDevice filled in. ReadDeviceList fills in the
// pbdevicetype, and if it's an unconfigured port, the unimodem or
// MXS modem flag.
//
dwErr = ReadDeviceList( h, pDupTFromA, ppbentry, ppblink, !ppbport, (fOldPhonebook) ? &fDisableModemSpeaker : NULL );
if (dwErr == ERROR_CORRUPT_PHONEBOOK) { // Blow away corrupt section and go on to the next one.
//
dwErr = 0; DeleteCurrentSection( h ); fSectionDeleted = TRUE; DtlRemoveNode( pFile->pdtllistEntries, pdtlnodeEntry ); DestroyEntryNode( pdtlnodeEntry ); break; } else if (dwErr != 0) { break; }
if (fOldPhonebook && ppbentry->dwBaseProtocol == BP_Slip) { // Set an after-dial terminal when upgrading old phonebooks.
// This was implied in the old format.
//
TRACE( "Add SLIP terminal" ); ppbentry->fScriptAfterTerminal = TRUE; }
if (!ppbport) { DTLNODE* pdtlnode;
// This is an old-format link not in the list of installed
// ports. Change it to the first device of the same device
// type or to an "unknown" device of that type. Note this is
// what converts "Any port".
//
//Loop over each loaded System Port
for (pdtlnode = DtlGetFirstNode( pdtllistPorts ); pdtlnode; pdtlnode = DtlGetNextNode( pdtlnode )) { ppbport = (PBPORT* )DtlGetData( pdtlnode ); // comments for bug 247189 234154 gangz
// Look for a system port has a matching pbdevicetype to the
// phonebook port
//
if (ppbport->pbdevicetype == ppblink->pbport.pbdevicetype) { // Don't convert two links of the entry to use the
// same port. If there aren't enough similar ports,
// the overflow will be left "unknown". (bug 63203).
//
//Comments for bug 247189 234154 gangz
// FILTER DUPE#1
// Look for a system port which is never used by the
// links read before the current one loaded from phonebook
//
DTLNODE* pNodeL;
for (pNodeL = DtlGetFirstNode( ppbentry->pdtllistLinks ); pNodeL; pNodeL = DtlGetNextNode( pNodeL )) { PBLINK* pLink = DtlGetData( pNodeL );
{ if ( (pLink->pbport.fConfigured) && // 373745
(lstrcmp( pLink->pbport.pszPort, ppbport->pszPort ) == 0) ) { break; } } }
if (!pNodeL) { //For whistler bug 247189 234254 gangz
//First we create a DUN on Com1 with no modem installed
//then create a DCC guest on Com2. A null modem will
//be installed on Com2, then this DUN is changed to
//be DCC type and also switches to use Com2's null
//modem which is only for DCC connections.
//
//The basic problem is:
//We cannot copy a system port just according to its
//pbdevicetype, we should also check its dwType
//because (1) NULL modem is not a modem for DUN, it's just for
// DCC Connection.
// (2) When creating NULL Modem, its pbdevicetype is
// assigned to RDT_Modem
// Then, we need also check if the dwType of the
// system port matches that of phonebook port
//
//Besides: file.c is in pbk.lib which is linked to both rasdlg.dll
//loaded into explorer and rasapi32.dll hosted by one of the
//svchost.exe!!!
if (ppblink->pbport.dwType == ppbport->dwType) { TRACE( "Port converted" ); dwErr = CopyToPbport( &ppblink->pbport, ppbport );
if ((ppblink->pbport.pbdevicetype == PBDT_Modem) || (ppblink->pbport.dwFlags & PBP_F_NullModem) ) { SetDefaultModemSettings( ppblink ); } fDirty = ppbentry->fDirty = TRUE; break; } }//end of if (!pNodeL) {}
}//end of if (ppbport->pbdevicetype == ppblink->pbport.pbdevicetype)
}//End of //Loop over each loaded System Port
// pmay: 383038
//
// We only want to fall into the following path if the type
// is Direct. Rao checked in the following path with the
// intention that a DCC connection not be rolled into a MODEM
// connection if another DCC device was present on the system.
//
if ( (ppbentry->dwType == RASET_Direct) || (ppbentry->dwType == RASET_Broadband)) { // If we don't find a port with the same devicetype try to find
// a port with the same entry type
//
for(pdtlnode = DtlGetFirstNode( pdtllistPorts); pdtlnode; pdtlnode = DtlGetNextNode(pdtlnode)) { DWORD dwType;
ppbport = (PBPORT *) DtlGetData(pdtlnode);
dwType = EntryTypeFromPbport( ppbport );
if(ppbentry->dwType == dwType) { TRACE("Port with same entry type found"); dwErr = CopyToPbport(&ppblink->pbport, ppbport);
fDirty = ppbentry->fDirty = TRUE; break; } } }
if (dwErr != 0) { break; } }
fFoundMedia = TRUE; } //end of Loop over each (media+device) section in a connectoid section
if (dwErr != 0) { break; }
if (!fSectionDeleted) { // pmay: 277801
//
// At this point, the list of pblinks is read in and ready to go.
// Apply the "preferred device" logic. (only applies to singlelink)
//
if (DtlGetNodes(ppbentry->pdtllistLinks) == 1) { PBLINK* pLink; DTLNODE* pNodeL, *pNodeP; pNodeL = DtlGetFirstNode( ppbentry->pdtllistLinks ); pLink = (PBLINK* )DtlGetData( pNodeL );
// If the preferred device has been assigned,
// use it if it exists
//
if (ppbentry->pszPreferredDevice && ppbentry->pszPreferredPort) { // The current device doesn't match the
// preferred device
//
if ((pLink->pbport.pszPort == NULL) || (pLink->pbport.pszDevice == NULL) || (lstrcmpi( pLink->pbport.pszPort, ppbentry->pszPreferredPort)) || (lstrcmpi( pLink->pbport.pszDevice, ppbentry->pszPreferredDevice))) { PBPORT* pPort; // See if the preferred device exists on the
// system
//
for (pNodeP = DtlGetFirstNode( pdtllistPorts ); pNodeP; pNodeP = DtlGetNextNode( pNodeP )) { pPort = (PBPORT*)DtlGetData(pNodeP);
// The preferred device is found! Use it.
//
if ((pPort->pszPort != NULL) && (pPort->pszDevice != NULL) && (lstrcmpi( ppbentry->pszPreferredPort, pPort->pszPort) == 0) && (lstrcmpi( ppbentry->pszPreferredDevice, pPort->pszDevice) == 0)) { dwErr = CopyToPbport(&pLink->pbport, pPort); // For .Net bug 639551 gangz
// Add Preferred modem settings
pLink->dwBps = ppbentry->dwPreferredBps; pLink->fHwFlow = ppbentry->fPreferredHwFlow; pLink->fEc = ppbentry->fPreferredEc; pLink->fEcc = ppbentry->fPreferredEcc; pLink->fSpeaker = ppbentry->fPreferredSpeaker; //For whistler bug 402522 gangz
//Add preferred modem protocol
//
pLink->dwModemProtocol = ppbentry->dwPreferredModemProtocol;
fDirty = ppbentry->fDirty = TRUE; break; } } } }
// pmay: 401398 -- bug postponed so I'm just commenting this out.
//
// If this is a DCC connection, then it is valid to have the
// preferred port set w/o having the prefered device set. This
// will be the case for NULL modems that we install. If the
// preferred port is set for such a connection, force the current
// device to resolve to a null modem on that port.
//
//else if (ppbentry->dwType == RASET_Direct)
//{
// if ((ppbentry->pszPreferredPort) &&
// (!ppbentry->pszPreferredDevice) &&
// (lstrcmpi(
// pLink->pbport.pszPort,
// ppbentry->pszPreferredPort))
// )
// {
// PBPORT* pPort;
//
// // Attempt to resolve the connection to the
// // correct preferred device.
// //
// for (pNodeP = DtlGetFirstNode( pdtllistPorts );
// pNodeP;
// pNodeP = DtlGetNextNode( pNodeP ))
// {
// pPort = (PBPORT*)DtlGetData(pNodeP);
//
// // The preferred device is found! Use it.
// //
// if ((pPort->pszPort != NULL) &&
// (lstrcmpi(
// ppbentry->pszPreferredPort,
// pPort->pszPort) == 0) &&
// (pPort->dwFlags & PBP_F_NullModem))
// {
// dwErr = CopyToPbport(&pLink->pbport, pPort);
// fDirty = ppbentry->fDirty = TRUE;
// break;
// }
// }
// }
//}
// The preferred device is not configured. This will only be
// the case for entries that were created before 277801 was
// resolved or for entries that went multilink->singlelink.
//
// Assign the preferred device as the currently selected
// device.
//
else { if (pLink->pbport.pszPort != NULL) { ppbentry->pszPreferredPort = StrDup(pLink->pbport.pszPort); } if (pLink->pbport.pszDevice != NULL) { ppbentry->pszPreferredDevice = StrDup(pLink->pbport.pszDevice); }
// For .Net 639551
ppbentry->dwPreferredBps = pLink->dwBps; ppbentry->fPreferredHwFlow = pLink->fHwFlow; ppbentry->fPreferredEc = pLink->fEc; ppbentry->fPreferredEcc = pLink->fEcc; ppbentry->fPreferredSpeaker = pLink->fSpeaker; //For whistler bug 402522
//
ppbentry->dwPreferredModemProtocol = pLink->dwModemProtocol; } }
// Translate old one-per-entry phone number part mapping to the
// new one-per-phone-number mapping.
//
if (fOldPhoneNumberParts) { DTLNODE* pNodeL; DTLNODE* pNodeP; PBLINK* pLink; PBPHONE* pPhone;
for (pNodeL = DtlGetFirstNode( ppbentry->pdtllistLinks ); pNodeL; pNodeL = DtlGetNextNode( pNodeL )) { pLink = (PBLINK* )DtlGetData( pNodeL );
for (pNodeP = DtlGetFirstNode( pLink->pdtllistPhones ); pNodeP; pNodeP = DtlGetNextNode( pNodeP )) { pPhone = (PBPHONE* )DtlGetData( pNodeP );
pPhone->fUseDialingRules = fOldUseDialingRules; Free0( pPhone->pszAreaCode ); pPhone->pszAreaCode = StrDup( pszOldAreaCode ); pPhone->dwCountryCode = dwOldCountryCode; pPhone->dwCountryID = dwOldCountryID;
fDirty = ppbentry->fDirty = TRUE; } }
TRACE( "Phone# parts remapped" ); }
// Multiple links only allowed with PPP framing.
//
if (ppbentry->dwBaseProtocol != BP_Ppp && DtlGetNodes( ppbentry->pdtllistLinks ) > 1) { TRACE( "Non-PPP multi-link corrected" ); ppbentry->dwBaseProtocol = BP_Ppp; fDirty = ppbentry->fDirty = TRUE; }
// Make sure entry type and dependent settings are appropriate for
// device list.
//
{ DTLNODE* pdtlnode; PBLINK* ppblinkTmp; DWORD dwType;
pdtlnode = DtlGetFirstNode( ppbentry->pdtllistLinks ); if (pdtlnode) { ppblinkTmp = (PBLINK* )DtlGetData( pdtlnode ); ASSERT( ppblinkTmp ); dwType = EntryTypeFromPbport( &ppblinkTmp->pbport );
if ( RASET_Internet != ppbentry->dwType && dwType != ppbentry->dwType) { TRACE2("Fix entry type, %d to %d", ppbentry->dwType, dwType); ChangeEntryType( ppbentry, dwType ); fDirty = ppbentry->fDirty = TRUE; }
if( (NULL != ppblinkTmp->pbport.pszDevice) && ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, TEXT("RASPPTPM"), -1, ppblinkTmp->pbport.pszDevice, -1 ) ) ) { TRACE1("Fix pptp device name. %s to " "WAN Miniport (PPTP)", ppblinkTmp->pbport.pszDevice);
Free(ppblinkTmp->pbport.pszDevice); ppblinkTmp->pbport.pszDevice = StrDup(TEXT("WAN Miniport (PPTP)"));
ppbentry->dwVpnStrategy = VS_Default;
fDirty = ppbentry->fDirty = TRUE; } } }
// If there was no shared phone number setting (i.e. upgrading an
// NT4.0 or earlier entry), set the flag on when there is a single
// link and off otherwise.
//
if (ppbentry->fSharedPhoneNumbers == (BOOL )-1) { ppbentry->fSharedPhoneNumbers = (DtlGetNodes( ppbentry->pdtllistLinks ) <= 1); fDirty = ppbentry->fDirty = TRUE; }
// Upgrade the authorization restrictions You'll know if you need
// to upgrade the dwAuthRestrictions variable because old phone
// books have this value set to 0 or have some of the bottom 3
// bits set.
//
if ( (ppbentry->dwAuthRestrictions == 0) || (ppbentry->dwAuthRestrictions & 0x7) ) { switch (ppbentry->dwAuthRestrictions) { case AR_AuthEncrypted: case AR_AuthMsEncrypted: { ppbentry->dwAuthRestrictions = AR_F_TypicalSecure; ppbentry->dwTypicalAuth = TA_Secure; break; }
case AR_AuthCustom: { ppbentry->dwAuthRestrictions = AR_F_TypicalCardOrCert; ppbentry->dwTypicalAuth = TA_CardOrCert; break; }
case AR_AuthTerminal: case AR_AuthAny: default: { ppbentry->dwAuthRestrictions = AR_F_TypicalUnsecure; ppbentry->dwTypicalAuth = TA_Unsecure; break; } } TRACE1( "Upgraded dwAuthRestrictions to %x", ppbentry->dwAuthRestrictions); fDirty = ppbentry->fDirty = TRUE; }
if ((ppbentry->dwAuthRestrictions & AR_F_AuthW95MSCHAP) && !(ppbentry->dwAuthRestrictions & AR_F_AuthMSCHAP)) { TRACE( "W95CHAP removed from dwAuthRestrictions" ); ppbentry->dwAuthRestrictions &= ~(AR_F_AuthW95MSCHAP); fDirty = ppbentry->fDirty = TRUE; }
// Upgrade old data encryption settings.
//
switch (ppbentry->dwDataEncryption) { case DE_Mppe40bit: case DE_IpsecDefault: case DE_VpnAlways: case DE_PhysAlways: { ppbentry->dwDataEncryption = DE_Require; fDirty = ppbentry->fDirty = TRUE; break; }
case DE_Mppe128bit: { ppbentry->dwDataEncryption = DE_RequireMax; fDirty = ppbentry->fDirty = TRUE; break; } }
//
// pmay: 233258
//
// Based on registry settings, this entry may need to
// be modified. (upgrade from nt4)
//
if ( fOldPhonebook ) { UpgradeRegistryOptions( (fRouter) ? pFile->hConnection : NULL, ppbentry ); fDirty = ppbentry->fDirty = TRUE; }
// pmay: 422924
//
// Make sure that the network components section is in sync
// with the values written into fBindMsNetClient and
// fShareMsFilePrint
//
{ // If the component is not listed, then the default
// is checked (on) for both settings. see rasdlg\penettab.c
//
BOOL fClient = TRUE, fServer = TRUE; BOOL fEnabled;
// Sync up the ms client value
//
if (FIsNetComponentListed( ppbentry, TEXT("ms_msclient"), &fEnabled, NULL)) { fClient = fEnabled; } if ((!!fClient) != (!!ppbentry->fBindMsNetClient)) { ppbentry->fBindMsNetClient = fClient; fDirty = ppbentry->fDirty = TRUE; }
// Sync up the ms server value
//
if (FIsNetComponentListed( ppbentry, TEXT("ms_server"), &fEnabled, NULL)) { fServer = fEnabled; } if ((!!fServer) != (!!ppbentry->fShareMsFilePrint)) { ppbentry->fShareMsFilePrint = fServer; fDirty = ppbentry->fDirty = TRUE; } }
//
// pmay: 336150
//
// If we translated this entry from ANSI to UTF8, then the
// entry name may have changed. We need to delete the old
// entry name so that there wont be a duplicate.
//
if (dwEncoding == EN_Ansi) { TRACE( "Ansi Encoding? (section deleted)" ); DeleteCurrentSection(h); fSectionDeleted = TRUE; }
// pmay: 387941
//
// Prevent connections from sharing credentials.
//
if (ppbentry->dwDialParamsUID == 0) { ppbentry->dwDialParamsUID = GetTickCount() + dwDialUIDOffset; dwDialUIDOffset++; fDirty = ppbentry->fDirty = TRUE; } } }//End of reading each connectoid section in a phonebook file
if (dwErr != 0) { if (dwFlags & RPBF_HeadersOnly) { DtlDestroyList( pFile->pdtllistEntries, DestroyPszNode ); } else if (dwFlags & RPBF_HeaderType) { DtlDestroyList( pFile->pdtllistEntries, DestroyEntryTypeNode ); } else { DtlDestroyList( pFile->pdtllistEntries, DestroyEntryNode ); } } else if(fDirty) { WritePhonebookFile( pFile, NULL ); }
if (pdtllistPorts) { DtlDestroyList( pdtllistPorts, DestroyPortNode ); }
Free0( pszOldAreaCode ); Free0( szValue );
return dwErr; }
DWORD ReadFlag( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT BOOL* pfResult )
// Utility routine to read a flag value from the next line in the scope
// 'rfscope' with key 'pszKey'. The result is placed in caller's
// '*ppszResult' buffer. The current line is reset to the start of the
// scope if the call was successful.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case '*pfResult' is not changed.
//
{ DWORD dwErr; LONG lResult = *pfResult;
dwErr = ReadLong( h, rfscope, pszKey, &lResult );
if (lResult != (LONG )*pfResult) { *pfResult = (lResult != 0); }
return dwErr; } DWORD ReadLong( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT LONG* plResult )
// Utility routine to read a long integer value from the next line in the
// scope 'rfscope' with key 'pszKey'. The result is placed in caller's
// '*ppszResult' buffer. The current line is reset to the start of the
// scope if the call was successful.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case '*plResult' is not changed.
//
{ CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ]; BOOL fFound;
fFound = RasfileFindNextKeyLine( h, pszKey, rfscope ); if (!fFound) { //DbgPrint( "Pbk Perf: seeking back to top of scope to look for '%s'\n",
// pszKey );
RasfileFindFirstLine( h, RFL_ANY, rfscope ); fFound = RasfileFindNextKeyLine( h, pszKey, rfscope ); }
if (fFound) { if (!RasfileGetKeyValueFields( h, NULL, szValue )) { return ERROR_NOT_ENOUGH_MEMORY; }
*plResult = atol( szValue ); }
return 0; }
VOID ReadNetComponents( IN HRASFILE h, IN DTLLIST* pdtllist )
// Read the list of networking component key/value pairs from the
// NETCOMPONENT group into 'pdtllist'. 'H' is the open RAS:FILE handle
// assumed to be positioned before somewhere before the NETCOMPONENTS
// group in the entry section. The RASFILE 'CurLine' is left just after
// the group.
//
{ if (!RasfilePutLineMark( h, MARK_BeginNetComponentsSearch )) { return; }
if (!RasfileFindNextLine( h, RFL_GROUP, RFS_SECTION ) || !IsNetComponentsLine( (CHAR* )RasfileGetLine( h ) )) { // No NetComponents group. Return 'CurLine' to starting position.
//
while (RasfileGetLineMark( h ) != MARK_BeginNetComponentsSearch) { RasfileFindPrevLine( h, RFL_ANY, RFS_SECTION ); }
RasfilePutLineMark( h, 0 ); return; }
// Found the NETCOMPONENTS group header.
//
while (RasfileFindNextLine( h, RFL_ANY, RFS_GROUP )) { DTLNODE* pdtlnode; CHAR szKey[ RAS_MAXLINEBUFLEN + 1 ]; CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ]; TCHAR* pszKey; TCHAR* pszValue;
if (!RasfileGetKeyValueFields( h, szKey, szValue )) { continue; }
pszKey = StrDupTFromA( szKey ); pszValue = StrDupTFromA( szValue ); if (pszKey && pszValue) { pdtlnode = CreateKvNode( pszKey, pszValue ); if (pdtlnode) { DtlAddNodeLast( pdtllist, pdtlnode ); } } Free0( pszKey ); Free0( pszValue ); } }
DWORD CalculatePhonebookPath( IN LPCTSTR pszPhonebookPath, IN PBUSER* pUser, IN DWORD dwFlags, OUT DWORD* lpdwMode, OUT LPTSTR* ppszFullPath) { DWORD dwErr = NO_ERROR, dwMode; TCHAR szFullPath[MAX_PATH + 1], *pszPath = NULL; BOOL f; PBUSER user;
do { if (pszPhonebookPath) { pszPath = StrDup( pszPhonebookPath ); if (!pszPath) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } dwMode = IsPublicPhonebook(pszPath) ? PBM_System : PBM_Alternate; } else { if (pUser) { f = GetPhonebookPath(pUser, dwFlags, &pszPath, &dwMode ); } else { // Caller didn't provide user preferences but we need them to
// find the phonebook, so look them up ourselves. Note that
// "not winlogon mode" is assumed.
//
dwErr = GetUserPreferences( NULL, &user, FALSE ); if (dwErr != 0) { break; }
f = GetPhonebookPath(&user, dwFlags, &pszPath, &dwMode );
DestroyUserPreferences( &user ); }
if (!f) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; } }
TRACEW1( "path=%s", pszPath ); if (GetFullPathName(pszPath, MAX_PATH, szFullPath, NULL) > 0) { TRACEW1( "full path=%s", szFullPath ); Free(pszPath); pszPath = StrDup(szFullPath);
if(NULL == pszPath) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; } }
// Ok, we've calulated the full path without error. Assign the return
// values
//
*lpdwMode = dwMode; *ppszFullPath = pszPath; }while (FALSE);
// Cleanup
//
{ if (dwErr != NO_ERROR) { Free0( pszPath ); } }
return dwErr; }
#ifdef _PBK_CACHE_
//Synchronize pbkcache's read file-last-write-time
//for bug 559381 and 537369
DWORD GetFileLastWriteTime( IN PWCHAR pwszFileName, OUT FILETIME* pTime ) { HANDLE hFile = NULL; DWORD dwErr = NO_ERROR; BOOL fOk = FALSE; BY_HANDLE_FILE_INFORMATION Info; FILETIME ftTime; BOOL fRet = FALSE; do { // Get the file handle
//
ASSERT( g_hmutexPb ); WaitForSingleObject( g_hmutexPb, INFINITE );
hFile = CreateFileW( pwszFileName, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); break; }
fOk = GetFileInformationByHandle( hFile, &Info); if (!fOk) { dwErr = GetLastError(); break; } } while(FALSE);
if( INVALID_HANDLE_VALUE != hFile ) { CloseHandle(hFile); } if( NO_ERROR == dwErr ) { *pTime = Info.ftLastWriteTime; }
ReleaseMutex( g_hmutexPb );
return dwErr; }
#endif
DWORD ReadPhonebookFile( IN LPCTSTR pszPhonebookPath, IN PBUSER* pUser, IN LPCTSTR pszSection, IN DWORD dwFlags, OUT PBFILE* pFile ) { return ReadPhonebookFileEx( pszPhonebookPath, pUser, pszSection, dwFlags, pFile, NULL); }
DWORD ReadPhonebookFileEx( IN LPCTSTR pszPhonebookPath, IN PBUSER* pUser, IN LPCTSTR pszSection, IN DWORD dwFlags, OUT PBFILE* pFile, OUT OPTIONAL FILETIME* pTime)
// Reads the phonebook file into a list of PBENTRY.
//
// 'PszPhonebookPath' specifies the full path to the RAS phonebook file,
// or is NULL indicating the default phonebook should be used.
//
// 'PUser' is the user preferences used to determine the default phonebook
// path or NULL if they should be looked up by this routine. If
// 'pszPhonebookPath' is non-NULL 'pUser' is ignored. Note that caller
// MUST provide his own 'pUser' in "winlogon" mode.
//
// 'PszSection' indicates that only the section named 'pszSection' should
// be loaded, or is NULL to indicate all sections.
//
// 'DwFlags' options: 'RPBF_ReadOnly' causes the file to be opened for
// reading only. 'RPBF_HeadersOnly' causes only the headers to loaded,
// and the memory image is parsed into a list of strings, unless the flag
// 'RPBF_NoList' is specified.
//
// 'PFile' is the address of caller's file block. This routine sets
// 'pFile->hrasfile' to the handle to the open phonebook, 'pFile->pszPath'
// to the full path to the file mode, 'pFile->dwPhonebookMode' to the mode
// of the file, and 'pFile->pdtllistEntries' to the parsed chain of entry
// blocks.
//
// Returns 0 if successful, otherwise a non-0 error code. On success,
// caller should eventually call ClosePhonebookFile on the returned
// PBFILE*.
//
{ DWORD dwErr = 0; BOOL fFileExists;
TRACE( "ReadPhonebookFile" );
pFile->hrasfile = -1; pFile->pszPath = NULL; pFile->dwPhonebookMode = PBM_System; pFile->pdtllistEntries = NULL;
do { dwErr = CalculatePhonebookPath( pszPhonebookPath, pUser, dwFlags, &(pFile->dwPhonebookMode), &(pFile->pszPath)); if (dwErr != NO_ERROR) { break; } fFileExists = FFileExists( pFile->pszPath );
if ((dwFlags & RPBF_NoCreate) && !fFileExists) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; }
if (!fFileExists) { // The phonebook file does not exist, so we need to create it.
//
HANDLE hFile; SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR pSd = NULL;
// If we are creating the public phonebook file, 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.
//
if (pFile->dwPhonebookMode == PBM_System) { dwErr = DwAllocateSecurityDescriptorAllowAccessToWorld( &pSd); if (dwErr) { break; } }
// Be sure that any directories on the path to the phonebook file
// exist. Otherwise, CreatFile will fail.
//
CreateDirectoriesOnPath( pFile->pszPath, NULL);
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = TRUE;
hFile = CreateFile( pFile->pszPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
Free0(pSd);
if (hFile == INVALID_HANDLE_VALUE) { CloseHandle( hFile ); dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; }
// for whistler 523647 gangz
// Have to check if this handle is for disk file
//
if( FILE_TYPE_DISK != GetFileType( hFile ) ) { CloseHandle( hFile ); dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; } CloseHandle( hFile );
if (pFile->dwPhonebookMode == PBM_System) { TRACE( "System phonebook created." ); } else { TRACE( "User phonebook created." ); } }
// Load the phonebook file into memory. In "write" mode, comments are
// loaded so user's custom comments (if any) will be preserved.
// Normally, there will be none so this costs nothing in the typical
// case.
//
{ DWORD dwMode; CHAR* pszPathA;
dwMode = 0; if (dwFlags & RPBF_ReadOnly) { dwMode |= RFM_READONLY; } else { dwMode |= RFM_CREATE | RFM_LOADCOMMENTS; }
if (dwFlags & RPBF_HeadersOnly) { dwMode |= RFM_ENUMSECTIONS; }
// Read the disk file into a linked list of lines.
//
pszPathA = StrDupAFromTAnsi( pFile->pszPath );
if (pszPathA) { ASSERT( g_hmutexPb ); WaitForSingleObject( g_hmutexPb, INFINITE );
pFile->hrasfile = RasfileLoadEx( pszPathA, dwMode, NULL, IsGroup, pTime);
ReleaseMutex( g_hmutexPb ); }
Free0( pszPathA );
if (pFile->hrasfile == -1) { dwErr = ERROR_CANNOT_LOAD_PHONEBOOK; break; } }
// Parse the linked list of lines
//
if (!(dwFlags & RPBF_NoList)) { // Read the phonebook file
//
dwErr = ReadEntryList( pFile, dwFlags, pszSection ); if (dwErr != NO_ERROR) { break; } } } while (FALSE);
if (dwErr != 0) { //
// If we failed to read entry lists, ReadEntry*List above would
// have cleaned the lists. NULL the lists so that ClosePhonebookFile
// doesn't attempt to free the already freed memory
//
pFile->pdtllistEntries = NULL; ClosePhonebookFile( pFile ); }
TRACE1( "ReadPhonebookFile=%d", dwErr ); return dwErr; }
DWORD ReadPhoneList( IN HRASFILE h, IN RFSCOPE rfscope, OUT DTLLIST** ppdtllist, OUT BOOL* pfDirty )
// Utility routine to read a list of PBPHONE nodes from next lines in the
// scope 'rfscope'. The result is placed in the allocated '*ppdtllist'
// list. The current line is reset to the start of the scope after the
// call. '*pfDirty' is set true if the entry should be re-written.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case 'pdtllistResult' is set to an
// empty list. Caller is responsible for freeing the returned
// '*ppdtllist' list.
//
{ CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ]; DTLNODE* pdtlnode; PBPHONE* pPhone; BOOL fOk;
// Free existing list, if present.
//
if (*ppdtllist) { DtlDestroyList( *ppdtllist, DestroyPhoneNode ); }
if (!(*ppdtllist = DtlCreateList( 0 ))) { return ERROR_NOT_ENOUGH_MEMORY; }
while (RasfileFindNextKeyLine( h, KEY_PhoneNumber, rfscope )) { fOk = FALSE;
do { // Allocate and link a node for the new phone number set.
//
pdtlnode = CreatePhoneNode(); if (!pdtlnode) { break; }
DtlAddNodeLast( *ppdtllist, pdtlnode ); pPhone = (PBPHONE* )DtlGetData( pdtlnode );
// Read the individual fields in the set.
//
if (!RasfileGetKeyValueFields( h, NULL, szValue ) || !(pPhone->pszPhoneNumber = StrDupTFromA( szValue ))) { break; }
if (RasfileFindNextKeyLine( h, KEY_AreaCode, rfscope )) { if (!RasfileGetKeyValueFields( h, NULL, szValue ) || !(pPhone->pszAreaCode = StrDupTFromA( szValue ))) { break; } }
if (RasfileFindNextKeyLine( h, KEY_CountryCode, rfscope )) { DWORD dwCountryCode;
if (!RasfileGetKeyValueFields( h, NULL, szValue )) { break; }
dwCountryCode = atol( szValue ); if (dwCountryCode > 0) { pPhone->dwCountryCode = dwCountryCode; } else { *pfDirty = TRUE; } }
if (RasfileFindNextKeyLine( h, KEY_CountryID, rfscope )) { DWORD dwCountryID;
if (!RasfileGetKeyValueFields( h, NULL, szValue )) { break; }
dwCountryID = atol( szValue ); if (dwCountryID > 0) { pPhone->dwCountryID = dwCountryID; } else { *pfDirty = TRUE; } }
if (RasfileFindNextKeyLine( h, KEY_UseDialingRules, rfscope )) { if (!RasfileGetKeyValueFields( h, NULL, szValue )) { break; }
pPhone->fUseDialingRules = !!(atol( szValue )); }
if (RasfileFindNextKeyLine( h, KEY_Comment, rfscope )) { if (!RasfileGetKeyValueFields( h, NULL, szValue ) || !(pPhone->pszComment = StrDupTFromA( szValue ))) { break; } }
fOk = TRUE;
} while (FALSE);
if (!fOk) { // One of the allocations failed. Clean up.
//
DtlDestroyList( *ppdtllist, DestroyPhoneNode ); *ppdtllist = NULL; return ERROR_NOT_ENOUGH_MEMORY; } }
return 0; }
DWORD ReadString( IN HRASFILE h, IN STRDUP_T_FROM_A_FUNC pStrDupTFromA, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT TCHAR** ppszResult )
// Utility routine to read a string value from the next line in the scope
// 'rfscope' with key 'pszKey'. The result is placed in the allocated
// '*ppszResult' buffer. The current line is reset to the start of the
// scope if the call was successful.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case '*ppszResult' is not changed.
// Caller is responsible for freeing the returned '*ppszResult' buffer.
//
{ CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ]; BOOL fFound;
fFound = RasfileFindNextKeyLine( h, pszKey, rfscope ); if (!fFound) { //DbgPrint( "Pbk Perf: seeking back to top of scope to look for '%s'\n",
// pszKey );
RasfileFindFirstLine( h, RFL_ANY, rfscope ); fFound = RasfileFindNextKeyLine( h, pszKey, rfscope ); }
if (fFound) { if (!RasfileGetKeyValueFields( h, NULL, szValue ) || !(*ppszResult = pStrDupTFromA( szValue ))) { return ERROR_NOT_ENOUGH_MEMORY; } }
return 0; }
DWORD ReadStringList( IN HRASFILE h, IN RFSCOPE rfscope, IN CHAR* pszKey, OUT DTLLIST** ppdtllistResult )
// Utility routine to read a list of string values from next lines in the
// scope 'rfscope' with key 'pszKey'. The result is placed in the
// allocated '*ppdtllistResult' list. The current line is reset to the
// start of the scope after the call.
//
// Returns 0 if successful, or a non-zero error code. "Not found" is
// considered successful, in which case 'pdtllistResult' is set to an
// empty list. Caller is responsible for freeing the returned
// '*ppdtllistResult' list.
//
{ CHAR szValue[ RAS_MAXLINEBUFLEN + 1 ];
// Free existing list, if present.
//
if (*ppdtllistResult) { DtlDestroyList( *ppdtllistResult, DestroyPszNode ); *ppdtllistResult = NULL; }
if (!(*ppdtllistResult = DtlCreateList( 0 ))) { return ERROR_NOT_ENOUGH_MEMORY; }
while (RasfileFindNextKeyLine( h, pszKey, rfscope )) { TCHAR* psz; DTLNODE* pdtlnode;
if (!RasfileGetKeyValueFields( h, NULL, szValue ) || !(psz = StrDupTFromA( szValue ))) { DtlDestroyList( *ppdtllistResult, DestroyPszNode ); *ppdtllistResult = NULL; return ERROR_NOT_ENOUGH_MEMORY; }
if (!(pdtlnode = DtlCreateNode( psz, 0 ))) { Free( psz ); DtlDestroyList( *ppdtllistResult, DestroyPszNode ); *ppdtllistResult = NULL; return ERROR_NOT_ENOUGH_MEMORY; }
DtlAddNodeLast( *ppdtllistResult, pdtlnode ); }
return 0; }
VOID TerminatePbk( void )
// Terminate the PBK library. This routine should be called after all
// PBK library access is complete. See also InitializePbk.
//
{ if (g_hmutexPb) { CloseHandle( g_hmutexPb ); } PbkPathInfoClear(&g_PbkPathInfo);
#ifdef _PBK_CACHE_
PbkCacheCleanup(); #endif
}
DWORD WritePhonebookFile( IN PBFILE* pFile, IN LPCTSTR pszSectionToDelete )
// Write out any dirty globals or entries in 'pFile'. The
// 'pszSectionToDelete' indicates a section to delete or is NULL.
//
// Returns 0 if successful, otherwise a non-zero error code.
//
{ DWORD dwErr; HRASFILE h = pFile->hrasfile;
TRACE( "WritePhonebookFile" );
if (pszSectionToDelete) { CHAR* pszSectionToDeleteA;
pszSectionToDeleteA = StrDupAFromT( pszSectionToDelete ); if (!pszSectionToDeleteA) { return ERROR_NOT_ENOUGH_MEMORY; }
if (RasfileFindSectionLine( h, pszSectionToDeleteA, TRUE )) { DeleteCurrentSection( h ); }
Free( pszSectionToDeleteA ); }
dwErr = ModifyEntryList( pFile ); if (dwErr != 0) { return dwErr; }
{ BOOL f;
ASSERT( g_hmutexPb ); WaitForSingleObject( g_hmutexPb, INFINITE );
f = RasfileWrite( h, NULL );
ReleaseMutex( g_hmutexPb );
if (!f) { return ERROR_CANNOT_WRITE_PHONEBOOK; } }
return 0; }
#ifdef _PBK_CACHE_
DWORD DwReadEntryFromCache( IN LPCTSTR pszPhonebook, IN LPCTSTR pszEntry, IN DWORD dwFlags, OUT DTLNODE **ppdtlnode, OUT OPTIONAL WCHAR **ppszFullPath) { DWORD dwErr = NO_ERROR, dwMode = 0; TCHAR* pszPath = NULL;
dwErr = CalculatePhonebookPath( pszPhonebook, NULL, dwFlags, &dwMode, &pszPath); if (dwErr != NO_ERROR) { return dwErr; } dwErr = PbkCacheGetEntry((WCHAR*)pszPath, (WCHAR*)pszEntry, ppdtlnode); if ((dwErr == NO_ERROR) && (ppszFullPath)) { *ppszFullPath = pszPath; } else { Free0(pszPath); }
return dwErr; }
#endif
// (0 )Reads the entry node from the name and the phoenbook
// file specified. 'pszPhonebook' can be NULL.
// (1) ppdtlnode and pFile cannot be NULL at the same time
// (2) if pFile == NULL, only return entry node to ppdtlnode
// (3) if pFile != NULL && ppdtlnode != NULL, return PBFILE info to pFile and
// return the pszEntry node pointer from pFile->pdtllistEntries to ppdtlnode
//
DWORD DwReadEntryFromSystem( IN LPCTSTR pszPhonebook, IN LPCTSTR pszEntry, IN DWORD dwFlags, IN OUT OPTIONAL PBFILE *pFile, OUT DTLNODE **ppdtlnode, OUT OPTIONAL WCHAR **ppszFullPath) { DWORD dwErr = NO_ERROR; DTLNODE *pdtlnode = NULL, *pCopyNode = NULL; PBFILE tmpFile, * pTmpFile = NULL; BOOL fFileOpened = FALSE; // For .Net bug 559381 (oobe bug) turn off pbkCache
// If we never find it is necessary in the future,
// (1) remove all the #ifdef _PBK_CACHE blocks
// (2) remove PbkCache.cpp/h
//
#ifdef _PBK_CACHE_
if (fReadFromCache) { return DwReadEntryFromCache( pszPhonebook, pszEntry, dwFlags, ppdtlnode, ppszFullPath); } #endif
if( NULL == ppdtlnode && NULL == pFile ) { return ERROR_INVALID_PARAMETER; } // Initialize output parameters
//
if( ppdtlnode ) *ppdtlnode = NULL; if( ppszFullPath ) *ppszFullPath = NULL; if( ppszFullPath ) { TCHAR* pszPath = NULL; DWORD dwMode = 0; dwErr = CalculatePhonebookPath( pszPhonebook, NULL, dwFlags, &dwMode, &pszPath); if (dwErr != NO_ERROR) { return dwErr; } if ((dwErr == NO_ERROR) && (ppszFullPath)) { *ppszFullPath = pszPath; } else { Free(pszPath); } }
// For bug 559381
// Only output ppdtlnode
if ( NULL == pFile ) { fFileOpened = FALSE; do { ZeroMemory( &tmpFile, sizeof(tmpFile)); pTmpFile = &tmpFile; pTmpFile->hrasfile = -1; dwErr = ReadPhonebookFile( pszPhonebook, NULL, NULL, dwFlags, pTmpFile);
if (SUCCESS != dwErr) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; }
fFileOpened = TRUE; //
// Find the specified phonebook entry.
//
pdtlnode = EntryNodeFromName( pTmpFile->pdtllistEntries, pszEntry);
if( NULL == pdtlnode ) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; break; }
//
// Copy this entry to output parameter ppdtlnode
//
pCopyNode = DuplicateEntryNode( pdtlnode );
if( NULL == pCopyNode ) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
*ppdtlnode = pCopyNode;
} while(FALSE);
// Free the memory
if( fFileOpened ) { ClosePhonebookFile(pTmpFile); } } else { // then pFile is not NULL
// if ppdtlnode is not NULL either, return the correct node
// in pFile->pdtllistEntries to ppdtlnode
//
fFileOpened = FALSE; do { dwErr = ReadPhonebookFile( pszPhonebook, NULL, NULL, dwFlags, pFile);
if ( NO_ERROR != dwErr) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; break; }
fFileOpened = TRUE; //
// Find the specified phonebook entry.
//
pdtlnode = EntryNodeFromName( pFile->pdtllistEntries, pszEntry);
if( NULL == pdtlnode ) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; break; }
if( ppdtlnode ) { *ppdtlnode = pdtlnode; }
} while(FALSE);
if( NO_ERROR != dwErr && fFileOpened ) { ClosePhonebookFile( pFile ); }
} //end of if..else
return dwErr; }
DWORD DwFindEntryInPersonalPhonebooks( IN LPCTSTR pszEntry, IN DWORD dwFlags, IN BOOL fLegacy, OUT OPTIONAL PBFILE *pFile, OUT OPTIONAL DTLNODE **ppdtlnode, OUT OPTIONAL WCHAR** ppszPbkPath)
// Tries to find the entry specified by pszEntry in the
// pbk files located in the users profile if fLegacy is
// false. Otherwise it looks in pbks in System32\Ras for
// the entry.
//
{ DWORD dwErr = SUCCESS;
//
// consider allocing the paths below.
// Too much on the stack otherwise.
//
TCHAR szFilePath[MAX_PATH + 1]; TCHAR szFileName[MAX_PATH + 1]; BOOL fFirstTime = TRUE;
WIN32_FIND_DATA wfdData;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
ZeroMemory((PBYTE) szFilePath, sizeof(szFilePath)); ZeroMemory((PBYTE) szFileName, sizeof(szFileName));
#if DBG
ASSERT(NULL != ppdtlnode); #endif
*ppdtlnode = NULL;
//
// Get the personal phonebook directory if its not
// legacy
//
if(fLegacy) { UINT cch = GetSystemDirectory(szFileName, MAX_PATH + 1);
if ( (cch == 0) || (cch > (MAX_PATH - (5 + 8 + 1 + 3)))) { goto done; }
lstrcat(szFileName, TEXT("\\Ras\\")); } else if(!GetPhonebookDirectory(PBM_Personal, szFileName)) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; goto done; }
if(lstrlen(szFilePath) > (MAX_PATH - lstrlen(TEXT("*.pbk")))) { dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; goto done; }
wsprintf(szFilePath, TEXT("%s%s"), szFileName, TEXT("*.pbk"));
//
// Look for files with .pbk extension in this
// directory.
//
while(SUCCESS == dwErr) { if(INVALID_HANDLE_VALUE == hFindFile) { hFindFile = FindFirstFile(szFilePath, &wfdData);
if(INVALID_HANDLE_VALUE == hFindFile) { dwErr = GetLastError(); break; } } else { if(!FindNextFile(hFindFile, &wfdData)) { dwErr = GetLastError(); break; } }
if(FILE_ATTRIBUTE_DIRECTORY & wfdData.dwFileAttributes) { continue; }
if(lstrlen(wfdData.cFileName) > (MAX_PATH - lstrlen(szFileName))) { //
// Modify RAS code to take into account file names
// larger than MAX_PATH.
//
dwErr = ERROR_CANNOT_OPEN_PHONEBOOK; goto done; }
//
// Construct full path name to the pbk file
//
wsprintf(szFilePath, TEXT("%s\\%s"), szFileName, wfdData.cFileName);
//
// Ignore the phonebook if its router.pbk
//
if( (fLegacy) && (IsRouterPhonebook(szFilePath))) { continue; }
dwErr = DwReadEntryFromSystem( szFilePath, pszEntry, dwFlags, pFile, ppdtlnode, ppszPbkPath);
if( (SUCCESS == dwErr) && (NULL != *ppdtlnode)) { break; } else { //
// For some reason we were not able to
// read the entry - entry not there,
// failed to open the phonebook. In all
// error cases try to open the next pbk
// file.
//
dwErr = SUCCESS; } }
done:
if(NULL == *ppdtlnode) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; }
if(INVALID_HANDLE_VALUE != hFindFile) { FindClose(hFindFile); }
return dwErr; }
DWORD DwEnumeratePhonebooksFromDirectory( TCHAR *pszDir, DWORD dwFlags, PBKENUMCALLBACK pfnCallback, VOID *pvContext ) { DWORD dwErr = SUCCESS;
//
// consider allocing the paths below.
// Too much on the stack otherwise.
//
TCHAR szFilePath[MAX_PATH + 1]; BOOL fFirstTime = TRUE; PBFILE file;
WIN32_FIND_DATA wfdData;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
if(NULL == pszDir) { dwErr = E_INVALIDARG; goto done; }
ZeroMemory((PBYTE) szFilePath, sizeof(szFilePath));
wsprintf(szFilePath, TEXT("%s%s"), pszDir, TEXT("*.pbk"));
//
// Look for files with .pbk extension in this
// directory.
//
while(SUCCESS == dwErr) { if(INVALID_HANDLE_VALUE == hFindFile) { hFindFile = FindFirstFile(szFilePath, &wfdData);
if(INVALID_HANDLE_VALUE == hFindFile) { dwErr = GetLastError(); break; } } else { if(!FindNextFile(hFindFile, &wfdData)) { dwErr = GetLastError(); break; } }
if(FILE_ATTRIBUTE_DIRECTORY & wfdData.dwFileAttributes) { continue; }
wsprintf(szFilePath, TEXT("%s%s"), pszDir, wfdData.cFileName);
//
// Ignore the phonebook if its router.pbk
//
if(IsRouterPhonebook(szFilePath)) { continue; }
dwErr = ReadPhonebookFile( szFilePath, NULL, NULL, dwFlags, &file);
if(SUCCESS == dwErr) { //
// Call back
//
pfnCallback(&file, pvContext);
ClosePhonebookFile(&file); } else { dwErr = SUCCESS; } }
done:
if( (ERROR_NO_MORE_FILES == dwErr) || (ERROR_FILE_NOT_FOUND == dwErr)) { dwErr = ERROR_SUCCESS; }
if(INVALID_HANDLE_VALUE != hFindFile) { FindClose(hFindFile); }
return dwErr; }
DWORD ReadEntryFromSystem( IN LPCTSTR pszPhonebook, IN LPCTSTR pszEntry, IN DWORD dwFlags, IN OUT PBFILE *pFile, OUT DTLNODE **ppdtlnode, OUT WCHAR **ppszPbkPath)
// Finds the phonebook entrynode given the entryname.
// The node is returned in 'ppdtlnode'. If 'pszPhonebook'
// is NULL, All Users phonebook is searched first for the
// entry and if its not found there, Phonebooks in the per
// user profile are searched for the entry. 'pFile' on return
// from this function contains the open phonebook containing
// the entry specified by pszEntry. Note: if there are
// mutiple entries with the same name across phonebooks, the
// entry correspoding the first phonebook enumerated is returned.
//
{ DWORD dwErr = SUCCESS; DTLNODE *pdtlnode = NULL; TCHAR* szPathBuf = NULL;
TRACE("GetPbkAndEntryName");
//
// Do some parameter validation
//
if( (NULL == pszEntry) || (NULL == ppdtlnode)) { dwErr = E_INVALIDARG; goto done; }
// Phonebook file must be provided if we are not reading from the cache.
//
/* //comment it out for .Net 61226, can delete it some time later
if ( (!fReadFromCache) && (NULL == pFile)) { dwErr = E_INVALIDARG; goto done; } */
if (! (szPathBuf = (TCHAR*) Malloc((MAX_PATH + 1) * sizeof(TCHAR)))) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto done; }
// XP 426903
//
// On consumer platforms, we default to looking at all-user connections
// even if the current user is not an admin.
//
if ((NULL == pszPhonebook) && (IsConsumerPlatform())) { dwFlags |= RPBF_AllUserPbk; }
//
// Load the phonebook file.
//
dwErr = DwReadEntryFromSystem( pszPhonebook, pszEntry, dwFlags, pFile, &pdtlnode, ppszPbkPath);
if( (ERROR_SUCCESS == dwErr) || (NULL != pszPhonebook)) { if( (ERROR_SUCCESS != dwErr) && (NULL != pszPhonebook)) { if(GetPhonebookDirectory( PBM_Alternate, szPathBuf)) { lstrcat(szPathBuf, TEXT("rasphone.pbk")); if(0 == lstrcmpi(szPathBuf, pszPhonebook)) { //
// some one is passing the legacy
// phonebook path exclusively, check
// to see if the entry is in the
// all-users phonebook. NetScape does
// the following which requires this
// workaround: Creates an entry with
// NULL pbk path so the entry gets
// created in all-users. Then passes
// %windir%\system32\ras\rasphone.pbk
// explicitly to find the entry - and
// because of the system pbk change in
// nt5 this doesn't work unless we do
// the hack below.
//
dwErr = DwReadEntryFromSystem( NULL, pszEntry, dwFlags, pFile, &pdtlnode, ppszPbkPath);
if(ERROR_SUCCESS != dwErr) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; } } } } goto done; }
//
// Try to find the entry in personal phonebooks.
//
dwErr = DwFindEntryInPersonalPhonebooks( pszEntry, dwFlags, FALSE, pFile, &pdtlnode, ppszPbkPath);
if(ERROR_SUCCESS == dwErr) { goto done; }
//
// Try to find the entry in the system32\ras phonebooks.
//
dwErr = DwFindEntryInPersonalPhonebooks( pszEntry, dwFlags, TRUE, pFile, &pdtlnode, ppszPbkPath); if(ERROR_SUCCESS == dwErr) { goto done; } //
// If the phonebookpath is NULL explicitly try out
// the public phonebook.
//
if(GetPublicPhonebookPath(szPathBuf)) { dwErr = DwReadEntryFromSystem( szPathBuf, pszEntry, dwFlags, pFile, &pdtlnode, ppszPbkPath); }
if(ERROR_SUCCESS != dwErr) { dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY; }
done:
*ppdtlnode = pdtlnode;
Free0(szPathBuf);
TRACE1("GetPbkAndEntryName. rc=0x%x", dwErr);
return dwErr;
}
DWORD GetPbkAndEntryName( IN LPCTSTR pszPhonebook, IN LPCTSTR pszEntry, IN DWORD dwFlags, OUT PBFILE *pFile, OUT DTLNODE **ppdtlnode) { return ReadEntryFromSystem( pszPhonebook, pszEntry, dwFlags, pFile, ppdtlnode, NULL); }
DWORD GetFmtServerFromConnection( IN HANDLE hConnection, IN PWCHAR pszServerFmt) { PWCHAR pszServer = (PWCHAR) RemoteGetServerName( hConnection );
if ( pszServer && *pszServer ) { if ( *pszServer == L'\0' ) { wcscpy( pszServerFmt, pszServer ); } else { pszServerFmt[0] = pszServerFmt[1] = L'\\'; wcscpy( pszServerFmt + 2, pszServer ); } } else { *pszServerFmt = L'\0'; }
return NO_ERROR; }
DWORD UpgradeSecureVpnOption( IN HKEY hkMachine, IN PBENTRY* pEntry )
// Called to upgrade the "secure vpn" option. If this was set in
// nt4, it meant that all vpn entries should use strong encryption.
// If we see this on nt5, then we should for this entry to use
// mschapv2.
//
{ DWORD dwErr = NO_ERROR; HKEY hkValue = NULL; DWORD dwType = REG_DWORD, dwSize = sizeof(DWORD), dwValue = 0;
do { // Open the registry key that we're looking at
//
dwErr = RegOpenKeyEx( hkMachine, c_pszRegKeySecureVpn, 0, KEY_READ, &hkValue); if (dwErr != NO_ERROR) { break; }
// Read in the value
//
dwErr = RegQueryValueEx( hkValue, c_pszRegValSecureVpn, NULL, &dwType, (LPBYTE)&dwValue, &dwSize); if (dwErr != NO_ERROR) { break; }
// Set the entry accordingly
//
if (dwValue) { pEntry->dwAuthRestrictions = AR_F_AuthCustom | AR_F_AuthMSCHAP2; } // Delete the registry value
//
RegDeleteValue( hkValue, c_pszRegValSecureVpn ); } while (FALSE);
// Cleanup
{ if (hkValue) { RegCloseKey (hkValue); } }
return dwErr; }
DWORD UpgradeForceStrongEncrptionOption( IN HKEY hkMachine, IN PBENTRY* pEntry )
// Called to upgrade the "force strong encryption" option. If this was
// set in nt4, it meant that all entries that force strong encryption
// should now force strong encryption.
//
{ DWORD dwErr = NO_ERROR; HKEY hkValue = NULL; DWORD dwType = REG_DWORD, dwSize = sizeof(DWORD), dwValue = 0;
do { // Open the registry key that we're looking at
//
dwErr = RegOpenKeyEx( hkMachine, c_pszRegKeyForceStrongEncryption, 0, KEY_READ, &hkValue); if (dwErr != NO_ERROR) { break; }
// Read in the value
//
dwErr = RegQueryValueEx( hkValue, c_pszRegValForceStrongEncryption, NULL, &dwType, (LPBYTE)&dwValue, &dwSize); if (dwErr != NO_ERROR) { break; }
// Set the entry accordingly
//
if (dwValue) { if ( pEntry->dwDataEncryption == DE_Require ) { pEntry->dwDataEncryption = DE_RequireMax; } }
// Delete the registry value
//
RegDeleteValue( hkValue, c_pszRegValForceStrongEncryption ); } while (FALSE);
// Cleanup
{ if (hkValue) { RegCloseKey (hkValue); } }
return dwErr; }
DWORD UpgradeRegistryOptions( IN HANDLE hConnection, IN PBENTRY* pEntry )
// Called to upgrade any options in this phonebook entry
// based on registry settings.
//
{ WCHAR pszServer[MAX_COMPUTERNAME_LENGTH + 3]; HKEY hkMachine = NULL; DWORD dwErr = NO_ERROR;
do { // Get the formatted server name
//
dwErr = GetFmtServerFromConnection(hConnection, pszServer); if (dwErr != NO_ERROR) { break; }
// Connect to the appropriate registry
//
dwErr = RegConnectRegistry( (*pszServer) ? pszServer : NULL, HKEY_LOCAL_MACHINE, &hkMachine); if (dwErr != NO_ERROR) { break; } if (hkMachine == NULL) { dwErr = ERROR_CAN_NOT_COMPLETE; break; }
// Upgrade the various options
if ( pEntry->dwType == RASET_Vpn ) { UpgradeSecureVpnOption( hkMachine, pEntry ); } UpgradeForceStrongEncrptionOption( hkMachine, pEntry ); } while (FALSE);
// Cleanup
{ if (hkMachine) { RegCloseKey (hkMachine); } }
return dwErr; }
|