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.

8607 lines
228 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. scope.cpp
  7. This file contains all of the implementation for the DHCP
  8. scope object and all objects that it may contain.
  9. They include:
  10. CDhcpScope
  11. CDhcpReservations
  12. CDhcpReservationClient
  13. CDhcpActiveLeases
  14. CDhcpAddressPool
  15. CDhcpScopeOptions
  16. FILE HISTORY:
  17. */
  18. #include "stdafx.h"
  19. #include "server.h" // server object
  20. #include "scope.h" // scope object
  21. #include "scopepp.h" // scope property page
  22. #include "addbootp.h" // add BOOTP entry dialog
  23. #include "addexcl.h" // add exclusion range dialog
  24. #include "addres.h" // add reservation dialog
  25. #include "rclntpp.h" // reserved client property page
  26. #include "nodes.h" // all node (result pane) definitions
  27. #include "optcfg.h" // option configuration sheet
  28. #include "dlgrecon.h" // reconcile database dialog
  29. #include "scopstat.h" // scope statistics
  30. #include "addtoss.h" // add scope to superscope dialog
  31. WORD gwUnicodeHeader = 0xFEFF;
  32. // scope options result pane message stuff
  33. #define SCOPE_OPTIONS_MESSAGE_MAX_STRING 5
  34. typedef enum _SCOPE_OPTIONS_MESSAGES
  35. {
  36. SCOPE_OPTIONS_MESSAGE_NO_OPTIONS,
  37. SCOPE_OPTIONS_MESSAGE_MAX
  38. };
  39. UINT g_uScopeOptionsMessages[SCOPE_OPTIONS_MESSAGE_MAX][SCOPE_OPTIONS_MESSAGE_MAX_STRING] =
  40. {
  41. {IDS_SCOPE_OPTIONS_MESSAGE_TITLE, Icon_Information, IDS_SCOPE_OPTIONS_MESSAGE_BODY, 0, 0}
  42. };
  43. // reservation options result pane message stuff
  44. #define RES_OPTIONS_MESSAGE_MAX_STRING 5
  45. typedef enum _RES_OPTIONS_MESSAGES
  46. {
  47. RES_OPTIONS_MESSAGE_NO_OPTIONS,
  48. RES_OPTIONS_MESSAGE_MAX
  49. };
  50. UINT g_uResOptionsMessages[RES_OPTIONS_MESSAGE_MAX][RES_OPTIONS_MESSAGE_MAX_STRING] =
  51. {
  52. {IDS_RES_OPTIONS_MESSAGE_TITLE, Icon_Information, IDS_RES_OPTIONS_MESSAGE_BODY, 0, 0}
  53. };
  54. // reservations result pane message stuff
  55. #define RESERVATIONS_MESSAGE_MAX_STRING 5
  56. typedef enum _RESERVATIONS_MESSAGES
  57. {
  58. RESERVATIONS_MESSAGE_NO_RES,
  59. RESERVATIONS_MESSAGE_MAX
  60. };
  61. UINT g_uReservationsMessages[RESERVATIONS_MESSAGE_MAX][RESERVATIONS_MESSAGE_MAX_STRING] =
  62. {
  63. {IDS_RESERVATIONS_MESSAGE_TITLE, Icon_Information, IDS_RESERVATIONS_MESSAGE_BODY, 0, 0}
  64. };
  65. /*---------------------------------------------------------------------------
  66. Class CDhcpScope implementation
  67. ---------------------------------------------------------------------------*/
  68. /*---------------------------------------------------------------------------
  69. CDhcpScope::CDhcpScope
  70. Description
  71. Author: EricDav
  72. ---------------------------------------------------------------------------*/
  73. CDhcpScope::CDhcpScope
  74. (
  75. ITFSComponentData * pComponentData,
  76. DHCP_IP_ADDRESS dhcpScopeIp,
  77. DHCP_IP_MASK dhcpSubnetMask,
  78. LPCWSTR pName,
  79. LPCWSTR pComment,
  80. DHCP_SUBNET_STATE dhcpSubnetState
  81. ) : CMTDhcpHandler(pComponentData)
  82. {
  83. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  84. // save off some parameters
  85. //
  86. m_dhcpIpAddress = dhcpScopeIp;
  87. m_dhcpSubnetMask = dhcpSubnetMask;
  88. m_strName = pName;
  89. m_strComment = pComment;
  90. m_dhcpSubnetState = dhcpSubnetState;
  91. m_bInSuperscope = FALSE;
  92. }
  93. /*---------------------------------------------------------------------------
  94. Function Name Here
  95. Description
  96. Author: EricDav
  97. ---------------------------------------------------------------------------*/
  98. CDhcpScope::CDhcpScope
  99. (
  100. ITFSComponentData * pComponentData,
  101. LPDHCP_SUBNET_INFO pdhcpSubnetInfo
  102. ) : CMTDhcpHandler(pComponentData)
  103. {
  104. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  105. // save off some parameters
  106. //
  107. m_dhcpIpAddress = pdhcpSubnetInfo->SubnetAddress;
  108. m_dhcpSubnetMask = pdhcpSubnetInfo->SubnetMask;
  109. m_strName = pdhcpSubnetInfo->SubnetName;
  110. m_strComment = pdhcpSubnetInfo->SubnetComment;
  111. m_dhcpSubnetState = pdhcpSubnetInfo->SubnetState;
  112. m_bInSuperscope = FALSE;
  113. }
  114. /*---------------------------------------------------------------------------
  115. Function Name Here
  116. Description
  117. Author: EricDav
  118. ---------------------------------------------------------------------------*/
  119. CDhcpScope::CDhcpScope
  120. (
  121. ITFSComponentData * pComponentData,
  122. CSubnetInfo & subnetInfo
  123. ) : CMTDhcpHandler(pComponentData)
  124. {
  125. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  126. // save off some parameters
  127. //
  128. m_dhcpIpAddress = subnetInfo.SubnetAddress;
  129. m_dhcpSubnetMask = subnetInfo.SubnetMask;
  130. m_strName = subnetInfo.SubnetName;
  131. m_strComment = subnetInfo.SubnetComment;
  132. m_dhcpSubnetState = subnetInfo.SubnetState;
  133. m_bInSuperscope = FALSE;
  134. }
  135. CDhcpScope::~CDhcpScope()
  136. {
  137. }
  138. /*!--------------------------------------------------------------------------
  139. CDhcpScope::InitializeNode
  140. Initializes node specific data
  141. Author: EricDav
  142. ---------------------------------------------------------------------------*/
  143. HRESULT
  144. CDhcpScope::InitializeNode
  145. (
  146. ITFSNode * pNode
  147. )
  148. {
  149. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  150. HRESULT hr = hrOK;
  151. int nImage;
  152. //
  153. // Create the display name for this scope
  154. //
  155. CString strDisplay, strIpAddress;
  156. UtilCvtIpAddrToWstr (m_dhcpIpAddress,
  157. &strIpAddress);
  158. BuildDisplayName(&strDisplay, strIpAddress, m_strName);
  159. SetDisplayName(strDisplay);
  160. //
  161. // Figure out the correct icon
  162. //
  163. if ( !IsEnabled() )
  164. {
  165. m_strState.LoadString(IDS_SCOPE_INACTIVE);
  166. }
  167. else
  168. {
  169. m_strState.LoadString(IDS_SCOPE_ACTIVE);
  170. }
  171. // Make the node immediately visible
  172. pNode->SetVisibilityState(TFS_VIS_SHOW);
  173. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  174. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  175. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  176. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  177. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_SCOPE);
  178. SetColumnStringIDs(&aColumns[DHCPSNAP_SCOPE][0]);
  179. SetColumnWidths(&aColumnWidths[DHCPSNAP_SCOPE][0]);
  180. return hr;
  181. }
  182. /*---------------------------------------------------------------------------
  183. CDhcpScope::DestroyHandler
  184. We need to free up any resources we are holding
  185. Author: EricDav
  186. ---------------------------------------------------------------------------*/
  187. STDMETHODIMP
  188. CDhcpScope::DestroyHandler(ITFSNode *pNode)
  189. {
  190. // cleanup the stats dialog
  191. WaitForStatisticsWindow(&m_dlgStats);
  192. return CMTDhcpHandler::DestroyHandler(pNode);
  193. }
  194. /*---------------------------------------------------------------------------
  195. CDhcpScope::OnCreateNodeId2
  196. Returns a unique string for this node
  197. Author: EricDav
  198. ---------------------------------------------------------------------------*/
  199. HRESULT CDhcpScope::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  200. {
  201. const GUID * pGuid = pNode->GetNodeType();
  202. CString strIpAddress, strGuid;
  203. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  204. strGuid.ReleaseBuffer();
  205. UtilCvtIpAddrToWstr (m_dhcpIpAddress, &strIpAddress);
  206. strId = GetServerObject()->GetName() + strIpAddress + strGuid;
  207. return hrOK;
  208. }
  209. /*---------------------------------------------------------------------------
  210. CDhcpScope::GetImageIndex
  211. Description
  212. Author: EricDav
  213. ---------------------------------------------------------------------------*/
  214. int
  215. CDhcpScope::GetImageIndex(BOOL bOpenImage)
  216. {
  217. int nIndex = -1;
  218. switch (m_nState)
  219. {
  220. // TODO: these need to be updated with new busy state icons
  221. case loading:
  222. if (bOpenImage)
  223. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_OPEN_BUSY : ICON_IDX_SCOPE_FOLDER_OPEN_BUSY;
  224. else
  225. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_CLOSED_BUSY : ICON_IDX_SCOPE_FOLDER_CLOSED_BUSY;
  226. return nIndex;
  227. case notLoaded:
  228. case loaded:
  229. if (bOpenImage)
  230. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_OPEN : ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN;
  231. else
  232. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_CLOSED : ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED;
  233. break;
  234. case unableToLoad:
  235. if (bOpenImage)
  236. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_OPEN_LOST_CONNECTION : ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN_LOST_CONNECTION;
  237. else
  238. nIndex = (IsEnabled()) ? ICON_IDX_SCOPE_FOLDER_CLOSED_LOST_CONNECTION : ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED_LOST_CONNECTION;
  239. return nIndex;
  240. default:
  241. ASSERT(FALSE);
  242. }
  243. // only calcualte alert/warnings if the scope is enabled.
  244. if (m_spServerNode && IsEnabled())
  245. {
  246. CDhcpServer * pServer = GetServerObject();
  247. LPDHCP_MIB_INFO pMibInfo = pServer->DuplicateMibInfo();
  248. if (!pMibInfo)
  249. return nIndex;
  250. LPSCOPE_MIB_INFO pScopeMibInfo = pMibInfo->ScopeInfo;
  251. // walk the list of scopes and find our info
  252. for (UINT i = 0; i < pMibInfo->Scopes; i++)
  253. {
  254. // Find our scope stats
  255. if (pScopeMibInfo[i].Subnet == m_dhcpIpAddress)
  256. {
  257. int nPercentInUse;
  258. if ((pScopeMibInfo[i].NumAddressesInuse + pScopeMibInfo[i].NumAddressesFree) == 0)
  259. nPercentInUse = 0;
  260. else
  261. nPercentInUse = (pScopeMibInfo[i].NumAddressesInuse * 100) / (pScopeMibInfo[i].NumAddressesInuse + pScopeMibInfo[i].NumAddressesFree);
  262. // look to see if this scope meets the warning or red flag case
  263. if (pScopeMibInfo[i].NumAddressesFree == 0)
  264. {
  265. // red flag case, no addresses free, this is the highest
  266. // level of warning, so break out of the loop if we set this.
  267. if (bOpenImage)
  268. nIndex = ICON_IDX_SCOPE_FOLDER_OPEN_ALERT;
  269. else
  270. nIndex = ICON_IDX_SCOPE_FOLDER_CLOSED_ALERT;
  271. break;
  272. }
  273. else
  274. if (nPercentInUse >= SCOPE_WARNING_LEVEL)
  275. {
  276. // warning condition if Num Addresses in use is greater than
  277. // some pre-defined threshold.
  278. if (bOpenImage)
  279. nIndex = ICON_IDX_SCOPE_FOLDER_OPEN_WARNING;
  280. else
  281. nIndex = ICON_IDX_SCOPE_FOLDER_CLOSED_WARNING;
  282. }
  283. break;
  284. }
  285. }
  286. pServer->FreeDupMibInfo(pMibInfo);
  287. }
  288. return nIndex;
  289. }
  290. /*---------------------------------------------------------------------------
  291. Overridden base handler functions
  292. ---------------------------------------------------------------------------*/
  293. /*---------------------------------------------------------------------------
  294. CDhcpScope::OnAddMenuItems
  295. Adds entries to the context sensitive menu
  296. Author: EricDav
  297. ---------------------------------------------------------------------------*/
  298. STDMETHODIMP
  299. CDhcpScope::OnAddMenuItems
  300. (
  301. ITFSNode * pNode,
  302. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  303. LPDATAOBJECT lpDataObject,
  304. DATA_OBJECT_TYPES type,
  305. DWORD dwType,
  306. long * pInsertionAllowed
  307. )
  308. {
  309. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  310. // Get the version of the server
  311. LONG fFlags = 0;
  312. LARGE_INTEGER liDhcpVersion;
  313. CDhcpServer * pServer = GetServerObject();
  314. pServer->GetVersion(liDhcpVersion);
  315. HRESULT hr = S_OK;
  316. CString strMenuText;
  317. if ( (m_nState != loaded) )
  318. {
  319. fFlags |= MF_GRAYED;
  320. }
  321. if (type == CCT_SCOPE)
  322. {
  323. //
  324. // these menu items go in the new menu,
  325. // only visible from scope pane
  326. //
  327. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  328. {
  329. strMenuText.LoadString(IDS_SCOPE_SHOW_STATISTICS);
  330. hr = LoadAndAddMenuItem( pContextMenuCallback,
  331. strMenuText,
  332. IDS_SCOPE_SHOW_STATISTICS,
  333. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  334. fFlags );
  335. ASSERT( SUCCEEDED(hr) );
  336. // separator
  337. hr = LoadAndAddMenuItem( pContextMenuCallback,
  338. strMenuText,
  339. 0,
  340. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  341. MF_SEPARATOR);
  342. ASSERT( SUCCEEDED(hr) );
  343. // reconcile is only supports for NT4 SP2 and greater.
  344. if (liDhcpVersion.QuadPart >= DHCP_SP2_VERSION)
  345. {
  346. strMenuText.LoadString(IDS_SCOPE_RECONCILE);
  347. hr = LoadAndAddMenuItem( pContextMenuCallback,
  348. strMenuText,
  349. IDS_SCOPE_RECONCILE,
  350. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  351. fFlags );
  352. ASSERT( SUCCEEDED(hr) );
  353. }
  354. // Superscope support only on NT4 SP2 and greater
  355. if (liDhcpVersion.QuadPart >= DHCP_SP2_VERSION)
  356. {
  357. int nID = 0;
  358. if (IsInSuperscope())
  359. {
  360. nID = IDS_SCOPE_REMOVE_SUPERSCOPE;
  361. }
  362. else
  363. {
  364. // check to see if there are superscopes to add to
  365. SPITFSNode spNode;
  366. pNode->GetParent(&spNode);
  367. CDhcpServer * pServer = GETHANDLER(CDhcpServer, spNode);
  368. if (pServer->HasSuperscopes(spNode))
  369. nID = IDS_SCOPE_ADD_SUPERSCOPE;
  370. }
  371. // load the menu item if we need to
  372. if (nID)
  373. {
  374. strMenuText.LoadString(nID);
  375. hr = LoadAndAddMenuItem( pContextMenuCallback,
  376. strMenuText,
  377. nID,
  378. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  379. fFlags );
  380. ASSERT( SUCCEEDED(hr) );
  381. }
  382. }
  383. // separator
  384. hr = LoadAndAddMenuItem( pContextMenuCallback,
  385. strMenuText,
  386. 0,
  387. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  388. MF_SEPARATOR);
  389. ASSERT( SUCCEEDED(hr) );
  390. // activate/deactivate
  391. if ( !IsEnabled() )
  392. {
  393. strMenuText.LoadString(IDS_SCOPE_ACTIVATE);
  394. hr = LoadAndAddMenuItem( pContextMenuCallback,
  395. strMenuText,
  396. IDS_SCOPE_ACTIVATE,
  397. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  398. fFlags );
  399. ASSERT( SUCCEEDED(hr) );
  400. }
  401. else
  402. {
  403. strMenuText.LoadString(IDS_SCOPE_DEACTIVATE);
  404. hr = LoadAndAddMenuItem( pContextMenuCallback,
  405. strMenuText,
  406. IDS_SCOPE_DEACTIVATE,
  407. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  408. fFlags );
  409. ASSERT( SUCCEEDED(hr) );
  410. }
  411. }
  412. }
  413. return hr;
  414. }
  415. /*---------------------------------------------------------------------------
  416. CDhcpScope::OnCommand
  417. Description
  418. Author: EricDav
  419. ---------------------------------------------------------------------------*/
  420. STDMETHODIMP
  421. CDhcpScope::OnCommand
  422. (
  423. ITFSNode * pNode,
  424. long nCommandId,
  425. DATA_OBJECT_TYPES type,
  426. LPDATAOBJECT pDataObject,
  427. DWORD dwType
  428. )
  429. {
  430. HRESULT hr = S_OK;
  431. switch (nCommandId)
  432. {
  433. case IDS_ACTIVATE:
  434. case IDS_DEACTIVATE:
  435. case IDS_SCOPE_ACTIVATE:
  436. case IDS_SCOPE_DEACTIVATE:
  437. OnActivateScope(pNode);
  438. break;
  439. case IDS_REFRESH:
  440. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  441. break;
  442. case IDS_SCOPE_SHOW_STATISTICS:
  443. OnShowScopeStats(pNode);
  444. break;
  445. case IDS_SCOPE_RECONCILE:
  446. OnReconcileScope(pNode);
  447. break;
  448. case IDS_DELETE:
  449. OnDelete(pNode);
  450. break;
  451. case IDS_SCOPE_ADD_SUPERSCOPE:
  452. OnAddToSuperscope(pNode);
  453. break;
  454. case IDS_SCOPE_REMOVE_SUPERSCOPE:
  455. OnRemoveFromSuperscope(pNode);
  456. break;
  457. default:
  458. break;
  459. }
  460. return hr;
  461. }
  462. /*!--------------------------------------------------------------------------
  463. CDhcpScope::OnDelete
  464. The base handler calls this when MMC sends a MMCN_DELETE for a
  465. scope pane item. We just call our delete command handler.
  466. Author: EricDav
  467. ---------------------------------------------------------------------------*/
  468. HRESULT
  469. CDhcpScope::OnDelete
  470. (
  471. ITFSNode * pNode,
  472. LPARAM arg,
  473. LPARAM lParam
  474. )
  475. {
  476. return OnDelete(pNode);
  477. }
  478. /*!--------------------------------------------------------------------------
  479. CDhcpScope::HasPropertyPages
  480. Says whether or not this handler has property pages
  481. Author: KennT
  482. ---------------------------------------------------------------------------*/
  483. STDMETHODIMP
  484. CDhcpScope::HasPropertyPages
  485. (
  486. ITFSNode * pNode,
  487. LPDATAOBJECT pDataObject,
  488. DATA_OBJECT_TYPES type,
  489. DWORD dwType
  490. )
  491. {
  492. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  493. HRESULT hr = hrOK;
  494. if (dwType & TFS_COMPDATA_CREATE)
  495. {
  496. // This is the case where we are asked to bring up property
  497. // pages when the user is adding a new snapin. These calls
  498. // are forwarded to the root node to handle.
  499. // Should never get here!!
  500. Assert(FALSE);
  501. hr = S_FALSE;
  502. }
  503. else
  504. {
  505. // we have property pages in the normal case
  506. hr = hrOK;
  507. }
  508. return hr;
  509. }
  510. /*---------------------------------------------------------------------------
  511. CDhcpScope::CreatePropertyPages
  512. Description
  513. Author: EricDav
  514. ---------------------------------------------------------------------------*/
  515. STDMETHODIMP
  516. CDhcpScope::CreatePropertyPages
  517. (
  518. ITFSNode * pNode,
  519. LPPROPERTYSHEETCALLBACK lpProvider,
  520. LPDATAOBJECT pDataObject,
  521. LONG_PTR handle,
  522. DWORD dwType
  523. )
  524. {
  525. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  526. HRESULT hr = hrOK;
  527. DWORD dwError;
  528. DWORD dwDynDnsFlags;
  529. SPIComponentData spComponentData;
  530. LARGE_INTEGER liVersion;
  531. CDhcpServer * pServer;
  532. CDhcpIpRange dhcpIpRange;
  533. //
  534. // Create the property page
  535. //
  536. m_spNodeMgr->GetComponentData(&spComponentData);
  537. CScopeProperties * pScopeProp =
  538. new CScopeProperties(pNode, spComponentData, m_spTFSCompData, NULL);
  539. // Get the Server version and set it in the property sheet
  540. pServer = GetServerObject();
  541. pServer->GetVersion(liVersion);
  542. pScopeProp->SetVersion(liVersion);
  543. pScopeProp->SetSupportsDynBootp(pServer->FSupportsDynBootp());
  544. // Set scope specific data in the prop sheet
  545. pScopeProp->m_pageGeneral.m_strName = m_strName;
  546. pScopeProp->m_pageGeneral.m_strComment = m_strComment;
  547. BEGIN_WAIT_CURSOR;
  548. dwError = GetIpRange(&dhcpIpRange);
  549. if (dwError != ERROR_SUCCESS)
  550. {
  551. ::DhcpMessageBox(dwError);
  552. return hrFalse;
  553. }
  554. pScopeProp->m_pageGeneral.m_dwStartAddress = dhcpIpRange.QueryAddr(TRUE);
  555. pScopeProp->m_pageGeneral.m_dwEndAddress = dhcpIpRange.QueryAddr(FALSE);
  556. pScopeProp->m_pageGeneral.m_dwSubnetMask = m_dhcpSubnetMask;
  557. pScopeProp->m_pageGeneral.m_uImage = GetImageIndex(FALSE);
  558. pScopeProp->m_pageAdvanced.m_RangeType = dhcpIpRange.GetRangeType();
  559. GetLeaseTime(&pScopeProp->m_pageGeneral.m_dwLeaseTime);
  560. if (dwError != ERROR_SUCCESS)
  561. {
  562. ::DhcpMessageBox(dwError);
  563. return hrFalse;
  564. }
  565. if (pServer->FSupportsDynBootp())
  566. {
  567. GetDynBootpLeaseTime(&pScopeProp->m_pageAdvanced.m_dwLeaseTime);
  568. if (dwError != ERROR_SUCCESS)
  569. {
  570. ::DhcpMessageBox(dwError);
  571. return hrFalse;
  572. }
  573. }
  574. // set the DNS registration option
  575. dwError = GetDnsRegistration(&dwDynDnsFlags);
  576. if (dwError != ERROR_SUCCESS)
  577. {
  578. ::DhcpMessageBox(dwError);
  579. return hrFalse;
  580. }
  581. END_WAIT_CURSOR;
  582. pScopeProp->SetDnsRegistration(dwDynDnsFlags, DhcpSubnetOptions);
  583. //
  584. // Object gets deleted when the page is destroyed
  585. //
  586. Assert(lpProvider != NULL);
  587. return pScopeProp->CreateModelessSheet(lpProvider, handle);
  588. }
  589. /*!--------------------------------------------------------------------------
  590. CDhcpScope::GetString
  591. Returns string information for display in the result pane columns
  592. Author: EricDav
  593. ---------------------------------------------------------------------------*/
  594. STDMETHODIMP_(LPCTSTR)
  595. CDhcpScope::GetString
  596. (
  597. ITFSNode * pNode,
  598. int nCol
  599. )
  600. {
  601. switch (nCol)
  602. {
  603. case 0:
  604. return GetDisplayName();
  605. case 1:
  606. return m_strState;
  607. case 2:
  608. return m_strComment;
  609. }
  610. return NULL;
  611. }
  612. /*---------------------------------------------------------------------------
  613. CDhcpScope::OnPropertyChange
  614. Description
  615. Author: EricDav
  616. ---------------------------------------------------------------------------*/
  617. HRESULT
  618. CDhcpScope::OnPropertyChange
  619. (
  620. ITFSNode * pNode,
  621. LPDATAOBJECT pDataobject,
  622. DWORD dwType,
  623. LPARAM arg,
  624. LPARAM lParam
  625. )
  626. {
  627. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  628. CScopeProperties * pScopeProp = reinterpret_cast<CScopeProperties *>(lParam);
  629. LONG_PTR changeMask = 0;
  630. // tell the property page to do whatever now that we are back on the
  631. // main thread
  632. pScopeProp->OnPropertyChange(TRUE, &changeMask);
  633. pScopeProp->AcknowledgeNotify();
  634. if (changeMask)
  635. pNode->ChangeNode(changeMask);
  636. return hrOK;
  637. }
  638. /*!--------------------------------------------------------------------------
  639. CDhcpScope::OnUpdateToolbarButtons
  640. We override this function to show/hide the correct
  641. activate/deactivate buttons
  642. Author: EricDav
  643. ---------------------------------------------------------------------------*/
  644. HRESULT
  645. CDhcpScope::OnUpdateToolbarButtons
  646. (
  647. ITFSNode * pNode,
  648. LPDHCPTOOLBARNOTIFY pToolbarNotify
  649. )
  650. {
  651. HRESULT hr = hrOK;
  652. if (pToolbarNotify->bSelect)
  653. {
  654. UpdateToolbarStates();
  655. }
  656. CMTDhcpHandler::OnUpdateToolbarButtons(pNode, pToolbarNotify);
  657. return hr;
  658. }
  659. /*!--------------------------------------------------------------------------
  660. CDhcpScope::UpdateToolbarStates
  661. Description
  662. Author: EricDav
  663. ---------------------------------------------------------------------------*/
  664. void
  665. CDhcpScope::UpdateToolbarStates()
  666. {
  667. if ( !IsEnabled() )
  668. {
  669. g_SnapinButtonStates[DHCPSNAP_SCOPE][TOOLBAR_IDX_ACTIVATE] = ENABLED;
  670. g_SnapinButtonStates[DHCPSNAP_SCOPE][TOOLBAR_IDX_DEACTIVATE] = HIDDEN;
  671. }
  672. else
  673. {
  674. g_SnapinButtonStates[DHCPSNAP_SCOPE][TOOLBAR_IDX_ACTIVATE] = HIDDEN;
  675. g_SnapinButtonStates[DHCPSNAP_SCOPE][TOOLBAR_IDX_DEACTIVATE] = ENABLED;
  676. }
  677. }
  678. /*---------------------------------------------------------------------------
  679. Background thread functionality
  680. ---------------------------------------------------------------------------*/
  681. /*---------------------------------------------------------------------------
  682. CDhcpScope:OnHaveData
  683. Description
  684. Author: EricDav
  685. ---------------------------------------------------------------------------*/
  686. void
  687. CDhcpScope::OnHaveData
  688. (
  689. ITFSNode * pParentNode,
  690. ITFSNode * pNewNode
  691. )
  692. {
  693. if (pNewNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ACTIVE_LEASES)
  694. {
  695. pParentNode->AddChild(pNewNode);
  696. m_spActiveLeases.Set(pNewNode);
  697. }
  698. else
  699. if (pNewNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ADDRESS_POOL)
  700. {
  701. pParentNode->AddChild(pNewNode);
  702. m_spAddressPool.Set(pNewNode);
  703. }
  704. else
  705. if (pNewNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_RESERVATIONS)
  706. {
  707. pParentNode->AddChild(pNewNode);
  708. m_spReservations.Set(pNewNode);
  709. }
  710. else
  711. if (pNewNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_SCOPE_OPTIONS)
  712. {
  713. pParentNode->AddChild(pNewNode);
  714. m_spOptions.Set(pNewNode);
  715. }
  716. // now tell the view to update themselves
  717. ExpandNode(pParentNode, TRUE);
  718. }
  719. /*---------------------------------------------------------------------------
  720. CDhcpScope::OnHaveData
  721. Description
  722. Author: EricDav
  723. ---------------------------------------------------------------------------*/
  724. void
  725. CDhcpScope::OnHaveData
  726. (
  727. ITFSNode * pParentNode,
  728. LPARAM Data,
  729. LPARAM Type
  730. )
  731. {
  732. // This is how we get non-node data back from the background thread.
  733. switch (Type)
  734. {
  735. case DHCP_QDATA_SUBNET_INFO:
  736. {
  737. LONG_PTR changeMask = 0;
  738. LPDHCP_SUBNET_INFO pdhcpSubnetInfo = reinterpret_cast<LPDHCP_SUBNET_INFO>(Data);
  739. // update the scope name and state based on the info
  740. if (m_strName.CompareNoCase(pdhcpSubnetInfo->SubnetName) != 0)
  741. {
  742. CString strDisplay, strIpAddress;
  743. m_strName = pdhcpSubnetInfo->SubnetName;
  744. UtilCvtIpAddrToWstr (m_dhcpIpAddress,
  745. &strIpAddress);
  746. BuildDisplayName(&strDisplay, strIpAddress, m_strName);
  747. SetDisplayName(strDisplay);
  748. changeMask = SCOPE_PANE_CHANGE_ITEM;
  749. }
  750. if (m_dhcpSubnetState != pdhcpSubnetInfo->SubnetState)
  751. {
  752. DHCP_SUBNET_STATE dhcpOldState = m_dhcpSubnetState;
  753. m_dhcpSubnetState = pdhcpSubnetInfo->SubnetState;
  754. // Tell the scope to update it's state
  755. DWORD err = SetInfo();
  756. if (err != 0)
  757. {
  758. ::DhcpMessageBox(err);
  759. m_dhcpSubnetState = dhcpOldState;
  760. }
  761. else
  762. {
  763. pParentNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  764. pParentNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  765. // Update the toolbar button
  766. UpdateToolbarStates();
  767. SendUpdateToolbar(pParentNode, TRUE);
  768. // need to notify the owning superscope to update it's state information
  769. // this is strictly for UI purposes only.
  770. if (IsInSuperscope())
  771. {
  772. SPITFSNode spSuperscopeNode;
  773. pParentNode->GetParent(&spSuperscopeNode);
  774. CDhcpSuperscope * pSuperscope = GETHANDLER(CDhcpSuperscope, spSuperscopeNode);
  775. Assert(pSuperscope);
  776. pSuperscope->NotifyScopeStateChange(spSuperscopeNode, m_dhcpSubnetState);
  777. }
  778. changeMask = SCOPE_PANE_CHANGE_ITEM;
  779. }
  780. }
  781. if (pdhcpSubnetInfo)
  782. ::DhcpRpcFreeMemory(pdhcpSubnetInfo);
  783. if (changeMask)
  784. VERIFY(SUCCEEDED(pParentNode->ChangeNode(changeMask)));
  785. }
  786. break;
  787. case DHCP_QDATA_OPTION_VALUES:
  788. {
  789. COptionValueEnum * pOptionValueEnum = reinterpret_cast<COptionValueEnum *>(Data);
  790. SetOptionValueEnum(pOptionValueEnum);
  791. pOptionValueEnum->RemoveAll();
  792. delete pOptionValueEnum;
  793. break;
  794. }
  795. default:
  796. break;
  797. }
  798. }
  799. /*---------------------------------------------------------------------------
  800. CDhcpScope::OnCreateQuery()
  801. Description
  802. Author: EricDav
  803. ---------------------------------------------------------------------------*/
  804. ITFSQueryObject*
  805. CDhcpScope::OnCreateQuery(ITFSNode * pNode)
  806. {
  807. CDhcpScopeQueryObj* pQuery =
  808. new CDhcpScopeQueryObj(m_spTFSCompData, m_spNodeMgr);
  809. pQuery->m_strServer = GetServerIpAddress();
  810. pQuery->m_dhcpScopeAddress = GetAddress();
  811. GetServerVersion(pQuery->m_liVersion);
  812. return pQuery;
  813. }
  814. /*---------------------------------------------------------------------------
  815. CDhcpScope::Execute()
  816. Description
  817. Author: EricDav
  818. ---------------------------------------------------------------------------*/
  819. STDMETHODIMP
  820. CDhcpScopeQueryObj::Execute()
  821. {
  822. HRESULT hr = hrOK;
  823. DWORD dwReturn;
  824. LPDHCP_SUBNET_INFO pdhcpSubnetInfo = NULL;
  825. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  826. COptionValueEnum * pOptionValueEnum = NULL;
  827. dwReturn = ::DhcpGetSubnetInfo(((LPWSTR) (LPCTSTR)m_strServer),
  828. m_dhcpScopeAddress,
  829. &pdhcpSubnetInfo);
  830. if (dwReturn == ERROR_SUCCESS && pdhcpSubnetInfo)
  831. {
  832. AddToQueue((LPARAM) pdhcpSubnetInfo, DHCP_QDATA_SUBNET_INFO);
  833. }
  834. else
  835. {
  836. Trace1("CDhcpScopeQueryObj::Execute - DhcpGetSubnetInfo failed! %d\n", dwReturn);
  837. PostError(dwReturn);
  838. return hrFalse;
  839. }
  840. // get the option info for this scope
  841. pOptionValueEnum = new COptionValueEnum();
  842. dhcpOptionScopeInfo.ScopeType = DhcpSubnetOptions;
  843. dhcpOptionScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpScopeAddress;
  844. pOptionValueEnum->Init(m_strServer, m_liVersion, dhcpOptionScopeInfo);
  845. dwReturn = pOptionValueEnum->Enum();
  846. if (dwReturn != ERROR_SUCCESS)
  847. {
  848. Trace1("CDhcpScopeQueryObj::Execute - EnumOptions Failed! %d\n", dwReturn);
  849. m_dwErr = dwReturn;
  850. PostError(dwReturn);
  851. delete pOptionValueEnum;
  852. }
  853. else
  854. {
  855. pOptionValueEnum->SortById();
  856. AddToQueue((LPARAM) pOptionValueEnum, DHCP_QDATA_OPTION_VALUES);
  857. }
  858. // now create the scope subcontainers
  859. CreateSubcontainers();
  860. return hrFalse;
  861. }
  862. /*---------------------------------------------------------------------------
  863. CDhcpScope::CreateSubcontainers()
  864. Description
  865. Author: EricDav
  866. ---------------------------------------------------------------------------*/
  867. HRESULT
  868. CDhcpScopeQueryObj::CreateSubcontainers()
  869. {
  870. HRESULT hr = hrOK;
  871. SPITFSNode spNode;
  872. //
  873. // create the address pool Handler
  874. //
  875. CDhcpAddressPool *pAddressPool = new CDhcpAddressPool(m_spTFSCompData);
  876. CreateContainerTFSNode(&spNode,
  877. &GUID_DhcpAddressPoolNodeType,
  878. pAddressPool,
  879. pAddressPool,
  880. m_spNodeMgr);
  881. // Tell the handler to initialize any specific data
  882. pAddressPool->InitializeNode((ITFSNode *) spNode);
  883. // Add the node as a child to this node
  884. AddToQueue(spNode);
  885. pAddressPool->Release();
  886. spNode.Set(NULL);
  887. //
  888. // create the Active Leases Handler
  889. //
  890. CDhcpActiveLeases *pActiveLeases = new CDhcpActiveLeases(m_spTFSCompData);
  891. CreateContainerTFSNode(&spNode,
  892. &GUID_DhcpActiveLeasesNodeType,
  893. pActiveLeases,
  894. pActiveLeases,
  895. m_spNodeMgr);
  896. // Tell the handler to initialize any specific data
  897. pActiveLeases->InitializeNode((ITFSNode *) spNode);
  898. // Add the node as a child to this node
  899. AddToQueue(spNode);
  900. pActiveLeases->Release();
  901. spNode.Set(NULL);
  902. //
  903. // create the reservations Handler
  904. //
  905. CDhcpReservations *pReservations = new CDhcpReservations(m_spTFSCompData);
  906. CreateContainerTFSNode(&spNode,
  907. &GUID_DhcpReservationsNodeType,
  908. pReservations,
  909. pReservations,
  910. m_spNodeMgr);
  911. // Tell the handler to initialize any specific data
  912. pReservations->InitializeNode((ITFSNode *) spNode);
  913. // Add the node as a child to this node
  914. AddToQueue(spNode);
  915. pReservations->Release();
  916. spNode.Set(NULL);
  917. //
  918. // create the Scope Options Handler
  919. //
  920. CDhcpScopeOptions *pScopeOptions = new CDhcpScopeOptions(m_spTFSCompData);
  921. CreateContainerTFSNode(&spNode,
  922. &GUID_DhcpScopeOptionsNodeType,
  923. pScopeOptions,
  924. pScopeOptions,
  925. m_spNodeMgr);
  926. // Tell the handler to initialize any specific data
  927. pScopeOptions->InitializeNode((ITFSNode *) spNode);
  928. // Add the node as a child to this node
  929. AddToQueue(spNode);
  930. pScopeOptions->Release();
  931. return hr;
  932. }
  933. /*---------------------------------------------------------------------------
  934. Command handlers
  935. ---------------------------------------------------------------------------*/
  936. /*---------------------------------------------------------------------------
  937. CDhcpScope::OnActivateScope
  938. Message handler for the scope activate/deactivate menu
  939. Author: EricDav
  940. ---------------------------------------------------------------------------*/
  941. DWORD
  942. CDhcpScope::OnActivateScope
  943. (
  944. ITFSNode * pNode
  945. )
  946. {
  947. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  948. DWORD err = 0;
  949. int nOpenImage, nClosedImage;
  950. DHCP_SUBNET_STATE dhcpOldState = m_dhcpSubnetState;
  951. if ( IsEnabled() )
  952. {
  953. // if they want to disable the scope, confirm
  954. if (AfxMessageBox(IDS_SCOPE_DISABLE_CONFIRM, MB_YESNO) != IDYES)
  955. {
  956. return err;
  957. }
  958. }
  959. SetState(
  960. IsEnabled()? DhcpSubnetDisabled : DhcpSubnetEnabled );
  961. // Tell the scope to update it's state
  962. err = SetInfo();
  963. if (err != 0)
  964. {
  965. ::DhcpMessageBox(err);
  966. m_dhcpSubnetState = dhcpOldState;
  967. }
  968. else
  969. {
  970. // update the icon and the status text
  971. if ( !IsEnabled() )
  972. {
  973. nOpenImage = ICON_IDX_SCOPE_INACTIVE_FOLDER_OPEN;
  974. nClosedImage = ICON_IDX_SCOPE_INACTIVE_FOLDER_CLOSED;
  975. m_strState.LoadString(IDS_SCOPE_INACTIVE);
  976. }
  977. else
  978. {
  979. nOpenImage = GetImageIndex(TRUE);
  980. nClosedImage = GetImageIndex(FALSE);
  981. m_strState.LoadString(IDS_SCOPE_ACTIVE);
  982. }
  983. pNode->SetData(TFS_DATA_IMAGEINDEX, nClosedImage);
  984. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, nOpenImage);
  985. VERIFY(SUCCEEDED(pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM)));
  986. // Update the toolbar button
  987. UpdateToolbarStates();
  988. SendUpdateToolbar(pNode, TRUE);
  989. // need to notify the owning superscope to update it's state information
  990. // this is strictly for UI purposes only.
  991. if (IsInSuperscope())
  992. {
  993. SPITFSNode spSuperscopeNode;
  994. pNode->GetParent(&spSuperscopeNode);
  995. CDhcpSuperscope * pSuperscope = GETHANDLER(CDhcpSuperscope, spSuperscopeNode);
  996. Assert(pSuperscope);
  997. pSuperscope->NotifyScopeStateChange(spSuperscopeNode, m_dhcpSubnetState);
  998. }
  999. }
  1000. TriggerStatsRefresh();
  1001. return err;
  1002. }
  1003. /*---------------------------------------------------------------------------
  1004. CDhcpScope::OnRefreshScope
  1005. Refreshes all of the subnodes of the scope
  1006. Author: EricDav
  1007. ---------------------------------------------------------------------------*/
  1008. HRESULT
  1009. CDhcpScope::OnRefreshScope
  1010. (
  1011. ITFSNode * pNode,
  1012. LPDATAOBJECT pDataObject,
  1013. DWORD dwType
  1014. )
  1015. {
  1016. HRESULT hr = hrOK;
  1017. CDhcpReservations * pReservations = GetReservationsObject();
  1018. CDhcpActiveLeases * pActiveLeases = GetActiveLeasesObject();
  1019. CDhcpAddressPool * pAddressPool = GetAddressPoolObject();
  1020. CDhcpScopeOptions * pScopeOptions = GetScopeOptionsObject();
  1021. Assert(pReservations);
  1022. Assert(pActiveLeases);
  1023. Assert(pAddressPool);
  1024. Assert(pScopeOptions);
  1025. if (pReservations)
  1026. pReservations->OnRefresh(m_spReservations, pDataObject, dwType, 0, 0);
  1027. if (pActiveLeases)
  1028. pActiveLeases->OnRefresh(m_spActiveLeases, pDataObject, dwType, 0, 0);
  1029. if (pAddressPool)
  1030. pAddressPool->OnRefresh(m_spAddressPool, pDataObject, dwType, 0, 0);
  1031. if (pScopeOptions)
  1032. pScopeOptions->OnRefresh(m_spOptions, pDataObject, dwType, 0, 0);
  1033. return hr;
  1034. }
  1035. /*---------------------------------------------------------------------------
  1036. CDhcpScope::OnReconcileScope
  1037. Reconciles the active leases database for this scope
  1038. Author: EricDav
  1039. ---------------------------------------------------------------------------*/
  1040. HRESULT
  1041. CDhcpScope::OnReconcileScope
  1042. (
  1043. ITFSNode * pNode
  1044. )
  1045. {
  1046. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1047. CReconcileDlg dlgRecon(pNode);
  1048. dlgRecon.DoModal();
  1049. return hrOK;
  1050. }
  1051. /*---------------------------------------------------------------------------
  1052. CDhcpScope::OnShowScopeStats()
  1053. Description
  1054. Author: EricDav
  1055. ---------------------------------------------------------------------------*/
  1056. HRESULT
  1057. CDhcpScope::OnShowScopeStats
  1058. (
  1059. ITFSNode * pNode
  1060. )
  1061. {
  1062. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1063. HRESULT hr = S_OK;
  1064. CString strScopeAddress;
  1065. // Fill in some information in the stats object.
  1066. // CreateNewStatisticsWindow handles the case if the window is
  1067. // already visible.
  1068. m_dlgStats.SetNode(pNode);
  1069. m_dlgStats.SetServer(GetServerIpAddress());
  1070. m_dlgStats.SetScope(m_dhcpIpAddress);
  1071. CreateNewStatisticsWindow(&m_dlgStats,
  1072. ::FindMMCMainWindow(),
  1073. IDD_STATS_NARROW);
  1074. return hr;
  1075. }
  1076. /*---------------------------------------------------------------------------
  1077. CDhcpScope::OnDelete()
  1078. Description
  1079. Author: EricDav
  1080. ---------------------------------------------------------------------------*/
  1081. HRESULT
  1082. CDhcpScope::OnDelete(ITFSNode * pNode)
  1083. {
  1084. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1085. HRESULT hr = S_OK;
  1086. SPITFSNode spServer;
  1087. SPITFSNode spSuperscopeNode;
  1088. int nVisible = 0, nTotal = 0;
  1089. int nResponse;
  1090. LONG err = 0 ;
  1091. if (IsInSuperscope())
  1092. {
  1093. pNode->GetParent(&spSuperscopeNode);
  1094. spSuperscopeNode->GetChildCount(&nVisible, &nTotal);
  1095. }
  1096. if (nTotal == 1)
  1097. {
  1098. // warn the user that this is the last scope in the superscope
  1099. // and the superscope will be removed.
  1100. nResponse = AfxMessageBox(IDS_DELETE_LAST_SCOPE_FROM_SS, MB_YESNO);
  1101. }
  1102. else
  1103. {
  1104. nResponse = ::DhcpMessageBox( IsEnabled() ?
  1105. IDS_MSG_DELETE_ACTIVE : IDS_MSG_DELETE_SCOPE,
  1106. MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION);
  1107. }
  1108. if (nResponse == IDYES)
  1109. {
  1110. SPITFSNode spTemp;
  1111. if (IsInSuperscope())
  1112. {
  1113. // superscope
  1114. spTemp.Set(spSuperscopeNode);
  1115. }
  1116. else
  1117. {
  1118. spTemp.Set(pNode);
  1119. }
  1120. spTemp->GetParent(&spServer);
  1121. CDhcpServer * pServer = GETHANDLER(CDhcpServer, spServer);
  1122. err = pServer->DeleteScope(pNode);
  1123. if (err == ERROR_SUCCESS &&
  1124. nTotal == 1)
  1125. {
  1126. // gotta remove the superscope
  1127. spServer->RemoveChild(spSuperscopeNode);
  1128. }
  1129. }
  1130. // trigger the statistics to refresh only if we removed this scope
  1131. if (spServer)
  1132. {
  1133. TriggerStatsRefresh();
  1134. }
  1135. return hr;
  1136. }
  1137. /*---------------------------------------------------------------------------
  1138. CDhcpScope::OnAddToSuperscope()
  1139. Adds this scope to a superscope
  1140. Author: EricDav
  1141. ---------------------------------------------------------------------------*/
  1142. HRESULT
  1143. CDhcpScope::OnAddToSuperscope
  1144. (
  1145. ITFSNode * pNode
  1146. )
  1147. {
  1148. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1149. CString strTitle, strAddress;
  1150. UtilCvtIpAddrToWstr(m_dhcpIpAddress, &strAddress);
  1151. AfxFormatString1(strTitle, IDS_ADD_SCOPE_DLG_TITLE, strAddress);
  1152. CAddScopeToSuperscope dlgAddScope(pNode, strTitle);
  1153. dlgAddScope.DoModal();
  1154. return hrOK;
  1155. }
  1156. /*---------------------------------------------------------------------------
  1157. CDhcpScope::OnRemoveFromSuperscope()
  1158. Removes this scope from a superscope
  1159. Author: EricDav
  1160. ---------------------------------------------------------------------------*/
  1161. HRESULT
  1162. CDhcpScope::OnRemoveFromSuperscope
  1163. (
  1164. ITFSNode * pNode
  1165. )
  1166. {
  1167. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1168. int nVisible, nTotal, nResponse;
  1169. SPITFSNode spSuperscopeNode;
  1170. pNode->GetParent(&spSuperscopeNode);
  1171. spSuperscopeNode->GetChildCount(&nVisible, &nTotal);
  1172. if (nTotal == 1)
  1173. {
  1174. // warn the user that this is the last scope in the superscope
  1175. // and the superscope will be removed.
  1176. nResponse = AfxMessageBox(IDS_REMOVE_LAST_SCOPE_FROM_SS, MB_YESNO);
  1177. }
  1178. else
  1179. {
  1180. nResponse = AfxMessageBox(IDS_REMOVE_SCOPE_FROM_SS, MB_YESNO);
  1181. }
  1182. if (nResponse == IDYES)
  1183. {
  1184. // set the superscope for this scope to be NULL
  1185. // effectively removing it from the scope.
  1186. DWORD dwError = SetSuperscope(NULL, TRUE);
  1187. if (dwError != ERROR_SUCCESS)
  1188. {
  1189. ::DhcpMessageBox(dwError);
  1190. return hrFalse;
  1191. }
  1192. // now move the scope out of the supersope in the UI
  1193. spSuperscopeNode->ExtractChild(pNode);
  1194. // now put the scope node back in at the server level.
  1195. SPITFSNode spServerNode;
  1196. spSuperscopeNode->GetParent(&spServerNode);
  1197. CDhcpServer * pServer = GETHANDLER(CDhcpServer, spServerNode);
  1198. pServer->AddScopeSorted(spServerNode, pNode);
  1199. SetInSuperscope(FALSE);
  1200. if (nTotal == 1)
  1201. {
  1202. // now delete the superscope.
  1203. spServerNode->RemoveChild(spSuperscopeNode);
  1204. }
  1205. }
  1206. return hrOK;
  1207. }
  1208. /*---------------------------------------------------------------------------
  1209. CDhcpScope::UpdateStatistics
  1210. Notification that stats are now available. Update stats for the
  1211. node and give all subnodes a chance to update.
  1212. Author: EricDav
  1213. ---------------------------------------------------------------------------*/
  1214. DWORD
  1215. CDhcpScope::UpdateStatistics
  1216. (
  1217. ITFSNode * pNode
  1218. )
  1219. {
  1220. HRESULT hr = hrOK;
  1221. SPITFSNodeEnum spNodeEnum;
  1222. SPITFSNode spCurrentNode;
  1223. ULONG nNumReturned;
  1224. HWND hStatsWnd;
  1225. BOOL bChangeIcon = FALSE;
  1226. // Check to see if this node has a stats sheet up.
  1227. hStatsWnd = m_dlgStats.GetSafeHwnd();
  1228. if (hStatsWnd != NULL)
  1229. {
  1230. PostMessage(hStatsWnd, WM_NEW_STATS_AVAILABLE, 0, 0);
  1231. }
  1232. if (!IsEnabled())
  1233. return hr;
  1234. // check to see if the image index has changed and only
  1235. // switch it if we have to--this avoids flickering.
  1236. LONG_PTR nOldIndex = pNode->GetData(TFS_DATA_IMAGEINDEX);
  1237. int nNewIndex = GetImageIndex(FALSE);
  1238. if (nOldIndex != nNewIndex)
  1239. {
  1240. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  1241. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  1242. pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_ICON);
  1243. }
  1244. return hr;
  1245. }
  1246. /*---------------------------------------------------------------------------
  1247. Scope manipulation functions
  1248. ---------------------------------------------------------------------------*/
  1249. /*---------------------------------------------------------------------------
  1250. CDhcpScope::SetState
  1251. Sets the state for this scope - updates cached information and
  1252. display string
  1253. Author: EricDav
  1254. ---------------------------------------------------------------------------*/
  1255. void
  1256. CDhcpScope::SetState
  1257. (
  1258. DHCP_SUBNET_STATE dhcpSubnetState
  1259. )
  1260. {
  1261. BOOL fSwitched = FALSE;
  1262. if( m_dhcpSubnetState != DhcpSubnetEnabled &&
  1263. m_dhcpSubnetState != DhcpSubnetDisabled ) {
  1264. fSwitched = TRUE;
  1265. }
  1266. if( fSwitched ) {
  1267. if( dhcpSubnetState == DhcpSubnetEnabled ) {
  1268. dhcpSubnetState = DhcpSubnetEnabledSwitched;
  1269. } else {
  1270. dhcpSubnetState = DhcpSubnetDisabledSwitched;
  1271. }
  1272. }
  1273. m_dhcpSubnetState = dhcpSubnetState;
  1274. // update the status text
  1275. if ( !IsEnabled() )
  1276. {
  1277. m_strState.LoadString(IDS_SCOPE_INACTIVE);
  1278. }
  1279. else
  1280. {
  1281. m_strState.LoadString(IDS_SCOPE_ACTIVE);
  1282. }
  1283. }
  1284. /*---------------------------------------------------------------------------
  1285. CDhcpScope::CreateReservation
  1286. Creates a reservation for this scope
  1287. Author: EricDav
  1288. ---------------------------------------------------------------------------*/
  1289. DWORD
  1290. CDhcpScope::CreateReservation
  1291. (
  1292. const CDhcpClient * pClient
  1293. )
  1294. {
  1295. SPITFSNode spResClientNode, spActiveLeaseNode;
  1296. DWORD err = 0;
  1297. //
  1298. // Tell the DHCP server to create this client
  1299. //
  1300. err = CreateClient(pClient);
  1301. if (err != 0)
  1302. return err;
  1303. //
  1304. // Now that we have this reservation on the server, create the UI object
  1305. // in both the reservation folder and the ActiveLeases folder
  1306. //
  1307. // create the Reservation client folder
  1308. //
  1309. CDhcpReservations * pRes = GETHANDLER(CDhcpReservations, m_spReservations);
  1310. CDhcpActiveLeases * pActLeases = GETHANDLER(CDhcpActiveLeases, m_spActiveLeases);
  1311. // only add to the UI if the node is expanded. MMC will fail the call if
  1312. // we try to add a child to a node that hasn't been expanded. If we don't add
  1313. // it now, it will be enumerated when the user selects the node.
  1314. if (pRes->m_bExpanded)
  1315. {
  1316. CDhcpReservationClient * pNewResClient =
  1317. new CDhcpReservationClient(m_spTFSCompData, (CDhcpClient&) *pClient);
  1318. CreateContainerTFSNode(&spResClientNode,
  1319. &GUID_DhcpReservationClientNodeType,
  1320. pNewResClient,
  1321. pNewResClient,
  1322. m_spNodeMgr);
  1323. // Tell the handler to initialize any specific data
  1324. pNewResClient->InitializeNode((ITFSNode *) spResClientNode);
  1325. // Add the node as a child to this node
  1326. CDhcpReservations * pReservations = GETHANDLER(CDhcpReservations, m_spReservations);
  1327. pReservations->AddReservationSorted(m_spReservations, spResClientNode);
  1328. pNewResClient->Release();
  1329. }
  1330. //
  1331. // Active Lease record
  1332. //
  1333. if (pActLeases->m_bExpanded)
  1334. {
  1335. CDhcpActiveLease * pNewLease =
  1336. new CDhcpActiveLease(m_spTFSCompData, (CDhcpClient&) *pClient);
  1337. CreateLeafTFSNode(&spActiveLeaseNode,
  1338. &GUID_DhcpActiveLeaseNodeType,
  1339. pNewLease,
  1340. pNewLease,
  1341. m_spNodeMgr);
  1342. // Tell the handler to initialize any specific data
  1343. pNewLease->InitializeNode((ITFSNode *) spActiveLeaseNode);
  1344. // Add the node as a child to the Active Leases container
  1345. m_spActiveLeases->AddChild(spActiveLeaseNode);
  1346. pNewLease->Release();
  1347. }
  1348. return err;
  1349. }
  1350. /*---------------------------------------------------------------------------
  1351. CDhcpScope::UpdateReservation
  1352. Creates a reservation for this scope
  1353. Author: EricDav
  1354. ---------------------------------------------------------------------------*/
  1355. DWORD
  1356. CDhcpScope::UpdateReservation
  1357. (
  1358. const CDhcpClient * pClient,
  1359. COptionValueEnum * pOptionValueEnum
  1360. )
  1361. {
  1362. DWORD err = 0;
  1363. const CByteArray & baHardwareAddress = pClient->QueryHardwareAddress();
  1364. SPITFSNode spResClientNode, spActiveLeaseNode;
  1365. //
  1366. // To update a reservation we need to remove the old one and update it
  1367. // with the new information. This is mostly for the client type field.
  1368. //
  1369. err = DeleteReservation((CByteArray&) baHardwareAddress,
  1370. pClient->QueryIpAddress());
  1371. // now add the updated one
  1372. err = AddReservation(pClient);
  1373. if (err != ERROR_SUCCESS)
  1374. return err;
  1375. // restore the options for this reserved client
  1376. err = RestoreReservationOptions(pClient, pOptionValueEnum);
  1377. if (err != ERROR_SUCCESS)
  1378. return err;
  1379. // Now update the client info record associated with this.
  1380. err = SetClientInfo(pClient);
  1381. return err;
  1382. }
  1383. /*---------------------------------------------------------------------------
  1384. CDhcpScope::RestoreReservationOptions
  1385. Restores options when updating a reservation becuase the only
  1386. way to update the reservation is to remove it and re-add it.
  1387. Author: EricDav
  1388. ---------------------------------------------------------------------------*/
  1389. DWORD
  1390. CDhcpScope::RestoreReservationOptions
  1391. (
  1392. const CDhcpClient * pClient,
  1393. COptionValueEnum * pOptionValueEnum
  1394. )
  1395. {
  1396. DWORD dwErr = ERROR_SUCCESS;
  1397. CDhcpOption * pCurOption;
  1398. LARGE_INTEGER liVersion;
  1399. GetServerVersion(liVersion);
  1400. // start at the top of the list
  1401. pOptionValueEnum->Reset();
  1402. // loop through all the options, re-adding them
  1403. while (pCurOption = pOptionValueEnum->Next())
  1404. {
  1405. CDhcpOptionValue optValue = pCurOption->QueryValue();
  1406. DHCP_OPTION_DATA * pOptData;
  1407. dwErr = optValue.CreateOptionDataStruct(&pOptData);
  1408. if (dwErr != ERROR_SUCCESS)
  1409. break;
  1410. if ( liVersion.QuadPart >= DHCP_NT5_VERSION )
  1411. {
  1412. LPCTSTR pClassName = pCurOption->IsClassOption() ? pCurOption->GetClassName() : NULL;
  1413. dwErr = ::DhcpSetOptionValueV5((LPTSTR) GetServerIpAddress(),
  1414. pCurOption->IsVendor() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  1415. pCurOption->QueryId(),
  1416. (LPTSTR) pClassName,
  1417. (LPTSTR) pCurOption->GetVendor(),
  1418. &pOptionValueEnum->m_dhcpOptionScopeInfo,
  1419. pOptData);
  1420. }
  1421. else
  1422. {
  1423. dwErr = ::DhcpSetOptionValue((LPTSTR) GetServerIpAddress(),
  1424. pCurOption->QueryId(),
  1425. &pOptionValueEnum->m_dhcpOptionScopeInfo,
  1426. pOptData);
  1427. }
  1428. if (dwErr != ERROR_SUCCESS)
  1429. break;
  1430. }
  1431. return dwErr;
  1432. }
  1433. /*---------------------------------------------------------------------------
  1434. CDhcpScope::AddReservation
  1435. Deletes a reservation
  1436. Author: EricDav
  1437. ---------------------------------------------------------------------------*/
  1438. DWORD
  1439. CDhcpScope::AddReservation
  1440. (
  1441. const CDhcpClient * pClient
  1442. )
  1443. {
  1444. DWORD err = 0 ;
  1445. DHCP_SUBNET_ELEMENT_DATA_V4 dhcSubElData;
  1446. DHCP_IP_RESERVATION_V4 dhcpIpReservation;
  1447. DHCP_CLIENT_UID dhcpClientUID;
  1448. const CByteArray& baHardwareAddress = pClient->QueryHardwareAddress();
  1449. dhcpClientUID.DataLength = (DWORD) baHardwareAddress.GetSize();
  1450. dhcpClientUID.Data = (BYTE *) baHardwareAddress.GetData();
  1451. dhcpIpReservation.ReservedIpAddress = pClient->QueryIpAddress();
  1452. dhcpIpReservation.ReservedForClient = &dhcpClientUID;
  1453. dhcSubElData.ElementType = DhcpReservedIps;
  1454. dhcSubElData.Element.ReservedIp = &dhcpIpReservation;
  1455. dhcpIpReservation.bAllowedClientTypes = pClient->QueryClientType();
  1456. LARGE_INTEGER liVersion;
  1457. GetServerVersion(liVersion);
  1458. if (liVersion.QuadPart >= DHCP_SP2_VERSION)
  1459. {
  1460. err = AddElementV4( &dhcSubElData );
  1461. }
  1462. else
  1463. {
  1464. err = AddElement( reinterpret_cast<DHCP_SUBNET_ELEMENT_DATA *>(&dhcSubElData) );
  1465. }
  1466. return err;
  1467. }
  1468. /*---------------------------------------------------------------------------
  1469. CDhcpScope::DeleteReservation
  1470. Deletes a reservation
  1471. Author: EricDav
  1472. ---------------------------------------------------------------------------*/
  1473. DWORD
  1474. CDhcpScope::DeleteReservation
  1475. (
  1476. CByteArray& baHardwareAddress,
  1477. DHCP_IP_ADDRESS dhcpReservedIpAddress
  1478. )
  1479. {
  1480. DHCP_SUBNET_ELEMENT_DATA dhcpSubnetElementData;
  1481. DHCP_IP_RESERVATION dhcpIpReservation;
  1482. DHCP_CLIENT_UID dhcpClientUID;
  1483. dhcpClientUID.DataLength = (DWORD) baHardwareAddress.GetSize();
  1484. dhcpClientUID.Data = baHardwareAddress.GetData();
  1485. dhcpIpReservation.ReservedIpAddress = dhcpReservedIpAddress;
  1486. dhcpIpReservation.ReservedForClient = &dhcpClientUID;
  1487. dhcpSubnetElementData.ElementType = DhcpReservedIps;
  1488. dhcpSubnetElementData.Element.ReservedIp = &dhcpIpReservation;
  1489. return RemoveElement(&dhcpSubnetElementData, TRUE);
  1490. }
  1491. /*---------------------------------------------------------------------------
  1492. CDhcpScope::DeleteReservation
  1493. Deletes a reservation
  1494. Author: EricDav
  1495. ---------------------------------------------------------------------------*/
  1496. DWORD
  1497. CDhcpScope::DeleteReservation
  1498. (
  1499. DHCP_CLIENT_UID &dhcpClientUID,
  1500. DHCP_IP_ADDRESS dhcpReservedIpAddress
  1501. )
  1502. {
  1503. DHCP_SUBNET_ELEMENT_DATA dhcpSubnetElementData;
  1504. DHCP_IP_RESERVATION dhcpIpReservation;
  1505. dhcpIpReservation.ReservedIpAddress = dhcpReservedIpAddress;
  1506. dhcpIpReservation.ReservedForClient = &dhcpClientUID;
  1507. dhcpSubnetElementData.ElementType = DhcpReservedIps;
  1508. dhcpSubnetElementData.Element.ReservedIp = &dhcpIpReservation;
  1509. return RemoveElement(&dhcpSubnetElementData, TRUE);
  1510. }
  1511. /*---------------------------------------------------------------------------
  1512. CDhcpScope::GetClientInfo
  1513. Gets a clients detailed information
  1514. Author: EricDav
  1515. ---------------------------------------------------------------------------*/
  1516. DWORD
  1517. CDhcpScope::GetClientInfo
  1518. (
  1519. DHCP_IP_ADDRESS dhcpClientIpAddress,
  1520. LPDHCP_CLIENT_INFO *ppdhcpClientInfo
  1521. )
  1522. {
  1523. DHCP_SEARCH_INFO dhcpSearchInfo;
  1524. dhcpSearchInfo.SearchType = DhcpClientIpAddress;
  1525. dhcpSearchInfo.SearchInfo.ClientIpAddress = dhcpClientIpAddress;
  1526. return ::DhcpGetClientInfo(GetServerIpAddress(), &dhcpSearchInfo, ppdhcpClientInfo);
  1527. }
  1528. /*---------------------------------------------------------------------------
  1529. CDhcpScope::CreateClient
  1530. CreateClient() creates a reservation for a client. The act
  1531. of adding a new reserved IP address causes the DHCP server
  1532. to create a new client record; we then set the client info
  1533. for this newly created client.
  1534. Author: EricDav
  1535. ---------------------------------------------------------------------------*/
  1536. DWORD
  1537. CDhcpScope::CreateClient
  1538. (
  1539. const CDhcpClient * pClient
  1540. )
  1541. {
  1542. DWORD err = 0;
  1543. do
  1544. {
  1545. err = AddReservation( pClient );
  1546. if (err != ERROR_SUCCESS)
  1547. break;
  1548. err = SetClientInfo( pClient );
  1549. }
  1550. while (FALSE);
  1551. return err;
  1552. }
  1553. /*---------------------------------------------------------------------------
  1554. CDhcpScope::SetClientInfo
  1555. Description
  1556. Author: EricDav
  1557. ---------------------------------------------------------------------------*/
  1558. DWORD
  1559. CDhcpScope::SetClientInfo
  1560. (
  1561. const CDhcpClient * pClient
  1562. )
  1563. {
  1564. DWORD err = 0 ;
  1565. DHCP_CLIENT_INFO_V4 dhcpClientInfo;
  1566. const CByteArray& baHardwareAddress = pClient->QueryHardwareAddress();
  1567. LARGE_INTEGER liVersion;
  1568. GetServerVersion(liVersion);
  1569. dhcpClientInfo.ClientIpAddress = pClient->QueryIpAddress();
  1570. dhcpClientInfo.SubnetMask = pClient->QuerySubnet();
  1571. dhcpClientInfo.ClientHardwareAddress.DataLength = (DWORD) baHardwareAddress.GetSize();
  1572. dhcpClientInfo.ClientHardwareAddress.Data = (BYTE *) baHardwareAddress.GetData();
  1573. dhcpClientInfo.ClientName = (LPTSTR) ((LPCTSTR) pClient->QueryName());
  1574. dhcpClientInfo.ClientComment = (LPTSTR) ((LPCTSTR) pClient->QueryComment());
  1575. dhcpClientInfo.ClientLeaseExpires = pClient->QueryExpiryDateTime();
  1576. dhcpClientInfo.OwnerHost.IpAddress = 0;
  1577. dhcpClientInfo.OwnerHost.HostName = NULL;
  1578. dhcpClientInfo.OwnerHost.NetBiosName = NULL;
  1579. if (liVersion.QuadPart >= DHCP_SP2_VERSION)
  1580. {
  1581. dhcpClientInfo.bClientType = pClient->QueryClientType();
  1582. err = ::DhcpSetClientInfoV4(GetServerIpAddress(),
  1583. &dhcpClientInfo);
  1584. }
  1585. else
  1586. {
  1587. err = ::DhcpSetClientInfo(GetServerIpAddress(),
  1588. reinterpret_cast<LPDHCP_CLIENT_INFO>(&dhcpClientInfo));
  1589. }
  1590. return err;
  1591. }
  1592. /*---------------------------------------------------------------------------
  1593. CDhcpScope::DeleteClient
  1594. Description
  1595. Author: EricDav
  1596. ---------------------------------------------------------------------------*/
  1597. DWORD
  1598. CDhcpScope::DeleteClient
  1599. (
  1600. DHCP_IP_ADDRESS dhcpClientIpAddress
  1601. )
  1602. {
  1603. DHCP_SEARCH_INFO dhcpClientInfo;
  1604. dhcpClientInfo.SearchType = DhcpClientIpAddress;
  1605. dhcpClientInfo.SearchInfo.ClientIpAddress = dhcpClientIpAddress;
  1606. return ::DhcpDeleteClientInfo((LPWSTR) GetServerIpAddress(),
  1607. &dhcpClientInfo);
  1608. }
  1609. /*---------------------------------------------------------------------------
  1610. CDhcpScope::SetInfo()
  1611. Updates the scope's information
  1612. Author: EricDav
  1613. ---------------------------------------------------------------------------*/
  1614. DWORD
  1615. CDhcpScope::SetInfo()
  1616. {
  1617. DWORD err = 0 ;
  1618. DHCP_SUBNET_INFO dhcpSubnetInfo;
  1619. dhcpSubnetInfo.SubnetAddress = m_dhcpIpAddress;
  1620. dhcpSubnetInfo.SubnetMask = m_dhcpSubnetMask;
  1621. dhcpSubnetInfo.SubnetName = (LPTSTR) ((LPCTSTR) m_strName);
  1622. dhcpSubnetInfo.SubnetComment = (LPTSTR) ((LPCTSTR) m_strComment);
  1623. dhcpSubnetInfo.SubnetState = m_dhcpSubnetState;
  1624. GetServerIpAddress(&dhcpSubnetInfo.PrimaryHost.IpAddress);
  1625. // Review : ericdav - do we need to fill these in?
  1626. dhcpSubnetInfo.PrimaryHost.NetBiosName = NULL;
  1627. dhcpSubnetInfo.PrimaryHost.HostName = NULL;
  1628. err = ::DhcpSetSubnetInfo(GetServerIpAddress(),
  1629. m_dhcpIpAddress,
  1630. &dhcpSubnetInfo);
  1631. return err;
  1632. }
  1633. /*---------------------------------------------------------------------------
  1634. CDhcpScope::GetIpRange()
  1635. returns the scope's allocation range. Connects to the server
  1636. to get the information
  1637. Author: EricDav
  1638. ---------------------------------------------------------------------------*/
  1639. DWORD
  1640. CDhcpScope::GetIpRange
  1641. (
  1642. CDhcpIpRange * pdhipr
  1643. )
  1644. {
  1645. BOOL bAlloced = FALSE;
  1646. DWORD dwError = ERROR_SUCCESS;
  1647. pdhipr->SetAddr(0, TRUE);
  1648. pdhipr->SetAddr(0, FALSE);
  1649. CDhcpAddressPool * pAddressPool = GetAddressPoolObject();
  1650. if (pAddressPool == NULL)
  1651. {
  1652. // the address pool folder isn't there yet...
  1653. // Create a temporary one for now...
  1654. pAddressPool = new CDhcpAddressPool(m_spTFSCompData);
  1655. bAlloced = TRUE;
  1656. }
  1657. // Get a query object from the address pool handler
  1658. CDhcpAddressPoolQueryObj * pQueryObject =
  1659. reinterpret_cast<CDhcpAddressPoolQueryObj *>(pAddressPool->OnCreateQuery(m_spAddressPool));
  1660. // if we created an address pool handler, then free it up now
  1661. if (bAlloced)
  1662. {
  1663. pQueryObject->m_strServer = GetServerIpAddress();
  1664. pQueryObject->m_dhcpScopeAddress = GetAddress();
  1665. pQueryObject->m_fSupportsDynBootp = GetServerObject()->FSupportsDynBootp();
  1666. pAddressPool->Release();
  1667. }
  1668. // tell the query object to get the ip ranges
  1669. pQueryObject->EnumerateIpRanges();
  1670. // check to see if there was any problems getting the information
  1671. dwError = pQueryObject->m_dwError;
  1672. if (dwError != ERROR_SUCCESS)
  1673. {
  1674. return dwError;
  1675. }
  1676. LPQUEUEDATA pQD;
  1677. while (pQD = pQueryObject->RemoveFromQueue())
  1678. {
  1679. Assert (pQD->Type == QDATA_PNODE);
  1680. SPITFSNode p;
  1681. p = reinterpret_cast<ITFSNode *>(pQD->Data);
  1682. delete pQD;
  1683. CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, p);
  1684. *pdhipr = *pAllocRange;
  1685. pdhipr->SetRangeType(pAllocRange->GetRangeType());
  1686. p.Release();
  1687. }
  1688. pQueryObject->Release();
  1689. return dwError;
  1690. }
  1691. /*---------------------------------------------------------------------------
  1692. CDhcpScope::UpdateIpRange()
  1693. This function updates the IP range on the server. We also need
  1694. to remove any exclusion ranges that fall outside of the new
  1695. allocation range.
  1696. Author: EricDav
  1697. ---------------------------------------------------------------------------*/
  1698. DWORD
  1699. CDhcpScope::UpdateIpRange
  1700. (
  1701. DHCP_IP_RANGE * pdhipr
  1702. )
  1703. {
  1704. return SetIpRange(pdhipr, TRUE);
  1705. }
  1706. /*---------------------------------------------------------------------------
  1707. CDhcpScope::QueryIpRange()
  1708. Returns the scope's allocation range (doesn't talk to the server
  1709. directly, only returns internally cached information).
  1710. Author: EricDav
  1711. ---------------------------------------------------------------------------*/
  1712. void
  1713. CDhcpScope::QueryIpRange
  1714. (
  1715. DHCP_IP_RANGE * pdhipr
  1716. )
  1717. {
  1718. pdhipr->StartAddress = 0;
  1719. pdhipr->EndAddress = 0;
  1720. SPITFSNodeEnum spNodeEnum;
  1721. SPITFSNode spCurrentNode;
  1722. ULONG nNumReturned = 0;
  1723. m_spAddressPool->GetEnum(&spNodeEnum);
  1724. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1725. while (nNumReturned)
  1726. {
  1727. if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
  1728. {
  1729. // found the address
  1730. //
  1731. CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, spCurrentNode);
  1732. pdhipr->StartAddress = pAllocRange->QueryAddr(TRUE);
  1733. pdhipr->EndAddress = pAllocRange->QueryAddr(FALSE);
  1734. }
  1735. spCurrentNode.Release();
  1736. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1737. }
  1738. }
  1739. /*---------------------------------------------------------------------------
  1740. CDhcpScope::SetIpRange
  1741. Set's the allocation range for this scope
  1742. Author: EricDav
  1743. ---------------------------------------------------------------------------*/
  1744. DWORD
  1745. CDhcpScope::SetIpRange
  1746. (
  1747. DHCP_IP_RANGE * pdhcpIpRange,
  1748. BOOL bUpdateOnServer
  1749. )
  1750. {
  1751. CDhcpIpRange dhcpIpRange = *pdhcpIpRange;
  1752. return SetIpRange(dhcpIpRange, bUpdateOnServer);
  1753. }
  1754. /*---------------------------------------------------------------------------
  1755. CDhcpScope::SetIpRange
  1756. Set's the allocation range for this scope
  1757. Author: EricDav
  1758. ---------------------------------------------------------------------------*/
  1759. DWORD
  1760. CDhcpScope::SetIpRange
  1761. (
  1762. CDhcpIpRange & dhcpIpRange,
  1763. BOOL bUpdateOnServer
  1764. )
  1765. {
  1766. DWORD err = 0;
  1767. if (bUpdateOnServer)
  1768. {
  1769. DHCP_SUBNET_ELEMENT_DATA dhcSubElData;
  1770. CDhcpIpRange dhipOldRange;
  1771. DHCP_IP_RANGE dhcpTempIpRange;
  1772. err = GetIpRange(&dhipOldRange);
  1773. if (err != ERROR_SUCCESS)
  1774. {
  1775. return err;
  1776. }
  1777. dhcpTempIpRange.StartAddress = dhipOldRange.QueryAddr(TRUE);
  1778. dhcpTempIpRange.EndAddress = dhipOldRange.QueryAddr(FALSE);
  1779. dhcSubElData.ElementType = DhcpIpRanges;
  1780. dhcSubElData.Element.IpRange = &dhcpTempIpRange;
  1781. //
  1782. // First update the information on the server
  1783. //
  1784. if (dhcpIpRange.GetRangeType() != 0)
  1785. {
  1786. // Dynamic BOOTP stuff...
  1787. DHCP_SUBNET_ELEMENT_DATA_V5 dhcSubElDataV5;
  1788. DHCP_BOOTP_IP_RANGE dhcpNewIpRange = {0};
  1789. dhcpNewIpRange.StartAddress = dhcpIpRange.QueryAddr(TRUE);
  1790. dhcpNewIpRange.EndAddress = dhcpIpRange.QueryAddr(FALSE);
  1791. dhcpNewIpRange.BootpAllocated = 0;
  1792. // this field could be set to allow X number of dyn bootp clients from a scope.
  1793. dhcpNewIpRange.MaxBootpAllowed = -1;
  1794. dhcSubElDataV5.Element.IpRange = &dhcpNewIpRange;
  1795. dhcSubElDataV5.ElementType = (DHCP_SUBNET_ELEMENT_TYPE) dhcpIpRange.GetRangeType();
  1796. err = AddElementV5(&dhcSubElDataV5);
  1797. if (err != ERROR_SUCCESS)
  1798. {
  1799. DHCP_BOOTP_IP_RANGE dhcpOldIpRange = {0};
  1800. // something bad happened, try to put the old range back
  1801. dhcpOldIpRange.StartAddress = dhipOldRange.QueryAddr(TRUE);
  1802. dhcpOldIpRange.EndAddress = dhipOldRange.QueryAddr(FALSE);
  1803. dhcSubElDataV5.Element.IpRange = &dhcpOldIpRange;
  1804. dhcSubElDataV5.ElementType = (DHCP_SUBNET_ELEMENT_TYPE) dhipOldRange.GetRangeType();
  1805. if (AddElementV5(&dhcSubElDataV5) != ERROR_SUCCESS)
  1806. {
  1807. Trace0("SetIpRange - cannot return ip range back to old state!!");
  1808. }
  1809. }
  1810. }
  1811. else
  1812. {
  1813. // Remove the old IP range; allow "not found" error in new scope.
  1814. //
  1815. (void)RemoveElement(&dhcSubElData);
  1816. DHCP_IP_RANGE dhcpNewIpRange = {0};
  1817. dhcpNewIpRange.StartAddress = dhcpIpRange.QueryAddr(TRUE);
  1818. dhcpNewIpRange.EndAddress = dhcpIpRange.QueryAddr(FALSE);
  1819. dhcSubElData.Element.IpRange = &dhcpNewIpRange;
  1820. err = AddElement( & dhcSubElData );
  1821. if (err != ERROR_SUCCESS)
  1822. {
  1823. // something bad happened, try to put the old range back
  1824. dhcpTempIpRange.StartAddress = dhipOldRange.QueryAddr(TRUE);
  1825. dhcpTempIpRange.EndAddress = dhipOldRange.QueryAddr(FALSE);
  1826. dhcSubElData.Element.IpRange = &dhcpTempIpRange;
  1827. if (AddElement(&dhcSubElData) != ERROR_SUCCESS)
  1828. {
  1829. Trace0("SetIpRange - cannot return ip range back to old state!!");
  1830. }
  1831. }
  1832. }
  1833. }
  1834. //
  1835. // Find the address pool folder and update the UI object
  1836. //
  1837. SPITFSNodeEnum spNodeEnum;
  1838. SPITFSNode spCurrentNode;
  1839. ULONG nNumReturned = 0;
  1840. if (m_spAddressPool == NULL)
  1841. return err;
  1842. m_spAddressPool->GetEnum(&spNodeEnum);
  1843. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1844. while (nNumReturned)
  1845. {
  1846. if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
  1847. {
  1848. // found the address
  1849. //
  1850. CDhcpAllocationRange * pAllocRange = GETHANDLER(CDhcpAllocationRange, spCurrentNode);
  1851. // now set them
  1852. //
  1853. pAllocRange->SetAddr(dhcpIpRange.QueryAddr(TRUE), TRUE);
  1854. pAllocRange->SetAddr(dhcpIpRange.QueryAddr(FALSE), FALSE);
  1855. // tell the UI to update
  1856. spCurrentNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
  1857. }
  1858. spCurrentNode.Release();
  1859. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1860. }
  1861. return err ;
  1862. }
  1863. /*---------------------------------------------------------------------------
  1864. CDhcpScope::IsOverlappingRange
  1865. determines if the exclusion overlaps an existing range
  1866. Author: EricDav
  1867. ---------------------------------------------------------------------------*/
  1868. BOOL
  1869. CDhcpScope::IsOverlappingRange
  1870. (
  1871. CDhcpIpRange & dhcpIpRange
  1872. )
  1873. {
  1874. SPITFSNodeEnum spNodeEnum;
  1875. SPITFSNode spCurrentNode;
  1876. ULONG nNumReturned = 0;
  1877. BOOL bOverlap = FALSE;
  1878. m_spActiveLeases->GetEnum(&spNodeEnum);
  1879. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1880. while (nNumReturned)
  1881. {
  1882. if (spCurrentNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_EXCLUSION_RANGE)
  1883. {
  1884. // found the address
  1885. //
  1886. CDhcpExclusionRange * pExclusion = GETHANDLER(CDhcpExclusionRange, spCurrentNode);
  1887. if ( bOverlap = pExclusion->IsOverlap( dhcpIpRange ) )
  1888. {
  1889. spCurrentNode.Release();
  1890. break;
  1891. }
  1892. }
  1893. spCurrentNode.Release();
  1894. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1895. }
  1896. return bOverlap ;
  1897. }
  1898. /*---------------------------------------------------------------------------
  1899. CDhcpScope::IsValidExclusion
  1900. determines if the exclusion is valid for this scope
  1901. Author: EricDav
  1902. ---------------------------------------------------------------------------*/
  1903. DWORD
  1904. CDhcpScope::IsValidExclusion
  1905. (
  1906. CDhcpIpRange & dhcpExclusionRange
  1907. )
  1908. {
  1909. DWORD err = 0;
  1910. CDhcpIpRange dhcpScopeRange;
  1911. err = GetIpRange (&dhcpScopeRange);
  1912. //
  1913. // Get the data into a range object.
  1914. //
  1915. if ( IsOverlappingRange( dhcpExclusionRange ) )
  1916. {
  1917. //
  1918. // Walk the current list, determining if the new range is valid.
  1919. // Then, if OK, verify that it's really a sub-range of the current range.
  1920. //
  1921. err = IDS_ERR_IP_RANGE_OVERLAP ;
  1922. }
  1923. else if ( ! dhcpExclusionRange.IsSubset( dhcpScopeRange ) )
  1924. {
  1925. //
  1926. // Guarantee that the new range is an (improper) subset of the scope's range
  1927. //
  1928. err = IDS_ERR_IP_RANGE_NOT_SUBSET ;
  1929. }
  1930. return err;
  1931. }
  1932. /*---------------------------------------------------------------------------
  1933. CDhcpScope::StoreExceptionList
  1934. Adds a bunch of exclusions to the scope
  1935. Author: EricDav
  1936. ---------------------------------------------------------------------------*/
  1937. LONG
  1938. CDhcpScope::StoreExceptionList
  1939. (
  1940. CExclusionList * plistExclusions
  1941. )
  1942. {
  1943. DHCP_SUBNET_ELEMENT_DATA dhcElement ;
  1944. DHCP_IP_RANGE dhipr ;
  1945. CDhcpIpRange * pobIpRange ;
  1946. DWORD err = 0, err1 = 0;
  1947. POSITION pos;
  1948. pos = plistExclusions->GetHeadPosition();
  1949. while ( pos )
  1950. {
  1951. pobIpRange = plistExclusions->GetNext(pos);
  1952. err1 = AddExclusion( *pobIpRange ) ;
  1953. if ( err1 != 0 )
  1954. {
  1955. err = err1;
  1956. Trace1("CDhcpScope::StoreExceptionList error adding range %d\n", err);
  1957. }
  1958. }
  1959. return err ;
  1960. }
  1961. /*---------------------------------------------------------------------------
  1962. CDhcpScope::AddExclusion
  1963. Adds an individual exclusion to the server
  1964. Author: EricDav
  1965. ---------------------------------------------------------------------------*/
  1966. DWORD
  1967. CDhcpScope::AddExclusion
  1968. (
  1969. CDhcpIpRange & dhcpIpRange,
  1970. BOOL bAddToUI
  1971. )
  1972. {
  1973. DHCP_SUBNET_ELEMENT_DATA dhcElement ;
  1974. DHCP_IP_RANGE dhipr ;
  1975. DWORD err = 0;
  1976. dhcElement.ElementType = DhcpExcludedIpRanges ;
  1977. dhipr = dhcpIpRange ;
  1978. dhcElement.Element.ExcludeIpRange = & dhipr ;
  1979. Trace2("CDhcpScope::AddExclusion add excluded range %lx %lx\n", dhipr.StartAddress, dhipr.EndAddress );
  1980. err = AddElement( & dhcElement ) ;
  1981. //if ( err != 0 && err != ERROR_DHCP_INVALID_RANGE)
  1982. if ( err != 0 )
  1983. {
  1984. Trace1("CDhcpScope::AddExclusion error removing range %d\n", err);
  1985. }
  1986. if (m_spAddressPool != NULL)
  1987. {
  1988. CDhcpAddressPool * pAddrPool = GETHANDLER(CDhcpAddressPool, m_spAddressPool);
  1989. if (!err && bAddToUI && pAddrPool->m_bExpanded)
  1990. {
  1991. SPITFSNode spNewExclusion;
  1992. CDhcpExclusionRange * pExclusion =
  1993. new CDhcpExclusionRange(m_spTFSCompData, &((DHCP_IP_RANGE) dhcpIpRange));
  1994. CreateLeafTFSNode(&spNewExclusion,
  1995. &GUID_DhcpExclusionNodeType,
  1996. pExclusion,
  1997. pExclusion,
  1998. m_spNodeMgr);
  1999. // Tell the handler to initialize any specific data
  2000. pExclusion->InitializeNode((ITFSNode *) spNewExclusion);
  2001. // Add the node as a child to this node
  2002. m_spAddressPool->AddChild(spNewExclusion);
  2003. pExclusion->Release();
  2004. }
  2005. }
  2006. TriggerStatsRefresh();
  2007. return err;
  2008. }
  2009. /*---------------------------------------------------------------------------
  2010. CDhcpScope::RemoveExclusion
  2011. Removes and exclusion from the server
  2012. Author: EricDav
  2013. ---------------------------------------------------------------------------*/
  2014. DWORD
  2015. CDhcpScope::RemoveExclusion
  2016. (
  2017. CDhcpIpRange & dhcpIpRange
  2018. )
  2019. {
  2020. DHCP_SUBNET_ELEMENT_DATA dhcElement ;
  2021. DHCP_IP_RANGE dhipr ;
  2022. DWORD err = 0;
  2023. dhcElement.ElementType = DhcpExcludedIpRanges ;
  2024. dhipr = dhcpIpRange ;
  2025. dhcElement.Element.ExcludeIpRange = & dhipr ;
  2026. Trace2("CDhcpScope::RemoveExclusion remove excluded range %lx %lx\n", dhipr.StartAddress, dhipr.EndAddress);
  2027. err = RemoveElement( & dhcElement ) ;
  2028. //if ( err != 0 && err != ERROR_DHCP_INVALID_RANGE)
  2029. if ( err != 0 )
  2030. {
  2031. Trace1("CDhcpScope::RemoveExclusion error removing range %d\n", err);
  2032. }
  2033. return err;
  2034. }
  2035. /*---------------------------------------------------------------------------
  2036. CDhcpScope::GetLeaseTime
  2037. Gets the least time for this scope
  2038. Author: EricDav
  2039. ---------------------------------------------------------------------------*/
  2040. DWORD
  2041. CDhcpScope::GetLeaseTime
  2042. (
  2043. LPDWORD pdwLeaseTime
  2044. )
  2045. {
  2046. //
  2047. // Check option 51 -- the lease duration
  2048. //
  2049. DWORD dwLeaseTime = 0;
  2050. DHCP_OPTION_VALUE * poptValue = NULL;
  2051. DWORD err = GetOptionValue(OPTION_LEASE_DURATION,
  2052. DhcpSubnetOptions,
  2053. &poptValue);
  2054. if (err != ERROR_SUCCESS)
  2055. {
  2056. Trace0("CDhcpScope::GetLeaseTime - couldn't get lease duration -- \
  2057. this scope may have been created by a pre-release version of the admin tool\n");
  2058. //
  2059. // The scope doesn't have a lease duration, maybe there's
  2060. // a global option that can come to the rescue here...
  2061. //
  2062. if ((err = GetOptionValue(OPTION_LEASE_DURATION,
  2063. DhcpGlobalOptions,
  2064. &poptValue)) != ERROR_SUCCESS)
  2065. {
  2066. Trace0("CDhcpScope::GetLeaseTime - No global lease duration either -- \
  2067. assuming permanent lease duration\n");
  2068. dwLeaseTime = 0;
  2069. }
  2070. }
  2071. if (err == ERROR_SUCCESS)
  2072. {
  2073. if (poptValue->Value.Elements != NULL)
  2074. dwLeaseTime = poptValue->Value.Elements[0].Element.DWordOption;
  2075. }
  2076. if (poptValue)
  2077. ::DhcpRpcFreeMemory(poptValue);
  2078. *pdwLeaseTime = dwLeaseTime;
  2079. return err;
  2080. }
  2081. /*---------------------------------------------------------------------------
  2082. CDhcpScope::SetLeaseTime
  2083. Sets the least time for this scope
  2084. Author: EricDav
  2085. ---------------------------------------------------------------------------*/
  2086. DWORD
  2087. CDhcpScope::SetLeaseTime
  2088. (
  2089. DWORD dwLeaseTime
  2090. )
  2091. {
  2092. DWORD err = 0;
  2093. //
  2094. // Set lease duration (option 51)
  2095. //
  2096. CDhcpOption dhcpOption (OPTION_LEASE_DURATION, DhcpDWordOption , _T(""), _T(""));
  2097. dhcpOption.QueryValue().SetNumber(dwLeaseTime);
  2098. err = SetOptionValue(&dhcpOption, DhcpSubnetOptions);
  2099. return err;
  2100. }
  2101. /*---------------------------------------------------------------------------
  2102. CDhcpScope::GetDynBootpLeaseTime
  2103. Gets the least time for this scope
  2104. Author: EricDav
  2105. ---------------------------------------------------------------------------*/
  2106. DWORD
  2107. CDhcpScope::GetDynBootpLeaseTime
  2108. (
  2109. LPDWORD pdwLeaseTime
  2110. )
  2111. {
  2112. //
  2113. // Check option 51 -- the lease duration
  2114. //
  2115. DWORD dwLeaseTime = 0;
  2116. DHCP_OPTION_VALUE * poptValue = NULL;
  2117. CString strName;
  2118. GetDynBootpClassName(strName);
  2119. DWORD err = GetOptionValue(OPTION_LEASE_DURATION,
  2120. DhcpSubnetOptions,
  2121. &poptValue,
  2122. 0,
  2123. strName,
  2124. NULL);
  2125. if (err != ERROR_SUCCESS)
  2126. {
  2127. Trace0("CDhcpScope::GetDynBootpLeaseTime - couldn't get lease duration -- \
  2128. this scope may have been created by a pre-release version of the admin tool\n");
  2129. //
  2130. // The scope doesn't have a lease duration, maybe there's
  2131. // a global option that can come to the rescue here...
  2132. //
  2133. if ((err = GetOptionValue(OPTION_LEASE_DURATION,
  2134. DhcpGlobalOptions,
  2135. &poptValue,
  2136. 0,
  2137. strName,
  2138. NULL)) != ERROR_SUCCESS)
  2139. {
  2140. Trace0("CDhcpScope::GetDynBootpLeaseTime - No global lease duration either -- \
  2141. assuming permanent lease duration\n");
  2142. dwLeaseTime = 0;
  2143. }
  2144. }
  2145. if (err == ERROR_SUCCESS)
  2146. {
  2147. if (poptValue->Value.Elements != NULL)
  2148. dwLeaseTime = poptValue->Value.Elements[0].Element.DWordOption;
  2149. }
  2150. else
  2151. {
  2152. // none specified, using default
  2153. dwLeaseTime = UtilConvertLeaseTime(DYN_BOOTP_DFAULT_LEASE_DAYS,
  2154. DYN_BOOTP_DFAULT_LEASE_HOURS,
  2155. DYN_BOOTP_DFAULT_LEASE_MINUTES);
  2156. }
  2157. if (poptValue)
  2158. ::DhcpRpcFreeMemory(poptValue);
  2159. *pdwLeaseTime = dwLeaseTime;
  2160. return err;
  2161. }
  2162. /*---------------------------------------------------------------------------
  2163. CDhcpScope::SetDynBootpLeaseTime
  2164. Sets the least time for this scope
  2165. Author: EricDav
  2166. ---------------------------------------------------------------------------*/
  2167. DWORD
  2168. CDhcpScope::SetDynBootpLeaseTime
  2169. (
  2170. DWORD dwLeaseTime
  2171. )
  2172. {
  2173. DWORD err = 0;
  2174. //
  2175. // Set lease duration (option 51)
  2176. //
  2177. CDhcpOption dhcpOption (OPTION_LEASE_DURATION, DhcpDWordOption , _T(""), _T(""));
  2178. dhcpOption.QueryValue().SetNumber(dwLeaseTime);
  2179. CString strName;
  2180. GetDynBootpClassName(strName);
  2181. err = SetOptionValue(&dhcpOption, DhcpSubnetOptions, 0, strName, NULL);
  2182. return err;
  2183. }
  2184. /*---------------------------------------------------------------------------
  2185. CDhcpScope::GetDynBootpClassName
  2186. returns the user class name to be used to set the lease time
  2187. Author: EricDav
  2188. ---------------------------------------------------------------------------*/
  2189. void
  2190. CDhcpScope::GetDynBootpClassName(CString & strName)
  2191. {
  2192. // use DHCP_BOOTP_CLASS_TXT as the class data to search for
  2193. CClassInfoArray classInfoArray;
  2194. GetServerObject()->GetClassInfoArray(classInfoArray);
  2195. for (int i = 0; i < classInfoArray.GetSize(); i++)
  2196. {
  2197. // check to make sure same size
  2198. if (classInfoArray[i].IsDynBootpClass())
  2199. {
  2200. // found it!
  2201. strName = classInfoArray[i].strName;
  2202. break;
  2203. }
  2204. }
  2205. }
  2206. DWORD
  2207. CDhcpScope::SetDynamicBootpInfo(UINT uRangeType, DWORD dwLeaseTime)
  2208. {
  2209. DWORD dwErr = 0;
  2210. // set the range type
  2211. CDhcpIpRange dhcpIpRange;
  2212. GetIpRange(&dhcpIpRange);
  2213. dhcpIpRange.SetRangeType(uRangeType);
  2214. // this updates the type
  2215. dwErr = SetIpRange(dhcpIpRange, TRUE);
  2216. if (dwErr != ERROR_SUCCESS)
  2217. return dwErr;
  2218. // set the lease time
  2219. dwErr = SetDynBootpLeaseTime(dwLeaseTime);
  2220. return dwErr;
  2221. }
  2222. /*---------------------------------------------------------------------------
  2223. CDhcpScope::GetDnsRegistration
  2224. Gets the DNS registration option value
  2225. Author: EricDav
  2226. ---------------------------------------------------------------------------*/
  2227. DWORD
  2228. CDhcpScope::GetDnsRegistration
  2229. (
  2230. LPDWORD pDnsRegOption
  2231. )
  2232. {
  2233. //
  2234. // Check option 81 -- the DNS registration option
  2235. //
  2236. DHCP_OPTION_VALUE * poptValue = NULL;
  2237. DWORD err = GetOptionValue(OPTION_DNS_REGISTATION,
  2238. DhcpSubnetOptions,
  2239. &poptValue);
  2240. // this is the default
  2241. if (pDnsRegOption)
  2242. *pDnsRegOption = DHCP_DYN_DNS_DEFAULT;
  2243. if (err == ERROR_SUCCESS)
  2244. {
  2245. if ((poptValue->Value.Elements != NULL) &&
  2246. (pDnsRegOption))
  2247. {
  2248. *pDnsRegOption = poptValue->Value.Elements[0].Element.DWordOption;
  2249. }
  2250. }
  2251. else
  2252. {
  2253. Trace0("CDhcpScope::GetDnsRegistration - couldn't get DNS reg value, option may not be defined, Getting Server value.\n");
  2254. CDhcpServer * pServer = GETHANDLER(CDhcpServer, m_spServerNode);
  2255. err = pServer->GetDnsRegistration(pDnsRegOption);
  2256. }
  2257. if (poptValue)
  2258. ::DhcpRpcFreeMemory(poptValue);
  2259. return err;
  2260. }
  2261. /*---------------------------------------------------------------------------
  2262. CDhcpScope::SetDnsRegistration
  2263. Sets the DNS Registration option for this scope
  2264. Author: EricDav
  2265. ---------------------------------------------------------------------------*/
  2266. DWORD
  2267. CDhcpScope::SetDnsRegistration
  2268. (
  2269. DWORD DnsRegOption
  2270. )
  2271. {
  2272. DWORD err = 0;
  2273. //
  2274. // Set DNS name registration (option 81)
  2275. //
  2276. CDhcpOption dhcpOption (OPTION_DNS_REGISTATION, DhcpDWordOption , _T(""), _T(""));
  2277. dhcpOption.QueryValue().SetNumber(DnsRegOption);
  2278. err = SetOptionValue(&dhcpOption, DhcpSubnetOptions);
  2279. return err;
  2280. }
  2281. /*---------------------------------------------------------------------------
  2282. CDhcpScope::SetOptionValue
  2283. Sets the least time for this scope
  2284. Author: EricDav
  2285. ---------------------------------------------------------------------------*/
  2286. DWORD
  2287. CDhcpScope::SetOptionValue
  2288. (
  2289. CDhcpOption * pdhcType,
  2290. DHCP_OPTION_SCOPE_TYPE dhcOptType,
  2291. DHCP_IP_ADDRESS dhipaReservation,
  2292. LPCTSTR pClassName,
  2293. LPCTSTR pVendorName
  2294. )
  2295. {
  2296. DWORD err = 0;
  2297. DHCP_OPTION_DATA * pdhcOptionData;
  2298. DHCP_OPTION_SCOPE_INFO dhcScopeInfo;
  2299. CDhcpOptionValue * pcOptionValue = NULL;
  2300. ZeroMemory( & dhcScopeInfo, sizeof(dhcScopeInfo) );
  2301. CATCH_MEM_EXCEPTION
  2302. {
  2303. pcOptionValue = new CDhcpOptionValue( & pdhcType->QueryValue() ) ;
  2304. //if ( (err = pcOptionValue->QueryError()) == 0 )
  2305. if ( pcOptionValue )
  2306. {
  2307. dhcScopeInfo.ScopeType = dhcOptType ;
  2308. //
  2309. // Provide the sub-net address if this is a scope-level operation
  2310. //
  2311. if ( dhcOptType == DhcpSubnetOptions )
  2312. {
  2313. dhcScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpIpAddress;
  2314. }
  2315. else if ( dhcOptType == DhcpReservedOptions )
  2316. {
  2317. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = dhipaReservation;
  2318. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = m_dhcpIpAddress;
  2319. }
  2320. pcOptionValue->CreateOptionDataStruct(&pdhcOptionData, TRUE);
  2321. if (pClassName || pVendorName)
  2322. {
  2323. err = (DWORD) ::DhcpSetOptionValueV5((LPTSTR) GetServerIpAddress(),
  2324. 0,
  2325. pdhcType->QueryId(),
  2326. (LPTSTR) pClassName,
  2327. (LPTSTR) pVendorName,
  2328. &dhcScopeInfo,
  2329. pdhcOptionData);
  2330. }
  2331. else
  2332. {
  2333. err = (DWORD) ::DhcpSetOptionValue(GetServerIpAddress(),
  2334. pdhcType->QueryId(),
  2335. &dhcScopeInfo,
  2336. pdhcOptionData);
  2337. }
  2338. }
  2339. }
  2340. END_MEM_EXCEPTION(err) ;
  2341. delete pcOptionValue ;
  2342. return err ;
  2343. }
  2344. /*---------------------------------------------------------------------------
  2345. CDhcpScope::GetValue
  2346. Gets an option value for this scope
  2347. Author: EricDav
  2348. ---------------------------------------------------------------------------*/
  2349. DWORD
  2350. CDhcpScope::GetOptionValue
  2351. (
  2352. DHCP_OPTION_ID OptionID,
  2353. DHCP_OPTION_SCOPE_TYPE dhcOptType,
  2354. DHCP_OPTION_VALUE ** ppdhcOptionValue,
  2355. DHCP_IP_ADDRESS dhipaReservation,
  2356. LPCTSTR pClassName,
  2357. LPCTSTR pVendorName
  2358. )
  2359. {
  2360. DWORD err = 0 ;
  2361. DHCP_OPTION_SCOPE_INFO dhcScopeInfo ;
  2362. ZeroMemory( &dhcScopeInfo, sizeof(dhcScopeInfo) );
  2363. CATCH_MEM_EXCEPTION
  2364. {
  2365. dhcScopeInfo.ScopeType = dhcOptType ;
  2366. //
  2367. // Provide the sub-net address if this is a scope-level operation
  2368. //
  2369. if ( dhcOptType == DhcpSubnetOptions )
  2370. {
  2371. dhcScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpIpAddress;
  2372. }
  2373. else if ( dhcOptType == DhcpReservedOptions )
  2374. {
  2375. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = dhipaReservation;
  2376. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = m_dhcpIpAddress;
  2377. }
  2378. if (pClassName || pVendorName)
  2379. {
  2380. err = (DWORD) ::DhcpGetOptionValueV5((LPTSTR) GetServerIpAddress(),
  2381. 0,
  2382. OptionID,
  2383. (LPTSTR) pClassName,
  2384. (LPTSTR) pVendorName,
  2385. &dhcScopeInfo,
  2386. ppdhcOptionValue );
  2387. }
  2388. else
  2389. {
  2390. err = (DWORD) ::DhcpGetOptionValue(GetServerIpAddress(),
  2391. OptionID,
  2392. &dhcScopeInfo,
  2393. ppdhcOptionValue );
  2394. }
  2395. }
  2396. END_MEM_EXCEPTION(err) ;
  2397. return err ;
  2398. }
  2399. /*---------------------------------------------------------------------------
  2400. CDhcpScope::RemoveValue
  2401. Removes an option
  2402. Author: EricDav
  2403. ---------------------------------------------------------------------------*/
  2404. DWORD
  2405. CDhcpScope::RemoveOptionValue
  2406. (
  2407. DHCP_OPTION_ID dhcOptId,
  2408. DHCP_OPTION_SCOPE_TYPE dhcOptType,
  2409. DHCP_IP_ADDRESS dhipaReservation
  2410. )
  2411. {
  2412. DHCP_OPTION_SCOPE_INFO dhcScopeInfo;
  2413. ZeroMemory( &dhcScopeInfo, sizeof(dhcScopeInfo) );
  2414. dhcScopeInfo.ScopeType = dhcOptType;
  2415. //
  2416. // Provide the sub-net address if this is a scope-level operation
  2417. //
  2418. if ( dhcOptType == DhcpSubnetOptions )
  2419. {
  2420. dhcScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpIpAddress;
  2421. }
  2422. else if ( dhcOptType == DhcpReservedOptions )
  2423. {
  2424. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = dhipaReservation;
  2425. dhcScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = m_dhcpIpAddress;
  2426. }
  2427. return (DWORD) ::DhcpRemoveOptionValue(GetServerIpAddress(),
  2428. dhcOptId,
  2429. &dhcScopeInfo);
  2430. }
  2431. /*---------------------------------------------------------------------------
  2432. CDhcpScope::AddElement
  2433. Description
  2434. Author: EricDav
  2435. ---------------------------------------------------------------------------*/
  2436. DWORD
  2437. CDhcpScope::AddElement
  2438. (
  2439. DHCP_SUBNET_ELEMENT_DATA * pdhcpSubnetElementData
  2440. )
  2441. {
  2442. return ::DhcpAddSubnetElement(GetServerIpAddress(),
  2443. m_dhcpIpAddress,
  2444. pdhcpSubnetElementData);
  2445. }
  2446. /*---------------------------------------------------------------------------
  2447. CDhcpScope::RemoveElement
  2448. Description
  2449. Author: EricDav
  2450. ---------------------------------------------------------------------------*/
  2451. DWORD
  2452. CDhcpScope::RemoveElement
  2453. (
  2454. DHCP_SUBNET_ELEMENT_DATA * pdhcpSubnetElementData,
  2455. BOOL bForce
  2456. )
  2457. {
  2458. return ::DhcpRemoveSubnetElement(GetServerIpAddress(),
  2459. m_dhcpIpAddress,
  2460. pdhcpSubnetElementData,
  2461. bForce ? DhcpFullForce : DhcpNoForce);
  2462. }
  2463. /*---------------------------------------------------------------------------
  2464. CDhcpScope::AddElementV4
  2465. Description
  2466. Author: EricDav
  2467. ---------------------------------------------------------------------------*/
  2468. DWORD
  2469. CDhcpScope::AddElementV4
  2470. (
  2471. DHCP_SUBNET_ELEMENT_DATA_V4 * pdhcpSubnetElementData
  2472. )
  2473. {
  2474. return ::DhcpAddSubnetElementV4(GetServerIpAddress(),
  2475. m_dhcpIpAddress,
  2476. pdhcpSubnetElementData);
  2477. }
  2478. /*---------------------------------------------------------------------------
  2479. CDhcpScope::RemoveElementV4
  2480. Description
  2481. Author: EricDav
  2482. ---------------------------------------------------------------------------*/
  2483. DWORD
  2484. CDhcpScope::RemoveElementV4
  2485. (
  2486. DHCP_SUBNET_ELEMENT_DATA_V4 * pdhcpSubnetElementData,
  2487. BOOL bForce
  2488. )
  2489. {
  2490. return ::DhcpRemoveSubnetElementV4(GetServerIpAddress(),
  2491. m_dhcpIpAddress,
  2492. pdhcpSubnetElementData,
  2493. bForce ? DhcpFullForce : DhcpNoForce);
  2494. }
  2495. /*---------------------------------------------------------------------------
  2496. CDhcpScope::AddElementV5
  2497. Description
  2498. Author: EricDav
  2499. ---------------------------------------------------------------------------*/
  2500. DWORD
  2501. CDhcpScope::AddElementV5
  2502. (
  2503. DHCP_SUBNET_ELEMENT_DATA_V5 * pdhcpSubnetElementData
  2504. )
  2505. {
  2506. return ::DhcpAddSubnetElementV5(GetServerIpAddress(),
  2507. m_dhcpIpAddress,
  2508. pdhcpSubnetElementData);
  2509. }
  2510. /*---------------------------------------------------------------------------
  2511. CDhcpScope::RemoveElementV5
  2512. Description
  2513. Author: EricDav
  2514. ---------------------------------------------------------------------------*/
  2515. DWORD
  2516. CDhcpScope::RemoveElementV5
  2517. (
  2518. DHCP_SUBNET_ELEMENT_DATA_V5 * pdhcpSubnetElementData,
  2519. BOOL bForce
  2520. )
  2521. {
  2522. return ::DhcpRemoveSubnetElementV5(GetServerIpAddress(),
  2523. m_dhcpIpAddress,
  2524. pdhcpSubnetElementData,
  2525. bForce ? DhcpFullForce : DhcpNoForce);
  2526. }
  2527. /*---------------------------------------------------------------------------
  2528. CDhcpScope::GetServerIpAddress()
  2529. Description
  2530. Author: EricDav
  2531. ---------------------------------------------------------------------------*/
  2532. LPCWSTR
  2533. CDhcpScope::GetServerIpAddress()
  2534. {
  2535. CDhcpServer * pServer = GetServerObject();
  2536. return pServer->GetIpAddress();
  2537. }
  2538. /*---------------------------------------------------------------------------
  2539. CDhcpScope::GetServerIpAddress
  2540. Description
  2541. Author: EricDav
  2542. ---------------------------------------------------------------------------*/
  2543. void
  2544. CDhcpScope::GetServerIpAddress(DHCP_IP_ADDRESS * pdhcpIpAddress)
  2545. {
  2546. CDhcpServer * pServer = GetServerObject();
  2547. pServer->GetIpAddress(pdhcpIpAddress);
  2548. }
  2549. /*---------------------------------------------------------------------------
  2550. CDhcpScope::GetServerVersion
  2551. Description
  2552. Author: EricDav
  2553. ---------------------------------------------------------------------------*/
  2554. void
  2555. CDhcpScope::GetServerVersion
  2556. (
  2557. LARGE_INTEGER& liVersion
  2558. )
  2559. {
  2560. CDhcpServer * pServer = GetServerObject();
  2561. pServer->GetVersion(liVersion);
  2562. }
  2563. /*---------------------------------------------------------------------------
  2564. CDhcpScope::SetSuperscope
  2565. Sets this scope as part of the given superscope name
  2566. Author: EricDav
  2567. ---------------------------------------------------------------------------*/
  2568. DWORD
  2569. CDhcpScope::SetSuperscope
  2570. (
  2571. LPCTSTR pSuperscopeName,
  2572. BOOL bRemove
  2573. )
  2574. {
  2575. DWORD dwReturn = 0;
  2576. dwReturn = ::DhcpSetSuperScopeV4(GetServerIpAddress(),
  2577. GetAddress(),
  2578. (LPWSTR) pSuperscopeName,
  2579. bRemove);
  2580. if (dwReturn != ERROR_SUCCESS)
  2581. {
  2582. Trace1("CDhcpScope::SetSuperscope - DhcpSetSuperScopeV4 failed!! %d\n", dwReturn);
  2583. }
  2584. return dwReturn;
  2585. }
  2586. /*---------------------------------------------------------------------------
  2587. Helper functions
  2588. ---------------------------------------------------------------------------*/
  2589. HRESULT
  2590. CDhcpScope::BuildDisplayName
  2591. (
  2592. CString * pstrDisplayName,
  2593. LPCTSTR pIpAddress,
  2594. LPCTSTR pName
  2595. )
  2596. {
  2597. if (pstrDisplayName)
  2598. {
  2599. CString strStandard, strIpAddress, strName;
  2600. strIpAddress = pIpAddress;
  2601. strName = pName;
  2602. strStandard.LoadString(IDS_SCOPE_FOLDER);
  2603. *pstrDisplayName = strStandard + L" [" + strIpAddress + L"] " + strName;
  2604. }
  2605. return hrOK;
  2606. }
  2607. HRESULT
  2608. CDhcpScope::SetName
  2609. (
  2610. LPCWSTR pName
  2611. )
  2612. {
  2613. if (pName != NULL)
  2614. {
  2615. m_strName = pName;
  2616. }
  2617. CString strIpAddress, strDisplayName;
  2618. //
  2619. // Create the display name for this scope
  2620. // Convert DHCP_IP_ADDRES to a string and initialize this object
  2621. //
  2622. UtilCvtIpAddrToWstr (m_dhcpIpAddress,
  2623. &strIpAddress);
  2624. BuildDisplayName(&strDisplayName, strIpAddress, pName);
  2625. SetDisplayName(strDisplayName);
  2626. return hrOK;
  2627. }
  2628. /*---------------------------------------------------------------------------
  2629. CDhcpScope::GetAddressPoolObject()
  2630. Description
  2631. Author: EricDav
  2632. ---------------------------------------------------------------------------*/
  2633. CDhcpAddressPool *
  2634. CDhcpScope::GetAddressPoolObject()
  2635. {
  2636. if (m_spAddressPool)
  2637. return GETHANDLER(CDhcpAddressPool, m_spAddressPool);
  2638. else
  2639. return NULL;
  2640. }
  2641. /*---------------------------------------------------------------------------
  2642. CDhcpScope::GetReservationsObject()
  2643. Description
  2644. Author: EricDav
  2645. ---------------------------------------------------------------------------*/
  2646. CDhcpReservations *
  2647. CDhcpScope::GetReservationsObject()
  2648. {
  2649. if (m_spAddressPool)
  2650. return GETHANDLER(CDhcpReservations, m_spReservations);
  2651. else
  2652. return NULL;
  2653. }
  2654. /*---------------------------------------------------------------------------
  2655. CDhcpScope::GetReservationsObject()
  2656. Description
  2657. Author: EricDav
  2658. ---------------------------------------------------------------------------*/
  2659. CDhcpActiveLeases *
  2660. CDhcpScope::GetActiveLeasesObject()
  2661. {
  2662. if (m_spAddressPool)
  2663. return GETHANDLER(CDhcpActiveLeases, m_spActiveLeases);
  2664. else
  2665. return NULL;
  2666. }
  2667. /*---------------------------------------------------------------------------
  2668. CDhcpScope::GetScopeOptionsContainer()
  2669. Description
  2670. Author: EricDav
  2671. ---------------------------------------------------------------------------*/
  2672. CDhcpScopeOptions *
  2673. CDhcpScope::GetScopeOptionsObject()
  2674. {
  2675. if (m_spAddressPool)
  2676. return GETHANDLER(CDhcpScopeOptions, m_spOptions);
  2677. else
  2678. return NULL;
  2679. }
  2680. /*---------------------------------------------------------------------------
  2681. CDhcpScope::TriggerStatsRefresh()
  2682. Calls into the server object to update the stats
  2683. Author: EricDav
  2684. ---------------------------------------------------------------------------*/
  2685. HRESULT
  2686. CDhcpScope::TriggerStatsRefresh()
  2687. {
  2688. GetServerObject()->TriggerStatsRefresh(m_spServerNode);
  2689. return hrOK;
  2690. }
  2691. /*---------------------------------------------------------------------------
  2692. CDhcpReservations Implementation
  2693. ---------------------------------------------------------------------------*/
  2694. /*---------------------------------------------------------------------------
  2695. CDhcpReservations::CDhcpReservations()
  2696. Description
  2697. Author: EricDav
  2698. ---------------------------------------------------------------------------*/
  2699. CDhcpReservations::CDhcpReservations
  2700. (
  2701. ITFSComponentData * pComponentData
  2702. ) : CMTDhcpHandler(pComponentData)
  2703. {
  2704. }
  2705. //
  2706. // copy all the resrved ips to an array and qsort it
  2707. // when matching an entry that is read from dhcp db
  2708. // we can do a binary search on the qsorted array
  2709. // a better algorithm for large n ( n number of active clients ) is to
  2710. // go through the active clients once for each m ( reserved ip ) where m >
  2711. // 100 but << n
  2712. BOOL
  2713. CDhcpReservationsQueryObj::AddReservedIPsToArray( )
  2714. {
  2715. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  2716. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  2717. DWORD dwElementsRead = 0, dwElementsTotal = 0, dwTotalRead = 0;
  2718. DWORD dwError = ERROR_MORE_DATA;
  2719. DWORD dwResvThreshold = 100;
  2720. while (dwError == ERROR_MORE_DATA)
  2721. {
  2722. dwError = ::DhcpEnumSubnetElements(((LPWSTR) (LPCTSTR)m_strServer),
  2723. m_dhcpScopeAddress,
  2724. DhcpReservedIps,
  2725. &dhcpResumeHandle,
  2726. -1,
  2727. &pdhcpSubnetElementArray,
  2728. &dwElementsRead,
  2729. &dwElementsTotal);
  2730. Trace3("BuildReservationList: Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal );
  2731. //
  2732. // If number of reservations is less than 100 handle it the old way
  2733. //
  2734. if ( dwElementsTotal <= dwResvThreshold )
  2735. {
  2736. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  2737. m_totalResvs = dwElementsTotal;
  2738. return( FALSE );
  2739. }
  2740. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  2741. {
  2742. //
  2743. // Loop through the array that was returned
  2744. //
  2745. if ( m_resvArray == NULL )
  2746. {
  2747. m_resvArray = (DWORD *)VirtualAlloc( NULL,
  2748. dwElementsTotal * sizeof( DWORD ),
  2749. MEM_COMMIT,
  2750. PAGE_READWRITE );
  2751. if ( m_resvArray == NULL )
  2752. {
  2753. return FALSE;
  2754. }
  2755. }
  2756. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  2757. {
  2758. m_resvArray[ i + dwTotalRead ] = pdhcpSubnetElementArray->Elements[i].Element.ReservedIp -> ReservedIpAddress;
  2759. }
  2760. dwTotalRead += dwElementsRead;
  2761. if ( dwTotalRead <= dwElementsTotal )
  2762. {
  2763. m_totalResvs = dwTotalRead;
  2764. }
  2765. else
  2766. {
  2767. m_totalResvs = dwElementsTotal;
  2768. }
  2769. }
  2770. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  2771. }
  2772. //
  2773. // now do a qsort on the data
  2774. //
  2775. ::qsort( (void *)m_resvArray, dwElementsTotal, sizeof( DWORD ), QCompare );
  2776. return( TRUE );
  2777. }
  2778. CDhcpReservations::~CDhcpReservations()
  2779. {
  2780. }
  2781. /*!--------------------------------------------------------------------------
  2782. CDhcpReservations::InitializeNode
  2783. Initializes node specific data
  2784. Author: EricDav
  2785. ---------------------------------------------------------------------------*/
  2786. HRESULT
  2787. CDhcpReservations::InitializeNode
  2788. (
  2789. ITFSNode * pNode
  2790. )
  2791. {
  2792. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  2793. HRESULT hr = hrOK;
  2794. //
  2795. // Create the display name for this scope
  2796. //
  2797. CString strTemp;
  2798. strTemp.LoadString(IDS_RESERVATIONS_FOLDER);
  2799. SetDisplayName(strTemp);
  2800. // Make the node immediately visible
  2801. pNode->SetVisibilityState(TFS_VIS_SHOW);
  2802. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  2803. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  2804. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  2805. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  2806. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_RESERVATIONS);
  2807. SetColumnStringIDs(&aColumns[DHCPSNAP_RESERVATIONS][0]);
  2808. SetColumnWidths(&aColumnWidths[DHCPSNAP_RESERVATIONS][0]);
  2809. return hr;
  2810. }
  2811. /*---------------------------------------------------------------------------
  2812. CDhcpReservations::OnCreateNodeId2
  2813. Returns a unique string for this node
  2814. Author: EricDav
  2815. ---------------------------------------------------------------------------*/
  2816. HRESULT CDhcpReservations::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  2817. {
  2818. const GUID * pGuid = pNode->GetNodeType();
  2819. CString strIpAddress, strGuid;
  2820. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  2821. strGuid.ReleaseBuffer();
  2822. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  2823. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  2824. strId = GetServerName(pNode) + strIpAddress + strGuid;
  2825. return hrOK;
  2826. }
  2827. /*---------------------------------------------------------------------------
  2828. CDhcpReservations::GetImageIndex
  2829. Description
  2830. Author: EricDav
  2831. ---------------------------------------------------------------------------*/
  2832. int
  2833. CDhcpReservations::GetImageIndex(BOOL bOpenImage)
  2834. {
  2835. int nIndex = -1;
  2836. switch (m_nState)
  2837. {
  2838. case notLoaded:
  2839. case loaded:
  2840. if (bOpenImage)
  2841. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN;
  2842. else
  2843. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED;
  2844. break;
  2845. case loading:
  2846. if (bOpenImage)
  2847. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN_BUSY;
  2848. else
  2849. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED_BUSY;
  2850. break;
  2851. case unableToLoad:
  2852. if (bOpenImage)
  2853. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN_LOST_CONNECTION;
  2854. else
  2855. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED_LOST_CONNECTION;
  2856. break;
  2857. default:
  2858. ASSERT(FALSE);
  2859. }
  2860. return nIndex;
  2861. }
  2862. /*!--------------------------------------------------------------------------
  2863. CDhcpReservations::RemoveReservationFromUI
  2864. Initializes node specific data
  2865. Author: EricDav
  2866. ---------------------------------------------------------------------------*/
  2867. DWORD
  2868. CDhcpReservations::RemoveReservationFromUI
  2869. (
  2870. ITFSNode * pReservationsNode,
  2871. DHCP_IP_ADDRESS dhcpReservationIp
  2872. )
  2873. {
  2874. DWORD dwError = E_UNEXPECTED;
  2875. CDhcpReservationClient * pReservationClient = NULL;
  2876. SPITFSNodeEnum spNodeEnum;
  2877. SPITFSNode spCurrentNode;
  2878. ULONG nNumReturned = 0;
  2879. pReservationsNode->GetEnum(&spNodeEnum);
  2880. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  2881. while (nNumReturned)
  2882. {
  2883. pReservationClient = GETHANDLER(CDhcpReservationClient, spCurrentNode);
  2884. if (dhcpReservationIp == pReservationClient->GetIpAddress())
  2885. {
  2886. //
  2887. // Tell this reservation to delete itself
  2888. //
  2889. pReservationsNode->RemoveChild(spCurrentNode);
  2890. spCurrentNode.Release();
  2891. dwError = ERROR_SUCCESS;
  2892. break;
  2893. }
  2894. spCurrentNode.Release();
  2895. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  2896. }
  2897. return dwError;
  2898. }
  2899. /*---------------------------------------------------------------------------
  2900. Overridden base handler functions
  2901. ---------------------------------------------------------------------------*/
  2902. /*---------------------------------------------------------------------------
  2903. CDhcpReservations::OnAddMenuItems
  2904. Adds entries to the context sensitive menu
  2905. Author: EricDav
  2906. ---------------------------------------------------------------------------*/
  2907. STDMETHODIMP
  2908. CDhcpReservations::OnAddMenuItems
  2909. (
  2910. ITFSNode * pNode,
  2911. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  2912. LPDATAOBJECT lpDataObject,
  2913. DATA_OBJECT_TYPES type,
  2914. DWORD dwType,
  2915. long * pInsertionAllowed
  2916. )
  2917. {
  2918. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  2919. LONG fFlags = 0;
  2920. HRESULT hr = S_OK;
  2921. CString strMenuText;
  2922. if ( (m_nState != loaded) )
  2923. {
  2924. fFlags |= MF_GRAYED;
  2925. }
  2926. if (type == CCT_SCOPE)
  2927. {
  2928. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  2929. {
  2930. // these menu items go in the new menu,
  2931. // only visible from scope pane
  2932. strMenuText.LoadString(IDS_CREATE_NEW_RESERVATION);
  2933. hr = LoadAndAddMenuItem( pContextMenuCallback,
  2934. strMenuText,
  2935. IDS_CREATE_NEW_RESERVATION,
  2936. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  2937. fFlags );
  2938. ASSERT( SUCCEEDED(hr) );
  2939. }
  2940. }
  2941. return hr;
  2942. }
  2943. /*---------------------------------------------------------------------------
  2944. CDhcpReservations::OnCommand
  2945. Description
  2946. Author: EricDav
  2947. ---------------------------------------------------------------------------*/
  2948. STDMETHODIMP
  2949. CDhcpReservations::OnCommand
  2950. (
  2951. ITFSNode * pNode,
  2952. long nCommandId,
  2953. DATA_OBJECT_TYPES type,
  2954. LPDATAOBJECT pDataObject,
  2955. DWORD dwType
  2956. )
  2957. {
  2958. HRESULT hr = S_OK;
  2959. switch (nCommandId)
  2960. {
  2961. case IDS_CREATE_NEW_RESERVATION:
  2962. OnCreateNewReservation(pNode);
  2963. break;
  2964. case IDS_REFRESH:
  2965. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  2966. break;
  2967. default:
  2968. break;
  2969. }
  2970. return hr;
  2971. }
  2972. /*---------------------------------------------------------------------------
  2973. CDhcpReservations::CompareItems
  2974. Description
  2975. Author: EricDav
  2976. ---------------------------------------------------------------------------*/
  2977. STDMETHODIMP_(int)
  2978. CDhcpReservations::CompareItems
  2979. (
  2980. ITFSComponent * pComponent,
  2981. MMC_COOKIE cookieA,
  2982. MMC_COOKIE cookieB,
  2983. int nCol
  2984. )
  2985. {
  2986. SPITFSNode spNode1, spNode2;
  2987. m_spNodeMgr->FindNode(cookieA, &spNode1);
  2988. m_spNodeMgr->FindNode(cookieB, &spNode2);
  2989. int nCompare = 0;
  2990. CDhcpReservationClient *pDhcpRC1 = GETHANDLER(CDhcpReservationClient, spNode1);
  2991. CDhcpReservationClient *pDhcpRC2 = GETHANDLER(CDhcpReservationClient, spNode2);
  2992. switch (nCol)
  2993. {
  2994. case 0:
  2995. {
  2996. // IP address compare
  2997. //
  2998. DHCP_IP_ADDRESS dhcpIp1 = pDhcpRC1->GetIpAddress();
  2999. DHCP_IP_ADDRESS dhcpIp2 = pDhcpRC2->GetIpAddress();
  3000. if (dhcpIp1 < dhcpIp2)
  3001. nCompare = -1;
  3002. else
  3003. if (dhcpIp1 > dhcpIp2)
  3004. nCompare = 1;
  3005. // default is that they are equal
  3006. }
  3007. break;
  3008. }
  3009. return nCompare;
  3010. }
  3011. /*!--------------------------------------------------------------------------
  3012. CDhcpReservations::OnGetResultViewType
  3013. MMC calls this to get the result view information
  3014. Author: EricDav
  3015. ---------------------------------------------------------------------------*/
  3016. HRESULT
  3017. CDhcpReservations::OnGetResultViewType
  3018. (
  3019. ITFSComponent * pComponent,
  3020. MMC_COOKIE cookie,
  3021. LPOLESTR * ppViewType,
  3022. long * pViewOptions
  3023. )
  3024. {
  3025. HRESULT hr = hrOK;
  3026. // call the base class to see if it is handling this
  3027. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  3028. {
  3029. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT | MMC_VIEW_OPTIONS_LEXICAL_SORT;
  3030. hr = S_FALSE;
  3031. }
  3032. return hr;
  3033. }
  3034. /*!--------------------------------------------------------------------------
  3035. CDhcpReservations::OnResultSelect
  3036. Update the verbs and the result pane message
  3037. Author: EricDav
  3038. ---------------------------------------------------------------------------*/
  3039. HRESULT CDhcpReservations::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  3040. {
  3041. HRESULT hr = hrOK;
  3042. SPITFSNode spNode;
  3043. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  3044. CORg (pComponent->GetSelectedNode(&spNode));
  3045. UpdateResultMessage(spNode);
  3046. Error:
  3047. return hr;
  3048. }
  3049. /*!--------------------------------------------------------------------------
  3050. CDhcpReservations::UpdateResultMessage
  3051. Figures out what message to put in the result pane, if any
  3052. Author: EricDav
  3053. ---------------------------------------------------------------------------*/
  3054. void CDhcpReservations::UpdateResultMessage(ITFSNode * pNode)
  3055. {
  3056. HRESULT hr = hrOK;
  3057. int nMessage = -1; // default
  3058. int nVisible, nTotal;
  3059. int i;
  3060. CString strTitle, strBody, strTemp;
  3061. if (!m_dwErr)
  3062. {
  3063. pNode->GetChildCount(&nVisible, &nTotal);
  3064. // determine what message to display
  3065. if ( (m_nState == notLoaded) ||
  3066. (m_nState == loading) )
  3067. {
  3068. nMessage = -1;
  3069. }
  3070. else
  3071. if (nTotal == 0)
  3072. {
  3073. nMessage = RESERVATIONS_MESSAGE_NO_RES;
  3074. }
  3075. // build the strings
  3076. if (nMessage != -1)
  3077. {
  3078. // now build the text strings
  3079. // first entry is the title
  3080. strTitle.LoadString(g_uReservationsMessages[nMessage][0]);
  3081. // second entry is the icon
  3082. // third ... n entries are the body strings
  3083. for (i = 2; g_uReservationsMessages[nMessage][i] != 0; i++)
  3084. {
  3085. strTemp.LoadString(g_uReservationsMessages[nMessage][i]);
  3086. strBody += strTemp;
  3087. }
  3088. }
  3089. }
  3090. // show the message
  3091. if (nMessage == -1)
  3092. {
  3093. ClearMessage(pNode);
  3094. }
  3095. else
  3096. {
  3097. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uReservationsMessages[nMessage][1]);
  3098. }
  3099. }
  3100. /*---------------------------------------------------------------------------
  3101. Message handlers
  3102. ---------------------------------------------------------------------------*/
  3103. /*---------------------------------------------------------------------------
  3104. CDhcpReservations::OnCreateNewReservation
  3105. Description
  3106. Author: EricDav
  3107. ---------------------------------------------------------------------------*/
  3108. DWORD
  3109. CDhcpReservations::OnCreateNewReservation
  3110. (
  3111. ITFSNode * pNode
  3112. )
  3113. {
  3114. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3115. SPITFSNode spScopeNode;
  3116. pNode->GetParent(&spScopeNode);
  3117. CDhcpScope * pScope = GETHANDLER(CDhcpScope, spScopeNode);
  3118. LARGE_INTEGER liVersion;
  3119. pScope->GetServerVersion(liVersion);
  3120. CAddReservation dlgAddReservation(spScopeNode, liVersion);
  3121. dlgAddReservation.DoModal();
  3122. GetScopeObject(pNode)->TriggerStatsRefresh();
  3123. UpdateResultMessage(pNode);
  3124. return 0;
  3125. }
  3126. /*---------------------------------------------------------------------------
  3127. Background thread functionality
  3128. ---------------------------------------------------------------------------*/
  3129. /*---------------------------------------------------------------------------
  3130. CDhcpReservations::OnHaveData
  3131. Description
  3132. Author: EricDav
  3133. ---------------------------------------------------------------------------*/
  3134. void
  3135. CDhcpReservations::OnHaveData
  3136. (
  3137. ITFSNode * pParentNode,
  3138. ITFSNode * pNewNode
  3139. )
  3140. {
  3141. AddReservationSorted(pParentNode, pNewNode);
  3142. // update the view
  3143. ExpandNode(pParentNode, TRUE);
  3144. }
  3145. /*---------------------------------------------------------------------------
  3146. CDhcpReservations::AddReservationSorted
  3147. Adding reservation after sorting it by comparing against the resvname
  3148. takes too much time.
  3149. Adds a scope node to the UI sorted
  3150. Author: EricDav
  3151. ---------------------------------------------------------------------------*/
  3152. HRESULT
  3153. CDhcpReservations::AddReservationSorted
  3154. (
  3155. ITFSNode * pReservationsNode,
  3156. ITFSNode * pResClientNode
  3157. )
  3158. {
  3159. HRESULT hr = hrOK;
  3160. SPITFSNodeEnum spNodeEnum;
  3161. SPITFSNode spCurrentNode;
  3162. SPITFSNode spPrevNode;
  3163. ULONG nNumReturned = 0;
  3164. CDhcpReservationClient * pResClient;
  3165. // get our target address
  3166. pResClient = GETHANDLER(CDhcpReservationClient, pResClientNode);
  3167. // get the enumerator for this node
  3168. CORg(pReservationsNode->GetEnum(&spNodeEnum));
  3169. CORg(spNodeEnum->Next(1, &spCurrentNode, &nNumReturned));
  3170. while (nNumReturned)
  3171. {
  3172. pResClient = GETHANDLER(CDhcpReservationClient, spCurrentNode);
  3173. // get the next node in the list
  3174. spPrevNode.Set(spCurrentNode);
  3175. spCurrentNode.Release();
  3176. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  3177. }
  3178. // Add the node in based on the PrevNode pointer
  3179. if (spPrevNode)
  3180. {
  3181. if (m_bExpanded)
  3182. {
  3183. pResClientNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_PREVIOUS);
  3184. pResClientNode->SetData(TFS_DATA_RELATIVE_SCOPEID, spPrevNode->GetData(TFS_DATA_SCOPEID));
  3185. }
  3186. CORg(pReservationsNode->InsertChild(spPrevNode, pResClientNode));
  3187. }
  3188. else
  3189. {
  3190. // add to the head
  3191. if (m_bExpanded)
  3192. {
  3193. pResClientNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_FIRST);
  3194. }
  3195. CORg(pReservationsNode->AddChild(pResClientNode));
  3196. }
  3197. Error:
  3198. return hr;
  3199. }
  3200. /*---------------------------------------------------------------------------
  3201. CDhcpReservations::OnCreateQuery()
  3202. Description
  3203. Author: EricDav
  3204. ---------------------------------------------------------------------------*/
  3205. ITFSQueryObject*
  3206. CDhcpReservations::OnCreateQuery(ITFSNode * pNode)
  3207. {
  3208. CDhcpReservationsQueryObj* pQuery =
  3209. new CDhcpReservationsQueryObj(m_spTFSCompData, m_spNodeMgr);
  3210. pQuery->m_strServer = GetServerIpAddress(pNode);
  3211. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  3212. pQuery->m_dhcpResumeHandle = NULL;
  3213. pQuery->m_dwPreferredMax = 2000;
  3214. pQuery->m_resvArray = NULL;
  3215. pQuery->m_totalResvs = 0;
  3216. GetScopeObject(pNode)->GetServerVersion(pQuery->m_liVersion);
  3217. return pQuery;
  3218. }
  3219. /*---------------------------------------------------------------------------
  3220. CDhcpReservationsQueryObj::Execute()
  3221. Description
  3222. Author: EricDav
  3223. ---------------------------------------------------------------------------*/
  3224. STDMETHODIMP
  3225. CDhcpReservationsQueryObj::Execute()
  3226. {
  3227. HRESULT hr = hrOK;
  3228. if (m_liVersion.QuadPart >= DHCP_SP2_VERSION)
  3229. {
  3230. if ( AddReservedIPsToArray( ) )
  3231. {
  3232. //
  3233. //
  3234. // this should handle the case where there are a large # of resvs.
  3235. //
  3236. //
  3237. hr = EnumerateReservationsV4();
  3238. }
  3239. else
  3240. {
  3241. //
  3242. // a typical corporation doesnt have more than 100 resvs
  3243. // handle it here
  3244. //
  3245. hr = EnumerateReservationsForLessResvsV4( );
  3246. }
  3247. }
  3248. else
  3249. {
  3250. hr = EnumerateReservations();
  3251. }
  3252. return hr;
  3253. }
  3254. HRESULT
  3255. CDhcpReservationsQueryObj::EnumerateReservationsForLessResvsV4( )
  3256. {
  3257. DWORD dwError = ERROR_MORE_DATA;
  3258. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 pdhcpSubnetElementArray = NULL;
  3259. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  3260. HRESULT hr = hrOK;
  3261. while (dwError == ERROR_MORE_DATA)
  3262. {
  3263. dwError = ::DhcpEnumSubnetElementsV4(((LPWSTR) (LPCTSTR)m_strServer),
  3264. m_dhcpScopeAddress,
  3265. DhcpReservedIps,
  3266. &m_dhcpResumeHandle,
  3267. m_dwPreferredMax,
  3268. &pdhcpSubnetElementArray,
  3269. &dwElementsRead,
  3270. &dwElementsTotal);
  3271. Trace3("Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  3272. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  3273. {
  3274. //
  3275. // Loop through the array that was returned
  3276. //
  3277. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  3278. {
  3279. //
  3280. // For each reservation, we need to get the client info
  3281. //
  3282. DWORD dwReturn;
  3283. LPDHCP_CLIENT_INFO_V4 pClientInfo = NULL;
  3284. DHCP_SEARCH_INFO dhcpSearchInfo;
  3285. dhcpSearchInfo.SearchType = DhcpClientIpAddress;
  3286. dhcpSearchInfo.SearchInfo.ClientIpAddress =
  3287. pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress;
  3288. dwReturn = ::DhcpGetClientInfoV4(m_strServer,
  3289. &dhcpSearchInfo,
  3290. &pClientInfo);
  3291. if (dwReturn == ERROR_SUCCESS)
  3292. {
  3293. //
  3294. // Create the result pane item for this element
  3295. //
  3296. SPITFSNode spNode;
  3297. CDhcpReservationClient * pDhcpReservationClient;
  3298. COM_PROTECT_TRY
  3299. {
  3300. pDhcpReservationClient =
  3301. new CDhcpReservationClient(m_spTFSCompData, pClientInfo);
  3302. // Tell the reservation what the client type is
  3303. pDhcpReservationClient->SetClientType(pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->bAllowedClientTypes);
  3304. CreateContainerTFSNode(&spNode,
  3305. &GUID_DhcpReservationClientNodeType,
  3306. pDhcpReservationClient,
  3307. pDhcpReservationClient,
  3308. m_spNodeMgr);
  3309. // Tell the handler to initialize any specific data
  3310. pDhcpReservationClient->InitializeNode(spNode);
  3311. AddToQueue(spNode);
  3312. pDhcpReservationClient->Release();
  3313. }
  3314. COM_PROTECT_CATCH
  3315. ::DhcpRpcFreeMemory(pClientInfo);
  3316. }
  3317. else
  3318. {
  3319. // REVIEW: ericdav - do we need to post the error back here?
  3320. Trace1("EnumReservationsV4 - GetClientInfoV4 failed! %d\n", dwReturn);
  3321. }
  3322. }
  3323. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  3324. pdhcpSubnetElementArray = NULL;
  3325. dwElementsRead = 0;
  3326. dwElementsTotal = 0;
  3327. }
  3328. // Check the abort flag on the thread
  3329. if (FCheckForAbort() == hrOK)
  3330. break;
  3331. // check to see if we have an error and post it to the main thread if we do..
  3332. if (dwError != ERROR_NO_MORE_ITEMS &&
  3333. dwError != ERROR_SUCCESS &&
  3334. dwError != ERROR_MORE_DATA)
  3335. {
  3336. Trace1("DHCP snapin: EnumerateReservationsV4 error: %d\n", dwError);
  3337. m_dwErr = dwError;
  3338. PostError(dwError);
  3339. }
  3340. }
  3341. return hrFalse;
  3342. }
  3343. /*---------------------------------------------------------------------------
  3344. CDhcpReservationsQueryObj::EnumerateReservationsV4()
  3345. Enumerates leases for NT4 SP2 and newer servers
  3346. Author: EricDav
  3347. ---------------------------------------------------------------------------*/
  3348. HRESULT
  3349. CDhcpReservationsQueryObj::EnumerateReservationsV4()
  3350. {
  3351. DWORD dwError = ERROR_MORE_DATA;
  3352. LPDHCP_CLIENT_INFO_ARRAY_V5 pdhcpClientArrayV5 = NULL;
  3353. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  3354. DWORD dwResvsHandled = 0;
  3355. DWORD dwEnumedClients = 0;
  3356. DWORD dwResvThreshold = 1000;
  3357. DWORD i = 0;
  3358. DWORD k = 0;
  3359. DWORD *j = NULL;
  3360. HRESULT hr = hrOK;
  3361. while (dwError == ERROR_MORE_DATA)
  3362. {
  3363. dwError = ::DhcpEnumSubnetClientsV5(((LPWSTR) (LPCTSTR)m_strServer),
  3364. m_dhcpScopeAddress,
  3365. &m_dhcpResumeHandle,
  3366. -1,
  3367. &pdhcpClientArrayV5,
  3368. &dwClientsRead,
  3369. &dwClientsTotal);
  3370. if ( dwClientsRead && dwClientsTotal && pdhcpClientArrayV5 )
  3371. {
  3372. //
  3373. // we do a binary search for a reservation
  3374. // that is present in the table.
  3375. //
  3376. for( i = 0; i < dwClientsRead; i ++ )
  3377. {
  3378. //
  3379. // do binary search against each client that was read to see
  3380. // if it is a reservation.
  3381. //
  3382. k = pdhcpClientArrayV5 -> Clients[i] -> ClientIpAddress;
  3383. j = (DWORD *)::bsearch( &k, m_resvArray, m_totalResvs, sizeof( DWORD ), QCompare );
  3384. //
  3385. // got a non NULL value back, implies it is a reservation.
  3386. // add it to the resv list.
  3387. //
  3388. if ( j )
  3389. {
  3390. //
  3391. // Create the result pane item for this element
  3392. //
  3393. SPITFSNode spNode;
  3394. CDhcpReservationClient * pDhcpReservationClient;
  3395. COM_PROTECT_TRY
  3396. {
  3397. pDhcpReservationClient =
  3398. new CDhcpReservationClient(m_spTFSCompData, reinterpret_cast<LPDHCP_CLIENT_INFO>(pdhcpClientArrayV5 -> Clients[ i ] ));
  3399. CreateContainerTFSNode(&spNode,
  3400. &GUID_DhcpReservationClientNodeType,
  3401. pDhcpReservationClient,
  3402. pDhcpReservationClient,
  3403. m_spNodeMgr);
  3404. //
  3405. // Tell the handler to initialize any specific data
  3406. //
  3407. pDhcpReservationClient->InitializeNode(spNode);
  3408. AddToQueue(spNode);
  3409. pDhcpReservationClient->Release();
  3410. }
  3411. COM_PROTECT_CATCH
  3412. } // end of if that adds a reservation
  3413. } // end of for
  3414. ::DhcpRpcFreeMemory(pdhcpClientArrayV5);
  3415. pdhcpClientArrayV5 = NULL;
  3416. dwEnumedClients += dwClientsRead;
  3417. dwClientsRead = 0;
  3418. dwClientsTotal = 0;
  3419. } // end of main if that checks if read succeeded.
  3420. // Check the abort flag on the thread
  3421. if (FCheckForAbort() == hrOK)
  3422. break;
  3423. // check to see if we have an error and post it to the main thread if we do..
  3424. if (dwError != ERROR_NO_MORE_ITEMS &&
  3425. dwError != ERROR_SUCCESS &&
  3426. dwError != ERROR_MORE_DATA)
  3427. {
  3428. Trace1("DHCP snapin: EnumerateReservationsV4 error: %d\n", dwError);
  3429. m_dwErr = dwError;
  3430. PostError(dwError);
  3431. }
  3432. }
  3433. VirtualFree( m_resvArray, 0, MEM_RELEASE );
  3434. m_totalResvs = 0;
  3435. m_resvArray = NULL;
  3436. return hrFalse;
  3437. }
  3438. /*---------------------------------------------------------------------------
  3439. CDhcpReservationsQueryObj::Execute()
  3440. Enumerates reservations for pre NT4 SP2 servers
  3441. Author: EricDav
  3442. ---------------------------------------------------------------------------*/
  3443. HRESULT
  3444. CDhcpReservationsQueryObj::EnumerateReservations()
  3445. {
  3446. DWORD dwError = ERROR_MORE_DATA;
  3447. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  3448. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  3449. while (dwError == ERROR_MORE_DATA)
  3450. {
  3451. dwError = ::DhcpEnumSubnetElements(((LPWSTR) (LPCTSTR)m_strServer),
  3452. m_dhcpScopeAddress,
  3453. DhcpReservedIps,
  3454. &m_dhcpResumeHandle,
  3455. m_dwPreferredMax,
  3456. &pdhcpSubnetElementArray,
  3457. &dwElementsRead,
  3458. &dwElementsTotal);
  3459. Trace3("Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  3460. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  3461. {
  3462. //
  3463. // Loop through the array that was returned
  3464. //
  3465. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  3466. {
  3467. //
  3468. // For each reservation, we need to get the client info
  3469. //
  3470. DWORD dwReturn;
  3471. LPDHCP_CLIENT_INFO pClientInfo = NULL;
  3472. DHCP_SEARCH_INFO dhcpSearchInfo;
  3473. dhcpSearchInfo.SearchType = DhcpClientIpAddress;
  3474. dhcpSearchInfo.SearchInfo.ClientIpAddress =
  3475. pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress;
  3476. dwReturn = ::DhcpGetClientInfo(m_strServer,
  3477. &dhcpSearchInfo,
  3478. &pClientInfo);
  3479. if (dwReturn == ERROR_SUCCESS)
  3480. {
  3481. //
  3482. // Create the result pane item for this element
  3483. //
  3484. SPITFSNode spNode;
  3485. CDhcpReservationClient * pDhcpReservationClient;
  3486. pDhcpReservationClient =
  3487. new CDhcpReservationClient(m_spTFSCompData, reinterpret_cast<LPDHCP_CLIENT_INFO>(pClientInfo));
  3488. CreateContainerTFSNode(&spNode,
  3489. &GUID_DhcpReservationClientNodeType,
  3490. pDhcpReservationClient,
  3491. pDhcpReservationClient,
  3492. m_spNodeMgr);
  3493. // Tell the handler to initialize any specific data
  3494. pDhcpReservationClient->InitializeNode(spNode);
  3495. AddToQueue(spNode);
  3496. pDhcpReservationClient->Release();
  3497. ::DhcpRpcFreeMemory(pClientInfo);
  3498. }
  3499. }
  3500. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  3501. pdhcpSubnetElementArray = NULL;
  3502. dwElementsRead = 0;
  3503. dwElementsTotal = 0;
  3504. }
  3505. // Check the abort flag on the thread
  3506. if (FCheckForAbort() == hrOK)
  3507. break;
  3508. // check to see if we have an error and post it to the main thread if we do..
  3509. if (dwError != ERROR_NO_MORE_ITEMS &&
  3510. dwError != ERROR_SUCCESS &&
  3511. dwError != ERROR_MORE_DATA)
  3512. {
  3513. Trace1("DHCP snapin: EnumerateReservations error: %d\n", dwError);
  3514. m_dwErr = dwError;
  3515. PostError(dwError);
  3516. }
  3517. }
  3518. return hrFalse;
  3519. }
  3520. /*!--------------------------------------------------------------------------
  3521. CDhcpReservations::OnNotifyExiting
  3522. CMTDhcpHandler overridden functionality
  3523. allows us to know when the background thread is done
  3524. Author: EricDav
  3525. ---------------------------------------------------------------------------*/
  3526. STDMETHODIMP
  3527. CDhcpReservations::OnNotifyExiting
  3528. (
  3529. LPARAM lParam
  3530. )
  3531. {
  3532. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3533. SPITFSNode spNode;
  3534. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  3535. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  3536. UpdateResultMessage(spNode);
  3537. return hr;
  3538. }
  3539. /*---------------------------------------------------------------------------
  3540. CDhcpReservationClient implementation
  3541. ---------------------------------------------------------------------------*/
  3542. /*---------------------------------------------------------------------------
  3543. Function Name Here
  3544. Description
  3545. Author: EricDav
  3546. ---------------------------------------------------------------------------*/
  3547. CDhcpReservationClient::CDhcpReservationClient
  3548. (
  3549. ITFSComponentData * pComponentData,
  3550. LPDHCP_CLIENT_INFO pDhcpClientInfo
  3551. ) : CMTDhcpHandler(pComponentData)
  3552. {
  3553. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3554. InitializeData(pDhcpClientInfo);
  3555. //
  3556. // Intialize our client type
  3557. //
  3558. m_bClientType = CLIENT_TYPE_UNSPECIFIED;
  3559. m_fResProp = TRUE;
  3560. }
  3561. CDhcpReservationClient::CDhcpReservationClient
  3562. (
  3563. ITFSComponentData * pComponentData,
  3564. LPDHCP_CLIENT_INFO_V4 pDhcpClientInfo
  3565. ) : CMTDhcpHandler(pComponentData)
  3566. {
  3567. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3568. InitializeData(reinterpret_cast<LPDHCP_CLIENT_INFO>(pDhcpClientInfo));
  3569. //
  3570. // Intialize our client type
  3571. //
  3572. m_bClientType = pDhcpClientInfo->bClientType;
  3573. m_fResProp = TRUE;
  3574. }
  3575. CDhcpReservationClient::CDhcpReservationClient
  3576. (
  3577. ITFSComponentData * pComponentData,
  3578. CDhcpClient & dhcpClient
  3579. ) : CMTDhcpHandler(pComponentData)
  3580. {
  3581. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3582. m_dhcpClientIpAddress = dhcpClient.QueryIpAddress();
  3583. //
  3584. // Copy data out if it's there
  3585. //
  3586. if (dhcpClient.QueryName().GetLength() > 0)
  3587. {
  3588. m_pstrClientName = new CString (dhcpClient.QueryName());
  3589. }
  3590. else
  3591. {
  3592. m_pstrClientName = NULL;
  3593. }
  3594. if (dhcpClient.QueryComment().GetLength() > 0)
  3595. {
  3596. m_pstrClientComment = new CString(dhcpClient.QueryComment());
  3597. }
  3598. else
  3599. {
  3600. m_pstrClientComment = NULL;
  3601. }
  3602. //
  3603. // build the clients hardware address
  3604. //
  3605. if (dhcpClient.QueryHardwareAddress().GetSize() > 0)
  3606. {
  3607. m_baHardwareAddress.Copy(dhcpClient.QueryHardwareAddress());
  3608. }
  3609. if ( (dhcpClient.QueryExpiryDateTime().dwLowDateTime == 0) &&
  3610. (dhcpClient.QueryExpiryDateTime().dwHighDateTime == 0) )
  3611. {
  3612. //
  3613. // This is an inactive reservation
  3614. //
  3615. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_INACTIVE);
  3616. }
  3617. else
  3618. {
  3619. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_ACTIVE);
  3620. }
  3621. //
  3622. // Intialize our client type
  3623. //
  3624. m_bClientType = dhcpClient.QueryClientType();
  3625. m_fResProp = TRUE;
  3626. }
  3627. CDhcpReservationClient::~CDhcpReservationClient()
  3628. {
  3629. if (m_pstrClientName)
  3630. {
  3631. delete m_pstrClientName;
  3632. }
  3633. if (m_pstrClientComment)
  3634. {
  3635. delete m_pstrClientComment;
  3636. }
  3637. }
  3638. void
  3639. CDhcpReservationClient::InitializeData
  3640. (
  3641. LPDHCP_CLIENT_INFO pDhcpClientInfo
  3642. )
  3643. {
  3644. Assert(pDhcpClientInfo);
  3645. m_dhcpClientIpAddress = pDhcpClientInfo->ClientIpAddress;
  3646. //
  3647. // Copy data out if it's there
  3648. //
  3649. if (pDhcpClientInfo->ClientName)
  3650. {
  3651. m_pstrClientName = new CString (pDhcpClientInfo->ClientName);
  3652. }
  3653. else
  3654. {
  3655. m_pstrClientName = NULL;
  3656. }
  3657. if (pDhcpClientInfo->ClientComment)
  3658. {
  3659. m_pstrClientComment = new CString(pDhcpClientInfo->ClientComment);
  3660. }
  3661. else
  3662. {
  3663. m_pstrClientComment = NULL;
  3664. }
  3665. // build a copy of the hardware address
  3666. if (pDhcpClientInfo->ClientHardwareAddress.DataLength)
  3667. {
  3668. for (DWORD i = 0; i < pDhcpClientInfo->ClientHardwareAddress.DataLength; i++)
  3669. {
  3670. m_baHardwareAddress.Add(pDhcpClientInfo->ClientHardwareAddress.Data[i]);
  3671. }
  3672. }
  3673. if ( (pDhcpClientInfo->ClientLeaseExpires.dwLowDateTime == 0) &&
  3674. (pDhcpClientInfo->ClientLeaseExpires.dwHighDateTime == 0) )
  3675. {
  3676. //
  3677. // This is an inactive reservation
  3678. //
  3679. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_INACTIVE);
  3680. }
  3681. else
  3682. {
  3683. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_ACTIVE);
  3684. }
  3685. }
  3686. /*!--------------------------------------------------------------------------
  3687. CDhcpReservationClient::InitializeNode
  3688. Initializes node specific data
  3689. Author: EricDav
  3690. ---------------------------------------------------------------------------*/
  3691. HRESULT
  3692. CDhcpReservationClient::InitializeNode
  3693. (
  3694. ITFSNode * pNode
  3695. )
  3696. {
  3697. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3698. HRESULT hr = hrOK;
  3699. CString strIpAddress, strDisplayName;
  3700. //
  3701. // Create the display name for this scope
  3702. // Convert DHCP_IP_ADDRES to a string and initialize this object
  3703. //
  3704. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  3705. &strIpAddress);
  3706. BuildDisplayName(&strDisplayName, strIpAddress, *m_pstrClientName);
  3707. SetDisplayName(strDisplayName);
  3708. // Make the node immediately visible
  3709. pNode->SetVisibilityState(TFS_VIS_SHOW);
  3710. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  3711. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  3712. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  3713. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  3714. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_RESERVATION_CLIENT);
  3715. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  3716. SetColumnStringIDs(&aColumns[DHCPSNAP_RESERVATION_CLIENT][0]);
  3717. SetColumnWidths(&aColumnWidths[DHCPSNAP_RESERVATION_CLIENT][0]);
  3718. return hr;
  3719. }
  3720. /*---------------------------------------------------------------------------
  3721. CDhcpReservationClient::OnCreateNodeId2
  3722. Returns a unique string for this node
  3723. Author: EricDav
  3724. ---------------------------------------------------------------------------*/
  3725. HRESULT CDhcpReservationClient::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  3726. {
  3727. const GUID * pGuid = pNode->GetNodeType();
  3728. CString strScopeIpAddress, strResIpAddress, strGuid;
  3729. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  3730. strGuid.ReleaseBuffer();
  3731. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode, TRUE)->GetAddress();
  3732. UtilCvtIpAddrToWstr (dhcpIpAddress, &strScopeIpAddress);
  3733. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress, &strResIpAddress);
  3734. strId = GetServerName(pNode, TRUE) + strScopeIpAddress + strResIpAddress + strGuid;
  3735. return hrOK;
  3736. }
  3737. /*---------------------------------------------------------------------------
  3738. CDhcpReservationClient::GetImageIndex
  3739. Description
  3740. Author: EricDav
  3741. ---------------------------------------------------------------------------*/
  3742. int
  3743. CDhcpReservationClient::GetImageIndex(BOOL bOpenImage)
  3744. {
  3745. int nIndex = -1;
  3746. switch (m_nState)
  3747. {
  3748. case notLoaded:
  3749. case loaded:
  3750. if (bOpenImage)
  3751. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN;
  3752. else
  3753. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED;
  3754. break;
  3755. case loading:
  3756. if (bOpenImage)
  3757. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN_BUSY;
  3758. else
  3759. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED_BUSY;
  3760. break;
  3761. case unableToLoad:
  3762. if (bOpenImage)
  3763. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN_LOST_CONNECTION;
  3764. else
  3765. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED_LOST_CONNECTION;
  3766. break;
  3767. default:
  3768. ASSERT(FALSE);
  3769. }
  3770. return nIndex;
  3771. }
  3772. /*---------------------------------------------------------------------------
  3773. Overridden base handler functions
  3774. ---------------------------------------------------------------------------*/
  3775. /*---------------------------------------------------------------------------
  3776. CDhcpReservationClient::OnAddMenuItems
  3777. Adds entries to the context sensitive menu
  3778. Author: EricDav
  3779. ---------------------------------------------------------------------------*/
  3780. STDMETHODIMP
  3781. CDhcpReservationClient::OnAddMenuItems
  3782. (
  3783. ITFSNode * pNode,
  3784. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  3785. LPDATAOBJECT lpDataObject,
  3786. DATA_OBJECT_TYPES type,
  3787. DWORD dwType,
  3788. long * pInsertionAllowed
  3789. )
  3790. {
  3791. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3792. LONG fFlags = 0;
  3793. HRESULT hr = S_OK;
  3794. CString strMenuText;
  3795. if ( (m_nState != loaded) )
  3796. {
  3797. fFlags |= MF_GRAYED;
  3798. }
  3799. if (type == CCT_SCOPE)
  3800. {
  3801. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  3802. {
  3803. strMenuText.LoadString(IDS_CREATE_OPTION_RESERVATION);
  3804. hr = LoadAndAddMenuItem( pContextMenuCallback,
  3805. strMenuText,
  3806. IDS_CREATE_OPTION_RESERVATION,
  3807. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  3808. fFlags );
  3809. ASSERT( SUCCEEDED(hr) );
  3810. }
  3811. }
  3812. return hr;
  3813. }
  3814. /*---------------------------------------------------------------------------
  3815. CDhcpReservationClient::OnCommand
  3816. Description
  3817. Author: EricDav
  3818. ---------------------------------------------------------------------------*/
  3819. STDMETHODIMP
  3820. CDhcpReservationClient::OnCommand
  3821. (
  3822. ITFSNode * pNode,
  3823. long nCommandId,
  3824. DATA_OBJECT_TYPES type,
  3825. LPDATAOBJECT pDataObject,
  3826. DWORD dwType
  3827. )
  3828. {
  3829. HRESULT hr = S_OK;
  3830. switch (nCommandId)
  3831. {
  3832. case IDS_REFRESH:
  3833. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  3834. break;
  3835. case IDS_DELETE:
  3836. OnDelete(pNode);
  3837. break;
  3838. case IDS_CREATE_OPTION_RESERVATION:
  3839. OnCreateNewOptions(pNode);
  3840. break;
  3841. default:
  3842. break;
  3843. }
  3844. return hr;
  3845. }
  3846. /*---------------------------------------------------------------------------
  3847. CDhcpReservationClient::CompareItems
  3848. Description
  3849. Author: EricDav
  3850. ---------------------------------------------------------------------------*/
  3851. STDMETHODIMP_(int)
  3852. CDhcpReservationClient::CompareItems
  3853. (
  3854. ITFSComponent * pComponent,
  3855. MMC_COOKIE cookieA,
  3856. MMC_COOKIE cookieB,
  3857. int nCol
  3858. )
  3859. {
  3860. SPITFSNode spNode1, spNode2;
  3861. m_spNodeMgr->FindNode(cookieA, &spNode1);
  3862. m_spNodeMgr->FindNode(cookieB, &spNode2);
  3863. int nCompare = 0;
  3864. CDhcpOptionItem *pOpt1 = GETHANDLER(CDhcpOptionItem, spNode1);
  3865. CDhcpOptionItem *pOpt2 = GETHANDLER(CDhcpOptionItem, spNode2);
  3866. switch (nCol)
  3867. {
  3868. case 0:
  3869. {
  3870. //
  3871. // Name compare - use the option #
  3872. //
  3873. LONG_PTR uImage1 = spNode1->GetData(TFS_DATA_IMAGEINDEX);
  3874. LONG_PTR uImage2 = spNode2->GetData(TFS_DATA_IMAGEINDEX);
  3875. nCompare = UtilGetOptionPriority((int) uImage1, (int) uImage2);
  3876. if (nCompare == 0)
  3877. {
  3878. DHCP_OPTION_ID id1 = pOpt1->GetOptionId();
  3879. DHCP_OPTION_ID id2 = pOpt2->GetOptionId();
  3880. if (id1 < id2)
  3881. nCompare = -1;
  3882. else
  3883. if (id1 > id2)
  3884. nCompare = 1;
  3885. }
  3886. }
  3887. break;
  3888. case 1:
  3889. {
  3890. // compare the vendor strings
  3891. CString str1, str2;
  3892. str1 = pOpt1->GetVendorDisplay();
  3893. str2 = pOpt2->GetVendorDisplay();
  3894. nCompare = str1.CompareNoCase(str2);
  3895. }
  3896. break;
  3897. case 3:
  3898. {
  3899. CString str1, str2;
  3900. str1 = pOpt1->GetClassName();
  3901. str2 = pOpt2->GetClassName();
  3902. nCompare = str1.CompareNoCase(str2);
  3903. }
  3904. break;
  3905. }
  3906. return nCompare;
  3907. }
  3908. /*!--------------------------------------------------------------------------
  3909. CDhcpReservationClient::OnResultSelect
  3910. Update the verbs and the result pane message
  3911. Author: EricDav
  3912. ---------------------------------------------------------------------------*/
  3913. HRESULT CDhcpReservationClient::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  3914. {
  3915. HRESULT hr = hrOK;
  3916. SPITFSNode spNode;
  3917. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  3918. CORg (pComponent->GetSelectedNode(&spNode));
  3919. UpdateResultMessage(spNode);
  3920. Error:
  3921. return hr;
  3922. }
  3923. /*!--------------------------------------------------------------------------
  3924. CDhcpReservationClient::UpdateResultMessage
  3925. Figures out what message to put in the result pane, if any
  3926. Author: EricDav
  3927. ---------------------------------------------------------------------------*/
  3928. void CDhcpReservationClient::UpdateResultMessage(ITFSNode * pNode)
  3929. {
  3930. HRESULT hr = hrOK;
  3931. int nMessage = -1; // default
  3932. int nVisible, nTotal;
  3933. int i;
  3934. CString strTitle, strBody, strTemp;
  3935. if (!m_dwErr)
  3936. {
  3937. pNode->GetChildCount(&nVisible, &nTotal);
  3938. // determine what message to display
  3939. if ( (m_nState == notLoaded) ||
  3940. (m_nState == loading) )
  3941. {
  3942. nMessage = -1;
  3943. }
  3944. else
  3945. if (nTotal == 0)
  3946. {
  3947. nMessage = RES_OPTIONS_MESSAGE_NO_OPTIONS;
  3948. }
  3949. // build the strings
  3950. if (nMessage != -1)
  3951. {
  3952. // now build the text strings
  3953. // first entry is the title
  3954. strTitle.LoadString(g_uResOptionsMessages[nMessage][0]);
  3955. // second entry is the icon
  3956. // third ... n entries are the body strings
  3957. for (i = 2; g_uResOptionsMessages[nMessage][i] != 0; i++)
  3958. {
  3959. strTemp.LoadString(g_uResOptionsMessages[nMessage][i]);
  3960. strBody += strTemp;
  3961. }
  3962. }
  3963. }
  3964. // show the message
  3965. if (nMessage == -1)
  3966. {
  3967. ClearMessage(pNode);
  3968. }
  3969. else
  3970. {
  3971. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uResOptionsMessages[nMessage][1]);
  3972. }
  3973. }
  3974. /*!--------------------------------------------------------------------------
  3975. CDhcpReservationClient::OnDelete
  3976. The base handler calls this when MMC sends a MMCN_DELETE for a
  3977. scope pane item. We just call our delete command handler.
  3978. Author: EricDav
  3979. ---------------------------------------------------------------------------*/
  3980. HRESULT
  3981. CDhcpReservationClient::OnDelete
  3982. (
  3983. ITFSNode * pNode,
  3984. LPARAM arg,
  3985. LPARAM lParam
  3986. )
  3987. {
  3988. return OnDelete(pNode);
  3989. }
  3990. /*---------------------------------------------------------------------------
  3991. Command handlers
  3992. ---------------------------------------------------------------------------*/
  3993. HRESULT
  3994. CDhcpReservationClient::OnCreateNewOptions
  3995. (
  3996. ITFSNode * pNode
  3997. )
  3998. {
  3999. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4000. CPropertyPageHolderBase * pPropSheet;
  4001. CString strOptCfgTitle, strOptType;
  4002. SPITFSNode spServerNode;
  4003. SPIComponentData spComponentData;
  4004. COptionsConfig * pOptCfg;
  4005. DHCP_OPTION_SCOPE_INFO dhcpScopeInfo;
  4006. HRESULT hr = hrOK;
  4007. COM_PROTECT_TRY
  4008. {
  4009. CString strOptCfgTitle, strOptType;
  4010. SPIComponentData spComponentData;
  4011. BOOL fFound = FALSE;
  4012. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_CLIENT);
  4013. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  4014. // this gets kinda weird because we implemented the option config page
  4015. // as a property page, so technically this node has two property pages.
  4016. //
  4017. // search the open prop pages to see if the option config is up
  4018. // if it's up, set it active instead of creating a new one.
  4019. for (int i = 0; i < HasPropSheetsOpen(); i++)
  4020. {
  4021. GetOpenPropSheet(i, &pPropSheet);
  4022. HWND hwnd = pPropSheet->GetSheetWindow();
  4023. CString strTitle;
  4024. ::GetWindowText(hwnd, strTitle.GetBuffer(256), 256);
  4025. strTitle.ReleaseBuffer();
  4026. if (strTitle == strOptCfgTitle)
  4027. {
  4028. pPropSheet->SetActiveWindow();
  4029. fFound = TRUE;
  4030. break;
  4031. }
  4032. }
  4033. if (!fFound)
  4034. {
  4035. m_spNodeMgr->GetComponentData(&spComponentData);
  4036. m_fResProp = FALSE;
  4037. hr = DoPropertiesOurselvesSinceMMCSucks(pNode, spComponentData, strOptCfgTitle);
  4038. m_fResProp = TRUE;
  4039. }
  4040. }
  4041. COM_PROTECT_CATCH;
  4042. return hr;
  4043. }
  4044. /*---------------------------------------------------------------------------
  4045. CDhcpReservationClient::OnDelete
  4046. Description
  4047. Author: EricDav
  4048. ---------------------------------------------------------------------------*/
  4049. DWORD
  4050. CDhcpReservationClient::OnDelete
  4051. (
  4052. ITFSNode * pNode
  4053. )
  4054. {
  4055. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4056. CString strMessage, strTemp;
  4057. DWORD dwError = 0;
  4058. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  4059. &strTemp);
  4060. AfxFormatString1(strMessage, IDS_DELETE_RESERVATION, (LPCTSTR) strTemp);
  4061. if (AfxMessageBox(strMessage, MB_YESNO) == IDYES)
  4062. {
  4063. BEGIN_WAIT_CURSOR;
  4064. dwError = GetScopeObject(pNode, TRUE)->DeleteReservation(m_baHardwareAddress, m_dhcpClientIpAddress);
  4065. if (dwError != 0)
  4066. {
  4067. //
  4068. // OOOpss. Something happened, reservation not
  4069. // deleted, so don't remove from UI and put up a message box
  4070. //
  4071. ::DhcpMessageBox(dwError);
  4072. }
  4073. else
  4074. {
  4075. CDhcpScope * pScope = NULL;
  4076. SPITFSNode spActiveLeasesNode;
  4077. pScope = GetScopeObject(pNode, TRUE);
  4078. pScope->GetActiveLeasesNode(&spActiveLeasesNode);
  4079. pScope->GetActiveLeasesObject()->DeleteClient(spActiveLeasesNode, m_dhcpClientIpAddress);
  4080. SPITFSNode spReservationsNode;
  4081. pNode->GetParent(&spReservationsNode);
  4082. spReservationsNode->RemoveChild(pNode);
  4083. // update stats
  4084. pScope->TriggerStatsRefresh();
  4085. }
  4086. END_WAIT_CURSOR;
  4087. }
  4088. return dwError;
  4089. }
  4090. /*---------------------------------------------------------------------------
  4091. CDhcpReservationClient::OnResultPropertyChange
  4092. Description
  4093. Author: EricDav
  4094. ---------------------------------------------------------------------------*/
  4095. HRESULT
  4096. CDhcpReservationClient::OnResultPropertyChange
  4097. (
  4098. ITFSComponent * pComponent,
  4099. LPDATAOBJECT pDataObject,
  4100. MMC_COOKIE cookie,
  4101. LPARAM arg,
  4102. LPARAM param
  4103. )
  4104. {
  4105. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4106. SPITFSNode spNode;
  4107. m_spNodeMgr->FindNode(cookie, &spNode);
  4108. COptionsConfig * pOptCfg = reinterpret_cast<COptionsConfig *>(param);
  4109. LPARAM changeMask = 0;
  4110. // tell the property page to do whatever now that we are back on the
  4111. // main thread
  4112. pOptCfg->OnPropertyChange(TRUE, &changeMask);
  4113. pOptCfg->AcknowledgeNotify();
  4114. if (changeMask)
  4115. spNode->ChangeNode(changeMask);
  4116. return hrOK;
  4117. }
  4118. /*---------------------------------------------------------------------------
  4119. CDhcpReservationClient::CreatePropertyPages
  4120. Description
  4121. Author: EricDav
  4122. ---------------------------------------------------------------------------*/
  4123. STDMETHODIMP
  4124. CDhcpReservationClient::CreatePropertyPages
  4125. (
  4126. ITFSNode * pNode,
  4127. LPPROPERTYSHEETCALLBACK lpProvider,
  4128. LPDATAOBJECT pDataObject,
  4129. LONG_PTR handle,
  4130. DWORD dwType
  4131. )
  4132. {
  4133. HRESULT hr = hrOK;
  4134. if (m_fResProp)
  4135. {
  4136. hr = DoResPages(pNode, lpProvider, pDataObject, handle, dwType);
  4137. }
  4138. else
  4139. {
  4140. hr = DoOptCfgPages(pNode, lpProvider, pDataObject, handle, dwType);
  4141. }
  4142. return hr;
  4143. }
  4144. HRESULT
  4145. CDhcpReservationClient::DoResPages
  4146. (
  4147. ITFSNode * pNode,
  4148. LPPROPERTYSHEETCALLBACK lpProvider,
  4149. LPDATAOBJECT pDataObject,
  4150. LONG_PTR handle,
  4151. DWORD dwType
  4152. )
  4153. {
  4154. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4155. //
  4156. // Create the property page
  4157. //
  4158. SPIComponentData spComponentData;
  4159. m_spNodeMgr->GetComponentData(&spComponentData);
  4160. CReservedClientProperties * pResClientProp =
  4161. new CReservedClientProperties(pNode, spComponentData, m_spTFSCompData, NULL);
  4162. // Get the Server version and set it in the property sheet
  4163. LARGE_INTEGER liVersion;
  4164. CDhcpServer * pServer = GetScopeObject(pNode, TRUE)->GetServerObject();
  4165. pServer->GetVersion(liVersion);
  4166. pResClientProp->SetVersion(liVersion);
  4167. // fill in the data for the prop page
  4168. pResClientProp->m_pageGeneral.m_dwClientAddress = m_dhcpClientIpAddress;
  4169. if (m_pstrClientName)
  4170. pResClientProp->m_pageGeneral.m_strName = *m_pstrClientName;
  4171. if (m_pstrClientComment)
  4172. pResClientProp->m_pageGeneral.m_strComment = *m_pstrClientComment;
  4173. pResClientProp->SetClientType(m_bClientType);
  4174. // fill in the UID string
  4175. UtilCvtByteArrayToString(m_baHardwareAddress, pResClientProp->m_pageGeneral.m_strUID);
  4176. // set the DNS registration option
  4177. DWORD dwDynDnsFlags;
  4178. DWORD dwError;
  4179. BEGIN_WAIT_CURSOR;
  4180. dwError = GetDnsRegistration(pNode, &dwDynDnsFlags);
  4181. if (dwError != ERROR_SUCCESS)
  4182. {
  4183. ::DhcpMessageBox(dwError);
  4184. return hrFalse;
  4185. }
  4186. END_WAIT_CURSOR;
  4187. pResClientProp->SetDnsRegistration(dwDynDnsFlags, DhcpReservedOptions);
  4188. //
  4189. // Object gets deleted when the page is destroyed
  4190. //
  4191. Assert(lpProvider != NULL);
  4192. return pResClientProp->CreateModelessSheet(lpProvider, handle);
  4193. }
  4194. HRESULT
  4195. CDhcpReservationClient::DoOptCfgPages
  4196. (
  4197. ITFSNode * pNode,
  4198. LPPROPERTYSHEETCALLBACK lpProvider,
  4199. LPDATAOBJECT pDataObject,
  4200. LONG_PTR handle,
  4201. DWORD dwType
  4202. )
  4203. {
  4204. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4205. DWORD dwError;
  4206. DWORD dwDynDnsFlags;
  4207. HRESULT hr = hrOK;
  4208. COptionsConfig * pOptCfg;
  4209. CString strOptCfgTitle, strOptType;
  4210. SPITFSNode spServerNode;
  4211. SPIComponentData spComponentData;
  4212. COptionValueEnum * pOptionValueEnum;
  4213. //
  4214. // Create the property page
  4215. //
  4216. COM_PROTECT_TRY
  4217. {
  4218. m_spNodeMgr->GetComponentData(&spComponentData);
  4219. BEGIN_WAIT_CURSOR;
  4220. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_CLIENT);
  4221. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  4222. GetScopeObject(pNode, TRUE)->GetServerNode(&spServerNode);
  4223. pOptCfg = new COptionsConfig(pNode,
  4224. spServerNode,
  4225. spComponentData,
  4226. m_spTFSCompData,
  4227. GetOptionValueEnum(),
  4228. strOptCfgTitle);
  4229. END_WAIT_CURSOR;
  4230. //
  4231. // Object gets deleted when the page is destroyed
  4232. //
  4233. Assert(lpProvider != NULL);
  4234. hr = pOptCfg->CreateModelessSheet(lpProvider, handle);
  4235. }
  4236. COM_PROTECT_CATCH
  4237. return hr;
  4238. }
  4239. /*---------------------------------------------------------------------------
  4240. CDhcpReservationClient::OnPropertyChange
  4241. Description
  4242. Author: EricDav
  4243. ---------------------------------------------------------------------------*/
  4244. HRESULT
  4245. CDhcpReservationClient::OnPropertyChange
  4246. (
  4247. ITFSNode * pNode,
  4248. LPDATAOBJECT pDataobject,
  4249. DWORD dwType,
  4250. LPARAM arg,
  4251. LPARAM lParam
  4252. )
  4253. {
  4254. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4255. CPropertyPageHolderBase * pProp =
  4256. reinterpret_cast<CPropertyPageHolderBase *>(lParam);
  4257. LONG_PTR changeMask = 0;
  4258. // tell the property page to do whatever now that we are back on the
  4259. // main thread
  4260. pProp->OnPropertyChange(TRUE, &changeMask);
  4261. pProp->AcknowledgeNotify();
  4262. if (changeMask)
  4263. pNode->ChangeNode(changeMask);
  4264. return hrOK;
  4265. }
  4266. /*---------------------------------------------------------------------------
  4267. CDhcpReservationClient::OnResultDelete
  4268. This function is called when we are supposed to delete result
  4269. pane items. We build a list of selected items and then delete them.
  4270. Author: EricDav
  4271. ---------------------------------------------------------------------------*/
  4272. HRESULT
  4273. CDhcpReservationClient::OnResultDelete
  4274. (
  4275. ITFSComponent * pComponent,
  4276. LPDATAOBJECT pDataObject,
  4277. MMC_COOKIE cookie,
  4278. LPARAM arg,
  4279. LPARAM param
  4280. )
  4281. {
  4282. HRESULT hr = hrOK;
  4283. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4284. // translate the cookie into a node pointer
  4285. SPITFSNode spResClient, spSelectedNode;
  4286. DWORD dwError;
  4287. m_spNodeMgr->FindNode(cookie, &spResClient);
  4288. pComponent->GetSelectedNode(&spSelectedNode);
  4289. Assert(spSelectedNode == spResClient);
  4290. if (spSelectedNode != spResClient)
  4291. return hr;
  4292. // build the list of selected nodes
  4293. CTFSNodeList listNodesToDelete;
  4294. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  4295. //
  4296. // Confirm with the user
  4297. //
  4298. CString strMessage, strTemp;
  4299. int nNodes = (int) listNodesToDelete.GetCount();
  4300. if (nNodes > 1)
  4301. {
  4302. strTemp.Format(_T("%d"), nNodes);
  4303. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  4304. }
  4305. else
  4306. {
  4307. strMessage.LoadString(IDS_DELETE_ITEM);
  4308. }
  4309. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  4310. {
  4311. return NOERROR;
  4312. }
  4313. // check to make sure we are deleting just scope options
  4314. POSITION pos = listNodesToDelete.GetHeadPosition();
  4315. while (pos)
  4316. {
  4317. ITFSNode * pNode = listNodesToDelete.GetNext(pos);
  4318. if (pNode->GetData(TFS_DATA_IMAGEINDEX) != ICON_IDX_CLIENT_OPTION_LEAF)
  4319. {
  4320. // this option is not scope option. Put up a dialog telling the user what to do
  4321. AfxMessageBox(IDS_CANNOT_DELETE_OPTION_RES);
  4322. return NOERROR;
  4323. }
  4324. }
  4325. CString strServer = GetServerIpAddress(spResClient, TRUE);
  4326. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  4327. dhcpOptionScopeInfo.ScopeType = DhcpReservedOptions;
  4328. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = m_dhcpClientIpAddress;
  4329. CDhcpScope * pScope = GetScopeObject(spResClient, TRUE);
  4330. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = pScope->GetAddress();
  4331. //
  4332. // Loop through all items deleting
  4333. //
  4334. BEGIN_WAIT_CURSOR;
  4335. while (listNodesToDelete.GetCount() > 0)
  4336. {
  4337. SPITFSNode spOptionNode;
  4338. spOptionNode = listNodesToDelete.RemoveHead();
  4339. CDhcpOptionItem * pOptItem = GETHANDLER(CDhcpOptionItem, spOptionNode);
  4340. //
  4341. // Try to remove it from the server
  4342. //
  4343. DWORD dwError;
  4344. if (pOptItem->IsVendorOption() ||
  4345. pOptItem->IsClassOption())
  4346. {
  4347. LPCTSTR pClassName = pOptItem->GetClassName();
  4348. if (lstrlen(pClassName) == 0)
  4349. pClassName = NULL;
  4350. dwError = ::DhcpRemoveOptionValueV5((LPTSTR) ((LPCTSTR) strServer),
  4351. pOptItem->IsVendorOption() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  4352. pOptItem->GetOptionId(),
  4353. (LPTSTR) pClassName,
  4354. (LPTSTR) pOptItem->GetVendor(),
  4355. &dhcpOptionScopeInfo);
  4356. }
  4357. else
  4358. {
  4359. dwError = ::DhcpRemoveOptionValue(strServer,
  4360. pOptItem->GetOptionId(),
  4361. &dhcpOptionScopeInfo);
  4362. }
  4363. if (dwError != 0)
  4364. {
  4365. ::DhcpMessageBox(dwError);
  4366. RESTORE_WAIT_CURSOR;
  4367. hr = E_FAIL;
  4368. continue;
  4369. }
  4370. GetOptionValueEnum()->Remove(pOptItem->GetOptionId(), pOptItem->GetVendor(), pOptItem->GetClassName());
  4371. //
  4372. // Remove from UI now
  4373. //
  4374. spResClient->RemoveChild(spOptionNode);
  4375. spOptionNode.Release();
  4376. }
  4377. END_WAIT_CURSOR;
  4378. UpdateResultMessage(spResClient);
  4379. return hr;
  4380. }
  4381. /*!--------------------------------------------------------------------------
  4382. CDhcpReservationClient::OnGetResultViewType
  4383. MMC calls this to get the result view information
  4384. Author: EricDav
  4385. ---------------------------------------------------------------------------*/
  4386. HRESULT
  4387. CDhcpReservationClient::OnGetResultViewType
  4388. (
  4389. ITFSComponent * pComponent,
  4390. MMC_COOKIE cookie,
  4391. LPOLESTR * ppViewType,
  4392. long * pViewOptions
  4393. )
  4394. {
  4395. HRESULT hr = hrOK;
  4396. // call the base class to see if it is handling this
  4397. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  4398. {
  4399. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  4400. hr = S_FALSE;
  4401. }
  4402. return hr;
  4403. }
  4404. /*!--------------------------------------------------------------------------
  4405. CDhcpReservationClient::OnHaveData
  4406. Description
  4407. Author: EricDav
  4408. ---------------------------------------------------------------------------*/
  4409. void
  4410. CDhcpReservationClient::OnHaveData
  4411. (
  4412. ITFSNode * pParentNode,
  4413. LPARAM Data,
  4414. LPARAM Type
  4415. )
  4416. {
  4417. // This is how we get non-node data back from the background thread.
  4418. switch (Type)
  4419. {
  4420. case DHCP_QDATA_OPTION_VALUES:
  4421. {
  4422. HRESULT hr = hrOK;
  4423. SPIComponentData spCompData;
  4424. SPIConsole spConsole;
  4425. SPIDataObject spDataObject;
  4426. IDataObject * pDataObject;
  4427. COptionValueEnum * pOptionValueEnum = reinterpret_cast<COptionValueEnum *>(Data);
  4428. SetOptionValueEnum(pOptionValueEnum);
  4429. pOptionValueEnum->RemoveAll();
  4430. delete pOptionValueEnum;
  4431. // now tell the view to update themselves
  4432. m_spNodeMgr->GetComponentData(&spCompData);
  4433. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pParentNode, CCT_SCOPE, &pDataObject) );
  4434. spDataObject = pDataObject;
  4435. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  4436. CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM) pParentNode, DHCPSNAP_UPDATE_OPTIONS) );
  4437. break;
  4438. }
  4439. }
  4440. Error:
  4441. return;
  4442. }
  4443. /*!--------------------------------------------------------------------------
  4444. CDhcpReservationClient::OnNotifyExiting
  4445. CMTDhcpHandler overridden functionality
  4446. allows us to know when the background thread is done
  4447. Author: EricDav
  4448. ---------------------------------------------------------------------------*/
  4449. STDMETHODIMP
  4450. CDhcpReservationClient::OnNotifyExiting
  4451. (
  4452. LPARAM lParam
  4453. )
  4454. {
  4455. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4456. SPITFSNode spNode;
  4457. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  4458. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  4459. UpdateResultMessage(spNode);
  4460. return hr;
  4461. }
  4462. /*!--------------------------------------------------------------------------
  4463. CDhcpReservationClient::OnResultUpdateView
  4464. Implementation of ITFSResultHandler::OnResultUpdateView
  4465. Author: EricDav
  4466. ---------------------------------------------------------------------------*/
  4467. HRESULT CDhcpReservationClient::OnResultUpdateView
  4468. (
  4469. ITFSComponent *pComponent,
  4470. LPDATAOBJECT pDataObject,
  4471. LPARAM data,
  4472. LPARAM hint
  4473. )
  4474. {
  4475. HRESULT hr = hrOK;
  4476. SPITFSNode spSelectedNode;
  4477. pComponent->GetSelectedNode(&spSelectedNode);
  4478. if (spSelectedNode == NULL)
  4479. return S_OK; // no selection for our IComponentData
  4480. if ( hint == DHCPSNAP_UPDATE_OPTIONS )
  4481. {
  4482. SPINTERNAL spInternal = ExtractInternalFormat(pDataObject);
  4483. ITFSNode * pNode = reinterpret_cast<ITFSNode *>(spInternal->m_cookie);
  4484. SPITFSNode spSelectedNode;
  4485. pComponent->GetSelectedNode(&spSelectedNode);
  4486. EnumerateResultPane(pComponent, (MMC_COOKIE) spSelectedNode.p, 0, 0);
  4487. }
  4488. else
  4489. {
  4490. // we don't handle this message, let the base class do it.
  4491. return CMTDhcpHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  4492. }
  4493. return hr;
  4494. }
  4495. /*!--------------------------------------------------------------------------
  4496. CDhcpReservationClient::EnumerateResultPane
  4497. We override this function for the options nodes for one reason.
  4498. Whenever an option class is deleted, then all options defined for
  4499. that class will be removed as well. Since there are multiple places
  4500. that these options may show up, it's easier to just not show any
  4501. options that don't have a class defined for it.
  4502. Author: EricDav
  4503. ---------------------------------------------------------------------------*/
  4504. HRESULT
  4505. CDhcpReservationClient::EnumerateResultPane
  4506. (
  4507. ITFSComponent * pComponent,
  4508. MMC_COOKIE cookie,
  4509. LPARAM arg,
  4510. LPARAM lParam
  4511. )
  4512. {
  4513. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4514. CClassInfoArray ClassInfoArray;
  4515. SPITFSNode spContainer, spServerNode;
  4516. CDhcpServer * pServer;
  4517. COptionValueEnum * aEnum[3];
  4518. int aImages[3] = {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF};
  4519. m_spNodeMgr->FindNode(cookie, &spContainer);
  4520. spServerNode = GetServerNode(spContainer, TRUE);
  4521. pServer = GETHANDLER(CDhcpServer, spServerNode);
  4522. pServer->GetClassInfoArray(ClassInfoArray);
  4523. aEnum[0] = GetOptionValueEnum();
  4524. aEnum[1] = GetScopeObject(spContainer, TRUE)->GetOptionValueEnum();
  4525. aEnum[2] = pServer->GetOptionValueEnum();
  4526. aEnum[0]->Reset();
  4527. aEnum[1]->Reset();
  4528. aEnum[2]->Reset();
  4529. return OnResultUpdateOptions(pComponent, spContainer, &ClassInfoArray, aEnum, aImages, 3);
  4530. }
  4531. /*---------------------------------------------------------------------------
  4532. Helper functions
  4533. ---------------------------------------------------------------------------*/
  4534. /*---------------------------------------------------------------------------
  4535. CDhcpReservationClient::GetDnsRegistration
  4536. Gets the DNS registration option value
  4537. Author: EricDav
  4538. ---------------------------------------------------------------------------*/
  4539. DWORD
  4540. CDhcpReservationClient::GetDnsRegistration
  4541. (
  4542. ITFSNode * pNode,
  4543. LPDWORD pDnsRegOption
  4544. )
  4545. {
  4546. //
  4547. // Check option 81 -- the DNS registration option
  4548. //
  4549. CDhcpScope * pScope = GetScopeObject(pNode, TRUE);
  4550. DHCP_OPTION_VALUE * poptValue = NULL;
  4551. DWORD err = pScope->GetOptionValue(OPTION_DNS_REGISTATION,
  4552. DhcpReservedOptions,
  4553. &poptValue,
  4554. m_dhcpClientIpAddress);
  4555. // this is the default
  4556. if (pDnsRegOption)
  4557. *pDnsRegOption = DHCP_DYN_DNS_DEFAULT;
  4558. if (err == ERROR_SUCCESS)
  4559. {
  4560. if ((poptValue->Value.Elements != NULL) &&
  4561. (pDnsRegOption))
  4562. {
  4563. *pDnsRegOption = poptValue->Value.Elements[0].Element.DWordOption;
  4564. }
  4565. }
  4566. else
  4567. {
  4568. Trace0("CDhcpReservationClient::GetDnsRegistration - couldn't get DNS reg value -- \
  4569. option may not be defined, Getting Scope value.\n");
  4570. err = pScope->GetDnsRegistration(pDnsRegOption);
  4571. }
  4572. if (poptValue)
  4573. ::DhcpRpcFreeMemory(poptValue);
  4574. return err;
  4575. }
  4576. /*---------------------------------------------------------------------------
  4577. CDhcpReservationClient::SetDnsRegistration
  4578. Sets the DNS Registration option for this scope
  4579. Author: EricDav
  4580. ---------------------------------------------------------------------------*/
  4581. DWORD
  4582. CDhcpReservationClient::SetDnsRegistration
  4583. (
  4584. ITFSNode * pNode,
  4585. DWORD DnsRegOption
  4586. )
  4587. {
  4588. CDhcpScope * pScope = GetScopeObject(pNode, TRUE);
  4589. DWORD err = 0;
  4590. //
  4591. // Set DNS name registration (option 81)
  4592. //
  4593. CDhcpOption dhcpOption (OPTION_DNS_REGISTATION, DhcpDWordOption , _T(""), _T(""));
  4594. dhcpOption.QueryValue().SetNumber(DnsRegOption);
  4595. err = pScope->SetOptionValue(&dhcpOption, DhcpReservedOptions, m_dhcpClientIpAddress);
  4596. return err;
  4597. }
  4598. /*---------------------------------------------------------------------------
  4599. CDhcpReservationClient::BuildDisplayName
  4600. Builds the display name string
  4601. Author: EricDav
  4602. ---------------------------------------------------------------------------*/
  4603. HRESULT
  4604. CDhcpReservationClient::BuildDisplayName
  4605. (
  4606. CString * pstrDisplayName,
  4607. LPCTSTR pIpAddress,
  4608. LPCTSTR pName
  4609. )
  4610. {
  4611. if (pstrDisplayName)
  4612. {
  4613. CString strTemp = pIpAddress;
  4614. strTemp = L"[" + strTemp + L"]";
  4615. if (pName)
  4616. {
  4617. CString strName = pName;
  4618. strTemp += L" " + strName;
  4619. }
  4620. *pstrDisplayName = strTemp;
  4621. }
  4622. return hrOK;
  4623. }
  4624. /*---------------------------------------------------------------------------
  4625. CDhcpReservationClient::BuildDisplayName
  4626. Updates the cached name for this reservation and updates the UI
  4627. Author: EricDav
  4628. ---------------------------------------------------------------------------*/
  4629. HRESULT
  4630. CDhcpReservationClient::SetName
  4631. (
  4632. LPCTSTR pName
  4633. )
  4634. {
  4635. if (pName != NULL)
  4636. {
  4637. if (m_pstrClientName)
  4638. {
  4639. *m_pstrClientName = pName;
  4640. }
  4641. else
  4642. {
  4643. m_pstrClientName = new CString(pName);
  4644. }
  4645. }
  4646. else
  4647. {
  4648. if (m_pstrClientName)
  4649. {
  4650. delete m_pstrClientName;
  4651. m_pstrClientName = NULL;
  4652. }
  4653. }
  4654. CString strIpAddress, strDisplayName;
  4655. //
  4656. // Create the display name for this scope
  4657. // Convert DHCP_IP_ADDRES to a string and initialize this object
  4658. //
  4659. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  4660. &strIpAddress);
  4661. BuildDisplayName(&strDisplayName, strIpAddress, pName);
  4662. SetDisplayName(strDisplayName);
  4663. return hrOK;
  4664. }
  4665. /*---------------------------------------------------------------------------
  4666. CDhcpReservationClient::BuildDisplayName
  4667. Updates the cached comment for this reservation
  4668. Author: EricDav
  4669. ---------------------------------------------------------------------------*/
  4670. HRESULT
  4671. CDhcpReservationClient::SetComment
  4672. (
  4673. LPCTSTR pComment
  4674. )
  4675. {
  4676. if (pComment != NULL)
  4677. {
  4678. if (m_pstrClientComment)
  4679. {
  4680. *m_pstrClientComment = pComment;
  4681. }
  4682. else
  4683. {
  4684. m_pstrClientComment = new CString(pComment);
  4685. }
  4686. }
  4687. else
  4688. {
  4689. if (m_pstrClientComment)
  4690. {
  4691. delete m_pstrClientComment;
  4692. m_pstrClientComment = NULL;
  4693. }
  4694. }
  4695. return hrOK;
  4696. }
  4697. /*---------------------------------------------------------------------------
  4698. CDhcpReservationClient::SetUID
  4699. Updates the cached unique ID for this reservation
  4700. Author: EricDav
  4701. ---------------------------------------------------------------------------*/
  4702. HRESULT
  4703. CDhcpReservationClient::SetUID
  4704. (
  4705. const CByteArray & baClientUID
  4706. )
  4707. {
  4708. m_baHardwareAddress.Copy(baClientUID);
  4709. return hrOK;
  4710. }
  4711. /*---------------------------------------------------------------------------
  4712. CDhcpReservationClient::SetClientType
  4713. Updates the cached client type for this record
  4714. Author: EricDav
  4715. ---------------------------------------------------------------------------*/
  4716. BYTE
  4717. CDhcpReservationClient::SetClientType
  4718. (
  4719. BYTE bClientType
  4720. )
  4721. {
  4722. BYTE bRet = m_bClientType;
  4723. m_bClientType = bClientType;
  4724. return bRet;
  4725. }
  4726. /*---------------------------------------------------------------------------
  4727. Background thread functionality
  4728. ---------------------------------------------------------------------------*/
  4729. /*---------------------------------------------------------------------------
  4730. CDhcpReservationClient::OnCreateQuery()
  4731. Description
  4732. Author: EricDav
  4733. ---------------------------------------------------------------------------*/
  4734. ITFSQueryObject*
  4735. CDhcpReservationClient::OnCreateQuery(ITFSNode * pNode)
  4736. {
  4737. CDhcpReservationClientQueryObj* pQuery =
  4738. new CDhcpReservationClientQueryObj(m_spTFSCompData, m_spNodeMgr);
  4739. pQuery->m_strServer = GetServerIpAddress(pNode, TRUE);
  4740. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode, TRUE)->GetAddress();
  4741. pQuery->m_dhcpClientIpAddress = m_dhcpClientIpAddress;
  4742. GetScopeObject(pNode, TRUE)->GetServerVersion(pQuery->m_liDhcpVersion);
  4743. GetScopeObject(pNode, TRUE)->GetDynBootpClassName(pQuery->m_strDynBootpClassName);
  4744. pQuery->m_dhcpResumeHandle = NULL;
  4745. pQuery->m_dwPreferredMax = 0xFFFFFFFF;
  4746. return pQuery;
  4747. }
  4748. /*---------------------------------------------------------------------------
  4749. CDhcpReservationClientQueryObj::Execute()
  4750. Description
  4751. Author: EricDav
  4752. ---------------------------------------------------------------------------*/
  4753. STDMETHODIMP
  4754. CDhcpReservationClientQueryObj::Execute()
  4755. {
  4756. DWORD dwErr;
  4757. COptionNodeEnum OptionNodeEnum(m_spTFSCompData, m_spNodeMgr);
  4758. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  4759. COptionValueEnum * pOptionValueEnum = new COptionValueEnum;
  4760. pOptionValueEnum->m_strDynBootpClassName = m_strDynBootpClassName;
  4761. dhcpOptionScopeInfo.ScopeType = DhcpReservedOptions;
  4762. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = m_dhcpClientIpAddress;
  4763. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = m_dhcpScopeAddress;
  4764. pOptionValueEnum->Init(m_strServer, m_liDhcpVersion, dhcpOptionScopeInfo);
  4765. dwErr = pOptionValueEnum->Enum();
  4766. // add all of the nodes
  4767. if (dwErr != ERROR_SUCCESS)
  4768. {
  4769. Trace1("CDhcpReservationClientQueryObj::Execute - Enum Failed! %d\n", dwErr);
  4770. m_dwErr = dwErr;
  4771. PostError(dwErr);
  4772. delete pOptionValueEnum;
  4773. }
  4774. else
  4775. {
  4776. pOptionValueEnum->SortById();
  4777. AddToQueue((LPARAM) pOptionValueEnum, DHCP_QDATA_OPTION_VALUES);
  4778. }
  4779. return hrFalse;
  4780. }
  4781. /////////////////////////////////////////////////////////////////////
  4782. //
  4783. // CDhcpActiveLeases implementation
  4784. //
  4785. /////////////////////////////////////////////////////////////////////
  4786. /*---------------------------------------------------------------------------
  4787. Function Name Here
  4788. Description
  4789. Author: EricDav
  4790. ---------------------------------------------------------------------------*/
  4791. CDhcpActiveLeases::CDhcpActiveLeases
  4792. (
  4793. ITFSComponentData * pComponentData
  4794. ) : CMTDhcpHandler(pComponentData)
  4795. {
  4796. }
  4797. CDhcpActiveLeases::~CDhcpActiveLeases()
  4798. {
  4799. }
  4800. /*!--------------------------------------------------------------------------
  4801. CDhcpActiveLeases::InitializeNode
  4802. Initializes node specific data
  4803. Author: EricDav
  4804. ---------------------------------------------------------------------------*/
  4805. HRESULT
  4806. CDhcpActiveLeases::InitializeNode
  4807. (
  4808. ITFSNode * pNode
  4809. )
  4810. {
  4811. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4812. HRESULT hr = hrOK;
  4813. //
  4814. // Create the display name for this scope
  4815. //
  4816. CString strTemp;
  4817. strTemp.LoadString(IDS_ACTIVE_LEASES_FOLDER);
  4818. SetDisplayName(strTemp);
  4819. // Make the node immediately visible
  4820. pNode->SetVisibilityState(TFS_VIS_SHOW);
  4821. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  4822. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  4823. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  4824. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  4825. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_ACTIVE_LEASES);
  4826. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  4827. SetColumnStringIDs(&aColumns[DHCPSNAP_ACTIVE_LEASES][0]);
  4828. SetColumnWidths(&aColumnWidths[DHCPSNAP_ACTIVE_LEASES][0]);
  4829. return hr;
  4830. }
  4831. /*---------------------------------------------------------------------------
  4832. CDhcpActiveLeases::OnCreateNodeId2
  4833. Returns a unique string for this node
  4834. Author: EricDav
  4835. ---------------------------------------------------------------------------*/
  4836. HRESULT CDhcpActiveLeases::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  4837. {
  4838. const GUID * pGuid = pNode->GetNodeType();
  4839. CString strIpAddress, strGuid;
  4840. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  4841. strGuid.ReleaseBuffer();
  4842. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  4843. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  4844. strId = GetServerName(pNode) + strIpAddress + strGuid;
  4845. return hrOK;
  4846. }
  4847. /*---------------------------------------------------------------------------
  4848. CDhcpActiveLeases::GetImageIndex
  4849. Description
  4850. Author: EricDav
  4851. ---------------------------------------------------------------------------*/
  4852. int
  4853. CDhcpActiveLeases::GetImageIndex(BOOL bOpenImage)
  4854. {
  4855. int nIndex = -1;
  4856. switch (m_nState)
  4857. {
  4858. case notLoaded:
  4859. case loaded:
  4860. if (bOpenImage)
  4861. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN;
  4862. else
  4863. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED;
  4864. break;
  4865. case loading:
  4866. if (bOpenImage)
  4867. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_BUSY;
  4868. else
  4869. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_BUSY;
  4870. break;
  4871. case unableToLoad:
  4872. if (bOpenImage)
  4873. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_LOST_CONNECTION;
  4874. else
  4875. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_LOST_CONNECTION;
  4876. break;
  4877. default:
  4878. ASSERT(FALSE);
  4879. }
  4880. return nIndex;
  4881. }
  4882. /*---------------------------------------------------------------------------
  4883. Overridden base handler functions
  4884. ---------------------------------------------------------------------------*/
  4885. /*---------------------------------------------------------------------------
  4886. CDhcpActiveLeases::OnAddMenuItems
  4887. Adds entries to the context sensitive menu
  4888. Author: EricDav
  4889. ---------------------------------------------------------------------------*/
  4890. STDMETHODIMP
  4891. CDhcpActiveLeases::OnAddMenuItems
  4892. (
  4893. ITFSNode * pNode,
  4894. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  4895. LPDATAOBJECT lpDataObject,
  4896. DATA_OBJECT_TYPES type,
  4897. DWORD dwType,
  4898. long * pInsertionAllowed
  4899. )
  4900. {
  4901. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4902. LONG fFlags = 0;
  4903. HRESULT hr = S_OK;
  4904. CString strMenuText;
  4905. if ( (m_nState != loaded) )
  4906. {
  4907. fFlags |= MF_GRAYED;
  4908. }
  4909. if (type == CCT_SCOPE)
  4910. {
  4911. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  4912. {
  4913. /* removed, using new MMC save list functionality
  4914. strMenuText.LoadString(IDS_EXPORT_LEASE_INFO);
  4915. hr = LoadAndAddMenuItem( pContextMenuCallback,
  4916. strMenuText,
  4917. IDS_EXPORT_LEASE_INFO,
  4918. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  4919. fFlags );
  4920. ASSERT( SUCCEEDED(hr) );
  4921. */
  4922. }
  4923. }
  4924. return hr;
  4925. }
  4926. /*---------------------------------------------------------------------------
  4927. CDhcpActiveLeases::OnCommand
  4928. Description
  4929. Author: EricDav
  4930. ---------------------------------------------------------------------------*/
  4931. STDMETHODIMP
  4932. CDhcpActiveLeases::OnCommand
  4933. (
  4934. ITFSNode * pNode,
  4935. long nCommandId,
  4936. DATA_OBJECT_TYPES type,
  4937. LPDATAOBJECT pDataObject,
  4938. DWORD dwType
  4939. )
  4940. {
  4941. HRESULT hr = S_OK;
  4942. switch (nCommandId)
  4943. {
  4944. case IDS_REFRESH:
  4945. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  4946. break;
  4947. case IDS_EXPORT_LEASE_INFO:
  4948. OnExportLeases(pNode);
  4949. break;
  4950. default:
  4951. break;
  4952. }
  4953. return hr;
  4954. }
  4955. /*---------------------------------------------------------------------------
  4956. CDhcpActiveLeases::OnResultDelete
  4957. This function is called when we are supposed to delete result
  4958. pane items. We build a list of selected items and then delete them.
  4959. Author: EricDav
  4960. ---------------------------------------------------------------------------*/
  4961. HRESULT
  4962. CDhcpActiveLeases::OnResultDelete
  4963. (
  4964. ITFSComponent * pComponent,
  4965. LPDATAOBJECT pDataObject,
  4966. MMC_COOKIE cookie,
  4967. LPARAM arg,
  4968. LPARAM param
  4969. )
  4970. {
  4971. HRESULT hr = hrOK;
  4972. BOOL bIsRes, bIsActive, bBadAddress;
  4973. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4974. // translate the cookie into a node pointer
  4975. SPITFSNode spActiveLeases, spSelectedNode;
  4976. m_spNodeMgr->FindNode(cookie, &spActiveLeases);
  4977. pComponent->GetSelectedNode(&spSelectedNode);
  4978. Assert(spSelectedNode == spActiveLeases);
  4979. if (spSelectedNode != spActiveLeases)
  4980. return hr;
  4981. // build the list of selected nodes
  4982. CTFSNodeList listNodesToDelete;
  4983. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  4984. //
  4985. // Confirm with the user
  4986. //
  4987. CString strMessage, strTemp;
  4988. int nNodes = (int) listNodesToDelete.GetCount();
  4989. if (nNodes > 1)
  4990. {
  4991. strTemp.Format(_T("%d"), nNodes);
  4992. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  4993. }
  4994. else
  4995. {
  4996. strMessage.LoadString(IDS_DELETE_ITEM);
  4997. }
  4998. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  4999. {
  5000. return NOERROR;
  5001. }
  5002. //
  5003. // Loop through all items deleting
  5004. //
  5005. BEGIN_WAIT_CURSOR;
  5006. while (listNodesToDelete.GetCount() > 0)
  5007. {
  5008. SPITFSNode spActiveLeaseNode;
  5009. spActiveLeaseNode = listNodesToDelete.RemoveHead();
  5010. CDhcpActiveLease * pActiveLease = GETHANDLER(CDhcpActiveLease, spActiveLeaseNode);
  5011. //
  5012. // delete the node, check to see if it is a reservation
  5013. //
  5014. bIsRes = pActiveLease->IsReservation(&bIsActive, &bBadAddress);
  5015. if (bIsRes && !bBadAddress)
  5016. {
  5017. //
  5018. // Delete the reservation
  5019. //
  5020. LPDHCP_CLIENT_INFO pdhcpClientInfo;
  5021. DWORD dwError = GetScopeObject(spActiveLeases)->GetClientInfo(pActiveLease->GetIpAddress(), &pdhcpClientInfo);
  5022. if (dwError == ERROR_SUCCESS)
  5023. {
  5024. dwError = GetScopeObject(spActiveLeases)->DeleteReservation(pdhcpClientInfo->ClientHardwareAddress,
  5025. pdhcpClientInfo->ClientIpAddress);
  5026. if (dwError == ERROR_SUCCESS)
  5027. {
  5028. //
  5029. // Tell the reservations folder to remove this from it's list
  5030. //
  5031. SPITFSNode spReservationsNode;
  5032. GetScopeObject(spActiveLeases)->GetReservationsNode(&spReservationsNode);
  5033. GetScopeObject(spActiveLeases)->GetReservationsObject()->
  5034. RemoveReservationFromUI((ITFSNode *) spReservationsNode, pActiveLease->GetIpAddress());
  5035. spActiveLeases->RemoveChild(spActiveLeaseNode);
  5036. }
  5037. else
  5038. {
  5039. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5040. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5041. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5042. {
  5043. break;
  5044. }
  5045. RESTORE_WAIT_CURSOR;
  5046. Trace1("Delete reservation failed %lx\n", dwError);
  5047. hr = E_FAIL;
  5048. }
  5049. ::DhcpRpcFreeMemory(pdhcpClientInfo);
  5050. }
  5051. else
  5052. {
  5053. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5054. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5055. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5056. {
  5057. break;
  5058. }
  5059. RESTORE_WAIT_CURSOR;
  5060. Trace1("GetClientInfo failed %lx\n", dwError);
  5061. hr = E_FAIL;
  5062. }
  5063. }
  5064. else
  5065. {
  5066. DWORD dwError = GetScopeObject(spActiveLeases)->DeleteClient(pActiveLease->GetIpAddress());
  5067. if (dwError == ERROR_SUCCESS)
  5068. {
  5069. //
  5070. // Client gone, now remove from UI
  5071. //
  5072. spActiveLeases->RemoveChild(spActiveLeaseNode);
  5073. // if we are deleting a lot of addresses, then we can hit the server hard..
  5074. // lets take a short time out to smooth out the process
  5075. Sleep(5);
  5076. }
  5077. else
  5078. {
  5079. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5080. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5081. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5082. {
  5083. break;
  5084. }
  5085. RESTORE_WAIT_CURSOR;
  5086. Trace1("DhcpDeleteClientInfo failed %lx\n", dwError);
  5087. hr = E_FAIL;
  5088. }
  5089. }
  5090. spActiveLeaseNode.Release();
  5091. }
  5092. // update stats
  5093. GetScopeObject(spActiveLeases)->TriggerStatsRefresh();
  5094. END_WAIT_CURSOR;
  5095. return hr;
  5096. }
  5097. /*---------------------------------------------------------------------------
  5098. CDhcpActiveLeases::DeleteClient
  5099. The reservations object will call this when a reservation is
  5100. deleted. Since a reservation also has an active lease record,
  5101. we have to delete it as well.
  5102. Author: EricDav
  5103. ---------------------------------------------------------------------------*/
  5104. DWORD
  5105. CDhcpActiveLeases::DeleteClient
  5106. (
  5107. ITFSNode * pActiveLeasesNode,
  5108. DHCP_IP_ADDRESS dhcpIpAddress
  5109. )
  5110. {
  5111. DWORD dwError = E_UNEXPECTED;
  5112. CDhcpActiveLease * pActiveLease = NULL;
  5113. SPITFSNodeEnum spNodeEnum;
  5114. SPITFSNode spCurrentNode;
  5115. ULONG nNumReturned = 0;
  5116. pActiveLeasesNode->GetEnum(&spNodeEnum);
  5117. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5118. while (nNumReturned)
  5119. {
  5120. pActiveLease = GETHANDLER(CDhcpActiveLease, spCurrentNode);
  5121. if (dhcpIpAddress == pActiveLease->GetIpAddress())
  5122. {
  5123. //
  5124. // Tell this reservation to delete itself
  5125. //
  5126. pActiveLeasesNode->RemoveChild(spCurrentNode);
  5127. spCurrentNode.Release();
  5128. dwError = ERROR_SUCCESS;
  5129. break;
  5130. }
  5131. spCurrentNode.Release();
  5132. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5133. }
  5134. return dwError;
  5135. }
  5136. /*!--------------------------------------------------------------------------
  5137. CDhcpActiveLeases::OnGetResultViewType
  5138. MMC calls this to get the result view information
  5139. Author: EricDav
  5140. ---------------------------------------------------------------------------*/
  5141. HRESULT CDhcpActiveLeases::OnGetResultViewType
  5142. (
  5143. ITFSComponent * pComponent,
  5144. MMC_COOKIE cookie,
  5145. LPOLESTR * ppViewType,
  5146. long * pViewOptions
  5147. )
  5148. {
  5149. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  5150. // we still want the default MMC result pane view, we just want
  5151. // multiselect, so return S_FALSE
  5152. return S_FALSE;
  5153. }
  5154. /*---------------------------------------------------------------------------
  5155. CDhcpActiveLeases::CompareItems
  5156. Description
  5157. Author: EricDav
  5158. ---------------------------------------------------------------------------*/
  5159. STDMETHODIMP_(int)
  5160. CDhcpActiveLeases::CompareItems
  5161. (
  5162. ITFSComponent * pComponent,
  5163. MMC_COOKIE cookieA,
  5164. MMC_COOKIE cookieB,
  5165. int nCol
  5166. )
  5167. {
  5168. SPITFSNode spNode1, spNode2;
  5169. m_spNodeMgr->FindNode(cookieA, &spNode1);
  5170. m_spNodeMgr->FindNode(cookieB, &spNode2);
  5171. int nCompare = 0;
  5172. CDhcpActiveLease *pDhcpAL1 = GETHANDLER(CDhcpActiveLease, spNode1);
  5173. CDhcpActiveLease *pDhcpAL2 = GETHANDLER(CDhcpActiveLease, spNode2);
  5174. switch (nCol)
  5175. {
  5176. case 0:
  5177. {
  5178. // IP address compare
  5179. //
  5180. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5181. }
  5182. break;
  5183. case 1:
  5184. {
  5185. // Client Name compare
  5186. //
  5187. CString strAL1 = pDhcpAL1->GetString(pComponent, cookieA, nCol);
  5188. CString strAL2 = pDhcpAL2->GetString(pComponent, cookieA, nCol);
  5189. nCompare = strAL1.CompareNoCase(strAL2);
  5190. }
  5191. break;
  5192. case 2:
  5193. {
  5194. // Lease expiration compare
  5195. //
  5196. BOOL bIsActive1, bIsActive2;
  5197. BOOL bIsBad1, bIsBad2;
  5198. BOOL bIsRes1 = pDhcpAL1->IsReservation(&bIsActive1, &bIsBad1);
  5199. BOOL bIsRes2 = pDhcpAL2->IsReservation(&bIsActive2, &bIsBad2);
  5200. //
  5201. // Check to see if these are reservations
  5202. //
  5203. if (bIsRes1 && bIsRes2)
  5204. {
  5205. //
  5206. // Figure out if this is a bad address
  5207. // They go first
  5208. //
  5209. if (bIsBad1 && bIsBad2)
  5210. {
  5211. //
  5212. // Sort by IP Address
  5213. //
  5214. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5215. }
  5216. else
  5217. if (bIsBad1)
  5218. nCompare = -1;
  5219. else
  5220. if (bIsBad2)
  5221. nCompare = 1;
  5222. else
  5223. if ((bIsActive1 && bIsActive2) ||
  5224. (!bIsActive1 && !bIsActive2))
  5225. {
  5226. //
  5227. // if both reservations are either active/inactive
  5228. // sort by IP address
  5229. //
  5230. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5231. }
  5232. else
  5233. if (bIsActive1)
  5234. nCompare = -1;
  5235. else
  5236. nCompare = 1;
  5237. }
  5238. else
  5239. if (bIsRes1)
  5240. {
  5241. nCompare = -1;
  5242. }
  5243. else
  5244. if (bIsRes2)
  5245. {
  5246. nCompare = 1;
  5247. }
  5248. else
  5249. {
  5250. CTime timeAL1, timeAL2;
  5251. pDhcpAL1->GetLeaseExpirationTime(timeAL1);
  5252. pDhcpAL2->GetLeaseExpirationTime(timeAL2);
  5253. if (timeAL1 < timeAL2)
  5254. nCompare = -1;
  5255. else
  5256. if (timeAL1 > timeAL2)
  5257. nCompare = 1;
  5258. }
  5259. // default is that they are equal
  5260. }
  5261. break;
  5262. case 3:
  5263. {
  5264. // Client Type Compare
  5265. CString strAL1 = pDhcpAL1->GetString(pComponent, cookieA, nCol);
  5266. CString strAL2 = pDhcpAL2->GetString(pComponent, cookieA, nCol);
  5267. nCompare = strAL1.Compare(strAL2);
  5268. }
  5269. break;
  5270. case 4:
  5271. {
  5272. CString strUID1 = pDhcpAL1->GetUID();
  5273. nCompare = strUID1.CompareNoCase(pDhcpAL2->GetUID());
  5274. }
  5275. break;
  5276. case 5:
  5277. {
  5278. CString strComment1 = pDhcpAL1->GetComment();
  5279. nCompare = strComment1.CompareNoCase(pDhcpAL2->GetComment());
  5280. }
  5281. break;
  5282. }
  5283. return nCompare;
  5284. }
  5285. /*---------------------------------------------------------------------------
  5286. Function Name Here
  5287. Description
  5288. Author: EricDav
  5289. ---------------------------------------------------------------------------*/
  5290. int
  5291. CDhcpActiveLeases::CompareIpAddresses
  5292. (
  5293. CDhcpActiveLease * pDhcpAL1,
  5294. CDhcpActiveLease * pDhcpAL2
  5295. )
  5296. {
  5297. int nCompare = 0;
  5298. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAL1->GetIpAddress();
  5299. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAL2->GetIpAddress();
  5300. if (dhcpIp1 < dhcpIp2)
  5301. nCompare = -1;
  5302. else
  5303. if (dhcpIp1 > dhcpIp2)
  5304. nCompare = 1;
  5305. return nCompare;
  5306. }
  5307. /*---------------------------------------------------------------------------
  5308. CDhcpActiveLeases::OnExportLeases()
  5309. -
  5310. Author: EricDav
  5311. ---------------------------------------------------------------------------*/
  5312. HRESULT
  5313. CDhcpActiveLeases::OnExportLeases(ITFSNode * pNode)
  5314. {
  5315. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  5316. HRESULT hr = hrOK;
  5317. // Bring up the Save Dialog
  5318. SPITFSNodeEnum spNodeEnum;
  5319. SPITFSNode spCurrentNode;
  5320. ULONG nNumReturned = 0;
  5321. CString strType;
  5322. CString strDefFileName;
  5323. CString strFilter;
  5324. CString strTitle;
  5325. CString strFileName;
  5326. strType.LoadString(IDS_FILE_EXTENSION);
  5327. strDefFileName.LoadString(IDS_FILE_DEFNAME);
  5328. strFilter.LoadString(IDS_STR_EXPORTFILE_FILTER);
  5329. CFileDialog cFileDlg(FALSE, strType, strDefFileName, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter);//_T("Comma Separated Files (*.csv)|*.csv||") );
  5330. strTitle.LoadString(IDS_EXPFILE_TITLE);
  5331. cFileDlg.m_ofn.lpstrTitle = strTitle;
  5332. // put up the file dialog
  5333. if( cFileDlg.DoModal() != IDOK )
  5334. return hrFalse;
  5335. strFileName = cFileDlg.GetPathName();
  5336. COM_PROTECT_TRY
  5337. {
  5338. CString strContent;
  5339. CString strLine;
  5340. CString strTemp;
  5341. CString strDelim = _T(',');
  5342. CString strNewLine = _T("\r\n");
  5343. int nCount = 0;
  5344. // create a file named "WinsExp.txt" in the current directory
  5345. CFile cFileExp(strFileName, CFile::modeCreate | CFile::modeRead | CFile::modeWrite);
  5346. // this is a unicode file, write the unicde lead bytes (2)
  5347. cFileExp.Write(&gwUnicodeHeader, sizeof(WORD));
  5348. // write the header
  5349. for (int i = 0; i < MAX_COLUMNS; i++)
  5350. {
  5351. if (aColumns[DHCPSNAP_ACTIVE_LEASES][i])
  5352. {
  5353. if (!strLine.IsEmpty())
  5354. strLine += strDelim;
  5355. strTemp.LoadString(aColumns[DHCPSNAP_ACTIVE_LEASES][i]);
  5356. strLine += strTemp;
  5357. }
  5358. }
  5359. strLine += strNewLine;
  5360. cFileExp.Write(strLine, strLine.GetLength()*sizeof(TCHAR));
  5361. cFileExp.SeekToEnd();
  5362. BEGIN_WAIT_CURSOR
  5363. #ifdef DEBUG
  5364. CTime timeStart, timeFinish;
  5365. timeStart = CTime::GetCurrentTime();
  5366. #endif
  5367. // enumerate all the leases and output
  5368. pNode->GetEnum(&spNodeEnum);
  5369. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5370. while (nNumReturned)
  5371. {
  5372. CDhcpActiveLease * pLease = GETHANDLER(CDhcpActiveLease, spCurrentNode);
  5373. strLine.Empty();
  5374. // ipaddr, name, type, lease exp, UID, comment
  5375. for (int j = 0; j < 6; j++)
  5376. {
  5377. if (!strLine.IsEmpty())
  5378. strLine += strDelim;
  5379. strLine += pLease->GetString(NULL, NULL, j);
  5380. }
  5381. strLine += strNewLine;
  5382. strContent += strLine;
  5383. nCount++;
  5384. //optimize
  5385. // write to the file for every 1000 records converted
  5386. if( nCount % 1000 == 0)
  5387. {
  5388. cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) );
  5389. cFileExp.SeekToEnd();
  5390. // clear all the strings now
  5391. strContent.Empty();
  5392. }
  5393. spCurrentNode.Release();
  5394. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5395. }
  5396. // write to the file
  5397. cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) );
  5398. cFileExp.Close();
  5399. #ifdef DEBUG
  5400. timeFinish = CTime::GetCurrentTime();
  5401. CTimeSpan timeDelta = timeFinish - timeStart;
  5402. Trace2("ActiveLeases - Export Entries: %d records written, total time %s\n", nCount, timeDelta.Format(_T("%H:%M:%S")));
  5403. #endif
  5404. END_WAIT_CURSOR
  5405. }
  5406. COM_PROTECT_CATCH
  5407. CString strDisp;
  5408. AfxFormatString1(strDisp, IDS_EXPORT_SUCCESS, strFileName);
  5409. AfxMessageBox(strDisp, MB_ICONINFORMATION );
  5410. return hr;
  5411. }
  5412. /*---------------------------------------------------------------------------
  5413. Background thread functionality
  5414. ---------------------------------------------------------------------------*/
  5415. /*---------------------------------------------------------------------------
  5416. CDhcpActiveLeases::OnCreateQuery()
  5417. Description
  5418. Author: EricDav
  5419. ---------------------------------------------------------------------------*/
  5420. ITFSQueryObject*
  5421. CDhcpActiveLeases::OnCreateQuery(ITFSNode * pNode)
  5422. {
  5423. CDhcpActiveLeasesQueryObj* pQuery =
  5424. new CDhcpActiveLeasesQueryObj(m_spTFSCompData, m_spNodeMgr);
  5425. pQuery->m_strServer = GetServerIpAddress(pNode);
  5426. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  5427. pQuery->m_dhcpResumeHandle = NULL;
  5428. pQuery->m_dwPreferredMax = 2000;
  5429. GetServerVersion(pNode, pQuery->m_liDhcpVersion);
  5430. return pQuery;
  5431. }
  5432. /*---------------------------------------------------------------------------
  5433. CDhcpActiveLeasesQueryObj::Execute()
  5434. Description
  5435. Author: EricDav
  5436. ---------------------------------------------------------------------------*/
  5437. STDMETHODIMP
  5438. CDhcpActiveLeasesQueryObj::Execute()
  5439. {
  5440. HRESULT hr;
  5441. BuildReservationList();
  5442. if (m_liDhcpVersion.QuadPart >= DHCP_NT5_VERSION)
  5443. {
  5444. hr = EnumerateLeasesV5();
  5445. }
  5446. else
  5447. if (m_liDhcpVersion.QuadPart >= DHCP_SP2_VERSION)
  5448. {
  5449. hr = EnumerateLeasesV4();
  5450. }
  5451. else
  5452. {
  5453. hr = EnumerateLeases();
  5454. }
  5455. return hr;
  5456. }
  5457. /*---------------------------------------------------------------------------
  5458. CDhcpActiveLeasesQueryObj::IsReservation()
  5459. Description
  5460. Author: EricDav
  5461. ---------------------------------------------------------------------------*/
  5462. BOOL
  5463. CDhcpActiveLeasesQueryObj::IsReservation(DWORD dwIp)
  5464. {
  5465. BOOL fIsRes = FALSE;
  5466. for (int i = 0; i < m_ReservationArray.GetSize(); i++)
  5467. {
  5468. if (m_ReservationArray[i] == dwIp)
  5469. {
  5470. fIsRes = TRUE;
  5471. break;
  5472. }
  5473. }
  5474. return fIsRes;
  5475. }
  5476. /*---------------------------------------------------------------------------
  5477. CDhcpActiveLeasesQueryObj::BuildReservationList()
  5478. Description
  5479. Author: EricDav
  5480. ---------------------------------------------------------------------------*/
  5481. HRESULT
  5482. CDhcpActiveLeasesQueryObj::BuildReservationList()
  5483. {
  5484. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  5485. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  5486. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  5487. DWORD dwError = ERROR_MORE_DATA;
  5488. while (dwError == ERROR_MORE_DATA)
  5489. {
  5490. dwError = ::DhcpEnumSubnetElements(((LPWSTR) (LPCTSTR)m_strServer),
  5491. m_dhcpScopeAddress,
  5492. DhcpReservedIps,
  5493. &dhcpResumeHandle,
  5494. -1,
  5495. &pdhcpSubnetElementArray,
  5496. &dwElementsRead,
  5497. &dwElementsTotal);
  5498. Trace3("BuildReservationList: Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  5499. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  5500. {
  5501. //
  5502. // Loop through the array that was returned
  5503. //
  5504. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  5505. {
  5506. m_ReservationArray.Add(pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress);
  5507. }
  5508. }
  5509. // Check the abort flag on the thread
  5510. if (FCheckForAbort() == hrOK)
  5511. break;
  5512. // check to see if we have an error and post it to the main thread if we do..
  5513. if (dwError != ERROR_NO_MORE_ITEMS &&
  5514. dwError != ERROR_SUCCESS &&
  5515. dwError != ERROR_MORE_DATA)
  5516. {
  5517. Trace1("DHCP snapin: BuildReservationList error: %d\n", dwError);
  5518. m_dwErr = dwError;
  5519. PostError(dwError);
  5520. }
  5521. }
  5522. return hrFalse;
  5523. }
  5524. /*---------------------------------------------------------------------------
  5525. CDhcpActiveLeasesQueryObj::EnumerateLeasesV5()
  5526. Description
  5527. Author: EricDav
  5528. ---------------------------------------------------------------------------*/
  5529. HRESULT
  5530. CDhcpActiveLeasesQueryObj::EnumerateLeasesV5()
  5531. {
  5532. DWORD dwError = ERROR_MORE_DATA;
  5533. LPDHCP_CLIENT_INFO_ARRAY_V5 pdhcpClientArrayV5 = NULL;
  5534. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5535. DWORD dwEnumedClients = 0;
  5536. while (dwError == ERROR_MORE_DATA)
  5537. {
  5538. dwError = ::DhcpEnumSubnetClientsV5(((LPWSTR) (LPCTSTR)m_strServer),
  5539. m_dhcpScopeAddress,
  5540. &m_dhcpResumeHandle,
  5541. m_dwPreferredMax,
  5542. &pdhcpClientArrayV5,
  5543. &dwClientsRead,
  5544. &dwClientsTotal);
  5545. if (dwClientsRead && dwClientsTotal && pdhcpClientArrayV5)
  5546. {
  5547. //
  5548. // loop through all of the elements that were returned
  5549. //
  5550. for (DWORD i = 0; i < dwClientsRead; i++)
  5551. {
  5552. CDhcpActiveLease * pDhcpActiveLease;
  5553. //
  5554. // Create the result pane item for this element
  5555. //
  5556. SPITFSNode spNode;
  5557. pDhcpActiveLease =
  5558. new CDhcpActiveLease(m_spTFSCompData, pdhcpClientArrayV5->Clients[i]);
  5559. // filter these types of records out
  5560. if (pDhcpActiveLease->IsUnreg())
  5561. {
  5562. delete pDhcpActiveLease;
  5563. continue;
  5564. }
  5565. if (IsReservation(pdhcpClientArrayV5->Clients[i]->ClientIpAddress))
  5566. pDhcpActiveLease->SetReservation(TRUE);
  5567. CreateLeafTFSNode(&spNode,
  5568. &GUID_DhcpActiveLeaseNodeType,
  5569. pDhcpActiveLease,
  5570. pDhcpActiveLease,
  5571. m_spNodeMgr);
  5572. // Tell the handler to initialize any specific data
  5573. pDhcpActiveLease->InitializeNode(spNode);
  5574. AddToQueue(spNode);
  5575. pDhcpActiveLease->Release();
  5576. }
  5577. ::DhcpRpcFreeMemory(pdhcpClientArrayV5);
  5578. dwEnumedClients += dwClientsRead;
  5579. dwClientsRead = 0;
  5580. dwClientsTotal = 0;
  5581. pdhcpClientArrayV5 = NULL;
  5582. }
  5583. // Check the abort flag on the thread
  5584. if (FCheckForAbort() == hrOK)
  5585. break;
  5586. // check to see if we have an error and post it to the main thread if we do..
  5587. if (dwError != ERROR_NO_MORE_ITEMS &&
  5588. dwError != ERROR_SUCCESS &&
  5589. dwError != ERROR_MORE_DATA)
  5590. {
  5591. Trace1("DHCP snapin: EnumerateLeasesV5 error: %d\n", dwError);
  5592. m_dwErr = dwError;
  5593. PostError(dwError);
  5594. }
  5595. }
  5596. Trace1("DHCP snapin: V5 Leases enumerated: %d\n", dwEnumedClients);
  5597. return hrFalse;
  5598. }
  5599. /*---------------------------------------------------------------------------
  5600. CDhcpActiveLeasesQueryObj::EnumerateLeasesV4()
  5601. Description
  5602. Author: EricDav
  5603. ---------------------------------------------------------------------------*/
  5604. HRESULT
  5605. CDhcpActiveLeasesQueryObj::EnumerateLeasesV4()
  5606. {
  5607. DWORD dwError = ERROR_MORE_DATA;
  5608. LPDHCP_CLIENT_INFO_ARRAY_V4 pdhcpClientArrayV4 = NULL;
  5609. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5610. DWORD dwEnumedClients = 0;
  5611. while (dwError == ERROR_MORE_DATA)
  5612. {
  5613. dwError = ::DhcpEnumSubnetClientsV4(((LPWSTR) (LPCTSTR)m_strServer),
  5614. m_dhcpScopeAddress,
  5615. &m_dhcpResumeHandle,
  5616. m_dwPreferredMax,
  5617. &pdhcpClientArrayV4,
  5618. &dwClientsRead,
  5619. &dwClientsTotal);
  5620. if (dwClientsRead && dwClientsTotal && pdhcpClientArrayV4)
  5621. {
  5622. //
  5623. // loop through all of the elements that were returned
  5624. //
  5625. //for (DWORD i = 0; i < pdhcpClientArrayV4->NumElements; i++)
  5626. for (DWORD i = 0; i < dwClientsRead; i++)
  5627. {
  5628. CDhcpActiveLease * pDhcpActiveLease;
  5629. //
  5630. // Create the result pane item for this element
  5631. //
  5632. SPITFSNode spNode;
  5633. pDhcpActiveLease =
  5634. new CDhcpActiveLease(m_spTFSCompData, pdhcpClientArrayV4->Clients[i]);
  5635. // filter these types of records out
  5636. if (pDhcpActiveLease->IsGhost() ||
  5637. pDhcpActiveLease->IsUnreg() ||
  5638. pDhcpActiveLease->IsDoomed() )
  5639. {
  5640. delete pDhcpActiveLease;
  5641. continue;
  5642. }
  5643. if (IsReservation(pdhcpClientArrayV4->Clients[i]->ClientIpAddress))
  5644. pDhcpActiveLease->SetReservation(TRUE);
  5645. CreateLeafTFSNode(&spNode,
  5646. &GUID_DhcpActiveLeaseNodeType,
  5647. pDhcpActiveLease,
  5648. pDhcpActiveLease,
  5649. m_spNodeMgr);
  5650. // Tell the handler to initialize any specific data
  5651. pDhcpActiveLease->InitializeNode(spNode);
  5652. AddToQueue(spNode);
  5653. pDhcpActiveLease->Release();
  5654. }
  5655. ::DhcpRpcFreeMemory(pdhcpClientArrayV4);
  5656. dwEnumedClients += dwClientsRead;
  5657. dwClientsRead = 0;
  5658. dwClientsTotal = 0;
  5659. pdhcpClientArrayV4 = NULL;
  5660. }
  5661. // Check the abort flag on the thread
  5662. if (FCheckForAbort() == hrOK)
  5663. break;
  5664. // check to see if we have an error and post it to the main thread if we do..
  5665. if (dwError != ERROR_NO_MORE_ITEMS &&
  5666. dwError != ERROR_SUCCESS &&
  5667. dwError != ERROR_MORE_DATA)
  5668. {
  5669. Trace1("DHCP snapin: EnumerateLeasesV4 error: %d\n", dwError);
  5670. m_dwErr = dwError;
  5671. PostError(dwError);
  5672. }
  5673. }
  5674. Trace1("DHCP snapin: V4 Leases enumerated: %d\n", dwEnumedClients);
  5675. return hrFalse;
  5676. }
  5677. /*---------------------------------------------------------------------------
  5678. CDhcpActiveLeasesQueryObj::EnumerateLeases()
  5679. Description
  5680. Author: EricDav
  5681. ---------------------------------------------------------------------------*/
  5682. HRESULT
  5683. CDhcpActiveLeasesQueryObj::EnumerateLeases()
  5684. {
  5685. DWORD dwError = ERROR_MORE_DATA;
  5686. LPDHCP_CLIENT_INFO_ARRAY pdhcpClientArray = NULL;
  5687. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5688. DWORD dwEnumedClients = 0;
  5689. while (dwError == ERROR_MORE_DATA)
  5690. {
  5691. dwError = ::DhcpEnumSubnetClients(((LPWSTR) (LPCTSTR)m_strServer),
  5692. m_dhcpScopeAddress,
  5693. &m_dhcpResumeHandle,
  5694. m_dwPreferredMax,
  5695. &pdhcpClientArray,
  5696. &dwClientsRead,
  5697. &dwClientsTotal);
  5698. if (dwClientsRead && dwClientsTotal && pdhcpClientArray)
  5699. {
  5700. //
  5701. // loop through all of the elements that were returned
  5702. //
  5703. for (DWORD i = 0; i < pdhcpClientArray->NumElements; i++)
  5704. {
  5705. CDhcpActiveLease * pDhcpActiveLease;
  5706. //
  5707. // Create the result pane item for this element
  5708. //
  5709. SPITFSNode spNode;
  5710. pDhcpActiveLease =
  5711. new CDhcpActiveLease(m_spTFSCompData,pdhcpClientArray->Clients[i]);
  5712. // filter these types of records out
  5713. if (pDhcpActiveLease->IsGhost() ||
  5714. pDhcpActiveLease->IsUnreg() ||
  5715. pDhcpActiveLease->IsDoomed() )
  5716. {
  5717. delete pDhcpActiveLease;
  5718. continue;
  5719. }
  5720. if (IsReservation(pdhcpClientArray->Clients[i]->ClientIpAddress))
  5721. pDhcpActiveLease->SetReservation(TRUE);
  5722. CreateLeafTFSNode(&spNode,
  5723. &GUID_DhcpActiveLeaseNodeType,
  5724. pDhcpActiveLease,
  5725. pDhcpActiveLease,
  5726. m_spNodeMgr);
  5727. // Tell the handler to initialize any specific data
  5728. pDhcpActiveLease->InitializeNode(spNode);
  5729. AddToQueue(spNode);
  5730. pDhcpActiveLease->Release();
  5731. }
  5732. ::DhcpRpcFreeMemory(pdhcpClientArray);
  5733. dwEnumedClients += dwClientsRead;
  5734. dwClientsRead = 0;
  5735. dwClientsTotal = 0;
  5736. pdhcpClientArray = NULL;
  5737. }
  5738. // Check the abort flag on the thread
  5739. if (FCheckForAbort() == hrOK)
  5740. break;
  5741. // check to see if we have an error and post it to the main thread if we do..
  5742. if (dwError != ERROR_NO_MORE_ITEMS &&
  5743. dwError != ERROR_SUCCESS &&
  5744. dwError != ERROR_MORE_DATA)
  5745. {
  5746. Trace1("DHCP snapin: EnumerateLeases error: %d\n", dwError);
  5747. m_dwErr = dwError;
  5748. PostError(dwError);
  5749. }
  5750. }
  5751. Trace1("DHCP snpain: Leases enumerated: %d\n", dwEnumedClients);
  5752. return hrFalse;
  5753. }
  5754. /*---------------------------------------------------------------------------
  5755. Class CDhcpAddressPool implementation
  5756. ---------------------------------------------------------------------------*/
  5757. /*---------------------------------------------------------------------------
  5758. Function Name Here
  5759. Description
  5760. Author: EricDav
  5761. ---------------------------------------------------------------------------*/
  5762. CDhcpAddressPool::CDhcpAddressPool
  5763. (
  5764. ITFSComponentData * pComponentData
  5765. ) : CMTDhcpHandler(pComponentData)
  5766. {
  5767. }
  5768. CDhcpAddressPool::~CDhcpAddressPool()
  5769. {
  5770. }
  5771. /*!--------------------------------------------------------------------------
  5772. CDhcpAddressPool::InitializeNode
  5773. Initializes node specific data
  5774. Author: EricDav
  5775. ---------------------------------------------------------------------------*/
  5776. HRESULT
  5777. CDhcpAddressPool::InitializeNode
  5778. (
  5779. ITFSNode * pNode
  5780. )
  5781. {
  5782. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5783. HRESULT hr = hrOK;
  5784. //
  5785. // Create the display name for this scope
  5786. //
  5787. CString strTemp;
  5788. strTemp.LoadString(IDS_ADDRESS_POOL_FOLDER);
  5789. SetDisplayName(strTemp);
  5790. // Make the node immediately visible
  5791. pNode->SetVisibilityState(TFS_VIS_SHOW);
  5792. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  5793. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  5794. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  5795. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  5796. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_ADDRESS_POOL);
  5797. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  5798. SetColumnStringIDs(&aColumns[DHCPSNAP_ADDRESS_POOL][0]);
  5799. SetColumnWidths(&aColumnWidths[DHCPSNAP_ADDRESS_POOL][0]);
  5800. return hr;
  5801. }
  5802. /*---------------------------------------------------------------------------
  5803. CDhcpAddressPool::OnCreateNodeId2
  5804. Returns a unique string for this node
  5805. Author: EricDav
  5806. ---------------------------------------------------------------------------*/
  5807. HRESULT CDhcpAddressPool::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  5808. {
  5809. const GUID * pGuid = pNode->GetNodeType();
  5810. CString strIpAddress, strGuid;
  5811. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  5812. strGuid.ReleaseBuffer();
  5813. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  5814. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  5815. strId = GetServerName(pNode) + strIpAddress + strGuid;
  5816. return hrOK;
  5817. }
  5818. /*---------------------------------------------------------------------------
  5819. CDhcpAddressPool::GetImageIndex
  5820. Description
  5821. Author: EricDav
  5822. ---------------------------------------------------------------------------*/
  5823. int
  5824. CDhcpAddressPool::GetImageIndex(BOOL bOpenImage)
  5825. {
  5826. int nIndex = -1;
  5827. switch (m_nState)
  5828. {
  5829. case notLoaded:
  5830. case loaded:
  5831. if (bOpenImage)
  5832. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN;
  5833. else
  5834. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED;
  5835. break;
  5836. case loading:
  5837. if (bOpenImage)
  5838. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_BUSY;
  5839. else
  5840. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_BUSY;
  5841. break;
  5842. case unableToLoad:
  5843. if (bOpenImage)
  5844. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_LOST_CONNECTION;
  5845. else
  5846. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_LOST_CONNECTION;
  5847. break;
  5848. default:
  5849. ASSERT(FALSE);
  5850. }
  5851. return nIndex;
  5852. }
  5853. /*---------------------------------------------------------------------------
  5854. Overridden base handler functions
  5855. ---------------------------------------------------------------------------*/
  5856. /*---------------------------------------------------------------------------
  5857. CDhcpAddressPool::OnAddMenuItems
  5858. Adds entries to the context sensitive menu
  5859. Author: EricDav
  5860. ---------------------------------------------------------------------------*/
  5861. STDMETHODIMP
  5862. CDhcpAddressPool::OnAddMenuItems
  5863. (
  5864. ITFSNode * pNode,
  5865. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  5866. LPDATAOBJECT lpDataObject,
  5867. DATA_OBJECT_TYPES type,
  5868. DWORD dwType,
  5869. long * pInsertionAllowed
  5870. )
  5871. {
  5872. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5873. LONG fFlags = 0;
  5874. HRESULT hr = S_OK;
  5875. CString strMenuText;
  5876. if ( (m_nState != loaded) )
  5877. {
  5878. fFlags |= MF_GRAYED;
  5879. }
  5880. if (type == CCT_SCOPE)
  5881. {
  5882. // these menu items go in the new menu,
  5883. // only visible from scope pane
  5884. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  5885. {
  5886. strMenuText.LoadString(IDS_CREATE_NEW_EXCLUSION);
  5887. hr = LoadAndAddMenuItem( pContextMenuCallback,
  5888. strMenuText,
  5889. IDS_CREATE_NEW_EXCLUSION,
  5890. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  5891. fFlags );
  5892. ASSERT( SUCCEEDED(hr) );
  5893. }
  5894. }
  5895. return hr;
  5896. }
  5897. /*---------------------------------------------------------------------------
  5898. CDhcpAddressPool::OnCommand
  5899. Description
  5900. Author: EricDav
  5901. ---------------------------------------------------------------------------*/
  5902. STDMETHODIMP
  5903. CDhcpAddressPool::OnCommand
  5904. (
  5905. ITFSNode * pNode,
  5906. long nCommandId,
  5907. DATA_OBJECT_TYPES type,
  5908. LPDATAOBJECT pDataObject,
  5909. DWORD dwType
  5910. )
  5911. {
  5912. HRESULT hr = S_OK;
  5913. switch (nCommandId)
  5914. {
  5915. case IDS_CREATE_NEW_EXCLUSION:
  5916. OnCreateNewExclusion(pNode);
  5917. break;
  5918. case IDS_REFRESH:
  5919. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  5920. break;
  5921. default:
  5922. break;
  5923. }
  5924. return hr;
  5925. }
  5926. /*---------------------------------------------------------------------------
  5927. Message handlers
  5928. ---------------------------------------------------------------------------*/
  5929. /*---------------------------------------------------------------------------
  5930. CDhcpAddressPool::OnCreateNewExclusion
  5931. Description
  5932. Author: EricDav
  5933. ---------------------------------------------------------------------------*/
  5934. DWORD
  5935. CDhcpAddressPool::OnCreateNewExclusion
  5936. (
  5937. ITFSNode * pNode
  5938. )
  5939. {
  5940. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5941. SPITFSNode spScopeNode;
  5942. pNode->GetParent(&spScopeNode);
  5943. CAddExclusion dlgAddExclusion(spScopeNode);
  5944. dlgAddExclusion.DoModal();
  5945. return 0;
  5946. }
  5947. /*---------------------------------------------------------------------------
  5948. CDhcpAddressPool::OnResultDelete
  5949. This function is called when we are supposed to delete result
  5950. pane items. We build a list of selected items and then delete them.
  5951. Author: EricDav
  5952. ---------------------------------------------------------------------------*/
  5953. HRESULT
  5954. CDhcpAddressPool::OnResultDelete
  5955. (
  5956. ITFSComponent * pComponent,
  5957. LPDATAOBJECT pDataObject,
  5958. MMC_COOKIE cookie,
  5959. LPARAM arg,
  5960. LPARAM param
  5961. )
  5962. {
  5963. HRESULT hr = NOERROR;
  5964. BOOL bIsRes, bIsActive, bBadAddress;
  5965. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  5966. // translate the cookie into a node pointer
  5967. SPITFSNode spAddressPool, spSelectedNode;
  5968. m_spNodeMgr->FindNode(cookie, &spAddressPool);
  5969. pComponent->GetSelectedNode(&spSelectedNode);
  5970. Assert(spSelectedNode == spAddressPool);
  5971. if (spSelectedNode != spAddressPool)
  5972. return hr;
  5973. // build the list of selected nodes
  5974. CTFSNodeList listNodesToDelete;
  5975. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  5976. //
  5977. // Confirm with the user
  5978. //
  5979. CString strMessage, strTemp;
  5980. int nNodes = (int)listNodesToDelete.GetCount();
  5981. if (nNodes > 1)
  5982. {
  5983. strTemp.Format(_T("%d"), nNodes);
  5984. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  5985. }
  5986. else
  5987. {
  5988. strMessage.LoadString(IDS_DELETE_ITEM);
  5989. }
  5990. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  5991. {
  5992. return NOERROR;
  5993. }
  5994. //
  5995. // Loop through all items deleting
  5996. //
  5997. BEGIN_WAIT_CURSOR;
  5998. while (listNodesToDelete.GetCount() > 0)
  5999. {
  6000. SPITFSNode spExclusionRangeNode;
  6001. spExclusionRangeNode = listNodesToDelete.RemoveHead();
  6002. CDhcpExclusionRange * pExclusion = GETHANDLER(CDhcpExclusionRange, spExclusionRangeNode);
  6003. if (spExclusionRangeNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
  6004. {
  6005. //
  6006. // This is the allocation range, can't delete
  6007. //
  6008. AfxMessageBox(IDS_CANNOT_DELETE_ALLOCATION_RANGE);
  6009. spExclusionRangeNode.Release();
  6010. continue;
  6011. }
  6012. //
  6013. // Try to remove it from the server
  6014. //
  6015. CDhcpIpRange dhcpIpRange((DHCP_IP_RANGE) *pExclusion);
  6016. DWORD dwError = GetScopeObject(spAddressPool)->RemoveExclusion(dhcpIpRange);
  6017. if (dwError != 0)
  6018. {
  6019. ::DhcpMessageBox(dwError);
  6020. RESTORE_WAIT_CURSOR;
  6021. hr = E_FAIL;
  6022. continue;
  6023. }
  6024. //
  6025. // Remove from UI now
  6026. //
  6027. spAddressPool->RemoveChild(spExclusionRangeNode);
  6028. spExclusionRangeNode.Release();
  6029. }
  6030. // update stats
  6031. GetScopeObject(spAddressPool)->TriggerStatsRefresh();
  6032. END_WAIT_CURSOR;
  6033. return hr;
  6034. }
  6035. /*!--------------------------------------------------------------------------
  6036. CDhcpAddressPool::OnGetResultViewType
  6037. MMC calls this to get the result view information
  6038. Author: EricDav
  6039. ---------------------------------------------------------------------------*/
  6040. HRESULT
  6041. CDhcpAddressPool::OnGetResultViewType
  6042. (
  6043. ITFSComponent * pComponent,
  6044. MMC_COOKIE cookie,
  6045. LPOLESTR * ppViewType,
  6046. long * pViewOptions
  6047. )
  6048. {
  6049. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  6050. // we still want the default MMC result pane view, we just want
  6051. // multiselect, so return S_FALSE
  6052. return S_FALSE;
  6053. }
  6054. /*---------------------------------------------------------------------------
  6055. Background thread functionality
  6056. ---------------------------------------------------------------------------*/
  6057. /*---------------------------------------------------------------------------
  6058. CDhcpAddressPool::OnCreateQuery()
  6059. Description
  6060. Author: EricDav
  6061. ---------------------------------------------------------------------------*/
  6062. ITFSQueryObject*
  6063. CDhcpAddressPool::OnCreateQuery(ITFSNode * pNode)
  6064. {
  6065. CDhcpAddressPoolQueryObj* pQuery =
  6066. new CDhcpAddressPoolQueryObj(m_spTFSCompData, m_spNodeMgr);
  6067. pQuery->m_strServer = GetServerIpAddress(pNode);
  6068. CDhcpScope * pScope = GetScopeObject(pNode);
  6069. if (pScope)
  6070. {
  6071. pQuery->m_dhcpScopeAddress = pScope->GetAddress();
  6072. pQuery->m_fSupportsDynBootp = pScope->GetServerObject()->FSupportsDynBootp();
  6073. }
  6074. pQuery->m_dhcpExclResumeHandle = NULL;
  6075. pQuery->m_dwExclPreferredMax = 0xFFFFFFFF;
  6076. pQuery->m_dhcpIpResumeHandle = NULL;
  6077. pQuery->m_dwIpPreferredMax = 0xFFFFFFFF;
  6078. return pQuery;
  6079. }
  6080. /*---------------------------------------------------------------------------
  6081. CDhcpAddressPoolQueryObj::Execute()
  6082. Description
  6083. Author: EricDav
  6084. ---------------------------------------------------------------------------*/
  6085. STDMETHODIMP
  6086. CDhcpAddressPoolQueryObj::Execute()
  6087. {
  6088. HRESULT hr1 = EnumerateIpRanges();
  6089. HRESULT hr2 = EnumerateExcludedIpRanges();
  6090. if (hr1 == hrOK || hr2 == hrOK)
  6091. return hrOK;
  6092. else
  6093. return hrFalse;
  6094. }
  6095. /*---------------------------------------------------------------------------
  6096. Function Name Here
  6097. Description
  6098. Author: EricDav
  6099. ---------------------------------------------------------------------------*/
  6100. HRESULT
  6101. CDhcpAddressPoolQueryObj::EnumerateExcludedIpRanges()
  6102. {
  6103. DWORD dwError = ERROR_MORE_DATA;
  6104. DHCP_RESUME_HANDLE dhcpResumeHandle = 0;
  6105. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  6106. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6107. while (dwError == ERROR_MORE_DATA)
  6108. {
  6109. dwError = ::DhcpEnumSubnetElements((LPWSTR) ((LPCTSTR) m_strServer),
  6110. m_dhcpScopeAddress,
  6111. DhcpExcludedIpRanges,
  6112. &m_dhcpExclResumeHandle,
  6113. m_dwExclPreferredMax,
  6114. &pdhcpSubnetElementArray,
  6115. &dwElementsRead,
  6116. &dwElementsTotal);
  6117. Trace3("Scope %lx Excluded Ip Ranges read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  6118. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  6119. {
  6120. //
  6121. // loop through all of the elements that were returned
  6122. //
  6123. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6124. {
  6125. //
  6126. // Create the result pane item for this element
  6127. //
  6128. SPITFSNode spNode;
  6129. CDhcpExclusionRange * pDhcpExclusionRange =
  6130. new CDhcpExclusionRange(m_spTFSCompData,
  6131. pdhcpSubnetElementArray->Elements[i].Element.ExcludeIpRange);
  6132. CreateLeafTFSNode(&spNode,
  6133. &GUID_DhcpExclusionNodeType,
  6134. pDhcpExclusionRange,
  6135. pDhcpExclusionRange,
  6136. m_spNodeMgr);
  6137. // Tell the handler to initialize any specific data
  6138. pDhcpExclusionRange->InitializeNode(spNode);
  6139. AddToQueue(spNode);
  6140. pDhcpExclusionRange->Release();
  6141. }
  6142. // Free up the memory from the RPC call
  6143. //
  6144. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6145. }
  6146. // Check the abort flag on the thread
  6147. if (FCheckForAbort() == hrOK)
  6148. break;
  6149. // check to see if we have an error and post it to the main thread if we do..
  6150. if (dwError != ERROR_NO_MORE_ITEMS &&
  6151. dwError != ERROR_SUCCESS &&
  6152. dwError != ERROR_MORE_DATA)
  6153. {
  6154. Trace1("DHCP snapin: EnumerateExcludedIpRanges error: %d\n", dwError);
  6155. m_dwErr = dwError;
  6156. PostError(dwError);
  6157. }
  6158. }
  6159. return hrFalse;
  6160. }
  6161. /*---------------------------------------------------------------------------
  6162. Function Name Here
  6163. Description
  6164. Author: EricDav
  6165. ---------------------------------------------------------------------------*/
  6166. HRESULT
  6167. CDhcpAddressPoolQueryObj::EnumerateIpRanges()
  6168. {
  6169. DWORD dwError = ERROR_MORE_DATA;
  6170. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  6171. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6172. if (m_fSupportsDynBootp)
  6173. {
  6174. return EnumerateIpRangesV5();
  6175. }
  6176. while (dwError == ERROR_MORE_DATA)
  6177. {
  6178. dwError = ::DhcpEnumSubnetElements((LPWSTR) ((LPCTSTR) m_strServer),
  6179. m_dhcpScopeAddress,
  6180. DhcpIpRanges,
  6181. &m_dhcpIpResumeHandle,
  6182. m_dwIpPreferredMax,
  6183. &pdhcpSubnetElementArray,
  6184. &dwElementsRead,
  6185. &dwElementsTotal);
  6186. Trace4("Scope %lx allocation ranges read %d, total %d, dwError = %lx\n",
  6187. m_dhcpScopeAddress, dwElementsRead, dwElementsTotal, dwError);
  6188. if ((dwError == ERROR_MORE_DATA) ||
  6189. ( (dwElementsRead) && (dwError == ERROR_SUCCESS) ))
  6190. {
  6191. //
  6192. // Loop through the array that was returned
  6193. //
  6194. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6195. {
  6196. //
  6197. // Create the result pane item for this element
  6198. //
  6199. SPITFSNode spNode;
  6200. CDhcpAllocationRange * pDhcpAllocRange =
  6201. new CDhcpAllocationRange(m_spTFSCompData,
  6202. pdhcpSubnetElementArray->Elements[i].Element.IpRange);
  6203. CreateLeafTFSNode(&spNode,
  6204. &GUID_DhcpAllocationNodeType,
  6205. pDhcpAllocRange,
  6206. pDhcpAllocRange,
  6207. m_spNodeMgr);
  6208. // Tell the handler to initialize any specific data
  6209. pDhcpAllocRange->InitializeNode(spNode);
  6210. AddToQueue(spNode);
  6211. pDhcpAllocRange->Release();
  6212. }
  6213. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6214. }
  6215. else
  6216. if (dwError != ERROR_SUCCESS &&
  6217. dwError != ERROR_NO_MORE_ITEMS)
  6218. {
  6219. // set the error variable so that it can be looked at later
  6220. m_dwError = dwError;
  6221. }
  6222. // Check the abort flag on the thread
  6223. if (FCheckForAbort() == hrOK)
  6224. break;
  6225. // check to see if we have an error and post it to the main thread if we do..
  6226. if (dwError != ERROR_NO_MORE_ITEMS &&
  6227. dwError != ERROR_SUCCESS &&
  6228. dwError != ERROR_MORE_DATA)
  6229. {
  6230. Trace1("DHCP snapin: EnumerateAllocationRanges error: %d\n", dwError);
  6231. m_dwErr = dwError;
  6232. PostError(dwError);
  6233. }
  6234. }
  6235. return hrFalse;
  6236. }
  6237. HRESULT
  6238. CDhcpAddressPoolQueryObj::EnumerateIpRangesV5()
  6239. {
  6240. DWORD dwError = ERROR_MORE_DATA;
  6241. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 pdhcpSubnetElementArray = NULL;
  6242. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6243. while (dwError == ERROR_MORE_DATA)
  6244. {
  6245. dwError = ::DhcpEnumSubnetElementsV5((LPWSTR) ((LPCTSTR) m_strServer),
  6246. m_dhcpScopeAddress,
  6247. DhcpIpRangesDhcpBootp,
  6248. &m_dhcpIpResumeHandle,
  6249. m_dwIpPreferredMax,
  6250. &pdhcpSubnetElementArray,
  6251. &dwElementsRead,
  6252. &dwElementsTotal);
  6253. Trace4("EnumerateIpRangesV5: Scope %lx allocation ranges read %d, total %d, dwError = %lx\n",
  6254. m_dhcpScopeAddress, dwElementsRead, dwElementsTotal, dwError);
  6255. if ((dwError == ERROR_MORE_DATA) ||
  6256. ( (dwElementsRead) && (dwError == ERROR_SUCCESS) ))
  6257. {
  6258. //
  6259. // Loop through the array that was returned
  6260. //
  6261. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6262. {
  6263. //
  6264. // Create the result pane item for this element
  6265. //
  6266. SPITFSNode spNode;
  6267. CDhcpAllocationRange * pDhcpAllocRange =
  6268. new CDhcpAllocationRange(m_spTFSCompData,
  6269. pdhcpSubnetElementArray->Elements[i].Element.IpRange);
  6270. pDhcpAllocRange->SetRangeType(pdhcpSubnetElementArray->Elements[i].ElementType);
  6271. CreateLeafTFSNode(&spNode,
  6272. &GUID_DhcpAllocationNodeType,
  6273. pDhcpAllocRange,
  6274. pDhcpAllocRange,
  6275. m_spNodeMgr);
  6276. // Tell the handler to initialize any specific data
  6277. pDhcpAllocRange->InitializeNode(spNode);
  6278. AddToQueue(spNode);
  6279. pDhcpAllocRange->Release();
  6280. }
  6281. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6282. }
  6283. else
  6284. if (dwError != ERROR_SUCCESS &&
  6285. dwError != ERROR_NO_MORE_ITEMS)
  6286. {
  6287. // set the error variable so that it can be looked at later
  6288. m_dwError = dwError;
  6289. }
  6290. // Check the abort flag on the thread
  6291. if (FCheckForAbort() == hrOK)
  6292. break;
  6293. // check to see if we have an error and post it to the main thread if we do..
  6294. if (dwError != ERROR_NO_MORE_ITEMS &&
  6295. dwError != ERROR_SUCCESS &&
  6296. dwError != ERROR_MORE_DATA)
  6297. {
  6298. Trace1("DHCP snapin: EnumerateAllocationRanges error: %d\n", dwError);
  6299. m_dwErr = dwError;
  6300. PostError(dwError);
  6301. }
  6302. }
  6303. return hrFalse;
  6304. }
  6305. /*---------------------------------------------------------------------------
  6306. CDhcpAddressPool::CompareItems
  6307. Description
  6308. Author: EricDav
  6309. ---------------------------------------------------------------------------*/
  6310. STDMETHODIMP_(int)
  6311. CDhcpAddressPool::CompareItems
  6312. (
  6313. ITFSComponent * pComponent,
  6314. MMC_COOKIE cookieA,
  6315. MMC_COOKIE cookieB,
  6316. int nCol
  6317. )
  6318. {
  6319. SPITFSNode spNode1, spNode2;
  6320. m_spNodeMgr->FindNode(cookieA, &spNode1);
  6321. m_spNodeMgr->FindNode(cookieB, &spNode2);
  6322. int nCompare = 0;
  6323. CDhcpAllocationRange *pDhcpAR1 = GETHANDLER(CDhcpAllocationRange, spNode1);
  6324. CDhcpAllocationRange *pDhcpAR2 = GETHANDLER(CDhcpAllocationRange, spNode2);
  6325. switch (nCol)
  6326. {
  6327. case 0:
  6328. {
  6329. // Start IP address compare
  6330. //
  6331. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(TRUE);
  6332. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(TRUE);
  6333. if (dhcpIp1 < dhcpIp2)
  6334. nCompare = -1;
  6335. else
  6336. if (dhcpIp1 > dhcpIp2)
  6337. nCompare = 1;
  6338. // default is that they are equal
  6339. }
  6340. break;
  6341. case 1:
  6342. {
  6343. // End IP address compare
  6344. //
  6345. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(FALSE);
  6346. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(FALSE);
  6347. if (dhcpIp1 < dhcpIp2)
  6348. nCompare = -1;
  6349. else
  6350. if (dhcpIp1 > dhcpIp2)
  6351. nCompare = 1;
  6352. // default is that they are equal
  6353. }
  6354. break;
  6355. case 2:
  6356. {
  6357. // Description compare
  6358. //
  6359. CString strRange1 = pDhcpAR1->GetString(pComponent, cookieA, nCol);
  6360. CString strRange2 = pDhcpAR2->GetString(pComponent, cookieA, nCol);
  6361. // Compare should not be case sensitive
  6362. //
  6363. strRange1.MakeUpper();
  6364. strRange2.MakeUpper();
  6365. nCompare = strRange1.Compare(strRange2);
  6366. }
  6367. break;
  6368. }
  6369. return nCompare;
  6370. }
  6371. /*---------------------------------------------------------------------------
  6372. CDhcpScopeOptions Implementation
  6373. ---------------------------------------------------------------------------*/
  6374. /*---------------------------------------------------------------------------
  6375. CDhcpScopeOptions Constructor and destructor
  6376. Author: EricDav
  6377. ---------------------------------------------------------------------------*/
  6378. CDhcpScopeOptions::CDhcpScopeOptions
  6379. (
  6380. ITFSComponentData * pComponentData
  6381. ) : CMTDhcpHandler(pComponentData)
  6382. {
  6383. }
  6384. CDhcpScopeOptions::~CDhcpScopeOptions()
  6385. {
  6386. }
  6387. /*!--------------------------------------------------------------------------
  6388. CDhcpScopeOptions::InitializeNode
  6389. Initializes node specific data
  6390. Author: EricDav
  6391. ---------------------------------------------------------------------------*/
  6392. HRESULT
  6393. CDhcpScopeOptions::InitializeNode
  6394. (
  6395. ITFSNode * pNode
  6396. )
  6397. {
  6398. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6399. HRESULT hr = hrOK;
  6400. //
  6401. // Create the display name for this scope
  6402. //
  6403. CString strTemp;
  6404. strTemp.LoadString(IDS_SCOPE_OPTIONS_FOLDER);
  6405. SetDisplayName(strTemp);
  6406. // Make the node immediately visible
  6407. pNode->SetVisibilityState(TFS_VIS_SHOW);
  6408. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  6409. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  6410. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  6411. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  6412. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_SCOPE_OPTIONS);
  6413. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  6414. SetColumnStringIDs(&aColumns[DHCPSNAP_SCOPE_OPTIONS][0]);
  6415. SetColumnWidths(&aColumnWidths[DHCPSNAP_SCOPE_OPTIONS][0]);
  6416. return hr;
  6417. }
  6418. /*---------------------------------------------------------------------------
  6419. CDhcpScopeOptions::OnCreateNodeId2
  6420. Returns a unique string for this node
  6421. Author: EricDav
  6422. ---------------------------------------------------------------------------*/
  6423. HRESULT CDhcpScopeOptions::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  6424. {
  6425. const GUID * pGuid = pNode->GetNodeType();
  6426. CString strIpAddress, strGuid;
  6427. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  6428. strGuid.ReleaseBuffer();
  6429. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  6430. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  6431. strId = GetServerName(pNode) + strIpAddress + strGuid;
  6432. return hrOK;
  6433. }
  6434. /*---------------------------------------------------------------------------
  6435. CDhcpScopeOptions::GetImageIndex
  6436. Description
  6437. Author: EricDav
  6438. ---------------------------------------------------------------------------*/
  6439. int
  6440. CDhcpScopeOptions::GetImageIndex(BOOL bOpenImage)
  6441. {
  6442. int nIndex = -1;
  6443. switch (m_nState)
  6444. {
  6445. case notLoaded:
  6446. case loaded:
  6447. if (bOpenImage)
  6448. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN;
  6449. else
  6450. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED;
  6451. break;
  6452. case loading:
  6453. if (bOpenImage)
  6454. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN_BUSY;
  6455. else
  6456. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED_BUSY;
  6457. break;
  6458. case unableToLoad:
  6459. if (bOpenImage)
  6460. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN_LOST_CONNECTION;
  6461. else
  6462. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED_LOST_CONNECTION;
  6463. break;
  6464. default:
  6465. ASSERT(FALSE);
  6466. }
  6467. return nIndex;
  6468. }
  6469. /*---------------------------------------------------------------------------
  6470. Overridden base handler functions
  6471. ---------------------------------------------------------------------------*/
  6472. /*---------------------------------------------------------------------------
  6473. CDhcpScopeOptions::OnAddMenuItems
  6474. Adds entries to the context sensitive menu
  6475. Author: EricDav
  6476. ---------------------------------------------------------------------------*/
  6477. STDMETHODIMP
  6478. CDhcpScopeOptions::OnAddMenuItems
  6479. (
  6480. ITFSNode * pNode,
  6481. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  6482. LPDATAOBJECT lpDataObject,
  6483. DATA_OBJECT_TYPES type,
  6484. DWORD dwType,
  6485. long * pInsertionAllowed
  6486. )
  6487. {
  6488. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6489. LONG fFlags = 0;
  6490. HRESULT hr = S_OK;
  6491. CString strMenuText;
  6492. if ( (m_nState != loaded) )
  6493. {
  6494. fFlags |= MF_GRAYED;
  6495. }
  6496. if (type == CCT_SCOPE)
  6497. {
  6498. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  6499. {
  6500. // these menu items go in the new menu,
  6501. // only visible from scope pane
  6502. strMenuText.LoadString(IDS_CREATE_OPTION_SCOPE);
  6503. hr = LoadAndAddMenuItem( pContextMenuCallback,
  6504. strMenuText,
  6505. IDS_CREATE_OPTION_SCOPE,
  6506. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  6507. fFlags );
  6508. ASSERT( SUCCEEDED(hr) );
  6509. }
  6510. }
  6511. return hr;
  6512. }
  6513. /*---------------------------------------------------------------------------
  6514. CDhcpScopeOptions::OnCommand
  6515. Description
  6516. Author: EricDav
  6517. ---------------------------------------------------------------------------*/
  6518. STDMETHODIMP
  6519. CDhcpScopeOptions::OnCommand
  6520. (
  6521. ITFSNode * pNode,
  6522. long nCommandId,
  6523. DATA_OBJECT_TYPES type,
  6524. LPDATAOBJECT pDataObject,
  6525. DWORD dwType
  6526. )
  6527. {
  6528. HRESULT hr = S_OK;
  6529. switch (nCommandId)
  6530. {
  6531. case IDS_CREATE_OPTION_SCOPE:
  6532. OnCreateNewOptions(pNode);
  6533. break;
  6534. case IDS_REFRESH:
  6535. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  6536. break;
  6537. default:
  6538. break;
  6539. }
  6540. return hr;
  6541. }
  6542. /*!--------------------------------------------------------------------------
  6543. CDhcpScopeOptions::HasPropertyPages
  6544. Implementation of ITFSNodeHandler::HasPropertyPages
  6545. NOTE: the root node handler has to over-ride this function to
  6546. handle the snapin manager property page (wizard) case!!!
  6547. Author: KennT
  6548. ---------------------------------------------------------------------------*/
  6549. STDMETHODIMP
  6550. CDhcpScopeOptions::HasPropertyPages
  6551. (
  6552. ITFSNode * pNode,
  6553. LPDATAOBJECT pDataObject,
  6554. DATA_OBJECT_TYPES type,
  6555. DWORD dwType
  6556. )
  6557. {
  6558. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6559. HRESULT hr = hrOK;
  6560. // we have property pages in the normal case, but don't put the
  6561. // menu up if we are not loaded yet
  6562. if ( m_nState != loaded )
  6563. {
  6564. hr = hrFalse;
  6565. }
  6566. else
  6567. {
  6568. hr = hrOK;
  6569. }
  6570. return hr;
  6571. }
  6572. /*---------------------------------------------------------------------------
  6573. CDhcpScopeOptions::CreatePropertyPages
  6574. Description
  6575. Author: EricDav
  6576. ---------------------------------------------------------------------------*/
  6577. STDMETHODIMP
  6578. CDhcpScopeOptions::CreatePropertyPages
  6579. (
  6580. ITFSNode * pNode,
  6581. LPPROPERTYSHEETCALLBACK lpProvider,
  6582. LPDATAOBJECT pDataObject,
  6583. LONG_PTR handle,
  6584. DWORD dwType
  6585. )
  6586. {
  6587. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6588. DWORD dwError;
  6589. DWORD dwDynDnsFlags;
  6590. HRESULT hr = hrOK;
  6591. COptionsConfig * pOptCfg;
  6592. CString strOptCfgTitle, strOptType;
  6593. SPITFSNode spServerNode;
  6594. SPIComponentData spComponentData;
  6595. COptionValueEnum * pOptionValueEnum;
  6596. //
  6597. // Create the property page
  6598. //
  6599. COM_PROTECT_TRY
  6600. {
  6601. m_spNodeMgr->GetComponentData(&spComponentData);
  6602. BEGIN_WAIT_CURSOR;
  6603. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_SCOPE);
  6604. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  6605. GetScopeObject(pNode)->GetServerNode(&spServerNode);
  6606. pOptionValueEnum = GetScopeObject(pNode)->GetOptionValueEnum();
  6607. pOptCfg = new COptionsConfig(pNode,
  6608. spServerNode,
  6609. spComponentData,
  6610. m_spTFSCompData,
  6611. pOptionValueEnum,
  6612. strOptCfgTitle);
  6613. END_WAIT_CURSOR;
  6614. //
  6615. // Object gets deleted when the page is destroyed
  6616. //
  6617. Assert(lpProvider != NULL);
  6618. hr = pOptCfg->CreateModelessSheet(lpProvider, handle);
  6619. }
  6620. COM_PROTECT_CATCH
  6621. return hr;
  6622. }
  6623. /*---------------------------------------------------------------------------
  6624. CDhcpScopeOptions::OnPropertyChange
  6625. Description
  6626. Author: EricDav
  6627. ---------------------------------------------------------------------------*/
  6628. HRESULT
  6629. CDhcpScopeOptions::OnPropertyChange
  6630. (
  6631. ITFSNode * pNode,
  6632. LPDATAOBJECT pDataobject,
  6633. DWORD dwType,
  6634. LPARAM arg,
  6635. LPARAM lParam
  6636. )
  6637. {
  6638. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6639. COptionsConfig * pOptCfg = reinterpret_cast<COptionsConfig *>(lParam);
  6640. LPARAM changeMask = 0;
  6641. // tell the property page to do whatever now that we are back on the
  6642. // main thread
  6643. pOptCfg->OnPropertyChange(TRUE, &changeMask);
  6644. pOptCfg->AcknowledgeNotify();
  6645. if (changeMask)
  6646. pNode->ChangeNode(changeMask);
  6647. return hrOK;
  6648. }
  6649. /*---------------------------------------------------------------------------
  6650. CDhcpScopeOptions::OnPropertyChange
  6651. Description
  6652. Author: EricDav
  6653. ---------------------------------------------------------------------------*/
  6654. HRESULT
  6655. CDhcpScopeOptions::OnResultPropertyChange
  6656. (
  6657. ITFSComponent * pComponent,
  6658. LPDATAOBJECT pDataObject,
  6659. MMC_COOKIE cookie,
  6660. LPARAM arg,
  6661. LPARAM param
  6662. )
  6663. {
  6664. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6665. SPITFSNode spNode;
  6666. m_spNodeMgr->FindNode(cookie, &spNode);
  6667. COptionsConfig * pOptCfg = reinterpret_cast<COptionsConfig *>(param);
  6668. LPARAM changeMask = 0;
  6669. // tell the property page to do whatever now that we are back on the
  6670. // main thread
  6671. pOptCfg->OnPropertyChange(TRUE, &changeMask);
  6672. pOptCfg->AcknowledgeNotify();
  6673. if (changeMask)
  6674. spNode->ChangeNode(changeMask);
  6675. return hrOK;
  6676. }
  6677. /*---------------------------------------------------------------------------
  6678. CDhcpScopeOptions::CompareItems
  6679. Description
  6680. Author: EricDav
  6681. ---------------------------------------------------------------------------*/
  6682. STDMETHODIMP_(int)
  6683. CDhcpScopeOptions::CompareItems
  6684. (
  6685. ITFSComponent * pComponent,
  6686. MMC_COOKIE cookieA,
  6687. MMC_COOKIE cookieB,
  6688. int nCol
  6689. )
  6690. {
  6691. SPITFSNode spNode1, spNode2;
  6692. m_spNodeMgr->FindNode(cookieA, &spNode1);
  6693. m_spNodeMgr->FindNode(cookieB, &spNode2);
  6694. int nCompare = 0;
  6695. CDhcpOptionItem *pOpt1 = GETHANDLER(CDhcpOptionItem, spNode1);
  6696. CDhcpOptionItem *pOpt2 = GETHANDLER(CDhcpOptionItem, spNode2);
  6697. switch (nCol)
  6698. {
  6699. case 0:
  6700. {
  6701. //
  6702. // Name compare - use the option #
  6703. //
  6704. LONG_PTR uImage1 = spNode1->GetData(TFS_DATA_IMAGEINDEX);
  6705. LONG_PTR uImage2 = spNode2->GetData(TFS_DATA_IMAGEINDEX);
  6706. nCompare = UtilGetOptionPriority((int) uImage1, (int) uImage2);
  6707. if (nCompare == 0)
  6708. {
  6709. DHCP_OPTION_ID id1 = pOpt1->GetOptionId();
  6710. DHCP_OPTION_ID id2 = pOpt2->GetOptionId();
  6711. if (id1 < id2)
  6712. nCompare = -1;
  6713. else
  6714. if (id1 > id2)
  6715. nCompare = 1;
  6716. }
  6717. }
  6718. break;
  6719. case 1:
  6720. {
  6721. // compare the vendor strings
  6722. CString str1, str2;
  6723. str1 = pOpt1->GetVendorDisplay();
  6724. str2 = pOpt2->GetVendorDisplay();
  6725. nCompare = str1.CompareNoCase(str2);
  6726. }
  6727. break;
  6728. case 3:
  6729. {
  6730. CString str1, str2;
  6731. str1 = pOpt1->GetClassName();
  6732. str2 = pOpt2->GetClassName();
  6733. nCompare = str1.CompareNoCase(str2);
  6734. }
  6735. break;
  6736. }
  6737. return nCompare;
  6738. }
  6739. /*!--------------------------------------------------------------------------
  6740. CDhcpScopeOptions::OnResultSelect
  6741. Update the verbs and the result pane message
  6742. Author: EricDav
  6743. ---------------------------------------------------------------------------*/
  6744. HRESULT CDhcpScopeOptions::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  6745. {
  6746. HRESULT hr = hrOK;
  6747. SPITFSNode spNode;
  6748. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  6749. CORg (pComponent->GetSelectedNode(&spNode));
  6750. UpdateResultMessage(spNode);
  6751. Error:
  6752. return hr;
  6753. }
  6754. /*---------------------------------------------------------------------------
  6755. CDhcpScopeOptions::OnResultDelete
  6756. This function is called when we are supposed to delete result
  6757. pane items. We build a list of selected items and then delete them.
  6758. Author: EricDav
  6759. ---------------------------------------------------------------------------*/
  6760. HRESULT
  6761. CDhcpScopeOptions::OnResultDelete
  6762. (
  6763. ITFSComponent * pComponent,
  6764. LPDATAOBJECT pDataObject,
  6765. MMC_COOKIE cookie,
  6766. LPARAM arg,
  6767. LPARAM param
  6768. )
  6769. {
  6770. HRESULT hr = hrOK;
  6771. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6772. // translate the cookie into a node pointer
  6773. SPITFSNode spScopeOpt, spSelectedNode;
  6774. m_spNodeMgr->FindNode(cookie, &spScopeOpt);
  6775. pComponent->GetSelectedNode(&spSelectedNode);
  6776. Assert(spSelectedNode == spScopeOpt);
  6777. if (spSelectedNode != spScopeOpt)
  6778. return hr;
  6779. // build the list of selected nodes
  6780. CTFSNodeList listNodesToDelete;
  6781. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  6782. //
  6783. // Confirm with the user
  6784. //
  6785. CString strMessage, strTemp;
  6786. int nNodes = (int)listNodesToDelete.GetCount();
  6787. if (nNodes > 1)
  6788. {
  6789. strTemp.Format(_T("%d"), nNodes);
  6790. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  6791. }
  6792. else
  6793. {
  6794. strMessage.LoadString(IDS_DELETE_ITEM);
  6795. }
  6796. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  6797. {
  6798. return NOERROR;
  6799. }
  6800. // check to make sure we are deleting just scope options
  6801. POSITION pos = listNodesToDelete.GetHeadPosition();
  6802. while (pos)
  6803. {
  6804. ITFSNode * pNode = listNodesToDelete.GetNext(pos);
  6805. if (pNode->GetData(TFS_DATA_IMAGEINDEX) != ICON_IDX_SCOPE_OPTION_LEAF)
  6806. {
  6807. // this option is not scope option. Put up a dialog telling the user what to do
  6808. AfxMessageBox(IDS_CANNOT_DELETE_OPTION_SCOPE);
  6809. return NOERROR;
  6810. }
  6811. }
  6812. CString strServer = GetServerIpAddress(spScopeOpt);
  6813. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  6814. dhcpOptionScopeInfo.ScopeType = DhcpSubnetOptions;
  6815. dhcpOptionScopeInfo.ScopeInfo.SubnetScopeInfo = GetScopeObject(spScopeOpt)->GetAddress();
  6816. //
  6817. // Loop through all items deleting
  6818. //
  6819. BEGIN_WAIT_CURSOR;
  6820. while (listNodesToDelete.GetCount() > 0)
  6821. {
  6822. SPITFSNode spOptionNode;
  6823. spOptionNode = listNodesToDelete.RemoveHead();
  6824. CDhcpOptionItem * pOptItem = GETHANDLER(CDhcpOptionItem, spOptionNode);
  6825. //
  6826. // Try to remove it from the server
  6827. //
  6828. DWORD dwError;
  6829. if (pOptItem->IsVendorOption() ||
  6830. pOptItem->IsClassOption())
  6831. {
  6832. LPCTSTR pClassName = pOptItem->GetClassName();
  6833. if (lstrlen(pClassName) == 0)
  6834. pClassName = NULL;
  6835. dwError = ::DhcpRemoveOptionValueV5((LPTSTR) ((LPCTSTR) strServer),
  6836. pOptItem->IsVendorOption() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  6837. pOptItem->GetOptionId(),
  6838. (LPTSTR) pClassName,
  6839. (LPTSTR) pOptItem->GetVendor(),
  6840. &dhcpOptionScopeInfo);
  6841. }
  6842. else
  6843. {
  6844. dwError = ::DhcpRemoveOptionValue(strServer,
  6845. pOptItem->GetOptionId(),
  6846. &dhcpOptionScopeInfo);
  6847. }
  6848. if (dwError != 0)
  6849. {
  6850. ::DhcpMessageBox(dwError);
  6851. RESTORE_WAIT_CURSOR;
  6852. hr = E_FAIL;
  6853. continue;
  6854. }
  6855. //
  6856. // remove from our internal list
  6857. //
  6858. GetScopeObject(spScopeOpt)->GetOptionValueEnum()->Remove(pOptItem->GetOptionId(), pOptItem->GetVendor(), pOptItem->GetClassName());
  6859. //
  6860. // Remove from UI now
  6861. //
  6862. spScopeOpt->RemoveChild(spOptionNode);
  6863. spOptionNode.Release();
  6864. }
  6865. END_WAIT_CURSOR;
  6866. UpdateResultMessage(spScopeOpt);
  6867. return hr;
  6868. }
  6869. /*!--------------------------------------------------------------------------
  6870. CDhcpScopeOptions::OnHaveData
  6871. Description
  6872. Author: EricDav
  6873. ---------------------------------------------------------------------------*/
  6874. void
  6875. CDhcpScopeOptions::OnHaveData
  6876. (
  6877. ITFSNode * pParentNode,
  6878. LPARAM Data,
  6879. LPARAM Type
  6880. )
  6881. {
  6882. // This is how we get non-node data back from the background thread.
  6883. switch (Type)
  6884. {
  6885. case DHCP_QDATA_OPTION_VALUES:
  6886. {
  6887. HRESULT hr = hrOK;
  6888. SPIComponentData spCompData;
  6889. SPIConsole spConsole;
  6890. SPIDataObject spDataObject;
  6891. IDataObject * pDataObject;
  6892. CDhcpScope * pScope = GetScopeObject(pParentNode);
  6893. COptionValueEnum * pOptionValueEnum = reinterpret_cast<COptionValueEnum *>(Data);
  6894. pScope->SetOptionValueEnum(pOptionValueEnum);
  6895. pOptionValueEnum->RemoveAll();
  6896. delete pOptionValueEnum;
  6897. // now tell the view to update themselves
  6898. m_spNodeMgr->GetComponentData(&spCompData);
  6899. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pParentNode, CCT_SCOPE, &pDataObject) );
  6900. spDataObject = pDataObject;
  6901. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  6902. CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM) pParentNode, DHCPSNAP_UPDATE_OPTIONS) );
  6903. break;
  6904. }
  6905. }
  6906. Error:
  6907. return;
  6908. }
  6909. /*!--------------------------------------------------------------------------
  6910. CDhcpScopeOptions::OnResultUpdateView
  6911. Implementation of ITFSResultHandler::OnResultUpdateView
  6912. Author: EricDav
  6913. ---------------------------------------------------------------------------*/
  6914. HRESULT CDhcpScopeOptions::OnResultUpdateView
  6915. (
  6916. ITFSComponent *pComponent,
  6917. LPDATAOBJECT pDataObject,
  6918. LPARAM data,
  6919. LPARAM hint
  6920. )
  6921. {
  6922. HRESULT hr = hrOK;
  6923. SPITFSNode spSelectedNode;
  6924. pComponent->GetSelectedNode(&spSelectedNode);
  6925. if (spSelectedNode == NULL)
  6926. return S_OK; // no selection for our IComponentData
  6927. if ( hint == DHCPSNAP_UPDATE_OPTIONS )
  6928. {
  6929. SPINTERNAL spInternal = ExtractInternalFormat(pDataObject);
  6930. ITFSNode * pNode = reinterpret_cast<ITFSNode *>(spInternal->m_cookie);
  6931. SPITFSNode spSelectedNode;
  6932. pComponent->GetSelectedNode(&spSelectedNode);
  6933. EnumerateResultPane(pComponent, (MMC_COOKIE) spSelectedNode.p, 0, 0);
  6934. }
  6935. else
  6936. {
  6937. // we don't handle this message, let the base class do it.
  6938. return CMTDhcpHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  6939. }
  6940. return hr;
  6941. }
  6942. /*!--------------------------------------------------------------------------
  6943. CDhcpScopeOptions::OnGetResultViewType
  6944. MMC calls this to get the result view information
  6945. Author: EricDav
  6946. ---------------------------------------------------------------------------*/
  6947. HRESULT
  6948. CDhcpScopeOptions::OnGetResultViewType
  6949. (
  6950. ITFSComponent * pComponent,
  6951. MMC_COOKIE cookie,
  6952. LPOLESTR * ppViewType,
  6953. long * pViewOptions
  6954. )
  6955. {
  6956. HRESULT hr = hrOK;
  6957. // call the base class to see if it is handling this
  6958. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  6959. {
  6960. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  6961. hr = S_FALSE;
  6962. }
  6963. return hr;
  6964. }
  6965. /*!--------------------------------------------------------------------------
  6966. CDhcpScopeOptions::UpdateResultMessage
  6967. Figures out what message to put in the result pane, if any
  6968. Author: EricDav
  6969. ---------------------------------------------------------------------------*/
  6970. void CDhcpScopeOptions::UpdateResultMessage(ITFSNode * pNode)
  6971. {
  6972. HRESULT hr = hrOK;
  6973. int nMessage = -1; // default
  6974. int nVisible, nTotal;
  6975. int i;
  6976. CString strTitle, strBody, strTemp;
  6977. if (!m_dwErr)
  6978. {
  6979. pNode->GetChildCount(&nVisible, &nTotal);
  6980. // determine what message to display
  6981. if ( (m_nState == notLoaded) ||
  6982. (m_nState == loading) )
  6983. {
  6984. nMessage = -1;
  6985. }
  6986. else
  6987. if (nTotal == 0)
  6988. {
  6989. nMessage = SCOPE_OPTIONS_MESSAGE_NO_OPTIONS;
  6990. }
  6991. // build the strings
  6992. if (nMessage != -1)
  6993. {
  6994. // now build the text strings
  6995. // first entry is the title
  6996. strTitle.LoadString(g_uScopeOptionsMessages[nMessage][0]);
  6997. // second entry is the icon
  6998. // third ... n entries are the body strings
  6999. for (i = 2; g_uScopeOptionsMessages[nMessage][i] != 0; i++)
  7000. {
  7001. strTemp.LoadString(g_uScopeOptionsMessages[nMessage][i]);
  7002. strBody += strTemp;
  7003. }
  7004. }
  7005. }
  7006. // show the message
  7007. if (nMessage == -1)
  7008. {
  7009. ClearMessage(pNode);
  7010. }
  7011. else
  7012. {
  7013. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uScopeOptionsMessages[nMessage][1]);
  7014. }
  7015. }
  7016. /*!--------------------------------------------------------------------------
  7017. CDhcpScopeOptions::EnumerateResultPane
  7018. We override this function for the options nodes for one reason.
  7019. Whenever an option class is deleted, then all options defined for
  7020. that class will be removed as well. Since there are multiple places
  7021. that these options may show up, it's easier to just not show any
  7022. options that don't have a class defined for it.
  7023. Author: EricDav
  7024. ---------------------------------------------------------------------------*/
  7025. HRESULT
  7026. CDhcpScopeOptions::EnumerateResultPane
  7027. (
  7028. ITFSComponent * pComponent,
  7029. MMC_COOKIE cookie,
  7030. LPARAM arg,
  7031. LPARAM lParam
  7032. )
  7033. {
  7034. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  7035. CClassInfoArray ClassInfoArray;
  7036. SPITFSNode spContainer, spServerNode;
  7037. CDhcpServer * pServer;
  7038. COptionValueEnum * aEnum[2];
  7039. int aImages[2] = {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF};
  7040. m_spNodeMgr->FindNode(cookie, &spContainer);
  7041. spServerNode = GetServerNode(spContainer);
  7042. pServer = GETHANDLER(CDhcpServer, spServerNode);
  7043. pServer->GetClassInfoArray(ClassInfoArray);
  7044. aEnum[0] = GetScopeObject(spContainer)->GetOptionValueEnum();
  7045. aEnum[1] = pServer->GetOptionValueEnum();
  7046. aEnum[0]->Reset();
  7047. aEnum[1]->Reset();
  7048. return OnResultUpdateOptions(pComponent, spContainer, &ClassInfoArray, aEnum, aImages, 2);
  7049. }
  7050. /*---------------------------------------------------------------------------
  7051. Command handlers
  7052. ---------------------------------------------------------------------------*/
  7053. HRESULT
  7054. CDhcpScopeOptions::OnCreateNewOptions
  7055. (
  7056. ITFSNode * pNode
  7057. )
  7058. {
  7059. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  7060. CPropertyPageHolderBase * pPropSheet;
  7061. HRESULT hr = hrOK;
  7062. COM_PROTECT_TRY
  7063. {
  7064. if (HasPropSheetsOpen())
  7065. {
  7066. GetOpenPropSheet(0, &pPropSheet);
  7067. pPropSheet->SetActiveWindow();
  7068. }
  7069. else
  7070. {
  7071. CString strOptCfgTitle, strOptType;
  7072. SPIComponentData spComponentData;
  7073. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_SCOPE);
  7074. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  7075. m_spNodeMgr->GetComponentData(&spComponentData);
  7076. hr = DoPropertiesOurselvesSinceMMCSucks(pNode, spComponentData, strOptCfgTitle);
  7077. }
  7078. }
  7079. COM_PROTECT_CATCH
  7080. return hr;
  7081. }
  7082. /*---------------------------------------------------------------------------
  7083. Background thread functionality
  7084. ---------------------------------------------------------------------------*/
  7085. /*---------------------------------------------------------------------------
  7086. CDhcpScopeOptions::OnCreateQuery()
  7087. Description
  7088. Author: EricDav
  7089. ---------------------------------------------------------------------------*/
  7090. ITFSQueryObject*
  7091. CDhcpScopeOptions::OnCreateQuery(ITFSNode * pNode)
  7092. {
  7093. CDhcpScopeOptionsQueryObj* pQuery =
  7094. new CDhcpScopeOptionsQueryObj(m_spTFSCompData, m_spNodeMgr);
  7095. pQuery->m_strServer = GetServerIpAddress(pNode);
  7096. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  7097. pQuery->m_dhcpResumeHandle = NULL;
  7098. pQuery->m_dwPreferredMax = 0xFFFFFFFF;
  7099. GetScopeObject(pNode)->GetDynBootpClassName(pQuery->m_strDynBootpClassName);
  7100. GetScopeObject(pNode)->GetServerVersion(pQuery->m_liDhcpVersion);
  7101. return pQuery;
  7102. }
  7103. /*---------------------------------------------------------------------------
  7104. CDhcpScopeOptionsQueryObj::Execute()
  7105. Description
  7106. Author: EricDav
  7107. ---------------------------------------------------------------------------*/
  7108. STDMETHODIMP
  7109. CDhcpScopeOptionsQueryObj::Execute()
  7110. {
  7111. DWORD dwErr;
  7112. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  7113. COptionValueEnum * pOptionValueEnum;
  7114. pOptionValueEnum = new COptionValueEnum();
  7115. pOptionValueEnum->m_strDynBootpClassName = m_strDynBootpClassName;
  7116. dhcpOptionScopeInfo.ScopeType = DhcpSubnetOptions;
  7117. dhcpOptionScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpScopeAddress;
  7118. pOptionValueEnum->Init(m_strServer, m_liDhcpVersion, dhcpOptionScopeInfo);
  7119. dwErr = pOptionValueEnum->Enum();
  7120. if (dwErr != ERROR_SUCCESS)
  7121. {
  7122. Trace1("CDhcpScopeOptionsQueryObj::Execute - Enum Failed! %d\n", dwErr);
  7123. m_dwErr = dwErr;
  7124. PostError(dwErr);
  7125. delete pOptionValueEnum;
  7126. }
  7127. else
  7128. {
  7129. pOptionValueEnum->SortById();
  7130. AddToQueue((LPARAM) pOptionValueEnum, DHCP_QDATA_OPTION_VALUES);
  7131. }
  7132. return hrFalse;
  7133. }
  7134. /*!--------------------------------------------------------------------------
  7135. CDhcpScopeOptions::OnNotifyExiting
  7136. CMTDhcpHandler overridden functionality
  7137. allows us to know when the background thread is done
  7138. Author: EricDav
  7139. ---------------------------------------------------------------------------*/
  7140. STDMETHODIMP
  7141. CDhcpScopeOptions::OnNotifyExiting
  7142. (
  7143. LPARAM lParam
  7144. )
  7145. {
  7146. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  7147. SPITFSNode spNode;
  7148. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  7149. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  7150. UpdateResultMessage(spNode);
  7151. return hr;
  7152. }
  7153. //
  7154. //
  7155. // qsort comparison routine to compare the ip addresses.
  7156. //
  7157. //
  7158. int __cdecl QCompare( const void *ip1, const void *ip2 )
  7159. {
  7160. DWORD *lip1, *lip2;
  7161. if ( ip1 && ip2 )
  7162. {
  7163. lip1 = (DWORD *)ip1;
  7164. lip2 = (DWORD *)ip2;
  7165. if ( *lip1 < *lip2 )
  7166. {
  7167. return -1;
  7168. }
  7169. else if ( *lip1 > *lip2 )
  7170. {
  7171. return 1;
  7172. }
  7173. else
  7174. {
  7175. return 0;
  7176. }
  7177. }
  7178. return 0;
  7179. }