|
|
//+----------------------------------------------------------------------------
//
// 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)); }
|