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.
 
 
 
 
 
 

16845 lines
601 KiB

//+----------------------------------------------------------------------------
//
// File: profwiz.cpp
//
// Module: CMAK.EXE
//
// Synopsis: Main code for CMAK
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// Author: a-frankh Created 05/15/97
// quintinb Updated header and made a 08/07/98
// few other changes
//
//+----------------------------------------------------------------------------
#include "cmmaster.h"
#include "cmsecure.h"
// linkdll is needed because of cmsecure
#include "linkdll.h" // LinkToDll and BindLinkage
#include "linkdll.cpp" // LinkToDll and BindLinkage
//
// Include HasSpecifiedAccessToFileOrDir
//
#ifndef CreateFileU
#ifdef UNICODE
#define CreateFileU CreateFileW
#else
#define CreateFileU CreateFileA
#endif
#endif
#include "hasfileaccess.cpp"
#include "gppswithalloc.cpp"
//
// Include the locale-safe replacement for lstrcmpi
//
#include "CompareString.cpp"
//
// Globals
//
//
// This global specifies what the return value of CMAK should be. Note that if the user
// cancels the wizard this value isn't used and FALSE (0) is returned by the wizard code.
//
int g_iCMAKReturnVal = CMAK_RETURN_CANCEL;
//
// This was added for shipping with IEAK. If the /o command line switch is specified this
// bool is set to true and we don't show the finish dialog (either one).
//
BOOL g_bIEAKBuild = FALSE;
const TCHAR* const g_szBadFilenameChars = TEXT("!@#$%^&*(){}[]+=,;:?/\\'\"`~|<>. ");
const TCHAR* const g_szBadLongServiceNameChars = TEXT("*/\\:?\"<>|[]");
const TCHAR* const c_pszDoNotShowLcidMisMatchDialog = TEXT("DoNotShowLcidMisMatchDialog");
TCHAR g_szInfFile[MAX_PATH+1]; // full path/filename of working inf file
TCHAR g_szCmakdir[MAX_PATH+1]; // full path of working inf file (includes ending slash)
TCHAR g_szOsdir[MAX_PATH+1]; // full path of platform branch (includes ending slash)
TCHAR g_szSedFile[MAX_PATH+1]; // full path of working sed file
TCHAR g_szCmsFile[MAX_PATH+1];
TCHAR g_szCmpFile[MAX_PATH+1];
TCHAR g_szSupportDir[MAX_PATH+1]; // full path of support files are located
TCHAR g_szTempDir[MAX_PATH+1];
TCHAR g_szLastBrowsePath[MAX_PATH+1] = {0};
TCHAR g_szShortServiceName[MAX_PATH+1];
TCHAR g_szLongServiceName[MAX_PATH+1];
TCHAR g_szBrandBmp[MAX_PATH+1];
TCHAR g_szPhoneBmp[MAX_PATH+1];
TCHAR g_szLargeIco[MAX_PATH+1];
TCHAR g_szSmallIco[MAX_PATH+1];
TCHAR g_szTrayIco[MAX_PATH+1];
TCHAR g_szPhonebk[MAX_PATH+1];
TCHAR g_szRegion[MAX_PATH+1];
TCHAR g_szHelp[MAX_PATH+1];
TCHAR g_szOutdir[MAX_PATH+1];
TCHAR g_szUrl[MAX_PATH+1];
TCHAR g_szOutExe[MAX_PATH+1];
TCHAR g_szSvcMsg[MAX_PATH+1];
TCHAR g_szPrefix[MAX_PATH+1];
TCHAR g_szSuffix[MAX_PATH+1];
TCHAR g_szLicense[MAX_PATH+1];
TCHAR g_szPhoneName[MAX_PATH+1];
TCHAR g_szAppTitle[MAX_PATH+1];
TCHAR g_szCmProxyFile[MAX_PATH+1];
TCHAR g_szCmRouteFile[MAX_PATH+1];
TCHAR g_szVpnFile[MAX_PATH+1];
BOOL g_bNewProfile = TRUE;
BOOL g_bUseTunneling = FALSE;
BOOL g_bUseSamePwd = FALSE;
BOOL g_bUpdatePhonebook = FALSE;
BOOL g_bPresharedKeyNeeded = FALSE;
#ifdef _WIN64
BOOL g_bIncludeCmCode = FALSE; // don't include CM code on IA64
#else
TCHAR g_szCmBinsTempDir[MAX_PATH+1] = {0};
BOOL g_bIncludeCmCode = TRUE;
#endif
HINSTANCE g_hInstance;
ListBxList * g_pHeadDunEntry=NULL;
ListBxList * g_pTailDunEntry=NULL;
ListBxList * g_pHeadVpnEntry=NULL;
ListBxList * g_pTailVpnEntry=NULL;
ListBxList * g_pHeadProfile=NULL;
ListBxList * g_pTailProfile=NULL;
ListBxList * g_pHeadExtra=NULL;
ListBxList * g_pTailExtra=NULL;
ListBxList * g_pHeadMerge=NULL;
ListBxList * g_pTailMerge=NULL;
ListBxList * g_pHeadRefs=NULL;
ListBxList * g_pTailRefs=NULL;
ListBxList * g_pHeadRename=NULL;
ListBxList * g_pTailRename=NULL;
CustomActionList* g_pCustomActionList = NULL;
IconMenu * g_pHeadIcon;
IconMenu * g_pTailIcon;
IconMenu DlgEditItem; //global used to pass info to/from dialogs
//+----------------------------------------------------------------------------
//
// Function: TextIsRoundTripable
//
// Synopsis: Tests to see if the passed in text is convertables from Unicode
// to ANSI and then back to Unicode again. If so returns TRUE,
// else FALSE.
//
// Arguments: LPCTSTR pszCharBuffer - string to test
// BOOL bDisplayError - whether to display an error message or not
// if the text isn't roundtripable
//
// Returns: BOOL - TRUE if the roundtrip was success
//
// History: quintinb Created Header 6/16/99
//
//+----------------------------------------------------------------------------
BOOL TextIsRoundTripable(LPCTSTR pszCharBuffer, BOOL bDisplayError)
{
LPWSTR pszUnicodeBuffer = NULL;
BOOL bRoundTrip = FALSE;
MYDBGASSERT(pszCharBuffer);
if (pszCharBuffer)
{
LPSTR pszAnsiBuffer = WzToSzWithAlloc(pszCharBuffer);
if (pszAnsiBuffer)
{
pszUnicodeBuffer = SzToWzWithAlloc(pszAnsiBuffer);
if (pszUnicodeBuffer && (0 == lstrcmp(pszCharBuffer, pszUnicodeBuffer)))
{
//
// Then we were able to round trip the strings successfully
// Set bRoundTrip to TRUE so that we don't throw an error.
//
bRoundTrip = TRUE;
}
CmFree(pszUnicodeBuffer);
CmFree(pszAnsiBuffer);
}
if (!bRoundTrip && bDisplayError)
{
//
// Throw an error message.
//
LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_CANNOT_ROUNDTRIP);
if (pszTmp)
{
DWORD dwSize = lstrlen(pszTmp) + lstrlen(pszCharBuffer) + 1;
LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
if (pszMsg)
{
wsprintf(pszMsg, pszTmp, pszCharBuffer);
MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
CmFree(pszMsg);
}
CmFree(pszTmp);
}
}
}
return bRoundTrip;
}
//+----------------------------------------------------------------------------
//
// Function: GetTextFromControl
//
// Synopsis: This is a wrapper function that sends a WM_GETTEXT message to
// the control specified by the input parameters. Once the text
// is retrieved from the control, we convert it to ANSI and then
// back to UNICODE so that we can compare the original Unicode
// string to the round-tripped string. If these are not equal we
// throw an error message, if bDisplayError is TRUE, and return
// a failure value (-1). It is up to the caller to take appropriate
// behavior (preventing the user from continuing, etc.)
//
// Arguments: IN HWND hDlg - HWND of the dialog the control is on
// IN int nCtrlId - ID of the control to get text from
// OUT LPTSTR pszCharBuffer - out buffer to hold the returned TEXT
// IN DWORD dwCharInBuffer - numbers of chars in out buffer
// BOOL bDisplayError - if TRUE display an error message if
// the text isn't roundtripable
//
// Returns: LONG - the number of chars copied to the output buffer or -1 on error
//
// History: quintinb Created 6/15/99
//
//+----------------------------------------------------------------------------
LRESULT GetTextFromControl(IN HWND hDlg, IN int nCtrlId, OUT LPTSTR pszCharBuffer, IN DWORD dwCharInBuffer, BOOL bDisplayError)
{
LRESULT lResult = 0;
if (hDlg && nCtrlId && pszCharBuffer && dwCharInBuffer)
{
lResult = SendDlgItemMessage(hDlg, nCtrlId, WM_GETTEXT, (WPARAM)dwCharInBuffer, (LPARAM)pszCharBuffer);
#ifdef UNICODE
//
// We want to make sure that we can convert the strings to MBCS. If we cannot then we are not
// going to be able to store the string in the our ANSI data files (.cms, .cmp, .inf, etc.).
// Thus we need to convert the string to MBCS and then back to UNICODE. We will then compare the original
// string to the resultant string and see if they match.
//
if (TEXT('\0') != pszCharBuffer[0])
{
if (!TextIsRoundTripable(pszCharBuffer, bDisplayError))
{
//
// Set the return code to an error value.
//
lResult = -1;
}
}
#endif
}
else
{
CMASSERTMSG(FALSE, TEXT("Bad Parameter passed to GetTextFromControl!"));
}
return lResult;
}
//+----------------------------------------------------------------------------
//
// Function: FreeIconMenu
//
// Synopsis: This function frees the linked list of status area menu icons.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb Created Header 05/09/00
//
//+----------------------------------------------------------------------------
void FreeIconMenu()
{
IconMenu * LoopPtr;
IconMenu * TmpPtr;
if (g_pHeadIcon == NULL)
{
return;
}
LoopPtr = g_pHeadIcon;
while( LoopPtr != NULL)
{
TmpPtr = LoopPtr;
LoopPtr = LoopPtr->next;
CmFree(TmpPtr);
}
g_pHeadIcon = NULL;
g_pTailIcon = NULL;
}
//+----------------------------------------------------------------------------
//
// Function: ReferencedDownLoad
//
// Synopsis: This function opens each referenced cms file to check and see if it has a
// PBURL. If so, then this files is considered to do PB downloads and should
// cause the top level profile to run the cmdl connect action.
//
// Arguments: None
//
// Returns: BOOL - returns whether referenced profiles need cmdl
//
// History: quintinb Created 2/2/98
//
//+----------------------------------------------------------------------------
BOOL ReferencedDownLoad()
{
ListBxList * ptrMergeProfile = NULL;
TCHAR szRefCmsFile[MAX_PATH+1];
TCHAR szPbUrl[MAX_PATH+1];
if (NULL == g_pHeadMerge)
{
return FALSE;
}
else
{
//
// Enumerate the referenced profiles to try to find one that has a PBURL field.
//
ptrMergeProfile = g_pHeadMerge;
while (NULL != ptrMergeProfile)
{
//
// Let's try the profile directory for the merged profile in order to get the most up to date version. This
// is where CMAK will pull it from if available. If not, we will fall back to the one in the temp directory.
//
MYVERIFY(CELEMS(szRefCmsFile) > (UINT)wsprintf(szRefCmsFile, TEXT("%s%s\\%s.cms"), g_szOsdir, ptrMergeProfile->szName, ptrMergeProfile->szName));
if (!FileExists(szRefCmsFile))
{
//
// Next check to see if the merged cms file exists in the temp dir
//
MYVERIFY(CELEMS(szRefCmsFile) > (UINT)wsprintf(szRefCmsFile, TEXT("%s\\%s.cms"), g_szTempDir, ptrMergeProfile->szName));
}
GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), szPbUrl, MAX_PATH, szRefCmsFile); //lint !e534
if (TEXT('\0') != szPbUrl[0])
{
//
// Only takes one phonebook with a URL to enable referenced downloads
//
return TRUE;
}
ptrMergeProfile = ptrMergeProfile->next;
}
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: SetWindowLongWrapper
//
// Synopsis: This function is an error checking wrapper for the Windows API
// SetWindowLong. This function returns the value that is being
// overwritten by this call (if you set a the window long to a value
// you are overwriting the previous value that it contained. This
// previous value is the value returned by the API). If there is an
// error then this function returns 0. However, the previous value
// could have been 0. The only way to distinguish the two cases (an
// actual error and the previous value being zero) is to call SetLastError
// with a zero value. Then you can call GetLastError after the call and if
// the returned error code isn't zero then we know we have an error. All
// of this functionality is combined in this function.
//
// Arguments: HWND hWnd - handle of window to set the long var in
// int nIndex - offset of value to set
// LONG dwNewLong - new value
//
// Returns: BOOL - Returns TRUE if the call succeeded
//
// History: quintinb Created 1/7/98
//
//+----------------------------------------------------------------------------
BOOL SetWindowLongWrapper(HWND hWnd, int nIndex, LONG dwNewLong )
{
DWORD dwError;
SetLastError(0);
SetWindowLongPtr(hWnd, nIndex, (LONG_PTR)dwNewLong); //lint !e534
dwError = GetLastError();
return (0 == dwError);
}
//+---------------------------------------------------------------------------
//
// Function: CopyFileWrapper
//
// Synopsis: Bundles disk full Error Handling with standard CopyFile functionality
//
// Arguments: lpExistingFileName -- source file of copy
// lpNewFileName -- destination file of copy
// bFailIfExists -- flag to tell copy to fail if file already exists
//
// Assumptions: This function assumes that the two filename parameters contain the
// fully qualified path to the source and destination files.
//
// Returns: TRUE if copy was sucessful, FALSE on an error
//
// History: quintinb created 11/7/97
//
//----------------------------------------------------------------------------
BOOL CopyFileWrapper(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists)
{
DWORD dwError;
int nMessageReturn = 0;
TCHAR szMsg[2*MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szPath[MAX_PATH+1];
do {
if (!CopyFile(lpExistingFileName, lpNewFileName, bFailIfExists))
{
//
// The CopyFile failed, best check error codes
//
dwError = GetLastError();
switch(dwError)
{
case ERROR_HANDLE_DISK_FULL:
case ERROR_DISK_FULL:
if (0 == GetFilePath(lpNewFileName, szPath))
{
_tcscpy(szPath, lpNewFileName);
}
MYVERIFY(0 != LoadString(g_hInstance, IDS_DISKFULL, szTemp, MAX_PATH));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, szPath));
nMessageReturn = MessageBox(NULL, szMsg, g_szAppTitle, MB_RETRYCANCEL | MB_ICONERROR
| MB_TASKMODAL);
if (nMessageReturn != IDRETRY)
{
return FALSE;
}
break;
default:
//
// Replaces the functionality of the FileAccessErr function so all the file
// errors are trapped in one place. This function still exits for special
// cases.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_NOACCESS, szTemp, MAX_PATH));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, lpNewFileName));
MessageBox(NULL ,szMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL
| MB_TOPMOST );
return FALSE;
}
} else {
nMessageReturn = 0;
}
} while (IDRETRY == nMessageReturn);
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: CheckDiskSpaceForCompression
//
// Synopsis: Checks to see if there is sufficient disk space for compressing
// the files listed in the passed in sed file. To do this, uses a simplistic
// algorithm of adding up the disk space used by all the files listed in the
// strings section of the SED file, under the FILE<num> entries. If there is
// at least dwBytes (space taken up by all the files in the SED) of space left
// on the partition containing the SED file, then the function returns true.
// Otherwise false is returned, indicating that there may not be enough space left.
//
// Arguments: szSed -- the full path to the SED file to look for filenames in
//
// Returns: TRUE if sufficient space to continue, FALSE if not sure or probably
// not enough
//
// Assumptions: That the partition we are checking for diskspace on is the partition of
// the current directory.
//
// History: quintinb created 11/10/97
//
//----------------------------------------------------------------------------
BOOL CheckDiskSpaceForCompression (LPCTSTR szSed)
{
TCHAR szKey[MAX_PATH+1];
TCHAR szFileName[MAX_PATH+1];
DWORD dwBytes = 0;
DWORD dwChars;
//
// Calculate the amount of space taken up by the files listed in the SED
//
int nCount = 0;
do
{
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("FILE%d"), nCount));
dwChars = GetPrivateProfileString(c_pszInfSectionStrings, szKey, TEXT(""),
szFileName, MAX_PATH, szSed);
if (0 != dwChars)
{
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
dwBytes += GetFileSize(hFile, NULL);
MYVERIFY(0 != CloseHandle(hFile));
}
}
nCount++;
} while (0 != dwChars);
//
// Now that we know how much space the files in the SED take up, we should see how much space is on
// the partition.
//
DWORD dwFreeClusters;
DWORD dwBytesPerSector;
DWORD dwSectorsPerCluster;
DWORD dwTotalClusters;
DWORD dwModulus;
if (GetDiskFreeSpace(NULL, &dwSectorsPerCluster, &dwBytesPerSector,
&dwFreeClusters, &dwTotalClusters))
{
//
// Because dwSectorsPerCluster*dwBytesPerSector*dwFreeClusters could very easily
// overflow a 32 bit value, we will calculate the total size of the files to compress
// in clusters (dwBytes/(dwSectorsPerCluster*dwBytesPerSector)) and compare
// against the dwFreeClusters value.
//
DWORD dwSizeInSectors = dwBytes / dwBytesPerSector;
dwModulus = dwBytes % dwBytesPerSector;
if (dwModulus)
{
dwSizeInSectors++; // we want to round up if it didn't divide evenly
}
DWORD dwSizeInClusters = dwSizeInSectors / dwSectorsPerCluster;
dwModulus = dwSizeInSectors % dwSectorsPerCluster;
if (dwModulus)
{
dwSizeInClusters++; // we want to round up if it didn't divide evenly
}
if (dwFreeClusters > dwSizeInClusters)
{
return TRUE;
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessBold
//
// Synopsis: This function makes the IDC_LBLTITLE static text control bold
// on the WM_INITDIALOG message and releases the bold on WM_DESTROY.
// This function is usually placed at the top of a window procedure
// so that these messages are handled automatically. Note that the
// function doesn't otherwise affect the processing of these messages
// by the original window procedure.
//
// Arguments: HWND hDlg - dialog window handle to process messages for
// UINT message - message to handle
//
// Returns: Nothing
//
// History: quintinb Created Header 05/09/00
//
//+----------------------------------------------------------------------------
void ProcessBold(HWND hDlg, UINT message)
{
switch (message)
{
case WM_INITDIALOG:
MYVERIFY(ERROR_SUCCESS == MakeBold(GetDlgItem(hDlg, IDC_LBLTITLE), TRUE));
break;
case WM_DESTROY:
MYVERIFY(ERROR_SUCCESS == ReleaseBold(GetDlgItem(hDlg, IDC_LBLTITLE)));
break;
default:
break;
}
}
//+---------------------------------------------------------------------------
//
// Function: SetDefaultGUIFont
//
// Synopsis: Sets the font of the control to be the Default GUI Font.
//
// Arguments: hwnd - Window handle of the dialog
// message - message from the dialog box procedure
// cltID - ID of the control you want changed.
//
// Returns: ERROR_SUCCESS
//
// History: 4/31/97 a-frankh Created
// quintinb Renamed from ProcessDBCS and cleaned up
//----------------------------------------------------------------------------
void SetDefaultGUIFont(HWND hDlg, UINT message, int ctlID)
{
HFONT hFont = NULL;
switch (message)
{
case WM_INITDIALOG:
hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
if (hFont == NULL)
{
hFont = (HFONT) GetStockObject(SYSTEM_FONT);
}
if (hFont != NULL)
{
SendMessage(GetDlgItem(hDlg, ctlID), WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0)); //lint !e534 WM_SETFONT doesn't return anything
}
break;
default:
break;
}
}
//+----------------------------------------------------------------------------
//
// Function: IsAlpha
//
// Synopsis: Determines if the current platform is Alpha.
//
// Arguments: None
//
// Returns: static BOOL - TRUE if the current platform is Alpha
//
// History: nickball Created 10/11/97
//
//+----------------------------------------------------------------------------
static BOOL IsAlpha()
{
SYSTEM_INFO sysinfo;
ZeroMemory(&sysinfo, sizeof(sysinfo));
GetSystemInfo(&sysinfo);
return (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA);
}
//+----------------------------------------------------------------------------
//
// Function: ShowMessage
//
// Synopsis: Simple helper function to handle message display
//
// Arguments: HWND hDlg - Parent window handle
// int strID - Resource ID of the string to be displayed
// int mbtype - The type of messagebox (MB_OK, etc.)
//
// Returns: static int - User response to message box
//
// History: nickball Created Header 10/11/97
// quintinb Changed strID and mbtype to UINTs for LINT 1-5-98
// quintinb Change to use CmLoadString 6/17/99
//
//+----------------------------------------------------------------------------
int ShowMessage(HWND hDlg, UINT strID, UINT mbtype)
{
int iReturn = 0;
LPTSTR pszMsg = CmLoadString(g_hInstance, strID);
if (pszMsg)
{
iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, mbtype);
}
CmFree(pszMsg);
return iReturn;
}
//+----------------------------------------------------------------------------
//
// Function: GetFileName
//
// Synopsis: Get just the filename from a full path and filename
//
// Arguments: LPCTSTR lpPath - Ptr to the full name and path
// LPTSTR lpFileName - Ptr to the buffer the hold the extracted name
//
// Returns: Nothing
//
// History: nickball Created Header 10/11/97
// quintinb modified to fix bug with URL's 7-15-98
//
//+----------------------------------------------------------------------------
void GetFileName(LPCTSTR lpPath, LPTSTR lpFileName)
{
LPTSTR pch;
pch = _tcsrchr(lpPath, _T('\\'));
if (NULL == pch)
{
//
// Catch paths like c:temp.inf
//
if (_istalpha(lpPath[0]) && (_T(':') == lpPath[1])) //lint !e732
{
pch = (TCHAR*)&(lpPath[1]);
}
}
if (NULL == pch)
{
_tcscpy(lpFileName, lpPath);
}
else
{
pch = CharNext(pch);
_tcscpy(lpFileName, pch);
}
}
//+----------------------------------------------------------------------------
//
// Function: GetFilePath
//
// Synopsis: Get just the full path from a full path and filename
//
// Arguments: LPCTSTR lpFullPath - Ptr to the full name and path
// LPTSTR lpPath - Ptr to the buffer the hold the extracted path
//
// Returns: either 0 or the number of chars copied into the return buffer
//
// History: quintinb Created 11/11/97
//
//+----------------------------------------------------------------------------
int GetFilePath(LPCTSTR lpFullPath, LPTSTR lpPath)
{
LPTSTR pch;
_tcscpy(lpPath, lpFullPath);
// first find the last \ char in the
// string
pch = _tcsrchr(lpPath,_T('\\'));
// if this is null, look for a path similar to
// c:junk
if (pch == NULL)
{
pch = _tcsrchr(lpPath,_T(':'));
if (NULL != pch)
{
pch = CharNext(pch);
_tcscpy(pch, TEXT("\\"));
pch = CharNext(pch);
*pch = TEXT('\0');
return _tcslen(lpPath);
} else {
lpPath[0] = TEXT('\0');
return 0;
}
} else {
*pch = TEXT('\0');
return _tcslen(lpPath);
}
}
//+----------------------------------------------------------------------------
//
// Function: IsFileNameValid
//
// Synopsis: Check if this is a valid filename and if we have environment macro
//
// Custom Action filename require different validation. That's what the
// 3rd parameter distinguishes and thus still keeps the validation code
// in one function.
//
// CUSTOM ACTIONS:
//
// If a full path (including drive letter) is present the
// warning message doesn't occur
//
// Extension Macro Action Example
// ----------------------------------------------------
// No No Warn notepad
// Yes No Warn notepad.exe
// Yes No Warn C:\notepad.exe
// No Yes Warn %windir%\notepad
// Yes Yes No Warning %windir%\notepad.exe
// Yes Yes Warn C:\%windir%\notepad.exe
//
// MENU ITEMS:
//
// Menu Item paths don't support macros or full paths.
// We only want to warn the user if the file extension
// is missing.
//
// Arguments: LPCTSTR pszFileName - filename to check
// hDlg - HWND
// iControl - control to set focus to
// fCustomActionFileName - TRUE if path is for custom action
//
// Returns: TRUE/FALSE
//
// History: tomkel Created 01/31/2002
//
//+----------------------------------------------------------------------------
BOOL IsFileNameValid(LPTSTR pszFileName, HWND hDlg, int iControl, BOOL fCustomActionFileName)
{
BOOL fRetVal = TRUE;
LPTSTR pszPercent = NULL;
LPTSTR pszPercent2 = NULL;
if (!pszFileName || !hDlg)
{
return FALSE;
}
CFileNameParts cPrgFileName(pszFileName);
if (fCustomActionFileName)
{
//
// Custom Action filename - macros are supported
//
//
// Check for %somemacro% (eg. %windir%), thus need to find 2 of '%'
//
pszPercent = CmStrchr(cPrgFileName.m_Dir, TEXT('%'));
if (pszPercent && pszPercent[0])
{
pszPercent++;
pszPercent2 = CmStrchr(pszPercent, TEXT('%'));
}
if ((NULL == cPrgFileName.m_Extension[0]) && (FALSE == (pszPercent && pszPercent2)))
{
//
// Warn the user he has a missing extension and no environment macro.
//
if (IDNO == ShowMessage(hDlg, IDS_BAD_EXTENSION, MB_YESNO))
{
SetFocus(GetDlgItem(hDlg, iControl));
return FALSE;
}
}
else if ((cPrgFileName.m_Extension[0]) && (FALSE == (pszPercent && pszPercent2)) && (NULL == cPrgFileName.m_Drive[0]))
{
//
// Warn the user he has no environment macro even though an extension is present,
// but only if this isn't a full path
//
if (IDNO == ShowMessage(hDlg, IDS_NO_MACRO, MB_YESNO))
{
SetFocus(GetDlgItem(hDlg, iControl));
return FALSE;
}
}
else if ((NULL == cPrgFileName.m_Extension[0]) && (TRUE == (pszPercent && pszPercent2)))
{
//
// Warn the user he has no extension, even though an environment macro is present.
//
if (IDNO == ShowMessage(hDlg, IDS_NO_EXT_WITH_MACRO, MB_YESNO))
{
SetFocus(GetDlgItem(hDlg, iControl));
return FALSE;
}
}
else
{
//
// For custom action file name
// warn the user if they have a string with a path but
// doesn't start with an environment variable.
//
LPTSTR pszSlash = CmStrchr(pszFileName, TEXT('\\'));
if (pszSlash && (TEXT('%') != pszFileName[0]))
{
if (IDYES == ShowMessage(hDlg, IDS_PATH_WITH_NO_ENV, MB_YESNO | MB_ICONWARNING))
{
SetFocus(GetDlgItem(hDlg, iControl));
return FALSE;
}
}
}
}
else
{
//
// Menu item file name - macros are NOT supported, but we don't warn users about it
//
if (NULL == cPrgFileName.m_Extension[0])
{
//
// Warn the user he has a missing extension and no environment macro.
//
if (IDNO == ShowMessage(hDlg, IDS_BAD_EXTENSION, MB_YESNO))
{
SetFocus(GetDlgItem(hDlg, iControl));
return FALSE;
}
}
}
return fRetVal;
}
//+----------------------------------------------------------------------------
//
// Function: GetName
//
// Synopsis: Extracts filename from a full path and file name and returns a p
// tointer to the result.
//
// Arguments: LPCTSTR lpPath - Ptr to the full name and path
//
// Returns: LPTSTR - Ptr to the static buffer containing the result of the extraction.
//
// History: nickball Created Header 10/11/97
//
//+----------------------------------------------------------------------------
LPTSTR GetName(LPCTSTR lpPath)
{
static TCHAR szStr[MAX_PATH+1];
GetFileName(lpPath,szStr);
return szStr;
}
BOOL GetShortFileName(LPTSTR lpFile, LPTSTR lpShortName)
{
HANDLE hFile;
WIN32_FIND_DATA FindData;
TCHAR szPath[MAX_PATH+1];
GetFileName(lpFile,lpShortName);
hFile = FindFirstFile(lpFile,&FindData);
if (hFile == INVALID_HANDLE_VALUE)
{
//
// Not found, try looking from OS dir as the root, because
// the filename may be a relative path from a CMS file entry.
//
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH,szPath));
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
hFile = FindFirstFile(lpFile,&FindData);
MYVERIFY(0 != SetCurrentDirectory(szPath));
}
if (hFile != INVALID_HANDLE_VALUE)
{
if (*FindData.cAlternateFileName)
{
if (_tcsicmp(lpShortName,FindData.cAlternateFileName) != 0)
{
_tcscpy(lpShortName,FindData.cAlternateFileName);
}
}
MYVERIFY(0 != FindClose(hFile));
return TRUE;
}
else
{
return FALSE;
}
}
//+----------------------------------------------------------------------------
//
// Function: GetBaseName
//
// Synopsis: Extracts the base filename (no extension) from a full filename
// and path
//
// Arguments: LPTSTR lpPath - The full path and filename
// LPTSTR lpFileName - The buffer to receive the extracted base name.
//
// Returns: Nothing
//
// History: nickball Created Header 10/11/97
//
//+----------------------------------------------------------------------------
void GetBaseName(LPTSTR lpPath,LPTSTR lpFileName)
{
LPTSTR pch;
GetFileName(lpPath, lpFileName);
pch = _tcsrchr(lpFileName, _T('.'));
if (pch)
{
*pch = TEXT('\0');
}
}
//+----------------------------------------------------------------------------
//
// Function: FileAccessErr
//
// Synopsis: Helper function that handles notification of a file access error
//
// Arguments: HWND hDlg - Parent window handle
// LPTSTR lpFile - The file that caused the access error.
//
// Returns: static void - Nothing
//
// History: nickball Created Header 10/11/97
//
//+----------------------------------------------------------------------------
static void FileAccessErr(HWND hDlg,LPCTSTR lpFile)
{
TCHAR szMsg[MAX_PATH+1];
TCHAR szTemp2[2*MAX_PATH+1];
MYVERIFY(0 != LoadString(g_hInstance,IDS_NOACCESS,szMsg,MAX_PATH));
MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2,szMsg,lpFile));
MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
}
//+----------------------------------------------------------------------------
//
// Function: VerifyFile
//
// Synopsis: Given the ID of a dialog box edit control in ctrlID
// Check if user entered in something different than what is contained in lpFile
// If it is different, get the entire path and verify it exists.
// If it doesn't exist and ShowErr = TRUE, display an error message
// Copy the full path to lpFile if exists
//
// Arguments: HWND hDlg - Window handle of the dialog containing the edit control
// DWORD ctrlID - edit control containing the file to check
// LPTSTR lpFile - Filename to verify (checked against that contained in the control)
// BOOL ShowErr - Whether to show an error message or not
//
// Returns: BOOL - Return TRUE if the file was verified to exist
//
// History: quintinb Created Header 1/8/98
//
//+----------------------------------------------------------------------------
BOOL VerifyFile(HWND hDlg, DWORD ctrlID, LPTSTR lpFile, BOOL ShowErr)
{
TCHAR szMsg[MAX_PATH+1] = {0};
TCHAR szTemp[MAX_PATH+1] = {0};
TCHAR szTemp2[2*MAX_PATH+1] = {0};
TCHAR szPath[MAX_PATH+1] = {0};
int nResult = 0;
LPTSTR lpfilename = NULL;
HANDLE hInf = INVALID_HANDLE_VALUE;
LRESULT lrNumChars = 0;
lrNumChars = GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, ShowErr); // bDisplayError == ShowErr
//
// don't check blank entry
//
if (0 == lrNumChars || 0 == szTemp[0])
{
if (lpFile)
{
lpFile[0] = TEXT('\0');
}
return TRUE;
}
//
// Also check to make sure that we were able to convert the text to ANSI
//
if (-1 == lrNumChars)
{
SetFocus(GetDlgItem(hDlg, ctrlID));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return FALSE;
}
//
// if filename is still the same, ignore entry box
//
CheckNameChange(lpFile, szTemp);
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szPath));
//
// Check current directory, if not found, check OS directory as root.
// This handles relative paths from the CMS
//
nResult = SearchPath(NULL, lpFile, NULL, MAX_PATH, szTemp2, &lpfilename);
if (!nResult)
{
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
nResult = SearchPath(NULL, lpFile, NULL, MAX_PATH, szTemp2, &lpfilename);
if (!nResult)
{
goto Error;
}
}
hInf = CreateFile(szTemp2, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
MYVERIFY(0 != SetCurrentDirectory(szPath));
if (hInf == INVALID_HANDLE_VALUE)
{
goto Error;
}
else
{
MYVERIFY(0 != CloseHandle(hInf));
}
_tcscpy(lpFile,szTemp2);
return TRUE;
Error:
_tcscpy(lpFile,szTemp);
if (TEXT('\0') != szPath[0])
{
MYVERIFY(0 != SetCurrentDirectory(szPath));
}
if (ShowErr)
{
MYVERIFY(0 != LoadString(g_hInstance, IDS_NOEXIST, szMsg, MAX_PATH));
MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2, szMsg, szTemp));
MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
SetFocus(GetDlgItem(hDlg, ctrlID));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
}
return FALSE;
}
// If has entry but file doesn't exist, blank out entry.
BOOL VerifyPhonebk(HWND hDlg,DWORD ctrlID,LPTSTR lpFile)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szTemp2[MAX_PATH+1];
TCHAR szPath[MAX_PATH+1];
int nResult;
LPTSTR lpfilename;
HANDLE hInf;
LRESULT lrNumChars;
//
// If the text is not convertable to ANSI then we will catch it on the Next/Back. Thus
// don't try to catch it here, would throw too many error messages at the user.
//
lrNumChars = GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
// don't check blank entry
if (0 == lrNumChars || 0 == szTemp[0])
{
lpFile[0] = 0;
return TRUE;
}
// if filename is still the same, don't check
CheckNameChange(lpFile,szTemp);
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH,szPath));
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
nResult = SearchPath(NULL,lpFile,NULL,MAX_PATH,szTemp2,&lpfilename);
if (!nResult)
{
goto Error;
}
hInf = CreateFile(szTemp2,GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
MYVERIFY(0 != SetCurrentDirectory(szPath));
if (hInf == INVALID_HANDLE_VALUE)
{
goto Error;
}
else
{
MYVERIFY(0 != CloseHandle(hInf));
}
_tcscpy(lpFile,szTemp2);
// SendMessage(GetDlgItem(hDlg, ctrlID), WM_SETTEXT, 0, (LPARAM)lpFile);
return TRUE;
Error:
lpFile[0] = TEXT('\0');
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, ctrlID), WM_SETTEXT, 0, (LPARAM)lpFile));
return FALSE;
}
// If user entered in a new filename, copy it to lpnew
void CheckNameChange(LPTSTR lpold, LPTSTR lpnew)
{
//
// if filename changed or if new name contains directories, copy new to old
//
if ((_tcsicmp(GetName(lpold), lpnew) != 0) || (_tcschr(lpnew, TEXT('\\')) != NULL))
{
_tcscpy(lpold, lpnew);
}
}
//+----------------------------------------------------------------------------
//
// Function: WriteRegStringValue
//
// Synopsis: Wrapper function to encapsulate opening a key for write access and
// then setting a string value. Assumes the string is NULL terminated.
//
// Arguments: HKEY hBaseKey - base key, HKCU/HKLM/etc.
// LPCTSTR pszKeyName - subkey name
// LPCTSTR pszValueName - Value name to write
// LPCTSTR pszValueToWrite - Value data string to write
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb Created 6/15/99
//
//+----------------------------------------------------------------------------
BOOL WriteRegStringValue(HKEY hBaseKey, LPCTSTR pszKeyName, LPCTSTR pszValueName, LPCTSTR pszValueToWrite)
{
HKEY hKey;
DWORD dwSize;
BOOL bReturn = FALSE;
if (hBaseKey && pszKeyName && pszValueName && pszValueToWrite &&
TEXT('\0') != pszKeyName[0] && TEXT('\0') != pszValueName[0]) // pszValueToWrite could be empty
{
LONG lReturn = RegOpenKeyEx(hBaseKey, pszKeyName, 0, KEY_WRITE, &hKey);
if (ERROR_SUCCESS == lReturn)
{
dwSize = (lstrlen(pszValueToWrite) +1)*sizeof(TCHAR);
lReturn = RegSetValueEx(hKey, pszValueName, 0, REG_SZ, (LPBYTE)pszValueToWrite, dwSize);
if (ERROR_SUCCESS == lReturn)
{
bReturn = TRUE;
}
RegCloseKey(hKey);
}
}
return bReturn;
}
// check to see if the original CMAK installtion directory exists and
// contains the language directories.
//+----------------------------------------------------------------------------
//
// Function: EraseTempDir
//
// Synopsis: This function deletes all the files in the tempdir (stored in the global g_szTempDir)
// then changes directories to the CMAK dir (stored in the global g_szCmakdir). From
// there the temp dir is deleted.
//
// Arguments: None
//
// Returns: BOOL - TRUE if the temp dir was deleted
//
// History: quintinb Created Header 1/5/98
// quintinb changed return type to a BOOL
//
//+----------------------------------------------------------------------------
BOOL EraseTempDir()
{
SHFILEOPSTRUCT FileOp;
ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
//
// First save a copy of the file
//
FileOp.wFunc = FO_DELETE;
FileOp.pFrom = g_szTempDir;
FileOp.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION;
int iRet = SHFileOperation (&FileOp); // return 0 on success
return (iRet ? FALSE : TRUE);
}
// copies service profile information from the CMAK directory to the
// temporary directory
static BOOL CopyToTempDir(LPTSTR szName)
{
HANDLE hCopyFileSearch;
WIN32_FIND_DATA FindData;
BOOL bCopyResult;
TCHAR szTemp[MAX_PATH+1];
MYVERIFY(0 != SetCurrentDirectory(g_szCmakdir));
if (!CreateDirectory(g_szTempDir,NULL))
{
if (ERROR_ALREADY_EXISTS != GetLastError())
{
return FALSE;
}
}
if (TEXT('\0') == szName[0])
{
return TRUE;
}
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szOsdir, szName));
if (!SetCurrentDirectory(szTemp))
{
return FALSE;
}
hCopyFileSearch = FindFirstFile(c_pszWildCard,&FindData);
if (hCopyFileSearch != INVALID_HANDLE_VALUE)
{
do
{
if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
{
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, FindData.cFileName));
//
// CLEAN OUT ANY READ ONLY ATTRIBUTES
//
MYVERIFY(0 != SetFileAttributes(FindData.cFileName,FILE_ATTRIBUTE_NORMAL));
if (!CopyFileWrapper(FindData.cFileName,szTemp,FALSE))
{
return FALSE;
}
}
bCopyResult = FindNextFile(hCopyFileSearch,&FindData);
} while (TRUE == bCopyResult);
}
MYVERIFY(0 != FindClose(hCopyFileSearch));
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: GetInfVersion
//
// Synopsis: Opens the inf file and tries to get the InfVersion key from the CMAK Status
// section. If the inf file doesn't contain a version stamp then we know it is
// version 0 (1.0 and 1.1 releases).
//
// Arguments: LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
//
// Returns: int - returns the version value or zero if one wasn't found.
//
// History: quintinb Created 3/4/98
//
//+----------------------------------------------------------------------------
int GetInfVersion(LPTSTR szFullPathToInfFile)
{
if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
{
CMASSERTMSG(FALSE, TEXT("GetInfVersion -- Invalid InfPath Input."));
return FALSE;
}
return ((int)GetPrivateProfileInt(c_pszCmakStatus, c_pszInfVersion, 0, szFullPathToInfFile));
}
//+----------------------------------------------------------------------------
//
// Function: WriteInfVersion
//
// Synopsis: Opens the inf file and writes the current INF file version to the Cmak Status section.
//
// Arguments: LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
//
// Returns: Returns TRUE if able to write the value
//
// History: quintinb Created 3/4/98
//
//+----------------------------------------------------------------------------
BOOL WriteInfVersion(LPTSTR szFullPathToInfFile, int iVersion)
{
TCHAR szTemp[MAX_PATH+1];
if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
{
CMASSERTMSG(FALSE, TEXT("WriteInfVersion -- Invalid InfPath Input."));
return FALSE;
}
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), iVersion));
return (0 != WritePrivateProfileString(c_pszCmakStatus, c_pszInfVersion, szTemp, szFullPathToInfFile));
}
//+----------------------------------------------------------------------------
//
// Function: UpgradeInf
//
// Synopsis: This function upgrades and INF from an older version to the current
// version.
//
// Arguments: LPCTSTR szRenamedInfFile - Filename to save the old INF to
// LPCTSTR szFullPathToInfFile - Profile INF file
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb Created Header 7/31/98
//
//+----------------------------------------------------------------------------
BOOL UpgradeInf(LPCTSTR szRenamedInfFile, LPCTSTR szFullPathToInfFile)
{
SHFILEOPSTRUCT FileOp;
TCHAR szTemp[MAX_PATH+1];
DWORD dwSize;
TCHAR* pszBuffer = NULL;
const int NUMSECTIONS = 3;
const TCHAR* const aszSectionName[NUMSECTIONS] =
{
c_pszCmakStatus,
c_pszExtraFiles,
c_pszMergeProfiles
};
const int NUMKEYS = 4;
const TCHAR* const aszKeyName[NUMKEYS] =
{
c_pszCmEntryServiceName,
c_pszShortSvcName,
c_pszUninstallAppTitle,
c_pszDesktopIcon
};
ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
//
// First save a copy of the file
//
FileOp.wFunc = FO_COPY;
FileOp.pFrom = szFullPathToInfFile;
FileOp.pTo = szRenamedInfFile;
FileOp.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION;
if (0 != SHFileOperation (&FileOp))
{
return FALSE;
}
//
// First Copy the template.inf from the lang dir so that we have something to work from
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szSupportDir, c_pszTemplateInf));
MYVERIFY(FALSE != CopyFileWrapper(szTemp, szFullPathToInfFile, FALSE));
MYVERIFY(0 != SetFileAttributes(szFullPathToInfFile, FILE_ATTRIBUTE_NORMAL));
//
// now migrate the [CMAK Status], [Extra Files], [Merge Profiles] sections
//
for (int i=0; i < NUMSECTIONS; i++)
{
pszBuffer = GetPrivateProfileSectionWithAlloc(aszSectionName[i], szRenamedInfFile);
if (pszBuffer)
{
MYVERIFY(0 != WritePrivateProfileSection(aszSectionName[i], pszBuffer, szFullPathToInfFile));
//
// Free the allocated Buffer
//
CmFree(pszBuffer);
pszBuffer = NULL;
}
}
//
// Migrate the ServiceName, ShortSvcName, DesktopGUID, UninstallAppTitle, DesktopIcon values
// from the strings section.
//
for (i=0; i < NUMKEYS; i++)
{
dwSize = GetPrivateProfileString(c_pszInfSectionStrings, aszKeyName[i], TEXT(""), szTemp, MAX_PATH, szRenamedInfFile);
if (0 != dwSize)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, aszKeyName[i], szTemp, szFullPathToInfFile));
}
}
//
// Special Case for the Desktop GUID. We always write Quotes around the GUID and these get
// stripped by the reading routine. Thus we need to add them back.
//
dwSize = GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szTemp, MAX_PATH, szRenamedInfFile);
if (0 != dwSize)
{
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, szTemp, szFullPathToInfFile);
}
// The follwing sections should get rewritten and won't need to be migrated.
// [Xnstall.AddReg.Icon]
// [RegisterOCXSection], [Xnstall.CopyFiles], [Xnstall.CopyFiles.SingleUser], [Xnstall.CopyFiles.ICM],
// [Remove.DelFiles.ICM], [SourceDisksFiles], [Xnstall.RenameReg],
// [Remove.DelFiles]
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: EnsureInfIsCurrent
//
// Synopsis: This function does whatever processing is necessary to upgrade the inf from
// its current version to the current version of CMAK itself.
//
// Arguments: HWND hDlg - window handle of the dialog box for modal messagebox purposes.
// LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
//
// Returns: BOOL - return TRUE if the inf was successfully upgraded, otherwise FALSE
//
// History: quintinb Created 3/4/98
//
//+----------------------------------------------------------------------------
BOOL EnsureInfIsCurrent(HWND hDlg, LPTSTR szFullPathToInfFile)
{
int iInfVersion;
TCHAR szRenamedInfFile[2*MAX_PATH+1];
TCHAR szTitle[2*MAX_PATH+1];
TCHAR szMsg[2*MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
BOOL bUpgradeProfile = FALSE;
if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
{
CMASSERTMSG(FALSE, TEXT("EnsureInfIsCurrent -- Invalid InfPath Input."));
return FALSE;
}
iInfVersion = GetInfVersion(szFullPathToInfFile);
ZeroMemory(szRenamedInfFile, sizeof(szRenamedInfFile));
MYVERIFY(CELEMS(szRenamedInfFile) > (UINT)wsprintf(szRenamedInfFile, TEXT("%s.bak"),
szFullPathToInfFile));
//
// We want to upgrade the inf if the Profile versions don't match. We also have
// a special case to handle upgrading NT5 Beta3 (and IEAK) profiles to NT5 RTM
// profiles. In order to fix NTRAID 323721 and 331446, the inf format had to change
// slightly thus we need to make sure to upgrade these profiles. We will use any
// cmdial32.dll build prior to 2055 as needing this fix. If version == 4 and the BuildNumber
// doesn't exist we assume it is a new profile. Thus don't upgrade.
//
const DWORD c_dwBuild2080 = ((2080 << c_iShiftAmount) + VER_PRODUCTBUILD_QFE);
DWORD dwProfileBuildNumber = (DWORD)GetPrivateProfileInt(c_pszSectionCmDial32, c_pszVerBuild,
(c_dwBuild2080 + 1), szFullPathToInfFile);
bUpgradeProfile = (iInfVersion != PROFILEVERSION) ||
((4 == iInfVersion) && (c_dwBuild2080 > dwProfileBuildNumber));
//
// Always grab most of the information out of the template so that we get the correct language
// info.
//
if (bUpgradeProfile)
{
MYVERIFY(0 != LoadString(g_hInstance, IDS_MUST_UPGRADE_INF, szTitle, 2*MAX_PATH)); // temporarily use szTitle
GetFileName(szRenamedInfFile, szTemp);
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTitle, szTemp));
MYVERIFY(IDOK == MessageBox(hDlg, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL));
return UpgradeInf(szRenamedInfFile, szFullPathToInfFile);
}
return TRUE;
}
BOOL CopyFromTempDir(LPTSTR szName)
{
HANDLE hCopyFileSearch;
WIN32_FIND_DATA FindData;
BOOL bCopyResult;
TCHAR szSource[MAX_PATH+1];
TCHAR szDest[MAX_PATH+1];
TCHAR szOut[MAX_PATH+1];
//
// Create profile directory
//
MYVERIFY(CELEMS(szOut) > (UINT)wsprintf(szOut, TEXT("%s%s"), g_szOsdir, szName));
if (0 == SetCurrentDirectory(szOut))
{
MYVERIFY(0 != CreateDirectory(szOut,NULL));
}
MYVERIFY(0 != SetCurrentDirectory(g_szTempDir));
hCopyFileSearch = FindFirstFile(c_pszWildCard, &FindData);
if (hCopyFileSearch != INVALID_HANDLE_VALUE)
{
do
{
if (0 == (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"), szOut, FindData.cFileName));
MYVERIFY(CELEMS(szSource) > (UINT)wsprintf(szSource, TEXT("%s\\%s"), g_szTempDir, FindData.cFileName));
if (!CopyFileWrapper(szSource, szDest, FALSE))
{
return FALSE;
}
}
bCopyResult = FindNextFile(hCopyFileSearch, &FindData);
} while (bCopyResult == TRUE);
}
MYVERIFY(0 != FindClose(hCopyFileSearch));
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: LoadServiceProfiles
//
// Synopsis: This function loads all the service profiles in the subdirectories
// of the current directory (thus you set this to c:\program files\cmak\profiles-32
// to have it load the normal profiles). The profiles are loaded into
// CMAK's internal linked list of available profiles to edit.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb Created Header 6/24/98
// quintinb removed two boolean arguments 6/24/98
//
//+----------------------------------------------------------------------------
void LoadServiceProfiles()
{
WIN32_FIND_DATA FindData;
HANDLE hFileSearch;
HANDLE hCms;
BOOL bResult;
TCHAR szTemp[MAX_PATH+1];
hFileSearch = FindFirstFile(c_pszWildCard,&FindData);
if (hFileSearch != INVALID_HANDLE_VALUE)
{
do
{
if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0)
{
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"),
FindData.cFileName, FindData.cFileName));
//
// If we can open the file, add a record to our profile list
//
hCms = CreateFile(szTemp,GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if (hCms != INVALID_HANDLE_VALUE)
{
MYVERIFY(0 != CloseHandle(hCms));
MYVERIFY(FALSE != createListBxRecord(&g_pHeadProfile, &g_pTailProfile, (void *)NULL, 0, FindData.cFileName));
}
}
bResult = FindNextFile(hFileSearch, &FindData);
} while (TRUE == bResult);
MYVERIFY(0 != FindClose(hFileSearch));
}
}
//+---------------------------------------------------------------------------
//
// Function: CopyNonLocalProfile
//
// Synopsis: Helper function to handle details of copying an external profile
// to the local CMAK layout.
//
// Arguments: pszName - The name of the profile to be copied
//
// Returns: Nothing
//
// History: nickball - created - 11/16/97
// quintinb - modified to not change directory -- 6/24/98
//
//----------------------------------------------------------------------------
void CopyNonLocalProfile(LPCTSTR pszName, LPCTSTR pszExistingProfileDir)
{
WIN32_FIND_DATA FindData;
TCHAR szTemp[MAX_PATH+1];
TCHAR szProfileDestDir[MAX_PATH+1];
TCHAR szOldInf[MAX_PATH+1];
TCHAR szFindFilePath[MAX_PATH+1];
TCHAR szTempDest[MAX_PATH+1];
BOOL bCopyResult;
HANDLE hCopyFileSearch;
//
// First determine if it exists already, we don't want to overwrite
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s\\%s.cms"), g_szCmakdir,
c_pszProfiles, pszName, pszName));
if (!FileExists(szTemp))
{
//
// Profile does not exist locally, create profile and platform sub-dirs
//
MYVERIFY(CELEMS(szProfileDestDir) > (UINT)wsprintf(szProfileDestDir,
TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, pszName));
MYVERIFY(0 != CreateDirectory(szProfileDestDir, NULL));
//
// First try to copy the inf from the system directory. This is the old location.
// If it doesn't exist here, then we will pick it up when we copy the profile directory, so
// don't report an error on failure.
//
MYVERIFY(0 != GetSystemDirectory(szTemp, CELEMS(szTemp)));
MYVERIFY(CELEMS(szOldInf) > (UINT)wsprintf(szOldInf, TEXT("%s\\%s.inf"),
szTemp, pszName));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.inf"),
szProfileDestDir, pszName));
if (FileExists(szOldInf))
{
MYVERIFY(0 != CopyFile(szOldInf, szTemp, FALSE));
}
//
// Start copying files
//
MYVERIFY (CELEMS(szFindFilePath) > (UINT)wsprintf(szFindFilePath, TEXT("%s\\*.*"),
pszExistingProfileDir));
hCopyFileSearch = FindFirstFile(szFindFilePath, &FindData);
if (hCopyFileSearch != INVALID_HANDLE_VALUE)
{
do
{
if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
{
MYVERIFY (CELEMS(szTempDest) > (UINT)wsprintf(szTempDest, TEXT("%s\\%s"), szProfileDestDir, FindData.cFileName));
MYVERIFY (CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), pszExistingProfileDir, FindData.cFileName));
MYVERIFY(0 != CopyFile(szTemp, szTempDest, FALSE));
MYVERIFY(0 != SetFileAttributes(szTempDest, FILE_ATTRIBUTE_NORMAL));
}
bCopyResult = FindNextFile(hCopyFileSearch,&FindData);
} while (TRUE == bCopyResult);
MYVERIFY(0 != FindClose(hCopyFileSearch));
}
//4404 - don't copy .cmp with user information in it. always create new.
}
}
//+----------------------------------------------------------------------------
//
// Function: GetProfileDirAndShortSvcNameFromCmpFilePath
//
// Synopsis:
//
// Arguments: IN LPCTSTR szCmpFileLocation - Cmp File location of the profile
// OUT LPTSTR pszShortServiceName - returns the ShortServiceName of the profile
// OUT LPTSTR pszProfileDirLocation - returns the Full path to the profile dir
// IN UINT uiStrLen - Length of the buffer pointed to by pszProfileDirLocation
// in characters.
//
// Returns: TRUE if successful
//
// History: quintinb Created 6/24/98
//
//+----------------------------------------------------------------------------
BOOL GetProfileDirAndShortSvcNameFromCmpFilePath(IN LPCTSTR pszCmpFileLocation,
OUT LPTSTR pszShortServiceName,
OUT LPTSTR pszProfileDirLocation,
IN UINT uiStrLen)
{
//
// Check Inputs
//
MYDBGASSERT(pszCmpFileLocation);
MYDBGASSERT(pszProfileDirLocation);
MYDBGASSERT(pszShortServiceName);
MYDBGASSERT(0 != uiStrLen);
MYDBGASSERT(TEXT('\0') != pszCmpFileLocation[0]);
if ((NULL == pszCmpFileLocation) ||
(TEXT('\0') == pszCmpFileLocation[0]) ||
(NULL == pszProfileDirLocation) ||
(NULL == pszShortServiceName) ||
(0 == uiStrLen)
)
{
return FALSE;
}
//
// Split the input cmp path
//
CFileNameParts FileParts(pszCmpFileLocation);
//
// Construct the cms path from the cmp path parts
//
MYVERIFY(uiStrLen > (UINT)wsprintf(pszProfileDirLocation, TEXT("%s%s%s"), FileParts.m_Drive, FileParts.m_Dir, FileParts.m_FileName));
//
// Short Service Names are 8.3, thus copy upto 9 chars which includes the NULL.
//
MYVERIFY(NULL != lstrcpyn(pszShortServiceName, FileParts.m_FileName, 9));
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: CopyInstalledProfilesForCmakToEdit
//
// Synopsis: This function finds all the installed profiles that a user has
// access to and copies them to the CMAK\Profiles-32 directory so
// the user may edit them in CMAK. To do this it enumerates both
// the HKLM and the current HKCU Connection Manager Mappings keys
// and calls CopyNonLocalProfile on each found profile.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb Created 6/24/98
//
//+----------------------------------------------------------------------------
void CopyInstalledProfilesForCmakToEdit()
{
HKEY hKey;
HKEY hBaseKey;
DWORD dwType;
LPTSTR pszCurrentValue = NULL;
LPTSTR pszCurrentData = NULL;
TCHAR szShortServiceName[MAX_PATH+1];
TCHAR szCurrentProfileDirPath[MAX_PATH+1];
LPTSTR pszExpandedPath = NULL;
for (int i=0; i < 2; i++)
{
//
// First Load the Single User Profiles (we want to give preference to loading these if
// they happen to have it installed both all user and single user)
//
if (0 == i)
{
hBaseKey = HKEY_CURRENT_USER;
}
else
{
hBaseKey = HKEY_LOCAL_MACHINE;
}
if (ERROR_SUCCESS == RegOpenKeyEx(hBaseKey, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey))
{
DWORD dwValueBufSize = 0;
DWORD dwDataBufSize = 0;
//
// figure out how big the buffers need to be
//
if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueBufSize, &dwDataBufSize, NULL, NULL))
{
//
// Increment the count we got back to include the terminating NULL char
//
dwValueBufSize++;
dwDataBufSize += 2; // this is in bytes
//
// allocate the space we need
//
pszCurrentValue = (LPTSTR) CmMalloc(dwValueBufSize * sizeof(TCHAR));
pszCurrentData = (LPTSTR) CmMalloc(dwDataBufSize);
CMASSERTMSG(pszCurrentValue && pszCurrentData, TEXT("CopyInstalledProfilesForCmakToEdit -- CmMalloc failed allocating value and data buffers."));
if (pszCurrentValue && pszCurrentData)
{
DWORD dwIndex = 0;
DWORD dwValueSize = dwValueBufSize; // only used for the in/out param
DWORD dwDataSize = dwDataBufSize; // only used for the in/out param
while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, pszCurrentValue, &dwValueSize, NULL, &dwType, (LPBYTE)pszCurrentData, &dwDataSize))
{
if (REG_SZ == dwType)
{
MYDBGASSERT(0 != pszCurrentValue[0]);
MYDBGASSERT(0 != pszCurrentData[0]);
//
// Expand environment strings if necessary (single user profiles contain the
// %USERPROFILE% environment var).
//
DWORD dwDataSizeExpanded = ExpandEnvironmentStrings(pszCurrentData, NULL, 0);
CMASSERTMSG((dwDataSizeExpanded != 0),
TEXT("CopyInstalledProfilesForCmakToEdit -- Error expanding environment vars."));
if (dwDataSizeExpanded)
{
pszExpandedPath = (LPTSTR) CmMalloc(dwDataSizeExpanded * sizeof(TCHAR));
if (NULL != pszExpandedPath)
{
DWORD dwTmp = ExpandEnvironmentStrings(pszCurrentData, pszExpandedPath, dwDataSizeExpanded);
MYDBGASSERT(dwTmp == dwDataSizeExpanded);
if (dwTmp)
{
MYVERIFY(0 != GetProfileDirAndShortSvcNameFromCmpFilePath(pszExpandedPath,
szShortServiceName, szCurrentProfileDirPath,
CELEMS(szCurrentProfileDirPath)));
MYDBGASSERT(0 != szCurrentProfileDirPath[0]);
MYDBGASSERT(0 != szShortServiceName[0]);
CopyNonLocalProfile(szShortServiceName, szCurrentProfileDirPath);
}
CmFree(pszExpandedPath);
}
}
}
dwValueSize = dwValueBufSize;
dwDataSize = dwDataBufSize;
dwIndex++;
}
CmFree(pszCurrentValue);
CmFree(pszCurrentData);
}
}
MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
}
}
}
//+----------------------------------------------------------------------------
//
// Function: GetLangFromInfTemplate
//
// Synopsis: Wrote to replace GetLangFromDir. This function gets the LCID value
// from an inf and then calls GetLocaleInfo to get the Language Display
// name.
//
// Arguments: LPCTSTR szFullInfPath - full path to the inf file
// OUT LPTSTR pszLanguageDisplayName - out param to hold the display name of the LCID value
// IN int iCharsInBuffer - number of chars in the out buffer
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb Created Header 8/8/98
//
//+----------------------------------------------------------------------------
BOOL GetLangFromInfTemplate(LPCTSTR szFullInfPath, OUT LPTSTR pszLanguageDisplayName, IN int iCharsInBuffer)
{
TCHAR szTemp[MAX_PATH+1] = TEXT("");
MYDBGASSERT(NULL != szFullInfPath);
MYDBGASSERT(TEXT('\0') != szFullInfPath[0]);
MYDBGASSERT(NULL != pszLanguageDisplayName);
MYDBGASSERT(0 < iCharsInBuffer);
if (FileExists(szFullInfPath))
{
//
// First check for the new LCID location under strings, we shouldn't need to
// check both places because it is template.inf but we will anyway just for
// completeness.
//
if (0 == GetPrivateProfileString(c_pszInfSectionStrings, c_pszCmLCID,
TEXT(""), szTemp, CELEMS(szTemp), szFullInfPath))
{
//
// If the new key didn't exist, then try the old [Intl] section and
// display key. The change was made during the CMAK Unicode changes to
// make the inf template easier to localize.
//
MYVERIFY(0 != GetPrivateProfileString(c_pszIntl, c_pszDisplay,
TEXT(""), szTemp, CELEMS(szTemp), szFullInfPath));
}
//
// Now try to extract the LCID from the string if we have one.
//
if (TEXT('\0') != szTemp[0])
{
//
// This value should be an LCID so a negative value is invalid anyway
//
DWORD dwLang = (DWORD)_ttol(szTemp);
int nResult = GetLocaleInfo(dwLang, LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
pszLanguageDisplayName, iCharsInBuffer);
if (0 == nResult)
{
ZeroMemory(pszLanguageDisplayName, sizeof(TCHAR)*iCharsInBuffer);
return FALSE;
}
else
{
return TRUE;
}
}
}
else
{
CMTRACE1(TEXT("GetLangFromInfTemplate can't find %s"), szFullInfPath);
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: GetLocalizedLanguageNameFromLCID
//
// Synopsis: This function returns the language name of the given LCID in the
// language of the current system default language.
//
// Arguments: DWORD dwLCID - Locale Identifier to get the language for
//
// Returns: LPTSTR - returns NULL if unsuccessful, a pointer to the string
// otherwise. The Caller is responsible for CmFree-ing it.
//
// History: quintinb Created 6/17/99
//
//+----------------------------------------------------------------------------
LPTSTR GetLocalizedLanguageNameFromLCID(DWORD dwLCID)
{
LPTSTR pszReturnString = NULL;
LPTSTR pszTmp = NULL;
if (dwLCID)
{
int nCharsNeeded = GetLocaleInfo(dwLCID, LOCALE_SLANGUAGE, NULL, 0);
pszTmp = (LPTSTR)CmMalloc(nCharsNeeded*sizeof(TCHAR) + sizeof(TCHAR)); // one extra for the NULL
if (pszTmp)
{
nCharsNeeded = GetLocaleInfo(dwLCID, LOCALE_SLANGUAGE, pszTmp, nCharsNeeded);
if (0 != nCharsNeeded)
{
pszReturnString = pszTmp;
}
}
}
return pszReturnString;
}
//+----------------------------------------------------------------------------
//
// Function: GetDoNotShowLcidMisMatchDialogRegValue
//
// Synopsis: This function gets the registry key value which stores whether
// the user has checked the box on the Lcids don't match dialog
// displayed by CMAK which says, "Don't show this dialog again".
//
//
// Arguments: None
//
// Returns: BOOL - TRUE if cmak should NOT show the dialog or FALSE if it should
//
// History: quintinb Created 03/22/2001
//
//+----------------------------------------------------------------------------
BOOL GetDoNotShowLcidMisMatchDialogRegValue()
{
BOOL bReturn = FALSE;
HKEY hKey;
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmak, 0, KEY_READ, &hKey);
if (ERROR_SUCCESS == lResult)
{
DWORD dwType = 0;
DWORD dwDoNotShowDialog = 0;
DWORD dwSize = sizeof(DWORD);
lResult = RegQueryValueEx(hKey, c_pszDoNotShowLcidMisMatchDialog, NULL, &dwType,
(LPBYTE)&dwDoNotShowDialog, &dwSize);
if (ERROR_SUCCESS == lResult)
{
bReturn = (BOOL)dwDoNotShowDialog;
}
RegCloseKey(hKey);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: SetDoNotShowLcidMisMatchDialogRegValue
//
// Synopsis: This function sets the registry key value which stores whether
// the user has checked the box on the Lcids don't match dialog
// displayed by CMAK which says, "Don't show this dialog again".
//
//
// Arguments: DWORD dwValueToSet - TRUE or FALSE value that should be set in reg
//
// Returns: BOOL - TRUE if the value was set successfully, FALSE otherwise
//
// History: quintinb Created 03/22/2001
//
//+----------------------------------------------------------------------------
BOOL SetDoNotShowLcidMisMatchDialogRegValue(DWORD dwValueToSet)
{
HKEY hKey;
BOOL bReturn = FALSE;
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmak, 0, KEY_WRITE, &hKey);
if (ERROR_SUCCESS == lResult)
{
lResult = RegSetValueEx(hKey, c_pszDoNotShowLcidMisMatchDialog, NULL, REG_DWORD,
(LPBYTE)&dwValueToSet, sizeof(DWORD));
if (ERROR_SUCCESS == lResult)
{
bReturn = TRUE;
}
RegCloseKey(hKey);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessLCIDsDontMatchPopup
//
// Synopsis: Processes windows messages for the dialog which tells the user they
// have a mismatch between the system locale and the language of CMAK
// itself. Note that we pass in a pointer to the message string containing
// the language names through the lParam parameter.
//
// Arguments: WND hDlg - dialog window handle
// UINT message - message identifier
// WPARAM wParam - wParam Value
// LPARAM lParam - lParam Value
//
//
// History: quintinb Created 03/22/01
//
//+----------------------------------------------------------------------------
INT_PTR CALLBACK ProcessLCIDsDontMatchPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DWORD dwChecked = 0;
SetDefaultGUIFont(hDlg, message, IDC_MSG);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_LCID_POPUP)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
//
// We need to set the text passed through the lParam parameter
// to the IDC_MSG control.
//
if (lParam)
{
LPTSTR pszMsg = (LPTSTR)lParam;
MYVERIFY(TRUE == SendDlgItemMessage (hDlg, IDC_MSG, WM_SETTEXT, (WPARAM)0, (LPARAM)pszMsg));
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK: // Continue
//
// Get the value of the "Do not show me this dialog again", checkbox
// and save it to the registry
//
dwChecked = IsDlgButtonChecked(hDlg, IDC_CHECK1);
MYVERIFY(FALSE != SetDoNotShowLcidMisMatchDialogRegValue(dwChecked));
MYVERIFY(0 != EndDialog(hDlg, IDOK));
return TRUE;
break;
case IDCANCEL: // Cancel
MYVERIFY(0 != EndDialog(hDlg, IDCANCEL));
return TRUE;
break;
default:
break;
}
break;
default:
return FALSE;
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: DisplayLcidsDoNotMatchDialog
//
// Synopsis: This function handles the details of displaying the Lcids don't
// match dialog. Including such details as checking the registry
// key to see if the user has already seen the message and asked
// not to see it again, loading the proper string resources, displaying
// the dialog, and processing the user's answer.
//
//
// Arguments: HINSTANCE hInstance - Instance handle for resources
// DWORD dwCmakNativeLCID - LCID of CMAK itself
// DWORD dwSystemDefaultLCID - current system LCID
//
// Returns: BOOL - TRUE if cmak should continue, FALSE if it should exit
//
// History: quintinb Created 03/26/2001
//
//+----------------------------------------------------------------------------
BOOL DisplayLcidsDoNotMatchDialog(HINSTANCE hInstance, DWORD dwCmakNativeLCID, DWORD dwSystemDefaultLCID)
{
//
// If we are in here, then the CMAK LCID and the Default System LCID
// have a different Primary language (Japanese vs English for instance).
// Thus we want to warn the user that they can continue but that the
// language version of CM is potentially going to be different than the
// language version of the text that they are typing into the profile.
// It would probably be a better user experience to use the native version
// of CMAK that makes the language you have set as your default locale.
// First, however, we need to check to see if a registry value exists which
// tells us the user has already seen the dialog and asked not to see it again...
//
BOOL bReturn = TRUE;
if (FALSE == GetDoNotShowLcidMisMatchDialogRegValue())
{
//
// Get the Language Names of the Two LCIDs (sys default and CMAK lang)
//
LPTSTR pszSystemLanguage = GetLocalizedLanguageNameFromLCID(dwSystemDefaultLCID);
LPTSTR pszCmakLanguage = GetLocalizedLanguageNameFromLCID(dwCmakNativeLCID);
LPTSTR pszFmtString = CmLoadString(hInstance, IDS_LCIDS_DONT_MATCH);
if (pszSystemLanguage && pszCmakLanguage && pszFmtString)
{
LPTSTR pszMsg = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lstrlen(pszSystemLanguage) +
lstrlen(pszCmakLanguage) + lstrlen(pszFmtString) + 1));
if (pszMsg)
{
wsprintf(pszMsg, pszFmtString, pszSystemLanguage, pszCmakLanguage);
INT_PTR nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_LCIDS_DONT_MATCH_POPUP), NULL,
ProcessLCIDsDontMatchPopup,(LPARAM)pszMsg);
if (IDCANCEL == nResult)
{
bReturn = FALSE;
}
CmFree(pszMsg);
}
}
CmFree(pszSystemLanguage);
CmFree(pszCmakLanguage);
CmFree(pszFmtString);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: CheckLocalization
//
// Synopsis: This function checks to make sure that the current default
// system language has a default ANSI code page and that the
// CMAK Native language (what it is localized to) and the current
// default system language are in the same language family. If there
// is no default ANSI code page or the LCIDs of CMAK and the system
// don't match, then we throw an error message.
//
//
// Arguments: HINSTANCE hInstance - Instance handle for resources
//
// Returns: BOOL - TRUE if cmak should continue, FALSE if it should exit
//
// History: quintinb Created 6/25/99
//
//+----------------------------------------------------------------------------
BOOL CheckLocalization(HINSTANCE hInstance)
{
TCHAR szTemp[MAX_PATH+1];
BOOL bReturn = TRUE;
//
// Check localization requirements. We want to make sure that the current system
// default language has an ANSI code page, otherwise we are not going to be
// able to convert the Unicode text that the user types in to anything that we
// can store in our ANSI text data store (ini files).
//
DWORD dwSystemDefaultLCID = GetSystemDefaultLCID();
CMTRACE1(TEXT("CheckLocalization -- System Default LCID is %u"), dwSystemDefaultLCID);
GetLocaleInfo(dwSystemDefaultLCID, LOCALE_IDEFAULTANSICODEPAGE, szTemp, CELEMS(szTemp));
DWORD dwAnsiCodePage = CmAtol(szTemp);
if (0 == dwAnsiCodePage)
{
//
// Then this LCID has no ANSI code page and we need to throw an error. The user
// will not be able to create a profile without an ANSI codepage of some sort.
//
int iReturn = ShowMessage(NULL, IDS_NO_ANSI_CODEPAGE, MB_YESNO);
if (IDNO == iReturn)
{
return FALSE;
}
}
else
{
//
// We have an ANSI codepage, very good. We want to check and see if the current language the
// user is using is different from that of CMAK itself. If so, then we need to tell the user
// that the language they are entering and the language of the CM bits are different. While this
// is okay, it may not provide the experience they are looking for.
//
//
// Get the CMAK Native LCID
//
CmakVersion CmakVer;
DWORD dwCmakNativeLCID = CmakVer.GetNativeCmakLCID();
BOOL bSeenDialog = FALSE;
//
// Compare the Primary Lang IDs of the language that CMAK is in and the language
// the system locale is set to (this tells us what code page is loaded.
//
if (!ArePrimaryLangIDsEqual(dwCmakNativeLCID, dwSystemDefaultLCID))
{
bReturn = DisplayLcidsDoNotMatchDialog(hInstance, dwCmakNativeLCID, dwSystemDefaultLCID);
bSeenDialog = TRUE;
}
//
// Now load the Native CMAK LCID from the CMAK resources. If this doesn't match
// what we got from above we know MUI is involved and we still could have a problem
// as the user may be entering text in a different language then what we are expecting.
//
if (!bSeenDialog)
{
MYVERIFY(0 != LoadString(hInstance, IDS_NATIVE_LCID, szTemp, CELEMS(szTemp)));
dwCmakNativeLCID = CmAtol(szTemp);
if (!ArePrimaryLangIDsEqual(dwCmakNativeLCID, dwSystemDefaultLCID))
{
bReturn = DisplayLcidsDoNotMatchDialog(hInstance, dwCmakNativeLCID, dwSystemDefaultLCID);
}
}
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: WinMain
//
// Synopsis: Main function for CMAK. Basically does some initialization and
// then launches the wizard.
//
//
// History: quintinb on 8/26/97: made changes to fix bug 10406, see below
// quintinb Created new style Header 3/29/98
//
//+----------------------------------------------------------------------------
int APIENTRY WinMain(
HINSTANCE, //hInstance
HINSTANCE, //hPrevInstance
LPSTR, //lpCmdLine
int nCmdShow
)
{
LPTSTR lpfilename;
int nresult;
TCHAR szSaveDir[MAX_PATH+1];
TCHAR szTemp[2*MAX_PATH+1];
HWND hwndPrev;
HWND hwndChild;
BOOL bTempDirExists; // added by quintinb, please see comment below
HINSTANCE hInstance = GetModuleHandle(NULL);
LPTSTR lpCmdLine = GetCommandLine();
DWORD dwFlags;
INITCOMMONCONTROLSEX InitCommonControlsExStruct = {0};
g_hInstance = hInstance;
//
// Process Command Line Arguments
//
ZeroMemory(szTemp, sizeof(szTemp));
const DWORD c_dwIeakBuild = 0x1;
ArgStruct Args;
Args.pszArgString = TEXT("/o");
Args.dwFlagModifier = c_dwIeakBuild;
{ // Make sure ArgProcessor gets destructed properly and we don't leak mem
CProcessCmdLn ArgProcessor(1, (ArgStruct*)&Args, TRUE,
TRUE); //bSkipFirstToken == TRUE, bBlankCmdLnOkay == TRUE
if (ArgProcessor.GetCmdLineArgs(lpCmdLine, &dwFlags, szTemp, 2*MAX_PATH))
{
g_bIEAKBuild = dwFlags & c_dwIeakBuild;
}
}
//
// Get the name product name from resource, now we're just a lowly component.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_APP_TITLE, g_szAppTitle, MAX_PATH));
// Check if already executing program by trying to set Mutex
MYVERIFY(NULL != CreateMutex(NULL, TRUE, TEXT("spwmutex")));
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// if error, then must already be in use by first instance
hwndPrev = FindWindow(NULL, c_pszAppCaption);
if (!hwndPrev)
{
// check for error message box
hwndPrev = FindWindow(NULL, g_szAppTitle);
if (!hwndPrev)
{
return CMAK_RETURN_ERROR;
}
}
// Bring up previous executing copy to the top.
ShowWindow(hwndPrev,SW_SHOWNORMAL);
hwndChild = GetLastActivePopup(hwndPrev);
MYVERIFY(0 != BringWindowToTop(hwndPrev));
if (IsIconic(hwndPrev))
{
ShowWindow(hwndPrev,SW_RESTORE);
}
if (hwndChild != hwndPrev)
{
MYVERIFY(0 != BringWindowToTop(hwndChild));
}
MYVERIFY(0 != SetForegroundWindow(hwndChild));
return CMAK_RETURN_ERROR;
}
// save off the current instance
g_szPhonebk[0] = TEXT('\0');
g_szRegion[0] = TEXT('\0');
g_szHelp[0] = TEXT('\0');
g_szLicense[0] = TEXT('\0');
g_szPhoneName[0] = TEXT('\0');
g_szCmProxyFile[0] = TEXT('\0');
g_szCmRouteFile[0] = TEXT('\0');
g_szVpnFile[0] = TEXT('\0');
// SearchPath will return only the ugly filename format of the path.
// On NT, it works
// On 95, it returns upper case form.
nresult = SearchPath(NULL, c_pszCmakExe, NULL, CELEMS(g_szCmakdir), g_szCmakdir, &lpfilename);
if (nresult == 0)
{
FileAccessErr(NULL, c_pszCmakExe);
return CMAK_RETURN_ERROR;
}
// delete the file name to leave the exe directory
*lpfilename = TEXT('\0');
if (ERROR_SUCCESS != RegisterBitmapClass(hInstance))
{
MYVERIFY(IDOK == ShowMessage(NULL, IDS_NO_CMBINS, MB_OK));
return CMAK_RETURN_ERROR;
}
//
// Make sure we have a temp directory and then create %TEMP%\cmaktemp
//
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szSaveDir));
MYVERIFY(0 != GetTempPath(CELEMS(g_szTempDir), g_szTempDir));
// begin changes by quintinb on 8/26/97
// added to handle bug 10406
bTempDirExists = SetCurrentDirectory(g_szTempDir);
if (!bTempDirExists)
{
// temp dir doesn't exist even though the system thinks it does,
// so create it and everybody is happy
MYVERIFY(0 != CreateDirectory(g_szTempDir, NULL));
}
// end changes by quintinb on 8/26/97
_tcscat(g_szTempDir,TEXT("cmaktemp"));
MYDBGASSERT(_tcslen(g_szTempDir) <= CELEMS(g_szTempDir));
MYVERIFY(0 != CreateDirectory(g_szTempDir,NULL));
//
// Fill in the path for the support directory, we will need it below
//
MYVERIFY(CELEMS(g_szSupportDir) > (UINT)wsprintf(g_szSupportDir,
TEXT("%s%s"), g_szCmakdir, c_pszSupport));
//
// Now we need to check that we have compatible versions of cmak.exe and cmbins.exe.
// In the win64 case, we have no cmbins.exe so we use the native cmdial32.dll in
// system32. On x86, we need to open the CM binaries cab and check the version of cmdial32.dll
// to ensure that they are compatible. For instance different versions (5.0 vs 5.1)
// shouldn't work together. We also don't want CMAK to work with
// a cmdial that is of the same version but the cmdial has a lower build number.
//
#ifdef _WIN64
//
// On Win64 we are using the native cmdial32.dll in system32
//
CmVersion CmDialVer;
#else
//
// Extract the CM binaries from the cmbins.exe so that we can get
// the version number from cmdial32.dll and can get the correct version
// of cmstp.exe to put in the cab.
//
wsprintf(g_szCmBinsTempDir, TEXT("%s\\cmbins"), g_szTempDir);
//
// Check if cmbins.exe exists
//
wsprintf(szTemp, TEXT("%s\\cmbins.exe"), g_szSupportDir);
if (FALSE == FileExists(szTemp))
{
//
// Warn the user to reinstall because it's missing cmbins.
//
MYVERIFY(IDOK == ShowMessage(NULL, IDS_NO_CMBINS, MB_OK));
EraseTempDir();
return CMAK_RETURN_ERROR;
}
if (FAILED(ExtractCmBinsFromExe(g_szSupportDir, g_szCmBinsTempDir)))
{
CMASSERTMSG(FALSE, TEXT("WinMain -- ExtractCmBinsFromExe Failed."));
//
// Warn the user to reinstall because we couldn't extract cmbins.exe
// because the user doesn't have access to the file.
//
MYVERIFY(IDOK == ShowMessage(NULL, IDS_NO_CMBINS, MB_OK));
EraseTempDir();
return CMAK_RETURN_ERROR;
}
wsprintf(szTemp, TEXT("%s\\cmdial32.dll"), g_szCmBinsTempDir);
CVersion CmDialVer(szTemp);
#endif
CmakVersion CmakVer;
if (CmDialVer.IsPresent())
{
const DWORD c_dwCmakBuildNumber = VER_PRODUCTBUILD;
if ((c_dwCurrentCmakVersionNumber < CmDialVer.GetVersionNumber()))
{
//
// Then we have a newer version of CM then we know how to handle,
// throw an error and exit
//
MYVERIFY(IDOK == ShowMessage(NULL, IDS_CM_TOO_NEW, MB_OK));
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
else if ((c_dwCurrentCmakVersionNumber > CmDialVer.GetVersionNumber()) ||
((c_dwCurrentCmakVersionNumber == CmDialVer.GetVersionNumber()) &&
(c_dwCmakBuildNumber > CmDialVer.GetBuildNumber())))
{
//
// Then we have a older version of CM then we need,
// throw an error and exit
//
MYVERIFY(IDOK == ShowMessage(NULL, IDS_CM_TOO_OLD, MB_OK));
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
}
else
{
//
// Then we have no CM bits, lets throw an error
//
MYVERIFY(IDOK == ShowMessage(NULL, IDS_NO_CM_BITS, MB_OK));
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
//
// Setup the profiles path in Temp
//
g_szShortServiceName[0] = TEXT('\0');
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szCmakdir, c_pszProfiles));
if (0 == SetCurrentDirectory(szTemp))
{
MYVERIFY(0 != CreateDirectory(szTemp, NULL));
MYVERIFY(0 != SetCurrentDirectory(szTemp));
}
//
// We need to make sure that the user has Read/Write
// permissions to the Profiles directory. Otherwise they can
// get themselves into the situation where they would build a
// whole profile and lose all of the work because they couldn't
// save it to the output directory (since we work out of the temp
// dir until we actually build the cab itself). NTRAID 372081
// Also note that since this function is shared by cmdial we use
// function pointers (here just the function names themselves)
// for items that cmdial32.dll doesn't statically link to so that
// it can dynamically link to them but still use the same code while
// allowing cmak not to have to do the dynamic link. Quirky but it
// works.
//
if (!HasSpecifiedAccessToFileOrDir(szTemp, FILE_GENERIC_READ | FILE_GENERIC_WRITE))
{
//
// Then we need to throw an error to the user and exit.
//
LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_INSUFF_PERMS);
if (pszTmp)
{
DWORD dwSize = lstrlen(pszTmp) + lstrlen(szTemp) + 1;
LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
if (pszMsg)
{
wsprintf(pszMsg, pszTmp, szTemp);
MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
CmFree(pszMsg);
}
CmFree(pszTmp);
}
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
//
// Grab all the installed CM profiles and copy them
// to the CMAK dir so that they can be edited.
//
CopyInstalledProfilesForCmakToEdit();
LoadServiceProfiles();
//
// Ensure that the directory CMAK\Support exists
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szCmakdir, c_pszSupport));
if (0 == SetCurrentDirectory(szTemp))
{
MYVERIFY(IDOK == ShowMessage(NULL, IDS_NOLANGRES, MB_OK));
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
MYVERIFY(0 != SetCurrentDirectory(szSaveDir));
if (!CheckLocalization(g_hInstance))
{
g_iCMAKReturnVal = CMAK_RETURN_CANCEL;
goto exit;
}
//
// Initialize the common controls
//
InitCommonControlsExStruct.dwSize = sizeof(InitCommonControlsExStruct);
InitCommonControlsExStruct.dwICC = ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES;
if (FALSE == InitCommonControlsEx(&InitCommonControlsExStruct))
{
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
goto exit;
}
g_pCustomActionList = new CustomActionList();
MYVERIFY(-1 != CreateWizard(NULL));
//
// Make sure to delete the CustomActionList Class, it is
// allocated on the custom action screen.
//
delete g_pCustomActionList;
exit:
//
// Note: global memory must be freed here.
//
FreeList(&g_pHeadProfile, &g_pTailProfile);
EraseTempDir();
ExitProcess((UINT)g_iCMAKReturnVal);
return g_iCMAKReturnVal;
} //lint !e715 we don't use nCmdShow, lpCmdLine, nor hPrevInstance
//+----------------------------------------------------------------------------
//
// Function: DoBrowse
//
// Synopsis: This function does the necessary work to pop up a Browse Common Dialog (either for
// saving files or for opening files depending on the SaveAs flag).
//
// Arguments: WND hDlg - handle of current dialog
// UINT IDS_FILTER - ID for display filter description
// LPTSTR lpMask - file filter (*.ext)
// int IDC_EDIT - ID of edit field
// LPCTSTR lpDefExt - file filter extension (ext)
// LPTSTR lpFile - path/filename currently selected file on input and output
//
// Returns: Returns 1 if successful, -1 if the user hit cancel, and 0 if there was an error.
//
// History: quintinb 8-26-97
// Reorganized and rewrote most of this function to resolve bug # 13159.
// Tried to keep the original variable names and style as much as possible
// to keep the code style the same.
//
//
// quintinb 01/22/1998 changed the return value to int so that we could
// return -1 on cancel and 0 on error and distinguish the
// two cases.
// quintinb 07/13/1998 changed the function prototype so that more than one filter/mask
// pair could be specified.
// quintinb 01/14/2000 Remove SaveAs functionality as it was no longer used
//
//+----------------------------------------------------------------------------
int DoBrowse(HWND hDlg, UINT* pFilterArray, LPTSTR* pMaskArray, UINT uNumFilters, int IDC_EDIT, LPCTSTR lpDefExt, LPTSTR lpFile)
{
OPENFILENAME filedef;
TCHAR szMsg[MAX_PATH+1];
TCHAR szFile[MAX_PATH+1];
TCHAR* pszFilter = NULL;
TCHAR szTemp[MAX_PATH+1];
TCHAR szDir[MAX_PATH+1];
TCHAR szFileTitle[MAX_PATH+1];
int nResult;
LPTSTR lpfilename;
int iReturnValue;
//
// Check Inputs
//
MYDBGASSERT(uNumFilters);
MYDBGASSERT(pFilterArray);
MYDBGASSERT(pMaskArray);
if ((NULL == pFilterArray) ||
(NULL == pMaskArray) ||
(0 == uNumFilters))
{
return FALSE;
}
ZeroMemory(&filedef, sizeof(OPENFILENAME));
szFile[0] = TEXT('\0');
szDir[0] = TEXT('\0');
//
// Allocate Memory for the Filter string
//
pszFilter = (TCHAR*)CmMalloc(sizeof(TCHAR)*MAX_PATH*uNumFilters);
if (pszFilter)
{
ZeroMemory(pszFilter, sizeof(TCHAR)*MAX_PATH*uNumFilters);// REVIEW: This really isn't necessary since CmMalloc always zeros
}
else
{
CMASSERTMSG(FALSE, TEXT("DoBrowse -- CmMalloc returned a NULL pointer"));
return FALSE;
}
//
// Initialize the OPENFILENAME data structure
//
filedef.lStructSize = sizeof(OPENFILENAME);
filedef.hwndOwner = hDlg;
filedef.hInstance = g_hInstance;
filedef.lpstrFilter = pszFilter;
filedef.lpstrCustomFilter = NULL;
filedef.nMaxCustFilter = 0;
filedef.nFilterIndex = 0;
filedef.lpstrFile = szFile;
filedef.nMaxFile = MAX_PATH;
filedef.lpstrFileTitle = szFileTitle;
filedef.nMaxFileTitle = MAX_PATH;
filedef.lpstrInitialDir = szDir;
filedef.lpstrTitle = szMsg;
filedef.Flags = OFN_FILEMUSTEXIST|OFN_LONGNAMES|OFN_PATHMUSTEXIST;
filedef.lpstrDefExt = lpDefExt;
//
// create filter string - separated by 0 and ends with 2 0's
//
UINT uCurrentCharInBuffer=0;
UINT uTempChars;
for (UINT i = 0; i < uNumFilters; i++)
{
uTempChars = (UINT)LoadString(g_hInstance, pFilterArray[i], szTemp, MAX_PATH);
if ((MAX_PATH*uNumFilters) <= (uCurrentCharInBuffer + uTempChars))
{
//
// We don't want to overrun the buffer
//
break;
}
_tcscpy(&(pszFilter[uCurrentCharInBuffer]), szTemp);
uCurrentCharInBuffer += uTempChars;
uTempChars = (UINT)_tcslen(pMaskArray[i]);
if ((MAX_PATH*uNumFilters) <= (uCurrentCharInBuffer + uTempChars))
{
//
// We don't want to overrun the buffer
//
break;
}
_tcscpy(&(pszFilter[uCurrentCharInBuffer + 1]), pMaskArray[i]);
//
// Add 2 chars so that we get a \0 between strings.
//
uCurrentCharInBuffer = (uCurrentCharInBuffer + uTempChars + 2);
}
//
// if a path/file passed in, find its directory and make it szDir
//
if (TEXT('\0') != lpFile[0])
{
nResult = GetFullPathName(lpFile, CELEMS(szDir), szDir, &lpfilename);
if (nResult != 0)
{
if (lpfilename) // 13062
{
_tcscpy(szFile,lpfilename);
*lpfilename = TEXT('\0');
}
}
}
MYVERIFY(0 != LoadString(g_hInstance, IDS_BROWSETITLE, szMsg, MAX_PATH));
//
// pop up the open dialog
//
if (GetOpenFileName((OPENFILENAME*)&filedef))
{
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT), WM_SETTEXT, 0, (LPARAM)szFileTitle));
_tcscpy(lpFile, szFile);
iReturnValue = 1;
}
else
{
//
// If we are in this state than the user could have hit cancel or there could have
// been an error. If the CommDlgExtendedError function returns 0 then we know it was
// just a cancel, otherwise we have an error.
//
if (0 == CommDlgExtendedError())
{
iReturnValue = -1;
}
else
{
iReturnValue = 0;
}
}
CmFree(pszFilter);
return iReturnValue;
}
INT_PTR APIENTRY ProcessCancel(HWND hDlg, UINT message, LPARAM lParam)
{
int iRes;
NMHDR* pnmHeader = (NMHDR*)lParam;
switch (message)
{
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_QUERYCANCEL:
iRes = ShowMessage(hDlg, IDS_CANCELWIZ, MB_YESNO);
if (iRes==IDYES)
{
//
// Free Up the memory we used
//
ClearCmakGlobals();
FreeList(&g_pHeadProfile, &g_pTailProfile);
EraseTempDir();
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT,FALSE));
}
else
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT,TRUE));
}
return TRUE;
default:
return FALSE;
}
default:
return FALSE;
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessHelp
//
// Synopsis: Processes messages that have to do with the Help button.
//
// Arguments: WND hDlg - dialog handle
// UINT message - Message ID to process
// LPARAM lParam - the lParam of the message
// DWORD_PTR dwHelpId - The Help ID of the page in question
// (this is the ID that will be launched
// for a help request from this page).
//
// Returns: BOOL - TRUE if the message was handled
//
// History: quintinb Created Header 10/15/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessHelp(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, DWORD_PTR dwHelpId)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
switch (message)
{
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_HELP:
HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
return TRUE;
default:
return FALSE;
}
break;
case WM_HELP:
HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
return TRUE;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_HELPBUTTON:
HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
return TRUE;
break;
}
default:
return FALSE;
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessWelcome
//
// Synopsis: Welcome to the Connection Manager Administration Kit.
//
//
// History: quintinb Created Header and renamed from ProcessPage1 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessWelcome(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
RECT rDlg;
RECT rWorkArea;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_WELCOME)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
if (GetWindowRect(GetParent(hDlg),&rDlg) && SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
{
MoveWindow(GetParent(hDlg),
rWorkArea.left + ((rWorkArea.right-rWorkArea.left)-(rDlg.right-rDlg.left))/2,
rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top)-(rDlg.bottom-rDlg.top))/2,
rDlg.right-rDlg.left,
rDlg.bottom-rDlg.top,
FALSE);
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void ClearCmakGlobals(void)
{
//
// Free the connect action class
//
delete(g_pCustomActionList);
g_pCustomActionList = NULL;
FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
FreeList(&g_pHeadExtra, &g_pTailExtra);
FreeList(&g_pHeadMerge, &g_pTailMerge);
FreeList(&g_pHeadRefs, &g_pTailRefs);
FreeList(&g_pHeadRename, &g_pTailRename);
FreeIconMenu();
g_szOutExe[0] = TEXT('\0');
g_szCmsFile[0] = TEXT('\0');
g_szInfFile[0] = TEXT('\0');
g_szCmpFile[0] = TEXT('\0');
g_szSedFile[0] = TEXT('\0');
EraseTempDir();
_tcscpy(g_szOutdir, g_szTempDir);
//
// Reset Connect Action Intro Screen
//
g_bUseTunneling = FALSE;
}
BOOL EnsureProfileFileExists(LPTSTR pszOutFile, LPCTSTR szTemplateFileName, LPCTSTR szExtension, UINT uCharsInBuffer)
{
TCHAR szTemp[MAX_PATH+1];
MYVERIFY(uCharsInBuffer > (UINT)wsprintf(pszOutFile, TEXT("%s\\%s%s"), g_szOutdir,
g_szShortServiceName, szExtension));
if (!FileExists(pszOutFile))
{
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
g_szSupportDir, szTemplateFileName));
if (!CopyFileWrapper(szTemp, pszOutFile, FALSE))
{
return FALSE;
}
MYVERIFY(0 != SetFileAttributes(pszOutFile, FILE_ATTRIBUTE_NORMAL));
}
return TRUE;
}
BOOL IsNativeLCID(LPCTSTR szFullPathToInf)
{
HANDLE hFile;
TCHAR szName[MAX_PATH+1] = TEXT("");
TCHAR szNativeLCID[MAX_PATH+1] = TEXT("");
hFile = CreateFile(szFullPathToInf, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
MYVERIFY(0 != CloseHandle(hFile));
//
// First check for the new LCID location under strings
//
if (0 == GetPrivateProfileString(c_pszInfSectionStrings, c_pszCmLCID,
TEXT(""), szName, CELEMS(szName), szFullPathToInf))
{
//
// If the new key didn't exist, then try the old [Intl] section and
// display key. The change was made during the CMAK Unicode changes to
// make the inf template easier to localize.
//
MYVERIFY(0 != GetPrivateProfileString(c_pszIntl, c_pszDisplay,
TEXT(""), szName, CELEMS(szName), szFullPathToInf));
}
if (TEXT('\0') != szName[0])
{
//
// This value should be an LCID so a negative value is invalid anyway
//
DWORD dwLang = (DWORD)_ttol(szName);
MYDBGASSERT((long)dwLang >= 0);
CmakVersion CmakVer;
DWORD dwNative = CmakVer.GetNativeCmakLCID();
MYDBGASSERT((long)dwNative >= 0);
if (dwLang == dwNative)
{
return TRUE;
}
}
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessAddEditProfile
//
// Synopsis: Choose whether to create a new profile or edit an existing one.
//
//
// History: quintinb Created Header and renamed from ProcessPage1A 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessAddEditProfile(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
INT_PTR nResult;
INT_PTR lCount;
TCHAR szName[MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
TCHAR szLanguageDisplayName[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
static LONG_PTR iCBSel = 0;
BOOL bNameChanged;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_STARTCUST)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_COMBO1);
switch (message)
{
case WM_INITDIALOG:
RefreshComboList(hDlg, g_pHeadProfile);
EnableWindow(GetDlgItem(hDlg, IDC_COMBO1), FALSE);
lCount = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if ((CB_ERR != lCount) && (lCount > 0))
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)0, (LPARAM)0));
}
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
g_bNewProfile = TRUE;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1: //Build a new service profile
g_szShortServiceName[0] = TEXT('\0');
EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),FALSE);
g_bNewProfile = TRUE;
break;
case IDC_RADIO2: //Edit an existing service profile
EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),TRUE);
lCount = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, 0, (LPARAM)0);
if ((CB_ERR != lCount) && (lCount > 0))
{
if (iCBSel > lCount)
{
iCBSel = 0;
}
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL,
(WPARAM)iCBSel, (LPARAM)0));
}
g_bNewProfile = FALSE;
break;
case IDC_COMBO1:
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
nResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, 0, (LPARAM)0);
if (nResult != LB_ERR)
{
iCBSel = nResult;
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
(WPARAM)iCBSel, (LPARAM)szName));
}
else
{
SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, 0, (LPARAM)0); //lint !e534 this will error if no items in combo
nResult = SendDlgItemMessage(hDlg,IDC_COMBO1,CB_GETCURSEL,0,(LPARAM)0);
if (nResult != LB_ERR)
{
iCBSel = nResult;
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
(WPARAM)nResult, (LPARAM)szName));
}
else
{
return 1;
}
}
EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),TRUE);
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Establish global platform path
//
MYVERIFY(CELEMS(g_szOsdir) > (UINT)wsprintf(g_szOsdir, TEXT("%s%s\\"),
g_szCmakdir, c_pszProfiles));
//
// Create the support dir path and get the Name of its Language
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
g_szCmakdir, c_pszSupport, c_pszTemplateInf));
MYVERIFY(FALSE != GetLangFromInfTemplate(szTemp, szLanguageDisplayName,
CELEMS(szLanguageDisplayName)));
//
// Determine if its a new or existing profile
//
if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
{
//
// Editing an existing profile
//
nResult = SendDlgItemMessage(hDlg,IDC_COMBO1,CB_GETCURSEL,0,(LPARAM)0);
if (nResult != LB_ERR)
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
(WPARAM)nResult, (LPARAM)szName));
}
else
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPROF, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_COMBO1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// if already editing a profile, don't reset everything
// if didn't switch to another profile.
//
bNameChanged = (_tcsicmp(szName,g_szShortServiceName) != 0);
if (bNameChanged)
{
_tcscpy(g_szShortServiceName, szName);
ClearCmakGlobals();
//
// Okay, copy the profile files to the temp dir
//
if (!CopyToTempDir(g_szShortServiceName))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
//
// We need to make sure that the user has Read/Write
// permissions to the Profiles\<g_szShortServiceName> directory. Otherwise
// they can get themselves into the situation where they would build a
// whole profile and lose all of the work because they couldn't
// save it to the output directory (since we work out of the temp
// dir until we actually build the cab itself). NTRAID 372081
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, g_szShortServiceName));
if (!HasSpecifiedAccessToFileOrDir(szTemp, FILE_GENERIC_READ | FILE_GENERIC_WRITE))
{
//
// Then we need to throw an error to the user and exit.
//
LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_INSUFF_PERMS);
if (pszTmp)
{
DWORD dwSize = lstrlen(pszTmp) + lstrlen(szTemp) + 1;
LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
if (pszMsg)
{
wsprintf(pszMsg, pszTmp, szTemp);
MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
CmFree(pszMsg);
}
CmFree(pszTmp);
}
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
else
{
//
// Building a new profile
//
if (TEXT('\0') == g_szShortServiceName[0])
{
ClearCmakGlobals();
if (FileExists(g_szTempDir))
{
EraseTempDir();
}
MYVERIFY(0 != CreateDirectory(g_szTempDir, NULL));
}
}
// CHECK IF .CMS .CMP .INF .SED FILES EXIST, CREATE FROM TEMPLATE IF NOT EXIST
// Don't do this if in the special case where we have not verified the short name.
GetFileName(g_szCmsFile, szTemp);
if (_tcsicmp(szTemp, TEXT(".cms")) != 0)
{
if (!EnsureProfileFileExists(g_szCmsFile, c_pszTemplateCms, TEXT(".cms"), MAX_PATH))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!EnsureProfileFileExists(g_szCmpFile, c_pszTemplateCmp, c_pszCmpExt, MAX_PATH))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!EnsureProfileFileExists(g_szSedFile, c_pszTemplateSed, TEXT(".sed"), MAX_PATH))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!EnsureProfileFileExists(g_szInfFile, c_pszTemplateInf, TEXT(".inf"), MAX_PATH))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Since we removed multi-language support from CMAK (NTRAID 177515),
// we need to check to make sure they aren't trying to edit a foriegn
// language profile. If so then we need to force an upgrade.
//
if (!IsNativeLCID(g_szInfFile))
{
MYVERIFY(0 != LoadString(g_hInstance, IDS_NONNATIVELCID, szTemp, MAX_PATH));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, g_szShortServiceName, szLanguageDisplayName));
if (IDYES == MessageBox(hDlg, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION))
{
//
// They want to continue in the current language so upgrade the
// inf so that it uses the native language template.
//
MYVERIFY(CELEMS(szTemp) > (UINT) wsprintf(szTemp, TEXT("%s.bak"), g_szInfFile));
MYVERIFY(TRUE == UpgradeInf(szTemp, g_szInfFile));
}
else
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
//
// Since the Unicode changes to CMAK and the multi-language capabilities of NT5, it is
// possible to create many different language profiles inside CMAK. Thus we need to check that
// the Current System Default language and the language of the profile the user is editing have
// the same primary language ID, otherwise display problems may arise. For instance, a use
// with an English version of the OS and CMAK, could set their default system locale to Japanese
// and create a Japanese profile for a client. Then if they change their system default language
// back to English and try to edit the profile the Japanese characters in the profile will not
// display correctly. Thus, we should detect the situation where the display language of the profile
// and the current system default language are not the same and throw a warning.
//
DWORD dwSystemDefaultLCID = GetSystemDefaultLCID();
DWORD dwProfileDisplayLanguage = 0;
if (0 != GetPrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLCID,
TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile))
{
dwProfileDisplayLanguage = (DWORD)_ttol(szTemp);
if (!ArePrimaryLangIDsEqual(dwProfileDisplayLanguage, dwSystemDefaultLCID))
{
//
// If we are in here, then the default system LCID that the profile was
// last editted in and the current Default System LCID
// have a different Primary language (Japanese vs English for instance).
// Thus we want to warn the user that they can continue but certain characters
// may not display properly. They should probably change their system default
// locale back to the setting that it was originally editted in.
//
//
// Get the Language Names of the Two LCIDs (sys default and CMAK lang)
//
LPTSTR pszSystemLanguage = GetLocalizedLanguageNameFromLCID(dwSystemDefaultLCID);
LPTSTR pszProfileDisplayLanguage = GetLocalizedLanguageNameFromLCID(dwProfileDisplayLanguage);
LPTSTR pszFmtString = CmLoadString(g_hInstance, IDS_DIFF_DISPLAY_LCID);
if (pszSystemLanguage && pszProfileDisplayLanguage && pszFmtString)
{
LPTSTR pszMsg = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lstrlen(pszSystemLanguage) +
lstrlen(pszProfileDisplayLanguage) + lstrlen(pszFmtString) + 1));
if (pszMsg)
{
wsprintf(pszMsg, pszFmtString, pszSystemLanguage, pszProfileDisplayLanguage);
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK | MB_ICONINFORMATION);
CmFree(pszMsg);
}
}
CmFree(pszSystemLanguage);
CmFree(pszProfileDisplayLanguage);
CmFree(pszFmtString);
}
}
//
// We have the possiblity that the inf will be of an old format. Call
// Upgrade Inf to see if it needs to be upgraded.
//
MYVERIFY (TRUE == EnsureInfIsCurrent(hDlg, g_szInfFile));
WriteInfVersion(g_szInfFile); //lint !e534
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//
// Write out profile strings with quotes around the entry
// Takes string const as second param
//
void QS_WritePrivateProfileString(LPCTSTR pszSection, LPCTSTR pszItem, LPTSTR entry, LPCTSTR inifile)
{
TCHAR szTemp[2*MAX_PATH+1] = TEXT("");
if (NULL != entry)
{
MYDBGASSERT(_tcslen(entry) <= ((2 * MAX_PATH) - 2));
_tcscpy(szTemp,TEXT("\""));
_tcscat(szTemp,entry);
_tcscat(szTemp,TEXT("\""));
}
MYDBGASSERT(_tcslen(szTemp) <= sizeof(szTemp));
MYVERIFY(0 != WritePrivateProfileString(pszSection, pszItem, szTemp, inifile));
}
//+----------------------------------------------------------------------------
//
// Function: ValidateServiceName
//
// Synopsis: This function makes sure that a long service name is valid.
// For a long service name to be valid it must contain at least
// one alpha-numeric character, not start with a period (.), and
// not contain any of the following characters : */\\:?\"<>|[]
//
// Arguments: LPCTSTR pszLongServiceName - the service name to check
//
// Returns: BOOL returns TRUE if the name is valid.
//
//
// History: quintinb Created 10/29/98
//
//+----------------------------------------------------------------------------
int ValidateServiceName(HWND hDlg, LPTSTR pszLongServiceName)
{
BOOL bBadServiceNameCharFound = FALSE;
BOOL bFoundAlphaNumeric = FALSE;
LPTSTR pch;
int iLen;
if ((NULL == pszLongServiceName) || (TEXT('\0') == pszLongServiceName[0]))
{
//
// Cannot have an empty service name
//
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSERVICE, MB_OK));
return FALSE;
}
else if (MAX_LONG_SERVICE_NAME_LENGTH < _tcslen(pszLongServiceName))
{
//
// Too Long
//
TCHAR* pszMsg = CmFmtMsg(g_hInstance, IDS_SERVICENAMETOBIG, MAX_LONG_SERVICE_NAME_LENGTH);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
return FALSE;
}
else
{
iLen = lstrlen(g_szBadLongServiceNameChars);
pch = pszLongServiceName;
//
// Check that the service name doesn't start with a period
//
if (TEXT('.') == pszLongServiceName[0])
{
bBadServiceNameCharFound = TRUE;
}
//
// Check that it doesn't contain any bad characters
//
while (!bBadServiceNameCharFound && (*pch != _T('\0')))
{
for (int j = 0; j < iLen; ++j)
{
if (*pch == g_szBadLongServiceNameChars[j])
{
bBadServiceNameCharFound = TRUE;
break;
}
}
pch = CharNext(pch);
}
//
// Check that it contains at least one alphanumeric character
//
iLen = lstrlen(pszLongServiceName);
WORD *pwCharTypeArray = (WORD*)CmMalloc(sizeof(WORD)*(iLen + 1));
if (pwCharTypeArray)
{
if (GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, pszLongServiceName, -1, pwCharTypeArray))
{
for (int i = 0; i < iLen; i++)
{
if (pwCharTypeArray[i] & (C1_ALPHA | C1_DIGIT))
{
bFoundAlphaNumeric = TRUE;
break; // only need one alpha numeric char.
}
}
}
CmFree(pwCharTypeArray);
}
if (bBadServiceNameCharFound || !bFoundAlphaNumeric)
{
//
// Contains bad chars.
//
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADLONGNAME, g_szBadLongServiceNameChars);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
return FALSE;
}
else
{
//
// A good long service name
//
return TRUE;
}
}
}
//+----------------------------------------------------------------------------
//
// Function: ValidateShortServiceName
//
// Synopsis: This function checks to see if a given short service name is valid.
// To be valid, a short service name must be less than 8 bytes long
// (but not empty) and must not contain any characters found in
// g_szBadFilenameChars ... basically we only allow letters and
// numbers.
//
// Arguments: LPTSTR pszShortServiceName - the short service name to verify
//
// Returns: BOOL - TRUE if the short service name passed in is valid
//
// History: quintinb Created 10/29/98
//
//+----------------------------------------------------------------------------
BOOL ValidateShortServiceName(HWND hDlg, LPTSTR pszShortServiceName)
{
LPTSTR pch;
if ((NULL == pszShortServiceName) || (TEXT('\0') == pszShortServiceName[0]))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSHORTNAME, MB_OK));
return FALSE;
}
//
// Notice that 8.3 filenames are 8 bytes not 8 characters. Thus we can only have
// 4 DBCS chars.
//
#ifdef UNICODE
LPSTR pszAnsiShortServiceName = WzToSzWithAlloc(pszShortServiceName);
if (MAX_SHORT_SERVICE_NAME_LENGTH < lstrlenA(pszAnsiShortServiceName))
#else
if (MAX_SHORT_SERVICE_NAME_LENGTH < strlen(pszShortServiceName))
#endif
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_TOOLONG, MB_OK));
return FALSE;
}
else
{
// check for valid file name
int iLen = lstrlen(g_szBadFilenameChars);
pch = pszShortServiceName;
while(*pch != _T('\0'))
{
for (int j = 0; j < iLen; ++j)
{
if (*pch == g_szBadFilenameChars[j])
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADNAME, g_szBadFilenameChars);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
return FALSE;
}
}
pch = CharNext(pch);
}
}
#ifdef UNICODE
CmFree(pszAnsiShortServiceName);
#endif
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: CmStrStrI
//
// Synopsis: Simple replacement for StrStr from C runtime, but case-insensitive
//
// Arguments: LPCTSTR pszString - The string to search in
// LPCTSTR pszSubString - The string to search for
//
// Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
// NULL if pszSubString does not occur in pszString
//
//
// History: SumitC copied from CmStrStrW 15-Mar-2001
//
//+----------------------------------------------------------------------------
CMUTILAPI LPWSTR CmStrStrI(LPCWSTR pszString, LPCWSTR pszSubString)
{
//
// Check the inputs
//
MYDBGASSERT(pszString);
MYDBGASSERT(pszSubString);
if (NULL == pszSubString || NULL == pszString)
{
return NULL;
}
//
// Check to make sure we have something to look for
//
if (TEXT('\0') == pszSubString[0])
{
return((LPWSTR)pszString);
}
//
// Okay, start looking for the string
//
LPWSTR pszCurrent = (LPWSTR)pszString;
LPWSTR pszTmp1;
LPWSTR pszTmp2;
while (*pszCurrent)
{
pszTmp1 = pszCurrent;
pszTmp2 = (LPWSTR) pszSubString;
while (*pszTmp1 && *pszTmp2 && (tolower(*pszTmp1) == tolower(*pszTmp2)))
{
pszTmp1 = CharNext(pszTmp1);
pszTmp2 = CharNext(pszTmp2);
}
if (TEXT('\0') == *pszTmp2)
{
return pszCurrent;
}
pszCurrent = CharNext(pszCurrent);
}
return NULL;
}
//+----------------------------------------------------------------------------
//
// Func: FixupCMSFileForClonedProfile
//
// Desc: Parses the CMS file and replaces references to the old shortname
//
// Args: [pszCMSFile] - name of the CMS file
// [pszOld] - old short service name
// [pszNew] - new short service name
//
// Return: HRESULT
//
// Notes:
//
// History: 16-Feb-2001 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
FixupCMSFileForClonedProfile(LPTSTR pszCMSFile, LPTSTR pszOld, LPTSTR pszNew)
{
HRESULT hr = S_OK;
LPTSTR pszCurrentSection = NULL;
MYDBGASSERT(pszCMSFile);
MYDBGASSERT(pszOld);
MYDBGASSERT(pszNew);
MYDBGASSERT(lstrlen(pszOld) <= MAX_SHORT_SERVICE_NAME_LENGTH);
if (NULL == pszCMSFile || NULL == pszOld || NULL == pszNew ||
(lstrlen(pszOld) > MAX_SHORT_SERVICE_NAME_LENGTH))
{
return E_INVALIDARG;
}
//
// Set up the string we're going to look for in the Values
//
TCHAR szOldNamePlusSlash[MAX_SHORT_SERVICE_NAME_LENGTH + 1 + 1];
lstrcpy(szOldNamePlusSlash, pszOld);
lstrcat(szOldNamePlusSlash, TEXT("\\"));
//
// read in all the sections from the CMS file
//
LPTSTR pszAllSections = GetPrivateProfileStringWithAlloc(NULL, NULL, TEXT(""), pszCMSFile);
//
// iterate over all the sections
//
for (pszCurrentSection = pszAllSections;
pszCurrentSection && (TEXT('\0') != pszCurrentSection[0]);
pszCurrentSection += (lstrlen(pszCurrentSection) + 1))
{
//
// Skip the [Connection Manager] section. The entries here are image files,
// and are dealt with in a later CMAK page.
//
if (0 == lstrcmpi(c_pszCmSection, pszCurrentSection))
{
continue;
}
//
// for each section, get all the keys
//
LPTSTR pszKeysInThisSection = GetPrivateProfileStringWithAlloc(pszCurrentSection, NULL, TEXT(""), pszCMSFile);
LPTSTR pszCurrentKey = NULL;
//
// iterate over all the keys
//
for (pszCurrentKey = pszKeysInThisSection;
pszCurrentKey && (TEXT('\0') != pszCurrentKey[0]);
pszCurrentKey += (lstrlen(pszCurrentKey) + 1)) // alternate is CmEndOfStr(pszCurrentKeyName) & pszCurrentKeyName++
{
//
// Get the value for this key
//
LPTSTR pszValue = GetPrivateProfileStringWithAlloc(pszCurrentSection, pszCurrentKey, TEXT(""), pszCMSFile);
if (pszValue)
{
//
// Search for "pszOld\", and replace with "pszNew\" (the \ is
// to ensure that it is part of a path)
//
if (CmStrStrI(pszValue, szOldNamePlusSlash) == pszValue)
{
UINT cLen = lstrlen(pszValue) - lstrlen(pszOld) + lstrlen(pszNew) + 1;
LPTSTR pszNewValue = (LPTSTR) CmMalloc(cLen * sizeof(TCHAR));
if (pszNewValue)
{
lstrcpy(pszNewValue, pszNew);
lstrcat(pszNewValue, TEXT("\\"));
lstrcat(pszNewValue, pszValue + lstrlen(szOldNamePlusSlash));
//
// Write back the value (this doesn't affect the list
// of keys, so it is safe to do.)
//
MYVERIFY(0 != WritePrivateProfileString(pszCurrentSection, pszCurrentKey, pszNewValue, pszCMSFile));
CmFree(pszNewValue);
}
}
CmFree(pszValue);
}
}
CmFree(pszKeysInThisSection);
}
CmFree(pszAllSections);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: CloneProfile
//
// Desc: Does the gruntwork to clone a given profile
//
// Args: [pszShortServiceName] - new short service name
// [pszLongServiceName] - new long service name
//
// Return: HRESULT
//
// Notes:
//
// History: 16-Feb-2001 SumitC Created (most code copied from ProcessServiceName)
//
//-----------------------------------------------------------------------------
HRESULT
CloneProfile(IN LPTSTR pszShortServiceName, IN LPTSTR pszLongServiceName)
{
HRESULT hr = S_OK;
TCHAR szMsg[MAX_PATH+1];
MYDBGASSERT(pszShortServiceName);
MYDBGASSERT(pszLongServiceName);
if ((_tcsicmp(g_szShortServiceName, pszShortServiceName) != 0))
{
//
// If this is a cloned profile, we want to delete the
// old executable file and the old .inf.bak file so that
// we don't leave it around.
//
if (TEXT('\0') != g_szShortServiceName[0])
{
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg,
TEXT("%s\\%s.exe"), g_szOutdir, g_szShortServiceName));
DeleteFile(szMsg);
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg,
TEXT("%s\\%s.inf.bak"), g_szOutdir, g_szShortServiceName));
DeleteFile(szMsg);
}
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
c_pszDesktopGuid,TEXT(""), g_szInfFile));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.inf"),
g_szOutdir, pszShortServiceName));
MYVERIFY(0 != MoveFile(g_szInfFile, szMsg));
_tcscpy(g_szInfFile, szMsg);
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.sed"),
g_szOutdir, pszShortServiceName));
MYVERIFY(0 != MoveFile(g_szSedFile, szMsg));
_tcscpy(g_szSedFile, szMsg);
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.cms"),
g_szOutdir, pszShortServiceName));
MYVERIFY(0 != MoveFile(g_szCmsFile, szMsg));
_tcscpy(g_szCmsFile, szMsg);
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.cmp"),
g_szOutdir, pszShortServiceName));
MYVERIFY(0 != MoveFile(g_szCmpFile, szMsg));
_tcscpy(g_szCmpFile, szMsg);
//
// Fix up any entries that are pointing to the old path
//
(void) FixupCMSFileForClonedProfile(g_szCmsFile, g_szShortServiceName, pszShortServiceName);
}
_tcscpy(g_szShortServiceName, pszShortServiceName);
//
// Check to see if the user changed the long service name
//
if ((0 != lstrcmpi(pszLongServiceName, g_szLongServiceName)) && (TEXT('\0') != g_szLongServiceName[0]))
{
const int c_iNumDunSubSections = 4;
TCHAR szCurrentSectionName[MAX_PATH+1];
TCHAR szNewSectionName[MAX_PATH+1];
const TCHAR* const ArrayOfSubSections[c_iNumDunSubSections] =
{
c_pszCmSectionDunServer,
c_pszCmSectionDunNetworking,
c_pszCmSectionDunTcpIp,
c_pszCmSectionDunScripting
};
//
// Free the DNS list so that we will re-read it later. This ensures that
// we will get rid of any default entries we added that don't really exist
// and will add new defaults if we need them.
//
FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
//
// The user cloned the long service name. Update the DUN key and rename the
// default DUN entry if the long service name and the DUN name match. If they
// don't match we don't want to rename them as a phonebook may be referencing them
// by their original name.
//
GetDefaultDunSettingName(g_szCmsFile, g_szLongServiceName, pszShortServiceName, MAX_PATH + 1);
if (0 == lstrcmpi(g_szLongServiceName, pszShortServiceName))
{
for (int i = 0; i < c_iNumDunSubSections; i++)
{
wsprintf(szCurrentSectionName, TEXT("%s&%s"), ArrayOfSubSections[i], g_szLongServiceName);
wsprintf(szNewSectionName, TEXT("%s&%s"), ArrayOfSubSections[i], pszLongServiceName);
RenameSection(szCurrentSectionName, szNewSectionName, g_szCmsFile);
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryDun, pszLongServiceName, g_szCmsFile));
}
//
// Now update the TunnelDUN key and rename the Tunnel DUN entry if Tunnel DUN name is based on the original
// long service name. If they aren't related then we don't want to rename them.
//
GetTunnelDunSettingName(g_szCmsFile, g_szLongServiceName, pszShortServiceName, MAX_PATH + 1);
wsprintf(szMsg, TEXT("%s %s"), g_szLongServiceName, c_pszCmEntryTunnelPrimary);
if (0 == lstrcmpi(szMsg, pszShortServiceName))
{
for (int i = 0; i < c_iNumDunSubSections; i++)
{
wsprintf(szCurrentSectionName, TEXT("%s&%s %s"), ArrayOfSubSections[i], g_szLongServiceName, c_pszCmEntryTunnelPrimary);
wsprintf(szNewSectionName, TEXT("%s&%s %s"), ArrayOfSubSections[i], pszLongServiceName, c_pszCmEntryTunnelPrimary);
RenameSection(szCurrentSectionName, szNewSectionName, g_szCmsFile);
}
MYVERIFY(CELEMS(szNewSectionName) > (UINT)wsprintf(szNewSectionName, TEXT("%s %s"), pszLongServiceName, c_pszCmEntryTunnelPrimary));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, szNewSectionName, g_szCmsFile));
}
}
CMTRACEHR("CloneProfile", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessServiceName
//
// Synopsis: Setup service and File Names
//
//
// History: quintinb Created Header and renamed from ProcessPage2 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessServiceName(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szTemp2[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
LONG lLongServiceReturn;
LONG lShortServiceReturn;
int nResult;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_NAMES)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_SERVICE);
SetDefaultGUIFont(hDlg,message,IDC_SSERVICE);
switch (message)
{
case WM_INITDIALOG:
// this init's the focus, otherwise Setfocus won't work 1st time
SetFocus(GetDlgItem(hDlg, IDC_SERVICE));
// bug fix 6234, quintinb 9-8-97
SendDlgItemMessage(hDlg, IDC_SERVICE, EM_SETLIMITTEXT, (WPARAM)MAX_LONG_SERVICE_NAME_LENGTH, (LPARAM)0);//lint !e534 EM_SETLIMITTEXT doesn't return anything useful
// end bug fix 6234, quintinb
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
if (*g_szShortServiceName)
{
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SSERVICE, WM_SETTEXT,
(WPARAM)0, (LPARAM) g_szShortServiceName));
GetFileName(g_szCmsFile,szTemp);
if (_tcsicmp(szTemp,TEXT(".cms")) != 0)
{
MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
TEXT(""), g_szLongServiceName, CELEMS(g_szLongServiceName), g_szCmsFile));
}
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SERVICE, WM_SETTEXT, (WPARAM)0,
(LPARAM) g_szLongServiceName));
}
else
{
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SERVICE, WM_SETTEXT,
(WPARAM)0, (LPARAM) NULL));
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SSERVICE, WM_SETTEXT,
(WPARAM)0, (LPARAM) NULL));
}
break;
case PSN_WIZBACK: // fall through to Next
case PSN_WIZNEXT:
// the Next button was pressed
if (-1 == GetTextFromControl(hDlg, IDC_SERVICE, szTemp2, MAX_PATH, (PSN_WIZNEXT == pnmHeader->code))) // bDisplayError == (PSN_WIZBACK == pnmHeader->code)
{
//
// Let the user go back if there is a problem with retrieving their text so that
// they can choose another profile.
//
if (PSN_WIZBACK == pnmHeader->code)
{
return FALSE;
}
else
{
goto ServiceNameError;
}
}
CmStrTrim(szTemp2);
if (-1 == GetTextFromControl(hDlg, IDC_SSERVICE, szTemp, MAX_PATH, (PSN_WIZNEXT == pnmHeader->code))) // bDisplayError == (PSN_WIZBACK == pnmHeader->code)
{
//
// Let the user go back if there is a problem with retrieving their text so that
// they can choose another profile.
//
if (PSN_WIZBACK == pnmHeader->code)
{
return FALSE;
}
else
{
goto ServiceNameError;
}
}
//
// If both the servicename and the short servicename are blank and the user
// is navigating back, then allow them to continue. Otherwise go through all
// the normal checks.
//
if ((pnmHeader && (PSN_WIZBACK == pnmHeader->code)))
{
if ((szTemp[0] == TEXT('\0')) && (szTemp2[0] == TEXT('\0')))
{
return 0;
}
}
//
// Validate the Long Service Name
//
if (!ValidateServiceName(hDlg, szTemp2))
{
goto ServiceNameError;
}
//
// Now lets validate the short service name
//
if (!ValidateShortServiceName(hDlg, szTemp))
{
goto ShortServiceNameError;
}
//
// Changing one of the service names without changing the
// other can cause problems when installing the profile
// later. Warn the user if this is the case.
//
{ // scoping braces
BOOL bShortServiceNameChanged = !!lstrcmpi(g_szShortServiceName, szTemp);
BOOL bLongServiceNameChanged = !!lstrcmpi(g_szLongServiceName, szTemp2);
if ((FALSE == g_bNewProfile) && (bShortServiceNameChanged != bLongServiceNameChanged))
{
nResult = ShowMessage(hDlg, IDS_CHANGED_ONLY_SS_OR_LS, MB_YESNO);
if (nResult == IDYES)
{
if (bShortServiceNameChanged)
{
goto ServiceNameError;
}
if (bLongServiceNameChanged)
{
goto ShortServiceNameError;
}
}
}
}
//
// Create a default output directory based on the short name.
//
// NTRAID 159367 -- quintinb
// Must leave the comparison between the ShortName and szTemp, otherwise the
// user can change the shortname and we won't rename the files. This allows
// profile cloning.
//
if ((_tcsicmp(g_szShortServiceName, szTemp) != 0))
{
BOOL bFound;
bFound = FindListItemByName(szTemp, g_pHeadProfile, NULL); // NULL passed because we don't need a pointer to the item returned
if (bFound)
{
nResult = ShowMessage(hDlg,IDS_PROFEXISTS,MB_YESNO);
if (nResult == IDNO)
{
goto ShortServiceNameError;
}
}
MYVERIFY(S_OK == CloneProfile(szTemp, szTemp2));
}
//
// The Long Service Name is valid, lets keep it.
//
_tcscpy(g_szLongServiceName, szTemp2);
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName, g_szLongServiceName, g_szCmsFile));
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszCmEntryServiceName, g_szLongServiceName, g_szInfFile);
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszUninstallAppTitle, g_szLongServiceName, g_szInfFile);
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszShortSvcName, g_szShortServiceName, g_szInfFile);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
ServiceNameError:
SetFocus(GetDlgItem(hDlg, IDC_SERVICE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
ShortServiceNameError:
SetFocus(GetDlgItem(hDlg, IDC_SSERVICE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessSupportInfo
//
// Synopsis: Customize Support Information
//
//
// History: quintinb Created Header and renamed from ProcessPage2_A 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessSupportInfo(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_SUPPINFO)) return TRUE;
if (ProcessCancel(hDlg, message, lParam)) return TRUE;
SetDefaultGUIFont(hDlg, message, IDC_SUPPORT);
switch (message)
{
case WM_INITDIALOG:
// Fix for Whistler bug 9156
SendDlgItemMessage(hDlg, IDC_SUPPORT, EM_SETLIMITTEXT, (WPARAM) 50, 0);
// this init's the focus, otherwise Setfocus won't work 1st time
SetFocus(GetDlgItem(hDlg, IDC_SUPPORT));
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// this call to GetPrivateProfileString may retreive a blank string, thus don't use the MYVERIFY macro
//
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceMessage, TEXT(""),
g_szSvcMsg, CELEMS(g_szSvcMsg), g_szCmsFile); //lint !e534
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SUPPORT, WM_SETTEXT,
(WPARAM)0, (LPARAM) g_szSvcMsg));
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
// the Next button was pressed
if (-1 == GetTextFromControl(hDlg, IDC_SUPPORT, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_SUPPORT));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szTemp);
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SUPPORT, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
_tcscpy(g_szSvcMsg,szTemp);
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryServiceMessage,g_szSvcMsg,g_szCmsFile));
#ifdef _WIN64
//
// If we are going forward, skip the Include CM binaries page if this is IA64
//
if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_LICENSE));
}
#endif
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessIncludeCm
//
// Synopsis: Include CM bits
//
//
// History: quintinb Created Header and renamed from ProcessPage2A 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessIncludeCm(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CMSW)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
MYVERIFY(0 != GetPrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode,
c_pszOne, szTemp, CELEMS(szTemp), g_szInfFile));
if (*szTemp == TEXT('1'))
{
g_bIncludeCmCode = TRUE;
MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,TRUE));
}
else
{
g_bIncludeCmCode = FALSE;
MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,FALSE));
}
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
g_bIncludeCmCode = IsDlgButtonChecked(hDlg,IDC_CHECK1);
if (g_bIncludeCmCode)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszIncludeCmCode,c_pszOne,g_szInfFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszIncludeCmCode,c_pszZero,g_szInfFile));
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void EnableDisableCmProxyControls(HWND hDlg)
{
BOOL bCmProxyEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
HWND hControl = GetDlgItem(hDlg, IDC_EDIT1);
if (hControl)
{
EnableWindow(hControl, bCmProxyEnabled);
}
hControl = GetDlgItem(hDlg, IDC_CHECK1);
if (hControl)
{
EnableWindow(hControl, bCmProxyEnabled);
}
hControl = GetDlgItem(hDlg, IDC_PROXYLABEL);
if (hControl)
{
EnableWindow(hControl, bCmProxyEnabled);
}
}
BOOL FillInCustomActionStructWithCmProxy(BOOL bRestorePrevProxySettings, CustomActionListItem* pCustomAction,
BOOL bDisconnectAction, LPCTSTR pszProxyFile)
{
BOOL bReturn = FALSE;
MYDBGASSERT(pCustomAction && pszProxyFile && (TEXT('\0') != pszProxyFile[0]));
if (pCustomAction && pszProxyFile && (TEXT('\0') != pszProxyFile[0]))
{
const TCHAR* const c_pszBackupFileName = TEXT("proxy.bak");
const TCHAR* const c_pszDialRasEntry = TEXT("%DIALRASENTRY%");
const TCHAR* const c_pszProfile = TEXT("%PROFILE%");
const TCHAR* const c_pszTunnelRasEntry = TEXT("%TUNNELRASENTRY%");
const TCHAR* const c_pszSetProxyFunction = TEXT("SetProxy");
UINT uDescription;
LPTSTR aArrayOfStrings[10];
UINT uCount = 0;
if (bDisconnectAction)
{
aArrayOfStrings[uCount] = (LPTSTR)c_pszSourceFileNameSwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileName;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntrySwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntry;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntrySwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntry;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszProfileSwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszProfile;
uCount++;
uDescription = IDS_CMPROXY_DIS_DESC;
}
else
{
aArrayOfStrings[uCount] = (LPTSTR)c_pszSourceFileNameSwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)pszProxyFile;
uCount++;
if (bRestorePrevProxySettings)
{
aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileNameSwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileName;
uCount++;
}
aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntrySwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntry;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntrySwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntry;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszProfileSwitch;
uCount++;
aArrayOfStrings[uCount] = (LPTSTR)c_pszProfile;
uCount++;
uDescription = IDS_CMPROXY_CON_DESC;
}
MYVERIFY(0 != LoadString(g_hInstance, uDescription, pCustomAction->szDescription, CELEMS(pCustomAction->szDescription)));
pCustomAction->Type = bDisconnectAction ? ONDISCONNECT : ONCONNECT;
wsprintf(pCustomAction->szProgram, TEXT("%s\\cmproxy.dll"), g_szSupportDir);
lstrcpy(pCustomAction->szFunctionName, c_pszSetProxyFunction);
pCustomAction->bIncludeBinary = TRUE;
pCustomAction->bBuiltInAction = TRUE;
pCustomAction->bTempDescription = FALSE;
pCustomAction->dwFlags = ALL_CONNECTIONS | NONINTERACTIVE;
HRESULT hr = BuildCustomActionParamString(&(aArrayOfStrings[0]), uCount, &(pCustomAction->pszParameters));
bReturn = (SUCCEEDED(hr) && pCustomAction->pszParameters);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessCmProxy
//
// Synopsis: Automatic IE proxy configuration
//
// History: quintinb Created 03/23/00
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessCmProxy(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
BOOL bEnableCmProxy;
BOOL bRestorePrevProxySettings;
TCHAR szTemp[MAX_PATH+1];
HRESULT hr;
CustomActionListItem* pCmProxyCustomAction = NULL;
CustomActionListItem UpdatedCmProxyAction;
ProcessBold(hDlg, message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_APCONFIG)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
switch (message)
{
case WM_INITDIALOG:
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
case IDC_RADIO2:
EnableDisableCmProxyControls(hDlg);
break;
case IDC_BUTTON1: // browse
{
//
// If the user clicked the browse button without clicking the Proxy radio button,
// then we need to set the radio and make sure the other Proxy controls are
// enabled.
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
EnableDisableCmProxyControls(hDlg);
UINT uFilter = IDS_TXTFILTER;
TCHAR* pszMask = TEXT("*.txt");
int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_EDIT1, TEXT("txt"), g_szLastBrowsePath);
MYDBGASSERT(0 != iTemp);
if (0 < iTemp) // -1 means the user cancelled
{
//
// We want to copy the full path to the filename into g_szCmProxyFile so
// that we have it for later in case the user wants to include it in the profile.
//
lstrcpy (g_szCmProxyFile, g_szLastBrowsePath);
//
// We also want to save the last browse path so that when the user next
// opens the browse dialog they will be in the same place they last
// browsed from.
//
LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
if (pszLastSlash)
{
pszLastSlash = CharNext(pszLastSlash);
*pszLastSlash = TEXT('\0');
}
else
{
g_szLastBrowsePath[0] = TEXT('\0');
}
}
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// Ensure we have a custom action list
//
if (NULL == g_pCustomActionList)
{
g_pCustomActionList = new CustomActionList;
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return FALSE;
}
//
// Read in the custom actions from the Cms File
//
hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCmProxy -- Loading custom actions failed."));
}
//
// Init the static variables to no proxy settings
//
bEnableCmProxy = FALSE;
bRestorePrevProxySettings = FALSE;
g_szCmProxyFile[0] = TEXT('\0');
//
// Now lets search the custom action list for cmproxy
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmProxyCustomAction);
if (SUCCEEDED(hr) && pCmProxyCustomAction)
{
//
// Get the filename that the user specified and add it to the UI
//
if (FindSwitchInString(pCmProxyCustomAction->pszParameters, c_pszSourceFileNameSwitch, TRUE, szTemp)) // bReturnNextToken == TRUE
{
//
// Figure out if we have the disconnect action too, ensuring to free the existing action first
//
CmFree(pCmProxyCustomAction->pszParameters);
CmFree(pCmProxyCustomAction);
wsprintf(g_szCmProxyFile, TEXT("%s\\%s"), g_szTempDir, szTemp);
bEnableCmProxy = TRUE;
MYVERIFY(0 != LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONDISCONNECT, &pCmProxyCustomAction);
if (SUCCEEDED(hr) && pCmProxyCustomAction)
{
bRestorePrevProxySettings = TRUE;
CmFree(pCmProxyCustomAction->pszParameters);
CmFree(pCmProxyCustomAction);
}
}
else
{
CmFree(pCmProxyCustomAction->pszParameters);
CmFree(pCmProxyCustomAction);
CMASSERTMSG(FALSE, TEXT("ProcessCmProxy -- parameter string format incorrect"));
}
}
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, bRestorePrevProxySettings));
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, (bEnableCmProxy ? IDC_RADIO2 : IDC_RADIO1)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)GetName(g_szCmProxyFile)));
//
// Now make sure the correct set of controls is enabled.
//
EnableDisableCmProxyControls(hDlg);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Get the checkbox and radio button state
//
bEnableCmProxy = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
bRestorePrevProxySettings = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_CHECK1));
if (bEnableCmProxy)
{
//
// Lets get the proxy file and verify that they gave us a file and that
// the file actually exists.
//
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szTemp);
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEED_PROXY_FILE, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!VerifyFile(hDlg, IDC_EDIT1, g_szCmProxyFile, TRUE))
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
//
// Lets copy the proxy file to the temp dir
//
wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szCmProxyFile));
if (0 != lstrcmpi(szTemp, g_szCmProxyFile))
{
MYVERIFY(TRUE == CopyFileWrapper(g_szCmProxyFile, szTemp, FALSE));
MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
}
//
// Now we have all of the data we need, lets build the custom action struct and then
// either edit it or add it depending on whether it already exists or not.
//
MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
if (szTemp[0])
{
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmProxyCustomAction);
if (SUCCEEDED(hr))
{
FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
FALSE, GetName(g_szCmProxyFile)); // bDisconnectAction == FALSE
hr = g_pCustomActionList->Edit(g_hInstance, pCmProxyCustomAction, &UpdatedCmProxyAction, g_szShortServiceName);
MYVERIFY(SUCCEEDED(hr));
CmFree(UpdatedCmProxyAction.pszParameters);
UpdatedCmProxyAction.pszParameters = NULL;
CmFree(pCmProxyCustomAction->pszParameters);
CmFree(pCmProxyCustomAction);
}
else
{
FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
FALSE, GetName(g_szCmProxyFile)); // bDisconnectAction == FALSE
hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmProxyAction, g_szShortServiceName);
CmFree(UpdatedCmProxyAction.pszParameters);
UpdatedCmProxyAction.pszParameters = NULL;
MYVERIFY(SUCCEEDED(hr));
}
}
}
else
{
//
// Clear out the global proxy file path
//
g_szCmProxyFile[0] = TEXT('\0');
//
// The user doesn't want cmproxy. Delete it from the connect action list.
//
MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
g_pCustomActionList->Delete(g_hInstance, szTemp, ONCONNECT);
}
//
// Now do the same for the disconnect cmproxy action if needed
//
if (bEnableCmProxy && bRestorePrevProxySettings)
{
MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
if (szTemp[0])
{
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONDISCONNECT, &pCmProxyCustomAction);
if (S_OK == hr)
{
FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
TRUE, GetName(g_szCmProxyFile)); // bDisconnectAction == TRUE
hr = g_pCustomActionList->Edit(g_hInstance, pCmProxyCustomAction, &UpdatedCmProxyAction, g_szShortServiceName);
MYVERIFY(SUCCEEDED(hr));
CmFree(UpdatedCmProxyAction.pszParameters);
UpdatedCmProxyAction.pszParameters = NULL;
CmFree(pCmProxyCustomAction->pszParameters);
CmFree(pCmProxyCustomAction);
}
else
{
FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
TRUE, GetName(g_szCmProxyFile)); // bDisconnectAction == TRUE
hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmProxyAction, g_szShortServiceName);
MYVERIFY(SUCCEEDED(hr));
CmFree(UpdatedCmProxyAction.pszParameters);
UpdatedCmProxyAction.pszParameters = NULL;
}
}
}
else
{
//
// Now try to delete the disconnect action
//
MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
if (szTemp[0])
{
g_pCustomActionList->Delete(g_hInstance, szTemp, ONDISCONNECT);
}
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void EnableDisableCmRouteControls(HWND hDlg)
{
BOOL bCmRouteEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
HWND hControl = GetDlgItem(hDlg, IDC_ROUTE_FILE);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled);
}
hControl = GetDlgItem(hDlg, IDC_ROUTE_FILE_LABEL);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled);
}
hControl = GetDlgItem(hDlg, IDC_ROUTE_URL);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled);
}
hControl = GetDlgItem(hDlg, IDC_ROUTE_URL_LABEL);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled);
}
//
// We only want to enable the require URL checkbox if there is text in the URL field.
//
LRESULT lResult = SendDlgItemMessage(hDlg, IDC_ROUTE_URL, WM_GETTEXTLENGTH, 0, 0);
hControl = GetDlgItem(hDlg, IDC_CHECK1);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled && lResult);
}
hControl = GetDlgItem(hDlg, IDC_CHECK2);
if (hControl)
{
EnableWindow(hControl, bCmRouteEnabled);
}
}
BOOL FindSwitchInString(LPCTSTR pszStringToSearch, LPCTSTR pszSwitchToFind, BOOL bReturnNextToken, LPTSTR pszToken)
{
if ((NULL == pszStringToSearch) || (NULL == pszSwitchToFind) || (bReturnNextToken && (NULL == pszToken)))
{
CMASSERTMSG(FALSE, TEXT("FindSwitchInString -- invalid parameter"));
return FALSE;
}
BOOL bReturn = FALSE;
BOOL bLongFileName = FALSE;
LPTSTR pszSourceFileName = CmStrStr(pszStringToSearch, pszSwitchToFind);
if (pszSourceFileName)
{
if (bReturnNextToken)
{
pszSourceFileName = pszSourceFileName + lstrlen(pszSwitchToFind);
while (CmIsSpace(pszSourceFileName))
{
pszSourceFileName = CharNext(pszSourceFileName);
}
if (TEXT('"') == *pszSourceFileName)
{
bLongFileName = TRUE;
pszSourceFileName = CharNext(pszSourceFileName);
}
LPTSTR pszCurrent = pszSourceFileName;
while (pszCurrent && (TEXT('\0') != *pszCurrent))
{
if (bLongFileName && (TEXT('"') == *pszCurrent))
{
break;
}
else if ((FALSE == bLongFileName) && (CmIsSpace(pszCurrent)))
{
break;
}
pszCurrent = CharNext(pszCurrent);
}
if (pszCurrent)
{
lstrcpyn(pszToken, pszSourceFileName, (int)(pszCurrent - pszSourceFileName + 1));
bReturn = TRUE;
}
else
{
CMASSERTMSG(FALSE, TEXT("FindSwitchInString -- unable to find next token to return"));
}
}
else
{
bReturn = TRUE;
}
}
return bReturn;
}
HRESULT BuildCustomActionParamString(LPTSTR* aArrayOfStrings, UINT uCountOfStrings, LPTSTR* ppszParamsOutput)
{
if ((NULL == aArrayOfStrings) || (0 == uCountOfStrings) || (NULL == ppszParamsOutput))
{
CMASSERTMSG(FALSE, TEXT("BuildCustomActionParamString -- Invalid Parameter"));
return E_INVALIDARG;
}
UINT uMemoryNeeded = 0;
LPTSTR pszCurrent;
BOOL bNeedQuotes;
//
// First lets figure out how much memory we need to allocate
//
for (UINT i = 0; i < uCountOfStrings; i++)
{
if (aArrayOfStrings[i] && (TEXT('\0') != aArrayOfStrings[i]))
{
uMemoryNeeded = uMemoryNeeded + lstrlen(aArrayOfStrings[i]);
//
// Next check to see if we need double quotes around the item because it contains spaces
//
pszCurrent = (LPTSTR)aArrayOfStrings[i];
bNeedQuotes = FALSE;
while (pszCurrent && (TEXT('\0') != *pszCurrent))
{
if (CmIsSpace(pszCurrent))
{
bNeedQuotes = TRUE;
break;
}
pszCurrent = CharNext(pszCurrent);
}
//
// Add the item to the string, making sure to add a space if this isn't the last
// item in the list
//
if (bNeedQuotes)
{
uMemoryNeeded = uMemoryNeeded + 2;
}
//
// Add a space unless this is the last item in the list
//
if (i < (uCountOfStrings - 1))
{
uMemoryNeeded++;
}
}
}
//
// Make sure to add one for the null terminator and multiply by the size of a character
//
uMemoryNeeded = (uMemoryNeeded + 1)*sizeof(TCHAR);
//
// Now allocate the memory we need
//
*ppszParamsOutput = (LPTSTR)CmMalloc(uMemoryNeeded);
//
// Finally copy over the data
//
if (*ppszParamsOutput)
{
for (UINT i = 0; i < uCountOfStrings; i++)
{
if (aArrayOfStrings[i] && (TEXT('\0') != aArrayOfStrings[i]))
{
//
// Next check to see if we need double quotes around the item because it contains spaces
//
pszCurrent = (LPTSTR)aArrayOfStrings[i];
bNeedQuotes = FALSE;
while (pszCurrent && (TEXT('\0') != *pszCurrent))
{
if (CmIsSpace(pszCurrent))
{
bNeedQuotes = TRUE;
break;
}
pszCurrent = CharNext(pszCurrent);
}
//
// Add the item to the string, making sure to add a space if this isn't the last
// item in the list
//
if (bNeedQuotes)
{
lstrcat(*ppszParamsOutput, TEXT("\""));
}
lstrcat(*ppszParamsOutput, aArrayOfStrings[i]);
if (bNeedQuotes)
{
lstrcat(*ppszParamsOutput, TEXT("\""));
}
//
// Add a space unless this is the last item in the list
//
if (i < (uCountOfStrings - 1))
{
lstrcat(*ppszParamsOutput, TEXT(" "));
}
}
}
}
else
{
return E_OUTOFMEMORY;
}
return S_OK;
}
BOOL FillInCustomActionStructWithCmRoute(CustomActionListItem* pCustomAction,
BOOL bDisconnectIfUrlUnavailable, LPCTSTR pszUrlPath, LPCTSTR pszRouteFile)
{
BOOL bReturn = FALSE;
MYDBGASSERT(pCustomAction && pszUrlPath && pszRouteFile && ((TEXT('\0') != pszRouteFile[0]) || (TEXT('\0') != pszUrlPath[0])));
if (pCustomAction && pszUrlPath && pszRouteFile && ((TEXT('\0') != pszRouteFile[0]) || (TEXT('\0') != pszUrlPath[0])))
{
const TCHAR* const c_pszCmRouteFunction = TEXT("SetRoutes");
const TCHAR* const c_pszProfileMacro = TEXT("%PROFILE%");
MYVERIFY(LoadString(g_hInstance, IDS_CMROUTE_DESC, pCustomAction->szDescription, CELEMS(pCustomAction->szDescription)));
pCustomAction->Type = ONCONNECT;
wsprintf(pCustomAction->szProgram, TEXT("%s\\cmroute.dll"), g_szSupportDir);
LPTSTR aArrayOfStrings[9] = {0};
UINT uIndex = 0;
if (TEXT('\0') != pszRouteFile[0])
{
aArrayOfStrings[uIndex] = (LPTSTR)c_pszProfileSwitch;
uIndex++;
aArrayOfStrings[uIndex] = (LPTSTR)c_pszProfileMacro;
uIndex++;
aArrayOfStrings[uIndex] = (LPTSTR)c_pszStaticFileNameSwitch;
uIndex++;
aArrayOfStrings[uIndex] = (LPTSTR)pszRouteFile;
uIndex++;
}
if (TEXT('\0') != pszUrlPath[0])
{
aArrayOfStrings[uIndex] = (LPTSTR)c_pszUrlPathSwitch;
uIndex++;
aArrayOfStrings[uIndex] = (LPTSTR)pszUrlPath;
uIndex++;
}
if ((FALSE == bDisconnectIfUrlUnavailable) && (TEXT('\0') != pszUrlPath[0]))
{
aArrayOfStrings[uIndex] = (LPTSTR)c_pszDontRequireUrlSwitch;
uIndex++;
}
//
// For non-admin users, cmroute returns an error because the IPHLPAPI
// calls to add/delete routes fail with ERROR_NETWORK_ACCESS_DENIED.
// Sending this error back to CMdial results in the connection being
// taken down. This flag allows the connection to stay alive anyway.
//
// Note that:
// - this flag is not secure-by-default.
// - we currently have no UI to unset this flag, it has to be removed
// from the .CMS file by hand
//
aArrayOfStrings[uIndex] = (LPTSTR)c_pszDontFailIfAccessDenied;
uIndex++;
HRESULT hr = BuildCustomActionParamString(&(aArrayOfStrings[0]), uIndex, &(pCustomAction->pszParameters));
MYDBGASSERT(SUCCEEDED(hr));
lstrcpy(pCustomAction->szFunctionName, c_pszCmRouteFunction);
pCustomAction->bIncludeBinary = TRUE;
pCustomAction->bBuiltInAction = TRUE;
pCustomAction->bTempDescription = FALSE;
pCustomAction->dwFlags = ALL_CONNECTIONS | NONINTERACTIVE;
bReturn = (NULL != pCustomAction->pszParameters);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessRoutePlumbing
//
// Synopsis: Add Route Plumbing information
//
// History: quintinb Created 03/23/00
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessRoutePlumbing(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
BOOL bEnableRoutePlumbing;
BOOL bDisconnectIfUrlUnavailable;
TCHAR szTemp[MAX_PATH+1];
TCHAR szUrlPath[MAX_PATH+1];
HRESULT hr;
CustomActionListItem UpdatedCmRouteAction;
CustomActionListItem* pCmRouteCustomAction = NULL;
ProcessBold(hDlg, message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_RTPLUMB)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_ROUTE_FILE);
SetDefaultGUIFont(hDlg,message,IDC_ROUTE_URL);
switch (message)
{
case WM_INITDIALOG:
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_ROUTE_URL:
if (HIWORD(wParam) == EN_CHANGE)
{
EnableDisableCmRouteControls(hDlg);
return (TRUE);
}
break;
case IDC_RADIO1:
case IDC_RADIO2:
EnableDisableCmRouteControls(hDlg);
break;
case IDC_BUTTON1: // browse
{
//
// If the user clicked the browse button without clicking the CmRoute radio button,
// then we need to set the radio and make sure the other CmRoute controls are
// enabled.
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
EnableDisableCmRouteControls(hDlg);
UINT uFilter = IDS_TXTFILTER;
TCHAR* pszMask = TEXT("*.txt");
int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_ROUTE_FILE, TEXT("txt"), g_szLastBrowsePath);
MYDBGASSERT(0 != iTemp);
if (0 < iTemp) // -1 means the user cancelled
{
//
// We want to copy the full path to the filename into g_szCmRouteFile so
// that we have it for later in case the user wants to include it in the profile.
//
lstrcpy (g_szCmRouteFile, g_szLastBrowsePath);
//
// We also want to save the last browse path so that when the user next
// opens the browse dialog they will be in the same place they last
// browsed from.
//
LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
if (pszLastSlash)
{
pszLastSlash = CharNext(pszLastSlash);
*pszLastSlash = TEXT('\0');
}
else
{
g_szLastBrowsePath[0] = TEXT('\0');
}
}
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// Ensure we have a custom action list
//
if (NULL == g_pCustomActionList)
{
g_pCustomActionList = new CustomActionList;
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return FALSE;
}
//
// Read in the custom actions from the Cms File
//
hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessRoutePlumbing -- Loading custom actions failed."));
}
//
// Init the static variables to no route plumbing
//
bEnableRoutePlumbing = FALSE;
bDisconnectIfUrlUnavailable = TRUE; // default behavior is to disconnect if URL is unreachable
g_szCmRouteFile[0] = TEXT('\0');
szUrlPath[0] = TEXT('\0');
//
// Now lets search the custom action list for cmproxy
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmRouteCustomAction);
if (SUCCEEDED(hr))
{
//
// Enable Route plumbing
//
bEnableRoutePlumbing = TRUE;
//
// Get the name of the static text file specified for cmroute.dll
//
if (FindSwitchInString(pCmRouteCustomAction->pszParameters, c_pszStaticFileNameSwitch, TRUE, szTemp)) //bReturnNextToken == TRUE
{
wsprintf(g_szCmRouteFile, TEXT("%s\\%s"), g_szTempDir, szTemp);
}
//
// Get the name of the URL to a route file
//
if (FindSwitchInString(pCmRouteCustomAction->pszParameters, c_pszUrlPathSwitch, TRUE, szUrlPath)) //bReturnNextToken == TRUE
{
bDisconnectIfUrlUnavailable = (FALSE == FindSwitchInString(pCmRouteCustomAction->pszParameters,
c_pszDontRequireUrlSwitch, FALSE, NULL)); //bReturnNextToken == FALSE
}
CmFree(pCmRouteCustomAction->pszParameters);
CmFree(pCmRouteCustomAction);
}
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, (bEnableRoutePlumbing ? IDC_RADIO2 : IDC_RADIO1)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_ROUTE_FILE), WM_SETTEXT, 0, (LPARAM)GetName(g_szCmRouteFile)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_ROUTE_URL), WM_SETTEXT, 0, (LPARAM)szUrlPath));
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, bDisconnectIfUrlUnavailable));
//
// Now make sure the correct set of controls is enabled.
//
EnableDisableCmRouteControls(hDlg);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Lets figure out if Route plumbing should be enabled or not.
//
bEnableRoutePlumbing = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
if (bEnableRoutePlumbing)
{
//
// First try to get the static route file. If we don't have one that is okay
// as long as they gave us a route URL.
//
if (-1 == GetTextFromControl(hDlg, IDC_ROUTE_FILE, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szTemp);
if (-1 == GetTextFromControl(hDlg, IDC_ROUTE_URL, szUrlPath, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_ROUTE_URL));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szUrlPath);
if ((TEXT('\0') == szTemp[0]) && (TEXT('\0') == szUrlPath[0]))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEED_ROUTE_FILE, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// If they gave us a static route file then we need to verify it
//
if (TEXT('\0') != szTemp[0])
{
if (!VerifyFile(hDlg, IDC_ROUTE_FILE, g_szCmRouteFile, TRUE))
{
SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
return TRUE;
}
else
{
//
// Lets copy the route file to the temp dir
//
wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szCmRouteFile));
if (0 != lstrcmpi(szTemp, g_szCmRouteFile))
{
MYVERIFY(TRUE == CopyFileWrapper(g_szCmRouteFile, szTemp, FALSE));
MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
}
}
}
else
{
g_szCmRouteFile[0] = TEXT('\0');
}
//
// If they gave us a route URL then we need to make sure it starts with
// http:// or https:// or file://, basically that it contains ://. Note we
// really don't do any validation here under the assumption that they will discover
// it doesn't work when they test it if the URL is invalid.
//
if ((szUrlPath[0]) && (NULL == CmStrStr(szUrlPath, TEXT("://"))))
{
lstrcpy (szTemp, szUrlPath);
wsprintf (szUrlPath, TEXT("http://%s"), szTemp);
}
bDisconnectIfUrlUnavailable = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_CHECK1)); // note we don't write this if we don't have a URL path
//
// Now we have all of the data we need, lets build the custom action struct and then
// either edit it or add it depending on whether it already exists or not.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmRouteCustomAction);
if (SUCCEEDED(hr))
{
FillInCustomActionStructWithCmRoute(&UpdatedCmRouteAction,
bDisconnectIfUrlUnavailable, szUrlPath, GetName(g_szCmRouteFile));
hr = g_pCustomActionList->Edit(g_hInstance, pCmRouteCustomAction, &UpdatedCmRouteAction, g_szShortServiceName);
MYVERIFY(SUCCEEDED(hr));
CmFree(UpdatedCmRouteAction.pszParameters);
UpdatedCmRouteAction.pszParameters = NULL;
CmFree(pCmRouteCustomAction->pszParameters);
CmFree(pCmRouteCustomAction);
}
else
{
FillInCustomActionStructWithCmRoute(&UpdatedCmRouteAction,
bDisconnectIfUrlUnavailable, szUrlPath, GetName(g_szCmRouteFile));
hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmRouteAction, g_szShortServiceName);
MYVERIFY(SUCCEEDED(hr));
CmFree(UpdatedCmRouteAction.pszParameters);
UpdatedCmRouteAction.pszParameters = NULL;
}
}
else
{
//
// Clear out the global route file path
//
g_szCmRouteFile[0] = TEXT('\0');
//
// The user doesn't want cmroute. Delete it from the connect action list.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
if (szTemp[0])
{
hr = g_pCustomActionList->Delete(g_hInstance, szTemp, ONCONNECT);
}
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void EnableDisableRealmControls(HWND hDlg)
{
BOOL bRealmControlsEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
HWND hControl;
hControl = GetDlgItem(hDlg, IDC_EDIT1);
if (hControl)
{
EnableWindow(hControl, bRealmControlsEnabled);
}
hControl = GetDlgItem(hDlg, IDC_REALMNAME);
if (hControl)
{
EnableWindow(hControl, bRealmControlsEnabled);
}
hControl = GetDlgItem(hDlg, IDC_RADIO3);
if (hControl)
{
EnableWindow(hControl, bRealmControlsEnabled);
}
hControl = GetDlgItem(hDlg, IDC_RADIO4);
if (hControl)
{
EnableWindow(hControl, bRealmControlsEnabled);
}
hControl = GetDlgItem(hDlg, IDC_REALM_SEP);
if (hControl)
{
EnableWindow(hControl, bRealmControlsEnabled);
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessRealmInfo
//
// Synopsis: Add a Realm Name
//
// History: quintinb Created Header and renamed from ProcessPage2B 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessRealmInfo(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_REALM)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
switch (message)
{
case WM_INITDIALOG:
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1: // Do not Add a Realm Name
case IDC_RADIO2: // Add a Realm Name
EnableDisableRealmControls(hDlg);
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// The next two calls to GetPrivateProfileString could return empty strings, thus don't use MYVERIFY macro
//
ZeroMemory(g_szPrefix, sizeof(g_szPrefix));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, TEXT(""),
g_szPrefix, CELEMS(g_szPrefix), g_szCmsFile); //lint !e534
ZeroMemory(g_szSuffix, sizeof(g_szSuffix));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, TEXT(""),
g_szSuffix, CELEMS(g_szSuffix), g_szCmsFile); //lint !e534
if (*g_szSuffix)
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO4));
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM) g_szSuffix));
}
else if (*g_szPrefix)
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO3));
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM) g_szPrefix));
}
else
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM)TEXT("")));
//
// Suffix is the default, set this just in case the user adds a suffix or prefix
//
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO4));
}
EnableDisableRealmControls(hDlg);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// First check if IDC_RADIO1 is checked, if so that means that the user
// doesn't want Realm info
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryUserPrefix,TEXT(""),g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryUserSuffix,TEXT(""),g_szCmsFile));
g_szSuffix[0] = TEXT('\0');
g_szPrefix[0] = TEXT('\0');
}
else if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2))
{
//
// If Radio2 is checked then they do want Realm info and we need to
// see if the string exists and if it is convertable to ANSI form.
//
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szTemp);
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOREALM, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Now check to see if this is a Prefix or a Suffix
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO3)) // Prefix
{
_tcscpy(g_szPrefix, szTemp);
g_szSuffix[0] = TEXT('\0');
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, g_szPrefix, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, TEXT(""), g_szCmsFile));
}
else if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO4)) // Suffix
{
_tcscpy(g_szSuffix, szTemp);
g_szPrefix[0] = TEXT('\0');
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, g_szSuffix, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, TEXT(""), g_szCmsFile));
}
else
{
CMASSERTMSG(FALSE, TEXT("ProcessRealmInfo -- Unknown State, bailing"));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
else
{
CMASSERTMSG(FALSE, TEXT("ProcessRealmInfo -- Unknown State, bailing"));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void RefreshList(HWND hwndDlg, UINT uCrtlId, ListBxList * HeadPtr)
{
ListBxList * LoopPtr;
SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_RESETCONTENT, 0, (LPARAM)0); //lint !e534 LB_RESETCONTENT doesn't return anything
if (HeadPtr == NULL)
{
return;
}
LoopPtr = HeadPtr;
while( LoopPtr != NULL)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hwndDlg, uCrtlId, LB_ADDSTRING, 0,
(LPARAM)LoopPtr->szName));
LoopPtr = LoopPtr->next;
}
}
void RefreshComboList(HWND hwndDlg, ListBxList * HeadPtr)
{
ListBxList * LoopPtr;
SendDlgItemMessage(hwndDlg,IDC_COMBO1,CB_RESETCONTENT,0,(LPARAM)0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
if (HeadPtr == NULL)
{
return;
}
LoopPtr = HeadPtr;
while( LoopPtr != NULL)
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hwndDlg, IDC_COMBO1, CB_ADDSTRING, 0,
(LPARAM)LoopPtr->szName));
LoopPtr = LoopPtr->next;
}
}
void FreeList(ListBxList ** pHeadPtr, ListBxList ** pTailPtr)
{
ListBxList * pTmpPtr;
ListBxList * pLoopPtr = *pHeadPtr;
while(NULL != pLoopPtr)
{
CmFree(pLoopPtr->ListBxData);
pTmpPtr = pLoopPtr;
pLoopPtr = pLoopPtr->next;
CmFree(pTmpPtr);
}
*pHeadPtr = NULL;
*pTailPtr = NULL;
}
//+----------------------------------------------------------------------------
//
// Function: MoveCmsFile
//
// Synopsis: This function checks a referenced CMS file to see if it contains
// script files. If the CMS file contains script files, then it
// copies them to the temporary directory and adds a referenced
// file entry to the g_pHeadRefs linked list.
//
// Arguments: LPTSTR szFile - name of the cms file to move
//
// Returns: BOOL - returns TRUE on Success
//
// History: quintinb Created Header 01/09/98
// quintinb rewrote for the Unicode Converversion 06/14/99
// quintinb updated for rewrite of DUN settings 03/21/00
//
//+----------------------------------------------------------------------------
BOOL MoveCmsFile(LPCTSTR pszCmsFile, LPCTSTR pszShortServiceName)
{
BOOL bReturn = TRUE;
ListBxList* pTmpHeadDns = NULL;
ListBxList* pTmpTailDns = NULL;
ListBxList* pTmpCurrentDns = NULL;
CDunSetting* pTmpDunSetting = NULL;
TCHAR szFileName[MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szDest[MAX_PATH+1];
if ((NULL == pszCmsFile) || (NULL == pszShortServiceName) ||
(TEXT('\0') == pszCmsFile[0]) || (TEXT('\0') == pszShortServiceName[0]))
{
return FALSE;
}
//
// Get the Long Service Name from the profile just in case we need a default entry.
//
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile); //lint !e534
if (ReadNetworkSettings(pszCmsFile, szTemp, TEXT(""), &pTmpHeadDns, &pTmpTailDns, g_szOsdir, FALSE)) // FALSE == bLookingForVpnEntries
{
if (NULL != pTmpHeadDns) // just return TRUE if no entries
{
pTmpCurrentDns = pTmpHeadDns;
while (pTmpCurrentDns && pTmpCurrentDns->ListBxData)
{
pTmpDunSetting = (CDunSetting*)pTmpCurrentDns->ListBxData;
if (TEXT('\0') != pTmpDunSetting->szScript[0])
{
//
// Then we have a script, lets copy it and then add it to the g_pHeadRefs List
//
GetFileName(pTmpDunSetting->szScript, szFileName);
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"),
g_szOutdir, szFileName));
//
// Copy the Script File
//
if (CopyFileWrapper(pTmpDunSetting->szScript, szDest, FALSE))
{
MYVERIFY(0 != SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL));
//
// Add the file to the Referenced files list
//
bReturn = bReturn && createListBxRecord(&g_pHeadRefs, &g_pTailRefs,
(void *)NULL, 0, szFileName);
//
// Update the script section in the existing cms to point
// to the new directory.
// Originally: [Scripting&Merge Profile Name]
// Name=merge\script.scp
// Becomes: [Scripting&Merge Profile Name]
// Name=toplvl\script.scp
//
// Note the change in directory name so that the script file
// can be found.
//
TCHAR szSection[MAX_PATH+1];
MYVERIFY(CELEMS(szSection) > (UINT)wsprintf(szSection, TEXT("%s&%s"),
c_pszCmSectionDunScripting,
pTmpCurrentDns->szName));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
pszShortServiceName, szFileName));
MYVERIFY(0 != WritePrivateProfileString(szSection,
c_pszCmEntryDunScriptingName,
szTemp, pszCmsFile));
}
}
pTmpCurrentDns = pTmpCurrentDns->next;
}
}
}
else
{
CMTRACE1(TEXT("MoveCmsFile -- ReadDnsList Failed. GetLastError Returns %d"), GetLastError());
bReturn = FALSE;
goto exit;
}
exit:
//
// Free the DNS List
//
FreeDnsList(&pTmpHeadDns, &pTmpTailDns);
return (bReturn);
}
//+----------------------------------------------------------------------------
//
// Function: ProcessDunEntries
//
// Synopsis: Set up Dial-up networking
//
// History: quintinb Created Header and renamed from ProcessPage2C 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessDunEntries(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
//
// We have a static Memory buffer and a static pointer
// so that we can know when the user has changed the phonebook
// on us (meaning we need to reread the Networking settings).
// Note that we use the static pointer to tell us if we have read
// the settings at least once.
//
static TCHAR szCachedPhoneBook[MAX_PATH+1] = {0};
static TCHAR* pszCachedPhoneBook = NULL;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_DENTRY)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LIST1);
switch (message)
{
case WM_INITDIALOG:
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
OnProcessDunEntriesAdd(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, FALSE, g_szLongServiceName, g_szCmsFile); // FALSE == bCreateTunnelEntry
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON2: //edit
OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON3: //delete
OnProcessDunEntriesDelete(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_LIST1:
if (LBN_SELCHANGE == HIWORD(wParam))
{
//
// The selection in the listbox changed, lets figure out if we need to
// enable/disable the delete button
//
EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
}
else if (LBN_DBLCLK == HIWORD(wParam))
{
OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// To avoid reading the network settings more than we have to, we only want to
// read the networking settings the first time the users hits this page or any
// time the user changes the phonebook (if they clone the profile or edit a different
// one, clearing this will be taken care of elsewhere).
//
if ((NULL == g_pHeadDunEntry) || (NULL == pszCachedPhoneBook) || lstrcmpi(g_szPhonebk, pszCachedPhoneBook))
{
FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szPhonebk, &g_pHeadDunEntry, &g_pTailDunEntry, g_szOsdir, FALSE)); //FALSE == bLookingForVpnEntries
pszCachedPhoneBook = szCachedPhoneBook;
lstrcpy(pszCachedPhoneBook, g_szPhonebk);
}
RefreshDnsList(g_hInstance, hDlg, IDC_LIST1, g_pHeadDunEntry, g_szLongServiceName, g_szCmsFile, NULL);
SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
break;
case PSN_WIZNEXT:
{
//
// Check the list count is > 1 check if the user has selected either
// to download phonebooks or is including a phonebook. If not then
// display a message box and don't let them continue.
//
LRESULT lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
if ((1 < lResult) && (0 == lstrlen(g_szPhonebk)) && (FALSE == g_bUpdatePhonebook))
{
ShowMessage(hDlg, IDS_DUN_DIALUP_WARNING, MB_OK);
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return TRUE;
}
// Fall through to PSN_WIZBACK
}
case PSN_WIZBACK:
//
// Before writing out the entries we must make sure that we don't have a name collision with entries
// from the VPN list. Thus we will check each name in the DUN entries list for a matching name in the
// VPN entries list. If we detect a collision, then we will throw an error message to the user and
// let them deal with the problem.
//
if (!CheckForDUNversusVPNNameConflicts(hDlg, g_pHeadDunEntry, g_pHeadVpnEntry))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Now it is okay to write out the networking entries
//
WriteNetworkingEntries(g_szCmsFile, g_szLongServiceName, g_szShortServiceName, g_pHeadDunEntry);
//
// If we aren't updating the phonebook then we need to go right back to the phonebook page
// and skip the pbk update page
//
if (pnmHeader && (PSN_WIZBACK == pnmHeader->code) && !g_bUpdatePhonebook)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: DoesSomeVPNsettingUsePresharedKey
//
// Synopsis: Checks VPN DUN settings to see if any chose to use a preshared key
//
// Returns: BOOL (TRUE if some VPN setting does use a pre-shared key)
//
// History: 25-Apr-2001 SumitC Created
//
//+----------------------------------------------------------------------------
BOOL DoesSomeVPNsettingUsePresharedKey()
{
BOOL bReturn = FALSE;
ListBxList * ptr = g_pHeadVpnEntry;
if (g_bUseTunneling)
{
while (ptr != NULL)
{
CDunSetting * pDunSetting = (CDunSetting*)(ptr->ListBxData);
if (pDunSetting && (pDunSetting->bUsePskOnWin2kPlus || pDunSetting->bUsePskDownLevel))
{
bReturn = TRUE;
break;
}
ptr = ptr->next;
}
}
return bReturn;
}
INT_PTR APIENTRY ProcessVpnEntries(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
//
// We have a static Memory buffer and a static pointer
// so that we can know when the user has changed the phonebook
// on us (meaning we need to reread the Networking settings).
// Note that we use the static pointer to tell us if we have read
// the settings at least once.
//
BOOL bFreeDunList = FALSE;
static TCHAR szCachedPhoneBook[MAX_PATH+1] = {0};
static TCHAR* pszCachedPhoneBook = NULL;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_VENTRY)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LIST1);
switch (message)
{
case WM_INITDIALOG:
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
OnProcessDunEntriesAdd(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, TRUE, g_szLongServiceName, g_szCmsFile); // TRUE == bCreateTunnelEntry
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON2: //edit
OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON3: //delete
OnProcessDunEntriesDelete(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_LIST1:
if (LBN_SELCHANGE == HIWORD(wParam))
{
//
// The selection in the listbox changed, lets figure out if we need to
// enable/disable the delete button
//
EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
}
else if (LBN_DBLCLK == HIWORD(wParam))
{
OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// To avoid reading the network settings more than we have to, we only want to
// read the networking settings the first time the users hits this page or any
// time the user changes the VPN File (if they clone the profile or edit a different
// one, clearing this will be taken care of elsewhere).
//
if ((NULL == g_pHeadVpnEntry) || (NULL == pszCachedPhoneBook) || lstrcmpi(g_szVpnFile, pszCachedPhoneBook))
{
FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szVpnFile, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szOsdir, TRUE)); //TRUE == bLookingForVpnEntries
pszCachedPhoneBook = szCachedPhoneBook;
lstrcpy(pszCachedPhoneBook, g_szVpnFile);
}
RefreshDnsList(g_hInstance, hDlg, IDC_LIST1, g_pHeadVpnEntry, g_szLongServiceName, g_szCmsFile, NULL);
SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
break;
case PSN_WIZNEXT:
{
//
// Check the list count and if > 1 check if the user has selected a vpn file
// otherwise display a message box and don't let them continue.
//
LRESULT lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
//
// Check if VPN File is included. If not, then display warning message and
// prevent user from continuing.
//
if (1 < lResult && 0 == lstrlen(g_szVpnFile))
{
ShowMessage(hDlg, IDS_DUN_VPN_WARNING, MB_OK);
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return TRUE;
}
// Fall through to PSN_WIZBACK
}
case PSN_WIZBACK:
//
// Before writing out the entries we must make sure that we don't have a name collision with entries
// from the DUN list. Thus we will check each name in the VPN entries list for a matching name in the
// DUN entries list. If we detect a collision, then we will throw an error message to the user and
// let them deal with the problem. One further complication here is that the DUN entries list may not be
// read in yet and we can't read it in permanently in that case since the phonebook may not have been
// given yet or may change. Thus we will read in a temp copy to compare against if the list pointer is NULL.
//
if (NULL == g_pHeadDunEntry)
{
bFreeDunList = TRUE;
MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szPhonebk, &g_pHeadDunEntry, &g_pTailDunEntry, g_szOsdir, FALSE)); //FALSE == bLookingForVpnEntries
}
if (!CheckForDUNversusVPNNameConflicts(hDlg, g_pHeadDunEntry, g_pHeadVpnEntry))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (bFreeDunList)
{
FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
}
//
// Okay, now it's safe to write out the entries
//
WriteNetworkingEntries(g_szCmsFile, g_szLongServiceName, g_szShortServiceName, g_pHeadVpnEntry);
//
// If any of the VPN dun settings has Pre-shared key enabled, go to the Pre-Shared key page
//
if (g_pHeadVpnEntry)
{
//
// If we are going forward, skip the Pre-shared key page if
// no DUN entries have Preshared key enabled.
//
g_bPresharedKeyNeeded = DoesSomeVPNsettingUsePresharedKey();
if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bPresharedKeyNeeded)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
}
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
void EnableDisableTunnelAddressControls(HWND hDlg)
{
BOOL bEnabledTunnelControls = IsDlgButtonChecked(hDlg, IDC_CHECK1) || IsDlgButtonChecked(hDlg, IDC_CHECK2);
BOOL bUseVpnFile = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
//
// Enable/Disable the single VPN Server Edit control
//
HWND hControl = GetDlgItem(hDlg, IDC_RADIO1);
if (hControl)
{
EnableWindow(hControl, bEnabledTunnelControls);
}
hControl = GetDlgItem(hDlg, IDC_EDIT1);
if (hControl)
{
EnableWindow(hControl, (bEnabledTunnelControls && !bUseVpnFile));
}
//
// Enable/Disable the VPN File edit control, and browse button
//
hControl = GetDlgItem(hDlg, IDC_RADIO2);
if (hControl)
{
EnableWindow(hControl, bEnabledTunnelControls);
}
hControl = GetDlgItem(hDlg, IDC_EDIT2);
if (hControl)
{
EnableWindow(hControl, (bEnabledTunnelControls && bUseVpnFile));
}
hControl = GetDlgItem(hDlg, IDC_BUTTON1);
if (hControl)
{
EnableWindow(hControl, bEnabledTunnelControls);
}
//
// Enable/Disable the use same username checkbox
//
hControl = GetDlgItem(hDlg, IDC_CHECK3);
if (hControl)
{
EnableWindow(hControl, bEnabledTunnelControls);
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessTunneling
//
// Synopsis: Setup Tunneling
//
//
// History: quintinb Created Header and renamed from ProcessPage2E 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessTunneling(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
UINT uEditControl = 0;
UINT uRadioButton = 0;
UINT uMissingMsgId = 0;
TCHAR szTemp[MAX_PATH+1];
TCHAR szTempVpnFile[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_SECURE)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_CHECK1));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
case IDC_RADIO2:
case IDC_CHECK1:
case IDC_CHECK2:
EnableDisableTunnelAddressControls(hDlg);
break;
case IDC_BUTTON1: // Browse button
{
//
// If the user clicked the browse button without clicking the VPN File radio button,
// then we need to set the radio and make sure the other controls are
// enabled.
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
EnableDisableTunnelAddressControls(hDlg);
UINT uFilter = IDS_TXTFILTER;
TCHAR* pszMask = TEXT("*.txt");
int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_EDIT2, TEXT("txt"), g_szLastBrowsePath);
MYDBGASSERT(0 != iTemp);
if (0 < iTemp) // -1 means the user cancelled
{
//
// We want to copy the full path to the filename into g_szVpnFile so
// that we have it for later in case the user wants to include it in the profile.
//
lstrcpy (g_szVpnFile, g_szLastBrowsePath);
//
// We also want to save the last browse path so that when the user next
// opens the browse dialog they will be in the same place they last
// browsed from.
//
LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
if (pszLastSlash)
{
pszLastSlash = CharNext(pszLastSlash);
*pszLastSlash = TEXT('\0');
}
else
{
g_szLastBrowsePath[0] = TEXT('\0');
}
}
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// Is this a tunneling profile? If so, check the tunnel this profile checkbox
//
MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryTunnelPrimary, c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,(*szTemp == TEXT('1'))));
//
// If we have merged profiles and the profile has tunnel references turned on then
// we want to check the tunnel references checkbox.
//
if (g_pHeadMerge == NULL)
{
MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK2,FALSE));
EnableWindow(GetDlgItem(hDlg,IDC_CHECK2),FALSE);
}
else
{
EnableWindow(GetDlgItem(hDlg,IDC_CHECK2),TRUE);
MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences,
c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK2,(*szTemp == TEXT('1'))));
}
//
// Now we need to decide if we have a VPN File for this profile or just a single
// Tunnel Address. First try the TunnelFile entry.
//
szTemp[0] = TEXT('\0');
szTempVpnFile[0] = TEXT('\0');
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, TEXT(""),
szTempVpnFile, CELEMS(szTempVpnFile), g_szCmsFile); //lint !e534
if (TEXT('\0') != szTempVpnFile[0])
{
//
// The VpnFile text should be a relative path (corpras\vpn.txt) and
// thus we will want to add the path to the profile dir in front of it.
//
wsprintf(g_szVpnFile, TEXT("%s%s"), g_szOsdir, szTempVpnFile);
//
// Now verify that this exists
//
if (FileExists(g_szVpnFile))
{
LPTSTR pszSlash = CmStrrchr(g_szVpnFile, TEXT('\\'));
if (pszSlash)
{
pszSlash = CharNext(pszSlash);
lstrcpy(szTempVpnFile, pszSlash);
}
}
else
{
//
// This might just mean that the file is in the temp dir and we haven't
// created a dir under profiles yet ... Lets try looking for the file
// in the temp dir instead.
//
LPTSTR pszSlash = CmStrrchr(g_szVpnFile, TEXT('\\'));
if (pszSlash)
{
pszSlash = CharNext(pszSlash);
lstrcpy(szTempVpnFile, pszSlash);
}
wsprintf(g_szVpnFile, TEXT("%s\\%s"), g_szTempDir, szTempVpnFile);
if (!FileExists(g_szVpnFile))
{
//
// Well, we still didn't find it. Looks like the user has us baffled at this point.
// Clear out the buffers and the user will be forced to fill in the correct
// file path before continuing.
//
g_szVpnFile[0] = TEXT('\0');
szTempVpnFile[0] = TEXT('\0');
}
}
uRadioButton = IDC_RADIO2;
}
else
{
//
// We didn't get a VPN file so lets try for a Tunnel Address
//
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, TEXT(""),
szTemp, CELEMS(szTemp), g_szCmsFile); //lint !e534
uRadioButton = IDC_RADIO1;
}
//
// Now fill in one of the edit controls and set a Radio Button
//
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)szTemp));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)szTempVpnFile));
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, uRadioButton));
//
// Now get the UseSameUserName value and set that as appropriate
//
MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryUseSameUserName, c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
g_bUseSamePwd = (*szTemp == TEXT('1'));
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK3, (UINT)g_bUseSamePwd));
EnableDisableTunnelAddressControls(hDlg);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Read the checkboxes to figure out if we are tunneling or not
//
if (IsDlgButtonChecked(hDlg,IDC_CHECK1))
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelPrimary, c_pszOne, g_szCmsFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelPrimary, c_pszZero, g_szCmsFile));
}
if (IsDlgButtonChecked(hDlg,IDC_CHECK2))
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences, c_pszOne, g_szCmsFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences, c_pszZero, g_szCmsFile));
}
//
// If we are tunneling then set the tunnel settings
//
if (IsDlgButtonChecked(hDlg,IDC_CHECK2) || IsDlgButtonChecked(hDlg,IDC_CHECK1))
{
g_bUseTunneling = TRUE;
//
// Figure out if we are looking for a single tunnel address or a VPN file
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
{
uEditControl = IDC_EDIT1;
uMissingMsgId = IDS_NOTUNNEL;
g_szVpnFile[0] = TEXT('\0');
}
else
{
uEditControl = IDC_EDIT2;
uMissingMsgId = IDS_NOTUNNELFILE;
}
//
// Get the tunnel server address or VPN file
//
LRESULT lResult = GetTextFromControl(hDlg, uEditControl, szTemp, MAX_PATH, TRUE); // bDisplayError == TRUE
if (-1 == lResult)
{
SetFocus(GetDlgItem(hDlg, uEditControl));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
else if (0 == lResult)
{
szTemp[0] = TEXT('\0');
}
//
// Trim the string
//
CmStrTrim(szTemp);
//
// Check to make sure that they actually gave us text
//
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, uMissingMsgId, MB_OK));
SetFocus(GetDlgItem(hDlg, uEditControl));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// If we have a VPN file, we need to verify it
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2))
{
if (!VerifyFile(hDlg, IDC_EDIT2, g_szVpnFile, TRUE))
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return TRUE;
}
else
{
//
// We have now verified that we can find the file, but since
// the user cannot enter their own tunnel address we need to
// go one step further and make sure that there is at least one
// tunnel address in the file.
//
if (!VerifyVpnFile(g_szVpnFile))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_BADVPNFORMAT, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return TRUE;
}
//
// Lets copy the VPN file to the temp dir
//
wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szVpnFile));
if (0 != lstrcmpi(szTemp, g_szVpnFile))
{
MYVERIFY(TRUE == CopyFileWrapper(g_szVpnFile, szTemp, FALSE));
MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
}
}
}
//
// Write out the vpn file and tunnel address entries
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
{
//
// szTemp contains the tunnel address already, so just
// clear the vpn file variable.
//
szTempVpnFile[0] = TEXT('\0');
}
else
{
//
// clear the tunnel address and set the vpn file
//
szTemp[0] = TEXT('\0');
wsprintf(szTempVpnFile, TEXT("%s\\%s"), g_szShortServiceName, GetName(g_szVpnFile));
}
//
// Write out the tunnel address
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, szTemp, g_szCmsFile));
//
// Write out the tunnel file
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, szTempVpnFile, g_szCmsFile));
//
// Set the name of the Tunnel Dun setting
//
MYVERIFY(0 != GetTunnelDunSettingName(g_szCmsFile, g_szLongServiceName, szTemp, CELEMS(szTemp)));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, szTemp, g_szCmsFile));
//
// Write out the use same user name value
//
g_bUseSamePwd = IsDlgButtonChecked(hDlg,IDC_CHECK3);
if (g_bUseSamePwd)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, c_pszOne, g_szCmsFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, c_pszZero, g_szCmsFile));
}
}
else
{
//
// Set g_bUseTunneling to False but don't clear out the tunnel settings until the
// user hits the finish button. That way if they change their mind part way through
// building the profile we don't throw away their settings.
//
g_bUseTunneling = FALSE;
}
//
// Skip the VPN entries dialog if we don't have tunneling enabled.
//
if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bUseTunneling)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ValidatePresharedKey
//
// Synopsis: Checks the given pre-shared key for validity
//
// Arguments: pszPresharedKey - string to check
//
// Returns: BOOL - TRUE => key is good, FALSE => bad
//
// History: sumitc Created 03/27/01
//
//+----------------------------------------------------------------------------
BOOL ValidatePresharedKey(LPTSTR pszPresharedKey)
{
BOOL bReturn = FALSE;
MYDBGASSERT(pszPresharedKey);
//
// To ensure that this works similarly for DBCS and downlevel (Safenet), we
// convert to Ansi before doing length checks
//
if (pszPresharedKey && (TEXT('\0') != pszPresharedKey[0]))
{
LPSTR pszAnsiPresharedKey = WzToSzWithAlloc(pszPresharedKey);
if (pszAnsiPresharedKey)
{
DWORD dwPresharedKeyLength = lstrlenA(pszAnsiPresharedKey);
if ((dwPresharedKeyLength <= c_dwMaxPresharedKey) &&
(dwPresharedKeyLength >= c_dwMinPresharedKey))
{
bReturn = TRUE;
}
CmFree(pszAnsiPresharedKey);
}
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ValidatePresharedKeyPIN
//
// Synopsis: Checks the given PIN for validity
//
// Arguments: pszPresharedKey - string to check
//
// Returns: BOOL - TRUE => PIN is good, FALSE => bad
//
// History: sumitc Created 03/27/01
//
//+----------------------------------------------------------------------------
BOOL ValidatePresharedKeyPIN(LPTSTR pszPresharedKeyPIN)
{
BOOL bReturn = FALSE;
MYDBGASSERT(pszPresharedKeyPIN);
if (pszPresharedKeyPIN && (TEXT('\0') != pszPresharedKeyPIN[0]) &&
(lstrlen(pszPresharedKeyPIN) >= c_dwMinPresharedKeyPIN) &&
(lstrlen(pszPresharedKeyPIN) <= c_dwMaxPresharedKeyPIN))
{
bReturn = TRUE;
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: EncryptPresharedKey
//
// Synopsis: Encrypts the given key into a form that can be serialized.
//
// Arguments: szKey - key to encrypt
// szPIN - pin to use as seed
// ppszEncrypted - resultant string
//
// Returns: BOOL - TRUE => successfully encrypted key, FALSE => failed
//
// History: sumitc Created 03/27/01
//
//+----------------------------------------------------------------------------
BOOL EncryptPresharedKey(IN LPTSTR szKey,
IN LPTSTR szPIN,
OUT LPTSTR * ppszEncrypted)
{
BOOL bReturn = FALSE;
DWORD dwLenEncrypted = 0;
LPSTR pszAnsiEncrypted = NULL;
MYDBGASSERT(ppszEncrypted);
LPSTR pszAnsiKey = WzToSzWithAlloc(szKey);
LPSTR pszAnsiPIN = WzToSzWithAlloc(szPIN);
MYDBGASSERT(pszAnsiKey && pszAnsiPIN);
if (ppszEncrypted && pszAnsiKey && pszAnsiPIN)
{
//
// Initialize
//
InitSecure(FALSE); // use secure, not fast encryption
//
// Encrypt it
//
if (EncryptString(pszAnsiKey,
pszAnsiPIN,
(PBYTE*) &pszAnsiEncrypted,
&dwLenEncrypted,
#if defined(DEBUG) && defined(DEBUG_MEM)
(PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
(PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
#else
(PFN_CMSECUREALLOC)CmMalloc, // mem allocator
(PFN_CMSECUREFREE)CmFree)) // mem deallocator
#endif
{
bReturn = TRUE;
}
//
// Uninitialize
//
DeInitSecure();
if (bReturn)
{
*ppszEncrypted = SzToWzWithAlloc(pszAnsiEncrypted);
ZeroMemory(pszAnsiEncrypted, lstrlenA(pszAnsiEncrypted) * sizeof(CHAR));
#if defined(DEBUG) && defined(DEBUG_MEM)
FreeDebugMem(pszAnsiEncrypted);
#else
CmFree(pszAnsiEncrypted);
#endif
}
}
CmFree(pszAnsiKey);
CmFree(pszAnsiPIN);
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: EnableDisablePresharedKeyControls
//
// Synopsis: Based on whether we have a key, set enabled/disabled state of UI
//
// History: 27-Mar-2001 SumitC Created
//
//+----------------------------------------------------------------------------
void EnableDisablePresharedKeyControls(HWND hDlg, BOOL bEnable, BOOL bEncrypt)
{
//
// Enable edit controls and checkboxes
//
EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY), bEnable);
EnableWindow(GetDlgItem(hDlg, IDC_USEENCRYPTION), bEnable);
EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN), bEnable);
EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM), bEnable);
if (bEnable)
{
CheckDlgButton(hDlg, IDC_USEENCRYPTION, TRUE);
}
//
// Either clear edit control or fill with info text
//
if (bEnable)
{
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, WM_SETTEXT, 0, (LPARAM)TEXT(""));
SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY));
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN, WM_SETTEXT, 0, (LPARAM)TEXT(""));
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM, WM_SETTEXT, 0, (LPARAM)TEXT(""));
}
else
{
LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_PRESHAREDKEY_ALREADY);
if (pszTmp)
{
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, WM_SETTEXT, 0, (LPARAM)pszTmp);
}
CmFree(pszTmp);
if (bEncrypt)
{
CheckDlgButton(hDlg, IDC_USEENCRYPTION, TRUE);
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN, WM_SETTEXT, 0, (LPARAM)TEXT("**********"));
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM, WM_SETTEXT, 0, (LPARAM)TEXT("**********"));
}
}
//
// Show or hide the "Replace Key" button
//
ShowWindow(GetDlgItem(hDlg, IDC_REPLACE_PSK), !bEnable);
EnableWindow(GetDlgItem(hDlg, IDC_REPLACE_PSK), !bEnable);
//
// Set the default button for the pane
//
#define IDNEXT 12324
SendMessage(hDlg, DM_SETDEFID, IDNEXT, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
}
//+----------------------------------------------------------------------------
//
// Function: ProcessPresharedKey
//
// Synopsis: Setup Pre-shared key usage for this profile
//
// History: 27-Mar-2001 SumitC Created
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessPresharedKey(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
static LPTSTR pszPresharedKey = NULL;
static BOOL bEncryptPresharedKey = FALSE;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PRESHARED)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
//
// Set max text lengths for the edit controls. Allow one extra char for the PSK itself to catch larger than expected
// cut and pastes...
//
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, EM_SETLIMITTEXT, (WPARAM)(c_dwMaxPresharedKey + 1), (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN, EM_SETLIMITTEXT, (WPARAM)c_dwMaxPresharedKeyPIN, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM, EM_SETLIMITTEXT, (WPARAM)c_dwMaxPresharedKeyPIN, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_REPLACE_PSK:
if (IDYES == ShowMessage(hDlg, IDS_REALLY_REPLACE_PSK, MB_YESNO | MB_ICONWARNING))
{
CmFree(pszPresharedKey);
pszPresharedKey = NULL;
EnableDisablePresharedKeyControls(hDlg, TRUE, FALSE);
}
break;
case IDC_USEENCRYPTION:
EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN), IsDlgButtonChecked(hDlg, IDC_USEENCRYPTION));
EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM), IsDlgButtonChecked(hDlg, IDC_USEENCRYPTION));
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
CMASSERTMSG(g_bPresharedKeyNeeded, TEXT("we shouldn't get to this page otherwise."));
//
// Read in the Pre-shared key and the flag that says if it's encrypted
//
pszPresharedKey = GetPrivateProfileStringWithAlloc(c_pszCmSection, c_pszCmEntryPresharedKey,
TEXT(""), g_szCmpFile); //lint !e534
bEncryptPresharedKey = (BOOL)GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryKeyIsEncrypted,
FALSE, g_szCmpFile); //lint !e534
//
// If we don't have a pre-shared key, hide the Replace button, and enable all
// the other controls. If we already have a pre-shared key, disable all the
// controls and enable the Replace button.
//
EnableDisablePresharedKeyControls(hDlg, !pszPresharedKey, bEncryptPresharedKey);
break;
case PSN_WIZBACK:
g_bPresharedKeyNeeded = FALSE; // force this to be recomputed, since it can change if we go back
// fall through and verify pre-shared key as well
case PSN_WIZNEXT:
if ((TRUE == g_bPresharedKeyNeeded) && (NULL == pszPresharedKey))
{
TCHAR szPresharedKey[c_dwMaxPresharedKey + 2]; // add one extra so that if we have a large cut and paste we can give the user an error message.
TCHAR szPresharedKeyPIN[c_dwMaxPresharedKeyPIN + 1];
TCHAR szConfirmPresharedKeyPIN[c_dwMaxPresharedKeyPIN + 1];
//
// verify Pre-shared Key
//
GetTextFromControl(hDlg, IDC_PRESHARED_KEY, szPresharedKey, (c_dwMaxPresharedKey + 2), TRUE); // make sure to add a couple of extra to be able to
if (FALSE == ValidatePresharedKey(szPresharedKey))
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PRESHAREDKEY_BAD, c_dwMinPresharedKey, c_dwMaxPresharedKey);
MYDBGASSERT(pszMsg);
if (pszMsg)
{
MYVERIFY(IDOK == MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK | MB_ICONSTOP));
CmFree(pszMsg);
}
SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// if key is being encrypted, verify the PIN and use to encrypt key
//
if (IsDlgButtonChecked(hDlg, IDC_USEENCRYPTION))
{
GetTextFromControl(hDlg, IDC_PRESHARED_KEY_PIN, szPresharedKeyPIN, c_dwMaxPresharedKeyPIN, TRUE);
if (FALSE == ValidatePresharedKeyPIN(szPresharedKeyPIN))
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PRESHAREDKEY_PIN_BAD, c_dwMinPresharedKeyPIN, c_dwMaxPresharedKeyPIN);
MYDBGASSERT(pszMsg);
if (pszMsg)
{
MYVERIFY(IDOK == MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK | MB_ICONSTOP));
CmFree(pszMsg);
}
SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Verify that both PINs are the same
//
GetTextFromControl(hDlg, IDC_PRESHARED_KEY_PIN_CONFIRM, szConfirmPresharedKeyPIN, c_dwMaxPresharedKeyPIN, TRUE);
if (0 != lstrcmp(szPresharedKeyPIN, szConfirmPresharedKeyPIN))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_PRESHAREDKEY_MATCHING_PINS, MB_OK | MB_ICONSTOP));
SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Encrypt Pre-shared Key
//
if (FALSE == EncryptPresharedKey(szPresharedKey, szPresharedKeyPIN, &pszPresharedKey))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_PSK_ENCRYPT_FAILED, MB_OK | MB_ICONSTOP));
SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
MYDBGASSERT(pszPresharedKey);
bEncryptPresharedKey = TRUE;
}
else
{
pszPresharedKey = CmStrCpyAlloc(szPresharedKey);
bEncryptPresharedKey = FALSE;
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPresharedKey,
pszPresharedKey,
g_szCmpFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryKeyIsEncrypted,
(bEncryptPresharedKey ? c_pszOne : c_pszZero),
g_szCmpFile));
ZeroMemory(szPresharedKey, c_dwMaxPresharedKey * sizeof(TCHAR));
ZeroMemory(szPresharedKeyPIN, c_dwMaxPresharedKeyPIN * sizeof(TCHAR));
}
CmFree(pszPresharedKey);
pszPresharedKey = NULL;
break;
default:
return FALSE;
}
break;
case WM_DESTROY:
CmFree(pszPresharedKey);
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: RenameSection
//
// Synopsis: This function renames an INI file section from the current name to
// the new name.
//
// Arguments: LPCTSTR szCurrentSectionName - Current name that you want renamed
// LPCTSTR szNewSectionName - name you want the above renamed to
// LPCTSTR szFile - INI file to rename the section in
//
// Returns: BOOL - Returns TRUE unless a malloc error occurred
//
// History: quintinb Created 9/11/98
//
//+----------------------------------------------------------------------------
BOOL RenameSection(LPCTSTR szCurrentSectionName, LPCTSTR szNewSectionName, LPCTSTR szFile)
{
//
// Get the existing section
//
LPTSTR pszBuffer = GetPrivateProfileSectionWithAlloc(szCurrentSectionName, szFile);
if (NULL == pszBuffer)
{
return FALSE;
}
else
{
//
// Erase the old section
//
MYVERIFY(0 != WritePrivateProfileString(szCurrentSectionName, NULL, NULL, szFile));
//
// Write out the renamed section
//
MYVERIFY(0 != WritePrivateProfileSection(szNewSectionName, pszBuffer, szFile));
}
CmFree(pszBuffer);
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessCustomActionPopup
//
// Synopsis: Processes windows messages for the dialog which allows CMAK to add
// or edit custom actions. Note that we pass in a pointer to a
// CustomActionListItem struct on WM_INITDIALOG through the lParam.
// If the user hits OK, we copy the data that they gave us into this
// structure. Note that we only do this to communicate the data back to
// the caller as we update the custom action list ourselves.
//
// Arguments: WND hDlg - dialog window handle
// UINT message - message identifier
// WPARAM wParam - wParam Value
// LPARAM lParam - lParam Value
//
//
// History: quintinb Created 02/25/00
//
//+----------------------------------------------------------------------------
INT_PTR CALLBACK ProcessCustomActionPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
HRESULT hr;
int iTemp;
LRESULT lResult;
LPTSTR pszTypeString = NULL;
CustomActionTypes Type;
CustomActionExecutionStates ExecutionIndex;
static CustomActionListItem* pItem;
CustomActionListItem* pTempItem = NULL;
CustomActionListItem NewItem;
static TCHAR szFullPathToProgram[MAX_PATH+1] = {0};
HWND hControl;
LPTSTR pszTemp;
SetDefaultGUIFont(hDlg, message, IDC_EDIT1);
SetDefaultGUIFont(hDlg, message, IDC_EDIT2);
SetDefaultGUIFont(hDlg, message, IDC_EDIT3);
SetDefaultGUIFont(hDlg, message, IDC_COMBO1);
SetDefaultGUIFont(hDlg, message, IDC_COMBO2);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CONNECT)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return TRUE;
}
//
// We keep the full path to the program in this static string.
//
ZeroMemory(szFullPathToProgram, sizeof(szFullPathToProgram));
//
// Check to see if we got an initialization parameter
//
if (lParam)
{
//
// Thus we were passed a CustomActionListItem structure. It either contains a
// type and a description, meaning that this is an edit and we should lookup the
// data, or we got just a type and we just need to pre-set the type combo to the
// type the user was currently viewing in the listbox.
//
pItem = (CustomActionListItem*)lParam;
if (pItem->szDescription[0])
{
hr = g_pCustomActionList->GetExistingActionData(g_hInstance, pItem->szDescription, pItem->Type, &pTempItem);
if (SUCCEEDED(hr))
{
//
// Let's set the dialog title to say that we are editing an entry. If we fail to retrive
// the string the dialog may look a little funny but should still be functional so we
// won't try to bail out.
//
pszTemp = CmLoadString(g_hInstance, IDS_CA_EDIT_TITLE);
if (pszTemp)
{
MYVERIFY(SendMessage (hDlg, WM_SETTEXT, 0, (LPARAM)pszTemp));
CmFree(pszTemp);
}
//
// Okay, we have data so lets set the item fields. Don't set the description if it
// is only the temporary description that we concatenated from the program and the
// arguments.
//
if (FALSE == pTempItem->bTempDescription)
{
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT3), WM_SETTEXT, 0, (LPARAM)pTempItem->szDescription));
}
//
// Set the program edit control, note we only show the filename if the user is including the
// binary in the package. Also note that we save the full path in szFullPathToProgram so that
// we have it for later.
//
if (pTempItem->bIncludeBinary)
{
GetFileName(pTempItem->szProgram, szTemp);
lstrcpyn(szFullPathToProgram, pTempItem->szProgram, CELEMS(szFullPathToProgram));
}
else
{
lstrcpyn(szTemp, pTempItem->szProgram, CELEMS(szTemp));
}
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)szTemp));
//
// Set the include program checkbox
//
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, pTempItem->bIncludeBinary));
//
// Set the parameters edit control. Note that we put the function name and the parameters
// back together if necessary.
//
if (NULL != pTempItem->pszParameters)
{
LPTSTR pszParamToDisplay = NULL;
if (pTempItem->szFunctionName[0])
{
pszParamToDisplay = CmStrCpyAlloc(pTempItem->szFunctionName);
MYDBGASSERT(pszParamToDisplay);
if (pszParamToDisplay && pTempItem->pszParameters[0])
{
pszParamToDisplay = CmStrCatAlloc(&pszParamToDisplay, TEXT(" "));
MYDBGASSERT(pszParamToDisplay);
if (pszParamToDisplay)
{
pszParamToDisplay = CmStrCatAlloc(&pszParamToDisplay, pTempItem->pszParameters);
MYDBGASSERT(pszParamToDisplay);
}
}
}
else
{
pszParamToDisplay = CmStrCpyAlloc(pTempItem->pszParameters);
MYDBGASSERT(pszParamToDisplay);
}
if (pszParamToDisplay)
{
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)pszParamToDisplay));
CmFree(pszParamToDisplay);
}
}
else
{
CMASSERTMSG(FALSE, TEXT("pTempItem->pszParameters is NULL"));
}
}
}
//
// Figure out what type of custom action we are editing or trying to add (we pre-seed the add type with
// the type the user was viewing. If they were viewing all we set it to the first in the combo).
//
Type = pItem->Type;
hr = g_pCustomActionList->MapFlagsToIndex((pTempItem ? pTempItem->dwFlags : 0), (int*)&ExecutionIndex);
if (FAILED(hr))
{
CMASSERTMSG(FALSE, TEXT("ProcessCustomActionPopup -- MapFlagsToIndex failed, setting execution state to Always."));
ExecutionIndex = (CustomActionExecutionStates)0; // set it to the first item in the enum
}
//
// Set the Interactive checkbox
//
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK2, (0 == (pTempItem ? (pTempItem->dwFlags & NONINTERACTIVE) : 0))));
}
else
{
pItem = NULL;
Type = (CustomActionTypes)0; // set it to the first item in the enum
ExecutionIndex = (CustomActionExecutionStates)0; // set it to the first item in the enum
//
// Set the Interactive checkbox to Interactive by default
//
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK2, TRUE));
}
if (pTempItem)
{
CmFree(pTempItem->pszParameters);
CmFree(pTempItem);
pTempItem = NULL;
}
//
// Setup the custom action types combobox, note that we set bAddAll to FALSE so that we don't add the
// All connect action type used for viewing the connect actions on the main dialog.
//
hr = g_pCustomActionList->AddCustomActionTypesToComboBox(hDlg, IDC_COMBO1, g_hInstance, g_bUseTunneling, FALSE);
//
// Pick a connect action type
//
hr = g_pCustomActionList->GetTypeStringFromType(g_hInstance, Type, &pszTypeString);
if (SUCCEEDED(hr))
{
lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszTypeString);
if (CB_ERR != lResult)
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0));
}
CmFree(pszTypeString);
}
//
// Next initialize the the combo that tells us when to run a connect action. If we are tunneling
// then the user can pick to run the connection for direct connections only, dialup connections only,
// all connections that involve dialup, all connections that involve a tunnel, or all connections.
//
hr = g_pCustomActionList->AddExecutionTypesToComboBox(hDlg, IDC_COMBO2, g_hInstance, g_bUseTunneling);
//
// Pick when the connect action will execute if it is enabled
//
if (g_bUseTunneling)
{
lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if ((CB_ERR != lResult) && (lResult > 0))
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)ExecutionIndex, (LPARAM)0));
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: // Browse
{
UINT uFilterArray[2] = {IDS_CONACTFILTER, IDS_ALLFILTER};
TCHAR* pszMaskArray[2] = {TEXT("*.exe;*.com;*.bat;*.dll"), TEXT("*.*")};
iTemp = DoBrowse(hDlg, uFilterArray, pszMaskArray, 2, IDC_EDIT1, TEXT("exe"), g_szLastBrowsePath);
MYDBGASSERT(0 != iTemp);
if (0 < iTemp) // -1 means the user cancelled
{
//
// Check the include binary button for the user
//
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
//
// We want to copy the full path to the filename into szFullPathToProgram so
// that we have it for later in case the user wants to include it in the profile.
//
lstrcpyn(szFullPathToProgram, g_szLastBrowsePath, CELEMS(szFullPathToProgram));
//
// We also want to save the last browse path so that when the user next
// opens the browse dialog they will be in the same place they last
// browsed from.
//
LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
if (pszLastSlash)
{
pszLastSlash = CharNext(pszLastSlash);
*pszLastSlash = TEXT('\0');
}
else
{
g_szLastBrowsePath[0] = TEXT('\0');
}
}
}
break;
case IDOK:
{
//
// Make sure we have a valid custom action list
//
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return TRUE;
}
//
// Get the text from the Program Edit Control, verifying
// we can convert it to something ANSI
//
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
//
// Check to make sure the program field isn't blank.
//
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPROG, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
//
// Make sure that the program doesn't have a comma or a plus
// sign in it as that will mess up our parsing routines. There
// is no need to allow users to use such odd ball file names.
//
if (CmStrchr(szTemp, TEXT('+')) || CmStrchr(szTemp, TEXT(',')))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOPLUSORCOMMAINPROG, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
//
// Now check to see if we need to verify that the file exists.
// We only want to do that if they have the include program files
// checkbox checked.
//
ZeroMemory(&NewItem, sizeof(CustomActionListItem));
NewItem.bIncludeBinary = IsDlgButtonChecked(hDlg, IDC_CHECK1);
if (NewItem.bIncludeBinary)
{
if (!VerifyFile(hDlg, IDC_EDIT1, szFullPathToProgram, TRUE))
{
return TRUE;
}
else
{
lstrcpyn(NewItem.szProgram, szFullPathToProgram, CELEMS(NewItem.szProgram));
}
}
else
{
CmStrTrim(szTemp);
//
// Check if this is a valid filename and if we have environment macro
// 3rd parameter - TRUE for Custom Action files
//
if (FALSE == IsFileNameValid(szTemp, hDlg, IDC_EDIT1, TRUE))
{
return TRUE;
}
lstrcpyn(NewItem.szProgram, szTemp, CELEMS(NewItem.szProgram));
}
//
// Get the Text from the Params edit control, make sure to validate
// that we can convert it to ANSI
//
hControl = GetDlgItem(hDlg, IDC_EDIT2);
MYDBGASSERT(hControl);
pszTemp = NULL;
if (hControl)
{
iTemp = GetCurrentEditControlTextAlloc(hControl, &pszTemp);
if (-1 == iTemp)
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
return TRUE;
}
}
//
// Check to see if we have a dll for a program. If so, the first parameter is the function name.
//
if (pszTemp)
{
CmStrTrim(pszTemp);
iTemp = lstrlen(NewItem.szProgram) - 4; // 4 == lstrlen (TEXT(".dll"));
if (0 == SafeCompareString(TEXT(".dll"), (NewItem.szProgram + iTemp)))
{
//
// Make sure that we have a parameter string
//
if (pszTemp && pszTemp[0])
{
LPTSTR pszEndOfFunctionName = CmStrchr(pszTemp, TEXT(' '));
if (pszEndOfFunctionName)
{
LPTSTR pszParams = CharNext(pszEndOfFunctionName);
*pszEndOfFunctionName = TEXT('\0');
lstrcpyn(NewItem.szFunctionName, pszTemp, CELEMS(NewItem.szFunctionName));
NewItem.pszParameters = CmStrCpyAlloc(pszParams);
}
else
{
lstrcpyn(NewItem.szFunctionName, pszTemp, CELEMS(NewItem.szFunctionName));
}
}
else
{
MYVERIFY (IDOK == ShowMessage(hDlg, IDS_DLLMUSTHAVEPARAM, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
return TRUE;
}
CmFree(pszTemp);
}
else
{
NewItem.pszParameters = pszTemp;
pszTemp = NULL;
}
}
else
{
NewItem.pszParameters = CmStrCpyAlloc(TEXT(""));
MYDBGASSERT(NewItem.pszParameters);
}
//
// Get the Text from the Description edit control
//
if (-1 == GetTextFromControl(hDlg, IDC_EDIT3, NewItem.szDescription, CELEMS(NewItem.szDescription), TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT3));
return TRUE;
}
//
// If the description was empty, then fill it in from the program and the parameters. Also
// remember to keep track of the fact that this is only a temporary description.
//
if (TEXT('\0') == NewItem.szDescription[0])
{
hr = g_pCustomActionList->FillInTempDescription(&NewItem);
MYDBGASSERT(SUCCEEDED(hr));
}
//
// Figure out the type of custom action
//
hr = MapComboSelectionToType(hDlg, IDC_COMBO1, FALSE, g_bUseTunneling, &(NewItem.Type)); // bIncludesAll == FALSE
if ((ONINTCONNECT == NewItem.Type) && NewItem.szFunctionName[0])
{
MYVERIFY (IDOK == ShowMessage(hDlg, IDS_NODLLAUTOAPP, MB_OK));
return TRUE;
}
//
// Now build the flags section
//
lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_GETCURSEL, 0, (LPARAM)0);
if (lResult != LB_ERR)
{
hr = g_pCustomActionList->MapIndexToFlags((int)lResult, &(NewItem.dwFlags));
if (FAILED(hr))
{
MYDBGASSERT(FALSE);
NewItem.dwFlags = 0;
}
}
else
{
MYDBGASSERT(FALSE);
NewItem.dwFlags = 0;
}
//
// OR on the NonInteractive flag (0x10) if the checkbox is NOT checked.
//
NewItem.dwFlags |= ((IsDlgButtonChecked(hDlg, IDC_CHECK2)) ? 0 : NONINTERACTIVE);
//
// Now, lets try to add the New or Edited entry. If we have a description
// in pItem->szDescription then we need to call edit, otherwise add.
//
if (pItem && pItem->szDescription[0])
{
hr = g_pCustomActionList->Edit(g_hInstance, pItem, &NewItem, g_szShortServiceName);
}
else
{
hr = g_pCustomActionList->Add(g_hInstance, &NewItem, g_szShortServiceName);
}
//
// Check to see if we failed because a duplicate exists
//
if (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)
{
//
// The user has tried to add an entry which already exists. Inform the
// user and see if they want to overwrite.
//
pszTypeString = NULL;
hr = g_pCustomActionList->GetTypeStringFromType(g_hInstance, NewItem.Type, &pszTypeString);
MYDBGASSERT(pszTypeString);
if (pszTypeString)
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_CANAMEEXISTS, NewItem.szDescription, pszTypeString);
MYDBGASSERT(pszMsg);
if (pszMsg)
{
iTemp = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION);
if (IDYES == iTemp)
{
//
// Okay, they want to replace it. Note that the old item is only
// used to get the szDescription and the Type thus
// it is safe to call Edit with NewItem as both Old and New.
//
if (pItem && pItem->szDescription[0])
{
hr = g_pCustomActionList->Delete (g_hInstance, pItem->szDescription, pItem->Type);
MYDBGASSERT(SUCCEEDED(hr));
}
hr = g_pCustomActionList->Edit(g_hInstance, &NewItem, &NewItem, g_szShortServiceName);
MYDBGASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
MYVERIFY(0 != EndDialog(hDlg, IDOK));
if (pItem)
{
//
// Make sure the type and description are up to date in pItem if we have one
//
lstrcpyn(pItem->szDescription, NewItem.szDescription, CELEMS(pItem->szDescription));
pItem->Type = NewItem.Type;
}
}
}
else
{
//
// Let's put the user back to the description field if it has text in it, otherwise
// we want to put the user in the program field.
//
LRESULT lTextLen = SendDlgItemMessage(hDlg, IDC_EDIT3, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
SetFocus(GetDlgItem(hDlg, lTextLen ? IDC_EDIT3 : IDC_EDIT1));
}
CmFree(pszMsg);
}
CmFree(pszTypeString);
}
}
else if (FAILED(hr))
{
CMASSERTMSG(FALSE, TEXT("ProcessCustomActionPopUp -- unknown failure when trying to add or edit a connect action."));
}
else
{
if (pItem)
{
//
// Make sure the type and description are up to date in pItem if we have one
//
lstrcpyn(pItem->szDescription, NewItem.szDescription, CELEMS(pItem->szDescription));
pItem->Type = NewItem.Type;
}
MYVERIFY(0 != EndDialog(hDlg, IDOK));
}
CmFree(NewItem.pszParameters);
NewItem.pszParameters = NULL;
return (TRUE);
}
case IDCANCEL:
MYVERIFY(0 != EndDialog(hDlg, IDCANCEL));
return (TRUE);
default:
break;
}
break;
default:
return FALSE;
}
return FALSE;
}
// Read files under the [Extra Files] section in the .inf
static void ReadExtraList()
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szTemp2[MAX_PATH+1];
TCHAR szNum[MAX_PATH+1];
ExtraData TmpExtraData;
int ConnectCnt = 0;
HANDLE hInf;
_itot(ConnectCnt,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
//
// The following call to GetPrivateProfileString could return an empty string
// so we don't want to use the MYVERIFY macro on it.
//
ZeroMemory(szTemp, sizeof(szTemp));
GetPrivateProfileString(c_pszExtraFiles, szNum, TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile); //lint !e534
while (*szTemp)
{
_tcscpy(TmpExtraData.szPathname, szTemp);
GetFileName(TmpExtraData.szPathname, TmpExtraData.szName);
MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2, TEXT("%s\\%s"), g_szOutdir, TmpExtraData.szName));
hInf = CreateFile(szTemp2,GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if (hInf != INVALID_HANDLE_VALUE)
{
_tcscpy(TmpExtraData.szPathname,szTemp2);
MYVERIFY(0 != CloseHandle(hInf));
}
MYVERIFY(FALSE != createListBxRecord(&g_pHeadExtra,&g_pTailExtra,(void *)&TmpExtraData,sizeof(TmpExtraData),TmpExtraData.szName));
++ConnectCnt;
_itot(ConnectCnt,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
//
// The following call to GetPrivateProfileString could return an empty string
// so we don't want to use the MYVERIFY macro on it.
//
ZeroMemory(szTemp, sizeof(szTemp));
GetPrivateProfileString(c_pszExtraFiles, szNum, TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile); //lint !e534
}
}
//+----------------------------------------------------------------------------
//
// Function: ReadMergeList
//
// Synopsis: This function reads entries from the [Merge Profiles] section of the inf file.
// Any entries found are added to the g_pHeadMerge Linked list.
//
// Arguments: None
//
// Returns: Nothing
//
// History: Quintinb Created Header and restructured to use dwNumChars 1/7/98
//
//+----------------------------------------------------------------------------
static void ReadMergeList()
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szNum[MAX_PATH+1];
int filenum = 0;
DWORD dwNumChars;
//
// Convert the number zero to the string "0"
//
_itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
//
// Try to get a merged profile entry from the INF
//
dwNumChars = GetPrivateProfileString(c_pszMergeProfiles, szNum,TEXT(""), szTemp,
CELEMS(szTemp), g_szInfFile);
while ((dwNumChars > 0) && (TEXT('\0') != szTemp[0]))
{
//
// If we are in this loop then we have a profile entry
//
MYVERIFY(FALSE != createListBxRecord(&g_pHeadMerge,&g_pTailMerge,(void *)NULL,0,szTemp));
//
// Increment the filenumber to look for the next entry
//
++filenum;
//
// Convert the filenumber to a string
//
_itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
//
// Try to read in the next merge entry
//
dwNumChars = GetPrivateProfileString(c_pszMergeProfiles, szNum, TEXT(""), szTemp,
CELEMS(szTemp), g_szInfFile);
}
}
static void WriteExtraList()
{
ExtraData * pExtraData;
ListBxList * LoopPtr;
TCHAR szNum[MAX_PATH+1];
TCHAR szName[MAX_PATH+1];
int filenum = 0;
MYVERIFY(0 != WritePrivateProfileSection(c_pszExtraFiles, TEXT("\0\0"), g_szInfFile));
if (g_pHeadExtra == NULL)
{
return;
}
LoopPtr = g_pHeadExtra;
// WRITE IN ALL ENTRIES
while( LoopPtr != NULL)
{
pExtraData = (ExtraData *)LoopPtr->ListBxData;
{
_itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
GetFileName(pExtraData->szPathname,szName);
MYVERIFY(0 != WritePrivateProfileString(c_pszExtraFiles, szNum, szName, g_szInfFile));
filenum = filenum+1;
}
LoopPtr = LoopPtr->next;
}
}
static void WriteMergeList()
{
ListBxList * LoopPtr;
TCHAR szNum[MAX_PATH+1];
int filenum = 0;
MYVERIFY(0 != WritePrivateProfileSection(c_pszMergeProfiles,TEXT("\0\0"),g_szInfFile));
if (g_pHeadMerge == NULL)
{
return;
}
LoopPtr = g_pHeadMerge;
// WRITE IN ALL ENTRIES
while( LoopPtr != NULL)
{
_itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
MYVERIFY(0 != WritePrivateProfileString(c_pszMergeProfiles, szNum,LoopPtr->szName, g_szInfFile));
filenum = filenum+1;
LoopPtr = LoopPtr->next;
}
}
//+----------------------------------------------------------------------------
//
// Function: IsFile8dot3
//
// Synopsis: Returns TRUE if the filename is in the 8.3 dos filename format
//
// Arguments: LPTSTR pszFileName - just the filename of the file to be checked (no path)
//
// Returns: BOOL - TRUE or FALSE if the file is 8.3
//
// History: quintinb created 11/26/97
//
//+----------------------------------------------------------------------------
BOOL IsFile8dot3(LPTSTR pszFileName)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR * pszPtr;
if (!pszFileName)
{
return FALSE;
}
if (TEXT('\0') == pszFileName[0])
{
return TRUE;
}
_tcscpy(szTemp, pszFileName);
pszPtr = _tcsrchr(szTemp, TEXT('.'));
//
// If there is an extension check the length
//
if (pszPtr)
{
if (_tcslen(pszPtr) > 4)
{
return FALSE;
}
//
// Extension is ok check name part
//
*pszPtr = 0;
}
if (_tcslen(szTemp) > 8)
{
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessCustomActions
//
// Synopsis: Processes windows messages for the page in CMAK that allows users
// to manipulate custom actions (add, edit, delete, move, etc.)
//
// Arguments: WND hDlg - dialog window handle
// UINT message - message identifier
// WPARAM wParam - wParam Value
// LPARAM lParam - lParam Value
//
//
// History: quintinb Created 02/25/00
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessCustomActions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
INT_PTR nResult;
int iTemp;
HRESULT hr;
static HWND hListView;
NMHDR* pnmHeader = (NMHDR*)lParam;
LPNMLISTVIEW pNMListView;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CONNECT)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LISTVIEW);
SetDefaultGUIFont(hDlg,message,IDC_COMBO1);
switch (message)
{
case WM_INITDIALOG:
{
if (NULL == g_pCustomActionList)
{
g_pCustomActionList = new CustomActionList;
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return FALSE;
}
//
// Read in the custom actions from the Cms File
//
hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Loading custom actions failed."));
}
//
// Cache the List View window handle
//
hListView = GetDlgItem(hDlg, IDC_LISTVIEW);
//
// Load the arrow images for the move up and move down buttons
//
HICON hUpArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_UP_ARROW), IMAGE_ICON, 0, 0, 0);
HICON hDownArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DOWN_ARROW), IMAGE_ICON, 0, 0, 0);
//
// Set the arrow button bit maps
//
if (hUpArrow)
{
SendMessage(GetDlgItem(hDlg, IDC_BUTTON4), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hUpArrow);
}
if (hDownArrow)
{
SendMessage(GetDlgItem(hDlg, IDC_BUTTON5), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDownArrow);
}
//
// Set the Column headings
//
AddListViewColumnHeadings(g_hInstance, hListView);
break;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
OnProcessCustomActionsAdd(g_hInstance, hDlg, hListView, g_bUseTunneling);
break;
case IDC_BUTTON2: //edit
OnProcessCustomActionsEdit(g_hInstance, hDlg, hListView, g_bUseTunneling);
break;
case IDC_BUTTON3: //delete
OnProcessCustomActionsDelete(g_hInstance, hDlg, hListView, g_bUseTunneling);
break;
case IDC_BUTTON4: //UP
OnProcessCustomActionsMoveUp(g_hInstance, hDlg, hListView, g_bUseTunneling);
break;
case IDC_BUTTON5: //down
OnProcessCustomActionsMoveDown(g_hInstance, hDlg, hListView, g_bUseTunneling);
break;
case IDC_COMBO1: // type of connect action to display
if (HIWORD(wParam) == CBN_SELCHANGE)
{
UINT uStringId;
CustomActionTypes Type;
hr = MapComboSelectionToType(hDlg, IDC_COMBO1, TRUE, g_bUseTunneling, &Type); // TRUE == bIncludesAll
MYDBGASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
if (ALL == Type)
{
uStringId = IDS_TYPE_COL_TITLE;
}
else
{
uStringId = IDS_PROGRAM_COL_TITLE;
}
UpdateListViewColumnHeadings(g_hInstance, hListView, uStringId, 1); // 1 == second column
RefreshListView(g_hInstance, hDlg, IDC_COMBO1, hListView, 0, g_bUseTunneling);
}
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case LVN_ITEMCHANGED:
//
// We want to process item changed messages for when the selection changes. This
// way when the user selects an item in the list (either using the arrow keys or
// the mouse) we will accurately update the arrow keys. In order to cut down on the
// number of calls we filter out the unselected messages.
//
pNMListView = (LPNMLISTVIEW) lParam;
if ((LVIF_STATE & pNMListView->uChanged) && (LVIS_SELECTED & pNMListView->uNewState))
{
int iTempItem = pNMListView->iItem;
RefreshEditDeleteMoveButtonStates(g_hInstance, hDlg, hListView, IDC_COMBO1, &iTempItem, g_bUseTunneling);
}
break;
case NM_DBLCLK:
case NM_RETURN:
if (ListView_GetItemCount(hListView))
{
OnProcessCustomActionsEdit(g_hInstance, hDlg, hListView, g_bUseTunneling);
}
break;
case LVN_KEYDOWN:
{
//
// User hit the right click key or typed Shift+F10
//
NMLVKEYDOWN* pKeyDown = (NMLVKEYDOWN*)lParam;
if (((VK_F10 == pKeyDown->wVKey) && (0 > GetKeyState(VK_SHIFT))) || (VK_APPS == pKeyDown->wVKey))
{
//
// Figure out what item is currently selected and gets its position
//
iTemp = ListView_GetSelectionMark(hListView);
NMITEMACTIVATE ItemActivate = {0};
if (-1 != iTemp)
{
POINT ptPoint = {0};
if (ListView_GetItemPosition(hListView, iTemp, &ptPoint))
{
RECT ItemRect;
if (ListView_GetItemRect(hListView, iTemp, &ItemRect, LVIR_LABEL))
{
LONG lIndent = (ItemRect.bottom - ItemRect.top) / 2;
ItemActivate.ptAction.x = ptPoint.x + lIndent;
ItemActivate.ptAction.y = ptPoint.y + lIndent;
ItemActivate.iItem = iTemp;
OnProcessCustomActionsContextMenu(g_hInstance, hDlg, hListView, &ItemActivate, g_bUseTunneling, IDC_COMBO1);
}
}
}
}
}
break;
case NM_RCLICK:
OnProcessCustomActionsContextMenu(g_hInstance, hDlg, hListView, (NMITEMACTIVATE*)lParam, g_bUseTunneling, IDC_COMBO1);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// Make sure we have a custom action class to work with
//
if (NULL == g_pCustomActionList)
{
g_pCustomActionList = new CustomActionList;
MYDBGASSERT(g_pCustomActionList);
if (NULL == g_pCustomActionList)
{
return FALSE;
}
//
// Read in the custom actions from the Cms File
//
hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Loading custom actions failed."));
}
//
// Setup the ListView control and the corresponding Combo box, note that we set bAddAll to TRUE so
// that the All option is added.
//
hr = g_pCustomActionList->AddCustomActionTypesToComboBox(hDlg, IDC_COMBO1, g_hInstance, g_bUseTunneling, TRUE);
nResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if ((CB_ERR != nResult) && (nResult > 0))
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)0, (LPARAM)0));
}
//
// Add built in custom actions
//
{ // adding scope
BOOL bAddCmdlForVpn = FALSE;
if (g_szVpnFile[0])
{
//
// We have a VPN file so let's check and see if they defined an UpdateUrl
//
GetPrivateProfileString(c_pszCmSectionSettings, c_pszCmEntryVpnUpdateUrl, TEXT(""), szTemp, MAX_PATH, g_szVpnFile);
if (szTemp[0])
{
bAddCmdlForVpn = TRUE;
}
}
hr = g_pCustomActionList->AddOrRemoveCmdl(g_hInstance, bAddCmdlForVpn, TRUE); // TRUE == bForVpn
MYDBGASSERT(SUCCEEDED(hr));
hr = g_pCustomActionList->AddOrRemoveCmdl(g_hInstance, (g_bUpdatePhonebook || ReferencedDownLoad()), FALSE); // FALSE == bForVpn
MYDBGASSERT(SUCCEEDED(hr));
}
//
// Add the items to the list view control
//
RefreshListView(g_hInstance, hDlg, IDC_COMBO1, hListView, 0, g_bUseTunneling);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Set bUseTunneling == TRUE even though we may not be tunneling. The reason for this is that
// the user may have had a tunneling profile and then turned off tunneling. If they turn
// it back on again we don't want to lose all of their Pre-Tunnel actions nor do we want to
// lose all of the flag settings that they have added to each action. We will make sure
// to use the actual g_bUseTunneling value when we write the actions to the cms file in
// WriteCMSFile.
//
MYDBGASSERT(g_pCustomActionList);
if (g_pCustomActionList)
{
hr = g_pCustomActionList->WriteCustomActionsToCms(g_szCmsFile, g_szShortServiceName, TRUE);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Failed to write out connect actions"));
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessStatusMenuPopup
//
// Synopsis: Processes Messages for the Popup dialog for Adding/Editing Status
// Area Icon Menu items
//
// History: quintinb Created Header and renamed from ProcessPage2G1 8/6/98
//
//+----------------------------------------------------------------------------
// USES GLOBAL VARIABLE DLGEDITITEM as input and output to the page
// You must sent DlgEditItem to the initial value of this page.
//
INT_PTR APIENTRY ProcessStatusMenuPopup(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
BOOL bChecked;
static TCHAR szOld[MAX_PATH+1];
IconMenu TempEditItem;
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
SetDefaultGUIFont(hDlg,message,IDC_EDIT2);
SetDefaultGUIFont(hDlg,message,IDC_EDIT3);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MENU)) return TRUE;
switch (message)
{
case WM_INITDIALOG:
//
// If we are editing we need to change the title
//
if (TEXT('\0') != DlgEditItem.szProgram[0])
{
LPTSTR pszTemp = CmLoadString(g_hInstance, IDS_EDIT_SHORTCUT_TITLE);
if (pszTemp)
{
MYVERIFY(SendMessage (hDlg, WM_SETTEXT, 0, (LPARAM)pszTemp));
CmFree(pszTemp);
}
}
_tcscpy (szOld, DlgEditItem.szName);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)DlgEditItem.szName));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)GetName(DlgEditItem.szProgram)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT3), WM_SETTEXT, 0, (LPARAM)DlgEditItem.szParams));
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, (UINT)DlgEditItem.bDoCopy));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
{
UINT uFilter = IDS_PROGFILTER;
TCHAR* szMask = TEXT("*.exe;*.com;*.bat");
int iReturn = DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDIT2, TEXT("exe"), DlgEditItem.szProgram);
MYDBGASSERT(0 != iReturn);
if (iReturn && (-1 != iReturn))
{
//
// Check the include binary button for the user
//
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
}
}
break;
case IDOK:
{
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, DlgEditItem.szName, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
if (-1 == GetTextFromControl(hDlg, IDC_EDIT2, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
return TRUE;
}
if (szTemp[0] == TEXT('\0'))
{
MYVERIFY(IDOK == ShowMessage(hDlg,IDS_NEEDPROG,MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
return TRUE;
}
CheckNameChange(DlgEditItem.szProgram,szTemp);
if (NULL != _tcschr(DlgEditItem.szProgram, TEXT('=')))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOEQUALSINMENU, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
return TRUE;
}
if (-1 == GetTextFromControl(hDlg, IDC_EDIT3, DlgEditItem.szParams, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT3));
return TRUE;
}
if (DlgEditItem.szName[0] == TEXT('\0'))
{
GetFileName(DlgEditItem.szProgram,DlgEditItem.szName);
}
if (_tcschr(DlgEditItem.szName, TEXT('=')))
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOEQUALSINMENU, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
return TRUE;
}
bChecked = IsDlgButtonChecked(hDlg,IDC_CHECK1);
if (bChecked)
{
if (!VerifyFile(hDlg,IDC_EDIT2,DlgEditItem.szProgram,TRUE))
{
DlgEditItem.bDoCopy = FALSE;
return TRUE;
}
else
{
DlgEditItem.bDoCopy = TRUE;
}
}
else
{
CmStrTrim(DlgEditItem.szProgram);
//
// Check if this is a valid filename and if we have environment macro
// 3rd parameter - FALSE because it's not a custom action file being validated
//
if (FALSE == IsFileNameValid(DlgEditItem.szProgram, hDlg, IDC_EDIT2, FALSE))
{
return TRUE;
}
DlgEditItem.bDoCopy = FALSE;
}
if ((0 != _tcscmp(szOld, DlgEditItem.szName)) &&
(GetIconMenuItem(DlgEditItem.szName, &TempEditItem)))
{
//
// We have a duplicate entry, prompt the user to replace or try
// again.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_MENUITEMEXISTS, szTemp, MAX_PATH));
//
// write the previously used name in the string
//
wsprintf(szMsg, szTemp, DlgEditItem.szName);
//
// If the user doesn't want to replace the duplicate item then we should set the focus to the description
// edit control if it has text in it, otherwise we should set it to the program edit control.
//
if (IDNO == MessageBox(hDlg, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION))
{
LRESULT lTextLen = SendDlgItemMessage(hDlg, IDC_EDIT1, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
SetFocus(GetDlgItem(hDlg, lTextLen ? IDC_EDIT1 : IDC_EDIT2));
return TRUE;
}
}
MYVERIFY(0 != EndDialog(hDlg,IDOK));
return (TRUE);
}
case IDCANCEL:
MYVERIFY(0 != EndDialog(hDlg,IDCANCEL));
return (TRUE);
default:
break;
}
break;
default:
return FALSE;
}
return FALSE;
} //lint !e715 we don't reference lParam
BOOL createListBxRecord(ListBxList ** HeadPtrListBx, ListBxList ** TailPtrListBx, void * pData, DWORD dwSize, LPCTSTR lpName)
{
ListBxList * ptr;
void * dataptr;
unsigned int n;
// check for same named record and update
if ( *HeadPtrListBx != NULL )
{
ptr = *HeadPtrListBx;
while (ptr != NULL)
{
if (_tcsicmp(lpName, ptr->szName) == 0)
{
memcpy(ptr->ListBxData,pData,dwSize);
return (TRUE);
}
ptr = ptr->next;
}
}
n = sizeof( struct ListBxStruct );
ptr = (ListBxList *) CmMalloc(n);
if (ptr == NULL )
{
return FALSE;
}
_tcscpy(ptr->szName, lpName);
if (pData)
{
dataptr = CmMalloc(dwSize);
if (dataptr)
{
memcpy(dataptr, pData, dwSize);
ptr->ListBxData = dataptr;
}
else
{
CmFree(ptr);
return FALSE;
}
}
ptr->next = NULL;
if ( *HeadPtrListBx == NULL ) // If this is the first record in the linked list
{
*HeadPtrListBx = ptr;
}
else
{
(*TailPtrListBx)->next = ptr;
}
*TailPtrListBx = ptr;
return TRUE;
}
// delete named IconMenu item from linked list
void DeleteListBxRecord(ListBxList ** HeadPtrListBx,ListBxList ** TailPtrListBx, LPTSTR lpName)
{
ListBxList * ptr;
ListBxList * prevptr;
if ( HeadPtrListBx != NULL )
{
ptr = *HeadPtrListBx;
prevptr = NULL;
while (ptr != NULL)
{
if (_tcsicmp(lpName,ptr->szName) == 0)
{
if (prevptr == NULL)
{
*HeadPtrListBx = ptr->next;
if (*HeadPtrListBx == NULL)
{
*TailPtrListBx = NULL;
}
else
{
if ((*HeadPtrListBx)->next == NULL)
{
*TailPtrListBx = *HeadPtrListBx;
}
}
}
else
{
prevptr->next = ptr->next;
if (prevptr->next == NULL)
{
*TailPtrListBx = prevptr;
}
}
CmFree(ptr->ListBxData);
CmFree(ptr);
return;
}
prevptr = ptr;
ptr = ptr->next;
}
}
}
BOOL FindListItemByName(LPTSTR pszName, ListBxList* pHeadOfList, ListBxList** pFoundItem)
{
if (NULL == pszName)
{
CMASSERTMSG(FALSE, TEXT("FindListItemByName -- Invalid parameter"));
return FALSE;
}
if (NULL != pHeadOfList)
{
ListBxList * pCurrent = pHeadOfList;
while (NULL != pCurrent)
{
if (0 == lstrcmpi(pszName, pCurrent->szName))
{
//
// Return the pointer to pCurrent if the caller asked for it
//
if (pFoundItem)
{
*pFoundItem = pCurrent;
}
return TRUE;
}
pCurrent = pCurrent->next;
}
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: updateRecord
//
// Synopsis: Function updates an entry in the list of tray icon data structures
// thus the entry is not added and then deleted when the user edits an
// entry. This takes away the putting the entry at the bottom of the list
// problem cited in the bug.
//
// Arguments: PTSTR szName - New name of the entry
// LPTSTR szProgram - Program string to add to the Tray Icon Entry
// LPTSTR szParams - Parameter string to add to the Tray Icon Entry
// BOOL bDoCopy - Value of whether this program should be included with the profile data item
// LPTSTR szOld - Name of the entry to update
//
// Returns: BOOL - TRUE if able to update the record
// FALSE if not able to find it
//
// Side Effects: Replaces the entry named by szOld with the entry data and name for
// entry called szName.
// History: quintinb Created for bugfix 14399 9-9-97
//
//+----------------------------------------------------------------------------
static BOOL updateRecord(LPTSTR szName, LPTSTR szProgram, LPTSTR szParams, BOOL bDoCopy, LPTSTR szOld)
{
IconMenu * ptr;
// check for same named record and update
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (_tcsicmp(szOld,ptr->szName) == 0)
{
_tcscpy(ptr->szProgram,szProgram);
_tcscpy(ptr->szParams,szParams);
ptr->bDoCopy = bDoCopy;
_tcscpy(ptr->szName, szName);
return (TRUE);
}
ptr = ptr->next;
}
}
return (FALSE);
}
// note, as of bug 14399 updating should be done with the above function
BOOL createRecord(LPCTSTR szName, LPCTSTR szProgram, LPCTSTR szParams, BOOL bDoCopy)
{
IconMenu * ptr;
unsigned int n;
// check for same named record and update
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (_tcsicmp(szName,ptr->szName) == 0)
{
_tcscpy(ptr->szProgram,szProgram);
_tcscpy(ptr->szParams,szParams);
ptr->bDoCopy = bDoCopy;
return (TRUE);
}
ptr = ptr->next;
}
}
//
n = sizeof( struct IconMenuStruct );
ptr = (IconMenu *) CmMalloc(n);
if ( ptr == NULL )
{
return FALSE;
}
_tcscpy(ptr->szName,szName);
_tcscpy(ptr->szProgram,szProgram);
_tcscpy(ptr->szParams,szParams);
ptr->bDoCopy = bDoCopy;
ptr->next = NULL;
if ( g_pHeadIcon == NULL ) // If this is the first record in the linked list
{
g_pHeadIcon = ptr;
}
else
{
g_pTailIcon->next = ptr;
}
g_pTailIcon = ptr;
return TRUE;
}
// delete named IconMenu item from linked list
static void DeleteRecord(LPTSTR lpName)
{
IconMenu * ptr;
IconMenu * prevptr;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
prevptr = NULL;
while (ptr != NULL)
{
if (_tcsicmp(lpName,ptr->szName) == 0)
{
if (prevptr == NULL)
{
g_pHeadIcon = ptr->next;
if (g_pHeadIcon == NULL)
{
g_pTailIcon = NULL;
}
else
{
if (g_pHeadIcon->next == NULL)
{
g_pTailIcon = g_pHeadIcon;
}
}
}
else
{
prevptr->next = ptr->next;
if (prevptr->next == NULL)
{
g_pTailIcon = prevptr;
}
}
CmFree(ptr);
return;
}
prevptr = ptr;
ptr = ptr->next;
}
}
}
static BOOL MoveRecord(LPTSTR lpName, int direction)
{
IconMenu * ptr;
IconMenu * prevptr;
IconMenu * nextptr;
IconMenu TempIconMenu;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
prevptr = NULL;
while (ptr != NULL)
{
if (_tcsicmp(lpName,ptr->szName) == 0)
{
if (((direction > 0)&&(ptr->next == NULL))||
((direction < 0)&&(prevptr == NULL)))
return FALSE;
if ((direction > 0)&&(ptr->next != NULL))
{
//swap contents with next element
nextptr = ptr->next;
_tcscpy(TempIconMenu.szName,ptr->szName);
_tcscpy(TempIconMenu.szProgram,ptr->szProgram);
_tcscpy(TempIconMenu.szParams,ptr->szParams);
TempIconMenu.bDoCopy = ptr->bDoCopy;
_tcscpy(ptr->szName,nextptr->szName);
_tcscpy(ptr->szProgram,nextptr->szProgram);
_tcscpy(ptr->szParams,nextptr->szParams);
ptr->bDoCopy = nextptr->bDoCopy;
_tcscpy(nextptr->szName,TempIconMenu.szName);
_tcscpy(nextptr->szProgram,TempIconMenu.szProgram);
_tcscpy(nextptr->szParams,TempIconMenu.szParams);
nextptr->bDoCopy = TempIconMenu.bDoCopy;
}
else
{
if ((direction < 0)&&(prevptr != NULL))
{
_tcscpy(TempIconMenu.szName,ptr->szName);
_tcscpy(TempIconMenu.szProgram,ptr->szProgram);
_tcscpy(TempIconMenu.szParams,ptr->szParams);
TempIconMenu.bDoCopy = ptr->bDoCopy;
_tcscpy(ptr->szName,prevptr->szName);
_tcscpy(ptr->szProgram,prevptr->szProgram);
_tcscpy(ptr->szParams,prevptr->szParams);
ptr->bDoCopy = prevptr->bDoCopy;
_tcscpy(prevptr->szName,TempIconMenu.szName);
_tcscpy(prevptr->szProgram,TempIconMenu.szProgram);
_tcscpy(prevptr->szParams,TempIconMenu.szParams);
prevptr->bDoCopy = TempIconMenu.bDoCopy;
}
}
return TRUE;
}
prevptr = ptr;
ptr = ptr->next;
}
}
return TRUE;
}
// retrieve named IconMenu item from linked list
BOOL GetIconMenuItem(LPTSTR lpName, IconMenu * EditItem)
{
IconMenu * ptr;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (_tcsicmp(lpName,ptr->szName) == 0)
{
_tcscpy(EditItem->szName,ptr->szName);
_tcscpy(EditItem->szProgram,ptr->szProgram);
_tcscpy(EditItem->szParams,ptr->szParams);
EditItem->bDoCopy = ptr->bDoCopy;
return TRUE;
}
ptr = ptr->next;
}
}
return FALSE;
}
static BOOL WriteCopyMenuItemFiles(HANDLE hInf,LPTSTR pszFailFile, BOOL bWriteShortName)
{
IconMenu * ptr;
if (g_pHeadIcon != NULL)
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (ptr->bDoCopy)
{
if (!WriteCopy(hInf, ptr->szProgram, bWriteShortName))
{
_tcscpy(pszFailFile, ptr->szProgram);
return FALSE;
}
}
ptr = ptr->next;
}
}
return TRUE;
}
static BOOL WriteCopyConActFiles(HANDLE hInf, LPTSTR pszFailFile, BOOL bWriteShortName)
{
TCHAR szTemp[MAX_PATH+1];
HRESULT hr = E_INVALIDARG;
MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
MYDBGASSERT(pszFailFile);
MYDBGASSERT(g_pCustomActionList);
if ((INVALID_HANDLE_VALUE != hInf) && pszFailFile && g_pCustomActionList)
{
CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
do
{
hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
if (!WriteCopy(hInf, szTemp, bWriteShortName))
{
_tcscpy(pszFailFile, szTemp);
hr = E_UNEXPECTED;
}
}
} while (SUCCEEDED(hr) && (S_FALSE != hr));
}
return SUCCEEDED(hr);
}
static BOOL WriteCopyExtraFiles(HANDLE hInf,LPTSTR pszFailFile, BOOL bWriteShortName)
{
ListBxList * ptr;
ExtraData * pExtraData;
if (g_pHeadExtra != NULL)
{
ptr = g_pHeadExtra;
while (ptr != NULL)
{
pExtraData = (ExtraData *)(ptr->ListBxData);
if (!WriteCopy(hInf, pExtraData->szPathname, bWriteShortName))
{
_tcscpy(pszFailFile, pExtraData->szPathname);
return FALSE;
}
ptr = ptr->next;
}
}
return TRUE;
}
static BOOL WriteCopyDnsFiles(HANDLE hInf, LPTSTR pszFailFile, BOOL bWriteShortName)
{
ListBxList * ptr;
CDunSetting* pDunSetting;
if (g_pHeadDunEntry != NULL)
{
ptr = g_pHeadDunEntry;
while (ptr != NULL)
{
pDunSetting = (CDunSetting*)(ptr->ListBxData);
if (!WriteCopy(hInf, pDunSetting->szScript, bWriteShortName))
{
_tcscpy(pszFailFile, pDunSetting->szScript);
return FALSE;
}
ptr = ptr->next;
}
}
return TRUE;
}
void WriteDelMenuItemFiles(HANDLE hInf)
{
IconMenu * ptr;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (ptr->bDoCopy)
{
MYVERIFY(FALSE != WriteInfLine(hInf,ptr->szProgram));
}
ptr = ptr->next;
}
}
}
static BOOL WriteRefsFiles(HANDLE hInf,BOOL WriteCM)
{
ListBxList * ptr;
TCHAR szTemp[MAX_PATH+1];
if ( g_pHeadRefs != NULL )
{
ptr = g_pHeadRefs;
while (ptr != NULL)
{
if ((_tcsstr(ptr->szName,c_pszCmpExt) == NULL) && (!WriteCM))
{
MYVERIFY(FALSE != WriteInfLine(hInf,ptr->szName));
}
else
{
if ((_tcsstr(ptr->szName,c_pszCmpExt) != NULL) && (WriteCM))
{
_tcscpy(szTemp,ptr->szName);
_tcscat(szTemp, TEXT(",,,16")); // set to not overwrite existing file
MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
}
}
ptr = ptr->next;
}
}
return TRUE;
}
static BOOL WriteShortRefsFiles(HANDLE hInf,BOOL WriteCM)
{
ListBxList * ptr;
TCHAR szTemp[MAX_PATH+1];
TCHAR szShort[MAX_PATH + 1];
RenameData TmpRenameData;
TCHAR szCurrentDir[MAX_PATH+1];
if (g_pHeadRefs != NULL)
{
ptr = g_pHeadRefs;
// hack to fix short filename resolution
// change dir to cmaktemp dir and use getshortpathname
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szCurrentDir));
MYVERIFY(0 != SetCurrentDirectory(g_szTempDir));
while (ptr != NULL)
{
if ((_tcsstr(ptr->szName,c_pszCmpExt) == NULL) && (!WriteCM))
{
// writing non-cmp files so I want to make sure that I use
// the short file name if it is actually a long filename.
if (GetShortPathName(ptr->szName, szShort, MAX_PATH))
{
_tcscpy(szTemp, szShort);
if (_tcsicmp(szShort,ptr->szName) != 0)
{
_tcscpy(TmpRenameData.szShortName,szShort);
_tcscpy(TmpRenameData.szLongName,ptr->szName);
MYVERIFY(FALSE != createListBxRecord(&g_pHeadRename,&g_pTailRename,(void *)&TmpRenameData,sizeof(TmpRenameData),TmpRenameData.szShortName));
}
}
else
{
_tcscpy(szTemp, ptr->szName);
}
MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
}
else
{
if ((_tcsstr(ptr->szName,c_pszCmpExt) != NULL) && (WriteCM))
{
_tcscpy(szTemp,ptr->szName);
_tcscat(szTemp, TEXT(",,,16")); // set to not overwrite existing file
MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
}
}
ptr = ptr->next;
}
MYVERIFY(0 != SetCurrentDirectory(szCurrentDir));
}
return TRUE;
}
static BOOL WriteLongRefsFiles(HANDLE hInf)
{
ListBxList * ptr;
TCHAR szTemp[MAX_PATH+1];
TCHAR szShort[MAX_PATH + 1];
RenameData TmpRenameData;
TCHAR szCurrentDir[MAX_PATH+1];
if (g_pHeadRefs != NULL)
{
ptr = g_pHeadRefs;
while (ptr != NULL)
{
GetFileName(ptr->szName, szTemp);
MYVERIFY(FALSE != WriteInfLine(hInf, szTemp));
ptr = ptr->next;
}
}
return TRUE;
}
BOOL WriteDelConActFiles(HANDLE hInf)
{
TCHAR szTemp[MAX_PATH+1];
HRESULT hr = E_INVALIDARG;
MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
MYDBGASSERT(g_pCustomActionList);
if ((INVALID_HANDLE_VALUE != hInf) && g_pCustomActionList)
{
CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
do
{
hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
if (FALSE == WriteInfLine(hInf, szTemp))
{
hr = E_UNEXPECTED;
}
}
} while (SUCCEEDED(hr) && (S_FALSE != hr));
}
MYDBGASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
void WriteDelExtraFiles(HANDLE hInf)
{
ListBxList * ptr;
ExtraData * pExtraData;
if ( g_pHeadExtra != NULL )
{
ptr = g_pHeadExtra;
while (ptr != NULL)
{
pExtraData = (ExtraData *)(ptr->ListBxData);
MYVERIFY(FALSE != WriteInfLine(hInf,pExtraData->szPathname));
ptr = ptr->next;
}
}
}
void WriteDelDnsFiles(HANDLE hInf)
{
ListBxList * ptr;
CDunSetting * pDunSetting;
if (NULL != g_pHeadDunEntry)
{
ptr = g_pHeadDunEntry;
while (ptr != NULL)
{
pDunSetting = (CDunSetting*)(ptr->ListBxData);
MYVERIFY(FALSE != WriteInfLine(hInf, pDunSetting->szScript));
ptr = ptr->next;
}
}
}
void WriteSrcMenuItemFiles(HANDLE hInf)
{
IconMenu * ptr;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (ptr->bDoCopy)
{
MYVERIFY(FALSE != WriteSrcInfLine(hInf,ptr->szProgram));
}
ptr = ptr->next;
}
}
}
BOOL WriteSrcConActFiles(HANDLE hInf)
{
TCHAR szTemp[MAX_PATH+1];
HRESULT hr = E_INVALIDARG;
MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
MYDBGASSERT(g_pCustomActionList);
if ((INVALID_HANDLE_VALUE != hInf) && g_pCustomActionList)
{
CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
do
{
hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
if (FALSE == WriteSrcInfLine(hInf, szTemp))
{
hr = E_UNEXPECTED;
}
}
} while (SUCCEEDED(hr) && (S_FALSE != hr));
}
return SUCCEEDED(hr);
}
//+----------------------------------------------------------------------------
//
// Function: WriteSrcRefsFiles
//
// Synopsis: This function writes all the files on the HeadRef list to the
// [SourceDisksFiles] section of the INF. Note that it has to change
// directory to the temp dir so that the WriteSrcInfLine won't fail
// (it needs to locate the file to see if a short name should be used).
//
// Arguments: HANDLE hInf - Handle to the open inf file to pass to WriteSrcInfLine
//
// Returns: Returns TRUE if all the files were written out successfully
//
// History: quintinb Created Header and added hack to fix failure of WriteSrcInfLine
// because it couldn't find the file to find its short name 1/22/98
//
//+----------------------------------------------------------------------------
BOOL WriteSrcRefsFiles(HANDLE hInf)
{
ListBxList * ptr;
BOOL bSuccess = TRUE;
TCHAR szSavedDir[MAX_PATH+1];
//
// Save the current directory and then set the current dir to
// the temp dir so that WriteSrcInfLine can find the shortfilename
// of the referenced files.
//
if ( g_pHeadRefs != NULL )
{
if (0 == GetCurrentDirectory(MAX_PATH, szSavedDir))
{
return FALSE;
}
if (0 == SetCurrentDirectory(g_szTempDir))
{
return FALSE;
}
ptr = g_pHeadRefs;
while (ptr != NULL)
{
bSuccess = (bSuccess && WriteSrcInfLine(hInf,ptr->szName));
ptr = ptr->next;
}
MYVERIFY(0 != SetCurrentDirectory(szSavedDir));
}
return bSuccess;
}
void WriteSrcExtraFiles(HANDLE hInf)
{
ListBxList * ptr;
ExtraData * pExtraData;
if ( g_pHeadExtra != NULL )
{
ptr = g_pHeadExtra;
while (ptr != NULL)
{
pExtraData = (ExtraData *)(ptr->ListBxData);
MYVERIFY(FALSE != WriteSrcInfLine(hInf,pExtraData->szPathname));
ptr = ptr->next;
}
}
}
void WriteSrcDnsFiles(HANDLE hInf)
{
ListBxList * ptr;
CDunSetting* pDunSetting;
if (NULL != g_pHeadDunEntry)
{
ptr = g_pHeadDunEntry;
while (NULL != ptr)
{
pDunSetting = (CDunSetting*)(ptr->ListBxData);
MYVERIFY(FALSE != WriteSrcInfLine(hInf, pDunSetting->szScript));
ptr = ptr->next;
}
}
}
BOOL WriteSEDConActFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szFileName[MAX_PATH+1];
HRESULT hr = E_INVALIDARG;
MYDBGASSERT(hDlg);
MYDBGASSERT(pFileNum);
MYDBGASSERT(szSed);
MYDBGASSERT(g_pCustomActionList);
if (hDlg && pFileNum && szSed && g_pCustomActionList)
{
CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
do
{
hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
if (SUCCEEDED(hr) && (S_FALSE != hr))
{
GetFileName(szTemp, szFileName);
if (FALSE == WriteSED(hDlg, szFileName, pFileNum, szSed))
{
hr = E_UNEXPECTED;
}
}
} while (SUCCEEDED(hr) && (S_FALSE != hr));
}
return SUCCEEDED(hr);
}
BOOL WriteSEDExtraFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
{
ListBxList * ptr;
ExtraData * pExtraData;
BOOL bReturn = TRUE;
if ( g_pHeadExtra != NULL )
{
ptr = g_pHeadExtra;
while (ptr != NULL)
{
pExtraData = (ExtraData *)(ptr->ListBxData);
bReturn &= WriteSED(hDlg, pExtraData->szPathname, pFileNum, szSed);
ptr = ptr->next;
}
}
return bReturn;
}
BOOL WriteSEDDnsFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
{
BOOL bReturn = TRUE;
ListBxList * ptr;
CDunSetting* pDunSetting;
if (NULL != g_pHeadDunEntry)
{
ptr = g_pHeadDunEntry;
while (NULL != ptr)
{
pDunSetting = (CDunSetting*)(ptr->ListBxData);
bReturn &= WriteSED(hDlg, pDunSetting->szScript, pFileNum, szSed);
ptr = ptr->next;
}
}
return bReturn;
}
BOOL WriteSEDRefsFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
{
ListBxList * ptr;
BOOL bReturn = TRUE;
if ( g_pHeadRefs != NULL )
{
ptr = g_pHeadRefs;
while (ptr != NULL)
{
bReturn &= WriteSED(hDlg, ptr->szName, pFileNum, szSed);
ptr = ptr->next;
}
}
return bReturn;
}
BOOL WriteSEDMenuItemFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
{
IconMenu * ptr;
BOOL bReturn = TRUE;
if ( g_pHeadIcon != NULL )
{
ptr = g_pHeadIcon;
while (ptr != NULL)
{
if (ptr->bDoCopy)
{
bReturn &= WriteSED(hDlg, ptr->szProgram, pFileNum, szSed);
}
ptr = ptr->next;
}
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: WriteRenameSection
//
// Synopsis: This function verifies that the name used in the rename data structure
// is correct (the files name in the temp directory could be different
// if the file was moved from a directory with multiple similarly named files) and then
// writes the rename section to the inf.
//
// Arguments: HANDLE hInf - handle to the inf to add the rename section to.
//
// Returns: Nothing
//
// History: quintinb Created Header and added checking functionality 2/22/98
//
//+----------------------------------------------------------------------------
void WriteRenameSection(HANDLE hInf)
{
ListBxList * ptr;
TCHAR szOut[MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szPathToFileInTempDir[MAX_PATH+1];
RenameData * pRenameData;
if ( g_pHeadRename != NULL )
{
ptr = g_pHeadRename;
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.RenameReg]\r\n")));
WriteInf(hInf, TEXT("HKLM,%KEY_RENAME%\\CMRENAME,,,\"%49001%\\%ShortSvcName%\"\r\n"));//lint !e534 compile doesn't like the MYVERIFY macro and big strings
while (ptr != NULL)
{
pRenameData = (RenameData *)(ptr->ListBxData);
//
// Get the current ShortName for the File
//
GetFileName(pRenameData->szLongName, szTemp);
MYVERIFY(CELEMS(szPathToFileInTempDir) > (UINT)wsprintf(szPathToFileInTempDir,
TEXT("%s\\%s"), g_szTempDir, szTemp));
MYVERIFY(0 != GetShortPathName(szPathToFileInTempDir, szTemp, MAX_PATH));
GetFileName(szTemp, pRenameData->szShortName);
//
// Now Write out the files
//
_tcscpy(szOut,TEXT("HKLM,%KEY_RENAME%\\CMRENAME,"));
_tcscat(szOut,pRenameData->szShortName);
_tcscat(szOut,TEXT(",,\""));
_tcscat(szOut,pRenameData->szLongName);
_tcscat(szOut,TEXT("\"\r\n"));
MYDBGASSERT(_tcslen(szOut) <= sizeof(szOut));
MYVERIFY(FALSE != WriteInf(hInf,szOut));
ptr = ptr->next;
}
}
}
void WriteEraseLongName(HANDLE hInf)
{
ListBxList * ptr;
TCHAR szOut[MAX_PATH+1];
RenameData * pRenameData;
if ( g_pHeadRename != NULL )
{
ptr = g_pHeadRename;
while (ptr != NULL)
{
pRenameData = (RenameData *)(ptr->ListBxData);
pRenameData->szShortName[7] = pRenameData->szShortName[7]+1;
_tcscpy(szOut,pRenameData->szShortName);
_tcscat(szOut,TEXT("\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szOut));
ptr = ptr->next;
}
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessMenuItem
//
// Synopsis: This function retrieves the data associated with the given keyname
// under the [Menu Options] section of the given cms file. It then
// processes the data line into a program part and a parameters part.
// Then using the keyname, the program string, and the params string
// it adds an entry to the Status Area Menu Item linked list.
//
// Arguments: LPCTSTR pszKeyName - Name of the Menu Item
// LPCTSTR pszCmsFile - CMS file containing the menu items
// LPCTSTR pszProfilesDir - directory containing the profiles dir
// (to help determine if the file was included or not)
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb Created 6/14/99
//
//+----------------------------------------------------------------------------
BOOL ProcessMenuItem(LPCTSTR pszKeyName, LPCTSTR pszCmsFile, LPCTSTR pszProfilesDir)
{
//
// Check parameters
//
if ((NULL == pszKeyName) || (NULL == pszCmsFile) ||
(TEXT('\0') == pszKeyName[0]) || (TEXT('\0') == pszCmsFile[0]))
{
CMTRACE(TEXT("ProcessMenuItem -- bad parameter passed."));
return FALSE;
}
BOOL bFileIncluded = FALSE;
BOOL bLongFileName = FALSE;
BOOL bReturn = FALSE;
LPTSTR pszParams = NULL;
LPTSTR pszProgram = NULL;
TCHAR szProgram[MAX_PATH+1];
TCHAR SeperatorChar = TEXT('\0');
//
// Get the Menu Item specified by pszKeyName
//
LPTSTR pszLine = GetPrivateProfileStringWithAlloc(c_pszCmSectionMenuOptions, pszKeyName, TEXT(""), pszCmsFile);
if ((NULL == pszLine) || (TEXT('\0') == pszLine[0]))
{
CMTRACE(TEXT("ProcessMenuItem -- GetPrivateProfileStringWithAlloc failed"));
goto exit;
}
//
// Now that we have a menu item, begin processing. Since we have the keyname, we already
// have the name of the menu item. We now could have any of the following strings:
//
// +Program Name+ Params
// +Program Name+
// ProgName Params
// ProgName
//
// Note that we surround long filenames with the '+' char.
//
CmStrTrim(pszLine);
if (TEXT('+') == pszLine[0])
{
bLongFileName = TRUE;
SeperatorChar = TEXT('+');
pszProgram = CharNext(pszLine); // move past the initial +
}
else
{
bLongFileName = FALSE;
SeperatorChar = TEXT(' ');
pszProgram = pszLine;
}
pszParams = CmStrchr(pszProgram, SeperatorChar);
if (pszParams)
{
LPTSTR pszTemp = pszParams;
pszParams = CharNext(pszParams); // pszParams is either a NULL string or it is the parameters with a space.
*pszTemp = TEXT('\0');
}
else
{
if (bLongFileName)
{
CMTRACE1(TEXT("ProcessMenuItem -- Unexpected Menu Item format: %s"), pszLine);
goto exit;
}
else
{
//
// Then we don't have any parameters, just a Program
//
pszParams = CmEndOfStr(pszProgram);
}
}
CmStrTrim(pszParams);
CmStrTrim(pszProgram);
//
// Now check to see if the file exists in the profile or not
//
MYVERIFY(CELEMS(szProgram) > (UINT)wsprintf(szProgram, TEXT("%s%s"), pszProfilesDir, pszProgram));
bFileIncluded = FileExists(szProgram);
if (bFileIncluded)
{
//
// If we are in this if block then we have an edited profile that contains menu items.
// Use the full path to add to the record list.
//
pszProgram = szProgram; // memory will be cleaned up below because we only had one
// allocation that we split up into several pieces.
}
bReturn = createRecord(pszKeyName, pszProgram, pszParams, bFileIncluded);
exit:
CmFree(pszLine);
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ReadIconMenu
//
// Synopsis: This function converts the Menu Options section of the given CMS
// into the Status Area Menu Items linked list that internally
// represents it.
//
// Arguments: LPCTSTR pszCmsFile - Cms File to read the menu items from
// LPCTSTR pszProfilesDir - full path to the Profiles directory
// (c:\program files\cmak\profiles usually)
//
// Returns: BOOL - Returns TRUE if Successful
//
// History: Created Header 6/14/99
// quintinb Rewrote for Unicode Conversion 6/14/99
//
//+----------------------------------------------------------------------------
BOOL ReadIconMenu(LPCTSTR pszCmsFile, LPCTSTR pszProfilesDir)
{
BOOL bReturn = TRUE;
LPTSTR pszCurrentKeyName = NULL;
//
// First we want to get all of the keynames in the Menu Options section
//
LPTSTR pszKeyNames = GetPrivateProfileStringWithAlloc(c_pszCmSectionMenuOptions, NULL, TEXT(""), pszCmsFile);
if (NULL == pszKeyNames)
{
//
// Nothing to process
//
goto exit;
}
pszCurrentKeyName = pszKeyNames;
while (TEXT('\0') != (*pszCurrentKeyName))
{
//
// Process the command line
//
bReturn = bReturn && ProcessMenuItem(pszCurrentKeyName, pszCmsFile, pszProfilesDir);
//
// Find the next string by going to the end of the string
// and then going one more char. Note that we cannot use
// CharNext here but must use just ++.
//
pszCurrentKeyName = CmEndOfStr(pszCurrentKeyName);
pszCurrentKeyName++;
}
exit:
CmFree(pszKeyNames);
return bReturn;
}
static void WriteIconMenu()
{
IconMenu * LoopPtr;
TCHAR szTemp[2*MAX_PATH+1];
TCHAR szName[MAX_PATH+1];
BOOL longname;
// CLEAR OUT SECTION
MYVERIFY(0 != WritePrivateProfileSection(c_pszCmSectionMenuOptions,TEXT("\0\0"),g_szCmsFile));
if (g_pHeadIcon == NULL)
{
return;
}
LoopPtr = g_pHeadIcon;
// WRITE IN ALL ENTRIES
while( LoopPtr != NULL)
{
GetFileName(LoopPtr->szProgram,szName);
if (IsFile8dot3(szName))
{
longname = FALSE;
}
else
{
longname = TRUE;
}
// surround long file names with plus signs - quotes won't work cause
// they get stripped by the reading routines
if (longname)
{
_tcscpy(szTemp,TEXT("+"));
}
else
{
szTemp[0] = TEXT('\0');
}
if (LoopPtr->bDoCopy)
{
_tcscat(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT("\\"));
}
_tcscat(szTemp,szName);
if (longname)
{
_tcscat(szTemp,TEXT("+"));
}
_tcscat(szTemp,TEXT(" "));
_tcscat(szTemp,LoopPtr->szParams);
MYDBGASSERT(_tcslen(szTemp) <= CELEMS(szTemp));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionMenuOptions,LoopPtr->szName,szTemp,g_szCmsFile));
LoopPtr = LoopPtr->next;
}
}
static void RefreshIconMenu(HWND hwndDlg)
{
IconMenu * LoopPtr;
SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_RESETCONTENT,0,(LPARAM)0); //lint !e534 LB_RESETCONTENT doesn't return anything
if (g_pHeadIcon == NULL)
{
return;
}
LoopPtr = g_pHeadIcon;
while( LoopPtr != NULL)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0,
(LPARAM) LoopPtr->szName));
LoopPtr = LoopPtr->next;
}
}
void UpdateEditDeleteMoveButtons(HWND hDlg, IconMenu* pHeadIcon)
{
LRESULT lResult;
BOOL bEnableDeleteAndEdit = FALSE;
BOOL bEnableMoveUp = FALSE;
BOOL bEnableMoveDown = FALSE;
lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
if (LB_ERR != lResult)
{
//
// Enable the Delete and Edit Buttons because we have at least 1 item.
//
bEnableDeleteAndEdit = (0 < lResult);
//
// If we have more than 1 item, then we need to enable the moveup and movedown
// buttons, depending on which item is selected.
//
if (1 < lResult)
{
bEnableMoveUp = TRUE;
bEnableMoveDown = TRUE;
//
// Get the name of the currently selected item
//
TCHAR szCurrentItem[MAX_PATH+1];
lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, 0);
if (LB_ERR != lResult)
{
lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, lResult, (LPARAM)szCurrentItem);
if (LB_ERR != lResult)
{
IconMenu* pFollower = NULL;
IconMenu* pCurrent = pHeadIcon;
while (pCurrent)
{
if (0 == lstrcmpi(szCurrentItem, pCurrent->szName))
{
if (NULL == pFollower)
{
//
// First item in the list, disable move up
//
bEnableMoveUp = FALSE;
}
else if (NULL == pCurrent->next)
{
//
// Last item in the list, disable move down
//
bEnableMoveDown = FALSE;
}
break;
}
pFollower = pCurrent;
pCurrent = pCurrent->next;
}
}
}
}
}
HWND hCurrentFocus = GetFocus();
HWND hEditButton = GetDlgItem(hDlg, IDC_BUTTON2);
HWND hDeleteButton = GetDlgItem(hDlg, IDC_BUTTON3);
HWND hMoveUpButton = GetDlgItem(hDlg, IDC_BUTTON4);
HWND hMoveDownButton = GetDlgItem(hDlg, IDC_BUTTON5);
HWND hControl;
if (hEditButton)
{
EnableWindow(hEditButton, bEnableDeleteAndEdit);
}
if (hDeleteButton)
{
EnableWindow(hDeleteButton, bEnableDeleteAndEdit);
}
if (hMoveUpButton)
{
EnableWindow(hMoveUpButton, bEnableMoveUp);
}
if (hMoveDownButton)
{
EnableWindow(hMoveDownButton, bEnableMoveDown);
}
if(hCurrentFocus && (FALSE == IsWindowEnabled(hCurrentFocus)))
{
if (hDeleteButton == hCurrentFocus)
{
//
// If delete is disabled and contained the focus, shift it to the Add button
//
hControl = GetDlgItem(hDlg, IDC_BUTTON1);
SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON1, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
SetFocus(hControl);
}
else if ((hMoveUpButton == hCurrentFocus) && IsWindowEnabled(hMoveDownButton))
{
SetFocus(hMoveDownButton);
SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON5, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
}
else if ((hMoveDownButton == hCurrentFocus) && IsWindowEnabled(hMoveUpButton))
{
SetFocus(hMoveUpButton);
SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON4, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
}
else
{
//
// If all else fails set the focus to the list control
//
hControl = GetDlgItem(hDlg, IDC_LIST1);
SetFocus(hControl);
}
}
}
BOOL OnProcessStatusMenuIconsEdit(HWND hDlg)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szOld[MAX_PATH+1];
INT_PTR nResult;
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
if (nResult == LB_ERR)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
return TRUE;
}
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult, (LPARAM)szTemp));
MYVERIFY(FALSE != GetIconMenuItem(szTemp, &DlgEditItem));
_tcscpy(szOld, szTemp);
nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_MENU_ITEM_POPUP), hDlg, ProcessStatusMenuPopup, (LPARAM)0);
if ((IDOK == nResult) && (TEXT('\0') != DlgEditItem.szName[0]))
{
if (0 == lstrcmpi(szOld, DlgEditItem.szName))
{
MYVERIFY(FALSE != updateRecord(DlgEditItem.szName, DlgEditItem.szProgram,
DlgEditItem.szParams, DlgEditItem.bDoCopy, szOld));
}
else
{
DeleteRecord(szOld);
MYVERIFY(TRUE == createRecord(DlgEditItem.szName, DlgEditItem.szProgram,
DlgEditItem.szParams, DlgEditItem.bDoCopy));
}
RefreshIconMenu(hDlg);
WriteIconMenu();
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)DlgEditItem.szName);
if (LB_ERR != nResult)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg,IDC_LIST1,LB_SETCURSEL,(WPARAM)nResult,(LPARAM)0));
}
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessStatusMenuIcons
//
// Synopsis: Customize the status area icon menu
//
//
// History: quintinb Created Header and renamed from ProcessPage2F1 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessStatusMenuIcons(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szOld[MAX_PATH+1];
INT_PTR nResult;
int direction;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MENU)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LIST1);
switch (message)
{
case WM_INITDIALOG:
{
//
// Load the arrow images for the move up and move down buttons
//
HICON hUpArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_UP_ARROW), IMAGE_ICON, 0, 0, 0);
HICON hDownArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DOWN_ARROW), IMAGE_ICON, 0, 0, 0);
//
// Set the arrow button bit maps
//
if (hUpArrow)
{
SendMessage(GetDlgItem(hDlg, IDC_BUTTON4), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hUpArrow);
}
if (hDownArrow)
{
SendMessage(GetDlgItem(hDlg, IDC_BUTTON5), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDownArrow);
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
ZeroMemory(&DlgEditItem,sizeof(DlgEditItem));
nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_MENU_ITEM_POPUP), hDlg, ProcessStatusMenuPopup, (LPARAM)0);
if ((nResult == IDOK) && (DlgEditItem.szName[0] != 0))
{
MYVERIFY(FALSE != createRecord(DlgEditItem.szName, DlgEditItem.szProgram, DlgEditItem.szParams, DlgEditItem.bDoCopy));
RefreshIconMenu(hDlg);
WriteIconMenu();
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)DlgEditItem.szName);
if (LB_ERR != nResult)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg,IDC_LIST1,LB_SETCURSEL,(WPARAM)nResult,(LPARAM)0));
}
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
}
return (TRUE);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON2: //edit
OnProcessStatusMenuIconsEdit(hDlg);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON3: //delete
nResult = SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,(LPARAM)0);
if (nResult == LB_ERR)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
return TRUE;
}
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult,
(LPARAM)szTemp));
DeleteRecord(szTemp);
RefreshIconMenu(hDlg);
//
// Reset the cursor selection to the first in the list, unless the list is empty.
//
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if (nResult)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)0, (LPARAM)0));
}
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
WriteIconMenu();
return (TRUE);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON4: //UP
case IDC_BUTTON5: //down
if (LOWORD(wParam) == IDC_BUTTON4)
{
direction = -1;
}
else
{
direction = 1;
}
nResult = SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,(LPARAM)0);
if (nResult == LB_ERR)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
return TRUE;
}
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT,
(WPARAM)nResult, (LPARAM)szTemp));
if (MoveRecord(szTemp,direction))
{
RefreshIconMenu(hDlg);
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL,
(WPARAM)(nResult + direction), (LPARAM)0));
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
}
WriteIconMenu();
return (TRUE);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_LIST1:
if (LBN_DBLCLK == HIWORD(wParam))
{
OnProcessStatusMenuIconsEdit(hDlg);
}
else if (LBN_SELCHANGE == HIWORD(wParam))
{
//
// The selection in the list box changed, update the move buttons if needed
//
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
if (g_pHeadIcon == NULL)
{
MYVERIFY(FALSE != ReadIconMenu(g_szCmsFile, g_szOsdir));
}
RefreshIconMenu(hDlg);
//
// Reset the cursor selection to the first in the list, unless the list is empty.
// Then we should set focus on the Add button
//
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if (nResult)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)0, (LPARAM)0));
}
else
{
SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
}
UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
break;
case PSN_WIZBACK:
WriteIconMenu();
break;
case PSN_WIZNEXT:
WriteIconMenu();
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: DisplayBitmap
//
// Synopsis: This function takes a BMPDATA structure with a valid HDIBitmap data
// (device Independent bitmap data) and creates a device dependent bitmap
// and displays it on the specified bitmap window control.
//
// Arguments: HWND hDlg - Window handle of the dialog containing the Bitmap control
// int iBitmapControl - Resource ID of the bitmap window control
// HPALETTE* phMasterPalette - pointer to the master palette
// BMPDATA* pBmpData - pointer to the BMPDATA to display
//
// Returns: Nothing
//
// History: quintinb Created 8/6/98
//
//+----------------------------------------------------------------------------
void DisplayBitmap(HWND hDlg, int iBitmapControl, HPALETTE* phMasterPalette, BMPDATA* pBmpData)
{
MYDBGASSERT(NULL != pBmpData);
MYDBGASSERT(pBmpData->hDIBitmap);
MYDBGASSERT(NULL != phMasterPalette);
if ((NULL != pBmpData) && (pBmpData->hDIBitmap) && (NULL != phMasterPalette))
{
pBmpData->phMasterPalette = phMasterPalette;
pBmpData->bForceBackground = FALSE; // Paint as a Foreground App
if (CreateBitmapData(pBmpData->hDIBitmap, pBmpData, hDlg, TRUE))
{
SendDlgItemMessage(hDlg, iBitmapControl, STM_SETIMAGE,
IMAGE_BITMAP,
(LPARAM) pBmpData); //lint !e534 STM_SETIMAGE doesn't return error info
}
}
}
//+----------------------------------------------------------------------------
//
// Function: LoadAndDisplayBitmap
//
// Synopsis: Utility function to combine the code to load and display a bitmap.
// Makes sure to send a STM_SETIMAGE message with a NULL bitmap pointer
// to the bitmap control before releasing the bitmap data. This prevents
// the control from holding a pointer to memory that is then freed.
//
// Arguments: HWND hDlg - Window handle of the dialog containing the Bitmap control
// int iBitmapControl - Resource ID of the bitmap window control
// HPALETTE* phMasterPalette - pointer to the master palette
// BMPDATA* pBmpData - pointer to the BMPDATA to display
//
// Returns: Nothing
//
// History: quintinb Created 06/07/01
//
//+----------------------------------------------------------------------------
void LoadAndDisplayBitmap (HINSTANCE hInstance, BMPDATA* pBmpData, HPALETTE* phMasterPalette, LPTSTR pszBitmap, HWND hDlg, UINT uControl)
{
if ((NULL == pBmpData) || (NULL == phMasterPalette) || (NULL == pszBitmap))
{
CMASSERTMSG(FALSE, TEXT("LoadAndDisplayBitmap -- invalid parameter."));
return;
}
//
// Release the existing bitmap data. First make sure to send a STM_SETIMAGE with a NULL bitmap param
// so that it isn't holding a pointer to memory that we are going to free.
//
SendDlgItemMessage(hDlg, uControl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
ReleaseBitmapData(pBmpData);
//
// Load the new bitmap
//
pBmpData->hDIBitmap = CmLoadBitmap(hInstance, pszBitmap);
//
// Display it
//
DisplayBitmap(hDlg, uControl, phMasterPalette, pBmpData);
}
//+----------------------------------------------------------------------------
//
// Function: ProcesssSigninBitmap
//
// Synopsis: Customize the sign-in bitmap -- this function processes the
// messages for the page in CMAK that handles customizing the
// sign-in dialog bitmap.
//
//
// History: quintinb Created Header 8/6/98
// quintinb Rewrote to use new shared bitmap handling code 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessSigninBitmap(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR* pszBitmap;
NMHDR* pnmHeader = (NMHDR*)lParam;
static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
static BMPDATA BmpData;
static HPALETTE hMasterPalette;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_BITMAPS)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITSPLASH);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
break;
case WM_PALETTEISCHANGING:
break;
case WM_PALETTECHANGED:
if ((wParam != (WPARAM) hDlg) && (BmpData.hDIBitmap))
{
//
// Handle the palette change.
//
CMTRACE2(TEXT("ProcessSigninBitmap handling WM_PALETTECHANGED message, wParam=0x%x, hDlg=0x%x."), wParam, hDlg);
PaletteChanged(&BmpData, hDlg, IDC_DEFAULTBRAND);
}
return TRUE;
break; //lint !e527 Unreachable but please keep in case someone removes the return
case WM_QUERYNEWPALETTE:
QueryNewPalette(&BmpData, hDlg, IDC_DEFAULTBRAND);
return TRUE;
break; //lint !e527 Unreachable but please keep in case someone removes the return
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
//
// Display the Default Bitmap
//
EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),FALSE);
_tcscpy(szDisplay, g_szBrandBmp);
//
// Load and display the default Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, MAKEINTRESOURCE(IDB_CM_DEFAULT), hDlg, IDC_DEFAULTBRAND);
break;
case IDC_RADIO2:
//
// Display a custom Bitmap
//
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
if (TEXT('\0') != g_szBrandBmp[0])
{
pszBitmap = g_szBrandBmp;
}
else if (TEXT('\0') != szDisplay[0])
{
pszBitmap = szDisplay;
}
else
{
break;
}
//
// Load and display the Custom Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, pszBitmap, hDlg, IDC_DEFAULTBRAND);
break;
case IDC_BROWSEBMP1:
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
{
UINT uFilter = IDS_BMPFILTER;
TCHAR* szMask = TEXT("*.bmp");
MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
IDC_EDITSPLASH, TEXT("bmp"), g_szBrandBmp));
}
//
// If we have a custom bitmap name, load and display it
//
if (TEXT('\0') != g_szBrandBmp[0])
{
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szBrandBmp, hDlg, IDC_DEFAULTBRAND);
}
break;
case IDC_EDITSPLASH:
if (HIWORD(wParam) == EN_KILLFOCUS)
{
//
// Notice that we do not do a file check on the text retrieved from the control.
// We do this because, changing focus is an awkward time to do this check and brings
// up the error dialog way to often. We will catch this on Back or Next anyway so let
// it go by here.
//
GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
CheckNameChange(g_szBrandBmp, szTemp);
if (TEXT('\0') != g_szBrandBmp[0])
{
//
// Load and display the custom bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szBrandBmp, hDlg, IDC_DEFAULTBRAND);
}
return TRUE;
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// Get the bitmap string from the CMS and verify that the file
// exists.
//
ZeroMemory(g_szBrandBmp, sizeof(g_szBrandBmp));
ZeroMemory(&BmpData, sizeof(BMPDATA));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryLogo, TEXT(""),
g_szBrandBmp, CELEMS(g_szBrandBmp), g_szCmsFile); //lint !e534
if (TEXT('\0') == g_szBrandBmp[0])
{
//
// Then we use the default CM bitmap, disable edit control
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), FALSE);
//
// Note that we use szDisplay here just in case the use selects a
// bitmap and then switches back to default.
//
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH),
WM_SETTEXT, 0, (LPARAM)GetName(szDisplay)));
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, MAKEINTRESOURCE(IDB_CM_DEFAULT), hDlg, IDC_DEFAULTBRAND);
}
else
{
//
// Use whatever bitmap is specified in the CMS.
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH),
WM_SETTEXT, 0, (LPARAM)GetName(g_szBrandBmp)));
MYVERIFY(FALSE != VerifyFile(hDlg, IDC_EDITSPLASH, g_szBrandBmp, FALSE));
//
// Load the specified Bitmap
//
if (!FileExists(g_szBrandBmp))
{
TCHAR szFile[MAX_PATH+1];
// LOOK UP THE FILE IN THE PROFILE DIRECTORY
GetFileName(g_szBrandBmp, szFile);
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
g_szOsdir, g_szShortServiceName, szFile));
if (!FileExists(szTemp))
{
return FALSE; //GIVE UP;
}
else
{
_tcscpy(g_szBrandBmp, szTemp);
}
}
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szBrandBmp, hDlg, IDC_DEFAULTBRAND);
}
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Make sure that the user typed in a Bitmap name if they selected
// to have a custom bitmap.
//
if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
{
if (-1 == GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!VerifyFile(hDlg, IDC_EDITSPLASH, g_szBrandBmp, TRUE))
{
return 1;
}
else if (TEXT('\0') == g_szBrandBmp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOBMP, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
else
{
//
// Try to Load the bitmap to make sure it is valid
//
TCHAR szTemp1[MAX_PATH+1];
SendDlgItemMessage(hDlg, IDC_DEFAULTBRAND, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); // release pointer held by bmp control before freeing it
ReleaseBitmapData(&BmpData);
BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szBrandBmp);
if (NULL == BmpData.hDIBitmap)
{
//
// Use szTemp1 to hold the format string
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_INVALIDBMP, szTemp1, MAX_PATH));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, szTemp1, g_szBrandBmp));
MessageBox(hDlg, szTemp, g_szAppTitle, MB_OK);
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
}
else
{
g_szBrandBmp[0] = TEXT('\0');
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryLogo,
g_szBrandBmp, g_szCmsFile));
//
// Fall through to cleanup code in RESET handler
//
case PSN_RESET:
//
// Cleanup the Graphics Objects
//
SendDlgItemMessage(hDlg, IDC_DEFAULTBRAND, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); // release pointer held by bmp control before freeing it
ReleaseBitmapData(&BmpData);
if (NULL != hMasterPalette)
{
DeleteObject(hMasterPalette);
hMasterPalette = NULL;
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessPhoneBookBitmap
//
// Synopsis: Customize the Phone Book bitmap -- this function processes the
// messages for the page in CMAK that handles customizing the
// pb dialog bitmap.
//
//
// History: quintinb Created Header 8/6/98
// quintinb Rewrote to use new shared bitmap handling code 8/6/98
// quintinb Renamed from ProcessPage4
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessPhoneBookBitmap(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szFile[MAX_PATH+1];
TCHAR* pszBitmap;
NMHDR* pnmHeader = (NMHDR*)lParam;
static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
static BMPDATA BmpData;
static HPALETTE hMasterPalette;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_BITMAPS)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITSPLASH);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
break;
case WM_PALETTEISCHANGING:
break;
case WM_PALETTECHANGED:
if ((wParam != (WPARAM) hDlg) && (BmpData.hDIBitmap))
{
//
// Handle the palette change.
//
CMTRACE2(TEXT("ProcessSigninBitmap handling WM_PALETTECHANGED message, wParam=0x%x, hDlg=0x%x."), wParam, hDlg);
PaletteChanged(&BmpData, hDlg, IDC_PDEFAULTBRAND);
}
return TRUE;
break; //lint !e527 Unreachable but please keep in case someone removes the return
case WM_QUERYNEWPALETTE:
QueryNewPalette(&BmpData, hDlg, IDC_PDEFAULTBRAND);
return TRUE;
break; //lint !e527 Unreachable but please keep in case someone removes the return
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
//
// Display the Default Bitmap
//
EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),FALSE);
_tcscpy(szDisplay, g_szPhoneBmp);
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, MAKEINTRESOURCE(IDB_CM_PB_DEFAULT), hDlg, IDC_PDEFAULTBRAND);
break;
case IDC_RADIO2:
//
// Display a custom Bitmap
//
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
if (TEXT('\0') != g_szPhoneBmp[0])
{
pszBitmap = g_szPhoneBmp;
}
else if (TEXT('\0') != szDisplay[0])
{
pszBitmap = szDisplay;
}
else
{
//
// Nothing has been specified yet
//
break;
}
//
// Load and Display the Custom Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, pszBitmap, hDlg, IDC_PDEFAULTBRAND);
break;
case IDC_BROWSEBMP2:
EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),TRUE);
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
{
UINT uFilter = IDS_BMPFILTER;
TCHAR* szMask = TEXT("*.bmp");
MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
IDC_EDITSPLASH, TEXT("bmp"), g_szPhoneBmp));
}
//
// If we have a custom bitmap name, load and display it
//
if (TEXT('\0') != g_szPhoneBmp[0])
{
//
// Load and display the Custom Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szPhoneBmp, hDlg, IDC_PDEFAULTBRAND);
}
break;
case IDC_EDITSPLASH:
if (HIWORD(wParam) == EN_KILLFOCUS)
{
//
// Note that we do not check whether we can convert the files to ANSI on Change of Focus
// the reason is because the user would get too many error messages and they would be somewhat
// confusing. Instead we will catch this on Next/Back and ignore it here.
//
GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
CheckNameChange(g_szPhoneBmp, szTemp);
if (TEXT('\0') != g_szPhoneBmp[0])
{
//
// Load and display the Custom Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szPhoneBmp, hDlg, IDC_PDEFAULTBRAND);
}
return TRUE;
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
ZeroMemory(g_szPhoneBmp, sizeof(g_szPhoneBmp));
ZeroMemory(&BmpData, sizeof(BMPDATA));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPbLogo, TEXT(""),
g_szPhoneBmp, CELEMS(g_szPhoneBmp), g_szCmsFile); //lint !e534
if (TEXT('\0') != g_szPhoneBmp[0])
{
//
// We want to Display a Custom Bitmap
//
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH), WM_SETTEXT,
0, (LPARAM)GetName(g_szPhoneBmp)));
MYVERIFY(FALSE != VerifyFile(hDlg, IDC_EDITSPLASH, g_szPhoneBmp, FALSE));
if (!FileExists(g_szPhoneBmp))
{
//
// We couldn't find it the first time so build the path to the profile
// directory and try again.
//
GetFileName(g_szPhoneBmp, szFile);
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
g_szOsdir, g_szShortServiceName, szFile));
if (!FileExists(szTemp))
{
//
// We can't find it so give up.
//
return FALSE;
}
else
{
_tcscpy(g_szPhoneBmp, szTemp);
}
}
//
// Load and display the Custom Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, g_szPhoneBmp, hDlg, IDC_PDEFAULTBRAND);
}
else
{
//
// We want to Display the Default Bitmap
//
MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), FALSE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH), WM_SETTEXT,
0, (LPARAM)GetName(szDisplay)));
//
// Load and display the default Bitmap
//
LoadAndDisplayBitmap (g_hInstance, &BmpData, &hMasterPalette, MAKEINTRESOURCE(IDB_CM_PB_DEFAULT), hDlg, IDC_PDEFAULTBRAND);
}
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// First check to see if the user entered a bmp file if they
// selected that they wanted to display a custom bitmap.
//
if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
{
if (-1 == GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!VerifyFile(hDlg, IDC_EDITSPLASH, g_szPhoneBmp, TRUE))
{
return 1;
}
else if (TEXT('\0') == g_szPhoneBmp[0])
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOBMP, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
else
{
SendDlgItemMessage(hDlg, IDC_PDEFAULTBRAND, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); // release pointer held by bmp control before freeing it
ReleaseBitmapData(&BmpData);
BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szPhoneBmp);
if (NULL == BmpData.hDIBitmap)
{
TCHAR szTemp1[MAX_PATH+1];
//
// Then we have an invalid bitmap file. Inform the user.
// Using szTemp1 as a temp var for the format string.
//
MYVERIFY(0 != LoadString(g_hInstance, IDS_INVALIDBMP, szTemp1, MAX_PATH));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, szTemp1, g_szPhoneBmp));
MessageBox(hDlg, szTemp, g_szAppTitle, MB_OK);
SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
}
else
{
g_szPhoneBmp[0] = TEXT('\0');
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryPbLogo,g_szPhoneBmp,g_szCmsFile));
//
// Fall through to cleanup code in RESET handler
//
case PSN_RESET:
//
// Cleanup the Graphics Objects
//
SendDlgItemMessage(hDlg, IDC_PDEFAULTBRAND, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); // release pointer held by bmp control before freeing it
ReleaseBitmapData(&BmpData);
if (NULL != hMasterPalette)
{
DeleteObject(hMasterPalette);
hMasterPalette = NULL;
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
BOOL UpdateIcon(HWND hDlg,DWORD ctrlID,LPTSTR lpFile,BOOL issmall)
{
HANDLE hRes = NULL;
DWORD nResult;
LPTSTR lpfilename;
TCHAR szTemp[MAX_PATH+1] = TEXT("");
BOOL bReturn = FALSE;
//
// Don't do the ANSI conversion check on the Icons here because this function
// is only called from the Kill Focus windows message. Thus we don't want to
// put up an error message here. It will be caught by the Next/Back messages
// anyway so ignore it here.
//
GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
CheckNameChange(lpFile, szTemp);
lstrcpy(szTemp, lpFile); // we need a temp to hold lpFile so that it can be modified by Search Path as necessary.
nResult = SearchPath(NULL, szTemp, NULL, MAX_PATH, lpFile, &lpfilename);
if (nResult != 0)
{
if (issmall)
{
hRes = LoadImage(NULL, lpFile, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
}
else
{
hRes = LoadImage(NULL, lpFile, IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
}
}
return (NULL != hRes);
}
BOOL VerifyIcon(HWND hDlg,DWORD ctrlID,LPTSTR lpFile,DWORD iconID,BOOL issmall,LPTSTR lpDispFile)
{
TCHAR szTemp2[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
HANDLE hRes;
if ((lpFile[0] == TEXT('\0')) && (lpDispFile[0] != TEXT('\0')))
{
_tcscpy(lpFile,lpDispFile);
}
if (!VerifyFile(hDlg,ctrlID,lpFile,TRUE))
{
return FALSE;
}
else
{
//check for blank entry
if (lpFile[0] == TEXT('\0'))
return TRUE;
if (issmall)
{
hRes = LoadImage(NULL,lpFile,IMAGE_ICON,16,16,LR_LOADFROMFILE);
}
else
{
hRes = LoadImage(NULL,lpFile,IMAGE_ICON,32,32,LR_LOADFROMFILE);
}
if (hRes == 0)
{
MYVERIFY(0 != LoadString(g_hInstance,IDS_INVALIDICO,szMsg,MAX_PATH));
MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2,szMsg,lpFile));
MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
SetFocus(GetDlgItem(hDlg, ctrlID));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return FALSE;
}
else
{
SendDlgItemMessage(hDlg,iconID,STM_SETIMAGE,IMAGE_ICON,(LPARAM) hRes); //lint !e534 STM_SETIMAGE doesn't return error info
}
return TRUE;
}
}
//+----------------------------------------------------------------------------
//
// Function: InitIconEntry
//
// Synopsis: This function takes a resource ID of a key under the Connection Manager
// section and retrives the value and stores it in lpFile. It then sets the text
// in the passed in edit control and verifies that the file exists. Should the
// not exist, then the string will be set to the empty string.
//
// Arguments: HWND hDlg - Window handle of the icon dialog
// LPCTSTR pszKey - the flag string of the Icon to retrieve
// LPTSTR lpFile - String buffer to write the icon path in
// UINT CtrlId - Edit Control that is supposed to receive the icon string
//
// Returns: Nothing
//
// History: quintinb Created Header 8/4/98
//
//+----------------------------------------------------------------------------
void InitIconEntry(HWND hDlg, LPCTSTR pszKey, LPTSTR lpFile, UINT CtrlId)
{
//
// The following call to GetPrivateProfileString could return a blank string, thus don't
// use the MYVERIFY macro on it.
//
ZeroMemory(lpFile, sizeof(lpFile));
GetPrivateProfileString(c_pszCmSection, pszKey, TEXT(""), lpFile,
MAX_PATH, g_szCmsFile); //lint !e534
//
// Both of the following functions will correctly handle a blank string.
//
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, CtrlId), WM_SETTEXT, 0,
(LPARAM)GetName(lpFile)));
MYVERIFY(FALSE != VerifyFile(hDlg, CtrlId, lpFile, FALSE));
}
//+----------------------------------------------------------------------------
//
// Function: RefreshIconDisplay
//
// Synopsis: This fucntion is used to refresh the icons shown on the icons page.
// It takes a path to an Icon and tries to load it. If the load fails
// or if the boolean SetDefault is set, then it loads the default icon
// specified by the Instance handle and the integer resource ID (iDefault).
// The icon is displayed to the dwControlID passed into the function.
//
// Arguments: HWND hDlg -
// HINSTANCE hInstance -
// LPTSTR szIconFile -
// int iDefault -
// int xSize -
// int ySize -
// DWORD dwControlID -
// BOOL SetDefault -
//
// Returns: Nothing
//
// History: quintinb Created Header 8/4/98
// quintinb Changed Default setting to take a resource ID instead of
// a string. Thus we won't have to ship the icon files.
//
//+----------------------------------------------------------------------------
void RefreshIconDisplay(HWND hDlg, HINSTANCE hInstance, LPTSTR szIconFile, int iDefault, int xSize, int ySize, DWORD dwControlID, BOOL SetDefault)
{
HANDLE hRes;
if (SetDefault)
{
hRes = NULL;
}
else
{
hRes = LoadImage(NULL, szIconFile, IMAGE_ICON, xSize, ySize, LR_LOADFROMFILE);
}
if (NULL == hRes)
{
//
// IF ICON IS NOT VALID OR WE WERE ASKED FOR THE DEFAULT, SO LOAD THE DEFAULT
//
hRes = LoadImage(hInstance, MAKEINTRESOURCE(iDefault), IMAGE_ICON, xSize, ySize,
LR_DEFAULTCOLOR);
}
if (NULL != hRes)
{
SendDlgItemMessage(hDlg, dwControlID, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hRes); //lint !e534 STM_SETIMAGE doesn't return error info
}
}
//+----------------------------------------------------------------------------
//
// Function: EnableCustomIconControls
//
// Synopsis: Function to enable or disable all of the controls associated with
// the custom icons. If the bEnabled value is TRUE the controls are
// enabled, otherwise the controls are disabled.
//
// Arguments: WND hDlg - window handle of the icon dialog
// BOOL bEnabled - whether the controls are enabled or disabled
//
// History: quintinb Created 11/12/99
//
//+----------------------------------------------------------------------------
void EnableCustomIconControls(HWND hDlg, BOOL bEnabled)
{
EnableWindow(GetDlgItem(hDlg, IDC_EDITLARGE), bEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_LABEL1), bEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_EDITSMALL), bEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_LABEL2), bEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_EDITTRAY), bEnabled);
EnableWindow(GetDlgItem(hDlg, IDC_LABEL3), bEnabled);
//
// Comment about using defaults for unspecified icons
//
EnableWindow(GetDlgItem(hDlg,IDC_LABEL4), bEnabled);
}
//+----------------------------------------------------------------------------
//
// Function: ProcessIcons
//
// Synopsis: Function that processes messages for the page in CMAK that allows
// the user to add custom icons to their profile.
//
// Arguments: WND hDlg - window handle of the dialog
// UINT message - message ID
// WPARAM wParam - wParam of the message
// LPARAM lParam - lParma of the message
//
//
// History: quintinb Created Header 12/5/97
// quintinb modified to handle both w16 and w32 dialogs
// quintinb added fix for 35622, custom large icon not displaying on page load
// quintinb removed 16 bit support 7-8-98
// quintinb Renamed from ProcessPage5 8-6-98
// quintinb Added EnableCustomIconControls and changed browse button
// behavior for consistency 367112 11-12-99
//
//+----------------------------------------------------------------------------
// Customize icons
INT_PTR APIENTRY ProcessIcons(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
static TCHAR szDispLargeIco[MAX_PATH+1];
static TCHAR szDispSmallIco[MAX_PATH+1];
static TCHAR szDispTrayIco[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ICONS)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITLARGE);
SetDefaultGUIFont(hDlg,message,IDC_EDITSMALL);
SetDefaultGUIFont(hDlg,message,IDC_EDITTRAY);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDITLARGE));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
EnableCustomIconControls (hDlg, FALSE);
RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, TRUE);
RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, TRUE);
RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, TRUE);
_tcscpy(szDispTrayIco,g_szTrayIco);
_tcscpy(szDispLargeIco,g_szLargeIco);
_tcscpy(szDispSmallIco,g_szSmallIco);
break;
case IDC_RADIO2:
EnableCustomIconControls (hDlg, TRUE);
if (!VerifyIcon(hDlg,IDC_EDITLARGE,g_szLargeIco,IDC_ICONLARGE,FALSE,szDispLargeIco))
{
return 1;
}
if (!VerifyIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,IDC_ICONSMALL,TRUE,szDispSmallIco))
{
return 1;
}
if (!VerifyIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,IDC_ICONTRAY,TRUE,szDispTrayIco))
{
return 1;
}
break;
case IDC_EDITLARGE:
if (HIWORD(wParam) == EN_KILLFOCUS)
{
BOOL bIconUpdated = UpdateIcon(hDlg, IDC_EDITLARGE, g_szLargeIco, FALSE);
//
// If icon wasn't updated than load the defaults
//
RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, !bIconUpdated);
return TRUE;
}
break;
case IDC_EDITSMALL:
if (HIWORD(wParam) == EN_KILLFOCUS)
{
BOOL bIconUpdated = UpdateIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,TRUE);
//
// If icon wasn't updated than load the defaults
//
RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, !bIconUpdated);
return TRUE;
}
break;
case IDC_EDITTRAY:
if (HIWORD(wParam) == EN_KILLFOCUS)
{
BOOL bIconUpdated = UpdateIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,TRUE);
//
// If icon wasn't updated than load the defaults
//
RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, !bIconUpdated);
return TRUE;
}
break;
case IDC_BROWSE1:
{
UINT uFilter = IDS_ICOFILTER;
TCHAR* szMask = TEXT("*.ico");
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableCustomIconControls (hDlg, TRUE);
if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITLARGE, TEXT("ico"), g_szLargeIco))
{
RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, FALSE);
}
}
break;
case IDC_BROWSE2:
{
UINT uFilter = IDS_ICOFILTER;
TCHAR* szMask = TEXT("*.ico");
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableCustomIconControls (hDlg, TRUE);
if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITSMALL, TEXT("ico"), g_szSmallIco))
{
RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, FALSE);
}
}
break;
case IDC_BROWSE3:
{
UINT uFilter = IDS_ICOFILTER;
TCHAR* szMask = TEXT("*.ico");
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableCustomIconControls (hDlg, TRUE);
if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITTRAY, TEXT("ico"), g_szTrayIco))
{
RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, FALSE);
}
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
InitIconEntry(hDlg, c_pszCmEntryBigIcon, g_szLargeIco, IDC_EDITLARGE);
InitIconEntry(hDlg, c_pszCmEntrySmallIcon, g_szSmallIco, IDC_EDITSMALL);
InitIconEntry(hDlg, c_pszCmEntryTrayIcon, g_szTrayIco, IDC_EDITTRAY);
if ((g_szTrayIco[0] == TEXT('\0'))&&(g_szLargeIco[0] == TEXT('\0'))&&(g_szSmallIco[0] == TEXT('\0')))
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO1));
EnableCustomIconControls (hDlg, FALSE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITLARGE), WM_SETTEXT, 0, (LPARAM)GetName(szDispLargeIco)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSMALL), WM_SETTEXT, 0, (LPARAM)GetName(szDispSmallIco)));
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITTRAY), WM_SETTEXT, 0, (LPARAM)GetName(szDispTrayIco)));
}
else
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableCustomIconControls (hDlg, TRUE);
}
RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, FALSE);
RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, FALSE);
RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, FALSE);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
if (IsDlgButtonChecked(hDlg, IDC_RADIO1)!=BST_CHECKED)
{
if (!VerifyIcon(hDlg,IDC_EDITLARGE,g_szLargeIco,IDC_ICONLARGE,FALSE,TEXT("")))
{
return 1;
}
if (!VerifyIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,IDC_ICONSMALL,TRUE,TEXT("")))
{
return 1;
}
if (!VerifyIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,IDC_ICONTRAY,TRUE,TEXT("")))
{
return 1;
}
}
else
{
g_szTrayIco[0] = TEXT('\0');
g_szLargeIco[0] = TEXT('\0');
g_szSmallIco[0] = TEXT('\0');
}
// USE ICON IN CM AS ICON FOR DESKTOP IF NOT LARGE ICON SPECIFIED
if (TEXT('\0') != g_szLargeIco[0])
{
// SPECIFY ICON NAME FOR THE DESKTOP
GetFileName(g_szLargeIco,szTemp);
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopIcon, szTemp, g_szInfFile);
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryBigIcon, g_szLargeIco, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTrayIcon, g_szTrayIco, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntrySmallIcon, g_szSmallIco, g_szCmsFile));
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessPhoneBook
//
// Synopsis: Setup the phone book
//
//
// History: quintinb hid pbr browse button and edit control. Rewrote pbr/pbk logic for bug
// fix 14188 on 9-9-97
// quintinb added VerifyFileFormat check on .pbk file for bug fix 28416
// quintinb (11-18-97 29954) removed hidden pbr button and edit control from the dialog. Removed
// old verification code. Updated code to remove references to IDC_EDITREGION.
// quintinb (7-2-98) removed verifyfileformat call mentioned above because cm16 was pulled
// quintinb (8-6-98) Renamed from ProcessPage6
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessPhoneBook(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szMsg[2*MAX_PATH+1];
TCHAR* pzTmp;
HANDLE hFile = INVALID_HANDLE_VALUE;
static TCHAR szMorePhone[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PHONEBK)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITPHONE);
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
SendDlgItemMessage(hDlg, IDC_EDIT1, EM_SETLIMITTEXT, (WPARAM)MAX_PATH, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BROWSE1:
{
UINT uFilter = IDS_PBKFILTER;
TCHAR* szMask = TEXT("*.pbk");
MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
IDC_EDITPHONE, c_pszPbk, g_szPhonebk));
}
break;
case IDC_CHECK1:
g_bUpdatePhonebook = IsDlgButtonChecked(hDlg,IDC_CHECK1);
if (g_bUpdatePhonebook)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszOne, g_szInfFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszZero, g_szInfFile));
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// The following two calls to GetPrivateProfileString could return blank
// strings, thus we won't check the return with the MYVERIFY macro.
//
ZeroMemory(szMorePhone, sizeof(szMorePhone));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPbMessage, TEXT(""),
szMorePhone, CELEMS(szMorePhone), g_szCmsFile); //lint !e534
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0,
(LPARAM)szMorePhone));
ZeroMemory(g_szPhonebk, sizeof(g_szPhonebk));
GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, TEXT(""),
g_szPhonebk, CELEMS(g_szPhonebk), g_szCmsFile); //lint !e534
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITPHONE), WM_SETTEXT, 0,
(LPARAM)GetName(g_szPhonebk)));
//
// The following call will handle a blank g_szPhonebk by returning FALSE and setting
// the control on the dialog to blank. Don't use MYVERIFY.
//
VerifyPhonebk(hDlg, IDC_EDITPHONE, g_szPhonebk); //lint !e534
MYVERIFY(0 != GetPrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook,
c_pszOne, szTemp, CELEMS(szTemp), g_szInfFile));
if (TEXT('1') == szTemp[0])
{
g_bUpdatePhonebook = TRUE;
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
}
else
{
g_bUpdatePhonebook = FALSE;
MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, FALSE));
}
break;
case PSN_WIZBACK:
// fall through for further processing
case PSN_WIZNEXT:
//
// quintinb, 9-9-97 for bug fix 14188
// cases: use browse button: both up to date, shortname(g_szPhonebk) == szTemp
// type unc into edit control: szTemp up to date, g_szPhonebk = szTemp must be done
// type filename into edit control: szTemp up to date, g_szPhonebk = getcurrentdir + \\ + szTemp must be done
// unc left over from previous, both same
//
//
// get text in the edit control and put in szTemp
//
if (-1 == GetTextFromControl(hDlg, IDC_EDITPHONE, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// first get szTemp and g_szPhonebk consistent
//
if (szTemp[0] != TEXT('\0'))
{
//
// if in here then we know that we have some text to work with
// first test if the two strings are exactly equal or the shortname of g_szPhonebk
// equals szTemp
//
if (0 != _tcscmp(szTemp, g_szPhonebk))
{
if (0 != _tcscmp(szTemp, GetName(g_szPhonebk)))
{
//
// if not then g_szPhonebk and szTemp are out of sync, must update g_szPhonebk
// szTemp contains a backslash so it is probably a full path
//
if ( _tcsstr(szTemp, TEXT("\\")) )
{
// probably contains a unc
_tcscpy(g_szPhonebk, szTemp);
}
else
{
// use GetFullPathName to return a name
MYVERIFY(0 != GetFullPathName(szTemp, MAX_PATH, g_szPhonebk, &pzTmp));
}
}
}
//
// Okay, check that we can open the file now. We need
// to change the current dir to the cmak dir since
// g_szPhonebk can be a relative path from a CMS file
//
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH+1, szTemp));
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
hFile = CreateFile(g_szPhonebk,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//
// Restore the cur dir
//
MYVERIFY(0 != SetCurrentDirectory(szTemp));
if (INVALID_HANDLE_VALUE == hFile)
{
// then we have an error and have exhausted our possibilities
//
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_BADOUTEXE, MB_OK));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
MYVERIFY(0 != CloseHandle(hFile));
//
// if we got here then everything is sync-ed, make sure that the file is a pbk file
//
pzTmp = g_szPhonebk + _tcslen(g_szPhonebk) - _tcslen(c_pszPbk);
if (_tcsicmp(pzTmp, c_pszPbk) != 0)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOTPBK, MB_OK));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// now update the pbr file entry
//
_tcscpy(g_szRegion, g_szPhonebk);
pzTmp = g_szRegion + _tcslen(g_szPhonebk) - _tcslen(c_pszPbk);
_tcscpy(pzTmp, TEXT("pbr"));
// removed for 29954
//SendMessage(GetDlgItem(hDlg, IDC_EDITREGION), WM_SETTEXT, 0, (LPARAM)GetName(g_szRegion));
//
// Now open the pbr file to see that it exists. We need
// to change the current dir to the cmak dir since
// g_szPhonebk can be a relative path from a CMS file.
//
MYVERIFY(0 != GetCurrentDirectory(MAX_PATH+1, szTemp));
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
hFile = CreateFile(g_szRegion,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//
// Restore the current directory
//
MYVERIFY(0 != SetCurrentDirectory(szTemp));
if (INVALID_HANDLE_VALUE == hFile)
{
//
// then we can't find the pbr file
//
MYVERIFY(0 != LoadString(g_hInstance,IDS_NEEDSPBR,szTemp,MAX_PATH));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, GetName(g_szRegion), g_szPhonebk, GetName(g_szRegion)));
MessageBox(hDlg, szMsg, g_szAppTitle, MB_OK);
SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
MYVERIFY(0 != CloseHandle(hFile));
}
else
{
//
// just in case user wants to clear out the phonebk edit control
//
g_szPhonebk[0] = TEXT('\0');
g_szRegion[0] = TEXT('\0');
}
// end bugfix for 14188
if (g_bUpdatePhonebook)
{
GetFileName(g_szPhonebk, szTemp);
if (FALSE == IsFile8dot3(szTemp))
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADPBNAME, szTemp);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
// end of changes for 28416
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
CmStrTrim(szTemp);
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
_tcscpy(szMorePhone,szTemp);
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPbMessage, szMorePhone, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, g_szPhonebk, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, g_szRegion, g_szCmsFile));
if (pnmHeader && (PSN_WIZBACK == pnmHeader->code))
{
if (g_bUseTunneling)
{
//
// If we are going back, skip the Pre-shared key page if
// no DUN entries have Preshared key enabled.
//
// Note: g_bPresharedKeyNeeded should be current here, no need
// to call DoesSomeVPNsettingUsePresharedKey()
//
if (!g_bPresharedKeyNeeded)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_VPN_ENTRIES));
}
}
else
{
//
// If we are going back, skip the VPN entries dialog if we don't have any tunneling enabled.
//
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_TUNNELING));
}
}
//
// If we are going forward, skip the phonebook update page unless we are doing the PB download
//
if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bUpdatePhonebook)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_DUN_ENTRIES));
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessPhoneBookUpdate
//
// Synopsis: Specify Phone Book Files and Updates
//
//
// History: Created Header 8/6/98
// quintinb Renamed from ProcessPage6A 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessPhoneBookUpdate(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
int j, iLen;
LPTSTR pUrl,pch;
BOOL showerr;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PHONEBK)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
SetDefaultGUIFont(hDlg,message,IDC_EDITURL);
switch (message)
{
case WM_INITDIALOG:
SendDlgItemMessage(hDlg, IDC_EDITURL, EM_SETLIMITTEXT, (WPARAM)(MAX_PATH - 50), (LPARAM)0);//lint !e534 EM_SETLIMITTEXT doesn't return anything useful
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// The following two calls to GetPrivateProfileString could return an empty
// string. We shouldn't use MYVERIFY on the return code.
//
ZeroMemory(g_szPhoneName, sizeof(g_szPhoneName));
ZeroMemory(g_szUrl,sizeof(g_szUrl));
GetPrivateProfileString(c_pszCmakStatus, c_pszPhoneName, TEXT(""),
g_szPhoneName, CELEMS(g_szPhoneName), g_szInfFile); //lint !e534
GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), g_szUrl,
CELEMS(g_szUrl), g_szCmsFile); //lint !e534
// skip past initial http://
if (*g_szUrl)
{
pUrl = _tcsstr(g_szUrl, c_pszCpsUrl);
if (pUrl)
{
*pUrl = 0; //chop off dll filename
}
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITURL), WM_SETTEXT, 0, (LPARAM)&g_szUrl[7]));
}
else
{
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITURL), WM_SETTEXT, 0, (LPARAM)TEXT("")));
}
if (*g_szPhonebk)
{
GetBaseName(g_szPhonebk,szTemp);
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
EnableWindow(GetDlgItem(hDlg,IDC_EDIT1),FALSE);
}
else
{
EnableWindow(GetDlgItem(hDlg, IDC_EDIT1), TRUE);
if (*g_szPhoneName)
{
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) g_szPhoneName));
}
else
{
MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) TEXT("")));
}
}
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
showerr = (pnmHeader && (PSN_WIZNEXT == pnmHeader->code));
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, g_szPhoneName, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
// if ((g_szPhoneName[0] == TEXT('\0')) && (g_pHeadMerge == NULL) && showerr) - 20094
if ((g_szPhoneName[0] == TEXT('\0')) && showerr)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPHONENAME, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
iLen = lstrlen(g_szBadFilenameChars);
pch = g_szPhoneName;
while(*pch != _T('\0'))
{
for (j = 0; j < iLen; ++j)
{
if ((*pch == g_szBadFilenameChars[j]) && showerr)
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PHONENAMEERR, g_szBadFilenameChars);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
pch = CharNext(pch);
}
//
// Note that 8.3 means 8 bytes not 8 Characters. Thus we have a limit of 4 DBCS
// characters.
//
#ifdef UNICODE
LPSTR pszAnsiPhoneName;
pszAnsiPhoneName = WzToSzWithAlloc(g_szPhoneName);
if ((lstrlenA(pszAnsiPhoneName) > 8) && showerr)
#else
if ((strlen(g_szPhoneName) > 8) && showerr)
#endif
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PHONENAMEERR, g_szBadFilenameChars);
if (pszMsg)
{
MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
CmFree(pszMsg);
}
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
#ifdef UNICODE
CmFree(pszAnsiPhoneName);
#endif
if (-1 == GetTextFromControl(hDlg, IDC_EDITURL, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDITURL));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (szTemp[0] != TEXT('\0'))
{
MYVERIFY(CELEMS(g_szUrl) > (UINT)wsprintf(g_szUrl, TEXT("http://%s%s"), szTemp, c_pszCpsUrl));
}
else
{
g_szUrl[0] = TEXT('\0');
}
if ((g_szUrl[0] == TEXT('\0')) && showerr)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOURL, MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDITURL));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszPhoneName, g_szPhoneName, g_szInfFile));
if (TEXT('\0') != g_szUrl[0])
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,c_pszCmEntryIspUrl,g_szUrl,g_szCmsFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,c_pszCmEntryIspUrl,TEXT(""),g_szCmsFile));
}
// the Next button was pressed or the back button was pressed
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: RemoveReferencesFromCMS
//
// Synopsis: This function searches for any previous References line in
// the ISP section of the cms file. If it finds a References
// line, then it parses it to find what other profiles are
// mentioned in the CMS. Then it will search for and remove
// any of the following lines in the ISP section that correspond
// to these references:
// CMSFile&test2=test3\test2.cms
// FilterA&test2=NosurchargeSignon
// FilterB&test2=SurchargeSignon
//
// note the function removes the reference line itself too.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb created for bug fix 10537 8/28/97
//
//+----------------------------------------------------------------------------
void RemoveReferencesFromCMS()
{
TCHAR szKey[MAX_PATH+1];
TCHAR szReferences[MAX_PATH+1];
TCHAR* pszToken;
DWORD dwNumChars;
dwNumChars = GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, TEXT(""),
szReferences,MAX_PATH, g_szCmsFile);
if ((dwNumChars >0) && (TEXT('\0') != szReferences[0]))
{
// I have references, so we must parse them out and delete them
pszToken = _tcstok( szReferences, TEXT(" "));
while( pszToken != NULL )
{
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
c_pszCmEntryIspCmsFile, pszToken));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
g_szCmsFile));
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
c_pszCmEntryIspFilterA, pszToken));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
g_szCmsFile));
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
c_pszCmEntryIspFilterB, pszToken));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
g_szCmsFile));
pszToken = _tcstok( NULL, TEXT(" ") );
}
// after deleting the individual keys, must delete the references line itself
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, NULL, g_szCmsFile));
}
}
//+----------------------------------------------------------------------------
//
// Function: RefreshDualingListBoxes
//
// Synopsis: This function refreshes two listboxes from the given two linked
// lists. The destination listbox is filled from the destination
// linked list and then the source listbox is filled with all of the
// items in the source linked list that don't appear in the destination
// linked list and that aren't the name of the current profile to edit.
// Thus you effectively have one list where the items either show up
// in the source listbox or the destination listbox. Please note that
// there is one exception with the merged profile lists that this
// code was created for (items can exist in the merged list that we
// don't have profile source from, see the Delete/Remove code in
// ProcessMergedProfiles for more details). Also note that we
// enable/disable the corresponding Add and Remove buttons depending
// on the state of the lists.
//
//
// Arguments: HWND hDlg - window handle of the dialog containing all of the controls
// UINT uSourceListControlId - control id of the source listbox
// UINT uDestListControlId - control id of the dest listbox
// ListBxList* pSourceList - linked list to fill the source listbox from
// ListBxList* pDestList - linked list to fill the dest listbox from
// LPCTSTR pszShortName - short service name of the current profile
// UINT uAddCtrlId - control id of the Add button (add from source to dest)
// UINT uRemoveCtrlId - control id of the remove button (remove from dest to source)
//
// Returns: BOOL - TRUE if successful
//
// History: quintinb created 03/09/00
//
//+----------------------------------------------------------------------------
BOOL RefreshDualingListBoxes(HWND hDlg, UINT uSourceListControlId, UINT uDestListControlId, ListBxList* pSourceList, ListBxList* pDestList, LPCTSTR pszShortName, UINT uAddCtrlId, UINT uRemoveCtrlId)
{
if ((NULL == hDlg) || (0 == uSourceListControlId) || (0 == uDestListControlId))
{
CMASSERTMSG(FALSE, TEXT("RefreshDualingListBoxes -- Invalid argument passed"));
return FALSE;
}
//
// Reset both of the listboxes
//
LRESULT lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
MYDBGASSERT(LB_ERR != lResult);
lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
MYDBGASSERT(LB_ERR != lResult);
//
// Add the destination items to the destination listbox
//
ListBxList* pCurrent = pDestList;
while (pCurrent)
{
lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_ADDSTRING, (WPARAM)0, (LPARAM)pCurrent->szName);
MYDBGASSERT(LB_ERR != lResult);
pCurrent = pCurrent->next;
}
//
// Add the source items to the source listbox, making sure to filter out items that are already
// in the destination list
//
pCurrent = pSourceList;
while (pCurrent)
{
if ((FALSE == FindListItemByName(pCurrent->szName, pDestList, NULL)) && (0 != lstrcmpi(pCurrent->szName, pszShortName)))
{
lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_ADDSTRING, (WPARAM)0, (LPARAM)pCurrent->szName);
MYDBGASSERT(LB_ERR != lResult);
}
pCurrent = pCurrent->next;
}
//
// Now that we have refreshed the list, we need to update the button and selection status.
// If the source list is empty, then we cannot do any Adds. On the other
// hand if the dest list is empty, then we cannot do any deletes.
//
HWND hAddControl = GetDlgItem(hDlg, uAddCtrlId);
HWND hRemoveControl = GetDlgItem(hDlg, uRemoveCtrlId);
HWND hCurrentFocus = GetFocus();
lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_GETCOUNT, 0, (LPARAM)0);
BOOL bListNotEmpty = ((LB_ERR != lResult) && (0 != lResult));
EnableWindow(hAddControl, bListNotEmpty);
if (bListNotEmpty)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, uSourceListControlId, LB_SETCURSEL, 0, (LPARAM)0));
}
//
// Now check the destination list and the Remove button
//
lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_GETCOUNT, 0, (LPARAM)0);
bListNotEmpty = ((LB_ERR != lResult) && (0 != lResult));
EnableWindow(hRemoveControl, bListNotEmpty);
if (bListNotEmpty)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, uDestListControlId, LB_SETCURSEL, 0, (LPARAM)0));
}
//
// Figure out if we need to shift the focus because we just disabled the control that had it.
//
if (hCurrentFocus && (FALSE == IsWindowEnabled(hCurrentFocus)))
{
if ((hAddControl == hCurrentFocus) && IsWindowEnabled(hRemoveControl))
{
SendMessage(hDlg, DM_SETDEFID, uRemoveCtrlId, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
SetFocus(hRemoveControl);
}
else if ((hRemoveControl == hCurrentFocus) && IsWindowEnabled(hAddControl))
{
SendMessage(hDlg, DM_SETDEFID, uAddCtrlId, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
SetFocus(hAddControl);
}
else
{
SetFocus(GetDlgItem(hDlg, uSourceListControlId));
}
}
return TRUE;
}
void OnProcessMergedProfilesAdd(HWND hDlg)
{
TCHAR szTemp[MAX_PATH+1];
LRESULT lResult;
//
// Get the current selection from the listbox containing the items
// to merge.
//
lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
if (lResult != LB_ERR)
{
lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT,
(WPARAM)lResult, (LPARAM)szTemp);
if (lResult != LB_ERR)
{
MYVERIFY(FALSE != createListBxRecord(&g_pHeadMerge, &g_pTailMerge, NULL, 0, szTemp));
MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
}
}
}
void OnProcessMergedProfilesRemove(HWND hDlg)
{
TCHAR szTemp[MAX_PATH+1];
LRESULT lResult;
//
// Get the listbox selection from the already merged in list
//
lResult = SendDlgItemMessage(hDlg, IDC_LIST2, LB_GETCURSEL, 0, (LPARAM)0);
if (LB_ERR == lResult)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
}
else
{
//
// Get the name of the profile to remove from the merge list
//
lResult = SendDlgItemMessage(hDlg, IDC_LIST2, LB_GETTEXT, (WPARAM)lResult, (LPARAM)szTemp);
if (LB_ERR != lResult)
{
//
// Check to see if this is an item in the Profile list. If not, the user
// will not be able to add it back.
//
int iReturnValue = IDYES;
if (FALSE == FindListItemByName(szTemp, g_pHeadProfile, NULL)) // NULL because we don't need a pointer to the list item returned
{
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_NOTINPROFILELIST, szTemp, szTemp, szTemp);
if (pszMsg)
{
iReturnValue = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
CmFree(pszMsg);
}
}
if (IDYES == iReturnValue)
{
//
// Delete it from the merged profile linked list
//
DeleteListBxRecord(&g_pHeadMerge, &g_pTailMerge, szTemp);
//
// Remove it from the UI
//
MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
}
}
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessMergedProfiles
//
// Synopsis: Merge Profiles
//
// History: quintinb Created Header and renamed from ProcessPage6B 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessMergedProfiles(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MERGE)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LIST1);
SetDefaultGUIFont(hDlg,message,IDC_LIST2);
switch (message)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
OnProcessMergedProfilesAdd(hDlg);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON2: //remove
OnProcessMergedProfilesRemove(hDlg);
return TRUE;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_LIST1:
if (LBN_DBLCLK == HIWORD(wParam))
{
OnProcessMergedProfilesAdd(hDlg);
return TRUE;
}
break;
case IDC_LIST2:
if (LBN_DBLCLK == HIWORD(wParam))
{
OnProcessMergedProfilesRemove(hDlg);
return TRUE;
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// First lets setup the list of profiles that are actually merged into the
// profile. First step is to read in the merged profile list from the profile.
//
ReadMergeList();
//
// Now delete the merged profile list and any filter/cms references from the profile.
//
RemoveReferencesFromCMS();
//
// Refresh the two list boxes
//
MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
WriteMergeList();
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
BOOL CreateMergedProfile()
{
ListBxList * LoopPtr;
TCHAR szReferences[MAX_PATH+1];
LPTSTR pszName;
TCHAR szEntry[MAX_PATH+1];
TCHAR szFile[MAX_PATH+1];
TCHAR szKey[MAX_PATH+1];
TCHAR szTemp[MAX_PATH+1];
TCHAR szDest[MAX_PATH+1];
szReferences[0] = TEXT('\0');
if (g_pHeadMerge == NULL)
{
return TRUE;
}
LoopPtr = g_pHeadMerge;
while( LoopPtr != NULL)
{
pszName = LoopPtr->szName;
_tcscat(szReferences, pszName);
_tcscat(szReferences, TEXT(" "));
MYDBGASSERT(_tcslen(szReferences) <= CELEMS(szReferences));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cms"), g_szOsdir, pszName, pszName));
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s.cms"), g_szOutdir, pszName));
// COPY CMS FILE
//
// First check to see if the profile exists in profile directory
//
if (!FileExists(szTemp))
{
//
// Couldn't open it in the profile dir, lets try in the temp dir
//
if (!FileExists(szDest))
{
FileAccessErr(NULL, szDest);
return FALSE;
}
}
else
{
if (!CopyFileWrapper(szTemp, szDest, FALSE))
{
return FALSE;
}
}
MYVERIFY(0 != SetFileAttributes(szDest,FILE_ATTRIBUTE_NORMAL));
MYVERIFY(FALSE != MoveCmsFile(szDest, g_szShortServiceName));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s.cms"), pszName));
MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs,&g_pTailRefs,(void *)NULL,0,szTemp));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"), g_szShortServiceName, pszName));
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspCmsFile, pszName));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,szKey,szTemp,g_szCmsFile));
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspFilterA,
pszName));
// only write if it doesn't exist
//
// The following call to GetPrivateProfileString could return a blank string, thus we don't
// use the MYVERIFY macro on it.
//
ZeroMemory(szTemp, sizeof(szTemp));
GetPrivateProfileString(c_pszCmSectionIsp, szKey, TEXT(""), szTemp, CELEMS(szTemp),
g_szCmsFile); //lint !e534
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, TEXT("NosurchargeSignon"),
g_szCmsFile));
}
MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspFilterB,
pszName));
//
// The following call to GetPrivateProfileString could return a blank string, thus we shouldn't
// check its return code with MYVERIFY.
//
GetPrivateProfileString(c_pszCmSectionIsp, szKey, TEXT(""), szTemp, CELEMS(szTemp),
g_szCmsFile); //lint !e534
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, TEXT("SurchargeSignon"),
g_szCmsFile));
}
MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
// COPY PHONEBOOK
GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, TEXT(""), szEntry,
CELEMS(szEntry), szDest); //lint !e534 could return EMPTY string
GetFileName(szEntry,szFile);
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szOutdir, szFile));
if (CopyFile(szEntry,szTemp,FALSE))
{
MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs, &g_pTailRefs, (void *)NULL, 0, szFile));
MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
}
//
// DO NOT REPORT AN ERROR IF COULDN'T FIND PHONEBOOK, IT IS OPTIONAL
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szShortServiceName, szFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, szTemp,
szDest));
// COPY REGIONS
GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, TEXT(""), szEntry,
CELEMS(szEntry), szDest); //lint !e534
GetFileName(szEntry,szFile);
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szOutdir, szFile));
if (CopyFile(szEntry,szTemp,FALSE))
{
MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs,&g_pTailRefs,(void *)NULL,0,szFile));
MYVERIFY(0 != SetFileAttributes(szTemp,FILE_ATTRIBUTE_NORMAL));
}
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szShortServiceName, szFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, szTemp, szDest));
LoopPtr = LoopPtr->next;
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, szReferences, g_szCmsFile));
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessCustomHelp
//
// Synopsis: Set up windows help
//
//
// History: quintinb Created Header and renamed from ProcessPage7 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessCustomHelp(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CMHELP)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITHELP);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_RADIO1:
EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),FALSE);
_tcscpy(szDisplay,g_szHelp);
break;
case IDC_RADIO2:
EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
if (!(*g_szHelp) && (*szDisplay))
{
_tcscpy(g_szHelp,szDisplay);
}
break;
case IDC_BROWSE1:
{
EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
UINT uFilter = IDS_HLPFILTER;
TCHAR* szMask = TEXT("*.hlp");
MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
IDC_EDITHELP, TEXT("hlp"), g_szHelp));
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// The following call to GetPrivateProfileString could return an empty string
// thus we shouldn't check the return code with MYVERIFY.
//
ZeroMemory(g_szHelp, sizeof(g_szHelp));
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryHelpFile, TEXT(""),
g_szHelp, CELEMS(g_szHelp), g_szCmsFile); //lint !e534
if (TEXT('\0') == g_szHelp[0])
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO1));
EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),FALSE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITHELP), WM_SETTEXT, 0, (LPARAM)GetName(szDisplay)));
}
else
{
MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITHELP), WM_SETTEXT, 0, (LPARAM)GetName(g_szHelp)));
MYVERIFY(FALSE != VerifyFile(hDlg,IDC_EDITHELP,g_szHelp,FALSE));
}
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
// the Next button was pressed
if (IsDlgButtonChecked(hDlg, IDC_RADIO2)==BST_CHECKED)
{
if (-1 == GetTextFromControl(hDlg, IDC_EDITHELP, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!VerifyFile(hDlg,IDC_EDITHELP,g_szHelp,TRUE))
{
if (g_szHelp[0] != TEXT('\0'))
{
return 1;
}
}
if (g_szHelp[0] == TEXT('\0'))
{
MYVERIFY(IDOK == ShowMessage(hDlg,IDS_NOHELP,MB_OK));
SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
else
{
g_szHelp[0] = TEXT('\0');
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryHelpFile, g_szHelp, g_szCmsFile));
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessLicense
//
// Synopsis: Add a license agreement
//
//
// History: quintinb Created Header and renamed from ProcessPage7A 8/6/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessLicense(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_LICENSE)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BROWSE1:
{
UINT uFilter = IDS_TXTFILTER;
TCHAR* szMask = TEXT("*.txt");
MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDIT1, TEXT("txt"),
g_szLicense));
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
//
// The following call to GetPrivateProfileString could return an empty string,
// thus we shouldn't use MYVERIFY on it.
//
ZeroMemory(g_szLicense, sizeof(g_szLicense));
GetPrivateProfileString(c_pszCmakStatus, c_pszLicenseFile, TEXT(""), g_szLicense,
CELEMS(g_szLicense), g_szInfFile); //lint !e534
MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)GetName(g_szLicense)));
MYVERIFY(FALSE != VerifyFile(hDlg,IDC_EDIT1,g_szLicense,FALSE));
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
// the Next button was pressed
if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
{
SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
if (!VerifyFile(hDlg,IDC_EDIT1,g_szLicense,TRUE))
{
if (g_szLicense[0] != TEXT('\0'))
{
return 1;
}
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszLicenseFile,g_szLicense,g_szInfFile));
#ifdef _WIN64
//
// If we are going back, skip the Include CM binaries page if this is IA64
//
if (pnmHeader && (PSN_WIZBACK == pnmHeader->code))
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_SUPPORT_INFO));
}
#endif
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: MultiSelectOpenFileName
//
// Synopsis: This function is called to allow the user to select multiple items
// to add to cmak. It is currently only used in the Additional Files
// dialog of CMAK. Note that *pszStringBuffer should be NULL when passed
// in. The caller is responsible for calling CmFree on pszStringBuffer
// when finished.
//
// Arguments: HWND hDlg - HWND of the current dialog
// TCHAR** pszStringBuffer - pointer to the buffer to hold the results
//
// Returns: BOOL - Returns True if successful, -1 on cancel and 0 on error.
//
// History: quintinb Created 9/16/98
//
//+----------------------------------------------------------------------------
BOOL MultiSelectOpenFileName(HWND hDlg, TCHAR** pszStringBuffer)
{
OPENFILENAME filedef;
TCHAR szTitle[MAX_PATH+1]={0};
TCHAR szFile[MAX_PATH+1]={0};
TCHAR szFilter[MAX_PATH+1]={0};
TCHAR szFileTitle[MAX_PATH+1]={0};
LPTSTR lpfilename;
int iReturnValue;
//
// Check Inputs
//
MYDBGASSERT(pszStringBuffer);
if (NULL == pszStringBuffer)
{
return FALSE;
}
ZeroMemory(&filedef, sizeof(OPENFILENAME));
ZeroMemory(szFilter, sizeof(szFilter));
szFile[0] = TEXT('\0');
MYVERIFY(0 != LoadString(g_hInstance, IDS_BROWSETITLE, szTitle, MAX_PATH));
MYVERIFY(0 != LoadString(g_hInstance, IDS_ALLFILTER, szFilter, MAX_PATH));
// Get a pointer to memory after the null terminator.
TCHAR * pszTemp = &(szFilter[_tcslen(szFilter) + 1]);
// Copy the wild-card mask into the szFilter buffer, making sure it fits.
lstrcpyn(pszTemp, c_pszWildCard, CELEMS(szFilter) - (_tcslen(szFilter) + 1));
//
// Allocate memory for the multiple file selection return
//
DWORD dwSize = 10*1024;
*pszStringBuffer = (TCHAR*)CmMalloc(dwSize*sizeof(TCHAR));
if (NULL == *pszStringBuffer)
{
return FALSE;
}
ZeroMemory(*pszStringBuffer, dwSize*sizeof(TCHAR));
//
// Initialize the OPENFILENAME data structure
//
filedef.lStructSize = sizeof(OPENFILENAME);
filedef.hwndOwner = hDlg;
filedef.lpstrFilter = szFilter;
filedef.lpstrFile = *pszStringBuffer;
filedef.nMaxFile = dwSize;
filedef.lpstrTitle = szTitle;
filedef.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_PATHMUSTEXIST
| OFN_ALLOWMULTISELECT | OFN_EXPLORER;
//
// pop up the open dialog
//
BOOL bExit;
do
{
bExit = TRUE;
BOOL bRet = GetOpenFileName((OPENFILENAME*)&filedef);
if (bRet)
{
iReturnValue = 1;
}
else
{
//
// If we are in this state than the user could have hit cancel or there could have
// been an error. If the CommDlgExtendedError function returns 0 then we know it was
// just a cancel, otherwise we have an error.
//
DWORD dwError = CommDlgExtendedError();
if (0 == dwError)
{
//
// The user hit cancel
//
iReturnValue = -1;
}
else if (FNERR_BUFFERTOOSMALL == dwError)
{
//
// Not enough memory in the buffer. The user is picking a whole bunch
// of files. Lets warn them.
//
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_SELECTION_TOO_LARGE, MB_OK | MB_ICONWARNING));
bExit = FALSE;
}
else
{
//
// An actual error occured, fail.
//
iReturnValue = 0;
}
}
} while(!bExit);
return iReturnValue;
}
//+----------------------------------------------------------------------------
//
// Function: ParseAdditionalFiles
//
// Synopsis: This function is used to parse the output from MultiSelectOpenFileName.
// It takes a Null seperated list generated by OpenFileName (either one
// full file path, or a directory path, NULL, and then NULL seperated
// filenames.) From this list of filenames it adds them to the passed in
// list of Extra file structures.
//
// Arguments: ListBxList **g_pHeadExtra - pointer to the head of the Extra struct list
// ListBxList **g_pTailExtra - pointer to the tail of the Extra struct list
// TCHAR* pszStringBuffer - string buffer of filenames to process
//
// Returns: BOOL - TRUE on Success
//
// History: quintinb Created 9/16/98
//
//+----------------------------------------------------------------------------
BOOL ParseAdditionalFiles(ListBxList **g_pHeadExtra, ListBxList **g_pTailExtra, TCHAR* pszStringBuffer)
{
UINT uCurrentCharInBuffer=0;
UINT uTempChars;
TCHAR szPath[MAX_PATH+1];
ExtraData DlgExtraEdit;
MYDBGASSERT(NULL != g_pHeadExtra);
MYDBGASSERT(NULL != g_pTailExtra);
MYDBGASSERT(NULL != pszStringBuffer);
MYDBGASSERT(TEXT('\0') != pszStringBuffer[0]);
TCHAR* pStr = pszStringBuffer;
_tcscpy (szPath, pszStringBuffer);
pStr = pStr + (_tcslen(pStr) + 1);
if (TEXT('\0') == *pStr)
{
//
// If the user only selected one file, then we just need to copy it to a buffer
//
_tcscpy(DlgExtraEdit.szPathname, szPath);
GetFileName(DlgExtraEdit.szPathname, DlgExtraEdit.szName);
MYVERIFY(FALSE != createListBxRecord(g_pHeadExtra, g_pTailExtra,(void *)&DlgExtraEdit,
sizeof(DlgExtraEdit), DlgExtraEdit.szName));
return TRUE;
}
else
{
while (TEXT('\0') != *pStr)
{
//
// Fill the DlgExtra Struct with data
//
TCHAR szTemp[MAX_PATH+1];
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), szPath, pStr));
_tcscpy(DlgExtraEdit.szPathname, szTemp);
_tcscpy(DlgExtraEdit.szName, pStr);
//
// Create the List box entry
//
MYVERIFY(FALSE != createListBxRecord(g_pHeadExtra, g_pTailExtra,(void *)&DlgExtraEdit,
sizeof(DlgExtraEdit), DlgExtraEdit.szName));
//
// Increment
//
pStr = pStr + (_tcslen(pStr) + 1);
}
return TRUE;
}
return FALSE;
}
void EnableDisableDeleteButton(HWND hDlg)
{
//
// Enable the delete button if we have move than one item
//
LRESULT lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
HWND hDeleteButton = GetDlgItem(hDlg, IDC_BUTTON2);
HWND hCurrentFocus = GetFocus();
HWND hControl;
if (hDeleteButton)
{
EnableWindow(hDeleteButton, (1 <= lResult));
}
if (1 <= lResult)
{
SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, 0, 0);
}
if (hCurrentFocus && (FALSE == IsWindowEnabled(hCurrentFocus)))
{
if (hDeleteButton == hCurrentFocus)
{
//
// If delete is disabled and contained the focus, shift it to the Add button
//
hControl = GetDlgItem(hDlg, IDC_BUTTON1);
SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON1, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
SetFocus(hControl);
}
else
{
//
// If all else fails set the focus to the list control
//
hControl = GetDlgItem(hDlg, IDC_LIST1);
SetFocus(hControl);
}
}
}
//+----------------------------------------------------------------------------
//
// Function: ProcessAdditionalFiles
//
// Synopsis: Add additional files to the profile
//
//
// History: quintinb Created Header and renamed from ProcessPage7B 8/6/98
// quintinb Added Multi-Select capability and removed intermediate dialog 9/16/98
// (NTRAID 210849)
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessAdditionalFiles(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
INT_PTR nResult;
TCHAR* pszStringBuffer = NULL;
BOOL bRet;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ADDITION)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_LIST1);
switch (message)
{
case WM_INITDIALOG:
SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1: //add
bRet = MultiSelectOpenFileName(hDlg, &pszStringBuffer);
if ((-1 != bRet) && (0 != bRet))
{
ParseAdditionalFiles(&g_pHeadExtra, &g_pTailExtra, pszStringBuffer);
RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
WriteExtraList();
SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
EnableDisableDeleteButton(hDlg);
}
CmFree(pszStringBuffer);
return (TRUE);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case IDC_BUTTON2: //delete
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
if (nResult == LB_ERR)
{
MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
return TRUE;
}
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult,
(LPARAM)szTemp));
DeleteListBxRecord(&g_pHeadExtra, &g_pTailExtra, szTemp);
RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
EnableDisableDeleteButton(hDlg);
WriteExtraList();
return (TRUE);
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
if (g_pHeadExtra == NULL)
{
ReadExtraList();
}
RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
EnableDisableDeleteButton(hDlg);
break;
case PSN_WIZBACK:
case PSN_WIZNEXT:
//
// Before allowing the user to finish we need to check the extra files
// list and make sure that each file on it has a filename that is convertable
// to ANSI. If not then we need to make sure that we tell them so that they
// can delete the file or rename it. Checking this in ParseAdditional files
// seemed odd because they may have selected a bunch of files where only
// one of them was wrong. Thus we would be failing their browse and there was
// nothing they could do about it. Doing it here allows them to keep all of the
// good files that pass the roundtrip test and allows them to delete offending files
// at a spot where they can actually do so.
//
ExtraData * pExtraData;
ListBxList * LoopPtr;
if (NULL != g_pHeadExtra)
{
LoopPtr = g_pHeadExtra;
while( LoopPtr != NULL)
{
pExtraData = (ExtraData *)LoopPtr->ListBxData;
{
GetFileName(pExtraData->szPathname, szTemp);
if (!TextIsRoundTripable(szTemp, TRUE)) // TRUE == bDisplayError
{
//
// Set the Cursor on the offending item in the list
//
nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT,
(WPARAM)-1, (LPARAM)szTemp);
if (LB_ERR != nResult)
{
MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)nResult, (LPARAM)0));
}
//
// Set focus on the delete button
//
SetFocus(GetDlgItem(hDlg, IDC_BUTTON2));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
LoopPtr = LoopPtr->next;
}
}
WriteExtraList();
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
BOOL WriteInf(HANDLE hInf, LPCTSTR str)
{
DWORD written;
#ifdef UNICODE
BOOL bReturn = FALSE;
LPSTR pszAnsiString = WzToSzWithAlloc(str);
if (pszAnsiString)
{
bReturn = WriteFile(hInf, pszAnsiString, (lstrlenA(pszAnsiString))*sizeof(CHAR), &written, NULL);
CmFree(pszAnsiString);
}
return bReturn;
#else
return (WriteFile(hInf, str, (lstrlen(str))*sizeof(TCHAR), &written, NULL));
#endif
}
//+----------------------------------------------------------------------------
//
// Function: WriteCopy
//
// Synopsis: This function writes an INF entry and copies the file to the temp
// directory. Note that the function expects a fully qualified path
// in lpFile or <shortservicename>\filename.ext.
//
// Arguments: HANDLE hInf - handle to the open inf file to write to
// LPTSTR lpFile - fully qualified path and filename of file to copy
// BOOL bWriteShortName -- should the filename be converted to the shortname
//
// Returns: BOOL - TRUE if the INF entry is written properly and the file is
// copied properly.
//
// NOTE: This code is written such that filenames passed in should reference the
// copy of the file in the temp directory (thus the user is editing the profile
// and hasn't changed it) or the file is a new file and the path is to its original
// location. Unfortunately, we usually pass in the path to the file in the Profile
// directory instead of in the temp dir. This works fine, but makes an additional copy
// operation necessary (since we copy all files to the temp dir in the beginning when
// editting anyway).
//
// History: quintinb Created Header 1/30/98
//
//+----------------------------------------------------------------------------
BOOL WriteCopy(HANDLE hInf, LPTSTR lpFile, BOOL bWriteShortName)
{
TCHAR szDest[MAX_PATH+1];
TCHAR szSrc[MAX_PATH+1];
if (NULL != lpFile && lpFile[0] != TEXT('\0'))
{
//
// Prepare the destination in szDest
//
GetFileName(lpFile, szSrc);
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"), g_szOutdir, szSrc));
//
// Prepare the source in szSrc. If we have <shortservicename>\filename.ext, then
// we need to prepend the path to the profiles dir, otherwise use as is.
//
wsprintf(szSrc, TEXT("%s\\"), g_szShortServiceName);
CmStrTrim(lpFile);
if (lpFile == CmStrStr(lpFile, szSrc))
{
MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, lpFile));
}
else
{
lstrcpy(szSrc, lpFile);
}
//
// Copy the file
//
if (_tcsicmp(szSrc, szDest) != 0)
{
if (!CopyFileWrapper(szSrc, szDest, FALSE))
{
return FALSE;
}
}
MYVERIFY(0 != SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL));
//
// If WriteShortName is set, then we want to write the short name of the file
// in the inf section. Otherwise we want to write the long name.
//
if (bWriteShortName)
{
if (!GetShortFileName(szDest, szSrc))
{
return FALSE;
}
}
else
{
GetFileName(szDest, szSrc);
}
MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\r\n"), szSrc));
return WriteInf(hInf, szDest);
}
return TRUE;
}
BOOL WriteInfLine(HANDLE hInf,LPTSTR lpFile)
{
TCHAR szTemp[MAX_PATH+1];
if (lpFile[0] != TEXT('\0'))
{
GetFileName(lpFile,szTemp);
_tcscat(szTemp,TEXT("\r\n"));
return WriteInf(hInf,szTemp);
}
else
{
//
// If blank then nothing to write
//
return TRUE;
}
}
BOOL WriteSrcInfLine(HANDLE hInf,LPTSTR lpFile)
{
TCHAR szShort[MAX_PATH+1];
TCHAR szLong[MAX_PATH+1];
RenameData TmpRenameData;
if (lpFile[0] != TEXT('\0'))
{
if (!GetShortFileName(lpFile,szShort))
{
return FALSE;
}
GetFileName(lpFile,szLong);
if (_tcsicmp(szShort,szLong) != 0)
{
_tcscpy(TmpRenameData.szShortName,szShort);
_tcscpy(TmpRenameData.szLongName,szLong);
MYVERIFY(FALSE != createListBxRecord(&g_pHeadRename,&g_pTailRename,(void *)&TmpRenameData,sizeof(TmpRenameData),TmpRenameData.szShortName));
}
_tcscat(szLong,TEXT("= 55\r\n"));
return WriteInf(hInf,szLong);
}
else
{
//
// Nothing to write
//
return TRUE;
}
}
BOOL WriteFileSections(HWND hDlg)
{
HANDLE hInf;
TCHAR szTemp[MAX_PATH+1];
TCHAR szTempName[MAX_PATH+1];
CHAR ch = 0;
int i;
DWORD dwRead;
BOOL bWriteShortName;
hInf = CreateFile(g_szInfFile,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
_tcscpy(szTemp,g_szInfFile);
FileAccessErr(hDlg,szTemp);
goto error;
}
// MOVE TO END OF FILE TO BEGIN WRITING CUSTOM SECTIONS
// SKIP ANY BLANK SPACE AT THE END OF THE FILE
i = GetFileSize(hInf,NULL);
do
{
--i;
MYVERIFY(INVALID_SET_FILE_POINTER != SetFilePointer(hInf,i,NULL,FILE_BEGIN));
MYVERIFY(0 != ReadFile(hInf, &ch, sizeof(CHAR), &dwRead, NULL));
}
while (isspace(ch));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
// USE ICON IN CM AS ICON FOR DESKTOP IF NOT LARGE ICON SPECIFIED
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.AddReg.Icon]\r\n")));
if (g_szLargeIco[0]==TEXT('\0'))
{
WriteInf(hInf,TEXT("HKCR,\"CLSID\\%DesktopGUID%\\DefaultIcon\",,,\"%11%\\CMMGR32.EXE,0\"\r\n"));//lint !e534 compile doesn't like the MYVERIFY macro and big strings
}
else
{
WriteInf(hInf,TEXT("HKCR,\"CLSID\\%DesktopGUID%\\DefaultIcon\",,,\"%49000%\\%ShortSvcName%\\%DesktopIcon%\"\r\n"));//lint !e534 compile doesn't like the MYVERIFY macro and big strings
}
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
// WRITE OUT FILES INTO PROFILE DIRECTORY
//
// We need to write a CopyFiles section with Long File Names (for NT5 Single User installs)
// and one with Short Files Names (for win9x and All user NT). This is to help fix
// NTRAID 323721 -- CM: User level accounts cannot install profiles on W2K Server
// The problem is that single users on NT5 do not have permission to write the
// Rename key (HKLM\Software\Microsoft\Windows\CurrentVersion\RenameFiles) and
// NT doesn't really need it anyway since the NT setup api's deal with long file
// names better than those of win95.
//
for (bWriteShortName = 0; bWriteShortName < 2; bWriteShortName++)
{
if (!bWriteShortName)
{
//
// Write out the Single User Version of Xnstall.CopyFiles -- Set bWriteShortName == FALSE
//
MYVERIFY(FALSE != WriteInf(hInf, TEXT("[Xnstall.CopyFiles.SingleUser]\r\n")));
}
else
{
//
// Write out the All User Version of Xnstall.CopyFiles -- set bWriteShortName == TRUE
//
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.CopyFiles]\r\n")));
}
if (!WriteCopy(hInf, g_szPhonebk, bWriteShortName)) {_tcscpy(szTemp,g_szPhonebk);goto error;}
if (!WriteCopy(hInf, g_szRegion, bWriteShortName)) {_tcscpy(szTemp,g_szRegion);goto error;}
if (!WriteCopy(hInf, g_szBrandBmp, bWriteShortName)) {_tcscpy(szTemp,g_szBrandBmp);goto error;}
if (!WriteCopy(hInf, g_szPhoneBmp, bWriteShortName)) {_tcscpy(szTemp,g_szPhoneBmp);goto error;}
if (!WriteCopy(hInf, g_szLargeIco, bWriteShortName)) {_tcscpy(szTemp,g_szLargeIco);goto error;}
if (!WriteCopy(hInf, g_szSmallIco, bWriteShortName)) {_tcscpy(szTemp,g_szSmallIco);goto error;}
if (!WriteCopy(hInf, g_szTrayIco, bWriteShortName)) {_tcscpy(szTemp,g_szTrayIco);goto error;}
if (!WriteCopy(hInf, g_szHelp, bWriteShortName)) {_tcscpy(szTemp,g_szHelp);goto error;}
if (!WriteCopy(hInf, g_szLicense, bWriteShortName)) {_tcscpy(szTemp,g_szLicense);goto error;}
if (!WriteCopy(hInf, g_szCmProxyFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmProxyFile);goto error;}
if (!WriteCopy(hInf, g_szCmRouteFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmRouteFile);goto error;}
if (!WriteCopy(hInf, g_szVpnFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmRouteFile);goto error;}
//
// Write out tray icon command files
//
if (!WriteCopyMenuItemFiles(hInf, szTemp, bWriteShortName)) {goto error;}
// Write out connect action command files
if (!WriteCopyConActFiles(hInf,szTemp, bWriteShortName)) {goto error;}
if (!WriteCopyExtraFiles(hInf,szTemp, bWriteShortName)) {goto error;}
if (!WriteCopyDnsFiles(hInf,szTemp, bWriteShortName)) {goto error;}
if (bWriteShortName)
{
MYVERIFY(FALSE != WriteShortRefsFiles(hInf, FALSE));
}
else
{
MYVERIFY(FALSE != WriteLongRefsFiles (hInf));
}
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".cms,,,4\r\n")); // the 4 makes sure there is no version checking on the cms
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".inf\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
}
//
// End of quintinb fix for 323721
//
//WRITE OUT FILES TO COPY TO ICM DIRECTORY
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.CopyFiles.ICM]\r\n")));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".cmp\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
MYVERIFY(FALSE != WriteRefsFiles(hInf,TRUE));// doesn't do anything because no cmp files in HeadRef list, call just writes the CMP file under [Xnstall.CopyFiles.ICM]
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
// WRITE OUT FILES TO DELETE FROM ROOT ICM DIRECTORY
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Remove.DelFiles.ICM]\r\n")));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".cmp\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
MYVERIFY(FALSE != WriteRefsFiles(hInf,TRUE));// doesn't anything because no cmp files in HeadRef list, call just writes the CMP file under [Remove.DelFiles.ICM]
// WRITE LIST OF ALL FILES IN PRODUCT
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[SourceDisksFiles]\r\n")));
_tcscpy(szTemp,TEXT("%ShortSvcname%"));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szPhonebk));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szRegion));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szBrandBmp));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szPhoneBmp));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szLargeIco));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szSmallIco));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szTrayIco));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szHelp));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szLicense));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szCmProxyFile));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szCmRouteFile));
MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szVpnFile));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".inf = 55\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".cmp = 55\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
_tcscpy(szTemp,g_szShortServiceName);
_tcscat(szTemp,TEXT(".cms = 55\r\n"));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
WriteSrcMenuItemFiles(hInf);
WriteSrcConActFiles(hInf);
WriteSrcExtraFiles(hInf);
MYVERIFY(FALSE != WriteSrcRefsFiles(hInf)); // This call writes out the refs files to [Remove.DelFiles]
WriteSrcDnsFiles(hInf);
WriteRenameSection(hInf);
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Remove.DelFiles]\r\n")));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s.cms\r\n"), g_szShortServiceName));
MYVERIFY(FALSE != WriteInf(hInf,szTemp));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szPhonebk));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szRegion));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szBrandBmp));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szPhoneBmp));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szLargeIco));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szSmallIco));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szTrayIco));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szHelp));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szLicense));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szCmProxyFile));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szCmRouteFile));
MYVERIFY(FALSE != WriteInfLine(hInf,g_szVpnFile));
WriteDelMenuItemFiles(hInf);
WriteDelConActFiles(hInf);
WriteDelExtraFiles(hInf);
MYVERIFY(FALSE != WriteRefsFiles(hInf,FALSE));
WriteDelDnsFiles(hInf);
WriteEraseLongName(hInf);
MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
MYVERIFY(0 != CloseHandle(hInf));
MYVERIFY(0 != SetCurrentDirectory(g_szCmakdir));
return (TRUE);
error:
{
//FileAccessErr(hDlg,szTemp);
MYVERIFY(0 != CloseHandle(hInf));
return (FALSE);
}
}
void EraseSEDFiles(LPCTSTR szSed)
{
int i = 0;
TCHAR szTemp[MAX_PATH+1];
TCHAR szFileNum[MAX_PATH+1];
TCHAR szSourceFilesSection[MAX_PATH+1];
_tcscpy(szSourceFilesSection, TEXT("SourceFiles0"));
do
{
MYVERIFY(CELEMS(szFileNum) > (UINT)wsprintf(szFileNum, TEXT("FILE%d"), i));
//
// The following call to GetPrivateProfileString could return an empty string, thus don't
// use the MYVERIFY macro on it.
//
GetPrivateProfileString(c_pszInfSectionStrings, szFileNum, TEXT(""), szTemp,
MAX_PATH, szSed); //lint !e534
if (*szTemp)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, szFileNum, NULL, szSed));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%%%s%%"), szFileNum));
MYVERIFY(0 != WritePrivateProfileString(szSourceFilesSection, szTemp, NULL, szSed));
}
else
{
break;
}
++i; // increment the file number
}
while(*szTemp);
//
// Erase the finish message key from the Sed. This will avoid double finish messages
// (since cmstp is now supposed to take care of finish message but older profiles had
// the message from here).
//
MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, TEXT("FinishMessage"), TEXT(""), szSed));
//
// Write out the word <None> into the post install command so that showicon isn't a problem
// on an upgrade.
//
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, TEXT("PostInstallCmd"), TEXT("<None>"), szSed));
}
//+----------------------------------------------------------------------------
//
// Function: WriteSED
//
// Synopsis: This function takes a fullpath to a file and the current file
// number entry to write it to and writes the file entry in the SED
// passed in. Before writing the entry, the functions enumerates all
// other files in the sed to check for duplicates. If it finds a
// file with the sme filename, it will not write the entry because
// since we are using a flat directory structure two files of the same
// name will overwrite each other anyway. Note that if the file is
// written, *pFileNum is incremented.
//
// Arguments: HWND hDlg - Window handle for FileAccessErr Messages
// LPTSTR szFullFilePath - Full path of the file to write
// LPINT pFileNum - Current File entry number
// LPCTSTR szSed - Full path to the sed file to write the entry to
//
// Returns: Nothing
//
// History: quintinb Created Header, Removed UseLangDir, Changed to take a full path,
// and generally cleaned up. 8/7/98
//
//+----------------------------------------------------------------------------
BOOL WriteSED(HWND hDlg, LPTSTR szFullFilePath, LPINT pFileNum, LPCTSTR szSed)
{
TCHAR szTemp[MAX_PATH+1]={0};
TCHAR szFileName[MAX_PATH+1]={0};
TCHAR szFileNumber[MAX_PATH+1]={0};
if (TEXT('\0') != szFullFilePath[0])
{
//
// First Check to see if the file exists. If we write a file in the SED that
// IExpress can't find, then it will throw an error. We should definitely try
// to throw an error earlier and try to give the user a chance to fix it.
//
if (!FileExists(szFullFilePath))
{
CFileNameParts FileParts(szFullFilePath);
if ((TEXT('\0') == FileParts.m_Drive[0]) &&
(TEXT('\0') == FileParts.m_Dir[0]) &&
(TEXT('\0') != FileParts.m_FileName[0]) &&
(TEXT('\0') != FileParts.m_Extension[0]))
{
//
// The user only passed in the filename and extension. Lets look in
// the profile directory. If it isn't here then throw an error.
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s%s"),
g_szOsdir, g_szShortServiceName, FileParts.m_FileName, FileParts.m_Extension));
if (!FileExists(szTemp))
{
FileAccessErr(hDlg, szFullFilePath);
return FALSE;
}
else
{
(VOID)lstrcpyn(szFullFilePath, szTemp, CELEMS(szFullFilePath));
}
}
else
{
FileAccessErr(hDlg, szFullFilePath);
return FALSE;
}
}
//
// Get just the file name from the full path. We use this
// later to determine if the file already exists in the SED
// file.
//
GetFileName(szFullFilePath, szFileName);
//
// Construct the next FileNumber Entry
//
MYVERIFY(CELEMS(szFileNumber) > (UINT)wsprintf(szFileNumber, TEXT("FILE%d"), *pFileNum));
//
// Check to make sure that we already don't have the file in the cab. If
// so then just ignore the entry.
//
for (int i=0; i<*pFileNum; ++i)
{
//
// Write the FILEX entry into a string to read in the file name for the
// current i.
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("FILE%d"), i));
TCHAR szTempFileName[MAX_PATH+1];
GetPrivateProfileString(c_pszInfSectionStrings, szTemp,
TEXT(""), szTempFileName, CELEMS(szTempFileName), szSed); //lint !e534
if (TEXT('\0') != szTempFileName[0])
{
//
// Get the filenames of both files since we are using a flat directory space.
// Two files of the same name will collide anyway.
//
GetFileName(szTempFileName, szTemp);
if (0 == _tcsicmp(szTemp, szFileName))
{
//
// don't add it because it already exists
//
CMASSERTMSG(0 == _tcsicmp(szFullFilePath, szTempFileName), TEXT("WriteSed -- We have two files that have the same FileName but different paths."));
return TRUE;
}
}
}
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
szFileNumber, szFullFilePath, szSed));
*pFileNum = (*pFileNum) + 1;
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%%%s%%"), szFileNumber));
MYVERIFY(0 != WritePrivateProfileString(TEXT("SourceFiles0"), szTemp, TEXT(""), szSed));
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: WriteCMPFile
//
// Synopsis: This function is a wrapper file to write out the version to the CMP.
//
// Arguments: None
//
// History: nickball Created Header 07/22/98
//
//+----------------------------------------------------------------------------
void WriteCMPFile()
{
TCHAR szTemp[MAX_PATH+1];
//
// Ensure that the version number is up to date in the .CMP
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), PROFILEVERSION));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionProfileFormat, c_pszVersion, szTemp, g_szCmpFile));
//
// Write the CMS entry to the CMP File
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"), g_szShortServiceName, g_szShortServiceName));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryCmsFile, szTemp, g_szCmpFile));
}
//+----------------------------------------------------------------------------
//
// Function: WriteOutRelativeFilePathOrNull
//
// Synopsis: This helper routine was written to shorten WriteCMSFile(). It tests
// to see if the inputted pszFile parameter is an empty string. If it
// is then it writes an empty string to the File entry specified by
// pszSection, pszEntryName, and pszFileToWriteTo. Otherwise it concats
// just the file name from pszFile with the parameter specified in
// pszShortName, seperating them with a '\' character. This is useful
// for CMS parameters that are either empty or a relative path from the
// cmp file location.
//
// Arguments: LPCTSTR pszFile - file entry to write
// LPCTSTR pszShortName - shortname of the profile
// LPCTSTR pszSection - string name of the section string
// LPCTSTR pszEntryName - string name of the entry name string
// LPCTSTR pszFileToWriteTo - full path of the file to write the entry to
//
// Returns: Nothing
//
// History: quintinb Created 8/8/98
//
//+----------------------------------------------------------------------------
void WriteOutRelativeFilePathOrNull(LPCTSTR pszFile, LPCTSTR pszShortName, LPCTSTR pszSection, LPCTSTR pszEntryName, LPCTSTR pszFileToWriteTo)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szName[MAX_PATH+1];
//
// Check Inputs
//
if ((NULL == pszFile) ||
(NULL == pszShortName) || (TEXT('\0') == pszShortName[0]) ||
(NULL == pszFileToWriteTo) || (TEXT('\0') == pszFileToWriteTo[0]) ||
(NULL == pszSection) || (TEXT('\0') == pszSection[0]) ||
(NULL == pszEntryName) || (TEXT('\0') == pszEntryName[0]))
{
CMASSERTMSG(FALSE, TEXT("WriteoutRelativeFilePathOrNull -- Bad Parameter"));
return;
}
if (TEXT('\0') != pszFile[0])
{
GetFileName(pszFile, szName);
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
pszShortName, szName));
}
else
{
szTemp[0] = TEXT('\0');
}
MYVERIFY(0 != WritePrivateProfileString(pszSection, pszEntryName, szTemp, pszFileToWriteTo));
}
//+----------------------------------------------------------------------------
//
// Function: WriteCMSFile
//
// Synopsis: This function is a wrapper file to write out the CMS file. Note
// that the cms is modified throughout CMAK, but this should be the
// last place where it is modified.
//
// Arguments: None
//
// History: quintinb Created Header 12/4/97
//
//+----------------------------------------------------------------------------
BOOL WriteCMSFile()
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szName[MAX_PATH+1];
//
// Ensure that the Profile Format version number is up to date
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), PROFILEVERSION));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionProfileFormat, c_pszVersion, szTemp, g_szCmsFile));
//
// erase name of phone book to be loaded if not doing download.
//
if (!g_bUpdatePhonebook)
{
g_szPhoneName[0] = TEXT('\0');
}
//
// Write out the Phonebook Name
//
if (TEXT('\0') != g_szPhonebk[0])
{
GetFileName(g_szPhonebk, szName);
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszVersion, c_pszOne,
g_szCmsFile));
}
else
{
//
// if no phone number, then set version to zero
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszVersion, c_pszZero,
g_szCmsFile));
if (TEXT('\0') != g_szPhoneName[0])
{
MYVERIFY(CELEMS(szName) > (UINT)wsprintf(szName, TEXT("%s.pbk"), g_szPhoneName));
}
else
{
//
// no phone book entered or set for download
//
szName[0] = TEXT('\0');
}
}
WriteOutRelativeFilePathOrNull(szName, g_szShortServiceName, c_pszCmSectionIsp,
c_pszCmEntryIspPbFile, g_szCmsFile);
//
// Write out the Phonebook Name
//
if (TEXT('\0') != g_szRegion[0])
{
GetFileName(g_szRegion, szName);
}
else
{
if (TEXT('\0') != g_szPhoneName[0])
{
MYVERIFY(CELEMS(szName) > (UINT)wsprintf(szName, TEXT("%s.pbr"), g_szPhoneName));
}
else
{
szName[0] = TEXT('\0');
}
}
WriteOutRelativeFilePathOrNull(szName, g_szShortServiceName, c_pszCmSectionIsp,
c_pszCmEntryIspRegionFile, g_szCmsFile);
//
// Write out the Large Icon
//
WriteOutRelativeFilePathOrNull(g_szLargeIco, g_szShortServiceName, c_pszCmSection,
c_pszCmEntryBigIcon, g_szCmsFile);
//
// Write out the Small Icon
//
WriteOutRelativeFilePathOrNull(g_szSmallIco, g_szShortServiceName, c_pszCmSection,
c_pszCmEntrySmallIcon, g_szCmsFile);
//
// Write out the Tray Icon
//
WriteOutRelativeFilePathOrNull(g_szTrayIco, g_szShortServiceName, c_pszCmSection,
c_pszCmEntryTrayIcon, g_szCmsFile);
//
// Write out the custom help file
//
WriteOutRelativeFilePathOrNull(g_szHelp, g_szShortServiceName, c_pszCmSection,
c_pszCmEntryHelpFile, g_szCmsFile);
//
// Write out the License File to the INF, thus we can easily redisplay
// it if they edit the profile again. (basically stash the license file
// name in the CMAK Status section of the inf)
//
WriteOutRelativeFilePathOrNull(g_szLicense, g_szShortServiceName, c_pszCmakStatus,
c_pszLicenseFile, g_szInfFile);
//
// Write out the Main Screen Bitmap
//
WriteOutRelativeFilePathOrNull(g_szBrandBmp, g_szShortServiceName, c_pszCmSection,
c_pszCmEntryLogo, g_szCmsFile);
//
// Write out the Phone Bitmap
//
WriteOutRelativeFilePathOrNull(g_szPhoneBmp, g_szShortServiceName, c_pszCmSection,
c_pszCmEntryPbLogo, g_szCmsFile);
//
// Write the HideDomain flag
//
GetPrivateProfileString(c_pszCmSection, c_pszCmEntryHideDomain, TEXT(""),
szTemp, MAX_PATH, g_szCmsFile); //lint !e534
//
// If using tunneling and the HideDomain entry doesn't previously exist, then write
// zero for the entry. Otherwise nothing should be written for this entry.
//
if (!(_tcscmp(TEXT(""), szTemp) ) && g_bUseTunneling)
{
//
// Don't want to overwrite a 1 if it exists.
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryHideDomain,
c_pszZero, g_szCmsFile));
}
//
// If we aren't tunneling, make sure to delete the tunnel settings
//
if (FALSE == g_bUseTunneling)
{
//
// First delete all of the Tunnel DUN Settings
//
ListBxList * pCurrent = g_pHeadVpnEntry;
while (NULL != pCurrent)
{
EraseNetworkingSections(pCurrent->szName, g_szCmsFile);
pCurrent = pCurrent->next;
}
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, NULL, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, NULL, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, NULL, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, NULL, g_szCmsFile));
}
//
// Write out the rest of the CMS entries (service name, support message, etc.)
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
g_szLongServiceName,g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceMessage,
g_szSvcMsg, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix,
g_szPrefix, g_szCmsFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix,
g_szSuffix, g_szCmsFile));
//
// Set the name of the default Dun setting
//
MYVERIFY(0 != GetDefaultDunSettingName(g_szCmsFile, g_szLongServiceName, szTemp, CELEMS(szTemp)));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryDun, szTemp, g_szCmsFile));
//
// Write out the custom actions, make sure to set the bUseTunneling flag with the actual
// value to erase the PreTunnel section and set all of the flag values to zero if necessary
// (if for instance the user editted a tunneling profile and decided to make it non-Tunneling).
//
MYDBGASSERT(g_pCustomActionList);
if (g_pCustomActionList)
{
HRESULT hr = g_pCustomActionList->WriteCustomActionsToCms(g_szCmsFile, g_szShortServiceName, g_bUseTunneling);
CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Failed to write out connect actions"));
}
//
// Delete mbslgn32.dll special handling in the INF, it is no longer supported.
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUsePwdCache, NULL, g_szInfFile));
if (g_bUpdatePhonebook)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszOne, g_szInfFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszZero, g_szInfFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszPhoneName, TEXT(""), g_szInfFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), g_szCmsFile));
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: IncludeOptionalCode
//
// Synopsis: This function writes the flags to CMAK to tell the profile installer
// whether or not CM bits and Support dll's should be installed.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb Created Header and rewrote 5/23/98
// quintinb NTRAID 162321, CM bits should not be installed on NT5 - 5/23/98
// quintinb NTRAID 192500, Support Dll's now always included with CM bits - 9-2-98
// quintinb we no longer ship the support dlls, removed support for them 4-19-2001
//
//+----------------------------------------------------------------------------
void IncludeOptionalCode()
{
if (g_bIncludeCmCode)
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode, c_pszOne, g_szInfFile));
}
else
{
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode, c_pszZero, g_szInfFile));
}
//
// We no longer ship the support files, erase the entry from the inf
//
MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeSupportDll, NULL, g_szInfFile));
}
//+----------------------------------------------------------------------------
//
// Function: HandleWindowMessagesWhileCompressing
//
// Synopsis: This function pumps messages while iexpress is running.
//
// Arguments: None
//
// Returns: Nothing
//
// History: quintinb Created 7/29/98
//
//+----------------------------------------------------------------------------
void HandleWindowMessagesWhileCompressing()
{
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);//lint !e534 ignore dispatchmessage return values
}
}
//+----------------------------------------------------------------------------
//
// Function: DisableWizardButtons
//
// Synopsis: This function disables the four wizard buttons at the bottom
// of the wizard page. Since these buttons aren't really ours we
// need to get the window handle of the parent dialog and then get
// the window handle of the individual button controls that we want to
// disable (Help, Cancel, Back, and Finish/Next). When we have the
// window handle of each button we call EnableWindow on the button
// to disable it. This function also disables the geek pane controls
// and the advanced checkbox on the build profile page if they exist.
//
// Arguments: HWND hDlg - Wizard page window handle (handle to our template page)
//
// Returns: Nothing
//
// History: quintinb Created 7/29/98
//
//+----------------------------------------------------------------------------
void DisableWizardButtons(HWND hDlg)
{
#define IDBACK 12323
#define IDNEXT 12324
#define IDFINISH 12325
HWND hCurrentPage = GetParent(hDlg);
if (hCurrentPage)
{
const int c_NumButtons = 5;
int iArrayOfButtonsToDisable[c_NumButtons] = {IDCANCEL, IDHELP, IDBACK, IDNEXT, IDFINISH};
//
// Disable the Cancel Button
//
for (int i = 0; i < c_NumButtons; i++)
{
HWND hButton = GetDlgItem(hCurrentPage, iArrayOfButtonsToDisable[i]);
if (hButton)
{
EnableWindow(hButton, FALSE);
}
}
}
//
// Disable the advanced button and the geek pane controls if they exist.
//
int iArrayOfItemsToDisable[] = {IDC_ADVANCED, IDC_COMBO1, IDC_COMBO2, IDC_COMBO3, IDC_EDIT1, IDC_BUTTON1};
const int c_NumItems = CELEMS(iArrayOfItemsToDisable);
for (int i = 0; i < c_NumItems; i++)
{
HWND hControl = GetDlgItem(hDlg, iArrayOfItemsToDisable[i]);
if (hControl)
{
EnableWindow(hControl, FALSE);
}
}
}
//+----------------------------------------------------------------------------
//
// Function: WriteInfBeginAndEndPrompts
//
// Synopsis: This function writes the Begin and End Prompt strings to the
// inf file. These are written dynamically because they need to
// contain the Service Name.
//
// Arguments: HINSTANCE hInstance - Instance Handle to get string resources with
// LPTSTR szInf - Inf file to write the prompts too
// LPTSTR szServiceName - Long Service name of the profile
//
// Returns: Nothing
//
// History: Created Header 7/31/98
//
//+----------------------------------------------------------------------------
void WriteInfBeginAndEndPrompts(HINSTANCE hInstance, LPCTSTR szInf, LPCTSTR szServiceName)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szPrompt[MAX_PATH+1];
MYVERIFY(0 != LoadString(hInstance, IDS_BeginPromptText, szTemp, MAX_PATH));
MYDBGASSERT(TEXT('\0') != szTemp[0]);
MYVERIFY(CELEMS(szPrompt) > (UINT)wsprintf(szPrompt, szTemp, szServiceName));
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszInfBeginPrompt, szPrompt, szInf);
MYVERIFY(0 != LoadString(hInstance, IDS_EndPromptText, szTemp, MAX_PATH));
MYDBGASSERT(TEXT('\0') != szTemp[0]);
MYVERIFY(CELEMS(szPrompt) > (UINT)wsprintf(szPrompt, szTemp, szServiceName));
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszInfEndPrompt, szPrompt, szInf);
}
//+----------------------------------------------------------------------------
//
// Function: WriteInfFile
//
// Synopsis: This function encapsulates all the code needed to write an inf file.
//
// Arguments: HINSTANCE hInstance - Instance handle to get string resources from
// LPCTSTR szInf - Name of the Inf to write to
// LPCTSTR szLongServiceName - Long Service Name of the Profile
//
// Returns: BOOL - returns TRUE if succeeded
//
// History: quintinb created 8/10/98
//
//+----------------------------------------------------------------------------
BOOL WriteInfFile(HINSTANCE hInstance, HWND hDlg, LPCTSTR szInf, LPCTSTR szLongServiceName)
{
TCHAR szTemp[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
GUID vGUID;
//
// Write out the version number of cmdial32.dll to the INF. This tells the installer
// what version of cmdial32.dll that this profile was built to use. We do this
// because if CM bits aren't bundled then we don't have cmdial32.dll to directly compare
// with. Note that we now get the version of cmdial32.dll from the cm binaries cab, not
// the version in system32.
//
#ifdef _WIN64
CmVersion CmdialVersion;
#else
wsprintf(szTemp, TEXT("%s\\cmdial32.dll"), g_szCmBinsTempDir);
if (!FileExists(szTemp))
{
if (FAILED(ExtractCmBinsFromExe(g_szSupportDir, g_szCmBinsTempDir)))
{
CMASSERTMSG(FALSE, TEXT("WriteInfFile -- ExtractCmBinsFromExe Failed."));
return FALSE;
}
}
CVersion CmdialVersion(szTemp);
#endif
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), CmdialVersion.GetVersionNumber()));
MYVERIFY(0 != WritePrivateProfileString(c_pszSectionCmDial32, c_pszVersion, szTemp, szInf));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), CmdialVersion.GetBuildAndQfeNumber()));
MYVERIFY(0 != WritePrivateProfileString(c_pszSectionCmDial32, c_pszVerBuild, szTemp, szInf));
//
// Create a Desktop GUID if one doesn't already exist (a new profile instead of
// an editted one).
//
ZeroMemory(szTemp, sizeof(szTemp));
GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid,
TEXT(""), szTemp, CELEMS(szTemp), szInf); //lint !e534
if (TEXT('\0') == szTemp[0])
{
MYVERIFY(S_OK == CoCreateGuid(&vGUID));
MYVERIFY(0 != StringFromGUID2(vGUID, szTemp, MAX_PATH));
QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid,
szTemp, szInf);
}
//
// Write out the Display LCID of the profile
//
wsprintf(szTemp, TEXT("%d"), GetSystemDefaultLCID());
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLCID, szTemp, szInf));
//
// Erase the existing File sections
//
MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles"), NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles.SingleUser"), NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles.ICM"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Remove.DelFiles"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Remove.DelFiles.ICM"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("SourceDisksFiles"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.AddReg.Icon"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("RegisterOCXSection"),NULL, NULL, szInf));
MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.RenameReg"),NULL, NULL, szInf));
if (!CreateMergedProfile())
{
return FALSE;
}
IncludeOptionalCode();
//
// Add the dynamic file sections to the install
//
if (WriteFileSections(hDlg) == FALSE)
{
return FALSE;
}
//
// Write the Begin and End Prompts
//
WriteInfBeginAndEndPrompts(hInstance, szInf, szLongServiceName);
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ConCatPathAndWriteToSed
//
// Synopsis: This function is a wrapper for WriteSed that concats two paths
// together before calling WriteSed. This allows the caller to
// store a common path (such as the system directory) and call
// WriteSed with a bunch of different files all in the same directory
// without having to individually concatenate the common path and the
// filenames.
//
// Arguments: HWND hDlg - windows handle of the current dialog, needed for error messages
// LPCTSTR pszFileName - Name of the file
// LPCTSTR pszPath - Name of the path to prepend to the filename
// int* pFileNum - the number of the file in the SED file
// LPCTSTR szSed - the SED file to write to
//
// Returns: BOOL - Returns TRUE if succeeded
//
// History: quintinb Created 8/10/98
//
//+----------------------------------------------------------------------------
BOOL ConCatPathAndWriteToSed(HWND hDlg, LPCTSTR pszFileName, LPCTSTR pszPath,
int* pFileNum, LPCTSTR szSed)
{
TCHAR szTemp[MAX_PATH+1];
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), pszPath, pszFileName));
return WriteSED(hDlg, szTemp, pFileNum, szSed);
}
//+----------------------------------------------------------------------------
//
// Function: ConstructSedFile
//
// Synopsis: This function encapsulates all the work of creating an SED file.
//
// Arguments: HWND hDlg - window handle of the current dialog for error messages
// LPCTSTR szSed - filename of the sed file to write
// LPCTSTR szExe - executable filename for the SED to compress to
//
// Returns: BOOL - Returns TRUE if successful
//
// History: quintinb Created 8/10/98
//
//+----------------------------------------------------------------------------
BOOL ConstructSedFile(HWND hDlg, LPCTSTR szSed, LPCTSTR szExe)
{
int iFileNum=0;
TCHAR szTemp[MAX_PATH+1];
BOOL bReturn = TRUE;
CPlatform cmplat;
//
// Clear the SED and begin writing new settings
//
EraseSEDFiles(szSed);
//
// Write the Installer Package Exe Name
//
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
c_pszTargetName, szExe, szSed));
//
// Write the Long Service Name as the FriendlyName
//
if (!WritePrivateProfileString(c_pszInfSectionStrings, c_pszFriendlyName,
g_szLongServiceName, szSed))
{
FileAccessErr(hDlg, szSed);
return FALSE;
}
//
// Load up IDS_INSTALL_PROMPT from the resources
// Format the string using the g_szLongServiceName
//
LPTSTR pszInstallPromptTmp = CmFmtMsg(g_hInstance, IDS_INSTALL_PROMPT, g_szLongServiceName);
if (pszInstallPromptTmp)
{
//
// Write the Install Prompt string
//
if (!WritePrivateProfileString(c_pszInfSectionStrings, c_pszInstallPrompt,
pszInstallPromptTmp, szSed))
{
FileAccessErr(hDlg, szSed);
return FALSE;
}
CmFree(pszInstallPromptTmp);
pszInstallPromptTmp = NULL;
}
else
{
CMASSERTMSG(FALSE, TEXT("ConstructSedFile -- CmFmtMsg returned NULL."));
FileAccessErr(hDlg, szSed);
return FALSE;
}
//
// Clear the Target File Version Key
//
MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, c_pszTargetFileVersion,
TEXT(""), szSed));
//
// Set the Reboot Mode
//
MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, TEXT("RebootMode"), TEXT("N"),
g_szSedFile));
//
// Write the License text file into the SED. Otherwise make sure to clear it.
//
if (TEXT('\0') != g_szLicense[0])
{
//
// We write the license text file into the SED in two places. Once as a regular
// file and again using the c_pszDisplayLicense entry. Thus we copy it to the
// users profile dir and display it at install time. We want to make sure that
// we use the full file name in the SED files section, but the short file name
// in the part of the SED that actually lauches the license at install time
/// (aka the strings section).
//
TCHAR szTempName[MAX_PATH+1];
MYVERIFY (FALSE != GetShortFileName(g_szLicense, szTempName));
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"), g_szOsdir,
g_szShortServiceName, szTempName));
bReturn &= WriteSED(hDlg, g_szLicense, &iFileNum, szSed);
}
else
{
szTemp[0] = TEXT('\0');
}
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLicense,
szTemp, szSed));
//
// Add the install command to the SED file
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT(".\\cmstp.exe %s.inf"), g_szShortServiceName));
MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszAppLaunched,
szTemp, szSed));
//
// Get the System Directory path to concat to IEXPRESS and CM Files
//
TCHAR szSystemDir[MAX_PATH+1];
MYVERIFY(0 != GetSystemDirectory(szSystemDir, MAX_PATH));
//
// Begin Adding Files to the SED File. Note that all 32-bit profiles
// must include IExpress file(s)
//
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("advpack.dll"), szSystemDir, &iFileNum, szSed);
#ifndef _WIN64
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("w95inf16.dll"), g_szSupportDir, &iFileNum, szSed);
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("w95inf32.dll"), g_szSupportDir, &iFileNum, szSed);
//
// Always include cmstp.exe. Note that on x86 it comes from the binaries CAB.
//
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmstp.exe"), g_szCmBinsTempDir, &iFileNum, szSed);
#else
//
// Always include cmstp.exe. Note that on IA64 we get it from the system directory.
//
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmstp.exe"), szSystemDir, &iFileNum, szSed);
#endif
if (g_bIncludeCmCode)
{
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("instcm.inf"), g_szSupportDir, &iFileNum, szSed);
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmbins.exe"), g_szSupportDir, &iFileNum, szSed);
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmexcept.cat"), g_szSupportDir, &iFileNum, szSed);
#ifndef _WIN64
if (!(IsAlpha()))
{
//
// Add the win95 config files
//
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("ccfg95.dll"), g_szSupportDir, &iFileNum, szSed);
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cnet16.dll"), g_szSupportDir, &iFileNum, szSed);
//
// Add the Unicode to Ansi Conversion layer
//
bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmutoa.dll"), g_szSupportDir, &iFileNum, szSed);
}
#endif
}
//
// Write entry for Inf in SED
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.inf"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
//
// Write the Cmp to the Sed
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cmp"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
//
// Write the Cms to the Sed
//
MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cms"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
//
// Now include the Custom Added Files
//
bReturn &= WriteSED(hDlg, g_szPhonebk, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szRegion, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szBrandBmp, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szPhoneBmp, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szLargeIco, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szSmallIco, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szTrayIco, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szHelp, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szCmProxyFile, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szCmRouteFile, &iFileNum, szSed);
bReturn &= WriteSED(hDlg, g_szVpnFile, &iFileNum, szSed);
bReturn &=WriteSEDMenuItemFiles(hDlg, &iFileNum, szSed);
bReturn &=WriteSEDConActFiles(hDlg, &iFileNum, szSed);
bReturn &=WriteSEDExtraFiles(hDlg, &iFileNum, szSed);
bReturn &=WriteSEDRefsFiles(hDlg, &iFileNum, szSed);
bReturn &=WriteSEDDnsFiles(hDlg, &iFileNum, szSed);
return bReturn;
}
void AddAllSectionsInCurrentFileToCombo(HWND hDlg, UINT uComboId, LPCTSTR pszFile)
{
if ((NULL == hDlg) || (0 == uComboId) || (NULL == pszFile))
{
CMASSERTMSG(FALSE, TEXT("AddAllKeysInCurrentSectionToCombo -- Invalid Parameter passed."));
return;
}
//
// Reset the combobox contents
//
SendDlgItemMessage(hDlg, uComboId, CB_RESETCONTENT, 0, 0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
//
// First lets get all of the sections from the existing cmp
//
LPTSTR pszAllSections = GetPrivateProfileStringWithAlloc(NULL, NULL, TEXT(""), pszFile);
//
// Okay, now we have all of the sections in a buffer, lets add them to the combo
//
LPTSTR pszCurrentSection = pszAllSections;
while (pszCurrentSection && TEXT('\0') != pszCurrentSection[0])
{
//
// Okay, lets add all of the sections that we found
//
MYVERIFY(CB_ERR!= SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, 0, (LPARAM)pszCurrentSection));
//
// Now advance to the next string in pszAllSections
//
pszCurrentSection = pszCurrentSection + lstrlen(pszCurrentSection) + 1;
}
CmFree(pszAllSections);
}
void AddFilesToCombo(HWND hDlg, UINT uComboId)
{
//
// Reset the combobox contents
//
SendDlgItemMessage(hDlg, uComboId, CB_RESETCONTENT, 0, 0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
//
// Add the profile cmp
//
LRESULT lResult = SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, (WPARAM)0, (LPARAM)GetName(g_szCmpFile));
if (CB_ERR != lResult)
{
SendDlgItemMessage(hDlg, uComboId, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)g_szCmpFile);
}
else
{
CMASSERTMSG(FALSE, TEXT("AddFilesToCombo -- unable to set item data"));
}
//
// Add the profile cms
//
lResult = SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, (WPARAM)0, (LPARAM)GetName(g_szCmsFile));
if (CB_ERR != lResult)
{
SendDlgItemMessage(hDlg, uComboId, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)g_szCmsFile);
}
else
{
CMASSERTMSG(FALSE, TEXT("AddFilesToCombo -- unable to set item data"));
}
}
BOOL GetCurrentComboSelectionAlloc(HWND hDlg, UINT uComboId, LPTSTR* ppszText)
{
if ((NULL == hDlg) || (0 == uComboId) || (NULL == ppszText))
{
CMASSERTMSG(FALSE, TEXT("GetCurrentComboSelectionAlloc -- invalid parameter"));
return FALSE;
}
*ppszText = NULL;
LRESULT lTextLen;
BOOL bReturn = FALSE;
LRESULT lResult = SendDlgItemMessage(hDlg, uComboId, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
if (CB_ERR != lResult)
{
lTextLen = SendDlgItemMessage(hDlg, uComboId, CB_GETLBTEXTLEN, (WPARAM)lResult, (LPARAM)0);
if (0 != lTextLen)
{
lTextLen++; // NULL char
*ppszText = (LPTSTR)CmMalloc(sizeof(TCHAR)*lTextLen);
if (*ppszText)
{
lResult = SendDlgItemMessage(hDlg, uComboId, CB_GETLBTEXT, (WPARAM)lResult, (LPARAM)(*ppszText));
if (0 == lResult)
{
goto exit;
}
else
{
bReturn = TRUE;
}
}
else
{
goto exit;
}
}
else
{
goto exit;
}
}
else
{
goto exit;
}
exit:
if (FALSE == bReturn)
{
CmFree(*ppszText);
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: GetCurrentEditControlTextAlloc
//
// Synopsis: Figures out the length of the text in the edit control specified
// by the given window handle, allocates a buffer large enough to
// hold the text and then retrieves the text and stores it in the
// allocated buffer. The buffer is the caller's responsibility to
// free. Note that we ensure the data is roundtripable.
//
// Arguments: HWND hEditText - window handle of the edit control to get the text from
// LPTSTR* ppszText - pointer to a string pointer to recieve the output buffer
//
// Returns: int - Returns the number of characters copied to *ppszText
// 0 could be an error value but often means the control is empty
// -1 means that the text failed MBCS conversion and should not be used
//
// History: quintinb Created 04/07/00
//
//+----------------------------------------------------------------------------
int GetCurrentEditControlTextAlloc(HWND hEditText, LPTSTR* ppszText)
{
if ((NULL == hEditText) || (NULL == ppszText))
{
CMASSERTMSG(FALSE, TEXT("GetCurrentEditControlTextAlloc -- invalid parameter"));
return 0;
}
*ppszText = NULL;
int iReturn = 0;
LRESULT lResult;
LRESULT lTextLen = SendMessage(hEditText, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
if (0 != lTextLen)
{
lTextLen++; // NULL char
*ppszText = (LPTSTR)CmMalloc(sizeof(TCHAR)*lTextLen);
if (*ppszText)
{
lResult = SendMessage(hEditText, WM_GETTEXT, (WPARAM)lTextLen, (LPARAM)(*ppszText));
if (0 == lResult)
{
goto exit;
}
else
{
#ifdef UNICODE
//
// We want to make sure that we can convert the strings to MBCS. If we cannot then we are not
// going to be able to store the string in the our ANSI data files (.cms, .cmp, .inf, etc.).
// Thus we need to convert the string to MBCS and then back to UNICODE. We will then compare the original
// string to the resultant string and see if they match.
//
if (!TextIsRoundTripable(*ppszText, TRUE))
{
//
// Set the return code to an error value.
//
iReturn = -1;
goto exit;
}
#endif
iReturn = (int)lResult;
}
}
else
{
goto exit;
}
}
else
{
goto exit;
}
exit:
if ((0 == iReturn) || (-1 == iReturn))
{
CmFree(*ppszText);
*ppszText = NULL;
}
return iReturn;
}
//+----------------------------------------------------------------------------
//
// Function: RemoveBracketsFromSectionString
//
// Synopsis: Removes brackets from section string. If a string is
// invalid, this function returns a newly allocated
// valid string without brackets and deleted the old invalid one.
// If there are no valid characters in the string this function
// return NULL in ppszSection. It is the caller's responibility to
// free the string.
// This function was created to fix Bug 189379 for Whistler.
//
// Arguments: LPTSTR *ppszSection - pointer to the address of the string
//
// History: tomkel Created 11/15/2000
//
//+----------------------------------------------------------------------------
BOOL RemoveBracketsFromSectionString(LPTSTR *ppszSection)
{
BOOL bReturn = FALSE;
LPTSTR pszSection = NULL;
const TCHAR* const c_szBadSectionChars = TEXT("[]");
const TCHAR* const c_szLeftBracket = TEXT("[");
const TCHAR* const c_szRightBracket = TEXT("]");
if (NULL == ppszSection)
{
return bReturn;
}
pszSection = *ppszSection;
if (NULL != pszSection)
{
LPTSTR pszValidSection = NULL;
LPTSTR pszToken = NULL;
//
// We have a string so try to find an occurence of a bracket [].
//
if (CmStrStr(pszSection, c_szLeftBracket) || CmStrStr(pszSection, c_szRightBracket))
{
//
// The pszSection string contains brackets.
// This treats brackets [] as delimiters. The loop concatenates the newly
// valid string.
//
pszToken = CmStrtok(pszSection, c_szBadSectionChars);
if (NULL != pszToken)
{
//
// Found at least one valid token
//
while (NULL != pszToken)
{
if (NULL == pszValidSection)
{
pszValidSection = CmStrCpyAlloc(pszToken);
}
else
{
pszValidSection = CmStrCatAlloc(&pszValidSection, pszToken);
}
//
// Find the next valid token
//
pszToken = CmStrtok(NULL, c_szBadSectionChars);
}
if ( pszValidSection )
{
//
// We encountered brackets []. Lets copy the valid string back to
// pszSection string so that the code below this section doesn't
// need to be modified.
//
CmFree(pszSection);
pszSection = CmStrCpyAlloc(pszValidSection);
CmFree(pszValidSection);
pszValidSection = NULL;
}
}
else
{
//
// There are no valid tokens. Delete the string and set it to NULL.
//
CmFree(pszSection);
pszSection = NULL;
}
*ppszSection = pszSection;
bReturn = TRUE;
}
else
{
//
// Nothing to parse, which is ok.
//
bReturn = TRUE;
}
}
else
{
//
// Nothing to parse, which is ok.
//
bReturn = TRUE;
}
return bReturn;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessGeekPane
//
// Synopsis: Processes windows messages for the dialog which allows user to
// edit the cms/cmp files directly for features not exposed in CMAK
// directly.
//
// Arguments: WND hDlg - dialog window handle
// UINT message - message identifier
// WPARAM wParam - wParam Value
// LPARAM lParam - lParam Value
//
//
// History: quintinb Created 03/26/00
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessGeekPane(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
SetDefaultGUIFont(hDlg, message, IDC_EDIT1);
SetDefaultGUIFont(hDlg, message, IDC_COMBO1);
SetDefaultGUIFont(hDlg, message, IDC_COMBO2);
SetDefaultGUIFont(hDlg, message, IDC_COMBO3);
LRESULT lResult;
static LPTSTR pszFile = NULL;
static LPTSTR pszSection = NULL;
static LPTSTR pszKey = NULL;
LPTSTR pszValue = NULL;
HWND hControl;
static HWND hwndSectionEditControl = NULL;
static HWND hwndKeyEditControl = NULL;
COMBOBOXINFO cbInfo;
NMHDR* pnmHeader = (NMHDR*)lParam;
DWORD dwFinishPage;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ADVANCED)) return TRUE;
if (ProcessCancel(hDlg,message,lParam))
{
if (0 == GetWindowLongPtr(hDlg, DWLP_MSGRESULT))
{
//
// If the user accepted the cancel then the DWLP_MSGRESULT value will be FALSE. If
// they chose to deny the cancel it will be TRUE. Thus if we need to, let's free
// up any allocated resources. If you change the free code, make sure to change
// it below in the kill active state too.
//
CmFree(pszSection);
pszSection = NULL;
CmFree(pszKey);
pszKey = NULL;
}
return TRUE;
}
switch (message)
{
case WM_INITDIALOG:
//
// Fill in the files combo
//
AddFilesToCombo(hDlg, IDC_COMBO1);
//
// Choose the Cms File because it is the one they are most likely to edit
//
lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)GetName(g_szCmsFile));
if (CB_ERR != lResult)
{
MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0));
}
pszFile = g_szCmsFile;
AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
//
// Choose the first section in the list, don't assert because there may not be any
//
SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
if (GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection))
{
AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
//
// Choose the first key in the list, don't assert because there may not be any
//
SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
//
// Finally fill in the edit control
//
pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
if (pszValue)
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
CmFree(pszValue);
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
}
//
// Now lets get the window handles to the edit control portion of the section and key combobox controls
//
ZeroMemory(&cbInfo, sizeof(cbInfo));
cbInfo.cbSize = sizeof(cbInfo);
hControl = GetDlgItem(hDlg, IDC_COMBO2);
if (hControl)
{
if (GetComboBoxInfo (hControl, &cbInfo))
{
hwndSectionEditControl = cbInfo.hwndItem;
}
}
ZeroMemory(&cbInfo, sizeof(cbInfo));
cbInfo.cbSize = sizeof(cbInfo);
hControl = GetDlgItem(hDlg, IDC_COMBO3);
if (hControl)
{
if (GetComboBoxInfo (hControl, &cbInfo))
{
hwndKeyEditControl = cbInfo.hwndItem;
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_COMBO1:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
if (CB_ERR != lResult)
{
pszFile = (LPTSTR)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETITEMDATA, (WPARAM)lResult, (LPARAM)0);
if (NULL != pszFile)
{
AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
//
// Choose the first section in the list, don't assert because there may not be any
//
SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
}
}
//
// Note that we don't break here, we fail through to pick up changes for the
// section and keys combo boxes
//
}
else
{
break;
}
case IDC_COMBO2:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
CmFree(pszSection);
GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection);
AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
//
// Choose the first key in the list, don't assert because there may not be any
//
SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
}
else if (HIWORD(wParam) == CBN_EDITCHANGE)
{
CmFree(pszSection);
if (-1 != GetCurrentEditControlTextAlloc(hwndSectionEditControl, &pszSection))
{
AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
//
// Choose the first key in the list, don't assert because there may not be any
//
SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
}
else
{
break;
}
}
else
{
//
// Note we don't break if the message is CBN_SELCHANGE or CBN_EDITCHANGE because
// we want to execute the code for the key combo changing
//
break;
}
case IDC_COMBO3:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
CmFree(pszKey);
GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
//
// Fill in the edit control
//
if (pszKey)
{
pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
if (pszValue)
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
CmFree(pszValue);
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
}
else if (HIWORD(wParam) == CBN_EDITCHANGE)
{
CmFree(pszKey);
if (-1 != GetCurrentEditControlTextAlloc(hwndKeyEditControl, &pszKey))
{
//
// Fill in the edit control
//
if (pszKey)
{
pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
if (pszValue)
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
CmFree(pszValue);
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
}
else
{
break;
}
}
break;
case IDC_BUTTON1: // Update Value
if (RemoveBracketsFromSectionString(&pszSection))
{
//
// Successfully removed brackets. Check if the valid string is empty. If so clear
// the fields
//
if (NULL == pszSection)
{
//
// The section string contained all invalid characters, so clear the combobox
//
lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
//
// Clear the other edit boxes by sending a CBN_EDITCHANGE notification
//
hControl = GetDlgItem(hDlg,IDC_COMBO2);
if (hControl)
{
lResult= SendMessage(hDlg, WM_COMMAND, (WPARAM)MAKEWPARAM((WORD)IDC_COMBO2,(WORD)CBN_EDITCHANGE), (LPARAM)hControl);
}
}
}
else
{
CMASSERTMSG(FALSE, TEXT("ProcessGeekPane -- Trying to remove brackets from invalid section string."));
return 1;
}
hControl = GetDlgItem(hDlg, IDC_EDIT1);
if (hControl)
{
int iReturn = GetCurrentEditControlTextAlloc(hControl, &pszValue);
if (0 == iReturn)
{
pszValue = NULL; // delete the value
}
else if (-1 == iReturn)
{
return 1;
}
}
else
{
CMASSERTMSG(FALSE, TEXT("ProcessGeekPane -- Unable to get the window handle for the text control."));
return 1;
}
if (NULL == pszSection)
{
ShowMessage(hDlg, IDS_NEED_SECTION, MB_OK);
return 1;
}
else if (NULL == pszKey)
{
int iReturn = IDNO;
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_DELETE_SECTION, pszSection);
if (pszMsg)
{
iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
CmFree(pszMsg);
}
if (IDNO == iReturn)
{
return 1;
}
//
// Need to clear the value in case the section is NULL and the value isn't
// even though the WritePrivateProfileString handles it correctly
//
CmFree(pszValue);
pszValue = NULL;
}
else if (NULL == pszValue)
{
//
// This else if needs to be the last one
// The following message should only be displayed
// if NULL != pszKey && NULL != pszSection && NULL == pszValue
// Prompt user to ask to delete this key.
//
int iReturn = IDNO;
LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_DELETE_KEY, pszKey);
if (pszMsg)
{
iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
CmFree(pszMsg);
}
if (IDNO == iReturn)
{
return 1;
}
}
MYVERIFY(0 != WritePrivateProfileString(pszSection, pszKey, pszValue, pszFile));
CmFree(pszValue);
//
// Make sure to reselect the section and key the user had before (especially important
// if the user just added a new section or file). First add all of the sections
//
AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
//
// Select the correct section
//
lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszSection);
if (CB_ERR == lResult)
{
//
// Then the user deleted the value, lets select the first in the list
//
CmFree(pszSection);
SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection);
}
else
{
SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
}
//
// Now add all of the keys in that section
//
AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
//
// Select the correct key
//
lResult = SendDlgItemMessage(hDlg, IDC_COMBO3, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszKey);
if (CB_ERR == lResult)
{
//
// Then the user deleted the value, lets select the first in the list
//
CmFree(pszKey);
SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
lResult = 0;
}
else
{
SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
}
//
// Fill in the edit control, since the user may have deleted the last selection
//
pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
if (pszValue)
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
CmFree(pszValue);
}
else
{
SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
}
break;
default:
break;
}
break;
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
//
// Free up any allocated values. If you add new values to free here, also
// make sure to add them in the cancel case.
//
CmFree(pszSection);
pszSection = NULL;
CmFree(pszKey);
pszKey = NULL;
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
break;
case PSN_WIZBACK:
CMASSERTMSG(FALSE, TEXT("There shouldn't be a back button on the Geek Pane, why are we getting PSN_WIZBACK?"));
break;
case PSN_WIZNEXT:
if (BuildProfileExecutable(hDlg))
{
dwFinishPage = g_bIEAKBuild ? IDD_IEAK_FINISH_GOOD_BUILD : IDD_FINISH_GOOD_BUILD;
}
else
{
dwFinishPage = IDD_FINISH_BAD_BUILD;
}
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, dwFinishPage));
return 1;
break;
}
break;
default:
return FALSE;
}
return FALSE;
}
//+----------------------------------------------------------------------------
//
// Function: BuildProfileExecutable
//
// Synopsis: This function takes care of all of the details of turning the
// CMAK files in the temp dir into a profile executable.
//
// Arguments: HWND hDlg - window handle of the calling dialog
//
// Returns: BOOL - TRUE if the profile built successfully, FALSE otherwise
//
// History: quintinb Created 05/17/00
//
//+----------------------------------------------------------------------------
BOOL BuildProfileExecutable(HWND hDlg)
{
DWORD dwExitCode = 0;
DWORD dwWaitCode = 0;
BOOL bExitLoop = FALSE;
BOOL bEnoughSpaceToCompress;
SHELLEXECUTEINFO seiInfo;
static HANDLE hProcess = NULL;
TCHAR szTemp[MAX_PATH+1];
TCHAR szMsg[MAX_PATH+1];
TCHAR pszArgs[MAX_PATH+1];
BOOL bRes;
//
// The user may have unchecked UsePresharedKey for all VPN settings, in
// which case we need to remove the pre-shared key.
//
g_bPresharedKeyNeeded = DoesSomeVPNsettingUsePresharedKey();
if (FALSE == g_bPresharedKeyNeeded)
{
// remove the Pre-shared key values from the CMP
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPresharedKey, NULL, g_szCmpFile));
MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryKeyIsEncrypted, NULL, g_szCmpFile));
}
if (!CopyFromTempDir(g_szShortServiceName))
{
return FALSE;
}
//
// Write the SED File.
// Note that the SED file has been moved from the temp dir to
// the profile dir. We now want to write the SED file entries
// in place before compressing them. This way we can verify the
// files exist right before compressing them.
//
MYVERIFY(CELEMS(g_szSedFile) > (UINT)wsprintf(g_szSedFile, TEXT("%s%s\\%s.sed"),
g_szOsdir, g_szShortServiceName, g_szShortServiceName));
if (!ConstructSedFile(hDlg, g_szSedFile, g_szOutExe))
{
return FALSE;
}
_tcscpy(g_szOutdir, g_szOsdir);
_tcscat(g_szOutdir, g_szShortServiceName);
//
// Setup IExpress to build in the output directory.
//
MYVERIFY(0 != SetCurrentDirectory(g_szOutdir));
//
// Check to make sure there is enough disk space
//
do
{
bEnoughSpaceToCompress = CheckDiskSpaceForCompression(g_szSedFile);
if (!bEnoughSpaceToCompress)
{
MYVERIFY(0 != LoadString(g_hInstance, IDS_DISKFULL, szTemp, MAX_PATH));
MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, g_szOutdir));
int iMessageReturn = MessageBox(hDlg, szMsg, g_szAppTitle, MB_RETRYCANCEL | MB_ICONERROR
| MB_APPLMODAL );
if (iMessageReturn == IDCANCEL)
{
return FALSE;
}
}
} while(!bEnoughSpaceToCompress);
MYVERIFY(CELEMS(pszArgs) > (UINT)wsprintf(pszArgs, TEXT("/N %s.sed"),
g_szShortServiceName));
_tcscpy(szTemp, TEXT("iexpress.exe"));
ZeroMemory(&seiInfo,sizeof(seiInfo));
seiInfo.cbSize = sizeof(seiInfo);
seiInfo.fMask |= SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
seiInfo.lpFile = szTemp;
seiInfo.lpDirectory = g_szOutdir;
seiInfo.lpParameters = pszArgs;
seiInfo.nShow = SW_HIDE;
//
// Okay, we are finally ready to execute IExpress, lets disable all the
// wizard buttons.
//
DisableWizardButtons(hDlg);
//
// Execute IExpress
//
bRes = ShellExecuteEx(&seiInfo);
//
// Wait for the shellexecute to finish. Thus our cleanup code doesn't
// execute till IEpress is done.
//
if (bRes)
{
//
// hProcess contains the handle to the process
//
hProcess = seiInfo.hProcess;
do
{
dwWaitCode = MsgWaitForMultipleObjects(1, &hProcess, FALSE, INFINITE, QS_ALLINPUT);
//
// Check to see if we returned because of a message, process termination,
// or an error.
//
switch(dwWaitCode)
{
case 0:
//
// Normal termination case, we were signaled that the process ended
//
bExitLoop = TRUE;
break;
case 1:
HandleWindowMessagesWhileCompressing();
break;
case -1:
//
// MsgWait returned an error
//
MYVERIFY(0 != GetExitCodeProcess(seiInfo.hProcess, &dwExitCode));
if (dwExitCode == STILL_ACTIVE)
{
continue;
}
else
{
bExitLoop = TRUE;
}
break;
default:
//
// Do nothing
//
break;
}
} while (!bExitLoop);
}
//
// now need to send the user to the finish page. If their profile
// build successfully then we send them to the success page, otherwise
// we send them to the bad build page.
//
MYVERIFY(0 != GetExitCodeProcess(seiInfo.hProcess, &dwExitCode));
if (dwExitCode)
{
g_iCMAKReturnVal = CMAK_RETURN_ERROR;
//
// We encountered an error, clear the out exe val
// so that we write nothing to the output key.
//
ZeroMemory(g_szOutExe, sizeof(g_szOutExe));
}
else
{
g_iCMAKReturnVal = CMAK_RETURN_SUCCESS;
}
CloseHandle(seiInfo.hProcess);
//
// Create a registry entry for IEAK to retrieve
// the path of the output profile.
//
MYVERIFY(FALSE != WriteRegStringValue(HKEY_LOCAL_MACHINE, c_pszRegCmak, c_pszRegOutput, g_szOutExe));
//
// CMAK_RETURN_ERROR is -1, so return TRUE if g_iCMAKReturnVal is a positive integer
//
return (g_iCMAKReturnVal > 0);
}
//+----------------------------------------------------------------------------
//
// Function: ProcessBuildProfile
//
// Synopsis: Processes windows messages for the page in CMAK that allows the
// user to build their profile or advance to the Advanced Customization
// page to make final edits before building the profile.
//
// WM_INITDIALOG - intializes the page
// WM_NOTIFY - processes the notifications sent to the page
//
// Specify the installation package location
//
// Arguments: WND hDlg -
// UINT message -
// WPARAM wParam -
// LPARAM lParam -
//
// Returns: INT_PTR APIENTRY -
//
// History: a-anasj restructured the function and Created Header 1/7/98
// note: the function does not allow the user to choose a location for
// their profile anylonger. It only informs them of where it will be
// created.
// quintinb Renamed from the feared ProcessPage8 8-6-98
// quintinb restructured for Whistler 108269 05/17/00
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessBuildProfile(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szTemp[MAX_PATH+1];
int iMessageReturn;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CREATE)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
switch (message)
{
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_KILLACTIVE:
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
return 1;
break; //lint !e527 this line isn't reachable but
// keep it in case the return is removed
case PSN_SETACTIVE:
//
// Build default path of final executable
//
MYVERIFY(CELEMS(g_szOutExe) > (UINT)wsprintf(g_szOutExe, TEXT("%s%s\\%s.exe"),
g_szOsdir, g_szShortServiceName, g_szShortServiceName));
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_BACK | PSWIZB_NEXT));
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
//
// Ensure that profile directory exists
//
_tcscpy(szTemp,g_szOsdir);
_tcscat(szTemp,g_szShortServiceName);
if (0 == SetCurrentDirectory(szTemp))
{
MYVERIFY(0 != CreateDirectory(szTemp,NULL));
}
//
// Prompt the user to overwrite the existing Executable
//
if (FileExists(g_szOutExe))
{
iMessageReturn = ShowMessage(hDlg, IDS_OVERWRITE, MB_YESNO);
if (iMessageReturn == IDNO)
{
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
}
//
// Write out the Inf File
//
if (!WriteInfFile(g_hInstance, hDlg, g_szInfFile, g_szLongServiceName))
{
CMASSERTMSG(FALSE, TEXT("ProcessBuildProfile -- WriteInfFile Failed."));
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// Update version in CMP and party on the CMS
//
WriteCMPFile();
if (!WriteCMSFile())
{
FileAccessErr(hDlg, g_szCmsFile);
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
return 1;
}
//
// If the user wants to do advanced customization, delay building the profile executable
// until after they have done their final edits. Otherwise, it is time to build the profile!
//
if (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ADVANCED))
{
//
// The user is finished now, lets build the profile and skip over the advanced customization
// page to either the bad build page or the successful build page.
//
DWORD dwFinishPage;
if (BuildProfileExecutable(hDlg))
{
dwFinishPage = g_bIEAKBuild ? IDD_IEAK_FINISH_GOOD_BUILD : IDD_FINISH_GOOD_BUILD;
}
else
{
dwFinishPage = IDD_FINISH_BAD_BUILD;
}
MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, dwFinishPage));
return 1;
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: ProcessFinishPage
//
// Synopsis: Handles the finish page
//
// Arguments: WND hDlg -
// UINT message -
// WPARAM wParam -
// LPARAM lParam -
//
// Returns: INT_PTR APIENTRY -
//
// History: quintinb created 6/25/98
//
//+----------------------------------------------------------------------------
INT_PTR APIENTRY ProcessFinishPage(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HWND hDirEditControl;
HWND hCurrentPage;
NMHDR* pnmHeader = (NMHDR*)lParam;
ProcessBold(hDlg,message);
if (ProcessHelp(hDlg, message, wParam, lParam, IDH_FINISH)) return TRUE;
if (ProcessCancel(hDlg,message,lParam)) return TRUE;
SetDefaultGUIFont(hDlg,message,IDC_EDITDIR);
switch (message)
{
case WM_NOTIFY:
if (NULL == pnmHeader)
{
return FALSE;
}
switch (pnmHeader->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_FINISH));
//
// Disable the cancel button since it doesn't make a whole lot of
// sense on the last dialog.
//
hCurrentPage = GetParent(hDlg);
if (hCurrentPage)
{
HWND hCancelButton = GetDlgItem(hCurrentPage, IDCANCEL);
if (hCancelButton)
{
EnableWindow(hCancelButton, FALSE);
}
}
//
// Fill in the path edit control. Note that this control doesn't exist if
// this is an IEAK build.
//
if (hDirEditControl = GetDlgItem(hDlg, IDC_EDITDIR))
{
MYVERIFY(TRUE == SendMessage(hDirEditControl, WM_SETTEXT, 0,
(LPARAM)g_szOutExe));
}
break;
case PSN_WIZFINISH:
//
// Now that we know we aren't returning, we can release
// the temp dir and cleanup our files lists
//
ClearCmakGlobals();
FreeList(&g_pHeadProfile, &g_pTailProfile);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//
//
// FUNCTION: FillInPropertyPage(PROPSHEETPAGE *, int, LPTSTR, LPFN)
//
// PURPOSE: Fills in the given PROPSHEETPAGE structure
//
// COMMENTS:
//
// This function fills in a PROPSHEETPAGE structure with the
// information the system needs to create the page.
//
void FillInPropertyPage( PROPSHEETPAGE* psp, int idDlg, DLGPROC pfnDlgProc)
{
psp->dwSize = sizeof(PROPSHEETPAGE);
psp->dwFlags = PSP_HASHELP;
psp->hInstance = g_hInstance;
psp->pszTemplate = MAKEINTRESOURCE(idDlg);
psp->pszIcon = NULL;
psp->pfnDlgProc = pfnDlgProc;
psp->pszTitle = TEXT("");
psp->lParam = 0;
}
//+----------------------------------------------------------------------------
//
// Function: CreateWizard
//
// Synopsis: This function creates the wizard pages that make up CMAK.
//
// Arguments: HWND hwndOwner - window handle of the owner of this wizard
//
// Returns: int - A positive value if successful, -1 otherwise
//
// History: quintinb Created Header 1/5/98
// quintinb removed hInst from prototype, not used 1/5/98
//
//+----------------------------------------------------------------------------
INT_PTR CreateWizard(HWND hwndOwner)
{
PROPSHEETPAGE psp[28];
PROPSHEETHEADER psh;
FillInPropertyPage( &psp[0], IDD_WELCOME, ProcessWelcome);
FillInPropertyPage( &psp[1], IDD_ADD_EDIT_PROFILE, ProcessAddEditProfile);
FillInPropertyPage( &psp[2], IDD_SERVICENAME, ProcessServiceName);
FillInPropertyPage( &psp[3], IDD_REALM_INFO, ProcessRealmInfo);
FillInPropertyPage( &psp[4], IDD_MERGEDPROFILES, ProcessMergedProfiles);
FillInPropertyPage( &psp[5], IDD_TUNNELING, ProcessTunneling);
FillInPropertyPage( &psp[6], IDD_VPN_ENTRIES, ProcessVpnEntries);
FillInPropertyPage( &psp[7], IDD_PRESHARED_KEY, ProcessPresharedKey);
FillInPropertyPage( &psp[8], IDD_PHONEBOOK, ProcessPhoneBook); // Phonebook Setup
FillInPropertyPage( &psp[9], IDD_PBK_UPDATE, ProcessPhoneBookUpdate); // Phonebook Updates
FillInPropertyPage( &psp[10], IDD_DUN_ENTRIES, ProcessDunEntries);
FillInPropertyPage( &psp[11], IDD_ROUTE_PLUMBING, ProcessRoutePlumbing);
FillInPropertyPage( &psp[12], IDD_CMPROXY, ProcessCmProxy);
FillInPropertyPage( &psp[13], IDD_CUSTOM_ACTIONS , ProcessCustomActions); // Setup Connect Actions
FillInPropertyPage( &psp[14], IDD_SIGNIN_BITMAP, ProcessSigninBitmap); // Sign-in Bitmap
FillInPropertyPage( &psp[15], IDD_PBK_BITMAP, ProcessPhoneBookBitmap); // Phonebook Bitmap
FillInPropertyPage( &psp[16], IDD_ICONS, ProcessIcons); // Icons
FillInPropertyPage( &psp[17], IDD_STATUS_MENU, ProcessStatusMenuIcons); // Status area menu items
FillInPropertyPage( &psp[18], IDD_CUSTOM_HELP, ProcessCustomHelp); // Help
FillInPropertyPage( &psp[19], IDD_SUPPORT_INFO, ProcessSupportInfo);
FillInPropertyPage( &psp[20], IDD_INCLUDE_CM, ProcessIncludeCm); // Include CM, note this doesn't show on IA64
FillInPropertyPage( &psp[21], IDD_LICENSE, ProcessLicense); // License agreement
FillInPropertyPage( &psp[22], IDD_ADDITIONAL, ProcessAdditionalFiles); // Additional files
FillInPropertyPage( &psp[23], IDD_BUILDPROFILE, ProcessBuildProfile); // Build the profile
FillInPropertyPage( &psp[24], IDD_GEEK_PANE, ProcessGeekPane); // Advance customization
FillInPropertyPage( &psp[25], IDD_FINISH_GOOD_BUILD, ProcessFinishPage); // Finish Page -- Good Build
FillInPropertyPage( &psp[26], IDD_IEAK_FINISH_GOOD_BUILD, ProcessFinishPage); // Finish Page -- Good Build
FillInPropertyPage( &psp[27], IDD_FINISH_BAD_BUILD, ProcessFinishPage); // Finish Page -- Bad Build
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
psh.hwndParent = hwndOwner;
psh.pszCaption = (LPTSTR) TEXT("");
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE) &psp[0]; //lint !e545 Disables line error 545 for this line only
return (PropertySheet(&psh));
}