//+---------------------------------------------------------------------------- // // 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 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\ 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 \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 \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 into the post install command so that showicon isn't a problem // on an upgrade. // MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, TEXT("PostInstallCmd"), TEXT(""), 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)); }