Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2072 lines
59 KiB

//+----------------------------------------------------------------------------
//
// File: util.cpp
//
// Module: CMDIAL32.DLL
//
// Synopsis: Various utility functions
//
// Copyright (c) 1996-1999 Microsoft Corporation
//
// Author: dondu Created 01/01/96
//
//+----------------------------------------------------------------------------
#include "cmmaster.h"
#include "DynamicLib.h"
#include "profile_str.h"
#include "tunl_str.h"
#include "stp_str.h"
#include "dun_str.h"
#include "linkdll.cpp" // LinkToDll and BindLinkage
//
// Get the common functions AddAllKeysInCurrentSectionToCombo
// and GetPrivateProfileStringWithAlloc
//
#include "gppswithalloc.cpp"
const TCHAR* const c_pszTunnelName = TEXT(" Tunnel");
const TCHAR* const c_pszRegCurrentVersion = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
const TCHAR* const c_pszRegCsdVersion = TEXT("CSDVersion");
const TCHAR* const c_pszIconMgrClass = TEXT("IConnMgr Class");
const TCHAR* const c_pszCmEntryPasswordHandling = TEXT("PasswordHandling");
//+----------------------------------------------------------------------------
//
// Function: CmGetWindowTextAlloc
//
// Synopsis: Retrieves the text of a control in a dialog, returning the text in
// a block of allocated memory
//
// Arguments: HWND hwndDlg - The window that owns the control
// UINT nCtrl - The ID of the control
//
// Returns: LPTSTR - Ptr to buffer containing the window text
//
// History: nickball Created Header 4/1/98
//
//+----------------------------------------------------------------------------
LPTSTR CmGetWindowTextAlloc(HWND hwndDlg, UINT nCtrl)
{
LPTSTR pszRes = NULL;
HWND hwndCtrl = nCtrl ? GetDlgItem(hwndDlg, nCtrl) : hwndDlg;
if (hwndCtrl)
{
size_t nLen = GetWindowTextLengthU(hwndCtrl);
pszRes = (LPTSTR)CmMalloc((nLen+2)*sizeof(TCHAR));
if (pszRes)
{
GetWindowTextU(hwndCtrl, pszRes, nLen+1);
}
}
return (pszRes);
}
//+----------------------------------------------------------------------------
//
// Function: ReducePathToRelative
//
// Synopsis: Helper function, converts a full profile file path into a
// relative path.
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
// LPCTSTR pszFullPath - The full path to the file
//
//
// Returns: LPTSTR - The relative path form or NULL
//
// Note: The file to be reduced should exist and be located
// in the profile directory
//
// History: nickball Created 8/12/98
//
//+----------------------------------------------------------------------------
LPTSTR ReducePathToRelative(ArgsStruct *pArgs, LPCTSTR pszFullPath)
{
MYDBGASSERT(pszFullPath);
MYDBGASSERT(pArgs);
if (NULL == pszFullPath || NULL == pArgs || FALSE == FileExists(pszFullPath))
{
return NULL;
}
//
// Use CMS as base
//
LPTSTR pszReduced = CmStripPathAndExt(pArgs->piniService->GetFile());
MYDBGASSERT(pszReduced);
if (pszReduced)
{
//
// Append the filename
//
pszReduced = CmStrCatAlloc(&pszReduced, TEXT("\\"));
MYDBGASSERT(pszReduced);
if (pszReduced)
{
LPTSTR pszFileName = StripPath(pszFullPath);
MYDBGASSERT(pszFileName);
if (pszFileName)
{
pszReduced = CmStrCatAlloc(&pszReduced, pszFileName);
MYDBGASSERT(pszReduced);
CmFree(pszFileName);
if (pszReduced)
{
return pszReduced;
}
}
}
}
CmFree(pszReduced);
return NULL;
}
// get service name from the service file
LPTSTR GetServiceName(CIni *piniService)
{
LPTSTR pszTmp;
pszTmp = piniService->GPPS(c_pszCmSection,c_pszCmEntryServiceName);
if (!*pszTmp)
{
//
// failed to get service name, then use base filename
//
CmFree(pszTmp);
pszTmp = CmStripPathAndExt(piniService->GetFile());
//
// Do not write the entry back to .CMS file - #4849
//
// piniService->WPPS(c_pszCmSection, c_pszCmEntryServiceName, pszTmp);
}
return (pszTmp);
}
//+----------------------------------------------------------------------------
//
// Function GetTunnelSuffix
//
// Synopsis Returns an allocated string containing the tunnel suffix
//
// Arguments None
//
// Returns LPTSTR - Ptr to the suffix in its entirety, caller must free
//
// History 06/14/99 nickball Created
//
//-----------------------------------------------------------------------------
LPTSTR GetTunnelSuffix()
{
MYDBGASSERT(OS_W9X); // secondary connectoids only exist on 9X
//
// First copy the phrase " Tunnel", which is not localized
//
LPTSTR pszSuffix = CmStrCpyAlloc(c_pszTunnelName);
//
// Now retrieve the localizable phrase " (for advanced use only)"
//
if (pszSuffix)
{
LPTSTR pszTmp = CmLoadString(g_hInst, IDS_TUNNEL_SUFFIX);
pszSuffix = CmStrCatAlloc(&pszSuffix, pszTmp);
CmFree(pszTmp);
}
MYDBGASSERT(pszSuffix);
return pszSuffix;
}
//+----------------------------------------------------------------------------
//
// Function GetDefaultDunSettingName
//
// Synopsis Get the default DUN name from the specified .CMS
//
// Arguments piniService - The service file object to be used.
// fTunnel - Indicates if the profile is for tunneling
//
// Returns LPTSTR - Ptr to the DUN name
//
// History 10/28/98 nickball Created
//
//-----------------------------------------------------------------------------
LPTSTR GetDefaultDunSettingName(CIni* piniService, BOOL fTunnelEntry)
{
//
// Get the DUN name from the top level service file, ex: snowbird online service
//
LPTSTR pszTmp = NULL;
if (fTunnelEntry)
{
pszTmp = piniService->GPPS(c_pszCmSection, c_pszCmEntryTunnelDun);
MYDBGASSERT(pszTmp && *pszTmp); // CMAK writes this, it shouldn't be blank
}
else
{
pszTmp = piniService->GPPS(c_pszCmSection, c_pszCmEntryDun);
}
return (pszTmp);
}
//+----------------------------------------------------------------------------
//
// Function GetDunSettingName
//
// Synopsis Get the current DUN name
//
// Arguments pArgs - Ptr to ArgStruct
// dwEntry - index of rasentry (ignored if fTunnel is true)
// fTunnel - is this a VPN?
//
// Returns Dun setting name
//
// History 01-Nov-2000 SumitC Created
//
//-----------------------------------------------------------------------------
LPTSTR GetDunSettingName(ArgsStruct * pArgs, DWORD dwEntry, BOOL fTunnel)
{
LPTSTR pszTmp = NULL;
MYDBGASSERT(pArgs);
MYDBGASSERT(fTunnel || (dwEntry <= 1));
if (NULL == pArgs)
{
return NULL;
}
if (fTunnel)
{
pszTmp = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelDun);
MYDBGASSERT(pszTmp && *pszTmp); // CMAK writes this, it shouldn't be blank
if (pszTmp && !*pszTmp)
{
// the "empty string" case
CmFree(pszTmp);
pszTmp = NULL;
}
}
else
{
if (pArgs->aDialInfo[dwEntry].szDUN[0])
{
pszTmp = CmStrCpyAlloc(pArgs->aDialInfo[dwEntry].szDUN);
}
else
{
CIni * pIni = GetAppropriateIniService(pArgs, dwEntry);
if (pIni)
{
pszTmp = pIni->GPPS(c_pszCmSection, c_pszCmEntryDun);
delete pIni;
}
}
}
if (NULL == pszTmp)
{
pszTmp = GetDefaultDunSettingName(pArgs->piniService, fTunnel);
}
return pszTmp;
}
//+----------------------------------------------------------------------------
//
// Function GetCMSforPhoneBook
//
// Synopsis Get the name of the .CMS file that contains the current phonebook
//
// Arguments pArgs - Ptr to ArgStruct
// dwEntry - index of rasentry
//
// Returns phonebook filename (NULL if error or not found)
//
// History 10-Nov-2000 SumitC Created
//
//-----------------------------------------------------------------------------
LPTSTR GetCMSforPhoneBook(ArgsStruct * pArgs, DWORD dwEntry)
{
LPTSTR pszTmp = NULL;
MYDBGASSERT(pArgs);
MYDBGASSERT(dwEntry <= 1);
if (NULL == pArgs)
{
return NULL;
}
PHONEINFO * pPhoneInfo = &(pArgs->aDialInfo[dwEntry]);
if (pPhoneInfo && pPhoneInfo->szPhoneBookFile[0])
{
LPTSTR pszFileName = CmStrrchr(pPhoneInfo->szPhoneBookFile, TEXT('\\'));
if (pszFileName)
{
pszTmp = CmStrCpyAlloc(CharNextU(pszFileName));
}
}
return pszTmp;
}
//+----------------------------------------------------------------------------
//
// Function: FileExists
//
// Synopsis: Helper function to encapsulate determining if a file exists.
//
// Arguments: LPCTSTR pszFullNameAndPath - The FULL Name and Path of the file.
//
// Returns: BOOL - TRUE if the file is located
//
// History: nickball Created 3/9/98
//
//+----------------------------------------------------------------------------
BOOL FileExists(LPCTSTR pszFullNameAndPath)
{
MYDBGASSERT(pszFullNameAndPath);
if (pszFullNameAndPath && pszFullNameAndPath[0])
{
HANDLE hFile = CreateFileU(pszFullNameAndPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
if (GetFileType(hFile) == FILE_TYPE_DISK)
{
CloseHandle(hFile);
return TRUE;
}
else
{
CloseHandle(hFile);
return FALSE;
}
}
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: IsBlankString
//
// Synopsis: Check whether a given string contains only spaces(' ')
//
// Arguments: pszString string to be verified
//
// Returns: TRUE only space is in the string
// FALSE otherwise
//
// History: byao Modified 4/11/97
// byao Modified 4/14/97 Change the function to apply to
// all strings (instead of phone no only).
//----------------------------------------------------------------------------
BOOL IsBlankString(LPCTSTR pszString)
{
MYDBGASSERT(pszString);
DWORD dwIdx;
DWORD dwLen = lstrlenU(pszString);
if (NULL == pszString)
{
return FALSE;
}
for (dwIdx = 0; dwIdx < dwLen; dwIdx++)
{
if (pszString[dwIdx]!=TEXT(' '))
{
return FALSE;
}
}
return TRUE;
}
//
// Acceptable phone number characters
//
#define VALID_CTRL_CHARS TEXT("\03\026\030") // ctrl-c, ctrl-v, ctrl-x.
#define VALID_PHONE_CHARS TEXT("0123456789AaBbCcDdPpTtWw!@$ -()+*#,\0")
//+---------------------------------------------------------------------------
//
// Function: IsValidPhoneNumChar
//
// Synopsis: Helper function to encapsulate validation of a character to
// determine if it is an acceptable input char for a phone number
//
// Arguments: TCHAR tChar - the char in question
//
// Returns: TRUE if valid
// FALSE otherwise
//
// History: nickball - Created - 7/7/97
//
//----------------------------------------------------------------------------
BOOL IsValidPhoneNumChar(TCHAR tChar)
{
LPTSTR lpValid = NULL;
//
// Scan thru the list of valid tapi characters
//
for (lpValid = VALID_PHONE_CHARS; *lpValid; lpValid++)
{
if (tChar == (TCHAR) *lpValid)
{
return TRUE;
}
}
//
// Scan thru the list of valid ctrl characters
//
for (lpValid = VALID_CTRL_CHARS; *lpValid; lpValid++)
{
if (tChar == (TCHAR) *lpValid)
{
return TRUE;
}
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: ReadMappingByRoot
//
// Synopsis: Read in the mapping from the [HKCU or HKLM] branch of the registry
//
// Arguments: hkRoot either HKCU or HKLM
// pszDUN[IN] Connectoid name
// pszMapping[IN] Full path of the service profile(.CMS) for this connectoid
// dwNumCharsInMapping[IN] Number of chars in pszMapping, including the NULL char
//
// Returns: TRUE if registry key read in successfully
// FALSE otherwise
//
//----------------------------------------------------------------------------
BOOL ReadMappingByRoot(
HKEY hkRoot,
LPCTSTR pszDUN,
LPTSTR pszMapping,
DWORD dwNumCharsInMapping,
BOOL bExpandEnvStrings
)
{
MYDBGASSERT(pszDUN);
MYDBGASSERT(pszMapping);
MYDBGASSERT(dwNumCharsInMapping);
if (NULL == pszDUN || NULL == pszMapping)
{
return FALSE;
}
TCHAR szTmp[MAX_PATH + 1] = TEXT("");
DWORD dwNumBytesInTmp = sizeof(szTmp);
DWORD dwRes;
HKEY hkKey;
DWORD dwType;
dwRes = RegOpenKeyExU(hkRoot,
c_pszRegCmMappings, // Mappings sub-key
0,
KEY_READ,
&hkKey);
if (dwRes != ERROR_SUCCESS)
{
CMTRACE1(TEXT("ReadMappingByRoot() RegOpenKeyEx() failed, GLE=%u."), dwRes);
return (FALSE);
}
dwRes = RegQueryValueExU(hkKey, pszDUN, NULL, &dwType, (LPBYTE) szTmp, &dwNumBytesInTmp);
RegCloseKey(hkKey);
//
// If no value found, just bail
//
if ((dwRes != ERROR_SUCCESS) || (!*szTmp))
{
CMTRACE1(TEXT("ReadMappingByRoot() RegQueryValueEx() failed, GLE=%u."), dwRes);
return FALSE;
}
//
// Check for and expand environment strings
//
if (bExpandEnvStrings && (TEXT('%') == *szTmp))
{
CMTRACE1(TEXT("Expanding Mapping environment string as %s"), szTmp);
dwRes = ExpandEnvironmentStringsU(szTmp, pszMapping, dwNumCharsInMapping);
MYDBGASSERT(dwRes <= dwNumCharsInMapping);
}
else
{
lstrcpyU(pszMapping, szTmp);
dwRes = lstrlenU(pszMapping) + 1;
}
#ifdef DEBUG
if (dwRes <= dwNumCharsInMapping)
{
CMTRACE1(TEXT("ReadMappingByRoot() SUCCESS. Mapping is %s"), pszMapping);
}
else
{
CMTRACE(TEXT("ReadMappingByRoot() FAILED."));
}
#endif
return (dwRes <= dwNumCharsInMapping);
}
//+---------------------------------------------------------------------------
//
// Function: ReadMapping
//
// Synopsis: Read in the mapping from the registry
//
// Arguments: pszDUN[IN] Connectoid name
// pszMapping[IN] Full path of the service profile(.CMS) for this connectoid
// dwMapping[IN] Number of chars in pszMapping, including the NULL char
// fAllUser[IN] Look in the AllUser hive
//
// Returns: BOOL TRUE if found
//
//----------------------------------------------------------------------------
BOOL ReadMapping(
LPCTSTR pszDUN,
LPTSTR pszMapping,
DWORD dwMapping,
BOOL fAllUser,
BOOL bExpandEnvStrings)
{
BOOL fOk = FALSE;
//
// Copied from ntdef.h
//
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
if (fAllUser)
{
CMTRACE1(TEXT("ReadMapping() - Reading AllUser Mapping for %s"), pszDUN);
fOk = ReadMappingByRoot(HKEY_LOCAL_MACHINE, pszDUN, pszMapping, dwMapping, bExpandEnvStrings);
}
else
{
CMTRACE1(TEXT("ReadMapping() - Reading Single User Mapping for %s"), pszDUN);
//
// Only NT5 has single-user profiles
//
MYDBGASSERT(OS_NT5);
if (OS_NT5)
{
//
// There are cases where we aren't always running in the user context (certain
// WinLogon cases and certain delete notification cases). At these times we
// have impersonation setup but don't have direct access to the HKCU, thus
// we use RtlOpenCurrentUser in these instances.
//
CDynamicLibrary libNtDll; // Destructor will call FreeLibrary
HANDLE hCurrentUserKey = NULL;
if (libNtDll.Load(TEXT("NTDLL.DLL")))
{
typedef NTSTATUS (NTAPI * RtlOpenCurrentUserPROC)(IN ULONG DesiredAccess,
OUT PHANDLE CurrentUserKey);
typedef NTSTATUS (NTAPI * NtClosePROC)(IN HANDLE Handle);
RtlOpenCurrentUserPROC pfnRtlOpenCurrentUser;
if ( (pfnRtlOpenCurrentUser = (RtlOpenCurrentUserPROC)libNtDll.GetProcAddress("RtlOpenCurrentUser")) != NULL)
{
if (NT_SUCCESS (pfnRtlOpenCurrentUser(KEY_READ | KEY_WRITE, &hCurrentUserKey)))
{
fOk = ReadMappingByRoot((HKEY)hCurrentUserKey, pszDUN, pszMapping, dwMapping, bExpandEnvStrings);
NtClosePROC pfnNtClose;
if ( (pfnNtClose = (NtClosePROC)libNtDll.GetProcAddress("NtClose")) != NULL)
{
pfnNtClose(hCurrentUserKey);
}
}
}
}
MYDBGASSERT(hCurrentUserKey);
}
}
return fOk;
}
//+----------------------------------------------------------------------------
//
// Function: StripPath
//
// Synopsis: Helper function to deal with the tedium of extracting the filename
// part of a complete filename and path.
//
// Arguments: LPCTSTR pszFullNameAndPath - Ptr to the full filename with path
//
// Returns: LPTSTR - Ptr to an allocated buffer containing the dir, or NULL on failure.
//
// Note: It is up to the caller to provide reasonable input, the only requirement
// is that the input contain '\'.
//
// History: nickball Created 3/31/98
//
//+----------------------------------------------------------------------------
LPTSTR StripPath(LPCTSTR pszFullNameAndPath)
{
MYDBGASSERT(pszFullNameAndPath);
if (NULL == pszFullNameAndPath)
{
return NULL;
}
//
// Locate the last '\'
//
LPTSTR pszSlash = CmStrrchr(pszFullNameAndPath, TEXT('\\'));
if (NULL == pszSlash)
{
MYDBGASSERT(FALSE);
return NULL;
}
//
// Return an allocated copy of the string beyond the last '\'
//
pszSlash = CharNextU(pszSlash);
return (CmStrCpyAlloc(pszSlash));
}
//+----------------------------------------------------------------------------
//
// Function: NotifyUserOfExistingConnection
//
// Synopsis: Helper function to notify user that connection is either connect
// ing or connected already.
//
// Arguments: HWND hwndParent - Hwnd of parent if any.
// LPCM_CONNECTION pConnection - Ptr to CM_CONNECTION structure
// containing state, entry name, etc.
// BOOL fStatus - Flag indicating the status pane should be used for display.
//
// Returns: Nothing
//
// History: nickball Created Header 3/17/98
//
//+----------------------------------------------------------------------------
void NotifyUserOfExistingConnection(HWND hwndParent, LPCM_CONNECTION pConnection, BOOL fStatus)
{
MYDBGASSERT(pConnection);
//
// Test assumptions
//
if (NULL == pConnection)
{
return;
}
MYDBGASSERT(CM_CONNECTED == pConnection->CmState ||
CM_CONNECTING == pConnection->CmState ||
CM_DISCONNECTING == pConnection->CmState);
//
// First load the correct message based upon state
//
int iMsgId;
switch (pConnection->CmState)
{
case CM_CONNECTED:
iMsgId = IDMSG_ALREADY_CONNECTED;
break;
case CM_CONNECTING:
iMsgId = IDMSG_ALREADY_CONNECTING;
break;
case CM_DISCONNECTING:
iMsgId = IDMSG_ALREADY_DISCONNECTING;
break;
default:
MYDBGASSERT(FALSE);
return;
break;
}
//
// Format the message with service name
//
LPTSTR pszMsg = CmFmtMsg(g_hInst, iMsgId, pConnection->szEntry);
if (pszMsg)
{
//
// Display according to requested output
//
if (fStatus)
{
AppendStatusPane(hwndParent, pszMsg);
}
else
{
MessageBoxEx(hwndParent, pszMsg, pConnection->szEntry, MB_OK|MB_ICONINFORMATION, LANG_USER_DEFAULT);
}
CmFree(pszMsg);
}
}
//+----------------------------------------------------------------------------
//
// Function: GetConnection
//
// Synopsis: Helper routine to retrieve the connection data for the current
// service from the connection table.
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
//
// Returns: Allocated ptr to a CM_CONNECTION or NULL
//
// History: nickball Created 2/23/98
//
//+----------------------------------------------------------------------------
LPCM_CONNECTION GetConnection(ArgsStruct *pArgs)
{
MYDBGASSERT(pArgs);
MYDBGASSERT(pArgs->pConnTable);
LPCM_CONNECTION pConnection = (LPCM_CONNECTION) CmMalloc(sizeof(CM_CONNECTION));
if (pArgs && pArgs->pConnTable && pConnection)
{
//
// Retrieve the entry
//
if (FAILED(pArgs->pConnTable->GetEntry(pArgs->szServiceName, pConnection)))
{
CmFree(pConnection);
pConnection = NULL;
}
}
return pConnection;
}
//+----------------------------------------------------------------------------
//
// Function: SingleSpace
//
// Synopsis: Converts multiple space chars in a string to single spaces.
// For example: "1 206 645 7865" becomes "1 206 645 7865"
//
// Arguments: LPTSTR pszStr - The string to be examined/modified
//
// Returns: Nothing
//
// Note: This is a fix for the MungePhone problem on W95 where TAPI adds
// two spaces between the 9 and the 1 when dialing long distance
// with a prefix. RAID #3198
//
// History: nickball 4/1/98 Created Header
// nickball 4/1/98 Relocated from cm_misc.cpp
//
//+----------------------------------------------------------------------------
void SingleSpace(LPTSTR pszStr)
{
LPTSTR pszTmp = pszStr;
while (pszTmp && *pszTmp)
{
if (CmIsSpace(pszTmp) && CmIsSpace(pszTmp + 1))
{
lstrcpyU(pszTmp, (pszTmp + 1));
}
pszTmp++;
}
}
//+----------------------------------------------------------------------------
//
// Function: Ip_GPPS
//
// Synopsis: Retrieves the result of a GPPS on the specified CIni object in R
// ASIPADDR format. Used for reading IP addresses in INI files.
//
// Arguments: CIni *pIni - The Cini object to be used
// LPCTSTR pszSection - String name of the section to be read
// LPCTSTR pszEntry - String name of the entry to be read
// RASIPADDR *pIP - Ptr to the RASIPADDR structure to be filled.
//
// Returns: static void - Nothing
//
// History: nickball Created Header 8/22/98
//
//+----------------------------------------------------------------------------
void Ip_GPPS(CIni *pIni, LPCTSTR pszSection, LPCTSTR pszEntry, RASIPADDR *pIP)
{
LPTSTR pszTmp;
LPTSTR pszOctet;
RASIPADDR ip;
MYDBGASSERT(pszSection);
MYDBGASSERT(pszEntry);
pszTmp = pIni->GPPS(pszSection, pszEntry);
if (!*pszTmp)
{
CmFree(pszTmp);
return;
}
memset(&ip,0,sizeof(ip));
pszOctet = pszTmp;
ip.a = (BYTE)CmAtol(pszOctet);
while (CmIsDigit(pszOctet))
{
pszOctet++;
}
if (*pszOctet != '.')
{
CmFree(pszTmp);
return;
}
pszOctet++;
ip.b = (BYTE)CmAtol(pszOctet);
while (CmIsDigit(pszOctet))
{
pszOctet++;
}
if (*pszOctet != '.')
{
CmFree(pszTmp);
return;
}
pszOctet++;
ip.c = (BYTE)CmAtol(pszOctet);
while (CmIsDigit(pszOctet))
{
pszOctet++;
}
if (*pszOctet != '.')
{
CmFree(pszTmp);
return;
}
pszOctet++;
ip.d = (BYTE)CmAtol(pszOctet);
while (CmIsDigit(pszOctet))
{
pszOctet++;
}
if (*pszOctet)
{
CmFree(pszTmp);
return;
}
memcpy(pIP,&ip,sizeof(ip));
CmFree(pszTmp);
return;
}
//+----------------------------------------------------------------------------
//
// Function: CopyGPPS
//
// Synopsis: Copies the result of a GPPS call on the specified INI object to
// the buffer specified in pszBuffer.
//
// Arguments: CIni *pIni - Ptr to the CIni object to be used.
// LPCTSTR pszSection - String name the section to be read
// LPCTSTR pszEntry - String name of the entry to be read
// LPTSTR pszBuffer - The buffer to be filled with the result
// size_t nLen - The size of the buffer to be filled
//
// Returns: static void - Nothing
//
// History: nickball Created Header 8/22/98
//
//+----------------------------------------------------------------------------
void CopyGPPS(CIni *pIni, LPCTSTR pszSection, LPCTSTR pszEntry, LPTSTR pszBuffer, size_t nLen)
{
// REVIEW: Doesn't check input params
LPTSTR pszTmp;
pszTmp = pIni->GPPS(pszSection, pszEntry);
if (*pszTmp)
{
lstrcpynU(pszBuffer, pszTmp, nLen);
}
CmFree(pszTmp);
}
//
// From ras\ui\common\nouiutil\noui.c
//
CHAR HexChar(IN BYTE byte)
/* Returns an ASCII hexidecimal character corresponding to 0 to 15 value,
** 'byte'.
*/
{
const CHAR* pszHexDigits = "0123456789ABCDEF";
if (byte >= 0 && byte < 16)
return pszHexDigits[ byte ];
else
return '0';
}
//
// From ras\ui\common\nouiutil\noui.c
//
BYTE HexValue(IN CHAR ch)
/* Returns the value 0 to 15 of hexadecimal character 'ch'.
*/
{
if (ch >= '0' && ch <= '9')
return (BYTE )(ch - '0');
else if (ch >= 'A' && ch <= 'F')
return (BYTE )((ch - 'A') + 10);
else if (ch >= 'a' && ch <= 'f')
return (BYTE )((ch - 'a') + 10);
else
return 0;
}
//+----------------------------------------------------------------------------
//
// Function: StripCanonical
//
// Synopsis: Simple helper to strip canonical formatting codes from a phone number
// Obviously the number is assumed to be in canonical format.
//
// Arguments: LPTSTR pszSrc - the string to be modifed
//
// Returns: Nothing
//
// History: nickball 09/16/98 Created
//
//+----------------------------------------------------------------------------
void StripCanonical(LPTSTR pszSrc)
{
MYDBGASSERT(pszSrc);
MYDBGASSERT(pszSrc);
if (NULL == pszSrc || !*pszSrc)
{
return;
}
//
// eg. +1 (425) 555 5555
//
LPTSTR pszNext = CharNextU(pszSrc);
if (pszNext)
{
lstrcpyU(pszSrc, pszNext);
//
// eg. 1 (425) 555 5555
//
LPTSTR pszLast = CmStrchr(pszSrc, TEXT('('));
if (pszLast)
{
pszNext = CharNextU(pszLast);
if (pszNext)
{
lstrcpyU(pszLast, pszNext);
//
// eg. 1 425) 555 5555
//
pszLast = CmStrchr(pszSrc, TEXT(')'));
if (pszLast)
{
pszNext = CharNextU(pszLast);
if (pszNext)
{
lstrcpyU(pszLast, pszNext);
}
}
//
// eg. 1 425 555 5555
//
}
}
}
}
//+----------------------------------------------------------------------------
//
// Function: StripFirstElement
//
// Synopsis: Simple helper to strip the substring prior to the first space in
// a string
//
// Arguments: LPTSTR pszSrc - the string to be modifed
//
// Returns: Nothing
//
// History: nickball 09/16/98 Created
//
//+----------------------------------------------------------------------------
void StripFirstElement(LPTSTR pszSrc)
{
MYDBGASSERT(pszSrc);
MYDBGASSERT(pszSrc);
if (pszSrc && *pszSrc)
{
LPTSTR pszSpace = CmStrchr(pszSrc, TEXT(' '));
if (pszSpace && *pszSpace)
{
LPTSTR pszTmp = CharNextU(pszSpace);
if (pszTmp && *pszTmp)
{
lstrcpyU(pszSrc, pszTmp);
}
}
}
}
//+----------------------------------------------------------------------------
//
// Function: FrontExistingUI
//
// Synopsis: Fronts existing UI for a given profile connect or settings attempt
//
// Arguments: CConnectionTable *pConnTable - ptr to connection table if any.
// LPTSTR pszServiceName - the long service name
// BOOL fConnect - flag indicating that the request is for connect
//
// Note: Caller is required to ensure that there is not an existing
// (non-logon) window with the same service names as the title.
//
// Returns: TRUE if we fronted anything
//
//+----------------------------------------------------------------------------
BOOL FrontExistingUI(CConnectionTable *pConnTable, LPCTSTR pszServiceName, BOOL fConnect)
{
LPTSTR pszPropTitle = GetPropertiesDlgTitle(pszServiceName);
HWND hwndProperties = NULL;
HWND hwndLogon = NULL;
HWND hwndFront = NULL;
BOOL bRet = FALSE;
BOOL fLaunchProperties = FALSE;
//
// First look for a properties dialog
//
if (pszPropTitle)
{
hwndProperties = FindWindowExU(NULL, NULL, WC_DIALOG, pszPropTitle);
}
CmFree(pszPropTitle);
//
// Now see if we have a logon dialog up
//
hwndLogon = FindWindowExU(NULL, NULL, c_pszIconMgrClass, pszServiceName);
//
// Assume the common case, then consider the alternative scenarios.
//
hwndFront = hwndLogon ? hwndLogon : hwndProperties;
//
// Note: There is an ambiguous case in which both UIs are up, but aren't
// related, in which case we front according to the requested action.
//
if (hwndLogon && hwndProperties)
{
//
// We have both dialogs up, if the logon owns the properties dialog
// or the request is for a properties display, we'll front properties.
//
if (hwndLogon == GetParent(hwndProperties) || !fConnect)
{
hwndFront = hwndProperties;
}
}
//
// If we have a window handle, front it
//
if (hwndFront)
{
CMTRACE(TEXT("FrontExistingUI - Fronting existing connect instance UI"));
SetForegroundWindow(hwndFront);
bRet = TRUE;
//
// If the request is for properties, and there is a logon UI, but no
// properties, we want to launch the properties UI from the logon UI
// programmatically.
//
if (!fConnect && !hwndProperties) // fLaunchProperties)
{
if (pConnTable)
{
CM_CONNECTION Connection;
ZeroMemory(&Connection, sizeof(CM_CONNECTION));
//
// Don't launch in the middle of connecting, etc.
//
if (FAILED(pConnTable->GetEntry(pszServiceName, &Connection)))
{
PostMessageU(hwndLogon, WM_COMMAND, MAKEWPARAM(IDC_MAIN_PROPERTIES_BUTTON, 0), (LPARAM)0);
}
}
}
}
return bRet;
}
#if 0 // NT 301988
/*
//+----------------------------------------------------------------------------
//
// Function: IsAnotherInstanceRunning
//
// Synopsis: Check to see if another instance of the same profile running.
//
// Arguments: CConnectionTable *pConnTable - ptr to the connection table
// LPTSTR pszServiceName - the long service name
// DWORD dwFlags - the application flags FL_*
//
// Returns: Nothing
//
//+----------------------------------------------------------------------------
BOOL IsAnotherInstanceRunning(
CConnectionTable *pConnTable,
LPCTSTR pszServiceName,
DWORD dwFlags
)
{
BOOL fRet;
HWND hwnd;
LPTSTR pszPropTitle;
//
// first look for the Properties dialog
//
if (!(pszPropTitle = GetPropertiesDlgTitle(pszServiceName)))
{
return FALSE;
}
fRet = TRUE;
if (!(hwnd = FindWindowEx(NULL, NULL, WC_DIALOG, pszPropTitle)))
{
//
// now look for the main dialog. We make sure that the window returned
// is really the main dialog, not the Status dialog. Since the parent of
// the main dialog is the desktop, we can tell by making sure the parent
// of the window returned is the desktop window.
//
if ((hwnd = FindWindowEx(NULL, NULL, WC_DIALOG, pszServiceName)) &&
(GetWindow(hwnd, GW_OWNER) && GetWindow(hwnd, GW_OWNER) != GetDesktopWindow()))
{
hwnd = NULL;
}
}
CmFree(pszPropTitle);
BOOL fEntryExists;
CM_CONNECTION Connection;
ZeroMemory(&Connection, sizeof(CM_CONNECTION));
fEntryExists = pConnTable && SUCCEEDED(pConnTable->GetEntry(pszServiceName, &Connection));
if (hwnd)
{
CMTRACE(TEXT("Found a previous instance of the same profile."));
SetForegroundWindow(hwnd);
//
// if we're connecting, the "Properties" button is disabled and so we don't bring
// up the properties dialog. We don't want to do this also during disconnection
// and reconnecting.
//
if (dwFlags & FL_PROPERTIES &&
(!fEntryExists ||
fEntryExists &&
Connection.CmState != CM_CONNECTING &&
Connection.CmState != CM_RECONNECTPROMPT))
{
CMTRACE(TEXT("Bringing up the Properties dialog from the previous instance..."));
//
// try to bring up the properties dialog of the first instance
//
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_MAIN_PROPERTIES_BUTTON, 0), (LPARAM)0);
}
}
else
{
//
// During disconnect and reconnect, we don't want to pop up either the main or the
// properties dlg. However, we want to let cmdial run if the Reconnect prompt is gone
// and the this is a reconnect request from CMMON
//
if (fEntryExists &&
(Connection.CmState == CM_DISCONNECTING ||
Connection.CmState == CM_RECONNECTPROMPT &&
dwFlags & FL_PROPERTIES))
{
fRet = TRUE;
}
else
{
fRet = FALSE;
}
}
return fRet;
}
*/
#endif
LPTSTR GetPropertiesDlgTitle(
LPCTSTR pszServiceName
)
{
LPTSTR pszTmp = NULL;
LPTSTR pszTitle = NULL;
//
// first look for the Properties dialog
//
if (!(pszTmp = CmLoadString(g_hInst, IDS_PROPERTIES_SUFFIX)))
{
return NULL;
}
if (!(pszTitle = CmStrCpyAlloc(pszServiceName)))
{
CmFree(pszTmp);
return NULL;
}
if (!CmStrCatAlloc(&pszTitle, pszTmp))
{
CmFree(pszTmp);
CmFree(pszTitle);
return NULL;
}
CmFree(pszTmp);
return pszTitle;
}
//+----------------------------------------------------------------------------
//
// Function: GetPPTPMsgId
//
// Synopsis: Simple helper to determine appropriate PPTP msg based on OS cfg.
//
// Arguments: None
//
// Returns: Integer ID of resource string
//
// History: nickball 12/07/98 Created
//
//+----------------------------------------------------------------------------
int GetPPTPMsgId(void)
{
int nID;
if (OS_NT)
{
//
// We need to tell the user to re-apply the service pack after manual
// install of PPTP if they have one.
//
if (IsServicePackInstalled())
{
nID = IDMSG_NEED_PPTP_NT_SP;
}
else
{
nID = IDMSG_NEED_PPTP_NT; // NT w/o SP
}
}
else
{
nID = IDMSG_NEED_PPTP_WIN95;
}
return nID;
}
//+----------------------------------------------------------------------------
// Function IsServicePackInstalled
//
// Synopsis Checks the CSDVersion key in the registry to see if a service
// pack is installed on this machine
//
// Arguments None
//
// Returns TRUE if service pack (any SP) is installed
// FALSE if no service pack is installed
//
// History 2/4/98 VetriV Created
//-----------------------------------------------------------------------------
BOOL IsServicePackInstalled(void)
{
TCHAR szBuffer[MAX_PATH] = {TEXT("\0")};
HKEY hkey = NULL;
DWORD dwType = 0;
DWORD dwSize = sizeof(szBuffer);
if (ERROR_SUCCESS == RegOpenKeyExU(HKEY_LOCAL_MACHINE,
c_pszRegCurrentVersion,
0,
KEY_READ,
&hkey))
{
if (ERROR_SUCCESS == RegQueryValueExU(hkey,
c_pszRegCsdVersion,
NULL,
&dwType,
(LPBYTE)szBuffer,
&dwSize))
{
if (szBuffer[0] != TEXT('\0'))
{
RegCloseKey(hkey);
return TRUE;
}
}
RegCloseKey(hkey);
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: RegisterWindowClass
//
// Synopsis: Encapsulates registration of window class
//
// Arguments: HINSTANCE hInst - Hinst of DLL
//
// Returns: DWORD - GetLastError
//
// History: nickball Created Header 6/3/99
//
//+----------------------------------------------------------------------------
DWORD RegisterWindowClass(HINSTANCE hInst)
{
WNDCLASSEXA wc;
ZeroMemory(&wc, sizeof(wc));
if (GetClassInfoExA(NULL,(LPSTR)WC_DIALOG,&wc))
{
//
// Convert to Ansi before calling Ansi forms of APIs. We use the
// Ansi forms because GetClassInfoEx cannot be readily wrapped.
//
LPSTR pszClass = WzToSzWithAlloc(c_pszIconMgrClass);
if (!pszClass)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
wc.lpszClassName = pszClass;
wc.cbSize = sizeof(wc);
wc.hInstance = hInst;
if (!RegisterClassExA(&wc))
{
DWORD dwError = GetLastError();
CMTRACE1(TEXT("RegisterWindowClass() RegisterClassEx() failed, GLE=%u."), dwError);
//
// Only fail if the class does not already exist
//
if (ERROR_CLASS_ALREADY_EXISTS != dwError)
{
CmFree(pszClass);
return dwError;
}
}
CmFree(pszClass);
}
return ERROR_SUCCESS;
}
//+----------------------------------------------------------------------------
//
// Function: UnRegisterWindowClass
//
// Synopsis: Encapsulates un-registering window class
//
// Arguments: HINSTANCE hInst - Hinst of DLL
//
// Returns: BOOL - result of UnregsiterClass
//
// History: nickball Created Header 6/3/99
//
//+----------------------------------------------------------------------------
BOOL UnRegisterWindowClass(HINSTANCE hInst)
{
return UnregisterClassU(c_pszIconMgrClass, g_hInst);
}
//+----------------------------------------------------------------------------
//
// Function: IsActionEnabled
//
// Synopsis: checks Registry to see if a command is allowed to run
//
// Arguments: CONST WCHAR *pszProgram - Name of program to be executed
// CONST WCHAR *pszServiceName - Long service name
// CONST WCHAR *pszServiceFileName - Full path to Service file
// LPDWORD lpdwLoadType - Ptr to be filled with load type
//
// Returns: TRUE if action is allowed @ this time
//
// Notes: Checks SOFTWARE\Microsoft\Connection Manager\<ServiceName>
// Under which you will have the Values for each command
// 0 - system32 directory
// 1 - profile directory
//
// History: v-vijayb Created Header 07/20/99
// nickball Revised 07/27/99
//
//+----------------------------------------------------------------------------
BOOL IsActionEnabled(CONST WCHAR *pszProgram,
CONST WCHAR *pszServiceName,
CONST WCHAR *pszServiceFileName,
LPDWORD lpdwLoadType)
{
HKEY hKey;
DWORD dwLoadFlags, cb;
BOOL fIsAllowed = FALSE;
WCHAR szSubKey[MAX_PATH + 1];
WCHAR szBaseName[MAX_PATH + 1];
WCHAR szPath[MAX_PATH + 1];
WCHAR *pszTmp;
MYDBGASSERT(pszProgram && pszServiceName && pszServiceFileName && lpdwLoadType);
if (NULL == pszProgram ||
NULL == pszServiceName ||
NULL == pszServiceFileName ||
NULL == lpdwLoadType)
{
return FALSE;
}
*lpdwLoadType = -1;
if (!IsLogonAsSystem())
{
return (TRUE);
}
MYDBGASSERT(OS_NT);
lstrcpyW(szPath, pszProgram);
//
// Check for extension. We don't allow anything that doesn't have an extension.
//
pszTmp = CmStrrchrW(szPath, TEXT('.'));
if (pszTmp == NULL)
{
return (FALSE);
}
//
// Get Basename
//
pszTmp = CmStrrchrW(szPath, TEXT('\\'));
if (pszTmp)
{
lstrcpyW(szBaseName, CharNextW(pszTmp));
*pszTmp = TEXT('\0');
}
else
{
lstrcpyW(szBaseName, pszProgram);
}
lstrcpyW(szSubKey, L"SOFTWARE\\Microsoft\\Connection Manager\\");
lstrcatW(szSubKey, pszServiceName);
lstrcatW(szSubKey, L"\\WinLogon Actions");
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey) )
{
cb = sizeof(dwLoadFlags);
if (ERROR_SUCCESS == RegQueryValueExW(hKey, szBaseName, NULL, NULL, (PBYTE) &dwLoadFlags, &cb))
{
switch (dwLoadFlags)
{
case 0: // system32 directory only
//
// No paths in this case, .CMS entry should match key name
//
if (0 == lstrcmpiW(szBaseName, szPath))
{
fIsAllowed = TRUE;
*lpdwLoadType = dwLoadFlags;
}
break;
case 1: // profile directory only
//
// Get servicename path
//
pszTmp = CmStripFileNameW(pszServiceFileName, FALSE);
if (pszTmp && 0 == lstrcmpiW(pszTmp, szPath))
{
fIsAllowed = TRUE;
*lpdwLoadType = dwLoadFlags;
}
CmFree(pszTmp);
break;
default: // invalid flag
CMTRACE1(TEXT("IsActionEnabled() - Invalid LoadFlags %d"), dwLoadFlags);
goto OnError;
break;
}
}
OnError:
RegCloseKey(hKey);
}
if (fIsAllowed == FALSE)
{
CMTRACE1W(L"IsActionEnabled(returned FALSE) %s", pszProgram);
}
return (fIsAllowed);
}
//+----------------------------------------------------------------------------
//
// Function: ApplyPasswordHandlingToBuffer
//
// Synopsis: Convert password: all upper case, all lower case, or no conversion
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
// LPTSTR pszBuffer - Buffer to be modified
//
// Returns: Nothing
//
// Note: Available types are: PWHANDLE_LOWER, PWHANDLE_UPPER, PWHANDLE_NONE:
//
// History: nickball Created 03/03/00
//
//+----------------------------------------------------------------------------
void ApplyPasswordHandlingToBuffer(ArgsStruct *pArgs,
LPTSTR pszBuffer)
{
MYDBGASSERT(pArgs);
MYDBGASSERT(pszBuffer);
if (NULL == pArgs || NULL == pszBuffer)
{
return;
}
CIni *piniService = GetAppropriateIniService(pArgs, pArgs->nDialIdx);
if (piniService)
{
switch (piniService->GPPI(c_pszCmSection, c_pszCmEntryPasswordHandling))
{
case PWHANDLE_LOWER:
CharLowerU(pszBuffer);
break;
case PWHANDLE_UPPER:
CharUpperU(pszBuffer);
break;
case PWHANDLE_NONE:
default:
break;
}
}
delete piniService;
}
//+----------------------------------------------------------------------------
//
// Function: ApplyDomainHandlingToDialParams
//
// Synopsis: Handles the messy details of Domain management relative to username
// Returns a buffer containing the original buffer and (if appropriate)
// the domain prepended.
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
// CIni *piniService - Ptr to the Cini object to be used
// LPTSTR pszBuffer - Ptr to the current buffer to which we'll prepend
//
// Returns: LPTSTR -
//
// History: nickball Created 03/04/00
//
//+----------------------------------------------------------------------------
LPTSTR ApplyDomainPrependToBufferAlloc(ArgsStruct *pArgs,
CIni *piniService,
LPTSTR pszBuffer,
LPCTSTR pszDunName)
{
MYDBGASSERT(pArgs);
MYDBGASSERT(piniService);
MYDBGASSERT(pszBuffer);
MYDBGASSERT(pszDunName);
if (NULL == pArgs || NULL == piniService || NULL == pszBuffer || NULL == pszDunName)
{
return NULL;
}
BOOL bPrependDomain = FALSE;
//
// Prepare the user name. We may need to pre-pend the domain
//
if (*pArgs->szDomain)
{
//
// There is a domain, see if pre-pending is explicitly set in the
// DUN setting for this connection.
//
LPTSTR pszDunEntry = NULL;
LPTSTR pszPreviousSection = NULL;
if (pszDunName && *pszDunName)
{
pszDunEntry = CmStrCpyAlloc(pszDunName);
}
else
{
pszDunEntry = GetDefaultDunSettingName(piniService, FALSE); // FALSE == fTunnelEntry, never called from DoTunnelDial
}
MYDBGASSERT(pszDunEntry);
if (pszDunEntry)
{
//
// Since we are going to call SetSection on piniService to set it up
// to retrieve the DUN setting name, we should save the existing value
// before we overwrite it.
//
pszPreviousSection = CmStrCpyAlloc(piniService->GetSection());
MYDBGASSERT(pszPreviousSection);
if (pszPreviousSection) // this will either be "" or the previous section name
{
LPTSTR pszSection = CmStrCpyAlloc(TEXT("&"));
pszSection = CmStrCatAlloc(&pszSection, pszDunEntry);
MYDBGASSERT(pszSection);
piniService->SetSection(pszSection);
CmFree(pszSection);
}
}
int nTmp = piniService->GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunPrependDialupDomain, -1);
if (-1 == nTmp)
{
//
// There is no prepend flag, so on W9X infer from the VPN scenario.
// The inference is that if we're dialing a number that is part of
// a VPN scenario AND its a same-name logon, then we need to prepend
// the Domain to the user name (eg. REDMOND\username).
//
if (OS_W9X && pArgs->fUseTunneling && pArgs->fUseSameUserName)
{
bPrependDomain = TRUE;
}
}
else
{
bPrependDomain = (BOOL) nTmp;
}
//
// Restore the previous section to piniService to as not to have a function side effect.
//
if (pszPreviousSection)
{
piniService->SetSection(pszPreviousSection);
CmFree(pszPreviousSection);
}
CmFree(pszDunEntry);
}
//
// Build username as required
//
LPTSTR pszName = NULL;
if (bPrependDomain)
{
pszName = CmStrCpyAlloc(pArgs->szDomain);
CmStrCatAlloc(&pszName, TEXT("\\"));
CmStrCatAlloc(&pszName, pszBuffer);
}
else
{
pszName = CmStrCpyAlloc(pszBuffer);
}
return pszName;
}
//+----------------------------------------------------------------------------
//
// Function: GetPrefixAndSuffix
//
// Synopsis: Handles the messy details of determining the username prefix and
// suffix to be used. This data varies according to whether the
// referencING profile has either a prefix and suffix in which case
// they are used against all phone #s. However, if they do not exist
// in the referencING profile, then the prefix and suffix in the
// referecED profile (if any) are used.
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
// CIni *piniService - Ptr to the Cini object to be used
// LPTSTR *ppszUsernamePrefix - Address of pointer to be allocated
// filled w/ prefix.
// LPTSTR *ppszUsernamePrefix - Address of pointer to be allocated
// filled w/ suffix.
//
// Returns: Nothing, caller should validate output
//
// History: nickball Created 05/31/00
//
//+----------------------------------------------------------------------------
void GetPrefixSuffix(ArgsStruct *pArgs, CIni* piniService, LPTSTR *ppszUsernamePrefix, LPTSTR *ppszUsernameSuffix)
{
MYDBGASSERT(pArgs);
MYDBGASSERT(piniService);
MYDBGASSERT(ppszUsernameSuffix);
MYDBGASSERT(ppszUsernamePrefix);
if (NULL == pArgs || NULL == piniService || NULL == ppszUsernamePrefix || NULL == ppszUsernameSuffix)
{
return;
}
//
// If the referencING (top-level) service file includes a prefix or suffix,
// then we'll use it. Otherwise, we'll use the realm from the service file
// associated with the phone book from which the user selected the POP.
//
LPTSTR pszTmpPrefix = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryUserPrefix);
LPTSTR pszTmpSuffix = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryUserSuffix);
//
// Thus, if both prefix and suffix are empty and this is a referencED profile
// and the user has selected a phone # from a referenced pbk, we'll retrieve
// the data from the referencED service file.
//
if (pszTmpPrefix && pszTmpSuffix)
{
if (!*pszTmpPrefix && !*pszTmpSuffix)
{
if (pArgs->fHasRefs &&
lstrcmpiU(pArgs->aDialInfo[pArgs->nDialIdx].szPhoneBookFile, pArgs->piniService->GetFile()) != 0)
{
if (pszTmpPrefix)
{
CmFree(pszTmpPrefix);
}
if (pszTmpSuffix)
{
CmFree(pszTmpSuffix);
}
pszTmpPrefix = piniService->GPPS(c_pszCmSection, c_pszCmEntryUserPrefix);
pszTmpSuffix = piniService->GPPS(c_pszCmSection, c_pszCmEntryUserSuffix);
}
}
}
*ppszUsernamePrefix = pszTmpPrefix;
*ppszUsernameSuffix = pszTmpSuffix;
}
//+----------------------------------------------------------------------------
//
// Function: ApplyPrefixSuffixToBufferAlloc
//
// Synopsis: Handles the messy details of Domain management relative to username
// Updates the the RasDialParams as appropriate.
//
// Arguments: ArgsStruct *pArgs - Ptr to global Args struct
// CIni *piniService - Ptr to the Cini object to be used
// LPTSTR pszBuffer - Ptr to current buffer to which we'll apply
// suffix and prefix data.
//
// Returns: A new buffer allocation containing the original buffer
// with applied suffix and prefix data.
//
// Note: The CIni object is expected to be that associated with the current
// number. In other words, that returned by GetApporpriateIniService
//
// History: nickball Created 03/04/00
// nickball GetPrefixSuffix 05/31/00
//
//+----------------------------------------------------------------------------
LPTSTR ApplyPrefixSuffixToBufferAlloc(ArgsStruct *pArgs,
CIni *piniService,
LPTSTR pszBuffer)
{
MYDBGASSERT(pArgs);
MYDBGASSERT(piniService);
MYDBGASSERT(pszBuffer);
if (NULL == pArgs || NULL == piniService || NULL == pszBuffer)
{
return NULL;
}
LPTSTR pszUsernamePrefix = NULL;
LPTSTR pszUsernameSuffix = NULL;
GetPrefixSuffix(pArgs, piniService, &pszUsernamePrefix, &pszUsernameSuffix);
//
// Don't double prepend the prefix if there is one. User may have
// provided a fully qualified name including realm prefix.
// (eg. MSN/user)
//
if (*pszUsernamePrefix)
{
DWORD dwBufferLen = lstrlenU(pszBuffer);
DWORD dwPrefixLen = lstrlenU(pszUsernamePrefix);
if (dwBufferLen > dwPrefixLen)
{
TCHAR cReplacedChar = pszBuffer[dwPrefixLen];
pszBuffer[dwPrefixLen] = TEXT('\0');
if (0 == lstrcmpiU(pszBuffer, pszUsernamePrefix))
{
//
// The prefix has already been prepended. Let's clear out
// the pszUsernamePrefix field.
//
*pszUsernamePrefix = TEXT('\0');
}
pszBuffer[dwPrefixLen] = cReplacedChar;
}
}
CmStrCatAlloc(&pszUsernamePrefix, pszBuffer);
//
// Don't double append the suffix if there is one. User may have
// provided a fully qualified name including domain suffix.
// (eg. [email protected])
//
if (*pszUsernameSuffix)
{
DWORD dwSuffixLen = lstrlenU(pszUsernameSuffix);
DWORD dwUserNameLen = lstrlenU(pszUsernamePrefix);
//
// Make sure the total username is longer than the suffix itself,
// otherwise we have no change of a double append. If it is longer than
// the suffix length, go ahead and make sure we aren't appending the suffix
// twice.
//
if (dwSuffixLen && (dwSuffixLen < dwUserNameLen))
{
if (0 == lstrcmpiU(&(pszUsernamePrefix[dwUserNameLen - dwSuffixLen]), pszUsernameSuffix))
{
*pszUsernameSuffix = TEXT('\0');
}
}
}
CmStrCatAlloc(&pszUsernamePrefix, pszUsernameSuffix);
CmFree(pszUsernameSuffix);
//
// pszUsernamePrefix now contains the final product
//
return pszUsernamePrefix;
}
//+----------------------------------------------------------------------------
//
// Function: InBetween
//
// Synopsis: Simple function which returns TRUE if the passed in number is
// in between the given lower and upper bounds. Note that the
// boundaries themselves are considered in bounds.
//
// Arguments: int iLowerBound - lower bound
// int iNumber - number to test
// int iUpperBound - upper bound
//
// Returns: TRUE if the number is equal to either of the boundaries or in between
// the two numbers. Note that if the lower and upper boundary numbers
// are backwards it will always return FALSE.
//
//
// History: quintinb Created 07/24/00
//
//+----------------------------------------------------------------------------
BOOL InBetween(int iLowerBound, int iNumber, int iUpperBound)
{
return ((iLowerBound <= iNumber) && (iUpperBound >= iNumber));
}