Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

16578 lines
574 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: profwiz.cpp
  4. //
  5. // Module: CMAK.EXE
  6. //
  7. // Synopsis: Main code for CMAK
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation
  10. //
  11. // Author: a-frankh Created 05/15/97
  12. // quintinb Updated header and made a 08/07/98
  13. // few other changes
  14. //
  15. //+----------------------------------------------------------------------------
  16. #include "cmmaster.h"
  17. #include "cmsecure.h"
  18. // linkdll is needed because of cmsecure
  19. #include "linkdll.h" // LinkToDll and BindLinkage
  20. #include "linkdll.cpp" // LinkToDll and BindLinkage
  21. //
  22. // Include HasSpecifiedAccessToFileOrDir
  23. //
  24. #ifndef CreateFileU
  25. #ifdef UNICODE
  26. #define CreateFileU CreateFileW
  27. #else
  28. #define CreateFileU CreateFileA
  29. #endif
  30. #endif
  31. #include "hasfileaccess.cpp"
  32. #include "gppswithalloc.cpp"
  33. //
  34. // Globals
  35. //
  36. //
  37. // This global specifies what the return value of CMAK should be. Note that if the user
  38. // cancels the wizard this value isn't used and FALSE (0) is returned by the wizard code.
  39. //
  40. int g_iCMAKReturnVal = CMAK_RETURN_CANCEL;
  41. //
  42. // This was added for shipping with IEAK. If the /o command line switch is specified this
  43. // bool is set to true and we don't show the finish dialog (either one).
  44. //
  45. BOOL g_bIEAKBuild = FALSE;
  46. const TCHAR* const g_szBadFilenameChars = TEXT("!@#$%^&*(){}[]+=,;:?/\\'\"`~|<>. ");
  47. const TCHAR* const g_szBadLongServiceNameChars = TEXT("*/\\:?\"<>|[]");
  48. const TCHAR* const c_pszDoNotShowLcidMisMatchDialog = TEXT("DoNotShowLcidMisMatchDialog");
  49. TCHAR g_szInfFile[MAX_PATH+1]; // full path/filename of working inf file
  50. TCHAR g_szCmakdir[MAX_PATH+1]; // full path of working inf file (includes ending slash)
  51. TCHAR g_szOsdir[MAX_PATH+1]; // full path of platform branch (includes ending slash)
  52. TCHAR g_szSedFile[MAX_PATH+1]; // full path of working sed file
  53. TCHAR g_szCmsFile[MAX_PATH+1];
  54. TCHAR g_szCmpFile[MAX_PATH+1];
  55. TCHAR g_szSupportDir[MAX_PATH+1]; // full path of support files are located
  56. TCHAR g_szTempDir[MAX_PATH+1];
  57. TCHAR g_szLastBrowsePath[MAX_PATH+1] = {0};
  58. TCHAR g_szShortServiceName[MAX_PATH+1];
  59. TCHAR g_szLongServiceName[MAX_PATH+1];
  60. TCHAR g_szBrandBmp[MAX_PATH+1];
  61. TCHAR g_szPhoneBmp[MAX_PATH+1];
  62. TCHAR g_szLargeIco[MAX_PATH+1];
  63. TCHAR g_szSmallIco[MAX_PATH+1];
  64. TCHAR g_szTrayIco[MAX_PATH+1];
  65. TCHAR g_szPhonebk[MAX_PATH+1];
  66. TCHAR g_szRegion[MAX_PATH+1];
  67. TCHAR g_szHelp[MAX_PATH+1];
  68. TCHAR g_szOutdir[MAX_PATH+1];
  69. TCHAR g_szUrl[MAX_PATH+1];
  70. TCHAR g_szOutExe[MAX_PATH+1];
  71. TCHAR g_szSvcMsg[MAX_PATH+1];
  72. TCHAR g_szPrefix[MAX_PATH+1];
  73. TCHAR g_szSuffix[MAX_PATH+1];
  74. TCHAR g_szLicense[MAX_PATH+1];
  75. TCHAR g_szPhoneName[MAX_PATH+1];
  76. TCHAR g_szAppTitle[MAX_PATH+1];
  77. TCHAR g_szCmProxyFile[MAX_PATH+1];
  78. TCHAR g_szCmRouteFile[MAX_PATH+1];
  79. TCHAR g_szVpnFile[MAX_PATH+1];
  80. BOOL g_bNewProfile = TRUE;
  81. BOOL g_bUseTunneling = FALSE;
  82. BOOL g_bUseSamePwd = FALSE;
  83. BOOL g_bUpdatePhonebook = FALSE;
  84. BOOL g_bPresharedKeyNeeded = FALSE;
  85. #ifdef _WIN64
  86. BOOL g_bIncludeCmCode = FALSE; // don't include CM code on IA64
  87. #else
  88. TCHAR g_szCmBinsTempDir[MAX_PATH+1] = {0};
  89. BOOL g_bIncludeCmCode = TRUE;
  90. #endif
  91. HINSTANCE g_hInstance;
  92. ListBxList * g_pHeadDunEntry=NULL;
  93. ListBxList * g_pTailDunEntry=NULL;
  94. ListBxList * g_pHeadVpnEntry=NULL;
  95. ListBxList * g_pTailVpnEntry=NULL;
  96. ListBxList * g_pHeadProfile=NULL;
  97. ListBxList * g_pTailProfile=NULL;
  98. ListBxList * g_pHeadExtra=NULL;
  99. ListBxList * g_pTailExtra=NULL;
  100. ListBxList * g_pHeadMerge=NULL;
  101. ListBxList * g_pTailMerge=NULL;
  102. ListBxList * g_pHeadRefs=NULL;
  103. ListBxList * g_pTailRefs=NULL;
  104. ListBxList * g_pHeadRename=NULL;
  105. ListBxList * g_pTailRename=NULL;
  106. CustomActionList* g_pCustomActionList = NULL;
  107. IconMenu * g_pHeadIcon;
  108. IconMenu * g_pTailIcon;
  109. IconMenu DlgEditItem; //global used to pass info to/from dialogs
  110. //+----------------------------------------------------------------------------
  111. //
  112. // Function: TextIsRoundTripable
  113. //
  114. // Synopsis: Tests to see if the passed in text is convertables from Unicode
  115. // to ANSI and then back to Unicode again. If so returns TRUE,
  116. // else FALSE.
  117. //
  118. // Arguments: LPCTSTR pszCharBuffer - string to test
  119. // BOOL bDisplayError - whether to display an error message or not
  120. // if the text isn't roundtripable
  121. //
  122. // Returns: BOOL - TRUE if the roundtrip was success
  123. //
  124. // History: quintinb Created Header 6/16/99
  125. //
  126. //+----------------------------------------------------------------------------
  127. BOOL TextIsRoundTripable(LPCTSTR pszCharBuffer, BOOL bDisplayError)
  128. {
  129. LPWSTR pszUnicodeBuffer = NULL;
  130. BOOL bRoundTrip = FALSE;
  131. MYDBGASSERT(pszCharBuffer);
  132. if (pszCharBuffer)
  133. {
  134. LPSTR pszAnsiBuffer = WzToSzWithAlloc(pszCharBuffer);
  135. if (pszAnsiBuffer)
  136. {
  137. pszUnicodeBuffer = SzToWzWithAlloc(pszAnsiBuffer);
  138. if (pszUnicodeBuffer && (0 == lstrcmp(pszCharBuffer, pszUnicodeBuffer)))
  139. {
  140. //
  141. // Then we were able to round trip the strings successfully
  142. // Set bRoundTrip to TRUE so that we don't throw an error.
  143. //
  144. bRoundTrip = TRUE;
  145. }
  146. CmFree(pszUnicodeBuffer);
  147. CmFree(pszAnsiBuffer);
  148. }
  149. if (!bRoundTrip && bDisplayError)
  150. {
  151. //
  152. // Throw an error message.
  153. //
  154. LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_CANNOT_ROUNDTRIP);
  155. if (pszTmp)
  156. {
  157. DWORD dwSize = lstrlen(pszTmp) + lstrlen(pszCharBuffer) + 1;
  158. LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
  159. if (pszMsg)
  160. {
  161. wsprintf(pszMsg, pszTmp, pszCharBuffer);
  162. MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
  163. CmFree(pszMsg);
  164. }
  165. CmFree(pszTmp);
  166. }
  167. }
  168. }
  169. return bRoundTrip;
  170. }
  171. //+----------------------------------------------------------------------------
  172. //
  173. // Function: GetTextFromControl
  174. //
  175. // Synopsis: This is a wrapper function that sends a WM_GETTEXT message to
  176. // the control specified by the input parameters. Once the text
  177. // is retrieved from the control, we convert it to ANSI and then
  178. // back to UNICODE so that we can compare the original Unicode
  179. // string to the round-tripped string. If these are not equal we
  180. // throw an error message, if bDisplayError is TRUE, and return
  181. // a failure value (-1). It is up to the caller to take appropriate
  182. // behavior (preventing the user from continuing, etc.)
  183. //
  184. // Arguments: IN HWND hDlg - HWND of the dialog the control is on
  185. // IN int nCtrlId - ID of the control to get text from
  186. // OUT LPTSTR pszCharBuffer - out buffer to hold the returned TEXT
  187. // IN DWORD dwCharInBuffer - numbers of chars in out buffer
  188. // BOOL bDisplayError - if TRUE display an error message if
  189. // the text isn't roundtripable
  190. //
  191. // Returns: LONG - the number of chars copied to the output buffer or -1 on error
  192. //
  193. // History: quintinb Created 6/15/99
  194. //
  195. //+----------------------------------------------------------------------------
  196. LRESULT GetTextFromControl(IN HWND hDlg, IN int nCtrlId, OUT LPTSTR pszCharBuffer, IN DWORD dwCharInBuffer, BOOL bDisplayError)
  197. {
  198. LRESULT lResult = 0;
  199. if (hDlg && nCtrlId && pszCharBuffer && dwCharInBuffer)
  200. {
  201. lResult = SendDlgItemMessage(hDlg, nCtrlId, WM_GETTEXT, (WPARAM)dwCharInBuffer, (LPARAM)pszCharBuffer);
  202. #ifdef UNICODE
  203. //
  204. // We want to make sure that we can convert the strings to MBCS. If we cannot then we are not
  205. // going to be able to store the string in the our ANSI data files (.cms, .cmp, .inf, etc.).
  206. // Thus we need to convert the string to MBCS and then back to UNICODE. We will then compare the original
  207. // string to the resultant string and see if they match.
  208. //
  209. if (TEXT('\0') != pszCharBuffer[0])
  210. {
  211. if (!TextIsRoundTripable(pszCharBuffer, bDisplayError))
  212. {
  213. //
  214. // Set the return code to an error value.
  215. //
  216. lResult = -1;
  217. }
  218. }
  219. #endif
  220. }
  221. else
  222. {
  223. CMASSERTMSG(FALSE, TEXT("Bad Parameter passed to GetTextFromControl!"));
  224. }
  225. return lResult;
  226. }
  227. //+----------------------------------------------------------------------------
  228. //
  229. // Function: FreeIconMenu
  230. //
  231. // Synopsis: This function frees the linked list of status area menu icons.
  232. //
  233. // Arguments: None
  234. //
  235. // Returns: Nothing
  236. //
  237. // History: quintinb Created Header 05/09/00
  238. //
  239. //+----------------------------------------------------------------------------
  240. void FreeIconMenu()
  241. {
  242. IconMenu * LoopPtr;
  243. IconMenu * TmpPtr;
  244. if (g_pHeadIcon == NULL)
  245. {
  246. return;
  247. }
  248. LoopPtr = g_pHeadIcon;
  249. while( LoopPtr != NULL)
  250. {
  251. TmpPtr = LoopPtr;
  252. LoopPtr = LoopPtr->next;
  253. CmFree(TmpPtr);
  254. }
  255. g_pHeadIcon = NULL;
  256. g_pTailIcon = NULL;
  257. }
  258. //+----------------------------------------------------------------------------
  259. //
  260. // Function: ReferencedDownLoad
  261. //
  262. // Synopsis: This function opens each referenced cms file to check and see if it has a
  263. // PBURL. If so, then this files is considered to do PB downloads and should
  264. // cause the top level profile to run the cmdl connect action.
  265. //
  266. // Arguments: None
  267. //
  268. // Returns: BOOL - returns whether referenced profiles need cmdl
  269. //
  270. // History: quintinb Created 2/2/98
  271. //
  272. //+----------------------------------------------------------------------------
  273. BOOL ReferencedDownLoad()
  274. {
  275. ListBxList * ptrMergeProfile = NULL;
  276. TCHAR szRefCmsFile[MAX_PATH+1];
  277. TCHAR szPbUrl[MAX_PATH+1];
  278. if (NULL == g_pHeadMerge)
  279. {
  280. return FALSE;
  281. }
  282. else
  283. {
  284. //
  285. // Enumerate the referenced profiles to try to find one that has a PBURL field.
  286. //
  287. ptrMergeProfile = g_pHeadMerge;
  288. while (NULL != ptrMergeProfile)
  289. {
  290. //
  291. // Let's try the profile directory for the merged profile in order to get the most up to date version. This
  292. // is where CMAK will pull it from if available. If not, we will fall back to the one in the temp directory.
  293. //
  294. MYVERIFY(CELEMS(szRefCmsFile) > (UINT)wsprintf(szRefCmsFile, TEXT("%s%s\\%s.cms"), g_szOsdir, ptrMergeProfile->szName, ptrMergeProfile->szName));
  295. if (!FileExists(szRefCmsFile))
  296. {
  297. //
  298. // Next check to see if the merged cms file exists in the temp dir
  299. //
  300. MYVERIFY(CELEMS(szRefCmsFile) > (UINT)wsprintf(szRefCmsFile, TEXT("%s\\%s.cms"), g_szTempDir, ptrMergeProfile->szName));
  301. }
  302. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), szPbUrl, MAX_PATH, szRefCmsFile); //lint !e534
  303. if (TEXT('\0') != szPbUrl[0])
  304. {
  305. //
  306. // Only takes one phonebook with a URL to enable referenced downloads
  307. //
  308. return TRUE;
  309. }
  310. ptrMergeProfile = ptrMergeProfile->next;
  311. }
  312. }
  313. return FALSE;
  314. }
  315. //+----------------------------------------------------------------------------
  316. //
  317. // Function: SetWindowLongWrapper
  318. //
  319. // Synopsis: This function is an error checking wrapper for the Windows API
  320. // SetWindowLong. This function returns the value that is being
  321. // overwritten by this call (if you set a the window long to a value
  322. // you are overwriting the previous value that it contained. This
  323. // previous value is the value returned by the API). If there is an
  324. // error then this function returns 0. However, the previous value
  325. // could have been 0. The only way to distinguish the two cases (an
  326. // actual error and the previous value being zero) is to call SetLastError
  327. // with a zero value. Then you can call GetLastError after the call and if
  328. // the returned error code isn't zero then we know we have an error. All
  329. // of this functionality is combined in this function.
  330. //
  331. // Arguments: HWND hWnd - handle of window to set the long var in
  332. // int nIndex - offset of value to set
  333. // LONG dwNewLong - new value
  334. //
  335. // Returns: BOOL - Returns TRUE if the call succeeded
  336. //
  337. // History: quintinb Created 1/7/98
  338. //
  339. //+----------------------------------------------------------------------------
  340. BOOL SetWindowLongWrapper(HWND hWnd, int nIndex, LONG dwNewLong )
  341. {
  342. DWORD dwError;
  343. SetLastError(0);
  344. SetWindowLongPtr(hWnd, nIndex, (LONG_PTR)dwNewLong); //lint !e534
  345. dwError = GetLastError();
  346. return (0 == dwError);
  347. }
  348. //+---------------------------------------------------------------------------
  349. //
  350. // Function: CopyFileWrapper
  351. //
  352. // Synopsis: Bundles disk full Error Handling with standard CopyFile functionality
  353. //
  354. // Arguments: lpExistingFileName -- source file of copy
  355. // lpNewFileName -- destination file of copy
  356. // bFailIfExists -- flag to tell copy to fail if file already exists
  357. //
  358. // Assumptions: This function assumes that the two filename parameters contain the
  359. // fully qualified path to the source and destination files.
  360. //
  361. // Returns: TRUE if copy was sucessful, FALSE on an error
  362. //
  363. // History: quintinb created 11/7/97
  364. //
  365. //----------------------------------------------------------------------------
  366. BOOL CopyFileWrapper(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists)
  367. {
  368. DWORD dwError;
  369. int nMessageReturn = 0;
  370. TCHAR szMsg[2*MAX_PATH+1];
  371. TCHAR szTemp[MAX_PATH+1];
  372. TCHAR szPath[MAX_PATH+1];
  373. do {
  374. if (!CopyFile(lpExistingFileName, lpNewFileName, bFailIfExists))
  375. {
  376. //
  377. // The CopyFile failed, best check error codes
  378. //
  379. dwError = GetLastError();
  380. switch(dwError)
  381. {
  382. case ERROR_HANDLE_DISK_FULL:
  383. case ERROR_DISK_FULL:
  384. if (0 == GetFilePath(lpNewFileName, szPath))
  385. {
  386. _tcscpy(szPath, lpNewFileName);
  387. }
  388. MYVERIFY(0 != LoadString(g_hInstance, IDS_DISKFULL, szTemp, MAX_PATH));
  389. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, szPath));
  390. nMessageReturn = MessageBox(NULL, szMsg, g_szAppTitle, MB_RETRYCANCEL | MB_ICONERROR
  391. | MB_TASKMODAL);
  392. if (nMessageReturn != IDRETRY)
  393. {
  394. return FALSE;
  395. }
  396. break;
  397. default:
  398. //
  399. // Replaces the functionality of the FileAccessErr function so all the file
  400. // errors are trapped in one place. This function still exits for special
  401. // cases.
  402. //
  403. MYVERIFY(0 != LoadString(g_hInstance, IDS_NOACCESS, szTemp, MAX_PATH));
  404. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, lpNewFileName));
  405. MessageBox(NULL ,szMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL
  406. | MB_TOPMOST );
  407. return FALSE;
  408. }
  409. } else {
  410. nMessageReturn = 0;
  411. }
  412. } while (IDRETRY == nMessageReturn);
  413. return TRUE;
  414. }
  415. //+---------------------------------------------------------------------------
  416. //
  417. // Function: CheckDiskSpaceForCompression
  418. //
  419. // Synopsis: Checks to see if there is sufficient disk space for compressing
  420. // the files listed in the passed in sed file. To do this, uses a simplistic
  421. // algorithm of adding up the disk space used by all the files listed in the
  422. // strings section of the SED file, under the FILE<num> entries. If there is
  423. // at least dwBytes (space taken up by all the files in the SED) of space left
  424. // on the partition containing the SED file, then the function returns true.
  425. // Otherwise false is returned, indicating that there may not be enough space left.
  426. //
  427. // Arguments: szSed -- the full path to the SED file to look for filenames in
  428. //
  429. // Returns: TRUE if sufficient space to continue, FALSE if not sure or probably
  430. // not enough
  431. //
  432. // Assumptions: That the partition we are checking for diskspace on is the partition of
  433. // the current directory.
  434. //
  435. // History: quintinb created 11/10/97
  436. //
  437. //----------------------------------------------------------------------------
  438. BOOL CheckDiskSpaceForCompression (LPCTSTR szSed)
  439. {
  440. TCHAR szKey[MAX_PATH+1];
  441. TCHAR szFileName[MAX_PATH+1];
  442. DWORD dwBytes = 0;
  443. DWORD dwChars;
  444. //
  445. // Calculate the amount of space taken up by the files listed in the SED
  446. //
  447. int nCount = 0;
  448. do
  449. {
  450. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("FILE%d"), nCount));
  451. dwChars = GetPrivateProfileString(c_pszInfSectionStrings, szKey, TEXT(""),
  452. szFileName, MAX_PATH, szSed);
  453. if (0 != dwChars)
  454. {
  455. HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ,
  456. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  457. if (INVALID_HANDLE_VALUE != hFile)
  458. {
  459. dwBytes += GetFileSize(hFile, NULL);
  460. MYVERIFY(0 != CloseHandle(hFile));
  461. }
  462. }
  463. nCount++;
  464. } while (0 != dwChars);
  465. //
  466. // Now that we know how much space the files in the SED take up, we should see how much space is on
  467. // the partition.
  468. //
  469. DWORD dwFreeClusters;
  470. DWORD dwBytesPerSector;
  471. DWORD dwSectorsPerCluster;
  472. DWORD dwTotalClusters;
  473. DWORD dwModulus;
  474. if (GetDiskFreeSpace(NULL, &dwSectorsPerCluster, &dwBytesPerSector,
  475. &dwFreeClusters, &dwTotalClusters))
  476. {
  477. //
  478. // Because dwSectorsPerCluster*dwBytesPerSector*dwFreeClusters could very easily
  479. // overflow a 32 bit value, we will calculate the total size of the files to compress
  480. // in clusters (dwBytes/(dwSectorsPerCluster*dwBytesPerSector)) and compare
  481. // against the dwFreeClusters value.
  482. //
  483. DWORD dwSizeInSectors = dwBytes / dwBytesPerSector;
  484. dwModulus = dwBytes % dwBytesPerSector;
  485. if (dwModulus)
  486. {
  487. dwSizeInSectors++; // we want to round up if it didn't divide evenly
  488. }
  489. DWORD dwSizeInClusters = dwSizeInSectors / dwSectorsPerCluster;
  490. dwModulus = dwSizeInSectors % dwSectorsPerCluster;
  491. if (dwModulus)
  492. {
  493. dwSizeInClusters++; // we want to round up if it didn't divide evenly
  494. }
  495. if (dwFreeClusters > dwSizeInClusters)
  496. {
  497. return TRUE;
  498. }
  499. else
  500. {
  501. return FALSE;
  502. }
  503. }
  504. else
  505. {
  506. return FALSE;
  507. }
  508. }
  509. //+----------------------------------------------------------------------------
  510. //
  511. // Function: ProcessBold
  512. //
  513. // Synopsis: This function makes the IDC_LBLTITLE static text control bold
  514. // on the WM_INITDIALOG message and releases the bold on WM_DESTROY.
  515. // This function is usually placed at the top of a window procedure
  516. // so that these messages are handled automatically. Note that the
  517. // function doesn't otherwise affect the processing of these messages
  518. // by the original window procedure.
  519. //
  520. // Arguments: HWND hDlg - dialog window handle to process messages for
  521. // UINT message - message to handle
  522. //
  523. // Returns: Nothing
  524. //
  525. // History: quintinb Created Header 05/09/00
  526. //
  527. //+----------------------------------------------------------------------------
  528. void ProcessBold(HWND hDlg, UINT message)
  529. {
  530. switch (message)
  531. {
  532. case WM_INITDIALOG:
  533. MYVERIFY(ERROR_SUCCESS == MakeBold(GetDlgItem(hDlg, IDC_LBLTITLE), TRUE));
  534. break;
  535. case WM_DESTROY:
  536. MYVERIFY(ERROR_SUCCESS == ReleaseBold(GetDlgItem(hDlg, IDC_LBLTITLE)));
  537. break;
  538. default:
  539. break;
  540. }
  541. }
  542. //+---------------------------------------------------------------------------
  543. //
  544. // Function: SetDefaultGUIFont
  545. //
  546. // Synopsis: Sets the font of the control to be the Default GUI Font.
  547. //
  548. // Arguments: hwnd - Window handle of the dialog
  549. // message - message from the dialog box procedure
  550. // cltID - ID of the control you want changed.
  551. //
  552. // Returns: ERROR_SUCCESS
  553. //
  554. // History: 4/31/97 a-frankh Created
  555. // quintinb Renamed from ProcessDBCS and cleaned up
  556. //----------------------------------------------------------------------------
  557. void SetDefaultGUIFont(HWND hDlg, UINT message, int ctlID)
  558. {
  559. HFONT hFont = NULL;
  560. switch (message)
  561. {
  562. case WM_INITDIALOG:
  563. hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
  564. if (hFont == NULL)
  565. {
  566. hFont = (HFONT) GetStockObject(SYSTEM_FONT);
  567. }
  568. if (hFont != NULL)
  569. {
  570. SendMessage(GetDlgItem(hDlg, ctlID), WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0)); //lint !e534 WM_SETFONT doesn't return anything
  571. }
  572. break;
  573. default:
  574. break;
  575. }
  576. }
  577. //+----------------------------------------------------------------------------
  578. //
  579. // Function: IsAlpha
  580. //
  581. // Synopsis: Determines if the current platform is Alpha.
  582. //
  583. // Arguments: None
  584. //
  585. // Returns: static BOOL - TRUE if the current platform is Alpha
  586. //
  587. // History: nickball Created 10/11/97
  588. //
  589. //+----------------------------------------------------------------------------
  590. static BOOL IsAlpha()
  591. {
  592. SYSTEM_INFO sysinfo;
  593. ZeroMemory(&sysinfo, sizeof(sysinfo));
  594. GetSystemInfo(&sysinfo);
  595. return (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA);
  596. }
  597. //+----------------------------------------------------------------------------
  598. //
  599. // Function: ShowMessage
  600. //
  601. // Synopsis: Simple helper function to handle message display
  602. //
  603. // Arguments: HWND hDlg - Parent window handle
  604. // int strID - Resource ID of the string to be displayed
  605. // int mbtype - The type of messagebox (MB_OK, etc.)
  606. //
  607. // Returns: static int - User response to message box
  608. //
  609. // History: nickball Created Header 10/11/97
  610. // quintinb Changed strID and mbtype to UINTs for LINT 1-5-98
  611. // quintinb Change to use CmLoadString 6/17/99
  612. //
  613. //+----------------------------------------------------------------------------
  614. int ShowMessage(HWND hDlg, UINT strID, UINT mbtype)
  615. {
  616. int iReturn = 0;
  617. LPTSTR pszMsg = CmLoadString(g_hInstance, strID);
  618. if (pszMsg)
  619. {
  620. iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, mbtype);
  621. }
  622. CmFree(pszMsg);
  623. return iReturn;
  624. }
  625. //+----------------------------------------------------------------------------
  626. //
  627. // Function: GetFileName
  628. //
  629. // Synopsis: Get just the filename from a full path and filename
  630. //
  631. // Arguments: LPCTSTR lpPath - Ptr to the full name and path
  632. // LPTSTR lpFileName - Ptr to the buffer the hold the extracted name
  633. //
  634. // Returns: Nothing
  635. //
  636. // History: nickball Created Header 10/11/97
  637. // quintinb modified to fix bug with URL's 7-15-98
  638. //
  639. //+----------------------------------------------------------------------------
  640. void GetFileName(LPCTSTR lpPath, LPTSTR lpFileName)
  641. {
  642. LPTSTR pch;
  643. pch = _tcsrchr(lpPath, _T('\\'));
  644. if (NULL == pch)
  645. {
  646. //
  647. // Catch paths like c:temp.inf
  648. //
  649. if (_istalpha(lpPath[0]) && (_T(':') == lpPath[1])) //lint !e732
  650. {
  651. pch = (TCHAR*)&(lpPath[1]);
  652. }
  653. }
  654. if (NULL == pch)
  655. {
  656. _tcscpy(lpFileName, lpPath);
  657. }
  658. else
  659. {
  660. pch = CharNext(pch);
  661. _tcscpy(lpFileName, pch);
  662. }
  663. }
  664. //+----------------------------------------------------------------------------
  665. //
  666. // Function: GetFilePath
  667. //
  668. // Synopsis: Get just the full path from a full path and filename
  669. //
  670. // Arguments: LPCTSTR lpFullPath - Ptr to the full name and path
  671. // LPTSTR lpPath - Ptr to the buffer the hold the extracted path
  672. //
  673. // Returns: either 0 or the number of chars copied into the return buffer
  674. //
  675. // History: quintinb Created 11/11/97
  676. //
  677. //+----------------------------------------------------------------------------
  678. int GetFilePath(LPCTSTR lpFullPath, LPTSTR lpPath)
  679. {
  680. LPTSTR pch;
  681. _tcscpy(lpPath, lpFullPath);
  682. // first find the last \ char in the
  683. // string
  684. pch = _tcsrchr(lpPath,_T('\\'));
  685. // if this is null, look for a path similar to
  686. // c:junk
  687. if (pch == NULL)
  688. {
  689. pch = _tcsrchr(lpPath,_T(':'));
  690. if (NULL != pch)
  691. {
  692. pch = CharNext(pch);
  693. _tcscpy(pch, TEXT("\\"));
  694. pch = CharNext(pch);
  695. *pch = TEXT('\0');
  696. return _tcslen(lpPath);
  697. } else {
  698. lpPath[0] = TEXT('\0');
  699. return 0;
  700. }
  701. } else {
  702. *pch = TEXT('\0');
  703. return _tcslen(lpPath);
  704. }
  705. }
  706. //+----------------------------------------------------------------------------
  707. //
  708. // Function: GetName
  709. //
  710. // Synopsis: Extracts filename from a full path and file name and returns a p
  711. // tointer to the result.
  712. //
  713. // Arguments: LPCTSTR lpPath - Ptr to the full name and path
  714. //
  715. // Returns: LPTSTR - Ptr to the static buffer containing the result of the extraction.
  716. //
  717. // History: nickball Created Header 10/11/97
  718. //
  719. //+----------------------------------------------------------------------------
  720. LPTSTR GetName(LPCTSTR lpPath)
  721. {
  722. static TCHAR szStr[MAX_PATH+1];
  723. GetFileName(lpPath,szStr);
  724. return szStr;
  725. }
  726. BOOL GetShortFileName(LPTSTR lpFile, LPTSTR lpShortName)
  727. {
  728. HANDLE hFile;
  729. WIN32_FIND_DATA FindData;
  730. TCHAR szPath[MAX_PATH+1];
  731. GetFileName(lpFile,lpShortName);
  732. hFile = FindFirstFile(lpFile,&FindData);
  733. if (hFile == INVALID_HANDLE_VALUE)
  734. {
  735. //
  736. // Not found, try looking from OS dir as the root, because
  737. // the filename may be a relative path from a CMS file entry.
  738. //
  739. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH,szPath));
  740. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  741. hFile = FindFirstFile(lpFile,&FindData);
  742. MYVERIFY(0 != SetCurrentDirectory(szPath));
  743. }
  744. if (hFile != INVALID_HANDLE_VALUE)
  745. {
  746. if (*FindData.cAlternateFileName)
  747. {
  748. if (_tcsicmp(lpShortName,FindData.cAlternateFileName) != 0)
  749. {
  750. _tcscpy(lpShortName,FindData.cAlternateFileName);
  751. }
  752. }
  753. MYVERIFY(0 != FindClose(hFile));
  754. return TRUE;
  755. }
  756. else
  757. {
  758. return FALSE;
  759. }
  760. }
  761. //+----------------------------------------------------------------------------
  762. //
  763. // Function: GetBaseName
  764. //
  765. // Synopsis: Extracts the base filename (no extension) from a full filename
  766. // and path
  767. //
  768. // Arguments: LPTSTR lpPath - The full path and filename
  769. // LPTSTR lpFileName - The buffer to receive the extracted base name.
  770. //
  771. // Returns: Nothing
  772. //
  773. // History: nickball Created Header 10/11/97
  774. //
  775. //+----------------------------------------------------------------------------
  776. void GetBaseName(LPTSTR lpPath,LPTSTR lpFileName)
  777. {
  778. LPTSTR pch;
  779. GetFileName(lpPath, lpFileName);
  780. pch = _tcsrchr(lpFileName, _T('.'));
  781. if (pch)
  782. {
  783. *pch = TEXT('\0');
  784. }
  785. }
  786. //+----------------------------------------------------------------------------
  787. //
  788. // Function: FileAccessErr
  789. //
  790. // Synopsis: Helper function that handles notification of a file access error
  791. //
  792. // Arguments: HWND hDlg - Parent window handle
  793. // LPTSTR lpFile - The file that caused the access error.
  794. //
  795. // Returns: static void - Nothing
  796. //
  797. // History: nickball Created Header 10/11/97
  798. //
  799. //+----------------------------------------------------------------------------
  800. static void FileAccessErr(HWND hDlg,LPCTSTR lpFile)
  801. {
  802. TCHAR szMsg[MAX_PATH+1];
  803. TCHAR szTemp2[2*MAX_PATH+1];
  804. MYVERIFY(0 != LoadString(g_hInstance,IDS_NOACCESS,szMsg,MAX_PATH));
  805. MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2,szMsg,lpFile));
  806. MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
  807. }
  808. //+----------------------------------------------------------------------------
  809. //
  810. // Function: VerifyFile
  811. //
  812. // Synopsis: Given the ID of a dialog box edit control in ctrlID
  813. // Check if user entered in something different than what is contained in lpFile
  814. // If it is different, get the entire path and verify it exists.
  815. // If it doesn't exist and ShowErr = TRUE, display an error message
  816. // Copy the full path to lpFile if exists
  817. //
  818. // Arguments: HWND hDlg - Window handle of the dialog containing the edit control
  819. // DWORD ctrlID - edit control containing the file to check
  820. // LPTSTR lpFile - Filename to verify (checked against that contained in the control)
  821. // BOOL ShowErr - Whether to show an error message or not
  822. //
  823. // Returns: BOOL - Return TRUE if the file was verified to exist
  824. //
  825. // History: quintinb Created Header 1/8/98
  826. //
  827. //+----------------------------------------------------------------------------
  828. BOOL VerifyFile(HWND hDlg, DWORD ctrlID, LPTSTR lpFile, BOOL ShowErr)
  829. {
  830. TCHAR szMsg[MAX_PATH+1];
  831. TCHAR szTemp[MAX_PATH+1];
  832. TCHAR szTemp2[2*MAX_PATH+1];
  833. TCHAR szPath[MAX_PATH+1];
  834. int nResult;
  835. LPTSTR lpfilename;
  836. HANDLE hInf;
  837. LRESULT lrNumChars;
  838. lrNumChars = GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, ShowErr); // bDisplayError == ShowErr
  839. //
  840. // don't check blank entry
  841. //
  842. if (0 == lrNumChars || 0 == szTemp[0])
  843. {
  844. lpFile[0] = TEXT('\0');
  845. return TRUE;
  846. }
  847. //
  848. // Also check to make sure that we were able to convert the text to ANSI
  849. //
  850. if (-1 == lrNumChars)
  851. {
  852. SetFocus(GetDlgItem(hDlg, ctrlID));
  853. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  854. return FALSE;
  855. }
  856. //
  857. // if filename is still the same, ignore entry box
  858. //
  859. CheckNameChange(lpFile, szTemp);
  860. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szPath));
  861. //
  862. // Check current directory, if not found, check OS directory as root.
  863. // This handles relative paths from the CMS
  864. //
  865. nResult = SearchPath(NULL, lpFile, NULL, MAX_PATH, szTemp2, &lpfilename);
  866. if (!nResult)
  867. {
  868. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  869. nResult = SearchPath(NULL, lpFile, NULL, MAX_PATH, szTemp2, &lpfilename);
  870. if (!nResult)
  871. {
  872. goto Error;
  873. }
  874. }
  875. hInf = CreateFile(szTemp2, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  876. MYVERIFY(0 != SetCurrentDirectory(szPath));
  877. if (hInf == INVALID_HANDLE_VALUE)
  878. {
  879. goto Error;
  880. }
  881. else
  882. {
  883. MYVERIFY(0 != CloseHandle(hInf));
  884. }
  885. _tcscpy(lpFile,szTemp2);
  886. return TRUE;
  887. Error:
  888. _tcscpy(lpFile,szTemp);
  889. MYVERIFY(0 != SetCurrentDirectory(szPath));
  890. if (ShowErr)
  891. {
  892. MYVERIFY(0 != LoadString(g_hInstance, IDS_NOEXIST, szMsg, MAX_PATH));
  893. MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2, szMsg, szTemp));
  894. MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
  895. SetFocus(GetDlgItem(hDlg, ctrlID));
  896. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  897. }
  898. return FALSE;
  899. }
  900. // If has entry but file doesn't exist, blank out entry.
  901. BOOL VerifyPhonebk(HWND hDlg,DWORD ctrlID,LPTSTR lpFile)
  902. {
  903. TCHAR szTemp[MAX_PATH+1];
  904. TCHAR szTemp2[MAX_PATH+1];
  905. TCHAR szPath[MAX_PATH+1];
  906. int nResult;
  907. LPTSTR lpfilename;
  908. HANDLE hInf;
  909. LRESULT lrNumChars;
  910. //
  911. // If the text is not convertable to ANSI then we will catch it on the Next/Back. Thus
  912. // don't try to catch it here, would throw too many error messages at the user.
  913. //
  914. lrNumChars = GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
  915. // don't check blank entry
  916. if (0 == lrNumChars || 0 == szTemp[0])
  917. {
  918. lpFile[0] = 0;
  919. return TRUE;
  920. }
  921. // if filename is still the same, don't check
  922. CheckNameChange(lpFile,szTemp);
  923. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH,szPath));
  924. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  925. nResult = SearchPath(NULL,lpFile,NULL,MAX_PATH,szTemp2,&lpfilename);
  926. if (!nResult)
  927. {
  928. goto Error;
  929. }
  930. hInf = CreateFile(szTemp2,GENERIC_READ,0,NULL,OPEN_EXISTING,
  931. FILE_ATTRIBUTE_NORMAL,NULL);
  932. MYVERIFY(0 != SetCurrentDirectory(szPath));
  933. if (hInf == INVALID_HANDLE_VALUE)
  934. {
  935. goto Error;
  936. }
  937. else
  938. {
  939. MYVERIFY(0 != CloseHandle(hInf));
  940. }
  941. _tcscpy(lpFile,szTemp2);
  942. // SendMessage(GetDlgItem(hDlg, ctrlID), WM_SETTEXT, 0, (LPARAM)lpFile);
  943. return TRUE;
  944. Error:
  945. lpFile[0] = TEXT('\0');
  946. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, ctrlID), WM_SETTEXT, 0, (LPARAM)lpFile));
  947. return FALSE;
  948. }
  949. // If user entered in a new filename, copy it to lpnew
  950. void CheckNameChange(LPTSTR lpold, LPTSTR lpnew)
  951. {
  952. //
  953. // if filename changed or if new name contains directories, copy new to old
  954. //
  955. if ((_tcsicmp(GetName(lpold), lpnew) != 0) || (_tcschr(lpnew, TEXT('\\')) != NULL))
  956. {
  957. _tcscpy(lpold, lpnew);
  958. }
  959. }
  960. //+----------------------------------------------------------------------------
  961. //
  962. // Function: WriteRegStringValue
  963. //
  964. // Synopsis: Wrapper function to encapsulate opening a key for write access and
  965. // then setting a string value. Assumes the string is NULL terminated.
  966. //
  967. // Arguments: HKEY hBaseKey - base key, HKCU/HKLM/etc.
  968. // LPCTSTR pszKeyName - subkey name
  969. // LPCTSTR pszValueName - Value name to write
  970. // LPCTSTR pszValueToWrite - Value data string to write
  971. //
  972. // Returns: BOOL - TRUE if successful
  973. //
  974. // History: quintinb Created 6/15/99
  975. //
  976. //+----------------------------------------------------------------------------
  977. BOOL WriteRegStringValue(HKEY hBaseKey, LPCTSTR pszKeyName, LPCTSTR pszValueName, LPCTSTR pszValueToWrite)
  978. {
  979. HKEY hKey;
  980. DWORD dwSize;
  981. BOOL bReturn = FALSE;
  982. if (hBaseKey && pszKeyName && pszValueName && pszValueToWrite &&
  983. TEXT('\0') != pszKeyName[0] && TEXT('\0') != pszValueName[0]) // pszValueToWrite could be empty
  984. {
  985. LONG lReturn = RegOpenKeyEx(hBaseKey, pszKeyName, 0, KEY_WRITE, &hKey);
  986. if (ERROR_SUCCESS == lReturn)
  987. {
  988. dwSize = (lstrlen(pszValueToWrite) +1)*sizeof(TCHAR);
  989. lReturn = RegSetValueEx(hKey, pszValueName, 0, REG_SZ, (LPBYTE)pszValueToWrite, dwSize);
  990. if (ERROR_SUCCESS == lReturn)
  991. {
  992. bReturn = TRUE;
  993. }
  994. RegCloseKey(hKey);
  995. }
  996. }
  997. return bReturn;
  998. }
  999. // check to see if the original CMAK installtion directory exists and
  1000. // contains the language directories.
  1001. //+----------------------------------------------------------------------------
  1002. //
  1003. // Function: EraseTempDir
  1004. //
  1005. // Synopsis: This function deletes all the files in the tempdir (stored in the global g_szTempDir)
  1006. // then changes directories to the CMAK dir (stored in the global g_szCmakdir). From
  1007. // there the temp dir is deleted.
  1008. //
  1009. // Arguments: None
  1010. //
  1011. // Returns: BOOL - TRUE if the temp dir was deleted
  1012. //
  1013. // History: quintinb Created Header 1/5/98
  1014. // quintinb changed return type to a BOOL
  1015. //
  1016. //+----------------------------------------------------------------------------
  1017. BOOL EraseTempDir()
  1018. {
  1019. SHFILEOPSTRUCT FileOp;
  1020. ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
  1021. //
  1022. // First save a copy of the file
  1023. //
  1024. FileOp.wFunc = FO_DELETE;
  1025. FileOp.pFrom = g_szTempDir;
  1026. FileOp.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION;
  1027. int iRet = SHFileOperation (&FileOp); // return 0 on success
  1028. return (iRet ? FALSE : TRUE);
  1029. }
  1030. // copies service profile information from the CMAK directory to the
  1031. // temporary directory
  1032. static BOOL CopyToTempDir(LPTSTR szName)
  1033. {
  1034. HANDLE hCopyFileSearch;
  1035. WIN32_FIND_DATA FindData;
  1036. BOOL bCopyResult;
  1037. TCHAR szTemp[MAX_PATH+1];
  1038. MYVERIFY(0 != SetCurrentDirectory(g_szCmakdir));
  1039. if (!CreateDirectory(g_szTempDir,NULL))
  1040. {
  1041. return FALSE;
  1042. }
  1043. if (TEXT('\0') == szName[0])
  1044. {
  1045. return TRUE;
  1046. }
  1047. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szOsdir, szName));
  1048. if (!SetCurrentDirectory(szTemp))
  1049. {
  1050. return FALSE;
  1051. }
  1052. hCopyFileSearch = FindFirstFile(c_pszWildCard,&FindData);
  1053. if (hCopyFileSearch != INVALID_HANDLE_VALUE)
  1054. {
  1055. do
  1056. {
  1057. if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
  1058. {
  1059. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, FindData.cFileName));
  1060. //
  1061. // CLEAN OUT ANY READ ONLY ATTRIBUTES
  1062. //
  1063. MYVERIFY(0 != SetFileAttributes(FindData.cFileName,FILE_ATTRIBUTE_NORMAL));
  1064. if (!CopyFileWrapper(FindData.cFileName,szTemp,FALSE))
  1065. {
  1066. return FALSE;
  1067. }
  1068. }
  1069. bCopyResult = FindNextFile(hCopyFileSearch,&FindData);
  1070. } while (TRUE == bCopyResult);
  1071. }
  1072. MYVERIFY(0 != FindClose(hCopyFileSearch));
  1073. return TRUE;
  1074. }
  1075. //+----------------------------------------------------------------------------
  1076. //
  1077. // Function: GetInfVersion
  1078. //
  1079. // Synopsis: Opens the inf file and tries to get the InfVersion key from the CMAK Status
  1080. // section. If the inf file doesn't contain a version stamp then we know it is
  1081. // version 0 (1.0 and 1.1 releases).
  1082. //
  1083. // Arguments: LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
  1084. //
  1085. // Returns: int - returns the version value or zero if one wasn't found.
  1086. //
  1087. // History: quintinb Created 3/4/98
  1088. //
  1089. //+----------------------------------------------------------------------------
  1090. int GetInfVersion(LPTSTR szFullPathToInfFile)
  1091. {
  1092. if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
  1093. {
  1094. CMASSERTMSG(FALSE, TEXT("GetInfVersion -- Invalid InfPath Input."));
  1095. return FALSE;
  1096. }
  1097. return ((int)GetPrivateProfileInt(c_pszCmakStatus, c_pszInfVersion, 0, szFullPathToInfFile));
  1098. }
  1099. //+----------------------------------------------------------------------------
  1100. //
  1101. // Function: WriteInfVersion
  1102. //
  1103. // Synopsis: Opens the inf file and writes the current INF file version to the Cmak Status section.
  1104. //
  1105. // Arguments: LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
  1106. //
  1107. // Returns: Returns TRUE if able to write the value
  1108. //
  1109. // History: quintinb Created 3/4/98
  1110. //
  1111. //+----------------------------------------------------------------------------
  1112. BOOL WriteInfVersion(LPTSTR szFullPathToInfFile, int iVersion)
  1113. {
  1114. TCHAR szTemp[MAX_PATH+1];
  1115. if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
  1116. {
  1117. CMASSERTMSG(FALSE, TEXT("WriteInfVersion -- Invalid InfPath Input."));
  1118. return FALSE;
  1119. }
  1120. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), iVersion));
  1121. return (0 != WritePrivateProfileString(c_pszCmakStatus, c_pszInfVersion, szTemp, szFullPathToInfFile));
  1122. }
  1123. //+----------------------------------------------------------------------------
  1124. //
  1125. // Function: UpgradeInf
  1126. //
  1127. // Synopsis: This function upgrades and INF from an older version to the current
  1128. // version.
  1129. //
  1130. // Arguments: LPCTSTR szRenamedInfFile - Filename to save the old INF to
  1131. // LPCTSTR szFullPathToInfFile - Profile INF file
  1132. //
  1133. // Returns: BOOL - TRUE if successful
  1134. //
  1135. // History: quintinb Created Header 7/31/98
  1136. //
  1137. //+----------------------------------------------------------------------------
  1138. BOOL UpgradeInf(LPCTSTR szRenamedInfFile, LPCTSTR szFullPathToInfFile)
  1139. {
  1140. SHFILEOPSTRUCT FileOp;
  1141. TCHAR szTemp[MAX_PATH+1];
  1142. DWORD dwSize;
  1143. TCHAR* pszBuffer = NULL;
  1144. const int NUMSECTIONS = 3;
  1145. const TCHAR* const aszSectionName[NUMSECTIONS] =
  1146. {
  1147. c_pszCmakStatus,
  1148. c_pszExtraFiles,
  1149. c_pszMergeProfiles
  1150. };
  1151. const int NUMKEYS = 4;
  1152. const TCHAR* const aszKeyName[NUMKEYS] =
  1153. {
  1154. c_pszCmEntryServiceName,
  1155. c_pszShortSvcName,
  1156. c_pszUninstallAppTitle,
  1157. c_pszDesktopIcon
  1158. };
  1159. ZeroMemory(&FileOp, sizeof(SHFILEOPSTRUCT));
  1160. //
  1161. // First save a copy of the file
  1162. //
  1163. FileOp.wFunc = FO_COPY;
  1164. FileOp.pFrom = szFullPathToInfFile;
  1165. FileOp.pTo = szRenamedInfFile;
  1166. FileOp.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION;
  1167. if (0 != SHFileOperation (&FileOp))
  1168. {
  1169. return FALSE;
  1170. }
  1171. //
  1172. // First Copy the template.inf from the lang dir so that we have something to work from
  1173. //
  1174. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szSupportDir, c_pszTemplateInf));
  1175. MYVERIFY(FALSE != CopyFileWrapper(szTemp, szFullPathToInfFile, FALSE));
  1176. MYVERIFY(0 != SetFileAttributes(szFullPathToInfFile, FILE_ATTRIBUTE_NORMAL));
  1177. //
  1178. // now migrate the [CMAK Status], [Extra Files], [Merge Profiles] sections
  1179. //
  1180. for (int i=0; i < NUMSECTIONS; i++)
  1181. {
  1182. pszBuffer = GetPrivateProfileSectionWithAlloc(aszSectionName[i], szRenamedInfFile);
  1183. if (pszBuffer)
  1184. {
  1185. MYVERIFY(0 != WritePrivateProfileSection(aszSectionName[i], pszBuffer, szFullPathToInfFile));
  1186. }
  1187. }
  1188. //
  1189. // Free the allocated Buffer
  1190. //
  1191. CmFree(pszBuffer);
  1192. pszBuffer = NULL;
  1193. //
  1194. // Migrate the ServiceName, ShortSvcName, DesktopGUID, UninstallAppTitle, DesktopIcon values
  1195. // from the strings section.
  1196. //
  1197. for (i=0; i < NUMKEYS; i++)
  1198. {
  1199. dwSize = GetPrivateProfileString(c_pszInfSectionStrings, aszKeyName[i], TEXT(""), szTemp, MAX_PATH, szRenamedInfFile);
  1200. if (0 != dwSize)
  1201. {
  1202. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, aszKeyName[i], szTemp, szFullPathToInfFile));
  1203. }
  1204. }
  1205. //
  1206. // Special Case for the Desktop GUID. We always write Quotes around the GUID and these get
  1207. // stripped by the reading routine. Thus we need to add them back.
  1208. //
  1209. dwSize = GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, TEXT(""), szTemp, MAX_PATH, szRenamedInfFile);
  1210. if (0 != dwSize)
  1211. {
  1212. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid, szTemp, szFullPathToInfFile);
  1213. }
  1214. // The follwing sections should get rewritten and won't need to be migrated.
  1215. // [Xnstall.AddReg.Icon]
  1216. // [RegisterOCXSection], [Xnstall.CopyFiles], [Xnstall.CopyFiles.SingleUser], [Xnstall.CopyFiles.ICM],
  1217. // [Remove.DelFiles.ICM], [SourceDisksFiles], [Xnstall.RenameReg],
  1218. // [Remove.DelFiles]
  1219. return TRUE;
  1220. }
  1221. //+----------------------------------------------------------------------------
  1222. //
  1223. // Function: EnsureInfIsCurrent
  1224. //
  1225. // Synopsis: This function does whatever processing is necessary to upgrade the inf from
  1226. // its current version to the current version of CMAK itself.
  1227. //
  1228. // Arguments: HWND hDlg - window handle of the dialog box for modal messagebox purposes.
  1229. // LPTSTR szFullPathToInfFile - the full path the the inf file to get the version of
  1230. //
  1231. // Returns: BOOL - return TRUE if the inf was successfully upgraded, otherwise FALSE
  1232. //
  1233. // History: quintinb Created 3/4/98
  1234. //
  1235. //+----------------------------------------------------------------------------
  1236. BOOL EnsureInfIsCurrent(HWND hDlg, LPTSTR szFullPathToInfFile)
  1237. {
  1238. int iInfVersion;
  1239. TCHAR szRenamedInfFile[2*MAX_PATH+1];
  1240. TCHAR szTitle[2*MAX_PATH+1];
  1241. TCHAR szMsg[2*MAX_PATH+1];
  1242. TCHAR szTemp[MAX_PATH+1];
  1243. BOOL bUpgradeProfile = FALSE;
  1244. if ((NULL == szFullPathToInfFile) || (TEXT('\0') == szFullPathToInfFile[0]))
  1245. {
  1246. CMASSERTMSG(FALSE, TEXT("EnsureInfIsCurrent -- Invalid InfPath Input."));
  1247. return FALSE;
  1248. }
  1249. iInfVersion = GetInfVersion(szFullPathToInfFile);
  1250. ZeroMemory(szRenamedInfFile, sizeof(szRenamedInfFile));
  1251. MYVERIFY(CELEMS(szRenamedInfFile) > (UINT)wsprintf(szRenamedInfFile, TEXT("%s.bak"),
  1252. szFullPathToInfFile));
  1253. //
  1254. // We want to upgrade the inf if the Profile versions don't match. We also have
  1255. // a special case to handle upgrading NT5 Beta3 (and IEAK) profiles to NT5 RTM
  1256. // profiles. In order to fix NTRAID 323721 and 331446, the inf format had to change
  1257. // slightly thus we need to make sure to upgrade these profiles. We will use any
  1258. // cmdial32.dll build prior to 2055 as needing this fix. If version == 4 and the BuildNumber
  1259. // doesn't exist we assume it is a new profile. Thus don't upgrade.
  1260. //
  1261. const DWORD c_dwBuild2080 = ((2080 << c_iShiftAmount) + VER_PRODUCTBUILD_QFE);
  1262. DWORD dwProfileBuildNumber = (DWORD)GetPrivateProfileInt(c_pszSectionCmDial32, c_pszVerBuild,
  1263. (c_dwBuild2080 + 1), szFullPathToInfFile);
  1264. bUpgradeProfile = (iInfVersion != PROFILEVERSION) ||
  1265. ((4 == iInfVersion) && (c_dwBuild2080 > dwProfileBuildNumber));
  1266. //
  1267. // Always grab most of the information out of the template so that we get the correct language
  1268. // info.
  1269. //
  1270. if (bUpgradeProfile)
  1271. {
  1272. MYVERIFY(0 != LoadString(g_hInstance, IDS_MUST_UPGRADE_INF, szTitle, 2*MAX_PATH)); // temporarily use szTitle
  1273. GetFileName(szRenamedInfFile, szTemp);
  1274. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTitle, szTemp));
  1275. MYVERIFY(IDOK == MessageBox(hDlg, szMsg, g_szAppTitle, MB_OK | MB_APPLMODAL));
  1276. return UpgradeInf(szRenamedInfFile, szFullPathToInfFile);
  1277. }
  1278. return TRUE;
  1279. }
  1280. BOOL CopyFromTempDir(LPTSTR szName)
  1281. {
  1282. HANDLE hCopyFileSearch;
  1283. WIN32_FIND_DATA FindData;
  1284. BOOL bCopyResult;
  1285. TCHAR szSource[MAX_PATH+1];
  1286. TCHAR szDest[MAX_PATH+1];
  1287. TCHAR szOut[MAX_PATH+1];
  1288. //
  1289. // Create profile directory
  1290. //
  1291. MYVERIFY(CELEMS(szOut) > (UINT)wsprintf(szOut, TEXT("%s%s"), g_szOsdir, szName));
  1292. if (0 == SetCurrentDirectory(szOut))
  1293. {
  1294. MYVERIFY(0 != CreateDirectory(szOut,NULL));
  1295. }
  1296. MYVERIFY(0 != SetCurrentDirectory(g_szTempDir));
  1297. hCopyFileSearch = FindFirstFile(c_pszWildCard, &FindData);
  1298. if (hCopyFileSearch != INVALID_HANDLE_VALUE)
  1299. {
  1300. do
  1301. {
  1302. if (0 == (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1303. {
  1304. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"), szOut, FindData.cFileName));
  1305. MYVERIFY(CELEMS(szSource) > (UINT)wsprintf(szSource, TEXT("%s\\%s"), g_szTempDir, FindData.cFileName));
  1306. if (!CopyFileWrapper(szSource, szDest, FALSE))
  1307. {
  1308. return FALSE;
  1309. }
  1310. }
  1311. bCopyResult = FindNextFile(hCopyFileSearch, &FindData);
  1312. } while (bCopyResult == TRUE);
  1313. }
  1314. MYVERIFY(0 != FindClose(hCopyFileSearch));
  1315. return TRUE;
  1316. }
  1317. //+----------------------------------------------------------------------------
  1318. //
  1319. // Function: LoadServiceProfiles
  1320. //
  1321. // Synopsis: This function loads all the service profiles in the subdirectories
  1322. // of the current directory (thus you set this to c:\program files\cmak\profiles-32
  1323. // to have it load the normal profiles). The profiles are loaded into
  1324. // CMAK's internal linked list of available profiles to edit.
  1325. //
  1326. // Arguments: None
  1327. //
  1328. // Returns: Nothing
  1329. //
  1330. // History: quintinb Created Header 6/24/98
  1331. // quintinb removed two boolean arguments 6/24/98
  1332. //
  1333. //+----------------------------------------------------------------------------
  1334. void LoadServiceProfiles()
  1335. {
  1336. WIN32_FIND_DATA FindData;
  1337. HANDLE hFileSearch;
  1338. HANDLE hCms;
  1339. BOOL bResult;
  1340. TCHAR szTemp[MAX_PATH+1];
  1341. hFileSearch = FindFirstFile(c_pszWildCard,&FindData);
  1342. if (hFileSearch != INVALID_HANDLE_VALUE)
  1343. {
  1344. do
  1345. {
  1346. if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0)
  1347. {
  1348. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"),
  1349. FindData.cFileName, FindData.cFileName));
  1350. //
  1351. // If we can open the file, add a record to our profile list
  1352. //
  1353. hCms = CreateFile(szTemp,GENERIC_READ,0,NULL,OPEN_EXISTING,
  1354. FILE_ATTRIBUTE_NORMAL,NULL);
  1355. if (hCms != INVALID_HANDLE_VALUE)
  1356. {
  1357. MYVERIFY(0 != CloseHandle(hCms));
  1358. MYVERIFY(FALSE != createListBxRecord(&g_pHeadProfile, &g_pTailProfile, (void *)NULL, 0, FindData.cFileName));
  1359. }
  1360. }
  1361. bResult = FindNextFile(hFileSearch, &FindData);
  1362. } while (TRUE == bResult);
  1363. MYVERIFY(0 != FindClose(hFileSearch));
  1364. }
  1365. }
  1366. //+---------------------------------------------------------------------------
  1367. //
  1368. // Function: CopyNonLocalProfile
  1369. //
  1370. // Synopsis: Helper function to handle details of copying an external profile
  1371. // to the local CMAK layout.
  1372. //
  1373. // Arguments: pszName - The name of the profile to be copied
  1374. //
  1375. // Returns: Nothing
  1376. //
  1377. // History: nickball - created - 11/16/97
  1378. // quintinb - modified to not change directory -- 6/24/98
  1379. //
  1380. //----------------------------------------------------------------------------
  1381. void CopyNonLocalProfile(LPCTSTR pszName, LPCTSTR pszExistingProfileDir)
  1382. {
  1383. WIN32_FIND_DATA FindData;
  1384. TCHAR szTemp[MAX_PATH+1];
  1385. TCHAR szProfileDestDir[MAX_PATH+1];
  1386. TCHAR szOldInf[MAX_PATH+1];
  1387. TCHAR szFindFilePath[MAX_PATH+1];
  1388. TCHAR szTempDest[MAX_PATH+1];
  1389. BOOL bCopyResult;
  1390. HANDLE hCopyFileSearch;
  1391. //
  1392. // First determine if it exists already, we don't want to overwrite
  1393. //
  1394. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s\\%s.cms"), g_szCmakdir,
  1395. c_pszProfiles, pszName, pszName));
  1396. if (!FileExists(szTemp))
  1397. {
  1398. //
  1399. // Profile does not exist locally, create profile and platform sub-dirs
  1400. //
  1401. MYVERIFY(CELEMS(szProfileDestDir) > (UINT)wsprintf(szProfileDestDir,
  1402. TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, pszName));
  1403. MYVERIFY(0 != CreateDirectory(szProfileDestDir, NULL));
  1404. //
  1405. // First try to copy the inf from the system directory. This is the old location.
  1406. // If it doesn't exist here, then we will pick it up when we copy the profile directory, so
  1407. // don't report an error on failure.
  1408. //
  1409. MYVERIFY(0 != GetSystemDirectory(szTemp, CELEMS(szTemp)));
  1410. MYVERIFY(CELEMS(szOldInf) > (UINT)wsprintf(szOldInf, TEXT("%s\\%s.inf"),
  1411. szTemp, pszName));
  1412. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.inf"),
  1413. szProfileDestDir, pszName));
  1414. if (FileExists(szOldInf))
  1415. {
  1416. MYVERIFY(0 != CopyFile(szOldInf, szTemp, FALSE));
  1417. }
  1418. //
  1419. // Start copying files
  1420. //
  1421. MYVERIFY (CELEMS(szFindFilePath) > (UINT)wsprintf(szFindFilePath, TEXT("%s\\*.*"),
  1422. pszExistingProfileDir));
  1423. hCopyFileSearch = FindFirstFile(szFindFilePath, &FindData);
  1424. if (hCopyFileSearch != INVALID_HANDLE_VALUE)
  1425. {
  1426. do
  1427. {
  1428. if ((FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
  1429. {
  1430. MYVERIFY (CELEMS(szTempDest) > (UINT)wsprintf(szTempDest, TEXT("%s\\%s"), szProfileDestDir, FindData.cFileName));
  1431. MYVERIFY (CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), pszExistingProfileDir, FindData.cFileName));
  1432. MYVERIFY(0 != CopyFile(szTemp, szTempDest, FALSE));
  1433. MYVERIFY(0 != SetFileAttributes(szTempDest, FILE_ATTRIBUTE_NORMAL));
  1434. }
  1435. bCopyResult = FindNextFile(hCopyFileSearch,&FindData);
  1436. } while (TRUE == bCopyResult);
  1437. MYVERIFY(0 != FindClose(hCopyFileSearch));
  1438. }
  1439. //4404 - don't copy .cmp with user information in it. always create new.
  1440. }
  1441. }
  1442. //+----------------------------------------------------------------------------
  1443. //
  1444. // Function: GetProfileDirAndShortSvcNameFromCmpFilePath
  1445. //
  1446. // Synopsis:
  1447. //
  1448. // Arguments: IN LPCTSTR szCmpFileLocation - Cmp File location of the profile
  1449. // OUT LPTSTR pszShortServiceName - returns the ShortServiceName of the profile
  1450. // OUT LPTSTR pszProfileDirLocation - returns the Full path to the profile dir
  1451. // IN UINT uiStrLen - Length of the buffer pointed to by pszProfileDirLocation
  1452. // in characters.
  1453. //
  1454. // Returns: TRUE if successful
  1455. //
  1456. // History: quintinb Created 6/24/98
  1457. //
  1458. //+----------------------------------------------------------------------------
  1459. BOOL GetProfileDirAndShortSvcNameFromCmpFilePath(IN LPCTSTR pszCmpFileLocation,
  1460. OUT LPTSTR pszShortServiceName,
  1461. OUT LPTSTR pszProfileDirLocation,
  1462. IN UINT uiStrLen)
  1463. {
  1464. //
  1465. // Check Inputs
  1466. //
  1467. MYDBGASSERT(pszCmpFileLocation);
  1468. MYDBGASSERT(pszProfileDirLocation);
  1469. MYDBGASSERT(pszShortServiceName);
  1470. MYDBGASSERT(0 != uiStrLen);
  1471. MYDBGASSERT(TEXT('\0') != pszCmpFileLocation[0]);
  1472. if ((NULL == pszCmpFileLocation) ||
  1473. (TEXT('\0') == pszCmpFileLocation[0]) ||
  1474. (NULL == pszProfileDirLocation) ||
  1475. (NULL == pszShortServiceName) ||
  1476. (0 == uiStrLen)
  1477. )
  1478. {
  1479. return FALSE;
  1480. }
  1481. //
  1482. // Split the input cmp path
  1483. //
  1484. CFileNameParts FileParts(pszCmpFileLocation);
  1485. //
  1486. // Construct the cms path from the cmp path parts
  1487. //
  1488. MYVERIFY(uiStrLen > (UINT)wsprintf(pszProfileDirLocation, TEXT("%s%s%s"), FileParts.m_Drive, FileParts.m_Dir, FileParts.m_FileName));
  1489. //
  1490. // Short Service Names are 8.3
  1491. //
  1492. MYVERIFY(9 > (UINT)wsprintf(pszShortServiceName, TEXT("%s"), FileParts.m_FileName));
  1493. return TRUE;
  1494. }
  1495. //+----------------------------------------------------------------------------
  1496. //
  1497. // Function: CopyInstalledProfilesForCmakToEdit
  1498. //
  1499. // Synopsis: This function finds all the installed profiles that a user has
  1500. // access to and copies them to the CMAK\Profiles-32 directory so
  1501. // the user may edit them in CMAK. To do this it enumerates both
  1502. // the HKLM and the current HKCU Connection Manager Mappings keys
  1503. // and calls CopyNonLocalProfile on each found profile.
  1504. //
  1505. // Arguments: None
  1506. //
  1507. // Returns: Nothing
  1508. //
  1509. // History: quintinb Created 6/24/98
  1510. //
  1511. //+----------------------------------------------------------------------------
  1512. void CopyInstalledProfilesForCmakToEdit()
  1513. {
  1514. HKEY hKey;
  1515. HKEY hBaseKey;
  1516. DWORD dwType;
  1517. LPTSTR pszCurrentValue = NULL;
  1518. LPTSTR pszCurrentData = NULL;
  1519. TCHAR szShortServiceName[MAX_PATH+1];
  1520. TCHAR szCurrentProfileDirPath[MAX_PATH+1];
  1521. LPTSTR pszExpandedPath = NULL;
  1522. for (int i=0; i < 2; i++)
  1523. {
  1524. //
  1525. // First Load the Single User Profiles (we want to give preference to loading these if
  1526. // they happen to have it installed both all user and single user)
  1527. //
  1528. if (0 == i)
  1529. {
  1530. hBaseKey = HKEY_CURRENT_USER;
  1531. }
  1532. else
  1533. {
  1534. hBaseKey = HKEY_LOCAL_MACHINE;
  1535. }
  1536. if (ERROR_SUCCESS == RegOpenKeyEx(hBaseKey, c_pszRegCmMappings, 0, KEY_ALL_ACCESS, &hKey))
  1537. {
  1538. DWORD dwValueBufSize = 0;
  1539. DWORD dwDataBufSize = 0;
  1540. //
  1541. // figure out how big the buffers need to be
  1542. //
  1543. if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueBufSize, &dwDataBufSize, NULL, NULL))
  1544. {
  1545. //
  1546. // Increment the count we got back to include the terminating NULL char
  1547. //
  1548. dwValueBufSize++;
  1549. dwDataBufSize += 2; // this is in bytes
  1550. //
  1551. // allocate the space we need
  1552. //
  1553. pszCurrentValue = (LPTSTR) CmMalloc(dwValueBufSize * sizeof(TCHAR));
  1554. pszCurrentData = (LPTSTR) CmMalloc(dwDataBufSize);
  1555. CMASSERTMSG(pszCurrentValue && pszCurrentData, TEXT("CopyInstalledProfilesForCmakToEdit -- CmMalloc failed allocating value and data buffers."));
  1556. if (pszCurrentValue && pszCurrentData)
  1557. {
  1558. DWORD dwIndex = 0;
  1559. DWORD dwValueSize = dwValueBufSize; // only used for the in/out param
  1560. DWORD dwDataSize = dwDataBufSize; // only used for the in/out param
  1561. while (ERROR_SUCCESS == RegEnumValue(hKey, dwIndex, pszCurrentValue, &dwValueSize, NULL, &dwType, (LPBYTE)pszCurrentData, &dwDataSize))
  1562. {
  1563. if (REG_SZ == dwType)
  1564. {
  1565. MYDBGASSERT(0 != pszCurrentValue[0]);
  1566. MYDBGASSERT(0 != pszCurrentData[0]);
  1567. //
  1568. // Expand environment strings if necessary (single user profiles contain the
  1569. // %USERPROFILE% environment var).
  1570. //
  1571. DWORD dwDataSizeExpanded = ExpandEnvironmentStrings(pszCurrentData, NULL, 0);
  1572. CMASSERTMSG((dwDataSizeExpanded != 0),
  1573. TEXT("CopyInstalledProfilesForCmakToEdit -- Error expanding environment vars."));
  1574. if (dwDataSizeExpanded)
  1575. {
  1576. pszExpandedPath = (LPTSTR) CmMalloc(dwDataSizeExpanded * sizeof(TCHAR));
  1577. if (NULL != pszExpandedPath)
  1578. {
  1579. DWORD dwTmp = ExpandEnvironmentStrings(pszCurrentData, pszExpandedPath, dwDataSizeExpanded);
  1580. MYDBGASSERT(dwTmp == dwDataSizeExpanded);
  1581. if (dwTmp)
  1582. {
  1583. MYVERIFY(0 != GetProfileDirAndShortSvcNameFromCmpFilePath(pszExpandedPath,
  1584. szShortServiceName, szCurrentProfileDirPath,
  1585. CELEMS(szCurrentProfileDirPath)));
  1586. MYDBGASSERT(0 != szCurrentProfileDirPath[0]);
  1587. MYDBGASSERT(0 != szShortServiceName[0]);
  1588. CopyNonLocalProfile(szShortServiceName, szCurrentProfileDirPath);
  1589. }
  1590. CmFree(pszExpandedPath);
  1591. }
  1592. }
  1593. }
  1594. dwValueSize = dwValueBufSize;
  1595. dwDataSize = dwDataBufSize;
  1596. dwIndex++;
  1597. }
  1598. CmFree(pszCurrentValue);
  1599. CmFree(pszCurrentData);
  1600. }
  1601. }
  1602. MYVERIFY(ERROR_SUCCESS == RegCloseKey(hKey));
  1603. }
  1604. }
  1605. }
  1606. //+----------------------------------------------------------------------------
  1607. //
  1608. // Function: GetLangFromInfTemplate
  1609. //
  1610. // Synopsis: Wrote to replace GetLangFromDir. This function gets the LCID value
  1611. // from an inf and then calls GetLocaleInfo to get the Language Display
  1612. // name.
  1613. //
  1614. // Arguments: LPCTSTR szFullInfPath - full path to the inf file
  1615. // OUT LPTSTR pszLanguageDisplayName - out param to hold the display name of the LCID value
  1616. // IN int iCharsInBuffer - number of chars in the out buffer
  1617. //
  1618. // Returns: BOOL - TRUE if successful
  1619. //
  1620. // History: quintinb Created Header 8/8/98
  1621. //
  1622. //+----------------------------------------------------------------------------
  1623. BOOL GetLangFromInfTemplate(LPCTSTR szFullInfPath, OUT LPTSTR pszLanguageDisplayName, IN int iCharsInBuffer)
  1624. {
  1625. TCHAR szTemp[MAX_PATH+1] = TEXT("");
  1626. MYDBGASSERT(NULL != szFullInfPath);
  1627. MYDBGASSERT(TEXT('\0') != szFullInfPath[0]);
  1628. MYDBGASSERT(NULL != pszLanguageDisplayName);
  1629. MYDBGASSERT(0 < iCharsInBuffer);
  1630. if (FileExists(szFullInfPath))
  1631. {
  1632. //
  1633. // First check for the new LCID location under strings, we shouldn't need to
  1634. // check both places because it is template.inf but we will anyway just for
  1635. // completeness.
  1636. //
  1637. if (0 == GetPrivateProfileString(c_pszInfSectionStrings, c_pszCmLCID,
  1638. TEXT(""), szTemp, CELEMS(szTemp), szFullInfPath))
  1639. {
  1640. //
  1641. // If the new key didn't exist, then try the old [Intl] section and
  1642. // display key. The change was made during the CMAK Unicode changes to
  1643. // make the inf template easier to localize.
  1644. //
  1645. MYVERIFY(0 != GetPrivateProfileString(c_pszIntl, c_pszDisplay,
  1646. TEXT(""), szTemp, CELEMS(szTemp), szFullInfPath));
  1647. }
  1648. //
  1649. // Now try to extract the LCID from the string if we have one.
  1650. //
  1651. if (TEXT('\0') != szTemp[0])
  1652. {
  1653. //
  1654. // This value should be an LCID so a negative value is invalid anyway
  1655. //
  1656. DWORD dwLang = (DWORD)_ttol(szTemp);
  1657. int nResult = GetLocaleInfo(dwLang, LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
  1658. pszLanguageDisplayName, iCharsInBuffer);
  1659. if (0 == nResult)
  1660. {
  1661. ZeroMemory(pszLanguageDisplayName, sizeof(TCHAR)*iCharsInBuffer);
  1662. return FALSE;
  1663. }
  1664. else
  1665. {
  1666. return TRUE;
  1667. }
  1668. }
  1669. }
  1670. else
  1671. {
  1672. CMTRACE1(TEXT("GetLangFromInfTemplate can't find %s"), szFullInfPath);
  1673. }
  1674. return FALSE;
  1675. }
  1676. //+----------------------------------------------------------------------------
  1677. //
  1678. // Function: GetLocalizedLanguageNameFromLCID
  1679. //
  1680. // Synopsis: This function returns the language name of the given LCID in the
  1681. // language of the current system default language.
  1682. //
  1683. // Arguments: DWORD dwLCID - Locale Identifier to get the language for
  1684. //
  1685. // Returns: LPTSTR - returns NULL if unsuccessful, a pointer to the string
  1686. // otherwise. The Caller is responsible for CmFree-ing it.
  1687. //
  1688. // History: quintinb Created 6/17/99
  1689. //
  1690. //+----------------------------------------------------------------------------
  1691. LPTSTR GetLocalizedLanguageNameFromLCID(DWORD dwLCID)
  1692. {
  1693. LPTSTR pszReturnString = NULL;
  1694. LPTSTR pszTmp = NULL;
  1695. if (dwLCID)
  1696. {
  1697. int nCharsNeeded = GetLocaleInfo(dwLCID, LOCALE_SLANGUAGE, NULL, 0);
  1698. pszTmp = (LPTSTR)CmMalloc(nCharsNeeded*sizeof(TCHAR) + sizeof(TCHAR)); // one extra for the NULL
  1699. if (pszTmp)
  1700. {
  1701. nCharsNeeded = GetLocaleInfo(dwLCID, LOCALE_SLANGUAGE, pszTmp, nCharsNeeded);
  1702. if (0 != nCharsNeeded)
  1703. {
  1704. pszReturnString = pszTmp;
  1705. }
  1706. }
  1707. }
  1708. return pszReturnString;
  1709. }
  1710. //+----------------------------------------------------------------------------
  1711. //
  1712. // Function: GetDoNotShowLcidMisMatchDialogRegValue
  1713. //
  1714. // Synopsis: This function gets the registry key value which stores whether
  1715. // the user has checked the box on the Lcids don't match dialog
  1716. // displayed by CMAK which says, "Don't show this dialog again".
  1717. //
  1718. //
  1719. // Arguments: None
  1720. //
  1721. // Returns: BOOL - TRUE if cmak should NOT show the dialog or FALSE if it should
  1722. //
  1723. // History: quintinb Created 03/22/2001
  1724. //
  1725. //+----------------------------------------------------------------------------
  1726. BOOL GetDoNotShowLcidMisMatchDialogRegValue()
  1727. {
  1728. BOOL bReturn = FALSE;
  1729. HKEY hKey;
  1730. LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmak, 0, KEY_READ, &hKey);
  1731. if (ERROR_SUCCESS == lResult)
  1732. {
  1733. DWORD dwType = 0;
  1734. DWORD dwDoNotShowDialog = 0;
  1735. DWORD dwSize = sizeof(DWORD);
  1736. lResult = RegQueryValueEx(hKey, c_pszDoNotShowLcidMisMatchDialog, NULL, &dwType,
  1737. (LPBYTE)&dwDoNotShowDialog, &dwSize);
  1738. if (ERROR_SUCCESS == lResult)
  1739. {
  1740. bReturn = (BOOL)dwDoNotShowDialog;
  1741. }
  1742. RegCloseKey(hKey);
  1743. }
  1744. return bReturn;
  1745. }
  1746. //+----------------------------------------------------------------------------
  1747. //
  1748. // Function: SetDoNotShowLcidMisMatchDialogRegValue
  1749. //
  1750. // Synopsis: This function sets the registry key value which stores whether
  1751. // the user has checked the box on the Lcids don't match dialog
  1752. // displayed by CMAK which says, "Don't show this dialog again".
  1753. //
  1754. //
  1755. // Arguments: DWORD dwValueToSet - TRUE or FALSE value that should be set in reg
  1756. //
  1757. // Returns: BOOL - TRUE if the value was set successfully, FALSE otherwise
  1758. //
  1759. // History: quintinb Created 03/22/2001
  1760. //
  1761. //+----------------------------------------------------------------------------
  1762. BOOL SetDoNotShowLcidMisMatchDialogRegValue(DWORD dwValueToSet)
  1763. {
  1764. HKEY hKey;
  1765. BOOL bReturn = FALSE;
  1766. LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegCmak, 0, KEY_WRITE, &hKey);
  1767. if (ERROR_SUCCESS == lResult)
  1768. {
  1769. lResult = RegSetValueEx(hKey, c_pszDoNotShowLcidMisMatchDialog, NULL, REG_DWORD,
  1770. (LPBYTE)&dwValueToSet, sizeof(DWORD));
  1771. if (ERROR_SUCCESS == lResult)
  1772. {
  1773. bReturn = TRUE;
  1774. }
  1775. RegCloseKey(hKey);
  1776. }
  1777. return bReturn;
  1778. }
  1779. //+----------------------------------------------------------------------------
  1780. //
  1781. // Function: ProcessLCIDsDontMatchPopup
  1782. //
  1783. // Synopsis: Processes windows messages for the dialog which tells the user they
  1784. // have a mismatch between the system locale and the language of CMAK
  1785. // itself. Note that we pass in a pointer to the message string containing
  1786. // the language names through the lParam parameter.
  1787. //
  1788. // Arguments: WND hDlg - dialog window handle
  1789. // UINT message - message identifier
  1790. // WPARAM wParam - wParam Value
  1791. // LPARAM lParam - lParam Value
  1792. //
  1793. //
  1794. // History: quintinb Created 03/22/01
  1795. //
  1796. //+----------------------------------------------------------------------------
  1797. INT_PTR APIENTRY ProcessLCIDsDontMatchPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1798. {
  1799. DWORD dwChecked = 0;
  1800. SetDefaultGUIFont(hDlg, message, IDC_MSG);
  1801. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_LCID_POPUP)) return TRUE;
  1802. switch (message)
  1803. {
  1804. case WM_INITDIALOG:
  1805. //
  1806. // We need to set the text passed through the lParam parameter
  1807. // to the IDC_MSG control.
  1808. //
  1809. if (lParam)
  1810. {
  1811. LPTSTR pszMsg = (LPTSTR)lParam;
  1812. MYVERIFY(TRUE == SendDlgItemMessage (hDlg, IDC_MSG, WM_SETTEXT, (WPARAM)0, (LPARAM)pszMsg));
  1813. }
  1814. break;
  1815. case WM_COMMAND:
  1816. switch (LOWORD(wParam))
  1817. {
  1818. case IDOK: // Continue
  1819. //
  1820. // Get the value of the "Do not show me this dialog again", checkbox
  1821. // and save it to the registry
  1822. //
  1823. dwChecked = IsDlgButtonChecked(hDlg, IDC_CHECK1);
  1824. MYVERIFY(FALSE != SetDoNotShowLcidMisMatchDialogRegValue(dwChecked));
  1825. MYVERIFY(0 != EndDialog(hDlg, IDOK));
  1826. return TRUE;
  1827. break;
  1828. case IDCANCEL: // Cancel
  1829. MYVERIFY(0 != EndDialog(hDlg, IDCANCEL));
  1830. return TRUE;
  1831. break;
  1832. default:
  1833. break;
  1834. }
  1835. break;
  1836. default:
  1837. return FALSE;
  1838. }
  1839. return FALSE;
  1840. }
  1841. //+----------------------------------------------------------------------------
  1842. //
  1843. // Function: DisplayLcidsDoNotMatchDialog
  1844. //
  1845. // Synopsis: This function handles the details of displaying the Lcids don't
  1846. // match dialog. Including such details as checking the registry
  1847. // key to see if the user has already seen the message and asked
  1848. // not to see it again, loading the proper string resources, displaying
  1849. // the dialog, and processing the user's answer.
  1850. //
  1851. //
  1852. // Arguments: HINSTANCE hInstance - Instance handle for resources
  1853. // DWORD dwCmakNativeLCID - LCID of CMAK itself
  1854. // DWORD dwSystemDefaultLCID - current system LCID
  1855. //
  1856. // Returns: BOOL - TRUE if cmak should continue, FALSE if it should exit
  1857. //
  1858. // History: quintinb Created 03/26/2001
  1859. //
  1860. //+----------------------------------------------------------------------------
  1861. BOOL DisplayLcidsDoNotMatchDialog(HINSTANCE hInstance, DWORD dwCmakNativeLCID, DWORD dwSystemDefaultLCID)
  1862. {
  1863. //
  1864. // If we are in here, then the CMAK LCID and the Default System LCID
  1865. // have a different Primary language (Japanese vs English for instance).
  1866. // Thus we want to warn the user that they can continue but that the
  1867. // language version of CM is potentially going to be different than the
  1868. // language version of the text that they are typing into the profile.
  1869. // It would probably be a better user experience to use the native version
  1870. // of CMAK that makes the language you have set as your default locale.
  1871. // First, however, we need to check to see if a registry value exists which
  1872. // tells us the user has already seen the dialog and asked not to see it again...
  1873. //
  1874. BOOL bReturn = TRUE;
  1875. if (FALSE == GetDoNotShowLcidMisMatchDialogRegValue())
  1876. {
  1877. //
  1878. // Get the Language Names of the Two LCIDs (sys default and CMAK lang)
  1879. //
  1880. LPTSTR pszSystemLanguage = GetLocalizedLanguageNameFromLCID(dwSystemDefaultLCID);
  1881. LPTSTR pszCmakLanguage = GetLocalizedLanguageNameFromLCID(dwCmakNativeLCID);
  1882. LPTSTR pszFmtString = CmLoadString(hInstance, IDS_LCIDS_DONT_MATCH);
  1883. if (pszSystemLanguage && pszCmakLanguage && pszFmtString)
  1884. {
  1885. LPTSTR pszMsg = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lstrlen(pszSystemLanguage) +
  1886. lstrlen(pszCmakLanguage) + lstrlen(pszFmtString) + 1));
  1887. if (pszMsg)
  1888. {
  1889. wsprintf(pszMsg, pszFmtString, pszSystemLanguage, pszCmakLanguage);
  1890. INT_PTR nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_LCIDS_DONT_MATCH_POPUP), NULL,
  1891. (DLGPROC)ProcessLCIDsDontMatchPopup,(LPARAM)pszMsg);
  1892. if (IDCANCEL == nResult)
  1893. {
  1894. bReturn = FALSE;
  1895. }
  1896. CmFree(pszMsg);
  1897. }
  1898. }
  1899. CmFree(pszSystemLanguage);
  1900. CmFree(pszCmakLanguage);
  1901. CmFree(pszFmtString);
  1902. }
  1903. return bReturn;
  1904. }
  1905. //+----------------------------------------------------------------------------
  1906. //
  1907. // Function: CheckLocalization
  1908. //
  1909. // Synopsis: This function checks to make sure that the current default
  1910. // system language has a default ANSI code page and that the
  1911. // CMAK Native language (what it is localized to) and the current
  1912. // default system language are in the same language family. If there
  1913. // is no default ANSI code page or the LCIDs of CMAK and the system
  1914. // don't match, then we throw an error message.
  1915. //
  1916. //
  1917. // Arguments: HINSTANCE hInstance - Instance handle for resources
  1918. //
  1919. // Returns: BOOL - TRUE if cmak should continue, FALSE if it should exit
  1920. //
  1921. // History: quintinb Created 6/25/99
  1922. //
  1923. //+----------------------------------------------------------------------------
  1924. BOOL CheckLocalization(HINSTANCE hInstance)
  1925. {
  1926. TCHAR szTemp[MAX_PATH+1];
  1927. BOOL bReturn = TRUE;
  1928. //
  1929. // Check localization requirements. We want to make sure that the current system
  1930. // default language has an ANSI code page, otherwise we are not going to be
  1931. // able to convert the Unicode text that the user types in to anything that we
  1932. // can store in our ANSI text data store (ini files).
  1933. //
  1934. DWORD dwSystemDefaultLCID = GetSystemDefaultLCID();
  1935. CMTRACE1(TEXT("CheckLocalization -- System Default LCID is %u"), dwSystemDefaultLCID);
  1936. GetLocaleInfo(dwSystemDefaultLCID, LOCALE_IDEFAULTANSICODEPAGE, szTemp, CELEMS(szTemp));
  1937. DWORD dwAnsiCodePage = CmAtol(szTemp);
  1938. if (0 == dwAnsiCodePage)
  1939. {
  1940. //
  1941. // Then this LCID has no ANSI code page and we need to throw an error. The user
  1942. // will not be able to create a profile without an ANSI codepage of some sort.
  1943. //
  1944. int iReturn = ShowMessage(NULL, IDS_NO_ANSI_CODEPAGE, MB_YESNO);
  1945. if (IDNO == iReturn)
  1946. {
  1947. return FALSE;
  1948. }
  1949. }
  1950. else
  1951. {
  1952. //
  1953. // We have an ANSI codepage, very good. We want to check and see if the current language the
  1954. // user is using is different from that of CMAK itself. If so, then we need to tell the user
  1955. // that the language they are entering and the language of the CM bits are different. While this
  1956. // is okay, it may not provide the experience they are looking for.
  1957. //
  1958. //
  1959. // Get the CMAK Native LCID
  1960. //
  1961. CmakVersion CmakVer;
  1962. DWORD dwCmakNativeLCID = CmakVer.GetNativeCmakLCID();
  1963. BOOL bSeenDialog = FALSE;
  1964. //
  1965. // Compare the Primary Lang IDs of the language that CMAK is in and the language
  1966. // the system locale is set to (this tells us what code page is loaded.
  1967. //
  1968. if (!ArePrimaryLangIDsEqual(dwCmakNativeLCID, dwSystemDefaultLCID))
  1969. {
  1970. bReturn = DisplayLcidsDoNotMatchDialog(hInstance, dwCmakNativeLCID, dwSystemDefaultLCID);
  1971. bSeenDialog = TRUE;
  1972. }
  1973. //
  1974. // Now load the Native CMAK LCID from the CMAK resources. If this doesn't match
  1975. // what we got from above we know MUI is involved and we still could have a problem
  1976. // as the user may be entering text in a different language then what we are expecting.
  1977. //
  1978. if (!bSeenDialog)
  1979. {
  1980. MYVERIFY(0 != LoadString(hInstance, IDS_NATIVE_LCID, szTemp, CELEMS(szTemp)));
  1981. dwCmakNativeLCID = CmAtol(szTemp);
  1982. if (!ArePrimaryLangIDsEqual(dwCmakNativeLCID, dwSystemDefaultLCID))
  1983. {
  1984. bReturn = DisplayLcidsDoNotMatchDialog(hInstance, dwCmakNativeLCID, dwSystemDefaultLCID);
  1985. }
  1986. }
  1987. }
  1988. return bReturn;
  1989. }
  1990. //+----------------------------------------------------------------------------
  1991. //
  1992. // Function: WinMain
  1993. //
  1994. // Synopsis: Main function for CMAK. Basically does some initialization and
  1995. // then launches the wizard.
  1996. //
  1997. //
  1998. // History: quintinb on 8/26/97: made changes to fix bug 10406, see below
  1999. // quintinb Created new style Header 3/29/98
  2000. //
  2001. //+----------------------------------------------------------------------------
  2002. int APIENTRY WinMain(
  2003. HINSTANCE, //hInstance
  2004. HINSTANCE, //hPrevInstance
  2005. LPSTR, //lpCmdLine
  2006. int nCmdShow
  2007. )
  2008. {
  2009. LPTSTR lpfilename;
  2010. int nresult;
  2011. TCHAR szSaveDir[MAX_PATH+1];
  2012. TCHAR szTemp[2*MAX_PATH+1];
  2013. HWND hwndPrev;
  2014. HWND hwndChild;
  2015. BOOL bTempDirExists; // added by quintinb, please see comment below
  2016. HINSTANCE hInstance = GetModuleHandle(NULL);
  2017. LPTSTR lpCmdLine = GetCommandLine();
  2018. DWORD dwFlags;
  2019. INITCOMMONCONTROLSEX InitCommonControlsExStruct = {0};
  2020. g_hInstance = hInstance;
  2021. //
  2022. // Process Command Line Arguments
  2023. //
  2024. ZeroMemory(szTemp, sizeof(szTemp));
  2025. const DWORD c_dwIeakBuild = 0x1;
  2026. ArgStruct Args;
  2027. Args.pszArgString = TEXT("/o");
  2028. Args.dwFlagModifier = c_dwIeakBuild;
  2029. { // Make sure ArgProcessor gets destructed properly and we don't leak mem
  2030. CProcessCmdLn ArgProcessor(1, (ArgStruct*)&Args, TRUE,
  2031. TRUE); //bSkipFirstToken == TRUE, bBlankCmdLnOkay == TRUE
  2032. if (ArgProcessor.GetCmdLineArgs(lpCmdLine, &dwFlags, szTemp, 2*MAX_PATH))
  2033. {
  2034. g_bIEAKBuild = dwFlags & c_dwIeakBuild;
  2035. }
  2036. }
  2037. //
  2038. // Get the name product name from resource, now we're just a lowly component.
  2039. //
  2040. MYVERIFY(0 != LoadString(g_hInstance, IDS_APP_TITLE, g_szAppTitle, MAX_PATH));
  2041. // Check if already executing program by trying to set Mutex
  2042. MYVERIFY(NULL != CreateMutex(NULL, TRUE, TEXT("spwmutex")));
  2043. if (GetLastError() == ERROR_ALREADY_EXISTS)
  2044. {
  2045. // if error, then must already be in use by first instance
  2046. hwndPrev = FindWindow(NULL, c_pszAppCaption);
  2047. if (!hwndPrev)
  2048. {
  2049. // check for error message box
  2050. hwndPrev = FindWindow(NULL, g_szAppTitle);
  2051. if (!hwndPrev)
  2052. {
  2053. return CMAK_RETURN_ERROR;
  2054. }
  2055. }
  2056. // Bring up previous executing copy to the top.
  2057. ShowWindow(hwndPrev,SW_SHOWNORMAL);
  2058. hwndChild = GetLastActivePopup(hwndPrev);
  2059. MYVERIFY(0 != BringWindowToTop(hwndPrev));
  2060. if (IsIconic(hwndPrev))
  2061. {
  2062. ShowWindow(hwndPrev,SW_RESTORE);
  2063. }
  2064. if (hwndChild != hwndPrev)
  2065. {
  2066. MYVERIFY(0 != BringWindowToTop(hwndChild));
  2067. }
  2068. MYVERIFY(0 != SetForegroundWindow(hwndChild));
  2069. return CMAK_RETURN_ERROR;
  2070. }
  2071. // save off the current instance
  2072. g_szPhonebk[0] = TEXT('\0');
  2073. g_szRegion[0] = TEXT('\0');
  2074. g_szHelp[0] = TEXT('\0');
  2075. g_szLicense[0] = TEXT('\0');
  2076. g_szPhoneName[0] = TEXT('\0');
  2077. g_szCmProxyFile[0] = TEXT('\0');
  2078. g_szCmRouteFile[0] = TEXT('\0');
  2079. g_szVpnFile[0] = TEXT('\0');
  2080. // SearchPath will return only the ugly filename format of the path.
  2081. // On NT, it works
  2082. // On 95, it returns upper case form.
  2083. nresult = SearchPath(NULL, c_pszCmakExe, NULL, CELEMS(g_szCmakdir), g_szCmakdir, &lpfilename);
  2084. if (nresult == 0)
  2085. {
  2086. FileAccessErr(NULL, c_pszCmakExe);
  2087. return CMAK_RETURN_ERROR;
  2088. }
  2089. // delete the file name to leave the exe directory
  2090. *lpfilename = TEXT('\0');
  2091. if (ERROR_SUCCESS != RegisterBitmapClass(hInstance))
  2092. {
  2093. return CMAK_RETURN_ERROR;
  2094. }
  2095. //
  2096. // Make sure we have a temp directory and then create %TEMP%\cmaktemp
  2097. //
  2098. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szSaveDir));
  2099. MYVERIFY(0 != GetTempPath(CELEMS(g_szTempDir), g_szTempDir));
  2100. // begin changes by quintinb on 8/26/97
  2101. // added to handle bug 10406
  2102. bTempDirExists = SetCurrentDirectory(g_szTempDir);
  2103. if (!bTempDirExists)
  2104. {
  2105. // temp dir doesn't exist even though the system thinks it does,
  2106. // so create it and everybody is happy
  2107. MYVERIFY(0 != CreateDirectory(g_szTempDir, NULL));
  2108. }
  2109. // end changes by quintinb on 8/26/97
  2110. _tcscat(g_szTempDir,TEXT("cmaktemp"));
  2111. MYDBGASSERT(_tcslen(g_szTempDir) <= CELEMS(g_szTempDir));
  2112. MYVERIFY(0 != CreateDirectory(g_szTempDir,NULL));
  2113. //
  2114. // Fill in the path for the support directory, we will need it below
  2115. //
  2116. MYVERIFY(CELEMS(g_szSupportDir) > (UINT)wsprintf(g_szSupportDir,
  2117. TEXT("%s%s"), g_szCmakdir, c_pszSupport));
  2118. //
  2119. // Now we need to check that we have compatible versions of cmak.exe and cmbins.exe.
  2120. // In the win64 case, we have no cmbins.exe so we use the native cmdial32.dll in
  2121. // system32. On x86, we need to open the CM binaries cab and check the version of cmdial32.dll
  2122. // to ensure that they are compatible. For instance different versions (5.0 vs 5.1)
  2123. // shouldn't work together. We also don't want CMAK to work with
  2124. // a cmdial that is of the same version but the cmdial has a lower build number.
  2125. //
  2126. #ifdef _WIN64
  2127. //
  2128. // On Win64 we are using the native cmdial32.dll in system32
  2129. //
  2130. CmVersion CmDialVer;
  2131. #else
  2132. //
  2133. // Extract the CM binaries from the cmbins.exe so that we can get
  2134. // the version number from cmdial32.dll and can get the correct version
  2135. // of cmstp.exe to put in the cab.
  2136. //
  2137. wsprintf(g_szCmBinsTempDir, TEXT("%s\\cmbins"), g_szTempDir);
  2138. if (FAILED(ExtractCmBinsFromExe(g_szSupportDir, g_szCmBinsTempDir)))
  2139. {
  2140. CMASSERTMSG(FALSE, TEXT("WinMain -- ExtractCmBinsFromExe Failed."));
  2141. return CMAK_RETURN_ERROR;
  2142. }
  2143. wsprintf(szTemp, TEXT("%s\\cmdial32.dll"), g_szCmBinsTempDir);
  2144. CVersion CmDialVer(szTemp);
  2145. #endif
  2146. CmakVersion CmakVer;
  2147. if (CmDialVer.IsPresent())
  2148. {
  2149. const DWORD c_dwCmakBuildNumber = VER_PRODUCTBUILD;
  2150. if ((c_dwCurrentCmakVersionNumber < CmDialVer.GetVersionNumber()))
  2151. {
  2152. //
  2153. // Then we have a newer version of CM then we know how to handle,
  2154. // throw an error and exit
  2155. //
  2156. MYVERIFY(IDOK == ShowMessage(NULL, IDS_CM_TOO_NEW, MB_OK));
  2157. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2158. goto exit;
  2159. }
  2160. else if ((c_dwCurrentCmakVersionNumber > CmDialVer.GetVersionNumber()) ||
  2161. ((c_dwCurrentCmakVersionNumber == CmDialVer.GetVersionNumber()) &&
  2162. (c_dwCmakBuildNumber > CmDialVer.GetBuildNumber())))
  2163. {
  2164. //
  2165. // Then we have a older version of CM then we need,
  2166. // throw an error and exit
  2167. //
  2168. MYVERIFY(IDOK == ShowMessage(NULL, IDS_CM_TOO_OLD, MB_OK));
  2169. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2170. goto exit;
  2171. }
  2172. }
  2173. else
  2174. {
  2175. //
  2176. // Then we have no CM bits, lets throw an error
  2177. //
  2178. MYVERIFY(IDOK == ShowMessage(NULL, IDS_NO_CM_BITS, MB_OK));
  2179. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2180. goto exit;
  2181. }
  2182. //
  2183. // Setup the profiles path in Temp
  2184. //
  2185. g_szShortServiceName[0] = TEXT('\0');
  2186. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szCmakdir, c_pszProfiles));
  2187. if (0 == SetCurrentDirectory(szTemp))
  2188. {
  2189. MYVERIFY(0 != CreateDirectory(szTemp, NULL));
  2190. MYVERIFY(0 != SetCurrentDirectory(szTemp));
  2191. }
  2192. //
  2193. // We need to make sure that the user has Read/Write
  2194. // permissions to the Profiles directory. Otherwise they can
  2195. // get themselves into the situation where they would build a
  2196. // whole profile and lose all of the work because they couldn't
  2197. // save it to the output directory (since we work out of the temp
  2198. // dir until we actually build the cab itself). NTRAID 372081
  2199. // Also note that since this function is shared by cmdial we use
  2200. // function pointers (here just the function names themselves)
  2201. // for items that cmdial32.dll doesn't statically link to so that
  2202. // it can dynamically link to them but still use the same code while
  2203. // allowing cmak not to have to do the dynamic link. Quirky but it
  2204. // works.
  2205. //
  2206. if (!HasSpecifiedAccessToFileOrDir(szTemp, FILE_GENERIC_READ | FILE_GENERIC_WRITE))
  2207. {
  2208. //
  2209. // Then we need to throw an error to the user and exit.
  2210. //
  2211. LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_INSUFF_PERMS);
  2212. if (pszTmp)
  2213. {
  2214. DWORD dwSize = lstrlen(pszTmp) + lstrlen(szTemp) + 1;
  2215. LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
  2216. if (pszMsg)
  2217. {
  2218. wsprintf(pszMsg, pszTmp, szTemp);
  2219. MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
  2220. CmFree(pszMsg);
  2221. }
  2222. CmFree(pszTmp);
  2223. }
  2224. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2225. goto exit;
  2226. }
  2227. //
  2228. // Grab all the installed CM profiles and copy them
  2229. // to the CMAK dir so that they can be edited.
  2230. //
  2231. CopyInstalledProfilesForCmakToEdit();
  2232. LoadServiceProfiles();
  2233. //
  2234. // Ensure that the directory CMAK\Support exists
  2235. //
  2236. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s"), g_szCmakdir, c_pszSupport));
  2237. if (0 == SetCurrentDirectory(szTemp))
  2238. {
  2239. MYVERIFY(IDOK == ShowMessage(NULL, IDS_NOLANGRES, MB_OK));
  2240. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2241. goto exit;
  2242. }
  2243. MYVERIFY(0 != SetCurrentDirectory(szSaveDir));
  2244. if (!CheckLocalization(g_hInstance))
  2245. {
  2246. g_iCMAKReturnVal = CMAK_RETURN_CANCEL;
  2247. goto exit;
  2248. }
  2249. //
  2250. // Initialize the common controls
  2251. //
  2252. InitCommonControlsExStruct.dwSize = sizeof(InitCommonControlsExStruct);
  2253. InitCommonControlsExStruct.dwICC = ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES;
  2254. if (FALSE == InitCommonControlsEx(&InitCommonControlsExStruct))
  2255. {
  2256. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  2257. goto exit;
  2258. }
  2259. g_pCustomActionList = new CustomActionList();
  2260. MYVERIFY(-1 != CreateWizard(NULL));
  2261. //
  2262. // Make sure to delete the CustomActionList Class, it is
  2263. // allocated on the custom action screen.
  2264. //
  2265. delete g_pCustomActionList;
  2266. exit:
  2267. EraseTempDir();
  2268. ExitProcess((UINT)g_iCMAKReturnVal);
  2269. return g_iCMAKReturnVal;
  2270. } //lint !e715 we don't use nCmdShow, lpCmdLine, nor hPrevInstance
  2271. //+----------------------------------------------------------------------------
  2272. //
  2273. // Function: DoBrowse
  2274. //
  2275. // Synopsis: This function does the necessary work to pop up a Browse Common Dialog (either for
  2276. // saving files or for opening files depending on the SaveAs flag).
  2277. //
  2278. // Arguments: WND hDlg - handle of current dialog
  2279. // UINT IDS_FILTER - ID for display filter description
  2280. // LPTSTR lpMask - file filter (*.ext)
  2281. // int IDC_EDIT - ID of edit field
  2282. // LPCTSTR lpDefExt - file filter extension (ext)
  2283. // LPTSTR lpFile - path/filename currently selected file on input and output
  2284. //
  2285. // Returns: Returns 1 if successful, -1 if the user hit cancel, and 0 if there was an error.
  2286. //
  2287. // History: quintinb 8-26-97
  2288. // Reorganized and rewrote most of this function to resolve bug # 13159.
  2289. // Tried to keep the original variable names and style as much as possible
  2290. // to keep the code style the same.
  2291. //
  2292. //
  2293. // quintinb 01/22/1998 changed the return value to int so that we could
  2294. // return -1 on cancel and 0 on error and distinguish the
  2295. // two cases.
  2296. // quintinb 07/13/1998 changed the function prototype so that more than one filter/mask
  2297. // pair could be specified.
  2298. // quintinb 01/14/2000 Remove SaveAs functionality as it was no longer used
  2299. //
  2300. //+----------------------------------------------------------------------------
  2301. int DoBrowse(HWND hDlg, UINT* pFilterArray, LPTSTR* pMaskArray, UINT uNumFilters, int IDC_EDIT, LPCTSTR lpDefExt, LPTSTR lpFile)
  2302. {
  2303. OPENFILENAME filedef;
  2304. TCHAR szMsg[MAX_PATH+1];
  2305. TCHAR szFile[MAX_PATH+1];
  2306. TCHAR* pszFilter = NULL;
  2307. TCHAR szTemp[MAX_PATH+1];
  2308. TCHAR szDir[MAX_PATH+1];
  2309. TCHAR szFileTitle[MAX_PATH+1];
  2310. int nResult;
  2311. LPTSTR lpfilename;
  2312. int iReturnValue;
  2313. //
  2314. // Check Inputs
  2315. //
  2316. MYDBGASSERT(uNumFilters);
  2317. MYDBGASSERT(pFilterArray);
  2318. MYDBGASSERT(pMaskArray);
  2319. if ((NULL == pFilterArray) ||
  2320. (NULL == pMaskArray) ||
  2321. (0 == uNumFilters))
  2322. {
  2323. return FALSE;
  2324. }
  2325. ZeroMemory(&filedef, sizeof(OPENFILENAME));
  2326. szFile[0] = TEXT('\0');
  2327. szDir[0] = TEXT('\0');
  2328. //
  2329. // Allocate Memory for the Filter string
  2330. //
  2331. pszFilter = (TCHAR*)CmMalloc(sizeof(TCHAR)*MAX_PATH*uNumFilters);
  2332. if (pszFilter)
  2333. {
  2334. ZeroMemory(pszFilter, sizeof(TCHAR)*MAX_PATH*uNumFilters);// REVIEW: This really isn't necessary since CmMalloc always zeros
  2335. }
  2336. else
  2337. {
  2338. CMASSERTMSG(FALSE, TEXT("DoBrowse -- CmMalloc returned a NULL pointer"));
  2339. return FALSE;
  2340. }
  2341. //
  2342. // Initialize the OPENFILENAME data structure
  2343. //
  2344. filedef.lStructSize = sizeof(OPENFILENAME);
  2345. filedef.hwndOwner = hDlg;
  2346. filedef.hInstance = g_hInstance;
  2347. filedef.lpstrFilter = pszFilter;
  2348. filedef.lpstrCustomFilter = NULL;
  2349. filedef.nMaxCustFilter = 0;
  2350. filedef.nFilterIndex = 0;
  2351. filedef.lpstrFile = szFile;
  2352. filedef.nMaxFile = MAX_PATH;
  2353. filedef.lpstrFileTitle = szFileTitle;
  2354. filedef.nMaxFileTitle = MAX_PATH;
  2355. filedef.lpstrInitialDir = szDir;
  2356. filedef.lpstrTitle = szMsg;
  2357. filedef.Flags = OFN_FILEMUSTEXIST|OFN_LONGNAMES|OFN_PATHMUSTEXIST;
  2358. filedef.lpstrDefExt = lpDefExt;
  2359. //
  2360. // create filter string - separated by 0 and ends with 2 0's
  2361. //
  2362. UINT uCurrentCharInBuffer=0;
  2363. UINT uTempChars;
  2364. for (UINT i = 0; i < uNumFilters; i++)
  2365. {
  2366. uTempChars = (UINT)LoadString(g_hInstance, pFilterArray[i], szTemp, MAX_PATH);
  2367. if ((MAX_PATH*uNumFilters) <= (uCurrentCharInBuffer + uTempChars))
  2368. {
  2369. //
  2370. // We don't want to overrun the buffer
  2371. //
  2372. break;
  2373. }
  2374. _tcscpy(&(pszFilter[uCurrentCharInBuffer]), szTemp);
  2375. uCurrentCharInBuffer += uTempChars;
  2376. uTempChars = (UINT)_tcslen(pMaskArray[i]);
  2377. if ((MAX_PATH*uNumFilters) <= (uCurrentCharInBuffer + uTempChars))
  2378. {
  2379. //
  2380. // We don't want to overrun the buffer
  2381. //
  2382. break;
  2383. }
  2384. _tcscpy(&(pszFilter[uCurrentCharInBuffer + 1]), pMaskArray[i]);
  2385. //
  2386. // Add 2 chars so that we get a \0 between strings.
  2387. //
  2388. uCurrentCharInBuffer = (uCurrentCharInBuffer + uTempChars + 2);
  2389. }
  2390. //
  2391. // if a path/file passed in, find its directory and make it szDir
  2392. //
  2393. if (TEXT('\0') != lpFile[0])
  2394. {
  2395. nResult = GetFullPathName(lpFile, CELEMS(szDir), szDir, &lpfilename);
  2396. if (nResult != 0)
  2397. {
  2398. if (lpfilename) // 13062
  2399. {
  2400. _tcscpy(szFile,lpfilename);
  2401. *lpfilename = TEXT('\0');
  2402. }
  2403. }
  2404. }
  2405. MYVERIFY(0 != LoadString(g_hInstance, IDS_BROWSETITLE, szMsg, MAX_PATH));
  2406. //
  2407. // pop up the open dialog
  2408. //
  2409. if (GetOpenFileName((OPENFILENAME*)&filedef))
  2410. {
  2411. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT), WM_SETTEXT, 0, (LPARAM)szFileTitle));
  2412. _tcscpy(lpFile, szFile);
  2413. iReturnValue = 1;
  2414. }
  2415. else
  2416. {
  2417. //
  2418. // If we are in this state than the user could have hit cancel or there could have
  2419. // been an error. If the CommDlgExtendedError function returns 0 then we know it was
  2420. // just a cancel, otherwise we have an error.
  2421. //
  2422. if (0 == CommDlgExtendedError())
  2423. {
  2424. iReturnValue = -1;
  2425. }
  2426. else
  2427. {
  2428. iReturnValue = 0;
  2429. }
  2430. }
  2431. CmFree(pszFilter);
  2432. return iReturnValue;
  2433. }
  2434. INT_PTR APIENTRY ProcessCancel(HWND hDlg, UINT message, LPARAM lParam)
  2435. {
  2436. int iRes;
  2437. NMHDR* pnmHeader = (NMHDR*)lParam;
  2438. switch (message)
  2439. {
  2440. case WM_NOTIFY:
  2441. if (NULL == pnmHeader)
  2442. {
  2443. return FALSE;
  2444. }
  2445. switch (pnmHeader->code)
  2446. {
  2447. case PSN_QUERYCANCEL:
  2448. iRes = ShowMessage(hDlg, IDS_CANCELWIZ, MB_YESNO);
  2449. if (iRes==IDYES)
  2450. {
  2451. //
  2452. // Free Up the memory we used
  2453. //
  2454. ClearCmakGlobals();
  2455. FreeList(&g_pHeadProfile, &g_pTailProfile);
  2456. EraseTempDir();
  2457. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT,FALSE));
  2458. }
  2459. else
  2460. {
  2461. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT,TRUE));
  2462. }
  2463. return TRUE;
  2464. default:
  2465. return FALSE;
  2466. }
  2467. default:
  2468. return FALSE;
  2469. }
  2470. }
  2471. //+----------------------------------------------------------------------------
  2472. //
  2473. // Function: ProcessHelp
  2474. //
  2475. // Synopsis: Processes messages that have to do with the Help button.
  2476. //
  2477. // Arguments: WND hDlg - dialog handle
  2478. // UINT message - Message ID to process
  2479. // LPARAM lParam - the lParam of the message
  2480. // DWORD_PTR dwHelpId - The Help ID of the page in question
  2481. // (this is the ID that will be launched
  2482. // for a help request from this page).
  2483. //
  2484. // Returns: BOOL - TRUE if the message was handled
  2485. //
  2486. // History: quintinb Created Header 10/15/98
  2487. //
  2488. //+----------------------------------------------------------------------------
  2489. INT_PTR APIENTRY ProcessHelp(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam, DWORD_PTR dwHelpId)
  2490. {
  2491. NMHDR* pnmHeader = (NMHDR*)lParam;
  2492. switch (message)
  2493. {
  2494. case WM_NOTIFY:
  2495. if (NULL == pnmHeader)
  2496. {
  2497. return FALSE;
  2498. }
  2499. switch (pnmHeader->code)
  2500. {
  2501. case PSN_HELP:
  2502. HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
  2503. return TRUE;
  2504. default:
  2505. return FALSE;
  2506. }
  2507. break;
  2508. case WM_HELP:
  2509. HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
  2510. return TRUE;
  2511. break;
  2512. case WM_COMMAND:
  2513. switch (LOWORD(wParam))
  2514. {
  2515. case IDC_HELPBUTTON:
  2516. HtmlHelp(hDlg, c_pszCmakOpsChm, HH_HELP_CONTEXT, dwHelpId); //lint !e534 we don't care about the htmlhelp HWND
  2517. return TRUE;
  2518. break;
  2519. }
  2520. default:
  2521. return FALSE;
  2522. }
  2523. }
  2524. //+----------------------------------------------------------------------------
  2525. //
  2526. // Function: ProcessWelcome
  2527. //
  2528. // Synopsis: Welcome to the Connection Manager Administration Kit.
  2529. //
  2530. //
  2531. // History: quintinb Created Header and renamed from ProcessPage1 8/6/98
  2532. //
  2533. //+----------------------------------------------------------------------------
  2534. INT_PTR APIENTRY ProcessWelcome(
  2535. HWND hDlg,
  2536. UINT message,
  2537. WPARAM wParam,
  2538. LPARAM lParam)
  2539. {
  2540. NMHDR* pnmHeader = (NMHDR*)lParam;
  2541. RECT rDlg;
  2542. RECT rWorkArea;
  2543. ProcessBold(hDlg,message);
  2544. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_WELCOME)) return TRUE;
  2545. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  2546. switch (message)
  2547. {
  2548. case WM_INITDIALOG:
  2549. if (GetWindowRect(GetParent(hDlg),&rDlg) && SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
  2550. {
  2551. MoveWindow(GetParent(hDlg),
  2552. rWorkArea.left + ((rWorkArea.right-rWorkArea.left)-(rDlg.right-rDlg.left))/2,
  2553. rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top)-(rDlg.bottom-rDlg.top))/2,
  2554. rDlg.right-rDlg.left,
  2555. rDlg.bottom-rDlg.top,
  2556. FALSE);
  2557. }
  2558. break;
  2559. case WM_NOTIFY:
  2560. if (NULL == pnmHeader)
  2561. {
  2562. return FALSE;
  2563. }
  2564. switch (pnmHeader->code)
  2565. {
  2566. case PSN_KILLACTIVE:
  2567. break;
  2568. case PSN_SETACTIVE:
  2569. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  2570. break;
  2571. case PSN_WIZBACK:
  2572. break;
  2573. case PSN_WIZNEXT:
  2574. break;
  2575. default:
  2576. return FALSE;
  2577. }
  2578. break;
  2579. default:
  2580. return FALSE;
  2581. }
  2582. return TRUE;
  2583. }
  2584. void ClearCmakGlobals(void)
  2585. {
  2586. //
  2587. // Free the connect action class
  2588. //
  2589. delete(g_pCustomActionList);
  2590. g_pCustomActionList = NULL;
  2591. FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
  2592. FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
  2593. FreeList(&g_pHeadExtra, &g_pTailExtra);
  2594. FreeList(&g_pHeadMerge, &g_pTailMerge);
  2595. FreeList(&g_pHeadRefs, &g_pTailRefs);
  2596. FreeList(&g_pHeadRename, &g_pTailRename);
  2597. FreeIconMenu();
  2598. g_szOutExe[0] = TEXT('\0');
  2599. g_szCmsFile[0] = TEXT('\0');
  2600. g_szInfFile[0] = TEXT('\0');
  2601. g_szCmpFile[0] = TEXT('\0');
  2602. g_szSedFile[0] = TEXT('\0');
  2603. EraseTempDir();
  2604. _tcscpy(g_szOutdir, g_szTempDir);
  2605. //
  2606. // Reset Connect Action Intro Screen
  2607. //
  2608. g_bUseTunneling = FALSE;
  2609. }
  2610. BOOL EnsureProfileFileExists(LPTSTR pszOutFile, LPCTSTR szTemplateFileName, LPCTSTR szExtension, UINT uCharsInBuffer)
  2611. {
  2612. TCHAR szTemp[MAX_PATH+1];
  2613. MYVERIFY(uCharsInBuffer > (UINT)wsprintf(pszOutFile, TEXT("%s\\%s%s"), g_szOutdir,
  2614. g_szShortServiceName, szExtension));
  2615. if (!FileExists(pszOutFile))
  2616. {
  2617. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
  2618. g_szSupportDir, szTemplateFileName));
  2619. if (!CopyFileWrapper(szTemp, pszOutFile, FALSE))
  2620. {
  2621. return FALSE;
  2622. }
  2623. MYVERIFY(0 != SetFileAttributes(pszOutFile, FILE_ATTRIBUTE_NORMAL));
  2624. }
  2625. return TRUE;
  2626. }
  2627. BOOL IsNativeLCID(LPCTSTR szFullPathToInf)
  2628. {
  2629. HANDLE hFile;
  2630. TCHAR szName[MAX_PATH+1] = TEXT("");
  2631. TCHAR szNativeLCID[MAX_PATH+1] = TEXT("");
  2632. hFile = CreateFile(szFullPathToInf, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2633. if (INVALID_HANDLE_VALUE != hFile)
  2634. {
  2635. MYVERIFY(0 != CloseHandle(hFile));
  2636. //
  2637. // First check for the new LCID location under strings
  2638. //
  2639. if (0 == GetPrivateProfileString(c_pszInfSectionStrings, c_pszCmLCID,
  2640. TEXT(""), szName, CELEMS(szName), szFullPathToInf))
  2641. {
  2642. //
  2643. // If the new key didn't exist, then try the old [Intl] section and
  2644. // display key. The change was made during the CMAK Unicode changes to
  2645. // make the inf template easier to localize.
  2646. //
  2647. MYVERIFY(0 != GetPrivateProfileString(c_pszIntl, c_pszDisplay,
  2648. TEXT(""), szName, CELEMS(szName), szFullPathToInf));
  2649. }
  2650. if (TEXT('\0') != szName[0])
  2651. {
  2652. //
  2653. // This value should be an LCID so a negative value is invalid anyway
  2654. //
  2655. DWORD dwLang = (DWORD)_ttol(szName);
  2656. MYDBGASSERT((long)dwLang >= 0);
  2657. CmakVersion CmakVer;
  2658. DWORD dwNative = CmakVer.GetNativeCmakLCID();
  2659. MYDBGASSERT((long)dwNative >= 0);
  2660. if (dwLang == dwNative)
  2661. {
  2662. return TRUE;
  2663. }
  2664. }
  2665. }
  2666. return FALSE;
  2667. }
  2668. //+----------------------------------------------------------------------------
  2669. //
  2670. // Function: ProcessAddEditProfile
  2671. //
  2672. // Synopsis: Choose whether to create a new profile or edit an existing one.
  2673. //
  2674. //
  2675. // History: quintinb Created Header and renamed from ProcessPage1A 8/6/98
  2676. //
  2677. //+----------------------------------------------------------------------------
  2678. INT_PTR APIENTRY ProcessAddEditProfile(
  2679. HWND hDlg,
  2680. UINT message,
  2681. WPARAM wParam,
  2682. LPARAM lParam)
  2683. {
  2684. INT_PTR nResult;
  2685. INT_PTR lCount;
  2686. TCHAR szName[MAX_PATH+1];
  2687. TCHAR szTemp[MAX_PATH+1];
  2688. TCHAR szMsg[MAX_PATH+1];
  2689. TCHAR szLanguageDisplayName[MAX_PATH+1];
  2690. NMHDR* pnmHeader = (NMHDR*)lParam;
  2691. static LONG_PTR iCBSel = 0;
  2692. BOOL bNameChanged;
  2693. ProcessBold(hDlg,message);
  2694. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_STARTCUST)) return TRUE;
  2695. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  2696. SetDefaultGUIFont(hDlg,message,IDC_COMBO1);
  2697. switch (message)
  2698. {
  2699. case WM_INITDIALOG:
  2700. RefreshComboList(hDlg, g_pHeadProfile);
  2701. EnableWindow(GetDlgItem(hDlg, IDC_COMBO1), FALSE);
  2702. lCount = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  2703. if ((CB_ERR != lCount) && (lCount > 0))
  2704. {
  2705. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)0, (LPARAM)0));
  2706. }
  2707. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
  2708. g_bNewProfile = TRUE;
  2709. break;
  2710. case WM_COMMAND:
  2711. switch (LOWORD(wParam))
  2712. {
  2713. case IDC_RADIO1: //Build a new service profile
  2714. g_szShortServiceName[0] = TEXT('\0');
  2715. EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),FALSE);
  2716. g_bNewProfile = TRUE;
  2717. break;
  2718. case IDC_RADIO2: //Edit an existing service profile
  2719. EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),TRUE);
  2720. lCount = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, 0, (LPARAM)0);
  2721. if ((CB_ERR != lCount) && (lCount > 0))
  2722. {
  2723. if (iCBSel > lCount)
  2724. {
  2725. iCBSel = 0;
  2726. }
  2727. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL,
  2728. (WPARAM)iCBSel, (LPARAM)0));
  2729. }
  2730. g_bNewProfile = FALSE;
  2731. break;
  2732. case IDC_COMBO1:
  2733. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  2734. nResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, 0, (LPARAM)0);
  2735. if (nResult != LB_ERR)
  2736. {
  2737. iCBSel = nResult;
  2738. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
  2739. (WPARAM)iCBSel, (LPARAM)szName));
  2740. }
  2741. else
  2742. {
  2743. SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, 0, (LPARAM)0); //lint !e534 this will error if no items in combo
  2744. nResult = SendDlgItemMessage(hDlg,IDC_COMBO1,CB_GETCURSEL,0,(LPARAM)0);
  2745. if (nResult != LB_ERR)
  2746. {
  2747. iCBSel = nResult;
  2748. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
  2749. (WPARAM)nResult, (LPARAM)szName));
  2750. }
  2751. else
  2752. {
  2753. return 1;
  2754. }
  2755. }
  2756. EnableWindow(GetDlgItem(hDlg,IDC_COMBO1),TRUE);
  2757. break;
  2758. default:
  2759. break;
  2760. }
  2761. break;
  2762. case WM_NOTIFY:
  2763. if (NULL == pnmHeader)
  2764. {
  2765. return FALSE;
  2766. }
  2767. switch (pnmHeader->code)
  2768. {
  2769. case PSN_KILLACTIVE:
  2770. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  2771. return 1;
  2772. break; //lint !e527 this line isn't reachable but
  2773. // keep it in case the return is removed
  2774. case PSN_SETACTIVE:
  2775. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  2776. break;
  2777. case PSN_WIZBACK:
  2778. case PSN_WIZNEXT:
  2779. //
  2780. // Establish global platform path
  2781. //
  2782. MYVERIFY(CELEMS(g_szOsdir) > (UINT)wsprintf(g_szOsdir, TEXT("%s%s\\"),
  2783. g_szCmakdir, c_pszProfiles));
  2784. //
  2785. // Create the support dir path and get the Name of its Language
  2786. //
  2787. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
  2788. g_szCmakdir, c_pszSupport, c_pszTemplateInf));
  2789. MYVERIFY(FALSE != GetLangFromInfTemplate(szTemp, szLanguageDisplayName,
  2790. CELEMS(szLanguageDisplayName)));
  2791. //
  2792. // Determine if its a new or existing profile
  2793. //
  2794. if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
  2795. {
  2796. //
  2797. // Editing an existing profile
  2798. //
  2799. nResult = SendDlgItemMessage(hDlg,IDC_COMBO1,CB_GETCURSEL,0,(LPARAM)0);
  2800. if (nResult != LB_ERR)
  2801. {
  2802. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETLBTEXT,
  2803. (WPARAM)nResult, (LPARAM)szName));
  2804. }
  2805. else
  2806. {
  2807. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPROF, MB_OK));
  2808. SetFocus(GetDlgItem(hDlg, IDC_COMBO1));
  2809. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2810. return 1;
  2811. }
  2812. //
  2813. // if already editing a profile, don't reset everything
  2814. // if didn't switch to another profile.
  2815. //
  2816. bNameChanged = (_tcsicmp(szName,g_szShortServiceName) != 0);
  2817. if (bNameChanged)
  2818. {
  2819. _tcscpy(g_szShortServiceName, szName);
  2820. ClearCmakGlobals();
  2821. //
  2822. // Okay, copy the profile files to the temp dir
  2823. //
  2824. if (!CopyToTempDir(g_szShortServiceName))
  2825. {
  2826. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2827. return 1;
  2828. }
  2829. }
  2830. //
  2831. // We need to make sure that the user has Read/Write
  2832. // permissions to the Profiles\<g_szShortServiceName> directory. Otherwise
  2833. // they can get themselves into the situation where they would build a
  2834. // whole profile and lose all of the work because they couldn't
  2835. // save it to the output directory (since we work out of the temp
  2836. // dir until we actually build the cab itself). NTRAID 372081
  2837. //
  2838. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, g_szShortServiceName));
  2839. if (!HasSpecifiedAccessToFileOrDir(szTemp, FILE_GENERIC_READ | FILE_GENERIC_WRITE))
  2840. {
  2841. //
  2842. // Then we need to throw an error to the user and exit.
  2843. //
  2844. LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_INSUFF_PERMS);
  2845. if (pszTmp)
  2846. {
  2847. DWORD dwSize = lstrlen(pszTmp) + lstrlen(szTemp) + 1;
  2848. LPTSTR pszMsg = (LPTSTR)CmMalloc(dwSize*sizeof(TCHAR));
  2849. if (pszMsg)
  2850. {
  2851. wsprintf(pszMsg, pszTmp, szTemp);
  2852. MessageBox(NULL, pszMsg, g_szAppTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL);
  2853. CmFree(pszMsg);
  2854. }
  2855. CmFree(pszTmp);
  2856. }
  2857. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2858. return 1;
  2859. }
  2860. }
  2861. else
  2862. {
  2863. //
  2864. // Building a new profile
  2865. //
  2866. if (TEXT('\0') == g_szShortServiceName[0])
  2867. {
  2868. ClearCmakGlobals();
  2869. if (FileExists(g_szTempDir))
  2870. {
  2871. EraseTempDir();
  2872. }
  2873. MYVERIFY(0 != CreateDirectory(g_szTempDir, NULL));
  2874. }
  2875. }
  2876. // CHECK IF .CMS .CMP .INF .SED FILES EXIST, CREATE FROM TEMPLATE IF NOT EXIST
  2877. // Don't do this if in the special case where we have not verified the short name.
  2878. GetFileName(g_szCmsFile, szTemp);
  2879. if (_tcsicmp(szTemp, TEXT(".cms")) != 0)
  2880. {
  2881. if (!EnsureProfileFileExists(g_szCmsFile, c_pszTemplateCms, TEXT(".cms"), MAX_PATH))
  2882. {
  2883. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2884. return 1;
  2885. }
  2886. if (!EnsureProfileFileExists(g_szCmpFile, c_pszTemplateCmp, c_pszCmpExt, MAX_PATH))
  2887. {
  2888. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2889. return 1;
  2890. }
  2891. if (!EnsureProfileFileExists(g_szSedFile, c_pszTemplateSed, TEXT(".sed"), MAX_PATH))
  2892. {
  2893. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2894. return 1;
  2895. }
  2896. if (!EnsureProfileFileExists(g_szInfFile, c_pszTemplateInf, TEXT(".inf"), MAX_PATH))
  2897. {
  2898. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2899. return 1;
  2900. }
  2901. //
  2902. // Since we removed multi-language support from CMAK (NTRAID 177515),
  2903. // we need to check to make sure they aren't trying to edit a foriegn
  2904. // language profile. If so then we need to force an upgrade.
  2905. //
  2906. if (!IsNativeLCID(g_szInfFile))
  2907. {
  2908. MYVERIFY(0 != LoadString(g_hInstance, IDS_NONNATIVELCID, szTemp, MAX_PATH));
  2909. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, g_szShortServiceName, szLanguageDisplayName));
  2910. if (IDYES == MessageBox(hDlg, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION))
  2911. {
  2912. //
  2913. // They want to continue in the current language so upgrade the
  2914. // inf so that it uses the native language template.
  2915. //
  2916. MYVERIFY(CELEMS(szTemp) > (UINT) wsprintf(szTemp, TEXT("%s.bak"), g_szInfFile));
  2917. MYVERIFY(TRUE == UpgradeInf(szTemp, g_szInfFile));
  2918. }
  2919. else
  2920. {
  2921. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  2922. return 1;
  2923. }
  2924. }
  2925. //
  2926. // Since the Unicode changes to CMAK and the multi-language capabilities of NT5, it is
  2927. // possible to create many different language profiles inside CMAK. Thus we need to check that
  2928. // the Current System Default language and the language of the profile the user is editing have
  2929. // the same primary language ID, otherwise display problems may arise. For instance, a use
  2930. // with an English version of the OS and CMAK, could set their default system locale to Japanese
  2931. // and create a Japanese profile for a client. Then if they change their system default language
  2932. // back to English and try to edit the profile the Japanese characters in the profile will not
  2933. // display correctly. Thus, we should detect the situation where the display language of the profile
  2934. // and the current system default language are not the same and throw a warning.
  2935. //
  2936. DWORD dwSystemDefaultLCID = GetSystemDefaultLCID();
  2937. DWORD dwProfileDisplayLanguage = 0;
  2938. if (0 != GetPrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLCID,
  2939. TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile))
  2940. {
  2941. dwProfileDisplayLanguage = (DWORD)_ttol(szTemp);
  2942. if (!ArePrimaryLangIDsEqual(dwProfileDisplayLanguage, dwSystemDefaultLCID))
  2943. {
  2944. //
  2945. // If we are in here, then the default system LCID that the profile was
  2946. // last editted in and the current Default System LCID
  2947. // have a different Primary language (Japanese vs English for instance).
  2948. // Thus we want to warn the user that they can continue but certain characters
  2949. // may not display properly. They should probably change their system default
  2950. // locale back to the setting that it was originally editted in.
  2951. //
  2952. //
  2953. // Get the Language Names of the Two LCIDs (sys default and CMAK lang)
  2954. //
  2955. LPTSTR pszSystemLanguage = GetLocalizedLanguageNameFromLCID(dwSystemDefaultLCID);
  2956. LPTSTR pszProfileDisplayLanguage = GetLocalizedLanguageNameFromLCID(dwProfileDisplayLanguage);
  2957. LPTSTR pszFmtString = CmLoadString(g_hInstance, IDS_DIFF_DISPLAY_LCID);
  2958. if (pszSystemLanguage && pszProfileDisplayLanguage && pszFmtString)
  2959. {
  2960. LPTSTR pszMsg = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lstrlen(pszSystemLanguage) +
  2961. lstrlen(pszProfileDisplayLanguage) + lstrlen(pszFmtString) + 1));
  2962. if (pszMsg)
  2963. {
  2964. wsprintf(pszMsg, pszFmtString, pszSystemLanguage, pszProfileDisplayLanguage);
  2965. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK | MB_ICONINFORMATION);
  2966. CmFree(pszMsg);
  2967. }
  2968. }
  2969. CmFree(pszSystemLanguage);
  2970. CmFree(pszProfileDisplayLanguage);
  2971. CmFree(pszFmtString);
  2972. }
  2973. }
  2974. //
  2975. // We have the possiblity that the inf will be of an old format. Call
  2976. // Upgrade Inf to see if it needs to be upgraded.
  2977. //
  2978. MYVERIFY (TRUE == EnsureInfIsCurrent(hDlg, g_szInfFile));
  2979. WriteInfVersion(g_szInfFile); //lint !e534
  2980. }
  2981. break;
  2982. default:
  2983. return FALSE;
  2984. }
  2985. break;
  2986. default:
  2987. return FALSE;
  2988. }
  2989. return TRUE;
  2990. }
  2991. //
  2992. // Write out profile strings with quotes around the entry
  2993. // Takes string const as second param
  2994. //
  2995. void QS_WritePrivateProfileString(LPCTSTR pszSection, LPCTSTR pszItem, LPTSTR entry, LPCTSTR inifile)
  2996. {
  2997. TCHAR szTemp[2*MAX_PATH+1] = TEXT("");
  2998. if (NULL != entry)
  2999. {
  3000. MYDBGASSERT(_tcslen(entry) <= ((2 * MAX_PATH) - 2));
  3001. _tcscpy(szTemp,TEXT("\""));
  3002. _tcscat(szTemp,entry);
  3003. _tcscat(szTemp,TEXT("\""));
  3004. }
  3005. MYDBGASSERT(_tcslen(szTemp) <= sizeof(szTemp));
  3006. MYVERIFY(0 != WritePrivateProfileString(pszSection, pszItem, szTemp, inifile));
  3007. }
  3008. //+----------------------------------------------------------------------------
  3009. //
  3010. // Function: ValidateServiceName
  3011. //
  3012. // Synopsis: This function makes sure that a long service name is valid.
  3013. // For a long service name to be valid it must contain at least
  3014. // one alpha-numeric character, not start with a period (.), and
  3015. // not contain any of the following characters : */\\:?\"<>|[]
  3016. //
  3017. // Arguments: LPCTSTR pszLongServiceName - the service name to check
  3018. //
  3019. // Returns: BOOL returns TRUE if the name is valid.
  3020. //
  3021. //
  3022. // History: quintinb Created 10/29/98
  3023. //
  3024. //+----------------------------------------------------------------------------
  3025. int ValidateServiceName(HWND hDlg, LPTSTR pszLongServiceName)
  3026. {
  3027. BOOL bBadServiceNameCharFound = FALSE;
  3028. BOOL bFoundAlphaNumeric = FALSE;
  3029. LPTSTR pch;
  3030. int iLen;
  3031. if ((NULL == pszLongServiceName) || (TEXT('\0') == pszLongServiceName[0]))
  3032. {
  3033. //
  3034. // Cannot have an empty service name
  3035. //
  3036. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSERVICE, MB_OK));
  3037. return FALSE;
  3038. }
  3039. else if (MAX_LONG_SERVICE_NAME_LENGTH < _tcslen(pszLongServiceName))
  3040. {
  3041. //
  3042. // Too Long
  3043. //
  3044. TCHAR* pszMsg = CmFmtMsg(g_hInstance, IDS_SERVICENAMETOBIG, MAX_LONG_SERVICE_NAME_LENGTH);
  3045. if (pszMsg)
  3046. {
  3047. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  3048. CmFree(pszMsg);
  3049. }
  3050. return FALSE;
  3051. }
  3052. else
  3053. {
  3054. iLen = lstrlen(g_szBadLongServiceNameChars);
  3055. pch = pszLongServiceName;
  3056. //
  3057. // Check that the service name doesn't start with a period
  3058. //
  3059. if (TEXT('.') == pszLongServiceName[0])
  3060. {
  3061. bBadServiceNameCharFound = TRUE;
  3062. }
  3063. //
  3064. // Check that it doesn't contain any bad characters
  3065. //
  3066. while (!bBadServiceNameCharFound && (*pch != _T('\0')))
  3067. {
  3068. for (int j = 0; j < iLen; ++j)
  3069. {
  3070. if (*pch == g_szBadLongServiceNameChars[j])
  3071. {
  3072. bBadServiceNameCharFound = TRUE;
  3073. break;
  3074. }
  3075. }
  3076. pch = CharNext(pch);
  3077. }
  3078. //
  3079. // Check that it contains at least one alphanumeric character
  3080. //
  3081. iLen = lstrlen(pszLongServiceName);
  3082. WORD *pwCharTypeArray = (WORD*)CmMalloc(sizeof(WORD)*(iLen + 1));
  3083. if (pwCharTypeArray)
  3084. {
  3085. if (GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, pszLongServiceName, -1, pwCharTypeArray))
  3086. {
  3087. for (int i = 0; i < iLen; i++)
  3088. {
  3089. if (pwCharTypeArray[i] & (C1_ALPHA | C1_DIGIT))
  3090. {
  3091. bFoundAlphaNumeric = TRUE;
  3092. break; // only need one alpha numeric char.
  3093. }
  3094. }
  3095. }
  3096. CmFree(pwCharTypeArray);
  3097. }
  3098. if (bBadServiceNameCharFound || !bFoundAlphaNumeric)
  3099. {
  3100. //
  3101. // Contains bad chars.
  3102. //
  3103. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADLONGNAME, g_szBadLongServiceNameChars);
  3104. if (pszMsg)
  3105. {
  3106. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  3107. CmFree(pszMsg);
  3108. }
  3109. return FALSE;
  3110. }
  3111. else
  3112. {
  3113. //
  3114. // A good long service name
  3115. //
  3116. return TRUE;
  3117. }
  3118. }
  3119. }
  3120. //+----------------------------------------------------------------------------
  3121. //
  3122. // Function: ValidateShortServiceName
  3123. //
  3124. // Synopsis: This function checks to see if a given short service name is valid.
  3125. // To be valid, a short service name must be less than 8 bytes long
  3126. // (but not empty) and must not contain any characters found in
  3127. // g_szBadFilenameChars ... basically we only allow letters and
  3128. // numbers.
  3129. //
  3130. // Arguments: LPTSTR pszShortServiceName - the short service name to verify
  3131. //
  3132. // Returns: BOOL - TRUE if the short service name passed in is valid
  3133. //
  3134. // History: quintinb Created 10/29/98
  3135. //
  3136. //+----------------------------------------------------------------------------
  3137. BOOL ValidateShortServiceName(HWND hDlg, LPTSTR pszShortServiceName)
  3138. {
  3139. LPTSTR pch;
  3140. if ((NULL == pszShortServiceName) || (TEXT('\0') == pszShortServiceName[0]))
  3141. {
  3142. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSHORTNAME, MB_OK));
  3143. return FALSE;
  3144. }
  3145. //
  3146. // Notice that 8.3 filenames are 8 bytes not 8 characters. Thus we can only have
  3147. // 4 DBCS chars.
  3148. //
  3149. #ifdef UNICODE
  3150. LPSTR pszAnsiShortServiceName = WzToSzWithAlloc(pszShortServiceName);
  3151. if (MAX_SHORT_SERVICE_NAME_LENGTH < lstrlenA(pszAnsiShortServiceName))
  3152. #else
  3153. if (MAX_SHORT_SERVICE_NAME_LENGTH < strlen(pszShortServiceName))
  3154. #endif
  3155. {
  3156. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_TOOLONG, MB_OK));
  3157. return FALSE;
  3158. }
  3159. else
  3160. {
  3161. // check for valid file name
  3162. int iLen = lstrlen(g_szBadFilenameChars);
  3163. pch = pszShortServiceName;
  3164. while(*pch != _T('\0'))
  3165. {
  3166. for (int j = 0; j < iLen; ++j)
  3167. {
  3168. if (*pch == g_szBadFilenameChars[j])
  3169. {
  3170. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADNAME, g_szBadFilenameChars);
  3171. if (pszMsg)
  3172. {
  3173. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  3174. CmFree(pszMsg);
  3175. }
  3176. return FALSE;
  3177. }
  3178. }
  3179. pch = CharNext(pch);
  3180. }
  3181. }
  3182. #ifdef UNICODE
  3183. CmFree(pszAnsiShortServiceName);
  3184. #endif
  3185. return TRUE;
  3186. }
  3187. //+----------------------------------------------------------------------------
  3188. //
  3189. // Function: CmStrStrI
  3190. //
  3191. // Synopsis: Simple replacement for StrStr from C runtime, but case-insensitive
  3192. //
  3193. // Arguments: LPCTSTR pszString - The string to search in
  3194. // LPCTSTR pszSubString - The string to search for
  3195. //
  3196. // Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
  3197. // NULL if pszSubString does not occur in pszString
  3198. //
  3199. //
  3200. // History: SumitC copied from CmStrStrW 15-Mar-2001
  3201. //
  3202. //+----------------------------------------------------------------------------
  3203. CMUTILAPI LPWSTR CmStrStrI(LPCWSTR pszString, LPCWSTR pszSubString)
  3204. {
  3205. //
  3206. // Check the inputs
  3207. //
  3208. MYDBGASSERT(pszString);
  3209. MYDBGASSERT(pszSubString);
  3210. if (NULL == pszSubString || NULL == pszString)
  3211. {
  3212. return NULL;
  3213. }
  3214. //
  3215. // Check to make sure we have something to look for
  3216. //
  3217. if (TEXT('\0') == pszSubString[0])
  3218. {
  3219. return((LPWSTR)pszString);
  3220. }
  3221. //
  3222. // Okay, start looking for the string
  3223. //
  3224. LPWSTR pszCurrent = (LPWSTR)pszString;
  3225. LPWSTR pszTmp1;
  3226. LPWSTR pszTmp2;
  3227. while (*pszCurrent)
  3228. {
  3229. pszTmp1 = pszCurrent;
  3230. pszTmp2 = (LPWSTR) pszSubString;
  3231. while (*pszTmp1 && *pszTmp2 && (tolower(*pszTmp1) == tolower(*pszTmp2)))
  3232. {
  3233. pszTmp1 = CharNext(pszTmp1);
  3234. pszTmp2 = CharNext(pszTmp2);
  3235. }
  3236. if (TEXT('\0') == *pszTmp2)
  3237. {
  3238. return pszCurrent;
  3239. }
  3240. pszCurrent = CharNext(pszCurrent);
  3241. }
  3242. return NULL;
  3243. }
  3244. //+----------------------------------------------------------------------------
  3245. //
  3246. // Func: FixupCMSFileForClonedProfile
  3247. //
  3248. // Desc: Parses the CMS file and replaces references to the old shortname
  3249. //
  3250. // Args: [pszCMSFile] - name of the CMS file
  3251. // [pszOld] - old short service name
  3252. // [pszNew] - new short service name
  3253. //
  3254. // Return: HRESULT
  3255. //
  3256. // Notes:
  3257. //
  3258. // History: 16-Feb-2001 SumitC Created
  3259. //
  3260. //-----------------------------------------------------------------------------
  3261. HRESULT
  3262. FixupCMSFileForClonedProfile(LPTSTR pszCMSFile, LPTSTR pszOld, LPTSTR pszNew)
  3263. {
  3264. HRESULT hr = S_OK;
  3265. LPTSTR pszCurrentSection = NULL;
  3266. MYDBGASSERT(pszCMSFile);
  3267. MYDBGASSERT(pszOld);
  3268. MYDBGASSERT(pszNew);
  3269. MYDBGASSERT(lstrlen(pszOld) <= MAX_SHORT_SERVICE_NAME_LENGTH);
  3270. if (NULL == pszCMSFile || NULL == pszOld || NULL == pszNew ||
  3271. (lstrlen(pszOld) > MAX_SHORT_SERVICE_NAME_LENGTH))
  3272. {
  3273. return E_INVALIDARG;
  3274. }
  3275. //
  3276. // Set up the string we're going to look for in the Values
  3277. //
  3278. TCHAR szOldNamePlusSlash[MAX_SHORT_SERVICE_NAME_LENGTH + 1 + 1];
  3279. lstrcpy(szOldNamePlusSlash, pszOld);
  3280. lstrcat(szOldNamePlusSlash, TEXT("\\"));
  3281. //
  3282. // read in all the sections from the CMS file
  3283. //
  3284. LPTSTR pszAllSections = GetPrivateProfileStringWithAlloc(NULL, NULL, TEXT(""), pszCMSFile);
  3285. //
  3286. // iterate over all the sections
  3287. //
  3288. for (pszCurrentSection = pszAllSections;
  3289. pszCurrentSection && (TEXT('\0') != pszCurrentSection[0]);
  3290. pszCurrentSection += (lstrlen(pszCurrentSection) + 1))
  3291. {
  3292. //
  3293. // Skip the [Connection Manager] section. The entries here are image files,
  3294. // and are dealt with in a later CMAK page.
  3295. //
  3296. if (0 == lstrcmpi(c_pszCmSection, pszCurrentSection))
  3297. {
  3298. continue;
  3299. }
  3300. //
  3301. // for each section, get all the keys
  3302. //
  3303. LPTSTR pszKeysInThisSection = GetPrivateProfileStringWithAlloc(pszCurrentSection, NULL, TEXT(""), pszCMSFile);
  3304. LPTSTR pszCurrentKey = NULL;
  3305. //
  3306. // iterate over all the keys
  3307. //
  3308. for (pszCurrentKey = pszKeysInThisSection;
  3309. pszCurrentKey && (TEXT('\0') != pszCurrentKey[0]);
  3310. pszCurrentKey += (lstrlen(pszCurrentKey) + 1)) // alternate is CmEndOfStr(pszCurrentKeyName) & pszCurrentKeyName++
  3311. {
  3312. //
  3313. // Get the value for this key
  3314. //
  3315. LPTSTR pszValue = GetPrivateProfileStringWithAlloc(pszCurrentSection, pszCurrentKey, TEXT(""), pszCMSFile);
  3316. if (pszValue)
  3317. {
  3318. //
  3319. // Search for "pszOld\", and replace with "pszNew\" (the \ is
  3320. // to ensure that it is part of a path)
  3321. //
  3322. if (CmStrStrI(pszValue, szOldNamePlusSlash) == pszValue)
  3323. {
  3324. UINT cLen = lstrlen(pszValue) - lstrlen(pszOld) + lstrlen(pszNew) + 1;
  3325. LPTSTR pszNewValue = (LPTSTR) CmMalloc(cLen * sizeof(TCHAR));
  3326. if (pszNewValue)
  3327. {
  3328. lstrcpy(pszNewValue, pszNew);
  3329. lstrcat(pszNewValue, TEXT("\\"));
  3330. lstrcat(pszNewValue, pszValue + lstrlen(szOldNamePlusSlash));
  3331. //
  3332. // Write back the value (this doesn't affect the list
  3333. // of keys, so it is safe to do.)
  3334. //
  3335. MYDBGASSERT(0 != WritePrivateProfileString(pszCurrentSection, pszCurrentKey, pszNewValue, pszCMSFile));
  3336. CmFree(pszNewValue);
  3337. }
  3338. }
  3339. CmFree(pszValue);
  3340. }
  3341. }
  3342. CmFree(pszKeysInThisSection);
  3343. }
  3344. CmFree(pszAllSections);
  3345. return hr;
  3346. }
  3347. //+----------------------------------------------------------------------------
  3348. //
  3349. // Func: CloneProfile
  3350. //
  3351. // Desc: Does the gruntwork to clone a given profile
  3352. //
  3353. // Args: [pszShortServiceName] - new short service name
  3354. // [pszLongServiceName] - new long service name
  3355. //
  3356. // Return: HRESULT
  3357. //
  3358. // Notes:
  3359. //
  3360. // History: 16-Feb-2001 SumitC Created (most code copied from ProcessServiceName)
  3361. //
  3362. //-----------------------------------------------------------------------------
  3363. HRESULT
  3364. CloneProfile(IN LPTSTR pszShortServiceName, IN LPTSTR pszLongServiceName)
  3365. {
  3366. HRESULT hr = S_OK;
  3367. TCHAR szMsg[MAX_PATH+1];
  3368. MYDBGASSERT(pszShortServiceName);
  3369. MYDBGASSERT(pszLongServiceName);
  3370. if ((_tcsicmp(g_szShortServiceName, pszShortServiceName) != 0))
  3371. {
  3372. //
  3373. // If this is a cloned profile, we want to delete the
  3374. // old executable file and the old .inf.bak file so that
  3375. // we don't leave it around.
  3376. //
  3377. if (TEXT('\0') != g_szShortServiceName[0])
  3378. {
  3379. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg,
  3380. TEXT("%s\\%s.exe"), g_szOutdir, g_szShortServiceName));
  3381. DeleteFile(szMsg);
  3382. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg,
  3383. TEXT("%s\\%s.inf.bak"), g_szOutdir, g_szShortServiceName));
  3384. DeleteFile(szMsg);
  3385. }
  3386. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
  3387. c_pszDesktopGuid,TEXT(""), g_szInfFile));
  3388. //
  3389. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  3390. // (win95 only). This call will return 0.
  3391. //
  3392. WritePrivateProfileString(NULL, NULL, NULL, g_szInfFile); //lint !e534 this call will return 0
  3393. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.inf"),
  3394. g_szOutdir, pszShortServiceName));
  3395. MYVERIFY(0 != MoveFile(g_szInfFile, szMsg));
  3396. _tcscpy(g_szInfFile, szMsg);
  3397. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.sed"),
  3398. g_szOutdir, pszShortServiceName));
  3399. MYVERIFY(0 != MoveFile(g_szSedFile, szMsg));
  3400. _tcscpy(g_szSedFile, szMsg);
  3401. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.cms"),
  3402. g_szOutdir, pszShortServiceName));
  3403. MYVERIFY(0 != MoveFile(g_szCmsFile, szMsg));
  3404. _tcscpy(g_szCmsFile, szMsg);
  3405. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, TEXT("%s\\%s.cmp"),
  3406. g_szOutdir, pszShortServiceName));
  3407. MYVERIFY(0 != MoveFile(g_szCmpFile, szMsg));
  3408. _tcscpy(g_szCmpFile, szMsg);
  3409. //
  3410. // Fix up any entries that are pointing to the old path
  3411. //
  3412. (void) FixupCMSFileForClonedProfile(g_szCmsFile, g_szShortServiceName, pszShortServiceName);
  3413. }
  3414. _tcscpy(g_szShortServiceName, pszShortServiceName);
  3415. //
  3416. // Check to see if the user changed the long service name
  3417. //
  3418. if ((0 != lstrcmpi(pszLongServiceName, g_szLongServiceName)) && (TEXT('\0') != g_szLongServiceName[0]))
  3419. {
  3420. const int c_iNumDunSubSections = 4;
  3421. TCHAR szCurrentSectionName[MAX_PATH+1];
  3422. TCHAR szNewSectionName[MAX_PATH+1];
  3423. const TCHAR* const ArrayOfSubSections[c_iNumDunSubSections] =
  3424. {
  3425. c_pszCmSectionDunServer,
  3426. c_pszCmSectionDunNetworking,
  3427. c_pszCmSectionDunTcpIp,
  3428. c_pszCmSectionDunScripting
  3429. };
  3430. //
  3431. // Free the DNS list so that we will re-read it later. This ensures that
  3432. // we will get rid of any default entries we added that don't really exist
  3433. // and will add new defaults if we need them.
  3434. //
  3435. FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
  3436. FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
  3437. //
  3438. // The user cloned the long service name. Update the DUN key and rename the
  3439. // default DUN entry if the long service name and the DUN name match. If they
  3440. // don't match we don't want to rename them as a phonebook may be referencing them
  3441. // by their original name.
  3442. //
  3443. GetDefaultDunSettingName(g_szCmsFile, g_szLongServiceName, pszShortServiceName, MAX_PATH + 1);
  3444. if (0 == lstrcmpi(g_szLongServiceName, pszShortServiceName))
  3445. {
  3446. for (int i = 0; i < c_iNumDunSubSections; i++)
  3447. {
  3448. wsprintf(szCurrentSectionName, TEXT("%s&%s"), ArrayOfSubSections[i], g_szLongServiceName);
  3449. wsprintf(szNewSectionName, TEXT("%s&%s"), ArrayOfSubSections[i], pszLongServiceName);
  3450. RenameSection(szCurrentSectionName, szNewSectionName, g_szCmsFile);
  3451. }
  3452. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryDun, pszLongServiceName, g_szCmsFile));
  3453. }
  3454. //
  3455. // Now update the TunnelDUN key and rename the Tunnel DUN entry if Tunnel DUN name is based on the original
  3456. // long service name. If they aren't related then we don't want to rename them.
  3457. //
  3458. GetTunnelDunSettingName(g_szCmsFile, g_szLongServiceName, pszShortServiceName, MAX_PATH + 1);
  3459. wsprintf(szMsg, TEXT("%s %s"), g_szLongServiceName, c_pszCmEntryTunnelPrimary);
  3460. if (0 == lstrcmpi(szMsg, pszShortServiceName))
  3461. {
  3462. for (int i = 0; i < c_iNumDunSubSections; i++)
  3463. {
  3464. wsprintf(szCurrentSectionName, TEXT("%s&%s %s"), ArrayOfSubSections[i], g_szLongServiceName, c_pszCmEntryTunnelPrimary);
  3465. wsprintf(szNewSectionName, TEXT("%s&%s %s"), ArrayOfSubSections[i], pszLongServiceName, c_pszCmEntryTunnelPrimary);
  3466. RenameSection(szCurrentSectionName, szNewSectionName, g_szCmsFile);
  3467. }
  3468. MYVERIFY(CELEMS(szNewSectionName) > (UINT)wsprintf(szNewSectionName, TEXT("%s %s"), pszLongServiceName, c_pszCmEntryTunnelPrimary));
  3469. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, szNewSectionName, g_szCmsFile));
  3470. }
  3471. }
  3472. CMTRACEHR("CloneProfile", hr);
  3473. return hr;
  3474. }
  3475. //+----------------------------------------------------------------------------
  3476. //
  3477. // Function: ProcessServiceName
  3478. //
  3479. // Synopsis: Setup service and File Names
  3480. //
  3481. //
  3482. // History: quintinb Created Header and renamed from ProcessPage2 8/6/98
  3483. //
  3484. //+----------------------------------------------------------------------------
  3485. INT_PTR APIENTRY ProcessServiceName(
  3486. HWND hDlg,
  3487. UINT message,
  3488. WPARAM wParam,
  3489. LPARAM lParam)
  3490. {
  3491. TCHAR szTemp[MAX_PATH+1];
  3492. TCHAR szTemp2[MAX_PATH+1];
  3493. TCHAR szMsg[MAX_PATH+1];
  3494. LONG lLongServiceReturn;
  3495. LONG lShortServiceReturn;
  3496. int nResult;
  3497. NMHDR* pnmHeader = (NMHDR*)lParam;
  3498. ProcessBold(hDlg,message);
  3499. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_NAMES)) return TRUE;
  3500. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  3501. SetDefaultGUIFont(hDlg,message,IDC_SERVICE);
  3502. SetDefaultGUIFont(hDlg,message,IDC_SSERVICE);
  3503. switch (message)
  3504. {
  3505. case WM_INITDIALOG:
  3506. // this init's the focus, otherwise Setfocus won't work 1st time
  3507. SetFocus(GetDlgItem(hDlg, IDC_SERVICE));
  3508. // bug fix 6234, quintinb 9-8-97
  3509. SendDlgItemMessage(hDlg, IDC_SERVICE, EM_SETLIMITTEXT, (WPARAM)MAX_LONG_SERVICE_NAME_LENGTH, (LPARAM)0);//lint !e534 EM_SETLIMITTEXT doesn't return anything useful
  3510. // end bug fix 6234, quintinb
  3511. break;
  3512. case WM_NOTIFY:
  3513. if (NULL == pnmHeader)
  3514. {
  3515. return FALSE;
  3516. }
  3517. switch (pnmHeader->code)
  3518. {
  3519. case PSN_KILLACTIVE:
  3520. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  3521. return 1;
  3522. break; //lint !e527 this line isn't reachable but
  3523. // keep it in case the return is removed
  3524. case PSN_SETACTIVE:
  3525. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  3526. if (*g_szShortServiceName)
  3527. {
  3528. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SSERVICE, WM_SETTEXT,
  3529. (WPARAM)0, (LPARAM) g_szShortServiceName));
  3530. GetFileName(g_szCmsFile,szTemp);
  3531. if (_tcsicmp(szTemp,TEXT(".cms")) != 0)
  3532. {
  3533. MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
  3534. TEXT(""), g_szLongServiceName, CELEMS(g_szLongServiceName), g_szCmsFile));
  3535. }
  3536. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SERVICE, WM_SETTEXT, (WPARAM)0,
  3537. (LPARAM) g_szLongServiceName));
  3538. }
  3539. else
  3540. {
  3541. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SERVICE, WM_SETTEXT,
  3542. (WPARAM)0, (LPARAM) NULL));
  3543. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SSERVICE, WM_SETTEXT,
  3544. (WPARAM)0, (LPARAM) NULL));
  3545. }
  3546. break;
  3547. case PSN_WIZBACK: // fall through to Next
  3548. case PSN_WIZNEXT:
  3549. // the Next button was pressed
  3550. if (-1 == GetTextFromControl(hDlg, IDC_SERVICE, szTemp2, MAX_PATH, (PSN_WIZNEXT == pnmHeader->code))) // bDisplayError == (PSN_WIZBACK == pnmHeader->code)
  3551. {
  3552. //
  3553. // Let the user go back if there is a problem with retrieving their text so that
  3554. // they can choose another profile.
  3555. //
  3556. if (PSN_WIZBACK == pnmHeader->code)
  3557. {
  3558. return FALSE;
  3559. }
  3560. else
  3561. {
  3562. goto ServiceNameError;
  3563. }
  3564. }
  3565. CmStrTrim(szTemp2);
  3566. if (-1 == GetTextFromControl(hDlg, IDC_SSERVICE, szTemp, MAX_PATH, (PSN_WIZNEXT == pnmHeader->code))) // bDisplayError == (PSN_WIZBACK == pnmHeader->code)
  3567. {
  3568. //
  3569. // Let the user go back if there is a problem with retrieving their text so that
  3570. // they can choose another profile.
  3571. //
  3572. if (PSN_WIZBACK == pnmHeader->code)
  3573. {
  3574. return FALSE;
  3575. }
  3576. else
  3577. {
  3578. goto ServiceNameError;
  3579. }
  3580. }
  3581. //
  3582. // If both the servicename and the short servicename are blank and the user
  3583. // is navigating back, then allow them to continue. Otherwise go through all
  3584. // the normal checks.
  3585. //
  3586. if ((pnmHeader && (PSN_WIZBACK == pnmHeader->code)))
  3587. {
  3588. if ((szTemp[0] == TEXT('\0')) && (szTemp2[0] == TEXT('\0')))
  3589. {
  3590. return 0;
  3591. }
  3592. }
  3593. //
  3594. // Validate the Long Service Name
  3595. //
  3596. if (!ValidateServiceName(hDlg, szTemp2))
  3597. {
  3598. goto ServiceNameError;
  3599. }
  3600. //
  3601. // Now lets validate the short service name
  3602. //
  3603. if (!ValidateShortServiceName(hDlg, szTemp))
  3604. {
  3605. goto ShortServiceNameError;
  3606. }
  3607. //
  3608. // Changing one of the service names without changing the
  3609. // other can cause problems when installing the profile
  3610. // later. Warn the user if this is the case.
  3611. //
  3612. { // scoping braces
  3613. BOOL bShortServiceNameChanged = !!lstrcmpi(g_szShortServiceName, szTemp);
  3614. BOOL bLongServiceNameChanged = !!lstrcmpi(g_szLongServiceName, szTemp2);
  3615. if ((FALSE == g_bNewProfile) && (bShortServiceNameChanged != bLongServiceNameChanged))
  3616. {
  3617. nResult = ShowMessage(hDlg, IDS_CHANGED_ONLY_SS_OR_LS, MB_YESNO);
  3618. if (nResult == IDYES)
  3619. {
  3620. if (bShortServiceNameChanged)
  3621. {
  3622. goto ServiceNameError;
  3623. }
  3624. if (bLongServiceNameChanged)
  3625. {
  3626. goto ShortServiceNameError;
  3627. }
  3628. }
  3629. }
  3630. }
  3631. //
  3632. // Create a default output directory based on the short name.
  3633. //
  3634. // NTRAID 159367 -- quintinb
  3635. // Must leave the comparison between the ShortName and szTemp, otherwise the
  3636. // user can change the shortname and we won't rename the files. This allows
  3637. // profile cloning.
  3638. //
  3639. if ((_tcsicmp(g_szShortServiceName, szTemp) != 0))
  3640. {
  3641. BOOL bFound;
  3642. bFound = FindListItemByName(szTemp, g_pHeadProfile, NULL); // NULL passed because we don't need a pointer to the item returned
  3643. if (bFound)
  3644. {
  3645. nResult = ShowMessage(hDlg,IDS_PROFEXISTS,MB_YESNO);
  3646. if (nResult == IDNO)
  3647. {
  3648. goto ShortServiceNameError;
  3649. }
  3650. }
  3651. MYVERIFY(S_OK == CloneProfile(szTemp, szTemp2));
  3652. }
  3653. //
  3654. // The Long Service Name is valid, lets keep it.
  3655. //
  3656. _tcscpy(g_szLongServiceName, szTemp2);
  3657. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName, g_szLongServiceName, g_szCmsFile));
  3658. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszCmEntryServiceName, g_szLongServiceName, g_szInfFile);
  3659. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszUninstallAppTitle, g_szLongServiceName, g_szInfFile);
  3660. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszShortSvcName, g_szShortServiceName, g_szInfFile);
  3661. break;
  3662. default:
  3663. return FALSE;
  3664. }
  3665. break;
  3666. default:
  3667. return FALSE;
  3668. }
  3669. return TRUE;
  3670. ServiceNameError:
  3671. SetFocus(GetDlgItem(hDlg, IDC_SERVICE));
  3672. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  3673. return 1;
  3674. ShortServiceNameError:
  3675. SetFocus(GetDlgItem(hDlg, IDC_SSERVICE));
  3676. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  3677. return 1;
  3678. }
  3679. //+----------------------------------------------------------------------------
  3680. //
  3681. // Function: ProcessSupportInfo
  3682. //
  3683. // Synopsis: Customize Support Information
  3684. //
  3685. //
  3686. // History: quintinb Created Header and renamed from ProcessPage2_A 8/6/98
  3687. //
  3688. //+----------------------------------------------------------------------------
  3689. INT_PTR APIENTRY ProcessSupportInfo(
  3690. HWND hDlg,
  3691. UINT message,
  3692. WPARAM wParam,
  3693. LPARAM lParam)
  3694. {
  3695. TCHAR szTemp[MAX_PATH+1];
  3696. NMHDR* pnmHeader = (NMHDR*)lParam;
  3697. ProcessBold(hDlg,message);
  3698. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_SUPPINFO)) return TRUE;
  3699. if (ProcessCancel(hDlg, message, lParam)) return TRUE;
  3700. SetDefaultGUIFont(hDlg, message, IDC_SUPPORT);
  3701. switch (message)
  3702. {
  3703. case WM_INITDIALOG:
  3704. // Fix for Whistler bug 9156
  3705. SendDlgItemMessage(hDlg, IDC_SUPPORT, EM_SETLIMITTEXT, (WPARAM) 50, 0);
  3706. // this init's the focus, otherwise Setfocus won't work 1st time
  3707. SetFocus(GetDlgItem(hDlg, IDC_SUPPORT));
  3708. break;
  3709. case WM_NOTIFY:
  3710. if (NULL == pnmHeader)
  3711. {
  3712. return FALSE;
  3713. }
  3714. switch (pnmHeader->code)
  3715. {
  3716. case PSN_KILLACTIVE:
  3717. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  3718. return 1;
  3719. break; //lint !e527 this line isn't reachable but
  3720. // keep it in case the return is removed
  3721. case PSN_SETACTIVE:
  3722. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  3723. //
  3724. // this call to GetPrivateProfileString may retreive a blank string, thus don't use the MYVERIFY macro
  3725. //
  3726. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceMessage, TEXT(""),
  3727. g_szSvcMsg, CELEMS(g_szSvcMsg), g_szCmsFile); //lint !e534
  3728. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SUPPORT, WM_SETTEXT,
  3729. (WPARAM)0, (LPARAM) g_szSvcMsg));
  3730. break;
  3731. case PSN_WIZBACK:
  3732. case PSN_WIZNEXT:
  3733. // the Next button was pressed
  3734. if (-1 == GetTextFromControl(hDlg, IDC_SUPPORT, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  3735. {
  3736. SetFocus(GetDlgItem(hDlg, IDC_SUPPORT));
  3737. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  3738. return 1;
  3739. }
  3740. CmStrTrim(szTemp);
  3741. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_SUPPORT, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
  3742. _tcscpy(g_szSvcMsg,szTemp);
  3743. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryServiceMessage,g_szSvcMsg,g_szCmsFile));
  3744. #ifdef _WIN64
  3745. //
  3746. // If we are going forward, skip the Include CM binaries page if this is IA64
  3747. //
  3748. if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code))
  3749. {
  3750. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_LICENSE));
  3751. }
  3752. #endif
  3753. break;
  3754. default:
  3755. return FALSE;
  3756. }
  3757. break;
  3758. default:
  3759. return FALSE;
  3760. }
  3761. return TRUE;
  3762. }
  3763. //+----------------------------------------------------------------------------
  3764. //
  3765. // Function: ProcessIncludeCm
  3766. //
  3767. // Synopsis: Include CM bits
  3768. //
  3769. //
  3770. // History: quintinb Created Header and renamed from ProcessPage2A 8/6/98
  3771. //
  3772. //+----------------------------------------------------------------------------
  3773. INT_PTR APIENTRY ProcessIncludeCm(
  3774. HWND hDlg,
  3775. UINT message,
  3776. WPARAM wParam,
  3777. LPARAM lParam)
  3778. {
  3779. TCHAR szTemp[MAX_PATH+1];
  3780. NMHDR* pnmHeader = (NMHDR*)lParam;
  3781. ProcessBold(hDlg,message);
  3782. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CMSW)) return TRUE;
  3783. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  3784. switch (message)
  3785. {
  3786. case WM_INITDIALOG:
  3787. break;
  3788. case WM_NOTIFY:
  3789. if (NULL == pnmHeader)
  3790. {
  3791. return FALSE;
  3792. }
  3793. switch (pnmHeader->code)
  3794. {
  3795. case PSN_KILLACTIVE:
  3796. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  3797. return 1;
  3798. break; //lint !e527 this line isn't reachable but
  3799. // keep it in case the return is removed
  3800. case PSN_SETACTIVE:
  3801. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  3802. MYVERIFY(0 != GetPrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode,
  3803. c_pszOne, szTemp, CELEMS(szTemp), g_szInfFile));
  3804. if (*szTemp == TEXT('1'))
  3805. {
  3806. g_bIncludeCmCode = TRUE;
  3807. MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,TRUE));
  3808. }
  3809. else
  3810. {
  3811. g_bIncludeCmCode = FALSE;
  3812. MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,FALSE));
  3813. }
  3814. break;
  3815. case PSN_WIZBACK:
  3816. case PSN_WIZNEXT:
  3817. g_bIncludeCmCode = IsDlgButtonChecked(hDlg,IDC_CHECK1);
  3818. if (g_bIncludeCmCode)
  3819. {
  3820. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszIncludeCmCode,c_pszOne,g_szInfFile));
  3821. }
  3822. else
  3823. {
  3824. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszIncludeCmCode,c_pszZero,g_szInfFile));
  3825. }
  3826. break;
  3827. default:
  3828. return FALSE;
  3829. }
  3830. break;
  3831. default:
  3832. return FALSE;
  3833. }
  3834. return TRUE;
  3835. }
  3836. void EnableDisableCmProxyControls(HWND hDlg)
  3837. {
  3838. BOOL bCmProxyEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  3839. HWND hControl = GetDlgItem(hDlg, IDC_EDIT1);
  3840. EnableWindow(hControl, bCmProxyEnabled);
  3841. hControl = GetDlgItem(hDlg, IDC_CHECK1);
  3842. EnableWindow(hControl, bCmProxyEnabled);
  3843. hControl = GetDlgItem(hDlg, IDC_PROXYLABEL);
  3844. EnableWindow(hControl, bCmProxyEnabled);
  3845. }
  3846. BOOL FillInCustomActionStructWithCmProxy(BOOL bRestorePrevProxySettings, CustomActionListItem* pCustomAction,
  3847. BOOL bDisconnectAction, LPCTSTR pszProxyFile)
  3848. {
  3849. BOOL bReturn = FALSE;
  3850. MYDBGASSERT(pCustomAction && pszProxyFile && (TEXT('\0') != pszProxyFile[0]));
  3851. if (pCustomAction && pszProxyFile && (TEXT('\0') != pszProxyFile[0]))
  3852. {
  3853. const TCHAR* const c_pszBackupFileName = TEXT("proxy.bak");
  3854. const TCHAR* const c_pszDialRasEntry = TEXT("%DIALRASENTRY%");
  3855. const TCHAR* const c_pszProfile = TEXT("%PROFILE%");
  3856. const TCHAR* const c_pszTunnelRasEntry = TEXT("%TUNNELRASENTRY%");
  3857. const TCHAR* const c_pszSetProxyFunction = TEXT("SetProxy");
  3858. UINT uDescription;
  3859. LPTSTR aArrayOfStrings[10];
  3860. UINT uCount = 0;
  3861. if (bDisconnectAction)
  3862. {
  3863. aArrayOfStrings[uCount] = (LPTSTR)c_pszSourceFileNameSwitch;
  3864. uCount++;
  3865. aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileName;
  3866. uCount++;
  3867. aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntrySwitch;
  3868. uCount++;
  3869. aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntry;
  3870. uCount++;
  3871. aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntrySwitch;
  3872. uCount++;
  3873. aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntry;
  3874. uCount++;
  3875. aArrayOfStrings[uCount] = (LPTSTR)c_pszProfileSwitch;
  3876. uCount++;
  3877. aArrayOfStrings[uCount] = (LPTSTR)c_pszProfile;
  3878. uCount++;
  3879. uDescription = IDS_CMPROXY_DIS_DESC;
  3880. }
  3881. else
  3882. {
  3883. aArrayOfStrings[uCount] = (LPTSTR)c_pszSourceFileNameSwitch;
  3884. uCount++;
  3885. aArrayOfStrings[uCount] = (LPTSTR)pszProxyFile;
  3886. uCount++;
  3887. if (bRestorePrevProxySettings)
  3888. {
  3889. aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileNameSwitch;
  3890. uCount++;
  3891. aArrayOfStrings[uCount] = (LPTSTR)c_pszBackupFileName;
  3892. uCount++;
  3893. }
  3894. aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntrySwitch;
  3895. uCount++;
  3896. aArrayOfStrings[uCount] = (LPTSTR)c_pszDialRasEntry;
  3897. uCount++;
  3898. aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntrySwitch;
  3899. uCount++;
  3900. aArrayOfStrings[uCount] = (LPTSTR)c_pszTunnelRasEntry;
  3901. uCount++;
  3902. aArrayOfStrings[uCount] = (LPTSTR)c_pszProfileSwitch;
  3903. uCount++;
  3904. aArrayOfStrings[uCount] = (LPTSTR)c_pszProfile;
  3905. uCount++;
  3906. uDescription = IDS_CMPROXY_CON_DESC;
  3907. }
  3908. MYVERIFY(0 != LoadString(g_hInstance, uDescription, pCustomAction->szDescription, CELEMS(pCustomAction->szDescription)));
  3909. pCustomAction->Type = bDisconnectAction ? ONDISCONNECT : ONCONNECT;
  3910. wsprintf(pCustomAction->szProgram, TEXT("%s\\cmproxy.dll"), g_szSupportDir);
  3911. lstrcpy(pCustomAction->szFunctionName, c_pszSetProxyFunction);
  3912. pCustomAction->bIncludeBinary = TRUE;
  3913. pCustomAction->bBuiltInAction = TRUE;
  3914. pCustomAction->bTempDescription = FALSE;
  3915. pCustomAction->dwFlags = ALL_CONNECTIONS;
  3916. HRESULT hr = BuildCustomActionParamString(&(aArrayOfStrings[0]), uCount, &(pCustomAction->pszParameters));
  3917. bReturn = (SUCCEEDED(hr) && pCustomAction->pszParameters);
  3918. }
  3919. return bReturn;
  3920. }
  3921. //+----------------------------------------------------------------------------
  3922. //
  3923. // Function: ProcessCmProxy
  3924. //
  3925. // Synopsis: Automatic IE proxy configuration
  3926. //
  3927. // History: quintinb Created 03/23/00
  3928. //
  3929. //+----------------------------------------------------------------------------
  3930. INT_PTR APIENTRY ProcessCmProxy(
  3931. HWND hDlg,
  3932. UINT message,
  3933. WPARAM wParam,
  3934. LPARAM lParam)
  3935. {
  3936. NMHDR* pnmHeader = (NMHDR*)lParam;
  3937. BOOL bEnableCmProxy;
  3938. BOOL bRestorePrevProxySettings;
  3939. TCHAR szTemp[MAX_PATH+1];
  3940. HRESULT hr;
  3941. CustomActionListItem* pCmProxyCustomAction = NULL;
  3942. CustomActionListItem UpdatedCmProxyAction;
  3943. ProcessBold(hDlg, message);
  3944. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_APCONFIG)) return TRUE;
  3945. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  3946. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  3947. switch (message)
  3948. {
  3949. case WM_INITDIALOG:
  3950. break;
  3951. case WM_COMMAND:
  3952. switch (LOWORD(wParam))
  3953. {
  3954. case IDC_RADIO1:
  3955. case IDC_RADIO2:
  3956. EnableDisableCmProxyControls(hDlg);
  3957. break;
  3958. case IDC_BUTTON1: // browse
  3959. {
  3960. //
  3961. // If the user clicked the browse button without clicking the Proxy radio button,
  3962. // then we need to set the radio and make sure the other Proxy controls are
  3963. // enabled.
  3964. //
  3965. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  3966. EnableDisableCmProxyControls(hDlg);
  3967. UINT uFilter = IDS_TXTFILTER;
  3968. TCHAR* pszMask = TEXT("*.txt");
  3969. int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_EDIT1, TEXT("txt"), g_szLastBrowsePath);
  3970. MYDBGASSERT(0 != iTemp);
  3971. if (0 < iTemp) // -1 means the user cancelled
  3972. {
  3973. //
  3974. // We want to copy the full path to the filename into g_szCmProxyFile so
  3975. // that we have it for later in case the user wants to include it in the profile.
  3976. //
  3977. lstrcpy (g_szCmProxyFile, g_szLastBrowsePath);
  3978. //
  3979. // We also want to save the last browse path so that when the user next
  3980. // opens the browse dialog they will be in the same place they last
  3981. // browsed from.
  3982. //
  3983. LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
  3984. if (pszLastSlash)
  3985. {
  3986. pszLastSlash = CharNext(pszLastSlash);
  3987. *pszLastSlash = TEXT('\0');
  3988. }
  3989. else
  3990. {
  3991. g_szLastBrowsePath[0] = TEXT('\0');
  3992. }
  3993. }
  3994. }
  3995. break;
  3996. default:
  3997. break;
  3998. }
  3999. break;
  4000. case WM_NOTIFY:
  4001. if (NULL == pnmHeader)
  4002. {
  4003. return FALSE;
  4004. }
  4005. switch (pnmHeader->code)
  4006. {
  4007. case PSN_KILLACTIVE:
  4008. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  4009. return 1;
  4010. break; //lint !e527 this line isn't reachable but
  4011. // keep it in case the return is removed
  4012. case PSN_SETACTIVE:
  4013. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  4014. //
  4015. // Ensure we have a custom action list
  4016. //
  4017. if (NULL == g_pCustomActionList)
  4018. {
  4019. g_pCustomActionList = new CustomActionList;
  4020. MYDBGASSERT(g_pCustomActionList);
  4021. if (NULL == g_pCustomActionList)
  4022. {
  4023. return FALSE;
  4024. }
  4025. //
  4026. // Read in the custom actions from the Cms File
  4027. //
  4028. hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
  4029. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCmProxy -- Loading custom actions failed."));
  4030. }
  4031. //
  4032. // Init the static variables to no proxy settings
  4033. //
  4034. bEnableCmProxy = FALSE;
  4035. bRestorePrevProxySettings = FALSE;
  4036. g_szCmProxyFile[0] = TEXT('\0');
  4037. //
  4038. // Now lets search the custom action list for cmproxy
  4039. //
  4040. MYVERIFY(0 != LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
  4041. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmProxyCustomAction);
  4042. if (SUCCEEDED(hr) && pCmProxyCustomAction)
  4043. {
  4044. //
  4045. // Get the filename that the user specified and add it to the UI
  4046. //
  4047. if (FindSwitchInString(pCmProxyCustomAction->pszParameters, c_pszSourceFileNameSwitch, TRUE, szTemp)) // bReturnNextToken == TRUE
  4048. {
  4049. //
  4050. // Figure out if we have the disconnect action too, ensuring to free the existing action first
  4051. //
  4052. CmFree(pCmProxyCustomAction->pszParameters);
  4053. CmFree(pCmProxyCustomAction);
  4054. wsprintf(g_szCmProxyFile, TEXT("%s\\%s"), g_szTempDir, szTemp);
  4055. bEnableCmProxy = TRUE;
  4056. MYVERIFY(0 != LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
  4057. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONDISCONNECT, &pCmProxyCustomAction);
  4058. if (SUCCEEDED(hr) && pCmProxyCustomAction)
  4059. {
  4060. bRestorePrevProxySettings = TRUE;
  4061. CmFree(pCmProxyCustomAction->pszParameters);
  4062. CmFree(pCmProxyCustomAction);
  4063. }
  4064. }
  4065. else
  4066. {
  4067. CmFree(pCmProxyCustomAction->pszParameters);
  4068. CmFree(pCmProxyCustomAction);
  4069. CMASSERTMSG(FALSE, TEXT("ProcessCmProxy -- parameter string format incorrect"));
  4070. }
  4071. }
  4072. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, bRestorePrevProxySettings));
  4073. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, (bEnableCmProxy ? IDC_RADIO2 : IDC_RADIO1)));
  4074. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)GetName(g_szCmProxyFile)));
  4075. //
  4076. // Now make sure the correct set of controls is enabled.
  4077. //
  4078. EnableDisableCmProxyControls(hDlg);
  4079. break;
  4080. case PSN_WIZBACK:
  4081. case PSN_WIZNEXT:
  4082. //
  4083. // Get the checkbox and radio button state
  4084. //
  4085. bEnableCmProxy = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  4086. bRestorePrevProxySettings = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_CHECK1));
  4087. if (bEnableCmProxy)
  4088. {
  4089. //
  4090. // Lets get the proxy file and verify that they gave us a file and that
  4091. // the file actually exists.
  4092. //
  4093. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  4094. {
  4095. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  4096. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4097. return 1;
  4098. }
  4099. CmStrTrim(szTemp);
  4100. if (TEXT('\0') == szTemp[0])
  4101. {
  4102. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEED_PROXY_FILE, MB_OK));
  4103. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  4104. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4105. return 1;
  4106. }
  4107. if (!VerifyFile(hDlg, IDC_EDIT1, g_szCmProxyFile, TRUE))
  4108. {
  4109. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  4110. return TRUE;
  4111. }
  4112. //
  4113. // Lets copy the proxy file to the temp dir
  4114. //
  4115. wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szCmProxyFile));
  4116. if (0 != lstrcmpi(szTemp, g_szCmProxyFile))
  4117. {
  4118. MYVERIFY(TRUE == CopyFileWrapper(g_szCmProxyFile, szTemp, FALSE));
  4119. MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
  4120. }
  4121. //
  4122. // Now we have all of the data we need, lets build the custom action struct and then
  4123. // either edit it or add it depending on whether it already exists or not.
  4124. //
  4125. MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
  4126. if (szTemp[0])
  4127. {
  4128. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmProxyCustomAction);
  4129. if (SUCCEEDED(hr))
  4130. {
  4131. FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
  4132. FALSE, GetName(g_szCmProxyFile)); // bDisconnectAction == FALSE
  4133. hr = g_pCustomActionList->Edit(g_hInstance, pCmProxyCustomAction, &UpdatedCmProxyAction, g_szShortServiceName);
  4134. MYVERIFY(SUCCEEDED(hr));
  4135. CmFree(UpdatedCmProxyAction.pszParameters);
  4136. UpdatedCmProxyAction.pszParameters = NULL;
  4137. CmFree(pCmProxyCustomAction->pszParameters);
  4138. CmFree(pCmProxyCustomAction);
  4139. }
  4140. else
  4141. {
  4142. FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
  4143. FALSE, GetName(g_szCmProxyFile)); // bDisconnectAction == FALSE
  4144. hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmProxyAction, g_szShortServiceName);
  4145. CmFree(UpdatedCmProxyAction.pszParameters);
  4146. UpdatedCmProxyAction.pszParameters = NULL;
  4147. MYVERIFY(SUCCEEDED(hr));
  4148. }
  4149. }
  4150. }
  4151. else
  4152. {
  4153. //
  4154. // Clear out the global proxy file path
  4155. //
  4156. g_szCmProxyFile[0] = TEXT('\0');
  4157. //
  4158. // The user doesn't want cmproxy. Delete it from the connect action list.
  4159. //
  4160. MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_CON_DESC, szTemp, CELEMS(szTemp)));
  4161. g_pCustomActionList->Delete(g_hInstance, szTemp, ONCONNECT);
  4162. }
  4163. //
  4164. // Now do the same for the disconnect cmproxy action if needed
  4165. //
  4166. if (bEnableCmProxy && bRestorePrevProxySettings)
  4167. {
  4168. MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
  4169. if (szTemp[0])
  4170. {
  4171. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONDISCONNECT, &pCmProxyCustomAction);
  4172. if (S_OK == hr)
  4173. {
  4174. FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
  4175. TRUE, GetName(g_szCmProxyFile)); // bDisconnectAction == TRUE
  4176. hr = g_pCustomActionList->Edit(g_hInstance, pCmProxyCustomAction, &UpdatedCmProxyAction, g_szShortServiceName);
  4177. MYVERIFY(SUCCEEDED(hr));
  4178. CmFree(UpdatedCmProxyAction.pszParameters);
  4179. UpdatedCmProxyAction.pszParameters = NULL;
  4180. CmFree(pCmProxyCustomAction->pszParameters);
  4181. CmFree(pCmProxyCustomAction);
  4182. }
  4183. else
  4184. {
  4185. FillInCustomActionStructWithCmProxy(bRestorePrevProxySettings, &UpdatedCmProxyAction,
  4186. TRUE, GetName(g_szCmProxyFile)); // bDisconnectAction == TRUE
  4187. hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmProxyAction, g_szShortServiceName);
  4188. MYVERIFY(SUCCEEDED(hr));
  4189. CmFree(UpdatedCmProxyAction.pszParameters);
  4190. UpdatedCmProxyAction.pszParameters = NULL;
  4191. }
  4192. }
  4193. }
  4194. else
  4195. {
  4196. //
  4197. // Now try to delete the disconnect action
  4198. //
  4199. MYVERIFY(LoadString(g_hInstance, IDS_CMPROXY_DIS_DESC, szTemp, CELEMS(szTemp)));
  4200. if (szTemp[0])
  4201. {
  4202. g_pCustomActionList->Delete(g_hInstance, szTemp, ONDISCONNECT);
  4203. }
  4204. }
  4205. break;
  4206. default:
  4207. return FALSE;
  4208. }
  4209. break;
  4210. default:
  4211. return FALSE;
  4212. }
  4213. return TRUE;
  4214. }
  4215. void EnableDisableCmRouteControls(HWND hDlg)
  4216. {
  4217. BOOL bCmRouteEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  4218. HWND hControl = GetDlgItem(hDlg, IDC_ROUTE_FILE);
  4219. EnableWindow(hControl, bCmRouteEnabled);
  4220. hControl = GetDlgItem(hDlg, IDC_ROUTE_FILE_LABEL);
  4221. EnableWindow(hControl, bCmRouteEnabled);
  4222. hControl = GetDlgItem(hDlg, IDC_ROUTE_URL);
  4223. EnableWindow(hControl, bCmRouteEnabled);
  4224. hControl = GetDlgItem(hDlg, IDC_ROUTE_URL_LABEL);
  4225. EnableWindow(hControl, bCmRouteEnabled);
  4226. //
  4227. // We only want to enable the require URL checkbox if there is text in the URL field.
  4228. //
  4229. LRESULT lResult = SendDlgItemMessage(hDlg, IDC_ROUTE_URL, WM_GETTEXTLENGTH, 0, 0);
  4230. hControl = GetDlgItem(hDlg, IDC_CHECK1);
  4231. EnableWindow(hControl, bCmRouteEnabled && lResult);
  4232. hControl = GetDlgItem(hDlg, IDC_CHECK2);
  4233. EnableWindow(hControl, bCmRouteEnabled);
  4234. }
  4235. BOOL FindSwitchInString(LPCTSTR pszStringToSearch, LPCTSTR pszSwitchToFind, BOOL bReturnNextToken, LPTSTR pszToken)
  4236. {
  4237. if ((NULL == pszStringToSearch) || (NULL == pszSwitchToFind) || (bReturnNextToken && (NULL == pszToken)))
  4238. {
  4239. CMASSERTMSG(FALSE, TEXT("FindSwitchInString -- invalid parameter"));
  4240. return FALSE;
  4241. }
  4242. BOOL bReturn = FALSE;
  4243. BOOL bLongFileName = FALSE;
  4244. LPTSTR pszSourceFileName = CmStrStr(pszStringToSearch, pszSwitchToFind);
  4245. if (pszSourceFileName)
  4246. {
  4247. if (bReturnNextToken)
  4248. {
  4249. pszSourceFileName = pszSourceFileName + lstrlen(pszSwitchToFind);
  4250. while (CmIsSpace(pszSourceFileName))
  4251. {
  4252. pszSourceFileName = CharNext(pszSourceFileName);
  4253. }
  4254. if (TEXT('"') == *pszSourceFileName)
  4255. {
  4256. bLongFileName = TRUE;
  4257. pszSourceFileName = CharNext(pszSourceFileName);
  4258. }
  4259. LPTSTR pszCurrent = pszSourceFileName;
  4260. while (pszCurrent && (TEXT('\0') != *pszCurrent))
  4261. {
  4262. if (bLongFileName && (TEXT('"') == *pszCurrent))
  4263. {
  4264. break;
  4265. }
  4266. else if ((FALSE == bLongFileName) && (CmIsSpace(pszCurrent)))
  4267. {
  4268. break;
  4269. }
  4270. pszCurrent = CharNext(pszCurrent);
  4271. }
  4272. if (pszCurrent)
  4273. {
  4274. lstrcpyn(pszToken, pszSourceFileName, (int)(pszCurrent - pszSourceFileName + 1));
  4275. bReturn = TRUE;
  4276. }
  4277. else
  4278. {
  4279. CMASSERTMSG(FALSE, TEXT("FindSwitchInString -- unable to find next token to return"));
  4280. }
  4281. }
  4282. else
  4283. {
  4284. bReturn = TRUE;
  4285. }
  4286. }
  4287. return bReturn;
  4288. }
  4289. HRESULT BuildCustomActionParamString(LPTSTR* aArrayOfStrings, UINT uCountOfStrings, LPTSTR* ppszParamsOutput)
  4290. {
  4291. if ((NULL == aArrayOfStrings) || (0 == uCountOfStrings) || (NULL == ppszParamsOutput))
  4292. {
  4293. CMASSERTMSG(FALSE, TEXT("BuildCustomActionParamString -- Invalid Parameter"));
  4294. return E_INVALIDARG;
  4295. }
  4296. UINT uMemoryNeeded = 0;
  4297. LPTSTR pszCurrent;
  4298. BOOL bNeedQuotes;
  4299. //
  4300. // First lets figure out how much memory we need to allocate
  4301. //
  4302. for (UINT i = 0; i < uCountOfStrings; i++)
  4303. {
  4304. if (aArrayOfStrings[i] && (TEXT('\0') != aArrayOfStrings[i]))
  4305. {
  4306. uMemoryNeeded = uMemoryNeeded + lstrlen(aArrayOfStrings[i]);
  4307. //
  4308. // Next check to see if we need double quotes around the item because it contains spaces
  4309. //
  4310. pszCurrent = (LPTSTR)aArrayOfStrings[i];
  4311. bNeedQuotes = FALSE;
  4312. while (pszCurrent && (TEXT('\0') != *pszCurrent))
  4313. {
  4314. if (CmIsSpace(pszCurrent))
  4315. {
  4316. bNeedQuotes = TRUE;
  4317. break;
  4318. }
  4319. pszCurrent = CharNext(pszCurrent);
  4320. }
  4321. //
  4322. // Add the item to the string, making sure to add a space if this isn't the last
  4323. // item in the list
  4324. //
  4325. if (bNeedQuotes)
  4326. {
  4327. uMemoryNeeded = uMemoryNeeded + 2;
  4328. }
  4329. //
  4330. // Add a space unless this is the last item in the list
  4331. //
  4332. if (i < (uCountOfStrings - 1))
  4333. {
  4334. uMemoryNeeded++;
  4335. }
  4336. }
  4337. }
  4338. //
  4339. // Make sure to add one for the null terminator and multiply by the size of a character
  4340. //
  4341. uMemoryNeeded = (uMemoryNeeded + 1)*sizeof(TCHAR);
  4342. //
  4343. // Now allocate the memory we need
  4344. //
  4345. *ppszParamsOutput = (LPTSTR)CmMalloc(uMemoryNeeded);
  4346. //
  4347. // Finally copy over the data
  4348. //
  4349. if (*ppszParamsOutput)
  4350. {
  4351. for (UINT i = 0; i < uCountOfStrings; i++)
  4352. {
  4353. if (aArrayOfStrings[i] && (TEXT('\0') != aArrayOfStrings[i]))
  4354. {
  4355. //
  4356. // Next check to see if we need double quotes around the item because it contains spaces
  4357. //
  4358. pszCurrent = (LPTSTR)aArrayOfStrings[i];
  4359. bNeedQuotes = FALSE;
  4360. while (pszCurrent && (TEXT('\0') != *pszCurrent))
  4361. {
  4362. if (CmIsSpace(pszCurrent))
  4363. {
  4364. bNeedQuotes = TRUE;
  4365. break;
  4366. }
  4367. pszCurrent = CharNext(pszCurrent);
  4368. }
  4369. //
  4370. // Add the item to the string, making sure to add a space if this isn't the last
  4371. // item in the list
  4372. //
  4373. if (bNeedQuotes)
  4374. {
  4375. lstrcat(*ppszParamsOutput, TEXT("\""));
  4376. }
  4377. lstrcat(*ppszParamsOutput, aArrayOfStrings[i]);
  4378. if (bNeedQuotes)
  4379. {
  4380. lstrcat(*ppszParamsOutput, TEXT("\""));
  4381. }
  4382. //
  4383. // Add a space unless this is the last item in the list
  4384. //
  4385. if (i < (uCountOfStrings - 1))
  4386. {
  4387. lstrcat(*ppszParamsOutput, TEXT(" "));
  4388. }
  4389. }
  4390. }
  4391. }
  4392. else
  4393. {
  4394. return E_OUTOFMEMORY;
  4395. }
  4396. return S_OK;
  4397. }
  4398. BOOL FillInCustomActionStructWithCmRoute(CustomActionListItem* pCustomAction,
  4399. BOOL bDisconnectIfUrlUnavailable, LPCTSTR pszUrlPath, LPCTSTR pszRouteFile)
  4400. {
  4401. BOOL bReturn = FALSE;
  4402. MYDBGASSERT(pCustomAction && pszUrlPath && pszRouteFile && ((TEXT('\0') != pszRouteFile[0]) || (TEXT('\0') != pszUrlPath[0])));
  4403. if (pCustomAction && pszUrlPath && pszRouteFile && ((TEXT('\0') != pszRouteFile[0]) || (TEXT('\0') != pszUrlPath[0])))
  4404. {
  4405. const TCHAR* const c_pszCmRouteFunction = TEXT("SetRoutes");
  4406. const TCHAR* const c_pszProfileMacro = TEXT("%PROFILE%");
  4407. MYVERIFY(LoadString(g_hInstance, IDS_CMROUTE_DESC, pCustomAction->szDescription, CELEMS(pCustomAction->szDescription)));
  4408. pCustomAction->Type = ONCONNECT;
  4409. wsprintf(pCustomAction->szProgram, TEXT("%s\\cmroute.dll"), g_szSupportDir);
  4410. LPTSTR aArrayOfStrings[8] = {0};
  4411. UINT uIndex = 0;
  4412. if (TEXT('\0') != pszRouteFile[0])
  4413. {
  4414. aArrayOfStrings[uIndex] = (LPTSTR)c_pszProfileSwitch;
  4415. uIndex++;
  4416. aArrayOfStrings[uIndex] = (LPTSTR)c_pszProfileMacro;
  4417. uIndex++;
  4418. aArrayOfStrings[uIndex] = (LPTSTR)c_pszStaticFileNameSwitch;
  4419. uIndex++;
  4420. aArrayOfStrings[uIndex] = (LPTSTR)pszRouteFile;
  4421. uIndex++;
  4422. }
  4423. if (TEXT('\0') != pszUrlPath[0])
  4424. {
  4425. aArrayOfStrings[uIndex] = (LPTSTR)c_pszUrlPathSwitch;
  4426. uIndex++;
  4427. aArrayOfStrings[uIndex] = (LPTSTR)pszUrlPath;
  4428. uIndex++;
  4429. }
  4430. if ((FALSE == bDisconnectIfUrlUnavailable) && (TEXT('\0') != pszUrlPath[0]))
  4431. {
  4432. aArrayOfStrings[uIndex] = (LPTSTR)c_pszDontRequireUrlSwitch;
  4433. uIndex++;
  4434. }
  4435. HRESULT hr = BuildCustomActionParamString(&(aArrayOfStrings[0]), uIndex, &(pCustomAction->pszParameters));
  4436. MYDBGASSERT(SUCCEEDED(hr));
  4437. lstrcpy(pCustomAction->szFunctionName, c_pszCmRouteFunction);
  4438. pCustomAction->bIncludeBinary = TRUE;
  4439. pCustomAction->bBuiltInAction = TRUE;
  4440. pCustomAction->bTempDescription = FALSE;
  4441. pCustomAction->dwFlags = ALL_CONNECTIONS;
  4442. bReturn = (NULL != pCustomAction->pszParameters);
  4443. }
  4444. return bReturn;
  4445. }
  4446. //+----------------------------------------------------------------------------
  4447. //
  4448. // Function: ProcessRoutePlumbing
  4449. //
  4450. // Synopsis: Add Route Plumbing information
  4451. //
  4452. // History: quintinb Created 03/23/00
  4453. //
  4454. //+----------------------------------------------------------------------------
  4455. INT_PTR APIENTRY ProcessRoutePlumbing(
  4456. HWND hDlg,
  4457. UINT message,
  4458. WPARAM wParam,
  4459. LPARAM lParam)
  4460. {
  4461. NMHDR* pnmHeader = (NMHDR*)lParam;
  4462. BOOL bEnableRoutePlumbing;
  4463. BOOL bDisconnectIfUrlUnavailable;
  4464. TCHAR szTemp[MAX_PATH+1];
  4465. TCHAR szUrlPath[MAX_PATH+1];
  4466. HRESULT hr;
  4467. CustomActionListItem UpdatedCmRouteAction;
  4468. CustomActionListItem* pCmRouteCustomAction = NULL;
  4469. ProcessBold(hDlg, message);
  4470. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_RTPLUMB)) return TRUE;
  4471. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  4472. SetDefaultGUIFont(hDlg,message,IDC_ROUTE_FILE);
  4473. SetDefaultGUIFont(hDlg,message,IDC_ROUTE_URL);
  4474. switch (message)
  4475. {
  4476. case WM_INITDIALOG:
  4477. break;
  4478. case WM_COMMAND:
  4479. switch (LOWORD(wParam))
  4480. {
  4481. case IDC_ROUTE_URL:
  4482. if (HIWORD(wParam) == EN_CHANGE)
  4483. {
  4484. EnableDisableCmRouteControls(hDlg);
  4485. return (TRUE);
  4486. }
  4487. break;
  4488. case IDC_RADIO1:
  4489. case IDC_RADIO2:
  4490. EnableDisableCmRouteControls(hDlg);
  4491. break;
  4492. case IDC_BUTTON1: // browse
  4493. {
  4494. //
  4495. // If the user clicked the browse button without clicking the CmRoute radio button,
  4496. // then we need to set the radio and make sure the other CmRoute controls are
  4497. // enabled.
  4498. //
  4499. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  4500. EnableDisableCmRouteControls(hDlg);
  4501. UINT uFilter = IDS_TXTFILTER;
  4502. TCHAR* pszMask = TEXT("*.txt");
  4503. int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_ROUTE_FILE, TEXT("txt"), g_szLastBrowsePath);
  4504. MYDBGASSERT(0 != iTemp);
  4505. if (0 < iTemp) // -1 means the user cancelled
  4506. {
  4507. //
  4508. // We want to copy the full path to the filename into g_szCmRouteFile so
  4509. // that we have it for later in case the user wants to include it in the profile.
  4510. //
  4511. lstrcpy (g_szCmRouteFile, g_szLastBrowsePath);
  4512. //
  4513. // We also want to save the last browse path so that when the user next
  4514. // opens the browse dialog they will be in the same place they last
  4515. // browsed from.
  4516. //
  4517. LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
  4518. if (pszLastSlash)
  4519. {
  4520. pszLastSlash = CharNext(pszLastSlash);
  4521. *pszLastSlash = TEXT('\0');
  4522. }
  4523. else
  4524. {
  4525. g_szLastBrowsePath[0] = TEXT('\0');
  4526. }
  4527. }
  4528. }
  4529. break;
  4530. default:
  4531. break;
  4532. }
  4533. break;
  4534. case WM_NOTIFY:
  4535. if (NULL == pnmHeader)
  4536. {
  4537. return FALSE;
  4538. }
  4539. switch (pnmHeader->code)
  4540. {
  4541. case PSN_KILLACTIVE:
  4542. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  4543. return 1;
  4544. break; //lint !e527 this line isn't reachable but
  4545. // keep it in case the return is removed
  4546. case PSN_SETACTIVE:
  4547. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  4548. //
  4549. // Ensure we have a custom action list
  4550. //
  4551. if (NULL == g_pCustomActionList)
  4552. {
  4553. g_pCustomActionList = new CustomActionList;
  4554. MYDBGASSERT(g_pCustomActionList);
  4555. if (NULL == g_pCustomActionList)
  4556. {
  4557. return FALSE;
  4558. }
  4559. //
  4560. // Read in the custom actions from the Cms File
  4561. //
  4562. hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
  4563. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessRoutePlumbing -- Loading custom actions failed."));
  4564. }
  4565. //
  4566. // Init the static variables to no route plumbing
  4567. //
  4568. bEnableRoutePlumbing = FALSE;
  4569. bDisconnectIfUrlUnavailable = TRUE; // default behavior is to disconnect if URL is unreachable
  4570. g_szCmRouteFile[0] = TEXT('\0');
  4571. szUrlPath[0] = TEXT('\0');
  4572. //
  4573. // Now lets search the custom action list for cmproxy
  4574. //
  4575. MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
  4576. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmRouteCustomAction);
  4577. if (SUCCEEDED(hr))
  4578. {
  4579. //
  4580. // Enable Route plumbing
  4581. //
  4582. bEnableRoutePlumbing = TRUE;
  4583. //
  4584. // Get the name of the static text file specified for cmroute.dll
  4585. //
  4586. if (FindSwitchInString(pCmRouteCustomAction->pszParameters, c_pszStaticFileNameSwitch, TRUE, szTemp)) //bReturnNextToken == TRUE
  4587. {
  4588. wsprintf(g_szCmRouteFile, TEXT("%s\\%s"), g_szTempDir, szTemp);
  4589. }
  4590. //
  4591. // Get the name of the URL to a route file
  4592. //
  4593. if (FindSwitchInString(pCmRouteCustomAction->pszParameters, c_pszUrlPathSwitch, TRUE, szUrlPath)) //bReturnNextToken == TRUE
  4594. {
  4595. bDisconnectIfUrlUnavailable = (FALSE == FindSwitchInString(pCmRouteCustomAction->pszParameters,
  4596. c_pszDontRequireUrlSwitch, FALSE, NULL)); //bReturnNextToken == FALSE
  4597. }
  4598. CmFree(pCmRouteCustomAction->pszParameters);
  4599. CmFree(pCmRouteCustomAction);
  4600. }
  4601. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, (bEnableRoutePlumbing ? IDC_RADIO2 : IDC_RADIO1)));
  4602. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_ROUTE_FILE), WM_SETTEXT, 0, (LPARAM)GetName(g_szCmRouteFile)));
  4603. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_ROUTE_URL), WM_SETTEXT, 0, (LPARAM)szUrlPath));
  4604. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, bDisconnectIfUrlUnavailable));
  4605. //
  4606. // Now make sure the correct set of controls is enabled.
  4607. //
  4608. EnableDisableCmRouteControls(hDlg);
  4609. break;
  4610. case PSN_WIZBACK:
  4611. case PSN_WIZNEXT:
  4612. //
  4613. // Lets figure out if Route plumbing should be enabled or not.
  4614. //
  4615. bEnableRoutePlumbing = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  4616. if (bEnableRoutePlumbing)
  4617. {
  4618. //
  4619. // First try to get the static route file. If we don't have one that is okay
  4620. // as long as they gave us a route URL.
  4621. //
  4622. if (-1 == GetTextFromControl(hDlg, IDC_ROUTE_FILE, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  4623. {
  4624. SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
  4625. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4626. return 1;
  4627. }
  4628. CmStrTrim(szTemp);
  4629. if (-1 == GetTextFromControl(hDlg, IDC_ROUTE_URL, szUrlPath, MAX_PATH, TRUE)) // bDisplayError == TRUE
  4630. {
  4631. SetFocus(GetDlgItem(hDlg, IDC_ROUTE_URL));
  4632. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4633. return 1;
  4634. }
  4635. CmStrTrim(szUrlPath);
  4636. if ((TEXT('\0') == szTemp[0]) && (TEXT('\0') == szUrlPath[0]))
  4637. {
  4638. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEED_ROUTE_FILE, MB_OK));
  4639. SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
  4640. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4641. return 1;
  4642. }
  4643. //
  4644. // If they gave us a static route file then we need to verify it
  4645. //
  4646. if (TEXT('\0') != szTemp[0])
  4647. {
  4648. if (!VerifyFile(hDlg, IDC_ROUTE_FILE, g_szCmRouteFile, TRUE))
  4649. {
  4650. SetFocus(GetDlgItem(hDlg, IDC_ROUTE_FILE));
  4651. return TRUE;
  4652. }
  4653. else
  4654. {
  4655. //
  4656. // Lets copy the route file to the temp dir
  4657. //
  4658. wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szCmRouteFile));
  4659. if (0 != lstrcmpi(szTemp, g_szCmRouteFile))
  4660. {
  4661. MYVERIFY(TRUE == CopyFileWrapper(g_szCmRouteFile, szTemp, FALSE));
  4662. MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
  4663. }
  4664. }
  4665. }
  4666. else
  4667. {
  4668. g_szCmRouteFile[0] = TEXT('\0');
  4669. }
  4670. //
  4671. // If they gave us a route URL then we need to make sure it starts with
  4672. // http:// or https:// or file://, basically that it contains ://. Note we
  4673. // really don't do any validation here under the assumption that they will discover
  4674. // it doesn't work when they test it if the URL is invalid.
  4675. //
  4676. if ((szUrlPath[0]) && (NULL == CmStrStr(szUrlPath, TEXT("://"))))
  4677. {
  4678. lstrcpy (szTemp, szUrlPath);
  4679. wsprintf (szUrlPath, TEXT("http://%s"), szTemp);
  4680. }
  4681. bDisconnectIfUrlUnavailable = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_CHECK1)); // note we don't write this if we don't have a URL path
  4682. //
  4683. // Now we have all of the data we need, lets build the custom action struct and then
  4684. // either edit it or add it depending on whether it already exists or not.
  4685. //
  4686. MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
  4687. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, szTemp, ONCONNECT, &pCmRouteCustomAction);
  4688. if (SUCCEEDED(hr))
  4689. {
  4690. FillInCustomActionStructWithCmRoute(&UpdatedCmRouteAction,
  4691. bDisconnectIfUrlUnavailable, szUrlPath, GetName(g_szCmRouteFile));
  4692. hr = g_pCustomActionList->Edit(g_hInstance, pCmRouteCustomAction, &UpdatedCmRouteAction, g_szShortServiceName);
  4693. MYVERIFY(SUCCEEDED(hr));
  4694. CmFree(UpdatedCmRouteAction.pszParameters);
  4695. UpdatedCmRouteAction.pszParameters = NULL;
  4696. CmFree(pCmRouteCustomAction->pszParameters);
  4697. CmFree(pCmRouteCustomAction);
  4698. }
  4699. else
  4700. {
  4701. FillInCustomActionStructWithCmRoute(&UpdatedCmRouteAction,
  4702. bDisconnectIfUrlUnavailable, szUrlPath, GetName(g_szCmRouteFile));
  4703. hr = g_pCustomActionList->Add(g_hInstance, &UpdatedCmRouteAction, g_szShortServiceName);
  4704. MYVERIFY(SUCCEEDED(hr));
  4705. CmFree(UpdatedCmRouteAction.pszParameters);
  4706. UpdatedCmRouteAction.pszParameters = NULL;
  4707. }
  4708. }
  4709. else
  4710. {
  4711. //
  4712. // Clear out the global route file path
  4713. //
  4714. g_szCmRouteFile[0] = TEXT('\0');
  4715. //
  4716. // The user doesn't want cmroute. Delete it from the connect action list.
  4717. //
  4718. MYVERIFY(0 != LoadString(g_hInstance, IDS_CMROUTE_DESC, szTemp, CELEMS(szTemp)));
  4719. if (szTemp[0])
  4720. {
  4721. hr = g_pCustomActionList->Delete(g_hInstance, szTemp, ONCONNECT);
  4722. }
  4723. }
  4724. break;
  4725. default:
  4726. return FALSE;
  4727. }
  4728. break;
  4729. default:
  4730. return FALSE;
  4731. }
  4732. return TRUE;
  4733. }
  4734. void EnableDisableRealmControls(HWND hDlg)
  4735. {
  4736. BOOL bRealmControlsEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  4737. HWND hControl;
  4738. hControl = GetDlgItem(hDlg, IDC_EDIT1);
  4739. if (hControl)
  4740. {
  4741. EnableWindow(hControl, bRealmControlsEnabled);
  4742. }
  4743. hControl = GetDlgItem(hDlg, IDC_REALMNAME);
  4744. if (hControl)
  4745. {
  4746. EnableWindow(hControl, bRealmControlsEnabled);
  4747. }
  4748. hControl = GetDlgItem(hDlg, IDC_RADIO3);
  4749. if (hControl)
  4750. {
  4751. EnableWindow(hControl, bRealmControlsEnabled);
  4752. }
  4753. hControl = GetDlgItem(hDlg, IDC_RADIO4);
  4754. if (hControl)
  4755. {
  4756. EnableWindow(hControl, bRealmControlsEnabled);
  4757. }
  4758. hControl = GetDlgItem(hDlg, IDC_REALM_SEP);
  4759. if (hControl)
  4760. {
  4761. EnableWindow(hControl, bRealmControlsEnabled);
  4762. }
  4763. }
  4764. //+----------------------------------------------------------------------------
  4765. //
  4766. // Function: ProcessRealmInfo
  4767. //
  4768. // Synopsis: Add a Realm Name
  4769. //
  4770. // History: quintinb Created Header and renamed from ProcessPage2B 8/6/98
  4771. //
  4772. //+----------------------------------------------------------------------------
  4773. INT_PTR APIENTRY ProcessRealmInfo(
  4774. HWND hDlg,
  4775. UINT message,
  4776. WPARAM wParam,
  4777. LPARAM lParam)
  4778. {
  4779. TCHAR szTemp[MAX_PATH+1];
  4780. NMHDR* pnmHeader = (NMHDR*)lParam;
  4781. ProcessBold(hDlg,message);
  4782. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_REALM)) return TRUE;
  4783. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  4784. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  4785. switch (message)
  4786. {
  4787. case WM_INITDIALOG:
  4788. break;
  4789. case WM_COMMAND:
  4790. switch (LOWORD(wParam))
  4791. {
  4792. case IDC_RADIO1: // Do not Add a Realm Name
  4793. case IDC_RADIO2: // Add a Realm Name
  4794. EnableDisableRealmControls(hDlg);
  4795. break;
  4796. default:
  4797. break;
  4798. }
  4799. break;
  4800. case WM_NOTIFY:
  4801. if (NULL == pnmHeader)
  4802. {
  4803. return FALSE;
  4804. }
  4805. switch (pnmHeader->code)
  4806. {
  4807. case PSN_KILLACTIVE:
  4808. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  4809. return 1;
  4810. break; //lint !e527 this line isn't reachable but
  4811. // keep it in case the return is removed
  4812. case PSN_SETACTIVE:
  4813. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  4814. //
  4815. // The next two calls to GetPrivateProfileString could return empty strings, thus don't use MYVERIFY macro
  4816. //
  4817. ZeroMemory(g_szPrefix, sizeof(g_szPrefix));
  4818. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, TEXT(""),
  4819. g_szPrefix, CELEMS(g_szPrefix), g_szCmsFile); //lint !e534
  4820. ZeroMemory(g_szSuffix, sizeof(g_szSuffix));
  4821. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, TEXT(""),
  4822. g_szSuffix, CELEMS(g_szSuffix), g_szCmsFile); //lint !e534
  4823. if (*g_szSuffix)
  4824. {
  4825. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  4826. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO4));
  4827. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM) g_szSuffix));
  4828. }
  4829. else if (*g_szPrefix)
  4830. {
  4831. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  4832. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO3));
  4833. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM) g_szPrefix));
  4834. }
  4835. else
  4836. {
  4837. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
  4838. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)MAX_PATH, (LPARAM)TEXT("")));
  4839. //
  4840. // Suffix is the default, set this just in case the user adds a suffix or prefix
  4841. //
  4842. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO3, IDC_RADIO4, IDC_RADIO4));
  4843. }
  4844. EnableDisableRealmControls(hDlg);
  4845. break;
  4846. case PSN_WIZBACK:
  4847. case PSN_WIZNEXT:
  4848. //
  4849. // First check if IDC_RADIO1 is checked, if so that means that the user
  4850. // doesn't want Realm info
  4851. //
  4852. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
  4853. {
  4854. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryUserPrefix,TEXT(""),g_szCmsFile));
  4855. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryUserSuffix,TEXT(""),g_szCmsFile));
  4856. g_szSuffix[0] = TEXT('\0');
  4857. g_szPrefix[0] = TEXT('\0');
  4858. }
  4859. else if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2))
  4860. {
  4861. //
  4862. // If Radio2 is checked then they do want Realm info and we need to
  4863. // see if the string exists and if it is convertable to ANSI form.
  4864. //
  4865. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  4866. {
  4867. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  4868. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4869. return 1;
  4870. }
  4871. CmStrTrim(szTemp);
  4872. if (TEXT('\0') == szTemp[0])
  4873. {
  4874. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOREALM, MB_OK));
  4875. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  4876. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4877. return 1;
  4878. }
  4879. //
  4880. // Now check to see if this is a Prefix or a Suffix
  4881. //
  4882. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO3)) // Prefix
  4883. {
  4884. _tcscpy(g_szPrefix, szTemp);
  4885. g_szSuffix[0] = TEXT('\0');
  4886. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, g_szPrefix, g_szCmsFile));
  4887. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, TEXT(""), g_szCmsFile));
  4888. }
  4889. else if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO4)) // Suffix
  4890. {
  4891. _tcscpy(g_szSuffix, szTemp);
  4892. g_szPrefix[0] = TEXT('\0');
  4893. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix, g_szSuffix, g_szCmsFile));
  4894. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix, TEXT(""), g_szCmsFile));
  4895. }
  4896. else
  4897. {
  4898. CMASSERTMSG(FALSE, TEXT("ProcessRealmInfo -- Unknown State, bailing"));
  4899. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4900. return 1;
  4901. }
  4902. }
  4903. else
  4904. {
  4905. CMASSERTMSG(FALSE, TEXT("ProcessRealmInfo -- Unknown State, bailing"));
  4906. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  4907. return 1;
  4908. }
  4909. break;
  4910. default:
  4911. return FALSE;
  4912. }
  4913. break;
  4914. default:
  4915. return FALSE;
  4916. }
  4917. return TRUE;
  4918. }
  4919. void RefreshList(HWND hwndDlg, UINT uCrtlId, ListBxList * HeadPtr)
  4920. {
  4921. ListBxList * LoopPtr;
  4922. SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_RESETCONTENT, 0, (LPARAM)0); //lint !e534 LB_RESETCONTENT doesn't return anything
  4923. if (HeadPtr == NULL)
  4924. {
  4925. return;
  4926. }
  4927. LoopPtr = HeadPtr;
  4928. while( LoopPtr != NULL)
  4929. {
  4930. MYVERIFY(LB_ERR != SendDlgItemMessage(hwndDlg, uCrtlId, LB_ADDSTRING, 0,
  4931. (LPARAM)LoopPtr->szName));
  4932. LoopPtr = LoopPtr->next;
  4933. }
  4934. }
  4935. void RefreshComboList(HWND hwndDlg, ListBxList * HeadPtr)
  4936. {
  4937. ListBxList * LoopPtr;
  4938. SendDlgItemMessage(hwndDlg,IDC_COMBO1,CB_RESETCONTENT,0,(LPARAM)0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
  4939. if (HeadPtr == NULL)
  4940. {
  4941. return;
  4942. }
  4943. LoopPtr = HeadPtr;
  4944. while( LoopPtr != NULL)
  4945. {
  4946. MYVERIFY(CB_ERR != SendDlgItemMessage(hwndDlg, IDC_COMBO1, CB_ADDSTRING, 0,
  4947. (LPARAM)LoopPtr->szName));
  4948. LoopPtr = LoopPtr->next;
  4949. }
  4950. }
  4951. void FreeList(ListBxList ** pHeadPtr, ListBxList ** pTailPtr)
  4952. {
  4953. ListBxList * pTmpPtr;
  4954. ListBxList * pLoopPtr = *pHeadPtr;
  4955. while(NULL != pLoopPtr)
  4956. {
  4957. CmFree(pLoopPtr->ListBxData);
  4958. pTmpPtr = pLoopPtr;
  4959. pLoopPtr = pLoopPtr->next;
  4960. CmFree(pTmpPtr);
  4961. }
  4962. *pHeadPtr = NULL;
  4963. *pTailPtr = NULL;
  4964. }
  4965. //+----------------------------------------------------------------------------
  4966. //
  4967. // Function: MoveCmsFile
  4968. //
  4969. // Synopsis: This function checks a referenced CMS file to see if it contains
  4970. // script files. If the CMS file contains script files, then it
  4971. // copies them to the temporary directory and adds a referenced
  4972. // file entry to the g_pHeadRefs linked list.
  4973. //
  4974. // Arguments: LPTSTR szFile - name of the cms file to move
  4975. //
  4976. // Returns: BOOL - returns TRUE on Success
  4977. //
  4978. // History: quintinb Created Header 01/09/98
  4979. // quintinb rewrote for the Unicode Converversion 06/14/99
  4980. // quintinb updated for rewrite of DUN settings 03/21/00
  4981. //
  4982. //+----------------------------------------------------------------------------
  4983. BOOL MoveCmsFile(LPCTSTR pszCmsFile, LPCTSTR pszShortServiceName)
  4984. {
  4985. BOOL bReturn = TRUE;
  4986. ListBxList* pTmpHeadDns = NULL;
  4987. ListBxList* pTmpTailDns = NULL;
  4988. ListBxList* pTmpCurrentDns = NULL;
  4989. CDunSetting* pTmpDunSetting = NULL;
  4990. TCHAR szFileName[MAX_PATH+1];
  4991. TCHAR szTemp[MAX_PATH+1];
  4992. TCHAR szDest[MAX_PATH+1];
  4993. if ((NULL == pszCmsFile) || (NULL == pszShortServiceName) ||
  4994. (TEXT('\0') == pszCmsFile[0]) || (TEXT('\0') == pszShortServiceName[0]))
  4995. {
  4996. return FALSE;
  4997. }
  4998. //
  4999. // Get the Long Service Name from the profile just in case we need a default entry.
  5000. //
  5001. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
  5002. TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile); //lint !e534
  5003. if (ReadNetworkSettings(pszCmsFile, szTemp, TEXT(""), &pTmpHeadDns, &pTmpTailDns, g_szOsdir, FALSE)) // FALSE == bLookingForVpnEntries
  5004. {
  5005. if (NULL != pTmpHeadDns) // just return TRUE if no entries
  5006. {
  5007. pTmpCurrentDns = pTmpHeadDns;
  5008. while (pTmpCurrentDns && pTmpCurrentDns->ListBxData)
  5009. {
  5010. pTmpDunSetting = (CDunSetting*)pTmpCurrentDns->ListBxData;
  5011. if (TEXT('\0') != pTmpDunSetting->szScript[0])
  5012. {
  5013. //
  5014. // Then we have a script, lets copy it and then add it to the g_pHeadRefs List
  5015. //
  5016. GetFileName(pTmpDunSetting->szScript, szFileName);
  5017. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"),
  5018. g_szOutdir, szFileName));
  5019. //
  5020. // Copy the Script File
  5021. //
  5022. if (CopyFileWrapper(pTmpDunSetting->szScript, szDest, FALSE))
  5023. {
  5024. MYVERIFY(0 != SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL));
  5025. //
  5026. // Add the file to the Referenced files list
  5027. //
  5028. bReturn = bReturn && createListBxRecord(&g_pHeadRefs, &g_pTailRefs,
  5029. (void *)NULL, 0, szFileName);
  5030. //
  5031. // Update the script section in the existing cms to point
  5032. // to the new directory.
  5033. // Originally: [Scripting&Merge Profile Name]
  5034. // Name=merge\script.scp
  5035. // Becomes: [Scripting&Merge Profile Name]
  5036. // Name=toplvl\script.scp
  5037. //
  5038. // Note the change in directory name so that the script file
  5039. // can be found.
  5040. //
  5041. TCHAR szSection[MAX_PATH+1];
  5042. MYVERIFY(CELEMS(szSection) > (UINT)wsprintf(szSection, TEXT("%s&%s"),
  5043. c_pszCmSectionDunScripting,
  5044. pTmpCurrentDns->szName));
  5045. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
  5046. pszShortServiceName, szFileName));
  5047. MYVERIFY(0 != WritePrivateProfileString(szSection,
  5048. c_pszCmEntryDunScriptingName,
  5049. szTemp, pszCmsFile));
  5050. }
  5051. }
  5052. pTmpCurrentDns = pTmpCurrentDns->next;
  5053. }
  5054. }
  5055. }
  5056. else
  5057. {
  5058. CMTRACE1(TEXT("MoveCmsFile -- ReadDnsList Failed. GetLastError Returns %d"), GetLastError());
  5059. bReturn = FALSE;
  5060. goto exit;
  5061. }
  5062. exit:
  5063. //
  5064. // Free the DNS List
  5065. //
  5066. FreeDnsList(&pTmpHeadDns, &pTmpTailDns);
  5067. return (bReturn);
  5068. }
  5069. //+----------------------------------------------------------------------------
  5070. //
  5071. // Function: ProcessDunEntries
  5072. //
  5073. // Synopsis: Set up Dial-up networking
  5074. //
  5075. // History: quintinb Created Header and renamed from ProcessPage2C 8/6/98
  5076. //
  5077. //+----------------------------------------------------------------------------
  5078. INT_PTR APIENTRY ProcessDunEntries(
  5079. HWND hDlg,
  5080. UINT message,
  5081. WPARAM wParam,
  5082. LPARAM lParam)
  5083. {
  5084. //
  5085. // We have a static Memory buffer and a static pointer
  5086. // so that we can know when the user has changed the phonebook
  5087. // on us (meaning we need to reread the Networking settings).
  5088. // Note that we use the static pointer to tell us if we have read
  5089. // the settings at least once.
  5090. //
  5091. static TCHAR szCachedPhoneBook[MAX_PATH+1] = {0};
  5092. static TCHAR* pszCachedPhoneBook = NULL;
  5093. NMHDR* pnmHeader = (NMHDR*)lParam;
  5094. ProcessBold(hDlg,message);
  5095. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_DENTRY)) return TRUE;
  5096. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  5097. SetDefaultGUIFont(hDlg,message,IDC_LIST1);
  5098. switch (message)
  5099. {
  5100. case WM_INITDIALOG:
  5101. break;
  5102. case WM_COMMAND:
  5103. switch (LOWORD(wParam))
  5104. {
  5105. case IDC_BUTTON1: //add
  5106. OnProcessDunEntriesAdd(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, FALSE, g_szLongServiceName, g_szCmsFile); // FALSE == bCreateTunnelEntry
  5107. return TRUE;
  5108. break; //lint !e527 this line isn't reachable but
  5109. // keep it in case the return is removed
  5110. case IDC_BUTTON2: //edit
  5111. OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
  5112. return TRUE;
  5113. break; //lint !e527 this line isn't reachable but
  5114. // keep it in case the return is removed
  5115. case IDC_BUTTON3: //delete
  5116. OnProcessDunEntriesDelete(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
  5117. return TRUE;
  5118. break; //lint !e527 this line isn't reachable but
  5119. // keep it in case the return is removed
  5120. case IDC_LIST1:
  5121. if (LBN_SELCHANGE == HIWORD(wParam))
  5122. {
  5123. //
  5124. // The selection in the listbox changed, lets figure out if we need to
  5125. // enable/disable the delete button
  5126. //
  5127. EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
  5128. }
  5129. else if (LBN_DBLCLK == HIWORD(wParam))
  5130. {
  5131. OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadDunEntry, &g_pTailDunEntry, g_szLongServiceName, g_szCmsFile);
  5132. }
  5133. break;
  5134. default:
  5135. break;
  5136. }
  5137. break;
  5138. case WM_NOTIFY:
  5139. if (NULL == pnmHeader)
  5140. {
  5141. return FALSE;
  5142. }
  5143. switch (pnmHeader->code)
  5144. {
  5145. case PSN_KILLACTIVE:
  5146. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  5147. return 1;
  5148. break; //lint !e527 this line isn't reachable but
  5149. // keep it in case the return is removed
  5150. case PSN_SETACTIVE:
  5151. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  5152. //
  5153. // To avoid reading the network settings more than we have to, we only want to
  5154. // read the networking settings the first time the users hits this page or any
  5155. // time the user changes the phonebook (if they clone the profile or edit a different
  5156. // one, clearing this will be taken care of elsewhere).
  5157. //
  5158. if ((NULL == g_pHeadDunEntry) || (NULL == pszCachedPhoneBook) || lstrcmpi(g_szPhonebk, pszCachedPhoneBook))
  5159. {
  5160. FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
  5161. MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szPhonebk, &g_pHeadDunEntry, &g_pTailDunEntry, g_szOsdir, FALSE)); //FALSE == bLookingForVpnEntries
  5162. pszCachedPhoneBook = szCachedPhoneBook;
  5163. lstrcpy(pszCachedPhoneBook, g_szPhonebk);
  5164. }
  5165. RefreshDnsList(g_hInstance, hDlg, IDC_LIST1, g_pHeadDunEntry, g_szLongServiceName, g_szCmsFile, NULL);
  5166. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  5167. EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
  5168. break;
  5169. case PSN_WIZBACK:
  5170. case PSN_WIZNEXT:
  5171. //
  5172. // Before writing out the entries we must make sure that we don't have a name collision with entries
  5173. // from the VPN list. Thus we will check each name in the DUN entries list for a matching name in the
  5174. // VPN entries list. If we detect a collision, then we will throw an error message to the user and
  5175. // let them deal with the problem.
  5176. //
  5177. if (!CheckForDUNversusVPNNameConflicts(hDlg, g_pHeadDunEntry, g_pHeadVpnEntry))
  5178. {
  5179. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5180. return 1;
  5181. }
  5182. //
  5183. // Now it is okay to write out the networking entries
  5184. //
  5185. WriteNetworkingEntries(g_szCmsFile, g_szLongServiceName, g_szShortServiceName, g_pHeadDunEntry);
  5186. //
  5187. // If we aren't updating the phonebook then we need to go right back to the phonebook page
  5188. // and skip the pbk update page
  5189. //
  5190. if (pnmHeader && (PSN_WIZBACK == pnmHeader->code) && !g_bUpdatePhonebook)
  5191. {
  5192. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
  5193. }
  5194. break;
  5195. default:
  5196. return FALSE;
  5197. }
  5198. break;
  5199. default:
  5200. return FALSE;
  5201. }
  5202. return TRUE;
  5203. }
  5204. //+----------------------------------------------------------------------------
  5205. //
  5206. // Function: DoesSomeVPNsettingUsePresharedKey
  5207. //
  5208. // Synopsis: Checks VPN DUN settings to see if any chose to use a preshared key
  5209. //
  5210. // Returns: BOOL (TRUE if some VPN setting does use a pre-shared key)
  5211. //
  5212. // History: 25-Apr-2001 SumitC Created
  5213. //
  5214. //+----------------------------------------------------------------------------
  5215. BOOL DoesSomeVPNsettingUsePresharedKey()
  5216. {
  5217. BOOL bReturn = FALSE;
  5218. ListBxList * ptr = g_pHeadVpnEntry;
  5219. if (g_bUseTunneling)
  5220. {
  5221. while (ptr != NULL)
  5222. {
  5223. CDunSetting * pDunSetting = (CDunSetting*)(ptr->ListBxData);
  5224. if (pDunSetting && pDunSetting->bUsePresharedKey)
  5225. {
  5226. bReturn = TRUE;
  5227. break;
  5228. }
  5229. ptr = ptr->next;
  5230. }
  5231. }
  5232. return bReturn;
  5233. }
  5234. INT_PTR APIENTRY ProcessVpnEntries(
  5235. HWND hDlg,
  5236. UINT message,
  5237. WPARAM wParam,
  5238. LPARAM lParam)
  5239. {
  5240. //
  5241. // We have a static Memory buffer and a static pointer
  5242. // so that we can know when the user has changed the phonebook
  5243. // on us (meaning we need to reread the Networking settings).
  5244. // Note that we use the static pointer to tell us if we have read
  5245. // the settings at least once.
  5246. //
  5247. BOOL bFreeDunList = FALSE;
  5248. static TCHAR szCachedPhoneBook[MAX_PATH+1] = {0};
  5249. static TCHAR* pszCachedPhoneBook = NULL;
  5250. NMHDR* pnmHeader = (NMHDR*)lParam;
  5251. ProcessBold(hDlg,message);
  5252. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_VENTRY)) return TRUE;
  5253. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  5254. SetDefaultGUIFont(hDlg,message,IDC_LIST1);
  5255. switch (message)
  5256. {
  5257. case WM_INITDIALOG:
  5258. break;
  5259. case WM_COMMAND:
  5260. switch (LOWORD(wParam))
  5261. {
  5262. case IDC_BUTTON1: //add
  5263. OnProcessDunEntriesAdd(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, TRUE, g_szLongServiceName, g_szCmsFile); // TRUE == bCreateTunnelEntry
  5264. return TRUE;
  5265. break; //lint !e527 this line isn't reachable but
  5266. // keep it in case the return is removed
  5267. case IDC_BUTTON2: //edit
  5268. OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
  5269. return TRUE;
  5270. break; //lint !e527 this line isn't reachable but
  5271. // keep it in case the return is removed
  5272. case IDC_BUTTON3: //delete
  5273. OnProcessDunEntriesDelete(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
  5274. return TRUE;
  5275. break; //lint !e527 this line isn't reachable but
  5276. // keep it in case the return is removed
  5277. case IDC_LIST1:
  5278. if (LBN_SELCHANGE == HIWORD(wParam))
  5279. {
  5280. //
  5281. // The selection in the listbox changed, lets figure out if we need to
  5282. // enable/disable the delete button
  5283. //
  5284. EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
  5285. }
  5286. else if (LBN_DBLCLK == HIWORD(wParam))
  5287. {
  5288. OnProcessDunEntriesEdit(g_hInstance, hDlg, IDC_LIST1, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szLongServiceName, g_szCmsFile);
  5289. }
  5290. break;
  5291. default:
  5292. break;
  5293. }
  5294. break;
  5295. case WM_NOTIFY:
  5296. if (NULL == pnmHeader)
  5297. {
  5298. return FALSE;
  5299. }
  5300. switch (pnmHeader->code)
  5301. {
  5302. case PSN_KILLACTIVE:
  5303. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  5304. return 1;
  5305. break; //lint !e527 this line isn't reachable but
  5306. // keep it in case the return is removed
  5307. case PSN_SETACTIVE:
  5308. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  5309. //
  5310. // To avoid reading the network settings more than we have to, we only want to
  5311. // read the networking settings the first time the users hits this page or any
  5312. // time the user changes the VPN File (if they clone the profile or edit a different
  5313. // one, clearing this will be taken care of elsewhere).
  5314. //
  5315. if ((NULL == g_pHeadVpnEntry) || (NULL == pszCachedPhoneBook) || lstrcmpi(g_szVpnFile, pszCachedPhoneBook))
  5316. {
  5317. FreeDnsList(&g_pHeadVpnEntry, &g_pTailVpnEntry);
  5318. MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szVpnFile, &g_pHeadVpnEntry, &g_pTailVpnEntry, g_szOsdir, TRUE)); //TRUE == bLookingForVpnEntries
  5319. pszCachedPhoneBook = szCachedPhoneBook;
  5320. lstrcpy(pszCachedPhoneBook, g_szVpnFile);
  5321. }
  5322. RefreshDnsList(g_hInstance, hDlg, IDC_LIST1, g_pHeadVpnEntry, g_szLongServiceName, g_szCmsFile, NULL);
  5323. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  5324. EnableDisableDunEntryButtons(g_hInstance, hDlg, g_szCmsFile, g_szLongServiceName);
  5325. break;
  5326. case PSN_WIZBACK:
  5327. case PSN_WIZNEXT:
  5328. //
  5329. // Before writing out the entries we must make sure that we don't have a name collision with entries
  5330. // from the DUN list. Thus we will check each name in the VPN entries list for a matching name in the
  5331. // DUN entries list. If we detect a collision, then we will throw an error message to the user and
  5332. // let them deal with the problem. One further complication here is that the DUN entries list may not be
  5333. // read in yet and we can't read it in permanently in that case since the phonebook may not have been
  5334. // given yet or may change. Thus we will read in a temp copy to compare against if the list pointer is NULL.
  5335. //
  5336. if (NULL == g_pHeadDunEntry)
  5337. {
  5338. bFreeDunList = TRUE;
  5339. MYVERIFY(ReadNetworkSettings(g_szCmsFile, g_szLongServiceName, g_szPhonebk, &g_pHeadDunEntry, &g_pTailDunEntry, g_szOsdir, FALSE)); //FALSE == bLookingForVpnEntries
  5340. }
  5341. if (!CheckForDUNversusVPNNameConflicts(hDlg, g_pHeadDunEntry, g_pHeadVpnEntry))
  5342. {
  5343. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5344. return 1;
  5345. }
  5346. if (bFreeDunList)
  5347. {
  5348. FreeDnsList(&g_pHeadDunEntry, &g_pTailDunEntry);
  5349. }
  5350. //
  5351. // Okay, now it's safe to write out the entries
  5352. //
  5353. WriteNetworkingEntries(g_szCmsFile, g_szLongServiceName, g_szShortServiceName, g_pHeadVpnEntry);
  5354. //
  5355. // If any of the VPN dun settings has Pre-shared key enabled, go to the Pre-Shared key page
  5356. //
  5357. if (g_pHeadVpnEntry)
  5358. {
  5359. //
  5360. // If we are going forward, skip the Pre-shared key page if
  5361. // no DUN entries have Preshared key enabled.
  5362. //
  5363. g_bPresharedKeyNeeded = DoesSomeVPNsettingUsePresharedKey();
  5364. if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bPresharedKeyNeeded)
  5365. {
  5366. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
  5367. }
  5368. }
  5369. break;
  5370. default:
  5371. return FALSE;
  5372. }
  5373. break;
  5374. default:
  5375. return FALSE;
  5376. }
  5377. return TRUE;
  5378. }
  5379. void EnableDisableTunnelAddressControls(HWND hDlg)
  5380. {
  5381. BOOL bEnabledTunnelControls = IsDlgButtonChecked(hDlg, IDC_CHECK1) || IsDlgButtonChecked(hDlg, IDC_CHECK2);
  5382. BOOL bUseVpnFile = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  5383. //
  5384. // Enable/Disable the single VPN Server Edit control
  5385. //
  5386. HWND hControl = GetDlgItem(hDlg, IDC_RADIO1);
  5387. EnableWindow(hControl, bEnabledTunnelControls);
  5388. hControl = GetDlgItem(hDlg, IDC_EDIT1);
  5389. EnableWindow(hControl, (bEnabledTunnelControls && !bUseVpnFile));
  5390. //
  5391. // Enable/Disable the VPN File edit control, and browse button
  5392. //
  5393. hControl = GetDlgItem(hDlg, IDC_RADIO2);
  5394. EnableWindow(hControl, bEnabledTunnelControls);
  5395. hControl = GetDlgItem(hDlg, IDC_EDIT2);
  5396. EnableWindow(hControl, (bEnabledTunnelControls && bUseVpnFile));
  5397. hControl = GetDlgItem(hDlg, IDC_BUTTON1);
  5398. EnableWindow(hControl, bEnabledTunnelControls);
  5399. //
  5400. // Enable/Disable the use same username checkbox
  5401. //
  5402. hControl = GetDlgItem(hDlg, IDC_CHECK3);
  5403. EnableWindow(hControl, bEnabledTunnelControls);
  5404. }
  5405. //+----------------------------------------------------------------------------
  5406. //
  5407. // Function: ProcessTunneling
  5408. //
  5409. // Synopsis: Setup Tunneling
  5410. //
  5411. //
  5412. // History: quintinb Created Header and renamed from ProcessPage2E 8/6/98
  5413. //
  5414. //+----------------------------------------------------------------------------
  5415. INT_PTR APIENTRY ProcessTunneling(
  5416. HWND hDlg,
  5417. UINT message,
  5418. WPARAM wParam,
  5419. LPARAM lParam)
  5420. {
  5421. UINT uEditControl = 0;
  5422. UINT uRadioButton = 0;
  5423. UINT uMissingMsgId = 0;
  5424. TCHAR szTemp[MAX_PATH+1];
  5425. TCHAR szTempVpnFile[MAX_PATH+1];
  5426. NMHDR* pnmHeader = (NMHDR*)lParam;
  5427. ProcessBold(hDlg,message);
  5428. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_SECURE)) return TRUE;
  5429. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  5430. switch (message)
  5431. {
  5432. case WM_INITDIALOG:
  5433. SetFocus(GetDlgItem(hDlg, IDC_CHECK1));
  5434. break;
  5435. case WM_COMMAND:
  5436. switch (LOWORD(wParam))
  5437. {
  5438. case IDC_RADIO1:
  5439. case IDC_RADIO2:
  5440. case IDC_CHECK1:
  5441. case IDC_CHECK2:
  5442. EnableDisableTunnelAddressControls(hDlg);
  5443. break;
  5444. case IDC_BUTTON1: // Browse button
  5445. {
  5446. //
  5447. // If the user clicked the browse button without clicking the VPN File radio button,
  5448. // then we need to set the radio and make sure the other controls are
  5449. // enabled.
  5450. //
  5451. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  5452. EnableDisableTunnelAddressControls(hDlg);
  5453. UINT uFilter = IDS_TXTFILTER;
  5454. TCHAR* pszMask = TEXT("*.txt");
  5455. int iTemp = DoBrowse(hDlg, &uFilter, &pszMask, 1, IDC_EDIT2, TEXT("txt"), g_szLastBrowsePath);
  5456. MYDBGASSERT(0 != iTemp);
  5457. if (0 < iTemp) // -1 means the user cancelled
  5458. {
  5459. //
  5460. // We want to copy the full path to the filename into g_szVpnFile so
  5461. // that we have it for later in case the user wants to include it in the profile.
  5462. //
  5463. lstrcpy (g_szVpnFile, g_szLastBrowsePath);
  5464. //
  5465. // We also want to save the last browse path so that when the user next
  5466. // opens the browse dialog they will be in the same place they last
  5467. // browsed from.
  5468. //
  5469. LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
  5470. if (pszLastSlash)
  5471. {
  5472. pszLastSlash = CharNext(pszLastSlash);
  5473. *pszLastSlash = TEXT('\0');
  5474. }
  5475. else
  5476. {
  5477. g_szLastBrowsePath[0] = TEXT('\0');
  5478. }
  5479. }
  5480. }
  5481. break;
  5482. default:
  5483. break;
  5484. }
  5485. break;
  5486. case WM_NOTIFY:
  5487. if (NULL == pnmHeader)
  5488. {
  5489. return FALSE;
  5490. }
  5491. switch (pnmHeader->code)
  5492. {
  5493. case PSN_KILLACTIVE:
  5494. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  5495. return 1;
  5496. break; //lint !e527 this line isn't reachable but
  5497. // keep it in case the return is removed
  5498. case PSN_SETACTIVE:
  5499. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  5500. //
  5501. // Is this a tunneling profile? If so, check the tunnel this profile checkbox
  5502. //
  5503. MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection,
  5504. c_pszCmEntryTunnelPrimary, c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
  5505. MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK1,(*szTemp == TEXT('1'))));
  5506. //
  5507. // If we have merged profiles and the profile has tunnel references turned on then
  5508. // we want to check the tunnel references checkbox.
  5509. //
  5510. if (g_pHeadMerge == NULL)
  5511. {
  5512. MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK2,FALSE));
  5513. EnableWindow(GetDlgItem(hDlg,IDC_CHECK2),FALSE);
  5514. }
  5515. else
  5516. {
  5517. EnableWindow(GetDlgItem(hDlg,IDC_CHECK2),TRUE);
  5518. MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences,
  5519. c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
  5520. MYVERIFY(0 != CheckDlgButton(hDlg,IDC_CHECK2,(*szTemp == TEXT('1'))));
  5521. }
  5522. //
  5523. // Now we need to decide if we have a VPN File for this profile or just a single
  5524. // Tunnel Address. First try the TunnelFile entry.
  5525. //
  5526. szTemp[0] = TEXT('\0');
  5527. szTempVpnFile[0] = TEXT('\0');
  5528. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, TEXT(""),
  5529. szTempVpnFile, CELEMS(szTempVpnFile), g_szCmsFile); //lint !e534
  5530. if (TEXT('\0') != szTempVpnFile[0])
  5531. {
  5532. //
  5533. // The VpnFile text should be a relative path (corpras\vpn.txt) and
  5534. // thus we will want to add the path to the profile dir in front of it.
  5535. //
  5536. wsprintf(g_szVpnFile, TEXT("%s%s"), g_szOsdir, szTempVpnFile);
  5537. //
  5538. // Now verify that this exists
  5539. //
  5540. if (FileExists(g_szVpnFile))
  5541. {
  5542. LPTSTR pszSlash = CmStrrchr(g_szVpnFile, TEXT('\\'));
  5543. if (pszSlash)
  5544. {
  5545. pszSlash = CharNext(pszSlash);
  5546. lstrcpy(szTempVpnFile, pszSlash);
  5547. }
  5548. }
  5549. else
  5550. {
  5551. //
  5552. // This might just mean that the file is in the temp dir and we haven't
  5553. // created a dir under profiles yet ... Lets try looking for the file
  5554. // in the temp dir instead.
  5555. //
  5556. LPTSTR pszSlash = CmStrrchr(g_szVpnFile, TEXT('\\'));
  5557. if (pszSlash)
  5558. {
  5559. pszSlash = CharNext(pszSlash);
  5560. lstrcpy(szTempVpnFile, pszSlash);
  5561. }
  5562. wsprintf(g_szVpnFile, TEXT("%s\\%s"), g_szTempDir, szTempVpnFile);
  5563. if (!FileExists(g_szVpnFile))
  5564. {
  5565. //
  5566. // Well, we still didn't find it. Looks like the user has us baffled at this point.
  5567. // Clear out the buffers and the user will be forced to fill in the correct
  5568. // file path before continuing.
  5569. //
  5570. g_szVpnFile[0] = TEXT('\0');
  5571. szTempVpnFile[0] = TEXT('\0');
  5572. }
  5573. }
  5574. uRadioButton = IDC_RADIO2;
  5575. }
  5576. else
  5577. {
  5578. //
  5579. // We didn't get a VPN file so lets try for a Tunnel Address
  5580. //
  5581. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, TEXT(""),
  5582. szTemp, CELEMS(szTemp), g_szCmsFile); //lint !e534
  5583. uRadioButton = IDC_RADIO1;
  5584. }
  5585. //
  5586. // Now fill in one of the edit controls and set a Radio Button
  5587. //
  5588. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)szTemp));
  5589. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)szTempVpnFile));
  5590. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, uRadioButton));
  5591. //
  5592. // Now get the UseSameUserName value and set that as appropriate
  5593. //
  5594. MYVERIFY(0 != GetPrivateProfileString(c_pszCmSection,
  5595. c_pszCmEntryUseSameUserName, c_pszZero, szTemp, CELEMS(szTemp), g_szCmsFile));
  5596. g_bUseSamePwd = (*szTemp == TEXT('1'));
  5597. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK3, (UINT)g_bUseSamePwd));
  5598. EnableDisableTunnelAddressControls(hDlg);
  5599. break;
  5600. case PSN_WIZBACK:
  5601. case PSN_WIZNEXT:
  5602. //
  5603. // Read the checkboxes to figure out if we are tunneling or not
  5604. //
  5605. if (IsDlgButtonChecked(hDlg,IDC_CHECK1))
  5606. {
  5607. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelPrimary, c_pszOne, g_szCmsFile));
  5608. }
  5609. else
  5610. {
  5611. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelPrimary, c_pszZero, g_szCmsFile));
  5612. }
  5613. if (IsDlgButtonChecked(hDlg,IDC_CHECK2))
  5614. {
  5615. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences, c_pszOne, g_szCmsFile));
  5616. }
  5617. else
  5618. {
  5619. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelReferences, c_pszZero, g_szCmsFile));
  5620. }
  5621. //
  5622. // If we are tunneling then set the tunnel settings
  5623. //
  5624. if (IsDlgButtonChecked(hDlg,IDC_CHECK2) || IsDlgButtonChecked(hDlg,IDC_CHECK1))
  5625. {
  5626. g_bUseTunneling = TRUE;
  5627. //
  5628. // Figure out if we are looking for a single tunnel address or a VPN file
  5629. //
  5630. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
  5631. {
  5632. uEditControl = IDC_EDIT1;
  5633. uMissingMsgId = IDS_NOTUNNEL;
  5634. g_szVpnFile[0] = TEXT('\0');
  5635. }
  5636. else
  5637. {
  5638. uEditControl = IDC_EDIT2;
  5639. uMissingMsgId = IDS_NOTUNNELFILE;
  5640. }
  5641. //
  5642. // Get the tunnel server address or VPN file
  5643. //
  5644. LRESULT lResult = GetTextFromControl(hDlg, uEditControl, szTemp, MAX_PATH, TRUE); // bDisplayError == TRUE
  5645. if (-1 == lResult)
  5646. {
  5647. SetFocus(GetDlgItem(hDlg, uEditControl));
  5648. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5649. return 1;
  5650. }
  5651. else if (0 == lResult)
  5652. {
  5653. szTemp[0] = TEXT('\0');
  5654. }
  5655. //
  5656. // Trim the string
  5657. //
  5658. CmStrTrim(szTemp);
  5659. //
  5660. // Check to make sure that they actually gave us text
  5661. //
  5662. if (TEXT('\0') == szTemp[0])
  5663. {
  5664. MYVERIFY(IDOK == ShowMessage(hDlg, uMissingMsgId, MB_OK));
  5665. SetFocus(GetDlgItem(hDlg, uEditControl));
  5666. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5667. return 1;
  5668. }
  5669. //
  5670. // If we have a VPN file, we need to verify it
  5671. //
  5672. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2))
  5673. {
  5674. if (!VerifyFile(hDlg, IDC_EDIT2, g_szVpnFile, TRUE))
  5675. {
  5676. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  5677. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5678. return TRUE;
  5679. }
  5680. else
  5681. {
  5682. //
  5683. // We have now verified that we can find the file, but since
  5684. // the user cannot enter their own tunnel address we need to
  5685. // go one step further and make sure that there is at least one
  5686. // tunnel address in the file.
  5687. //
  5688. if (!VerifyVpnFile(g_szVpnFile))
  5689. {
  5690. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_BADVPNFORMAT, MB_OK));
  5691. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  5692. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  5693. return TRUE;
  5694. }
  5695. //
  5696. // Lets copy the VPN file to the temp dir
  5697. //
  5698. wsprintf(szTemp, TEXT("%s\\%s"), g_szTempDir, GetName(g_szVpnFile));
  5699. if (0 != lstrcmpi(szTemp, g_szVpnFile))
  5700. {
  5701. MYVERIFY(TRUE == CopyFileWrapper(g_szVpnFile, szTemp, FALSE));
  5702. MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
  5703. }
  5704. }
  5705. }
  5706. //
  5707. // Write out the vpn file and tunnel address entries
  5708. //
  5709. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO1))
  5710. {
  5711. //
  5712. // szTemp contains the tunnel address already, so just
  5713. // clear the vpn file variable.
  5714. //
  5715. szTempVpnFile[0] = TEXT('\0');
  5716. }
  5717. else
  5718. {
  5719. //
  5720. // clear the tunnel address and set the vpn file
  5721. //
  5722. szTemp[0] = TEXT('\0');
  5723. wsprintf(szTempVpnFile, TEXT("%s\\%s"), g_szShortServiceName, GetName(g_szVpnFile));
  5724. }
  5725. //
  5726. // Write out the tunnel address
  5727. //
  5728. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, szTemp, g_szCmsFile));
  5729. //
  5730. // Write out the tunnel file
  5731. //
  5732. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, szTempVpnFile, g_szCmsFile));
  5733. //
  5734. // Set the name of the Tunnel Dun setting
  5735. //
  5736. MYVERIFY(0 != GetTunnelDunSettingName(g_szCmsFile, g_szLongServiceName, szTemp, CELEMS(szTemp)));
  5737. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, szTemp, g_szCmsFile));
  5738. //
  5739. // Write out the use same user name value
  5740. //
  5741. g_bUseSamePwd = IsDlgButtonChecked(hDlg,IDC_CHECK3);
  5742. if (g_bUseSamePwd)
  5743. {
  5744. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, c_pszOne, g_szCmsFile));
  5745. }
  5746. else
  5747. {
  5748. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, c_pszZero, g_szCmsFile));
  5749. }
  5750. }
  5751. else
  5752. {
  5753. //
  5754. // Set g_bUseTunneling to False but don't clear out the tunnel settings until the
  5755. // user hits the finish button. That way if they change their mind part way through
  5756. // building the profile we don't throw away their settings.
  5757. //
  5758. g_bUseTunneling = FALSE;
  5759. }
  5760. //
  5761. // Skip the VPN entries dialog if we don't have tunneling enabled.
  5762. //
  5763. if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bUseTunneling)
  5764. {
  5765. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_PHONEBOOK));
  5766. }
  5767. break;
  5768. default:
  5769. return FALSE;
  5770. }
  5771. break;
  5772. default:
  5773. return FALSE;
  5774. }
  5775. return TRUE;
  5776. }
  5777. //+----------------------------------------------------------------------------
  5778. //
  5779. // Function: ValidatePresharedKey
  5780. //
  5781. // Synopsis: Checks the given pre-shared key for validity
  5782. //
  5783. // Arguments: pszPresharedKey - string to check
  5784. //
  5785. // Returns: BOOL - TRUE => key is good, FALSE => bad
  5786. //
  5787. // History: sumitc Created 03/27/01
  5788. //
  5789. //+----------------------------------------------------------------------------
  5790. BOOL ValidatePresharedKey(LPTSTR pszPresharedKey)
  5791. {
  5792. BOOL bReturn = FALSE;
  5793. MYDBGASSERT(pszPresharedKey);
  5794. if (pszPresharedKey && (TEXT('\0') != pszPresharedKey[0]) &&
  5795. (lstrlen(pszPresharedKey) <= c_dwMaxPresharedKey))
  5796. {
  5797. bReturn = TRUE;
  5798. }
  5799. return bReturn;
  5800. }
  5801. //+----------------------------------------------------------------------------
  5802. //
  5803. // Function: ValidatePresharedKeyPIN
  5804. //
  5805. // Synopsis: Checks the given PIN for validity
  5806. //
  5807. // Arguments: pszPresharedKey - string to check
  5808. //
  5809. // Returns: BOOL - TRUE => PIN is good, FALSE => bad
  5810. //
  5811. // History: sumitc Created 03/27/01
  5812. //
  5813. //+----------------------------------------------------------------------------
  5814. BOOL ValidatePresharedKeyPIN(LPTSTR pszPresharedKeyPIN)
  5815. {
  5816. BOOL bReturn = FALSE;
  5817. MYDBGASSERT(pszPresharedKeyPIN);
  5818. if (pszPresharedKeyPIN && (TEXT('\0') != pszPresharedKeyPIN[0]) &&
  5819. (lstrlen(pszPresharedKeyPIN) >= c_dwMinPresharedKeyPIN) &&
  5820. (lstrlen(pszPresharedKeyPIN) <= c_dwMaxPresharedKeyPIN))
  5821. {
  5822. bReturn = TRUE;
  5823. }
  5824. return bReturn;
  5825. }
  5826. //+----------------------------------------------------------------------------
  5827. //
  5828. // Function: EncryptPresharedKey
  5829. //
  5830. // Synopsis: Encrypts the given key into a form that can be serialized.
  5831. //
  5832. // Arguments: szKey - key to encrypt
  5833. // szPIN - pin to use as seed
  5834. // ppszEncrypted - resultant string
  5835. //
  5836. // Returns: BOOL - TRUE => successfully encrypted key, FALSE => failed
  5837. //
  5838. // History: sumitc Created 03/27/01
  5839. //
  5840. //+----------------------------------------------------------------------------
  5841. BOOL EncryptPresharedKey(IN LPTSTR szKey,
  5842. IN LPTSTR szPIN,
  5843. OUT LPTSTR * ppszEncrypted)
  5844. {
  5845. BOOL bReturn = FALSE;
  5846. DWORD dwLenEncrypted = 0;
  5847. LPSTR pszAnsiEncrypted = NULL;
  5848. MYDBGASSERT(ppszEncrypted);
  5849. LPSTR pszAnsiKey = WzToSzWithAlloc(szKey);
  5850. LPSTR pszAnsiPIN = WzToSzWithAlloc(szPIN);
  5851. MYDBGASSERT(pszAnsiKey && pszAnsiPIN);
  5852. if (ppszEncrypted && pszAnsiKey && pszAnsiPIN)
  5853. {
  5854. //
  5855. // Initialize
  5856. //
  5857. InitSecure(FALSE); // use secure, not fast encryption
  5858. //
  5859. // Encrypt it
  5860. //
  5861. if (EncryptString(pszAnsiKey,
  5862. pszAnsiPIN,
  5863. (PBYTE*) &pszAnsiEncrypted,
  5864. &dwLenEncrypted,
  5865. #if defined(DEBUG) && defined(DEBUG_MEM)
  5866. (PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
  5867. (PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
  5868. #else
  5869. (PFN_CMSECUREALLOC)CmMalloc, // mem allocator
  5870. (PFN_CMSECUREFREE)CmFree)) // mem deallocator
  5871. #endif
  5872. {
  5873. bReturn = TRUE;
  5874. }
  5875. //
  5876. // Uninitialize
  5877. //
  5878. DeInitSecure();
  5879. if (bReturn)
  5880. {
  5881. *ppszEncrypted = SzToWzWithAlloc(pszAnsiEncrypted);
  5882. ZeroMemory(pszAnsiEncrypted, lstrlenA(pszAnsiEncrypted) * sizeof(CHAR));
  5883. #if defined(DEBUG) && defined(DEBUG_MEM)
  5884. FreeDebugMem(pszAnsiEncrypted);
  5885. #else
  5886. CmFree(pszAnsiEncrypted);
  5887. #endif
  5888. }
  5889. }
  5890. CmFree(pszAnsiKey);
  5891. CmFree(pszAnsiPIN);
  5892. return bReturn;
  5893. }
  5894. //+----------------------------------------------------------------------------
  5895. //
  5896. // Function: EnableDisablePresharedKeyControls
  5897. //
  5898. // Synopsis: Based on whether we have a key, set enabled/disabled state of UI
  5899. //
  5900. // History: 27-Mar-2001 SumitC Created
  5901. //
  5902. //+----------------------------------------------------------------------------
  5903. void EnableDisablePresharedKeyControls(HWND hDlg, BOOL bEnable)
  5904. {
  5905. //
  5906. // Enable edit controls and checkboxes
  5907. //
  5908. EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY), bEnable);
  5909. EnableWindow(GetDlgItem(hDlg, IDC_USEENCRYPTION), bEnable);
  5910. EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN), bEnable);
  5911. if (bEnable)
  5912. {
  5913. CheckDlgButton(hDlg, IDC_USEENCRYPTION, TRUE);
  5914. }
  5915. //
  5916. // Either clear edit control or fill with info text
  5917. //
  5918. if (bEnable)
  5919. {
  5920. SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, WM_SETTEXT, 0, (LPARAM)TEXT(""));
  5921. SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY));
  5922. }
  5923. else
  5924. {
  5925. LPTSTR pszTmp = CmLoadString(g_hInstance, IDS_PRESHAREDKEY_ALREADY);
  5926. if (pszTmp)
  5927. {
  5928. SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, WM_SETTEXT, 0, (LPARAM)pszTmp);
  5929. }
  5930. CmFree(pszTmp);
  5931. }
  5932. //
  5933. // Show or hide the "Replace Key" button
  5934. //
  5935. ShowWindow(GetDlgItem(hDlg, IDC_REPLACE_PSK), !bEnable);
  5936. }
  5937. //+----------------------------------------------------------------------------
  5938. //
  5939. // Function: ProcessPresharedKey
  5940. //
  5941. // Synopsis: Setup Pre-shared key usage for this profile
  5942. //
  5943. // History: 27-Mar-2001 SumitC Created
  5944. //
  5945. //+----------------------------------------------------------------------------
  5946. INT_PTR APIENTRY ProcessPresharedKey(
  5947. HWND hDlg,
  5948. UINT message,
  5949. WPARAM wParam,
  5950. LPARAM lParam)
  5951. {
  5952. NMHDR* pnmHeader = (NMHDR*)lParam;
  5953. static LPTSTR pszPresharedKey = NULL;
  5954. static BOOL bEncryptPresharedKey = FALSE;
  5955. ProcessBold(hDlg,message);
  5956. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PRESHARED)) return TRUE;
  5957. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  5958. switch (message)
  5959. {
  5960. case WM_INITDIALOG:
  5961. //
  5962. // Set max text lengths for the edit controls
  5963. //
  5964. SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY, EM_SETLIMITTEXT, (WPARAM)c_dwMaxPresharedKey, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
  5965. SendDlgItemMessage(hDlg, IDC_PRESHARED_KEY_PIN, EM_SETLIMITTEXT, (WPARAM)c_dwMaxPresharedKeyPIN, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
  5966. break;
  5967. case WM_COMMAND:
  5968. switch (LOWORD(wParam))
  5969. {
  5970. case IDC_REPLACE_PSK:
  5971. if (IDYES == ShowMessage(hDlg, IDS_REALLY_REPLACE_PSK, MB_YESNO | MB_ICONWARNING))
  5972. {
  5973. CmFree(pszPresharedKey);
  5974. pszPresharedKey = NULL;
  5975. EnableDisablePresharedKeyControls(hDlg, TRUE);
  5976. }
  5977. break;
  5978. case IDC_USEENCRYPTION:
  5979. EnableWindow(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN), IsDlgButtonChecked(hDlg, IDC_USEENCRYPTION));
  5980. break;
  5981. default:
  5982. break;
  5983. }
  5984. break;
  5985. case WM_NOTIFY:
  5986. if (NULL == pnmHeader)
  5987. {
  5988. return FALSE;
  5989. }
  5990. switch (pnmHeader->code)
  5991. {
  5992. case PSN_KILLACTIVE:
  5993. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  5994. return 1;
  5995. break; //lint !e527 this line isn't reachable but
  5996. // keep it in case the return is removed
  5997. case PSN_SETACTIVE:
  5998. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  5999. CMASSERTMSG(g_bPresharedKeyNeeded, TEXT("we shouldn't get to this page otherwise."));
  6000. //
  6001. // Read in the Pre-shared key and the flag that says if it's encrypted
  6002. //
  6003. pszPresharedKey = GetPrivateProfileStringWithAlloc(c_pszCmSection, c_pszCmEntryPresharedKey,
  6004. TEXT(""), g_szCmpFile); //lint !e534
  6005. bEncryptPresharedKey = (BOOL)GetPrivateProfileInt(c_pszCmSection, c_pszCmEntryKeyIsEncrypted,
  6006. FALSE, g_szCmpFile); //lint !e534
  6007. //
  6008. // If we don't have a pre-shared key, hide the Replace button, and enable all
  6009. // the other controls. If we already have a pre-shared key, disable all the
  6010. // controls and enable the Replace button.
  6011. //
  6012. EnableDisablePresharedKeyControls(hDlg, !pszPresharedKey);
  6013. break;
  6014. case PSN_WIZBACK:
  6015. g_bPresharedKeyNeeded = FALSE; // force this to be recomputed, since it can change if we go back
  6016. // fall through and verify pre-shared key as well
  6017. case PSN_WIZNEXT:
  6018. if (NULL == pszPresharedKey)
  6019. {
  6020. TCHAR szPresharedKey[c_dwMaxPresharedKey + 1];
  6021. TCHAR szPresharedKeyPIN[c_dwMaxPresharedKeyPIN + 1];
  6022. //
  6023. // verify Pre-shared Key
  6024. //
  6025. GetTextFromControl(hDlg, IDC_PRESHARED_KEY, szPresharedKey, c_dwMaxPresharedKey, TRUE);
  6026. if (FALSE == ValidatePresharedKey(szPresharedKey))
  6027. {
  6028. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_PRESHAREDKEY_BAD, MB_OK | MB_ICONSTOP));
  6029. SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY));
  6030. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  6031. return 1;
  6032. }
  6033. //
  6034. // if key is being encrypted, verify the PIN and use to encrypt key
  6035. //
  6036. if (IsDlgButtonChecked(hDlg, IDC_USEENCRYPTION))
  6037. {
  6038. GetTextFromControl(hDlg, IDC_PRESHARED_KEY_PIN, szPresharedKeyPIN, c_dwMaxPresharedKeyPIN, TRUE);
  6039. if (FALSE == ValidatePresharedKeyPIN(szPresharedKeyPIN))
  6040. {
  6041. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_PRESHAREDKEY_PIN_BAD, MB_OK | MB_ICONSTOP));
  6042. SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN));
  6043. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  6044. return 1;
  6045. }
  6046. //
  6047. // Encrypt Pre-shared Key
  6048. //
  6049. if (FALSE == EncryptPresharedKey(szPresharedKey, szPresharedKeyPIN, &pszPresharedKey))
  6050. {
  6051. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_PSK_ENCRYPT_FAILED, MB_OK | MB_ICONSTOP));
  6052. SetFocus(GetDlgItem(hDlg, IDC_PRESHARED_KEY_PIN));
  6053. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  6054. return 1;
  6055. }
  6056. MYDBGASSERT(pszPresharedKey);
  6057. bEncryptPresharedKey = TRUE;
  6058. }
  6059. else
  6060. {
  6061. pszPresharedKey = CmStrCpyAlloc(szPresharedKey);
  6062. }
  6063. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPresharedKey,
  6064. pszPresharedKey,
  6065. g_szCmpFile));
  6066. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryKeyIsEncrypted,
  6067. (bEncryptPresharedKey ? c_pszOne : c_pszZero),
  6068. g_szCmpFile));
  6069. ZeroMemory(szPresharedKey, c_dwMaxPresharedKey * sizeof(TCHAR));
  6070. ZeroMemory(szPresharedKeyPIN, c_dwMaxPresharedKeyPIN * sizeof(TCHAR));
  6071. }
  6072. CmFree(pszPresharedKey);
  6073. pszPresharedKey = NULL;
  6074. break;
  6075. default:
  6076. return FALSE;
  6077. }
  6078. break;
  6079. default:
  6080. return FALSE;
  6081. }
  6082. return TRUE;
  6083. }
  6084. //+----------------------------------------------------------------------------
  6085. //
  6086. // Function: RenameSection
  6087. //
  6088. // Synopsis: This function renames an INI file section from the current name to
  6089. // the new name.
  6090. //
  6091. // Arguments: LPCTSTR szCurrentSectionName - Current name that you want renamed
  6092. // LPCTSTR szNewSectionName - name you want the above renamed to
  6093. // LPCTSTR szFile - INI file to rename the section in
  6094. //
  6095. // Returns: BOOL - Returns TRUE unless a malloc error occurred
  6096. //
  6097. // History: quintinb Created 9/11/98
  6098. //
  6099. //+----------------------------------------------------------------------------
  6100. BOOL RenameSection(LPCTSTR szCurrentSectionName, LPCTSTR szNewSectionName, LPCTSTR szFile)
  6101. {
  6102. //
  6103. // Get the existing section
  6104. //
  6105. LPTSTR pszBuffer = GetPrivateProfileSectionWithAlloc(szCurrentSectionName, szFile);
  6106. if (NULL == pszBuffer)
  6107. {
  6108. return FALSE;
  6109. }
  6110. else
  6111. {
  6112. //
  6113. // Erase the old section
  6114. //
  6115. MYVERIFY(0 != WritePrivateProfileString(szCurrentSectionName, NULL, NULL, szFile));
  6116. //
  6117. // Write out the renamed section
  6118. //
  6119. MYVERIFY(0 != WritePrivateProfileSection(szNewSectionName, pszBuffer, szFile));
  6120. }
  6121. CmFree(pszBuffer);
  6122. return TRUE;
  6123. }
  6124. //+----------------------------------------------------------------------------
  6125. //
  6126. // Function: ProcessCustomActionPopup
  6127. //
  6128. // Synopsis: Processes windows messages for the dialog which allows CMAK to add
  6129. // or edit custom actions. Note that we pass in a pointer to a
  6130. // CustomActionListItem struct on WM_INITDIALOG through the lParam.
  6131. // If the user hits OK, we copy the data that they gave us into this
  6132. // structure. Note that we only do this to communicate the data back to
  6133. // the caller as we update the custom action list ourselves.
  6134. //
  6135. // Arguments: WND hDlg - dialog window handle
  6136. // UINT message - message identifier
  6137. // WPARAM wParam - wParam Value
  6138. // LPARAM lParam - lParam Value
  6139. //
  6140. //
  6141. // History: quintinb Created 02/25/00
  6142. //
  6143. //+----------------------------------------------------------------------------
  6144. INT_PTR APIENTRY ProcessCustomActionPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  6145. {
  6146. TCHAR szTemp[MAX_PATH+1];
  6147. HRESULT hr;
  6148. int iTemp;
  6149. LRESULT lResult;
  6150. LPTSTR pszTypeString = NULL;
  6151. CustomActionTypes Type;
  6152. CustomActionExecutionStates ExecutionIndex;
  6153. static CustomActionListItem* pItem;
  6154. CustomActionListItem* pTempItem = NULL;
  6155. CustomActionListItem NewItem;
  6156. static TCHAR szFullPathToProgram[MAX_PATH+1] = {0};
  6157. HWND hControl;
  6158. LPTSTR pszTemp;
  6159. SetDefaultGUIFont(hDlg, message, IDC_EDIT1);
  6160. SetDefaultGUIFont(hDlg, message, IDC_EDIT2);
  6161. SetDefaultGUIFont(hDlg, message, IDC_EDIT3);
  6162. SetDefaultGUIFont(hDlg, message, IDC_COMBO1);
  6163. SetDefaultGUIFont(hDlg, message, IDC_COMBO2);
  6164. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CONNECT)) return TRUE;
  6165. switch (message)
  6166. {
  6167. case WM_INITDIALOG:
  6168. MYDBGASSERT(g_pCustomActionList);
  6169. if (NULL == g_pCustomActionList)
  6170. {
  6171. return TRUE;
  6172. }
  6173. //
  6174. // We keep the full path to the program in this static string.
  6175. //
  6176. ZeroMemory(szFullPathToProgram, sizeof(szFullPathToProgram));
  6177. //
  6178. // Check to see if we got an initialization parameter
  6179. //
  6180. if (lParam)
  6181. {
  6182. //
  6183. // Thus we were passed a CustomActionListItem structure. It either contains a
  6184. // type and a description, meaning that this is an edit and we should lookup the
  6185. // data, or we got just a type and we just need to pre-set the type combo to the
  6186. // type the user was currently viewing in the listbox.
  6187. //
  6188. pItem = (CustomActionListItem*)lParam;
  6189. if (pItem->szDescription[0])
  6190. {
  6191. hr = g_pCustomActionList->GetExistingActionData(g_hInstance, pItem->szDescription, pItem->Type, &pTempItem);
  6192. if (SUCCEEDED(hr))
  6193. {
  6194. //
  6195. // Let's set the dialog title to say that we are editing an entry. If we fail to retrive
  6196. // the string the dialog may look a little funny but should still be functional so we
  6197. // won't try to bail out.
  6198. //
  6199. pszTemp = CmLoadString(g_hInstance, IDS_CA_EDIT_TITLE);
  6200. if (pszTemp)
  6201. {
  6202. MYVERIFY(SendMessage (hDlg, WM_SETTEXT, 0, (LPARAM)pszTemp));
  6203. CmFree(pszTemp);
  6204. }
  6205. //
  6206. // Okay, we have data so lets set the item fields. Don't set the description if it
  6207. // is only the temporary description that we concatenated from the program and the
  6208. // arguments.
  6209. //
  6210. if (FALSE == pTempItem->bTempDescription)
  6211. {
  6212. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT3), WM_SETTEXT, 0, (LPARAM)pTempItem->szDescription));
  6213. }
  6214. //
  6215. // Set the program edit control, note we only show the filename if the user is including the
  6216. // binary in the package. Also note that we save the full path in szFullPathToProgram so that
  6217. // we have it for later.
  6218. //
  6219. if (pTempItem->bIncludeBinary)
  6220. {
  6221. GetFileName(pTempItem->szProgram, szTemp);
  6222. lstrcpyn(szFullPathToProgram, pTempItem->szProgram, CELEMS(szFullPathToProgram));
  6223. }
  6224. else
  6225. {
  6226. lstrcpyn(szTemp, pTempItem->szProgram, CELEMS(szTemp));
  6227. }
  6228. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)szTemp));
  6229. //
  6230. // Set the include program checkbox
  6231. //
  6232. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, pTempItem->bIncludeBinary));
  6233. //
  6234. // Set the parameters edit control. Note that we put the function name and the parameters
  6235. // back together if necessary.
  6236. //
  6237. if (NULL != pTempItem->pszParameters)
  6238. {
  6239. LPTSTR pszParamToDisplay = NULL;
  6240. if (pTempItem->szFunctionName[0])
  6241. {
  6242. pszParamToDisplay = CmStrCpyAlloc(pTempItem->szFunctionName);
  6243. MYDBGASSERT(pszParamToDisplay);
  6244. if (pszParamToDisplay && pTempItem->pszParameters[0])
  6245. {
  6246. pszParamToDisplay = CmStrCatAlloc(&pszParamToDisplay, TEXT(" "));
  6247. MYDBGASSERT(pszParamToDisplay);
  6248. if (pszParamToDisplay)
  6249. {
  6250. pszParamToDisplay = CmStrCatAlloc(&pszParamToDisplay, pTempItem->pszParameters);
  6251. MYDBGASSERT(pszParamToDisplay);
  6252. }
  6253. }
  6254. }
  6255. else
  6256. {
  6257. pszParamToDisplay = CmStrCpyAlloc(pTempItem->pszParameters);
  6258. MYDBGASSERT(pszParamToDisplay);
  6259. }
  6260. if (pszParamToDisplay)
  6261. {
  6262. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)pszParamToDisplay));
  6263. CmFree(pszParamToDisplay);
  6264. }
  6265. }
  6266. else
  6267. {
  6268. CMASSERTMSG(FALSE, TEXT("pTempItem->pszParameters is NULL"));
  6269. }
  6270. }
  6271. }
  6272. //
  6273. // Figure out what type of custom action we are editing or trying to add (we pre-seed the add type with
  6274. // the type the user was viewing. If they were viewing all we set it to the first in the combo).
  6275. //
  6276. Type = pItem->Type;
  6277. hr = g_pCustomActionList->MapFlagsToIndex((pTempItem ? pTempItem->dwFlags : 0), (int*)&ExecutionIndex);
  6278. if (FAILED(hr))
  6279. {
  6280. CMASSERTMSG(FALSE, TEXT("ProcessCustomActionPopup -- MapFlagsToIndex failed, setting execution state to Always."));
  6281. ExecutionIndex = (CustomActionExecutionStates)0; // set it to the first item in the enum
  6282. }
  6283. }
  6284. else
  6285. {
  6286. pItem = NULL;
  6287. Type = (CustomActionTypes)0; // set it to the first item in the enum
  6288. ExecutionIndex = (CustomActionExecutionStates)0; // set it to the first item in the enum
  6289. }
  6290. if (pTempItem)
  6291. {
  6292. CmFree(pTempItem->pszParameters);
  6293. CmFree(pTempItem);
  6294. pTempItem = NULL;
  6295. }
  6296. //
  6297. // Setup the custom action types combobox, note that we set bAddAll to FALSE so that we don't add the
  6298. // All connect action type used for viewing the connect actions on the main dialog.
  6299. //
  6300. hr = g_pCustomActionList->AddCustomActionTypesToComboBox(hDlg, IDC_COMBO1, g_hInstance, g_bUseTunneling, FALSE);
  6301. //
  6302. // Pick a connect action type
  6303. //
  6304. hr = g_pCustomActionList->GetTypeStringFromType(g_hInstance, Type, &pszTypeString);
  6305. if (SUCCEEDED(hr))
  6306. {
  6307. lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszTypeString);
  6308. if (CB_ERR != lResult)
  6309. {
  6310. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0));
  6311. }
  6312. CmFree(pszTypeString);
  6313. }
  6314. //
  6315. // Next initialize the the combo that tells us when to run a connect action. If we are tunneling
  6316. // then the user can pick to run the connection for direct connections only, dialup connections only,
  6317. // all connections that involve dialup, all connections that involve a tunnel, or all connections.
  6318. //
  6319. hr = g_pCustomActionList->AddExecutionTypesToComboBox(hDlg, IDC_COMBO2, g_hInstance, g_bUseTunneling);
  6320. //
  6321. // Pick when the connect action will execute if it is enabled
  6322. //
  6323. if (g_bUseTunneling)
  6324. {
  6325. lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  6326. if ((CB_ERR != lResult) && (lResult > 0))
  6327. {
  6328. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)ExecutionIndex, (LPARAM)0));
  6329. }
  6330. }
  6331. break;
  6332. case WM_COMMAND:
  6333. switch (LOWORD(wParam))
  6334. {
  6335. case IDC_BUTTON1: // Browse
  6336. {
  6337. UINT uFilterArray[2] = {IDS_CONACTFILTER, IDS_ALLFILTER};
  6338. TCHAR* pszMaskArray[2] = {TEXT("*.exe;*.com;*.bat;*.dll"), TEXT("*.*")};
  6339. iTemp = DoBrowse(hDlg, uFilterArray, pszMaskArray, 2, IDC_EDIT1, TEXT("exe"), g_szLastBrowsePath);
  6340. MYDBGASSERT(0 != iTemp);
  6341. if (0 < iTemp) // -1 means the user cancelled
  6342. {
  6343. //
  6344. // Check the include binary button for the user
  6345. //
  6346. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
  6347. //
  6348. // We want to copy the full path to the filename into szFullPathToProgram so
  6349. // that we have it for later in case the user wants to include it in the profile.
  6350. //
  6351. lstrcpyn(szFullPathToProgram, g_szLastBrowsePath, CELEMS(szFullPathToProgram));
  6352. //
  6353. // We also want to save the last browse path so that when the user next
  6354. // opens the browse dialog they will be in the same place they last
  6355. // browsed from.
  6356. //
  6357. LPTSTR pszLastSlash = CmStrrchr(g_szLastBrowsePath, TEXT('\\'));
  6358. if (pszLastSlash)
  6359. {
  6360. pszLastSlash = CharNext(pszLastSlash);
  6361. *pszLastSlash = TEXT('\0');
  6362. }
  6363. else
  6364. {
  6365. g_szLastBrowsePath[0] = TEXT('\0');
  6366. }
  6367. }
  6368. }
  6369. break;
  6370. case IDOK:
  6371. //
  6372. // Make sure we have a valid custom action list
  6373. //
  6374. MYDBGASSERT(g_pCustomActionList);
  6375. if (NULL == g_pCustomActionList)
  6376. {
  6377. return TRUE;
  6378. }
  6379. //
  6380. // Get the text from the Program Edit Control, verifying
  6381. // we can convert it to something ANSI
  6382. //
  6383. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  6384. {
  6385. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  6386. return TRUE;
  6387. }
  6388. //
  6389. // Check to make sure the program field isn't blank.
  6390. //
  6391. if (TEXT('\0') == szTemp[0])
  6392. {
  6393. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPROG, MB_OK));
  6394. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  6395. return TRUE;
  6396. }
  6397. //
  6398. // Make sure that the program doesn't have a comma or a plus
  6399. // sign in it as that will mess up our parsing routines. There
  6400. // is no need to allow users to use such odd ball file names.
  6401. //
  6402. if (CmStrchr(szTemp, TEXT('+')) || CmStrchr(szTemp, TEXT(',')))
  6403. {
  6404. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOPLUSORCOMMAINPROG, MB_OK));
  6405. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  6406. return TRUE;
  6407. }
  6408. //
  6409. // Now check to see if we need to verify that the file exists.
  6410. // We only want to do that if they have the include program files
  6411. // checkbox checked.
  6412. //
  6413. ZeroMemory(&NewItem, sizeof(CustomActionListItem));
  6414. NewItem.bIncludeBinary = IsDlgButtonChecked(hDlg, IDC_CHECK1);
  6415. if (NewItem.bIncludeBinary)
  6416. {
  6417. if (!VerifyFile(hDlg, IDC_EDIT1, szFullPathToProgram, TRUE))
  6418. {
  6419. return TRUE;
  6420. }
  6421. else
  6422. {
  6423. lstrcpyn(NewItem.szProgram, szFullPathToProgram, CELEMS(NewItem.szProgram));
  6424. }
  6425. }
  6426. else
  6427. {
  6428. //
  6429. // Copy the file as is, but warn the user if they have
  6430. // a string with a path but doesn't start with a environment
  6431. // variable.
  6432. //
  6433. iTemp = IDNO;
  6434. CmStrTrim(szTemp);
  6435. LPTSTR pszSlash = CmStrchr(szTemp, TEXT('\\'));
  6436. if (pszSlash && (TEXT('%') != szTemp[0]))
  6437. {
  6438. iTemp = ShowMessage(hDlg, IDS_PATH_WITH_NO_ENV, MB_YESNO | MB_ICONWARNING);
  6439. }
  6440. if (IDNO == iTemp)
  6441. {
  6442. lstrcpyn(NewItem.szProgram, szTemp, CELEMS(NewItem.szProgram));
  6443. }
  6444. else
  6445. {
  6446. return TRUE;
  6447. }
  6448. }
  6449. //
  6450. // Get the Text from the Params edit control, make sure to validate
  6451. // that we can convert it to ANSI
  6452. //
  6453. hControl = GetDlgItem(hDlg, IDC_EDIT2);
  6454. MYDBGASSERT(hControl);
  6455. pszTemp = NULL;
  6456. if (hControl)
  6457. {
  6458. iTemp = GetCurrentEditControlTextAlloc(hControl, &pszTemp);
  6459. if (-1 == iTemp)
  6460. {
  6461. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  6462. return TRUE;
  6463. }
  6464. }
  6465. //
  6466. // Check to see if we have a dll for a program. If so, the first parameter is the function name.
  6467. //
  6468. if (pszTemp)
  6469. {
  6470. CmStrTrim(pszTemp);
  6471. iTemp = lstrlen(NewItem.szProgram) - 4; // 4 == lstrlen (TEXT(".dll"));
  6472. if (0 == lstrcmpi(TEXT(".dll"), (NewItem.szProgram + iTemp)))
  6473. {
  6474. //
  6475. // Make sure that we have a parameter string
  6476. //
  6477. if (pszTemp && pszTemp[0])
  6478. {
  6479. LPTSTR pszEndOfFunctionName = CmStrchr(pszTemp, TEXT(' '));
  6480. if (pszEndOfFunctionName)
  6481. {
  6482. LPTSTR pszParams = CharNext(pszEndOfFunctionName);
  6483. *pszEndOfFunctionName = TEXT('\0');
  6484. lstrcpyn(NewItem.szFunctionName, pszTemp, CELEMS(NewItem.szFunctionName));
  6485. NewItem.pszParameters = CmStrCpyAlloc(pszParams);
  6486. }
  6487. else
  6488. {
  6489. lstrcpyn(NewItem.szFunctionName, pszTemp, CELEMS(NewItem.szFunctionName));
  6490. }
  6491. }
  6492. else
  6493. {
  6494. MYVERIFY (IDOK == ShowMessage(hDlg, IDS_DLLMUSTHAVEPARAM, MB_OK));
  6495. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  6496. return TRUE;
  6497. }
  6498. CmFree(pszTemp);
  6499. }
  6500. else
  6501. {
  6502. NewItem.pszParameters = pszTemp;
  6503. pszTemp = NULL;
  6504. }
  6505. }
  6506. else
  6507. {
  6508. NewItem.pszParameters = CmStrCpyAlloc(TEXT(""));
  6509. MYDBGASSERT(NewItem.pszParameters);
  6510. }
  6511. //
  6512. // Get the Text from the Description edit control
  6513. //
  6514. if (-1 == GetTextFromControl(hDlg, IDC_EDIT3, NewItem.szDescription, CELEMS(NewItem.szDescription), TRUE)) // bDisplayError == TRUE
  6515. {
  6516. SetFocus(GetDlgItem(hDlg, IDC_EDIT3));
  6517. return TRUE;
  6518. }
  6519. //
  6520. // If the description was empty, then fill it in from the program and the parameters. Also
  6521. // remember to keep track of the fact that this is only a temporary description.
  6522. //
  6523. if (TEXT('\0') == NewItem.szDescription[0])
  6524. {
  6525. hr = g_pCustomActionList->FillInTempDescription(&NewItem);
  6526. MYDBGASSERT(SUCCEEDED(hr));
  6527. }
  6528. //
  6529. // Figure out the type of custom action
  6530. //
  6531. hr = MapComboSelectionToType(hDlg, IDC_COMBO1, FALSE, g_bUseTunneling, &(NewItem.Type)); // bIncludesAll == FALSE
  6532. if ((ONINTCONNECT == NewItem.Type) && NewItem.szFunctionName[0])
  6533. {
  6534. MYVERIFY (IDOK == ShowMessage(hDlg, IDS_NODLLAUTOAPP, MB_OK));
  6535. return TRUE;
  6536. }
  6537. //
  6538. // Now build the flags section
  6539. //
  6540. lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_GETCURSEL, 0, (LPARAM)0);
  6541. if (lResult != LB_ERR)
  6542. {
  6543. hr = g_pCustomActionList->MapIndexToFlags((int)lResult, &(NewItem.dwFlags));
  6544. if (FAILED(hr))
  6545. {
  6546. MYDBGASSERT(FALSE);
  6547. NewItem.dwFlags = 0;
  6548. }
  6549. }
  6550. else
  6551. {
  6552. MYDBGASSERT(FALSE);
  6553. NewItem.dwFlags = 0;
  6554. }
  6555. //
  6556. // Now, lets try to add the New or Edited entry. If we have a description
  6557. // in pItem->szDescription then we need to call edit, otherwise add.
  6558. //
  6559. if (pItem && pItem->szDescription[0])
  6560. {
  6561. hr = g_pCustomActionList->Edit(g_hInstance, pItem, &NewItem, g_szShortServiceName);
  6562. }
  6563. else
  6564. {
  6565. hr = g_pCustomActionList->Add(g_hInstance, &NewItem, g_szShortServiceName);
  6566. }
  6567. //
  6568. // Check to see if we failed because a duplicate exists
  6569. //
  6570. if (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)
  6571. {
  6572. //
  6573. // The user has tried to add an entry which already exists. Inform the
  6574. // user and see if they want to overwrite.
  6575. //
  6576. pszTypeString = NULL;
  6577. hr = g_pCustomActionList->GetTypeStringFromType(g_hInstance, NewItem.Type, &pszTypeString);
  6578. MYDBGASSERT(pszTypeString);
  6579. if (pszTypeString)
  6580. {
  6581. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_CANAMEEXISTS, NewItem.szDescription, pszTypeString);
  6582. MYDBGASSERT(pszMsg);
  6583. if (pszMsg)
  6584. {
  6585. iTemp = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION);
  6586. if (IDYES == iTemp)
  6587. {
  6588. //
  6589. // Okay, they want to replace it. Note that the old item is only
  6590. // used to get the szDescription and the Type thus
  6591. // it is safe to call Edit with NewItem as both Old and New.
  6592. //
  6593. if (pItem && pItem->szDescription[0])
  6594. {
  6595. hr = g_pCustomActionList->Delete (g_hInstance, pItem->szDescription, pItem->Type);
  6596. MYDBGASSERT(SUCCEEDED(hr));
  6597. }
  6598. hr = g_pCustomActionList->Edit(g_hInstance, &NewItem, &NewItem, g_szShortServiceName);
  6599. MYDBGASSERT(SUCCEEDED(hr));
  6600. if (SUCCEEDED(hr))
  6601. {
  6602. MYVERIFY(0 != EndDialog(hDlg, IDOK));
  6603. if (pItem)
  6604. {
  6605. //
  6606. // Make sure the type and description are up to date in pItem if we have one
  6607. //
  6608. lstrcpyn(pItem->szDescription, NewItem.szDescription, CELEMS(pItem->szDescription));
  6609. pItem->Type = NewItem.Type;
  6610. }
  6611. }
  6612. }
  6613. else
  6614. {
  6615. //
  6616. // Let's put the user back to the description field if it has text in it, otherwise
  6617. // we want to put the user in the program field.
  6618. //
  6619. LRESULT lTextLen = SendDlgItemMessage(hDlg, IDC_EDIT3, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
  6620. SetFocus(GetDlgItem(hDlg, lTextLen ? IDC_EDIT3 : IDC_EDIT1));
  6621. }
  6622. CmFree(pszMsg);
  6623. }
  6624. CmFree(pszTypeString);
  6625. }
  6626. }
  6627. else if (FAILED(hr))
  6628. {
  6629. CMASSERTMSG(FALSE, TEXT("ProcessCustomActionPopUp -- unknown failure when trying to add or edit a connect action."));
  6630. }
  6631. else
  6632. {
  6633. if (pItem)
  6634. {
  6635. //
  6636. // Make sure the type and description are up to date in pItem if we have one
  6637. //
  6638. lstrcpyn(pItem->szDescription, NewItem.szDescription, CELEMS(pItem->szDescription));
  6639. pItem->Type = NewItem.Type;
  6640. }
  6641. MYVERIFY(0 != EndDialog(hDlg, IDOK));
  6642. }
  6643. CmFree(NewItem.pszParameters);
  6644. NewItem.pszParameters = NULL;
  6645. return (TRUE);
  6646. case IDCANCEL:
  6647. MYVERIFY(0 != EndDialog(hDlg, IDCANCEL));
  6648. return (TRUE);
  6649. default:
  6650. break;
  6651. }
  6652. break;
  6653. default:
  6654. return FALSE;
  6655. }
  6656. return FALSE;
  6657. }
  6658. // Read files under the [Extra Files] section in the .inf
  6659. static void ReadExtraList()
  6660. {
  6661. TCHAR szTemp[MAX_PATH+1];
  6662. TCHAR szTemp2[MAX_PATH+1];
  6663. TCHAR szNum[MAX_PATH+1];
  6664. ExtraData TmpExtraData;
  6665. int ConnectCnt = 0;
  6666. HANDLE hInf;
  6667. _itot(ConnectCnt,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6668. //
  6669. // The following call to GetPrivateProfileString could return an empty string
  6670. // so we don't want to use the MYVERIFY macro on it.
  6671. //
  6672. ZeroMemory(szTemp, sizeof(szTemp));
  6673. GetPrivateProfileString(c_pszExtraFiles, szNum, TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile); //lint !e534
  6674. while (*szTemp)
  6675. {
  6676. _tcscpy(TmpExtraData.szPathname, szTemp);
  6677. GetFileName(TmpExtraData.szPathname, TmpExtraData.szName);
  6678. MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2, TEXT("%s\\%s"), g_szOutdir, TmpExtraData.szName));
  6679. hInf = CreateFile(szTemp2,GENERIC_READ,0,NULL,OPEN_EXISTING,
  6680. FILE_ATTRIBUTE_NORMAL,NULL);
  6681. if (hInf != INVALID_HANDLE_VALUE)
  6682. {
  6683. _tcscpy(TmpExtraData.szPathname,szTemp2);
  6684. MYVERIFY(0 != CloseHandle(hInf));
  6685. }
  6686. MYVERIFY(FALSE != createListBxRecord(&g_pHeadExtra,&g_pTailExtra,(void *)&TmpExtraData,sizeof(TmpExtraData),TmpExtraData.szName));
  6687. ++ConnectCnt;
  6688. _itot(ConnectCnt,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6689. //
  6690. // The following call to GetPrivateProfileString could return an empty string
  6691. // so we don't want to use the MYVERIFY macro on it.
  6692. //
  6693. ZeroMemory(szTemp, sizeof(szTemp));
  6694. GetPrivateProfileString(c_pszExtraFiles, szNum, TEXT(""), szTemp, CELEMS(szTemp), g_szInfFile); //lint !e534
  6695. }
  6696. }
  6697. //+----------------------------------------------------------------------------
  6698. //
  6699. // Function: ReadMergeList
  6700. //
  6701. // Synopsis: This function reads entries from the [Merge Profiles] section of the inf file.
  6702. // Any entries found are added to the g_pHeadMerge Linked list.
  6703. //
  6704. // Arguments: None
  6705. //
  6706. // Returns: Nothing
  6707. //
  6708. // History: Quintinb Created Header and restructured to use dwNumChars 1/7/98
  6709. //
  6710. //+----------------------------------------------------------------------------
  6711. static void ReadMergeList()
  6712. {
  6713. TCHAR szTemp[MAX_PATH+1];
  6714. TCHAR szNum[MAX_PATH+1];
  6715. int filenum = 0;
  6716. DWORD dwNumChars;
  6717. //
  6718. // Convert the number zero to the string "0"
  6719. //
  6720. _itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6721. //
  6722. // Try to get a merged profile entry from the INF
  6723. //
  6724. dwNumChars = GetPrivateProfileString(c_pszMergeProfiles, szNum,TEXT(""), szTemp,
  6725. CELEMS(szTemp), g_szInfFile);
  6726. while ((dwNumChars > 0) && (TEXT('\0') != szTemp[0]))
  6727. {
  6728. //
  6729. // If we are in this loop then we have a profile entry
  6730. //
  6731. MYVERIFY(FALSE != createListBxRecord(&g_pHeadMerge,&g_pTailMerge,(void *)NULL,0,szTemp));
  6732. //
  6733. // Increment the filenumber to look for the next entry
  6734. //
  6735. ++filenum;
  6736. //
  6737. // Convert the filenumber to a string
  6738. //
  6739. _itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6740. //
  6741. // Try to read in the next merge entry
  6742. //
  6743. dwNumChars = GetPrivateProfileString(c_pszMergeProfiles, szNum, TEXT(""), szTemp,
  6744. CELEMS(szTemp), g_szInfFile);
  6745. }
  6746. }
  6747. static void WriteExtraList()
  6748. {
  6749. ExtraData * pExtraData;
  6750. ListBxList * LoopPtr;
  6751. TCHAR szNum[MAX_PATH+1];
  6752. TCHAR szName[MAX_PATH+1];
  6753. int filenum = 0;
  6754. MYVERIFY(0 != WritePrivateProfileSection(c_pszExtraFiles, TEXT("\0\0"), g_szInfFile));
  6755. if (g_pHeadExtra == NULL)
  6756. {
  6757. return;
  6758. }
  6759. LoopPtr = g_pHeadExtra;
  6760. // WRITE IN ALL ENTRIES
  6761. while( LoopPtr != NULL)
  6762. {
  6763. pExtraData = (ExtraData *)LoopPtr->ListBxData;
  6764. {
  6765. _itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6766. GetFileName(pExtraData->szPathname,szName);
  6767. MYVERIFY(0 != WritePrivateProfileString(c_pszExtraFiles, szNum, szName, g_szInfFile));
  6768. filenum = filenum+1;
  6769. }
  6770. LoopPtr = LoopPtr->next;
  6771. }
  6772. //
  6773. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  6774. // (win95 only). This call will return 0.
  6775. //
  6776. WritePrivateProfileString(NULL, NULL, NULL, g_szInfFile); //lint !e534 this call will always return 0
  6777. }
  6778. static void WriteMergeList()
  6779. {
  6780. ListBxList * LoopPtr;
  6781. TCHAR szNum[MAX_PATH+1];
  6782. int filenum = 0;
  6783. MYVERIFY(0 != WritePrivateProfileSection(c_pszMergeProfiles,TEXT("\0\0"),g_szInfFile));
  6784. if (g_pHeadMerge == NULL)
  6785. {
  6786. return;
  6787. }
  6788. LoopPtr = g_pHeadMerge;
  6789. // WRITE IN ALL ENTRIES
  6790. while( LoopPtr != NULL)
  6791. {
  6792. _itot(filenum,szNum,10); //lint !e534 itoa doesn't return anything useful for error handling
  6793. MYVERIFY(0 != WritePrivateProfileString(c_pszMergeProfiles, szNum,LoopPtr->szName, g_szInfFile));
  6794. filenum = filenum+1;
  6795. LoopPtr = LoopPtr->next;
  6796. }
  6797. //
  6798. // By calling WritePrivateProfileString with all NULL's we flush the file cache (win95 only). This call will
  6799. // return 0.
  6800. //
  6801. WritePrivateProfileString(NULL, NULL, NULL, g_szInfFile); //lint !e534 this call will always return 0.
  6802. }
  6803. //+----------------------------------------------------------------------------
  6804. //
  6805. // Function: IsFile8dot3
  6806. //
  6807. // Synopsis: Returns TRUE if the filename is in the 8.3 dos filename format
  6808. //
  6809. // Arguments: LPTSTR pszFileName - just the filename of the file to be checked (no path)
  6810. //
  6811. // Returns: BOOL - TRUE or FALSE if the file is 8.3
  6812. //
  6813. // History: quintinb created 11/26/97
  6814. //
  6815. //+----------------------------------------------------------------------------
  6816. BOOL IsFile8dot3(LPTSTR pszFileName)
  6817. {
  6818. TCHAR szTemp[MAX_PATH+1];
  6819. TCHAR * pszPtr;
  6820. if (!pszFileName)
  6821. {
  6822. return FALSE;
  6823. }
  6824. if (TEXT('\0') == pszFileName[0])
  6825. {
  6826. return TRUE;
  6827. }
  6828. _tcscpy(szTemp, pszFileName);
  6829. pszPtr = _tcsrchr(szTemp, TEXT('.'));
  6830. //
  6831. // If there is an extension check the length
  6832. //
  6833. if (pszPtr)
  6834. {
  6835. if (_tcslen(pszPtr) > 4)
  6836. {
  6837. return FALSE;
  6838. }
  6839. //
  6840. // Extension is ok check name part
  6841. //
  6842. *pszPtr = 0;
  6843. }
  6844. if (_tcslen(szTemp) > 8)
  6845. {
  6846. return FALSE;
  6847. }
  6848. return TRUE;
  6849. }
  6850. //+----------------------------------------------------------------------------
  6851. //
  6852. // Function: ProcessCustomActions
  6853. //
  6854. // Synopsis: Processes windows messages for the page in CMAK that allows users
  6855. // to manipulate custom actions (add, edit, delete, move, etc.)
  6856. //
  6857. // Arguments: WND hDlg - dialog window handle
  6858. // UINT message - message identifier
  6859. // WPARAM wParam - wParam Value
  6860. // LPARAM lParam - lParam Value
  6861. //
  6862. //
  6863. // History: quintinb Created 02/25/00
  6864. //
  6865. //+----------------------------------------------------------------------------
  6866. INT_PTR APIENTRY ProcessCustomActions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  6867. {
  6868. TCHAR szTemp[MAX_PATH+1];
  6869. INT_PTR nResult;
  6870. int iTemp;
  6871. HRESULT hr;
  6872. static HWND hListView;
  6873. NMHDR* pnmHeader = (NMHDR*)lParam;
  6874. LPNMLISTVIEW pNMListView;
  6875. ProcessBold(hDlg,message);
  6876. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CONNECT)) return TRUE;
  6877. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  6878. SetDefaultGUIFont(hDlg,message,IDC_LISTVIEW);
  6879. SetDefaultGUIFont(hDlg,message,IDC_COMBO1);
  6880. switch (message)
  6881. {
  6882. case WM_INITDIALOG:
  6883. {
  6884. if (NULL == g_pCustomActionList)
  6885. {
  6886. g_pCustomActionList = new CustomActionList;
  6887. MYDBGASSERT(g_pCustomActionList);
  6888. if (NULL == g_pCustomActionList)
  6889. {
  6890. return FALSE;
  6891. }
  6892. //
  6893. // Read in the custom actions from the Cms File
  6894. //
  6895. hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
  6896. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Loading custom actions failed."));
  6897. }
  6898. //
  6899. // Cache the List View window handle
  6900. //
  6901. hListView = GetDlgItem(hDlg, IDC_LISTVIEW);
  6902. //
  6903. // Load the arrow images for the move up and move down buttons
  6904. //
  6905. HICON hUpArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_UP_ARROW), IMAGE_ICON, 0, 0, 0);
  6906. HICON hDownArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DOWN_ARROW), IMAGE_ICON, 0, 0, 0);
  6907. //
  6908. // Set the arrow button bit maps
  6909. //
  6910. SendMessage(GetDlgItem(hDlg, IDC_BUTTON4), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hUpArrow);
  6911. SendMessage(GetDlgItem(hDlg, IDC_BUTTON5), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDownArrow);
  6912. //
  6913. // Set the Column headings
  6914. //
  6915. AddListViewColumnHeadings(g_hInstance, hListView);
  6916. break;
  6917. }
  6918. case WM_COMMAND:
  6919. switch (LOWORD(wParam))
  6920. {
  6921. case IDC_BUTTON1: //add
  6922. OnProcessCustomActionsAdd(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6923. break;
  6924. case IDC_BUTTON2: //edit
  6925. OnProcessCustomActionsEdit(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6926. break;
  6927. case IDC_BUTTON3: //delete
  6928. OnProcessCustomActionsDelete(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6929. break;
  6930. case IDC_BUTTON4: //UP
  6931. OnProcessCustomActionsMoveUp(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6932. break;
  6933. case IDC_BUTTON5: //down
  6934. OnProcessCustomActionsMoveDown(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6935. break;
  6936. case IDC_COMBO1: // type of connect action to display
  6937. if (HIWORD(wParam) == CBN_SELCHANGE)
  6938. {
  6939. UINT uStringId;
  6940. CustomActionTypes Type;
  6941. hr = MapComboSelectionToType(hDlg, IDC_COMBO1, TRUE, g_bUseTunneling, &Type); // TRUE == bIncludesAll
  6942. MYDBGASSERT(SUCCEEDED(hr));
  6943. if (SUCCEEDED(hr))
  6944. {
  6945. if (ALL == Type)
  6946. {
  6947. uStringId = IDS_TYPE_COL_TITLE;
  6948. }
  6949. else
  6950. {
  6951. uStringId = IDS_PROGRAM_COL_TITLE;
  6952. }
  6953. UpdateListViewColumnHeadings(g_hInstance, hListView, uStringId, 1); // 1 == second column
  6954. RefreshListView(g_hInstance, hDlg, IDC_COMBO1, hListView, 0, g_bUseTunneling);
  6955. }
  6956. }
  6957. break;
  6958. default:
  6959. break;
  6960. }
  6961. break;
  6962. case WM_NOTIFY:
  6963. if (NULL == pnmHeader)
  6964. {
  6965. return FALSE;
  6966. }
  6967. switch (pnmHeader->code)
  6968. {
  6969. case LVN_ITEMCHANGED:
  6970. //
  6971. // We want to process item changed messages for when the selection changes. This
  6972. // way when the user selects an item in the list (either using the arrow keys or
  6973. // the mouse) we will accurately update the arrow keys. In order to cut down on the
  6974. // number of calls we filter out the unselected messages.
  6975. //
  6976. pNMListView = (LPNMLISTVIEW) lParam;
  6977. if ((LVIF_STATE & pNMListView->uChanged) && (LVIS_SELECTED & pNMListView->uNewState))
  6978. {
  6979. int iTempItem = pNMListView->iItem;
  6980. RefreshEditDeleteMoveButtonStates(g_hInstance, hDlg, hListView, IDC_COMBO1, &iTempItem, g_bUseTunneling);
  6981. }
  6982. break;
  6983. case NM_DBLCLK:
  6984. case NM_RETURN:
  6985. if (ListView_GetItemCount(hListView))
  6986. {
  6987. OnProcessCustomActionsEdit(g_hInstance, hDlg, hListView, g_bUseTunneling);
  6988. }
  6989. break;
  6990. case LVN_KEYDOWN:
  6991. {
  6992. //
  6993. // User hit the right click key or typed Shift+F10
  6994. //
  6995. NMLVKEYDOWN* pKeyDown = (NMLVKEYDOWN*)lParam;
  6996. if (((VK_F10 == pKeyDown->wVKey) && (0 > GetKeyState(VK_SHIFT))) || (VK_APPS == pKeyDown->wVKey))
  6997. {
  6998. //
  6999. // Figure out what item is currently selected and gets its position
  7000. //
  7001. iTemp = ListView_GetSelectionMark(hListView);
  7002. NMITEMACTIVATE ItemActivate = {0};
  7003. if (-1 != iTemp)
  7004. {
  7005. POINT ptPoint = {0};
  7006. if (ListView_GetItemPosition(hListView, iTemp, &ptPoint))
  7007. {
  7008. RECT ItemRect;
  7009. if (ListView_GetItemRect(hListView, iTemp, &ItemRect, LVIR_LABEL))
  7010. {
  7011. LONG lIndent = (ItemRect.bottom - ItemRect.top) / 2;
  7012. ItemActivate.ptAction.x = ptPoint.x + lIndent;
  7013. ItemActivate.ptAction.y = ptPoint.y + lIndent;
  7014. ItemActivate.iItem = iTemp;
  7015. OnProcessCustomActionsContextMenu(g_hInstance, hDlg, hListView, &ItemActivate, g_bUseTunneling, IDC_COMBO1);
  7016. }
  7017. }
  7018. }
  7019. }
  7020. }
  7021. break;
  7022. case NM_RCLICK:
  7023. OnProcessCustomActionsContextMenu(g_hInstance, hDlg, hListView, (NMITEMACTIVATE*)lParam, g_bUseTunneling, IDC_COMBO1);
  7024. break;
  7025. case PSN_SETACTIVE:
  7026. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  7027. //
  7028. // Make sure we have a custom action class to work with
  7029. //
  7030. if (NULL == g_pCustomActionList)
  7031. {
  7032. g_pCustomActionList = new CustomActionList;
  7033. MYDBGASSERT(g_pCustomActionList);
  7034. if (NULL == g_pCustomActionList)
  7035. {
  7036. return FALSE;
  7037. }
  7038. //
  7039. // Read in the custom actions from the Cms File
  7040. //
  7041. hr = g_pCustomActionList->ReadCustomActionsFromCms(g_hInstance, g_szCmsFile, g_szShortServiceName);
  7042. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Loading custom actions failed."));
  7043. }
  7044. //
  7045. // Setup the ListView control and the corresponding Combo box, note that we set bAddAll to TRUE so
  7046. // that the All option is added.
  7047. //
  7048. hr = g_pCustomActionList->AddCustomActionTypesToComboBox(hDlg, IDC_COMBO1, g_hInstance, g_bUseTunneling, TRUE);
  7049. nResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  7050. if ((CB_ERR != nResult) && (nResult > 0))
  7051. {
  7052. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)0, (LPARAM)0));
  7053. }
  7054. //
  7055. // Add built in custom actions
  7056. //
  7057. { // adding scope
  7058. BOOL bAddCmdlForVpn = FALSE;
  7059. if (g_szVpnFile[0])
  7060. {
  7061. //
  7062. // We have a VPN file so let's check and see if they defined an UpdateUrl
  7063. //
  7064. GetPrivateProfileString(c_pszCmSectionSettings, c_pszCmEntryVpnUpdateUrl, TEXT(""), szTemp, MAX_PATH, g_szVpnFile);
  7065. if (szTemp[0])
  7066. {
  7067. bAddCmdlForVpn = TRUE;
  7068. }
  7069. }
  7070. hr = g_pCustomActionList->AddOrRemoveCmdl(g_hInstance, bAddCmdlForVpn, TRUE); // TRUE == bForVpn
  7071. MYDBGASSERT(SUCCEEDED(hr));
  7072. hr = g_pCustomActionList->AddOrRemoveCmdl(g_hInstance, (g_bUpdatePhonebook || ReferencedDownLoad()), FALSE); // FALSE == bForVpn
  7073. MYDBGASSERT(SUCCEEDED(hr));
  7074. }
  7075. //
  7076. // Add the items to the list view control
  7077. //
  7078. RefreshListView(g_hInstance, hDlg, IDC_COMBO1, hListView, 0, g_bUseTunneling);
  7079. break;
  7080. case PSN_WIZBACK:
  7081. case PSN_WIZNEXT:
  7082. //
  7083. // Set bUseTunneling == TRUE even though we may not be tunneling. The reason for this is that
  7084. // the user may have had a tunneling profile and then turned off tunneling. If they turn
  7085. // it back on again we don't want to lose all of their Pre-Tunnel actions nor do we want to
  7086. // lose all of the flag settings that they have added to each action. We will make sure
  7087. // to use the actual g_bUseTunneling value when we write the actions to the cms file in
  7088. // WriteCMSFile.
  7089. //
  7090. MYDBGASSERT(g_pCustomActionList);
  7091. if (g_pCustomActionList)
  7092. {
  7093. hr = g_pCustomActionList->WriteCustomActionsToCms(g_szCmsFile, g_szShortServiceName, TRUE);
  7094. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Failed to write out connect actions"));
  7095. }
  7096. break;
  7097. default:
  7098. return FALSE;
  7099. }
  7100. break;
  7101. default:
  7102. return FALSE;
  7103. }
  7104. return TRUE;
  7105. }
  7106. //+----------------------------------------------------------------------------
  7107. //
  7108. // Function: ProcessStatusMenuPopup
  7109. //
  7110. // Synopsis: Processes Messages for the Popup dialog for Adding/Editing Status
  7111. // Area Icon Menu items
  7112. //
  7113. // History: quintinb Created Header and renamed from ProcessPage2G1 8/6/98
  7114. //
  7115. //+----------------------------------------------------------------------------
  7116. // USES GLOBAL VARIABLE DLGEDITITEM as input and output to the page
  7117. // You must sent DlgEditItem to the initial value of this page.
  7118. //
  7119. INT_PTR APIENTRY ProcessStatusMenuPopup(
  7120. HWND hDlg,
  7121. UINT message,
  7122. WPARAM wParam,
  7123. LPARAM lParam)
  7124. {
  7125. TCHAR szTemp[MAX_PATH+1];
  7126. TCHAR szMsg[MAX_PATH+1];
  7127. BOOL bChecked;
  7128. static TCHAR szOld[MAX_PATH+1];
  7129. IconMenu TempEditItem;
  7130. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  7131. SetDefaultGUIFont(hDlg,message,IDC_EDIT2);
  7132. SetDefaultGUIFont(hDlg,message,IDC_EDIT3);
  7133. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MENU)) return TRUE;
  7134. switch (message)
  7135. {
  7136. case WM_INITDIALOG:
  7137. //
  7138. // If we are editing we need to change the title
  7139. //
  7140. if (TEXT('\0') != DlgEditItem.szProgram[0])
  7141. {
  7142. LPTSTR pszTemp = CmLoadString(g_hInstance, IDS_EDIT_SHORTCUT_TITLE);
  7143. if (pszTemp)
  7144. {
  7145. MYVERIFY(SendMessage (hDlg, WM_SETTEXT, 0, (LPARAM)pszTemp));
  7146. CmFree(pszTemp);
  7147. }
  7148. }
  7149. _tcscpy (szOld, DlgEditItem.szName);
  7150. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)DlgEditItem.szName));
  7151. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)GetName(DlgEditItem.szProgram)));
  7152. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT3), WM_SETTEXT, 0, (LPARAM)DlgEditItem.szParams));
  7153. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, (UINT)DlgEditItem.bDoCopy));
  7154. break;
  7155. case WM_COMMAND:
  7156. switch (LOWORD(wParam))
  7157. {
  7158. case IDC_BUTTON1:
  7159. {
  7160. UINT uFilter = IDS_PROGFILTER;
  7161. TCHAR* szMask = TEXT("*.exe;*.com;*.bat");
  7162. int iReturn = DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDIT2, TEXT("exe"), DlgEditItem.szProgram);
  7163. MYDBGASSERT(0 != iReturn);
  7164. if (iReturn && (-1 != iReturn))
  7165. {
  7166. //
  7167. // Check the include binary button for the user
  7168. //
  7169. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
  7170. }
  7171. }
  7172. break;
  7173. case IDOK:
  7174. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, DlgEditItem.szName, MAX_PATH, TRUE)) // bDisplayError == TRUE
  7175. {
  7176. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  7177. return TRUE;
  7178. }
  7179. if (-1 == GetTextFromControl(hDlg, IDC_EDIT2, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  7180. {
  7181. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  7182. return TRUE;
  7183. }
  7184. if (szTemp[0] == TEXT('\0'))
  7185. {
  7186. MYVERIFY(IDOK == ShowMessage(hDlg,IDS_NEEDPROG,MB_OK));
  7187. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  7188. return TRUE;
  7189. }
  7190. CheckNameChange(DlgEditItem.szProgram,szTemp);
  7191. if (NULL != _tcschr(DlgEditItem.szProgram, TEXT('=')))
  7192. {
  7193. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOEQUALSINMENU, MB_OK));
  7194. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  7195. return TRUE;
  7196. }
  7197. if (-1 == GetTextFromControl(hDlg, IDC_EDIT3, DlgEditItem.szParams, MAX_PATH, TRUE)) // bDisplayError == TRUE
  7198. {
  7199. SetFocus(GetDlgItem(hDlg, IDC_EDIT3));
  7200. return TRUE;
  7201. }
  7202. if (DlgEditItem.szName[0] == TEXT('\0'))
  7203. {
  7204. GetFileName(DlgEditItem.szProgram,DlgEditItem.szName);
  7205. }
  7206. if (_tcschr(DlgEditItem.szName, TEXT('=')))
  7207. {
  7208. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOEQUALSINMENU, MB_OK));
  7209. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  7210. return TRUE;
  7211. }
  7212. bChecked = IsDlgButtonChecked(hDlg,IDC_CHECK1);
  7213. if (bChecked)
  7214. {
  7215. if (!VerifyFile(hDlg,IDC_EDIT2,DlgEditItem.szProgram,TRUE))
  7216. {
  7217. DlgEditItem.bDoCopy = FALSE;
  7218. return TRUE;
  7219. }
  7220. else
  7221. {
  7222. DlgEditItem.bDoCopy = TRUE;
  7223. }
  7224. }
  7225. else
  7226. {
  7227. DlgEditItem.bDoCopy = FALSE;
  7228. }
  7229. if ((0 != _tcscmp(szOld, DlgEditItem.szName)) &&
  7230. (GetIconMenuItem(DlgEditItem.szName, &TempEditItem)))
  7231. {
  7232. //
  7233. // We have a duplicate entry, prompt the user to replace or try
  7234. // again.
  7235. //
  7236. MYVERIFY(0 != LoadString(g_hInstance, IDS_MENUITEMEXISTS, szTemp, MAX_PATH));
  7237. //
  7238. // write the previously used name in the string
  7239. //
  7240. wsprintf(szMsg, szTemp, DlgEditItem.szName);
  7241. //
  7242. // If the user doesn't want to replace the duplicate item then we should set the focus to the description
  7243. // edit control if it has text in it, otherwise we should set it to the program edit control.
  7244. //
  7245. if (IDNO == MessageBox(hDlg, szMsg, g_szAppTitle, MB_YESNO | MB_APPLMODAL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION))
  7246. {
  7247. LRESULT lTextLen = SendDlgItemMessage(hDlg, IDC_EDIT1, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
  7248. SetFocus(GetDlgItem(hDlg, lTextLen ? IDC_EDIT1 : IDC_EDIT2));
  7249. return TRUE;
  7250. }
  7251. }
  7252. MYVERIFY(0 != EndDialog(hDlg,IDOK));
  7253. return (TRUE);
  7254. case IDCANCEL:
  7255. MYVERIFY(0 != EndDialog(hDlg,IDCANCEL));
  7256. return (TRUE);
  7257. default:
  7258. break;
  7259. }
  7260. break;
  7261. default:
  7262. return FALSE;
  7263. }
  7264. return FALSE;
  7265. } //lint !e715 we don't reference lParam
  7266. BOOL createListBxRecord(ListBxList ** HeadPtrListBx, ListBxList ** TailPtrListBx, void * pData, DWORD dwSize, LPCTSTR lpName)
  7267. {
  7268. ListBxList * ptr;
  7269. void * dataptr;
  7270. unsigned int n;
  7271. // check for same named record and update
  7272. if ( *HeadPtrListBx != NULL )
  7273. {
  7274. ptr = *HeadPtrListBx;
  7275. while (ptr != NULL)
  7276. {
  7277. if (_tcsicmp(lpName, ptr->szName) == 0)
  7278. {
  7279. memcpy(ptr->ListBxData,pData,dwSize);
  7280. return (TRUE);
  7281. }
  7282. ptr = ptr->next;
  7283. }
  7284. }
  7285. n = sizeof( struct ListBxStruct );
  7286. ptr = (ListBxList *) CmMalloc(n);
  7287. if (ptr == NULL )
  7288. {
  7289. return FALSE;
  7290. }
  7291. _tcscpy(ptr->szName, lpName);
  7292. if (pData)
  7293. {
  7294. dataptr = CmMalloc(dwSize);
  7295. if (dataptr)
  7296. {
  7297. memcpy(dataptr, pData, dwSize);
  7298. ptr->ListBxData = dataptr;
  7299. }
  7300. else
  7301. {
  7302. CmFree(ptr);
  7303. return FALSE;
  7304. }
  7305. }
  7306. ptr->next = NULL;
  7307. if ( *HeadPtrListBx == NULL ) // If this is the first record in the linked list
  7308. {
  7309. *HeadPtrListBx = ptr;
  7310. }
  7311. else
  7312. {
  7313. (*TailPtrListBx)->next = ptr;
  7314. }
  7315. *TailPtrListBx = ptr;
  7316. return TRUE;
  7317. }
  7318. // delete named IconMenu item from linked list
  7319. void DeleteListBxRecord(ListBxList ** HeadPtrListBx,ListBxList ** TailPtrListBx, LPTSTR lpName)
  7320. {
  7321. ListBxList * ptr;
  7322. ListBxList * prevptr;
  7323. if ( HeadPtrListBx != NULL )
  7324. {
  7325. ptr = *HeadPtrListBx;
  7326. prevptr = NULL;
  7327. while (ptr != NULL)
  7328. {
  7329. if (_tcsicmp(lpName,ptr->szName) == 0)
  7330. {
  7331. if (prevptr == NULL)
  7332. {
  7333. *HeadPtrListBx = ptr->next;
  7334. if (*HeadPtrListBx == NULL)
  7335. {
  7336. *TailPtrListBx = NULL;
  7337. }
  7338. else
  7339. {
  7340. if ((*HeadPtrListBx)->next == NULL)
  7341. {
  7342. *TailPtrListBx = *HeadPtrListBx;
  7343. }
  7344. }
  7345. }
  7346. else
  7347. {
  7348. prevptr->next = ptr->next;
  7349. if (prevptr->next == NULL)
  7350. {
  7351. *TailPtrListBx = prevptr;
  7352. }
  7353. }
  7354. CmFree(ptr->ListBxData);
  7355. CmFree(ptr);
  7356. return;
  7357. }
  7358. prevptr = ptr;
  7359. ptr = ptr->next;
  7360. }
  7361. }
  7362. }
  7363. BOOL FindListItemByName(LPTSTR pszName, ListBxList* pHeadOfList, ListBxList** pFoundItem)
  7364. {
  7365. if (NULL == pszName)
  7366. {
  7367. CMASSERTMSG(FALSE, TEXT("FindListItemByName -- Invalid parameter"));
  7368. return FALSE;
  7369. }
  7370. if (NULL != pHeadOfList)
  7371. {
  7372. ListBxList * pCurrent = pHeadOfList;
  7373. while (NULL != pCurrent)
  7374. {
  7375. if (0 == lstrcmpi(pszName, pCurrent->szName))
  7376. {
  7377. //
  7378. // Return the pointer to pCurrent if the caller asked for it
  7379. //
  7380. if (pFoundItem)
  7381. {
  7382. *pFoundItem = pCurrent;
  7383. }
  7384. return TRUE;
  7385. }
  7386. pCurrent = pCurrent->next;
  7387. }
  7388. }
  7389. return FALSE;
  7390. }
  7391. //+----------------------------------------------------------------------------
  7392. //
  7393. // Function: updateRecord
  7394. //
  7395. // Synopsis: Function updates an entry in the list of tray icon data structures
  7396. // thus the entry is not added and then deleted when the user edits an
  7397. // entry. This takes away the putting the entry at the bottom of the list
  7398. // problem cited in the bug.
  7399. //
  7400. // Arguments: PTSTR szName - New name of the entry
  7401. // LPTSTR szProgram - Program string to add to the Tray Icon Entry
  7402. // LPTSTR szParams - Parameter string to add to the Tray Icon Entry
  7403. // BOOL bDoCopy - Value of whether this program should be included with the profile data item
  7404. // LPTSTR szOld - Name of the entry to update
  7405. //
  7406. // Returns: BOOL - TRUE if able to update the record
  7407. // FALSE if not able to find it
  7408. //
  7409. // Side Effects: Replaces the entry named by szOld with the entry data and name for
  7410. // entry called szName.
  7411. // History: quintinb Created for bugfix 14399 9-9-97
  7412. //
  7413. //+----------------------------------------------------------------------------
  7414. static BOOL updateRecord(LPTSTR szName, LPTSTR szProgram, LPTSTR szParams, BOOL bDoCopy, LPTSTR szOld)
  7415. {
  7416. IconMenu * ptr;
  7417. // check for same named record and update
  7418. if ( g_pHeadIcon != NULL )
  7419. {
  7420. ptr = g_pHeadIcon;
  7421. while (ptr != NULL)
  7422. {
  7423. if (_tcsicmp(szOld,ptr->szName) == 0)
  7424. {
  7425. _tcscpy(ptr->szProgram,szProgram);
  7426. _tcscpy(ptr->szParams,szParams);
  7427. ptr->bDoCopy = bDoCopy;
  7428. _tcscpy(ptr->szName, szName);
  7429. return (TRUE);
  7430. }
  7431. ptr = ptr->next;
  7432. }
  7433. }
  7434. return (FALSE);
  7435. }
  7436. // note, as of bug 14399 updating should be done with the above function
  7437. BOOL createRecord(LPCTSTR szName, LPCTSTR szProgram, LPCTSTR szParams, BOOL bDoCopy)
  7438. {
  7439. IconMenu * ptr;
  7440. unsigned int n;
  7441. // check for same named record and update
  7442. if ( g_pHeadIcon != NULL )
  7443. {
  7444. ptr = g_pHeadIcon;
  7445. while (ptr != NULL)
  7446. {
  7447. if (_tcsicmp(szName,ptr->szName) == 0)
  7448. {
  7449. _tcscpy(ptr->szProgram,szProgram);
  7450. _tcscpy(ptr->szParams,szParams);
  7451. ptr->bDoCopy = bDoCopy;
  7452. return (TRUE);
  7453. }
  7454. ptr = ptr->next;
  7455. }
  7456. }
  7457. //
  7458. n = sizeof( struct IconMenuStruct );
  7459. ptr = (IconMenu *) CmMalloc(n);
  7460. if ( ptr == NULL )
  7461. {
  7462. return FALSE;
  7463. }
  7464. _tcscpy(ptr->szName,szName);
  7465. _tcscpy(ptr->szProgram,szProgram);
  7466. _tcscpy(ptr->szParams,szParams);
  7467. ptr->bDoCopy = bDoCopy;
  7468. ptr->next = NULL;
  7469. if ( g_pHeadIcon == NULL ) // If this is the first record in the linked list
  7470. {
  7471. g_pHeadIcon = ptr;
  7472. }
  7473. else
  7474. {
  7475. g_pTailIcon->next = ptr;
  7476. }
  7477. g_pTailIcon = ptr;
  7478. return TRUE;
  7479. }
  7480. // delete named IconMenu item from linked list
  7481. static void DeleteRecord(LPTSTR lpName)
  7482. {
  7483. IconMenu * ptr;
  7484. IconMenu * prevptr;
  7485. if ( g_pHeadIcon != NULL )
  7486. {
  7487. ptr = g_pHeadIcon;
  7488. prevptr = NULL;
  7489. while (ptr != NULL)
  7490. {
  7491. if (_tcsicmp(lpName,ptr->szName) == 0)
  7492. {
  7493. if (prevptr == NULL)
  7494. {
  7495. g_pHeadIcon = ptr->next;
  7496. if (g_pHeadIcon == NULL)
  7497. {
  7498. g_pTailIcon = NULL;
  7499. }
  7500. else
  7501. {
  7502. if (g_pHeadIcon->next == NULL)
  7503. {
  7504. g_pTailIcon = g_pHeadIcon;
  7505. }
  7506. }
  7507. }
  7508. else
  7509. {
  7510. prevptr->next = ptr->next;
  7511. if (prevptr->next == NULL)
  7512. {
  7513. g_pTailIcon = prevptr;
  7514. }
  7515. }
  7516. CmFree(ptr);
  7517. return;
  7518. }
  7519. prevptr = ptr;
  7520. ptr = ptr->next;
  7521. }
  7522. }
  7523. }
  7524. static BOOL MoveRecord(LPTSTR lpName, int direction)
  7525. {
  7526. IconMenu * ptr;
  7527. IconMenu * prevptr;
  7528. IconMenu * nextptr;
  7529. IconMenu TempIconMenu;
  7530. if ( g_pHeadIcon != NULL )
  7531. {
  7532. ptr = g_pHeadIcon;
  7533. prevptr = NULL;
  7534. while (ptr != NULL)
  7535. {
  7536. if (_tcsicmp(lpName,ptr->szName) == 0)
  7537. {
  7538. if (((direction > 0)&&(ptr->next == NULL))||
  7539. ((direction < 0)&&(prevptr == NULL)))
  7540. return FALSE;
  7541. if ((direction > 0)&&(ptr->next != NULL))
  7542. {
  7543. //swap contents with next element
  7544. nextptr = ptr->next;
  7545. _tcscpy(TempIconMenu.szName,ptr->szName);
  7546. _tcscpy(TempIconMenu.szProgram,ptr->szProgram);
  7547. _tcscpy(TempIconMenu.szParams,ptr->szParams);
  7548. TempIconMenu.bDoCopy = ptr->bDoCopy;
  7549. _tcscpy(ptr->szName,nextptr->szName);
  7550. _tcscpy(ptr->szProgram,nextptr->szProgram);
  7551. _tcscpy(ptr->szParams,nextptr->szParams);
  7552. ptr->bDoCopy = nextptr->bDoCopy;
  7553. _tcscpy(nextptr->szName,TempIconMenu.szName);
  7554. _tcscpy(nextptr->szProgram,TempIconMenu.szProgram);
  7555. _tcscpy(nextptr->szParams,TempIconMenu.szParams);
  7556. nextptr->bDoCopy = TempIconMenu.bDoCopy;
  7557. }
  7558. else
  7559. {
  7560. if ((direction < 0)&&(prevptr != NULL))
  7561. {
  7562. _tcscpy(TempIconMenu.szName,ptr->szName);
  7563. _tcscpy(TempIconMenu.szProgram,ptr->szProgram);
  7564. _tcscpy(TempIconMenu.szParams,ptr->szParams);
  7565. TempIconMenu.bDoCopy = ptr->bDoCopy;
  7566. _tcscpy(ptr->szName,prevptr->szName);
  7567. _tcscpy(ptr->szProgram,prevptr->szProgram);
  7568. _tcscpy(ptr->szParams,prevptr->szParams);
  7569. ptr->bDoCopy = prevptr->bDoCopy;
  7570. _tcscpy(prevptr->szName,TempIconMenu.szName);
  7571. _tcscpy(prevptr->szProgram,TempIconMenu.szProgram);
  7572. _tcscpy(prevptr->szParams,TempIconMenu.szParams);
  7573. prevptr->bDoCopy = TempIconMenu.bDoCopy;
  7574. }
  7575. }
  7576. return TRUE;
  7577. }
  7578. prevptr = ptr;
  7579. ptr = ptr->next;
  7580. }
  7581. }
  7582. return TRUE;
  7583. }
  7584. // retrieve named IconMenu item from linked list
  7585. BOOL GetIconMenuItem(LPTSTR lpName, IconMenu * EditItem)
  7586. {
  7587. IconMenu * ptr;
  7588. if ( g_pHeadIcon != NULL )
  7589. {
  7590. ptr = g_pHeadIcon;
  7591. while (ptr != NULL)
  7592. {
  7593. if (_tcsicmp(lpName,ptr->szName) == 0)
  7594. {
  7595. _tcscpy(EditItem->szName,ptr->szName);
  7596. _tcscpy(EditItem->szProgram,ptr->szProgram);
  7597. _tcscpy(EditItem->szParams,ptr->szParams);
  7598. EditItem->bDoCopy = ptr->bDoCopy;
  7599. return TRUE;
  7600. }
  7601. ptr = ptr->next;
  7602. }
  7603. }
  7604. return FALSE;
  7605. }
  7606. static BOOL WriteCopyMenuItemFiles(HANDLE hInf,LPTSTR pszFailFile, BOOL bWriteShortName)
  7607. {
  7608. IconMenu * ptr;
  7609. if (g_pHeadIcon != NULL)
  7610. {
  7611. ptr = g_pHeadIcon;
  7612. while (ptr != NULL)
  7613. {
  7614. if (ptr->bDoCopy)
  7615. {
  7616. if (!WriteCopy(hInf, ptr->szProgram, bWriteShortName))
  7617. {
  7618. _tcscpy(pszFailFile, ptr->szProgram);
  7619. return FALSE;
  7620. }
  7621. }
  7622. ptr = ptr->next;
  7623. }
  7624. }
  7625. return TRUE;
  7626. }
  7627. static BOOL WriteCopyConActFiles(HANDLE hInf, LPTSTR pszFailFile, BOOL bWriteShortName)
  7628. {
  7629. TCHAR szTemp[MAX_PATH+1];
  7630. HRESULT hr = E_INVALIDARG;
  7631. MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
  7632. MYDBGASSERT(pszFailFile);
  7633. MYDBGASSERT(g_pCustomActionList);
  7634. if ((INVALID_HANDLE_VALUE != hInf) && pszFailFile && g_pCustomActionList)
  7635. {
  7636. CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
  7637. do
  7638. {
  7639. hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
  7640. if (SUCCEEDED(hr) && (S_FALSE != hr))
  7641. {
  7642. if (!WriteCopy(hInf, szTemp, bWriteShortName))
  7643. {
  7644. _tcscpy(pszFailFile, szTemp);
  7645. hr = E_UNEXPECTED;
  7646. }
  7647. }
  7648. } while (SUCCEEDED(hr) && (S_FALSE != hr));
  7649. }
  7650. return SUCCEEDED(hr);
  7651. }
  7652. static BOOL WriteCopyExtraFiles(HANDLE hInf,LPTSTR pszFailFile, BOOL bWriteShortName)
  7653. {
  7654. ListBxList * ptr;
  7655. ExtraData * pExtraData;
  7656. if (g_pHeadExtra != NULL)
  7657. {
  7658. ptr = g_pHeadExtra;
  7659. while (ptr != NULL)
  7660. {
  7661. pExtraData = (ExtraData *)(ptr->ListBxData);
  7662. if (!WriteCopy(hInf, pExtraData->szPathname, bWriteShortName))
  7663. {
  7664. _tcscpy(pszFailFile, pExtraData->szPathname);
  7665. return FALSE;
  7666. }
  7667. ptr = ptr->next;
  7668. }
  7669. }
  7670. return TRUE;
  7671. }
  7672. static BOOL WriteCopyDnsFiles(HANDLE hInf, LPTSTR pszFailFile, BOOL bWriteShortName)
  7673. {
  7674. ListBxList * ptr;
  7675. CDunSetting* pDunSetting;
  7676. if (g_pHeadDunEntry != NULL)
  7677. {
  7678. ptr = g_pHeadDunEntry;
  7679. while (ptr != NULL)
  7680. {
  7681. pDunSetting = (CDunSetting*)(ptr->ListBxData);
  7682. if (!WriteCopy(hInf, pDunSetting->szScript, bWriteShortName))
  7683. {
  7684. _tcscpy(pszFailFile, pDunSetting->szScript);
  7685. return FALSE;
  7686. }
  7687. ptr = ptr->next;
  7688. }
  7689. }
  7690. return TRUE;
  7691. }
  7692. void WriteDelMenuItemFiles(HANDLE hInf)
  7693. {
  7694. IconMenu * ptr;
  7695. if ( g_pHeadIcon != NULL )
  7696. {
  7697. ptr = g_pHeadIcon;
  7698. while (ptr != NULL)
  7699. {
  7700. if (ptr->bDoCopy)
  7701. {
  7702. MYVERIFY(FALSE != WriteInfLine(hInf,ptr->szProgram));
  7703. }
  7704. ptr = ptr->next;
  7705. }
  7706. }
  7707. }
  7708. static BOOL WriteRefsFiles(HANDLE hInf,BOOL WriteCM)
  7709. {
  7710. ListBxList * ptr;
  7711. TCHAR szTemp[MAX_PATH+1];
  7712. if ( g_pHeadRefs != NULL )
  7713. {
  7714. ptr = g_pHeadRefs;
  7715. while (ptr != NULL)
  7716. {
  7717. if ((_tcsstr(ptr->szName,c_pszCmpExt) == NULL) && (!WriteCM))
  7718. {
  7719. MYVERIFY(FALSE != WriteInfLine(hInf,ptr->szName));
  7720. }
  7721. else
  7722. {
  7723. if ((_tcsstr(ptr->szName,c_pszCmpExt) != NULL) && (WriteCM))
  7724. {
  7725. _tcscpy(szTemp,ptr->szName);
  7726. _tcscat(szTemp, TEXT(",,,16")); // set to not overwrite existing file
  7727. MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
  7728. }
  7729. }
  7730. ptr = ptr->next;
  7731. }
  7732. }
  7733. return TRUE;
  7734. }
  7735. static BOOL WriteShortRefsFiles(HANDLE hInf,BOOL WriteCM)
  7736. {
  7737. ListBxList * ptr;
  7738. TCHAR szTemp[MAX_PATH+1];
  7739. TCHAR szShort[MAX_PATH + 1];
  7740. RenameData TmpRenameData;
  7741. TCHAR szCurrentDir[MAX_PATH+1];
  7742. if (g_pHeadRefs != NULL)
  7743. {
  7744. ptr = g_pHeadRefs;
  7745. // hack to fix short filename resolution
  7746. // change dir to cmaktemp dir and use getshortpathname
  7747. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH, szCurrentDir));
  7748. MYVERIFY(0 != SetCurrentDirectory(g_szTempDir));
  7749. while (ptr != NULL)
  7750. {
  7751. if ((_tcsstr(ptr->szName,c_pszCmpExt) == NULL) && (!WriteCM))
  7752. {
  7753. // writing non-cmp files so I want to make sure that I use
  7754. // the short file name if it is actually a long filename.
  7755. if (GetShortPathName(ptr->szName, szShort, MAX_PATH))
  7756. {
  7757. _tcscpy(szTemp, szShort);
  7758. if (_tcsicmp(szShort,ptr->szName) != 0)
  7759. {
  7760. _tcscpy(TmpRenameData.szShortName,szShort);
  7761. _tcscpy(TmpRenameData.szLongName,ptr->szName);
  7762. MYVERIFY(FALSE != createListBxRecord(&g_pHeadRename,&g_pTailRename,(void *)&TmpRenameData,sizeof(TmpRenameData),TmpRenameData.szShortName));
  7763. }
  7764. }
  7765. else
  7766. {
  7767. _tcscpy(szTemp, ptr->szName);
  7768. }
  7769. MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
  7770. }
  7771. else
  7772. {
  7773. if ((_tcsstr(ptr->szName,c_pszCmpExt) != NULL) && (WriteCM))
  7774. {
  7775. _tcscpy(szTemp,ptr->szName);
  7776. _tcscat(szTemp, TEXT(",,,16")); // set to not overwrite existing file
  7777. MYVERIFY(FALSE != WriteInfLine(hInf,szTemp));
  7778. }
  7779. }
  7780. ptr = ptr->next;
  7781. }
  7782. MYVERIFY(0 != SetCurrentDirectory(szCurrentDir));
  7783. }
  7784. return TRUE;
  7785. }
  7786. static BOOL WriteLongRefsFiles(HANDLE hInf)
  7787. {
  7788. ListBxList * ptr;
  7789. TCHAR szTemp[MAX_PATH+1];
  7790. TCHAR szShort[MAX_PATH + 1];
  7791. RenameData TmpRenameData;
  7792. TCHAR szCurrentDir[MAX_PATH+1];
  7793. if (g_pHeadRefs != NULL)
  7794. {
  7795. ptr = g_pHeadRefs;
  7796. while (ptr != NULL)
  7797. {
  7798. GetFileName(ptr->szName, szTemp);
  7799. MYVERIFY(FALSE != WriteInfLine(hInf, szTemp));
  7800. ptr = ptr->next;
  7801. }
  7802. }
  7803. return TRUE;
  7804. }
  7805. BOOL WriteDelConActFiles(HANDLE hInf)
  7806. {
  7807. TCHAR szTemp[MAX_PATH+1];
  7808. HRESULT hr = E_INVALIDARG;
  7809. MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
  7810. MYDBGASSERT(g_pCustomActionList);
  7811. if ((INVALID_HANDLE_VALUE != hInf) && g_pCustomActionList)
  7812. {
  7813. CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
  7814. do
  7815. {
  7816. hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
  7817. if (SUCCEEDED(hr) && (S_FALSE != hr))
  7818. {
  7819. if (FALSE == WriteInfLine(hInf, szTemp))
  7820. {
  7821. hr = E_UNEXPECTED;
  7822. }
  7823. }
  7824. } while (SUCCEEDED(hr) && (S_FALSE != hr));
  7825. }
  7826. MYDBGASSERT(SUCCEEDED(hr));
  7827. return SUCCEEDED(hr);
  7828. }
  7829. void WriteDelExtraFiles(HANDLE hInf)
  7830. {
  7831. ListBxList * ptr;
  7832. ExtraData * pExtraData;
  7833. if ( g_pHeadExtra != NULL )
  7834. {
  7835. ptr = g_pHeadExtra;
  7836. while (ptr != NULL)
  7837. {
  7838. pExtraData = (ExtraData *)(ptr->ListBxData);
  7839. MYVERIFY(FALSE != WriteInfLine(hInf,pExtraData->szPathname));
  7840. ptr = ptr->next;
  7841. }
  7842. }
  7843. }
  7844. void WriteDelDnsFiles(HANDLE hInf)
  7845. {
  7846. ListBxList * ptr;
  7847. CDunSetting * pDunSetting;
  7848. if (NULL != g_pHeadDunEntry)
  7849. {
  7850. ptr = g_pHeadDunEntry;
  7851. while (ptr != NULL)
  7852. {
  7853. pDunSetting = (CDunSetting*)(ptr->ListBxData);
  7854. MYVERIFY(FALSE != WriteInfLine(hInf, pDunSetting->szScript));
  7855. ptr = ptr->next;
  7856. }
  7857. }
  7858. }
  7859. void WriteSrcMenuItemFiles(HANDLE hInf)
  7860. {
  7861. IconMenu * ptr;
  7862. if ( g_pHeadIcon != NULL )
  7863. {
  7864. ptr = g_pHeadIcon;
  7865. while (ptr != NULL)
  7866. {
  7867. if (ptr->bDoCopy)
  7868. {
  7869. MYVERIFY(FALSE != WriteSrcInfLine(hInf,ptr->szProgram));
  7870. }
  7871. ptr = ptr->next;
  7872. }
  7873. }
  7874. }
  7875. BOOL WriteSrcConActFiles(HANDLE hInf)
  7876. {
  7877. TCHAR szTemp[MAX_PATH+1];
  7878. HRESULT hr = E_INVALIDARG;
  7879. MYDBGASSERT(INVALID_HANDLE_VALUE != hInf);
  7880. MYDBGASSERT(g_pCustomActionList);
  7881. if ((INVALID_HANDLE_VALUE != hInf) && g_pCustomActionList)
  7882. {
  7883. CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
  7884. do
  7885. {
  7886. hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
  7887. if (SUCCEEDED(hr) && (S_FALSE != hr))
  7888. {
  7889. if (FALSE == WriteSrcInfLine(hInf, szTemp))
  7890. {
  7891. hr = E_UNEXPECTED;
  7892. }
  7893. }
  7894. } while (SUCCEEDED(hr) && (S_FALSE != hr));
  7895. }
  7896. return SUCCEEDED(hr);
  7897. }
  7898. //+----------------------------------------------------------------------------
  7899. //
  7900. // Function: WriteSrcRefsFiles
  7901. //
  7902. // Synopsis: This function writes all the files on the HeadRef list to the
  7903. // [SourceDisksFiles] section of the INF. Note that it has to change
  7904. // directory to the temp dir so that the WriteSrcInfLine won't fail
  7905. // (it needs to locate the file to see if a short name should be used).
  7906. //
  7907. // Arguments: HANDLE hInf - Handle to the open inf file to pass to WriteSrcInfLine
  7908. //
  7909. // Returns: Returns TRUE if all the files were written out successfully
  7910. //
  7911. // History: quintinb Created Header and added hack to fix failure of WriteSrcInfLine
  7912. // because it couldn't find the file to find its short name 1/22/98
  7913. //
  7914. //+----------------------------------------------------------------------------
  7915. BOOL WriteSrcRefsFiles(HANDLE hInf)
  7916. {
  7917. ListBxList * ptr;
  7918. BOOL bSuccess = TRUE;
  7919. TCHAR szSavedDir[MAX_PATH+1];
  7920. //
  7921. // Save the current directory and then set the current dir to
  7922. // the temp dir so that WriteSrcInfLine can find the shortfilename
  7923. // of the referenced files.
  7924. //
  7925. if ( g_pHeadRefs != NULL )
  7926. {
  7927. if (0 == GetCurrentDirectory(MAX_PATH, szSavedDir))
  7928. {
  7929. return FALSE;
  7930. }
  7931. if (0 == SetCurrentDirectory(g_szTempDir))
  7932. {
  7933. return FALSE;
  7934. }
  7935. ptr = g_pHeadRefs;
  7936. while (ptr != NULL)
  7937. {
  7938. bSuccess = (bSuccess && WriteSrcInfLine(hInf,ptr->szName));
  7939. ptr = ptr->next;
  7940. }
  7941. MYVERIFY(0 != SetCurrentDirectory(szSavedDir));
  7942. }
  7943. return bSuccess;
  7944. }
  7945. void WriteSrcExtraFiles(HANDLE hInf)
  7946. {
  7947. ListBxList * ptr;
  7948. ExtraData * pExtraData;
  7949. if ( g_pHeadExtra != NULL )
  7950. {
  7951. ptr = g_pHeadExtra;
  7952. while (ptr != NULL)
  7953. {
  7954. pExtraData = (ExtraData *)(ptr->ListBxData);
  7955. MYVERIFY(FALSE != WriteSrcInfLine(hInf,pExtraData->szPathname));
  7956. ptr = ptr->next;
  7957. }
  7958. }
  7959. }
  7960. void WriteSrcDnsFiles(HANDLE hInf)
  7961. {
  7962. ListBxList * ptr;
  7963. CDunSetting* pDunSetting;
  7964. if (NULL != g_pHeadDunEntry)
  7965. {
  7966. ptr = g_pHeadDunEntry;
  7967. while (NULL != ptr)
  7968. {
  7969. pDunSetting = (CDunSetting*)(ptr->ListBxData);
  7970. MYVERIFY(FALSE != WriteSrcInfLine(hInf, pDunSetting->szScript));
  7971. ptr = ptr->next;
  7972. }
  7973. }
  7974. }
  7975. BOOL WriteSEDConActFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
  7976. {
  7977. TCHAR szTemp[MAX_PATH+1];
  7978. TCHAR szFileName[MAX_PATH+1];
  7979. HRESULT hr = E_INVALIDARG;
  7980. MYDBGASSERT(hDlg);
  7981. MYDBGASSERT(pFileNum);
  7982. MYDBGASSERT(szSed);
  7983. MYDBGASSERT(g_pCustomActionList);
  7984. if (hDlg && pFileNum && szSed && g_pCustomActionList)
  7985. {
  7986. CustomActionListEnumerator EnumPrograms(g_pCustomActionList);
  7987. do
  7988. {
  7989. hr = EnumPrograms.GetNextIncludedProgram(szTemp, MAX_PATH);
  7990. if (SUCCEEDED(hr) && (S_FALSE != hr))
  7991. {
  7992. GetFileName(szTemp, szFileName);
  7993. if (FALSE == WriteSED(hDlg, szFileName, pFileNum, szSed))
  7994. {
  7995. hr = E_UNEXPECTED;
  7996. }
  7997. }
  7998. } while (SUCCEEDED(hr) && (S_FALSE != hr));
  7999. }
  8000. return SUCCEEDED(hr);
  8001. }
  8002. BOOL WriteSEDExtraFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
  8003. {
  8004. ListBxList * ptr;
  8005. ExtraData * pExtraData;
  8006. BOOL bReturn = TRUE;
  8007. if ( g_pHeadExtra != NULL )
  8008. {
  8009. ptr = g_pHeadExtra;
  8010. while (ptr != NULL)
  8011. {
  8012. pExtraData = (ExtraData *)(ptr->ListBxData);
  8013. bReturn &= WriteSED(hDlg, pExtraData->szPathname, pFileNum, szSed);
  8014. ptr = ptr->next;
  8015. }
  8016. }
  8017. return bReturn;
  8018. }
  8019. BOOL WriteSEDDnsFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
  8020. {
  8021. BOOL bReturn = TRUE;
  8022. ListBxList * ptr;
  8023. CDunSetting* pDunSetting;
  8024. if (NULL != g_pHeadDunEntry)
  8025. {
  8026. ptr = g_pHeadDunEntry;
  8027. while (NULL != ptr)
  8028. {
  8029. pDunSetting = (CDunSetting*)(ptr->ListBxData);
  8030. bReturn &= WriteSED(hDlg, pDunSetting->szScript, pFileNum, szSed);
  8031. ptr = ptr->next;
  8032. }
  8033. }
  8034. return bReturn;
  8035. }
  8036. BOOL WriteSEDRefsFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
  8037. {
  8038. ListBxList * ptr;
  8039. BOOL bReturn = TRUE;
  8040. if ( g_pHeadRefs != NULL )
  8041. {
  8042. ptr = g_pHeadRefs;
  8043. while (ptr != NULL)
  8044. {
  8045. bReturn &= WriteSED(hDlg, ptr->szName, pFileNum, szSed);
  8046. ptr = ptr->next;
  8047. }
  8048. }
  8049. return bReturn;
  8050. }
  8051. BOOL WriteSEDMenuItemFiles(HWND hDlg, int* pFileNum, LPCTSTR szSed)
  8052. {
  8053. IconMenu * ptr;
  8054. BOOL bReturn = TRUE;
  8055. if ( g_pHeadIcon != NULL )
  8056. {
  8057. ptr = g_pHeadIcon;
  8058. while (ptr != NULL)
  8059. {
  8060. if (ptr->bDoCopy)
  8061. {
  8062. bReturn &= WriteSED(hDlg, ptr->szProgram, pFileNum, szSed);
  8063. }
  8064. ptr = ptr->next;
  8065. }
  8066. }
  8067. return bReturn;
  8068. }
  8069. //+----------------------------------------------------------------------------
  8070. //
  8071. // Function: WriteRenameSection
  8072. //
  8073. // Synopsis: This function verifies that the name used in the rename data structure
  8074. // is correct (the files name in the temp directory could be different
  8075. // if the file was moved from a directory with multiple similarly named files) and then
  8076. // writes the rename section to the inf.
  8077. //
  8078. // Arguments: HANDLE hInf - handle to the inf to add the rename section to.
  8079. //
  8080. // Returns: Nothing
  8081. //
  8082. // History: quintinb Created Header and added checking functionality 2/22/98
  8083. //
  8084. //+----------------------------------------------------------------------------
  8085. void WriteRenameSection(HANDLE hInf)
  8086. {
  8087. ListBxList * ptr;
  8088. TCHAR szOut[MAX_PATH+1];
  8089. TCHAR szTemp[MAX_PATH+1];
  8090. TCHAR szPathToFileInTempDir[MAX_PATH+1];
  8091. RenameData * pRenameData;
  8092. if ( g_pHeadRename != NULL )
  8093. {
  8094. ptr = g_pHeadRename;
  8095. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  8096. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.RenameReg]\r\n")));
  8097. WriteInf(hInf, TEXT("HKLM,%KEY_RENAME%\\CMRENAME,,,\"%49001%\\%ShortSvcName%\"\r\n"));//lint !e534 compile doesn't like the MYVERIFY macro and big strings
  8098. while (ptr != NULL)
  8099. {
  8100. pRenameData = (RenameData *)(ptr->ListBxData);
  8101. //
  8102. // Get the current ShortName for the File
  8103. //
  8104. GetFileName(pRenameData->szLongName, szTemp);
  8105. MYVERIFY(CELEMS(szPathToFileInTempDir) > (UINT)wsprintf(szPathToFileInTempDir,
  8106. TEXT("%s\\%s"), g_szTempDir, szTemp));
  8107. MYVERIFY(0 != GetShortPathName(szPathToFileInTempDir, szTemp, MAX_PATH));
  8108. GetFileName(szTemp, pRenameData->szShortName);
  8109. //
  8110. // Now Write out the files
  8111. //
  8112. _tcscpy(szOut,TEXT("HKLM,%KEY_RENAME%\\CMRENAME,"));
  8113. _tcscat(szOut,pRenameData->szShortName);
  8114. _tcscat(szOut,TEXT(",,\""));
  8115. _tcscat(szOut,pRenameData->szLongName);
  8116. _tcscat(szOut,TEXT("\"\r\n"));
  8117. MYDBGASSERT(_tcslen(szOut) <= sizeof(szOut));
  8118. MYVERIFY(FALSE != WriteInf(hInf,szOut));
  8119. ptr = ptr->next;
  8120. }
  8121. }
  8122. }
  8123. void WriteEraseLongName(HANDLE hInf)
  8124. {
  8125. ListBxList * ptr;
  8126. TCHAR szOut[MAX_PATH+1];
  8127. RenameData * pRenameData;
  8128. if ( g_pHeadRename != NULL )
  8129. {
  8130. ptr = g_pHeadRename;
  8131. while (ptr != NULL)
  8132. {
  8133. pRenameData = (RenameData *)(ptr->ListBxData);
  8134. pRenameData->szShortName[7] = pRenameData->szShortName[7]+1;
  8135. _tcscpy(szOut,pRenameData->szShortName);
  8136. _tcscat(szOut,TEXT("\r\n"));
  8137. MYVERIFY(FALSE != WriteInf(hInf,szOut));
  8138. ptr = ptr->next;
  8139. }
  8140. }
  8141. }
  8142. //+----------------------------------------------------------------------------
  8143. //
  8144. // Function: ProcessMenuItem
  8145. //
  8146. // Synopsis: This function retrieves the data associated with the given keyname
  8147. // under the [Menu Options] section of the given cms file. It then
  8148. // processes the data line into a program part and a parameters part.
  8149. // Then using the keyname, the program string, and the params string
  8150. // it adds an entry to the Status Area Menu Item linked list.
  8151. //
  8152. // Arguments: LPCTSTR pszKeyName - Name of the Menu Item
  8153. // LPCTSTR pszCmsFile - CMS file containing the menu items
  8154. // LPCTSTR pszProfilesDir - directory containing the profiles dir
  8155. // (to help determine if the file was included or not)
  8156. //
  8157. // Returns: BOOL - TRUE if successful
  8158. //
  8159. // History: quintinb Created 6/14/99
  8160. //
  8161. //+----------------------------------------------------------------------------
  8162. BOOL ProcessMenuItem(LPCTSTR pszKeyName, LPCTSTR pszCmsFile, LPCTSTR pszProfilesDir)
  8163. {
  8164. //
  8165. // Check parameters
  8166. //
  8167. if ((NULL == pszKeyName) || (NULL == pszCmsFile) ||
  8168. (TEXT('\0') == pszKeyName[0]) || (TEXT('\0') == pszCmsFile[0]))
  8169. {
  8170. CMTRACE(TEXT("ProcessMenuItem -- bad parameter passed."));
  8171. return FALSE;
  8172. }
  8173. BOOL bFileIncluded = FALSE;
  8174. BOOL bLongFileName = FALSE;
  8175. BOOL bReturn = FALSE;
  8176. LPTSTR pszParams = NULL;
  8177. LPTSTR pszProgram = NULL;
  8178. TCHAR szProgram[MAX_PATH+1];
  8179. TCHAR SeperatorChar = TEXT('\0');
  8180. //
  8181. // Get the Menu Item specified by pszKeyName
  8182. //
  8183. LPTSTR pszLine = GetPrivateProfileStringWithAlloc(c_pszCmSectionMenuOptions, pszKeyName, TEXT(""), pszCmsFile);
  8184. if ((NULL == pszLine) || (TEXT('\0') == pszLine[0]))
  8185. {
  8186. CMTRACE(TEXT("ProcessMenuItem -- GetPrivateProfileStringWithAlloc failed"));
  8187. goto exit;
  8188. }
  8189. //
  8190. // Now that we have a menu item, begin processing. Since we have the keyname, we already
  8191. // have the name of the menu item. We now could have any of the following strings:
  8192. //
  8193. // +Program Name+ Params
  8194. // +Program Name+
  8195. // ProgName Params
  8196. // ProgName
  8197. //
  8198. // Note that we surround long filenames with the '+' char.
  8199. //
  8200. CmStrTrim(pszLine);
  8201. if (TEXT('+') == pszLine[0])
  8202. {
  8203. bLongFileName = TRUE;
  8204. SeperatorChar = TEXT('+');
  8205. pszProgram = CharNext(pszLine); // move past the initial +
  8206. }
  8207. else
  8208. {
  8209. bLongFileName = FALSE;
  8210. SeperatorChar = TEXT(' ');
  8211. pszProgram = pszLine;
  8212. }
  8213. pszParams = CmStrchr(pszProgram, SeperatorChar);
  8214. if (pszParams)
  8215. {
  8216. LPTSTR pszTemp = pszParams;
  8217. pszParams = CharNext(pszParams); // pszParams is either a NULL string or it is the parameters with a space.
  8218. *pszTemp = TEXT('\0');
  8219. }
  8220. else
  8221. {
  8222. if (bLongFileName)
  8223. {
  8224. CMTRACE1(TEXT("ProcessMenuItem -- Unexpected Menu Item format: %s"), pszLine);
  8225. goto exit;
  8226. }
  8227. else
  8228. {
  8229. //
  8230. // Then we don't have any parameters, just a Program
  8231. //
  8232. pszParams = CmEndOfStr(pszProgram);
  8233. }
  8234. }
  8235. CmStrTrim(pszParams);
  8236. CmStrTrim(pszProgram);
  8237. //
  8238. // Now check to see if the file exists in the profile or not
  8239. //
  8240. MYVERIFY(CELEMS(szProgram) > (UINT)wsprintf(szProgram, TEXT("%s%s"), pszProfilesDir, pszProgram));
  8241. bFileIncluded = FileExists(szProgram);
  8242. if (bFileIncluded)
  8243. {
  8244. //
  8245. // If we are in this if block then we have an edited profile that contains menu items.
  8246. // Use the full path to add to the record list.
  8247. //
  8248. pszProgram = szProgram; // memory will be cleaned up below because we only had one
  8249. // allocation that we split up into several pieces.
  8250. }
  8251. bReturn = createRecord(pszKeyName, pszProgram, pszParams, bFileIncluded);
  8252. exit:
  8253. CmFree(pszLine);
  8254. return bReturn;
  8255. }
  8256. //+----------------------------------------------------------------------------
  8257. //
  8258. // Function: ReadIconMenu
  8259. //
  8260. // Synopsis: This function converts the Menu Options section of the given CMS
  8261. // into the Status Area Menu Items linked list that internally
  8262. // represents it.
  8263. //
  8264. // Arguments: LPCTSTR pszCmsFile - Cms File to read the menu items from
  8265. // LPCTSTR pszProfilesDir - full path to the Profiles directory
  8266. // (c:\program files\cmak\profiles usually)
  8267. //
  8268. // Returns: BOOL - Returns TRUE if Successful
  8269. //
  8270. // History: Created Header 6/14/99
  8271. // quintinb Rewrote for Unicode Conversion 6/14/99
  8272. //
  8273. //+----------------------------------------------------------------------------
  8274. BOOL ReadIconMenu(LPCTSTR pszCmsFile, LPCTSTR pszProfilesDir)
  8275. {
  8276. BOOL bReturn = TRUE;
  8277. LPTSTR pszCurrentKeyName = NULL;
  8278. //
  8279. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  8280. // (win95 only). This call will return 0.
  8281. //
  8282. WritePrivateProfileString(NULL, NULL, NULL, g_szCmsFile); //lint !e534 this call will always return 0
  8283. //
  8284. // First we want to get all of the keynames in the Menu Options section
  8285. //
  8286. LPTSTR pszKeyNames = GetPrivateProfileStringWithAlloc(c_pszCmSectionMenuOptions, NULL, TEXT(""), pszCmsFile);
  8287. if (NULL == pszKeyNames)
  8288. {
  8289. //
  8290. // Nothing to process
  8291. //
  8292. goto exit;
  8293. }
  8294. pszCurrentKeyName = pszKeyNames;
  8295. while (TEXT('\0') != (*pszCurrentKeyName))
  8296. {
  8297. //
  8298. // Process the command line
  8299. //
  8300. bReturn = bReturn && ProcessMenuItem(pszCurrentKeyName, pszCmsFile, pszProfilesDir);
  8301. //
  8302. // Find the next string by going to the end of the string
  8303. // and then going one more char. Note that we cannot use
  8304. // CharNext here but must use just ++.
  8305. //
  8306. pszCurrentKeyName = CmEndOfStr(pszCurrentKeyName);
  8307. pszCurrentKeyName++;
  8308. }
  8309. exit:
  8310. CmFree(pszKeyNames);
  8311. return bReturn;
  8312. }
  8313. static void WriteIconMenu()
  8314. {
  8315. IconMenu * LoopPtr;
  8316. TCHAR szTemp[2*MAX_PATH+1];
  8317. TCHAR szName[MAX_PATH+1];
  8318. BOOL longname;
  8319. // CLEAR OUT SECTION
  8320. MYVERIFY(0 != WritePrivateProfileSection(c_pszCmSectionMenuOptions,TEXT("\0\0"),g_szCmsFile));
  8321. if (g_pHeadIcon == NULL)
  8322. {
  8323. return;
  8324. }
  8325. LoopPtr = g_pHeadIcon;
  8326. // WRITE IN ALL ENTRIES
  8327. while( LoopPtr != NULL)
  8328. {
  8329. GetFileName(LoopPtr->szProgram,szName);
  8330. if (IsFile8dot3(szName))
  8331. {
  8332. longname = FALSE;
  8333. }
  8334. else
  8335. {
  8336. longname = TRUE;
  8337. }
  8338. // surround long file names with plus signs - quotes won't work cause
  8339. // they get stripped by the reading routines
  8340. if (longname)
  8341. {
  8342. _tcscpy(szTemp,TEXT("+"));
  8343. }
  8344. else
  8345. {
  8346. szTemp[0] = TEXT('\0');
  8347. }
  8348. if (LoopPtr->bDoCopy)
  8349. {
  8350. _tcscat(szTemp,g_szShortServiceName);
  8351. _tcscat(szTemp,TEXT("\\"));
  8352. }
  8353. _tcscat(szTemp,szName);
  8354. if (longname)
  8355. {
  8356. _tcscat(szTemp,TEXT("+"));
  8357. }
  8358. _tcscat(szTemp,TEXT(" "));
  8359. _tcscat(szTemp,LoopPtr->szParams);
  8360. MYDBGASSERT(_tcslen(szTemp) <= CELEMS(szTemp));
  8361. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionMenuOptions,LoopPtr->szName,szTemp,g_szCmsFile));
  8362. LoopPtr = LoopPtr->next;
  8363. }
  8364. //
  8365. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  8366. // (win95 only). This call will return 0.
  8367. //
  8368. WritePrivateProfileString(NULL, NULL, NULL, g_szCmsFile); //lint !e534 this call will always return 0
  8369. }
  8370. static void RefreshIconMenu(HWND hwndDlg)
  8371. {
  8372. IconMenu * LoopPtr;
  8373. SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_RESETCONTENT,0,(LPARAM)0); //lint !e534 LB_RESETCONTENT doesn't return anything
  8374. if (g_pHeadIcon == NULL)
  8375. {
  8376. return;
  8377. }
  8378. LoopPtr = g_pHeadIcon;
  8379. while( LoopPtr != NULL)
  8380. {
  8381. MYVERIFY(LB_ERR != SendDlgItemMessage(hwndDlg, IDC_LIST1, LB_ADDSTRING, 0,
  8382. (LPARAM) LoopPtr->szName));
  8383. LoopPtr = LoopPtr->next;
  8384. }
  8385. }
  8386. void UpdateEditDeleteMoveButtons(HWND hDlg, IconMenu* pHeadIcon)
  8387. {
  8388. LRESULT lResult;
  8389. BOOL bEnableDeleteAndEdit = FALSE;
  8390. BOOL bEnableMoveUp = FALSE;
  8391. BOOL bEnableMoveDown = FALSE;
  8392. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
  8393. if (LB_ERR != lResult)
  8394. {
  8395. //
  8396. // Enable the Delete and Edit Buttons because we have at least 1 item.
  8397. //
  8398. bEnableDeleteAndEdit = (0 < lResult);
  8399. //
  8400. // If we have more than 1 item, then we need to enable the moveup and movedown
  8401. // buttons, depending on which item is selected.
  8402. //
  8403. if (1 < lResult)
  8404. {
  8405. bEnableMoveUp = TRUE;
  8406. bEnableMoveDown = TRUE;
  8407. //
  8408. // Get the name of the currently selected item
  8409. //
  8410. TCHAR szCurrentItem[MAX_PATH+1];
  8411. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, 0);
  8412. if (LB_ERR != lResult)
  8413. {
  8414. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, lResult, (LPARAM)szCurrentItem);
  8415. if (LB_ERR != lResult)
  8416. {
  8417. IconMenu* pFollower = NULL;
  8418. IconMenu* pCurrent = pHeadIcon;
  8419. while (pCurrent)
  8420. {
  8421. if (0 == lstrcmpi(szCurrentItem, pCurrent->szName))
  8422. {
  8423. if (NULL == pFollower)
  8424. {
  8425. //
  8426. // First item in the list, disable move up
  8427. //
  8428. bEnableMoveUp = FALSE;
  8429. }
  8430. else if (NULL == pCurrent->next)
  8431. {
  8432. //
  8433. // Last item in the list, disable move down
  8434. //
  8435. bEnableMoveDown = FALSE;
  8436. }
  8437. break;
  8438. }
  8439. pFollower = pCurrent;
  8440. pCurrent = pCurrent->next;
  8441. }
  8442. }
  8443. }
  8444. }
  8445. }
  8446. HWND hCurrentFocus = GetFocus();
  8447. HWND hEditButton = GetDlgItem(hDlg, IDC_BUTTON2);
  8448. HWND hDeleteButton = GetDlgItem(hDlg, IDC_BUTTON3);
  8449. HWND hMoveUpButton = GetDlgItem(hDlg, IDC_BUTTON4);
  8450. HWND hMoveDownButton = GetDlgItem(hDlg, IDC_BUTTON5);
  8451. HWND hControl;
  8452. if (hEditButton)
  8453. {
  8454. EnableWindow(hEditButton, bEnableDeleteAndEdit);
  8455. }
  8456. if (hDeleteButton)
  8457. {
  8458. EnableWindow(hDeleteButton, bEnableDeleteAndEdit);
  8459. }
  8460. if (hMoveUpButton)
  8461. {
  8462. EnableWindow(hMoveUpButton, bEnableMoveUp);
  8463. }
  8464. if (hMoveDownButton)
  8465. {
  8466. EnableWindow(hMoveDownButton, bEnableMoveDown);
  8467. }
  8468. if (FALSE == IsWindowEnabled(hCurrentFocus))
  8469. {
  8470. if (hDeleteButton == hCurrentFocus)
  8471. {
  8472. //
  8473. // If delete is disabled and contained the focus, shift it to the Add button
  8474. //
  8475. hControl = GetDlgItem(hDlg, IDC_BUTTON1);
  8476. SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON1, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  8477. SetFocus(hControl);
  8478. }
  8479. else if ((hMoveUpButton == hCurrentFocus) && IsWindowEnabled(hMoveDownButton))
  8480. {
  8481. SetFocus(hMoveDownButton);
  8482. SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON5, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  8483. }
  8484. else if ((hMoveDownButton == hCurrentFocus) && IsWindowEnabled(hMoveUpButton))
  8485. {
  8486. SetFocus(hMoveUpButton);
  8487. SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON4, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  8488. }
  8489. else
  8490. {
  8491. //
  8492. // If all else fails set the focus to the list control
  8493. //
  8494. hControl = GetDlgItem(hDlg, IDC_LIST1);
  8495. SetFocus(hControl);
  8496. }
  8497. }
  8498. }
  8499. BOOL OnProcessStatusMenuIconsEdit(HWND hDlg)
  8500. {
  8501. TCHAR szTemp[MAX_PATH+1];
  8502. TCHAR szOld[MAX_PATH+1];
  8503. INT_PTR nResult;
  8504. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
  8505. if (nResult == LB_ERR)
  8506. {
  8507. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  8508. return TRUE;
  8509. }
  8510. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult, (LPARAM)szTemp));
  8511. MYVERIFY(FALSE != GetIconMenuItem(szTemp, &DlgEditItem));
  8512. _tcscpy(szOld, szTemp);
  8513. nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_MENU_ITEM_POPUP), hDlg, ProcessStatusMenuPopup, (LPARAM)0);
  8514. if ((IDOK == nResult) && (TEXT('\0') != DlgEditItem.szName[0]))
  8515. {
  8516. if (0 == lstrcmpi(szOld, DlgEditItem.szName))
  8517. {
  8518. MYVERIFY(FALSE != updateRecord(DlgEditItem.szName, DlgEditItem.szProgram,
  8519. DlgEditItem.szParams, DlgEditItem.bDoCopy, szOld));
  8520. }
  8521. else
  8522. {
  8523. DeleteRecord(szOld);
  8524. MYVERIFY(TRUE == createRecord(DlgEditItem.szName, DlgEditItem.szProgram,
  8525. DlgEditItem.szParams, DlgEditItem.bDoCopy));
  8526. }
  8527. RefreshIconMenu(hDlg);
  8528. WriteIconMenu();
  8529. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)DlgEditItem.szName);
  8530. if (LB_ERR != nResult)
  8531. {
  8532. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg,IDC_LIST1,LB_SETCURSEL,(WPARAM)nResult,(LPARAM)0));
  8533. }
  8534. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8535. }
  8536. return TRUE;
  8537. }
  8538. //+----------------------------------------------------------------------------
  8539. //
  8540. // Function: ProcessStatusMenuIcons
  8541. //
  8542. // Synopsis: Customize the status area icon menu
  8543. //
  8544. //
  8545. // History: quintinb Created Header and renamed from ProcessPage2F1 8/6/98
  8546. //
  8547. //+----------------------------------------------------------------------------
  8548. INT_PTR APIENTRY ProcessStatusMenuIcons(
  8549. HWND hDlg,
  8550. UINT message,
  8551. WPARAM wParam,
  8552. LPARAM lParam)
  8553. {
  8554. TCHAR szTemp[MAX_PATH+1];
  8555. TCHAR szOld[MAX_PATH+1];
  8556. INT_PTR nResult;
  8557. int direction;
  8558. NMHDR* pnmHeader = (NMHDR*)lParam;
  8559. ProcessBold(hDlg,message);
  8560. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MENU)) return TRUE;
  8561. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  8562. SetDefaultGUIFont(hDlg,message,IDC_LIST1);
  8563. switch (message)
  8564. {
  8565. case WM_INITDIALOG:
  8566. {
  8567. //
  8568. // Load the arrow images for the move up and move down buttons
  8569. //
  8570. HICON hUpArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_UP_ARROW), IMAGE_ICON, 0, 0, 0);
  8571. HICON hDownArrow = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DOWN_ARROW), IMAGE_ICON, 0, 0, 0);
  8572. //
  8573. // Set the arrow button bit maps
  8574. //
  8575. SendMessage(GetDlgItem(hDlg, IDC_BUTTON4), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hUpArrow);
  8576. SendMessage(GetDlgItem(hDlg, IDC_BUTTON5), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hDownArrow);
  8577. }
  8578. break;
  8579. case WM_COMMAND:
  8580. switch (LOWORD(wParam))
  8581. {
  8582. case IDC_BUTTON1: //add
  8583. ZeroMemory(&DlgEditItem,sizeof(DlgEditItem));
  8584. nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_MENU_ITEM_POPUP), hDlg, ProcessStatusMenuPopup, (LPARAM)0);
  8585. if ((nResult == IDOK) && (DlgEditItem.szName[0] != 0))
  8586. {
  8587. MYVERIFY(FALSE != createRecord(DlgEditItem.szName, DlgEditItem.szProgram, DlgEditItem.szParams, DlgEditItem.bDoCopy));
  8588. RefreshIconMenu(hDlg);
  8589. WriteIconMenu();
  8590. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)DlgEditItem.szName);
  8591. if (LB_ERR != nResult)
  8592. {
  8593. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg,IDC_LIST1,LB_SETCURSEL,(WPARAM)nResult,(LPARAM)0));
  8594. }
  8595. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8596. }
  8597. return (TRUE);
  8598. break; //lint !e527 this line isn't reachable but
  8599. // keep it in case the return is removed
  8600. case IDC_BUTTON2: //edit
  8601. OnProcessStatusMenuIconsEdit(hDlg);
  8602. break; //lint !e527 this line isn't reachable but
  8603. // keep it in case the return is removed
  8604. case IDC_BUTTON3: //delete
  8605. nResult = SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,(LPARAM)0);
  8606. if (nResult == LB_ERR)
  8607. {
  8608. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  8609. return TRUE;
  8610. }
  8611. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult,
  8612. (LPARAM)szTemp));
  8613. DeleteRecord(szTemp);
  8614. RefreshIconMenu(hDlg);
  8615. //
  8616. // Reset the cursor selection to the first in the list, unless the list is empty.
  8617. //
  8618. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  8619. if (nResult)
  8620. {
  8621. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)0, (LPARAM)0));
  8622. }
  8623. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8624. WriteIconMenu();
  8625. return (TRUE);
  8626. break; //lint !e527 this line isn't reachable but
  8627. // keep it in case the return is removed
  8628. case IDC_BUTTON4: //UP
  8629. case IDC_BUTTON5: //down
  8630. if (LOWORD(wParam) == IDC_BUTTON4)
  8631. {
  8632. direction = -1;
  8633. }
  8634. else
  8635. {
  8636. direction = 1;
  8637. }
  8638. nResult = SendDlgItemMessage(hDlg,IDC_LIST1,LB_GETCURSEL,0,(LPARAM)0);
  8639. if (nResult == LB_ERR)
  8640. {
  8641. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  8642. return TRUE;
  8643. }
  8644. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT,
  8645. (WPARAM)nResult, (LPARAM)szTemp));
  8646. if (MoveRecord(szTemp,direction))
  8647. {
  8648. RefreshIconMenu(hDlg);
  8649. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL,
  8650. (WPARAM)(nResult + direction), (LPARAM)0));
  8651. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8652. }
  8653. WriteIconMenu();
  8654. return (TRUE);
  8655. break; //lint !e527 this line isn't reachable but
  8656. // keep it in case the return is removed
  8657. case IDC_LIST1:
  8658. if (LBN_DBLCLK == HIWORD(wParam))
  8659. {
  8660. OnProcessStatusMenuIconsEdit(hDlg);
  8661. }
  8662. else if (LBN_SELCHANGE == HIWORD(wParam))
  8663. {
  8664. //
  8665. // The selection in the list box changed, update the move buttons if needed
  8666. //
  8667. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8668. }
  8669. break;
  8670. default:
  8671. break;
  8672. }
  8673. break;
  8674. case WM_NOTIFY:
  8675. if (NULL == pnmHeader)
  8676. {
  8677. return FALSE;
  8678. }
  8679. switch (pnmHeader->code)
  8680. {
  8681. case PSN_KILLACTIVE:
  8682. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  8683. return 1;
  8684. break; //lint !e527 this line isn't reachable but
  8685. // keep it in case the return is removed
  8686. case PSN_SETACTIVE:
  8687. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  8688. if (g_pHeadIcon == NULL)
  8689. {
  8690. MYVERIFY(FALSE != ReadIconMenu(g_szCmsFile, g_szOsdir));
  8691. }
  8692. RefreshIconMenu(hDlg);
  8693. //
  8694. // Reset the cursor selection to the first in the list, unless the list is empty.
  8695. // Then we should set focus on the Add button
  8696. //
  8697. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  8698. if (nResult)
  8699. {
  8700. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)0, (LPARAM)0));
  8701. }
  8702. else
  8703. {
  8704. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  8705. }
  8706. UpdateEditDeleteMoveButtons(hDlg, g_pHeadIcon);
  8707. break;
  8708. case PSN_WIZBACK:
  8709. WriteIconMenu();
  8710. break;
  8711. case PSN_WIZNEXT:
  8712. WriteIconMenu();
  8713. break;
  8714. default:
  8715. return FALSE;
  8716. }
  8717. break;
  8718. default:
  8719. return FALSE;
  8720. }
  8721. return TRUE;
  8722. }
  8723. //+----------------------------------------------------------------------------
  8724. //
  8725. // Function: DisplayBitmap
  8726. //
  8727. // Synopsis: This function takes a BMPDATA structure with a valid HDIBitmap data
  8728. // (device Independent bitmap data) and creates a device dependent bitmap
  8729. // and displays it on the specified bitmap window control.
  8730. //
  8731. // Arguments: HWND hDlg - Window handle of the dialog containing the Bitmap control
  8732. // int iBitmapControl - Resource ID of the bitmap window control
  8733. // HPALETTE* phMasterPalette - pointer to the master palette
  8734. // BMPDATA* pBmpData - pointer to the BMPDATA to display
  8735. //
  8736. // Returns: Nothing
  8737. //
  8738. // History: quintinb Created 8/6/98
  8739. //
  8740. //+----------------------------------------------------------------------------
  8741. void DisplayBitmap(HWND hDlg, int iBitmapControl, HPALETTE* phMasterPalette, BMPDATA* pBmpData)
  8742. {
  8743. MYDBGASSERT(NULL != pBmpData);
  8744. MYDBGASSERT(pBmpData->hDIBitmap);
  8745. MYDBGASSERT(NULL != phMasterPalette);
  8746. if ((NULL != pBmpData) && (pBmpData->hDIBitmap) && (NULL != phMasterPalette))
  8747. {
  8748. pBmpData->phMasterPalette = phMasterPalette;
  8749. pBmpData->bForceBackground = FALSE; // Paint as a Foreground App
  8750. if (CreateBitmapData(pBmpData->hDIBitmap, pBmpData, hDlg, TRUE))
  8751. {
  8752. SendDlgItemMessage(hDlg, iBitmapControl, STM_SETIMAGE,
  8753. IMAGE_BITMAP,
  8754. (LPARAM) pBmpData); //lint !e534 STM_SETIMAGE doesn't return error info
  8755. }
  8756. }
  8757. }
  8758. //+----------------------------------------------------------------------------
  8759. //
  8760. // Function: ProcesssSigninBitmap
  8761. //
  8762. // Synopsis: Customize the sign-in bitmap -- this function processes the
  8763. // messages for the page in CMAK that handles customizing the
  8764. // sign-in dialog bitmap.
  8765. //
  8766. //
  8767. // History: quintinb Created Header 8/6/98
  8768. // quintinb Rewrote to use new shared bitmap handling code 8/6/98
  8769. //
  8770. //+----------------------------------------------------------------------------
  8771. INT_PTR APIENTRY ProcessSigninBitmap(
  8772. HWND hDlg,
  8773. UINT message,
  8774. WPARAM wParam,
  8775. LPARAM lParam)
  8776. {
  8777. TCHAR szTemp[MAX_PATH+1];
  8778. TCHAR* pszBitmap;
  8779. NMHDR* pnmHeader = (NMHDR*)lParam;
  8780. static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
  8781. static BMPDATA BmpData;
  8782. static HPALETTE hMasterPalette;
  8783. ProcessBold(hDlg,message);
  8784. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_BITMAPS)) return TRUE;
  8785. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  8786. SetDefaultGUIFont(hDlg,message,IDC_EDITSPLASH);
  8787. switch (message)
  8788. {
  8789. case WM_INITDIALOG:
  8790. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  8791. break;
  8792. case WM_PALETTEISCHANGING:
  8793. break;
  8794. case WM_PALETTECHANGED:
  8795. if ((wParam != (WPARAM) hDlg) && (BmpData.hDIBitmap))
  8796. {
  8797. //
  8798. // Handle the palette change.
  8799. //
  8800. CMTRACE2(TEXT("ProcessSigninBitmap handling WM_PALETTECHANGED message, wParam=0x%x, hDlg=0x%x."), wParam, hDlg);
  8801. PaletteChanged(&BmpData, hDlg, IDC_DEFAULTBRAND);
  8802. }
  8803. return TRUE;
  8804. break; //lint !e527 Unreachable but please keep in case someone removes the return
  8805. case WM_QUERYNEWPALETTE:
  8806. QueryNewPalette(&BmpData, hDlg, IDC_DEFAULTBRAND);
  8807. return TRUE;
  8808. break; //lint !e527 Unreachable but please keep in case someone removes the return
  8809. case WM_COMMAND:
  8810. switch (LOWORD(wParam))
  8811. {
  8812. case IDC_RADIO1:
  8813. //
  8814. // Display the Default Bitmap
  8815. //
  8816. EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),FALSE);
  8817. _tcscpy(szDisplay, g_szBrandBmp);
  8818. //
  8819. // Load the default Bitmap
  8820. //
  8821. ReleaseBitmapData(&BmpData);
  8822. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_CM_DEFAULT));
  8823. //
  8824. // Display it
  8825. //
  8826. DisplayBitmap(hDlg, IDC_DEFAULTBRAND, &hMasterPalette, &BmpData);
  8827. break;
  8828. case IDC_RADIO2:
  8829. //
  8830. // Display a custom Bitmap
  8831. //
  8832. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
  8833. if (TEXT('\0') != g_szBrandBmp[0])
  8834. {
  8835. pszBitmap = g_szBrandBmp;
  8836. }
  8837. else if (TEXT('\0') != szDisplay[0])
  8838. {
  8839. pszBitmap = szDisplay;
  8840. }
  8841. else
  8842. {
  8843. break;
  8844. }
  8845. //
  8846. // Load the Custom Bitmap
  8847. //
  8848. ReleaseBitmapData(&BmpData);
  8849. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, pszBitmap);
  8850. //
  8851. // Display it
  8852. //
  8853. DisplayBitmap(hDlg, IDC_DEFAULTBRAND, &hMasterPalette, &BmpData);
  8854. break;
  8855. case IDC_BROWSEBMP1:
  8856. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
  8857. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  8858. {
  8859. UINT uFilter = IDS_BMPFILTER;
  8860. TCHAR* szMask = TEXT("*.bmp");
  8861. MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
  8862. IDC_EDITSPLASH, TEXT("bmp"), g_szBrandBmp));
  8863. }
  8864. //
  8865. // If we have a custom bitmap name, load and display it
  8866. //
  8867. if (TEXT('\0') != g_szBrandBmp[0])
  8868. {
  8869. ReleaseBitmapData(&BmpData);
  8870. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szBrandBmp);
  8871. //
  8872. // Display it
  8873. //
  8874. DisplayBitmap(hDlg, IDC_DEFAULTBRAND, &hMasterPalette, &BmpData);
  8875. }
  8876. break;
  8877. case IDC_EDITSPLASH:
  8878. if (HIWORD(wParam) == EN_KILLFOCUS)
  8879. {
  8880. //
  8881. // Notice that we do not do a file check on the text retrieved from the control.
  8882. // We do this because, changing focus is an awkward time to do this check and brings
  8883. // up the error dialog way to often. We will catch this on Back or Next anyway so let
  8884. // it go by here.
  8885. //
  8886. GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
  8887. CheckNameChange(g_szBrandBmp, szTemp);
  8888. if (TEXT('\0') != g_szBrandBmp[0])
  8889. {
  8890. //
  8891. // Load the Custom Bitmap
  8892. //
  8893. ReleaseBitmapData(&BmpData);
  8894. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szBrandBmp);
  8895. //
  8896. // Display it
  8897. //
  8898. DisplayBitmap(hDlg, IDC_DEFAULTBRAND, &hMasterPalette, &BmpData);
  8899. }
  8900. return TRUE;
  8901. }
  8902. break;
  8903. default:
  8904. break;
  8905. }
  8906. break;
  8907. case WM_NOTIFY:
  8908. if (NULL == pnmHeader)
  8909. {
  8910. return FALSE;
  8911. }
  8912. switch (pnmHeader->code)
  8913. {
  8914. case PSN_KILLACTIVE:
  8915. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  8916. return 1;
  8917. break; //lint !e527 this line isn't reachable but
  8918. // keep it in case the return is removed
  8919. case PSN_SETACTIVE:
  8920. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  8921. //
  8922. // Get the bitmap string from the CMS and verify that the file
  8923. // exists.
  8924. //
  8925. ZeroMemory(g_szBrandBmp, sizeof(g_szBrandBmp));
  8926. ZeroMemory(&BmpData, sizeof(BMPDATA));
  8927. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryLogo, TEXT(""),
  8928. g_szBrandBmp, CELEMS(g_szBrandBmp), g_szCmsFile); //lint !e534
  8929. if (TEXT('\0') == g_szBrandBmp[0])
  8930. {
  8931. //
  8932. // Then we use the default CM bitmap, disable edit control
  8933. //
  8934. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
  8935. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), FALSE);
  8936. //
  8937. // Note that we use szDisplay here just in case the use selects a
  8938. // bitmap and then switches back to default.
  8939. //
  8940. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH),
  8941. WM_SETTEXT, 0, (LPARAM)GetName(szDisplay)));
  8942. //
  8943. // Load the default Bitmap
  8944. //
  8945. ReleaseBitmapData(&BmpData);
  8946. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_CM_DEFAULT));
  8947. }
  8948. else
  8949. {
  8950. //
  8951. // Use whatever bitmap is specified in the CMS.
  8952. //
  8953. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2));
  8954. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
  8955. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH),
  8956. WM_SETTEXT, 0, (LPARAM)GetName(g_szBrandBmp)));
  8957. MYVERIFY(FALSE != VerifyFile(hDlg, IDC_EDITSPLASH, g_szBrandBmp, FALSE));
  8958. //
  8959. // Load the specified Bitmap
  8960. //
  8961. if (!FileExists(g_szBrandBmp))
  8962. {
  8963. TCHAR szFile[MAX_PATH+1];
  8964. // LOOK UP THE FILE IN THE PROFILE DIRECTORY
  8965. GetFileName(g_szBrandBmp, szFile);
  8966. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
  8967. g_szOsdir, g_szShortServiceName, szFile));
  8968. if (!FileExists(szTemp))
  8969. {
  8970. return FALSE; //GIVE UP;
  8971. }
  8972. else
  8973. {
  8974. _tcscpy(g_szBrandBmp, szTemp);
  8975. }
  8976. }
  8977. if (TEXT('\0') != g_szBrandBmp[0])
  8978. {
  8979. //
  8980. // Load the custom Bitmap
  8981. //
  8982. ReleaseBitmapData(&BmpData);
  8983. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szBrandBmp);
  8984. }
  8985. }
  8986. //
  8987. // If we have a handle, create a new Device Dependent bitmap
  8988. // and display it.
  8989. //
  8990. DisplayBitmap(hDlg, IDC_DEFAULTBRAND, &hMasterPalette, &BmpData);
  8991. break;
  8992. case PSN_WIZBACK:
  8993. case PSN_WIZNEXT:
  8994. //
  8995. // Make sure that the user typed in a Bitmap name if they selected
  8996. // to have a custom bitmap.
  8997. //
  8998. if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
  8999. {
  9000. if (-1 == GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  9001. {
  9002. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9003. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9004. return 1;
  9005. }
  9006. if (!VerifyFile(hDlg, IDC_EDITSPLASH, g_szBrandBmp, TRUE))
  9007. {
  9008. return 1;
  9009. }
  9010. else if (TEXT('\0') == g_szBrandBmp[0])
  9011. {
  9012. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOBMP, MB_OK));
  9013. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9014. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9015. return 1;
  9016. }
  9017. else
  9018. {
  9019. //
  9020. // Try to Load the bitmap to make sure it is valid
  9021. //
  9022. TCHAR szTemp1[MAX_PATH+1];
  9023. ReleaseBitmapData(&BmpData);
  9024. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szBrandBmp);
  9025. if (NULL == BmpData.hDIBitmap)
  9026. {
  9027. //
  9028. // Use szTemp1 to hold the format string
  9029. //
  9030. MYVERIFY(0 != LoadString(g_hInstance, IDS_INVALIDBMP, szTemp1, MAX_PATH));
  9031. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, szTemp1, g_szBrandBmp));
  9032. MessageBox(hDlg, szTemp, g_szAppTitle, MB_OK);
  9033. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9034. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9035. return 1;
  9036. }
  9037. }
  9038. }
  9039. else
  9040. {
  9041. g_szBrandBmp[0] = TEXT('\0');
  9042. }
  9043. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryLogo,
  9044. g_szBrandBmp, g_szCmsFile));
  9045. //
  9046. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  9047. // (win95 only). This call will return 0.
  9048. //
  9049. WritePrivateProfileString(NULL, NULL, NULL, g_szCmpFile); //lint !e534 this call will always return 0
  9050. //
  9051. // Fall through to cleanup code in RESET handler
  9052. //
  9053. case PSN_RESET:
  9054. //
  9055. // Cleanup the Graphics Objects
  9056. //
  9057. ReleaseBitmapData(&BmpData);
  9058. if (NULL != hMasterPalette)
  9059. {
  9060. DeleteObject(hMasterPalette);
  9061. hMasterPalette = NULL;
  9062. }
  9063. break;
  9064. default:
  9065. return FALSE;
  9066. }
  9067. break;
  9068. default:
  9069. return FALSE;
  9070. }
  9071. return TRUE;
  9072. }
  9073. //+----------------------------------------------------------------------------
  9074. //
  9075. // Function: ProcessPhoneBookBitmap
  9076. //
  9077. // Synopsis: Customize the Phone Book bitmap -- this function processes the
  9078. // messages for the page in CMAK that handles customizing the
  9079. // pb dialog bitmap.
  9080. //
  9081. //
  9082. // History: quintinb Created Header 8/6/98
  9083. // quintinb Rewrote to use new shared bitmap handling code 8/6/98
  9084. // quintinb Renamed from ProcessPage4
  9085. //
  9086. //+----------------------------------------------------------------------------
  9087. INT_PTR APIENTRY ProcessPhoneBookBitmap(
  9088. HWND hDlg,
  9089. UINT message,
  9090. WPARAM wParam,
  9091. LPARAM lParam)
  9092. {
  9093. TCHAR szTemp[MAX_PATH+1];
  9094. TCHAR szFile[MAX_PATH+1];
  9095. TCHAR* pszBitmap;
  9096. NMHDR* pnmHeader = (NMHDR*)lParam;
  9097. static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
  9098. static BMPDATA BmpData;
  9099. static HPALETTE hMasterPalette;
  9100. ProcessBold(hDlg,message);
  9101. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_BITMAPS)) return TRUE;
  9102. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  9103. SetDefaultGUIFont(hDlg,message,IDC_EDITSPLASH);
  9104. switch (message)
  9105. {
  9106. case WM_INITDIALOG:
  9107. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9108. break;
  9109. case WM_PALETTEISCHANGING:
  9110. break;
  9111. case WM_PALETTECHANGED:
  9112. if ((wParam != (WPARAM) hDlg) && (BmpData.hDIBitmap))
  9113. {
  9114. //
  9115. // Handle the palette change.
  9116. //
  9117. CMTRACE2(TEXT("ProcessSigninBitmap handling WM_PALETTECHANGED message, wParam=0x%x, hDlg=0x%x."), wParam, hDlg);
  9118. PaletteChanged(&BmpData, hDlg, IDC_PDEFAULTBRAND);
  9119. }
  9120. return TRUE;
  9121. break; //lint !e527 Unreachable but please keep in case someone removes the return
  9122. case WM_QUERYNEWPALETTE:
  9123. QueryNewPalette(&BmpData, hDlg, IDC_PDEFAULTBRAND);
  9124. return TRUE;
  9125. break; //lint !e527 Unreachable but please keep in case someone removes the return
  9126. case WM_COMMAND:
  9127. switch (LOWORD(wParam))
  9128. {
  9129. case IDC_RADIO1:
  9130. //
  9131. // Display the Default Bitmap
  9132. //
  9133. EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),FALSE);
  9134. _tcscpy(szDisplay, g_szPhoneBmp);
  9135. //
  9136. // Load the default Bitmap
  9137. //
  9138. ReleaseBitmapData(&BmpData);
  9139. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_CM_PB_DEFAULT));
  9140. //
  9141. // Display it
  9142. //
  9143. DisplayBitmap(hDlg, IDC_PDEFAULTBRAND, &hMasterPalette, &BmpData);
  9144. break;
  9145. case IDC_RADIO2:
  9146. //
  9147. // Display a custom Bitmap
  9148. //
  9149. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
  9150. if (TEXT('\0') != g_szPhoneBmp[0])
  9151. {
  9152. pszBitmap = g_szPhoneBmp;
  9153. }
  9154. else if (TEXT('\0') != szDisplay[0])
  9155. {
  9156. pszBitmap = szDisplay;
  9157. }
  9158. else
  9159. {
  9160. //
  9161. // Nothing has been specified yet
  9162. //
  9163. break;
  9164. }
  9165. //
  9166. // Load the Custom Bitmap
  9167. //
  9168. ReleaseBitmapData(&BmpData);
  9169. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, pszBitmap);
  9170. //
  9171. // Display it
  9172. //
  9173. DisplayBitmap(hDlg, IDC_PDEFAULTBRAND, &hMasterPalette, &BmpData);
  9174. break;
  9175. case IDC_BROWSEBMP2:
  9176. EnableWindow(GetDlgItem(hDlg,IDC_EDITSPLASH),TRUE);
  9177. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9178. {
  9179. UINT uFilter = IDS_BMPFILTER;
  9180. TCHAR* szMask = TEXT("*.bmp");
  9181. MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
  9182. IDC_EDITSPLASH, TEXT("bmp"), g_szPhoneBmp));
  9183. }
  9184. //
  9185. // If we have a custom bitmap name, load and display it
  9186. //
  9187. if (TEXT('\0') != g_szPhoneBmp[0])
  9188. {
  9189. //
  9190. // Load the Custom Bitmap
  9191. //
  9192. ReleaseBitmapData(&BmpData);
  9193. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szPhoneBmp);
  9194. //
  9195. // Display it
  9196. //
  9197. DisplayBitmap(hDlg, IDC_PDEFAULTBRAND, &hMasterPalette, &BmpData);
  9198. }
  9199. break;
  9200. case IDC_EDITSPLASH:
  9201. if (HIWORD(wParam) == EN_KILLFOCUS)
  9202. {
  9203. //
  9204. // Note that we do not check whether we can convert the files to ANSI on Change of Focus
  9205. // the reason is because the user would get too many error messages and they would be somewhat
  9206. // confusing. Instead we will catch this on Next/Back and ignore it here.
  9207. //
  9208. GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
  9209. CheckNameChange(g_szPhoneBmp, szTemp);
  9210. if (TEXT('\0') != g_szPhoneBmp[0])
  9211. {
  9212. //
  9213. // Load the Custom Bitmap
  9214. //
  9215. ReleaseBitmapData(&BmpData);
  9216. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szPhoneBmp);
  9217. //
  9218. // Display it
  9219. //
  9220. DisplayBitmap(hDlg, IDC_PDEFAULTBRAND, &hMasterPalette, &BmpData);
  9221. }
  9222. return TRUE;
  9223. }
  9224. break;
  9225. default:
  9226. break;
  9227. }
  9228. break;
  9229. case WM_NOTIFY:
  9230. if (NULL == pnmHeader)
  9231. {
  9232. return FALSE;
  9233. }
  9234. switch (pnmHeader->code)
  9235. {
  9236. case PSN_KILLACTIVE:
  9237. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  9238. return 1;
  9239. break; //lint !e527 this line isn't reachable but
  9240. // keep it in case the return is removed
  9241. case PSN_SETACTIVE:
  9242. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  9243. ZeroMemory(g_szPhoneBmp, sizeof(g_szPhoneBmp));
  9244. ZeroMemory(&BmpData, sizeof(BMPDATA));
  9245. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPbLogo, TEXT(""),
  9246. g_szPhoneBmp, CELEMS(g_szPhoneBmp), g_szCmsFile); //lint !e534
  9247. if (TEXT('\0') != g_szPhoneBmp[0])
  9248. {
  9249. //
  9250. // We want to Display a Custom Bitmap
  9251. //
  9252. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9253. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), TRUE);
  9254. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH), WM_SETTEXT,
  9255. 0, (LPARAM)GetName(g_szPhoneBmp)));
  9256. MYVERIFY(FALSE != VerifyFile(hDlg, IDC_EDITSPLASH, g_szPhoneBmp, FALSE));
  9257. if (!FileExists(g_szPhoneBmp))
  9258. {
  9259. //
  9260. // We couldn't find it the first time so build the path to the profile
  9261. // directory and try again.
  9262. //
  9263. GetFileName(g_szPhoneBmp, szFile);
  9264. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"),
  9265. g_szOsdir, g_szShortServiceName, szFile));
  9266. if (!FileExists(szTemp))
  9267. {
  9268. //
  9269. // We can't find it so give up.
  9270. //
  9271. return FALSE;
  9272. }
  9273. else
  9274. {
  9275. _tcscpy(g_szPhoneBmp, szTemp);
  9276. }
  9277. }
  9278. //
  9279. // Load the Custom Bitmap
  9280. //
  9281. ReleaseBitmapData(&BmpData);
  9282. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szPhoneBmp);
  9283. }
  9284. else
  9285. {
  9286. //
  9287. // We want to Display the Default Bitmap
  9288. //
  9289. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1));
  9290. EnableWindow(GetDlgItem(hDlg, IDC_EDITSPLASH), FALSE);
  9291. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSPLASH), WM_SETTEXT,
  9292. 0, (LPARAM)GetName(szDisplay)));
  9293. //
  9294. // Load the default Bitmap
  9295. //
  9296. ReleaseBitmapData(&BmpData);
  9297. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_CM_PB_DEFAULT));
  9298. }
  9299. //
  9300. // Display it
  9301. //
  9302. DisplayBitmap(hDlg, IDC_PDEFAULTBRAND, &hMasterPalette, &BmpData);
  9303. break;
  9304. case PSN_WIZBACK:
  9305. case PSN_WIZNEXT:
  9306. //
  9307. // First check to see if the user entered a bmp file if they
  9308. // selected that they wanted to display a custom bitmap.
  9309. //
  9310. if (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED)
  9311. {
  9312. if (-1 == GetTextFromControl(hDlg, IDC_EDITSPLASH, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  9313. {
  9314. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9315. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9316. return 1;
  9317. }
  9318. if (!VerifyFile(hDlg, IDC_EDITSPLASH, g_szPhoneBmp, TRUE))
  9319. {
  9320. return 1;
  9321. }
  9322. else if (TEXT('\0') == g_szPhoneBmp[0])
  9323. {
  9324. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOBMP, MB_OK));
  9325. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9326. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9327. return 1;
  9328. }
  9329. else
  9330. {
  9331. ReleaseBitmapData(&BmpData);
  9332. BmpData.hDIBitmap = CmLoadBitmap(g_hInstance, g_szPhoneBmp);
  9333. if (NULL == BmpData.hDIBitmap)
  9334. {
  9335. TCHAR szTemp1[MAX_PATH+1];
  9336. //
  9337. // Then we have an invalid bitmap file. Inform the user.
  9338. // Using szTemp1 as a temp var for the format string.
  9339. //
  9340. MYVERIFY(0 != LoadString(g_hInstance, IDS_INVALIDBMP, szTemp1, MAX_PATH));
  9341. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, szTemp1, g_szPhoneBmp));
  9342. MessageBox(hDlg, szTemp, g_szAppTitle, MB_OK);
  9343. SetFocus(GetDlgItem(hDlg, IDC_EDITSPLASH));
  9344. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9345. return 1;
  9346. }
  9347. }
  9348. }
  9349. else
  9350. {
  9351. g_szPhoneBmp[0] = TEXT('\0');
  9352. }
  9353. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection,c_pszCmEntryPbLogo,g_szPhoneBmp,g_szCmsFile));
  9354. //
  9355. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  9356. // (win95 only). This call will return 0.
  9357. //
  9358. WritePrivateProfileString(NULL, NULL, NULL, g_szCmpFile); //lint !e534 this call will always return 0
  9359. //
  9360. // Fall through to cleanup code in RESET handler
  9361. //
  9362. case PSN_RESET:
  9363. //
  9364. // Cleanup the Graphics Objects
  9365. //
  9366. ReleaseBitmapData(&BmpData);
  9367. if (NULL != hMasterPalette)
  9368. {
  9369. DeleteObject(hMasterPalette);
  9370. hMasterPalette = NULL;
  9371. }
  9372. break;
  9373. default:
  9374. return FALSE;
  9375. }
  9376. break;
  9377. default:
  9378. return FALSE;
  9379. }
  9380. return TRUE;
  9381. }
  9382. BOOL UpdateIcon(HWND hDlg,DWORD ctrlID,LPTSTR lpFile,BOOL issmall)
  9383. {
  9384. HANDLE hRes = NULL;
  9385. DWORD nResult;
  9386. LPTSTR lpfilename;
  9387. TCHAR szTemp[MAX_PATH+1] = TEXT("");
  9388. BOOL bReturn = FALSE;
  9389. //
  9390. // Don't do the ANSI conversion check on the Icons here because this function
  9391. // is only called from the Kill Focus windows message. Thus we don't want to
  9392. // put up an error message here. It will be caught by the Next/Back messages
  9393. // anyway so ignore it here.
  9394. //
  9395. GetTextFromControl(hDlg, ctrlID, szTemp, MAX_PATH, FALSE); // bDisplayError == FALSE
  9396. CheckNameChange(lpFile, szTemp);
  9397. lstrcpy(szTemp, lpFile); // we need a temp to hold lpFile so that it can be modified by Search Path as necessary.
  9398. nResult = SearchPath(NULL, szTemp, NULL, MAX_PATH, lpFile, &lpfilename);
  9399. if (nResult != 0)
  9400. {
  9401. if (issmall)
  9402. {
  9403. hRes = LoadImage(NULL, lpFile, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
  9404. }
  9405. else
  9406. {
  9407. hRes = LoadImage(NULL, lpFile, IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
  9408. }
  9409. }
  9410. return (NULL != hRes);
  9411. }
  9412. BOOL VerifyIcon(HWND hDlg,DWORD ctrlID,LPTSTR lpFile,DWORD iconID,BOOL issmall,LPTSTR lpDispFile)
  9413. {
  9414. TCHAR szTemp2[MAX_PATH+1];
  9415. TCHAR szMsg[MAX_PATH+1];
  9416. HANDLE hRes;
  9417. if ((lpFile[0] == TEXT('\0')) && (lpDispFile[0] != TEXT('\0')))
  9418. {
  9419. _tcscpy(lpFile,lpDispFile);
  9420. }
  9421. if (!VerifyFile(hDlg,ctrlID,lpFile,TRUE))
  9422. {
  9423. return FALSE;
  9424. }
  9425. else
  9426. {
  9427. //check for blank entry
  9428. if (lpFile[0] == TEXT('\0'))
  9429. return TRUE;
  9430. if (issmall)
  9431. {
  9432. hRes = LoadImage(NULL,lpFile,IMAGE_ICON,16,16,LR_LOADFROMFILE);
  9433. }
  9434. else
  9435. {
  9436. hRes = LoadImage(NULL,lpFile,IMAGE_ICON,32,32,LR_LOADFROMFILE);
  9437. }
  9438. if (hRes == 0)
  9439. {
  9440. MYVERIFY(0 != LoadString(g_hInstance,IDS_INVALIDICO,szMsg,MAX_PATH));
  9441. MYVERIFY(CELEMS(szTemp2) > (UINT)wsprintf(szTemp2,szMsg,lpFile));
  9442. MessageBox(hDlg, szTemp2, g_szAppTitle, MB_OK);
  9443. SetFocus(GetDlgItem(hDlg, ctrlID));
  9444. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9445. return FALSE;
  9446. }
  9447. else
  9448. {
  9449. SendDlgItemMessage(hDlg,iconID,STM_SETIMAGE,IMAGE_ICON,(LPARAM) hRes); //lint !e534 STM_SETIMAGE doesn't return error info
  9450. }
  9451. return TRUE;
  9452. }
  9453. }
  9454. //+----------------------------------------------------------------------------
  9455. //
  9456. // Function: InitIconEntry
  9457. //
  9458. // Synopsis: This function takes a resource ID of a key under the Connection Manager
  9459. // section and retrives the value and stores it in lpFile. It then sets the text
  9460. // in the passed in edit control and verifies that the file exists. Should the
  9461. // not exist, then the string will be set to the empty string.
  9462. //
  9463. // Arguments: HWND hDlg - Window handle of the icon dialog
  9464. // LPCTSTR pszKey - the flag string of the Icon to retrieve
  9465. // LPTSTR lpFile - String buffer to write the icon path in
  9466. // UINT CtrlId - Edit Control that is supposed to receive the icon string
  9467. //
  9468. // Returns: Nothing
  9469. //
  9470. // History: quintinb Created Header 8/4/98
  9471. //
  9472. //+----------------------------------------------------------------------------
  9473. void InitIconEntry(HWND hDlg, LPCTSTR pszKey, LPTSTR lpFile, UINT CtrlId)
  9474. {
  9475. //
  9476. // The following call to GetPrivateProfileString could return a blank string, thus don't
  9477. // use the MYVERIFY macro on it.
  9478. //
  9479. ZeroMemory(lpFile, sizeof(lpFile));
  9480. GetPrivateProfileString(c_pszCmSection, pszKey, TEXT(""), lpFile,
  9481. MAX_PATH, g_szCmsFile); //lint !e534
  9482. //
  9483. // Both of the following functions will correctly handle a blank string.
  9484. //
  9485. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, CtrlId), WM_SETTEXT, 0,
  9486. (LPARAM)GetName(lpFile)));
  9487. MYVERIFY(FALSE != VerifyFile(hDlg, CtrlId, lpFile, FALSE));
  9488. }
  9489. //+----------------------------------------------------------------------------
  9490. //
  9491. // Function: RefreshIconDisplay
  9492. //
  9493. // Synopsis: This fucntion is used to refresh the icons shown on the icons page.
  9494. // It takes a path to an Icon and tries to load it. If the load fails
  9495. // or if the boolean SetDefault is set, then it loads the default icon
  9496. // specified by the Instance handle and the integer resource ID (iDefault).
  9497. // The icon is displayed to the dwControlID passed into the function.
  9498. //
  9499. // Arguments: HWND hDlg -
  9500. // HINSTANCE hInstance -
  9501. // LPTSTR szIconFile -
  9502. // int iDefault -
  9503. // int xSize -
  9504. // int ySize -
  9505. // DWORD dwControlID -
  9506. // BOOL SetDefault -
  9507. //
  9508. // Returns: Nothing
  9509. //
  9510. // History: quintinb Created Header 8/4/98
  9511. // quintinb Changed Default setting to take a resource ID instead of
  9512. // a string. Thus we won't have to ship the icon files.
  9513. //
  9514. //+----------------------------------------------------------------------------
  9515. void RefreshIconDisplay(HWND hDlg, HINSTANCE hInstance, LPTSTR szIconFile, int iDefault, int xSize, int ySize, DWORD dwControlID, BOOL SetDefault)
  9516. {
  9517. HANDLE hRes;
  9518. if (SetDefault)
  9519. {
  9520. hRes = NULL;
  9521. }
  9522. else
  9523. {
  9524. hRes = LoadImage(NULL, szIconFile, IMAGE_ICON, xSize, ySize, LR_LOADFROMFILE);
  9525. }
  9526. if (NULL == hRes)
  9527. {
  9528. //
  9529. // IF ICON IS NOT VALID OR WE WERE ASKED FOR THE DEFAULT, SO LOAD THE DEFAULT
  9530. //
  9531. hRes = LoadImage(hInstance, MAKEINTRESOURCE(iDefault), IMAGE_ICON, xSize, ySize,
  9532. LR_DEFAULTCOLOR);
  9533. }
  9534. if (NULL != hRes)
  9535. {
  9536. SendDlgItemMessage(hDlg, dwControlID, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hRes); //lint !e534 STM_SETIMAGE doesn't return error info
  9537. }
  9538. }
  9539. //+----------------------------------------------------------------------------
  9540. //
  9541. // Function: EnableCustomIconControls
  9542. //
  9543. // Synopsis: Function to enable or disable all of the controls associated with
  9544. // the custom icons. If the bEnabled value is TRUE the controls are
  9545. // enabled, otherwise the controls are disabled.
  9546. //
  9547. // Arguments: WND hDlg - window handle of the icon dialog
  9548. // BOOL bEnabled - whether the controls are enabled or disabled
  9549. //
  9550. // History: quintinb Created 11/12/99
  9551. //
  9552. //+----------------------------------------------------------------------------
  9553. void EnableCustomIconControls(HWND hDlg, BOOL bEnabled)
  9554. {
  9555. EnableWindow(GetDlgItem(hDlg, IDC_EDITLARGE), bEnabled);
  9556. EnableWindow(GetDlgItem(hDlg, IDC_LABEL1), bEnabled);
  9557. EnableWindow(GetDlgItem(hDlg, IDC_EDITSMALL), bEnabled);
  9558. EnableWindow(GetDlgItem(hDlg, IDC_LABEL2), bEnabled);
  9559. EnableWindow(GetDlgItem(hDlg, IDC_EDITTRAY), bEnabled);
  9560. EnableWindow(GetDlgItem(hDlg, IDC_LABEL3), bEnabled);
  9561. //
  9562. // Comment about using defaults for unspecified icons
  9563. //
  9564. EnableWindow(GetDlgItem(hDlg,IDC_LABEL4), bEnabled);
  9565. }
  9566. //+----------------------------------------------------------------------------
  9567. //
  9568. // Function: ProcessIcons
  9569. //
  9570. // Synopsis: Function that processes messages for the page in CMAK that allows
  9571. // the user to add custom icons to their profile.
  9572. //
  9573. // Arguments: WND hDlg - window handle of the dialog
  9574. // UINT message - message ID
  9575. // WPARAM wParam - wParam of the message
  9576. // LPARAM lParam - lParma of the message
  9577. //
  9578. //
  9579. // History: quintinb Created Header 12/5/97
  9580. // quintinb modified to handle both w16 and w32 dialogs
  9581. // quintinb added fix for 35622, custom large icon not displaying on page load
  9582. // quintinb removed 16 bit support 7-8-98
  9583. // quintinb Renamed from ProcessPage5 8-6-98
  9584. // quintinb Added EnableCustomIconControls and changed browse button
  9585. // behavior for consistency 367112 11-12-99
  9586. //
  9587. //+----------------------------------------------------------------------------
  9588. // Customize icons
  9589. INT_PTR APIENTRY ProcessIcons(
  9590. HWND hDlg,
  9591. UINT message,
  9592. WPARAM wParam,
  9593. LPARAM lParam)
  9594. {
  9595. TCHAR szTemp[MAX_PATH+1];
  9596. static TCHAR szDispLargeIco[MAX_PATH+1];
  9597. static TCHAR szDispSmallIco[MAX_PATH+1];
  9598. static TCHAR szDispTrayIco[MAX_PATH+1];
  9599. NMHDR* pnmHeader = (NMHDR*)lParam;
  9600. ProcessBold(hDlg,message);
  9601. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ICONS)) return TRUE;
  9602. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  9603. SetDefaultGUIFont(hDlg,message,IDC_EDITLARGE);
  9604. SetDefaultGUIFont(hDlg,message,IDC_EDITSMALL);
  9605. SetDefaultGUIFont(hDlg,message,IDC_EDITTRAY);
  9606. switch (message)
  9607. {
  9608. case WM_INITDIALOG:
  9609. SetFocus(GetDlgItem(hDlg, IDC_EDITLARGE));
  9610. break;
  9611. case WM_COMMAND:
  9612. switch (LOWORD(wParam))
  9613. {
  9614. case IDC_RADIO1:
  9615. EnableCustomIconControls (hDlg, FALSE);
  9616. RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, TRUE);
  9617. RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, TRUE);
  9618. RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, TRUE);
  9619. _tcscpy(szDispTrayIco,g_szTrayIco);
  9620. _tcscpy(szDispLargeIco,g_szLargeIco);
  9621. _tcscpy(szDispSmallIco,g_szSmallIco);
  9622. break;
  9623. case IDC_RADIO2:
  9624. EnableCustomIconControls (hDlg, TRUE);
  9625. if (!VerifyIcon(hDlg,IDC_EDITLARGE,g_szLargeIco,IDC_ICONLARGE,FALSE,szDispLargeIco))
  9626. {
  9627. return 1;
  9628. }
  9629. if (!VerifyIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,IDC_ICONSMALL,TRUE,szDispSmallIco))
  9630. {
  9631. return 1;
  9632. }
  9633. if (!VerifyIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,IDC_ICONTRAY,TRUE,szDispTrayIco))
  9634. {
  9635. return 1;
  9636. }
  9637. break;
  9638. case IDC_EDITLARGE:
  9639. if (HIWORD(wParam) == EN_KILLFOCUS)
  9640. {
  9641. BOOL bIconUpdated = UpdateIcon(hDlg, IDC_EDITLARGE, g_szLargeIco, FALSE);
  9642. //
  9643. // If icon wasn't updated than load the defaults
  9644. //
  9645. RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, !bIconUpdated);
  9646. return TRUE;
  9647. }
  9648. break;
  9649. case IDC_EDITSMALL:
  9650. if (HIWORD(wParam) == EN_KILLFOCUS)
  9651. {
  9652. BOOL bIconUpdated = UpdateIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,TRUE);
  9653. //
  9654. // If icon wasn't updated than load the defaults
  9655. //
  9656. RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, !bIconUpdated);
  9657. return TRUE;
  9658. }
  9659. break;
  9660. case IDC_EDITTRAY:
  9661. if (HIWORD(wParam) == EN_KILLFOCUS)
  9662. {
  9663. BOOL bIconUpdated = UpdateIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,TRUE);
  9664. //
  9665. // If icon wasn't updated than load the defaults
  9666. //
  9667. RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, !bIconUpdated);
  9668. return TRUE;
  9669. }
  9670. break;
  9671. case IDC_BROWSE1:
  9672. {
  9673. UINT uFilter = IDS_ICOFILTER;
  9674. TCHAR* szMask = TEXT("*.ico");
  9675. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9676. EnableCustomIconControls (hDlg, TRUE);
  9677. if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITLARGE, TEXT("ico"), g_szLargeIco))
  9678. {
  9679. RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, FALSE);
  9680. }
  9681. }
  9682. break;
  9683. case IDC_BROWSE2:
  9684. {
  9685. UINT uFilter = IDS_ICOFILTER;
  9686. TCHAR* szMask = TEXT("*.ico");
  9687. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9688. EnableCustomIconControls (hDlg, TRUE);
  9689. if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITSMALL, TEXT("ico"), g_szSmallIco))
  9690. {
  9691. RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, FALSE);
  9692. }
  9693. }
  9694. break;
  9695. case IDC_BROWSE3:
  9696. {
  9697. UINT uFilter = IDS_ICOFILTER;
  9698. TCHAR* szMask = TEXT("*.ico");
  9699. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9700. EnableCustomIconControls (hDlg, TRUE);
  9701. if (DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDITTRAY, TEXT("ico"), g_szTrayIco))
  9702. {
  9703. RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, FALSE);
  9704. }
  9705. }
  9706. break;
  9707. default:
  9708. break;
  9709. }
  9710. break;
  9711. case WM_NOTIFY:
  9712. if (NULL == pnmHeader)
  9713. {
  9714. return FALSE;
  9715. }
  9716. switch (pnmHeader->code)
  9717. {
  9718. case PSN_KILLACTIVE:
  9719. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  9720. return 1;
  9721. break; //lint !e527 this line isn't reachable but
  9722. // keep it in case the return is removed
  9723. case PSN_SETACTIVE:
  9724. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  9725. InitIconEntry(hDlg, c_pszCmEntryBigIcon, g_szLargeIco, IDC_EDITLARGE);
  9726. InitIconEntry(hDlg, c_pszCmEntrySmallIcon, g_szSmallIco, IDC_EDITSMALL);
  9727. InitIconEntry(hDlg, c_pszCmEntryTrayIcon, g_szTrayIco, IDC_EDITTRAY);
  9728. if ((g_szTrayIco[0] == TEXT('\0'))&&(g_szLargeIco[0] == TEXT('\0'))&&(g_szSmallIco[0] == TEXT('\0')))
  9729. {
  9730. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO1));
  9731. EnableCustomIconControls (hDlg, FALSE);
  9732. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITLARGE), WM_SETTEXT, 0, (LPARAM)GetName(szDispLargeIco)));
  9733. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITSMALL), WM_SETTEXT, 0, (LPARAM)GetName(szDispSmallIco)));
  9734. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITTRAY), WM_SETTEXT, 0, (LPARAM)GetName(szDispTrayIco)));
  9735. }
  9736. else
  9737. {
  9738. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  9739. EnableCustomIconControls (hDlg, TRUE);
  9740. }
  9741. RefreshIconDisplay(hDlg, g_hInstance, g_szLargeIco, IDI_CM_ICON, 32, 32, IDC_ICONLARGE, FALSE);
  9742. RefreshIconDisplay(hDlg, g_hInstance, g_szSmallIco, IDI_CM_ICON, 16, 16, IDC_ICONSMALL, FALSE);
  9743. RefreshIconDisplay(hDlg, g_hInstance, g_szTrayIco, IDI_CM_ICON, 16, 16, IDC_ICONTRAY, FALSE);
  9744. break;
  9745. case PSN_WIZBACK:
  9746. case PSN_WIZNEXT:
  9747. if (IsDlgButtonChecked(hDlg, IDC_RADIO1)!=BST_CHECKED)
  9748. {
  9749. if (!VerifyIcon(hDlg,IDC_EDITLARGE,g_szLargeIco,IDC_ICONLARGE,FALSE,TEXT("")))
  9750. {
  9751. return 1;
  9752. }
  9753. if (!VerifyIcon(hDlg,IDC_EDITSMALL,g_szSmallIco,IDC_ICONSMALL,TRUE,TEXT("")))
  9754. {
  9755. return 1;
  9756. }
  9757. if (!VerifyIcon(hDlg,IDC_EDITTRAY,g_szTrayIco,IDC_ICONTRAY,TRUE,TEXT("")))
  9758. {
  9759. return 1;
  9760. }
  9761. }
  9762. else
  9763. {
  9764. g_szTrayIco[0] = TEXT('\0');
  9765. g_szLargeIco[0] = TEXT('\0');
  9766. g_szSmallIco[0] = TEXT('\0');
  9767. }
  9768. // USE ICON IN CM AS ICON FOR DESKTOP IF NOT LARGE ICON SPECIFIED
  9769. if (TEXT('\0') != g_szLargeIco[0])
  9770. {
  9771. // SPECIFY ICON NAME FOR THE DESKTOP
  9772. GetFileName(g_szLargeIco,szTemp);
  9773. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopIcon, szTemp, g_szInfFile);
  9774. }
  9775. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryBigIcon, g_szLargeIco, g_szCmsFile));
  9776. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTrayIcon, g_szTrayIco, g_szCmsFile));
  9777. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntrySmallIcon, g_szSmallIco, g_szCmsFile));
  9778. //
  9779. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  9780. // (win95 only). This call will return 0.
  9781. //
  9782. WritePrivateProfileString(NULL, NULL, NULL, g_szCmsFile); //lint !e534 this call will always return 0
  9783. break;
  9784. default:
  9785. return FALSE;
  9786. }
  9787. break;
  9788. default:
  9789. return FALSE;
  9790. }
  9791. return TRUE;
  9792. }
  9793. //+----------------------------------------------------------------------------
  9794. //
  9795. // Function: ProcessPhoneBook
  9796. //
  9797. // Synopsis: Setup the phone book
  9798. //
  9799. //
  9800. // History: quintinb hid pbr browse button and edit control. Rewrote pbr/pbk logic for bug
  9801. // fix 14188 on 9-9-97
  9802. // quintinb added VerifyFileFormat check on .pbk file for bug fix 28416
  9803. // quintinb (11-18-97 29954) removed hidden pbr button and edit control from the dialog. Removed
  9804. // old verification code. Updated code to remove references to IDC_EDITREGION.
  9805. // quintinb (7-2-98) removed verifyfileformat call mentioned above because cm16 was pulled
  9806. // quintinb (8-6-98) Renamed from ProcessPage6
  9807. //+----------------------------------------------------------------------------
  9808. INT_PTR APIENTRY ProcessPhoneBook(
  9809. HWND hDlg,
  9810. UINT message,
  9811. WPARAM wParam,
  9812. LPARAM lParam)
  9813. {
  9814. TCHAR szTemp[MAX_PATH+1];
  9815. TCHAR szMsg[2*MAX_PATH+1];
  9816. TCHAR* pzTmp;
  9817. HANDLE hFile = INVALID_HANDLE_VALUE;
  9818. static TCHAR szMorePhone[MAX_PATH+1];
  9819. NMHDR* pnmHeader = (NMHDR*)lParam;
  9820. ProcessBold(hDlg,message);
  9821. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PHONEBK)) return TRUE;
  9822. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  9823. SetDefaultGUIFont(hDlg,message,IDC_EDITPHONE);
  9824. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  9825. switch (message)
  9826. {
  9827. case WM_INITDIALOG:
  9828. SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
  9829. SendDlgItemMessage(hDlg, IDC_EDIT1, EM_SETLIMITTEXT, (WPARAM)MAX_PATH, (LPARAM)0); //lint !e534 EM_SETLIMITTEXT doesn't return anything useful
  9830. break;
  9831. case WM_COMMAND:
  9832. switch (LOWORD(wParam))
  9833. {
  9834. case IDC_BROWSE1:
  9835. {
  9836. UINT uFilter = IDS_PBKFILTER;
  9837. TCHAR* szMask = TEXT("*.pbk");
  9838. MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
  9839. IDC_EDITPHONE, c_pszPbk, g_szPhonebk));
  9840. }
  9841. break;
  9842. case IDC_CHECK1:
  9843. g_bUpdatePhonebook = IsDlgButtonChecked(hDlg,IDC_CHECK1);
  9844. if (g_bUpdatePhonebook)
  9845. {
  9846. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszOne, g_szInfFile));
  9847. }
  9848. else
  9849. {
  9850. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszZero, g_szInfFile));
  9851. }
  9852. break;
  9853. default:
  9854. break;
  9855. }
  9856. break;
  9857. case WM_NOTIFY:
  9858. if (NULL == pnmHeader)
  9859. {
  9860. return FALSE;
  9861. }
  9862. switch (pnmHeader->code)
  9863. {
  9864. case PSN_KILLACTIVE:
  9865. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  9866. return 1;
  9867. break; //lint !e527 this line isn't reachable but
  9868. // keep it in case the return is removed
  9869. case PSN_SETACTIVE:
  9870. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  9871. //
  9872. // The following two calls to GetPrivateProfileString could return blank
  9873. // strings, thus we won't check the return with the MYVERIFY macro.
  9874. //
  9875. ZeroMemory(szMorePhone, sizeof(szMorePhone));
  9876. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryPbMessage, TEXT(""),
  9877. szMorePhone, CELEMS(szMorePhone), g_szCmsFile); //lint !e534
  9878. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0,
  9879. (LPARAM)szMorePhone));
  9880. ZeroMemory(g_szPhonebk, sizeof(g_szPhonebk));
  9881. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, TEXT(""),
  9882. g_szPhonebk, CELEMS(g_szPhonebk), g_szCmsFile); //lint !e534
  9883. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITPHONE), WM_SETTEXT, 0,
  9884. (LPARAM)GetName(g_szPhonebk)));
  9885. //
  9886. // The following call will handle a blank g_szPhonebk by returning FALSE and setting
  9887. // the control on the dialog to blank. Don't use MYVERIFY.
  9888. //
  9889. VerifyPhonebk(hDlg, IDC_EDITPHONE, g_szPhonebk); //lint !e534
  9890. MYVERIFY(0 != GetPrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook,
  9891. c_pszOne, szTemp, CELEMS(szTemp), g_szInfFile));
  9892. if (TEXT('1') == szTemp[0])
  9893. {
  9894. g_bUpdatePhonebook = TRUE;
  9895. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, TRUE));
  9896. }
  9897. else
  9898. {
  9899. g_bUpdatePhonebook = FALSE;
  9900. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, FALSE));
  9901. }
  9902. break;
  9903. case PSN_WIZBACK:
  9904. // fall through for further processing
  9905. case PSN_WIZNEXT:
  9906. //
  9907. // quintinb, 9-9-97 for bug fix 14188
  9908. // cases: use browse button: both up to date, shortname(g_szPhonebk) == szTemp
  9909. // type unc into edit control: szTemp up to date, g_szPhonebk = szTemp must be done
  9910. // type filename into edit control: szTemp up to date, g_szPhonebk = getcurrentdir + \\ + szTemp must be done
  9911. // unc left over from previous, both same
  9912. //
  9913. //
  9914. // get text in the edit control and put in szTemp
  9915. //
  9916. if (-1 == GetTextFromControl(hDlg, IDC_EDITPHONE, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  9917. {
  9918. SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
  9919. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9920. return 1;
  9921. }
  9922. //
  9923. // first get szTemp and g_szPhonebk consistent
  9924. //
  9925. if (szTemp[0] != TEXT('\0'))
  9926. {
  9927. //
  9928. // if in here then we know that we have some text to work with
  9929. // first test if the two strings are exactly equal or the shortname of g_szPhonebk
  9930. // equals szTemp
  9931. //
  9932. if (0 != _tcscmp(szTemp, g_szPhonebk))
  9933. {
  9934. if (0 != _tcscmp(szTemp, GetName(g_szPhonebk)))
  9935. {
  9936. //
  9937. // if not then g_szPhonebk and szTemp are out of sync, must update g_szPhonebk
  9938. // szTemp contains a backslash so it is probably a full path
  9939. //
  9940. if ( _tcsstr(szTemp, TEXT("\\")) )
  9941. {
  9942. // probably contains a unc
  9943. _tcscpy(g_szPhonebk, szTemp);
  9944. }
  9945. else
  9946. {
  9947. // use GetFullPathName to return a name
  9948. MYVERIFY(0 != GetFullPathName(szTemp, MAX_PATH, g_szPhonebk, &pzTmp));
  9949. }
  9950. }
  9951. }
  9952. //
  9953. // Okay, check that we can open the file now. We need
  9954. // to change the current dir to the cmak dir since
  9955. // g_szPhonebk can be a relative path from a CMS file
  9956. //
  9957. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH+1, szTemp));
  9958. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  9959. hFile = CreateFile(g_szPhonebk,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  9960. //
  9961. // Restore the cur dir
  9962. //
  9963. MYVERIFY(0 != SetCurrentDirectory(szTemp));
  9964. if (INVALID_HANDLE_VALUE == hFile)
  9965. {
  9966. // then we have an error and have exhausted our possibilities
  9967. //
  9968. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_BADOUTEXE, MB_OK));
  9969. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9970. return 1;
  9971. }
  9972. MYVERIFY(0 != CloseHandle(hFile));
  9973. //
  9974. // if we got here then everything is sync-ed, make sure that the file is a pbk file
  9975. //
  9976. pzTmp = g_szPhonebk + _tcslen(g_szPhonebk) - _tcslen(c_pszPbk);
  9977. if (_tcsicmp(pzTmp, c_pszPbk) != 0)
  9978. {
  9979. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOTPBK, MB_OK));
  9980. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  9981. return 1;
  9982. }
  9983. //
  9984. // now update the pbr file entry
  9985. //
  9986. _tcscpy(g_szRegion, g_szPhonebk);
  9987. pzTmp = g_szRegion + _tcslen(g_szPhonebk) - _tcslen(c_pszPbk);
  9988. _tcscpy(pzTmp, TEXT("pbr"));
  9989. // removed for 29954
  9990. //SendMessage(GetDlgItem(hDlg, IDC_EDITREGION), WM_SETTEXT, 0, (LPARAM)GetName(g_szRegion));
  9991. //
  9992. // Now open the pbr file to see that it exists. We need
  9993. // to change the current dir to the cmak dir since
  9994. // g_szPhonebk can be a relative path from a CMS file.
  9995. //
  9996. MYVERIFY(0 != GetCurrentDirectory(MAX_PATH+1, szTemp));
  9997. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  9998. hFile = CreateFile(g_szRegion,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  9999. //
  10000. // Restore the current directory
  10001. //
  10002. MYVERIFY(0 != SetCurrentDirectory(szTemp));
  10003. if (INVALID_HANDLE_VALUE == hFile)
  10004. {
  10005. //
  10006. // then we can't find the pbr file
  10007. //
  10008. MYVERIFY(0 != LoadString(g_hInstance,IDS_NEEDSPBR,szTemp,MAX_PATH));
  10009. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, GetName(g_szRegion), g_szPhonebk, GetName(g_szRegion)));
  10010. MessageBox(hDlg, szMsg, g_szAppTitle, MB_OK);
  10011. SetFocus(GetDlgItem(hDlg, IDC_EDITPHONE));
  10012. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10013. return 1;
  10014. }
  10015. MYVERIFY(0 != CloseHandle(hFile));
  10016. }
  10017. else
  10018. {
  10019. //
  10020. // just in case user wants to clear out the phonebk edit control
  10021. //
  10022. g_szPhonebk[0] = TEXT('\0');
  10023. g_szRegion[0] = TEXT('\0');
  10024. }
  10025. // end bugfix for 14188
  10026. if (g_bUpdatePhonebook)
  10027. {
  10028. GetFileName(g_szPhonebk, szTemp);
  10029. if (FALSE == IsFile8dot3(szTemp))
  10030. {
  10031. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_BADPBNAME, szTemp);
  10032. if (pszMsg)
  10033. {
  10034. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  10035. CmFree(pszMsg);
  10036. }
  10037. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10038. return 1;
  10039. }
  10040. }
  10041. // end of changes for 28416
  10042. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  10043. {
  10044. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10045. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10046. return 1;
  10047. }
  10048. CmStrTrim(szTemp);
  10049. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
  10050. _tcscpy(szMorePhone,szTemp);
  10051. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPbMessage, szMorePhone, g_szCmsFile));
  10052. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, g_szPhonebk, g_szCmsFile));
  10053. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, g_szRegion, g_szCmsFile));
  10054. if (pnmHeader && (PSN_WIZBACK == pnmHeader->code))
  10055. {
  10056. if (g_bUseTunneling)
  10057. {
  10058. //
  10059. // If we are going back, skip the Pre-shared key page if
  10060. // no DUN entries have Preshared key enabled.
  10061. //
  10062. // Note: g_bPresharedKeyNeeded should be current here, no need
  10063. // to call DoesSomeVPNsettingUsePresharedKey()
  10064. //
  10065. if (!g_bPresharedKeyNeeded)
  10066. {
  10067. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_VPN_ENTRIES));
  10068. }
  10069. }
  10070. else
  10071. {
  10072. //
  10073. // If we are going back, skip the VPN entries dialog if we don't have any tunneling enabled.
  10074. //
  10075. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_TUNNELING));
  10076. }
  10077. }
  10078. //
  10079. // If we are going forward, skip the phonebook update page unless we are doing the PB download
  10080. //
  10081. if (pnmHeader && (PSN_WIZNEXT == pnmHeader->code) && !g_bUpdatePhonebook)
  10082. {
  10083. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_DUN_ENTRIES));
  10084. }
  10085. break;
  10086. default:
  10087. return FALSE;
  10088. }
  10089. break;
  10090. default:
  10091. return FALSE;
  10092. }
  10093. return TRUE;
  10094. }
  10095. //+----------------------------------------------------------------------------
  10096. //
  10097. // Function: ProcessPhoneBookUpdate
  10098. //
  10099. // Synopsis: Specify Phone Book Files and Updates
  10100. //
  10101. //
  10102. // History: Created Header 8/6/98
  10103. // quintinb Renamed from ProcessPage6A 8/6/98
  10104. //
  10105. //+----------------------------------------------------------------------------
  10106. INT_PTR APIENTRY ProcessPhoneBookUpdate(
  10107. HWND hDlg,
  10108. UINT message,
  10109. WPARAM wParam,
  10110. LPARAM lParam)
  10111. {
  10112. TCHAR szTemp[MAX_PATH+1];
  10113. int j, iLen;
  10114. LPTSTR pUrl,pch;
  10115. BOOL showerr;
  10116. NMHDR* pnmHeader = (NMHDR*)lParam;
  10117. ProcessBold(hDlg,message);
  10118. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_PHONEBK)) return TRUE;
  10119. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  10120. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  10121. SetDefaultGUIFont(hDlg,message,IDC_EDITURL);
  10122. switch (message)
  10123. {
  10124. case WM_INITDIALOG:
  10125. SendDlgItemMessage(hDlg, IDC_EDITURL, EM_SETLIMITTEXT, (WPARAM)(MAX_PATH - 50), (LPARAM)0);//lint !e534 EM_SETLIMITTEXT doesn't return anything useful
  10126. break;
  10127. case WM_NOTIFY:
  10128. if (NULL == pnmHeader)
  10129. {
  10130. return FALSE;
  10131. }
  10132. switch (pnmHeader->code)
  10133. {
  10134. case PSN_SETACTIVE:
  10135. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  10136. //
  10137. // The following two calls to GetPrivateProfileString could return an empty
  10138. // string. We shouldn't use MYVERIFY on the return code.
  10139. //
  10140. ZeroMemory(g_szPhoneName, sizeof(g_szPhoneName));
  10141. ZeroMemory(g_szUrl,sizeof(g_szUrl));
  10142. GetPrivateProfileString(c_pszCmakStatus, c_pszPhoneName, TEXT(""),
  10143. g_szPhoneName, CELEMS(g_szPhoneName), g_szInfFile); //lint !e534
  10144. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), g_szUrl,
  10145. CELEMS(g_szUrl), g_szCmsFile); //lint !e534
  10146. // skip past initial http://
  10147. if (*g_szUrl)
  10148. {
  10149. pUrl = _tcsstr(g_szUrl, c_pszCpsUrl);
  10150. if (pUrl)
  10151. {
  10152. *pUrl = 0; //chop off dll filename
  10153. }
  10154. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITURL), WM_SETTEXT, 0, (LPARAM)&g_szUrl[7]));
  10155. }
  10156. else
  10157. {
  10158. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITURL), WM_SETTEXT, 0, (LPARAM)TEXT("")));
  10159. }
  10160. if (*g_szPhonebk)
  10161. {
  10162. GetBaseName(g_szPhonebk,szTemp);
  10163. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) szTemp));
  10164. EnableWindow(GetDlgItem(hDlg,IDC_EDIT1),FALSE);
  10165. }
  10166. else
  10167. {
  10168. EnableWindow(GetDlgItem(hDlg, IDC_EDIT1), TRUE);
  10169. if (*g_szPhoneName)
  10170. {
  10171. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) g_szPhoneName));
  10172. }
  10173. else
  10174. {
  10175. MYVERIFY(TRUE == SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM) TEXT("")));
  10176. }
  10177. }
  10178. break;
  10179. case PSN_WIZBACK:
  10180. case PSN_WIZNEXT:
  10181. showerr = (pnmHeader && (PSN_WIZNEXT == pnmHeader->code));
  10182. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, g_szPhoneName, MAX_PATH, TRUE)) // bDisplayError == TRUE
  10183. {
  10184. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10185. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10186. return 1;
  10187. }
  10188. // if ((g_szPhoneName[0] == TEXT('\0')) && (g_pHeadMerge == NULL) && showerr) - 20094
  10189. if ((g_szPhoneName[0] == TEXT('\0')) && showerr)
  10190. {
  10191. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEEDPHONENAME, MB_OK));
  10192. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10193. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10194. return 1;
  10195. }
  10196. iLen = lstrlen(g_szBadFilenameChars);
  10197. pch = g_szPhoneName;
  10198. while(*pch != _T('\0'))
  10199. {
  10200. for (j = 0; j < iLen; ++j)
  10201. {
  10202. if ((*pch == g_szBadFilenameChars[j]) && showerr)
  10203. {
  10204. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PHONENAMEERR, g_szBadFilenameChars);
  10205. if (pszMsg)
  10206. {
  10207. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  10208. CmFree(pszMsg);
  10209. }
  10210. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10211. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10212. return 1;
  10213. }
  10214. }
  10215. pch = CharNext(pch);
  10216. }
  10217. //
  10218. // Note that 8.3 means 8 bytes not 8 Characters. Thus we have a limit of 4 DBCS
  10219. // characters.
  10220. //
  10221. #ifdef UNICODE
  10222. LPSTR pszAnsiPhoneName;
  10223. pszAnsiPhoneName = WzToSzWithAlloc(g_szPhoneName);
  10224. if ((lstrlenA(pszAnsiPhoneName) > 8) && showerr)
  10225. #else
  10226. if ((strlen(g_szPhoneName) > 8) && showerr)
  10227. #endif
  10228. {
  10229. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_PHONENAMEERR, g_szBadFilenameChars);
  10230. if (pszMsg)
  10231. {
  10232. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  10233. CmFree(pszMsg);
  10234. }
  10235. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10236. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10237. return 1;
  10238. }
  10239. #ifdef UNICODE
  10240. CmFree(pszAnsiPhoneName);
  10241. #endif
  10242. if (-1 == GetTextFromControl(hDlg, IDC_EDITURL, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  10243. {
  10244. SetFocus(GetDlgItem(hDlg, IDC_EDITURL));
  10245. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10246. return 1;
  10247. }
  10248. if (szTemp[0] != TEXT('\0'))
  10249. {
  10250. MYVERIFY(CELEMS(g_szUrl) > (UINT)wsprintf(g_szUrl, TEXT("http://%s%s"), szTemp, c_pszCpsUrl));
  10251. }
  10252. else
  10253. {
  10254. g_szUrl[0] = TEXT('\0');
  10255. }
  10256. if ((g_szUrl[0] == TEXT('\0')) && showerr)
  10257. {
  10258. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOURL, MB_OK));
  10259. SetFocus(GetDlgItem(hDlg, IDC_EDITURL));
  10260. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10261. return 1;
  10262. }
  10263. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszPhoneName, g_szPhoneName, g_szInfFile));
  10264. if (TEXT('\0') != g_szUrl[0])
  10265. {
  10266. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,c_pszCmEntryIspUrl,g_szUrl,g_szCmsFile));
  10267. }
  10268. else
  10269. {
  10270. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,c_pszCmEntryIspUrl,TEXT(""),g_szCmsFile));
  10271. }
  10272. // the Next button was pressed or the back button was pressed
  10273. break;
  10274. default:
  10275. return FALSE;
  10276. }
  10277. break;
  10278. default:
  10279. return FALSE;
  10280. }
  10281. return TRUE;
  10282. }
  10283. //+----------------------------------------------------------------------------
  10284. //
  10285. // Function: RemoveReferencesFromCMS
  10286. //
  10287. // Synopsis: This function searches for any previous References line in
  10288. // the ISP section of the cms file. If it finds a References
  10289. // line, then it parses it to find what other profiles are
  10290. // mentioned in the CMS. Then it will search for and remove
  10291. // any of the following lines in the ISP section that correspond
  10292. // to these references:
  10293. // CMSFile&test2=test3\test2.cms
  10294. // FilterA&test2=NosurchargeSignon
  10295. // FilterB&test2=SurchargeSignon
  10296. //
  10297. // note the function removes the reference line itself too.
  10298. //
  10299. // Arguments: None
  10300. //
  10301. // Returns: Nothing
  10302. //
  10303. // History: quintinb created for bug fix 10537 8/28/97
  10304. //
  10305. //+----------------------------------------------------------------------------
  10306. void RemoveReferencesFromCMS()
  10307. {
  10308. TCHAR szKey[MAX_PATH+1];
  10309. TCHAR szReferences[MAX_PATH+1];
  10310. TCHAR* pszToken;
  10311. DWORD dwNumChars;
  10312. dwNumChars = GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, TEXT(""),
  10313. szReferences,MAX_PATH, g_szCmsFile);
  10314. if ((dwNumChars >0) && (TEXT('\0') != szReferences[0]))
  10315. {
  10316. // I have references, so we must parse them out and delete them
  10317. pszToken = _tcstok( szReferences, TEXT(" "));
  10318. while( pszToken != NULL )
  10319. {
  10320. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
  10321. c_pszCmEntryIspCmsFile, pszToken));
  10322. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
  10323. g_szCmsFile));
  10324. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
  10325. c_pszCmEntryIspFilterA, pszToken));
  10326. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
  10327. g_szCmsFile));
  10328. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"),
  10329. c_pszCmEntryIspFilterB, pszToken));
  10330. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, NULL,
  10331. g_szCmsFile));
  10332. pszToken = _tcstok( NULL, TEXT(" ") );
  10333. }
  10334. // after deleting the individual keys, must delete the references line itself
  10335. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, NULL, g_szCmsFile));
  10336. }
  10337. }
  10338. //+----------------------------------------------------------------------------
  10339. //
  10340. // Function: RefreshDualingListBoxes
  10341. //
  10342. // Synopsis: This function refreshes two listboxes from the given two linked
  10343. // lists. The destination listbox is filled from the destination
  10344. // linked list and then the source listbox is filled with all of the
  10345. // items in the source linked list that don't appear in the destination
  10346. // linked list and that aren't the name of the current profile to edit.
  10347. // Thus you effectively have one list where the items either show up
  10348. // in the source listbox or the destination listbox. Please note that
  10349. // there is one exception with the merged profile lists that this
  10350. // code was created for (items can exist in the merged list that we
  10351. // don't have profile source from, see the Delete/Remove code in
  10352. // ProcessMergedProfiles for more details). Also note that we
  10353. // enable/disable the corresponding Add and Remove buttons depending
  10354. // on the state of the lists.
  10355. //
  10356. //
  10357. // Arguments: HWND hDlg - window handle of the dialog containing all of the controls
  10358. // UINT uSourceListControlId - control id of the source listbox
  10359. // UINT uDestListControlId - control id of the dest listbox
  10360. // ListBxList* pSourceList - linked list to fill the source listbox from
  10361. // ListBxList* pDestList - linked list to fill the dest listbox from
  10362. // LPCTSTR pszShortName - short service name of the current profile
  10363. // UINT uAddCtrlId - control id of the Add button (add from source to dest)
  10364. // UINT uRemoveCtrlId - control id of the remove button (remove from dest to source)
  10365. //
  10366. // Returns: BOOL - TRUE if successful
  10367. //
  10368. // History: quintinb created 03/09/00
  10369. //
  10370. //+----------------------------------------------------------------------------
  10371. BOOL RefreshDualingListBoxes(HWND hDlg, UINT uSourceListControlId, UINT uDestListControlId, ListBxList* pSourceList, ListBxList* pDestList, LPCTSTR pszShortName, UINT uAddCtrlId, UINT uRemoveCtrlId)
  10372. {
  10373. if ((NULL == hDlg) || (0 == uSourceListControlId) || (0 == uDestListControlId))
  10374. {
  10375. CMASSERTMSG(FALSE, TEXT("RefreshDualingListBoxes -- Invalid argument passed"));
  10376. return FALSE;
  10377. }
  10378. //
  10379. // Reset both of the listboxes
  10380. //
  10381. LRESULT lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
  10382. MYDBGASSERT(LB_ERR != lResult);
  10383. lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
  10384. MYDBGASSERT(LB_ERR != lResult);
  10385. //
  10386. // Add the destination items to the destination listbox
  10387. //
  10388. ListBxList* pCurrent = pDestList;
  10389. while (pCurrent)
  10390. {
  10391. lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_ADDSTRING, (WPARAM)0, (LPARAM)pCurrent->szName);
  10392. MYDBGASSERT(LB_ERR != lResult);
  10393. pCurrent = pCurrent->next;
  10394. }
  10395. //
  10396. // Add the source items to the source listbox, making sure to filter out items that are already
  10397. // in the destination list
  10398. //
  10399. pCurrent = pSourceList;
  10400. while (pCurrent)
  10401. {
  10402. if ((FALSE == FindListItemByName(pCurrent->szName, pDestList, NULL)) && (0 != lstrcmpi(pCurrent->szName, pszShortName)))
  10403. {
  10404. lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_ADDSTRING, (WPARAM)0, (LPARAM)pCurrent->szName);
  10405. MYDBGASSERT(LB_ERR != lResult);
  10406. }
  10407. pCurrent = pCurrent->next;
  10408. }
  10409. //
  10410. // Now that we have refreshed the list, we need to update the button and selection status.
  10411. // If the source list is empty, then we cannot do any Adds. On the other
  10412. // hand if the dest list is empty, then we cannot do any deletes.
  10413. //
  10414. HWND hAddControl = GetDlgItem(hDlg, uAddCtrlId);
  10415. HWND hRemoveControl = GetDlgItem(hDlg, uRemoveCtrlId);
  10416. HWND hCurrentFocus = GetFocus();
  10417. lResult = SendDlgItemMessage(hDlg, uSourceListControlId, LB_GETCOUNT, 0, (LPARAM)0);
  10418. BOOL bListNotEmpty = ((LB_ERR != lResult) && (0 != lResult));
  10419. EnableWindow(hAddControl, bListNotEmpty);
  10420. if (bListNotEmpty)
  10421. {
  10422. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, uSourceListControlId, LB_SETCURSEL, 0, (LPARAM)0));
  10423. }
  10424. //
  10425. // Now check the destination list and the Remove button
  10426. //
  10427. lResult = SendDlgItemMessage(hDlg, uDestListControlId, LB_GETCOUNT, 0, (LPARAM)0);
  10428. bListNotEmpty = ((LB_ERR != lResult) && (0 != lResult));
  10429. EnableWindow(hRemoveControl, bListNotEmpty);
  10430. if (bListNotEmpty)
  10431. {
  10432. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, uDestListControlId, LB_SETCURSEL, 0, (LPARAM)0));
  10433. }
  10434. //
  10435. // Figure out if we need to shift the focus because we just disabled the control that had it.
  10436. //
  10437. if (FALSE == IsWindowEnabled(hCurrentFocus))
  10438. {
  10439. if ((hAddControl == hCurrentFocus) && IsWindowEnabled(hRemoveControl))
  10440. {
  10441. SendMessage(hDlg, DM_SETDEFID, uRemoveCtrlId, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  10442. SetFocus(hRemoveControl);
  10443. }
  10444. else if ((hRemoveControl == hCurrentFocus) && IsWindowEnabled(hAddControl))
  10445. {
  10446. SendMessage(hDlg, DM_SETDEFID, uAddCtrlId, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  10447. SetFocus(hAddControl);
  10448. }
  10449. else
  10450. {
  10451. SetFocus(GetDlgItem(hDlg, uSourceListControlId));
  10452. }
  10453. }
  10454. return TRUE;
  10455. }
  10456. void OnProcessMergedProfilesAdd(HWND hDlg)
  10457. {
  10458. TCHAR szTemp[MAX_PATH+1];
  10459. LRESULT lResult;
  10460. //
  10461. // Get the current selection from the listbox containing the items
  10462. // to merge.
  10463. //
  10464. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
  10465. if (lResult != LB_ERR)
  10466. {
  10467. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT,
  10468. (WPARAM)lResult, (LPARAM)szTemp);
  10469. if (lResult != LB_ERR)
  10470. {
  10471. MYVERIFY(FALSE != createListBxRecord(&g_pHeadMerge, &g_pTailMerge, NULL, 0, szTemp));
  10472. MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
  10473. g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
  10474. }
  10475. }
  10476. }
  10477. void OnProcessMergedProfilesRemove(HWND hDlg)
  10478. {
  10479. TCHAR szTemp[MAX_PATH+1];
  10480. LRESULT lResult;
  10481. //
  10482. // Get the listbox selection from the already merged in list
  10483. //
  10484. lResult = SendDlgItemMessage(hDlg, IDC_LIST2, LB_GETCURSEL, 0, (LPARAM)0);
  10485. if (LB_ERR == lResult)
  10486. {
  10487. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  10488. }
  10489. else
  10490. {
  10491. //
  10492. // Get the name of the profile to remove from the merge list
  10493. //
  10494. lResult = SendDlgItemMessage(hDlg, IDC_LIST2, LB_GETTEXT, (WPARAM)lResult, (LPARAM)szTemp);
  10495. if (LB_ERR != lResult)
  10496. {
  10497. //
  10498. // Check to see if this is an item in the Profile list. If not, the user
  10499. // will not be able to add it back.
  10500. //
  10501. int iReturnValue = IDYES;
  10502. if (FALSE == FindListItemByName(szTemp, g_pHeadProfile, NULL)) // NULL because we don't need a pointer to the list item returned
  10503. {
  10504. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_NOTINPROFILELIST, szTemp, szTemp, szTemp);
  10505. if (pszMsg)
  10506. {
  10507. iReturnValue = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
  10508. CmFree(pszMsg);
  10509. }
  10510. }
  10511. if (IDYES == iReturnValue)
  10512. {
  10513. //
  10514. // Delete it from the merged profile linked list
  10515. //
  10516. DeleteListBxRecord(&g_pHeadMerge, &g_pTailMerge, szTemp);
  10517. //
  10518. // Remove it from the UI
  10519. //
  10520. MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
  10521. g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
  10522. }
  10523. }
  10524. }
  10525. }
  10526. //+----------------------------------------------------------------------------
  10527. //
  10528. // Function: ProcessMergedProfiles
  10529. //
  10530. // Synopsis: Merge Profiles
  10531. //
  10532. // History: quintinb Created Header and renamed from ProcessPage6B 8/6/98
  10533. //
  10534. //+----------------------------------------------------------------------------
  10535. INT_PTR APIENTRY ProcessMergedProfiles(
  10536. HWND hDlg,
  10537. UINT message,
  10538. WPARAM wParam,
  10539. LPARAM lParam)
  10540. {
  10541. NMHDR* pnmHeader = (NMHDR*)lParam;
  10542. ProcessBold(hDlg,message);
  10543. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_MERGE)) return TRUE;
  10544. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  10545. SetDefaultGUIFont(hDlg,message,IDC_LIST1);
  10546. SetDefaultGUIFont(hDlg,message,IDC_LIST2);
  10547. switch (message)
  10548. {
  10549. case WM_COMMAND:
  10550. switch (LOWORD(wParam))
  10551. {
  10552. case IDC_BUTTON1: //add
  10553. OnProcessMergedProfilesAdd(hDlg);
  10554. return TRUE;
  10555. break; //lint !e527 this line isn't reachable but
  10556. // keep it in case the return is removed
  10557. case IDC_BUTTON2: //remove
  10558. OnProcessMergedProfilesRemove(hDlg);
  10559. return TRUE;
  10560. break; //lint !e527 this line isn't reachable but
  10561. // keep it in case the return is removed
  10562. case IDC_LIST1:
  10563. if (LBN_DBLCLK == HIWORD(wParam))
  10564. {
  10565. OnProcessMergedProfilesAdd(hDlg);
  10566. return TRUE;
  10567. }
  10568. break;
  10569. case IDC_LIST2:
  10570. if (LBN_DBLCLK == HIWORD(wParam))
  10571. {
  10572. OnProcessMergedProfilesRemove(hDlg);
  10573. return TRUE;
  10574. }
  10575. break;
  10576. default:
  10577. break;
  10578. }
  10579. break;
  10580. case WM_NOTIFY:
  10581. if (NULL == pnmHeader)
  10582. {
  10583. return FALSE;
  10584. }
  10585. switch (pnmHeader->code)
  10586. {
  10587. case PSN_KILLACTIVE:
  10588. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  10589. return 1;
  10590. break; //lint !e527 this line isn't reachable but
  10591. // keep it in case the return is removed
  10592. case PSN_SETACTIVE:
  10593. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  10594. //
  10595. // First lets setup the list of profiles that are actually merged into the
  10596. // profile. First step is to read in the merged profile list from the profile.
  10597. //
  10598. ReadMergeList();
  10599. //
  10600. // Now delete the merged profile list and any filter/cms references from the profile.
  10601. //
  10602. RemoveReferencesFromCMS();
  10603. //
  10604. // Refresh the two list boxes
  10605. //
  10606. MYVERIFY(RefreshDualingListBoxes(hDlg, IDC_LIST1, IDC_LIST2, g_pHeadProfile,
  10607. g_pHeadMerge, g_szShortServiceName, IDC_BUTTON1, IDC_BUTTON2));
  10608. break;
  10609. case PSN_WIZBACK:
  10610. case PSN_WIZNEXT:
  10611. WriteMergeList();
  10612. break;
  10613. default:
  10614. return FALSE;
  10615. }
  10616. break;
  10617. default:
  10618. return FALSE;
  10619. }
  10620. return TRUE;
  10621. }
  10622. BOOL CreateMergedProfile()
  10623. {
  10624. ListBxList * LoopPtr;
  10625. TCHAR szReferences[MAX_PATH+1];
  10626. LPTSTR pszName;
  10627. TCHAR szEntry[MAX_PATH+1];
  10628. TCHAR szFile[MAX_PATH+1];
  10629. TCHAR szKey[MAX_PATH+1];
  10630. TCHAR szTemp[MAX_PATH+1];
  10631. TCHAR szDest[MAX_PATH+1];
  10632. szReferences[0] = TEXT('\0');
  10633. if (g_pHeadMerge == NULL)
  10634. {
  10635. return TRUE;
  10636. }
  10637. LoopPtr = g_pHeadMerge;
  10638. while( LoopPtr != NULL)
  10639. {
  10640. pszName = LoopPtr->szName;
  10641. _tcscat(szReferences, pszName);
  10642. _tcscat(szReferences, TEXT(" "));
  10643. MYDBGASSERT(_tcslen(szReferences) <= CELEMS(szReferences));
  10644. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cms"), g_szOsdir, pszName, pszName));
  10645. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s.cms"), g_szOutdir, pszName));
  10646. // COPY CMS FILE
  10647. //
  10648. // First check to see if the profile exists in profile directory
  10649. //
  10650. if (!FileExists(szTemp))
  10651. {
  10652. //
  10653. // Couldn't open it in the profile dir, lets try in the temp dir
  10654. //
  10655. if (!FileExists(szDest))
  10656. {
  10657. FileAccessErr(NULL, szDest);
  10658. return FALSE;
  10659. }
  10660. }
  10661. else
  10662. {
  10663. if (!CopyFileWrapper(szTemp, szDest, FALSE))
  10664. {
  10665. return FALSE;
  10666. }
  10667. }
  10668. MYVERIFY(0 != SetFileAttributes(szDest,FILE_ATTRIBUTE_NORMAL));
  10669. MYVERIFY(FALSE != MoveCmsFile(szDest, g_szShortServiceName));
  10670. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s.cms"), pszName));
  10671. MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs,&g_pTailRefs,(void *)NULL,0,szTemp));
  10672. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"), g_szShortServiceName, pszName));
  10673. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspCmsFile, pszName));
  10674. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp,szKey,szTemp,g_szCmsFile));
  10675. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspFilterA,
  10676. pszName));
  10677. // only write if it doesn't exist
  10678. //
  10679. // The following call to GetPrivateProfileString could return a blank string, thus we don't
  10680. // use the MYVERIFY macro on it.
  10681. //
  10682. ZeroMemory(szTemp, sizeof(szTemp));
  10683. GetPrivateProfileString(c_pszCmSectionIsp, szKey, TEXT(""), szTemp, CELEMS(szTemp),
  10684. g_szCmsFile); //lint !e534
  10685. if (TEXT('\0') == szTemp[0])
  10686. {
  10687. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, TEXT("NosurchargeSignon"),
  10688. g_szCmsFile));
  10689. }
  10690. MYVERIFY(CELEMS(szKey) > (UINT)wsprintf(szKey, TEXT("%s%s"), c_pszCmEntryIspFilterB,
  10691. pszName));
  10692. //
  10693. // The following call to GetPrivateProfileString could return a blank string, thus we shouldn't
  10694. // check its return code with MYVERIFY.
  10695. //
  10696. GetPrivateProfileString(c_pszCmSectionIsp, szKey, TEXT(""), szTemp, CELEMS(szTemp),
  10697. g_szCmsFile); //lint !e534
  10698. if (TEXT('\0') == szTemp[0])
  10699. {
  10700. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, szKey, TEXT("SurchargeSignon"),
  10701. g_szCmsFile));
  10702. }
  10703. MYVERIFY(0 != SetCurrentDirectory(g_szOsdir));
  10704. // COPY PHONEBOOK
  10705. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, TEXT(""), szEntry,
  10706. CELEMS(szEntry), szDest); //lint !e534 could return EMPTY string
  10707. GetFileName(szEntry,szFile);
  10708. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szOutdir, szFile));
  10709. if (CopyFile(szEntry,szTemp,FALSE))
  10710. {
  10711. MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs, &g_pTailRefs, (void *)NULL, 0, szFile));
  10712. MYVERIFY(0 != SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL));
  10713. }
  10714. //
  10715. // DO NOT REPORT AN ERROR IF COULDN'T FIND PHONEBOOK, IT IS OPTIONAL
  10716. //
  10717. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szShortServiceName, szFile));
  10718. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspPbFile, szTemp,
  10719. szDest));
  10720. // COPY REGIONS
  10721. GetPrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, TEXT(""), szEntry,
  10722. CELEMS(szEntry), szDest); //lint !e534
  10723. GetFileName(szEntry,szFile);
  10724. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szOutdir, szFile));
  10725. if (CopyFile(szEntry,szTemp,FALSE))
  10726. {
  10727. MYVERIFY(FALSE != createListBxRecord(&g_pHeadRefs,&g_pTailRefs,(void *)NULL,0,szFile));
  10728. MYVERIFY(0 != SetFileAttributes(szTemp,FILE_ATTRIBUTE_NORMAL));
  10729. }
  10730. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), g_szShortServiceName, szFile));
  10731. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspRegionFile, szTemp, szDest));
  10732. LoopPtr = LoopPtr->next;
  10733. }
  10734. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspReferences, szReferences, g_szCmsFile));
  10735. return TRUE;
  10736. }
  10737. //+----------------------------------------------------------------------------
  10738. //
  10739. // Function: ProcessCustomHelp
  10740. //
  10741. // Synopsis: Set up windows help
  10742. //
  10743. //
  10744. // History: quintinb Created Header and renamed from ProcessPage7 8/6/98
  10745. //
  10746. //+----------------------------------------------------------------------------
  10747. INT_PTR APIENTRY ProcessCustomHelp(
  10748. HWND hDlg,
  10749. UINT message,
  10750. WPARAM wParam,
  10751. LPARAM lParam)
  10752. {
  10753. TCHAR szTemp[MAX_PATH+1];
  10754. static TCHAR szDisplay[MAX_PATH+1]; // keeps unselected custom entry
  10755. NMHDR* pnmHeader = (NMHDR*)lParam;
  10756. ProcessBold(hDlg,message);
  10757. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CMHELP)) return TRUE;
  10758. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  10759. SetDefaultGUIFont(hDlg,message,IDC_EDITHELP);
  10760. switch (message)
  10761. {
  10762. case WM_INITDIALOG:
  10763. SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
  10764. break;
  10765. case WM_COMMAND:
  10766. switch (LOWORD(wParam))
  10767. {
  10768. case IDC_RADIO1:
  10769. EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),FALSE);
  10770. _tcscpy(szDisplay,g_szHelp);
  10771. break;
  10772. case IDC_RADIO2:
  10773. EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
  10774. if (!(*g_szHelp) && (*szDisplay))
  10775. {
  10776. _tcscpy(g_szHelp,szDisplay);
  10777. }
  10778. break;
  10779. case IDC_BROWSE1:
  10780. {
  10781. EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
  10782. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  10783. UINT uFilter = IDS_HLPFILTER;
  10784. TCHAR* szMask = TEXT("*.hlp");
  10785. MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1,
  10786. IDC_EDITHELP, TEXT("hlp"), g_szHelp));
  10787. }
  10788. break;
  10789. default:
  10790. break;
  10791. }
  10792. break;
  10793. case WM_NOTIFY:
  10794. if (NULL == pnmHeader)
  10795. {
  10796. return FALSE;
  10797. }
  10798. switch (pnmHeader->code)
  10799. {
  10800. case PSN_KILLACTIVE:
  10801. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  10802. return 1;
  10803. break; //lint !e527 this line isn't reachable but
  10804. // keep it in case the return is removed
  10805. case PSN_SETACTIVE:
  10806. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  10807. //
  10808. // The following call to GetPrivateProfileString could return an empty string
  10809. // thus we shouldn't check the return code with MYVERIFY.
  10810. //
  10811. ZeroMemory(g_szHelp, sizeof(g_szHelp));
  10812. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryHelpFile, TEXT(""),
  10813. g_szHelp, CELEMS(g_szHelp), g_szCmsFile); //lint !e534
  10814. if (TEXT('\0') == g_szHelp[0])
  10815. {
  10816. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO1));
  10817. EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),FALSE);
  10818. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITHELP), WM_SETTEXT, 0, (LPARAM)GetName(szDisplay)));
  10819. }
  10820. else
  10821. {
  10822. MYVERIFY(0 != CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO2,IDC_RADIO2));
  10823. EnableWindow(GetDlgItem(hDlg,IDC_EDITHELP),TRUE);
  10824. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDITHELP), WM_SETTEXT, 0, (LPARAM)GetName(g_szHelp)));
  10825. MYVERIFY(FALSE != VerifyFile(hDlg,IDC_EDITHELP,g_szHelp,FALSE));
  10826. }
  10827. break;
  10828. case PSN_WIZBACK:
  10829. case PSN_WIZNEXT:
  10830. // the Next button was pressed
  10831. if (IsDlgButtonChecked(hDlg, IDC_RADIO2)==BST_CHECKED)
  10832. {
  10833. if (-1 == GetTextFromControl(hDlg, IDC_EDITHELP, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  10834. {
  10835. SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
  10836. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10837. return 1;
  10838. }
  10839. if (!VerifyFile(hDlg,IDC_EDITHELP,g_szHelp,TRUE))
  10840. {
  10841. if (g_szHelp[0] != TEXT('\0'))
  10842. {
  10843. return 1;
  10844. }
  10845. }
  10846. if (g_szHelp[0] == TEXT('\0'))
  10847. {
  10848. MYVERIFY(IDOK == ShowMessage(hDlg,IDS_NOHELP,MB_OK));
  10849. SetFocus(GetDlgItem(hDlg, IDC_EDITHELP));
  10850. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10851. return 1;
  10852. }
  10853. }
  10854. else
  10855. {
  10856. g_szHelp[0] = TEXT('\0');
  10857. }
  10858. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryHelpFile, g_szHelp, g_szCmsFile));
  10859. //
  10860. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  10861. // (win95 only). This call will return 0.
  10862. //
  10863. WritePrivateProfileString(NULL, NULL, NULL, g_szCmsFile); //lint !e534 this call will always return 0
  10864. break;
  10865. default:
  10866. return FALSE;
  10867. }
  10868. break;
  10869. default:
  10870. return FALSE;
  10871. }
  10872. return TRUE;
  10873. }
  10874. //+----------------------------------------------------------------------------
  10875. //
  10876. // Function: ProcessLicense
  10877. //
  10878. // Synopsis: Add a license agreement
  10879. //
  10880. //
  10881. // History: quintinb Created Header and renamed from ProcessPage7A 8/6/98
  10882. //
  10883. //+----------------------------------------------------------------------------
  10884. INT_PTR APIENTRY ProcessLicense(
  10885. HWND hDlg,
  10886. UINT message,
  10887. WPARAM wParam,
  10888. LPARAM lParam)
  10889. {
  10890. TCHAR szTemp[MAX_PATH+1];
  10891. NMHDR* pnmHeader = (NMHDR*)lParam;
  10892. ProcessBold(hDlg,message);
  10893. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_LICENSE)) return TRUE;
  10894. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  10895. SetDefaultGUIFont(hDlg,message,IDC_EDIT1);
  10896. switch (message)
  10897. {
  10898. case WM_INITDIALOG:
  10899. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10900. break;
  10901. case WM_COMMAND:
  10902. switch (LOWORD(wParam))
  10903. {
  10904. case IDC_BROWSE1:
  10905. {
  10906. UINT uFilter = IDS_TXTFILTER;
  10907. TCHAR* szMask = TEXT("*.txt");
  10908. MYVERIFY(0 != DoBrowse(hDlg, &uFilter, &szMask, 1, IDC_EDIT1, TEXT("txt"),
  10909. g_szLicense));
  10910. }
  10911. break;
  10912. default:
  10913. break;
  10914. }
  10915. break;
  10916. case WM_NOTIFY:
  10917. if (NULL == pnmHeader)
  10918. {
  10919. return FALSE;
  10920. }
  10921. switch (pnmHeader->code)
  10922. {
  10923. case PSN_KILLACTIVE:
  10924. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  10925. return 1;
  10926. break; //lint !e527 this line isn't reachable but
  10927. // keep it in case the return is removed
  10928. case PSN_SETACTIVE:
  10929. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  10930. //
  10931. // The following call to GetPrivateProfileString could return an empty string,
  10932. // thus we shouldn't use MYVERIFY on it.
  10933. //
  10934. ZeroMemory(g_szLicense, sizeof(g_szLicense));
  10935. GetPrivateProfileString(c_pszCmakStatus, c_pszLicenseFile, TEXT(""), g_szLicense,
  10936. CELEMS(g_szLicense), g_szInfFile); //lint !e534
  10937. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)GetName(g_szLicense)));
  10938. MYVERIFY(FALSE != VerifyFile(hDlg,IDC_EDIT1,g_szLicense,FALSE));
  10939. break;
  10940. case PSN_WIZBACK:
  10941. case PSN_WIZNEXT:
  10942. // the Next button was pressed
  10943. if (-1 == GetTextFromControl(hDlg, IDC_EDIT1, szTemp, MAX_PATH, TRUE)) // bDisplayError == TRUE
  10944. {
  10945. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  10946. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  10947. return 1;
  10948. }
  10949. if (!VerifyFile(hDlg,IDC_EDIT1,g_szLicense,TRUE))
  10950. {
  10951. if (g_szLicense[0] != TEXT('\0'))
  10952. {
  10953. return 1;
  10954. }
  10955. }
  10956. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus,c_pszLicenseFile,g_szLicense,g_szInfFile));
  10957. #ifdef _WIN64
  10958. //
  10959. // If we are going back, skip the Include CM binaries page if this is IA64
  10960. //
  10961. if (pnmHeader && (PSN_WIZBACK == pnmHeader->code))
  10962. {
  10963. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, IDD_SUPPORT_INFO));
  10964. }
  10965. #endif
  10966. break;
  10967. default:
  10968. return FALSE;
  10969. }
  10970. break;
  10971. default:
  10972. return FALSE;
  10973. }
  10974. return TRUE;
  10975. }
  10976. //+----------------------------------------------------------------------------
  10977. //
  10978. // Function: MultiSelectOpenFileName
  10979. //
  10980. // Synopsis: This function is called to allow the user to select multiple items
  10981. // to add to cmak. It is currently only used in the Additional Files
  10982. // dialog of CMAK. Note that *pszStringBuffer should be NULL when passed
  10983. // in. The caller is responsible for calling CmFree on pszStringBuffer
  10984. // when finished.
  10985. //
  10986. // Arguments: HWND hDlg - HWND of the current dialog
  10987. // TCHAR** pszStringBuffer - pointer to the buffer to hold the results
  10988. //
  10989. // Returns: BOOL - Returns True if successful, -1 on cancel and 0 on error.
  10990. //
  10991. // History: quintinb Created 9/16/98
  10992. //
  10993. //+----------------------------------------------------------------------------
  10994. BOOL MultiSelectOpenFileName(HWND hDlg, TCHAR** pszStringBuffer)
  10995. {
  10996. OPENFILENAME filedef;
  10997. TCHAR szTitle[MAX_PATH+1];
  10998. TCHAR szFile[MAX_PATH+1];
  10999. TCHAR szFilter[MAX_PATH+1];
  11000. TCHAR szTemp[MAX_PATH+1];
  11001. TCHAR szFileTitle[MAX_PATH+1];
  11002. LPTSTR lpfilename;
  11003. int iReturnValue;
  11004. //
  11005. // Check Inputs
  11006. //
  11007. MYDBGASSERT(pszStringBuffer);
  11008. if (NULL == pszStringBuffer)
  11009. {
  11010. return FALSE;
  11011. }
  11012. ZeroMemory(&filedef, sizeof(OPENFILENAME));
  11013. ZeroMemory(szFilter, sizeof(szFilter));
  11014. szFile[0] = TEXT('\0');
  11015. MYVERIFY(0 != LoadString(g_hInstance, IDS_BROWSETITLE, szTitle, MAX_PATH));
  11016. MYVERIFY(0 != LoadString(g_hInstance, IDS_ALLFILTER, szFilter, MAX_PATH));
  11017. TCHAR * pszTemp = &(szFilter[_tcslen(szFilter) + 1]);
  11018. MYVERIFY(0!= wsprintf(pszTemp, c_pszWildCard));
  11019. //
  11020. // Allocate memory for the multiple file selection return
  11021. //
  11022. DWORD dwSize = 10*1024;
  11023. *pszStringBuffer = (TCHAR*)CmMalloc(dwSize*sizeof(TCHAR));
  11024. if (NULL == *pszStringBuffer)
  11025. {
  11026. return FALSE;
  11027. }
  11028. ZeroMemory(*pszStringBuffer, dwSize*sizeof(TCHAR));
  11029. //
  11030. // Initialize the OPENFILENAME data structure
  11031. //
  11032. filedef.lStructSize = sizeof(OPENFILENAME);
  11033. filedef.hwndOwner = hDlg;
  11034. filedef.lpstrFilter = szFilter;
  11035. filedef.lpstrFile = *pszStringBuffer;
  11036. filedef.nMaxFile = dwSize;
  11037. filedef.lpstrTitle = szTitle;
  11038. filedef.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_PATHMUSTEXIST
  11039. | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
  11040. //
  11041. // pop up the open dialog
  11042. //
  11043. BOOL bExit;
  11044. do
  11045. {
  11046. bExit = TRUE;
  11047. BOOL bRet = GetOpenFileName((OPENFILENAME*)&filedef);
  11048. if (bRet)
  11049. {
  11050. iReturnValue = 1;
  11051. }
  11052. else
  11053. {
  11054. //
  11055. // If we are in this state than the user could have hit cancel or there could have
  11056. // been an error. If the CommDlgExtendedError function returns 0 then we know it was
  11057. // just a cancel, otherwise we have an error.
  11058. //
  11059. DWORD dwError = CommDlgExtendedError();
  11060. if (0 == dwError)
  11061. {
  11062. //
  11063. // The user hit cancel
  11064. //
  11065. iReturnValue = -1;
  11066. }
  11067. else if (FNERR_BUFFERTOOSMALL == dwError)
  11068. {
  11069. //
  11070. // Not enough memory in the buffer. The user is picking a whole bunch
  11071. // of files. Lets warn them.
  11072. //
  11073. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_SELECTION_TOO_LARGE, MB_OK | MB_ICONWARNING));
  11074. bExit = FALSE;
  11075. }
  11076. else
  11077. {
  11078. //
  11079. // An actual error occured, fail.
  11080. //
  11081. iReturnValue = 0;
  11082. }
  11083. }
  11084. } while(!bExit);
  11085. return iReturnValue;
  11086. }
  11087. //+----------------------------------------------------------------------------
  11088. //
  11089. // Function: ParseAdditionalFiles
  11090. //
  11091. // Synopsis: This function is used to parse the output from MultiSelectOpenFileName.
  11092. // It takes a Null seperated list generated by OpenFileName (either one
  11093. // full file path, or a directory path, NULL, and then NULL seperated
  11094. // filenames.) From this list of filenames it adds them to the passed in
  11095. // list of Extra file structures.
  11096. //
  11097. // Arguments: ListBxList **g_pHeadExtra - pointer to the head of the Extra struct list
  11098. // ListBxList **g_pTailExtra - pointer to the tail of the Extra struct list
  11099. // TCHAR* pszStringBuffer - string buffer of filenames to process
  11100. //
  11101. // Returns: BOOL - TRUE on Success
  11102. //
  11103. // History: quintinb Created 9/16/98
  11104. //
  11105. //+----------------------------------------------------------------------------
  11106. BOOL ParseAdditionalFiles(ListBxList **g_pHeadExtra, ListBxList **g_pTailExtra, TCHAR* pszStringBuffer)
  11107. {
  11108. UINT uCurrentCharInBuffer=0;
  11109. UINT uTempChars;
  11110. TCHAR szPath[MAX_PATH+1];
  11111. ExtraData DlgExtraEdit;
  11112. MYDBGASSERT(NULL != g_pHeadExtra);
  11113. MYDBGASSERT(NULL != g_pTailExtra);
  11114. MYDBGASSERT(NULL != pszStringBuffer);
  11115. MYDBGASSERT(TEXT('\0') != pszStringBuffer[0]);
  11116. TCHAR* pStr = pszStringBuffer;
  11117. _tcscpy (szPath, pszStringBuffer);
  11118. pStr = pStr + (_tcslen(pStr) + 1);
  11119. if (TEXT('\0') == *pStr)
  11120. {
  11121. //
  11122. // If the user only selected one file, then we just need to copy it to a buffer
  11123. //
  11124. _tcscpy(DlgExtraEdit.szPathname, szPath);
  11125. GetFileName(DlgExtraEdit.szPathname, DlgExtraEdit.szName);
  11126. MYVERIFY(FALSE != createListBxRecord(g_pHeadExtra, g_pTailExtra,(void *)&DlgExtraEdit,
  11127. sizeof(DlgExtraEdit), DlgExtraEdit.szName));
  11128. return TRUE;
  11129. }
  11130. else
  11131. {
  11132. while (TEXT('\0') != *pStr)
  11133. {
  11134. //
  11135. // Fill the DlgExtra Struct with data
  11136. //
  11137. TCHAR szTemp[MAX_PATH+1];
  11138. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), szPath, pStr));
  11139. _tcscpy(DlgExtraEdit.szPathname, szTemp);
  11140. _tcscpy(DlgExtraEdit.szName, pStr);
  11141. //
  11142. // Create the List box entry
  11143. //
  11144. MYVERIFY(FALSE != createListBxRecord(g_pHeadExtra, g_pTailExtra,(void *)&DlgExtraEdit,
  11145. sizeof(DlgExtraEdit), DlgExtraEdit.szName));
  11146. //
  11147. // Increment
  11148. //
  11149. pStr = pStr + (_tcslen(pStr) + 1);
  11150. }
  11151. return TRUE;
  11152. }
  11153. return FALSE;
  11154. }
  11155. void EnableDisableDeleteButton(HWND hDlg)
  11156. {
  11157. //
  11158. // Enable the delete button if we have move than one item
  11159. //
  11160. LRESULT lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
  11161. HWND hDeleteButton = GetDlgItem(hDlg, IDC_BUTTON2);
  11162. HWND hCurrentFocus = GetFocus();
  11163. HWND hControl;
  11164. if (hDeleteButton)
  11165. {
  11166. EnableWindow(hDeleteButton, (1 <= lResult));
  11167. }
  11168. if (1 <= lResult)
  11169. {
  11170. SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, 0, 0);
  11171. }
  11172. if (FALSE == IsWindowEnabled(hCurrentFocus))
  11173. {
  11174. if (hDeleteButton == hCurrentFocus)
  11175. {
  11176. //
  11177. // If delete is disabled and contained the focus, shift it to the Add button
  11178. //
  11179. hControl = GetDlgItem(hDlg, IDC_BUTTON1);
  11180. SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON1, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  11181. SetFocus(hControl);
  11182. }
  11183. else
  11184. {
  11185. //
  11186. // If all else fails set the focus to the list control
  11187. //
  11188. hControl = GetDlgItem(hDlg, IDC_LIST1);
  11189. SetFocus(hControl);
  11190. }
  11191. }
  11192. }
  11193. //+----------------------------------------------------------------------------
  11194. //
  11195. // Function: ProcessAdditionalFiles
  11196. //
  11197. // Synopsis: Add additional files to the profile
  11198. //
  11199. //
  11200. // History: quintinb Created Header and renamed from ProcessPage7B 8/6/98
  11201. // quintinb Added Multi-Select capability and removed intermediate dialog 9/16/98
  11202. // (NTRAID 210849)
  11203. //+----------------------------------------------------------------------------
  11204. INT_PTR APIENTRY ProcessAdditionalFiles(
  11205. HWND hDlg,
  11206. UINT message,
  11207. WPARAM wParam,
  11208. LPARAM lParam)
  11209. {
  11210. TCHAR szTemp[MAX_PATH+1];
  11211. INT_PTR nResult;
  11212. TCHAR* pszStringBuffer = NULL;
  11213. BOOL bRet;
  11214. NMHDR* pnmHeader = (NMHDR*)lParam;
  11215. ProcessBold(hDlg,message);
  11216. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ADDITION)) return TRUE;
  11217. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  11218. SetDefaultGUIFont(hDlg,message,IDC_LIST1);
  11219. switch (message)
  11220. {
  11221. case WM_INITDIALOG:
  11222. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  11223. break;
  11224. case WM_COMMAND:
  11225. switch (LOWORD(wParam))
  11226. {
  11227. case IDC_BUTTON1: //add
  11228. bRet = MultiSelectOpenFileName(hDlg, &pszStringBuffer);
  11229. if ((-1 != bRet) && (0 != bRet))
  11230. {
  11231. ParseAdditionalFiles(&g_pHeadExtra, &g_pTailExtra, pszStringBuffer);
  11232. RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
  11233. WriteExtraList();
  11234. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  11235. EnableDisableDeleteButton(hDlg);
  11236. }
  11237. CmFree(pszStringBuffer);
  11238. return (TRUE);
  11239. break; //lint !e527 this line isn't reachable but
  11240. // keep it in case the return is removed
  11241. case IDC_BUTTON2: //delete
  11242. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, (LPARAM)0);
  11243. if (nResult == LB_ERR)
  11244. {
  11245. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  11246. return TRUE;
  11247. }
  11248. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult,
  11249. (LPARAM)szTemp));
  11250. DeleteListBxRecord(&g_pHeadExtra, &g_pTailExtra, szTemp);
  11251. RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
  11252. EnableDisableDeleteButton(hDlg);
  11253. WriteExtraList();
  11254. return (TRUE);
  11255. break; //lint !e527 this line isn't reachable but
  11256. // keep it in case the return is removed
  11257. default:
  11258. break;
  11259. }
  11260. break;
  11261. case WM_NOTIFY:
  11262. if (NULL == pnmHeader)
  11263. {
  11264. return FALSE;
  11265. }
  11266. switch (pnmHeader->code)
  11267. {
  11268. case PSN_KILLACTIVE:
  11269. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  11270. return 1;
  11271. break; //lint !e527 this line isn't reachable but
  11272. // keep it in case the return is removed
  11273. case PSN_SETACTIVE:
  11274. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_NEXT | PSWIZB_BACK));
  11275. if (g_pHeadExtra == NULL)
  11276. {
  11277. ReadExtraList();
  11278. }
  11279. RefreshList(hDlg, IDC_LIST1, g_pHeadExtra);
  11280. EnableDisableDeleteButton(hDlg);
  11281. break;
  11282. case PSN_WIZBACK:
  11283. case PSN_WIZNEXT:
  11284. //
  11285. // Before allowing the user to finish we need to check the extra files
  11286. // list and make sure that each file on it has a filename that is convertable
  11287. // to ANSI. If not then we need to make sure that we tell them so that they
  11288. // can delete the file or rename it. Checking this in ParseAdditional files
  11289. // seemed odd because they may have selected a bunch of files where only
  11290. // one of them was wrong. Thus we would be failing their browse and there was
  11291. // nothing they could do about it. Doing it here allows them to keep all of the
  11292. // good files that pass the roundtrip test and allows them to delete offending files
  11293. // at a spot where they can actually do so.
  11294. //
  11295. ExtraData * pExtraData;
  11296. ListBxList * LoopPtr;
  11297. if (NULL != g_pHeadExtra)
  11298. {
  11299. LoopPtr = g_pHeadExtra;
  11300. while( LoopPtr != NULL)
  11301. {
  11302. pExtraData = (ExtraData *)LoopPtr->ListBxData;
  11303. {
  11304. GetFileName(pExtraData->szPathname, szTemp);
  11305. if (!TextIsRoundTripable(szTemp, TRUE)) // TRUE == bDisplayError
  11306. {
  11307. //
  11308. // Set the Cursor on the offending item in the list
  11309. //
  11310. nResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_FINDSTRINGEXACT,
  11311. (WPARAM)-1, (LPARAM)szTemp);
  11312. if (LB_ERR != nResult)
  11313. {
  11314. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM)nResult, (LPARAM)0));
  11315. }
  11316. //
  11317. // Set focus on the delete button
  11318. //
  11319. SetFocus(GetDlgItem(hDlg, IDC_BUTTON2));
  11320. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  11321. return 1;
  11322. }
  11323. }
  11324. LoopPtr = LoopPtr->next;
  11325. }
  11326. }
  11327. WriteExtraList();
  11328. break;
  11329. default:
  11330. return FALSE;
  11331. }
  11332. break;
  11333. default:
  11334. return FALSE;
  11335. }
  11336. return TRUE;
  11337. }
  11338. BOOL WriteInf(HANDLE hInf, LPCTSTR str)
  11339. {
  11340. DWORD written;
  11341. #ifdef UNICODE
  11342. BOOL bReturn = FALSE;
  11343. LPSTR pszAnsiString = WzToSzWithAlloc(str);
  11344. if (pszAnsiString)
  11345. {
  11346. bReturn = WriteFile(hInf, pszAnsiString, (lstrlenA(pszAnsiString))*sizeof(CHAR), &written, NULL);
  11347. CmFree(pszAnsiString);
  11348. }
  11349. return bReturn;
  11350. #else
  11351. return (WriteFile(hInf, str, (lstrlen(str))*sizeof(TCHAR), &written, NULL));
  11352. #endif
  11353. }
  11354. //+----------------------------------------------------------------------------
  11355. //
  11356. // Function: WriteCopy
  11357. //
  11358. // Synopsis: This function writes an INF entry and copies the file to the temp
  11359. // directory. Note that the function expects a fully qualified path
  11360. // in lpFile or <shortservicename>\filename.ext.
  11361. //
  11362. // Arguments: HANDLE hInf - handle to the open inf file to write to
  11363. // LPTSTR lpFile - fully qualified path and filename of file to copy
  11364. // BOOL bWriteShortName -- should the filename be converted to the shortname
  11365. //
  11366. // Returns: BOOL - TRUE if the INF entry is written properly and the file is
  11367. // copied properly.
  11368. //
  11369. // NOTE: This code is written such that filenames passed in should reference the
  11370. // copy of the file in the temp directory (thus the user is editing the profile
  11371. // and hasn't changed it) or the file is a new file and the path is to its original
  11372. // location. Unfortunately, we usually pass in the path to the file in the Profile
  11373. // directory instead of in the temp dir. This works fine, but makes an additional copy
  11374. // operation necessary (since we copy all files to the temp dir in the beginning when
  11375. // editting anyway).
  11376. //
  11377. // History: quintinb Created Header 1/30/98
  11378. //
  11379. //+----------------------------------------------------------------------------
  11380. BOOL WriteCopy(HANDLE hInf, LPTSTR lpFile, BOOL bWriteShortName)
  11381. {
  11382. TCHAR szDest[MAX_PATH+1];
  11383. TCHAR szSrc[MAX_PATH+1];
  11384. if (NULL != lpFile && lpFile[0] != TEXT('\0'))
  11385. {
  11386. //
  11387. // Prepare the destination in szDest
  11388. //
  11389. GetFileName(lpFile, szSrc);
  11390. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\\%s"), g_szOutdir, szSrc));
  11391. //
  11392. // Prepare the source in szSrc. If we have <shortservicename>\filename.ext, then
  11393. // we need to prepend the path to the profiles dir, otherwise use as is.
  11394. //
  11395. wsprintf(szSrc, TEXT("%s\\"), g_szShortServiceName);
  11396. CmStrTrim(lpFile);
  11397. if (lpFile == CmStrStr(lpFile, szSrc))
  11398. {
  11399. MYVERIFY(CELEMS(szSrc) > (UINT)wsprintf(szSrc, TEXT("%s%s\\%s"), g_szCmakdir, c_pszProfiles, lpFile));
  11400. }
  11401. else
  11402. {
  11403. lstrcpy(szSrc, lpFile);
  11404. }
  11405. //
  11406. // Copy the file
  11407. //
  11408. if (_tcsicmp(szSrc, szDest) != 0)
  11409. {
  11410. if (!CopyFileWrapper(szSrc, szDest, FALSE))
  11411. {
  11412. return FALSE;
  11413. }
  11414. }
  11415. MYVERIFY(0 != SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL));
  11416. //
  11417. // If WriteShortName is set, then we want to write the short name of the file
  11418. // in the inf section. Otherwise we want to write the long name.
  11419. //
  11420. if (bWriteShortName)
  11421. {
  11422. if (!GetShortFileName(szDest, szSrc))
  11423. {
  11424. return FALSE;
  11425. }
  11426. }
  11427. else
  11428. {
  11429. GetFileName(szDest, szSrc);
  11430. }
  11431. MYVERIFY(CELEMS(szDest) > (UINT)wsprintf(szDest, TEXT("%s\r\n"), szSrc));
  11432. return WriteInf(hInf, szDest);
  11433. }
  11434. return TRUE;
  11435. }
  11436. BOOL WriteInfLine(HANDLE hInf,LPTSTR lpFile)
  11437. {
  11438. TCHAR szTemp[MAX_PATH+1];
  11439. if (lpFile[0] != TEXT('\0'))
  11440. {
  11441. GetFileName(lpFile,szTemp);
  11442. _tcscat(szTemp,TEXT("\r\n"));
  11443. return WriteInf(hInf,szTemp);
  11444. }
  11445. else
  11446. {
  11447. //
  11448. // If blank then nothing to write
  11449. //
  11450. return TRUE;
  11451. }
  11452. }
  11453. BOOL WriteSrcInfLine(HANDLE hInf,LPTSTR lpFile)
  11454. {
  11455. TCHAR szShort[MAX_PATH+1];
  11456. TCHAR szLong[MAX_PATH+1];
  11457. RenameData TmpRenameData;
  11458. if (lpFile[0] != TEXT('\0'))
  11459. {
  11460. if (!GetShortFileName(lpFile,szShort))
  11461. {
  11462. return FALSE;
  11463. }
  11464. GetFileName(lpFile,szLong);
  11465. if (_tcsicmp(szShort,szLong) != 0)
  11466. {
  11467. _tcscpy(TmpRenameData.szShortName,szShort);
  11468. _tcscpy(TmpRenameData.szLongName,szLong);
  11469. MYVERIFY(FALSE != createListBxRecord(&g_pHeadRename,&g_pTailRename,(void *)&TmpRenameData,sizeof(TmpRenameData),TmpRenameData.szShortName));
  11470. }
  11471. _tcscat(szLong,TEXT("= 55\r\n"));
  11472. return WriteInf(hInf,szLong);
  11473. }
  11474. else
  11475. {
  11476. //
  11477. // Nothing to write
  11478. //
  11479. return TRUE;
  11480. }
  11481. }
  11482. BOOL WriteFileSections(HWND hDlg)
  11483. {
  11484. HANDLE hInf;
  11485. TCHAR szTemp[MAX_PATH+1];
  11486. TCHAR szTempName[MAX_PATH+1];
  11487. TCHAR ch;
  11488. int i;
  11489. DWORD dwRead;
  11490. BOOL bWriteShortName;
  11491. hInf = CreateFile(g_szInfFile,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,
  11492. FILE_ATTRIBUTE_NORMAL,NULL);
  11493. if (hInf == INVALID_HANDLE_VALUE)
  11494. {
  11495. _tcscpy(szTemp,g_szInfFile);
  11496. FileAccessErr(hDlg,szTemp);
  11497. goto error;
  11498. }
  11499. // MOVE TO END OF FILE TO BEGIN WRITING CUSTOM SECTIONS
  11500. // SKIP ANY BLANK SPACE AT THE END OF THE FILE
  11501. i = GetFileSize(hInf,NULL);
  11502. do
  11503. {
  11504. --i;
  11505. MYVERIFY(INVALID_SET_FILE_POINTER != SetFilePointer(hInf,i,NULL,FILE_BEGIN));
  11506. MYVERIFY(0 != ReadFile(hInf,&ch,1,&dwRead,NULL));
  11507. }
  11508. while ((ch == TEXT('\r'))||(ch == TEXT('\n'))||(ch == TEXT(' ')));
  11509. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11510. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11511. // USE ICON IN CM AS ICON FOR DESKTOP IF NOT LARGE ICON SPECIFIED
  11512. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.AddReg.Icon]\r\n")));
  11513. if (g_szLargeIco[0]==TEXT('\0'))
  11514. {
  11515. 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
  11516. }
  11517. else
  11518. {
  11519. WriteInf(hInf,TEXT("HKCR,\"CLSID\\%DesktopGUID%\\DefaultIcon\",,,\"%49000%\\%ShortSvcName%\\%DesktopIcon%\"\r\n"));//lint !e534 compile doesn't like the MYVERIFY macro and big strings
  11520. }
  11521. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11522. // WRITE OUT FILES INTO PROFILE DIRECTORY
  11523. //
  11524. // We need to write a CopyFiles section with Long File Names (for NT5 Single User installs)
  11525. // and one with Short Files Names (for win9x and All user NT). This is to help fix
  11526. // NTRAID 323721 -- CM: User level accounts cannot install profiles on W2K Server
  11527. // The problem is that single users on NT5 do not have permission to write the
  11528. // Rename key (HKLM\Software\Microsoft\Windows\CurrentVersion\RenameFiles) and
  11529. // NT doesn't really need it anyway since the NT setup api's deal with long file
  11530. // names better than those of win95.
  11531. //
  11532. for (bWriteShortName = 0; bWriteShortName < 2; bWriteShortName++)
  11533. {
  11534. if (!bWriteShortName)
  11535. {
  11536. //
  11537. // Write out the Single User Version of Xnstall.CopyFiles -- Set bWriteShortName == FALSE
  11538. //
  11539. MYVERIFY(FALSE != WriteInf(hInf, TEXT("[Xnstall.CopyFiles.SingleUser]\r\n")));
  11540. }
  11541. else
  11542. {
  11543. //
  11544. // Write out the All User Version of Xnstall.CopyFiles -- set bWriteShortName == TRUE
  11545. //
  11546. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.CopyFiles]\r\n")));
  11547. }
  11548. if (!WriteCopy(hInf, g_szPhonebk, bWriteShortName)) {_tcscpy(szTemp,g_szPhonebk);goto error;}
  11549. if (!WriteCopy(hInf, g_szRegion, bWriteShortName)) {_tcscpy(szTemp,g_szRegion);goto error;}
  11550. if (!WriteCopy(hInf, g_szBrandBmp, bWriteShortName)) {_tcscpy(szTemp,g_szBrandBmp);goto error;}
  11551. if (!WriteCopy(hInf, g_szPhoneBmp, bWriteShortName)) {_tcscpy(szTemp,g_szPhoneBmp);goto error;}
  11552. if (!WriteCopy(hInf, g_szLargeIco, bWriteShortName)) {_tcscpy(szTemp,g_szLargeIco);goto error;}
  11553. if (!WriteCopy(hInf, g_szSmallIco, bWriteShortName)) {_tcscpy(szTemp,g_szSmallIco);goto error;}
  11554. if (!WriteCopy(hInf, g_szTrayIco, bWriteShortName)) {_tcscpy(szTemp,g_szTrayIco);goto error;}
  11555. if (!WriteCopy(hInf, g_szHelp, bWriteShortName)) {_tcscpy(szTemp,g_szHelp);goto error;}
  11556. if (!WriteCopy(hInf, g_szLicense, bWriteShortName)) {_tcscpy(szTemp,g_szLicense);goto error;}
  11557. if (!WriteCopy(hInf, g_szCmProxyFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmProxyFile);goto error;}
  11558. if (!WriteCopy(hInf, g_szCmRouteFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmRouteFile);goto error;}
  11559. if (!WriteCopy(hInf, g_szVpnFile, bWriteShortName)) {_tcscpy(szTemp,g_szCmRouteFile);goto error;}
  11560. if (g_bIncludeCmCode)
  11561. {
  11562. MYVERIFY(0 != LoadString(g_hInstance, IDS_READMETXT, szTemp, MAX_PATH));
  11563. _tcscat(szTemp,TEXT("\r\n"));
  11564. if (!WriteInf(hInf, szTemp)) {goto error;}
  11565. }
  11566. //
  11567. // Write out tray icon command files
  11568. //
  11569. if (!WriteCopyMenuItemFiles(hInf, szTemp, bWriteShortName)) {goto error;}
  11570. // Write out connect action command files
  11571. if (!WriteCopyConActFiles(hInf,szTemp, bWriteShortName)) {goto error;}
  11572. if (!WriteCopyExtraFiles(hInf,szTemp, bWriteShortName)) {goto error;}
  11573. if (!WriteCopyDnsFiles(hInf,szTemp, bWriteShortName)) {goto error;}
  11574. if (bWriteShortName)
  11575. {
  11576. MYVERIFY(FALSE != WriteShortRefsFiles(hInf, FALSE));
  11577. }
  11578. else
  11579. {
  11580. MYVERIFY(FALSE != WriteLongRefsFiles (hInf));
  11581. }
  11582. _tcscpy(szTemp,g_szShortServiceName);
  11583. _tcscat(szTemp,TEXT(".cms,,,4\r\n")); // the 4 makes sure there is no version checking on the cms
  11584. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11585. _tcscpy(szTemp,g_szShortServiceName);
  11586. _tcscat(szTemp,TEXT(".inf\r\n"));
  11587. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11588. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11589. }
  11590. //
  11591. // End of quintinb fix for 323721
  11592. //
  11593. //WRITE OUT FILES TO COPY TO ICM DIRECTORY
  11594. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Xnstall.CopyFiles.ICM]\r\n")));
  11595. _tcscpy(szTemp,g_szShortServiceName);
  11596. _tcscat(szTemp,TEXT(".cmp\r\n"));
  11597. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11598. 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]
  11599. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11600. // WRITE OUT FILES TO DELETE FROM ROOT ICM DIRECTORY
  11601. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Remove.DelFiles.ICM]\r\n")));
  11602. _tcscpy(szTemp,g_szShortServiceName);
  11603. _tcscat(szTemp,TEXT(".cmp\r\n"));
  11604. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11605. 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]
  11606. // WRITE LIST OF ALL FILES IN PRODUCT
  11607. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11608. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[SourceDisksFiles]\r\n")));
  11609. _tcscpy(szTemp,TEXT("%ShortSvcname%"));
  11610. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szPhonebk));
  11611. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szRegion));
  11612. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szBrandBmp));
  11613. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szPhoneBmp));
  11614. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szLargeIco));
  11615. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szSmallIco));
  11616. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szTrayIco));
  11617. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szHelp));
  11618. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szLicense));
  11619. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szCmProxyFile));
  11620. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szCmRouteFile));
  11621. MYVERIFY(FALSE != WriteSrcInfLine(hInf,g_szVpnFile));
  11622. _tcscpy(szTemp,g_szShortServiceName);
  11623. _tcscat(szTemp,TEXT(".inf = 55\r\n"));
  11624. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11625. _tcscpy(szTemp,g_szShortServiceName);
  11626. _tcscat(szTemp,TEXT(".cmp = 55\r\n"));
  11627. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11628. _tcscpy(szTemp,g_szShortServiceName);
  11629. _tcscat(szTemp,TEXT(".cms = 55\r\n"));
  11630. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11631. WriteSrcMenuItemFiles(hInf);
  11632. WriteSrcConActFiles(hInf);
  11633. WriteSrcExtraFiles(hInf);
  11634. MYVERIFY(FALSE != WriteSrcRefsFiles(hInf)); // This call writes out the refs files to [Remove.DelFiles]
  11635. WriteSrcDnsFiles(hInf);
  11636. WriteRenameSection(hInf);
  11637. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11638. MYVERIFY(FALSE != WriteInf(hInf,TEXT("[Remove.DelFiles]\r\n")));
  11639. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s.cms\r\n"), g_szShortServiceName));
  11640. MYVERIFY(FALSE != WriteInf(hInf,szTemp));
  11641. if (g_bIncludeCmCode)
  11642. {
  11643. MYVERIFY(0 != LoadString(g_hInstance, IDS_READMETXT, szTemp, MAX_PATH));
  11644. _tcscat(szTemp,TEXT("\r\n"));
  11645. MYVERIFY(0 != WriteInf(hInf,szTemp));
  11646. }
  11647. MYVERIFY(FALSE != WriteInfLine(hInf,g_szPhonebk));
  11648. MYVERIFY(FALSE != WriteInfLine(hInf,g_szRegion));
  11649. MYVERIFY(FALSE != WriteInfLine(hInf,g_szBrandBmp));
  11650. MYVERIFY(FALSE != WriteInfLine(hInf,g_szPhoneBmp));
  11651. MYVERIFY(FALSE != WriteInfLine(hInf,g_szLargeIco));
  11652. MYVERIFY(FALSE != WriteInfLine(hInf,g_szSmallIco));
  11653. MYVERIFY(FALSE != WriteInfLine(hInf,g_szTrayIco));
  11654. MYVERIFY(FALSE != WriteInfLine(hInf,g_szHelp));
  11655. MYVERIFY(FALSE != WriteInfLine(hInf,g_szLicense));
  11656. MYVERIFY(FALSE != WriteInfLine(hInf,g_szCmProxyFile));
  11657. MYVERIFY(FALSE != WriteInfLine(hInf,g_szCmRouteFile));
  11658. MYVERIFY(FALSE != WriteInfLine(hInf,g_szVpnFile));
  11659. WriteDelMenuItemFiles(hInf);
  11660. WriteDelConActFiles(hInf);
  11661. WriteDelExtraFiles(hInf);
  11662. MYVERIFY(FALSE != WriteRefsFiles(hInf,FALSE));
  11663. WriteDelDnsFiles(hInf);
  11664. WriteEraseLongName(hInf);
  11665. MYVERIFY(FALSE != WriteInf(hInf,TEXT("\r\n")));
  11666. MYVERIFY(0 != CloseHandle(hInf));
  11667. MYVERIFY(0 != SetCurrentDirectory(g_szCmakdir));
  11668. return (TRUE);
  11669. error:
  11670. {
  11671. //FileAccessErr(hDlg,szTemp);
  11672. MYVERIFY(0 != CloseHandle(hInf));
  11673. return (FALSE);
  11674. }
  11675. }
  11676. void EraseSEDFiles(LPCTSTR szSed)
  11677. {
  11678. int i = 0;
  11679. TCHAR szTemp[MAX_PATH+1];
  11680. TCHAR szFileNum[MAX_PATH+1];
  11681. TCHAR szSourceFilesSection[MAX_PATH+1];
  11682. _tcscpy(szSourceFilesSection, TEXT("SourceFiles0"));
  11683. do
  11684. {
  11685. MYVERIFY(CELEMS(szFileNum) > (UINT)wsprintf(szFileNum, TEXT("FILE%d"), i));
  11686. //
  11687. // The following call to GetPrivateProfileString could return an empty string, thus don't
  11688. // use the MYVERIFY macro on it.
  11689. //
  11690. GetPrivateProfileString(c_pszInfSectionStrings, szFileNum, TEXT(""), szTemp,
  11691. MAX_PATH, szSed); //lint !e534
  11692. if (*szTemp)
  11693. {
  11694. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, szFileNum, NULL, szSed));
  11695. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%%%s%%"), szFileNum));
  11696. MYVERIFY(0 != WritePrivateProfileString(szSourceFilesSection, szTemp, NULL, szSed));
  11697. }
  11698. else
  11699. {
  11700. break;
  11701. }
  11702. ++i; // increment the file number
  11703. }
  11704. while(*szTemp);
  11705. //
  11706. // Erase the finish message key from the Sed. This will avoid double finish messages
  11707. // (since cmstp is now supposed to take care of finish message but older profiles had
  11708. // the message from here).
  11709. //
  11710. MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, TEXT("FinishMessage"), TEXT(""), szSed));
  11711. //
  11712. // Write out the word <None> into the post install command so that showicon isn't a problem
  11713. // on an upgrade.
  11714. //
  11715. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, TEXT("PostInstallCmd"), TEXT("<None>"), szSed));
  11716. //
  11717. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  11718. // (win95 only). This call will return 0.
  11719. //
  11720. WritePrivateProfileString(NULL, NULL, NULL, szSed); //lint !e534 this call will always return 0
  11721. }
  11722. //+----------------------------------------------------------------------------
  11723. //
  11724. // Function: WriteSED
  11725. //
  11726. // Synopsis: This function takes a fullpath to a file and the current file
  11727. // number entry to write it to and writes the file entry in the SED
  11728. // passed in. Before writing the entry, the functions enumerates all
  11729. // other files in the sed to check for duplicates. If it finds a
  11730. // file with the sme filename, it will not write the entry because
  11731. // since we are using a flat directory structure two files of the same
  11732. // name will overwrite each other anyway. Note that if the file is
  11733. // written, *pFileNum is incremented.
  11734. //
  11735. // Arguments: HWND hDlg - Window handle for FileAccessErr Messages
  11736. // LPTSTR szFullFilePath - Full path of the file to write
  11737. // LPINT pFileNum - Current File entry number
  11738. // LPCTSTR szSed - Full path to the sed file to write the entry to
  11739. //
  11740. // Returns: Nothing
  11741. //
  11742. // History: quintinb Created Header, Removed UseLangDir, Changed to take a full path,
  11743. // and generally cleaned up. 8/7/98
  11744. //
  11745. //+----------------------------------------------------------------------------
  11746. BOOL WriteSED(HWND hDlg, LPTSTR szFullFilePath, LPINT pFileNum, LPCTSTR szSed)
  11747. {
  11748. TCHAR szTemp[MAX_PATH+1];
  11749. TCHAR szFileName[MAX_PATH+1];
  11750. TCHAR szFileNumber[MAX_PATH+1];
  11751. if (TEXT('\0') != szFullFilePath[0])
  11752. {
  11753. //
  11754. // First Check to see if the file exists. If we write a file in the SED that
  11755. // IExpress can't find, then it will throw an error. We should definitely try
  11756. // to throw an error earlier and try to give the user a chance to fix it.
  11757. //
  11758. if (!FileExists(szFullFilePath))
  11759. {
  11760. CFileNameParts FileParts(szFullFilePath);
  11761. if ((TEXT('\0') == FileParts.m_Drive[0]) &&
  11762. (TEXT('\0') == FileParts.m_Dir[0]) &&
  11763. (TEXT('\0') != FileParts.m_FileName[0]) &&
  11764. (TEXT('\0') != FileParts.m_Extension[0]))
  11765. {
  11766. //
  11767. // The user only passed in the filename and extension. Lets look in
  11768. // the profile directory. If it isn't here then throw an error.
  11769. //
  11770. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s%s"),
  11771. g_szOsdir, g_szShortServiceName, FileParts.m_FileName, FileParts.m_Extension));
  11772. if (!FileExists(szTemp))
  11773. {
  11774. FileAccessErr(hDlg, szFullFilePath);
  11775. return FALSE;
  11776. }
  11777. else
  11778. {
  11779. MYVERIFY(CELEMS(szFullFilePath) > (UINT)wsprintf(szFullFilePath, szTemp));
  11780. }
  11781. }
  11782. else
  11783. {
  11784. FileAccessErr(hDlg, szFullFilePath);
  11785. return FALSE;
  11786. }
  11787. }
  11788. //
  11789. // Get just the file name from the full path. We use this
  11790. // later to determine if the file already exists in the SED
  11791. // file.
  11792. //
  11793. GetFileName(szFullFilePath, szFileName);
  11794. //
  11795. // Construct the next FileNumber Entry
  11796. //
  11797. MYVERIFY(CELEMS(szFileNumber) > (UINT)wsprintf(szFileNumber, TEXT("FILE%d"), *pFileNum));
  11798. //
  11799. // Check to make sure that we already don't have the file in the cab. If
  11800. // so then just ignore the entry.
  11801. //
  11802. for (int i=0; i<*pFileNum; ++i)
  11803. {
  11804. //
  11805. // Write the FILEX entry into a string to read in the file name for the
  11806. // current i.
  11807. //
  11808. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("FILE%d"), i));
  11809. TCHAR szTempFileName[MAX_PATH+1];
  11810. GetPrivateProfileString(c_pszInfSectionStrings, szTemp,
  11811. TEXT(""), szTempFileName, CELEMS(szTempFileName), szSed); //lint !e534
  11812. if (TEXT('\0') != szTempFileName[0])
  11813. {
  11814. //
  11815. // Get the filenames of both files since we are using a flat directory space.
  11816. // Two files of the same name will collide anyway.
  11817. //
  11818. GetFileName(szTempFileName, szTemp);
  11819. if (0 == _tcsicmp(szTemp, szFileName))
  11820. {
  11821. //
  11822. // don't add it because it already exists
  11823. //
  11824. CMASSERTMSG(0 == _tcsicmp(szFullFilePath, szTempFileName), TEXT("WriteSed -- We have two files that have the same FileName but different paths."));
  11825. return TRUE;
  11826. }
  11827. }
  11828. }
  11829. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
  11830. szFileNumber, szFullFilePath, szSed));
  11831. *pFileNum = (*pFileNum) + 1;
  11832. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%%%s%%"), szFileNumber));
  11833. MYVERIFY(0 != WritePrivateProfileString(TEXT("SourceFiles0"), szTemp, TEXT(""), szSed));
  11834. }
  11835. return TRUE;
  11836. }
  11837. //+----------------------------------------------------------------------------
  11838. //
  11839. // Function: WriteCMPFile
  11840. //
  11841. // Synopsis: This function is a wrapper file to write out the version to the CMP.
  11842. //
  11843. // Arguments: None
  11844. //
  11845. // History: nickball Created Header 07/22/98
  11846. //
  11847. //+----------------------------------------------------------------------------
  11848. void WriteCMPFile()
  11849. {
  11850. TCHAR szTemp[MAX_PATH+1];
  11851. //
  11852. // Ensure that the version number is up to date in the .CMP
  11853. //
  11854. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), PROFILEVERSION));
  11855. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionProfileFormat, c_pszVersion, szTemp, g_szCmpFile));
  11856. //
  11857. // Write the CMS entry to the CMP File
  11858. //
  11859. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s.cms"), g_szShortServiceName, g_szShortServiceName));
  11860. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryCmsFile, szTemp, g_szCmpFile));
  11861. }
  11862. //+----------------------------------------------------------------------------
  11863. //
  11864. // Function: WriteOutRelativeFilePathOrNull
  11865. //
  11866. // Synopsis: This helper routine was written to shorten WriteCMSFile(). It tests
  11867. // to see if the inputted pszFile parameter is an empty string. If it
  11868. // is then it writes an empty string to the File entry specified by
  11869. // pszSection, pszEntryName, and pszFileToWriteTo. Otherwise it concats
  11870. // just the file name from pszFile with the parameter specified in
  11871. // pszShortName, seperating them with a '\' character. This is useful
  11872. // for CMS parameters that are either empty or a relative path from the
  11873. // cmp file location.
  11874. //
  11875. // Arguments: LPCTSTR pszFile - file entry to write
  11876. // LPCTSTR pszShortName - shortname of the profile
  11877. // LPCTSTR pszSection - string name of the section string
  11878. // LPCTSTR pszEntryName - string name of the entry name string
  11879. // LPCTSTR pszFileToWriteTo - full path of the file to write the entry to
  11880. //
  11881. // Returns: Nothing
  11882. //
  11883. // History: quintinb Created 8/8/98
  11884. //
  11885. //+----------------------------------------------------------------------------
  11886. void WriteOutRelativeFilePathOrNull(LPCTSTR pszFile, LPCTSTR pszShortName, LPCTSTR pszSection, LPCTSTR pszEntryName, LPCTSTR pszFileToWriteTo)
  11887. {
  11888. TCHAR szTemp[MAX_PATH+1];
  11889. TCHAR szName[MAX_PATH+1];
  11890. //
  11891. // Check Inputs
  11892. //
  11893. if ((NULL == pszFile) ||
  11894. (NULL == pszShortName) || (TEXT('\0') == pszShortName[0]) ||
  11895. (NULL == pszFileToWriteTo) || (TEXT('\0') == pszFileToWriteTo[0]) ||
  11896. (NULL == pszSection) || (TEXT('\0') == pszSection[0]) ||
  11897. (NULL == pszEntryName) || (TEXT('\0') == pszEntryName[0]))
  11898. {
  11899. CMASSERTMSG(FALSE, TEXT("WriteoutRelativeFilePathOrNull -- Bad Parameter"));
  11900. return;
  11901. }
  11902. if (TEXT('\0') != pszFile[0])
  11903. {
  11904. GetFileName(pszFile, szName);
  11905. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"),
  11906. pszShortName, szName));
  11907. }
  11908. else
  11909. {
  11910. szTemp[0] = TEXT('\0');
  11911. }
  11912. MYVERIFY(0 != WritePrivateProfileString(pszSection, pszEntryName, szTemp, pszFileToWriteTo));
  11913. }
  11914. //+----------------------------------------------------------------------------
  11915. //
  11916. // Function: WriteCMSFile
  11917. //
  11918. // Synopsis: This function is a wrapper file to write out the CMS file. Note
  11919. // that the cms is modified throughout CMAK, but this should be the
  11920. // last place where it is modified.
  11921. //
  11922. // Arguments: None
  11923. //
  11924. // History: quintinb Created Header 12/4/97
  11925. //
  11926. //+----------------------------------------------------------------------------
  11927. BOOL WriteCMSFile()
  11928. {
  11929. TCHAR szTemp[MAX_PATH+1];
  11930. TCHAR szName[MAX_PATH+1];
  11931. //
  11932. // Ensure that the Profile Format version number is up to date
  11933. //
  11934. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), PROFILEVERSION));
  11935. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionProfileFormat, c_pszVersion, szTemp, g_szCmsFile));
  11936. //
  11937. // erase name of phone book to be loaded if not doing download.
  11938. //
  11939. if (!g_bUpdatePhonebook)
  11940. {
  11941. g_szPhoneName[0] = TEXT('\0');
  11942. }
  11943. //
  11944. // Write out the Phonebook Name
  11945. //
  11946. if (TEXT('\0') != g_szPhonebk[0])
  11947. {
  11948. GetFileName(g_szPhonebk, szName);
  11949. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszVersion, c_pszOne,
  11950. g_szCmsFile));
  11951. }
  11952. else
  11953. {
  11954. //
  11955. // if no phone number, then set version to zero
  11956. //
  11957. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszVersion, c_pszZero,
  11958. g_szCmsFile));
  11959. if (TEXT('\0') != g_szPhoneName[0])
  11960. {
  11961. MYVERIFY(CELEMS(szName) > (UINT)wsprintf(szName, TEXT("%s.pbk"), g_szPhoneName));
  11962. }
  11963. else
  11964. {
  11965. //
  11966. // no phone book entered or set for download
  11967. //
  11968. szName[0] = TEXT('\0');
  11969. }
  11970. }
  11971. WriteOutRelativeFilePathOrNull(szName, g_szShortServiceName, c_pszCmSectionIsp,
  11972. c_pszCmEntryIspPbFile, g_szCmsFile);
  11973. //
  11974. // Write out the Phonebook Name
  11975. //
  11976. if (TEXT('\0') != g_szRegion[0])
  11977. {
  11978. GetFileName(g_szRegion, szName);
  11979. }
  11980. else
  11981. {
  11982. if (TEXT('\0') != g_szPhoneName[0])
  11983. {
  11984. MYVERIFY(CELEMS(szName) > (UINT)wsprintf(szName, TEXT("%s.pbr"), g_szPhoneName));
  11985. }
  11986. else
  11987. {
  11988. szName[0] = TEXT('\0');
  11989. }
  11990. }
  11991. WriteOutRelativeFilePathOrNull(szName, g_szShortServiceName, c_pszCmSectionIsp,
  11992. c_pszCmEntryIspRegionFile, g_szCmsFile);
  11993. //
  11994. // Write out the Large Icon
  11995. //
  11996. WriteOutRelativeFilePathOrNull(g_szLargeIco, g_szShortServiceName, c_pszCmSection,
  11997. c_pszCmEntryBigIcon, g_szCmsFile);
  11998. //
  11999. // Write out the Small Icon
  12000. //
  12001. WriteOutRelativeFilePathOrNull(g_szSmallIco, g_szShortServiceName, c_pszCmSection,
  12002. c_pszCmEntrySmallIcon, g_szCmsFile);
  12003. //
  12004. // Write out the Tray Icon
  12005. //
  12006. WriteOutRelativeFilePathOrNull(g_szTrayIco, g_szShortServiceName, c_pszCmSection,
  12007. c_pszCmEntryTrayIcon, g_szCmsFile);
  12008. //
  12009. // Write out the custom help file
  12010. //
  12011. WriteOutRelativeFilePathOrNull(g_szHelp, g_szShortServiceName, c_pszCmSection,
  12012. c_pszCmEntryHelpFile, g_szCmsFile);
  12013. //
  12014. // Write out the License File to the INF, thus we can easily redisplay
  12015. // it if they edit the profile again. (basically stash the license file
  12016. // name in the CMAK Status section of the inf)
  12017. //
  12018. WriteOutRelativeFilePathOrNull(g_szLicense, g_szShortServiceName, c_pszCmakStatus,
  12019. c_pszLicenseFile, g_szInfFile);
  12020. //
  12021. // Write out the Main Screen Bitmap
  12022. //
  12023. WriteOutRelativeFilePathOrNull(g_szBrandBmp, g_szShortServiceName, c_pszCmSection,
  12024. c_pszCmEntryLogo, g_szCmsFile);
  12025. //
  12026. // Write out the Phone Bitmap
  12027. //
  12028. WriteOutRelativeFilePathOrNull(g_szPhoneBmp, g_szShortServiceName, c_pszCmSection,
  12029. c_pszCmEntryPbLogo, g_szCmsFile);
  12030. //
  12031. // Write the HideDomain flag
  12032. //
  12033. GetPrivateProfileString(c_pszCmSection, c_pszCmEntryHideDomain, TEXT(""),
  12034. szTemp, MAX_PATH, g_szCmsFile); //lint !e534
  12035. //
  12036. // If using tunneling and the HideDomain entry doesn't previously exist, then write
  12037. // zero for the entry. Otherwise nothing should be written for this entry.
  12038. //
  12039. if (!(_tcscmp(TEXT(""), szTemp) ) && g_bUseTunneling)
  12040. {
  12041. //
  12042. // Don't want to overwrite a 1 if it exists.
  12043. //
  12044. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryHideDomain,
  12045. c_pszZero, g_szCmsFile));
  12046. }
  12047. //
  12048. // If we aren't tunneling, make sure to delete the tunnel settings
  12049. //
  12050. if (FALSE == g_bUseTunneling)
  12051. {
  12052. //
  12053. // First delete all of the Tunnel DUN Settings
  12054. //
  12055. ListBxList * pCurrent = g_pHeadVpnEntry;
  12056. while (NULL != pCurrent)
  12057. {
  12058. EraseNetworkingSections(pCurrent->szName, g_szCmsFile);
  12059. pCurrent = pCurrent->next;
  12060. }
  12061. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelDun, NULL, g_szCmsFile));
  12062. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelAddress, NULL, g_szCmsFile));
  12063. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryTunnelFile, NULL, g_szCmsFile));
  12064. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUseSameUserName, NULL, g_szCmsFile));
  12065. }
  12066. //
  12067. // Write out the rest of the CMS entries (service name, support message, etc.)
  12068. //
  12069. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName,
  12070. g_szLongServiceName,g_szCmsFile));
  12071. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryServiceMessage,
  12072. g_szSvcMsg, g_szCmsFile));
  12073. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserPrefix,
  12074. g_szPrefix, g_szCmsFile));
  12075. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryUserSuffix,
  12076. g_szSuffix, g_szCmsFile));
  12077. //
  12078. // Set the name of the default Dun setting
  12079. //
  12080. MYVERIFY(0 != GetDefaultDunSettingName(g_szCmsFile, g_szLongServiceName, szTemp, CELEMS(szTemp)));
  12081. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryDun, szTemp, g_szCmsFile));
  12082. //
  12083. // Write out the custom actions, make sure to set the bUseTunneling flag with the actual
  12084. // value to erase the PreTunnel section and set all of the flag values to zero if necessary
  12085. // (if for instance the user editted a tunneling profile and decided to make it non-Tunneling).
  12086. //
  12087. MYDBGASSERT(g_pCustomActionList);
  12088. if (g_pCustomActionList)
  12089. {
  12090. HRESULT hr = g_pCustomActionList->WriteCustomActionsToCms(g_szCmsFile, g_szShortServiceName, g_bUseTunneling);
  12091. CMASSERTMSG(SUCCEEDED(hr), TEXT("ProcessCustomActions -- Failed to write out connect actions"));
  12092. }
  12093. //
  12094. // Delete mbslgn32.dll special handling in the INF, it is no longer supported.
  12095. //
  12096. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUsePwdCache, NULL, g_szInfFile));
  12097. if (g_bUpdatePhonebook)
  12098. {
  12099. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszOne, g_szInfFile));
  12100. }
  12101. else
  12102. {
  12103. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszUpdatePhonebook, c_pszZero, g_szInfFile));
  12104. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszPhoneName, TEXT(""), g_szInfFile));
  12105. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSectionIsp, c_pszCmEntryIspUrl, TEXT(""), g_szCmsFile));
  12106. }
  12107. //
  12108. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  12109. // (win95 only). This call will return 0.
  12110. //
  12111. WritePrivateProfileString(NULL, NULL, NULL, g_szCmpFile); //lint !e534 this call will always return 0
  12112. return TRUE;
  12113. }
  12114. //+----------------------------------------------------------------------------
  12115. //
  12116. // Function: IncludeOptionalCode
  12117. //
  12118. // Synopsis: This function writes the flags to CMAK to tell the profile installer
  12119. // whether or not CM bits and Support dll's should be installed.
  12120. //
  12121. // Arguments: None
  12122. //
  12123. // Returns: Nothing
  12124. //
  12125. // History: quintinb Created Header and rewrote 5/23/98
  12126. // quintinb NTRAID 162321, CM bits should not be installed on NT5 - 5/23/98
  12127. // quintinb NTRAID 192500, Support Dll's now always included with CM bits - 9-2-98
  12128. // quintinb we no longer ship the support dlls, removed support for them 4-19-2001
  12129. //
  12130. //+----------------------------------------------------------------------------
  12131. void IncludeOptionalCode()
  12132. {
  12133. if (g_bIncludeCmCode)
  12134. {
  12135. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode, c_pszOne, g_szInfFile));
  12136. }
  12137. else
  12138. {
  12139. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeCmCode, c_pszZero, g_szInfFile));
  12140. }
  12141. //
  12142. // We no longer ship the support files, erase the entry from the inf
  12143. //
  12144. MYVERIFY(0 != WritePrivateProfileString(c_pszCmakStatus, c_pszIncludeSupportDll, NULL, g_szInfFile));
  12145. }
  12146. //+----------------------------------------------------------------------------
  12147. //
  12148. // Function: HandleWindowMessagesWhileCompressing
  12149. //
  12150. // Synopsis: This function pumps messages while iexpress is running.
  12151. //
  12152. // Arguments: None
  12153. //
  12154. // Returns: Nothing
  12155. //
  12156. // History: quintinb Created 7/29/98
  12157. //
  12158. //+----------------------------------------------------------------------------
  12159. void HandleWindowMessagesWhileCompressing()
  12160. {
  12161. MSG msg;
  12162. while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  12163. {
  12164. TranslateMessage(&msg);
  12165. DispatchMessage(&msg);//lint !e534 ignore dispatchmessage return values
  12166. }
  12167. }
  12168. //+----------------------------------------------------------------------------
  12169. //
  12170. // Function: DisableWizardButtons
  12171. //
  12172. // Synopsis: This function disables the four wizard buttons at the bottom
  12173. // of the wizard page. Since these buttons aren't really ours we
  12174. // need to get the window handle of the parent dialog and then get
  12175. // the window handle of the individual button controls that we want to
  12176. // disable (Help, Cancel, Back, and Finish/Next). When we have the
  12177. // window handle of each button we call EnableWindow on the button
  12178. // to disable it. This function also disables the geek pane controls
  12179. // and the advanced checkbox on the build profile page if they exist.
  12180. //
  12181. // Arguments: HWND hDlg - Wizard page window handle (handle to our template page)
  12182. //
  12183. // Returns: Nothing
  12184. //
  12185. // History: quintinb Created 7/29/98
  12186. //
  12187. //+----------------------------------------------------------------------------
  12188. void DisableWizardButtons(HWND hDlg)
  12189. {
  12190. #define IDBACK 12323
  12191. #define IDNEXT 12324
  12192. #define IDFINISH 12325
  12193. HWND hCurrentPage = GetParent(hDlg);
  12194. if (hCurrentPage)
  12195. {
  12196. const int c_NumButtons = 5;
  12197. int iArrayOfButtonsToDisable[c_NumButtons] = {IDCANCEL, IDHELP, IDBACK, IDNEXT, IDFINISH};
  12198. //
  12199. // Disable the Cancel Button
  12200. //
  12201. for (int i = 0; i < c_NumButtons; i++)
  12202. {
  12203. HWND hButton = GetDlgItem(hCurrentPage, iArrayOfButtonsToDisable[i]);
  12204. if (hButton)
  12205. {
  12206. EnableWindow(hButton, FALSE);
  12207. }
  12208. }
  12209. }
  12210. //
  12211. // Disable the advanced button and the geek pane controls if they exist.
  12212. //
  12213. int iArrayOfItemsToDisable[] = {IDC_ADVANCED, IDC_COMBO1, IDC_COMBO2, IDC_COMBO3, IDC_EDIT1, IDC_BUTTON1};
  12214. const int c_NumItems = CELEMS(iArrayOfItemsToDisable);
  12215. for (int i = 0; i < c_NumItems; i++)
  12216. {
  12217. HWND hControl = GetDlgItem(hDlg, iArrayOfItemsToDisable[i]);
  12218. if (hControl)
  12219. {
  12220. EnableWindow(hControl, FALSE);
  12221. }
  12222. }
  12223. }
  12224. //+----------------------------------------------------------------------------
  12225. //
  12226. // Function: WriteInfBeginAndEndPrompts
  12227. //
  12228. // Synopsis: This function writes the Begin and End Prompt strings to the
  12229. // inf file. These are written dynamically because they need to
  12230. // contain the Service Name.
  12231. //
  12232. // Arguments: HINSTANCE hInstance - Instance Handle to get string resources with
  12233. // LPTSTR szInf - Inf file to write the prompts too
  12234. // LPTSTR szServiceName - Long Service name of the profile
  12235. //
  12236. // Returns: Nothing
  12237. //
  12238. // History: Created Header 7/31/98
  12239. //
  12240. //+----------------------------------------------------------------------------
  12241. void WriteInfBeginAndEndPrompts(HINSTANCE hInstance, LPCTSTR szInf, LPCTSTR szServiceName)
  12242. {
  12243. TCHAR szTemp[MAX_PATH+1];
  12244. TCHAR szPrompt[MAX_PATH+1];
  12245. MYVERIFY(0 != LoadString(hInstance, IDS_BeginPromptText, szTemp, MAX_PATH));
  12246. MYDBGASSERT(TEXT('\0') != szTemp[0]);
  12247. MYVERIFY(CELEMS(szPrompt) > (UINT)wsprintf(szPrompt, szTemp, szServiceName));
  12248. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszInfBeginPrompt, szPrompt, szInf);
  12249. MYVERIFY(0 != LoadString(hInstance, IDS_EndPromptText, szTemp, MAX_PATH));
  12250. MYDBGASSERT(TEXT('\0') != szTemp[0]);
  12251. MYVERIFY(CELEMS(szPrompt) > (UINT)wsprintf(szPrompt, szTemp, szServiceName));
  12252. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszInfEndPrompt, szPrompt, szInf);
  12253. }
  12254. //+----------------------------------------------------------------------------
  12255. //
  12256. // Function: WriteInfFile
  12257. //
  12258. // Synopsis: This function encapsulates all the code needed to write an inf file.
  12259. //
  12260. // Arguments: HINSTANCE hInstance - Instance handle to get string resources from
  12261. // LPCTSTR szInf - Name of the Inf to write to
  12262. // LPCTSTR szLongServiceName - Long Service Name of the Profile
  12263. //
  12264. // Returns: BOOL - returns TRUE if succeeded
  12265. //
  12266. // History: quintinb created 8/10/98
  12267. //
  12268. //+----------------------------------------------------------------------------
  12269. BOOL WriteInfFile(HINSTANCE hInstance, HWND hDlg, LPCTSTR szInf, LPCTSTR szLongServiceName)
  12270. {
  12271. TCHAR szTemp[MAX_PATH+1];
  12272. TCHAR szMsg[MAX_PATH+1];
  12273. GUID vGUID;
  12274. //
  12275. // Write out the version number of cmdial32.dll to the INF. This tells the installer
  12276. // what version of cmdial32.dll that this profile was built to use. We do this
  12277. // because if CM bits aren't bundled then we don't have cmdial32.dll to directly compare
  12278. // with. Note that we now get the version of cmdial32.dll from the cm binaries cab, not
  12279. // the version in system32.
  12280. //
  12281. #ifdef _WIN64
  12282. CmVersion CmdialVersion;
  12283. #else
  12284. wsprintf(szTemp, TEXT("%s\\cmdial32.dll"), g_szCmBinsTempDir);
  12285. if (!FileExists(szTemp))
  12286. {
  12287. if (FAILED(ExtractCmBinsFromExe(g_szSupportDir, g_szCmBinsTempDir)))
  12288. {
  12289. CMASSERTMSG(FALSE, TEXT("WriteInfFile -- ExtractCmBinsFromExe Failed."));
  12290. return FALSE;
  12291. }
  12292. }
  12293. CVersion CmdialVersion(szTemp);
  12294. #endif
  12295. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), CmdialVersion.GetVersionNumber()));
  12296. MYVERIFY(0 != WritePrivateProfileString(c_pszSectionCmDial32, c_pszVersion, szTemp, szInf));
  12297. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%d"), CmdialVersion.GetBuildAndQfeNumber()));
  12298. MYVERIFY(0 != WritePrivateProfileString(c_pszSectionCmDial32, c_pszVerBuild, szTemp, szInf));
  12299. //
  12300. // Create a Desktop GUID if one doesn't already exist (a new profile instead of
  12301. // an editted one).
  12302. //
  12303. ZeroMemory(szTemp, sizeof(szTemp));
  12304. GetPrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid,
  12305. TEXT(""), szTemp, CELEMS(szTemp), szInf); //lint !e534
  12306. if (TEXT('\0') == szTemp[0])
  12307. {
  12308. MYVERIFY(S_OK == CoCreateGuid(&vGUID));
  12309. MYVERIFY(0 != StringFromGUID2(vGUID, szTemp, MAX_PATH));
  12310. QS_WritePrivateProfileString(c_pszInfSectionStrings, c_pszDesktopGuid,
  12311. szTemp, szInf);
  12312. }
  12313. //
  12314. // Write out the Display LCID of the profile
  12315. //
  12316. wsprintf(szTemp, TEXT("%d"), GetSystemDefaultLCID());
  12317. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLCID, szTemp, szInf));
  12318. //
  12319. // Erase the existing File sections
  12320. //
  12321. MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles"), NULL, NULL, szInf));
  12322. MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles.SingleUser"), NULL, NULL, szInf));
  12323. MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.CopyFiles.ICM"),NULL, NULL, szInf));
  12324. MYVERIFY(0 != WritePrivateProfileString(TEXT("Remove.DelFiles"),NULL, NULL, szInf));
  12325. MYVERIFY(0 != WritePrivateProfileString(TEXT("Remove.DelFiles.ICM"),NULL, NULL, szInf));
  12326. MYVERIFY(0 != WritePrivateProfileString(TEXT("SourceDisksFiles"),NULL, NULL, szInf));
  12327. MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.AddReg.Icon"),NULL, NULL, szInf));
  12328. MYVERIFY(0 != WritePrivateProfileString(TEXT("RegisterOCXSection"),NULL, NULL, szInf));
  12329. MYVERIFY(0 != WritePrivateProfileString(TEXT("Xnstall.RenameReg"),NULL, NULL, szInf));
  12330. if (!CreateMergedProfile())
  12331. {
  12332. return FALSE;
  12333. }
  12334. IncludeOptionalCode();
  12335. //
  12336. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  12337. // (win95 only). This call will return 0.
  12338. //
  12339. WritePrivateProfileString(NULL, NULL, NULL, szInf); //lint !e534 this call will always return 0
  12340. //
  12341. // Add the dynamic file sections to the install
  12342. //
  12343. if (WriteFileSections(hDlg) == FALSE)
  12344. {
  12345. return FALSE;
  12346. }
  12347. //
  12348. // Write the Begin and End Prompts
  12349. //
  12350. WriteInfBeginAndEndPrompts(hInstance, szInf, szLongServiceName);
  12351. return TRUE;
  12352. }
  12353. //+----------------------------------------------------------------------------
  12354. //
  12355. // Function: ConCatPathAndWriteToSed
  12356. //
  12357. // Synopsis: This function is a wrapper for WriteSed that concats two paths
  12358. // together before calling WriteSed. This allows the caller to
  12359. // store a common path (such as the system directory) and call
  12360. // WriteSed with a bunch of different files all in the same directory
  12361. // without having to individually concatenate the common path and the
  12362. // filenames.
  12363. //
  12364. // Arguments: HWND hDlg - windows handle of the current dialog, needed for error messages
  12365. // LPCTSTR pszFileName - Name of the file
  12366. // LPCTSTR pszPath - Name of the path to prepend to the filename
  12367. // int* pFileNum - the number of the file in the SED file
  12368. // LPCTSTR szSed - the SED file to write to
  12369. //
  12370. // Returns: BOOL - Returns TRUE if succeeded
  12371. //
  12372. // History: quintinb Created 8/10/98
  12373. //
  12374. //+----------------------------------------------------------------------------
  12375. BOOL ConCatPathAndWriteToSed(HWND hDlg, LPCTSTR pszFileName, LPCTSTR pszPath,
  12376. int* pFileNum, LPCTSTR szSed)
  12377. {
  12378. TCHAR szTemp[MAX_PATH+1];
  12379. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s\\%s"), pszPath, pszFileName));
  12380. return WriteSED(hDlg, szTemp, pFileNum, szSed);
  12381. }
  12382. //+----------------------------------------------------------------------------
  12383. //
  12384. // Function: ConstructSedFile
  12385. //
  12386. // Synopsis: This function encapsulates all the work of creating an SED file.
  12387. //
  12388. // Arguments: HWND hDlg - window handle of the current dialog for error messages
  12389. // LPCTSTR szSed - filename of the sed file to write
  12390. // LPCTSTR szExe - executable filename for the SED to compress to
  12391. //
  12392. // Returns: BOOL - Returns TRUE if successful
  12393. //
  12394. // History: quintinb Created 8/10/98
  12395. //
  12396. //+----------------------------------------------------------------------------
  12397. BOOL ConstructSedFile(HWND hDlg, LPCTSTR szSed, LPCTSTR szExe)
  12398. {
  12399. int iFileNum=0;
  12400. TCHAR szTemp[MAX_PATH+1];
  12401. BOOL bReturn = TRUE;
  12402. CPlatform cmplat;
  12403. //
  12404. // Clear the SED and begin writing new settings
  12405. //
  12406. EraseSEDFiles(szSed);
  12407. //
  12408. // Write the Installer Package Exe Name
  12409. //
  12410. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings,
  12411. c_pszTargetName, szExe, szSed));
  12412. //
  12413. // Write the Long Service Name as the FriendlyName
  12414. //
  12415. if (!WritePrivateProfileString(c_pszInfSectionStrings, c_pszFriendlyName,
  12416. g_szLongServiceName, szSed))
  12417. {
  12418. FileAccessErr(hDlg, szSed);
  12419. return FALSE;
  12420. }
  12421. //
  12422. // Load up IDS_INSTALL_PROMPT from the resources
  12423. // Format the string using the g_szLongServiceName
  12424. //
  12425. LPTSTR pszInstallPromptTmp = CmFmtMsg(g_hInstance, IDS_INSTALL_PROMPT, g_szLongServiceName);
  12426. if (pszInstallPromptTmp)
  12427. {
  12428. //
  12429. // Write the Install Prompt string
  12430. //
  12431. if (!WritePrivateProfileString(c_pszInfSectionStrings, c_pszInstallPrompt,
  12432. pszInstallPromptTmp, szSed))
  12433. {
  12434. FileAccessErr(hDlg, szSed);
  12435. return FALSE;
  12436. }
  12437. CmFree(pszInstallPromptTmp);
  12438. pszInstallPromptTmp = NULL;
  12439. }
  12440. else
  12441. {
  12442. CMASSERTMSG(FALSE, TEXT("ConstructSedFile -- CmFmtMsg returned NULL."));
  12443. FileAccessErr(hDlg, szSed);
  12444. return FALSE;
  12445. }
  12446. //
  12447. // Clear the Target File Version Key
  12448. //
  12449. MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, c_pszTargetFileVersion,
  12450. TEXT(""), szSed));
  12451. //
  12452. // Set the Reboot Mode
  12453. //
  12454. MYVERIFY(0 != WritePrivateProfileString(c_pszOptions, TEXT("RebootMode"), TEXT("N"),
  12455. g_szSedFile));
  12456. //
  12457. // Write the License text file into the SED. Otherwise make sure to clear it.
  12458. //
  12459. if (TEXT('\0') != g_szLicense[0])
  12460. {
  12461. //
  12462. // We write the license text file into the SED in two places. Once as a regular
  12463. // file and again using the c_pszDisplayLicense entry. Thus we copy it to the
  12464. // users profile dir and display it at install time. We want to make sure that
  12465. // we use the full file name in the SED files section, but the short file name
  12466. // in the part of the SED that actually lauches the license at install time
  12467. /// (aka the strings section).
  12468. //
  12469. TCHAR szTempName[MAX_PATH+1];
  12470. MYVERIFY (FALSE != GetShortFileName(g_szLicense, szTempName));
  12471. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s"), g_szOsdir,
  12472. g_szShortServiceName, szTempName));
  12473. bReturn &= WriteSED(hDlg, g_szLicense, &iFileNum, szSed);
  12474. }
  12475. else
  12476. {
  12477. szTemp[0] = TEXT('\0');
  12478. }
  12479. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszDisplayLicense,
  12480. szTemp, szSed));
  12481. //
  12482. // Add the install command to the SED file
  12483. //
  12484. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT(".\\cmstp.exe %s.inf"), g_szShortServiceName));
  12485. MYVERIFY(0 != WritePrivateProfileString(c_pszInfSectionStrings, c_pszAppLaunched,
  12486. szTemp, szSed));
  12487. //
  12488. // Get the System Directory path to concat to IEXPRESS and CM Files
  12489. //
  12490. TCHAR szSystemDir[MAX_PATH+1];
  12491. MYVERIFY(0 != GetSystemDirectory(szSystemDir, MAX_PATH));
  12492. //
  12493. // Begin Adding Files to the SED File. Note that all 32-bit profiles
  12494. // must include IExpress file(s)
  12495. //
  12496. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("advpack.dll"), szSystemDir, &iFileNum, szSed);
  12497. #ifndef _WIN64
  12498. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("w95inf16.dll"), g_szSupportDir, &iFileNum, szSed);
  12499. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("w95inf32.dll"), g_szSupportDir, &iFileNum, szSed);
  12500. //
  12501. // Always include cmstp.exe. Note that on x86 it comes from the binaries CAB.
  12502. //
  12503. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmstp.exe"), g_szCmBinsTempDir, &iFileNum, szSed);
  12504. #else
  12505. //
  12506. // Always include cmstp.exe. Note that on IA64 we get it from the system directory.
  12507. //
  12508. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmstp.exe"), szSystemDir, &iFileNum, szSed);
  12509. #endif
  12510. if (g_bIncludeCmCode)
  12511. {
  12512. //
  12513. // Readme.txt is a special case since it is a localizable filename.
  12514. //
  12515. MYVERIFY(0 != LoadString(g_hInstance, IDS_READMETXT, szTemp, MAX_PATH));
  12516. bReturn &= ConCatPathAndWriteToSed(hDlg, szTemp, g_szSupportDir, &iFileNum, szSed);
  12517. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("instcm.inf"), g_szSupportDir, &iFileNum, szSed);
  12518. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmbins.exe"), g_szSupportDir, &iFileNum, szSed);
  12519. #ifndef _WIN64
  12520. if (!(IsAlpha()))
  12521. {
  12522. //
  12523. // Add the win95 config files
  12524. //
  12525. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("ccfg95.dll"), g_szSupportDir, &iFileNum, szSed);
  12526. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cnet16.dll"), g_szSupportDir, &iFileNum, szSed);
  12527. //
  12528. // Add the Unicode to Ansi Conversion layer
  12529. //
  12530. bReturn &= ConCatPathAndWriteToSed(hDlg, TEXT("cmutoa.dll"), g_szSupportDir, &iFileNum, szSed);
  12531. }
  12532. #endif
  12533. }
  12534. //
  12535. // Write entry for Inf in SED
  12536. //
  12537. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.inf"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
  12538. bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
  12539. //
  12540. // Write the Cmp to the Sed
  12541. //
  12542. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cmp"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
  12543. bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
  12544. //
  12545. // Write the Cms to the Sed
  12546. //
  12547. MYVERIFY(CELEMS(szTemp) > (UINT)wsprintf(szTemp, TEXT("%s%s\\%s.cms"), g_szOsdir, g_szShortServiceName, g_szShortServiceName));
  12548. bReturn &= WriteSED(hDlg, szTemp, &iFileNum, szSed);
  12549. //
  12550. // Now include the Custom Added Files
  12551. //
  12552. bReturn &= WriteSED(hDlg, g_szPhonebk, &iFileNum, szSed);
  12553. bReturn &= WriteSED(hDlg, g_szRegion, &iFileNum, szSed);
  12554. bReturn &= WriteSED(hDlg, g_szBrandBmp, &iFileNum, szSed);
  12555. bReturn &= WriteSED(hDlg, g_szPhoneBmp, &iFileNum, szSed);
  12556. bReturn &= WriteSED(hDlg, g_szLargeIco, &iFileNum, szSed);
  12557. bReturn &= WriteSED(hDlg, g_szSmallIco, &iFileNum, szSed);
  12558. bReturn &= WriteSED(hDlg, g_szTrayIco, &iFileNum, szSed);
  12559. bReturn &= WriteSED(hDlg, g_szHelp, &iFileNum, szSed);
  12560. bReturn &= WriteSED(hDlg, g_szCmProxyFile, &iFileNum, szSed);
  12561. bReturn &= WriteSED(hDlg, g_szCmRouteFile, &iFileNum, szSed);
  12562. bReturn &= WriteSED(hDlg, g_szVpnFile, &iFileNum, szSed);
  12563. bReturn &=WriteSEDMenuItemFiles(hDlg, &iFileNum, szSed);
  12564. bReturn &=WriteSEDConActFiles(hDlg, &iFileNum, szSed);
  12565. bReturn &=WriteSEDExtraFiles(hDlg, &iFileNum, szSed);
  12566. bReturn &=WriteSEDRefsFiles(hDlg, &iFileNum, szSed);
  12567. bReturn &=WriteSEDDnsFiles(hDlg, &iFileNum, szSed);
  12568. //
  12569. // By calling WritePrivateProfileString with all NULL's we flush the file cache
  12570. // (win95 only). This call will return 0.
  12571. //
  12572. WritePrivateProfileString(NULL, NULL, NULL, g_szSedFile); //lint !e534 this call will always return 0
  12573. return bReturn;
  12574. }
  12575. void AddAllSectionsInCurrentFileToCombo(HWND hDlg, UINT uComboId, LPCTSTR pszFile)
  12576. {
  12577. if ((NULL == hDlg) || (0 == uComboId) || (NULL == pszFile))
  12578. {
  12579. CMASSERTMSG(FALSE, TEXT("AddAllKeysInCurrentSectionToCombo -- Invalid Parameter passed."));
  12580. return;
  12581. }
  12582. //
  12583. // Reset the combobox contents
  12584. //
  12585. SendDlgItemMessage(hDlg, uComboId, CB_RESETCONTENT, 0, 0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
  12586. //
  12587. // First lets get all of the sections from the existing cmp
  12588. //
  12589. LPTSTR pszAllSections = GetPrivateProfileStringWithAlloc(NULL, NULL, TEXT(""), pszFile);
  12590. //
  12591. // Okay, now we have all of the sections in a buffer, lets add them to the combo
  12592. //
  12593. LPTSTR pszCurrentSection = pszAllSections;
  12594. while (pszCurrentSection && TEXT('\0') != pszCurrentSection[0])
  12595. {
  12596. //
  12597. // Okay, lets add all of the sections that we found
  12598. //
  12599. MYVERIFY(CB_ERR!= SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, 0, (LPARAM)pszCurrentSection));
  12600. //
  12601. // Now advance to the next string in pszAllSections
  12602. //
  12603. pszCurrentSection = pszCurrentSection + lstrlen(pszCurrentSection) + 1;
  12604. }
  12605. CmFree(pszAllSections);
  12606. }
  12607. void AddFilesToCombo(HWND hDlg, UINT uComboId)
  12608. {
  12609. //
  12610. // Reset the combobox contents
  12611. //
  12612. SendDlgItemMessage(hDlg, uComboId, CB_RESETCONTENT, 0, 0); //lint !e534 CB_RESETCONTENT doesn't return anything useful
  12613. //
  12614. // Add the profile cmp
  12615. //
  12616. LRESULT lResult = SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, (WPARAM)0, (LPARAM)GetName(g_szCmpFile));
  12617. if (CB_ERR != lResult)
  12618. {
  12619. SendDlgItemMessage(hDlg, uComboId, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)g_szCmpFile);
  12620. }
  12621. else
  12622. {
  12623. CMASSERTMSG(FALSE, TEXT("AddFilesToCombo -- unable to set item data"));
  12624. }
  12625. //
  12626. // Add the profile cms
  12627. //
  12628. lResult = SendDlgItemMessage(hDlg, uComboId, CB_ADDSTRING, (WPARAM)0, (LPARAM)GetName(g_szCmsFile));
  12629. if (CB_ERR != lResult)
  12630. {
  12631. SendDlgItemMessage(hDlg, uComboId, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)g_szCmsFile);
  12632. }
  12633. else
  12634. {
  12635. CMASSERTMSG(FALSE, TEXT("AddFilesToCombo -- unable to set item data"));
  12636. }
  12637. }
  12638. BOOL GetCurrentComboSelectionAlloc(HWND hDlg, UINT uComboId, LPTSTR* ppszText)
  12639. {
  12640. if ((NULL == hDlg) || (0 == uComboId) || (NULL == ppszText))
  12641. {
  12642. CMASSERTMSG(FALSE, TEXT("GetCurrentComboSelectionAlloc -- invalid parameter"));
  12643. return FALSE;
  12644. }
  12645. *ppszText = NULL;
  12646. LRESULT lTextLen;
  12647. BOOL bReturn = FALSE;
  12648. LRESULT lResult = SendDlgItemMessage(hDlg, uComboId, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  12649. if (CB_ERR != lResult)
  12650. {
  12651. lTextLen = SendDlgItemMessage(hDlg, uComboId, CB_GETLBTEXTLEN, (WPARAM)lResult, (LPARAM)0);
  12652. if (0 != lTextLen)
  12653. {
  12654. lTextLen++; // NULL char
  12655. *ppszText = (LPTSTR)CmMalloc(sizeof(TCHAR)*lTextLen);
  12656. if (*ppszText)
  12657. {
  12658. lResult = SendDlgItemMessage(hDlg, uComboId, CB_GETLBTEXT, (WPARAM)lResult, (LPARAM)(*ppszText));
  12659. if (0 == lResult)
  12660. {
  12661. goto exit;
  12662. }
  12663. else
  12664. {
  12665. bReturn = TRUE;
  12666. }
  12667. }
  12668. else
  12669. {
  12670. goto exit;
  12671. }
  12672. }
  12673. else
  12674. {
  12675. goto exit;
  12676. }
  12677. }
  12678. else
  12679. {
  12680. goto exit;
  12681. }
  12682. exit:
  12683. if (FALSE == bReturn)
  12684. {
  12685. CmFree(*ppszText);
  12686. }
  12687. return bReturn;
  12688. }
  12689. //+----------------------------------------------------------------------------
  12690. //
  12691. // Function: GetCurrentEditControlTextAlloc
  12692. //
  12693. // Synopsis: Figures out the length of the text in the edit control specified
  12694. // by the given window handle, allocates a buffer large enough to
  12695. // hold the text and then retrieves the text and stores it in the
  12696. // allocated buffer. The buffer is the caller's responsibility to
  12697. // free. Note that we ensure the data is roundtripable.
  12698. //
  12699. // Arguments: HWND hEditText - window handle of the edit control to get the text from
  12700. // LPTSTR* ppszText - pointer to a string pointer to recieve the output buffer
  12701. //
  12702. // Returns: int - Returns the number of characters copied to *ppszText
  12703. // 0 could be an error value but often means the control is empty
  12704. // -1 means that the text failed MBCS conversion and should not be used
  12705. //
  12706. // History: quintinb Created 04/07/00
  12707. //
  12708. //+----------------------------------------------------------------------------
  12709. int GetCurrentEditControlTextAlloc(HWND hEditText, LPTSTR* ppszText)
  12710. {
  12711. if ((NULL == hEditText) || (NULL == ppszText))
  12712. {
  12713. CMASSERTMSG(FALSE, TEXT("GetCurrentEditControlTextAlloc -- invalid parameter"));
  12714. return 0;
  12715. }
  12716. *ppszText = NULL;
  12717. int iReturn = 0;
  12718. LRESULT lResult;
  12719. LRESULT lTextLen = SendMessage(hEditText, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0);
  12720. if (0 != lTextLen)
  12721. {
  12722. lTextLen++; // NULL char
  12723. *ppszText = (LPTSTR)CmMalloc(sizeof(TCHAR)*lTextLen);
  12724. if (*ppszText)
  12725. {
  12726. lResult = SendMessage(hEditText, WM_GETTEXT, (WPARAM)lTextLen, (LPARAM)(*ppszText));
  12727. if (0 == lResult)
  12728. {
  12729. goto exit;
  12730. }
  12731. else
  12732. {
  12733. #ifdef UNICODE
  12734. //
  12735. // We want to make sure that we can convert the strings to MBCS. If we cannot then we are not
  12736. // going to be able to store the string in the our ANSI data files (.cms, .cmp, .inf, etc.).
  12737. // Thus we need to convert the string to MBCS and then back to UNICODE. We will then compare the original
  12738. // string to the resultant string and see if they match.
  12739. //
  12740. if (!TextIsRoundTripable(*ppszText, TRUE))
  12741. {
  12742. //
  12743. // Set the return code to an error value.
  12744. //
  12745. iReturn = -1;
  12746. goto exit;
  12747. }
  12748. #endif
  12749. iReturn = (int)lResult;
  12750. }
  12751. }
  12752. else
  12753. {
  12754. goto exit;
  12755. }
  12756. }
  12757. else
  12758. {
  12759. goto exit;
  12760. }
  12761. exit:
  12762. if ((0 == iReturn) || (-1 == iReturn))
  12763. {
  12764. CmFree(*ppszText);
  12765. *ppszText = NULL;
  12766. }
  12767. return iReturn;
  12768. }
  12769. //+----------------------------------------------------------------------------
  12770. //
  12771. // Function: RemoveBracketsFromSectionString
  12772. //
  12773. // Synopsis: Removes brackets from section string. If a string is
  12774. // invalid, this function returns a newly allocated
  12775. // valid string without brackets and deleted the old invalid one.
  12776. // If there are no valid characters in the string this function
  12777. // return NULL in ppszSection. It is the caller's responibility to
  12778. // free the string.
  12779. // This function was created to fix Bug 189379 for Whistler.
  12780. //
  12781. // Arguments: LPTSTR *ppszSection - pointer to the address of the string
  12782. //
  12783. // History: tomkel Created 11/15/2000
  12784. //
  12785. //+----------------------------------------------------------------------------
  12786. BOOL RemoveBracketsFromSectionString(LPTSTR *ppszSection)
  12787. {
  12788. BOOL bReturn = FALSE;
  12789. LPTSTR pszSection = NULL;
  12790. const TCHAR* const c_szBadSectionChars = TEXT("[]");
  12791. const TCHAR* const c_szLeftBracket = TEXT("[");
  12792. const TCHAR* const c_szRightBracket = TEXT("]");
  12793. if (NULL == ppszSection)
  12794. {
  12795. return bReturn;
  12796. }
  12797. pszSection = *ppszSection;
  12798. if (NULL != pszSection)
  12799. {
  12800. LPTSTR pszValidSection = NULL;
  12801. LPTSTR pszToken = NULL;
  12802. //
  12803. // We have a string so try to find an occurence of a bracket [].
  12804. //
  12805. if (CmStrStr(pszSection, c_szLeftBracket) || CmStrStr(pszSection, c_szRightBracket))
  12806. {
  12807. //
  12808. // The pszSection string contains brackets.
  12809. // This treats brackets [] as delimiters. The loop concatenates the newly
  12810. // valid string.
  12811. //
  12812. pszToken = CmStrtok(pszSection, c_szBadSectionChars);
  12813. if (NULL != pszToken)
  12814. {
  12815. //
  12816. // Found at least one valid token
  12817. //
  12818. while (NULL != pszToken)
  12819. {
  12820. if (NULL == pszValidSection)
  12821. {
  12822. pszValidSection = CmStrCpyAlloc(pszToken);
  12823. }
  12824. else
  12825. {
  12826. pszValidSection = CmStrCatAlloc(&pszValidSection, pszToken);
  12827. }
  12828. //
  12829. // Find the next valid token
  12830. //
  12831. pszToken = CmStrtok(NULL, c_szBadSectionChars);
  12832. }
  12833. if ( pszValidSection )
  12834. {
  12835. //
  12836. // We encountered brackets []. Lets copy the valid string back to
  12837. // pszSection string so that the code below this section doesn't
  12838. // need to be modified.
  12839. //
  12840. CmFree(pszSection);
  12841. pszSection = CmStrCpyAlloc(pszValidSection);
  12842. CmFree(pszValidSection);
  12843. pszValidSection = NULL;
  12844. }
  12845. }
  12846. else
  12847. {
  12848. //
  12849. // There are no valid tokens. Delete the string and set it to NULL.
  12850. //
  12851. CmFree(pszSection);
  12852. pszSection = NULL;
  12853. }
  12854. *ppszSection = pszSection;
  12855. bReturn = TRUE;
  12856. }
  12857. else
  12858. {
  12859. //
  12860. // Nothing to parse, which is ok.
  12861. //
  12862. bReturn = TRUE;
  12863. }
  12864. }
  12865. else
  12866. {
  12867. //
  12868. // Nothing to parse, which is ok.
  12869. //
  12870. bReturn = TRUE;
  12871. }
  12872. return bReturn;
  12873. }
  12874. //+----------------------------------------------------------------------------
  12875. //
  12876. // Function: ProcessGeekPane
  12877. //
  12878. // Synopsis: Processes windows messages for the dialog which allows user to
  12879. // edit the cms/cmp files directly for features not exposed in CMAK
  12880. // directly.
  12881. //
  12882. // Arguments: WND hDlg - dialog window handle
  12883. // UINT message - message identifier
  12884. // WPARAM wParam - wParam Value
  12885. // LPARAM lParam - lParam Value
  12886. //
  12887. //
  12888. // History: quintinb Created 03/26/00
  12889. //
  12890. //+----------------------------------------------------------------------------
  12891. INT_PTR APIENTRY ProcessGeekPane(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  12892. {
  12893. SetDefaultGUIFont(hDlg, message, IDC_EDIT1);
  12894. SetDefaultGUIFont(hDlg, message, IDC_COMBO1);
  12895. SetDefaultGUIFont(hDlg, message, IDC_COMBO2);
  12896. SetDefaultGUIFont(hDlg, message, IDC_COMBO3);
  12897. LRESULT lResult;
  12898. static LPTSTR pszFile = NULL;
  12899. static LPTSTR pszSection = NULL;
  12900. static LPTSTR pszKey = NULL;
  12901. LPTSTR pszValue = NULL;
  12902. HWND hControl;
  12903. static HWND hwndSectionEditControl = NULL;
  12904. static HWND hwndKeyEditControl = NULL;
  12905. COMBOBOXINFO cbInfo;
  12906. NMHDR* pnmHeader = (NMHDR*)lParam;
  12907. DWORD dwFinishPage;
  12908. ProcessBold(hDlg,message);
  12909. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_ADVANCED)) return TRUE;
  12910. if (ProcessCancel(hDlg,message,lParam))
  12911. {
  12912. if (0 == GetWindowLongPtr(hDlg, DWLP_MSGRESULT))
  12913. {
  12914. //
  12915. // If the user accepted the cancel then the DWLP_MSGRESULT value will be FALSE. If
  12916. // they chose to deny the cancel it will be TRUE. Thus if we need to, let's free
  12917. // up any allocated resources. If you change the free code, make sure to change
  12918. // it below in the kill active state too.
  12919. //
  12920. CmFree(pszSection);
  12921. pszSection = NULL;
  12922. CmFree(pszKey);
  12923. pszKey = NULL;
  12924. }
  12925. return TRUE;
  12926. }
  12927. switch (message)
  12928. {
  12929. case WM_INITDIALOG:
  12930. //
  12931. // Fill in the files combo
  12932. //
  12933. AddFilesToCombo(hDlg, IDC_COMBO1);
  12934. //
  12935. // Choose the Cms File because it is the one they are most likely to edit
  12936. //
  12937. lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)GetName(g_szCmsFile));
  12938. if (CB_ERR != lResult)
  12939. {
  12940. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0));
  12941. }
  12942. pszFile = g_szCmsFile;
  12943. AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
  12944. //
  12945. // Choose the first section in the list, don't assert because there may not be any
  12946. //
  12947. SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  12948. if (GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection))
  12949. {
  12950. AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
  12951. //
  12952. // Choose the first key in the list, don't assert because there may not be any
  12953. //
  12954. SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  12955. GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
  12956. //
  12957. // Finally fill in the edit control
  12958. //
  12959. pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
  12960. if (pszValue)
  12961. {
  12962. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
  12963. CmFree(pszValue);
  12964. }
  12965. else
  12966. {
  12967. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  12968. }
  12969. }
  12970. //
  12971. // Now lets get the window handles to the edit control portion of the section and key combobox controls
  12972. //
  12973. ZeroMemory(&cbInfo, sizeof(cbInfo));
  12974. cbInfo.cbSize = sizeof(cbInfo);
  12975. hControl = GetDlgItem(hDlg, IDC_COMBO2);
  12976. if (hControl)
  12977. {
  12978. if (GetComboBoxInfo (hControl, &cbInfo))
  12979. {
  12980. hwndSectionEditControl = cbInfo.hwndItem;
  12981. }
  12982. }
  12983. ZeroMemory(&cbInfo, sizeof(cbInfo));
  12984. cbInfo.cbSize = sizeof(cbInfo);
  12985. hControl = GetDlgItem(hDlg, IDC_COMBO3);
  12986. if (hControl)
  12987. {
  12988. if (GetComboBoxInfo (hControl, &cbInfo))
  12989. {
  12990. hwndKeyEditControl = cbInfo.hwndItem;
  12991. }
  12992. }
  12993. break;
  12994. case WM_COMMAND:
  12995. switch (LOWORD(wParam))
  12996. {
  12997. case IDC_COMBO1:
  12998. if (HIWORD(wParam) == CBN_SELCHANGE)
  12999. {
  13000. lResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  13001. if (CB_ERR != lResult)
  13002. {
  13003. pszFile = (LPTSTR)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETITEMDATA, (WPARAM)lResult, (LPARAM)0);
  13004. if (NULL != pszFile)
  13005. {
  13006. AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
  13007. //
  13008. // Choose the first section in the list, don't assert because there may not be any
  13009. //
  13010. SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  13011. }
  13012. }
  13013. //
  13014. // Note that we don't break here, we fail through to pick up changes for the
  13015. // section and keys combo boxes
  13016. //
  13017. }
  13018. else
  13019. {
  13020. break;
  13021. }
  13022. case IDC_COMBO2:
  13023. if (HIWORD(wParam) == CBN_SELCHANGE)
  13024. {
  13025. CmFree(pszSection);
  13026. GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection);
  13027. AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
  13028. //
  13029. // Choose the first key in the list, don't assert because there may not be any
  13030. //
  13031. SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  13032. }
  13033. else if (HIWORD(wParam) == CBN_EDITCHANGE)
  13034. {
  13035. CmFree(pszSection);
  13036. if (-1 != GetCurrentEditControlTextAlloc(hwndSectionEditControl, &pszSection))
  13037. {
  13038. AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
  13039. //
  13040. // Choose the first key in the list, don't assert because there may not be any
  13041. //
  13042. SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  13043. }
  13044. else
  13045. {
  13046. break;
  13047. }
  13048. }
  13049. else
  13050. {
  13051. //
  13052. // Note we don't break if the message is CBN_SELCHANGE or CBN_EDITCHANGE because
  13053. // we want to execute the code for the key combo changing
  13054. //
  13055. break;
  13056. }
  13057. case IDC_COMBO3:
  13058. if (HIWORD(wParam) == CBN_SELCHANGE)
  13059. {
  13060. CmFree(pszKey);
  13061. GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
  13062. //
  13063. // Fill in the edit control
  13064. //
  13065. if (pszKey)
  13066. {
  13067. pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
  13068. if (pszValue)
  13069. {
  13070. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
  13071. CmFree(pszValue);
  13072. }
  13073. else
  13074. {
  13075. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13076. }
  13077. }
  13078. else
  13079. {
  13080. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13081. }
  13082. }
  13083. else if (HIWORD(wParam) == CBN_EDITCHANGE)
  13084. {
  13085. CmFree(pszKey);
  13086. if (-1 != GetCurrentEditControlTextAlloc(hwndKeyEditControl, &pszKey))
  13087. {
  13088. //
  13089. // Fill in the edit control
  13090. //
  13091. if (pszKey)
  13092. {
  13093. pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
  13094. if (pszValue)
  13095. {
  13096. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
  13097. CmFree(pszValue);
  13098. }
  13099. else
  13100. {
  13101. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13102. }
  13103. }
  13104. else
  13105. {
  13106. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13107. }
  13108. }
  13109. else
  13110. {
  13111. break;
  13112. }
  13113. }
  13114. break;
  13115. case IDC_BUTTON1: // Update Value
  13116. if (RemoveBracketsFromSectionString(&pszSection))
  13117. {
  13118. //
  13119. // Successfully removed brackets. Check if the valid string is empty. If so clear
  13120. // the fields
  13121. //
  13122. if (NULL == pszSection)
  13123. {
  13124. //
  13125. // The section string contained all invalid characters, so clear the combobox
  13126. //
  13127. lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13128. //
  13129. // Clear the other edit boxes by sending a CBN_EDITCHANGE notification
  13130. //
  13131. lResult= SendMessage(hDlg, WM_COMMAND, (WPARAM)MAKEWPARAM((WORD)IDC_COMBO2,(WORD)CBN_EDITCHANGE), (LPARAM)GetDlgItem(hDlg,IDC_COMBO2));
  13132. }
  13133. }
  13134. else
  13135. {
  13136. CMASSERTMSG(FALSE, TEXT("ProcessGeekPane -- Trying to remove brackets from invalid section string."));
  13137. return 1;
  13138. }
  13139. hControl = GetDlgItem(hDlg, IDC_EDIT1);
  13140. if (hControl)
  13141. {
  13142. int iReturn = GetCurrentEditControlTextAlloc(hControl, &pszValue);
  13143. if (0 == iReturn)
  13144. {
  13145. pszValue = NULL; // delete the value
  13146. }
  13147. else if (-1 == iReturn)
  13148. {
  13149. return 1;
  13150. }
  13151. }
  13152. else
  13153. {
  13154. CMASSERTMSG(FALSE, TEXT("ProcessGeekPane -- Unable to get the window handle for the text control."));
  13155. return 1;
  13156. }
  13157. if (NULL == pszSection)
  13158. {
  13159. ShowMessage(hDlg, IDS_NEED_SECTION, MB_OK);
  13160. return 1;
  13161. }
  13162. else if (NULL == pszKey)
  13163. {
  13164. int iReturn = IDNO;
  13165. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_DELETE_SECTION, pszSection);
  13166. if (pszMsg)
  13167. {
  13168. iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
  13169. CmFree(pszMsg);
  13170. }
  13171. if (IDNO == iReturn)
  13172. {
  13173. return 1;
  13174. }
  13175. //
  13176. // Need to clear the value in case the section is NULL and the value isn't
  13177. // even though the WritePrivateProfileString handles it correctly
  13178. //
  13179. CmFree(pszValue);
  13180. pszValue = NULL;
  13181. }
  13182. else if (NULL == pszValue)
  13183. {
  13184. //
  13185. // This else if needs to be the last one
  13186. // The following message should only be displayed
  13187. // if NULL != pszKey && NULL != pszSection && NULL == pszValue
  13188. // Prompt user to ask to delete this key.
  13189. //
  13190. int iReturn = IDNO;
  13191. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_DELETE_KEY, pszKey);
  13192. if (pszMsg)
  13193. {
  13194. iReturn = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
  13195. CmFree(pszMsg);
  13196. }
  13197. if (IDNO == iReturn)
  13198. {
  13199. return 1;
  13200. }
  13201. }
  13202. MYVERIFY(0 != WritePrivateProfileString(pszSection, pszKey, pszValue, pszFile));
  13203. CmFree(pszValue);
  13204. //
  13205. // Make sure to reselect the section and key the user had before (especially important
  13206. // if the user just added a new section or file). First add all of the sections
  13207. //
  13208. AddAllSectionsInCurrentFileToCombo(hDlg, IDC_COMBO2, (LPCTSTR)pszFile);
  13209. //
  13210. // Select the correct section
  13211. //
  13212. lResult = SendDlgItemMessage(hDlg, IDC_COMBO2, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszSection);
  13213. if (CB_ERR == lResult)
  13214. {
  13215. //
  13216. // Then the user deleted the value, lets select the first in the list
  13217. //
  13218. CmFree(pszSection);
  13219. SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  13220. GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO2, &pszSection);
  13221. }
  13222. else
  13223. {
  13224. SendDlgItemMessage(hDlg, IDC_COMBO2, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
  13225. }
  13226. //
  13227. // Now add all of the keys in that section
  13228. //
  13229. AddAllKeysInCurrentSectionToCombo(hDlg, IDC_COMBO3, pszSection, pszFile);
  13230. //
  13231. // Select the correct key
  13232. //
  13233. lResult = SendDlgItemMessage(hDlg, IDC_COMBO3, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszKey);
  13234. if (CB_ERR == lResult)
  13235. {
  13236. //
  13237. // Then the user deleted the value, lets select the first in the list
  13238. //
  13239. CmFree(pszKey);
  13240. SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  13241. GetCurrentComboSelectionAlloc(hDlg, IDC_COMBO3, &pszKey);
  13242. lResult = 0;
  13243. }
  13244. else
  13245. {
  13246. SendDlgItemMessage(hDlg, IDC_COMBO3, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
  13247. }
  13248. //
  13249. // Fill in the edit control, since the user may have deleted the last selection
  13250. //
  13251. pszValue = GetPrivateProfileStringWithAlloc(pszSection, pszKey, TEXT(""), pszFile);
  13252. if (pszValue)
  13253. {
  13254. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)pszValue);
  13255. CmFree(pszValue);
  13256. }
  13257. else
  13258. {
  13259. SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  13260. }
  13261. break;
  13262. default:
  13263. break;
  13264. }
  13265. break;
  13266. case WM_NOTIFY:
  13267. if (NULL == pnmHeader)
  13268. {
  13269. return FALSE;
  13270. }
  13271. switch (pnmHeader->code)
  13272. {
  13273. case PSN_KILLACTIVE:
  13274. //
  13275. // Free up any allocated values. If you add new values to free here, also
  13276. // make sure to add them in the cancel case.
  13277. //
  13278. CmFree(pszSection);
  13279. pszSection = NULL;
  13280. CmFree(pszKey);
  13281. pszKey = NULL;
  13282. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  13283. return 1;
  13284. break; //lint !e527 this line isn't reachable but
  13285. // keep it in case the return is removed
  13286. case PSN_SETACTIVE:
  13287. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  13288. break;
  13289. case PSN_WIZBACK:
  13290. CMASSERTMSG(FALSE, TEXT("There shouldn't be a back button on the Geek Pane, why are we getting PSN_WIZBACK?"));
  13291. break;
  13292. case PSN_WIZNEXT:
  13293. if (BuildProfileExecutable(hDlg))
  13294. {
  13295. dwFinishPage = g_bIEAKBuild ? IDD_IEAK_FINISH_GOOD_BUILD : IDD_FINISH_GOOD_BUILD;
  13296. }
  13297. else
  13298. {
  13299. dwFinishPage = IDD_FINISH_BAD_BUILD;
  13300. }
  13301. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, dwFinishPage));
  13302. return 1;
  13303. break;
  13304. }
  13305. break;
  13306. default:
  13307. return FALSE;
  13308. }
  13309. return FALSE;
  13310. }
  13311. //+----------------------------------------------------------------------------
  13312. //
  13313. // Function: BuildProfileExecutable
  13314. //
  13315. // Synopsis: This function takes care of all of the details of turning the
  13316. // CMAK files in the temp dir into a profile executable.
  13317. //
  13318. // Arguments: HWND hDlg - window handle of the calling dialog
  13319. //
  13320. // Returns: BOOL - TRUE if the profile built successfully, FALSE otherwise
  13321. //
  13322. // History: quintinb Created 05/17/00
  13323. //
  13324. //+----------------------------------------------------------------------------
  13325. BOOL BuildProfileExecutable(HWND hDlg)
  13326. {
  13327. DWORD dwExitCode = 0;
  13328. DWORD dwWaitCode = 0;
  13329. BOOL bExitLoop = FALSE;
  13330. BOOL bEnoughSpaceToCompress;
  13331. SHELLEXECUTEINFO seiInfo;
  13332. static HANDLE hProcess = NULL;
  13333. TCHAR szTemp[MAX_PATH+1];
  13334. TCHAR szMsg[MAX_PATH+1];
  13335. TCHAR pszArgs[MAX_PATH+1];
  13336. BOOL bRes;
  13337. //
  13338. // The user may have unchecked UsePresharedKey for all VPN settings, in
  13339. // which case we need to remove the pre-shared key.
  13340. //
  13341. g_bPresharedKeyNeeded = DoesSomeVPNsettingUsePresharedKey();
  13342. if (FALSE == g_bPresharedKeyNeeded)
  13343. {
  13344. // remove the Pre-shared key values from the CMP
  13345. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryPresharedKey, NULL, g_szCmpFile));
  13346. MYVERIFY(0 != WritePrivateProfileString(c_pszCmSection, c_pszCmEntryKeyIsEncrypted, NULL, g_szCmpFile));
  13347. }
  13348. if (!CopyFromTempDir(g_szShortServiceName))
  13349. {
  13350. return FALSE;
  13351. }
  13352. //
  13353. // Write the SED File.
  13354. // Note that the SED file has been moved from the temp dir to
  13355. // the profile dir. We now want to write the SED file entries
  13356. // in place before compressing them. This way we can verify the
  13357. // files exist right before compressing them.
  13358. //
  13359. MYVERIFY(CELEMS(g_szSedFile) > (UINT)wsprintf(g_szSedFile, TEXT("%s%s\\%s.sed"),
  13360. g_szOsdir, g_szShortServiceName, g_szShortServiceName));
  13361. if (!ConstructSedFile(hDlg, g_szSedFile, g_szOutExe))
  13362. {
  13363. return FALSE;
  13364. }
  13365. _tcscpy(g_szOutdir, g_szOsdir);
  13366. _tcscat(g_szOutdir, g_szShortServiceName);
  13367. //
  13368. // Setup IExpress to build in the output directory.
  13369. //
  13370. MYVERIFY(0 != SetCurrentDirectory(g_szOutdir));
  13371. //
  13372. // Check to make sure there is enough disk space
  13373. //
  13374. do
  13375. {
  13376. bEnoughSpaceToCompress = CheckDiskSpaceForCompression(g_szSedFile);
  13377. if (!bEnoughSpaceToCompress)
  13378. {
  13379. MYVERIFY(0 != LoadString(g_hInstance, IDS_DISKFULL, szTemp, MAX_PATH));
  13380. MYVERIFY(CELEMS(szMsg) > (UINT)wsprintf(szMsg, szTemp, g_szOutdir));
  13381. int iMessageReturn = MessageBox(hDlg, szMsg, g_szAppTitle, MB_RETRYCANCEL | MB_ICONERROR
  13382. | MB_APPLMODAL );
  13383. if (iMessageReturn == IDCANCEL)
  13384. {
  13385. return FALSE;
  13386. }
  13387. }
  13388. } while(!bEnoughSpaceToCompress);
  13389. MYVERIFY(CELEMS(pszArgs) > (UINT)wsprintf(pszArgs, TEXT("/N %s.sed"),
  13390. g_szShortServiceName));
  13391. _tcscpy(szTemp, TEXT("iexpress.exe"));
  13392. ZeroMemory(&seiInfo,sizeof(seiInfo));
  13393. seiInfo.cbSize = sizeof(seiInfo);
  13394. seiInfo.fMask |= SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
  13395. seiInfo.lpFile = szTemp;
  13396. seiInfo.lpDirectory = g_szOutdir;
  13397. seiInfo.lpParameters = pszArgs;
  13398. seiInfo.nShow = SW_HIDE;
  13399. //
  13400. // Okay, we are finally ready to execute IExpress, lets disable all the
  13401. // wizard buttons.
  13402. //
  13403. DisableWizardButtons(hDlg);
  13404. //
  13405. // Execute IExpress
  13406. //
  13407. bRes = ShellExecuteEx(&seiInfo);
  13408. //
  13409. // Wait for the shellexecute to finish. Thus our cleanup code doesn't
  13410. // execute till IEpress is done.
  13411. //
  13412. if (bRes)
  13413. {
  13414. //
  13415. // hProcess contains the handle to the process
  13416. //
  13417. hProcess = seiInfo.hProcess;
  13418. do
  13419. {
  13420. dwWaitCode = MsgWaitForMultipleObjects(1, &hProcess, FALSE, INFINITE, QS_ALLINPUT);
  13421. //
  13422. // Check to see if we returned because of a message, process termination,
  13423. // or an error.
  13424. //
  13425. switch(dwWaitCode)
  13426. {
  13427. case 0:
  13428. //
  13429. // Normal termination case, we were signaled that the process ended
  13430. //
  13431. bExitLoop = TRUE;
  13432. break;
  13433. case 1:
  13434. HandleWindowMessagesWhileCompressing();
  13435. break;
  13436. case -1:
  13437. //
  13438. // MsgWait returned an error
  13439. //
  13440. MYVERIFY(0 != GetExitCodeProcess(seiInfo.hProcess, &dwExitCode));
  13441. if (dwExitCode == STILL_ACTIVE)
  13442. {
  13443. continue;
  13444. }
  13445. else
  13446. {
  13447. bExitLoop = TRUE;
  13448. }
  13449. break;
  13450. default:
  13451. //
  13452. // Do nothing
  13453. //
  13454. break;
  13455. }
  13456. } while (!bExitLoop);
  13457. }
  13458. //
  13459. // now need to send the user to the finish page. If their profile
  13460. // build successfully then we send them to the success page, otherwise
  13461. // we send them to the bad build page.
  13462. //
  13463. MYVERIFY(0 != GetExitCodeProcess(seiInfo.hProcess, &dwExitCode));
  13464. if (dwExitCode)
  13465. {
  13466. g_iCMAKReturnVal = CMAK_RETURN_ERROR;
  13467. //
  13468. // We encountered an error, clear the out exe val
  13469. // so that we write nothing to the output key.
  13470. //
  13471. ZeroMemory(g_szOutExe, sizeof(g_szOutExe));
  13472. }
  13473. else
  13474. {
  13475. g_iCMAKReturnVal = CMAK_RETURN_SUCCESS;
  13476. }
  13477. CloseHandle(seiInfo.hProcess);
  13478. //
  13479. // Create a registry entry for IEAK to retrieve
  13480. // the path of the output profile.
  13481. //
  13482. MYVERIFY(FALSE != WriteRegStringValue(HKEY_LOCAL_MACHINE, c_pszRegCmak, c_pszRegOutput, g_szOutExe));
  13483. //
  13484. // CMAK_RETURN_ERROR is -1, so return TRUE if g_iCMAKReturnVal is a positive integer
  13485. //
  13486. return (g_iCMAKReturnVal > 0);
  13487. }
  13488. //+----------------------------------------------------------------------------
  13489. //
  13490. // Function: ProcessBuildProfile
  13491. //
  13492. // Synopsis: Processes windows messages for the page in CMAK that allows the
  13493. // user to build their profile or advance to the Advanced Customization
  13494. // page to make final edits before building the profile.
  13495. //
  13496. // WM_INITDIALOG - intializes the page
  13497. // WM_NOTIFY - processes the notifications sent to the page
  13498. //
  13499. // Specify the installation package location
  13500. //
  13501. // Arguments: WND hDlg -
  13502. // UINT message -
  13503. // WPARAM wParam -
  13504. // LPARAM lParam -
  13505. //
  13506. // Returns: INT_PTR APIENTRY -
  13507. //
  13508. // History: a-anasj restructured the function and Created Header 1/7/98
  13509. // note: the function does not allow the user to choose a location for
  13510. // their profile anylonger. It only informs them of where it will be
  13511. // created.
  13512. // quintinb Renamed from the feared ProcessPage8 8-6-98
  13513. // quintinb restructured for Whistler 108269 05/17/00
  13514. //
  13515. //+----------------------------------------------------------------------------
  13516. INT_PTR APIENTRY ProcessBuildProfile(
  13517. HWND hDlg,
  13518. UINT message,
  13519. WPARAM wParam,
  13520. LPARAM lParam)
  13521. {
  13522. TCHAR szTemp[MAX_PATH+1];
  13523. int iMessageReturn;
  13524. NMHDR* pnmHeader = (NMHDR*)lParam;
  13525. ProcessBold(hDlg,message);
  13526. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_CREATE)) return TRUE;
  13527. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  13528. switch (message)
  13529. {
  13530. case WM_NOTIFY:
  13531. if (NULL == pnmHeader)
  13532. {
  13533. return FALSE;
  13534. }
  13535. switch (pnmHeader->code)
  13536. {
  13537. case PSN_KILLACTIVE:
  13538. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, FALSE));
  13539. return 1;
  13540. break; //lint !e527 this line isn't reachable but
  13541. // keep it in case the return is removed
  13542. case PSN_SETACTIVE:
  13543. //
  13544. // Build default path of final executable
  13545. //
  13546. MYVERIFY(CELEMS(g_szOutExe) > (UINT)wsprintf(g_szOutExe, TEXT("%s%s\\%s.exe"),
  13547. g_szOsdir, g_szShortServiceName, g_szShortServiceName));
  13548. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_BACK | PSWIZB_NEXT));
  13549. break;
  13550. case PSN_WIZBACK:
  13551. break;
  13552. case PSN_WIZNEXT:
  13553. //
  13554. // Ensure that profile directory exists
  13555. //
  13556. _tcscpy(szTemp,g_szOsdir);
  13557. _tcscat(szTemp,g_szShortServiceName);
  13558. if (0 == SetCurrentDirectory(szTemp))
  13559. {
  13560. MYVERIFY(0 != CreateDirectory(szTemp,NULL));
  13561. }
  13562. //
  13563. // Prompt the user to overwrite the existing Executable
  13564. //
  13565. if (FileExists(g_szOutExe))
  13566. {
  13567. iMessageReturn = ShowMessage(hDlg, IDS_OVERWRITE, MB_YESNO);
  13568. if (iMessageReturn == IDNO)
  13569. {
  13570. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  13571. return 1;
  13572. }
  13573. }
  13574. //
  13575. // Write out the Inf File
  13576. //
  13577. if (!WriteInfFile(g_hInstance, hDlg, g_szInfFile, g_szLongServiceName))
  13578. {
  13579. CMASSERTMSG(FALSE, TEXT("ProcessBuildProfile -- WriteInfFile Failed."));
  13580. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  13581. return 1;
  13582. }
  13583. //
  13584. // Update version in CMP and party on the CMS
  13585. //
  13586. WriteCMPFile();
  13587. if (!WriteCMSFile())
  13588. {
  13589. FileAccessErr(hDlg, g_szCmsFile);
  13590. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, -1));
  13591. return 1;
  13592. }
  13593. //
  13594. // If the user wants to do advanced customization, delay building the profile executable
  13595. // until after they have done their final edits. Otherwise, it is time to build the profile!
  13596. //
  13597. if (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_ADVANCED))
  13598. {
  13599. //
  13600. // The user is finished now, lets build the profile and skip over the advanced customization
  13601. // page to either the bad build page or the successful build page.
  13602. //
  13603. DWORD dwFinishPage;
  13604. if (BuildProfileExecutable(hDlg))
  13605. {
  13606. dwFinishPage = g_bIEAKBuild ? IDD_IEAK_FINISH_GOOD_BUILD : IDD_FINISH_GOOD_BUILD;
  13607. }
  13608. else
  13609. {
  13610. dwFinishPage = IDD_FINISH_BAD_BUILD;
  13611. }
  13612. MYVERIFY(FALSE != SetWindowLongWrapper(hDlg, DWLP_MSGRESULT, dwFinishPage));
  13613. return 1;
  13614. }
  13615. break;
  13616. default:
  13617. return FALSE;
  13618. }
  13619. break;
  13620. default:
  13621. return FALSE;
  13622. }
  13623. return TRUE;
  13624. }
  13625. //+----------------------------------------------------------------------------
  13626. //
  13627. // Function: ProcessFinishPage
  13628. //
  13629. // Synopsis: Handles the finish page
  13630. //
  13631. // Arguments: WND hDlg -
  13632. // UINT message -
  13633. // WPARAM wParam -
  13634. // LPARAM lParam -
  13635. //
  13636. // Returns: INT_PTR APIENTRY -
  13637. //
  13638. // History: quintinb created 6/25/98
  13639. //
  13640. //+----------------------------------------------------------------------------
  13641. INT_PTR APIENTRY ProcessFinishPage(
  13642. HWND hDlg,
  13643. UINT message,
  13644. WPARAM wParam,
  13645. LPARAM lParam)
  13646. {
  13647. HWND hDirEditControl;
  13648. HWND hCurrentPage;
  13649. NMHDR* pnmHeader = (NMHDR*)lParam;
  13650. ProcessBold(hDlg,message);
  13651. if (ProcessHelp(hDlg, message, wParam, lParam, IDH_FINISH)) return TRUE;
  13652. if (ProcessCancel(hDlg,message,lParam)) return TRUE;
  13653. SetDefaultGUIFont(hDlg,message,IDC_EDITDIR);
  13654. switch (message)
  13655. {
  13656. case WM_NOTIFY:
  13657. if (NULL == pnmHeader)
  13658. {
  13659. return FALSE;
  13660. }
  13661. switch (pnmHeader->code)
  13662. {
  13663. case PSN_SETACTIVE:
  13664. PropSheet_SetWizButtons(GetParent(hDlg), (PSWIZB_FINISH));
  13665. //
  13666. // Disable the cancel button since it doesn't make a whole lot of
  13667. // sense on the last dialog.
  13668. //
  13669. hCurrentPage = GetParent(hDlg);
  13670. if (hCurrentPage)
  13671. {
  13672. HWND hCancelButton = GetDlgItem(hCurrentPage, IDCANCEL);
  13673. if (hCancelButton)
  13674. {
  13675. EnableWindow(hCancelButton, FALSE);
  13676. }
  13677. }
  13678. //
  13679. // Fill in the path edit control. Note that this control doesn't exist if
  13680. // this is an IEAK build.
  13681. //
  13682. if (hDirEditControl = GetDlgItem(hDlg, IDC_EDITDIR))
  13683. {
  13684. MYVERIFY(TRUE == SendMessage(hDirEditControl, WM_SETTEXT, 0,
  13685. (LPARAM)g_szOutExe));
  13686. }
  13687. break;
  13688. case PSN_WIZFINISH:
  13689. //
  13690. // Now that we know we aren't returning, we can release
  13691. // the temp dir and cleanup our files lists
  13692. //
  13693. ClearCmakGlobals();
  13694. FreeList(&g_pHeadProfile, &g_pTailProfile);
  13695. break;
  13696. default:
  13697. return FALSE;
  13698. }
  13699. break;
  13700. default:
  13701. return FALSE;
  13702. }
  13703. return TRUE;
  13704. }
  13705. //
  13706. //
  13707. // FUNCTION: FillInPropertyPage(PROPSHEETPAGE *, int, LPTSTR, LPFN)
  13708. //
  13709. // PURPOSE: Fills in the given PROPSHEETPAGE structure
  13710. //
  13711. // COMMENTS:
  13712. //
  13713. // This function fills in a PROPSHEETPAGE structure with the
  13714. // information the system needs to create the page.
  13715. //
  13716. void FillInPropertyPage( PROPSHEETPAGE* psp, int idDlg, DLGPROC pfnDlgProc)
  13717. {
  13718. psp->dwSize = sizeof(PROPSHEETPAGE);
  13719. psp->dwFlags = PSP_HASHELP;
  13720. psp->hInstance = g_hInstance;
  13721. psp->pszTemplate = MAKEINTRESOURCE(idDlg);
  13722. psp->pszIcon = NULL;
  13723. psp->pfnDlgProc = pfnDlgProc;
  13724. psp->pszTitle = TEXT("");
  13725. psp->lParam = 0;
  13726. }
  13727. //+----------------------------------------------------------------------------
  13728. //
  13729. // Function: CreateWizard
  13730. //
  13731. // Synopsis: This function creates the wizard pages that make up CMAK.
  13732. //
  13733. // Arguments: HWND hwndOwner - window handle of the owner of this wizard
  13734. //
  13735. // Returns: int - A positive value if successful, -1 otherwise
  13736. //
  13737. // History: quintinb Created Header 1/5/98
  13738. // quintinb removed hInst from prototype, not used 1/5/98
  13739. //
  13740. //+----------------------------------------------------------------------------
  13741. INT_PTR CreateWizard(HWND hwndOwner)
  13742. {
  13743. PROPSHEETPAGE psp[28];
  13744. PROPSHEETHEADER psh;
  13745. FillInPropertyPage( &psp[0], IDD_WELCOME, ProcessWelcome);
  13746. FillInPropertyPage( &psp[1], IDD_ADD_EDIT_PROFILE, ProcessAddEditProfile);
  13747. FillInPropertyPage( &psp[2], IDD_SERVICENAME, ProcessServiceName);
  13748. FillInPropertyPage( &psp[3], IDD_REALM_INFO, ProcessRealmInfo);
  13749. FillInPropertyPage( &psp[4], IDD_MERGEDPROFILES, ProcessMergedProfiles);
  13750. FillInPropertyPage( &psp[5], IDD_TUNNELING, ProcessTunneling);
  13751. FillInPropertyPage( &psp[6], IDD_VPN_ENTRIES, ProcessVpnEntries);
  13752. FillInPropertyPage( &psp[7], IDD_PRESHARED_KEY, ProcessPresharedKey);
  13753. FillInPropertyPage( &psp[8], IDD_PHONEBOOK, ProcessPhoneBook); // Phonebook Setup
  13754. FillInPropertyPage( &psp[9], IDD_PBK_UPDATE, ProcessPhoneBookUpdate); // Phonebook Updates
  13755. FillInPropertyPage( &psp[10], IDD_DUN_ENTRIES, ProcessDunEntries);
  13756. FillInPropertyPage( &psp[11], IDD_ROUTE_PLUMBING, ProcessRoutePlumbing);
  13757. FillInPropertyPage( &psp[12], IDD_CMPROXY, ProcessCmProxy);
  13758. FillInPropertyPage( &psp[13], IDD_CUSTOM_ACTIONS , ProcessCustomActions); // Setup Connect Actions
  13759. FillInPropertyPage( &psp[14], IDD_SIGNIN_BITMAP, ProcessSigninBitmap); // Sign-in Bitmap
  13760. FillInPropertyPage( &psp[15], IDD_PBK_BITMAP, ProcessPhoneBookBitmap); // Phonebook Bitmap
  13761. FillInPropertyPage( &psp[16], IDD_ICONS, ProcessIcons); // Icons
  13762. FillInPropertyPage( &psp[17], IDD_STATUS_MENU, ProcessStatusMenuIcons); // Status area menu items
  13763. FillInPropertyPage( &psp[18], IDD_CUSTOM_HELP, ProcessCustomHelp); // Help
  13764. FillInPropertyPage( &psp[19], IDD_SUPPORT_INFO, ProcessSupportInfo);
  13765. FillInPropertyPage( &psp[20], IDD_INCLUDE_CM, ProcessIncludeCm); // Include CM, note this doesn't show on IA64
  13766. FillInPropertyPage( &psp[21], IDD_LICENSE, ProcessLicense); // License agreement
  13767. FillInPropertyPage( &psp[22], IDD_ADDITIONAL, ProcessAdditionalFiles); // Additional files
  13768. FillInPropertyPage( &psp[23], IDD_BUILDPROFILE, ProcessBuildProfile); // Build the profile
  13769. FillInPropertyPage( &psp[24], IDD_GEEK_PANE, ProcessGeekPane); // Advance customization
  13770. FillInPropertyPage( &psp[25], IDD_FINISH_GOOD_BUILD, ProcessFinishPage); // Finish Page -- Good Build
  13771. FillInPropertyPage( &psp[26], IDD_IEAK_FINISH_GOOD_BUILD, ProcessFinishPage); // Finish Page -- Good Build
  13772. FillInPropertyPage( &psp[27], IDD_FINISH_BAD_BUILD, ProcessFinishPage); // Finish Page -- Bad Build
  13773. psh.dwSize = sizeof(PROPSHEETHEADER);
  13774. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
  13775. psh.hwndParent = hwndOwner;
  13776. psh.pszCaption = (LPTSTR) TEXT("");
  13777. psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
  13778. psh.nStartPage = 0;
  13779. psh.ppsp = (LPCPROPSHEETPAGE) &psp; //lint !e545 Disables line error 545 for this line only
  13780. return (PropertySheet(&psh));
  13781. }