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

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