Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4921 lines
193 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: netsettings.cpp
  4. //
  5. // Module: CMAK.EXE
  6. //
  7. // Synopsis: Code dealing with network settings (DUN settings).
  8. //
  9. // Copyright (c) 2000 Microsoft Corporation
  10. //
  11. // Author: quintinb Created 03/22/00
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. #include <windowsx.h>
  16. extern BOOL g_bNewProfile;
  17. #define CM_CMAK 1
  18. #include "cm_eap.cpp"
  19. //+----------------------------------------------------------------------------
  20. //
  21. // Function: ReadDunServerSettings
  22. //
  23. // Synopsis: Reads in all of the settings from the Server DUN setting section
  24. // specified.
  25. //
  26. // Arguments: LPCTSTR pszSectionName - full name of the server section to read
  27. // (Server&Fred or whatever)
  28. // CDunSetting* pDunSetting - Dun Settings data structure to store
  29. // the read in values to
  30. // LPCTSTR pszCmsFile - Cms file to read the settings from
  31. // BOOL bTunnelDunSetting - whether this is a tunnel dun setting or not
  32. //
  33. // Returns: BOOL - TRUE if the settings were read in correctly
  34. //
  35. // History: quintinb Created 03/22/00
  36. //
  37. //+----------------------------------------------------------------------------
  38. BOOL ReadDunServerSettings(LPCTSTR pszSectionName, CDunSetting* pDunSetting, LPCTSTR pszCmsFile, BOOL bTunnelDunSetting)
  39. {
  40. if ((NULL == pszSectionName) || (NULL == pDunSetting) || (NULL == pszCmsFile) ||
  41. (TEXT('\0') == pszSectionName[0]) || (TEXT('\0') == pszCmsFile[0]))
  42. {
  43. CMASSERTMSG(FALSE, TEXT("ReadDunServerSettings -- invalid parameter"));
  44. return FALSE;
  45. }
  46. GetBoolSettings ArrayOfServerSettings[] = {
  47. {c_pszCmEntryDunServerNetworkLogon, &(pDunSetting->bNetworkLogon), bTunnelDunSetting},
  48. {c_pszCmEntryDunServerSwCompress, &(pDunSetting->bPppSoftwareCompression), 1},
  49. {c_pszCmEntryDunServerDisableLcp, &(pDunSetting->bDisableLCP), 0},
  50. {c_pszCmEntryDunServerPwEncrypt, &(pDunSetting->bPWEncrypt), 0},
  51. {c_pszCmEntryDunServerPwEncryptMs, &(pDunSetting->bPWEncrypt_MS), 0},
  52. {c_pszCmEntryDunServerSecureLocalFiles, &(pDunSetting->bSecureLocalFiles), 0},
  53. {c_pszCmEntryDunServerRequirePap, &(pDunSetting->bAllowPap), 0},
  54. {c_pszCmEntryDunServerRequireSpap, &(pDunSetting->bAllowSpap), 0},
  55. {c_pszCmEntryDunServerRequireEap, &(pDunSetting->bAllowEap), 0},
  56. {c_pszCmEntryDunServerRequireChap, &(pDunSetting->bAllowChap), 0},
  57. {c_pszCmEntryDunServerRequireMsChap, &(pDunSetting->bAllowMsChap), 0},
  58. {c_pszCmEntryDunServerRequireMsChap2, &(pDunSetting->bAllowMsChap2), 0},
  59. {c_pszCmEntryDunServerRequireW95MsChap, &(pDunSetting->bAllowW95MsChap), 0},
  60. {c_pszCmEntryDunServerDataEncrypt, &(pDunSetting->bDataEncrypt), 0},
  61. };
  62. const int c_iNumDunServerBools = sizeof(ArrayOfServerSettings)/sizeof(ArrayOfServerSettings[0]);
  63. for (int i = 0; i < c_iNumDunServerBools; i++)
  64. {
  65. *(ArrayOfServerSettings[i].pbValue) = GetPrivateProfileInt(pszSectionName, ArrayOfServerSettings[i].pszKeyName,
  66. ArrayOfServerSettings[i].bDefault, pszCmsFile);
  67. }
  68. //
  69. // Now get the EAP settings if necessary
  70. //
  71. pDunSetting->dwCustomAuthKey = GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunServerCustomAuthKey, 0, pszCmsFile);
  72. if (pDunSetting->dwCustomAuthKey)
  73. {
  74. if (!ReadDunSettingsEapData(pszSectionName, &(pDunSetting->pCustomAuthData), &(pDunSetting->dwCustomAuthDataSize), pDunSetting->dwCustomAuthKey, pszCmsFile))
  75. {
  76. CMASSERTMSG(FALSE, TEXT("ReadDunServerSettings -- Failed to read in EAP Data."));
  77. pDunSetting->dwCustomAuthDataSize = 0;
  78. CmFree(pDunSetting->pCustomAuthData);
  79. pDunSetting->pCustomAuthData = NULL;
  80. }
  81. }
  82. //
  83. // Now get the Encryption type
  84. //
  85. pDunSetting->dwEncryptionType = (DWORD)GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunServerEncryptionType,
  86. (bTunnelDunSetting ? ET_Require : ET_Optional), pszCmsFile);
  87. //
  88. // Figure out what type of security model we are using
  89. //
  90. if (GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunServerEnforceCustomSecurity, 0, pszCmsFile))
  91. {
  92. pDunSetting->iHowToHandleSecuritySettings = FORCE_WIN2K_AND_ABOVE;
  93. }
  94. else
  95. {
  96. int iWin2kSecSettings = pDunSetting->bAllowPap | pDunSetting->bAllowSpap | pDunSetting->bAllowEap |
  97. pDunSetting->bAllowChap | pDunSetting->bAllowMsChap | pDunSetting->bAllowMsChap2 |
  98. pDunSetting->bAllowW95MsChap;
  99. if (iWin2kSecSettings)
  100. {
  101. pDunSetting->iHowToHandleSecuritySettings = SEPARATE_FOR_LEGACY_AND_WIN2K;
  102. }
  103. else
  104. {
  105. pDunSetting->iHowToHandleSecuritySettings = SAME_ON_ALL_PLATFORMS;
  106. //
  107. // In case the user chooses the advanced tab without configuring settings, lets
  108. // set some reasonable defaults for them. If they have already configured their
  109. // Win2k settings we don't want to mess with them. Also note that if the user
  110. // doesn't change the iHowToHandleSecuritySettings value, we won't write out
  111. // the advanced security settings anyway.
  112. //
  113. pDunSetting->bAllowChap = !bTunnelDunSetting;
  114. pDunSetting->bAllowMsChap = 1;
  115. pDunSetting->bAllowMsChap2 = 1;
  116. }
  117. }
  118. return TRUE;
  119. }
  120. //+----------------------------------------------------------------------------
  121. //
  122. // Function: ReadDunNetworkingSettings
  123. //
  124. // Synopsis: Reads in all of the settings from the DUN Networking section
  125. // specified.
  126. //
  127. // Arguments: LPCTSTR pszSectionName - full name of the networking section to read
  128. // (Networking&Fred or whatever)
  129. // CDunSetting* pDunSetting - Dun Settings data structure to store
  130. // the read in values to
  131. // LPCTSTR pszCmsFile - Cms file to read the settings from
  132. // BOOL bTunnel - is this a tunnel DUN setting or not
  133. //
  134. // Returns: BOOL - TRUE if the settings were read in correctly
  135. //
  136. // History: quintinb Created 03/22/00
  137. //
  138. //+----------------------------------------------------------------------------
  139. BOOL ReadDunNetworkingSettings(LPCTSTR pszSectionName, CDunSetting* pDunSetting, LPCTSTR pszCmsFile, BOOL bTunnel)
  140. {
  141. if ((NULL == pszSectionName) || (NULL == pDunSetting) || (NULL == pszCmsFile) ||
  142. (TEXT('\0') == pszSectionName[0]) || (TEXT('\0') == pszCmsFile[0]))
  143. {
  144. CMASSERTMSG(FALSE, TEXT("ReadDunNetworkingSettings -- invalid parameter"));
  145. return FALSE;
  146. }
  147. pDunSetting->dwVpnStrategy = (DWORD)GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunNetworkingVpnStrategy,
  148. (bTunnel ? VS_PptpFirst : 0), pszCmsFile);
  149. //
  150. // If the profile had automatic, then set it to VS_PptpFirst instead.
  151. //
  152. if (bTunnel && ((VS_PptpOnly > pDunSetting->dwVpnStrategy) || (VS_L2tpFirst < pDunSetting->dwVpnStrategy)))
  153. {
  154. pDunSetting->dwVpnStrategy = VS_PptpFirst;
  155. }
  156. //
  157. // Get the value for UseDownLevelL2TP
  158. //
  159. pDunSetting->bUseDownLevelL2TP = (BOOL)GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunNetworkingUseDownLevelL2TP,
  160. FALSE, pszCmsFile);
  161. pDunSetting->bUsePskOnWin2kPlus = (BOOL)GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunNetworkingUsePreSharedKey,
  162. FALSE, pszCmsFile);
  163. pDunSetting->bUsePskDownLevel = (BOOL)GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunNetworkingUsePskDownLevel,
  164. FALSE, pszCmsFile);
  165. return TRUE;
  166. }
  167. //+----------------------------------------------------------------------------
  168. //
  169. // Function: ConvertIpStringToDword
  170. //
  171. // Synopsis: This function takes the given string containing an IP address and
  172. // converts it to a packed DWORD. The first octet of the IP address
  173. // going in the most significant byte of the DWORD, the next octet in
  174. // the second most significant byte of the DWORD, etc. The packed
  175. // DWORD format is used by the IP address common controls and is a much
  176. // easier format to store the data in than a string.
  177. //
  178. // Arguments: LPTSTR pszIpAddress - string containing the ip address, each octet
  179. // seperated by a period.
  180. //
  181. // Returns: DWORD - the ip address specified by the inputted string in
  182. // packed byte format (first octet in the most significant)
  183. // Note that zero is returned if there is a problem with the
  184. // IP address format (one of the numbers is out of bounds or
  185. // there are too many or too few octets).
  186. //
  187. // History: quintinb Created 03/22/00
  188. //
  189. //+----------------------------------------------------------------------------
  190. DWORD ConvertIpStringToDword(LPTSTR pszIpAddress)
  191. {
  192. DWORD dwIpAddress = 0;
  193. if (pszIpAddress && pszIpAddress[0])
  194. {
  195. CmStrTrim(pszIpAddress);
  196. LPTSTR pszCurrent = pszIpAddress;
  197. DWORD dwOctetCounter = 0;
  198. DWORD dwCurrentOctetValue = 0;
  199. const int c_iCharBase = TEXT('0');
  200. BOOL bExitLoop = FALSE;
  201. while (pszCurrent && !bExitLoop)
  202. {
  203. switch(*pszCurrent)
  204. {
  205. case TEXT('.'):
  206. if (3 > dwOctetCounter)
  207. {
  208. dwIpAddress = (dwIpAddress << 8) + dwCurrentOctetValue;
  209. dwOctetCounter++;
  210. dwCurrentOctetValue = 0;
  211. }
  212. else
  213. {
  214. CMASSERTMSG(FALSE, TEXT("ConvertIpStringToDword -- Too many octets"));
  215. return 0;
  216. }
  217. break;
  218. case TEXT('\0'):
  219. if (3 == dwOctetCounter)
  220. {
  221. dwIpAddress = (dwIpAddress << 8) + dwCurrentOctetValue;
  222. bExitLoop = TRUE;
  223. }
  224. else
  225. {
  226. CMASSERTMSG(FALSE, TEXT("ConvertIpStringToDword -- Incorrect number of octets"));
  227. return 0;
  228. }
  229. break;
  230. default:
  231. dwCurrentOctetValue = dwCurrentOctetValue*10 + (int(*pszCurrent) - c_iCharBase);
  232. if (255 < dwCurrentOctetValue)
  233. {
  234. CMASSERTMSG(FALSE, TEXT("ConvertIpStringToDword -- Octet value out of range"));
  235. return 0;
  236. }
  237. break;
  238. }
  239. pszCurrent = CharNext(pszCurrent);
  240. }
  241. }
  242. return dwIpAddress;
  243. }
  244. //+----------------------------------------------------------------------------
  245. //
  246. // Function: ConvertIpDwordToString
  247. //
  248. // Synopsis: This function takes the given Packed DWORD and returns an IP
  249. // address string for it, making sure to print the octets so that
  250. // the most significant bits are printed in the string first.
  251. //
  252. // Arguments: DWORD dwIpAddress - packed DWORD containing the Ip address to convert
  253. // LPTSTR pszIpAddress - string to write the IP address too
  254. //
  255. // Returns: int - the number of chars written to the string buffer. Zero signifies
  256. // failure.
  257. //
  258. // History: quintinb Created 03/22/00
  259. //
  260. //+----------------------------------------------------------------------------
  261. int ConvertIpDwordToString(DWORD dwIpAddress, LPTSTR pszIpAddress)
  262. {
  263. int iReturn = 0;
  264. if (pszIpAddress)
  265. {
  266. iReturn = wsprintf(pszIpAddress, TEXT("%d.%d.%d.%d"), FIRST_IPADDRESS(dwIpAddress), SECOND_IPADDRESS(dwIpAddress),
  267. THIRD_IPADDRESS(dwIpAddress), FOURTH_IPADDRESS(dwIpAddress));
  268. }
  269. else
  270. {
  271. CMASSERTMSG(FALSE, TEXT("ConvertIpDwordToString -- Null pointer passed for pszIpAddress"));
  272. }
  273. return iReturn;
  274. }
  275. //+----------------------------------------------------------------------------
  276. //
  277. // Function: ReadDunTcpIpSettings
  278. //
  279. // Synopsis: This function reads the TCP/IP DUN settings from the specified
  280. // section and stores them in the given pDunSetting structure.
  281. //
  282. // Arguments: LPCTSTR pszSectionName - complete section name to read the TCP/IP
  283. // settings from, ie. Networking&Fred
  284. // CDunSetting* pDunSetting - pointer to a DUN setting structure to hold
  285. // the read in data
  286. // LPCTSTR pszCmsFile - cms file to read the settings from
  287. //
  288. // Returns: BOOL - TRUE on success
  289. //
  290. // History: quintinb Created 03/22/00
  291. //
  292. //+----------------------------------------------------------------------------
  293. BOOL ReadDunTcpIpSettings(LPCTSTR pszSectionName, CDunSetting* pDunSetting, LPCTSTR pszCmsFile)
  294. {
  295. if ((NULL == pszSectionName) || (NULL == pDunSetting) || (NULL == pszCmsFile) ||
  296. (TEXT('\0') == pszSectionName[0]) || (TEXT('\0') == pszCmsFile[0]))
  297. {
  298. CMASSERTMSG(FALSE, TEXT("ReadDunTcpIpSettings -- invalid parameter"));
  299. return FALSE;
  300. }
  301. TCHAR szTemp[MAX_PATH];
  302. //
  303. // Are we using Admin specified DNS and WINS settings or is the server going to assign them
  304. //
  305. if (GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunTcpIpSpecifyServerAddress, 0, pszCmsFile))
  306. {
  307. //
  308. // Get the DNS and WINS configurations that were specified
  309. //
  310. GetPrivateProfileString(pszSectionName, c_pszCmEntryDunTcpIpDnsAddress, TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile);
  311. pDunSetting->dwPrimaryDns = ConvertIpStringToDword (szTemp);
  312. GetPrivateProfileString(pszSectionName, c_pszCmEntryDunTcpIpDnsAltAddress, TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile);
  313. pDunSetting->dwSecondaryDns = ConvertIpStringToDword (szTemp);
  314. GetPrivateProfileString(pszSectionName, c_pszCmEntryDunTcpIpWinsAddress, TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile);
  315. pDunSetting->dwPrimaryWins = ConvertIpStringToDword (szTemp);
  316. GetPrivateProfileString(pszSectionName, c_pszCmEntryDunTcpIpWinsAltAddress, TEXT(""), szTemp, CELEMS(szTemp), pszCmsFile);
  317. pDunSetting->dwSecondaryWins = ConvertIpStringToDword (szTemp);
  318. }
  319. else
  320. {
  321. pDunSetting->dwPrimaryDns = 0;
  322. pDunSetting->dwSecondaryDns = 0;
  323. pDunSetting->dwPrimaryWins = 0;
  324. pDunSetting->dwSecondaryWins = 0;
  325. }
  326. //
  327. // Now Read in IP Header Compress and whether to use the Remote Gateway or not
  328. //
  329. pDunSetting->bIpHeaderCompression = GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunTcpIpIpHeaderCompress, 1, pszCmsFile);
  330. pDunSetting->bGatewayOnRemote = GetPrivateProfileInt(pszSectionName, c_pszCmEntryDunTcpIpGatewayOnRemote, 1, pszCmsFile);
  331. return 0;
  332. }
  333. //+----------------------------------------------------------------------------
  334. //
  335. // Function: ReadDunScriptingSettings
  336. //
  337. // Synopsis: This function reads in the script name from the passed in scripting
  338. // section name and stores it in the passed in DUN setting struct.
  339. //
  340. // Arguments: LPCTSTR pszSectionName - complete section name to read the scripting
  341. // settings from, ie. Scripting&Fred
  342. // CDunSetting* pDunSetting - pointer to a DUN setting structure to hold
  343. // the read in data
  344. // LPCTSTR pszCmsFile - cms file to read the settings from
  345. //
  346. // Returns: BOOL - TRUE on success
  347. //
  348. // History: quintinb Created 03/22/00
  349. //
  350. //+----------------------------------------------------------------------------
  351. BOOL ReadDunScriptingSettings(LPCTSTR pszSectionName, CDunSetting* pDunSetting, LPCTSTR pszOsDir, LPCTSTR pszCmsFile)
  352. {
  353. if ((NULL == pszSectionName) || (NULL == pDunSetting) || (NULL == pszCmsFile) || (NULL == pszOsDir) ||
  354. (TEXT('\0') == pszSectionName[0]) || (TEXT('\0') == pszCmsFile[0]) || (TEXT('\0') == pszOsDir[0]))
  355. {
  356. CMASSERTMSG(FALSE, TEXT("ReadDunScriptingSettings -- invalid parameter"));
  357. return FALSE;
  358. }
  359. TCHAR szTemp[MAX_PATH+1] = TEXT("");
  360. if (GetPrivateProfileString(pszSectionName, c_pszCmEntryDunScriptingName, TEXT(""),
  361. szTemp, CELEMS(szTemp), pszCmsFile))
  362. {
  363. MYVERIFY(CELEMS(pDunSetting->szScript) > (UINT)wsprintf(pDunSetting->szScript, TEXT("%s%s"), pszOsDir, szTemp));
  364. }
  365. return TRUE;
  366. }
  367. //+----------------------------------------------------------------------------
  368. //
  369. // Function: AddDunNameToListIfDoesNotExist
  370. //
  371. // Synopsis: This function walks through the list of existing DUN settings
  372. // to see if it can find a setting with the name pszDunName. If it
  373. // finds the entry, then fine it returns TRUE. If it cannot find the
  374. // entry then it creates an otherwise blank entry and adds it to the list.
  375. //
  376. // Arguments: LPCTSTR pszDunName - name of the item to add to the list if
  377. // it doesn't already exist
  378. // ListBxList **pHeadDns - head of the list of DUN entries
  379. // ListBxList** pTailDns - tail of the list of DUN entries
  380. // BOOL bTunnelDunName - whether this is a tunnel DUN name or not
  381. //
  382. // Returns: BOOL - TRUE if the item was added or if it already existed in the list
  383. //
  384. // History: quintinb Created 03/22/00
  385. //
  386. //+----------------------------------------------------------------------------
  387. BOOL AddDunNameToListIfDoesNotExist(LPCTSTR pszDunName, ListBxList **pHeadDns, ListBxList** pTailDns, BOOL bTunnelDunName)
  388. {
  389. if ((NULL == pszDunName) || (NULL == pHeadDns) || (NULL == pTailDns) || (TEXT('\0') == pszDunName[0]))
  390. {
  391. CMASSERTMSG(FALSE, TEXT("AddDunNameToListIfDoesNotExist -- Invalid Parameter"));
  392. return FALSE;
  393. }
  394. ListBxList* pCurrent = *pHeadDns;
  395. BOOL bReturn = TRUE;
  396. while (pCurrent)
  397. {
  398. if (0 == lstrcmpi(pszDunName, pCurrent->szName))
  399. {
  400. //
  401. // We already have this item, nothing to do
  402. //
  403. goto exit;
  404. }
  405. pCurrent = pCurrent->next;
  406. }
  407. //
  408. // If we are here then either we didn't find the item or the list
  409. // is empty. Either way, add the item.
  410. //
  411. pCurrent = (ListBxList*)CmMalloc(sizeof(ListBxList));
  412. if (pCurrent)
  413. {
  414. pCurrent->ListBxData = new CDunSetting(bTunnelDunName);
  415. if (NULL == pCurrent->ListBxData)
  416. {
  417. CmFree(pCurrent);
  418. CMASSERTMSG(FALSE, TEXT("AddDunNameToListIfDoesNotExist -- Failed to allocate a new CDunSetting"));
  419. return FALSE;
  420. }
  421. }
  422. else
  423. {
  424. CMASSERTMSG(FALSE, TEXT("ReadDunServerSettings -- Failed to allocate a new ListBxList struct"));
  425. return FALSE;
  426. }
  427. //
  428. // Now that we have allocated a pCurrent, we need to add it to the list
  429. //
  430. if (NULL == *pHeadDns)
  431. {
  432. *pHeadDns = pCurrent;
  433. }
  434. else
  435. {
  436. (*pTailDns)->next = pCurrent;
  437. }
  438. *pTailDns = pCurrent;
  439. //
  440. // Finally copy the name over
  441. //
  442. lstrcpy(pCurrent->szName, pszDunName);
  443. exit:
  444. return bReturn;
  445. }
  446. //+----------------------------------------------------------------------------
  447. //
  448. // Function: GetVpnEntryNamesFromFile
  449. //
  450. // Synopsis: This function parses through the tunnel server address entries within
  451. // the given VPN file. For each entry that contains a VPN setting,
  452. // if calls AddDunNameToListIfDoesNotExist.
  453. //
  454. // Arguments: LPCTSTR pszPhoneBook - VPN file to search for VPN entry names
  455. // ListBxList **pHeadDns - head of the VPN entry list
  456. // ListBxList** pTailDns - tail of the VPN entry list
  457. //
  458. // Returns: BOOL - TRUE if the phonebook was successfully parsed.
  459. //
  460. // History: quintinb Created 10/28/00
  461. //
  462. //+----------------------------------------------------------------------------
  463. BOOL GetVpnEntryNamesFromFile(LPCTSTR pszVpnFile, ListBxList **pHeadDns, ListBxList** pTailDns)
  464. {
  465. if ((NULL == pszVpnFile) || (NULL == pHeadDns) || (NULL == pTailDns))
  466. {
  467. CMASSERTMSG(FALSE, TEXT("GetVpnEntryNamesFromFile -- invalid params passed."));
  468. return FALSE;
  469. }
  470. //
  471. // Note that the vpn file string passed in may be empty. That is okay because the profile
  472. // may be a tunneling profile using only one tunnel address.
  473. //
  474. if ((TEXT('\0') != pszVpnFile[0]))
  475. {
  476. LPTSTR pszVpnServersSection = GetPrivateProfileSectionWithAlloc(c_pszCmSectionVpnServers, pszVpnFile);
  477. if (pszVpnServersSection)
  478. {
  479. LPTSTR pszCurrentLine = pszVpnServersSection;
  480. LPTSTR pszVpnSetting = NULL;
  481. while (TEXT('\0') != (*pszCurrentLine))
  482. {
  483. //
  484. // First look for the equal sign
  485. //
  486. pszVpnSetting = CmStrchr(pszCurrentLine, TEXT('='));
  487. if (pszVpnSetting)
  488. {
  489. //
  490. // Now look for the last comma
  491. //
  492. pszVpnSetting = CmStrrchr(pszVpnSetting, TEXT(','));
  493. if (pszVpnSetting)
  494. {
  495. pszVpnSetting = CharNext(pszVpnSetting);
  496. MYVERIFY(AddDunNameToListIfDoesNotExist(pszVpnSetting, pHeadDns, pTailDns, TRUE)); // TRUE == bTunnelDunName
  497. }
  498. }
  499. //
  500. // Find the next string by going to the end of the string
  501. // and then going one more char. Note that we cannot use
  502. // CharNext here but must use just ++.
  503. //
  504. pszCurrentLine = CmEndOfStr(pszCurrentLine);
  505. pszCurrentLine++;
  506. }
  507. }
  508. else
  509. {
  510. CMASSERTMSG(FALSE, TEXT("GetVpnEntryNamesFromFile -- GetPrivateProfileSectionWithAlloc return NULL."));
  511. return FALSE;
  512. }
  513. CmFree(pszVpnServersSection);
  514. }
  515. return TRUE;
  516. }
  517. //+----------------------------------------------------------------------------
  518. //
  519. // Function: VerifyVpnFile
  520. //
  521. // Synopsis: This function examines the VPN servers section of a VPN file
  522. // to ensure that at least one line of a valid format is found. While
  523. // this doesn't guarantee that the entry is valid (it could be a bogus
  524. // server name), it does at least mean the Admin didn't give the user a
  525. // junk file. This is important because the user cannot enter their own
  526. // tunnel server destination.
  527. //
  528. // Arguments: LPCTSTR pszPhoneBook - VPN file to search for VPN entry names
  529. //
  530. // Returns: BOOL - TRUE if the VPN file contains at least one tunnel server
  531. // entry in a valid format
  532. //
  533. // History: quintinb Created 10/28/00
  534. //
  535. //+----------------------------------------------------------------------------
  536. BOOL VerifyVpnFile(LPCTSTR pszVpnFile)
  537. {
  538. if (NULL == pszVpnFile)
  539. {
  540. CMASSERTMSG(FALSE, TEXT("VerifyVpnFile -- invalid params passed."));
  541. return FALSE;
  542. }
  543. BOOL bReturn = FALSE;
  544. //
  545. // Note that the vpn file string passed in may be empty. That is okay because the profile
  546. // may be a tunneling profile using only one tunnel address.
  547. //
  548. if ((TEXT('\0') != pszVpnFile[0]))
  549. {
  550. LPTSTR pszVpnServersSection = GetPrivateProfileSectionWithAlloc(c_pszCmSectionVpnServers, pszVpnFile);
  551. if (pszVpnServersSection)
  552. {
  553. LPTSTR pszCurrentLine = pszVpnServersSection;
  554. LPTSTR pszEqualSign = NULL;
  555. while ((TEXT('\0') != (*pszCurrentLine)) && !bReturn)
  556. {
  557. //
  558. // To be considered a "valid" line, all we need is to have
  559. // an equal sign (=) surrounded by text. Not that stringent of a test
  560. // but better than nothing.
  561. //
  562. pszEqualSign = CmStrchr(pszCurrentLine, TEXT('='));
  563. if (pszEqualSign && (pszEqualSign != pszCurrentLine)) // line cannot start with an equal sign to count
  564. {
  565. pszCurrentLine = CharNext(pszEqualSign);
  566. CmStrTrim(pszCurrentLine);
  567. if (*pszCurrentLine)
  568. {
  569. bReturn = TRUE;
  570. }
  571. }
  572. //
  573. // Find the next string by going to the end of the string
  574. // and then going one more char. Note that we cannot use
  575. // CharNext here but must use just ++.
  576. //
  577. pszCurrentLine = CmEndOfStr(pszCurrentLine);
  578. pszCurrentLine++;
  579. }
  580. CmFree(pszVpnServersSection);
  581. }
  582. }
  583. return bReturn;
  584. }
  585. //+----------------------------------------------------------------------------
  586. //
  587. // Function: GetDunEntryNamesFromPbk
  588. //
  589. // Synopsis: This function memory maps the given phonebook into memory and
  590. // then walks through it as one big string. The function is searching
  591. // the phonebook for DUN entry names. If it finds a DUN entry name then
  592. // it uses AddDunNameToListIfDoesNotExist to add the entry name if
  593. // it doesn't already exist.
  594. //
  595. // Arguments: LPCTSTR pszPhoneBook - phonebook to search for DUN entry names
  596. // ListBxList **pHeadDns - head of the DUN entry list
  597. // ListBxList** pTailDns - tail of the DUN entry list
  598. //
  599. // Returns: BOOL - TRUE if the phonebook was successfully parsed.
  600. //
  601. // History: quintinb Created 03/22/00
  602. //
  603. //+----------------------------------------------------------------------------
  604. BOOL GetDunEntryNamesFromPbk(LPCTSTR pszPhoneBook, ListBxList **pHeadDns, ListBxList** pTailDns)
  605. {
  606. if ((NULL == pszPhoneBook) || (NULL == pHeadDns) || (NULL == pTailDns))
  607. {
  608. CMASSERTMSG(FALSE, TEXT("GetDunEntryNamesFromPbk -- Invalid Parameter"));
  609. return FALSE;
  610. }
  611. BOOL bReturn = TRUE;
  612. if ((TEXT('\0') != pszPhoneBook[0]))
  613. {
  614. HANDLE hPhoneBookFile = CreateFile(pszPhoneBook, GENERIC_READ, FILE_SHARE_READ, NULL,
  615. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  616. if (INVALID_HANDLE_VALUE != hPhoneBookFile)
  617. {
  618. //
  619. // Get the size of the file
  620. //
  621. DWORD dwFileSize = GetFileSize(hPhoneBookFile, NULL);
  622. if (-1 != dwFileSize)
  623. {
  624. //
  625. // Create a file mapping
  626. //
  627. HANDLE hFileMapping = CreateFileMapping(hPhoneBookFile, NULL, PAGE_READONLY, 0, 0, NULL);
  628. if (NULL != hFileMapping)
  629. {
  630. CHAR* pszPhoneBookContents = (CHAR*)MapViewOfFileEx(hFileMapping, FILE_MAP_READ, 0, 0, 0, NULL);
  631. CHAR* pszCurrent = pszPhoneBookContents;
  632. LPSTR pszLastComma = NULL;
  633. //
  634. // We want to walk through the file character by character. Whenever we encounter
  635. // a '\n', we know that is the end of a line. If we hit EOF then we are done with the file.
  636. // We are looking for all of the DUN entry names in the phonebook file.
  637. //
  638. while (pszCurrent && ((dwFileSize + pszPhoneBookContents) > pszCurrent))
  639. {
  640. CHAR szTemp[MAX_PATH+1];
  641. int iNumChars;
  642. switch (*pszCurrent)
  643. {
  644. case ',':
  645. pszLastComma = pszCurrent;
  646. break;
  647. case '\r':
  648. //
  649. // End of a line, remember we have a \r\n <CRLF> to end a line in a file.
  650. //
  651. if (pszLastComma)
  652. {
  653. iNumChars = (int)(pszCurrent - pszLastComma);
  654. if (iNumChars - 1)
  655. {
  656. lstrcpynA(szTemp, CharNextA(pszLastComma), iNumChars);
  657. LPTSTR pszUnicodeDunName = SzToWzWithAlloc(szTemp);
  658. MYDBGASSERT(pszUnicodeDunName);
  659. if (pszUnicodeDunName)
  660. {
  661. MYVERIFY(AddDunNameToListIfDoesNotExist(pszUnicodeDunName, pHeadDns, pTailDns, FALSE)); // FALSE == bTunnelDunName
  662. CmFree(pszUnicodeDunName);
  663. }
  664. }
  665. //
  666. // Reset the last comma
  667. //
  668. pszLastComma = NULL;
  669. }
  670. break;
  671. case '\0':
  672. case EOF:
  673. //
  674. // We shouldn't hit an EOF or a zero byte in a memory mapped text file.
  675. //
  676. bReturn = FALSE;
  677. CMASSERTMSG(FALSE, TEXT("GetDunEntryNamesFromPbk -- phonebook file format incorrect!"));
  678. break;
  679. }
  680. //
  681. // Advance to the next line assuming we still have some of the file
  682. // to parse
  683. //
  684. if (pszCurrent && ((EOF == *pszCurrent) || ('\0' == *pszCurrent)))
  685. {
  686. //
  687. // Then we have an invalid file and it is time to exit...
  688. //
  689. pszCurrent = NULL;
  690. }
  691. else if (pszCurrent)
  692. {
  693. pszCurrent = CharNextA(pszCurrent);
  694. }
  695. }
  696. MYVERIFY(UnmapViewOfFile(pszPhoneBookContents));
  697. CloseHandle(hFileMapping);
  698. }
  699. }
  700. CloseHandle(hPhoneBookFile);
  701. }
  702. }
  703. return bReturn;
  704. }
  705. //+----------------------------------------------------------------------------
  706. //
  707. // Function: CDunSetting::CDunSetting
  708. //
  709. // Synopsis: Constructor for the CDunSetting data structure. Note that all
  710. // default values should be changed here and not imposed anywhere
  711. // else. All the DUN setting UI is setup to read from a DUN setting
  712. // structure, either a newly constructed one (thus setting up the defaults)
  713. // or one read in from the cms.
  714. //
  715. // Arguments: BOOL bTunnel - tells whether this is a Tunnel DUN setting or not
  716. // note that this value defaults to FALSE.
  717. //
  718. // Returns: Nothing
  719. //
  720. // History: quintinb Created 03/22/00
  721. //
  722. //+----------------------------------------------------------------------------
  723. CDunSetting::CDunSetting(BOOL bTunnel)
  724. {
  725. //
  726. // Note that bTunnelDunSetting has a default value of FALSE.
  727. // Init the class params.
  728. //
  729. bNetworkLogon = bTunnel ? 1 : 0;
  730. bPppSoftwareCompression = 1;
  731. bDisableLCP = 0;
  732. bPWEncrypt = bTunnel ? 0 : 1; // if we are not tunneling, default to secure password
  733. bPWEncrypt_MS = bTunnel ? 1 : 0; // if we are tunneling, default to MS secure password
  734. szScript[0] = TEXT('\0');
  735. dwVpnStrategy = bTunnel ? VS_PptpFirst : 0;
  736. bTunnelDunSetting = bTunnel;
  737. bUseDownLevelL2TP = 0;
  738. //
  739. // TCP/IP Settings
  740. //
  741. dwPrimaryDns = 0;
  742. dwSecondaryDns = 0;
  743. dwPrimaryWins = 0;
  744. dwSecondaryWins = 0;
  745. bIpHeaderCompression = 1;
  746. bGatewayOnRemote = 1;
  747. //
  748. // Security Settings
  749. //
  750. dwEncryptionType = bTunnel ? ET_Require : ET_Optional;
  751. bDataEncrypt = bTunnel ? 1 : 0; // if we are tunneling, default to data encryption
  752. bAllowPap = 0;
  753. bAllowSpap = 0;
  754. bAllowEap = 0;
  755. bAllowChap = bTunnel ? 0 : 1;
  756. bAllowMsChap = 1;
  757. bAllowMsChap2 = 1;
  758. bAllowW95MsChap = 0;
  759. bSecureLocalFiles = 0;
  760. //
  761. // Due to RASEO_RequireMsEncryptPw & MSCAHPv2 bug in RAS API on Win2K & XP
  762. // we want a default profile to correctly work on Win2k and above. Thus
  763. // CMAK needs to default to lagacy and Win2k settings. That way the correct Win2K+ RASEO_ flags
  764. // are written out.
  765. //
  766. iHowToHandleSecuritySettings = SEPARATE_FOR_LEGACY_AND_WIN2K;
  767. dwCustomAuthKey = 0;
  768. pCustomAuthData = NULL;
  769. dwCustomAuthDataSize = 0;
  770. bUsePskOnWin2kPlus = 0;
  771. bUsePskDownLevel = 0;
  772. }
  773. //+----------------------------------------------------------------------------
  774. //
  775. // Function: CDunSetting::~CDunSetting
  776. //
  777. // Synopsis: Destructor for the CDunSetting data structure. Frees the EAP
  778. // blob if one exists
  779. //
  780. // Arguments: None
  781. //
  782. // Returns: Nothing
  783. //
  784. // History: quintinb Created 03/22/00
  785. //
  786. //+----------------------------------------------------------------------------
  787. CDunSetting::~CDunSetting()
  788. {
  789. CmFree(pCustomAuthData);
  790. }
  791. //+----------------------------------------------------------------------------
  792. //
  793. // Function: ReadNetworkSettings
  794. //
  795. // Synopsis: Constructor for the CDunSetting data structure. Note that all
  796. // default values should be changed here and not imposed anywhere
  797. // else. All the DUN setting UI is setup to read from a DUN setting
  798. // structure, either a newly constructed one (thus setting up the defaults)
  799. // or one read in from the cms.
  800. //
  801. // Arguments: LPCTSTR pszCmsFile - Cms file to read the network settings from
  802. // LPCTSTR pszLongServiceName - Long service name of the profile
  803. // LPCTSTR pszPhoneBook - phonebook of the current service profile,
  804. // if the profile doesn't have a phonebook
  805. // then "" should be passed
  806. // ListBxList **pHeadDns - pointer to the head of the DUN settings list
  807. // ListBxList** pTailDns - pointer to the tail of the DUN settings list
  808. // LPCTSTR pszOsDir - full path of the profiles directory
  809. //
  810. // Returns: BOOL - TRUE if successful
  811. //
  812. // History: quintinb Created 03/22/00
  813. //
  814. //+----------------------------------------------------------------------------
  815. BOOL ReadNetworkSettings(LPCTSTR pszCmsFile, LPCTSTR pszLongServiceName, LPCTSTR pszPhoneBook,
  816. ListBxList **pHeadDns, ListBxList** pTailDns, LPCTSTR pszOsDir, BOOL bLookingForVpnEntries)
  817. {
  818. //
  819. // Check inputs, note that the phonebook could be ""
  820. //
  821. if ((NULL == pszCmsFile) || (NULL == pszLongServiceName) || (NULL == pszPhoneBook) || (NULL == pszOsDir) || (NULL == pHeadDns) ||
  822. (NULL == pTailDns) || (TEXT('\0') == pszCmsFile[0]) || (TEXT('\0') == pszLongServiceName[0]) || (TEXT('\0') == pszOsDir[0]) ||
  823. ((NULL == *pHeadDns) ^ (NULL == *pTailDns)))
  824. {
  825. CMASSERTMSG(FALSE, TEXT("ReadNetworkSettings -- invalid parameter"));
  826. return FALSE;
  827. }
  828. BOOL bReturn = TRUE;
  829. LPTSTR pszCurrentSectionName = NULL;
  830. TCHAR szDefaultDunName[MAX_PATH+1] = TEXT("");
  831. TCHAR szTunnelDunName[MAX_PATH+1] = TEXT("");
  832. //
  833. // First we want to call GetPrivateProfileString with a NULL AppName and a NULL KeyName. This will
  834. // Return all of the Section Names in the file in a buffer. We can then go through the buffer and
  835. // get the section information that interests us.
  836. //
  837. LPTSTR pszSectionNames = GetPrivateProfileStringWithAlloc(NULL, NULL, TEXT(""), pszCmsFile);
  838. if ((NULL == pszSectionNames) || (TEXT('\0') == pszSectionNames[0]))
  839. {
  840. CMTRACE(TEXT("ReadNetworkSettings -- GetPrivateProfileStringWithAlloc failed"));
  841. bReturn = FALSE;
  842. goto exit;
  843. }
  844. //
  845. // At this point we have a list of section names, they are all NULL terminated with the last one double
  846. // NULL terminated. We need to walk through the list and see if any of them start with "[TCP/IP&" if
  847. // so then we have a DUN section and we want to read it in.
  848. //
  849. LPTSTR pszAmpersand;
  850. LPTSTR pszDunName;
  851. TCHAR szTemp[MAX_PATH+1];
  852. BOOL bTunnelDunSetting;
  853. pszCurrentSectionName = pszSectionNames;
  854. //
  855. // Get the name of the Tunnel Dun setting
  856. //
  857. MYVERIFY(0 != GetTunnelDunSettingName(pszCmsFile, pszLongServiceName, szTunnelDunName, CELEMS(szTunnelDunName)));
  858. //
  859. // Get the name of the default Dun setting
  860. //
  861. MYVERIFY(0 != GetDefaultDunSettingName(pszCmsFile, pszLongServiceName, szDefaultDunName, CELEMS(szDefaultDunName)));
  862. while (TEXT('\0') != (*pszCurrentSectionName))
  863. {
  864. pszAmpersand = CmStrchr(pszCurrentSectionName, TEXT('&'));
  865. if (pszAmpersand)
  866. {
  867. //
  868. // Then we have a DUN or VPN section name.
  869. //
  870. pszDunName = CharNext(pszAmpersand);
  871. //
  872. // Next we need to see if the entry that we have is of the type we
  873. // are looking for ... a VPN entry if bLookingForVpnEntries is TRUE
  874. // or a DUN entry if bLookingForVpnEntries is FALSE. We can tell the
  875. // DUN and VPN entries apart by the existence of a Networking&<name>
  876. // section or because it is the VPN default entryname.
  877. //
  878. wsprintf(szTemp, TEXT("%s&%s"), c_pszCmSectionDunNetworking, pszDunName);
  879. BOOL bIsVpnEntry = GetPrivateProfileInt(szTemp, c_pszCmEntryDunNetworkingVpnEntry, 0, pszCmsFile);
  880. bTunnelDunSetting = (bIsVpnEntry || (0 == lstrcmpi(szTunnelDunName, pszDunName)));
  881. //
  882. // If we have a VPN entry and are looking for VPN entries or we have a DUN entry and are looking for
  883. // DUN entries, then go ahead and process it.
  884. //
  885. if ((bTunnelDunSetting && bLookingForVpnEntries) || (!bTunnelDunSetting && !bLookingForVpnEntries))
  886. {
  887. ListBxList * pCurrent = *pHeadDns;
  888. while (pCurrent)
  889. {
  890. if(0 == lstrcmpi(pCurrent->szName, pszDunName))
  891. {
  892. //
  893. // Then we already have a DUN setting of this name
  894. //
  895. break;
  896. }
  897. pCurrent = pCurrent->next;
  898. }
  899. //
  900. // We didn't find the item we were looking for, lets create one.
  901. //
  902. if (NULL == pCurrent)
  903. {
  904. pCurrent = (ListBxList*)CmMalloc(sizeof(ListBxList));
  905. if (pCurrent)
  906. {
  907. pCurrent->ListBxData = new CDunSetting(bTunnelDunSetting);
  908. if (NULL == pCurrent->ListBxData)
  909. {
  910. CmFree(pCurrent);
  911. CMASSERTMSG(FALSE, TEXT("ReadDunServerSettings -- Failed to allocate a new DunSettingData struct"));
  912. bReturn = FALSE;
  913. goto exit;
  914. }
  915. }
  916. else
  917. {
  918. CMASSERTMSG(FALSE, TEXT("ReadDunServerSettings -- Failed to allocate a new ListBxList struct"));
  919. bReturn = FALSE;
  920. goto exit;
  921. }
  922. //
  923. // Now that we have allocated a pCurrent, we need to add it to the list
  924. //
  925. if (NULL == *pHeadDns)
  926. {
  927. *pHeadDns = pCurrent;
  928. }
  929. else
  930. {
  931. (*pTailDns)->next = pCurrent;
  932. }
  933. *pTailDns = pCurrent;
  934. //
  935. // Finally copy the name over
  936. //
  937. lstrcpy(pCurrent->szName, pszDunName);
  938. ((CDunSetting*)(pCurrent->ListBxData))->bTunnelDunSetting = bTunnelDunSetting;
  939. }
  940. //
  941. // Now lets figure out which section type we have
  942. //
  943. DWORD dwSize = (DWORD)(pszAmpersand - pszCurrentSectionName + 1);
  944. lstrcpyn(szTemp, pszCurrentSectionName, dwSize);
  945. if (0 == lstrcmpi(szTemp, c_pszCmSectionDunServer))
  946. {
  947. ReadDunServerSettings(pszCurrentSectionName, (CDunSetting*)pCurrent->ListBxData, pszCmsFile, bTunnelDunSetting);
  948. }
  949. else if (0 == lstrcmpi(szTemp, c_pszCmSectionDunNetworking))
  950. {
  951. ReadDunNetworkingSettings(pszCurrentSectionName, (CDunSetting*)pCurrent->ListBxData, pszCmsFile, bTunnelDunSetting);
  952. }
  953. else if (0 == lstrcmpi(szTemp, c_pszCmSectionDunTcpIp))
  954. {
  955. ReadDunTcpIpSettings(pszCurrentSectionName, (CDunSetting*)pCurrent->ListBxData, pszCmsFile);
  956. }
  957. else if (0 == lstrcmpi(szTemp, c_pszCmSectionDunScripting))
  958. {
  959. ReadDunScriptingSettings(pszCurrentSectionName, (CDunSetting*)pCurrent->ListBxData, pszOsDir, pszCmsFile);
  960. }
  961. }
  962. }
  963. //
  964. // Find the next string by going to the end of the string
  965. // and then going one more char. Note that we cannot use
  966. // CharNext here but must use just ++.
  967. //
  968. pszCurrentSectionName = CmEndOfStr(pszCurrentSectionName);
  969. pszCurrentSectionName++;
  970. }
  971. //
  972. // Now we have processed all of the settings that the user has, how about
  973. // the settings that they could have. Lets add the default setting, the
  974. // default Tunnel setting, and all of the settings from the
  975. // current phonebook if there is one. Note that everyone has a tunnel setting,
  976. // but we won't show it in the listbox if the user isn't tunneling.
  977. //
  978. if (bLookingForVpnEntries)
  979. {
  980. MYVERIFY(GetVpnEntryNamesFromFile(pszPhoneBook, pHeadDns, pTailDns));
  981. MYVERIFY(AddDunNameToListIfDoesNotExist(szTunnelDunName, pHeadDns, pTailDns, TRUE)); // TRUE == bTunnelDunName
  982. }
  983. else
  984. {
  985. MYVERIFY(GetDunEntryNamesFromPbk(pszPhoneBook, pHeadDns, pTailDns));
  986. MYVERIFY(AddDunNameToListIfDoesNotExist(szDefaultDunName, pHeadDns, pTailDns, FALSE)); // FALSE == bTunnelDunName
  987. }
  988. exit:
  989. CmFree(pszSectionNames);
  990. return bReturn;
  991. }
  992. //+----------------------------------------------------------------------------
  993. //
  994. // Function: WriteOutNetworkingEntry
  995. //
  996. // Synopsis: This function writes out the given networking entry to the
  997. // appropriate DUN sections in the given cms file.
  998. //
  999. // Arguments: LPCTSTR pszDunName - name of the DUN setting
  1000. // CDunSetting* pDunSetting - settings data to output
  1001. // LPCTSTR pszShortServiceName - short service name of the profile
  1002. // LPCTSTR pszCmsFile - Cms file to write the settings too
  1003. //
  1004. // Returns: Nothing
  1005. //
  1006. // History: quintinb Created 03/22/00
  1007. //
  1008. //+----------------------------------------------------------------------------
  1009. void WriteOutNetworkingEntry(LPCTSTR pszDunName, CDunSetting* pDunSetting, LPCTSTR pszShortServiceName, LPCTSTR pszCmsFile)
  1010. {
  1011. if ((NULL == pszDunName) || (NULL == pDunSetting) || (NULL == pszCmsFile) || (NULL == pszShortServiceName) ||
  1012. (TEXT('\0') == pszCmsFile[0]) || (TEXT('\0') == pszDunName[0]) || (TEXT('\0') == pszShortServiceName[0]))
  1013. {
  1014. CMASSERTMSG(FALSE, TEXT("WriteOutNetworkingEntry -- Invalid input parameter"));
  1015. return;
  1016. }
  1017. //
  1018. // Lets build our four section headers
  1019. //
  1020. TCHAR szServerSection[MAX_PATH+1];
  1021. TCHAR szNetworkingSection[MAX_PATH+1];
  1022. TCHAR szTcpIpSection[MAX_PATH+1];
  1023. TCHAR szScriptingSection[MAX_PATH+1];
  1024. TCHAR szTemp[MAX_PATH+1] = {0};
  1025. TCHAR szEncryptionType[2] = {0};
  1026. TCHAR szVpnStrategy[2] = {0};
  1027. TCHAR szCustomAuthKey[32] = {0};
  1028. MYVERIFY(CELEMS(szServerSection) > (UINT)wsprintf(szServerSection, TEXT("%s&%s"), c_pszCmSectionDunServer, pszDunName));
  1029. MYVERIFY(CELEMS(szNetworkingSection) > (UINT)wsprintf(szNetworkingSection, TEXT("%s&%s"), c_pszCmSectionDunNetworking, pszDunName));
  1030. MYVERIFY(CELEMS(szTcpIpSection) > (UINT)wsprintf(szTcpIpSection, TEXT("%s&%s"), c_pszCmSectionDunTcpIp, pszDunName));
  1031. MYVERIFY(CELEMS(szScriptingSection) > (UINT)wsprintf(szScriptingSection, TEXT("%s&%s"), c_pszCmSectionDunScripting, pszDunName));
  1032. //
  1033. // Now setup a list of all of the Booleans we need to set.
  1034. //
  1035. SetBoolSettings SetBoolSettingsStruct[] = {
  1036. {szServerSection, c_pszCmEntryDunServerNetworkLogon, pDunSetting->bNetworkLogon},
  1037. {szServerSection, c_pszCmEntryDunServerSwCompress, pDunSetting->bPppSoftwareCompression},
  1038. {szServerSection, c_pszCmEntryDunServerDisableLcp, pDunSetting->bDisableLCP},
  1039. {szServerSection, c_pszCmEntryDunServerNegotiateTcpIp, 1}, // always negotiate TCP/IP
  1040. {szServerSection, c_pszCmEntryDunServerSecureLocalFiles, pDunSetting->bSecureLocalFiles},
  1041. {szTcpIpSection, c_pszCmEntryDunTcpIpIpHeaderCompress, pDunSetting->bIpHeaderCompression},
  1042. {szTcpIpSection, c_pszCmEntryDunTcpIpGatewayOnRemote, pDunSetting->bGatewayOnRemote}
  1043. };
  1044. const int c_iNumBools = sizeof(SetBoolSettingsStruct)/sizeof(SetBoolSettingsStruct[0]);
  1045. //
  1046. // Write out the boolean values
  1047. //
  1048. for (int i = 0; i < c_iNumBools; i++)
  1049. {
  1050. MYVERIFY(0 != WritePrivateProfileString(SetBoolSettingsStruct[i].pszSectionName,
  1051. SetBoolSettingsStruct[i].pszKeyName,
  1052. ((SetBoolSettingsStruct[i].bValue) ? c_pszOne : c_pszZero),
  1053. pszCmsFile));
  1054. }
  1055. //
  1056. // Write out the security settings. If the user choose to use the same settings everywhere, then we
  1057. // only want to write out the legacy security flags. If the user choose to have separate settings
  1058. // then we need to write out both sets of settings. Or if the user choose to force win2k and above,
  1059. // we want to write out only the newer settings and set the EnforceCustomSecurity flag to TRUE
  1060. //
  1061. LPTSTR pszCustomSecurity = NULL;
  1062. LPTSTR pszEnforceCustomSecurity = NULL;
  1063. LPTSTR pszAllowPap = NULL;
  1064. LPTSTR pszAllowSpap = NULL;
  1065. LPTSTR pszAllowChap = NULL;
  1066. LPTSTR pszAllowMsChap = NULL;
  1067. LPTSTR pszAllowW95MsChap = NULL;
  1068. LPTSTR pszAllowMsChap2 = NULL;
  1069. LPTSTR pszAllowEAP = NULL;
  1070. LPTSTR pszEncryptionType = NULL;
  1071. LPTSTR pszVpnStrategy = NULL;
  1072. LPTSTR pszUseDownLevelL2TP = NULL;
  1073. LPTSTR pszCustomAuthKey = NULL;
  1074. LPTSTR pszUsePresharedKey = NULL;
  1075. LPTSTR pszUsePskDownLevel = NULL;
  1076. LPTSTR pszPwEncrypt = NULL;
  1077. LPTSTR pszPwEncryptMs = NULL;
  1078. LPTSTR pszDataEncrypt = NULL;
  1079. //
  1080. // Set the legacy security settings if we aren't forcing Win2k+
  1081. //
  1082. if ((SAME_ON_ALL_PLATFORMS == pDunSetting->iHowToHandleSecuritySettings) ||
  1083. (SEPARATE_FOR_LEGACY_AND_WIN2K == pDunSetting->iHowToHandleSecuritySettings))
  1084. {
  1085. pszPwEncrypt = (LPTSTR)(pDunSetting->bPWEncrypt ? c_pszOne : c_pszZero);
  1086. pszPwEncryptMs = (LPTSTR)(pDunSetting->bPWEncrypt_MS ? c_pszOne : c_pszZero);
  1087. pszDataEncrypt = (LPTSTR)((pDunSetting->bPWEncrypt_MS & pDunSetting->bDataEncrypt) ? c_pszOne : c_pszZero);
  1088. }
  1089. //
  1090. // Set the Win2k specific settings if we aren't using the same settings everywhere
  1091. //
  1092. if ((FORCE_WIN2K_AND_ABOVE == pDunSetting->iHowToHandleSecuritySettings) ||
  1093. (SEPARATE_FOR_LEGACY_AND_WIN2K == pDunSetting->iHowToHandleSecuritySettings))
  1094. {
  1095. if (FORCE_WIN2K_AND_ABOVE == pDunSetting->iHowToHandleSecuritySettings)
  1096. {
  1097. pszEnforceCustomSecurity = (LPTSTR)c_pszOne;
  1098. }
  1099. else
  1100. {
  1101. pszEnforceCustomSecurity = (LPTSTR)c_pszZero;
  1102. }
  1103. pszCustomSecurity = (LPTSTR)c_pszOne;
  1104. if (pDunSetting->bAllowEap)
  1105. {
  1106. pszAllowEAP = (LPTSTR)c_pszOne;
  1107. wsprintf(szCustomAuthKey, TEXT("%d"), pDunSetting->dwCustomAuthKey);
  1108. pszCustomAuthKey = szCustomAuthKey;
  1109. }
  1110. else
  1111. {
  1112. pszAllowPap = (LPTSTR)(pDunSetting->bAllowPap ? c_pszOne : c_pszZero);
  1113. pszAllowSpap = (LPTSTR)(pDunSetting->bAllowSpap ? c_pszOne : c_pszZero);
  1114. pszAllowChap = (LPTSTR)(pDunSetting->bAllowChap ? c_pszOne : c_pszZero);
  1115. pszAllowMsChap = (LPTSTR)(pDunSetting->bAllowMsChap ? c_pszOne : c_pszZero);
  1116. pszAllowMsChap2 = (LPTSTR)(pDunSetting->bAllowMsChap2 ? c_pszOne : c_pszZero);
  1117. pszAllowW95MsChap = (LPTSTR)(pDunSetting->bAllowW95MsChap ? c_pszOne : c_pszZero);
  1118. }
  1119. wsprintf(szEncryptionType, TEXT("%d"), pDunSetting->dwEncryptionType);
  1120. pszEncryptionType = szEncryptionType;
  1121. }
  1122. //
  1123. // Now write out the Win2k security settings
  1124. //
  1125. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerEnforceCustomSecurity, pszEnforceCustomSecurity, pszCmsFile);
  1126. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerCustomSecurity, pszCustomSecurity, pszCmsFile);
  1127. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireEap, pszAllowEAP, pszCmsFile);
  1128. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerCustomAuthKey, pszCustomAuthKey, pszCmsFile);
  1129. if (pszAllowEAP)
  1130. {
  1131. MYVERIFY(SUCCEEDED(WriteDunSettingsEapData(szServerSection, pDunSetting, pszCmsFile)));
  1132. }
  1133. else
  1134. {
  1135. MYVERIFY(SUCCEEDED(EraseDunSettingsEapData(szServerSection, pszCmsFile)));
  1136. }
  1137. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequirePap, pszAllowPap, pszCmsFile);
  1138. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireSpap, pszAllowSpap, pszCmsFile);
  1139. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireChap, pszAllowChap, pszCmsFile);
  1140. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireMsChap, pszAllowMsChap, pszCmsFile);
  1141. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireMsChap2, pszAllowMsChap2, pszCmsFile);
  1142. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerRequireW95MsChap, pszAllowW95MsChap, pszCmsFile);
  1143. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerEncryptionType, pszEncryptionType, pszCmsFile);
  1144. //
  1145. // Write out the Networking section if this is a VPN entry, otherwise blank the section. Don't forget to
  1146. // mark the entry as a VPN entry.
  1147. //
  1148. if (pDunSetting->bTunnelDunSetting)
  1149. {
  1150. //
  1151. // Okay, first let's figure out what the VPN settings need to be.
  1152. //
  1153. if (FORCE_WIN2K_AND_ABOVE == pDunSetting->iHowToHandleSecuritySettings)
  1154. {
  1155. pszUseDownLevelL2TP = NULL;
  1156. pszUsePskDownLevel = NULL;
  1157. wsprintf(szVpnStrategy, TEXT("%d"), pDunSetting->dwVpnStrategy);
  1158. pszVpnStrategy = szVpnStrategy;
  1159. pszUsePresharedKey = (LPTSTR)(pDunSetting->bUsePskOnWin2kPlus ? c_pszOne : NULL); // only write UsePreSharedKey if it is 1
  1160. }
  1161. else if (SEPARATE_FOR_LEGACY_AND_WIN2K == pDunSetting->iHowToHandleSecuritySettings)
  1162. {
  1163. wsprintf(szVpnStrategy, TEXT("%d"), pDunSetting->dwVpnStrategy);
  1164. pszVpnStrategy = szVpnStrategy;
  1165. //
  1166. // Only write out the PSK keys and the Downlevel L2TP key if they are 1
  1167. //
  1168. pszUseDownLevelL2TP = (LPTSTR)(pDunSetting->bUseDownLevelL2TP ? c_pszOne : NULL);
  1169. pszUsePskDownLevel = (LPTSTR)(pDunSetting->bUsePskDownLevel ? c_pszOne : NULL);
  1170. pszUsePresharedKey = (LPTSTR)(pDunSetting->bUsePskOnWin2kPlus ? c_pszOne : NULL);
  1171. }
  1172. else
  1173. {
  1174. //
  1175. // Using common settings for both Win2k+ and downlevel. Note that we are
  1176. // basing VpnStrategy and UsePreSharedKey (for XP) off of the downlevel values.
  1177. //
  1178. if (pDunSetting->bUsePskDownLevel)
  1179. {
  1180. pszUsePresharedKey = (LPTSTR)c_pszOne;
  1181. pszUsePskDownLevel = (LPTSTR)c_pszOne;
  1182. }
  1183. else
  1184. {
  1185. pszUsePresharedKey = NULL;
  1186. pszUsePskDownLevel = NULL;
  1187. }
  1188. if (pDunSetting->bUseDownLevelL2TP)
  1189. {
  1190. pszUseDownLevelL2TP = (LPTSTR)c_pszOne;
  1191. wsprintf(szVpnStrategy, TEXT("%d"), VS_L2tpFirst);
  1192. pszVpnStrategy = szVpnStrategy;
  1193. }
  1194. else
  1195. {
  1196. pszUseDownLevelL2TP = NULL;
  1197. wsprintf(szVpnStrategy, TEXT("%d"), VS_PptpFirst);
  1198. pszVpnStrategy = szVpnStrategy;
  1199. }
  1200. }
  1201. //
  1202. // Okay, now write them out
  1203. //
  1204. WritePrivateProfileString(szNetworkingSection, c_pszCmEntryDunNetworkingVpnStrategy, pszVpnStrategy, pszCmsFile);
  1205. WritePrivateProfileString(szNetworkingSection, c_pszCmEntryDunNetworkingUseDownLevelL2TP, pszUseDownLevelL2TP, pszCmsFile);
  1206. WritePrivateProfileString(szNetworkingSection, c_pszCmEntryDunNetworkingUsePreSharedKey, pszUsePresharedKey, pszCmsFile);
  1207. WritePrivateProfileString(szNetworkingSection, c_pszCmEntryDunNetworkingUsePskDownLevel, pszUsePskDownLevel, pszCmsFile);
  1208. WritePrivateProfileString(szNetworkingSection, c_pszCmEntryDunNetworkingVpnEntry, c_pszOne, pszCmsFile);
  1209. }
  1210. else
  1211. {
  1212. WritePrivateProfileString(szNetworkingSection, NULL, NULL, pszCmsFile);
  1213. }
  1214. //
  1215. // Write the legacy security settings
  1216. //
  1217. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerPwEncrypt, pszPwEncrypt, pszCmsFile);
  1218. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerPwEncryptMs, pszPwEncryptMs, pszCmsFile);
  1219. WritePrivateProfileString(szServerSection, c_pszCmEntryDunServerDataEncrypt, pszDataEncrypt, pszCmsFile);
  1220. //
  1221. // Now write out the script section if we have one
  1222. //
  1223. if (pDunSetting->szScript[0])
  1224. {
  1225. TCHAR szScriptFile[MAX_PATH+1];
  1226. GetFileName(pDunSetting->szScript, szTemp);
  1227. MYVERIFY(CELEMS(szScriptFile) > (UINT)wsprintf(szScriptFile, TEXT("%s\\%s"), pszShortServiceName, szTemp));
  1228. MYVERIFY(0 != WritePrivateProfileString(szScriptingSection, c_pszCmEntryDunScriptingName, szScriptFile, pszCmsFile));
  1229. }
  1230. else
  1231. {
  1232. MYVERIFY(0 != WritePrivateProfileString(szScriptingSection, c_pszCmEntryDunScriptingName, NULL, pszCmsFile));
  1233. }
  1234. //
  1235. // Did the admin specify Wins and Dns addresses or is the server going to set them
  1236. //
  1237. if ((pDunSetting->dwPrimaryDns) || (pDunSetting->dwSecondaryDns) || (pDunSetting->dwPrimaryWins) || (pDunSetting->dwSecondaryWins))
  1238. {
  1239. MYVERIFY(ConvertIpDwordToString(pDunSetting->dwPrimaryDns, szTemp));
  1240. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpDnsAddress, szTemp, pszCmsFile));
  1241. MYVERIFY(ConvertIpDwordToString(pDunSetting->dwSecondaryDns, szTemp));
  1242. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpDnsAltAddress, szTemp, pszCmsFile));
  1243. MYVERIFY(ConvertIpDwordToString(pDunSetting->dwPrimaryWins, szTemp));
  1244. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpWinsAddress, szTemp, pszCmsFile));
  1245. MYVERIFY(ConvertIpDwordToString(pDunSetting->dwSecondaryWins, szTemp));
  1246. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpWinsAltAddress, szTemp, pszCmsFile));
  1247. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpSpecifyServerAddress, c_pszOne, pszCmsFile));
  1248. }
  1249. else
  1250. {
  1251. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpSpecifyServerAddress, c_pszZero, pszCmsFile));
  1252. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpDnsAddress, NULL, pszCmsFile));
  1253. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpDnsAltAddress, NULL, pszCmsFile));
  1254. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpWinsAddress, NULL, pszCmsFile));
  1255. MYVERIFY(0 != WritePrivateProfileString(szTcpIpSection, c_pszCmEntryDunTcpIpWinsAltAddress, NULL, pszCmsFile));
  1256. }
  1257. }
  1258. //+----------------------------------------------------------------------------
  1259. //
  1260. // Function: EraseNetworkingSections
  1261. //
  1262. // Synopsis: This function erases all the networking sections for the given
  1263. // DUN name. Thus if you give it a DUN name of Fred, it will
  1264. // erase Server&Fred, Networking&Fred, etc.
  1265. //
  1266. // Arguments: LPCTSTR pszDunName - base dun name to erase all of the settings for
  1267. // LPCTSTR pszCmsFile - cms file to erase the setting from
  1268. //
  1269. // Returns: Nothing
  1270. //
  1271. // History: quintinb Created 03/22/00
  1272. //
  1273. //+----------------------------------------------------------------------------
  1274. void EraseNetworkingSections(LPCTSTR pszDunName, LPCTSTR pszCmsFile)
  1275. {
  1276. TCHAR szSection[MAX_PATH+1];
  1277. const int c_iNumDunSubSections = 4;
  1278. const TCHAR* const ArrayOfSubSections[c_iNumDunSubSections] =
  1279. {
  1280. c_pszCmSectionDunServer,
  1281. c_pszCmSectionDunNetworking,
  1282. c_pszCmSectionDunTcpIp,
  1283. c_pszCmSectionDunScripting
  1284. };
  1285. if (pszDunName)
  1286. {
  1287. for (int i = 0; i < c_iNumDunSubSections; i++)
  1288. {
  1289. MYVERIFY(CELEMS(szSection) > (UINT)wsprintf(szSection, TEXT("%s&%s"), ArrayOfSubSections[i], pszDunName));
  1290. MYVERIFY(0 != WritePrivateProfileString(szSection, NULL, NULL, pszCmsFile));
  1291. }
  1292. }
  1293. }
  1294. //+----------------------------------------------------------------------------
  1295. //
  1296. // Function: WriteNetworkingEntries
  1297. //
  1298. // Synopsis: This function walks through the list of networking entries and
  1299. // either adds the networking entry to the given CMS file or
  1300. // if the entry is a VPN entry and the user turned off VPN's then
  1301. // it erases the VPN sections.
  1302. //
  1303. // Arguments: LPCTSTR pszCmsFile - Cms File to write the networking entries too
  1304. // LPCTSTR pszLongServiceName - long service name of the profile
  1305. // LPCTSTR pszShortServiceName - short service name of the profile
  1306. // ListBxList *g_pHeadDns - pointer to the head of the Dun entries list
  1307. //
  1308. // Returns: Nothing
  1309. //
  1310. // History: quintinb Created 03/22/00
  1311. //
  1312. //+----------------------------------------------------------------------------
  1313. void WriteNetworkingEntries(LPCTSTR pszCmsFile, LPCTSTR pszLongServiceName, LPCTSTR pszShortServiceName, ListBxList *pHeadDns)
  1314. {
  1315. MYDBGASSERT(pszCmsFile);
  1316. MYDBGASSERT(pszShortServiceName);
  1317. MYDBGASSERT(pszLongServiceName);
  1318. if (pszCmsFile && pszShortServiceName && pszLongServiceName && pHeadDns)
  1319. {
  1320. ListBxList * pCurrent = pHeadDns;
  1321. TCHAR szTemp[MAX_PATH];
  1322. TCHAR szTunnelDunName[MAX_PATH] = TEXT("");
  1323. //
  1324. // Get the name of the Tunnel Dun setting
  1325. //
  1326. MYVERIFY(0 != GetTunnelDunSettingName(pszCmsFile, pszLongServiceName, szTunnelDunName, CELEMS(szTunnelDunName)));
  1327. while (pCurrent)
  1328. {
  1329. //
  1330. // If we don't have any data for the entry (it was a placeholder that the user choose not to fill in) or
  1331. // if the entry is the tunneling entry and we aren't actually Tunneling then erase the entry instead of actually
  1332. // writing it out.
  1333. //
  1334. if (NULL == pCurrent->ListBxData)
  1335. {
  1336. EraseNetworkingSections(pCurrent->szName, pszCmsFile);
  1337. }
  1338. else
  1339. {
  1340. WriteOutNetworkingEntry(pCurrent->szName, (CDunSetting*)pCurrent->ListBxData, pszShortServiceName, pszCmsFile);
  1341. }
  1342. pCurrent = pCurrent->next;
  1343. }
  1344. }
  1345. }
  1346. //+----------------------------------------------------------------------------
  1347. //
  1348. // Function: EnableDisableDataEncryptCheckbox
  1349. //
  1350. // Synopsis: This function enables or disables the data encrypt checkbox
  1351. // depending on whether the user has selected to allow MsChap or not.
  1352. // For data encryption to be negotiated, the authentication protocol
  1353. // must be MsChap.
  1354. //
  1355. // Arguments: HWND hDlg - window handle to the dialog
  1356. //
  1357. // Returns: Nothing
  1358. //
  1359. // History: quintinb Created 03/27/00
  1360. //
  1361. //+----------------------------------------------------------------------------
  1362. void EnableDisableDataEncryptCheckbox(HWND hDlg)
  1363. {
  1364. BOOL bMsChapEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_MS_ENCRYPTED_AUTH));
  1365. HWND hControl = GetDlgItem(hDlg, IDC_CHECK1);
  1366. if (hControl)
  1367. {
  1368. EnableWindow (hControl, bMsChapEnabled);
  1369. }
  1370. }
  1371. //+----------------------------------------------------------------------------
  1372. //
  1373. // Function: EnableDisableUsePskCheckbox
  1374. //
  1375. // Synopsis: This function enables or disables the use a pre-shared key checkbox
  1376. // depending on whether the user has selected to allow L2TP or not.
  1377. //
  1378. // Arguments: HWND hDlg - window handle to the dialog
  1379. //
  1380. // Returns: Nothing
  1381. //
  1382. // History: quintinb Created 09/12/01
  1383. //
  1384. //+----------------------------------------------------------------------------
  1385. void EnableDisableUsePskCheckbox(HWND hDlg)
  1386. {
  1387. BOOL bL2TPEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_L2TP));
  1388. HWND hControl = GetDlgItem(hDlg, IDC_CHECK2);
  1389. if (hControl)
  1390. {
  1391. EnableWindow (hControl, bL2TPEnabled);
  1392. }
  1393. }
  1394. //+----------------------------------------------------------------------------
  1395. //
  1396. // Function: ProcessSecurityPopup
  1397. //
  1398. // Synopsis: This function processes messages for the simple security dialog.
  1399. // This dialog only contains authorization protocols and encryption
  1400. // settings supported on all platforms.
  1401. //
  1402. // Arguments: HWND hDlg - window handle to the dialog
  1403. // UINT message - the current message to process
  1404. // WPARAM wParam - wParam see individual message type for details
  1405. // LPARAM lParam - lParam see individual message type for details
  1406. //
  1407. // Returns: INT_PTR - TRUE if the message was completely handled
  1408. //
  1409. // History: quintinb Created 03/27/00
  1410. //
  1411. //+----------------------------------------------------------------------------
  1412. INT_PTR APIENTRY ProcessSecurityPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1413. {
  1414. static DWORD_PTR HelpId = 0;
  1415. static CDunSetting* pDunSetting = NULL;
  1416. if (ProcessHelp(hDlg, message, wParam, lParam, HelpId)) return TRUE;
  1417. switch (message)
  1418. {
  1419. case WM_INITDIALOG:
  1420. if (lParam)
  1421. {
  1422. pDunSetting = (CDunSetting*)lParam;
  1423. //
  1424. // Setup the help ID appropriately
  1425. //
  1426. HelpId = ((pDunSetting->bTunnelDunSetting) ? IDH_VENTRY : IDH_DENTRY);
  1427. //
  1428. // Set the radio button to the correct choice
  1429. //
  1430. UINT uRadioButtonToSet;
  1431. if (pDunSetting->bPWEncrypt_MS)
  1432. {
  1433. uRadioButtonToSet = IDC_MS_ENCRYPTED_AUTH;
  1434. //
  1435. // Set the Data Encryption checkbox, note that data encryption requires MSChap
  1436. //
  1437. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, pDunSetting->bDataEncrypt));
  1438. }
  1439. else if (pDunSetting->bPWEncrypt)
  1440. {
  1441. uRadioButtonToSet = IDC_ENCRYPTED_AUTH;
  1442. }
  1443. else
  1444. {
  1445. uRadioButtonToSet = IDC_ANY_AUTH;
  1446. }
  1447. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_ANY_AUTH, IDC_MS_ENCRYPTED_AUTH, uRadioButtonToSet));
  1448. if (pDunSetting->bTunnelDunSetting)
  1449. {
  1450. //
  1451. // Set the radio buttons for using PPTP or using L2TP depending on the setting...
  1452. //
  1453. if (pDunSetting->bUseDownLevelL2TP)
  1454. {
  1455. uRadioButtonToSet = IDC_USE_L2TP;
  1456. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK2, pDunSetting->bUsePskDownLevel));
  1457. }
  1458. else
  1459. {
  1460. uRadioButtonToSet = IDC_USE_PPTP;
  1461. }
  1462. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_USE_PPTP, IDC_USE_L2TP, uRadioButtonToSet));
  1463. }
  1464. }
  1465. else
  1466. {
  1467. pDunSetting = NULL;
  1468. CMASSERTMSG(FALSE, TEXT("ProcessSecurityPopup -- NULL lParam passed to InitDialog. Dialog controls will all be set to off."));
  1469. }
  1470. EnableDisableDataEncryptCheckbox(hDlg);
  1471. EnableDisableUsePskCheckbox(hDlg);
  1472. break;
  1473. case WM_COMMAND:
  1474. switch (LOWORD(wParam))
  1475. {
  1476. case IDC_MS_ENCRYPTED_AUTH:
  1477. case IDC_ENCRYPTED_AUTH:
  1478. case IDC_ANY_AUTH:
  1479. EnableDisableDataEncryptCheckbox(hDlg);
  1480. break;
  1481. case IDC_USE_L2TP:
  1482. case IDC_USE_PPTP:
  1483. EnableDisableUsePskCheckbox(hDlg);
  1484. break;
  1485. case IDOK:
  1486. MYDBGASSERT(pDunSetting);
  1487. if (pDunSetting)
  1488. {
  1489. pDunSetting->bDataEncrypt = IsDlgButtonChecked(hDlg, IDC_CHECK1); // if mschap isn't enabled we will write out zero for DataEncrypt
  1490. pDunSetting->bPWEncrypt_MS = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_MS_ENCRYPTED_AUTH));
  1491. pDunSetting->bPWEncrypt = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ENCRYPTED_AUTH));
  1492. pDunSetting->bUseDownLevelL2TP = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_L2TP));
  1493. // IDC_CHECK2 can be disabled but still checked, thus if it's not enabled we need to
  1494. // explicitly set bUsePskDownLevel to FALSE
  1495. if (pDunSetting->bUseDownLevelL2TP)
  1496. {
  1497. pDunSetting->bUsePskDownLevel = IsDlgButtonChecked(hDlg, IDC_CHECK2); // if L2TP isn't enabled we will write out zero for UsePskDownLevel
  1498. }
  1499. else
  1500. {
  1501. pDunSetting->bUsePskDownLevel = FALSE;
  1502. }
  1503. }
  1504. EndDialog(hDlg, IDOK);
  1505. break;
  1506. case IDCANCEL:
  1507. EndDialog(hDlg, IDCANCEL);
  1508. break;
  1509. default:
  1510. break;
  1511. }
  1512. break;
  1513. }
  1514. return FALSE;
  1515. }
  1516. //+----------------------------------------------------------------------------
  1517. //
  1518. // Function: EnableDisableEapPropertiesButton
  1519. //
  1520. // Synopsis: This function enables or disables the EAP properties button found
  1521. // on the Win2k specific security settings dialog. If the currently
  1522. // selected EAP has configuration UI then the properties button should
  1523. // be enabled. The function determines this by getting the EAPData
  1524. // structure pointer that is cached in the ItemData of the combobox.
  1525. // Note that the Properties button should also be disabled when EAP
  1526. // is disabled but that this function doesn't deal with that case.
  1527. //
  1528. // Arguments: HWND hDlg - window handle to the win2k security dialog
  1529. //
  1530. // Returns: Nothing
  1531. //
  1532. // History: quintinb Created 03/27/00
  1533. //
  1534. //+----------------------------------------------------------------------------
  1535. void EnableDisableEapPropertiesButton(HWND hDlg)
  1536. {
  1537. BOOL bEnablePropButton = FALSE;
  1538. LRESULT lResult = SendDlgItemMessage(hDlg, IDC_EAP_TYPES, CB_GETCURSEL, 0, 0);
  1539. if (CB_ERR != lResult)
  1540. {
  1541. lResult = SendDlgItemMessage(hDlg, IDC_EAP_TYPES, CB_GETITEMDATA, (WPARAM)lResult, 0);
  1542. EAPData* pEAPData = (EAPData*)lResult;
  1543. if (pEAPData)
  1544. {
  1545. bEnablePropButton = (pEAPData->pszConfigDllPath && pEAPData->pszConfigDllPath[0]);
  1546. }
  1547. }
  1548. EnableWindow(GetDlgItem(hDlg, IDC_EAP_PROPERTIES), bEnablePropButton);
  1549. }
  1550. //+----------------------------------------------------------------------------
  1551. //
  1552. // Function: EnableAppropriateSecurityControls
  1553. //
  1554. // Synopsis: This function enables or disables all of the authorization
  1555. // protocol controls on the win2k security dialog. If EAP
  1556. // is selected then only the EAP combobox and potentially the
  1557. // EAP properties button should be enabled (depending on if the
  1558. // currently selected EAP supports configuration UI or not).
  1559. // If EAP is NOT selected then the EAP controls should be disabled
  1560. // and the other authorization checkboxes (PAP, SPAP, CHAP, etc.)
  1561. // should be enabled.
  1562. //
  1563. // Arguments: HWND hDlg - window handle to the win2k security dialog
  1564. //
  1565. // Returns: Nothing
  1566. //
  1567. // History: quintinb Created 03/27/00
  1568. //
  1569. //+----------------------------------------------------------------------------
  1570. void EnableAppropriateSecurityControls(HWND hDlg)
  1571. {
  1572. BOOL bUseEAP = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_EAP));
  1573. //
  1574. // If EAP is enabled then we need to disable all of the
  1575. // other security authorization protocols.
  1576. //
  1577. EnableWindow(GetDlgItem(hDlg, IDC_ALLOW_PAP), !bUseEAP);
  1578. EnableWindow(GetDlgItem(hDlg, IDC_ALLOW_SPAP), !bUseEAP);
  1579. EnableWindow(GetDlgItem(hDlg, IDC_ALLOW_CHAP), !bUseEAP);
  1580. EnableWindow(GetDlgItem(hDlg, IDC_ALLOW_MSCHAP), !bUseEAP);
  1581. EnableWindow(GetDlgItem(hDlg, IDC_ALLOW_MSCHAP2), !bUseEAP);
  1582. //
  1583. // If EAP is disabled then we need to enable the enable combobox
  1584. // and the EAP properties button.
  1585. //
  1586. EnableWindow(GetDlgItem(hDlg, IDC_EAP_TYPES), bUseEAP);
  1587. if (bUseEAP)
  1588. {
  1589. EnableDisableEapPropertiesButton(hDlg);
  1590. }
  1591. else
  1592. {
  1593. EnableWindow(GetDlgItem(hDlg, IDC_EAP_PROPERTIES), FALSE);
  1594. }
  1595. }
  1596. #define MAX_BLOB_CHARS_PER_LINE 128
  1597. //
  1598. // From ras\ui\common\nouiutil\noui.c
  1599. //
  1600. BYTE HexValue(IN CHAR ch)
  1601. /* Returns the value 0 to 15 of hexadecimal character 'ch'.
  1602. */
  1603. {
  1604. if (ch >= '0' && ch <= '9')
  1605. return (BYTE )(ch - '0');
  1606. else if (ch >= 'A' && ch <= 'F')
  1607. return (BYTE )((ch - 'A') + 10);
  1608. else if (ch >= 'a' && ch <= 'f')
  1609. return (BYTE )((ch - 'a') + 10);
  1610. else
  1611. return 0;
  1612. }
  1613. //+----------------------------------------------------------------------------
  1614. //
  1615. // Function: ReadDunSettingsEapData
  1616. //
  1617. // Synopsis: Retrieves DUN setting for EAP config (opaque blob) data. The
  1618. // entry may span several lines and contain several EAP data blocks.
  1619. //
  1620. // Arguments: CIni *pIni - Ptr to ini object to be used.
  1621. // LPBYTE* ppbEapData - Address of pointer to store EapData, allocated here.
  1622. // LPDWORD pdwEapSize - Ptr to a DWORD to record the size of the data blob.
  1623. // DWORD dwCustomAuthKey - The EAP type that we are interested in.
  1624. //
  1625. // Returns: TRUE on success
  1626. //
  1627. // Note: CM expects blob data to be provided in numbered entries such as:
  1628. // CustomAuthData0=, CustomAuthData1=, CustomAuthData2=, etc.
  1629. //
  1630. // History: nickball Created 08/24/98
  1631. // nickball Handle multiple EAP data blocks in blob. 09/11/99
  1632. // quintinb modified not to use CIni 03/27/00
  1633. //
  1634. //+----------------------------------------------------------------------------
  1635. BOOL ReadDunSettingsEapData(LPCTSTR pszSection, LPBYTE* ppbEapData, LPDWORD pdwEapSize, const DWORD dwCustomAuthKey, LPCTSTR pszCmsFile)
  1636. {
  1637. CHAR *pchBuf = NULL;
  1638. CHAR szTmp[MAX_BLOB_CHARS_PER_LINE + 2];
  1639. CHAR szEntry[128];
  1640. int nLine = -1;
  1641. int nRead = -1;
  1642. int nTotal = 0;
  1643. LPBYTE pbEapBytes = NULL;
  1644. MYDBGASSERT(pszSection);
  1645. MYDBGASSERT(pszSection[0]);
  1646. MYDBGASSERT(ppbEapData);
  1647. MYDBGASSERT(pdwEapSize);
  1648. if ((NULL == pszSection) || (NULL == ppbEapData) || (NULL == pdwEapSize) || (TEXT('\0') == pszSection[0]))
  1649. {
  1650. return FALSE;
  1651. }
  1652. //
  1653. // Convert the Section and the CMS File to ANSI strings
  1654. //
  1655. BOOL bRet = FALSE;
  1656. LPSTR pszAnsiSection = WzToSzWithAlloc(pszSection);
  1657. LPSTR pszAnsiCmsFile = WzToSzWithAlloc(pszCmsFile);
  1658. if (!pszAnsiSection || !pszAnsiCmsFile)
  1659. {
  1660. bRet = FALSE;
  1661. goto exit;
  1662. }
  1663. //
  1664. // Read numbered entries until there are no more.
  1665. // Note: RAS blob doesn't exceed 64 chars, but can wrap over multiple lines
  1666. //
  1667. while (nRead)
  1668. {
  1669. //
  1670. // Read CustomAuthDataX where X is the number of entries
  1671. //
  1672. nLine++;
  1673. wsprintfA(szEntry, "%s%d", c_pszCmEntryDunServerCustomAuthData, nLine);
  1674. nRead = GetPrivateProfileStringA(pszAnsiSection, szEntry, "", szTmp, sizeof(szTmp), pszAnsiCmsFile);
  1675. if (nRead)
  1676. {
  1677. //
  1678. // If line exceeded 128 chars, it is considered corrupt
  1679. //
  1680. if (MAX_BLOB_CHARS_PER_LINE < nRead)
  1681. {
  1682. nTotal = 0;
  1683. break;
  1684. }
  1685. //
  1686. // Update our local master buffer with the latest fragment
  1687. //
  1688. if (nLine)
  1689. {
  1690. pchBuf = CmStrCatAllocA(&pchBuf, szTmp);
  1691. }
  1692. else
  1693. {
  1694. pchBuf = CmStrCpyAllocA(szTmp);
  1695. }
  1696. if (!pchBuf)
  1697. {
  1698. bRet = FALSE;
  1699. goto exit;
  1700. }
  1701. nTotal += nRead;
  1702. }
  1703. }
  1704. //
  1705. // At this point we should have the entire entry in pchBuf in HEX format
  1706. // Convert the buffer to byte format and store in supplied EAP buffer.
  1707. //
  1708. if (nTotal && !(nTotal & 1))
  1709. {
  1710. nTotal /= 2; // Only need half the hex char size
  1711. pbEapBytes = (BYTE *) CmMalloc(nTotal + 1);
  1712. if (!pbEapBytes)
  1713. {
  1714. goto exit;
  1715. }
  1716. CHAR *pch = pchBuf;
  1717. BYTE *pb = pbEapBytes;
  1718. while (*pch != '\0')
  1719. {
  1720. *pb = HexValue( *pch++ ) * 16;
  1721. *pb += HexValue( *pch++ );
  1722. ++pb;
  1723. }
  1724. //
  1725. // Now we have the bytes, locate and extract the data block that we
  1726. // are after. Note: Multiple blocks are arrayed using the following
  1727. // header:
  1728. //
  1729. // typedef struct _EAP_CUSTOM_DATA
  1730. // {
  1731. // DWORD dwSignature;
  1732. // DWORD dwCustomAuthKey;
  1733. // DWORD dwSize;
  1734. // BYTE abdata[1];
  1735. // } EAP_CUSTOM_DATA;
  1736. //
  1737. EAP_CUSTOM_DATA *pCustomData = (EAP_CUSTOM_DATA *) pbEapBytes;
  1738. while (((LPBYTE) pCustomData - pbEapBytes) < nTotal)
  1739. {
  1740. if (pCustomData->dwCustomAuthKey == dwCustomAuthKey)
  1741. {
  1742. //
  1743. // Bingo! We have a match, first make sure that the indicated
  1744. // size isn't pointing out into space, then make a copy and
  1745. // run for the hills.
  1746. //
  1747. if (((LPBYTE) pCustomData - pbEapBytes) + sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize > (DWORD) nTotal)
  1748. {
  1749. MYDBGASSERT(FALSE);
  1750. goto exit;
  1751. }
  1752. *ppbEapData = (BYTE *) CmMalloc(pCustomData->dwSize);
  1753. if (*ppbEapData)
  1754. {
  1755. CopyMemory(*ppbEapData, pCustomData->abdata, pCustomData->dwSize);
  1756. *pdwEapSize = pCustomData->dwSize;
  1757. bRet = TRUE;
  1758. goto exit;
  1759. }
  1760. }
  1761. //
  1762. // Locate the next data block
  1763. //
  1764. pCustomData = (EAP_CUSTOM_DATA *) ((LPBYTE) pCustomData + sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize);
  1765. }
  1766. }
  1767. else if (0 == nTotal)
  1768. {
  1769. //
  1770. // No CustomAuthData, that is perfectly exceptable. MD5 challenge for instance doesn't require any
  1771. //
  1772. *ppbEapData = NULL;
  1773. *pdwEapSize = 0;
  1774. bRet = TRUE;
  1775. }
  1776. exit:
  1777. CmFree(pchBuf);
  1778. CmFree(pszAnsiSection);
  1779. CmFree(pszAnsiCmsFile);
  1780. CmFree(pbEapBytes);
  1781. return bRet;
  1782. }
  1783. //
  1784. // From ras\ui\common\nouiutil\noui.c
  1785. //
  1786. CHAR HexChar(IN BYTE byte)
  1787. /* Returns an ASCII hexidecimal character corresponding to 0 to 15 value,
  1788. ** 'byte'.
  1789. */
  1790. {
  1791. const CHAR* pszHexDigits = "0123456789ABCDEF";
  1792. if (byte >= 0 && byte < 16)
  1793. return pszHexDigits[ byte ];
  1794. else
  1795. return '0';
  1796. }
  1797. //+----------------------------------------------------------------------------
  1798. //
  1799. // Function: WriteDunSettingsEapData
  1800. //
  1801. // Synopsis: This function writes out the CustomAuthData key of the EAP settings
  1802. // to the given section and CMS file. Since CM expects the EAP data
  1803. // to have the RAS EAP header on it (the header that RAS adds when it
  1804. // puts the EAP data in the phonebook) and thus we need to add this
  1805. // to the EAP blob before writing it to the CMS.
  1806. //
  1807. // Arguments: LPCTSTR pszSection - section name to write the CustomAuthData to
  1808. // CDunSetting* pDunSetting - Dun settings data
  1809. // LPCTSTR pszCmsFile - cms file to write the data to
  1810. //
  1811. // Returns: HRESULT - standard COM style error codes
  1812. //
  1813. // History: quintinb Created 03/27/00
  1814. //
  1815. //+----------------------------------------------------------------------------
  1816. HRESULT WriteDunSettingsEapData(LPCTSTR pszSection, CDunSetting* pDunSetting, LPCTSTR pszCmsFile)
  1817. {
  1818. if ((NULL == pszSection) || (NULL == pDunSetting) || (NULL == pszCmsFile) ||
  1819. (TEXT('\0') == pszSection[0]) || (TEXT('\0') == pszCmsFile[0]))
  1820. {
  1821. return E_INVALIDARG;
  1822. }
  1823. //
  1824. // Make sure to erase any existing lines just in case the existing data is longer
  1825. // than our current data. If we leave lines around that don't need to be there then
  1826. // the EAP data will be invalid.
  1827. //
  1828. HRESULT hr = EraseDunSettingsEapData(pszSection, pszCmsFile);
  1829. //
  1830. // Check to see if we need to do anything. Not all EAP's require custom data so
  1831. // let's not try to write it out unless we have some.
  1832. //
  1833. if (pDunSetting->dwCustomAuthDataSize && pDunSetting->pCustomAuthData)
  1834. {
  1835. //
  1836. // We need to add the EAP_CUSTOM_DATA header to the
  1837. // data returned from the EAP because this is the format
  1838. // that CM expects to find it in (the format it would be in
  1839. // if an Admin copied it by hand).
  1840. //
  1841. hr = S_OK;
  1842. DWORD dwSize = pDunSetting->dwCustomAuthDataSize + sizeof(EAP_CUSTOM_DATA);
  1843. EAP_CUSTOM_DATA* pEAPCustomData = (EAP_CUSTOM_DATA*)CmMalloc(dwSize);
  1844. LPSTR pszAnsiSection = WzToSzWithAlloc(pszSection);
  1845. LPSTR pszAnsiCmsFile = WzToSzWithAlloc(pszCmsFile);
  1846. if (pEAPCustomData && pszAnsiSection && pszAnsiCmsFile)
  1847. {
  1848. pEAPCustomData->dwSignature = EAP_CUSTOM_KEY;
  1849. pEAPCustomData->dwCustomAuthKey = pDunSetting->dwCustomAuthKey;
  1850. pEAPCustomData->dwSize = pDunSetting->dwCustomAuthDataSize;
  1851. CopyMemory(pEAPCustomData->abdata, pDunSetting->pCustomAuthData, pDunSetting->dwCustomAuthDataSize);
  1852. CHAR szOutput[MAX_BLOB_CHARS_PER_LINE+1];
  1853. CHAR szAnsiKeyName[MAX_BLOB_CHARS_PER_LINE];
  1854. CHAR* pszOutput;
  1855. LPBYTE pCurrentByte = (LPBYTE)pEAPCustomData;
  1856. int iCount = 0;
  1857. int iLineNum = 0;
  1858. pszOutput = szOutput;
  1859. while (pCurrentByte < ((LPBYTE)pEAPCustomData + dwSize))
  1860. {
  1861. *pszOutput++ = HexChar( (BYTE )(*pCurrentByte / 16) );
  1862. *pszOutput++ = HexChar( (BYTE )(*pCurrentByte % 16) );
  1863. pCurrentByte++;
  1864. iCount = iCount + 2; // keep track of number of chars in ansi output buffer
  1865. if ((MAX_BLOB_CHARS_PER_LINE == iCount) || (pCurrentByte == ((LPBYTE)pEAPCustomData + dwSize)))
  1866. {
  1867. *pszOutput = '\0';
  1868. wsprintfA(szAnsiKeyName, "%s%d", c_pszCmEntryDunServerCustomAuthData, iLineNum);
  1869. MYVERIFY(0 != WritePrivateProfileStringA(pszAnsiSection, szAnsiKeyName, szOutput, pszAnsiCmsFile));
  1870. pszOutput = szOutput;
  1871. iCount = 0;
  1872. iLineNum++;
  1873. }
  1874. }
  1875. }
  1876. else
  1877. {
  1878. hr = E_OUTOFMEMORY;
  1879. }
  1880. CmFree(pEAPCustomData);
  1881. CmFree(pszAnsiCmsFile);
  1882. CmFree(pszAnsiSection);
  1883. }
  1884. return hr;
  1885. }
  1886. //+----------------------------------------------------------------------------
  1887. //
  1888. // Function: GetEAPDataFromUser
  1889. //
  1890. // Synopsis: This function is called when the user hits the properties button
  1891. // for EAP configuration. This function gets the EAP configuration
  1892. // UI path from the EAPData structure cached in the Combobox Item data
  1893. // and tries to call the configuration UI. If the user configures the
  1894. // EAP then the new EAP data and data size are set in the EAPData
  1895. // struct for the combobox. If the user cancels then nothing is changed.
  1896. // Note that when the user hits OK on the win2k security dialog the EAP
  1897. // data will be retrieved from the EAPData struct and set in the
  1898. // actual DUN setting.
  1899. //
  1900. // Arguments: HWND hDlg - dialog window handle
  1901. // UINT uCtrlId - control ID of the EAP combobox
  1902. //
  1903. // Returns: Nothing
  1904. //
  1905. // History: quintinb Created 03/27/00
  1906. //
  1907. //+----------------------------------------------------------------------------
  1908. void GetEAPDataFromUser(HWND hDlg, UINT uCtrlId)
  1909. {
  1910. MYDBGASSERT(hDlg && uCtrlId);
  1911. if (hDlg && uCtrlId)
  1912. {
  1913. LRESULT lResult = SendDlgItemMessage(hDlg, uCtrlId, CB_GETCURSEL, 0, 0);
  1914. MYDBGASSERT(CB_ERR != lResult);
  1915. if (CB_ERR != lResult)
  1916. {
  1917. lResult = SendDlgItemMessage(hDlg, uCtrlId, CB_GETITEMDATA, (WPARAM)lResult, 0);
  1918. EAPData* pEAPData = (EAPData*)lResult;
  1919. if (pEAPData && pEAPData->pszConfigDllPath && pEAPData->pszConfigDllPath[0])
  1920. {
  1921. HINSTANCE hEapConfigDll = LoadLibrary(pEAPData->pszConfigDllPath);
  1922. if (hEapConfigDll)
  1923. {
  1924. typedef DWORD (WINAPI *RasEapInvokeConfigUIProc)(DWORD, HWND, DWORD, BYTE*, DWORD, BYTE**, DWORD*);
  1925. typedef DWORD (WINAPI *RasEapFreeMemoryProc)(BYTE*);
  1926. const char* const c_pszRasEapFreeMemory = "RasEapFreeMemory";
  1927. const char* const c_pszRasEapInvokeConfigUI = "RasEapInvokeConfigUI";
  1928. RasEapFreeMemoryProc pfnRasEapFreeMemory = (RasEapFreeMemoryProc)GetProcAddress(hEapConfigDll, c_pszRasEapFreeMemory);
  1929. RasEapInvokeConfigUIProc pfnRasEapInvokeConfigUI = (RasEapInvokeConfigUIProc)GetProcAddress(hEapConfigDll, c_pszRasEapInvokeConfigUI);
  1930. if (pfnRasEapFreeMemory && pfnRasEapInvokeConfigUI)
  1931. {
  1932. DWORD dwNewSize = 0;
  1933. BYTE* pNewData = NULL;
  1934. DWORD dwReturn = pfnRasEapInvokeConfigUI(pEAPData->dwCustomAuthKey, hDlg, 0, pEAPData->pCustomAuthData,
  1935. pEAPData->dwCustomAuthDataSize, &pNewData, &dwNewSize);
  1936. if (NO_ERROR == dwReturn)
  1937. {
  1938. CmFree(pEAPData->pCustomAuthData);
  1939. pEAPData->pCustomAuthData = (LPBYTE)CmMalloc(dwNewSize);
  1940. if (pEAPData->pCustomAuthData)
  1941. {
  1942. pEAPData->dwCustomAuthDataSize = dwNewSize;
  1943. CopyMemory(pEAPData->pCustomAuthData, pNewData, dwNewSize);
  1944. }
  1945. else
  1946. {
  1947. pEAPData->dwCustomAuthDataSize = 0;
  1948. pEAPData->pCustomAuthData = NULL;
  1949. CMASSERTMSG(FALSE, TEXT("GetEAPDataFromUser -- CmMalloc failed."));
  1950. }
  1951. MYVERIFY(NO_ERROR == pfnRasEapFreeMemory(pNewData));
  1952. }
  1953. else if (ERROR_CANCELLED != dwReturn)
  1954. {
  1955. CMTRACE3(TEXT("EAP %d (%s) failed with return code %d"), pEAPData->dwCustomAuthKey, pEAPData->pszConfigDllPath, dwReturn);
  1956. CMASSERTMSG(FALSE, TEXT("GetEAPDataFromUser -- pfnRasEapInvokeConfigUI from EAP dll failed."));
  1957. }
  1958. }
  1959. else
  1960. {
  1961. CMASSERTMSG(FALSE, TEXT("GetEAPDataFromUser -- GetProcAddressFailed on the EAP dll."));
  1962. }
  1963. }
  1964. else
  1965. {
  1966. CMTRACE2(TEXT("Failed to load EAP %d (%s)"), pEAPData->dwCustomAuthKey, pEAPData->pszConfigDllPath);
  1967. CMASSERTMSG(FALSE, TEXT("GetEAPDataFromUser -- Unable to load the specified EAP Dll."));
  1968. }
  1969. }
  1970. }
  1971. }
  1972. }
  1973. int MapEncryptionTypeToComboId(DWORD dwEncryptionType)
  1974. {
  1975. int iReturn;
  1976. switch(dwEncryptionType)
  1977. {
  1978. case ET_None:
  1979. iReturn = 0;
  1980. break;
  1981. case ET_RequireMax:
  1982. case ET_Require:
  1983. iReturn = 1;
  1984. break;
  1985. case ET_Optional:
  1986. default:
  1987. iReturn = 2;
  1988. break;
  1989. }
  1990. return iReturn;
  1991. }
  1992. DWORD MapComboIdToEncryptionType(INT_PTR iComboIndex)
  1993. {
  1994. DWORD dwReturn;
  1995. switch(iComboIndex)
  1996. {
  1997. case 0:
  1998. dwReturn = ET_None;
  1999. break;
  2000. case 1:
  2001. dwReturn = ET_Require; // note that we never set require max
  2002. break;
  2003. case 2:
  2004. default:
  2005. dwReturn = ET_Optional;
  2006. break;
  2007. }
  2008. return dwReturn;
  2009. }
  2010. //+----------------------------------------------------------------------------
  2011. //
  2012. // Function: EnablePskCheckboxForL2TP
  2013. //
  2014. // Synopsis: This function enables the PSK checkbox
  2015. //
  2016. // Arguments: HWND hDlg - window handle
  2017. //
  2018. // Returns: Nothing
  2019. //
  2020. // History: quintinb Created 09/12/01
  2021. //
  2022. //+----------------------------------------------------------------------------
  2023. void EnablePskCheckboxForL2TP(HWND hDlg)
  2024. {
  2025. BOOL bEnable = FALSE;
  2026. DWORD dwVpnStrategy = (DWORD)SendDlgItemMessage(hDlg, IDC_VPN_TYPE, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2027. if (CB_ERR != dwVpnStrategy)
  2028. {
  2029. dwVpnStrategy += 1; // adjust for not having automatic in the list.
  2030. if ((VS_L2tpFirst == dwVpnStrategy) || (VS_L2tpOnly == dwVpnStrategy))
  2031. {
  2032. bEnable = TRUE;
  2033. }
  2034. }
  2035. //
  2036. // Enable the psk checkbox if an L2TP protocol is selected but disable it if
  2037. // PPTP is the primary protocol (PPTP first or PPTP only).
  2038. //
  2039. EnableWindow(GetDlgItem(hDlg, IDC_USE_PSK), bEnable);
  2040. }
  2041. //+----------------------------------------------------------------------------
  2042. //
  2043. // Function: ProcessWin2kSecurityPopup
  2044. //
  2045. // Synopsis: This function processes messages for the Win2k+ security dialog.
  2046. // This dialog contains configuration UI for all of the advanced
  2047. // settings allowed by Win2k (EAP, PAP, SPAP, etc plus encryption
  2048. // type and vpn strategy).
  2049. //
  2050. // Arguments: HWND hDlg - window handle to the dialog
  2051. // UINT message - the current message to process
  2052. // WPARAM wParam - wParam see individual message type for details
  2053. // LPARAM lParam - lParam see individual message type for details
  2054. //
  2055. // Returns: INT_PTR - TRUE if the message was completely handled
  2056. //
  2057. // History: quintinb Created 03/27/00
  2058. //
  2059. //+----------------------------------------------------------------------------
  2060. INT_PTR APIENTRY ProcessWin2kSecurityPopup(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  2061. {
  2062. static DWORD_PTR HelpId = 0;
  2063. static CDunSetting* pDunSetting = NULL;
  2064. SetDefaultGUIFont(hDlg, message, IDC_ENCRYPTION_TYPE);
  2065. SetDefaultGUIFont(hDlg, message, IDC_EAP_TYPES);
  2066. SetDefaultGUIFont(hDlg, message, IDC_VPN_TYPE);
  2067. if (ProcessHelp(hDlg, message, wParam, lParam, HelpId)) return TRUE;
  2068. switch (message)
  2069. {
  2070. case WM_INITDIALOG:
  2071. if (lParam)
  2072. {
  2073. pDunSetting = (CDunSetting*)lParam;
  2074. //
  2075. // Setup the help ID appropriately
  2076. //
  2077. HelpId = ((pDunSetting->bTunnelDunSetting) ? IDH_VENTRY : IDH_DENTRY);
  2078. //
  2079. // Load and add the strings to the Data Encryption combobox
  2080. //
  2081. LPTSTR pszString;
  2082. for (int i = BASE_ENCRYPT_TYPE_ID; i < (BASE_ENCRYPT_TYPE_ID + NUM_ENCRYPT_TYPES); i++)
  2083. {
  2084. pszString = CmLoadString(g_hInstance, i);
  2085. MYDBGASSERT(pszString);
  2086. if (pszString)
  2087. {
  2088. SendDlgItemMessage(hDlg, IDC_ENCRYPTION_TYPE, CB_ADDSTRING, 0, (LPARAM)pszString);
  2089. CmFree(pszString);
  2090. }
  2091. }
  2092. //
  2093. // Now pick the type of encryption the user has selected
  2094. //
  2095. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_ENCRYPTION_TYPE, CB_SETCURSEL, (WPARAM)MapEncryptionTypeToComboId(pDunSetting->dwEncryptionType), (LPARAM)0));
  2096. //
  2097. // Enumerate all of the available EAP's on the machine
  2098. //
  2099. MYVERIFY(SUCCEEDED(HrAddAvailableEAPsToCombo(hDlg, IDC_EAP_TYPES, pDunSetting)));
  2100. //
  2101. // Select the appropriate EAP as necessary
  2102. //
  2103. SelectAppropriateEAP(hDlg, IDC_EAP_TYPES, pDunSetting);
  2104. //
  2105. // Figure out what authentication protocols the user wants to allow.
  2106. // Note that if we are doing EAP then that is all we allow them to do
  2107. // and the other settings will be ignored. Also note that we don't have
  2108. // UI for w95CHAP but we won't touch the setting if it exists.
  2109. //
  2110. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_ALLOW_PAP, pDunSetting->bAllowPap));
  2111. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_ALLOW_SPAP, pDunSetting->bAllowSpap));
  2112. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_ALLOW_CHAP, pDunSetting->bAllowChap));
  2113. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_ALLOW_MSCHAP, pDunSetting->bAllowMsChap));
  2114. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_ALLOW_MSCHAP2, pDunSetting->bAllowMsChap2));
  2115. if (pDunSetting->bAllowEap)
  2116. {
  2117. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_USE_EAP, IDC_ALLOWED_PROTOCOLS, IDC_USE_EAP));
  2118. }
  2119. else
  2120. {
  2121. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_USE_EAP, IDC_ALLOWED_PROTOCOLS, IDC_ALLOWED_PROTOCOLS));
  2122. }
  2123. //
  2124. // Note that the VPN controls do not exist unless we have a Tunnel Dun Setting and are
  2125. // thus using the tunnel dun setting dialog.
  2126. //
  2127. if (pDunSetting->bTunnelDunSetting)
  2128. {
  2129. //
  2130. // Load and add the Vpn type string to the vpn type combobox
  2131. //
  2132. for (int i = BASE_VPN_TYPE_ID; i < (BASE_VPN_TYPE_ID + NUM_VPN_TYPES); i++)
  2133. {
  2134. pszString = CmLoadString(g_hInstance, i);
  2135. MYDBGASSERT(pszString);
  2136. if (pszString)
  2137. {
  2138. SendDlgItemMessage(hDlg, IDC_VPN_TYPE, CB_ADDSTRING, 0, (LPARAM)pszString);
  2139. CmFree(pszString);
  2140. }
  2141. }
  2142. //
  2143. // Pick the type of vpn strategy the user has selected
  2144. //
  2145. MYDBGASSERT(pDunSetting->dwVpnStrategy != 0);
  2146. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_VPN_TYPE, CB_SETCURSEL, (WPARAM)(pDunSetting->dwVpnStrategy - 1), (LPARAM)0));
  2147. //
  2148. // Fill in the PSK checkbox as needed
  2149. //
  2150. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_USE_PSK, pDunSetting->bUsePskOnWin2kPlus));
  2151. }
  2152. //
  2153. // We only want either the EAP controls or the non-EAP auth controls
  2154. // enabled at once. Thus figure out which to enable/disable
  2155. //
  2156. EnableAppropriateSecurityControls(hDlg);
  2157. EnablePskCheckboxForL2TP(hDlg);
  2158. }
  2159. else
  2160. {
  2161. pDunSetting = NULL;
  2162. CMASSERTMSG(FALSE, TEXT("ProcessWin2kSecurityPopup -- NULL lParam passed to InitDialog. Dialog controls will all be set to off."));
  2163. }
  2164. break;
  2165. case WM_COMMAND:
  2166. switch (LOWORD(wParam))
  2167. {
  2168. case IDC_EAP_PROPERTIES:
  2169. GetEAPDataFromUser(hDlg, IDC_EAP_TYPES);
  2170. break;
  2171. case IDOK:
  2172. MYDBGASSERT(pDunSetting);
  2173. if (pDunSetting)
  2174. {
  2175. //
  2176. // Since we are storing the settings directly in the data struct given to us, first
  2177. // verify that the authentication protocol and the encryption type match up properly.
  2178. // Otherwise a user could modify settings, hit OK, we tell them the settings are
  2179. // inappropriate and they hit cancel. Any settings we modifed before we did the
  2180. // verification would then actually be modified. To avoid that check to make sure
  2181. // we have at least one security protocol checked before continuing.
  2182. //
  2183. BOOL bHasAuthProtocol = FALSE;
  2184. for (int i = BASE_AUTH_CONTROL_ID; i < (BASE_AUTH_CONTROL_ID + NUM_AUTH_TYPES); i++)
  2185. {
  2186. if (BST_CHECKED == IsDlgButtonChecked(hDlg, i))
  2187. {
  2188. bHasAuthProtocol = TRUE;
  2189. break;
  2190. }
  2191. }
  2192. if ((FALSE == bHasAuthProtocol) && (BST_UNCHECKED == IsDlgButtonChecked(hDlg, IDC_USE_EAP)))
  2193. {
  2194. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NEED_AUTH_PROTOCOL, MB_OK | MB_ICONSTOP));
  2195. return TRUE;
  2196. }
  2197. //
  2198. // Next we need to decide whether the user is using EAP or not. Retrieving the data
  2199. // for the EAP they have picked from the combo (if any) will help us decide whether the
  2200. // auth protocol they choose matches up with the encryption settings they asked for.
  2201. //
  2202. EAPData* pEAPData = NULL;
  2203. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_EAP))
  2204. {
  2205. //
  2206. // Get the EAP Type and the data associated with it.
  2207. //
  2208. LRESULT lResult = SendDlgItemMessage(hDlg, IDC_EAP_TYPES, CB_GETCURSEL, 0, 0);
  2209. MYDBGASSERT(CB_ERR != lResult);
  2210. if (CB_ERR != lResult)
  2211. {
  2212. lResult = SendDlgItemMessage(hDlg, IDC_EAP_TYPES, CB_GETITEMDATA, (WPARAM)lResult, 0);
  2213. pEAPData = (EAPData*)lResult;
  2214. if (pEAPData && pEAPData->bMustConfig && (NULL == pEAPData->pCustomAuthData))
  2215. {
  2216. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_EAP_NEEDS_CONFIG, pEAPData->pszFriendlyName);
  2217. if (pszMsg)
  2218. {
  2219. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK | MB_ICONSTOP);
  2220. CmFree(pszMsg);
  2221. }
  2222. else
  2223. {
  2224. CMASSERTMSG(FALSE, TEXT("ProcessWin2kSecurityPopup -- CmMalloc failed!"));
  2225. }
  2226. HWND hButton = GetDlgItem(hDlg, IDC_EAP_PROPERTIES);
  2227. if (hButton && IsWindowEnabled(hButton))
  2228. {
  2229. SetFocus(hButton);
  2230. }
  2231. return TRUE;
  2232. }
  2233. }
  2234. }
  2235. //
  2236. // Now get the encryption type that the user selected. Note that in order to negotiate
  2237. // encryption we must have EAP or some sort of MSCHAP.
  2238. //
  2239. LRESULT lResult = (DWORD)SendDlgItemMessage(hDlg, IDC_ENCRYPTION_TYPE, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2240. DWORD dwTemp = MapComboIdToEncryptionType(lResult);
  2241. MYDBGASSERT(ET_RequireMax != dwTemp); // we should never be setting require max
  2242. if ((ET_Require == dwTemp) || (ET_Optional == dwTemp))
  2243. {
  2244. //
  2245. // If the user is using EAP, then the EAP type they picked must support
  2246. // encryption. Otherwise, the user must not be using EAP and they must
  2247. // be using some sort of MSChap. The following could be expressed more
  2248. // succintly, but there is no sense in confusing the issue.
  2249. //
  2250. BOOL bEncryptionAllowed = FALSE;
  2251. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_EAP))
  2252. {
  2253. if (pEAPData)
  2254. {
  2255. bEncryptionAllowed = pEAPData->bSupportsEncryption;
  2256. }
  2257. }
  2258. else
  2259. {
  2260. bEncryptionAllowed = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_MSCHAP)) ||
  2261. (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_MSCHAP2));
  2262. }
  2263. //
  2264. // Warn the user if he selected one of these three authentication methods,
  2265. // he needs to make a correction since he requires encryption, but we don't
  2266. // want to show a warning when using 'L2TP Only'.
  2267. //
  2268. if ((BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOWED_PROTOCOLS)) &&
  2269. ((BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_PAP)) ||
  2270. (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_SPAP)) ||
  2271. (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_CHAP))))
  2272. {
  2273. DWORD dwVpnStrategyTemp = (DWORD)SendDlgItemMessage(hDlg, IDC_VPN_TYPE, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2274. if (CB_ERR == dwVpnStrategyTemp)
  2275. {
  2276. CMASSERTMSG(FALSE, TEXT("ProcessWin2kSecurityPopup -- CB_ERR returned for VPN strategy."));
  2277. dwVpnStrategyTemp = VS_PptpFirst;
  2278. }
  2279. else
  2280. {
  2281. //
  2282. // Adjust Vpn Strategy because we no longer offer Automatic as a choice
  2283. //
  2284. dwVpnStrategyTemp +=1;
  2285. }
  2286. if (VS_L2tpOnly != dwVpnStrategyTemp)
  2287. {
  2288. if (IDNO == ShowMessage(hDlg, IDS_NEED_EAP_OR_MSCHAP, MB_YESNO | MB_ICONSTOP))
  2289. {
  2290. CheckDlgButton(hDlg, IDC_ALLOW_PAP, FALSE);
  2291. CheckDlgButton(hDlg, IDC_ALLOW_SPAP, FALSE);
  2292. CheckDlgButton(hDlg, IDC_ALLOW_CHAP, FALSE);
  2293. return TRUE;
  2294. }
  2295. }
  2296. }
  2297. else
  2298. {
  2299. if (FALSE == bEncryptionAllowed)
  2300. {
  2301. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_EAP_HAS_NO_ECRYPTION, MB_OK | MB_ICONSTOP));
  2302. return TRUE;
  2303. }
  2304. }
  2305. }
  2306. //
  2307. // Now save the actual settings
  2308. //
  2309. pDunSetting->dwEncryptionType = dwTemp;
  2310. if (pEAPData)
  2311. {
  2312. //
  2313. // Now lets update pDunSetting with the actual data. Note that we are past the
  2314. // last place we could throw an error to the user and thus it is okay to touch
  2315. // the pDunSetting data (even if the user got an error and then hit cancel we will
  2316. // leave their previous data untouched). Note that we don't want to touch the existing
  2317. // data if we don't have the EAP installed because we know that we couldn't have
  2318. // actually changed the data.
  2319. //
  2320. pDunSetting->bAllowEap = TRUE;
  2321. if (FALSE == pEAPData->bNotInstalled)
  2322. {
  2323. CmFree(pDunSetting->pCustomAuthData);
  2324. pDunSetting->dwCustomAuthKey = pEAPData->dwCustomAuthKey;
  2325. pDunSetting->pCustomAuthData = pEAPData->pCustomAuthData;
  2326. pDunSetting->dwCustomAuthDataSize = pEAPData->dwCustomAuthDataSize;
  2327. //
  2328. // Now NULL out the pEapData entry, this saves us from having to
  2329. // allocate mem and copy to pDunSetting but keeps the code
  2330. // that cleans up the EapData structs from freeing our data
  2331. //
  2332. pEAPData->pCustomAuthData = NULL;
  2333. pEAPData->dwCustomAuthDataSize = 0;
  2334. }
  2335. }
  2336. else
  2337. {
  2338. pDunSetting->bAllowEap = FALSE;
  2339. }
  2340. //
  2341. // Get the non-EAP protocols. Note that if the user selected EAP we will clear
  2342. // these before writing them out.
  2343. //
  2344. pDunSetting->bAllowPap = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_PAP));
  2345. pDunSetting->bAllowSpap = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_SPAP));
  2346. pDunSetting->bAllowChap = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_CHAP));
  2347. pDunSetting->bAllowMsChap = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_MSCHAP));
  2348. pDunSetting->bAllowMsChap2 = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_ALLOW_MSCHAP2));
  2349. if (pDunSetting->bTunnelDunSetting)
  2350. {
  2351. pDunSetting->dwVpnStrategy = (DWORD)SendDlgItemMessage(hDlg, IDC_VPN_TYPE, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2352. if (CB_ERR == pDunSetting->dwVpnStrategy)
  2353. {
  2354. CMASSERTMSG(FALSE, TEXT("ProcessWin2kSecurityPopup -- CB_ERR returned for VPN strategy."));
  2355. pDunSetting->dwVpnStrategy = VS_PptpFirst;
  2356. }
  2357. else
  2358. {
  2359. //
  2360. // Adjust Vpn Strategy because we no longer offer Automatic as a choice
  2361. //
  2362. pDunSetting->dwVpnStrategy += 1;
  2363. MYDBGASSERT((pDunSetting->dwVpnStrategy >= VS_PptpOnly) && (pDunSetting->dwVpnStrategy <= VS_L2tpFirst));
  2364. }
  2365. if ((VS_L2tpFirst == pDunSetting->dwVpnStrategy) || (VS_L2tpOnly == pDunSetting->dwVpnStrategy))
  2366. {
  2367. pDunSetting->bUsePskOnWin2kPlus = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_USE_PSK));
  2368. }
  2369. else
  2370. {
  2371. pDunSetting->bUsePskOnWin2kPlus = FALSE;
  2372. }
  2373. }
  2374. }
  2375. FreeEapData(hDlg, IDC_EAP_TYPES);
  2376. EndDialog(hDlg, IDOK);
  2377. break;
  2378. case IDCANCEL:
  2379. FreeEapData(hDlg, IDC_EAP_TYPES);
  2380. EndDialog(hDlg, IDCANCEL);
  2381. break;
  2382. case IDC_USE_EAP:
  2383. MYDBGASSERT(pDunSetting);
  2384. if (pDunSetting)
  2385. {
  2386. SelectAppropriateEAP(hDlg, IDC_EAP_TYPES, pDunSetting);
  2387. }
  2388. case IDC_ALLOWED_PROTOCOLS:
  2389. EnableAppropriateSecurityControls(hDlg);
  2390. break;
  2391. case IDC_EAP_TYPES:
  2392. if (HIWORD(wParam) == CBN_SELCHANGE)
  2393. {
  2394. EnableDisableEapPropertiesButton(hDlg);
  2395. }
  2396. break;
  2397. case IDC_VPN_TYPE:
  2398. if (HIWORD(wParam) == CBN_SELCHANGE)
  2399. {
  2400. EnablePskCheckboxForL2TP(hDlg);
  2401. }
  2402. break;
  2403. default:
  2404. break;
  2405. }
  2406. break;
  2407. }
  2408. return FALSE;
  2409. }
  2410. //+----------------------------------------------------------------------------
  2411. //
  2412. // Function: EnableDisableSecurityButtons
  2413. //
  2414. // Synopsis: This function determines which of the two configure buttons
  2415. // should be enabled. The configure buttons allow the user to
  2416. // configure the security settings of the DUN settings. There is
  2417. // one button for platform independent security settings and one for
  2418. // win2k+ security settings.
  2419. //
  2420. // Arguments: HWND hDlg - window handle to the general property sheet
  2421. //
  2422. // Returns: Nothing
  2423. //
  2424. // History: quintinb Created 03/27/00
  2425. //
  2426. //+----------------------------------------------------------------------------
  2427. void EnableDisableSecurityButtons(HWND hDlg)
  2428. {
  2429. INT_PTR nResult = SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2430. if (CB_ERR == nResult)
  2431. {
  2432. nResult = 0;
  2433. }
  2434. //
  2435. // Disable the Win2k config button if the first selection is chosen
  2436. //
  2437. EnableWindow(GetDlgItem(hDlg, IDC_CONFIG_WIN2K), (0 != nResult));
  2438. //
  2439. // Disable the standard config button if the last selection is chosen
  2440. //
  2441. EnableWindow(GetDlgItem(hDlg, IDC_CONFIG_ALL), (2 != nResult));
  2442. }
  2443. //+----------------------------------------------------------------------------
  2444. //
  2445. // Function: GeneralPropSheetProc
  2446. //
  2447. // Synopsis: This function processes messages for General property sheet of
  2448. // the DUN settings UI. This property sheet holds UI for configuring
  2449. // the name of the DUN setting and dialup scripting.
  2450. //
  2451. // Arguments: HWND hDlg - window handle to the dialog
  2452. // UINT message - the current message to process
  2453. // WPARAM wParam - wParam see individual message type for details
  2454. // LPARAM lParam - lParam see individual message type for details
  2455. //
  2456. // Returns: INT_PTR - TRUE if the message was completely handled
  2457. //
  2458. // History: quintinb Created 03/27/00
  2459. //
  2460. //+----------------------------------------------------------------------------
  2461. INT_PTR APIENTRY GeneralPropSheetProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  2462. {
  2463. NMHDR* pnmHeader = (NMHDR*)lParam;
  2464. INT_PTR nResult;
  2465. static DWORD_PTR HelpId = 0;
  2466. static ListBxList* pListEntry = NULL;
  2467. static CDunSetting* pDunSetting = NULL;
  2468. SetDefaultGUIFont(hDlg, message, IDC_EDIT1);
  2469. SetDefaultGUIFont(hDlg, message, IDC_EDIT2);
  2470. if (ProcessHelp(hDlg, message, wParam, lParam, HelpId)) return TRUE;
  2471. switch (message)
  2472. {
  2473. case WM_INITDIALOG:
  2474. if (lParam)
  2475. {
  2476. PROPSHEETPAGE* pPropSheetPage = (PROPSHEETPAGE*)lParam;
  2477. if (pPropSheetPage->lParam)
  2478. {
  2479. pListEntry = (ListBxList*)pPropSheetPage->lParam;
  2480. pDunSetting = (CDunSetting*)pListEntry->ListBxData;
  2481. if (pListEntry && pDunSetting)
  2482. {
  2483. //
  2484. // Setup the help ID appropriately...
  2485. //
  2486. HelpId = ((pDunSetting->bTunnelDunSetting) ? IDH_VENTRY : IDH_DENTRY);
  2487. if (pListEntry->szName[0])
  2488. {
  2489. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT1), WM_SETTEXT, 0, (LPARAM)pListEntry->szName));
  2490. EnableWindow(GetDlgItem(hDlg, IDC_EDIT1), FALSE); // don't allow the user to edit the name
  2491. }
  2492. //
  2493. // Now lets set the disable file and printer sharing checkbox and the network logon checkbox
  2494. //
  2495. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, pDunSetting->bSecureLocalFiles));
  2496. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK2, pDunSetting->bNetworkLogon));
  2497. if (pDunSetting->szScript[0])
  2498. {
  2499. MYVERIFY(TRUE == SendMessage(GetDlgItem(hDlg, IDC_EDIT2), WM_SETTEXT, 0, (LPARAM)GetName(pDunSetting->szScript)));
  2500. }
  2501. //
  2502. // If this is a VPN DUN setting, then hide the script controls
  2503. //
  2504. if (pDunSetting->bTunnelDunSetting)
  2505. {
  2506. ShowWindow(GetDlgItem(hDlg, IDC_SCRIPT_LABEL), SW_HIDE);
  2507. ShowWindow(GetDlgItem(hDlg, IDC_EDIT2), SW_HIDE);
  2508. ShowWindow(GetDlgItem(hDlg, IDC_BUTTON1), SW_HIDE);
  2509. }
  2510. }
  2511. else
  2512. {
  2513. CMASSERTMSG(FALSE, TEXT("GeneralPropSheetProc -- pListEntry or pDunSetting are NULL"));
  2514. }
  2515. }
  2516. else
  2517. {
  2518. pListEntry = NULL;
  2519. pDunSetting = NULL;
  2520. CMASSERTMSG(FALSE, TEXT("GeneralPropSheetProc -- NULL lParam passed to InitDialog. Dialog controls will all be set to off."));
  2521. }
  2522. }
  2523. else
  2524. {
  2525. pListEntry = NULL;
  2526. pDunSetting = NULL;
  2527. CMASSERTMSG(FALSE, TEXT("GeneralPropSheetProc -- NULL PropSheetPage pointer passed for lParam."));
  2528. }
  2529. break;
  2530. case WM_COMMAND:
  2531. switch (LOWORD(wParam))
  2532. {
  2533. case IDC_BUTTON1: // browse button
  2534. if (pDunSetting)
  2535. {
  2536. UINT uScpFilter = IDS_SCPFILTER;
  2537. TCHAR* szScpMask = TEXT("*.scp");
  2538. MYVERIFY(0 != DoBrowse(hDlg, &uScpFilter, &szScpMask, 1, IDC_EDIT2,
  2539. TEXT("scp"), pDunSetting->szScript));
  2540. }
  2541. break;
  2542. }
  2543. break;
  2544. case WM_NOTIFY:
  2545. if (NULL == pnmHeader)
  2546. {
  2547. return FALSE;
  2548. }
  2549. switch (pnmHeader->code)
  2550. {
  2551. case PSN_APPLY:
  2552. if (pListEntry && pDunSetting)
  2553. {
  2554. //
  2555. // Get the name of the entry
  2556. //
  2557. nResult = GetTextFromControl(hDlg, IDC_EDIT1, pListEntry->szName, MAX_PATH, TRUE); // bDisplayError == TRUE
  2558. if (-1 == nResult)
  2559. {
  2560. //
  2561. // If we read in a string we cannot convert from the cms file and then the user editted the entry
  2562. // then the edit control may contain "bad" data but the user won't be able to edit it. Since this
  2563. // is extremely unlikely we won't add special handling for it other than to prevent the focus from
  2564. // being set to a disabled control.
  2565. //
  2566. if (IsWindowEnabled(GetDlgItem(hDlg, IDC_EDIT1)))
  2567. {
  2568. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  2569. }
  2570. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  2571. return TRUE;
  2572. }
  2573. //
  2574. // Now, let's trim the name and make sure it isn't empty
  2575. //
  2576. CmStrTrim(pListEntry->szName);
  2577. if ((TEXT('\0') == pListEntry->szName[0]) || (0 == nResult))
  2578. {
  2579. ShowMessage(hDlg, IDS_NEED_DUN_NAME, MB_OK);
  2580. if (IsWindowEnabled(GetDlgItem(hDlg, IDC_EDIT1)))
  2581. {
  2582. SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
  2583. }
  2584. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  2585. return TRUE;
  2586. }
  2587. //
  2588. // Get the values for the Secure local files and the network logon checkboxes
  2589. //
  2590. pDunSetting->bSecureLocalFiles = IsDlgButtonChecked(hDlg, IDC_CHECK1);
  2591. pDunSetting->bNetworkLogon = IsDlgButtonChecked(hDlg, IDC_CHECK2);
  2592. //
  2593. // Get and verify the script
  2594. //
  2595. if (FALSE == pDunSetting->bTunnelDunSetting)
  2596. {
  2597. if (!VerifyFile(hDlg, IDC_EDIT2, pDunSetting->szScript, TRUE))
  2598. {
  2599. SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
  2600. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  2601. return TRUE;
  2602. }
  2603. }
  2604. break;
  2605. }
  2606. }
  2607. break;
  2608. default:
  2609. return FALSE;
  2610. }
  2611. return FALSE;
  2612. }
  2613. //+----------------------------------------------------------------------------
  2614. //
  2615. // Function: SecurityPropSheetProc
  2616. //
  2617. // Synopsis: This function processes messages for Security property sheet of
  2618. // the DUN settings UI. This property sheet holds UI for configuring
  2619. // how the user wants their security settings applied.
  2620. //
  2621. // Arguments: HWND hDlg - window handle to the dialog
  2622. // UINT message - the current message to process
  2623. // WPARAM wParam - wParam see individual message type for details
  2624. // LPARAM lParam - lParam see individual message type for details
  2625. //
  2626. // Returns: INT_PTR - TRUE if the message was completely handled
  2627. //
  2628. // History: quintinb Created 03/27/00
  2629. //
  2630. //+----------------------------------------------------------------------------
  2631. INT_PTR APIENTRY SecurityPropSheetProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  2632. {
  2633. NMHDR* pnmHeader = (NMHDR*)lParam;
  2634. INT_PTR nResult;
  2635. static DWORD_PTR HelpId = 0;
  2636. static ListBxList* pListEntry = NULL;
  2637. static CDunSetting* pDunSetting = NULL;
  2638. static fUpdateVPNStrategy = TRUE;
  2639. SetDefaultGUIFont(hDlg, message, IDC_COMBO1);
  2640. if (ProcessHelp(hDlg, message, wParam, lParam, HelpId)) return TRUE;
  2641. switch (message)
  2642. {
  2643. case WM_INITDIALOG:
  2644. if (lParam)
  2645. {
  2646. PROPSHEETPAGE* pPropSheetPage = (PROPSHEETPAGE*)lParam;
  2647. fUpdateVPNStrategy = TRUE;
  2648. if (pPropSheetPage->lParam)
  2649. {
  2650. pListEntry = (ListBxList*)pPropSheetPage->lParam;
  2651. pDunSetting = (CDunSetting*)pListEntry->ListBxData;
  2652. if (pListEntry && pDunSetting) // this will give a big visual clue that something is wrong
  2653. {
  2654. //
  2655. // Setup the help ID appropriately
  2656. //
  2657. HelpId = ((pDunSetting->bTunnelDunSetting) ? IDH_VENTRY : IDH_DENTRY);
  2658. //
  2659. // Load and set the strings for the combo box
  2660. //
  2661. LPTSTR pszString;
  2662. for (int i = BASE_SECURITY_SCENARIO_ID; i < (BASE_SECURITY_SCENARIO_ID + NUM_SECURITY_SCENARIOS); i++)
  2663. {
  2664. pszString = CmLoadString(g_hInstance, i);
  2665. MYDBGASSERT(pszString);
  2666. if (pszString)
  2667. {
  2668. SendDlgItemMessage(hDlg, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)pszString);
  2669. CmFree(pszString);
  2670. }
  2671. }
  2672. //
  2673. // Now figure out which selection to pick
  2674. //
  2675. MYVERIFY(CB_ERR != SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, (WPARAM)(pDunSetting->iHowToHandleSecuritySettings), (LPARAM)0));
  2676. EnableDisableSecurityButtons(hDlg);
  2677. }
  2678. else
  2679. {
  2680. CMASSERTMSG(FALSE, TEXT("SecurityPropSheetProc -- pListEntry or pDunSetting is NULL"));
  2681. }
  2682. }
  2683. else
  2684. {
  2685. pListEntry = NULL;
  2686. pDunSetting = NULL;
  2687. CMASSERTMSG(FALSE, TEXT("SecurityPropSheetProc -- NULL lParam passed to InitDialog. Dialog controls will all be set to off."));
  2688. }
  2689. }
  2690. else
  2691. {
  2692. pListEntry = NULL;
  2693. pDunSetting = NULL;
  2694. CMASSERTMSG(FALSE, TEXT("SecurityPropSheetProc -- NULL PropSheetPage pointer passed for lParam."));
  2695. }
  2696. break;
  2697. case WM_COMMAND:
  2698. switch (LOWORD(wParam))
  2699. {
  2700. case IDC_CONFIG_ALL:
  2701. {
  2702. UINT uDialogId = pDunSetting->bTunnelDunSetting ? IDD_VPN_SECURITY_POPUP: IDD_DUN_SECURITY_POPUP;
  2703. nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(uDialogId), hDlg, ProcessSecurityPopup, (LPARAM)pDunSetting);
  2704. }
  2705. break;
  2706. case IDC_CONFIG_WIN2K:
  2707. if (pDunSetting)
  2708. {
  2709. UINT uDialogId = pDunSetting->bTunnelDunSetting ? IDD_WIN2K_SECURITY_TUNNEL_POPUP: IDD_WIN2K_SECURITY_POPUP;
  2710. nResult = DialogBoxParam(NULL, MAKEINTRESOURCE(uDialogId), hDlg, ProcessWin2kSecurityPopup, (LPARAM)pDunSetting);
  2711. if (IDOK == nResult)
  2712. {
  2713. fUpdateVPNStrategy = FALSE;
  2714. }
  2715. }
  2716. break;
  2717. case IDC_COMBO1: // how does the user want the security settings applied
  2718. if (HIWORD(wParam) == CBN_SELCHANGE)
  2719. {
  2720. EnableDisableSecurityButtons(hDlg);
  2721. }
  2722. break;
  2723. }
  2724. break;
  2725. case WM_NOTIFY:
  2726. if (NULL == pnmHeader)
  2727. {
  2728. return FALSE;
  2729. }
  2730. switch (pnmHeader->code)
  2731. {
  2732. case PSN_APPLY:
  2733. if (pListEntry && pDunSetting)
  2734. {
  2735. //
  2736. // Figure out if the Admin wanted us to enforce the Win2k custom security flags or not
  2737. //
  2738. pDunSetting->iHowToHandleSecuritySettings = (int)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  2739. break;
  2740. }
  2741. }
  2742. break;
  2743. default:
  2744. return FALSE;
  2745. }
  2746. return FALSE;
  2747. }
  2748. //+----------------------------------------------------------------------------
  2749. //
  2750. // Function: CreateNetworkingEntryPropertySheet
  2751. //
  2752. // Synopsis: This function creates and launches the Networking DUN entry
  2753. // property sheet which allows networking entry configuration.
  2754. //
  2755. // Arguments: HINSTANCE hInstance - instance handle for resources
  2756. // HWND hWizard - window handle of the current CMAK wizard page
  2757. // LPARAM lParam - initialization parameter passed to each propsheet page
  2758. // BOOL bEdit - whether we are launching the property sheet to edit
  2759. // an existing entry or add a new one (affects the title).
  2760. //
  2761. // Returns: int - returns a positive value if successful, -1 on error
  2762. //
  2763. // History: quintinb Created 03/27/00
  2764. //
  2765. //+----------------------------------------------------------------------------
  2766. INT_PTR CreateNetworkingEntryPropertySheet(HINSTANCE hInstance, HWND hWizard, LPARAM lParam, BOOL bEdit, BOOL bUseVpnTitle)
  2767. {
  2768. PROPSHEETPAGE psp[3];
  2769. PROPSHEETHEADER psh = {0};
  2770. LPTSTR pszCaption = NULL;
  2771. INT_PTR iReturn = -1;
  2772. UINT uTitleStringId;
  2773. //
  2774. // Check the params, note that lParam could be NULL
  2775. //
  2776. if ((NULL == hInstance) || (NULL == hWizard))
  2777. {
  2778. CMASSERTMSG(FALSE, TEXT("CreateNetworkingEntryPropertySheet -- Invalid Parameter passed."));
  2779. goto exit;
  2780. }
  2781. //
  2782. // Fill in the property page structures
  2783. //
  2784. for (int i = 0; i < 3; i++)
  2785. {
  2786. psp[i].dwSize = sizeof(psp[0]);
  2787. psp[i].dwFlags = PSP_HASHELP;
  2788. psp[i].hInstance = hInstance;
  2789. psp[i].lParam = lParam;
  2790. }
  2791. psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
  2792. psp[1].pszTemplate = MAKEINTRESOURCE(IDD_TCPIP_SETTINGS);
  2793. psp[2].pszTemplate = MAKEINTRESOURCE(IDD_SECURITY);
  2794. psp[0].pfnDlgProc = GeneralPropSheetProc;
  2795. psp[1].pfnDlgProc = TcpIpPropSheetProc;
  2796. psp[2].pfnDlgProc = SecurityPropSheetProc;
  2797. //
  2798. // Load the caption
  2799. //
  2800. uTitleStringId = bUseVpnTitle ? BASE_VPN_ENTRY_TITLE : BASE_DUN_ENTRY_TITLE;
  2801. if (bEdit)
  2802. {
  2803. uTitleStringId = uTitleStringId + EDIT_INCREMENT;
  2804. }
  2805. else
  2806. {
  2807. uTitleStringId = uTitleStringId + NEW_INCREMENT;
  2808. }
  2809. pszCaption = CmLoadString(hInstance, uTitleStringId);
  2810. if (NULL == pszCaption)
  2811. {
  2812. CMASSERTMSG(FALSE, TEXT("CreateNetworkingEntryPropertySheet -- CmLoadString failed trying to load the prop sheet title."));
  2813. goto exit;
  2814. }
  2815. //
  2816. // Fill in the property sheet header
  2817. //
  2818. psh.dwSize = sizeof(PROPSHEETHEADER);
  2819. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_HASHELP | PSH_NOCONTEXTHELP;
  2820. psh.hwndParent = hWizard;
  2821. psh.pszCaption = pszCaption;
  2822. psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
  2823. psh.ppsp = (LPCPROPSHEETPAGE) &psp[0];
  2824. //
  2825. // Launch the property sheet
  2826. //
  2827. iReturn = PropertySheet(&psh);
  2828. if (-1 == iReturn)
  2829. {
  2830. CMTRACE1(TEXT("CreateNetworkingEntryPropertySheet -- PropertySheet called failed, GLE %d"), GetLastError());
  2831. }
  2832. exit:
  2833. CmFree(pszCaption);
  2834. return iReturn;
  2835. }
  2836. //+----------------------------------------------------------------------------
  2837. //
  2838. // Function: OnProcessDunEntriesAdd
  2839. //
  2840. // Synopsis: This function is called when the Add button on the DUN entries
  2841. // page is pressed. It's job is to create a new CDunSetting
  2842. // structure and a new ListBox record and then launch the networking
  2843. // entries property page with this newly created DUN entry. If the
  2844. // user hits OK on the property sheet then this newly created entry
  2845. // is added to the DUN entry linked list. If the user hits cancel
  2846. // the entry is freed and never added to the list.
  2847. //
  2848. // Arguments: HINSTANCE hInstance - instance handle to load resources
  2849. // HWND hDlg - window handle of the DUN entries wizard page
  2850. // UINT uListCtrlId - control ID of the list containing the DUN entries
  2851. // ListBxStruct** pHeadDns - head of the dun entry list
  2852. // ListBxStruct** pTailDns - tail of the dun entry list
  2853. // BOOL bCreateTunnelEntry - whether we are adding a tunnel entry or not
  2854. // LPCTSTR pszLongServiceName - the long service name of the profile
  2855. // LPCTSTR pszCmsFile - CMS file to get the default/VPN DUN entry names from
  2856. //
  2857. // Returns: Nothing
  2858. //
  2859. // History: quintinb Created 03/27/00
  2860. //
  2861. //+----------------------------------------------------------------------------
  2862. void OnProcessDunEntriesAdd(HINSTANCE hInstance, HWND hDlg, UINT uListCtrlId, ListBxStruct** pHeadDns, ListBxStruct** pTailDns,
  2863. BOOL bCreateTunnelEntry, LPCTSTR pszLongServiceName, LPCTSTR pszCmsFile)
  2864. {
  2865. //
  2866. // Check the input params, make sure that *pHeadDns / *pTailDns are both NULL or both non-NULL
  2867. //
  2868. if (hInstance && hDlg && pHeadDns && pTailDns && (FALSE == ((NULL == *pHeadDns) ^ (NULL == *pTailDns))))
  2869. {
  2870. //
  2871. // We want to create an empty ListBxStruct and an new CDunSetting. This keeps all of the initialization
  2872. // logic in the CDunSetting constructor and keeps the dialog procedures very simple.
  2873. //
  2874. ListBxStruct* pLinkedListItem = (ListBxStruct*)CmMalloc(sizeof(ListBxStruct));
  2875. CDunSetting* pDunSetting = new CDunSetting(bCreateTunnelEntry);
  2876. INT_PTR iPropSheetReturnValue = -1;
  2877. if ((NULL == pDunSetting) || (NULL == pLinkedListItem))
  2878. {
  2879. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesAdd -- CmMalloc and/or new failed."));
  2880. CmFree(pDunSetting);
  2881. CmFree(pLinkedListItem);
  2882. return;
  2883. }
  2884. //
  2885. // Now call the property sheet
  2886. //
  2887. BOOL bExitLoop = FALSE;
  2888. do
  2889. {
  2890. pLinkedListItem->ListBxData = (void*)pDunSetting;
  2891. iPropSheetReturnValue = CreateNetworkingEntryPropertySheet(hInstance, hDlg, (LPARAM)pLinkedListItem, FALSE, pDunSetting->bTunnelDunSetting); // bEdit == FALSE
  2892. if (IDOK == iPropSheetReturnValue)
  2893. {
  2894. //
  2895. // Search the list to make sure that the user didn't give us the name of an existing
  2896. // DUN entry. If they did, then we should prompt them for overwrite.
  2897. //
  2898. ListBxStruct* pCurrent = *pHeadDns;
  2899. while (pCurrent)
  2900. {
  2901. if (0 == lstrcmpi(pCurrent->szName, pLinkedListItem->szName))
  2902. {
  2903. //
  2904. // Then we have a dup, lets prompt the user
  2905. //
  2906. LPTSTR pszMsg = CmFmtMsg(hInstance, IDS_DUN_NAME_EXISTS, pLinkedListItem->szName);
  2907. //
  2908. // Make sure to blank out the name. Two things can happen here. Either, the name
  2909. // wasn't what the user wanted and they want to change it. In that case, we blank the
  2910. // name so that when the dialog comes back up to edit, we won't gray out the name control
  2911. // as we normally do for an edit. Since the name was invalid this is an additional clue
  2912. // to the user as to what was wrong. If the name was valid and the user means to do a rename,
  2913. // then we are going to free pLinkedListItem anyway and blanking the name means nothing. However,
  2914. // if we fail to allocate pszMsg, then blanking the name will at least allow the dialog to come back
  2915. // up with a edittable name and the user may be able to fix the problem ... unlikely
  2916. // if mem allocs are failing but better than leaving the user truly hosed.
  2917. //
  2918. pLinkedListItem->szName[0] = TEXT('\0');
  2919. if (pszMsg)
  2920. {
  2921. int iResult = MessageBox(hDlg, pszMsg, g_szAppTitle, MB_YESNO);
  2922. CmFree(pszMsg);
  2923. //
  2924. // If the user said yes, lets replace the existing entry and get out of here, otherwise
  2925. // we want to loop again.
  2926. //
  2927. if (IDYES == iResult)
  2928. {
  2929. CDunSetting* pOldDunSetting = (CDunSetting*)pCurrent->ListBxData;
  2930. delete pOldDunSetting;
  2931. pCurrent->ListBxData = pDunSetting;
  2932. CmFree(pLinkedListItem);
  2933. RefreshDnsList(hInstance, hDlg, uListCtrlId, *pHeadDns, pszLongServiceName, pszCmsFile, pCurrent->szName);
  2934. bExitLoop = TRUE;
  2935. }
  2936. break;
  2937. }
  2938. }
  2939. pCurrent = pCurrent->next;
  2940. }
  2941. //
  2942. // If we didn't find a duplicate, then add the item to the list as usual,
  2943. // making sure that pLinkedListItem->next is NULL so that the list is terminated.
  2944. //
  2945. if (NULL == pCurrent)
  2946. {
  2947. pLinkedListItem->next = NULL; // make sure our list is terminated
  2948. if (*pHeadDns)
  2949. {
  2950. (*pTailDns)->next = pLinkedListItem;
  2951. }
  2952. else
  2953. {
  2954. *pHeadDns = pLinkedListItem;
  2955. }
  2956. *pTailDns = pLinkedListItem;
  2957. RefreshDnsList(hInstance, hDlg, uListCtrlId, *pHeadDns, pszLongServiceName, pszCmsFile, pLinkedListItem->szName);
  2958. bExitLoop = TRUE;
  2959. }
  2960. }
  2961. else
  2962. {
  2963. bExitLoop = TRUE;
  2964. CmFree(pLinkedListItem);
  2965. delete pDunSetting;
  2966. }
  2967. } while (!bExitLoop);
  2968. }
  2969. else
  2970. {
  2971. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesAdd -- Invalid parameter passed."));
  2972. }
  2973. }
  2974. //+----------------------------------------------------------------------------
  2975. //
  2976. // Function: OnProcessDunEntriesEdit
  2977. //
  2978. // Synopsis: This function is called when the Edit button on the DUN entries
  2979. // page is pressed. It's job is to find the ListBox and CDunSetting
  2980. // structures for the item currently selected in the listbox and then
  2981. // launch the networking entries property page with this DUN entry.
  2982. // The property sheet itself takes care of only changing the Dun Entry
  2983. // if Okay is pressed. Canceling should leave the entry unchanged.
  2984. //
  2985. // Arguments: HINSTANCE hInstance - instance handle to load resources
  2986. // HWND hDlg - window handle of the DUN entries wizard page
  2987. // UINT uListCtrlId - control ID of the list containing the DUN entries
  2988. // ListBxStruct** pHeadDns - head of the dun entry list
  2989. // ListBxStruct** pTailDns - tail of the dun entry list
  2990. // LPCTSTR pszLongServiceName - the long service name of the profile
  2991. // LPCTSTR pszCmsFile - CMS file to get the default/VPN DUN entry names from
  2992. //
  2993. // Returns: Nothing
  2994. //
  2995. // History: quintinb Created 03/27/00
  2996. //
  2997. //+----------------------------------------------------------------------------
  2998. void OnProcessDunEntriesEdit(HINSTANCE hInstance, HWND hDlg, UINT uListCtrlId, ListBxStruct** pHeadDns,
  2999. ListBxStruct** pTailDns, LPCTSTR pszLongServiceName, LPCTSTR pszCmsFile)
  3000. {
  3001. LPTSTR pszTunnelDunDisplayString = NULL;
  3002. LPTSTR pszDefaultDunDisplayString = NULL;
  3003. TCHAR szTunnelDunName[MAX_PATH+1] = TEXT("");
  3004. TCHAR szDefaultDunName[MAX_PATH+1] = TEXT("");
  3005. LPTSTR pszNameOfItemToEdit = NULL;
  3006. //
  3007. // Check the input params, make sure that *pHeadDns / *pTailDns are both NULL or both non-NULL
  3008. //
  3009. if (hInstance && hDlg && pHeadDns && pTailDns && (FALSE == ((NULL == *pHeadDns) ^ (NULL == *pTailDns))))
  3010. {
  3011. INT_PTR iPropSheetReturnValue = -1;
  3012. TCHAR szNameOfItemToEdit[MAX_PATH+1];
  3013. ListBxStruct* pItemToEdit = NULL;
  3014. //
  3015. // Lets get the current selection from the listbox
  3016. //
  3017. INT_PTR nResult = SendDlgItemMessage(hDlg, uListCtrlId, LB_GETCURSEL, 0, (LPARAM)0);
  3018. if (LB_ERR == nResult)
  3019. {
  3020. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  3021. }
  3022. else
  3023. {
  3024. if (LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult, (LPARAM)szNameOfItemToEdit))
  3025. {
  3026. //
  3027. // Get the name of the Tunnel Dun setting
  3028. //
  3029. MYVERIFY(0 != GetTunnelDunSettingName(pszCmsFile, pszLongServiceName, szTunnelDunName, CELEMS(szTunnelDunName)));
  3030. //
  3031. // Get the name of the default Dun setting
  3032. //
  3033. MYVERIFY(0 != GetDefaultDunSettingName(pszCmsFile, pszLongServiceName, szDefaultDunName, CELEMS(szDefaultDunName)));
  3034. //
  3035. // If we have the default DUN entry text or the default VPN entry text then we want
  3036. // to use the real item names for these instead of the text we inserted for
  3037. // the user to read.
  3038. //
  3039. pszTunnelDunDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, szTunnelDunName);
  3040. pszDefaultDunDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, szDefaultDunName);
  3041. MYDBGASSERT(pszTunnelDunDisplayString && pszDefaultDunDisplayString);
  3042. if (pszTunnelDunDisplayString && pszDefaultDunDisplayString)
  3043. {
  3044. if (0 == lstrcmpi(pszTunnelDunDisplayString, szNameOfItemToEdit))
  3045. {
  3046. pszNameOfItemToEdit = szTunnelDunName;
  3047. }
  3048. else if (0 == lstrcmpi(pszDefaultDunDisplayString, szNameOfItemToEdit))
  3049. {
  3050. pszNameOfItemToEdit = szDefaultDunName;
  3051. }
  3052. else
  3053. {
  3054. pszNameOfItemToEdit = szNameOfItemToEdit;
  3055. }
  3056. //
  3057. // Now find the entry in the list
  3058. //
  3059. if (FindListItemByName(pszNameOfItemToEdit, *pHeadDns, &pItemToEdit))
  3060. {
  3061. //
  3062. // Finally call the property sheet
  3063. //
  3064. CDunSetting* pDunSetting = ((CDunSetting*)(pItemToEdit->ListBxData));
  3065. BOOL bTunnelSetting = FALSE;
  3066. if (pDunSetting)
  3067. {
  3068. bTunnelSetting = pDunSetting->bTunnelDunSetting;
  3069. }
  3070. iPropSheetReturnValue = CreateNetworkingEntryPropertySheet(hInstance, hDlg, (LPARAM)pItemToEdit, TRUE, bTunnelSetting); // bEdit == TRUE
  3071. if (IDOK == iPropSheetReturnValue)
  3072. {
  3073. RefreshDnsList(hInstance, hDlg, uListCtrlId, *pHeadDns, pszLongServiceName, pszCmsFile, pItemToEdit->szName);
  3074. }
  3075. }
  3076. else
  3077. {
  3078. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesEdit -- FindListItemByName couldn't find the item in the list."));
  3079. }
  3080. }
  3081. }
  3082. else
  3083. {
  3084. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesEdit -- LB_GETTEXT returned an error."));
  3085. }
  3086. }
  3087. }
  3088. else
  3089. {
  3090. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesEdit -- Invalid parameter passed."));
  3091. }
  3092. CmFree(pszDefaultDunDisplayString);
  3093. CmFree(pszTunnelDunDisplayString);
  3094. }
  3095. //+----------------------------------------------------------------------------
  3096. //
  3097. // Function: OnProcessDunEntriesDelete
  3098. //
  3099. // Synopsis: This function is called when the Delete button on the DUN entries
  3100. // page is pressed. It's job is to find the ListBox and CDunSetting
  3101. // structures for the item currently selected in the listbox and then
  3102. // remove this item from the DUN entries linked list.
  3103. //
  3104. // Arguments: HINSTANCE hInstance - instance handle to load resources
  3105. // HWND hDlg - window handle of the DUN entries wizard page
  3106. // UINT uListCtrlId - control ID of the list containing the DUN entries
  3107. // ListBxStruct** pHeadDns - head of the dun entry list
  3108. // ListBxStruct** pTailDns - tail of the dun entry list
  3109. // LPCTSTR pszLongServiceName - the long service name of the profile
  3110. // LPCTSTR pszCmsFile - CMS file to get the default/VPN DUN entry names from
  3111. //
  3112. // Returns: Nothing
  3113. //
  3114. // History: quintinb Created 03/27/00
  3115. //
  3116. //+----------------------------------------------------------------------------
  3117. void OnProcessDunEntriesDelete(HINSTANCE hInstance, HWND hDlg, UINT uListCtrlId, ListBxStruct** pHeadDns,
  3118. ListBxStruct** pTailDns, LPCTSTR pszLongServiceName, LPCTSTR pszCmsFile)
  3119. {
  3120. //
  3121. // Check the input params, make sure that *pHeadDns / *pTailDns are both NULL or both non-NULL
  3122. //
  3123. if (hInstance && hDlg && pHeadDns && pTailDns && (FALSE == ((NULL == *pHeadDns) ^ (NULL == *pTailDns))))
  3124. {
  3125. TCHAR szNameOfItemToDelete[MAX_PATH+1];
  3126. //
  3127. // Lets get the current selection from the listbox
  3128. //
  3129. INT_PTR nResult = SendDlgItemMessage(hDlg, uListCtrlId, LB_GETCURSEL, 0, (LPARAM)0);
  3130. if (LB_ERR == nResult)
  3131. {
  3132. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_NOSELECTION, MB_OK));
  3133. }
  3134. else
  3135. {
  3136. if (LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, (WPARAM)nResult, (LPARAM)szNameOfItemToDelete))
  3137. {
  3138. //
  3139. // Now find the entry in the list
  3140. //
  3141. ListBxStruct* pCurrent = *pHeadDns;
  3142. ListBxStruct* pFollower = NULL;
  3143. while (pCurrent)
  3144. {
  3145. if (0 == lstrcmpi(szNameOfItemToDelete, pCurrent->szName))
  3146. {
  3147. //
  3148. // We found the item to delete
  3149. //
  3150. if (pFollower)
  3151. {
  3152. pFollower->next = pCurrent->next;
  3153. CDunSetting* pDunSetting = (CDunSetting*)pCurrent->ListBxData;
  3154. CmFree(pDunSetting);
  3155. CmFree(pCurrent);
  3156. //
  3157. // We want to continue to the end of the list so that
  3158. // we can set the tail pointer appropriately. Thus
  3159. // leave pFollower on the item it was on and update
  3160. // pCurrent to the next item in the list, if it is NULL
  3161. // then we will stop here.
  3162. //
  3163. pCurrent = pFollower->next;
  3164. }
  3165. else
  3166. {
  3167. //
  3168. // It is the first item in the list
  3169. //
  3170. *pHeadDns = (*pHeadDns)->next;
  3171. CDunSetting* pDunSetting = (CDunSetting*)pCurrent->ListBxData;
  3172. CmFree(pDunSetting);
  3173. CmFree(pCurrent);
  3174. //
  3175. // We want to go to the end of the list to find the tail pointer
  3176. // so reset pCurrent to the beginning of the list.
  3177. //
  3178. pCurrent = *pHeadDns;
  3179. }
  3180. //
  3181. // Don't forget to delete it from the CMS file itself
  3182. //
  3183. EraseNetworkingSections(szNameOfItemToDelete, pszCmsFile);
  3184. //
  3185. // Refresh the Dns list
  3186. //
  3187. RefreshDnsList(hInstance, hDlg, uListCtrlId, *pHeadDns, pszLongServiceName, pszCmsFile, NULL);
  3188. }
  3189. else
  3190. {
  3191. pFollower = pCurrent;
  3192. pCurrent = pCurrent->next;
  3193. }
  3194. }
  3195. //
  3196. // Reset the tail pointer to the last item in the list
  3197. //
  3198. *pTailDns = pFollower;
  3199. }
  3200. }
  3201. }
  3202. else
  3203. {
  3204. CMASSERTMSG(FALSE, TEXT("OnProcessDunEntriesDelete -- Invalid parameter passed."));
  3205. }
  3206. }
  3207. //+----------------------------------------------------------------------------
  3208. //
  3209. // Function: EnableDisableIpAddressControls
  3210. //
  3211. // Synopsis: This function enables or disables the IP address controls for
  3212. // the static IP address and for the Wins and DNS server addresses
  3213. // depending on the state of the enable/disable radio buttons.
  3214. //
  3215. // Arguments: HWND hDlg - window handle of the TCP/IP settings dialog
  3216. //
  3217. // Returns: Nothing
  3218. //
  3219. // History: quintinb Created 03/27/00
  3220. //
  3221. //+----------------------------------------------------------------------------
  3222. void EnableDisableIpAddressControls(HWND hDlg)
  3223. {
  3224. //
  3225. // Next Enable/Disable the Wins and DNS address controls
  3226. //
  3227. BOOL bCheckedState = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RADIO2));
  3228. EnableWindow(GetDlgItem(hDlg, IDC_PRIMARY_DNS), bCheckedState);
  3229. EnableWindow(GetDlgItem(hDlg, IDC_LABEL_DNS), bCheckedState);
  3230. EnableWindow(GetDlgItem(hDlg, IDC_SECONDARY_DNS), bCheckedState);
  3231. EnableWindow(GetDlgItem(hDlg, IDC_LABEL_DNS2), bCheckedState);
  3232. EnableWindow(GetDlgItem(hDlg, IDC_PRIMARY_WINS), bCheckedState);
  3233. EnableWindow(GetDlgItem(hDlg, IDC_LABEL_WINS), bCheckedState);
  3234. EnableWindow(GetDlgItem(hDlg, IDC_SECONDARY_WINS), bCheckedState);
  3235. EnableWindow(GetDlgItem(hDlg, IDC_LABEL_WINS2), bCheckedState);
  3236. }
  3237. //+----------------------------------------------------------------------------
  3238. //
  3239. // Function: TcpIpPropSheetProc
  3240. //
  3241. // Synopsis: This function processes messages for TCP/IP Settings property sheet.
  3242. //
  3243. // Arguments: HWND hDlg - window handle to the dialog
  3244. // UINT message - the current message to process
  3245. // WPARAM wParam - wParam see individual message type for details
  3246. // LPARAM lParam - lParam see individual message type for details
  3247. //
  3248. // Returns: INT_PTR - TRUE if the message was completely handled
  3249. //
  3250. // History: quintinb Created 03/27/00
  3251. //
  3252. //+----------------------------------------------------------------------------
  3253. INT_PTR APIENTRY TcpIpPropSheetProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  3254. {
  3255. NMHDR* pnmHeader = (NMHDR*)lParam;
  3256. static DWORD_PTR HelpId = 0;
  3257. static ListBxList* pListEntry = NULL;
  3258. static CDunSetting* pDunSetting = NULL;
  3259. if (ProcessHelp(hDlg, message, wParam, lParam, HelpId)) return TRUE;
  3260. switch (message)
  3261. {
  3262. case WM_INITDIALOG:
  3263. if (lParam)
  3264. {
  3265. PROPSHEETPAGE* pPropSheetPage = (PROPSHEETPAGE*)lParam;
  3266. if (pPropSheetPage->lParam)
  3267. {
  3268. pListEntry = (ListBxList*)pPropSheetPage->lParam;
  3269. pDunSetting = (CDunSetting*)pListEntry->ListBxData;
  3270. UINT uCrtlToSet;
  3271. if (pListEntry && pDunSetting)
  3272. {
  3273. //
  3274. // Setup the help ID appropriately
  3275. //
  3276. HelpId = ((pDunSetting->bTunnelDunSetting) ? IDH_VENTRY : IDH_DENTRY);
  3277. //
  3278. // Init the WINS and DNS IP address controls and the radio buttons specifying
  3279. // whether the user chose to give us addresses or not.
  3280. //
  3281. if (pDunSetting->dwPrimaryDns || pDunSetting->dwSecondaryDns || pDunSetting->dwPrimaryWins || pDunSetting->dwSecondaryWins)
  3282. {
  3283. uCrtlToSet = IDC_RADIO2;
  3284. SendDlgItemMessage(hDlg, IDC_PRIMARY_DNS, IPM_SETADDRESS, (WPARAM)0, (LPARAM)(pDunSetting->dwPrimaryDns));
  3285. SendDlgItemMessage(hDlg, IDC_SECONDARY_DNS, IPM_SETADDRESS, (WPARAM)0, (LPARAM)(pDunSetting->dwSecondaryDns));
  3286. SendDlgItemMessage(hDlg, IDC_PRIMARY_WINS, IPM_SETADDRESS, (WPARAM)0, (LPARAM)(pDunSetting->dwPrimaryWins));
  3287. SendDlgItemMessage(hDlg, IDC_SECONDARY_WINS, IPM_SETADDRESS, (WPARAM)0, (LPARAM)(pDunSetting->dwSecondaryWins));
  3288. }
  3289. else
  3290. {
  3291. uCrtlToSet = IDC_RADIO1;
  3292. SendDlgItemMessage(hDlg, IDC_PRIMARY_DNS, IPM_CLEARADDRESS, (WPARAM)0, (LPARAM)0);
  3293. SendDlgItemMessage(hDlg, IDC_SECONDARY_DNS, IPM_CLEARADDRESS, (WPARAM)0, (LPARAM)0);
  3294. SendDlgItemMessage(hDlg, IDC_PRIMARY_WINS, IPM_CLEARADDRESS, (WPARAM)0, (LPARAM)0);
  3295. SendDlgItemMessage(hDlg, IDC_SECONDARY_WINS, IPM_CLEARADDRESS, (WPARAM)0, (LPARAM)0);
  3296. }
  3297. MYVERIFY(0 != CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, uCrtlToSet));
  3298. //
  3299. // Finally set the checkboxes for IP header compression and whether to use
  3300. // the remote gateway or not.
  3301. //
  3302. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK1, pDunSetting->bGatewayOnRemote));
  3303. MYVERIFY(0 != CheckDlgButton(hDlg, IDC_CHECK2, pDunSetting->bIpHeaderCompression));
  3304. EnableDisableIpAddressControls(hDlg);
  3305. }
  3306. else
  3307. {
  3308. CMASSERTMSG(FALSE, TEXT("TcpIpPropSheetProc -- pListEntry or pDunSetting are NULL"));
  3309. }
  3310. }
  3311. else
  3312. {
  3313. pListEntry = NULL;
  3314. pDunSetting = NULL;
  3315. CMASSERTMSG(FALSE, TEXT("TcpIpPropSheetProc -- NULL lParam passed to InitDialog. Dialog controls will all be set to off."));
  3316. }
  3317. }
  3318. else
  3319. {
  3320. pListEntry = NULL;
  3321. pDunSetting = NULL;
  3322. CMASSERTMSG(FALSE, TEXT("TcpIpPropSheetProc -- NULL PropSheetPage pointer passed for lParam."));
  3323. }
  3324. break;
  3325. case WM_NOTIFY:
  3326. if (NULL == pnmHeader)
  3327. {
  3328. return FALSE;
  3329. }
  3330. switch (pnmHeader->code)
  3331. {
  3332. case PSN_APPLY:
  3333. if (pListEntry && pDunSetting)
  3334. {
  3335. //
  3336. // Okay, lets read in the settings and save them to the passed
  3337. // in CDunSetting pointer.
  3338. //
  3339. if (IsDlgButtonChecked(hDlg, IDC_RADIO2))
  3340. {
  3341. SendDlgItemMessage(hDlg, IDC_PRIMARY_DNS, IPM_GETADDRESS, (WPARAM)0, (LPARAM)&(pDunSetting->dwPrimaryDns));
  3342. SendDlgItemMessage(hDlg, IDC_SECONDARY_DNS, IPM_GETADDRESS, (WPARAM)0, (LPARAM)&(pDunSetting->dwSecondaryDns));
  3343. SendDlgItemMessage(hDlg, IDC_PRIMARY_WINS, IPM_GETADDRESS, (WPARAM)0, (LPARAM)&(pDunSetting->dwPrimaryWins));
  3344. SendDlgItemMessage(hDlg, IDC_SECONDARY_WINS, IPM_GETADDRESS, (WPARAM)0, (LPARAM)&(pDunSetting->dwSecondaryWins));
  3345. }
  3346. else
  3347. {
  3348. pDunSetting->dwPrimaryDns = 0;
  3349. pDunSetting->dwSecondaryDns = 0;
  3350. pDunSetting->dwPrimaryWins = 0;
  3351. pDunSetting->dwSecondaryWins = 0;
  3352. }
  3353. pDunSetting->bGatewayOnRemote = IsDlgButtonChecked(hDlg, IDC_CHECK1);
  3354. pDunSetting->bIpHeaderCompression = IsDlgButtonChecked(hDlg, IDC_CHECK2);
  3355. }
  3356. break;
  3357. default:
  3358. break;
  3359. }
  3360. break;
  3361. case WM_COMMAND:
  3362. switch (LOWORD(wParam))
  3363. {
  3364. case IDC_RADIO1:
  3365. case IDC_RADIO2:
  3366. EnableDisableIpAddressControls(hDlg);
  3367. break;
  3368. default:
  3369. break;
  3370. }
  3371. break;
  3372. default:
  3373. return FALSE;
  3374. }
  3375. return FALSE;
  3376. } //lint !e715 we don't reference lParam
  3377. //+----------------------------------------------------------------------------
  3378. //
  3379. // Function: RefreshDnsList
  3380. //
  3381. // Synopsis: This function clears the contents of the listbox specified by
  3382. // hDlg and uCrtlId. Then it adds each of the items in the DUN
  3383. // entries linked list specified by pHead to the listbox. The
  3384. // passed in CMS file is used to figure out which entries to special
  3385. // with the default entry and VPN entry text.
  3386. //
  3387. // Arguments: HINSTANCE hInstance - instance handle for loading resources
  3388. // HWND hDlg - window handle for the DUN entries dialog
  3389. // UINT uCtrlId - control ID of the Listbox to write the entries to
  3390. // ListBxList * pHead - head of the linked list of DUN entries
  3391. // LPCTSTR pszLongServiceName - long service name of the profile
  3392. // LPCTSTR pszCmsFile - CMS file to get the DUN and TunnelDUN entries from
  3393. // LPTSTR pszItemToSelect - Item in the list to select after the refresh,
  3394. // NULL chooses the first in the list
  3395. //
  3396. // Returns: Nothing
  3397. //
  3398. // History: quintinb Created 03/27/00
  3399. //
  3400. //+----------------------------------------------------------------------------
  3401. void RefreshDnsList(HINSTANCE hInstance, HWND hDlg, UINT uCtrlId, ListBxList * pHead,
  3402. LPCTSTR pszLongServiceName, LPCTSTR pszCmsFile, LPTSTR pszItemToSelect)
  3403. {
  3404. if (hDlg && pHead)
  3405. {
  3406. TCHAR szTunnelSettingName[MAX_PATH+1] = TEXT("");
  3407. TCHAR szDefaultSettingName[MAX_PATH+1] = TEXT("");
  3408. //
  3409. // Get the name of the Tunnel Dun setting
  3410. //
  3411. MYVERIFY(0 != GetTunnelDunSettingName(pszCmsFile, pszLongServiceName, szTunnelSettingName, CELEMS(szTunnelSettingName)));
  3412. //
  3413. // Get the name of the default Dun setting
  3414. //
  3415. MYVERIFY(0 != GetDefaultDunSettingName(pszCmsFile, pszLongServiceName, szDefaultSettingName, CELEMS(szDefaultSettingName)));
  3416. //
  3417. // Reset the listbox contents
  3418. //
  3419. SendDlgItemMessage(hDlg, uCtrlId, LB_RESETCONTENT, 0, (LPARAM)0); //lint !e534 LB_RESETCONTENT doesn't return anything
  3420. //
  3421. // Now loop through the Network settings, adding them to the listbox
  3422. //
  3423. ListBxList * pCurrent = pHead;
  3424. LPTSTR pszDisplayString;
  3425. BOOL bFreeString;
  3426. BOOL bAddDefaultFmtStr = TRUE;
  3427. while(pCurrent)
  3428. {
  3429. if ((0 == lstrcmpi(szTunnelSettingName, pCurrent->szName)) && bAddDefaultFmtStr)
  3430. {
  3431. pszDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, pCurrent->szName);
  3432. MYDBGASSERT(pszDisplayString);
  3433. bFreeString = TRUE;
  3434. bAddDefaultFmtStr = FALSE;
  3435. }
  3436. else if ((0 == lstrcmpi(szDefaultSettingName, pCurrent->szName)) && bAddDefaultFmtStr)
  3437. {
  3438. pszDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, pCurrent->szName);
  3439. MYDBGASSERT(pszDisplayString);
  3440. bFreeString = TRUE;
  3441. bAddDefaultFmtStr = FALSE;
  3442. }
  3443. else
  3444. {
  3445. pszDisplayString = pCurrent->szName;
  3446. bFreeString = FALSE;
  3447. }
  3448. if (pszDisplayString)
  3449. {
  3450. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, uCtrlId, LB_ADDSTRING, 0, (LPARAM)pszDisplayString));
  3451. if (bFreeString)
  3452. {
  3453. CmFree(pszDisplayString);
  3454. }
  3455. }
  3456. pCurrent = pCurrent->next;
  3457. }
  3458. //
  3459. // Now Select the requested item in the list. If the requested name is NULL, just select the
  3460. // first item in the list.
  3461. //
  3462. LRESULT lResult = 0;
  3463. if (pszItemToSelect)
  3464. {
  3465. LPTSTR pszSearchString;
  3466. if (0 == lstrcmpi(szTunnelSettingName, pszItemToSelect))
  3467. {
  3468. pszSearchString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, pszItemToSelect);
  3469. }
  3470. else if (0 == lstrcmpi(szDefaultSettingName, pszItemToSelect))
  3471. {
  3472. pszSearchString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, pszItemToSelect);
  3473. }
  3474. else
  3475. {
  3476. pszSearchString = CmStrCpyAlloc(pszItemToSelect);
  3477. }
  3478. if (pszSearchString)
  3479. {
  3480. lResult = SendDlgItemMessage(hDlg, uCtrlId, LB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pszSearchString);
  3481. if (LB_ERR == lResult)
  3482. {
  3483. lResult = 0;
  3484. }
  3485. CmFree(pszSearchString);
  3486. }
  3487. }
  3488. SendDlgItemMessage(hDlg, uCtrlId, LB_SETCURSEL, (WPARAM)lResult, (LPARAM)0); // don't assert we may not have any items
  3489. EnableDisableDunEntryButtons(hInstance, hDlg, pszCmsFile, pszLongServiceName);
  3490. }
  3491. }
  3492. //+----------------------------------------------------------------------------
  3493. //
  3494. // Function: SelectAppropriateEAP
  3495. //
  3496. // Synopsis: This functions walks through the list of EAPData structures held
  3497. // by the item data pointers of the EAP names in the combobox specified
  3498. // by hDlg and uCtrlId. For each EAPData structure it compares
  3499. // the dwCustomAuthKey field with that of the pDunSetting->dwCustomAuthKey.
  3500. // When it finds a match it selects that item in the list. Note there
  3501. // is a special case for pDunSetting->dwCustomAuthKey == 0, in that
  3502. // since the dun setting doesn't specify and EAP we pick the first
  3503. // one in the list. If the EAP specified in pDunSetting isn't found
  3504. // then nothing is selected. However, this should never happen because
  3505. // if the profile specifies an EAP type not found on the machine it will
  3506. // add a special entry for it.
  3507. //
  3508. // Arguments: HWND hDlg - window handle of the win2k security dialog
  3509. // UINT uCtrlId - control ID of the combo containing the EAP types
  3510. // CDunSetting* pDunSetting - dun setting for which to locate the EAP
  3511. // for, contains the dwCustomAuthKey to try
  3512. // to match.
  3513. //
  3514. // Returns: Nothing
  3515. //
  3516. // History: quintinb Created 03/27/00
  3517. //
  3518. //+----------------------------------------------------------------------------
  3519. void SelectAppropriateEAP(HWND hDlg, UINT uCtrlId, CDunSetting* pDunSetting)
  3520. {
  3521. MYDBGASSERT(hDlg && uCtrlId && pDunSetting);
  3522. if (hDlg && uCtrlId && pDunSetting)
  3523. {
  3524. WPARAM wpIndex = 0;
  3525. INT_PTR nResult;
  3526. BOOL bEapSelected = FALSE;
  3527. if (0 == pDunSetting->dwCustomAuthKey)
  3528. {
  3529. //
  3530. // Select the first EAP in the list
  3531. //
  3532. SendDlgItemMessage(hDlg, uCtrlId, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
  3533. }
  3534. else
  3535. {
  3536. do
  3537. {
  3538. nResult = SendDlgItemMessage(hDlg, uCtrlId, CB_GETITEMDATA, wpIndex, (LPARAM)0);
  3539. if (CB_ERR != nResult)
  3540. {
  3541. EAPData* pEapData = (EAPData*)nResult;
  3542. if (pEapData && (pEapData->dwCustomAuthKey == pDunSetting->dwCustomAuthKey))
  3543. {
  3544. SendDlgItemMessage(hDlg, uCtrlId, CB_SETCURSEL, wpIndex, (LPARAM)0);
  3545. bEapSelected = TRUE;
  3546. break;
  3547. }
  3548. wpIndex++;
  3549. }
  3550. } while (CB_ERR != nResult);
  3551. }
  3552. }
  3553. }
  3554. //+----------------------------------------------------------------------------
  3555. //
  3556. // Function: FreeEapData
  3557. //
  3558. // Synopsis: This functions walks through the list of EAPData structures held
  3559. // by the item data pointers of the EAP names in the combobox specified
  3560. // by hDlg and uCtrlId. For each EAPData structure it releases the
  3561. // memory held by the EAPData structure, including the pszFriendlyName,
  3562. // the config dll path, and any custom auth data blobs that exist.
  3563. //
  3564. // Arguments: HWND hDlg - window handle of the win2k security dialog
  3565. // UINT uCtrlId - control ID of the combo containing the EAP types
  3566. //
  3567. // Returns: Nothing
  3568. //
  3569. // History: quintinb Created 03/27/00
  3570. //
  3571. //+----------------------------------------------------------------------------
  3572. void FreeEapData(HWND hDlg, UINT uCtrlId)
  3573. {
  3574. MYDBGASSERT(hDlg && uCtrlId);
  3575. if (hDlg && uCtrlId)
  3576. {
  3577. WPARAM wpIndex = 0;
  3578. INT_PTR nResult;
  3579. EAPData* pEapData;
  3580. do
  3581. {
  3582. nResult = SendDlgItemMessage(hDlg, uCtrlId, CB_GETITEMDATA, wpIndex, (LPARAM)0);
  3583. if (CB_ERR != nResult)
  3584. {
  3585. pEapData = (EAPData*)nResult;
  3586. if (pEapData)
  3587. {
  3588. CmFree(pEapData->pszFriendlyName);
  3589. CmFree(pEapData->pszConfigDllPath);
  3590. CmFree(pEapData->pCustomAuthData);
  3591. CmFree(pEapData);
  3592. }
  3593. wpIndex++;
  3594. }
  3595. } while (CB_ERR != nResult);
  3596. }
  3597. }
  3598. //+----------------------------------------------------------------------------
  3599. //
  3600. // Function: HrQueryRegStringWithAlloc
  3601. //
  3602. // Synopsis: This functions retrieves the string value specified by hKey and
  3603. // pszValueName. Note that the function queries the value to find
  3604. // out how much memory is needed to retrieve the data and then
  3605. // allocates the correct amount and retrieves the data itself. The
  3606. // returned buffer must be freed by the caller.
  3607. //
  3608. // Arguments: HKEY hKey - open handle to the regkey to get the value from
  3609. // LPCTSTR pszValueName - name of the value to retrieve data for
  3610. // TCHAR** ppszReturnString - pointer to hold the allocated string
  3611. // data retrieved from the registry value.
  3612. //
  3613. // Returns: HRESULT - standard COM style return codes
  3614. //
  3615. // History: quintinb Created 03/27/00
  3616. //
  3617. //+----------------------------------------------------------------------------
  3618. HRESULT HrQueryRegStringWithAlloc(HKEY hKey, LPCTSTR pszValueName, TCHAR** ppszReturnString)
  3619. {
  3620. if ((NULL == hKey) || (NULL == pszValueName) || (NULL == ppszReturnString) || (TEXT('\0') == pszValueName[0]))
  3621. {
  3622. CMASSERTMSG(FALSE, TEXT("HrQueryRegStringWithAlloc -- invalid parameter"));
  3623. return E_INVALIDARG;
  3624. }
  3625. HRESULT hr = S_OK;
  3626. DWORD dwType;
  3627. DWORD dwSize = 2;
  3628. TCHAR szTwo[2];
  3629. LPTSTR pszTemp = NULL;
  3630. LONG lReturn = RegQueryValueEx(hKey, pszValueName, NULL, &dwType, (LPBYTE)szTwo, &dwSize);
  3631. if (ERROR_MORE_DATA == lReturn)
  3632. {
  3633. *ppszReturnString = (LPTSTR)CmMalloc(dwSize);
  3634. if (*ppszReturnString)
  3635. {
  3636. lReturn = RegQueryValueEx(hKey, pszValueName, NULL, &dwType, (LPBYTE)*ppszReturnString, &dwSize);
  3637. hr = HRESULT_FROM_WIN32(lReturn);
  3638. if (SUCCEEDED(hr))
  3639. {
  3640. if (REG_EXPAND_SZ == dwType)
  3641. {
  3642. DWORD dwExpandedSize = sizeof(TCHAR)*(ExpandEnvironmentStrings(*ppszReturnString, NULL, 0));
  3643. if (dwExpandedSize && (dwSize != dwExpandedSize))
  3644. {
  3645. pszTemp = *ppszReturnString;
  3646. *ppszReturnString = (LPTSTR)CmMalloc(dwExpandedSize);
  3647. if (*ppszReturnString)
  3648. {
  3649. ExpandEnvironmentStrings(pszTemp, *ppszReturnString, dwExpandedSize);
  3650. }
  3651. else
  3652. {
  3653. CMASSERTMSG(FALSE, TEXT("HrQueryRegStringWithAlloc -- CmMalloc returned a NULL pointer."));
  3654. hr = E_OUTOFMEMORY;
  3655. }
  3656. CmFree(pszTemp);
  3657. }
  3658. }
  3659. }
  3660. }
  3661. else
  3662. {
  3663. CMASSERTMSG(FALSE, TEXT("HrQueryRegStringWithAlloc -- CmMalloc returned a NULL pointer."));
  3664. hr = E_OUTOFMEMORY;
  3665. }
  3666. }
  3667. else
  3668. {
  3669. hr = HRESULT_FROM_WIN32(GetLastError());
  3670. }
  3671. return hr;
  3672. }
  3673. //+----------------------------------------------------------------------------
  3674. //
  3675. // Function: ComboBox_GetPsz
  3676. //
  3677. // Synopsis: This function automatically allocates and returns the string with
  3678. // the given index from the given combobox. Happily stolen from Rasdlg.
  3679. //
  3680. // Arguments: HWND hDlg - window handle to the combobox
  3681. //
  3682. // Returns: Nothing
  3683. //
  3684. // History: quintinb Created header 04/02/2002
  3685. //
  3686. //+----------------------------------------------------------------------------
  3687. TCHAR* ComboBox_GetPsz(IN HWND hwnd, IN INT nIndex)
  3688. //
  3689. // Returns heap block containing the text contents of the 'nIndex'th item
  3690. // of combo box 'hwnd' or NULL. It is caller's responsibility to Free the
  3691. // returned string.
  3692. //
  3693. {
  3694. INT cch;
  3695. TCHAR* psz;
  3696. cch = ComboBox_GetLBTextLen( hwnd, nIndex );
  3697. if (cch < 0)
  3698. {
  3699. return NULL;
  3700. }
  3701. psz = (TCHAR*)CmMalloc( (cch + 1) * sizeof(TCHAR) );
  3702. if (psz)
  3703. {
  3704. *psz = TEXT('\0');
  3705. ComboBox_GetLBText( hwnd, nIndex, psz );
  3706. }
  3707. return psz;
  3708. }
  3709. //+----------------------------------------------------------------------------
  3710. //
  3711. // Function: ComboBox_AutoSizeDroppedWidth
  3712. //
  3713. // Synopsis: This function automatically sizes the combobox dropdown based on
  3714. // the strings already in the combobox. Happily stolen from Rasdlg.
  3715. //
  3716. // Arguments: HWND hDlg - window handle to the combobox
  3717. //
  3718. // Returns: Nothing
  3719. //
  3720. // History: quintinb Created header 04/02/2002
  3721. //
  3722. //+----------------------------------------------------------------------------
  3723. VOID ComboBox_AutoSizeDroppedWidth(IN HWND hwndLb)
  3724. // Set the width of the drop-down list 'hwndLb' to the width of the
  3725. // longest item (or the width of the list box if that's wider).
  3726. //
  3727. {
  3728. HDC hdc;
  3729. HFONT hfont;
  3730. TCHAR* psz;
  3731. SIZE size;
  3732. DWORD cch;
  3733. DWORD dxNew;
  3734. DWORD i;
  3735. hfont = (HFONT )SendMessage(hwndLb, WM_GETFONT, 0, 0);
  3736. if (!hfont)
  3737. {
  3738. return;
  3739. }
  3740. hdc = GetDC(hwndLb);
  3741. if (!hdc)
  3742. {
  3743. return;
  3744. }
  3745. SelectObject(hdc, hfont);
  3746. dxNew = 0;
  3747. for (i = 0; psz = ComboBox_GetPsz(hwndLb, i); ++i)
  3748. {
  3749. cch = lstrlen( psz );
  3750. if (GetTextExtentPoint32(hdc, psz, cch, &size))
  3751. {
  3752. if (dxNew < (DWORD )size.cx)
  3753. dxNew = (DWORD )size.cx;
  3754. }
  3755. CmFree(psz);
  3756. }
  3757. ReleaseDC(hwndLb, hdc);
  3758. //
  3759. // Allow for the spacing on left and right added by the control.
  3760. //
  3761. dxNew += 6;
  3762. // Figure out if the vertical scrollbar will be displayed and, if so,
  3763. // allow for it's width.
  3764. //
  3765. RECT rectD;
  3766. RECT rectU;
  3767. DWORD dyItem;
  3768. DWORD cItemsInDrop;
  3769. DWORD cItemsInList;
  3770. GetWindowRect(hwndLb, &rectU);
  3771. SendMessage(hwndLb, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM )&rectD);
  3772. dyItem = (DWORD)SendMessage(hwndLb, CB_GETITEMHEIGHT, 0, 0);
  3773. cItemsInDrop = (rectD.bottom - rectU.bottom) / dyItem;
  3774. cItemsInList = ComboBox_GetCount(hwndLb);
  3775. if (cItemsInDrop < cItemsInList)
  3776. {
  3777. dxNew += GetSystemMetrics(SM_CXVSCROLL);
  3778. }
  3779. SendMessage(hwndLb, CB_SETDROPPEDWIDTH, dxNew, 0);
  3780. }
  3781. //+----------------------------------------------------------------------------
  3782. //
  3783. // Function: ShowEapToUser
  3784. //
  3785. // Synopsis: This function examines the roles value of the given registry key
  3786. // represented by the passed in registry handle and decides whether
  3787. // the role tells us to show it to the user or not.
  3788. //
  3789. // Arguments: HKEY hKeyPackage - handle to the reg key of the EAP package
  3790. //
  3791. // Returns: BOOL - TRUE shows it to the user, FALSE skips the package
  3792. //
  3793. // History: quintinb Created 11/12/02
  3794. //
  3795. //+----------------------------------------------------------------------------
  3796. BOOL ShowEapToUser(HKEY hKeyPackage)
  3797. {
  3798. DWORD dwRolesSupported = 0;
  3799. DWORD dwSize = sizeof(dwRolesSupported);
  3800. DWORD dwType = REG_DWORD;
  3801. DWORD dwReturn = RegQueryValueEx(hKeyPackage, RAS_EAP_VALUENAME_ROLES_SUPPORTED, NULL,
  3802. &dwType, (LPBYTE)(&dwRolesSupported), &dwSize);
  3803. //
  3804. // If we couldn't access the key, assume it is okay to show it to the user. This
  3805. // will generally mean the key didn't exist... (which is okay it supports all roles).
  3806. //
  3807. if (ERROR_SUCCESS == dwReturn)
  3808. {
  3809. //
  3810. // This value is a set of flags that tell what roles the EAP
  3811. // supports. Whether the EAP can be used in server (authenticator) or client
  3812. // (authenticatee) and whether it is supported for RAS connections (VPN) or
  3813. // in PEAP. For our purposes, we only want to show EAP's that can be used by the
  3814. // client for EAP and VPN. If the EAP supports all of that show it, otherwise don't.
  3815. //
  3816. if (0 != dwRolesSupported)
  3817. {
  3818. if (!(RAS_EAP_ROLE_AUTHENTICATEE & dwRolesSupported))
  3819. {
  3820. return FALSE;
  3821. }
  3822. if (RAS_EAP_ROLE_EXCLUDE_IN_EAP & dwRolesSupported)
  3823. {
  3824. return FALSE;
  3825. }
  3826. if (RAS_EAP_ROLE_EXCLUDE_IN_VPN & dwRolesSupported)
  3827. {
  3828. return FALSE;
  3829. }
  3830. }
  3831. }
  3832. return TRUE;
  3833. }
  3834. //+----------------------------------------------------------------------------
  3835. //
  3836. // Function: HrAddAvailableEAPsToCombo
  3837. //
  3838. // Synopsis: This functions enumerates the EAP types listed in the registry
  3839. // and adds them to the EAP types combo. For each type of EAP the
  3840. // dwCustomAuthKey (numerical type of the EAP), the description string,
  3841. // the configuration UI dll path, and whether configuration is
  3842. // required is recorded in an EAPData structure and stored in the
  3843. // item data pointer of the combobox item. The passed in CDunSetting
  3844. // structure is used for two purposes. First this function checks to
  3845. // make sure that the EAP of the type that is specified in the
  3846. // CDunSetting structure is actually installed on the machine. If it
  3847. // isn't the user is presented with a warning message and the type is
  3848. // added as "EAP Type %d <not installed>". This is a choice in the UI
  3849. // but the user is unable to configure it unless they install the EAP.
  3850. // Also, if the EAP of the type specified in the CDunSetting is installed
  3851. // then the dwCustomAuthData and dwCustomAuthDataSize elements of the
  3852. // CDunSetting are copied over. Thus maintains the simplicity of letting
  3853. // the user configure any EAP they wish and then only picking up that
  3854. // data in the DUN setting when they hit okay. Thus allowing Cancel
  3855. // to work as one would expect.
  3856. //
  3857. // Arguments: HWND hDlg - window handle to the win2k security dialog
  3858. // UINT uCtrlId - EAP types combo box ID
  3859. // CDunSetting* pDunSetting - DUN setting data that we are currently
  3860. // adding/editing
  3861. //
  3862. // Returns: HRESULT - standard COM style return codes
  3863. //
  3864. // History: quintinb Created 03/27/00
  3865. //
  3866. //+----------------------------------------------------------------------------
  3867. HRESULT HrAddAvailableEAPsToCombo(HWND hDlg, UINT uCtrlId, CDunSetting* pDunSetting)
  3868. {
  3869. if ((NULL == hDlg) || (0 == uCtrlId) || (NULL == pDunSetting))
  3870. {
  3871. CMASSERTMSG(FALSE, TEXT("HrAddAvailableEAPsToCombo -- Invalid parameter passed."));
  3872. return E_INVALIDARG;
  3873. }
  3874. HKEY hKey = NULL;
  3875. HRESULT hr = S_OK;
  3876. LONG lReturn;
  3877. LPTSTR pszPath;
  3878. BOOL bEapTypeFound = FALSE;
  3879. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, RAS_EAP_REGISTRY_LOCATION, 0, KEY_READ, &hKey))
  3880. {
  3881. //
  3882. // Now begin enumerating the EAPs
  3883. //
  3884. TCHAR szSubKeyName[MAX_PATH+1]; // the key names are numbers representing the type of EAP, thus MAX_PATH is probably overkill
  3885. DWORD dwIndex = 0;
  3886. HKEY hTempKey = NULL;
  3887. do
  3888. {
  3889. lReturn = RegEnumKey(hKey, dwIndex, szSubKeyName, CELEMS(szSubKeyName));
  3890. if (ERROR_SUCCESS == lReturn)
  3891. {
  3892. //
  3893. // We potentially have an EAP reg key. Thus lets open a handle to this
  3894. // key and see if it has the values we are looking for.
  3895. //
  3896. if (ERROR_SUCCESS == RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_READ, &hTempKey))
  3897. {
  3898. //
  3899. // Check to see if we need to filter out PEAP and EAP-MsChapV2. That means checking the
  3900. // checking the roles value of each EAP package.
  3901. //
  3902. if (FALSE == ShowEapToUser(hTempKey))
  3903. {
  3904. RegCloseKey(hTempKey);
  3905. dwIndex++; // bump the index
  3906. continue;
  3907. }
  3908. //
  3909. // Get the path value, if we don't have a path value then just ignore the entry and move on
  3910. //
  3911. hr = HrQueryRegStringWithAlloc(hTempKey, RAS_EAP_VALUENAME_PATH, &pszPath);
  3912. if (SUCCEEDED(hr))
  3913. {
  3914. //
  3915. // Free the path, we don't really need to keep this value.
  3916. //
  3917. CmFree(pszPath);
  3918. EAPData* pEapData = (EAPData*)CmMalloc(sizeof(EAPData));
  3919. if (pEapData)
  3920. {
  3921. //
  3922. // Now get the Friendly name of the EAP to add to the combobox
  3923. //
  3924. HrQueryRegStringWithAlloc(hTempKey, RAS_EAP_VALUENAME_FRIENDLY_NAME, &(pEapData->pszFriendlyName));
  3925. //
  3926. // Next check to see if we have configuration UI for this EAP, thus requiring we store the
  3927. //
  3928. HrQueryRegStringWithAlloc(hTempKey, RAS_EAP_VALUENAME_CONFIGUI, &(pEapData->pszConfigDllPath));
  3929. //
  3930. // We also need to save the type value
  3931. //
  3932. pEapData->dwCustomAuthKey = _ttoi(szSubKeyName);
  3933. //
  3934. // If the pDunSetting has pCustomAuthData and it is the same type as the current EAP we are
  3935. // processing then we need to add the copy the EAP blob to the EAPData structure.
  3936. //
  3937. if (pDunSetting->dwCustomAuthKey == pEapData->dwCustomAuthKey)
  3938. {
  3939. if (pDunSetting->pCustomAuthData && pDunSetting->dwCustomAuthDataSize)
  3940. {
  3941. pEapData->pCustomAuthData = (LPBYTE)CmMalloc(pDunSetting->dwCustomAuthDataSize);
  3942. if (pEapData->pCustomAuthData)
  3943. {
  3944. pEapData->dwCustomAuthDataSize = pDunSetting->dwCustomAuthDataSize;
  3945. CopyMemory(pEapData->pCustomAuthData, pDunSetting->pCustomAuthData, pEapData->dwCustomAuthDataSize);
  3946. }
  3947. }
  3948. bEapTypeFound = TRUE;
  3949. }
  3950. //
  3951. // Get whether we must require configuration or not
  3952. //
  3953. DWORD dwSize = sizeof(pEapData->bMustConfig);
  3954. DWORD dwType = REG_DWORD;
  3955. if (ERROR_SUCCESS != RegQueryValueEx(hTempKey, RAS_EAP_VALUENAME_REQUIRE_CONFIGUI, NULL, &dwType, (LPBYTE)&(pEapData->bMustConfig), &dwSize))
  3956. {
  3957. pEapData->bMustConfig = FALSE;
  3958. }
  3959. dwSize = sizeof(pEapData->bSupportsEncryption);
  3960. if (ERROR_SUCCESS != RegQueryValueEx(hTempKey, RAS_EAP_VALUENAME_ENCRYPTION, NULL, &dwType, (LPBYTE)&(pEapData->bSupportsEncryption), &dwSize))
  3961. {
  3962. pEapData->bSupportsEncryption = FALSE;
  3963. }
  3964. //
  3965. // Finally add the EAP to the combobox
  3966. //
  3967. LPTSTR pszDisplayString = NULL;
  3968. TCHAR szDisplayString[MAX_PATH+1];
  3969. if (pEapData->bSupportsEncryption)
  3970. {
  3971. LPTSTR pszSuffix = CmLoadString(g_hInstance, IDS_SUPPORTS_ENCRYPT);
  3972. if (pszSuffix)
  3973. {
  3974. wsprintf(szDisplayString, TEXT("%s %s"), pEapData->pszFriendlyName, pszSuffix);
  3975. pszDisplayString = szDisplayString;
  3976. CmFree(pszSuffix);
  3977. }
  3978. }
  3979. if (NULL == pszDisplayString)
  3980. {
  3981. pszDisplayString = pEapData->pszFriendlyName;
  3982. }
  3983. INT_PTR nResult = SendDlgItemMessage(hDlg, uCtrlId, CB_ADDSTRING, (WPARAM)0, (LPARAM)pszDisplayString);
  3984. if (CB_ERR != nResult)
  3985. {
  3986. SendDlgItemMessage(hDlg, uCtrlId, CB_SETITEMDATA, (WPARAM)nResult, (LPARAM)pEapData);
  3987. }
  3988. else
  3989. {
  3990. CMASSERTMSG(FALSE, TEXT("HrAddAvailableEAPsToCombo -- unable to set item data."));
  3991. hr = HRESULT_FROM_WIN32(GetLastError());
  3992. }
  3993. }
  3994. else
  3995. {
  3996. CMASSERTMSG(FALSE, TEXT("HrAddAvailableEAPsToCombo -- CmMalloc returned a NULL pointer."));
  3997. hr = E_OUTOFMEMORY;
  3998. }
  3999. }
  4000. else
  4001. {
  4002. CMTRACE2(TEXT("HrAddAvailableEAPsToCombo -- Unable to find Path value for EAP regkey %s, hr %d"), szSubKeyName, hr);
  4003. }
  4004. }
  4005. else
  4006. {
  4007. CMTRACE2(TEXT("HrAddAvailableEAPsToCombo -- Unable to Open EAP regkey %s, GLE %d"), szSubKeyName, GetLastError());
  4008. }
  4009. }
  4010. dwIndex++;
  4011. } while (ERROR_SUCCESS == lReturn);
  4012. if (hTempKey)
  4013. {
  4014. (VOID)RegCloseKey(hTempKey);
  4015. hTempKey = NULL;
  4016. }
  4017. //
  4018. // Auto size the combo box drop down
  4019. //
  4020. HWND hCombo = GetDlgItem(hDlg, uCtrlId);
  4021. if (hCombo)
  4022. {
  4023. ComboBox_AutoSizeDroppedWidth(hCombo);
  4024. }
  4025. //
  4026. // If the Dun setting contains an EAP that isn't on the system
  4027. // we need to prompt the user.
  4028. //
  4029. if (pDunSetting->dwCustomAuthKey && (FALSE == bEapTypeFound))
  4030. {
  4031. MYVERIFY(IDOK == ShowMessage(hDlg, IDS_EAP_NOT_FOUND, MB_OK | MB_ICONINFORMATION));
  4032. EAPData* pEapData = (EAPData*)CmMalloc(sizeof(EAPData));
  4033. if (pEapData)
  4034. {
  4035. pEapData->pszFriendlyName = CmFmtMsg(g_hInstance, IDS_EAP_NOT_FOUND_TYPE, pDunSetting->dwCustomAuthKey);
  4036. pEapData->dwCustomAuthKey = pDunSetting->dwCustomAuthKey;
  4037. pEapData->bNotInstalled = TRUE;
  4038. INT_PTR nResult = SendDlgItemMessage(hDlg, uCtrlId, CB_ADDSTRING, (WPARAM)0, (LPARAM)(pEapData->pszFriendlyName));
  4039. if (CB_ERR != nResult)
  4040. {
  4041. SendDlgItemMessage(hDlg, uCtrlId, CB_SETITEMDATA, (WPARAM)nResult, (LPARAM)pEapData);
  4042. }
  4043. else
  4044. {
  4045. CMASSERTMSG(FALSE, TEXT("HrAddAvailableEAPsToCombo -- CmMalloc returned a NULL pointer."));
  4046. hr = HRESULT_FROM_WIN32(GetLastError());
  4047. }
  4048. }
  4049. }
  4050. }
  4051. else
  4052. {
  4053. hr = HRESULT_FROM_WIN32(GetLastError());
  4054. }
  4055. if (hKey)
  4056. {
  4057. (VOID)RegCloseKey(hKey);
  4058. }
  4059. return hr;
  4060. }
  4061. //+----------------------------------------------------------------------------
  4062. //
  4063. // Function: FreeDnsList
  4064. //
  4065. // Synopsis: Since the ListBxData in the list box items of the DNS
  4066. // list are actually CDunSetting class pointers we must
  4067. // properly cast the pointer so that they are destructed
  4068. // corretly.
  4069. //
  4070. // Arguments: ListBxList ** HeadPtr - head of the DUN setting list
  4071. //
  4072. // Returns: nothing
  4073. //
  4074. // History: quintinb Created 03/27/00
  4075. //
  4076. //+----------------------------------------------------------------------------
  4077. void FreeDnsList(ListBxList ** pHeadPtr, ListBxList ** pTailPtr)
  4078. {
  4079. CDunSetting* pDunSetting;
  4080. ListBxList* pCurrent = *pHeadPtr;
  4081. ListBxList* pTemp;
  4082. while (NULL != pCurrent)
  4083. {
  4084. pTemp = pCurrent;
  4085. //
  4086. // Free the DunSetting
  4087. //
  4088. pDunSetting = (CDunSetting*)pCurrent->ListBxData;
  4089. delete pDunSetting;
  4090. pCurrent = pCurrent->next;
  4091. CmFree(pTemp);
  4092. }
  4093. *pHeadPtr = NULL;
  4094. *pTailPtr = NULL;
  4095. }
  4096. //+----------------------------------------------------------------------------
  4097. //
  4098. // Function: EnableDisableDunEntryButtons
  4099. //
  4100. // Synopsis: This function enables or disables the Add and Edit buttons on
  4101. // the Dun entries screen. It also enables or disables the delete
  4102. // button depending on whether the current selection is a built in
  4103. // entry or not.
  4104. //
  4105. // Arguments: HINSTANCE hInstance - instance handle to load resources with
  4106. // HWND hDlg - window handle to the dun entries dialog
  4107. // LPCTSTR pszCmsFile - full path to the cms file
  4108. // LPCTSTR pszLongServiceName - long service name of the profile
  4109. //
  4110. // Returns: Nothing
  4111. //
  4112. // History: quintinb Created 9/11/98
  4113. //
  4114. //+----------------------------------------------------------------------------
  4115. void EnableDisableDunEntryButtons(HINSTANCE hInstance, HWND hDlg, LPCTSTR pszCmsFile, LPCTSTR pszLongServiceName)
  4116. {
  4117. LRESULT lResult;
  4118. BOOL bEnableEdit = FALSE;
  4119. BOOL bEnableDelete = FALSE;
  4120. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCOUNT, 0, 0);
  4121. if (LB_ERR != lResult)
  4122. {
  4123. if (0 == lResult)
  4124. {
  4125. //
  4126. // Zero Items, set focus to the Add Button
  4127. //
  4128. SetFocus(GetDlgItem(hDlg, IDC_BUTTON1));
  4129. }
  4130. else
  4131. {
  4132. //
  4133. // Enable the Edit Button because we have at least 1 item.
  4134. //
  4135. bEnableEdit = TRUE;
  4136. //
  4137. // Now lets figure out if the delete button should be enabled or not.
  4138. // If we have at least one item then we normally want to enable the
  4139. // delete button. However, if the current selection is on the VPN
  4140. // connection or the default connection then we don't want the user to
  4141. // delete these and we will have to disable the delete button (note that
  4142. // even if the user hit the delete button on one of these items we wouldn't
  4143. // delete it). So, lets get the Cursor selection to see if we need to
  4144. // disable the delete button.
  4145. //
  4146. LRESULT lCurrentIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, 0, 0);
  4147. if (LB_ERR == lCurrentIndex)
  4148. {
  4149. MYVERIFY(LB_ERR != SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, 0, (LPARAM)0));
  4150. lCurrentIndex = 0;
  4151. }
  4152. TCHAR szTunnelDunName[MAX_PATH+1] = TEXT("");
  4153. TCHAR szDefaultDunName[MAX_PATH+1] = TEXT("");
  4154. //
  4155. // Get the name of the Tunnel Dun setting
  4156. //
  4157. MYVERIFY(0 != GetTunnelDunSettingName(pszCmsFile, pszLongServiceName, szTunnelDunName, CELEMS(szTunnelDunName)));
  4158. //
  4159. // Get the name of the default Dun setting
  4160. //
  4161. MYVERIFY(0 != GetDefaultDunSettingName(pszCmsFile, pszLongServiceName, szDefaultDunName, CELEMS(szDefaultDunName)));
  4162. //
  4163. // If we have the default entry text or the tunnel entry text then we want
  4164. // to use the real item names for these instead of the text we inserted for
  4165. // the user to read.
  4166. //
  4167. LPTSTR pszTunnelDunDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, szTunnelDunName);
  4168. LPTSTR pszDefaultDunDisplayString = CmFmtMsg(hInstance, IDS_DEFAULT_FMT_STR, szDefaultDunName);
  4169. LPTSTR pszCurrentSelection = NULL;
  4170. MYDBGASSERT(pszTunnelDunDisplayString && pszDefaultDunDisplayString);
  4171. if (pszTunnelDunDisplayString && pszDefaultDunDisplayString)
  4172. {
  4173. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXTLEN, lCurrentIndex, (LPARAM)0);
  4174. if (LB_ERR != lResult)
  4175. {
  4176. pszCurrentSelection = (LPTSTR)CmMalloc((lResult + 1) * sizeof(TCHAR));
  4177. if (pszCurrentSelection)
  4178. {
  4179. lResult = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETTEXT, lCurrentIndex, (LPARAM)pszCurrentSelection);
  4180. if ((0 != lstrcmpi(pszCurrentSelection, pszTunnelDunDisplayString)) &&
  4181. (0 != lstrcmpi(pszCurrentSelection, pszDefaultDunDisplayString)))
  4182. {
  4183. bEnableDelete = TRUE;
  4184. }
  4185. }
  4186. }
  4187. CmFree(pszTunnelDunDisplayString);
  4188. CmFree(pszDefaultDunDisplayString);
  4189. CmFree(pszCurrentSelection);
  4190. }
  4191. }
  4192. }
  4193. HWND hDeleteButton = GetDlgItem(hDlg, IDC_BUTTON3);
  4194. HWND hCurrentFocus = GetFocus();
  4195. HWND hControl = GetDlgItem(hDlg, IDC_BUTTON2); // Edit button == IDC_BUTTON2
  4196. if (hControl) // Edit
  4197. {
  4198. EnableWindow(hControl, bEnableEdit);
  4199. }
  4200. if (hDeleteButton) // Delete
  4201. {
  4202. EnableWindow(hDeleteButton, bEnableDelete);
  4203. }
  4204. if (hCurrentFocus && (FALSE == IsWindowEnabled(hCurrentFocus)))
  4205. {
  4206. if (hDeleteButton == hCurrentFocus)
  4207. {
  4208. //
  4209. // If delete is disabled and contained the focus, shift it to the Add button
  4210. //
  4211. SendMessage(hDlg, DM_SETDEFID, IDC_BUTTON1, (LPARAM)0L); //lint !e534 DM_SETDEFID doesn't return error info
  4212. hControl = GetDlgItem(hDlg, IDC_BUTTON1);
  4213. if (hControl)
  4214. {
  4215. SetFocus(hControl);
  4216. }
  4217. }
  4218. else
  4219. {
  4220. //
  4221. // If all else fails set the focus to the list control
  4222. //
  4223. hControl = GetDlgItem(hDlg, IDC_LIST1);
  4224. if (hControl)
  4225. {
  4226. SetFocus(hControl);
  4227. }
  4228. }
  4229. }
  4230. }
  4231. //+----------------------------------------------------------------------------
  4232. //
  4233. // Function: CheckForDUNversusVPNNameConflicts
  4234. //
  4235. // Synopsis: This function checks the names of all of the entries in the DUN
  4236. // entry list to make sure that no entries of the same name exist
  4237. // on the VPN list since the namespace that the two types of entries
  4238. // share (ie the cms file) is a flat namespace. If an identical entry
  4239. // name exists in both lists then one will overwrite the over in the cms.
  4240. //
  4241. // Arguments: HWND hDlg - window handle of the parent window
  4242. // ListBxList * pHeadDunEntry - head of the DUN settings list
  4243. // ListBxList * pHeadVpnEntry - head of the VPN settings list
  4244. //
  4245. // Returns: BOOL - TRUE if no collision was detected, FALSE if a collision was detected
  4246. //
  4247. // History: quintinb Created 11/01/00
  4248. //
  4249. //+----------------------------------------------------------------------------
  4250. BOOL CheckForDUNversusVPNNameConflicts(HWND hDlg, ListBxList * pHeadDunEntry, ListBxList * pHeadVpnEntry)
  4251. {
  4252. if (pHeadDunEntry && pHeadVpnEntry)
  4253. {
  4254. ListBxList * pCurrentDUN = pHeadDunEntry;
  4255. while (pCurrentDUN)
  4256. {
  4257. ListBxList * pCurrentVPN = pHeadVpnEntry;
  4258. while (pCurrentVPN)
  4259. {
  4260. CMTRACE2(TEXT("Comparing %s with %s"), pCurrentVPN->szName, pCurrentDUN->szName);
  4261. if (0 == lstrcmpi(pCurrentVPN->szName, pCurrentDUN->szName))
  4262. {
  4263. //
  4264. // Collision detected
  4265. //
  4266. LPTSTR pszMsg = CmFmtMsg(g_hInstance, IDS_DUN_NAME_CONFLICT, pCurrentDUN->szName);
  4267. if (pszMsg)
  4268. {
  4269. MessageBox(hDlg, pszMsg, g_szAppTitle, MB_OK);
  4270. CmFree (pszMsg);
  4271. }
  4272. return FALSE;
  4273. }
  4274. pCurrentVPN = pCurrentVPN->next;
  4275. }
  4276. pCurrentDUN = pCurrentDUN->next;
  4277. }
  4278. }
  4279. return TRUE;
  4280. }