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.

2760 lines
81 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. optcfg.cpp
  7. Individual option property page
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "optcfg.h"
  12. #include "listview.h"
  13. #include "server.h"
  14. #include "nodes.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. #define MAX_COLUMNS 2
  21. UINT COLUMN_HEADERS[MAX_COLUMNS] =
  22. {
  23. IDS_OPTCFG_NAME,
  24. // IDS_OPTCFG_TYPE,
  25. IDS_OPTCFG_COMMENT
  26. };
  27. int COLUMN_WIDTHS[MAX_COLUMNS] =
  28. {
  29. // 120, 55, 150
  30. 150, 175
  31. };
  32. const DWORD * OPTION_CONTROL_HELP_ARRAYS[] =
  33. {
  34. g_aHelpIDs_IDD_DATA_ENTRY_DWORD,
  35. g_aHelpIDs_IDD_DATA_ENTRY_IPADDRESS,
  36. g_aHelpIDs_IDD_DATA_ENTRY_IPADDRESS_ARRAY,
  37. g_aHelpIDs_IDD_DATA_ENTRY_BINARY,
  38. g_aHelpIDs_IDD_DATA_ENTRY_BINARY_ARRAY,
  39. g_aHelpIDs_IDD_DATA_ENTRY_STRING,
  40. g_aHelpIDs_IDD_DATA_ENTRY_ROUTE_ARRAY
  41. };
  42. // class CHelpMap
  43. CHelpMap::CHelpMap()
  44. {
  45. m_pdwHelpMap = NULL;
  46. }
  47. CHelpMap::~CHelpMap()
  48. {
  49. ResetMap();
  50. }
  51. void
  52. CHelpMap::BuildMap(DWORD pdwParentHelpMap[])
  53. {
  54. int i, j, nPos;
  55. int nSize = 0;
  56. int nCurSize;
  57. ResetMap();
  58. // calculate the size of the map
  59. // subtract off the terminators
  60. nSize += CountMap(pdwParentHelpMap);
  61. for (i = 0; i < ARRAYLEN(OPTION_CONTROL_HELP_ARRAYS); i++)
  62. {
  63. nSize += CountMap(OPTION_CONTROL_HELP_ARRAYS[i]);
  64. }
  65. nSize += 2; // for terminator
  66. m_pdwHelpMap = new DWORD[nSize];
  67. memset(m_pdwHelpMap, 0, sizeof(*m_pdwHelpMap));
  68. // fill in the parent help map
  69. nPos = 0;
  70. nCurSize = CountMap(pdwParentHelpMap);
  71. for (i = 0; i < nCurSize; i++)
  72. {
  73. m_pdwHelpMap[nPos++] = pdwParentHelpMap[i++];
  74. m_pdwHelpMap[nPos++] = pdwParentHelpMap[i];
  75. }
  76. // now add all of the possible option control help maps
  77. for (i = 0; i < ARRAYLEN(OPTION_CONTROL_HELP_ARRAYS); i++)
  78. {
  79. nCurSize = CountMap(OPTION_CONTROL_HELP_ARRAYS[i]);
  80. for (j = 0; j < nCurSize; j++)
  81. {
  82. m_pdwHelpMap[nPos++] = (OPTION_CONTROL_HELP_ARRAYS[i])[j++];
  83. m_pdwHelpMap[nPos++] = (OPTION_CONTROL_HELP_ARRAYS[i])[j];
  84. }
  85. }
  86. }
  87. DWORD * CHelpMap::GetMap()
  88. {
  89. return m_pdwHelpMap;
  90. }
  91. int CHelpMap::CountMap(const DWORD * pdwHelpMap)
  92. {
  93. int i = 0;
  94. while (pdwHelpMap[i] != 0)
  95. {
  96. i++;
  97. }
  98. return i++;
  99. }
  100. void CHelpMap::ResetMap()
  101. {
  102. if (m_pdwHelpMap)
  103. {
  104. delete m_pdwHelpMap;
  105. m_pdwHelpMap = NULL;
  106. }
  107. }
  108. DEBUG_DECLARE_INSTANCE_COUNTER(COptionsConfig);
  109. /////////////////////////////////////////////////////////////////////////////
  110. //
  111. // COptionsConfig holder
  112. //
  113. /////////////////////////////////////////////////////////////////////////////
  114. COptionsConfig::COptionsConfig
  115. (
  116. ITFSNode * pNode,
  117. ITFSNode * pServerNode,
  118. IComponentData * pComponentData,
  119. ITFSComponentData * pTFSCompData,
  120. COptionValueEnum * pOptionValueEnum,
  121. LPCTSTR pszSheetName,
  122. CDhcpOptionItem * pSelOption
  123. ) : CPropertyPageHolderBase(pNode, pComponentData, pszSheetName)
  124. {
  125. DEBUG_INCREMENT_INSTANCE_COUNTER(COptionsConfig);
  126. //ASSERT(pFolderNode == GetContainerNode());
  127. m_bAutoDeletePages = FALSE; // we have the pages as embedded members
  128. AddPageToList((CPropertyPageBase*) &m_pageGeneral);
  129. LARGE_INTEGER liServerVersion;
  130. CDhcpServer * pServer = GETHANDLER(CDhcpServer, pServerNode);
  131. pServer->GetVersion(m_liServerVersion);
  132. if (m_liServerVersion.QuadPart >= DHCP_NT5_VERSION)
  133. {
  134. AddPageToList((CPropertyPageBase*) &m_pageAdvanced);
  135. }
  136. Assert(pTFSCompData != NULL);
  137. m_spTFSCompData.Set(pTFSCompData);
  138. m_spServerNode.Set(pServerNode);
  139. // get all of the active options for this node
  140. SPITFSNode spNode;
  141. spNode = GetNode();
  142. m_bInitialized = FALSE;
  143. m_pOptionValueEnum = pOptionValueEnum;
  144. if (pSelOption)
  145. {
  146. m_strStartVendor = pSelOption->GetVendor();
  147. m_strStartClass = pSelOption->GetClassName();
  148. m_dhcpStartId = pSelOption->GetOptionId();
  149. }
  150. else
  151. {
  152. m_dhcpStartId = 0xffffffff;
  153. }
  154. }
  155. COptionsConfig::~COptionsConfig()
  156. {
  157. DEBUG_DECREMENT_INSTANCE_COUNTER(COptionsConfig);
  158. RemovePageFromList((CPropertyPageBase*) &m_pageGeneral, FALSE);
  159. RemovePageFromList((CPropertyPageBase*) &m_pageAdvanced, FALSE);
  160. }
  161. DWORD
  162. COptionsConfig::InitData()
  163. {
  164. DWORD dwErr = NO_ERROR;
  165. if (m_bInitialized)
  166. return dwErr;
  167. CDhcpServer * pServer = GETHANDLER(CDhcpServer, m_spServerNode);
  168. CClassInfoArray ClassInfoArray;
  169. pServer->GetClassInfoArray(ClassInfoArray);
  170. // create a standard DHCP options vendor tracker and a set of default class options
  171. CVendorTracker * pVendorTracker = AddVendorTracker(_T(""));
  172. AddClassTracker(pVendorTracker, _T(""));
  173. // walk the list of classes. For each vendor class, add a default user class.
  174. for (int i = 0; i < ClassInfoArray.GetSize(); i++)
  175. {
  176. if (ClassInfoArray[i].bIsVendor)
  177. {
  178. // create a vendor tracker and a set of default class options
  179. pVendorTracker = AddVendorTracker(ClassInfoArray[i].strName);
  180. AddClassTracker(pVendorTracker, _T(""));
  181. }
  182. }
  183. // now walk the list of vendor classes and add User class option lists
  184. POSITION pos = m_listVendorClasses.GetHeadPosition();
  185. while (pos)
  186. {
  187. pVendorTracker = m_listVendorClasses.GetNext(pos);
  188. // now build option sets for each user class in each vendor
  189. for (int j = 0; j < ClassInfoArray.GetSize(); j++)
  190. {
  191. if (!ClassInfoArray[j].bIsVendor)
  192. AddClassTracker(pVendorTracker, ClassInfoArray[j].strName);
  193. }
  194. }
  195. // now we need to update any active options with their current values
  196. UpdateActiveOptions();
  197. m_bInitialized = TRUE;
  198. return dwErr;
  199. }
  200. void
  201. COptionsConfig::SetTitle()
  202. {
  203. HWND hSheet = GetSheetWindow();
  204. ::SetWindowText(hSheet, m_stSheetTitle);
  205. }
  206. LPWSTR COptionsConfig::GetServerAddress()
  207. {
  208. CDhcpServer * pServer = GETHANDLER(CDhcpServer, m_spServerNode);
  209. return (LPWSTR) pServer->GetIpAddress();
  210. }
  211. CVendorTracker *
  212. COptionsConfig::AddVendorTracker(LPCTSTR pClassName)
  213. {
  214. CVendorTracker * pVendorTracker = new CVendorTracker();
  215. pVendorTracker->SetClassName(pClassName);
  216. m_listVendorClasses.AddTail(pVendorTracker);
  217. return pVendorTracker;
  218. }
  219. void COptionsConfig::AddClassTracker(CVendorTracker * pVendorTracker, LPCTSTR pClassName)
  220. {
  221. SPITFSNode spServerNode;
  222. spServerNode = GetServerNode();
  223. CDhcpServer * pServer = GETHANDLER(CDhcpServer, spServerNode);
  224. CClassTracker * pClassTracker = new CClassTracker();
  225. pClassTracker->SetClassName(pClassName);
  226. // add the new class tracker to the list.
  227. pVendorTracker->m_listUserClasses.AddTail(pClassTracker);
  228. // Get a pointer to the list of options on the server. We use this
  229. // to build our list of available options for this class
  230. CDhcpOption * pCurOption;
  231. CDhcpDefaultOptionsOnServer * pDefOptions = pServer->GetDefaultOptionsList();
  232. CString strVendor = pVendorTracker->GetClassName();
  233. CString strUserClass = pClassName;
  234. pCurOption = pDefOptions->First();
  235. while (pCurOption)
  236. {
  237. DHCP_OPTION_ID id = pCurOption->QueryId();
  238. // we filter out some options:
  239. // 1 - standard options with no user class call FilterOption
  240. // 2 - standard options with a user class call FilterUserClassOptions
  241. if ( (strVendor.IsEmpty() && !FilterOption(id) && !pCurOption->IsVendor()) ||
  242. (strVendor.IsEmpty() && !pCurOption->IsVendor() && !strUserClass.IsEmpty() && !FilterUserClassOption(id)) ||
  243. (pCurOption->GetVendor() && strVendor.Compare(pCurOption->GetVendor()) == 0) )
  244. {
  245. // create an option item for this entry. We do this because
  246. // these options are stored in the server node, but since this is a modeless
  247. // dialog the values could change, so we'll take a snapshot of the data
  248. // we can just use the copy constructor of the CDhcpOption
  249. COptionTracker * pOptionTracker = new COptionTracker;
  250. CDhcpOption * pNewOption = new CDhcpOption(*pCurOption);
  251. pOptionTracker->m_pOption = pNewOption;
  252. // add the option to the class tracker
  253. pClassTracker->m_listOptions.AddTail(pOptionTracker);
  254. }
  255. pCurOption = pDefOptions->Next();
  256. }
  257. }
  258. void COptionsConfig::UpdateActiveOptions()
  259. {
  260. // Now the known options are in the correct locations. We need to see
  261. // what options are enabled for this node. We querried the server to make
  262. // sure we have the latest information about active options.
  263. m_pOptionValueEnum->Reset();
  264. CDhcpOption * pOption;
  265. while (pOption = m_pOptionValueEnum->Next())
  266. {
  267. DHCP_OPTION_ID optionId = pOption->QueryId();
  268. // search all vendors options
  269. POSITION pos = m_listVendorClasses.GetHeadPosition();
  270. while (pos)
  271. {
  272. // search all vendor classes
  273. CVendorTracker * pVendorTracker = m_listVendorClasses.GetNext(pos);
  274. CString strVendor = pOption->GetVendor();
  275. if (pVendorTracker->m_strClassName.Compare(strVendor) == 0)
  276. {
  277. // ok, the vendor class matches so lets check user classes
  278. POSITION pos2 = pVendorTracker->m_listUserClasses.GetHeadPosition();
  279. while (pos2)
  280. {
  281. CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos2);
  282. // check to see if this option belongs to this class
  283. if ( (pClassTracker->m_strClassName.IsEmpty()) &&
  284. (!pOption->IsClassOption()) )
  285. {
  286. // both are empty... match.
  287. }
  288. else
  289. if ( ( pClassTracker->m_strClassName.IsEmpty() && pOption->IsClassOption() ) ||
  290. ( !pClassTracker->m_strClassName.IsEmpty() && !pOption->IsClassOption() ) )
  291. {
  292. // either the current option or the current class is null...
  293. continue;
  294. }
  295. else
  296. if (pClassTracker->m_strClassName.CompareNoCase(pOption->GetClassName()) != 0)
  297. {
  298. // both names are non-null and they don't match... keep looking
  299. continue;
  300. }
  301. // Ok, the class the option belong to is the same as the one we are currently
  302. // looking at. Loop through the default options for this class and update it's
  303. // state and value.
  304. POSITION posOption = pClassTracker->m_listOptions.GetHeadPosition();
  305. while (posOption)
  306. {
  307. COptionTracker * pCurOptTracker = pClassTracker->m_listOptions.GetNext(posOption);
  308. CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
  309. if ( (pCurOption->QueryId() == pOption->QueryId()) &&
  310. ( (pCurOption->IsVendor() && pOption->IsVendor()) ||
  311. (!pCurOption->IsVendor() && !pOption->IsVendor()) ) )
  312. {
  313. // update this option
  314. CDhcpOptionValue OptValue = pOption->QueryValue();
  315. pCurOption->Update(OptValue);
  316. pCurOptTracker->SetInitialState(OPTION_STATE_ACTIVE);
  317. pCurOptTracker->SetCurrentState(OPTION_STATE_ACTIVE);
  318. break;
  319. }
  320. } // while option list
  321. } // while User class list
  322. } // endif vendor class name compre
  323. } // while list of vendor classes
  324. }
  325. }
  326. void COptionsConfig::FillOptions(LPCTSTR pVendorName, LPCTSTR pUserClassName, CMyListCtrl & ListCtrl)
  327. {
  328. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  329. // look for the requested class and fill in the listbox
  330. // with all options for that class
  331. CString strVendorStandard, strClassStandard, strTargetVendor, strTargetClass;
  332. CString strTypeVendor, strTypeStandard;
  333. strVendorStandard.LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
  334. strClassStandard.LoadString(IDS_USER_STANDARD);
  335. if (strVendorStandard.Compare(pVendorName) != 0)
  336. strTargetVendor = pVendorName;
  337. if (strClassStandard.Compare(pUserClassName) != 0)
  338. strTargetClass = pUserClassName;
  339. POSITION posv = m_listVendorClasses.GetHeadPosition();
  340. while (posv)
  341. {
  342. // find the right vendor
  343. CVendorTracker * pVendorTracker = m_listVendorClasses.GetNext(posv);
  344. if (pVendorTracker->m_strClassName.Compare(strTargetVendor) == 0)
  345. {
  346. POSITION pos = NULL;
  347. pos = pVendorTracker->m_listUserClasses.GetHeadPosition();
  348. while (pos)
  349. {
  350. // now find the right user class
  351. CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos);
  352. if (pClassTracker->m_strClassName.Compare(strTargetClass) == 0)
  353. {
  354. // this is the class, add all of the options to the listbox
  355. CString strDisplay, strType, strComment;
  356. POSITION posOption = NULL;
  357. posOption = pClassTracker->m_listOptions.GetHeadPosition();
  358. while (posOption)
  359. {
  360. COptionTracker * pOptionTracker = pClassTracker->m_listOptions.GetNext(posOption);
  361. pOptionTracker->m_pOption->QueryDisplayName(strDisplay);
  362. strComment = pOptionTracker->m_pOption->QueryComment();
  363. strType = pOptionTracker->m_pOption->IsVendor() ? strTypeVendor : strTypeStandard;
  364. int nIndex = ListCtrl.AddItem(strDisplay, strComment, LISTVIEWEX_NOT_CHECKED);
  365. ListCtrl.SetItemData(nIndex, (LPARAM) pOptionTracker);
  366. if (pOptionTracker->GetCurrentState() == OPTION_STATE_ACTIVE)
  367. ListCtrl.CheckItem(nIndex);
  368. }
  369. break;
  370. }
  371. } // while
  372. } // if
  373. } // while
  374. // Finally, Set the column widths so that all items are visible.
  375. // Set the default column widths to the width of the widest column
  376. int * aColWidth = (int *) alloca(MAX_COLUMNS * sizeof(int));
  377. int nRow, nCol;
  378. CString strTemp;
  379. ZeroMemory(aColWidth, MAX_COLUMNS * sizeof(int));
  380. CopyMemory(aColWidth, &COLUMN_WIDTHS, sizeof(MAX_COLUMNS * sizeof(int)));
  381. // for each item, loop through each column and calculate the correct width
  382. for (nRow = 0; nRow < ListCtrl.GetItemCount(); nRow++)
  383. {
  384. for (nCol = 0; nCol < MAX_COLUMNS; nCol++)
  385. {
  386. strTemp = ListCtrl.GetItemText(nRow, nCol);
  387. if (aColWidth[nCol] < ListCtrl.GetStringWidth(strTemp))
  388. aColWidth[nCol] = ListCtrl.GetStringWidth(strTemp);
  389. }
  390. }
  391. // now update the column widths based on what we calculated
  392. for (nCol = 0; nCol < MAX_COLUMNS; nCol++)
  393. {
  394. // GetStringWidth doesn't seem to report the right thing,
  395. // so we have to add a fudge factor of 15.... oh well.
  396. if (aColWidth[nCol] > 0)
  397. ListCtrl.SetColumnWidth(nCol, aColWidth[nCol] + 15);
  398. }
  399. }
  400. /////////////////////////////////////////////////////////////////////////////
  401. // COptionsCfgBasic property page
  402. IMPLEMENT_DYNCREATE(COptionsCfgPropPage, CPropertyPageBase)
  403. COptionsCfgPropPage::COptionsCfgPropPage() :
  404. CPropertyPageBase(COptionsCfgPropPage::IDD),
  405. m_bInitialized(FALSE)
  406. {
  407. LoadBitmaps();
  408. m_helpMap.BuildMap(DhcpGetHelpMap(COptionsCfgPropPage::IDD));
  409. }
  410. COptionsCfgPropPage::COptionsCfgPropPage(UINT nIDTemplate, UINT nIDCaption) :
  411. CPropertyPageBase(nIDTemplate, nIDCaption),
  412. m_bInitialized(FALSE)
  413. {
  414. //{{AFX_DATA_INIT(COptionsCfgPropPage)
  415. //}}AFX_DATA_INIT
  416. LoadBitmaps();
  417. m_helpMap.BuildMap(DhcpGetHelpMap(COptionsCfgPropPage::IDD));
  418. }
  419. COptionsCfgPropPage::~COptionsCfgPropPage()
  420. {
  421. }
  422. void
  423. COptionsCfgPropPage::LoadBitmaps()
  424. {
  425. }
  426. void COptionsCfgPropPage::DoDataExchange(CDataExchange* pDX)
  427. {
  428. CPropertyPageBase::DoDataExchange(pDX);
  429. //{{AFX_DATA_MAP(COptionsCfgPropPage)
  430. DDX_Control(pDX, IDC_LIST_OPTIONS, m_listctrlOptions);
  431. //}}AFX_DATA_MAP
  432. }
  433. BEGIN_MESSAGE_MAP(COptionsCfgPropPage, CPropertyPageBase)
  434. //{{AFX_MSG_MAP(COptionsCfgPropPage)
  435. ON_WM_DESTROY()
  436. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_OPTIONS, OnItemchangedListOptions)
  437. //}}AFX_MSG_MAP
  438. ON_MESSAGE(WM_SELECTOPTION, OnSelectOption)
  439. // Binary array controls
  440. ON_EN_CHANGE(IDC_EDIT_VALUE, OnChangeEditValue)
  441. ON_BN_CLICKED(IDC_BUTTON_VALUE_UP, OnButtonValueUp)
  442. ON_BN_CLICKED(IDC_BUTTON_VALUE_DOWN, OnButtonValueDown)
  443. ON_BN_CLICKED(IDC_BUTTON_VALUE_ADD, OnButtonValueAdd)
  444. ON_BN_CLICKED(IDC_BUTTON_VALUE_DELETE, OnButtonValueDelete)
  445. ON_BN_CLICKED(IDC_RADIO_DECIMAL, OnClickedRadioDecimal)
  446. ON_BN_CLICKED(IDC_RADIO_HEX, OnClickedRadioHex)
  447. ON_LBN_SELCHANGE(IDC_LIST_VALUES, OnSelchangeListValues)
  448. // Byte, WORD and Long edit control
  449. ON_EN_CHANGE(IDC_EDIT_DWORD, OnChangeEditDword)
  450. // string edit control
  451. ON_EN_CHANGE(IDC_EDIT_STRING_VALUE, OnChangeEditString)
  452. // IP Address control
  453. ON_EN_CHANGE(IDC_IPADDR_ADDRESS, OnChangeIpAddress)
  454. // IP Address array controls
  455. ON_EN_CHANGE(IDC_EDIT_SERVER_NAME, OnChangeEditServerName)
  456. ON_EN_CHANGE(IDC_IPADDR_SERVER_ADDRESS, OnChangeIpAddressArray)
  457. ON_BN_CLICKED(IDC_BUTTON_RESOLVE, OnButtonResolve)
  458. ON_BN_CLICKED(IDC_BUTTON_IPADDR_UP, OnButtonIpAddrUp)
  459. ON_BN_CLICKED(IDC_BUTTON_IPADDR_DOWN, OnButtonIpAddrDown)
  460. ON_BN_CLICKED(IDC_BUTTON_IPADDR_ADD, OnButtonIpAddrAdd)
  461. ON_BN_CLICKED(IDC_BUTTON_IPADDR_DELETE, OnButtonIpAddrDelete)
  462. ON_LBN_SELCHANGE(IDC_LIST_IP_ADDRS, OnSelchangeListIpAddrs)
  463. // binary and encapsulated data
  464. ON_EN_CHANGE(IDC_VALUEDATA, OnChangeValueData)
  465. // route array controls
  466. ON_BN_CLICKED(IDC_BUTTON_ROUTE_ADD, OnButtonAddRoute)
  467. ON_BN_CLICKED(IDC_BUTTON_ROUTE_DEL, OnButtonDelRoute)
  468. END_MESSAGE_MAP()
  469. /////////////////////////////////////////////////////////////////////////////
  470. // COptionsCfgPropPage message handlers
  471. afx_msg long COptionsCfgPropPage::OnSelectOption(UINT wParam, LONG lParam)
  472. {
  473. COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
  474. if (wParam != NULL)
  475. {
  476. CDhcpOptionItem * pOptItem = (CDhcpOptionItem *) ULongToPtr(wParam);
  477. HWND hWnd = NULL;
  478. pOptionsConfig->m_strStartVendor = pOptItem->GetVendor();
  479. pOptionsConfig->m_strStartClass = pOptItem->GetClassName();
  480. pOptionsConfig->m_dhcpStartId = pOptItem->GetOptionId();
  481. if ( (!pOptionsConfig->m_strStartVendor.IsEmpty() ||
  482. !pOptionsConfig->m_strStartClass.IsEmpty()) &&
  483. GetWindowLongPtr(GetSafeHwnd(), GWLP_ID) != IDP_OPTION_ADVANCED)
  484. {
  485. // we're on the basic page, need to switch to advanced
  486. ::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)1, NULL);
  487. hWnd = pOptionsConfig->m_pageAdvanced.GetSafeHwnd();
  488. ::PostMessage(hWnd, WM_SELECTCLASSES, (WPARAM) &pOptionsConfig->m_strStartVendor, (LPARAM) &pOptionsConfig->m_strStartClass);
  489. }
  490. else
  491. if ( (pOptionsConfig->m_strStartVendor.IsEmpty() &&
  492. pOptionsConfig->m_strStartClass.IsEmpty()) &&
  493. GetWindowLongPtr(GetSafeHwnd(), GWLP_ID) != IDP_OPTION_BASIC)
  494. {
  495. // we're on the advanced page, need to switch to basic
  496. ::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)0, NULL);
  497. hWnd = pOptionsConfig->m_pageGeneral.GetSafeHwnd();
  498. }
  499. ::PostMessage(hWnd, WM_SELECTOPTION, 0, 0);
  500. return 0;
  501. }
  502. for (int i = 0; i < m_listctrlOptions.GetItemCount(); i++)
  503. {
  504. COptionTracker * pCurOptTracker =
  505. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(i));
  506. if (pCurOptTracker->m_pOption->QueryId() == pOptionsConfig->m_dhcpStartId)
  507. {
  508. BOOL bDirty = IsDirty();
  509. m_listctrlOptions.SelectItem(i);
  510. m_listctrlOptions.EnsureVisible(i, FALSE);
  511. SetDirty(bDirty);
  512. break;
  513. }
  514. }
  515. // reset this variable since we don't need it anymore
  516. pOptionsConfig->m_dhcpStartId = -1;
  517. return 0;
  518. }
  519. /*---------------------------------------------------------------------------
  520. Handlers for the IP Array controls
  521. ---------------------------------------------------------------------------*/
  522. void COptionsCfgPropPage::OnButtonIpAddrAdd()
  523. {
  524. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  525. CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
  526. DWORD dwIpAddress;
  527. pIpAddr->GetAddress(&dwIpAddress);
  528. if (dwIpAddress)
  529. {
  530. int nSelectedItem = m_listctrlOptions.GetSelectedItem();
  531. // make sure that sometime is selected
  532. Assert(nSelectedItem > -1);
  533. if (nSelectedItem > -1)
  534. {
  535. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
  536. CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
  537. COptionTracker * pOptTracker =
  538. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedItem));
  539. // fill in the information in the option struct
  540. CDhcpOption * pOption = pOptTracker->m_pOption;
  541. CDhcpOptionValue & optValue = pOption->QueryValue();
  542. // check to see if we need to grow the array or not
  543. int nOldUpperBound = optValue.QueryUpperBound();
  544. if ((nOldUpperBound == 1) &&
  545. (optValue.QueryIpAddr() == 0))
  546. {
  547. // this array is empty. Don't need to grow it
  548. nOldUpperBound -= 1;
  549. }
  550. else
  551. {
  552. // Set that the array is growing by 1
  553. optValue.SetUpperBound(nOldUpperBound + 1);
  554. }
  555. optValue.SetIpAddr((DHCP_IP_ADDRESS) dwIpAddress, nOldUpperBound);
  556. pOptTracker->SetDirty(TRUE);
  557. // add to the list box
  558. CString strAddress;
  559. ::UtilCvtIpAddrToWstr(dwIpAddress, &strAddress);
  560. pListBox->AddString(strAddress);
  561. // clear the server edit field and ip address
  562. pServerName->SetWindowText(_T(""));
  563. pIpAddr->ClearAddress();
  564. pIpAddr->SetFocusField(0);
  565. // finally, mark the page as dirty
  566. SetDirty(TRUE);
  567. }
  568. }
  569. else
  570. {
  571. ::DhcpMessageBox(IDS_ERR_DLL_INVALID_ADDRESS);
  572. }
  573. }
  574. void COptionsCfgPropPage::OnButtonIpAddrDelete()
  575. {
  576. int nSelectedOption = m_listctrlOptions.GetSelectedItem();
  577. CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
  578. CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
  579. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
  580. DWORD dwIpAddress;
  581. CString strIpAddress;
  582. int nSelectedIndex = pListBox->GetCurSel();
  583. // get the currently selected item
  584. pListBox->GetText(nSelectedIndex, strIpAddress);
  585. dwIpAddress = UtilCvtWstrToIpAddr(strIpAddress);
  586. // remove from the option
  587. COptionTracker * pOptTracker =
  588. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedOption));
  589. // pOptTracker can be null when the context moves to another option.
  590. // However, this is not disabled, so the user can still try to delete
  591. // an IP since it is active.
  592. //
  593. // Add a null check
  594. if (0 != pOptTracker ) {
  595. // fill in the information in the option struct
  596. CDhcpOption * pOption = pOptTracker->m_pOption;
  597. CDhcpOptionValue & optValue = pOption->QueryValue();
  598. // the listbox should match our array, so we'll remove the same index
  599. optValue.RemoveIpAddr(nSelectedIndex);
  600. optValue.SetUpperBound(optValue.QueryUpperBound() - 1);
  601. // remove from list box
  602. pListBox->DeleteString(nSelectedIndex);
  603. pIpAddr->SetAddress(dwIpAddress);
  604. pServerName->SetWindowText(_T(""));
  605. // mark the option and the page as dirty
  606. pOptTracker->SetDirty(TRUE);
  607. SetDirty(TRUE);
  608. HandleActivationIpArray();
  609. } // if
  610. } // COptionsCfgPropPage::OnButtonIpAddrDelete()
  611. void COptionsCfgPropPage::OnSelchangeListIpAddrs()
  612. {
  613. HandleActivationIpArray();
  614. }
  615. void COptionsCfgPropPage::OnChangeIpAddressArray()
  616. {
  617. HandleActivationIpArray();
  618. }
  619. void COptionsCfgPropPage::OnButtonResolve()
  620. {
  621. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  622. CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
  623. CString strServer;
  624. DHCP_IP_ADDRESS dhipa = 0;
  625. DWORD err = 0;
  626. pServerName->GetWindowText(strServer);
  627. //
  628. // See what type of name it is.
  629. //
  630. switch (UtilCategorizeName(strServer))
  631. {
  632. case HNM_TYPE_IP:
  633. dhipa = ::UtilCvtWstrToIpAddr( strServer ) ;
  634. break ;
  635. case HNM_TYPE_NB:
  636. case HNM_TYPE_DNS:
  637. err = ::UtilGetHostAddress( strServer, & dhipa ) ;
  638. if (!err)
  639. UtilCvtIpAddrToWstr(dhipa, &strServer);
  640. break ;
  641. default:
  642. err = IDS_ERR_BAD_HOST_NAME ;
  643. break ;
  644. }
  645. if (err)
  646. {
  647. ::DhcpMessageBox(err);
  648. }
  649. else
  650. {
  651. CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
  652. pIpAddr->SetAddress(dhipa);
  653. }
  654. }
  655. void COptionsCfgPropPage::OnChangeEditServerName()
  656. {
  657. HandleActivationIpArray();
  658. }
  659. void COptionsCfgPropPage::OnButtonIpAddrDown()
  660. {
  661. CButton * pIpAddrDown =
  662. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
  663. CButton * pIpAddrUp =
  664. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
  665. MoveValue(FALSE, FALSE);
  666. if (pIpAddrDown->IsWindowEnabled())
  667. pIpAddrDown->SetFocus();
  668. else
  669. pIpAddrUp->SetFocus();
  670. }
  671. void COptionsCfgPropPage::OnButtonIpAddrUp()
  672. {
  673. CButton * pIpAddrDown =
  674. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
  675. CButton * pIpAddrUp =
  676. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
  677. MoveValue(FALSE, TRUE);
  678. if (pIpAddrUp->IsWindowEnabled())
  679. pIpAddrUp->SetFocus();
  680. else
  681. pIpAddrDown->SetFocus();
  682. }
  683. /*---------------------------------------------------------------------------
  684. Handlers for the number array controls
  685. ---------------------------------------------------------------------------*/
  686. void COptionsCfgPropPage::OnButtonValueAdd()
  687. {
  688. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  689. COptionTracker * pOptTracker =
  690. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  691. CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
  692. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  693. // Get the OptionValue object
  694. CDhcpOption * pOption = pOptTracker->m_pOption;
  695. CDhcpOptionValue & optValue = pOption->QueryValue();
  696. DWORD dwValue;
  697. DWORD_DWORD dwdwValue;
  698. DWORD dwMask = 0xFFFFFFFF ;
  699. switch ( optValue.QueryDataType() )
  700. {
  701. case DhcpBinaryDataOption :
  702. case DhcpByteOption:
  703. dwMask = 0xFF ;
  704. break ;
  705. case DhcpWordOption:
  706. dwMask = 0xFFFF ;
  707. break ;
  708. } // switch
  709. if (optValue.QueryDataType() == DhcpDWordDWordOption)
  710. {
  711. CString strValue;
  712. pValue->GetWindowText(strValue);
  713. UtilConvertStringToDwordDword(strValue, &dwdwValue);
  714. }
  715. else
  716. {
  717. if (!FGetCtrlDWordValue(pValue->GetSafeHwnd(), &dwValue, 0, dwMask))
  718. return;
  719. }
  720. DWORD err = 0 ;
  721. CATCH_MEM_EXCEPTION
  722. {
  723. // Set that the array is growing by 1
  724. int nOldUpperBound = optValue.QueryUpperBound();
  725. optValue.SetUpperBound(nOldUpperBound + 1);
  726. // now insert the new item as the last item in the array
  727. (optValue.QueryDataType() == DhcpDWordDWordOption) ?
  728. optValue.SetDwordDword(dwdwValue, nOldUpperBound) : optValue.SetNumber(dwValue, nOldUpperBound) ;
  729. }
  730. END_MEM_EXCEPTION(err)
  731. if ( err )
  732. {
  733. ::DhcpMessageBox( err ) ;
  734. }
  735. else
  736. {
  737. pOptTracker->SetDirty(TRUE);
  738. SetDirty(TRUE);
  739. }
  740. //
  741. // update controls. clear the edit control
  742. //
  743. pValue->SetWindowText(_T(""));
  744. FillDataEntry(pOption);
  745. HandleActivationValueArray();
  746. }
  747. void COptionsCfgPropPage::OnButtonValueDelete()
  748. {
  749. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  750. COptionTracker * pOptTracker =
  751. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  752. CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
  753. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  754. // Get the OptionValue object
  755. CDhcpOption * pOption = pOptTracker->m_pOption;
  756. CDhcpOptionValue & optValue = pOption->QueryValue();
  757. /* DWORD dwValue;
  758. DWORD dwMask = 0xFFFFFFFF ;
  759. switch ( optValue.QueryDataType() )
  760. {
  761. case DhcpBinaryDataOption :
  762. case DhcpByteOption:
  763. dwMask = 0xFF ;
  764. break ;
  765. case DhcpWordOption:
  766. dwMask = 0xFFFF ;
  767. break ;
  768. } // switch
  769. */
  770. CString strValue;
  771. int nListBoxIndex = pListBox->GetCurSel();
  772. // get the currently selected item
  773. pListBox->GetText(nListBoxIndex, strValue);
  774. //if (!FGetCtrlDWordValue(pValue->GetSafeHwnd(), &dwValue, 0, dwMask))
  775. // return;
  776. // the listbox should match our array, so we'll remove the same index
  777. (optValue.QueryDataType() == DhcpDWordDWordOption) ?
  778. optValue.RemoveDwordDword(nListBoxIndex) : optValue.RemoveNumber(nListBoxIndex);
  779. optValue.SetUpperBound(optValue.QueryUpperBound() - 1);
  780. // remove from list box
  781. pListBox->DeleteString(nListBoxIndex);
  782. pValue->SetWindowText(strValue);
  783. // mark the option and the page as dirty
  784. pOptTracker->SetDirty(TRUE);
  785. SetDirty(TRUE);
  786. HandleActivationValueArray();
  787. }
  788. void COptionsCfgPropPage::OnButtonValueDown()
  789. {
  790. CButton * pValueDown =
  791. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
  792. CButton * pValueUp =
  793. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
  794. MoveValue(TRUE, FALSE);
  795. if (pValueDown->IsWindowEnabled())
  796. pValueDown->SetFocus();
  797. else
  798. pValueUp->SetFocus();
  799. }
  800. void COptionsCfgPropPage::OnButtonValueUp()
  801. {
  802. CButton * pValueDown =
  803. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
  804. CButton * pValueUp =
  805. reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
  806. MoveValue(TRUE, TRUE);
  807. if (pValueUp->IsWindowEnabled())
  808. pValueUp->SetFocus();
  809. else
  810. pValueDown->SetFocus();
  811. }
  812. void COptionsCfgPropPage::MoveValue(BOOL bValues, BOOL bUp)
  813. {
  814. int nSelectedOption = m_listctrlOptions.GetSelectedItem();
  815. // Get the option that describes this
  816. COptionTracker * pOptTracker =
  817. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedOption));
  818. if ( 0 == pOptTracker ) {
  819. return;
  820. }
  821. CDhcpOption * pOption = pOptTracker->m_pOption;
  822. if ( 0 == pOption ) {
  823. return;
  824. }
  825. CDhcpOptionValue & optValue = pOption->QueryValue();
  826. // Get the correct listbox
  827. CListBox * pListBox;
  828. if (bValues)
  829. {
  830. // this is for values
  831. pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  832. }
  833. else
  834. {
  835. // this is for IpAddrs
  836. pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
  837. }
  838. if ( 0 == pListBox ) {
  839. return;
  840. }
  841. // now get which item is selected in the listbox
  842. int cFocus = pListBox->GetCurSel();
  843. // make sure it's valid for this operation
  844. if ( (bUp && cFocus <= 0) ||
  845. (!bUp && cFocus >= pListBox->GetCount()) )
  846. {
  847. return;
  848. }
  849. DWORD dwValue;
  850. DWORD_DWORD dwdwValue;
  851. DWORD err = 0 ;
  852. // move the value up/down
  853. CATCH_MEM_EXCEPTION
  854. {
  855. if (optValue.QueryDataType() == DhcpDWordDWordOption)
  856. {
  857. DWORD_DWORD dwUpValue;
  858. DWORD_DWORD dwDownValue;
  859. if (bUp)
  860. {
  861. dwdwValue = dwUpValue = optValue.QueryDwordDword(cFocus);
  862. dwDownValue = optValue.QueryDwordDword(cFocus - 1);
  863. optValue.SetDwordDword(dwUpValue, cFocus - 1);
  864. optValue.SetDwordDword(dwDownValue, cFocus);
  865. }
  866. else
  867. {
  868. dwdwValue = dwDownValue = optValue.QueryDwordDword(cFocus);
  869. dwUpValue = optValue.QueryDwordDword(cFocus + 1);
  870. optValue.SetDwordDword(dwDownValue, cFocus + 1);
  871. optValue.SetDwordDword(dwUpValue, cFocus);
  872. }
  873. }
  874. else
  875. {
  876. DWORD dwUpValue;
  877. DWORD dwDownValue;
  878. if (bUp)
  879. {
  880. dwValue = dwUpValue = optValue.QueryNumber(cFocus);
  881. dwDownValue = optValue.QueryNumber(cFocus - 1);
  882. optValue.SetNumber(dwUpValue, cFocus - 1);
  883. optValue.SetNumber(dwDownValue, cFocus);
  884. }
  885. else
  886. {
  887. dwValue = dwDownValue = optValue.QueryNumber(cFocus);
  888. dwUpValue = optValue.QueryNumber(cFocus + 1);
  889. optValue.SetNumber(dwDownValue, cFocus + 1);
  890. optValue.SetNumber(dwUpValue, cFocus);
  891. }
  892. }
  893. }
  894. END_MEM_EXCEPTION(err)
  895. if ( err )
  896. {
  897. ::DhcpMessageBox( err ) ;
  898. }
  899. else
  900. {
  901. // everything is ok, mark this option and the prop sheet
  902. pOptTracker->SetDirty(TRUE);
  903. SetDirty(TRUE);
  904. }
  905. // update the data.
  906. FillDataEntry(pOption);
  907. for (int i = 0; i < pListBox->GetCount(); i++)
  908. {
  909. CString strTemp;
  910. pListBox->GetText(i, strTemp);
  911. if (optValue.QueryDataType() == DhcpDWordDWordOption)
  912. {
  913. DWORD_DWORD dwdwCur;
  914. UtilConvertStringToDwordDword(strTemp, &dwdwCur);
  915. if (dwdwCur.DWord1 == dwdwValue.DWord1 &&
  916. dwdwCur.DWord2 == dwdwValue.DWord2)
  917. {
  918. pListBox->SetCurSel(i);
  919. break;
  920. }
  921. }
  922. else
  923. {
  924. DWORD dwIp = ::UtilCvtWstrToIpAddr(strTemp);
  925. if (dwIp == dwValue)
  926. {
  927. pListBox->SetCurSel(i);
  928. break;
  929. }
  930. }
  931. }
  932. // update the controls
  933. if (bValues)
  934. {
  935. HandleActivationValueArray();
  936. }
  937. else
  938. {
  939. HandleActivationIpArray();
  940. }
  941. }
  942. void COptionsCfgPropPage::OnChangeEditValue()
  943. {
  944. HandleActivationValueArray();
  945. }
  946. void COptionsCfgPropPage::OnClickedRadioDecimal()
  947. {
  948. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  949. COptionTracker * pOptTracker =
  950. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  951. CDhcpOption * pOption = pOptTracker->m_pOption;
  952. FillDataEntry(pOption);
  953. }
  954. void COptionsCfgPropPage::OnClickedRadioHex()
  955. {
  956. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  957. COptionTracker * pOptTracker =
  958. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  959. CDhcpOption * pOption = pOptTracker->m_pOption;
  960. FillDataEntry(pOption);
  961. }
  962. void COptionsCfgPropPage::OnSelchangeListValues()
  963. {
  964. HandleActivationValueArray();
  965. }
  966. /*---------------------------------------------------------------------------
  967. Handlers for the binary and encapsulated data
  968. ---------------------------------------------------------------------------*/
  969. void COptionsCfgPropPage::OnChangeValueData()
  970. {
  971. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  972. COptionTracker * pOptTracker =
  973. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  974. CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
  975. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  976. // Get the OptionValue object
  977. CDhcpOption * pOption = pOptTracker->m_pOption;
  978. CDhcpOptionValue & optValue = pOption->QueryValue();
  979. // get the info from the control
  980. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(GetDlgItem(IDC_VALUEDATA)->GetSafeHwnd(), GWLP_USERDATA);
  981. DWORD err = 0;
  982. CATCH_MEM_EXCEPTION
  983. {
  984. // size we don't know what changed, we just have to copy all of the data
  985. for (int i = 0; i < pHexEditData->cbBuffer; i++)
  986. {
  987. DWORD dwValue = (BYTE) pHexEditData->pBuffer[i];
  988. optValue.SetNumber(dwValue, i);
  989. }
  990. }
  991. END_MEM_EXCEPTION(err)
  992. // mark the option and the page as dirty
  993. pOptTracker->SetDirty(TRUE);
  994. SetDirty(TRUE);
  995. }
  996. /*---------------------------------------------------------------------------
  997. Handlers for the single number entry controls
  998. ---------------------------------------------------------------------------*/
  999. void COptionsCfgPropPage::OnChangeEditDword()
  1000. {
  1001. HandleValueEdit();
  1002. }
  1003. /*---------------------------------------------------------------------------
  1004. Handlers for the single IP Address entry controls
  1005. ---------------------------------------------------------------------------*/
  1006. void COptionsCfgPropPage::OnChangeIpAddress()
  1007. {
  1008. HandleValueEdit();
  1009. }
  1010. /*---------------------------------------------------------------------------
  1011. Handlers for the string entry controls
  1012. ---------------------------------------------------------------------------*/
  1013. void COptionsCfgPropPage::OnChangeEditString()
  1014. {
  1015. HandleValueEdit();
  1016. }
  1017. /////////////////////////////////////////////////////////////////////////////
  1018. // CAddRoute dialog
  1019. CAddRoute::CAddRoute( CWnd *pParent)
  1020. : CBaseDialog( CAddRoute::IDD, pParent )
  1021. {
  1022. m_ipaDest.ClearAddress();
  1023. m_ipaMask.ClearAddress();
  1024. m_ipaRouter.ClearAddress();
  1025. m_bChange = FALSE;
  1026. }
  1027. void CAddRoute::DoDataExchange(CDataExchange* pDX)
  1028. {
  1029. CBaseDialog::DoDataExchange(pDX);
  1030. //{{AFX_DATA_MAP(CAddRoute)
  1031. //}}AFX_DATA_MAP
  1032. DDX_Control(pDX, IDC_IPADDR_ADDRESS, m_ipaDest);
  1033. DDX_Control(pDX, IDC_IPADDR_ADDRESS2, m_ipaMask);
  1034. DDX_Control(pDX, IDC_IPADDR_ADDRESS3, m_ipaRouter);
  1035. }
  1036. BEGIN_MESSAGE_MAP(CAddRoute, CBaseDialog)
  1037. //{{AFX_MSG_MAP(CAddRoute)
  1038. //}}AFX_MSG_MAP
  1039. END_MESSAGE_MAP()
  1040. /////////////////////////////////////////////////////////////////////////////
  1041. // CAddReservation message handlers
  1042. BOOL CAddRoute::OnInitDialog()
  1043. {
  1044. CBaseDialog::OnInitDialog();
  1045. // set focus on the destination..
  1046. CWnd *pWnd = GetDlgItem(IDC_IPADDR_ADDRESS);
  1047. if( NULL != pWnd )
  1048. {
  1049. pWnd->SetFocus();
  1050. return FALSE;
  1051. }
  1052. return TRUE; // return TRUE unless you set the focus to a control
  1053. // EXCEPTION: OCX Property Pages should return FALSE
  1054. }
  1055. void CAddRoute::OnOK()
  1056. {
  1057. DWORD err = 0;
  1058. UpdateData();
  1059. m_ipaDest.GetAddress( &Dest );
  1060. m_ipaMask.GetAddress( &Mask );
  1061. m_ipaRouter.GetAddress( &Router );
  1062. // validate the ip addresses
  1063. if( 0 == Router || (0 != Mask && 0 == Dest) ||
  1064. 0 != ((~Mask) & Dest) ||
  1065. (0 != ((~Mask) & ((~Mask)+1)) ) )
  1066. {
  1067. ::DhcpMessageBox( IDS_ERR_INVALID_ROUTE_ENTRY );
  1068. }
  1069. else
  1070. {
  1071. m_bChange = TRUE;
  1072. CBaseDialog::OnOK();
  1073. }
  1074. //CBaseDialog::OnOK();
  1075. }
  1076. /*---------------------------------------------------------------------------
  1077. Handlers for the route add data entry controls
  1078. ---------------------------------------------------------------------------*/
  1079. void COptionsCfgPropPage::OnButtonAddRoute()
  1080. {
  1081. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  1082. COptionTracker * pOptTracker =
  1083. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  1084. // Get the OptionValue object
  1085. CDhcpOption * pOption = pOptTracker->m_pOption;
  1086. CDhcpOptionValue & optValue = pOption->QueryValue();
  1087. // get the routes list control
  1088. CListCtrl *pList = reinterpret_cast<CListCtrl *>(
  1089. GetDlgItem( IDC_LIST_OF_ROUTES ) );
  1090. // get the add and remove buttons
  1091. CButton *pAdd = reinterpret_cast<CButton *>(
  1092. GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
  1093. CButton *pRemove = reinterpret_cast<CButton *>(
  1094. GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
  1095. // throw the add route UI
  1096. CAddRoute NewRoute(NULL);
  1097. NewRoute.DoModal();
  1098. if( NewRoute.m_bChange )
  1099. {
  1100. CString strDest, strMask, strRouter;
  1101. // obtain the three strings..
  1102. ::UtilCvtIpAddrToWstr(NewRoute.Dest, &strDest);
  1103. ::UtilCvtIpAddrToWstr(NewRoute.Mask, &strMask);
  1104. ::UtilCvtIpAddrToWstr(NewRoute.Router, &strRouter);
  1105. LV_ITEM lvi;
  1106. lvi.mask = LVIF_TEXT;
  1107. lvi.iItem = pList->GetItemCount();
  1108. lvi.iSubItem = 0;
  1109. lvi.pszText = (LPTSTR)(LPCTSTR)strDest;
  1110. lvi.iImage = 0;
  1111. lvi.stateMask = 0;
  1112. int nItem = pList->InsertItem(&lvi);
  1113. pList->SetItemText(nItem, 1, strMask);
  1114. pList->SetItemText(nItem, 2, strRouter);
  1115. pOptTracker->SetDirty(TRUE);
  1116. SetDirty(TRUE);
  1117. }
  1118. // now walk through the list control and get the values and
  1119. // put them back onto the optValue
  1120. HandleActivationRouteArray( &optValue );
  1121. }
  1122. void COptionsCfgPropPage::OnButtonDelRoute()
  1123. {
  1124. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  1125. COptionTracker * pOptTracker =
  1126. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  1127. // Get the OptionValue object
  1128. CDhcpOption * pOption = pOptTracker->m_pOption;
  1129. CDhcpOptionValue & optValue = pOption->QueryValue();
  1130. // get the routes list control
  1131. CListCtrl *pList = reinterpret_cast<CListCtrl *>(
  1132. GetDlgItem( IDC_LIST_OF_ROUTES ) );
  1133. // get the add and remove buttons
  1134. CButton *pAdd = reinterpret_cast<CButton *>(
  1135. GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
  1136. CButton *pRemove = reinterpret_cast<CButton *>(
  1137. GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
  1138. // get the selected column and delete it
  1139. int nItem = pList->GetNextItem(-1, LVNI_SELECTED);
  1140. while( nItem != -1 ) {
  1141. pList->DeleteItem( nItem ) ;
  1142. nItem = pList->GetNextItem(-1, LVNI_SELECTED);
  1143. pOptTracker->SetDirty(TRUE);
  1144. SetDirty(TRUE);
  1145. }
  1146. // now walk through the list control and get the values and
  1147. // put them back onto the optValue
  1148. HandleActivationRouteArray( &optValue );
  1149. }
  1150. BOOL COptionsCfgPropPage::OnInitDialog()
  1151. {
  1152. CPropertyPageBase::OnInitDialog();
  1153. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1154. // set the title
  1155. ((COptionsConfig *) GetHolder())->SetTitle();
  1156. // initialize the list control
  1157. InitListCtrl();
  1158. // initialize the option data
  1159. DWORD dwErr = ((COptionsConfig *) GetHolder())->InitData();
  1160. if (dwErr != ERROR_SUCCESS)
  1161. {
  1162. // CODEWORK: need to exit gracefull if this happens
  1163. ::DhcpMessageBox(dwErr);
  1164. }
  1165. else
  1166. {
  1167. // Fill the options for this page type - basic, advanced, custom
  1168. ((COptionsConfig *) GetHolder())->FillOptions(_T(""), _T(""), m_listctrlOptions);
  1169. }
  1170. // Create the type control switcher
  1171. m_cgsTypes.Create(this,IDC_DATA_ENTRY_ANCHOR,cgsPreCreateAll);
  1172. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_NONE, IDD_DATA_ENTRY_NONE, NULL);
  1173. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_DWORD, IDD_DATA_ENTRY_DWORD, NULL);
  1174. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS, IDD_DATA_ENTRY_IPADDRESS, NULL);
  1175. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY, IDD_DATA_ENTRY_IPADDRESS_ARRAY, NULL);
  1176. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_STRING, IDD_DATA_ENTRY_STRING, NULL);
  1177. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY_ARRAY, IDD_DATA_ENTRY_BINARY_ARRAY, NULL);
  1178. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY, IDD_DATA_ENTRY_BINARY, NULL);
  1179. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_ROUTE_ARRAY, IDD_DATA_ENTRY_ROUTE_ARRAY, NULL);
  1180. m_hexData.SubclassDlgItem(IDC_VALUEDATA, this);
  1181. SwitchDataEntry(-1, -1, 0, TRUE);
  1182. SetDirty(FALSE);
  1183. m_bInitialized = TRUE;
  1184. return TRUE; // return TRUE unless you set the focus to a control
  1185. // EXCEPTION: OCX Property Pages should return FALSE
  1186. }
  1187. void COptionsCfgPropPage::SelectOption(CDhcpOption * pOption)
  1188. {
  1189. for (int i = 0; i < m_listctrlOptions.GetItemCount(); i++)
  1190. {
  1191. COptionTracker * pCurOptTracker =
  1192. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(i));
  1193. if (pOption->QueryId() == pCurOptTracker->m_pOption->QueryId())
  1194. {
  1195. m_listctrlOptions.SelectItem(i);
  1196. m_listctrlOptions.EnsureVisible(i, FALSE);
  1197. }
  1198. }
  1199. }
  1200. void COptionsCfgPropPage::SwitchDataEntry(int datatype, int optiontype, BOOL fRouteArray, BOOL bEnable)
  1201. {
  1202. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1203. CString strType;
  1204. if( fRouteArray )
  1205. {
  1206. // ignore any other types passed and use route_array type
  1207. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_ROUTE_ARRAY);
  1208. }
  1209. else
  1210. switch(datatype)
  1211. {
  1212. case DhcpByteOption:
  1213. case DhcpWordOption:
  1214. case DhcpDWordOption:
  1215. case DhcpDWordDWordOption:
  1216. {
  1217. // build our string for the type of data
  1218. if ( (datatype == DhcpByteOption) ||
  1219. (datatype == DhcpEncapsulatedDataOption) )
  1220. {
  1221. strType.LoadString(IDS_INFO_TYPOPT_BYTE);
  1222. }
  1223. else
  1224. if (datatype == DhcpWordOption)
  1225. {
  1226. strType.LoadString(IDS_INFO_TYPOPT_WORD);
  1227. }
  1228. else
  1229. if (datatype == DhcpDWordOption)
  1230. {
  1231. strType.LoadString(IDS_INFO_TYPOPT_DWORD);
  1232. }
  1233. else
  1234. {
  1235. strType.LoadString(IDS_INFO_TYPOPT_DWDW);
  1236. }
  1237. if (optiontype == DhcpArrayTypeOption)
  1238. {
  1239. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY_ARRAY);
  1240. CButton * pRadioDecimal =
  1241. reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
  1242. pRadioDecimal->SetCheck(1);
  1243. // set some information text
  1244. CString strFrameText;
  1245. strFrameText.LoadString(IDS_DATA_ENTRY_FRAME);
  1246. strFrameText += _T(" ") + strType;
  1247. CWnd * pWnd = GetDlgItem(IDC_STATIC_BINARY_ARRAY_FRAME);
  1248. pWnd->SetWindowText(strFrameText);
  1249. }
  1250. else
  1251. {
  1252. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_DWORD);
  1253. CWnd * pWnd = GetDlgItem(IDC_STATIC_TYPE);
  1254. pWnd->SetWindowText(strType);
  1255. }
  1256. }
  1257. break;
  1258. case DhcpBinaryDataOption:
  1259. case DhcpEncapsulatedDataOption:
  1260. {
  1261. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY);
  1262. }
  1263. break;
  1264. case DhcpIpAddressOption:
  1265. if (optiontype == DhcpArrayTypeOption)
  1266. {
  1267. strType.LoadString(IDS_INFO_TYPOPT_BYTE);
  1268. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY);
  1269. CButton * pRadioDecimal =
  1270. reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
  1271. pRadioDecimal->SetCheck(1);
  1272. // set some information text
  1273. CString strFrameText;
  1274. strFrameText.LoadString(IDS_DATA_ENTRY_FRAME);
  1275. strFrameText += _T(" ") + strType;
  1276. CWnd * pWnd = GetDlgItem(IDC_STATIC_BINARY_ARRAY_FRAME);
  1277. pWnd->SetWindowText(strFrameText);
  1278. }
  1279. else
  1280. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_IPADDRESS);
  1281. break;
  1282. case DhcpStringDataOption:
  1283. if (optiontype == DhcpArrayTypeOption)
  1284. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_BINARY_ARRAY);
  1285. else
  1286. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_STRING);
  1287. break;
  1288. default:
  1289. m_cgsTypes.ShowGroup(IDC_DATA_ENTRY_NONE);
  1290. break;
  1291. }
  1292. // enable/disable the current group
  1293. m_cgsTypes.EnableGroup(-1, bEnable);
  1294. }
  1295. const int ROUTE_LIST_COL_WIDTHS[3] = {
  1296. 80, 80, 80
  1297. };
  1298. const int ROUTE_LIST_COL_HEADERS[3] = {
  1299. IDS_ROUTE_LIST_COL_DEST,
  1300. IDS_ROUTE_LIST_COL_MASK,
  1301. IDS_ROUTE_LIST_COL_ROUTER
  1302. };
  1303. void COptionsCfgPropPage::FillDataEntry(CDhcpOption * pOption)
  1304. {
  1305. CDhcpOptionValue & optValue = pOption->QueryValue();
  1306. int datatype = pOption->QueryDataType();
  1307. int optiontype = pOption->QueryOptType();
  1308. BOOL fRouteArray = (
  1309. !pOption->IsClassOption() &&
  1310. (DHCP_OPTION_ID_CSR == pOption->QueryId()) &&
  1311. optiontype == DhcpUnaryElementTypeOption &&
  1312. datatype == DhcpBinaryDataOption
  1313. );
  1314. CButton * pRadioHex =
  1315. reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_HEX));
  1316. BOOL bUseHex = pRadioHex->GetCheck();
  1317. if( fRouteArray )
  1318. {
  1319. const CByteArray * pbaData = optValue.QueryBinaryArray();
  1320. int nDataSize = (int)pbaData->GetSize();
  1321. LPBYTE pData = (LPBYTE) pbaData->GetData();
  1322. // initialize the list control view with data
  1323. CListCtrl *pList =
  1324. reinterpret_cast<CListCtrl *>(GetDlgItem(IDC_LIST_OF_ROUTES));
  1325. Assert(pList);
  1326. pList->DeleteAllItems();
  1327. pList->SetExtendedStyle(LVS_EX_FULLROWSELECT);
  1328. pList->DeleteColumn(2);
  1329. pList->DeleteColumn(1);
  1330. pList->DeleteColumn(0);
  1331. LV_COLUMN lvc;
  1332. CString strColHeader;
  1333. for( int i = 0; i < 3; i ++ )
  1334. {
  1335. lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT |
  1336. LVCF_WIDTH ;
  1337. lvc.iSubItem = i;
  1338. lvc.fmt = LVCFMT_LEFT;
  1339. lvc.cx = ROUTE_LIST_COL_WIDTHS[i];
  1340. strColHeader.LoadString(ROUTE_LIST_COL_HEADERS[i]);
  1341. lvc.pszText = (LPTSTR)(LPCTSTR)strColHeader;
  1342. pList->InsertColumn( i, &lvc );
  1343. }
  1344. // convert pData to list of ip addresses as per RFC
  1345. while( nDataSize > sizeof(DWORD) )
  1346. {
  1347. // first 1 byte contains the # of bits in subnetmask
  1348. nDataSize --;
  1349. BYTE nBitsMask = *pData ++;
  1350. DWORD Mask = (~0);
  1351. if( nBitsMask < 32 ) Mask <<= (32-nBitsMask);
  1352. // based on the # of bits, the next few bytes contain
  1353. // the subnet address for the 1-bits of subnet mask
  1354. int nBytesDest = (nBitsMask+7)/8;
  1355. if( nBytesDest > 4 ) nBytesDest = 4;
  1356. DWORD Dest = 0;
  1357. memcpy( &Dest, pData, nBytesDest );
  1358. pData += nBytesDest;
  1359. nDataSize -= nBytesDest;
  1360. // subnet address is obviously in network order.
  1361. Dest = ntohl(Dest);
  1362. // now the four bytes would be the router address
  1363. DWORD Router = 0;
  1364. if( nDataSize < sizeof(DWORD) )
  1365. {
  1366. Assert( FALSE ); break;
  1367. }
  1368. memcpy(&Router, pData, sizeof(DWORD));
  1369. Router = ntohl( Router );
  1370. pData += sizeof(DWORD);
  1371. nDataSize -= sizeof(DWORD);
  1372. // now fill the list box..
  1373. CString strDest, strMask, strRouter;
  1374. ::UtilCvtIpAddrToWstr(Dest, &strDest);
  1375. ::UtilCvtIpAddrToWstr(Mask, &strMask);
  1376. ::UtilCvtIpAddrToWstr(Router, &strRouter);
  1377. LV_ITEM lvi;
  1378. lvi.mask = LVIF_TEXT;
  1379. lvi.iItem = pList->GetItemCount();
  1380. lvi.iSubItem = 0;
  1381. lvi.pszText = (LPTSTR)(LPCTSTR) strDest;
  1382. lvi.iImage = 0;
  1383. lvi.stateMask = 0;
  1384. int nItem = pList->InsertItem(&lvi);
  1385. pList->SetItemText(nItem, 1, strMask);
  1386. pList->SetItemText(nItem, 2, strRouter);
  1387. }
  1388. HandleActivationRouteArray();
  1389. }
  1390. else
  1391. switch(datatype)
  1392. {
  1393. case DhcpByteOption:
  1394. case DhcpWordOption:
  1395. case DhcpDWordOption:
  1396. if (optiontype == DhcpArrayTypeOption)
  1397. {
  1398. CListBox * pListBox =
  1399. reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  1400. Assert(pListBox);
  1401. pListBox->ResetContent();
  1402. for (int i = 0; i < optValue.QueryUpperBound(); i++)
  1403. {
  1404. long lValue = optValue.QueryNumber(i);
  1405. CString strValue;
  1406. if (bUseHex)
  1407. strValue.Format(_T("0x%x"), lValue);
  1408. else
  1409. strValue.Format(_T("%d"), lValue);
  1410. pListBox->AddString(strValue);
  1411. }
  1412. HandleActivationValueArray();
  1413. }
  1414. else
  1415. {
  1416. CString strValue;
  1417. optValue.QueryDisplayString(strValue);
  1418. CWnd * pWnd = GetDlgItem(IDC_EDIT_DWORD);
  1419. Assert(pWnd);
  1420. pWnd->SetWindowText(strValue);
  1421. }
  1422. break;
  1423. case DhcpIpAddressOption:
  1424. if (optiontype == DhcpArrayTypeOption)
  1425. {
  1426. CListBox * pListBox =
  1427. reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
  1428. Assert(pListBox);
  1429. pListBox->ResetContent();
  1430. for (int i = 0; i < optValue.QueryUpperBound(); i++)
  1431. {
  1432. CString strValue;
  1433. DHCP_IP_ADDRESS ipAddress = optValue.QueryIpAddr(i);
  1434. if (ipAddress)
  1435. {
  1436. ::UtilCvtIpAddrToWstr(ipAddress, &strValue);
  1437. pListBox->AddString(strValue);
  1438. }
  1439. }
  1440. HandleActivationIpArray();
  1441. }
  1442. else
  1443. {
  1444. CWndIpAddress * pIpAddr =
  1445. reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_ADDRESS));
  1446. DHCP_IP_ADDRESS ipAddress = optValue.QueryIpAddr();
  1447. if (ipAddress)
  1448. pIpAddr->SetAddress(ipAddress);
  1449. else
  1450. pIpAddr->ClearAddress();
  1451. }
  1452. break;
  1453. case DhcpStringDataOption:
  1454. if (optiontype == DhcpArrayTypeOption)
  1455. {
  1456. CListBox * pListBox =
  1457. reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  1458. Assert(pListBox);
  1459. pListBox->ResetContent();
  1460. for (int i = 0; i < optValue.QueryUpperBound(); i++)
  1461. {
  1462. long lValue = optValue.QueryNumber(i);
  1463. CString strValue;
  1464. if (bUseHex)
  1465. strValue.Format(_T("0x%x"), lValue);
  1466. else
  1467. strValue.Format(_T("%d"), lValue);
  1468. pListBox->AddString(strValue);
  1469. }
  1470. }
  1471. else
  1472. {
  1473. CWnd * pWnd = GetDlgItem(IDC_EDIT_STRING_VALUE);
  1474. pWnd->SetWindowText(optValue.QueryString());
  1475. }
  1476. break;
  1477. case DhcpDWordDWordOption:
  1478. if (optiontype == DhcpArrayTypeOption)
  1479. {
  1480. CListBox * pListBox =
  1481. reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  1482. Assert(pListBox);
  1483. pListBox->ResetContent();
  1484. for (int i = 0; i < optValue.QueryUpperBound(); i++)
  1485. {
  1486. DWORD_DWORD dwdwValue = optValue.QueryDwordDword(i);
  1487. CString strValue;
  1488. ::UtilConvertDwordDwordToString(&dwdwValue, &strValue, !bUseHex);
  1489. pListBox->AddString(strValue);
  1490. }
  1491. HandleActivationValueArray();
  1492. }
  1493. else
  1494. {
  1495. CString strValue;
  1496. optValue.QueryDisplayString(strValue);
  1497. CWnd * pWnd = GetDlgItem(IDC_EDIT_DWORD);
  1498. Assert(pWnd);
  1499. pWnd->SetWindowText(strValue);
  1500. }
  1501. break;
  1502. case DhcpBinaryDataOption:
  1503. case DhcpEncapsulatedDataOption:
  1504. {
  1505. const CByteArray * pbaData = optValue.QueryBinaryArray();
  1506. int nDataSize = (int)pbaData->GetSize();
  1507. LPBYTE pData = (LPBYTE) pbaData->GetData();
  1508. memset(m_BinaryBuffer, 0, sizeof(m_BinaryBuffer));
  1509. if (pData)
  1510. {
  1511. memcpy(m_BinaryBuffer, pData, nDataSize);
  1512. }
  1513. SendDlgItemMessage(IDC_VALUEDATA, HEM_SETBUFFER, (WPARAM)
  1514. nDataSize, (LPARAM) m_BinaryBuffer);
  1515. }
  1516. break;
  1517. default:
  1518. Assert(FALSE);
  1519. break;
  1520. }
  1521. }
  1522. void COptionsCfgPropPage::InitListCtrl()
  1523. {
  1524. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1525. // set image lists
  1526. m_StateImageList.Create(IDB_LIST_STATE, 16, 1, RGB(255, 0, 0));
  1527. m_listctrlOptions.SetImageList(NULL, LVSIL_NORMAL);
  1528. m_listctrlOptions.SetImageList(NULL, LVSIL_SMALL);
  1529. m_listctrlOptions.SetImageList(&m_StateImageList, LVSIL_STATE);
  1530. // insert a column so we can see the items
  1531. LV_COLUMN lvc;
  1532. CString strColumnHeader;
  1533. for (int i = 0; i < MAX_COLUMNS; i++)
  1534. {
  1535. lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  1536. lvc.iSubItem = i;
  1537. lvc.fmt = LVCFMT_LEFT;
  1538. lvc.cx = COLUMN_WIDTHS[i];
  1539. strColumnHeader.LoadString(COLUMN_HEADERS[i]);
  1540. lvc.pszText = (LPTSTR) (LPCTSTR) strColumnHeader;
  1541. m_listctrlOptions.InsertColumn(i, &lvc);
  1542. }
  1543. m_listctrlOptions.SetFullRowSel(TRUE);
  1544. }
  1545. void COptionsCfgPropPage::OnDestroy()
  1546. {
  1547. CImageList * pStateImageList = NULL;
  1548. // if the control has been initialized, we need to cleanup
  1549. if (m_listctrlOptions.GetSafeHwnd() != NULL)
  1550. {
  1551. pStateImageList = m_listctrlOptions.SetImageList(NULL, LVSIL_STATE);
  1552. if (pStateImageList)
  1553. //pStateImageList->DeleteImageList();
  1554. // The OptionTrackers get delete in the destructor
  1555. m_listctrlOptions.DeleteAllItems();
  1556. }
  1557. m_listctrlOptions.DestroyWindow();
  1558. CPropertyPageBase::OnDestroy();
  1559. }
  1560. void COptionsCfgPropPage::OnItemchangedListOptions(NMHDR* pNMHDR, LRESULT* pResult)
  1561. {
  1562. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  1563. if (pNMListView->uChanged & LVIF_STATE)
  1564. {
  1565. BOOL bUpdate = FALSE, bEnable = FALSE;
  1566. UINT uFlags = pNMListView->uOldState ^ pNMListView->uNewState;
  1567. COptionTracker * pCurOptTracker =
  1568. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(pNMListView->iItem));
  1569. CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
  1570. BOOL bOldSelected = pNMListView->uOldState & LVIS_SELECTED;
  1571. BOOL bNewSelected = pNMListView->uNewState & LVIS_SELECTED;
  1572. BOOL bStateImageChanged = (pNMListView->uOldState & LVIS_STATEIMAGEMASK) !=
  1573. (pNMListView->uNewState & LVIS_STATEIMAGEMASK);
  1574. BOOL bIsSelected = m_listctrlOptions.IsSelected(pNMListView->iItem);
  1575. // has this item been selected?
  1576. if (!bOldSelected && bNewSelected)
  1577. {
  1578. // check to see if this item is checked
  1579. bEnable = m_listctrlOptions.GetCheck(pNMListView->iItem);
  1580. bUpdate = TRUE;
  1581. }
  1582. // has item been checked/unchecked?
  1583. if (bStateImageChanged && m_bInitialized)
  1584. {
  1585. // mark this as dirty and enable apply button
  1586. pCurOptTracker->SetDirty(TRUE);
  1587. SetDirty(TRUE);
  1588. // update the state in the option tracker
  1589. UINT uCurrentState = m_listctrlOptions.GetCheck(pNMListView->iItem) ? OPTION_STATE_ACTIVE : OPTION_STATE_INACTIVE;
  1590. pCurOptTracker->SetCurrentState(uCurrentState);
  1591. // we force the the selection of an item if the user changes it's checkbox state
  1592. if (!bIsSelected)
  1593. m_listctrlOptions.SelectItem(pNMListView->iItem);
  1594. }
  1595. // if we are changing the check box on a selected item, then update
  1596. if ((bStateImageChanged && bIsSelected))
  1597. {
  1598. bEnable = (pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(LISTVIEWEX_CHECKED));
  1599. bUpdate = TRUE;
  1600. }
  1601. // item needs to be updated
  1602. if (bUpdate)
  1603. {
  1604. BOOL fRouteArray = (
  1605. !pCurOption->IsClassOption() &&
  1606. (DHCP_OPTION_ID_CSR == pCurOption->QueryId()) &&
  1607. DhcpUnaryElementTypeOption ==
  1608. pCurOption->QueryOptType() &&
  1609. DhcpBinaryDataOption == pCurOption->QueryDataType()
  1610. );
  1611. SwitchDataEntry(
  1612. pCurOption->QueryDataType(),
  1613. pCurOption->QueryOptType(), fRouteArray, bEnable);
  1614. FillDataEntry(pCurOption);
  1615. // This sets focus to the first control in the group to edit the value of the
  1616. // selected option. This causes a problem when using the keyboard to move down
  1617. // the list of options in that the focus keeps jumping from the listctrl to
  1618. // the option value edit fields...
  1619. /*
  1620. CWnd* pWndNext = GetNextDlgTabItem(&m_listctrlOptions);
  1621. if (pWndNext != NULL)
  1622. {
  1623. pWndNext->SetFocus();
  1624. }
  1625. */
  1626. }
  1627. }
  1628. *pResult = 0;
  1629. }
  1630. BOOL COptionsCfgPropPage::OnSetActive()
  1631. {
  1632. return CPropertyPageBase::OnSetActive();
  1633. }
  1634. void COptionsCfgPropPage::HandleActivationIpArray()
  1635. {
  1636. CString strServerName;
  1637. CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_SERVER_ADDRESS));
  1638. CButton * pResolve = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_RESOLVE));
  1639. CButton * pAdd = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_ADD));
  1640. CButton * pRemove = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DELETE));
  1641. CButton * pUp = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_UP));
  1642. CButton * pDown = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_IPADDR_DOWN));
  1643. CEdit * pServerName = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_SERVER_NAME));
  1644. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_IP_ADDRS));
  1645. // set the resolve button
  1646. pServerName->GetWindowText(strServerName);
  1647. pResolve->EnableWindow(strServerName.GetLength() > 0);
  1648. // the add button
  1649. DWORD dwIpAddr = 0;
  1650. pIpAddr->GetAddress(&dwIpAddr);
  1651. if (GetFocus() == pAdd &&
  1652. dwIpAddr == 0)
  1653. {
  1654. pIpAddr->SetFocus();
  1655. SetDefID(IDOK);
  1656. }
  1657. pAdd->EnableWindow(dwIpAddr != 0);
  1658. // the remove button
  1659. if (GetFocus() == pRemove &&
  1660. pListBox->GetCurSel() < 0)
  1661. {
  1662. pIpAddr->SetFocus();
  1663. SetDefID(IDOK);
  1664. }
  1665. pRemove->EnableWindow(pListBox->GetCurSel() >= 0);
  1666. // up and down buttons
  1667. BOOL bEnableUp = (pListBox->GetCurSel() >= 0) && (pListBox->GetCurSel() != 0);
  1668. pUp->EnableWindow(bEnableUp);
  1669. BOOL bEnableDown = (pListBox->GetCurSel() >= 0) && (pListBox->GetCurSel() < pListBox->GetCount() - 1);
  1670. pDown->EnableWindow(bEnableDown);
  1671. }
  1672. void COptionsCfgPropPage::HandleActivationValueArray()
  1673. {
  1674. CButton * pAdd = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_ADD));
  1675. CButton * pRemove = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DELETE));
  1676. CButton * pUp = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_UP));
  1677. CButton * pDown = reinterpret_cast<CButton *>(GetDlgItem(IDC_BUTTON_VALUE_DOWN));
  1678. CButton * pRadioDecimal = reinterpret_cast<CButton *>(GetDlgItem(IDC_RADIO_DECIMAL));
  1679. CEdit * pValue = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_VALUE));
  1680. CListBox * pListBox = reinterpret_cast<CListBox *>(GetDlgItem(IDC_LIST_VALUES));
  1681. CString strValue;
  1682. // set the add button
  1683. pValue->GetWindowText(strValue);
  1684. if (GetFocus() == pAdd &&
  1685. strValue.GetLength() == 0)
  1686. {
  1687. pValue->SetFocus();
  1688. SetDefID(IDOK);
  1689. }
  1690. pAdd->EnableWindow(strValue.GetLength() > 0);
  1691. // the remove button
  1692. if (GetFocus() == pRemove &&
  1693. pListBox->GetCurSel() == LB_ERR)
  1694. {
  1695. pValue->SetFocus();
  1696. SetDefID(IDOK);
  1697. }
  1698. pRemove->EnableWindow(pListBox->GetCurSel() != LB_ERR);
  1699. // up and down buttons
  1700. BOOL bEnableUp = (pListBox->GetCurSel() != LB_ERR) && (pListBox->GetCurSel() > 0);
  1701. pUp->EnableWindow(bEnableUp);
  1702. BOOL bEnableDown = (pListBox->GetCurSel() != LB_ERR) && (pListBox->GetCurSel() < pListBox->GetCount() - 1);
  1703. pDown->EnableWindow(bEnableDown);
  1704. }
  1705. void COptionsCfgPropPage::HandleActivationRouteArray(
  1706. CDhcpOptionValue *optValue
  1707. )
  1708. {
  1709. // this route will enable the right dialog items and also set
  1710. // focus correctly.
  1711. // get the routes list control
  1712. CListCtrl *pList = reinterpret_cast<CListCtrl *>(
  1713. GetDlgItem( IDC_LIST_OF_ROUTES ) );
  1714. // get the add and remove buttons
  1715. CButton *pAdd = reinterpret_cast<CButton *>(
  1716. GetDlgItem(IDC_BUTTON_ROUTE_ADD) );
  1717. CButton *pRemove = reinterpret_cast<CButton *>(
  1718. GetDlgItem(IDC_BUTTON_ROUTE_DEL) );
  1719. // enable the remove button only if there are any
  1720. // elements at all
  1721. pAdd->EnableWindow(TRUE);
  1722. pRemove->EnableWindow( pList->GetItemCount() != 0 );
  1723. if( optValue )
  1724. {
  1725. // if there are no elements, then set focus on Add
  1726. if( pList->GetItemCount() == 0 )
  1727. {
  1728. pAdd->SetFocus();
  1729. }
  1730. else
  1731. {
  1732. pList->SetFocus();
  1733. pList->SetItemState( 0, LVIS_FOCUSED , LVIF_STATE );
  1734. }
  1735. // also, format the whole list of ip addresses into
  1736. // binary type.. allocate large enough buffer
  1737. int nItems = pList->GetItemCount();
  1738. LPBYTE Buffer = new BYTE [sizeof(DWORD)*4 * nItems];
  1739. if( NULL != Buffer )
  1740. {
  1741. int BufSize = 0;
  1742. for( int i = 0 ; i < nItems ; i ++ )
  1743. {
  1744. DHCP_IP_ADDRESS Dest, Mask, Router;
  1745. Dest = UtilCvtWstrToIpAddr(pList->GetItemText(i, 0));
  1746. Mask = UtilCvtWstrToIpAddr(pList->GetItemText(i, 1));
  1747. Router = UtilCvtWstrToIpAddr(pList->GetItemText(i, 2));
  1748. Dest = htonl(Dest);
  1749. Router = htonl(Router);
  1750. int nBitsInMask = 0;
  1751. while( Mask != 0 ) {
  1752. nBitsInMask ++; Mask = (Mask << 1);
  1753. }
  1754. // first add destination descriptor
  1755. // first byte contains # of bits in mask
  1756. // next few bytes contain the dest address for only
  1757. // the significant octets
  1758. Buffer[BufSize++] = (BYTE)nBitsInMask;
  1759. memcpy(&Buffer[BufSize], &Dest, (nBitsInMask+7)/8);
  1760. BufSize += (nBitsInMask+7)/8;
  1761. // now just copy the router address
  1762. memcpy(&Buffer[BufSize], &Router, sizeof(Router));
  1763. BufSize += sizeof(Router);
  1764. }
  1765. // now write back the option value
  1766. DHCP_OPTION_DATA_ELEMENT DataElement = {DhcpBinaryDataOption };
  1767. DHCP_OPTION_DATA Data = { 1, &DataElement };
  1768. DataElement.Element.BinaryDataOption.DataLength = BufSize;
  1769. DataElement.Element.BinaryDataOption.Data = Buffer;
  1770. optValue->SetData( &Data );
  1771. delete Buffer;
  1772. }
  1773. }
  1774. }
  1775. BOOL COptionsCfgPropPage::OnApply()
  1776. {
  1777. BOOL bErrors = FALSE;
  1778. DWORD err = 0;
  1779. LPCTSTR pClassName;
  1780. COptionsConfig * pOptConfig = reinterpret_cast<COptionsConfig *>(GetHolder());
  1781. LPWSTR pszServerAddr = pOptConfig->GetServerAddress();
  1782. if (IsDirty())
  1783. {
  1784. BEGIN_WAIT_CURSOR;
  1785. // loop through all vendors first
  1786. POSITION posv = ((COptionsConfig *) GetHolder())->m_listVendorClasses.GetHeadPosition();
  1787. while (posv)
  1788. {
  1789. CVendorTracker * pVendorTracker = ((COptionsConfig *) GetHolder())->m_listVendorClasses.GetNext(posv);
  1790. // loop through all classes and see if we have any options we need to update
  1791. POSITION pos = pVendorTracker->m_listUserClasses.GetHeadPosition();
  1792. while (pos)
  1793. {
  1794. CClassTracker * pClassTracker = pVendorTracker->m_listUserClasses.GetNext(pos);
  1795. pClassName = pClassTracker->m_strClassName.IsEmpty() ? NULL : (LPCTSTR) pClassTracker->m_strClassName;
  1796. POSITION posOption = pClassTracker->m_listOptions.GetHeadPosition();
  1797. while (posOption)
  1798. {
  1799. COptionTracker * pCurOptTracker = pClassTracker->m_listOptions.GetNext(posOption);
  1800. if (pCurOptTracker->IsDirty())
  1801. {
  1802. // we need to update this option
  1803. CDhcpOption * pCurOption = pCurOptTracker->m_pOption;
  1804. CDhcpOptionValue & optValue = pCurOption->QueryValue();
  1805. // check to see if the option has changed
  1806. if ((pCurOptTracker->GetInitialState() == OPTION_STATE_INACTIVE) &&
  1807. (pCurOptTracker->GetCurrentState() == OPTION_STATE_INACTIVE))
  1808. {
  1809. // the state hasn't changed, the user must have changed the
  1810. // state and then restored it to its original value
  1811. err = ERROR_SUCCESS;
  1812. }
  1813. else
  1814. if ((pCurOptTracker->GetInitialState() == OPTION_STATE_ACTIVE) &&
  1815. (pCurOptTracker->GetCurrentState() == OPTION_STATE_INACTIVE))
  1816. {
  1817. // if it is a vendor specific or class ID option, call the V5 api
  1818. if ( pOptConfig->m_liServerVersion.QuadPart >= DHCP_NT5_VERSION)
  1819. {
  1820. err = ::DhcpRemoveOptionValueV5(pszServerAddr,
  1821. pCurOption->IsVendor() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  1822. pCurOption->QueryId(),
  1823. (LPTSTR) pClassName,
  1824. (LPTSTR) pCurOption->GetVendor(),
  1825. &pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo ) ;
  1826. }
  1827. else
  1828. {
  1829. // need to remove this option for either global, scope or res client
  1830. err = ::DhcpRemoveOptionValue(pszServerAddr,
  1831. pCurOption->QueryId(),
  1832. &pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo ) ;
  1833. }
  1834. }
  1835. else
  1836. {
  1837. // check option 33
  1838. if ((pCurOption->QueryId() == 33 || pCurOption->QueryId() == 21) &&
  1839. (pCurOption->QueryValue().QueryUpperBound()) % 2 != 0)
  1840. {
  1841. // special case for option 33 & 21. Make sure it is a set of IP addres pairs
  1842. // and make sure we pick the right page to select
  1843. int nId = pClassName ? 1 : 0;
  1844. PropSheet_SetCurSel(GetHolder()->GetSheetWindow(), GetSafeHwnd(), nId);
  1845. SelectOption(pCurOption);
  1846. ::DhcpMessageBox(IDS_ERR_OPTION_ADDR_PAIRS);
  1847. m_listctrlOptions.SetFocus();
  1848. return 0;
  1849. }
  1850. // we are just updating this option
  1851. DHCP_OPTION_DATA * pOptData;
  1852. err = optValue.CreateOptionDataStruct(&pOptData);
  1853. if (err)
  1854. {
  1855. ::DhcpMessageBox(err);
  1856. RESTORE_WAIT_CURSOR;
  1857. bErrors = TRUE;
  1858. continue;
  1859. }
  1860. // if it is a vendor specific or class ID option, call the V5 api
  1861. if ( ((COptionsConfig *)GetHolder())->m_liServerVersion.QuadPart >= DHCP_NT5_VERSION )
  1862. {
  1863. err = ::DhcpSetOptionValueV5(pszServerAddr,
  1864. pCurOption->IsVendor() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  1865. pCurOption->QueryId(),
  1866. (LPTSTR) pClassName,
  1867. (LPTSTR) pCurOption->GetVendor(),
  1868. &pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo,
  1869. pOptData);
  1870. }
  1871. else
  1872. {
  1873. err = ::DhcpSetOptionValue(pszServerAddr,
  1874. pCurOption->QueryId(),
  1875. &pOptConfig->m_pOptionValueEnum->m_dhcpOptionScopeInfo,
  1876. pOptData);
  1877. }
  1878. }
  1879. if (err)
  1880. {
  1881. ::DhcpMessageBox(err);
  1882. RESTORE_WAIT_CURSOR;
  1883. bErrors = TRUE;
  1884. }
  1885. else
  1886. {
  1887. // all done with this option. Mark as clean and update
  1888. // the new initial state to the current state.
  1889. pCurOptTracker->SetDirty(FALSE);
  1890. pCurOptTracker->SetInitialState(pCurOptTracker->GetCurrentState());
  1891. }
  1892. } // endif option->IsDirty()
  1893. } // while user class options
  1894. } // while User class loop
  1895. } // while Vendor loop
  1896. END_WAIT_CURSOR;
  1897. }// endif IsDirty()
  1898. if (bErrors)
  1899. return 0;
  1900. else
  1901. {
  1902. BOOL bRet = CPropertyPageBase::OnApply();
  1903. if (bRet == FALSE)
  1904. {
  1905. // Something bad happened... grab the error code
  1906. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1907. ::DhcpMessageBox(GetHolder()->GetError());
  1908. }
  1909. return bRet;
  1910. }
  1911. }
  1912. // need to refresh the UI on the main app thread...
  1913. BOOL COptionsCfgPropPage::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask)
  1914. {
  1915. SPITFSNode spNode;
  1916. spNode = GetHolder()->GetNode();
  1917. CMTDhcpHandler * pMTHandler = GETHANDLER(CMTDhcpHandler, spNode);
  1918. pMTHandler->OnRefresh(spNode, NULL, 0, 0, 0);
  1919. return FALSE;
  1920. }
  1921. //
  1922. // See if any of the edit fields have been changed and perform the alteration.
  1923. // Return TRUE if the value was changed.
  1924. //
  1925. BOOL COptionsCfgPropPage::HandleValueEdit()
  1926. {
  1927. LONG err = 0;
  1928. int nSelectedIndex = m_listctrlOptions.GetSelectedItem();
  1929. if (nSelectedIndex > -1)
  1930. {
  1931. COptionTracker * pOptTracker =
  1932. reinterpret_cast<COptionTracker *>(m_listctrlOptions.GetItemData(nSelectedIndex));
  1933. CEdit * pDwordEdit = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_DWORD));
  1934. CWndIpAddress * pIpAddr = reinterpret_cast<CWndIpAddress *>(GetDlgItem(IDC_IPADDR_ADDRESS));
  1935. CEdit * pString = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_STRING_VALUE));
  1936. CDhcpOptionValue & dhcValue = pOptTracker->m_pOption->QueryValue();
  1937. DHCP_OPTION_DATA_TYPE dhcType = dhcValue.QueryDataType();
  1938. DHCP_IP_ADDRESS dhipa ;
  1939. CString strEdit;
  1940. BOOL bModified = FALSE;
  1941. switch ( dhcType )
  1942. {
  1943. case DhcpByteOption:
  1944. case DhcpWordOption:
  1945. case DhcpDWordOption:
  1946. case DhcpBinaryDataOption:
  1947. {
  1948. DWORD dwResult;
  1949. DWORD dwMask = 0xFFFFFFFF;
  1950. if (dhcType == DhcpByteOption)
  1951. {
  1952. dwMask = 0xFF;
  1953. }
  1954. else if (dhcType == DhcpWordOption)
  1955. {
  1956. dwMask = 0xFFFF;
  1957. }
  1958. if (!FGetCtrlDWordValue(pDwordEdit->GetSafeHwnd(), &dwResult, 0, dwMask))
  1959. return FALSE;
  1960. // only mark this dirty if the value has changed as we may just
  1961. // be updating the UI
  1962. if (dwResult != (DWORD) dhcValue.QueryNumber(0))
  1963. {
  1964. bModified = TRUE ;
  1965. (void)dhcValue.SetNumber(dwResult, 0);
  1966. ASSERT(err == FALSE);
  1967. }
  1968. }
  1969. break ;
  1970. case DhcpDWordDWordOption:
  1971. {
  1972. DWORD_DWORD dwdw;
  1973. CString strValue;
  1974. pDwordEdit->GetWindowText(strValue);
  1975. UtilConvertStringToDwordDword(strValue, &dwdw);
  1976. // only mark this dirty if the value has changed as we may just
  1977. // be updating the UI
  1978. if ((dwdw.DWord1 != dhcValue.QueryDwordDword(0).DWord1) &&
  1979. (dwdw.DWord2 != dhcValue.QueryDwordDword(0).DWord2) )
  1980. {
  1981. bModified = TRUE;
  1982. dhcValue.SetDwordDword(dwdw, 0);
  1983. }
  1984. }
  1985. break;
  1986. case DhcpStringDataOption:
  1987. pString->GetWindowText( strEdit );
  1988. // only mark this dirty if the value has changed as we may just
  1989. // be updating the UI
  1990. if (strEdit.Compare(dhcValue.QueryString(0)) != 0)
  1991. {
  1992. bModified = TRUE;
  1993. err = dhcValue.SetString( strEdit, 0 );
  1994. }
  1995. break ;
  1996. case DhcpIpAddressOption:
  1997. if (!pIpAddr->GetModify())
  1998. {
  1999. break ;
  2000. }
  2001. if ( !pIpAddr->IsBlank() )
  2002. {
  2003. if ( !pIpAddr->GetAddress(&dhipa) )
  2004. {
  2005. err = ERROR_INVALID_PARAMETER;
  2006. break;
  2007. }
  2008. // only mark this dirty if the value has changed as we may just
  2009. // be updating the UI
  2010. if (dhipa != dhcValue.QueryIpAddr(0))
  2011. {
  2012. bModified = TRUE ;
  2013. err = dhcValue.SetIpAddr( dhipa, 0 );
  2014. }
  2015. }
  2016. break;
  2017. default:
  2018. Trace0("invalid value type in HandleValueEdit");
  2019. Assert( FALSE );
  2020. err = ERROR_INVALID_PARAMETER;
  2021. break;
  2022. }
  2023. if (err)
  2024. {
  2025. ::DhcpMessageBox(err);
  2026. }
  2027. else if (bModified)
  2028. {
  2029. pOptTracker->SetDirty(TRUE);
  2030. SetDirty(TRUE);
  2031. }
  2032. }
  2033. return err == 0 ;
  2034. }
  2035. /////////////////////////////////////////////////////////////////////////////
  2036. //
  2037. // COptionCfgGeneral page
  2038. //
  2039. /////////////////////////////////////////////////////////////////////////////
  2040. BEGIN_MESSAGE_MAP(COptionCfgGeneral, COptionsCfgPropPage)
  2041. //{{AFX_MSG_MAP(COptionCfgGeneral)
  2042. //}}AFX_MSG_MAP
  2043. END_MESSAGE_MAP()
  2044. IMPLEMENT_DYNCREATE(COptionCfgGeneral, COptionsCfgPropPage)
  2045. COptionCfgGeneral::COptionCfgGeneral()
  2046. : COptionsCfgPropPage(IDP_OPTION_BASIC)
  2047. {
  2048. //{{AFX_DATA_INIT(COptionCfgGeneral)
  2049. //}}AFX_DATA_INIT
  2050. }
  2051. COptionCfgGeneral::COptionCfgGeneral(UINT nIDTemplate, UINT nIDCaption)
  2052. : COptionsCfgPropPage(nIDTemplate, nIDCaption)
  2053. {
  2054. }
  2055. COptionCfgGeneral::~COptionCfgGeneral()
  2056. {
  2057. }
  2058. void COptionCfgGeneral::DoDataExchange(CDataExchange* pDX)
  2059. {
  2060. COptionsCfgPropPage::DoDataExchange(pDX);
  2061. //{{AFX_DATA_MAP(COptionCfgGeneral)
  2062. //}}AFX_DATA_MAP
  2063. }
  2064. BOOL COptionCfgGeneral::OnInitDialog()
  2065. {
  2066. COptionsCfgPropPage::OnInitDialog();
  2067. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2068. // check to see if we should focus on a particular option
  2069. COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
  2070. if (pOptionsConfig->m_dhcpStartId != 0xffffffff)
  2071. {
  2072. // check to see if this option is on the advanced page
  2073. if (!pOptionsConfig->m_strStartVendor.IsEmpty() ||
  2074. !pOptionsConfig->m_strStartClass.IsEmpty())
  2075. {
  2076. // this option is on the advanced page
  2077. ::PostMessage(pOptionsConfig->GetSheetWindow(), PSM_SETCURSEL, (WPARAM)1, NULL);
  2078. return TRUE;
  2079. }
  2080. // find the option to select
  2081. OnSelectOption(0,0);
  2082. }
  2083. SetDirty(FALSE);
  2084. return TRUE; // return TRUE unless you set the focus to a control
  2085. // EXCEPTION: OCX Property Pages should return FALSE
  2086. }
  2087. /////////////////////////////////////////////////////////////////////////////
  2088. //
  2089. // COptionCfgAdvanced page
  2090. //
  2091. /////////////////////////////////////////////////////////////////////////////
  2092. BEGIN_MESSAGE_MAP(COptionCfgAdvanced, COptionsCfgPropPage)
  2093. //{{AFX_MSG_MAP(COptionCfgAdvanced)
  2094. ON_CBN_SELENDOK(IDC_COMBO_USER_CLASS, OnSelendokComboUserClass)
  2095. ON_CBN_SELENDOK(IDC_COMBO_VENDOR_CLASS, OnSelendokComboVendorClass)
  2096. //}}AFX_MSG_MAP
  2097. ON_MESSAGE(WM_SELECTCLASSES, OnSelectClasses)
  2098. END_MESSAGE_MAP()
  2099. IMPLEMENT_DYNCREATE(COptionCfgAdvanced, COptionsCfgPropPage)
  2100. COptionCfgAdvanced::COptionCfgAdvanced()
  2101. : COptionsCfgPropPage(IDP_OPTION_ADVANCED)
  2102. {
  2103. //{{AFX_DATA_INIT(COptionCfgAdvanced)
  2104. //}}AFX_DATA_INIT
  2105. m_helpMap.BuildMap(DhcpGetHelpMap(IDP_OPTION_ADVANCED));
  2106. }
  2107. COptionCfgAdvanced::COptionCfgAdvanced(UINT nIDTemplate, UINT nIDCaption)
  2108. : COptionsCfgPropPage(nIDTemplate, nIDCaption)
  2109. {
  2110. m_helpMap.BuildMap(DhcpGetHelpMap(IDP_OPTION_ADVANCED));
  2111. }
  2112. COptionCfgAdvanced::~COptionCfgAdvanced()
  2113. {
  2114. }
  2115. void COptionCfgAdvanced::DoDataExchange(CDataExchange* pDX)
  2116. {
  2117. COptionsCfgPropPage::DoDataExchange(pDX);
  2118. //{{AFX_DATA_MAP(COptionCfgAdvanced)
  2119. DDX_Control(pDX, IDC_COMBO_USER_CLASS, m_comboUserClasses);
  2120. DDX_Control(pDX, IDC_COMBO_VENDOR_CLASS, m_comboVendorClasses);
  2121. //}}AFX_DATA_MAP
  2122. }
  2123. BOOL COptionCfgAdvanced::OnInitDialog()
  2124. {
  2125. CPropertyPageBase::OnInitDialog();
  2126. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2127. // initialize the list control
  2128. InitListCtrl();
  2129. // initialize the option data
  2130. // this gets done in the general page init, only needs
  2131. // to be done once
  2132. /*
  2133. DWORD dwErr = ((COptionsConfig *) GetHolder())->InitData();
  2134. if (dwErr != ERROR_SUCCESS)
  2135. {
  2136. // CODEWORK: need to exit gracefull if this happens
  2137. ::DhcpMessageBox(dwErr);
  2138. }
  2139. */
  2140. // add the standard vendor class name
  2141. int nSel;
  2142. CString strVendor, strClass;
  2143. strVendor.LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
  2144. nSel = m_comboVendorClasses.AddString(strVendor);
  2145. m_comboVendorClasses.SetCurSel(nSel);
  2146. // add the default user class name
  2147. strClass.LoadString(IDS_USER_STANDARD);
  2148. nSel = m_comboUserClasses.AddString(strClass);
  2149. m_comboUserClasses.SetCurSel(nSel);
  2150. // now add all the other classes
  2151. SPITFSNode spNode;
  2152. spNode = ((COptionsConfig *) GetHolder())->GetServerNode();
  2153. CDhcpServer * pServer = GETHANDLER(CDhcpServer, spNode);
  2154. CClassInfoArray ClassInfoArray;
  2155. // add all the classes to the appropriate classes to the dropdown
  2156. pServer->GetClassInfoArray(ClassInfoArray);
  2157. for (int i = 0; i < ClassInfoArray.GetSize(); i++)
  2158. {
  2159. if (!ClassInfoArray[i].bIsVendor)
  2160. m_comboUserClasses.AddString(ClassInfoArray[i].strName);
  2161. else
  2162. m_comboVendorClasses.AddString(ClassInfoArray[i].strName);
  2163. }
  2164. // now fill the options listbox with whatever class is selected
  2165. ((COptionsConfig *) GetHolder())->FillOptions(strVendor, strClass, m_listctrlOptions);
  2166. m_bNoClasses = FALSE;
  2167. // Create the type control switcher
  2168. m_cgsTypes.Create(this,IDC_DATA_ENTRY_ANCHOR,cgsPreCreateAll);
  2169. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_NONE, IDD_DATA_ENTRY_NONE, NULL);
  2170. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_DWORD, IDD_DATA_ENTRY_DWORD, NULL);
  2171. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS, IDD_DATA_ENTRY_IPADDRESS, NULL);
  2172. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_IPADDRESS_ARRAY, IDD_DATA_ENTRY_IPADDRESS_ARRAY, NULL);
  2173. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_STRING, IDD_DATA_ENTRY_STRING, NULL);
  2174. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY_ARRAY, IDD_DATA_ENTRY_BINARY_ARRAY, NULL);
  2175. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_BINARY, IDD_DATA_ENTRY_BINARY, NULL);
  2176. m_cgsTypes.AddGroup(IDC_DATA_ENTRY_ROUTE_ARRAY, IDD_DATA_ENTRY_ROUTE_ARRAY, NULL);
  2177. SwitchDataEntry(-1, -1, 0, TRUE);
  2178. m_bInitialized = TRUE;
  2179. // check to see if we should focus on a particular option
  2180. COptionsConfig * pOptionsConfig = (COptionsConfig *) GetHolder();
  2181. if (pOptionsConfig->m_dhcpStartId != 0xffffffff)
  2182. {
  2183. // yes, first select the appropriate vendor/ user class
  2184. Assert(!pOptionsConfig->m_strStartVendor.IsEmpty() ||
  2185. !pOptionsConfig->m_strStartClass.IsEmpty());
  2186. if (!pOptionsConfig->m_strStartVendor.IsEmpty())
  2187. m_comboVendorClasses.SelectString(-1, pOptionsConfig->m_strStartVendor);
  2188. if (!pOptionsConfig->m_strStartClass.IsEmpty())
  2189. m_comboUserClasses.SelectString(-1, pOptionsConfig->m_strStartClass);
  2190. // update the list of options
  2191. OnSelendokComboVendorClass();
  2192. // now find the option
  2193. OnSelectOption(0,0);
  2194. }
  2195. SetDirty(FALSE);
  2196. return TRUE; // return TRUE unless you set the focus to a control
  2197. // EXCEPTION: OCX Property Pages should return FALSE
  2198. }
  2199. void COptionCfgAdvanced::OnSelendokComboUserClass()
  2200. {
  2201. OnSelendokComboVendorClass();
  2202. }
  2203. void COptionCfgAdvanced::OnSelendokComboVendorClass()
  2204. {
  2205. // If we have classes defined then its time to switch up the list ctrl
  2206. if (m_bNoClasses == FALSE)
  2207. {
  2208. CString strSelectedVendor, strSelectedClass;
  2209. int nSelVendorIndex = m_comboVendorClasses.GetCurSel();
  2210. int nSelClassIndex = m_comboUserClasses.GetCurSel();
  2211. m_comboVendorClasses.GetLBText(nSelVendorIndex, strSelectedVendor);
  2212. m_comboUserClasses.GetLBText(nSelClassIndex, strSelectedClass);
  2213. // mark the page as not initiailzed while we redo the options
  2214. m_bInitialized = FALSE;
  2215. m_listctrlOptions.DeleteAllItems();
  2216. ((COptionsConfig *) GetHolder())->FillOptions(strSelectedVendor, strSelectedClass, m_listctrlOptions);
  2217. m_bInitialized = TRUE;
  2218. }
  2219. }
  2220. long COptionCfgAdvanced::OnSelectClasses(UINT wParam, LONG lParam)
  2221. {
  2222. CString * pstrVendor = (CString *) ULongToPtr(wParam);
  2223. CString * pstrClass = (CString *) ULongToPtr(lParam);
  2224. if (pstrVendor->IsEmpty())
  2225. pstrVendor->LoadString(IDS_INFO_NAME_DHCP_DEFAULT);
  2226. if (pstrClass->IsEmpty())
  2227. pstrClass->LoadString(IDS_USER_STANDARD);
  2228. m_comboVendorClasses.SelectString(-1, *pstrVendor);
  2229. m_comboUserClasses.SelectString(-1, *pstrClass);
  2230. // update the list of options
  2231. OnSelendokComboVendorClass();
  2232. return 0;
  2233. }