You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7219 lines
204 KiB
7219 lines
204 KiB
// 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;
|
|
}
|