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

8613 lines
299 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. 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_spReservations )
  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_spActiveLeases)
  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_spOptions)
  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. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  2716. DWORD dwElementsRead = 0, dwElementsTotal = 0, dwTotalRead = 0;
  2717. DWORD dwError = ERROR_MORE_DATA;
  2718. DWORD dwResvThreshold = 100;
  2719. m_resvMap.RemoveAll();
  2720. m_subnetElements = NULL;
  2721. while (dwError == ERROR_MORE_DATA)
  2722. {
  2723. dwError = ::DhcpEnumSubnetElementsV4(((LPWSTR) (LPCTSTR)m_strServer),
  2724. m_dhcpScopeAddress,
  2725. DhcpReservedIps,
  2726. &dhcpResumeHandle,
  2727. -1,
  2728. &m_subnetElements,
  2729. &dwElementsRead,
  2730. &dwElementsTotal);
  2731. Trace3("BuildReservationList: Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal );
  2732. //
  2733. // If number of reservations is less than 100 handle it the old way
  2734. //
  2735. if ( dwElementsTotal <= dwResvThreshold )
  2736. {
  2737. m_totalResvs = dwElementsTotal;
  2738. return( FALSE );
  2739. }
  2740. if (dwElementsRead && dwElementsTotal && m_subnetElements )
  2741. {
  2742. //
  2743. // Loop through the array that was returned
  2744. //
  2745. for (DWORD i = 0; i < m_subnetElements->NumElements; i++)
  2746. {
  2747. m_resvMap.SetAt( m_subnetElements->Elements[i].Element.ReservedIp->ReservedIpAddress,
  2748. &m_subnetElements->Elements[ i ]);
  2749. }
  2750. dwTotalRead += dwElementsRead;
  2751. if ( dwTotalRead <= dwElementsTotal )
  2752. {
  2753. m_totalResvs = dwTotalRead;
  2754. }
  2755. else
  2756. {
  2757. m_totalResvs = dwElementsTotal;
  2758. }
  2759. }
  2760. } // while
  2761. return( TRUE );
  2762. }
  2763. CDhcpReservations::~CDhcpReservations()
  2764. {
  2765. }
  2766. /*!--------------------------------------------------------------------------
  2767. CDhcpReservations::InitializeNode
  2768. Initializes node specific data
  2769. Author: EricDav
  2770. ---------------------------------------------------------------------------*/
  2771. HRESULT
  2772. CDhcpReservations::InitializeNode
  2773. (
  2774. ITFSNode * pNode
  2775. )
  2776. {
  2777. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  2778. HRESULT hr = hrOK;
  2779. //
  2780. // Create the display name for this scope
  2781. //
  2782. CString strTemp;
  2783. strTemp.LoadString(IDS_RESERVATIONS_FOLDER);
  2784. SetDisplayName(strTemp);
  2785. // Make the node immediately visible
  2786. pNode->SetVisibilityState(TFS_VIS_SHOW);
  2787. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  2788. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  2789. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  2790. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  2791. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_RESERVATIONS);
  2792. SetColumnStringIDs(&aColumns[DHCPSNAP_RESERVATIONS][0]);
  2793. SetColumnWidths(&aColumnWidths[DHCPSNAP_RESERVATIONS][0]);
  2794. return hr;
  2795. }
  2796. /*---------------------------------------------------------------------------
  2797. CDhcpReservations::OnCreateNodeId2
  2798. Returns a unique string for this node
  2799. Author: EricDav
  2800. ---------------------------------------------------------------------------*/
  2801. HRESULT CDhcpReservations::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  2802. {
  2803. const GUID * pGuid = pNode->GetNodeType();
  2804. CString strIpAddress, strGuid;
  2805. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  2806. strGuid.ReleaseBuffer();
  2807. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  2808. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  2809. strId = GetServerName(pNode) + strIpAddress + strGuid;
  2810. return hrOK;
  2811. }
  2812. /*---------------------------------------------------------------------------
  2813. CDhcpReservations::GetImageIndex
  2814. Description
  2815. Author: EricDav
  2816. ---------------------------------------------------------------------------*/
  2817. int
  2818. CDhcpReservations::GetImageIndex(BOOL bOpenImage)
  2819. {
  2820. int nIndex = -1;
  2821. switch (m_nState)
  2822. {
  2823. case notLoaded:
  2824. case loaded:
  2825. if (bOpenImage)
  2826. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN;
  2827. else
  2828. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED;
  2829. break;
  2830. case loading:
  2831. if (bOpenImage)
  2832. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN_BUSY;
  2833. else
  2834. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED_BUSY;
  2835. break;
  2836. case unableToLoad:
  2837. if (bOpenImage)
  2838. nIndex = ICON_IDX_RESERVATIONS_FOLDER_OPEN_LOST_CONNECTION;
  2839. else
  2840. nIndex = ICON_IDX_RESERVATIONS_FOLDER_CLOSED_LOST_CONNECTION;
  2841. break;
  2842. default:
  2843. ASSERT(FALSE);
  2844. }
  2845. return nIndex;
  2846. }
  2847. /*!--------------------------------------------------------------------------
  2848. CDhcpReservations::RemoveReservationFromUI
  2849. Initializes node specific data
  2850. Author: EricDav
  2851. ---------------------------------------------------------------------------*/
  2852. DWORD
  2853. CDhcpReservations::RemoveReservationFromUI
  2854. (
  2855. ITFSNode * pReservationsNode,
  2856. DHCP_IP_ADDRESS dhcpReservationIp
  2857. )
  2858. {
  2859. DWORD dwError = E_UNEXPECTED;
  2860. CDhcpReservationClient * pReservationClient = NULL;
  2861. SPITFSNodeEnum spNodeEnum;
  2862. SPITFSNode spCurrentNode;
  2863. ULONG nNumReturned = 0;
  2864. pReservationsNode->GetEnum(&spNodeEnum);
  2865. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  2866. while (nNumReturned)
  2867. {
  2868. pReservationClient = GETHANDLER(CDhcpReservationClient, spCurrentNode);
  2869. if (dhcpReservationIp == pReservationClient->GetIpAddress())
  2870. {
  2871. //
  2872. // Tell this reservation to delete itself
  2873. //
  2874. pReservationsNode->RemoveChild(spCurrentNode);
  2875. spCurrentNode.Release();
  2876. dwError = ERROR_SUCCESS;
  2877. break;
  2878. }
  2879. spCurrentNode.Release();
  2880. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  2881. }
  2882. return dwError;
  2883. }
  2884. /*---------------------------------------------------------------------------
  2885. Overridden base handler functions
  2886. ---------------------------------------------------------------------------*/
  2887. /*---------------------------------------------------------------------------
  2888. CDhcpReservations::OnAddMenuItems
  2889. Adds entries to the context sensitive menu
  2890. Author: EricDav
  2891. ---------------------------------------------------------------------------*/
  2892. STDMETHODIMP
  2893. CDhcpReservations::OnAddMenuItems
  2894. (
  2895. ITFSNode * pNode,
  2896. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  2897. LPDATAOBJECT lpDataObject,
  2898. DATA_OBJECT_TYPES type,
  2899. DWORD dwType,
  2900. long * pInsertionAllowed
  2901. )
  2902. {
  2903. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  2904. LONG fFlags = 0;
  2905. HRESULT hr = S_OK;
  2906. CString strMenuText;
  2907. if ( (m_nState != loaded) )
  2908. {
  2909. fFlags |= MF_GRAYED;
  2910. }
  2911. if (type == CCT_SCOPE)
  2912. {
  2913. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  2914. {
  2915. // these menu items go in the new menu,
  2916. // only visible from scope pane
  2917. strMenuText.LoadString(IDS_CREATE_NEW_RESERVATION);
  2918. hr = LoadAndAddMenuItem( pContextMenuCallback,
  2919. strMenuText,
  2920. IDS_CREATE_NEW_RESERVATION,
  2921. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  2922. fFlags );
  2923. ASSERT( SUCCEEDED(hr) );
  2924. }
  2925. }
  2926. return hr;
  2927. }
  2928. /*---------------------------------------------------------------------------
  2929. CDhcpReservations::OnCommand
  2930. Description
  2931. Author: EricDav
  2932. ---------------------------------------------------------------------------*/
  2933. STDMETHODIMP
  2934. CDhcpReservations::OnCommand
  2935. (
  2936. ITFSNode * pNode,
  2937. long nCommandId,
  2938. DATA_OBJECT_TYPES type,
  2939. LPDATAOBJECT pDataObject,
  2940. DWORD dwType
  2941. )
  2942. {
  2943. HRESULT hr = S_OK;
  2944. switch (nCommandId)
  2945. {
  2946. case IDS_CREATE_NEW_RESERVATION:
  2947. OnCreateNewReservation(pNode);
  2948. break;
  2949. case IDS_REFRESH:
  2950. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  2951. break;
  2952. default:
  2953. break;
  2954. }
  2955. return hr;
  2956. }
  2957. /*---------------------------------------------------------------------------
  2958. CDhcpReservations::CompareItems
  2959. Description
  2960. Author: EricDav
  2961. ---------------------------------------------------------------------------*/
  2962. STDMETHODIMP_(int)
  2963. CDhcpReservations::CompareItems
  2964. (
  2965. ITFSComponent * pComponent,
  2966. MMC_COOKIE cookieA,
  2967. MMC_COOKIE cookieB,
  2968. int nCol
  2969. )
  2970. {
  2971. SPITFSNode spNode1, spNode2;
  2972. m_spNodeMgr->FindNode(cookieA, &spNode1);
  2973. m_spNodeMgr->FindNode(cookieB, &spNode2);
  2974. int nCompare = 0;
  2975. CDhcpReservationClient *pDhcpRC1 = GETHANDLER(CDhcpReservationClient, spNode1);
  2976. CDhcpReservationClient *pDhcpRC2 = GETHANDLER(CDhcpReservationClient, spNode2);
  2977. switch (nCol)
  2978. {
  2979. case 0:
  2980. {
  2981. // IP address compare
  2982. //
  2983. DHCP_IP_ADDRESS dhcpIp1 = pDhcpRC1->GetIpAddress();
  2984. DHCP_IP_ADDRESS dhcpIp2 = pDhcpRC2->GetIpAddress();
  2985. if (dhcpIp1 < dhcpIp2)
  2986. nCompare = -1;
  2987. else
  2988. if (dhcpIp1 > dhcpIp2)
  2989. nCompare = 1;
  2990. // default is that they are equal
  2991. }
  2992. break;
  2993. }
  2994. return nCompare;
  2995. }
  2996. /*!--------------------------------------------------------------------------
  2997. CDhcpReservations::OnGetResultViewType
  2998. MMC calls this to get the result view information
  2999. Author: EricDav
  3000. ---------------------------------------------------------------------------*/
  3001. HRESULT
  3002. CDhcpReservations::OnGetResultViewType
  3003. (
  3004. ITFSComponent * pComponent,
  3005. MMC_COOKIE cookie,
  3006. LPOLESTR * ppViewType,
  3007. long * pViewOptions
  3008. )
  3009. {
  3010. HRESULT hr = hrOK;
  3011. // call the base class to see if it is handling this
  3012. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  3013. {
  3014. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  3015. hr = S_FALSE;
  3016. }
  3017. return hr;
  3018. }
  3019. /*!--------------------------------------------------------------------------
  3020. CDhcpReservations::OnResultSelect
  3021. Update the verbs and the result pane message
  3022. Author: EricDav
  3023. ---------------------------------------------------------------------------*/
  3024. HRESULT CDhcpReservations::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  3025. {
  3026. HRESULT hr = hrOK;
  3027. SPITFSNode spNode;
  3028. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  3029. CORg (pComponent->GetSelectedNode(&spNode));
  3030. if ( spNode != 0 ) {
  3031. UpdateResultMessage(spNode);
  3032. }
  3033. Error:
  3034. return hr;
  3035. }
  3036. /*!--------------------------------------------------------------------------
  3037. CDhcpReservations::UpdateResultMessage
  3038. Figures out what message to put in the result pane, if any
  3039. Author: EricDav
  3040. ---------------------------------------------------------------------------*/
  3041. void CDhcpReservations::UpdateResultMessage(ITFSNode * pNode)
  3042. {
  3043. HRESULT hr = hrOK;
  3044. int nMessage = -1; // default
  3045. int nVisible, nTotal;
  3046. int i;
  3047. CString strTitle, strBody, strTemp;
  3048. if (!m_dwErr)
  3049. {
  3050. pNode->GetChildCount(&nVisible, &nTotal);
  3051. // determine what message to display
  3052. if ( (m_nState == notLoaded) ||
  3053. (m_nState == loading) )
  3054. {
  3055. nMessage = -1;
  3056. }
  3057. else
  3058. if (nTotal == 0)
  3059. {
  3060. nMessage = RESERVATIONS_MESSAGE_NO_RES;
  3061. }
  3062. // build the strings
  3063. if (nMessage != -1)
  3064. {
  3065. // now build the text strings
  3066. // first entry is the title
  3067. strTitle.LoadString(g_uReservationsMessages[nMessage][0]);
  3068. // second entry is the icon
  3069. // third ... n entries are the body strings
  3070. for (i = 2; g_uReservationsMessages[nMessage][i] != 0; i++)
  3071. {
  3072. strTemp.LoadString(g_uReservationsMessages[nMessage][i]);
  3073. strBody += strTemp;
  3074. }
  3075. }
  3076. }
  3077. // show the message
  3078. if (nMessage == -1)
  3079. {
  3080. ClearMessage(pNode);
  3081. }
  3082. else
  3083. {
  3084. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uReservationsMessages[nMessage][1]);
  3085. }
  3086. }
  3087. /*---------------------------------------------------------------------------
  3088. Message handlers
  3089. ---------------------------------------------------------------------------*/
  3090. /*---------------------------------------------------------------------------
  3091. CDhcpReservations::OnCreateNewReservation
  3092. Description
  3093. Author: EricDav
  3094. ---------------------------------------------------------------------------*/
  3095. DWORD
  3096. CDhcpReservations::OnCreateNewReservation
  3097. (
  3098. ITFSNode * pNode
  3099. )
  3100. {
  3101. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3102. SPITFSNode spScopeNode;
  3103. pNode->GetParent(&spScopeNode);
  3104. CDhcpScope * pScope = GETHANDLER(CDhcpScope, spScopeNode);
  3105. LARGE_INTEGER liVersion;
  3106. pScope->GetServerVersion(liVersion);
  3107. CAddReservation dlgAddReservation(spScopeNode, liVersion);
  3108. dlgAddReservation.DoModal();
  3109. GetScopeObject(pNode)->TriggerStatsRefresh();
  3110. UpdateResultMessage(pNode);
  3111. return 0;
  3112. }
  3113. /*---------------------------------------------------------------------------
  3114. Background thread functionality
  3115. ---------------------------------------------------------------------------*/
  3116. /*---------------------------------------------------------------------------
  3117. CDhcpReservations::OnHaveData
  3118. Description
  3119. Author: EricDav
  3120. ---------------------------------------------------------------------------*/
  3121. void
  3122. CDhcpReservations::OnHaveData
  3123. (
  3124. ITFSNode * pParentNode,
  3125. ITFSNode * pNewNode
  3126. )
  3127. {
  3128. AddReservationSorted(pParentNode, pNewNode);
  3129. // update the view
  3130. ExpandNode(pParentNode, TRUE);
  3131. }
  3132. /*---------------------------------------------------------------------------
  3133. CDhcpReservations::AddReservationSorted
  3134. Adding reservation after sorting it by comparing against the resvname
  3135. takes too much time.
  3136. Adds a scope node to the UI sorted
  3137. Author: EricDav
  3138. ---------------------------------------------------------------------------*/
  3139. HRESULT
  3140. CDhcpReservations::AddReservationSorted
  3141. (
  3142. ITFSNode * pReservationsNode,
  3143. ITFSNode * pResClientNode
  3144. )
  3145. {
  3146. HRESULT hr = hrOK;
  3147. SPITFSNodeEnum spNodeEnum;
  3148. SPITFSNode spCurrentNode;
  3149. SPITFSNode spPrevNode;
  3150. ULONG nNumReturned = 0;
  3151. CDhcpReservationClient * pResClient;
  3152. // get our target address
  3153. pResClient = GETHANDLER(CDhcpReservationClient, pResClientNode);
  3154. // get the enumerator for this node
  3155. CORg(pReservationsNode->GetEnum(&spNodeEnum));
  3156. CORg(spNodeEnum->Next(1, &spCurrentNode, &nNumReturned));
  3157. while (nNumReturned)
  3158. {
  3159. pResClient = GETHANDLER(CDhcpReservationClient, spCurrentNode);
  3160. // get the next node in the list
  3161. spPrevNode.Set(spCurrentNode);
  3162. spCurrentNode.Release();
  3163. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  3164. }
  3165. // Add the node in based on the PrevNode pointer
  3166. if (spPrevNode)
  3167. {
  3168. if (m_bExpanded)
  3169. {
  3170. pResClientNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_PREVIOUS);
  3171. pResClientNode->SetData(TFS_DATA_RELATIVE_SCOPEID, spPrevNode->GetData(TFS_DATA_SCOPEID));
  3172. }
  3173. CORg(pReservationsNode->InsertChild(spPrevNode, pResClientNode));
  3174. }
  3175. else
  3176. {
  3177. // add to the head
  3178. if (m_bExpanded)
  3179. {
  3180. pResClientNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_FIRST);
  3181. }
  3182. CORg(pReservationsNode->AddChild(pResClientNode));
  3183. }
  3184. Error:
  3185. return hr;
  3186. }
  3187. /*---------------------------------------------------------------------------
  3188. CDhcpReservations::OnCreateQuery()
  3189. Description
  3190. Author: EricDav
  3191. ---------------------------------------------------------------------------*/
  3192. ITFSQueryObject*
  3193. CDhcpReservations::OnCreateQuery(ITFSNode * pNode)
  3194. {
  3195. CDhcpReservationsQueryObj* pQuery =
  3196. new CDhcpReservationsQueryObj(m_spTFSCompData, m_spNodeMgr);
  3197. pQuery->m_strServer = GetServerIpAddress(pNode);
  3198. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  3199. pQuery->m_dhcpResumeHandle = NULL;
  3200. pQuery->m_dwPreferredMax = 2000;
  3201. pQuery->m_resvMap.RemoveAll();
  3202. pQuery->m_totalResvs = 0;
  3203. pQuery->m_subnetElements = NULL;
  3204. GetScopeObject(pNode)->GetServerVersion(pQuery->m_liVersion);
  3205. return pQuery;
  3206. }
  3207. /*---------------------------------------------------------------------------
  3208. CDhcpReservationsQueryObj::Execute()
  3209. Description
  3210. Author: EricDav
  3211. ---------------------------------------------------------------------------*/
  3212. STDMETHODIMP
  3213. CDhcpReservationsQueryObj::Execute()
  3214. {
  3215. HRESULT hr = hrOK;
  3216. if (m_liVersion.QuadPart >= DHCP_SP2_VERSION)
  3217. {
  3218. if ( AddReservedIPsToArray( ) )
  3219. {
  3220. //
  3221. //
  3222. // this should handle the case where there are a large # of resvs.
  3223. //
  3224. //
  3225. hr = EnumerateReservationsV4();
  3226. }
  3227. else
  3228. {
  3229. //
  3230. // a typical corporation doesnt have more than 100 resvs
  3231. // handle it here
  3232. //
  3233. hr = EnumerateReservationsForLessResvsV4( );
  3234. }
  3235. }
  3236. else
  3237. {
  3238. hr = EnumerateReservations();
  3239. }
  3240. return hr;
  3241. }
  3242. HRESULT
  3243. CDhcpReservationsQueryObj::EnumerateReservationsForLessResvsV4( )
  3244. {
  3245. DWORD dwError = ERROR_MORE_DATA;
  3246. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 pdhcpSubnetElementArray = NULL;
  3247. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  3248. HRESULT hr = hrOK;
  3249. while (dwError == ERROR_MORE_DATA)
  3250. {
  3251. dwError = ::DhcpEnumSubnetElementsV4(((LPWSTR) (LPCTSTR)m_strServer),
  3252. m_dhcpScopeAddress,
  3253. DhcpReservedIps,
  3254. &m_dhcpResumeHandle,
  3255. m_dwPreferredMax,
  3256. &pdhcpSubnetElementArray,
  3257. &dwElementsRead,
  3258. &dwElementsTotal);
  3259. Trace3("Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  3260. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  3261. {
  3262. //
  3263. // Loop through the array that was returned
  3264. //
  3265. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  3266. {
  3267. //
  3268. // For each reservation, we need to get the client info
  3269. //
  3270. DWORD dwReturn;
  3271. LPDHCP_CLIENT_INFO_V4 pClientInfo = NULL;
  3272. DHCP_SEARCH_INFO dhcpSearchInfo;
  3273. dhcpSearchInfo.SearchType = DhcpClientIpAddress;
  3274. dhcpSearchInfo.SearchInfo.ClientIpAddress =
  3275. pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress;
  3276. dwReturn = ::DhcpGetClientInfoV4(m_strServer,
  3277. &dhcpSearchInfo,
  3278. &pClientInfo);
  3279. if (dwReturn == ERROR_SUCCESS)
  3280. {
  3281. //
  3282. // Create the result pane item for this element
  3283. //
  3284. SPITFSNode spNode;
  3285. CDhcpReservationClient * pDhcpReservationClient;
  3286. COM_PROTECT_TRY
  3287. {
  3288. pDhcpReservationClient =
  3289. new CDhcpReservationClient(m_spTFSCompData, pClientInfo);
  3290. // Tell the reservation what the client type is
  3291. pDhcpReservationClient->SetClientType(pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->bAllowedClientTypes);
  3292. CreateContainerTFSNode(&spNode,
  3293. &GUID_DhcpReservationClientNodeType,
  3294. pDhcpReservationClient,
  3295. pDhcpReservationClient,
  3296. m_spNodeMgr);
  3297. // Tell the handler to initialize any specific data
  3298. pDhcpReservationClient->InitializeNode(spNode);
  3299. AddToQueue(spNode);
  3300. pDhcpReservationClient->Release();
  3301. }
  3302. COM_PROTECT_CATCH
  3303. ::DhcpRpcFreeMemory(pClientInfo);
  3304. }
  3305. else
  3306. {
  3307. // REVIEW: ericdav - do we need to post the error back here?
  3308. Trace1("EnumReservationsV4 - GetClientInfoV4 failed! %d\n", dwReturn);
  3309. }
  3310. }
  3311. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  3312. pdhcpSubnetElementArray = NULL;
  3313. dwElementsRead = 0;
  3314. dwElementsTotal = 0;
  3315. }
  3316. // Check the abort flag on the thread
  3317. if (FCheckForAbort() == hrOK)
  3318. break;
  3319. // check to see if we have an error and post it to the main thread if we do..
  3320. if (dwError != ERROR_NO_MORE_ITEMS &&
  3321. dwError != ERROR_SUCCESS &&
  3322. dwError != ERROR_MORE_DATA)
  3323. {
  3324. Trace1("DHCP snapin: EnumerateReservationsV4 error: %d\n", dwError);
  3325. m_dwErr = dwError;
  3326. PostError(dwError);
  3327. }
  3328. }
  3329. return hrFalse;
  3330. }
  3331. /*---------------------------------------------------------------------------
  3332. CDhcpReservationsQueryObj::EnumerateReservationsV4()
  3333. Enumerates leases for NT4 SP2 and newer servers
  3334. Author: EricDav
  3335. ---------------------------------------------------------------------------*/
  3336. HRESULT
  3337. CDhcpReservationsQueryObj::EnumerateReservationsV4()
  3338. {
  3339. DWORD dwError = ERROR_MORE_DATA;
  3340. LPDHCP_CLIENT_INFO_ARRAY_V5 pdhcpClientArrayV5 = NULL;
  3341. LPDHCP_SUBNET_ELEMENT_DATA_V4 pSubnetData = NULL;
  3342. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  3343. DWORD dwResvsHandled = 0;
  3344. DWORD dwEnumedClients = 0;
  3345. DWORD dwResvThreshold = 1000;
  3346. DWORD i = 0;
  3347. DWORD k = 0;
  3348. DWORD *j = NULL;
  3349. HRESULT hr = hrOK;
  3350. while (dwError == ERROR_MORE_DATA)
  3351. {
  3352. dwError = ::DhcpEnumSubnetClientsV5(((LPWSTR) (LPCTSTR)m_strServer),
  3353. m_dhcpScopeAddress,
  3354. &m_dhcpResumeHandle,
  3355. -1,
  3356. &pdhcpClientArrayV5,
  3357. &dwClientsRead,
  3358. &dwClientsTotal);
  3359. if ( dwClientsRead && dwClientsTotal && pdhcpClientArrayV5 )
  3360. {
  3361. //
  3362. // we do a binary search for a reservation
  3363. // that is present in the table.
  3364. //
  3365. for( i = 0; i < dwClientsRead; i ++ )
  3366. {
  3367. //
  3368. // do binary search against each client that was read to see
  3369. // if it is a reservation.
  3370. //
  3371. k = pdhcpClientArrayV5 -> Clients[i] -> ClientIpAddress;
  3372. if ( m_resvMap.Lookup( k, pSubnetData ))
  3373. {
  3374. //
  3375. // Create the result pane item for this element
  3376. //
  3377. SPITFSNode spNode;
  3378. CDhcpReservationClient * pDhcpReservationClient;
  3379. COM_PROTECT_TRY
  3380. {
  3381. pDhcpReservationClient =
  3382. new CDhcpReservationClient( m_spTFSCompData, reinterpret_cast<LPDHCP_CLIENT_INFO_V4>(pdhcpClientArrayV5 -> Clients[ i ] ));
  3383. pDhcpReservationClient->SetClientType( pSubnetData->Element.ReservedIp->bAllowedClientTypes );
  3384. CreateContainerTFSNode(&spNode,
  3385. &GUID_DhcpReservationClientNodeType,
  3386. pDhcpReservationClient,
  3387. pDhcpReservationClient,
  3388. m_spNodeMgr);
  3389. //
  3390. // Tell the handler to initialize any specific data
  3391. //
  3392. pDhcpReservationClient->InitializeNode(spNode);
  3393. AddToQueue(spNode);
  3394. pDhcpReservationClient->Release();
  3395. }
  3396. COM_PROTECT_CATCH
  3397. } // end of if that adds a reservation
  3398. } // end of for
  3399. ::DhcpRpcFreeMemory(pdhcpClientArrayV5);
  3400. pdhcpClientArrayV5 = NULL;
  3401. dwEnumedClients += dwClientsRead;
  3402. dwClientsRead = 0;
  3403. dwClientsTotal = 0;
  3404. } // end of main if that checks if read succeeded.
  3405. // Check the abort flag on the thread
  3406. if (FCheckForAbort() == hrOK)
  3407. break;
  3408. // check to see if we have an error and post it to the main thread if we do..
  3409. if (dwError != ERROR_NO_MORE_ITEMS &&
  3410. dwError != ERROR_SUCCESS &&
  3411. dwError != ERROR_MORE_DATA)
  3412. {
  3413. Trace1("DHCP snapin: EnumerateReservationsV4 error: %d\n", dwError);
  3414. m_dwErr = dwError;
  3415. PostError(dwError);
  3416. }
  3417. }
  3418. DhcpRpcFreeMemory( m_subnetElements );
  3419. m_subnetElements = NULL;
  3420. m_totalResvs = 0;
  3421. m_resvMap.RemoveAll();
  3422. return hrFalse;
  3423. }
  3424. /*---------------------------------------------------------------------------
  3425. CDhcpReservationsQueryObj::Execute()
  3426. Enumerates reservations for pre NT4 SP2 servers
  3427. Author: EricDav
  3428. ---------------------------------------------------------------------------*/
  3429. HRESULT
  3430. CDhcpReservationsQueryObj::EnumerateReservations()
  3431. {
  3432. DWORD dwError = ERROR_MORE_DATA;
  3433. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  3434. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  3435. while (dwError == ERROR_MORE_DATA)
  3436. {
  3437. dwError = ::DhcpEnumSubnetElements(((LPWSTR) (LPCTSTR)m_strServer),
  3438. m_dhcpScopeAddress,
  3439. DhcpReservedIps,
  3440. &m_dhcpResumeHandle,
  3441. m_dwPreferredMax,
  3442. &pdhcpSubnetElementArray,
  3443. &dwElementsRead,
  3444. &dwElementsTotal);
  3445. Trace3("Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  3446. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  3447. {
  3448. //
  3449. // Loop through the array that was returned
  3450. //
  3451. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  3452. {
  3453. //
  3454. // For each reservation, we need to get the client info
  3455. //
  3456. DWORD dwReturn;
  3457. LPDHCP_CLIENT_INFO pClientInfo = NULL;
  3458. DHCP_SEARCH_INFO dhcpSearchInfo;
  3459. dhcpSearchInfo.SearchType = DhcpClientIpAddress;
  3460. dhcpSearchInfo.SearchInfo.ClientIpAddress =
  3461. pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress;
  3462. dwReturn = ::DhcpGetClientInfo(m_strServer,
  3463. &dhcpSearchInfo,
  3464. &pClientInfo);
  3465. if (dwReturn == ERROR_SUCCESS)
  3466. {
  3467. //
  3468. // Create the result pane item for this element
  3469. //
  3470. SPITFSNode spNode;
  3471. CDhcpReservationClient * pDhcpReservationClient;
  3472. pDhcpReservationClient =
  3473. new CDhcpReservationClient(m_spTFSCompData, reinterpret_cast<LPDHCP_CLIENT_INFO>(pClientInfo));
  3474. CreateContainerTFSNode(&spNode,
  3475. &GUID_DhcpReservationClientNodeType,
  3476. pDhcpReservationClient,
  3477. pDhcpReservationClient,
  3478. m_spNodeMgr);
  3479. // Tell the handler to initialize any specific data
  3480. pDhcpReservationClient->InitializeNode(spNode);
  3481. AddToQueue(spNode);
  3482. pDhcpReservationClient->Release();
  3483. ::DhcpRpcFreeMemory(pClientInfo);
  3484. }
  3485. }
  3486. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  3487. pdhcpSubnetElementArray = NULL;
  3488. dwElementsRead = 0;
  3489. dwElementsTotal = 0;
  3490. }
  3491. // Check the abort flag on the thread
  3492. if (FCheckForAbort() == hrOK)
  3493. break;
  3494. // check to see if we have an error and post it to the main thread if we do..
  3495. if (dwError != ERROR_NO_MORE_ITEMS &&
  3496. dwError != ERROR_SUCCESS &&
  3497. dwError != ERROR_MORE_DATA)
  3498. {
  3499. Trace1("DHCP snapin: EnumerateReservations error: %d\n", dwError);
  3500. m_dwErr = dwError;
  3501. PostError(dwError);
  3502. }
  3503. }
  3504. return hrFalse;
  3505. }
  3506. /*!--------------------------------------------------------------------------
  3507. CDhcpReservations::OnNotifyExiting
  3508. CMTDhcpHandler overridden functionality
  3509. allows us to know when the background thread is done
  3510. Author: EricDav
  3511. ---------------------------------------------------------------------------*/
  3512. STDMETHODIMP
  3513. CDhcpReservations::OnNotifyExiting
  3514. (
  3515. LPARAM lParam
  3516. )
  3517. {
  3518. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3519. SPITFSNode spNode;
  3520. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  3521. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  3522. UpdateResultMessage(spNode);
  3523. return hr;
  3524. }
  3525. /*---------------------------------------------------------------------------
  3526. CDhcpReservationClient implementation
  3527. ---------------------------------------------------------------------------*/
  3528. /*---------------------------------------------------------------------------
  3529. Function Name Here
  3530. Description
  3531. Author: EricDav
  3532. ---------------------------------------------------------------------------*/
  3533. CDhcpReservationClient::CDhcpReservationClient
  3534. (
  3535. ITFSComponentData * pComponentData,
  3536. LPDHCP_CLIENT_INFO pDhcpClientInfo
  3537. ) : CMTDhcpHandler(pComponentData)
  3538. {
  3539. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3540. InitializeData(pDhcpClientInfo);
  3541. //
  3542. // Intialize our client type
  3543. //
  3544. m_bClientType = CLIENT_TYPE_UNSPECIFIED;
  3545. m_fResProp = TRUE;
  3546. }
  3547. CDhcpReservationClient::CDhcpReservationClient
  3548. (
  3549. ITFSComponentData * pComponentData,
  3550. LPDHCP_CLIENT_INFO_V4 pDhcpClientInfo
  3551. ) : CMTDhcpHandler(pComponentData)
  3552. {
  3553. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3554. InitializeData(reinterpret_cast<LPDHCP_CLIENT_INFO>(pDhcpClientInfo));
  3555. //
  3556. // Intialize our client type
  3557. //
  3558. m_bClientType = pDhcpClientInfo->bClientType;
  3559. m_fResProp = TRUE;
  3560. }
  3561. CDhcpReservationClient::CDhcpReservationClient
  3562. (
  3563. ITFSComponentData * pComponentData,
  3564. CDhcpClient & dhcpClient
  3565. ) : CMTDhcpHandler(pComponentData)
  3566. {
  3567. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  3568. m_dhcpClientIpAddress = dhcpClient.QueryIpAddress();
  3569. //
  3570. // Copy data out if it's there
  3571. //
  3572. if (dhcpClient.QueryName().GetLength() > 0)
  3573. {
  3574. m_pstrClientName = new CString (dhcpClient.QueryName());
  3575. }
  3576. else
  3577. {
  3578. m_pstrClientName = NULL;
  3579. }
  3580. if (dhcpClient.QueryComment().GetLength() > 0)
  3581. {
  3582. m_pstrClientComment = new CString(dhcpClient.QueryComment());
  3583. }
  3584. else
  3585. {
  3586. m_pstrClientComment = NULL;
  3587. }
  3588. //
  3589. // build the clients hardware address
  3590. //
  3591. if (dhcpClient.QueryHardwareAddress().GetSize() > 0)
  3592. {
  3593. m_baHardwareAddress.Copy(dhcpClient.QueryHardwareAddress());
  3594. }
  3595. if ( (dhcpClient.QueryExpiryDateTime().dwLowDateTime == 0) &&
  3596. (dhcpClient.QueryExpiryDateTime().dwHighDateTime == 0) )
  3597. {
  3598. //
  3599. // This is an inactive reservation
  3600. //
  3601. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_INACTIVE);
  3602. }
  3603. else
  3604. {
  3605. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_ACTIVE);
  3606. }
  3607. //
  3608. // Intialize our client type
  3609. //
  3610. m_bClientType = dhcpClient.QueryClientType();
  3611. m_fResProp = TRUE;
  3612. }
  3613. CDhcpReservationClient::~CDhcpReservationClient()
  3614. {
  3615. if (m_pstrClientName)
  3616. {
  3617. delete m_pstrClientName;
  3618. }
  3619. if (m_pstrClientComment)
  3620. {
  3621. delete m_pstrClientComment;
  3622. }
  3623. }
  3624. void
  3625. CDhcpReservationClient::InitializeData
  3626. (
  3627. LPDHCP_CLIENT_INFO pDhcpClientInfo
  3628. )
  3629. {
  3630. Assert(pDhcpClientInfo);
  3631. m_dhcpClientIpAddress = pDhcpClientInfo->ClientIpAddress;
  3632. //
  3633. // Copy data out if it's there
  3634. //
  3635. if (pDhcpClientInfo->ClientName)
  3636. {
  3637. m_pstrClientName = new CString (pDhcpClientInfo->ClientName);
  3638. }
  3639. else
  3640. {
  3641. m_pstrClientName = NULL;
  3642. }
  3643. if (pDhcpClientInfo->ClientComment)
  3644. {
  3645. m_pstrClientComment = new CString(pDhcpClientInfo->ClientComment);
  3646. }
  3647. else
  3648. {
  3649. m_pstrClientComment = NULL;
  3650. }
  3651. // build a copy of the hardware address
  3652. if (pDhcpClientInfo->ClientHardwareAddress.DataLength)
  3653. {
  3654. for (DWORD i = 0; i < pDhcpClientInfo->ClientHardwareAddress.DataLength; i++)
  3655. {
  3656. m_baHardwareAddress.Add(pDhcpClientInfo->ClientHardwareAddress.Data[i]);
  3657. }
  3658. }
  3659. if ( (pDhcpClientInfo->ClientLeaseExpires.dwLowDateTime == 0) &&
  3660. (pDhcpClientInfo->ClientLeaseExpires.dwHighDateTime == 0) )
  3661. {
  3662. //
  3663. // This is an inactive reservation
  3664. //
  3665. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_INACTIVE);
  3666. }
  3667. else
  3668. {
  3669. m_strLeaseExpires.LoadString(IDS_DHCP_INFINITE_LEASE_ACTIVE);
  3670. }
  3671. }
  3672. /*!--------------------------------------------------------------------------
  3673. CDhcpReservationClient::InitializeNode
  3674. Initializes node specific data
  3675. Author: EricDav
  3676. ---------------------------------------------------------------------------*/
  3677. HRESULT
  3678. CDhcpReservationClient::InitializeNode
  3679. (
  3680. ITFSNode * pNode
  3681. )
  3682. {
  3683. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3684. HRESULT hr = hrOK;
  3685. CString strIpAddress, strDisplayName;
  3686. //
  3687. // Create the display name for this scope
  3688. // Convert DHCP_IP_ADDRES to a string and initialize this object
  3689. //
  3690. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  3691. &strIpAddress);
  3692. BuildDisplayName(&strDisplayName, strIpAddress, *m_pstrClientName);
  3693. SetDisplayName(strDisplayName);
  3694. // Make the node immediately visible
  3695. pNode->SetVisibilityState(TFS_VIS_SHOW);
  3696. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  3697. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  3698. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  3699. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  3700. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_RESERVATION_CLIENT);
  3701. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  3702. SetColumnStringIDs(&aColumns[DHCPSNAP_RESERVATION_CLIENT][0]);
  3703. SetColumnWidths(&aColumnWidths[DHCPSNAP_RESERVATION_CLIENT][0]);
  3704. return hr;
  3705. }
  3706. /*---------------------------------------------------------------------------
  3707. CDhcpReservationClient::OnCreateNodeId2
  3708. Returns a unique string for this node
  3709. Author: EricDav
  3710. ---------------------------------------------------------------------------*/
  3711. HRESULT CDhcpReservationClient::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  3712. {
  3713. const GUID * pGuid = pNode->GetNodeType();
  3714. CString strScopeIpAddress, strResIpAddress, strGuid;
  3715. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  3716. strGuid.ReleaseBuffer();
  3717. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode, TRUE)->GetAddress();
  3718. UtilCvtIpAddrToWstr (dhcpIpAddress, &strScopeIpAddress);
  3719. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress, &strResIpAddress);
  3720. strId = GetServerName(pNode, TRUE) + strScopeIpAddress + strResIpAddress + strGuid;
  3721. return hrOK;
  3722. }
  3723. /*---------------------------------------------------------------------------
  3724. CDhcpReservationClient::GetImageIndex
  3725. Description
  3726. Author: EricDav
  3727. ---------------------------------------------------------------------------*/
  3728. int
  3729. CDhcpReservationClient::GetImageIndex(BOOL bOpenImage)
  3730. {
  3731. int nIndex = -1;
  3732. switch (m_nState)
  3733. {
  3734. case notLoaded:
  3735. case loaded:
  3736. if (bOpenImage)
  3737. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN;
  3738. else
  3739. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED;
  3740. break;
  3741. case loading:
  3742. if (bOpenImage)
  3743. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN_BUSY;
  3744. else
  3745. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED_BUSY;
  3746. break;
  3747. case unableToLoad:
  3748. if (bOpenImage)
  3749. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_OPEN_LOST_CONNECTION;
  3750. else
  3751. nIndex = ICON_IDX_CLIENT_OPTION_FOLDER_CLOSED_LOST_CONNECTION;
  3752. break;
  3753. default:
  3754. ASSERT(FALSE);
  3755. }
  3756. return nIndex;
  3757. }
  3758. /*---------------------------------------------------------------------------
  3759. Overridden base handler functions
  3760. ---------------------------------------------------------------------------*/
  3761. /*---------------------------------------------------------------------------
  3762. CDhcpReservationClient::OnAddMenuItems
  3763. Adds entries to the context sensitive menu
  3764. Author: EricDav
  3765. ---------------------------------------------------------------------------*/
  3766. STDMETHODIMP
  3767. CDhcpReservationClient::OnAddMenuItems
  3768. (
  3769. ITFSNode * pNode,
  3770. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  3771. LPDATAOBJECT lpDataObject,
  3772. DATA_OBJECT_TYPES type,
  3773. DWORD dwType,
  3774. long * pInsertionAllowed
  3775. )
  3776. {
  3777. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3778. LONG fFlags = 0;
  3779. HRESULT hr = S_OK;
  3780. CString strMenuText;
  3781. if ( (m_nState != loaded) )
  3782. {
  3783. fFlags |= MF_GRAYED;
  3784. }
  3785. if (type == CCT_SCOPE)
  3786. {
  3787. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  3788. {
  3789. strMenuText.LoadString(IDS_CREATE_OPTION_RESERVATION);
  3790. hr = LoadAndAddMenuItem( pContextMenuCallback,
  3791. strMenuText,
  3792. IDS_CREATE_OPTION_RESERVATION,
  3793. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  3794. fFlags );
  3795. ASSERT( SUCCEEDED(hr) );
  3796. }
  3797. }
  3798. return hr;
  3799. }
  3800. /*---------------------------------------------------------------------------
  3801. CDhcpReservationClient::OnCommand
  3802. Description
  3803. Author: EricDav
  3804. ---------------------------------------------------------------------------*/
  3805. STDMETHODIMP
  3806. CDhcpReservationClient::OnCommand
  3807. (
  3808. ITFSNode * pNode,
  3809. long nCommandId,
  3810. DATA_OBJECT_TYPES type,
  3811. LPDATAOBJECT pDataObject,
  3812. DWORD dwType
  3813. )
  3814. {
  3815. HRESULT hr = S_OK;
  3816. switch (nCommandId)
  3817. {
  3818. case IDS_REFRESH:
  3819. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  3820. break;
  3821. case IDS_DELETE:
  3822. OnDelete(pNode);
  3823. break;
  3824. case IDS_CREATE_OPTION_RESERVATION:
  3825. OnCreateNewOptions(pNode);
  3826. break;
  3827. default:
  3828. break;
  3829. }
  3830. return hr;
  3831. }
  3832. /*---------------------------------------------------------------------------
  3833. CDhcpReservationClient::CompareItems
  3834. Description
  3835. Author: EricDav
  3836. ---------------------------------------------------------------------------*/
  3837. STDMETHODIMP_(int)
  3838. CDhcpReservationClient::CompareItems
  3839. (
  3840. ITFSComponent * pComponent,
  3841. MMC_COOKIE cookieA,
  3842. MMC_COOKIE cookieB,
  3843. int nCol
  3844. )
  3845. {
  3846. SPITFSNode spNode1, spNode2;
  3847. m_spNodeMgr->FindNode(cookieA, &spNode1);
  3848. m_spNodeMgr->FindNode(cookieB, &spNode2);
  3849. int nCompare = 0;
  3850. CDhcpOptionItem *pOpt1 = GETHANDLER(CDhcpOptionItem, spNode1);
  3851. CDhcpOptionItem *pOpt2 = GETHANDLER(CDhcpOptionItem, spNode2);
  3852. switch (nCol)
  3853. {
  3854. case 0:
  3855. {
  3856. //
  3857. // Name compare - use the option #
  3858. //
  3859. LONG_PTR uImage1 = spNode1->GetData(TFS_DATA_IMAGEINDEX);
  3860. LONG_PTR uImage2 = spNode2->GetData(TFS_DATA_IMAGEINDEX);
  3861. nCompare = UtilGetOptionPriority((int) uImage1, (int) uImage2);
  3862. if (nCompare == 0)
  3863. {
  3864. DHCP_OPTION_ID id1 = pOpt1->GetOptionId();
  3865. DHCP_OPTION_ID id2 = pOpt2->GetOptionId();
  3866. if (id1 < id2)
  3867. nCompare = -1;
  3868. else
  3869. if (id1 > id2)
  3870. nCompare = 1;
  3871. }
  3872. }
  3873. break;
  3874. case 1:
  3875. {
  3876. // compare the vendor strings
  3877. CString str1, str2;
  3878. str1 = pOpt1->GetVendorDisplay();
  3879. str2 = pOpt2->GetVendorDisplay();
  3880. nCompare = str1.CompareNoCase(str2);
  3881. }
  3882. break;
  3883. case 2: {
  3884. // compare the printable values
  3885. CString str1, str2;
  3886. str1 = pOpt1->GetString( pComponent, cookieA, nCol );
  3887. str2 = pOpt2->GetString( pComponent, cookieB, nCol );
  3888. nCompare = str1.CompareNoCase( str2 );
  3889. break;
  3890. }
  3891. case 3:
  3892. {
  3893. CString str1, str2;
  3894. str1 = pOpt1->GetClassName();
  3895. str2 = pOpt2->GetClassName();
  3896. nCompare = str1.CompareNoCase(str2);
  3897. }
  3898. break;
  3899. }
  3900. return nCompare;
  3901. }
  3902. /*!--------------------------------------------------------------------------
  3903. CDhcpReservationClient::OnResultSelect
  3904. Update the verbs and the result pane message
  3905. Author: EricDav
  3906. ---------------------------------------------------------------------------*/
  3907. HRESULT CDhcpReservationClient::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  3908. {
  3909. HRESULT hr = hrOK;
  3910. SPITFSNode spNode;
  3911. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  3912. CORg (pComponent->GetSelectedNode(&spNode));
  3913. if ( spNode != 0 ) {
  3914. UpdateResultMessage(spNode);
  3915. }
  3916. Error:
  3917. return hr;
  3918. }
  3919. /*!--------------------------------------------------------------------------
  3920. CDhcpReservationClient::UpdateResultMessage
  3921. Figures out what message to put in the result pane, if any
  3922. Author: EricDav
  3923. ---------------------------------------------------------------------------*/
  3924. void CDhcpReservationClient::UpdateResultMessage(ITFSNode * pNode)
  3925. {
  3926. HRESULT hr = hrOK;
  3927. int nMessage = -1; // default
  3928. int nVisible, nTotal;
  3929. int i;
  3930. CString strTitle, strBody, strTemp;
  3931. if (!m_dwErr)
  3932. {
  3933. pNode->GetChildCount(&nVisible, &nTotal);
  3934. // determine what message to display
  3935. if ( (m_nState == notLoaded) ||
  3936. (m_nState == loading) )
  3937. {
  3938. nMessage = -1;
  3939. }
  3940. else
  3941. if (nTotal == 0)
  3942. {
  3943. nMessage = RES_OPTIONS_MESSAGE_NO_OPTIONS;
  3944. }
  3945. // build the strings
  3946. if (nMessage != -1)
  3947. {
  3948. // now build the text strings
  3949. // first entry is the title
  3950. strTitle.LoadString(g_uResOptionsMessages[nMessage][0]);
  3951. // second entry is the icon
  3952. // third ... n entries are the body strings
  3953. for (i = 2; g_uResOptionsMessages[nMessage][i] != 0; i++)
  3954. {
  3955. strTemp.LoadString(g_uResOptionsMessages[nMessage][i]);
  3956. strBody += strTemp;
  3957. }
  3958. }
  3959. }
  3960. // show the message
  3961. if (nMessage == -1)
  3962. {
  3963. ClearMessage(pNode);
  3964. }
  3965. else
  3966. {
  3967. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uResOptionsMessages[nMessage][1]);
  3968. }
  3969. }
  3970. /*!--------------------------------------------------------------------------
  3971. CDhcpReservationClient::OnDelete
  3972. The base handler calls this when MMC sends a MMCN_DELETE for a
  3973. scope pane item. We just call our delete command handler.
  3974. Author: EricDav
  3975. ---------------------------------------------------------------------------*/
  3976. HRESULT
  3977. CDhcpReservationClient::OnDelete
  3978. (
  3979. ITFSNode * pNode,
  3980. LPARAM arg,
  3981. LPARAM lParam
  3982. )
  3983. {
  3984. return OnDelete(pNode);
  3985. }
  3986. /*---------------------------------------------------------------------------
  3987. Command handlers
  3988. ---------------------------------------------------------------------------*/
  3989. HRESULT
  3990. CDhcpReservationClient::OnCreateNewOptions
  3991. (
  3992. ITFSNode * pNode
  3993. )
  3994. {
  3995. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  3996. CPropertyPageHolderBase * pPropSheet;
  3997. CString strOptCfgTitle, strOptType;
  3998. SPITFSNode spServerNode;
  3999. SPIComponentData spComponentData;
  4000. COptionsConfig * pOptCfg;
  4001. DHCP_OPTION_SCOPE_INFO dhcpScopeInfo;
  4002. HRESULT hr = hrOK;
  4003. COM_PROTECT_TRY
  4004. {
  4005. CString strOptCfgTitle, strOptType;
  4006. SPIComponentData spComponentData;
  4007. BOOL fFound = FALSE;
  4008. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_CLIENT);
  4009. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  4010. // this gets kinda weird because we implemented the option config page
  4011. // as a property page, so technically this node has two property pages.
  4012. //
  4013. // search the open prop pages to see if the option config is up
  4014. // if it's up, set it active instead of creating a new one.
  4015. for (int i = 0; i < HasPropSheetsOpen(); i++)
  4016. {
  4017. GetOpenPropSheet(i, &pPropSheet);
  4018. HWND hwnd = pPropSheet->GetSheetWindow();
  4019. CString strTitle;
  4020. ::GetWindowText(hwnd, strTitle.GetBuffer(256), 256);
  4021. strTitle.ReleaseBuffer();
  4022. if (strTitle == strOptCfgTitle)
  4023. {
  4024. pPropSheet->SetActiveWindow();
  4025. fFound = TRUE;
  4026. break;
  4027. }
  4028. }
  4029. if (!fFound)
  4030. {
  4031. m_spNodeMgr->GetComponentData(&spComponentData);
  4032. m_fResProp = FALSE;
  4033. hr = DoPropertiesOurselvesSinceMMCSucks(pNode, spComponentData, strOptCfgTitle);
  4034. m_fResProp = TRUE;
  4035. }
  4036. }
  4037. COM_PROTECT_CATCH;
  4038. return hr;
  4039. }
  4040. /*---------------------------------------------------------------------------
  4041. CDhcpReservationClient::OnDelete
  4042. Description
  4043. Author: EricDav
  4044. ---------------------------------------------------------------------------*/
  4045. DWORD
  4046. CDhcpReservationClient::OnDelete
  4047. (
  4048. ITFSNode * pNode
  4049. )
  4050. {
  4051. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4052. CString strMessage, strTemp;
  4053. DWORD dwError = 0;
  4054. CDhcpReservations *pResrv;
  4055. pResrv = GETHANDLER( CDhcpReservations, pNode );
  4056. // Check for any open property sheets
  4057. if ( pResrv->HasPropSheetsOpen()) {
  4058. AfxMessageBox( IDS_MSG_CLOSE_PROPSHEET );
  4059. return ERROR_INVALID_PARAMETER;
  4060. }
  4061. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  4062. &strTemp);
  4063. AfxFormatString1(strMessage, IDS_DELETE_RESERVATION, (LPCTSTR) strTemp);
  4064. if (AfxMessageBox(strMessage, MB_YESNO) == IDYES) {
  4065. BEGIN_WAIT_CURSOR;
  4066. dwError = GetScopeObject(pNode, TRUE)->DeleteReservation(m_baHardwareAddress, m_dhcpClientIpAddress);
  4067. if (dwError != 0) {
  4068. //
  4069. // OOOpss. Something happened, reservation not
  4070. // deleted, so don't remove from UI and put up a message box
  4071. //
  4072. ::DhcpMessageBox(dwError);
  4073. }
  4074. else {
  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. } // else
  4086. END_WAIT_CURSOR;
  4087. } // if
  4088. return dwError;
  4089. } // CDhcpReservationClient::OnDelete()
  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. if (pOptItem->IsVendorOption() ||
  4344. pOptItem->IsClassOption())
  4345. {
  4346. LPCTSTR pClassName = pOptItem->GetClassName();
  4347. if (lstrlen(pClassName) == 0)
  4348. pClassName = NULL;
  4349. dwError = ::DhcpRemoveOptionValueV5((LPTSTR) ((LPCTSTR) strServer),
  4350. pOptItem->IsVendorOption() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  4351. pOptItem->GetOptionId(),
  4352. (LPTSTR) pClassName,
  4353. (LPTSTR) pOptItem->GetVendor(),
  4354. &dhcpOptionScopeInfo);
  4355. }
  4356. else
  4357. {
  4358. dwError = ::DhcpRemoveOptionValue(strServer,
  4359. pOptItem->GetOptionId(),
  4360. &dhcpOptionScopeInfo);
  4361. }
  4362. if (dwError != 0)
  4363. {
  4364. ::DhcpMessageBox(dwError);
  4365. RESTORE_WAIT_CURSOR;
  4366. hr = E_FAIL;
  4367. continue;
  4368. }
  4369. GetOptionValueEnum()->Remove(pOptItem->GetOptionId(), pOptItem->GetVendor(), pOptItem->GetClassName());
  4370. //
  4371. // Remove from UI now
  4372. //
  4373. spResClient->RemoveChild(spOptionNode);
  4374. spOptionNode.Release();
  4375. }
  4376. END_WAIT_CURSOR;
  4377. UpdateResultMessage(spResClient);
  4378. return hr;
  4379. }
  4380. /*!--------------------------------------------------------------------------
  4381. CDhcpReservationClient::OnGetResultViewType
  4382. MMC calls this to get the result view information
  4383. Author: EricDav
  4384. ---------------------------------------------------------------------------*/
  4385. HRESULT
  4386. CDhcpReservationClient::OnGetResultViewType
  4387. (
  4388. ITFSComponent * pComponent,
  4389. MMC_COOKIE cookie,
  4390. LPOLESTR * ppViewType,
  4391. long * pViewOptions
  4392. )
  4393. {
  4394. HRESULT hr = hrOK;
  4395. // call the base class to see if it is handling this
  4396. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  4397. {
  4398. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  4399. hr = S_FALSE;
  4400. }
  4401. return hr;
  4402. }
  4403. /*!--------------------------------------------------------------------------
  4404. CDhcpReservationClient::OnHaveData
  4405. Description
  4406. Author: EricDav
  4407. ---------------------------------------------------------------------------*/
  4408. void
  4409. CDhcpReservationClient::OnHaveData
  4410. (
  4411. ITFSNode * pParentNode,
  4412. LPARAM Data,
  4413. LPARAM Type
  4414. )
  4415. {
  4416. // This is how we get non-node data back from the background thread.
  4417. switch (Type)
  4418. {
  4419. case DHCP_QDATA_OPTION_VALUES:
  4420. {
  4421. HRESULT hr = hrOK;
  4422. SPIComponentData spCompData;
  4423. SPIConsole spConsole;
  4424. SPIDataObject spDataObject;
  4425. IDataObject * pDataObject;
  4426. COptionValueEnum * pOptionValueEnum = reinterpret_cast<COptionValueEnum *>(Data);
  4427. SetOptionValueEnum(pOptionValueEnum);
  4428. pOptionValueEnum->RemoveAll();
  4429. delete pOptionValueEnum;
  4430. // now tell the view to update themselves
  4431. m_spNodeMgr->GetComponentData(&spCompData);
  4432. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pParentNode, CCT_SCOPE, &pDataObject) );
  4433. spDataObject = pDataObject;
  4434. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  4435. CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM) pParentNode, DHCPSNAP_UPDATE_OPTIONS) );
  4436. break;
  4437. }
  4438. }
  4439. Error:
  4440. return;
  4441. }
  4442. /*!--------------------------------------------------------------------------
  4443. CDhcpReservationClient::OnNotifyExiting
  4444. CMTDhcpHandler overridden functionality
  4445. allows us to know when the background thread is done
  4446. Author: EricDav
  4447. ---------------------------------------------------------------------------*/
  4448. STDMETHODIMP
  4449. CDhcpReservationClient::OnNotifyExiting
  4450. (
  4451. LPARAM lParam
  4452. )
  4453. {
  4454. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4455. SPITFSNode spNode;
  4456. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  4457. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  4458. UpdateResultMessage(spNode);
  4459. return hr;
  4460. }
  4461. /*!--------------------------------------------------------------------------
  4462. CDhcpReservationClient::OnResultUpdateView
  4463. Implementation of ITFSResultHandler::OnResultUpdateView
  4464. Author: EricDav
  4465. ---------------------------------------------------------------------------*/
  4466. HRESULT CDhcpReservationClient::OnResultUpdateView
  4467. (
  4468. ITFSComponent *pComponent,
  4469. LPDATAOBJECT pDataObject,
  4470. LPARAM data,
  4471. LPARAM hint
  4472. )
  4473. {
  4474. HRESULT hr = hrOK;
  4475. SPITFSNode spSelectedNode;
  4476. pComponent->GetSelectedNode(&spSelectedNode);
  4477. if (spSelectedNode == NULL)
  4478. return S_OK; // no selection for our IComponentData
  4479. if ( hint == DHCPSNAP_UPDATE_OPTIONS )
  4480. {
  4481. SPINTERNAL spInternal = ExtractInternalFormat(pDataObject);
  4482. ITFSNode * pNode = reinterpret_cast<ITFSNode *>(spInternal->m_cookie);
  4483. SPITFSNode spSelectedNode;
  4484. pComponent->GetSelectedNode(&spSelectedNode);
  4485. EnumerateResultPane(pComponent, (MMC_COOKIE) spSelectedNode.p, 0, 0);
  4486. }
  4487. else
  4488. {
  4489. // we don't handle this message, let the base class do it.
  4490. return CMTDhcpHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  4491. }
  4492. return hr;
  4493. }
  4494. /*!--------------------------------------------------------------------------
  4495. CDhcpReservationClient::EnumerateResultPane
  4496. We override this function for the options nodes for one reason.
  4497. Whenever an option class is deleted, then all options defined for
  4498. that class will be removed as well. Since there are multiple places
  4499. that these options may show up, it's easier to just not show any
  4500. options that don't have a class defined for it.
  4501. Author: EricDav
  4502. ---------------------------------------------------------------------------*/
  4503. HRESULT
  4504. CDhcpReservationClient::EnumerateResultPane
  4505. (
  4506. ITFSComponent * pComponent,
  4507. MMC_COOKIE cookie,
  4508. LPARAM arg,
  4509. LPARAM lParam
  4510. )
  4511. {
  4512. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4513. CClassInfoArray ClassInfoArray;
  4514. SPITFSNode spContainer, spServerNode;
  4515. CDhcpServer * pServer;
  4516. COptionValueEnum * aEnum[3];
  4517. int aImages[3] = {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF};
  4518. m_spNodeMgr->FindNode(cookie, &spContainer);
  4519. spServerNode = GetServerNode(spContainer, TRUE);
  4520. pServer = GETHANDLER(CDhcpServer, spServerNode);
  4521. pServer->GetClassInfoArray(ClassInfoArray);
  4522. aEnum[0] = GetOptionValueEnum();
  4523. aEnum[1] = GetScopeObject(spContainer, TRUE)->GetOptionValueEnum();
  4524. aEnum[2] = pServer->GetOptionValueEnum();
  4525. aEnum[0]->Reset();
  4526. aEnum[1]->Reset();
  4527. aEnum[2]->Reset();
  4528. return OnResultUpdateOptions(pComponent, spContainer, &ClassInfoArray, aEnum, aImages, 3);
  4529. }
  4530. /*---------------------------------------------------------------------------
  4531. Helper functions
  4532. ---------------------------------------------------------------------------*/
  4533. /*---------------------------------------------------------------------------
  4534. CDhcpReservationClient::GetDnsRegistration
  4535. Gets the DNS registration option value
  4536. Author: EricDav
  4537. ---------------------------------------------------------------------------*/
  4538. DWORD
  4539. CDhcpReservationClient::GetDnsRegistration
  4540. (
  4541. ITFSNode * pNode,
  4542. LPDWORD pDnsRegOption
  4543. )
  4544. {
  4545. //
  4546. // Check option 81 -- the DNS registration option
  4547. //
  4548. CDhcpScope * pScope = GetScopeObject(pNode, TRUE);
  4549. DHCP_OPTION_VALUE * poptValue = NULL;
  4550. DWORD err = pScope->GetOptionValue(OPTION_DNS_REGISTATION,
  4551. DhcpReservedOptions,
  4552. &poptValue,
  4553. m_dhcpClientIpAddress);
  4554. // this is the default
  4555. if (pDnsRegOption)
  4556. *pDnsRegOption = DHCP_DYN_DNS_DEFAULT;
  4557. if (err == ERROR_SUCCESS)
  4558. {
  4559. if ((poptValue->Value.Elements != NULL) &&
  4560. (pDnsRegOption))
  4561. {
  4562. *pDnsRegOption = poptValue->Value.Elements[0].Element.DWordOption;
  4563. }
  4564. }
  4565. else
  4566. {
  4567. Trace0("CDhcpReservationClient::GetDnsRegistration - couldn't get DNS reg value -- \
  4568. option may not be defined, Getting Scope value.\n");
  4569. err = pScope->GetDnsRegistration(pDnsRegOption);
  4570. }
  4571. if (poptValue)
  4572. ::DhcpRpcFreeMemory(poptValue);
  4573. return err;
  4574. }
  4575. /*---------------------------------------------------------------------------
  4576. CDhcpReservationClient::SetDnsRegistration
  4577. Sets the DNS Registration option for this scope
  4578. Author: EricDav
  4579. ---------------------------------------------------------------------------*/
  4580. DWORD
  4581. CDhcpReservationClient::SetDnsRegistration
  4582. (
  4583. ITFSNode * pNode,
  4584. DWORD DnsRegOption
  4585. )
  4586. {
  4587. CDhcpScope * pScope = GetScopeObject(pNode, TRUE);
  4588. DWORD err = 0;
  4589. //
  4590. // Set DNS name registration (option 81)
  4591. //
  4592. CDhcpOption dhcpOption (OPTION_DNS_REGISTATION, DhcpDWordOption , _T(""), _T(""));
  4593. dhcpOption.QueryValue().SetNumber(DnsRegOption);
  4594. err = pScope->SetOptionValue(&dhcpOption, DhcpReservedOptions, m_dhcpClientIpAddress);
  4595. return err;
  4596. }
  4597. /*---------------------------------------------------------------------------
  4598. CDhcpReservationClient::BuildDisplayName
  4599. Builds the display name string
  4600. Author: EricDav
  4601. ---------------------------------------------------------------------------*/
  4602. HRESULT
  4603. CDhcpReservationClient::BuildDisplayName
  4604. (
  4605. CString * pstrDisplayName,
  4606. LPCTSTR pIpAddress,
  4607. LPCTSTR pName
  4608. )
  4609. {
  4610. if (pstrDisplayName)
  4611. {
  4612. CString strTemp = pIpAddress;
  4613. strTemp = L"[" + strTemp + L"]";
  4614. if (pName)
  4615. {
  4616. CString strName = pName;
  4617. strTemp += L" " + strName;
  4618. }
  4619. *pstrDisplayName = strTemp;
  4620. }
  4621. return hrOK;
  4622. }
  4623. /*---------------------------------------------------------------------------
  4624. CDhcpReservationClient::BuildDisplayName
  4625. Updates the cached name for this reservation and updates the UI
  4626. Author: EricDav
  4627. ---------------------------------------------------------------------------*/
  4628. HRESULT
  4629. CDhcpReservationClient::SetName
  4630. (
  4631. LPCTSTR pName
  4632. )
  4633. {
  4634. if (pName != NULL)
  4635. {
  4636. if (m_pstrClientName)
  4637. {
  4638. *m_pstrClientName = pName;
  4639. }
  4640. else
  4641. {
  4642. m_pstrClientName = new CString(pName);
  4643. }
  4644. }
  4645. else
  4646. {
  4647. if (m_pstrClientName)
  4648. {
  4649. delete m_pstrClientName;
  4650. m_pstrClientName = NULL;
  4651. }
  4652. }
  4653. CString strIpAddress, strDisplayName;
  4654. //
  4655. // Create the display name for this scope
  4656. // Convert DHCP_IP_ADDRES to a string and initialize this object
  4657. //
  4658. UtilCvtIpAddrToWstr (m_dhcpClientIpAddress,
  4659. &strIpAddress);
  4660. BuildDisplayName(&strDisplayName, strIpAddress, pName);
  4661. SetDisplayName(strDisplayName);
  4662. return hrOK;
  4663. }
  4664. /*---------------------------------------------------------------------------
  4665. CDhcpReservationClient::BuildDisplayName
  4666. Updates the cached comment for this reservation
  4667. Author: EricDav
  4668. ---------------------------------------------------------------------------*/
  4669. HRESULT
  4670. CDhcpReservationClient::SetComment
  4671. (
  4672. LPCTSTR pComment
  4673. )
  4674. {
  4675. if (pComment != NULL)
  4676. {
  4677. if (m_pstrClientComment)
  4678. {
  4679. *m_pstrClientComment = pComment;
  4680. }
  4681. else
  4682. {
  4683. m_pstrClientComment = new CString(pComment);
  4684. }
  4685. }
  4686. else
  4687. {
  4688. if (m_pstrClientComment)
  4689. {
  4690. delete m_pstrClientComment;
  4691. m_pstrClientComment = NULL;
  4692. }
  4693. }
  4694. return hrOK;
  4695. }
  4696. /*---------------------------------------------------------------------------
  4697. CDhcpReservationClient::SetUID
  4698. Updates the cached unique ID for this reservation
  4699. Author: EricDav
  4700. ---------------------------------------------------------------------------*/
  4701. HRESULT
  4702. CDhcpReservationClient::SetUID
  4703. (
  4704. const CByteArray & baClientUID
  4705. )
  4706. {
  4707. m_baHardwareAddress.Copy(baClientUID);
  4708. return hrOK;
  4709. }
  4710. /*---------------------------------------------------------------------------
  4711. CDhcpReservationClient::SetClientType
  4712. Updates the cached client type for this record
  4713. Author: EricDav
  4714. ---------------------------------------------------------------------------*/
  4715. BYTE
  4716. CDhcpReservationClient::SetClientType
  4717. (
  4718. BYTE bClientType
  4719. )
  4720. {
  4721. BYTE bRet = m_bClientType;
  4722. m_bClientType = bClientType;
  4723. return bRet;
  4724. }
  4725. /*---------------------------------------------------------------------------
  4726. Background thread functionality
  4727. ---------------------------------------------------------------------------*/
  4728. /*---------------------------------------------------------------------------
  4729. CDhcpReservationClient::OnCreateQuery()
  4730. Description
  4731. Author: EricDav
  4732. ---------------------------------------------------------------------------*/
  4733. ITFSQueryObject*
  4734. CDhcpReservationClient::OnCreateQuery(ITFSNode * pNode)
  4735. {
  4736. CDhcpReservationClientQueryObj* pQuery =
  4737. new CDhcpReservationClientQueryObj(m_spTFSCompData, m_spNodeMgr);
  4738. pQuery->m_strServer = GetServerIpAddress(pNode, TRUE);
  4739. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode, TRUE)->GetAddress();
  4740. pQuery->m_dhcpClientIpAddress = m_dhcpClientIpAddress;
  4741. GetScopeObject(pNode, TRUE)->GetServerVersion(pQuery->m_liDhcpVersion);
  4742. GetScopeObject(pNode, TRUE)->GetDynBootpClassName(pQuery->m_strDynBootpClassName);
  4743. pQuery->m_dhcpResumeHandle = NULL;
  4744. pQuery->m_dwPreferredMax = 0xFFFFFFFF;
  4745. return pQuery;
  4746. }
  4747. /*---------------------------------------------------------------------------
  4748. CDhcpReservationClientQueryObj::Execute()
  4749. Description
  4750. Author: EricDav
  4751. ---------------------------------------------------------------------------*/
  4752. STDMETHODIMP
  4753. CDhcpReservationClientQueryObj::Execute()
  4754. {
  4755. DWORD dwErr;
  4756. COptionNodeEnum OptionNodeEnum(m_spTFSCompData, m_spNodeMgr);
  4757. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  4758. COptionValueEnum * pOptionValueEnum = new COptionValueEnum;
  4759. pOptionValueEnum->m_strDynBootpClassName = m_strDynBootpClassName;
  4760. dhcpOptionScopeInfo.ScopeType = DhcpReservedOptions;
  4761. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = m_dhcpClientIpAddress;
  4762. dhcpOptionScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = m_dhcpScopeAddress;
  4763. pOptionValueEnum->Init(m_strServer, m_liDhcpVersion, dhcpOptionScopeInfo);
  4764. dwErr = pOptionValueEnum->Enum();
  4765. // add all of the nodes
  4766. if (dwErr != ERROR_SUCCESS)
  4767. {
  4768. Trace1("CDhcpReservationClientQueryObj::Execute - Enum Failed! %d\n", dwErr);
  4769. m_dwErr = dwErr;
  4770. PostError(dwErr);
  4771. delete pOptionValueEnum;
  4772. }
  4773. else
  4774. {
  4775. pOptionValueEnum->SortById();
  4776. AddToQueue((LPARAM) pOptionValueEnum, DHCP_QDATA_OPTION_VALUES);
  4777. }
  4778. return hrFalse;
  4779. }
  4780. /////////////////////////////////////////////////////////////////////
  4781. //
  4782. // CDhcpActiveLeases implementation
  4783. //
  4784. /////////////////////////////////////////////////////////////////////
  4785. /*---------------------------------------------------------------------------
  4786. Function Name Here
  4787. Description
  4788. Author: EricDav
  4789. ---------------------------------------------------------------------------*/
  4790. CDhcpActiveLeases::CDhcpActiveLeases
  4791. (
  4792. ITFSComponentData * pComponentData
  4793. ) : CMTDhcpHandler(pComponentData)
  4794. {
  4795. }
  4796. CDhcpActiveLeases::~CDhcpActiveLeases()
  4797. {
  4798. }
  4799. /*!--------------------------------------------------------------------------
  4800. CDhcpActiveLeases::InitializeNode
  4801. Initializes node specific data
  4802. Author: EricDav
  4803. ---------------------------------------------------------------------------*/
  4804. HRESULT
  4805. CDhcpActiveLeases::InitializeNode
  4806. (
  4807. ITFSNode * pNode
  4808. )
  4809. {
  4810. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4811. HRESULT hr = hrOK;
  4812. //
  4813. // Create the display name for this scope
  4814. //
  4815. CString strTemp;
  4816. strTemp.LoadString(IDS_ACTIVE_LEASES_FOLDER);
  4817. SetDisplayName(strTemp);
  4818. // Make the node immediately visible
  4819. pNode->SetVisibilityState(TFS_VIS_SHOW);
  4820. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  4821. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  4822. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  4823. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  4824. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_ACTIVE_LEASES);
  4825. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  4826. SetColumnStringIDs(&aColumns[DHCPSNAP_ACTIVE_LEASES][0]);
  4827. SetColumnWidths(&aColumnWidths[DHCPSNAP_ACTIVE_LEASES][0]);
  4828. return hr;
  4829. }
  4830. /*---------------------------------------------------------------------------
  4831. CDhcpActiveLeases::OnCreateNodeId2
  4832. Returns a unique string for this node
  4833. Author: EricDav
  4834. ---------------------------------------------------------------------------*/
  4835. HRESULT CDhcpActiveLeases::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  4836. {
  4837. const GUID * pGuid = pNode->GetNodeType();
  4838. CString strIpAddress, strGuid;
  4839. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  4840. strGuid.ReleaseBuffer();
  4841. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  4842. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  4843. strId = GetServerName(pNode) + strIpAddress + strGuid;
  4844. return hrOK;
  4845. }
  4846. /*---------------------------------------------------------------------------
  4847. CDhcpActiveLeases::GetImageIndex
  4848. Description
  4849. Author: EricDav
  4850. ---------------------------------------------------------------------------*/
  4851. int
  4852. CDhcpActiveLeases::GetImageIndex(BOOL bOpenImage)
  4853. {
  4854. int nIndex = -1;
  4855. switch (m_nState)
  4856. {
  4857. case notLoaded:
  4858. case loaded:
  4859. if (bOpenImage)
  4860. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN;
  4861. else
  4862. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED;
  4863. break;
  4864. case loading:
  4865. if (bOpenImage)
  4866. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_BUSY;
  4867. else
  4868. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_BUSY;
  4869. break;
  4870. case unableToLoad:
  4871. if (bOpenImage)
  4872. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_OPEN_LOST_CONNECTION;
  4873. else
  4874. nIndex = ICON_IDX_ACTIVE_LEASES_FOLDER_CLOSED_LOST_CONNECTION;
  4875. break;
  4876. default:
  4877. ASSERT(FALSE);
  4878. }
  4879. return nIndex;
  4880. }
  4881. /*---------------------------------------------------------------------------
  4882. Overridden base handler functions
  4883. ---------------------------------------------------------------------------*/
  4884. /*---------------------------------------------------------------------------
  4885. CDhcpActiveLeases::OnAddMenuItems
  4886. Adds entries to the context sensitive menu
  4887. Author: EricDav
  4888. ---------------------------------------------------------------------------*/
  4889. STDMETHODIMP
  4890. CDhcpActiveLeases::OnAddMenuItems
  4891. (
  4892. ITFSNode * pNode,
  4893. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  4894. LPDATAOBJECT lpDataObject,
  4895. DATA_OBJECT_TYPES type,
  4896. DWORD dwType,
  4897. long * pInsertionAllowed
  4898. )
  4899. {
  4900. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  4901. LONG fFlags = 0;
  4902. HRESULT hr = S_OK;
  4903. CString strMenuText;
  4904. if ( (m_nState != loaded) )
  4905. {
  4906. fFlags |= MF_GRAYED;
  4907. }
  4908. if (type == CCT_SCOPE)
  4909. {
  4910. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  4911. {
  4912. /* removed, using new MMC save list functionality
  4913. strMenuText.LoadString(IDS_EXPORT_LEASE_INFO);
  4914. hr = LoadAndAddMenuItem( pContextMenuCallback,
  4915. strMenuText,
  4916. IDS_EXPORT_LEASE_INFO,
  4917. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  4918. fFlags );
  4919. ASSERT( SUCCEEDED(hr) );
  4920. */
  4921. }
  4922. }
  4923. return hr;
  4924. }
  4925. /*---------------------------------------------------------------------------
  4926. CDhcpActiveLeases::OnCommand
  4927. Description
  4928. Author: EricDav
  4929. ---------------------------------------------------------------------------*/
  4930. STDMETHODIMP
  4931. CDhcpActiveLeases::OnCommand
  4932. (
  4933. ITFSNode * pNode,
  4934. long nCommandId,
  4935. DATA_OBJECT_TYPES type,
  4936. LPDATAOBJECT pDataObject,
  4937. DWORD dwType
  4938. )
  4939. {
  4940. HRESULT hr = S_OK;
  4941. switch (nCommandId)
  4942. {
  4943. case IDS_REFRESH:
  4944. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  4945. break;
  4946. case IDS_EXPORT_LEASE_INFO:
  4947. OnExportLeases(pNode);
  4948. break;
  4949. default:
  4950. break;
  4951. }
  4952. return hr;
  4953. }
  4954. /*---------------------------------------------------------------------------
  4955. CDhcpActiveLeases::OnResultDelete
  4956. This function is called when we are supposed to delete result
  4957. pane items. We build a list of selected items and then delete them.
  4958. Author: EricDav
  4959. ---------------------------------------------------------------------------*/
  4960. HRESULT
  4961. CDhcpActiveLeases::OnResultDelete
  4962. (
  4963. ITFSComponent * pComponent,
  4964. LPDATAOBJECT pDataObject,
  4965. MMC_COOKIE cookie,
  4966. LPARAM arg,
  4967. LPARAM param
  4968. )
  4969. {
  4970. HRESULT hr = hrOK;
  4971. BOOL bIsRes, bIsActive, bBadAddress;
  4972. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  4973. // translate the cookie into a node pointer
  4974. SPITFSNode spActiveLeases, spSelectedNode;
  4975. m_spNodeMgr->FindNode(cookie, &spActiveLeases);
  4976. pComponent->GetSelectedNode(&spSelectedNode);
  4977. Assert(spSelectedNode == spActiveLeases);
  4978. if (spSelectedNode != spActiveLeases)
  4979. return hr;
  4980. // build the list of selected nodes
  4981. CTFSNodeList listNodesToDelete;
  4982. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  4983. //
  4984. // Confirm with the user
  4985. //
  4986. CString strMessage, strTemp;
  4987. int nNodes = (int) listNodesToDelete.GetCount();
  4988. if (nNodes > 1)
  4989. {
  4990. strTemp.Format(_T("%d"), nNodes);
  4991. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  4992. }
  4993. else
  4994. {
  4995. strMessage.LoadString(IDS_DELETE_ITEM);
  4996. }
  4997. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  4998. {
  4999. return NOERROR;
  5000. }
  5001. //
  5002. // Loop through all items deleting
  5003. //
  5004. BEGIN_WAIT_CURSOR;
  5005. while (listNodesToDelete.GetCount() > 0)
  5006. {
  5007. SPITFSNode spActiveLeaseNode;
  5008. spActiveLeaseNode = listNodesToDelete.RemoveHead();
  5009. CDhcpActiveLease * pActiveLease = GETHANDLER(CDhcpActiveLease, spActiveLeaseNode);
  5010. //
  5011. // delete the node, check to see if it is a reservation
  5012. //
  5013. bIsRes = pActiveLease->IsReservation(&bIsActive, &bBadAddress);
  5014. if (bIsRes && !bBadAddress)
  5015. {
  5016. //
  5017. // Delete the reservation
  5018. //
  5019. LPDHCP_CLIENT_INFO pdhcpClientInfo;
  5020. DWORD dwError = GetScopeObject(spActiveLeases)->GetClientInfo(pActiveLease->GetIpAddress(), &pdhcpClientInfo);
  5021. if (dwError == ERROR_SUCCESS)
  5022. {
  5023. dwError = GetScopeObject(spActiveLeases)->DeleteReservation(pdhcpClientInfo->ClientHardwareAddress,
  5024. pdhcpClientInfo->ClientIpAddress);
  5025. if (dwError == ERROR_SUCCESS)
  5026. {
  5027. //
  5028. // Tell the reservations folder to remove this from it's list
  5029. //
  5030. SPITFSNode spReservationsNode;
  5031. GetScopeObject(spActiveLeases)->GetReservationsNode(&spReservationsNode);
  5032. GetScopeObject(spActiveLeases)->GetReservationsObject()->
  5033. RemoveReservationFromUI((ITFSNode *) spReservationsNode, pActiveLease->GetIpAddress());
  5034. spActiveLeases->RemoveChild(spActiveLeaseNode);
  5035. }
  5036. else
  5037. {
  5038. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5039. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5040. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5041. {
  5042. break;
  5043. }
  5044. RESTORE_WAIT_CURSOR;
  5045. Trace1("Delete reservation failed %lx\n", dwError);
  5046. hr = E_FAIL;
  5047. }
  5048. ::DhcpRpcFreeMemory(pdhcpClientInfo);
  5049. }
  5050. else
  5051. {
  5052. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5053. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5054. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5055. {
  5056. break;
  5057. }
  5058. RESTORE_WAIT_CURSOR;
  5059. Trace1("GetClientInfo failed %lx\n", dwError);
  5060. hr = E_FAIL;
  5061. }
  5062. }
  5063. else
  5064. {
  5065. DWORD dwError = GetScopeObject(spActiveLeases)->DeleteClient(pActiveLease->GetIpAddress());
  5066. if (dwError == ERROR_SUCCESS)
  5067. {
  5068. //
  5069. // Client gone, now remove from UI
  5070. //
  5071. spActiveLeases->RemoveChild(spActiveLeaseNode);
  5072. // if we are deleting a lot of addresses, then we can hit the server hard..
  5073. // lets take a short time out to smooth out the process
  5074. Sleep(5);
  5075. }
  5076. else
  5077. {
  5078. UtilCvtIpAddrToWstr(pActiveLease->GetIpAddress(), &strTemp);
  5079. AfxFormatString1(strMessage, IDS_ERROR_DELETING_RECORD, (LPCTSTR) strTemp);
  5080. if (::DhcpMessageBoxEx(dwError, strMessage, MB_OKCANCEL) == IDCANCEL)
  5081. {
  5082. break;
  5083. }
  5084. RESTORE_WAIT_CURSOR;
  5085. Trace1("DhcpDeleteClientInfo failed %lx\n", dwError);
  5086. hr = E_FAIL;
  5087. }
  5088. }
  5089. spActiveLeaseNode.Release();
  5090. }
  5091. // update stats
  5092. GetScopeObject(spActiveLeases)->TriggerStatsRefresh();
  5093. END_WAIT_CURSOR;
  5094. return hr;
  5095. }
  5096. /*---------------------------------------------------------------------------
  5097. CDhcpActiveLeases::DeleteClient
  5098. The reservations object will call this when a reservation is
  5099. deleted. Since a reservation also has an active lease record,
  5100. we have to delete it as well.
  5101. Author: EricDav
  5102. ---------------------------------------------------------------------------*/
  5103. DWORD
  5104. CDhcpActiveLeases::DeleteClient
  5105. (
  5106. ITFSNode * pActiveLeasesNode,
  5107. DHCP_IP_ADDRESS dhcpIpAddress
  5108. )
  5109. {
  5110. DWORD dwError = E_UNEXPECTED;
  5111. CDhcpActiveLease * pActiveLease = NULL;
  5112. SPITFSNodeEnum spNodeEnum;
  5113. SPITFSNode spCurrentNode;
  5114. ULONG nNumReturned = 0;
  5115. pActiveLeasesNode->GetEnum(&spNodeEnum);
  5116. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5117. while (nNumReturned)
  5118. {
  5119. pActiveLease = GETHANDLER(CDhcpActiveLease, spCurrentNode);
  5120. if (dhcpIpAddress == pActiveLease->GetIpAddress())
  5121. {
  5122. //
  5123. // Tell this reservation to delete itself
  5124. //
  5125. pActiveLeasesNode->RemoveChild(spCurrentNode);
  5126. spCurrentNode.Release();
  5127. dwError = ERROR_SUCCESS;
  5128. break;
  5129. }
  5130. spCurrentNode.Release();
  5131. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5132. }
  5133. return dwError;
  5134. }
  5135. /*!--------------------------------------------------------------------------
  5136. CDhcpActiveLeases::OnGetResultViewType
  5137. MMC calls this to get the result view information
  5138. Author: EricDav
  5139. ---------------------------------------------------------------------------*/
  5140. HRESULT CDhcpActiveLeases::OnGetResultViewType
  5141. (
  5142. ITFSComponent * pComponent,
  5143. MMC_COOKIE cookie,
  5144. LPOLESTR * ppViewType,
  5145. long * pViewOptions
  5146. )
  5147. {
  5148. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  5149. // we still want the default MMC result pane view, we just want
  5150. // multiselect, so return S_FALSE
  5151. return S_FALSE;
  5152. }
  5153. /*---------------------------------------------------------------------------
  5154. CDhcpActiveLeases::CompareItems
  5155. Description
  5156. Author: EricDav
  5157. ---------------------------------------------------------------------------*/
  5158. STDMETHODIMP_(int)
  5159. CDhcpActiveLeases::CompareItems
  5160. (
  5161. ITFSComponent * pComponent,
  5162. MMC_COOKIE cookieA,
  5163. MMC_COOKIE cookieB,
  5164. int nCol
  5165. )
  5166. {
  5167. SPITFSNode spNode1, spNode2;
  5168. m_spNodeMgr->FindNode(cookieA, &spNode1);
  5169. m_spNodeMgr->FindNode(cookieB, &spNode2);
  5170. int nCompare = 0;
  5171. CDhcpActiveLease *pDhcpAL1 = GETHANDLER(CDhcpActiveLease, spNode1);
  5172. CDhcpActiveLease *pDhcpAL2 = GETHANDLER(CDhcpActiveLease, spNode2);
  5173. switch (nCol)
  5174. {
  5175. case 0:
  5176. {
  5177. // IP address compare
  5178. //
  5179. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5180. }
  5181. break;
  5182. case 1:
  5183. {
  5184. // Client Name compare
  5185. //
  5186. CString strAL1 = pDhcpAL1->GetString(pComponent, cookieA, nCol);
  5187. CString strAL2 = pDhcpAL2->GetString(pComponent, cookieA, nCol);
  5188. nCompare = strAL1.CompareNoCase(strAL2);
  5189. }
  5190. break;
  5191. case 2:
  5192. {
  5193. // Lease expiration compare
  5194. //
  5195. BOOL bIsActive1, bIsActive2;
  5196. BOOL bIsBad1, bIsBad2;
  5197. BOOL bIsRes1 = pDhcpAL1->IsReservation(&bIsActive1, &bIsBad1);
  5198. BOOL bIsRes2 = pDhcpAL2->IsReservation(&bIsActive2, &bIsBad2);
  5199. //
  5200. // Check to see if these are reservations
  5201. //
  5202. if (bIsRes1 && bIsRes2)
  5203. {
  5204. //
  5205. // Figure out if this is a bad address
  5206. // They go first
  5207. //
  5208. if (bIsBad1 && bIsBad2)
  5209. {
  5210. //
  5211. // Sort by IP Address
  5212. //
  5213. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5214. }
  5215. else
  5216. if (bIsBad1)
  5217. nCompare = -1;
  5218. else
  5219. if (bIsBad2)
  5220. nCompare = 1;
  5221. else
  5222. if ((bIsActive1 && bIsActive2) ||
  5223. (!bIsActive1 && !bIsActive2))
  5224. {
  5225. //
  5226. // if both reservations are either active/inactive
  5227. // sort by IP address
  5228. //
  5229. nCompare = CompareIpAddresses(pDhcpAL1, pDhcpAL2);
  5230. }
  5231. else
  5232. if (bIsActive1)
  5233. nCompare = -1;
  5234. else
  5235. nCompare = 1;
  5236. }
  5237. else
  5238. if (bIsRes1)
  5239. {
  5240. nCompare = -1;
  5241. }
  5242. else
  5243. if (bIsRes2)
  5244. {
  5245. nCompare = 1;
  5246. }
  5247. else
  5248. {
  5249. CTime timeAL1, timeAL2;
  5250. pDhcpAL1->GetLeaseExpirationTime(timeAL1);
  5251. pDhcpAL2->GetLeaseExpirationTime(timeAL2);
  5252. if (timeAL1 < timeAL2)
  5253. nCompare = -1;
  5254. else
  5255. if (timeAL1 > timeAL2)
  5256. nCompare = 1;
  5257. }
  5258. // default is that they are equal
  5259. }
  5260. break;
  5261. case 3:
  5262. {
  5263. // Client Type Compare
  5264. CString strAL1 = pDhcpAL1->GetString(pComponent, cookieA, nCol);
  5265. CString strAL2 = pDhcpAL2->GetString(pComponent, cookieA, nCol);
  5266. nCompare = strAL1.Compare(strAL2);
  5267. }
  5268. break;
  5269. case 4:
  5270. {
  5271. CString strUID1 = pDhcpAL1->GetUID();
  5272. nCompare = strUID1.CompareNoCase(pDhcpAL2->GetUID());
  5273. }
  5274. break;
  5275. case 5:
  5276. {
  5277. CString strComment1 = pDhcpAL1->GetComment();
  5278. nCompare = strComment1.CompareNoCase(pDhcpAL2->GetComment());
  5279. }
  5280. break;
  5281. }
  5282. return nCompare;
  5283. }
  5284. /*---------------------------------------------------------------------------
  5285. Function Name Here
  5286. Description
  5287. Author: EricDav
  5288. ---------------------------------------------------------------------------*/
  5289. int
  5290. CDhcpActiveLeases::CompareIpAddresses
  5291. (
  5292. CDhcpActiveLease * pDhcpAL1,
  5293. CDhcpActiveLease * pDhcpAL2
  5294. )
  5295. {
  5296. int nCompare = 0;
  5297. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAL1->GetIpAddress();
  5298. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAL2->GetIpAddress();
  5299. if (dhcpIp1 < dhcpIp2)
  5300. nCompare = -1;
  5301. else
  5302. if (dhcpIp1 > dhcpIp2)
  5303. nCompare = 1;
  5304. return nCompare;
  5305. }
  5306. /*---------------------------------------------------------------------------
  5307. CDhcpActiveLeases::OnExportLeases()
  5308. -
  5309. Author: EricDav
  5310. ---------------------------------------------------------------------------*/
  5311. HRESULT
  5312. CDhcpActiveLeases::OnExportLeases(ITFSNode * pNode)
  5313. {
  5314. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  5315. HRESULT hr = hrOK;
  5316. // Bring up the Save Dialog
  5317. SPITFSNodeEnum spNodeEnum;
  5318. SPITFSNode spCurrentNode;
  5319. ULONG nNumReturned = 0;
  5320. CString strType;
  5321. CString strDefFileName;
  5322. CString strFilter;
  5323. CString strTitle;
  5324. CString strFileName;
  5325. strType.LoadString(IDS_FILE_EXTENSION);
  5326. strDefFileName.LoadString(IDS_FILE_DEFNAME);
  5327. strFilter.LoadString(IDS_STR_EXPORTFILE_FILTER);
  5328. CFileDialog cFileDlg(FALSE, strType, strDefFileName, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter);//_T("Comma Separated Files (*.csv)|*.csv||") );
  5329. strTitle.LoadString(IDS_EXPFILE_TITLE);
  5330. cFileDlg.m_ofn.lpstrTitle = strTitle;
  5331. // put up the file dialog
  5332. if( cFileDlg.DoModal() != IDOK )
  5333. return hrFalse;
  5334. strFileName = cFileDlg.GetPathName();
  5335. COM_PROTECT_TRY
  5336. {
  5337. CString strContent;
  5338. CString strLine;
  5339. CString strTemp;
  5340. CString strDelim = _T(',');
  5341. CString strNewLine = _T("\r\n");
  5342. int nCount = 0;
  5343. // create a file named "WinsExp.txt" in the current directory
  5344. CFile cFileExp(strFileName, CFile::modeCreate | CFile::modeRead | CFile::modeWrite);
  5345. // this is a unicode file, write the unicde lead bytes (2)
  5346. cFileExp.Write(&gwUnicodeHeader, sizeof(WORD));
  5347. // write the header
  5348. for (int i = 0; i < MAX_COLUMNS; i++)
  5349. {
  5350. if (aColumns[DHCPSNAP_ACTIVE_LEASES][i])
  5351. {
  5352. if (!strLine.IsEmpty())
  5353. strLine += strDelim;
  5354. strTemp.LoadString(aColumns[DHCPSNAP_ACTIVE_LEASES][i]);
  5355. strLine += strTemp;
  5356. }
  5357. }
  5358. strLine += strNewLine;
  5359. cFileExp.Write(strLine, strLine.GetLength()*sizeof(TCHAR));
  5360. cFileExp.SeekToEnd();
  5361. BEGIN_WAIT_CURSOR
  5362. #ifdef DEBUG
  5363. CTime timeStart, timeFinish;
  5364. timeStart = CTime::GetCurrentTime();
  5365. #endif
  5366. // enumerate all the leases and output
  5367. pNode->GetEnum(&spNodeEnum);
  5368. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5369. while (nNumReturned)
  5370. {
  5371. CDhcpActiveLease * pLease = GETHANDLER(CDhcpActiveLease, spCurrentNode);
  5372. strLine.Empty();
  5373. // ipaddr, name, type, lease exp, UID, comment
  5374. for (int j = 0; j < 6; j++)
  5375. {
  5376. if (!strLine.IsEmpty())
  5377. strLine += strDelim;
  5378. strLine += pLease->GetString(NULL, NULL, j);
  5379. }
  5380. strLine += strNewLine;
  5381. strContent += strLine;
  5382. nCount++;
  5383. //optimize
  5384. // write to the file for every 1000 records converted
  5385. if( nCount % 1000 == 0)
  5386. {
  5387. cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) );
  5388. cFileExp.SeekToEnd();
  5389. // clear all the strings now
  5390. strContent.Empty();
  5391. }
  5392. spCurrentNode.Release();
  5393. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  5394. }
  5395. // write to the file
  5396. cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) );
  5397. cFileExp.Close();
  5398. #ifdef DEBUG
  5399. timeFinish = CTime::GetCurrentTime();
  5400. CTimeSpan timeDelta = timeFinish - timeStart;
  5401. Trace2("ActiveLeases - Export Entries: %d records written, total time %s\n", nCount, timeDelta.Format(_T("%H:%M:%S")));
  5402. #endif
  5403. END_WAIT_CURSOR
  5404. }
  5405. COM_PROTECT_CATCH
  5406. CString strDisp;
  5407. AfxFormatString1(strDisp, IDS_EXPORT_SUCCESS, strFileName);
  5408. AfxMessageBox(strDisp, MB_ICONINFORMATION );
  5409. return hr;
  5410. }
  5411. /*---------------------------------------------------------------------------
  5412. Background thread functionality
  5413. ---------------------------------------------------------------------------*/
  5414. /*---------------------------------------------------------------------------
  5415. CDhcpActiveLeases::OnCreateQuery()
  5416. Description
  5417. Author: EricDav
  5418. ---------------------------------------------------------------------------*/
  5419. ITFSQueryObject*
  5420. CDhcpActiveLeases::OnCreateQuery(ITFSNode * pNode)
  5421. {
  5422. CDhcpActiveLeasesQueryObj* pQuery =
  5423. new CDhcpActiveLeasesQueryObj(m_spTFSCompData, m_spNodeMgr);
  5424. pQuery->m_strServer = GetServerIpAddress(pNode);
  5425. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  5426. pQuery->m_dhcpResumeHandle = NULL;
  5427. pQuery->m_dwPreferredMax = 2000;
  5428. GetServerVersion(pNode, pQuery->m_liDhcpVersion);
  5429. return pQuery;
  5430. }
  5431. /*---------------------------------------------------------------------------
  5432. CDhcpActiveLeasesQueryObj::Execute()
  5433. Description
  5434. Author: EricDav
  5435. ---------------------------------------------------------------------------*/
  5436. STDMETHODIMP
  5437. CDhcpActiveLeasesQueryObj::Execute()
  5438. {
  5439. HRESULT hr;
  5440. BuildReservationList();
  5441. if (m_liDhcpVersion.QuadPart >= DHCP_NT5_VERSION)
  5442. {
  5443. hr = EnumerateLeasesV5();
  5444. }
  5445. else
  5446. if (m_liDhcpVersion.QuadPart >= DHCP_SP2_VERSION)
  5447. {
  5448. hr = EnumerateLeasesV4();
  5449. }
  5450. else
  5451. {
  5452. hr = EnumerateLeases();
  5453. }
  5454. return hr;
  5455. }
  5456. /*---------------------------------------------------------------------------
  5457. CDhcpActiveLeasesQueryObj::IsReservation()
  5458. Description
  5459. Author: EricDav
  5460. ---------------------------------------------------------------------------*/
  5461. BOOL
  5462. CDhcpActiveLeasesQueryObj::IsReservation(DWORD dwIp)
  5463. {
  5464. BOOL fIsRes = FALSE;
  5465. for (int i = 0; i < m_ReservationArray.GetSize(); i++)
  5466. {
  5467. if (m_ReservationArray[i] == dwIp)
  5468. {
  5469. fIsRes = TRUE;
  5470. break;
  5471. }
  5472. }
  5473. return fIsRes;
  5474. }
  5475. /*---------------------------------------------------------------------------
  5476. CDhcpActiveLeasesQueryObj::BuildReservationList()
  5477. Description
  5478. Author: EricDav
  5479. ---------------------------------------------------------------------------*/
  5480. HRESULT
  5481. CDhcpActiveLeasesQueryObj::BuildReservationList()
  5482. {
  5483. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  5484. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  5485. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  5486. DWORD dwError = ERROR_MORE_DATA;
  5487. while (dwError == ERROR_MORE_DATA)
  5488. {
  5489. dwError = ::DhcpEnumSubnetElements(((LPWSTR) (LPCTSTR)m_strServer),
  5490. m_dhcpScopeAddress,
  5491. DhcpReservedIps,
  5492. &dhcpResumeHandle,
  5493. -1,
  5494. &pdhcpSubnetElementArray,
  5495. &dwElementsRead,
  5496. &dwElementsTotal);
  5497. Trace3("BuildReservationList: Scope %lx Reservations read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  5498. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  5499. {
  5500. //
  5501. // Loop through the array that was returned
  5502. //
  5503. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  5504. {
  5505. m_ReservationArray.Add(pdhcpSubnetElementArray->Elements[i].Element.ReservedIp->ReservedIpAddress);
  5506. }
  5507. }
  5508. // Check the abort flag on the thread
  5509. if (FCheckForAbort() == hrOK)
  5510. break;
  5511. // check to see if we have an error and post it to the main thread if we do..
  5512. if (dwError != ERROR_NO_MORE_ITEMS &&
  5513. dwError != ERROR_SUCCESS &&
  5514. dwError != ERROR_MORE_DATA)
  5515. {
  5516. Trace1("DHCP snapin: BuildReservationList error: %d\n", dwError);
  5517. m_dwErr = dwError;
  5518. PostError(dwError);
  5519. }
  5520. }
  5521. return hrFalse;
  5522. }
  5523. /*---------------------------------------------------------------------------
  5524. CDhcpActiveLeasesQueryObj::EnumerateLeasesV5()
  5525. Description
  5526. Author: EricDav
  5527. ---------------------------------------------------------------------------*/
  5528. HRESULT
  5529. CDhcpActiveLeasesQueryObj::EnumerateLeasesV5()
  5530. {
  5531. DWORD dwError = ERROR_MORE_DATA;
  5532. LPDHCP_CLIENT_INFO_ARRAY_V5 pdhcpClientArrayV5 = NULL;
  5533. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5534. DWORD dwEnumedClients = 0;
  5535. while (dwError == ERROR_MORE_DATA)
  5536. {
  5537. dwError = ::DhcpEnumSubnetClientsV5(((LPWSTR) (LPCTSTR)m_strServer),
  5538. m_dhcpScopeAddress,
  5539. &m_dhcpResumeHandle,
  5540. m_dwPreferredMax,
  5541. &pdhcpClientArrayV5,
  5542. &dwClientsRead,
  5543. &dwClientsTotal);
  5544. if (dwClientsRead && dwClientsTotal && pdhcpClientArrayV5)
  5545. {
  5546. //
  5547. // loop through all of the elements that were returned
  5548. //
  5549. for (DWORD i = 0; i < dwClientsRead; i++)
  5550. {
  5551. CDhcpActiveLease * pDhcpActiveLease;
  5552. //
  5553. // Create the result pane item for this element
  5554. //
  5555. SPITFSNode spNode;
  5556. pDhcpActiveLease =
  5557. new CDhcpActiveLease(m_spTFSCompData, pdhcpClientArrayV5->Clients[i]);
  5558. // filter these types of records out
  5559. if (pDhcpActiveLease->IsUnreg())
  5560. {
  5561. delete pDhcpActiveLease;
  5562. continue;
  5563. }
  5564. if (IsReservation(pdhcpClientArrayV5->Clients[i]->ClientIpAddress))
  5565. pDhcpActiveLease->SetReservation(TRUE);
  5566. CreateLeafTFSNode(&spNode,
  5567. &GUID_DhcpActiveLeaseNodeType,
  5568. pDhcpActiveLease,
  5569. pDhcpActiveLease,
  5570. m_spNodeMgr);
  5571. // Tell the handler to initialize any specific data
  5572. pDhcpActiveLease->InitializeNode(spNode);
  5573. AddToQueue(spNode);
  5574. pDhcpActiveLease->Release();
  5575. }
  5576. ::DhcpRpcFreeMemory(pdhcpClientArrayV5);
  5577. dwEnumedClients += dwClientsRead;
  5578. dwClientsRead = 0;
  5579. dwClientsTotal = 0;
  5580. pdhcpClientArrayV5 = NULL;
  5581. }
  5582. // Check the abort flag on the thread
  5583. if (FCheckForAbort() == hrOK)
  5584. break;
  5585. // check to see if we have an error and post it to the main thread if we do..
  5586. if (dwError != ERROR_NO_MORE_ITEMS &&
  5587. dwError != ERROR_SUCCESS &&
  5588. dwError != ERROR_MORE_DATA)
  5589. {
  5590. Trace1("DHCP snapin: EnumerateLeasesV5 error: %d\n", dwError);
  5591. m_dwErr = dwError;
  5592. PostError(dwError);
  5593. }
  5594. }
  5595. Trace1("DHCP snapin: V5 Leases enumerated: %d\n", dwEnumedClients);
  5596. return hrFalse;
  5597. }
  5598. /*---------------------------------------------------------------------------
  5599. CDhcpActiveLeasesQueryObj::EnumerateLeasesV4()
  5600. Description
  5601. Author: EricDav
  5602. ---------------------------------------------------------------------------*/
  5603. HRESULT
  5604. CDhcpActiveLeasesQueryObj::EnumerateLeasesV4()
  5605. {
  5606. DWORD dwError = ERROR_MORE_DATA;
  5607. LPDHCP_CLIENT_INFO_ARRAY_V4 pdhcpClientArrayV4 = NULL;
  5608. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5609. DWORD dwEnumedClients = 0;
  5610. while (dwError == ERROR_MORE_DATA)
  5611. {
  5612. dwError = ::DhcpEnumSubnetClientsV4(((LPWSTR) (LPCTSTR)m_strServer),
  5613. m_dhcpScopeAddress,
  5614. &m_dhcpResumeHandle,
  5615. m_dwPreferredMax,
  5616. &pdhcpClientArrayV4,
  5617. &dwClientsRead,
  5618. &dwClientsTotal);
  5619. if (dwClientsRead && dwClientsTotal && pdhcpClientArrayV4)
  5620. {
  5621. //
  5622. // loop through all of the elements that were returned
  5623. //
  5624. //for (DWORD i = 0; i < pdhcpClientArrayV4->NumElements; i++)
  5625. for (DWORD i = 0; i < dwClientsRead; i++)
  5626. {
  5627. CDhcpActiveLease * pDhcpActiveLease;
  5628. //
  5629. // Create the result pane item for this element
  5630. //
  5631. SPITFSNode spNode;
  5632. pDhcpActiveLease =
  5633. new CDhcpActiveLease(m_spTFSCompData, pdhcpClientArrayV4->Clients[i]);
  5634. // filter these types of records out
  5635. if (pDhcpActiveLease->IsGhost() ||
  5636. pDhcpActiveLease->IsUnreg() ||
  5637. pDhcpActiveLease->IsDoomed() )
  5638. {
  5639. delete pDhcpActiveLease;
  5640. continue;
  5641. }
  5642. if (IsReservation(pdhcpClientArrayV4->Clients[i]->ClientIpAddress))
  5643. pDhcpActiveLease->SetReservation(TRUE);
  5644. CreateLeafTFSNode(&spNode,
  5645. &GUID_DhcpActiveLeaseNodeType,
  5646. pDhcpActiveLease,
  5647. pDhcpActiveLease,
  5648. m_spNodeMgr);
  5649. // Tell the handler to initialize any specific data
  5650. pDhcpActiveLease->InitializeNode(spNode);
  5651. AddToQueue(spNode);
  5652. pDhcpActiveLease->Release();
  5653. }
  5654. ::DhcpRpcFreeMemory(pdhcpClientArrayV4);
  5655. dwEnumedClients += dwClientsRead;
  5656. dwClientsRead = 0;
  5657. dwClientsTotal = 0;
  5658. pdhcpClientArrayV4 = NULL;
  5659. }
  5660. // Check the abort flag on the thread
  5661. if (FCheckForAbort() == hrOK)
  5662. break;
  5663. // check to see if we have an error and post it to the main thread if we do..
  5664. if (dwError != ERROR_NO_MORE_ITEMS &&
  5665. dwError != ERROR_SUCCESS &&
  5666. dwError != ERROR_MORE_DATA)
  5667. {
  5668. Trace1("DHCP snapin: EnumerateLeasesV4 error: %d\n", dwError);
  5669. m_dwErr = dwError;
  5670. PostError(dwError);
  5671. }
  5672. }
  5673. Trace1("DHCP snapin: V4 Leases enumerated: %d\n", dwEnumedClients);
  5674. return hrFalse;
  5675. }
  5676. /*---------------------------------------------------------------------------
  5677. CDhcpActiveLeasesQueryObj::EnumerateLeases()
  5678. Description
  5679. Author: EricDav
  5680. ---------------------------------------------------------------------------*/
  5681. HRESULT
  5682. CDhcpActiveLeasesQueryObj::EnumerateLeases()
  5683. {
  5684. DWORD dwError = ERROR_MORE_DATA;
  5685. LPDHCP_CLIENT_INFO_ARRAY pdhcpClientArray = NULL;
  5686. DWORD dwClientsRead = 0, dwClientsTotal = 0;
  5687. DWORD dwEnumedClients = 0;
  5688. while (dwError == ERROR_MORE_DATA)
  5689. {
  5690. dwError = ::DhcpEnumSubnetClients(((LPWSTR) (LPCTSTR)m_strServer),
  5691. m_dhcpScopeAddress,
  5692. &m_dhcpResumeHandle,
  5693. m_dwPreferredMax,
  5694. &pdhcpClientArray,
  5695. &dwClientsRead,
  5696. &dwClientsTotal);
  5697. if (dwClientsRead && dwClientsTotal && pdhcpClientArray)
  5698. {
  5699. //
  5700. // loop through all of the elements that were returned
  5701. //
  5702. for (DWORD i = 0; i < pdhcpClientArray->NumElements; i++)
  5703. {
  5704. CDhcpActiveLease * pDhcpActiveLease;
  5705. //
  5706. // Create the result pane item for this element
  5707. //
  5708. SPITFSNode spNode;
  5709. pDhcpActiveLease =
  5710. new CDhcpActiveLease(m_spTFSCompData,pdhcpClientArray->Clients[i]);
  5711. // filter these types of records out
  5712. if (pDhcpActiveLease->IsGhost() ||
  5713. pDhcpActiveLease->IsUnreg() ||
  5714. pDhcpActiveLease->IsDoomed() )
  5715. {
  5716. delete pDhcpActiveLease;
  5717. continue;
  5718. }
  5719. if (IsReservation(pdhcpClientArray->Clients[i]->ClientIpAddress))
  5720. pDhcpActiveLease->SetReservation(TRUE);
  5721. CreateLeafTFSNode(&spNode,
  5722. &GUID_DhcpActiveLeaseNodeType,
  5723. pDhcpActiveLease,
  5724. pDhcpActiveLease,
  5725. m_spNodeMgr);
  5726. // Tell the handler to initialize any specific data
  5727. pDhcpActiveLease->InitializeNode(spNode);
  5728. AddToQueue(spNode);
  5729. pDhcpActiveLease->Release();
  5730. }
  5731. ::DhcpRpcFreeMemory(pdhcpClientArray);
  5732. dwEnumedClients += dwClientsRead;
  5733. dwClientsRead = 0;
  5734. dwClientsTotal = 0;
  5735. pdhcpClientArray = NULL;
  5736. }
  5737. // Check the abort flag on the thread
  5738. if (FCheckForAbort() == hrOK)
  5739. break;
  5740. // check to see if we have an error and post it to the main thread if we do..
  5741. if (dwError != ERROR_NO_MORE_ITEMS &&
  5742. dwError != ERROR_SUCCESS &&
  5743. dwError != ERROR_MORE_DATA)
  5744. {
  5745. Trace1("DHCP snapin: EnumerateLeases error: %d\n", dwError);
  5746. m_dwErr = dwError;
  5747. PostError(dwError);
  5748. }
  5749. }
  5750. Trace1("DHCP snpain: Leases enumerated: %d\n", dwEnumedClients);
  5751. return hrFalse;
  5752. }
  5753. /*---------------------------------------------------------------------------
  5754. Class CDhcpAddressPool implementation
  5755. ---------------------------------------------------------------------------*/
  5756. /*---------------------------------------------------------------------------
  5757. Function Name Here
  5758. Description
  5759. Author: EricDav
  5760. ---------------------------------------------------------------------------*/
  5761. CDhcpAddressPool::CDhcpAddressPool
  5762. (
  5763. ITFSComponentData * pComponentData
  5764. ) : CMTDhcpHandler(pComponentData)
  5765. {
  5766. }
  5767. CDhcpAddressPool::~CDhcpAddressPool()
  5768. {
  5769. }
  5770. /*!--------------------------------------------------------------------------
  5771. CDhcpAddressPool::InitializeNode
  5772. Initializes node specific data
  5773. Author: EricDav
  5774. ---------------------------------------------------------------------------*/
  5775. HRESULT
  5776. CDhcpAddressPool::InitializeNode
  5777. (
  5778. ITFSNode * pNode
  5779. )
  5780. {
  5781. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5782. HRESULT hr = hrOK;
  5783. //
  5784. // Create the display name for this scope
  5785. //
  5786. CString strTemp;
  5787. strTemp.LoadString(IDS_ADDRESS_POOL_FOLDER);
  5788. SetDisplayName(strTemp);
  5789. // Make the node immediately visible
  5790. pNode->SetVisibilityState(TFS_VIS_SHOW);
  5791. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  5792. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  5793. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  5794. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  5795. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_ADDRESS_POOL);
  5796. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  5797. SetColumnStringIDs(&aColumns[DHCPSNAP_ADDRESS_POOL][0]);
  5798. SetColumnWidths(&aColumnWidths[DHCPSNAP_ADDRESS_POOL][0]);
  5799. return hr;
  5800. }
  5801. /*---------------------------------------------------------------------------
  5802. CDhcpAddressPool::OnCreateNodeId2
  5803. Returns a unique string for this node
  5804. Author: EricDav
  5805. ---------------------------------------------------------------------------*/
  5806. HRESULT CDhcpAddressPool::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  5807. {
  5808. const GUID * pGuid = pNode->GetNodeType();
  5809. CString strIpAddress, strGuid;
  5810. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  5811. strGuid.ReleaseBuffer();
  5812. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  5813. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  5814. strId = GetServerName(pNode) + strIpAddress + strGuid;
  5815. return hrOK;
  5816. }
  5817. /*---------------------------------------------------------------------------
  5818. CDhcpAddressPool::GetImageIndex
  5819. Description
  5820. Author: EricDav
  5821. ---------------------------------------------------------------------------*/
  5822. int
  5823. CDhcpAddressPool::GetImageIndex(BOOL bOpenImage)
  5824. {
  5825. int nIndex = -1;
  5826. switch (m_nState)
  5827. {
  5828. case notLoaded:
  5829. case loaded:
  5830. if (bOpenImage)
  5831. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN;
  5832. else
  5833. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED;
  5834. break;
  5835. case loading:
  5836. if (bOpenImage)
  5837. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_BUSY;
  5838. else
  5839. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_BUSY;
  5840. break;
  5841. case unableToLoad:
  5842. if (bOpenImage)
  5843. nIndex = ICON_IDX_ADDR_POOL_FOLDER_OPEN_LOST_CONNECTION;
  5844. else
  5845. nIndex = ICON_IDX_ADDR_POOL_FOLDER_CLOSED_LOST_CONNECTION;
  5846. break;
  5847. default:
  5848. ASSERT(FALSE);
  5849. }
  5850. return nIndex;
  5851. }
  5852. /*---------------------------------------------------------------------------
  5853. Overridden base handler functions
  5854. ---------------------------------------------------------------------------*/
  5855. /*---------------------------------------------------------------------------
  5856. CDhcpAddressPool::OnAddMenuItems
  5857. Adds entries to the context sensitive menu
  5858. Author: EricDav
  5859. ---------------------------------------------------------------------------*/
  5860. STDMETHODIMP
  5861. CDhcpAddressPool::OnAddMenuItems
  5862. (
  5863. ITFSNode * pNode,
  5864. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  5865. LPDATAOBJECT lpDataObject,
  5866. DATA_OBJECT_TYPES type,
  5867. DWORD dwType,
  5868. long * pInsertionAllowed
  5869. )
  5870. {
  5871. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5872. LONG fFlags = 0;
  5873. HRESULT hr = S_OK;
  5874. CString strMenuText;
  5875. if ( (m_nState != loaded) )
  5876. {
  5877. fFlags |= MF_GRAYED;
  5878. }
  5879. if (type == CCT_SCOPE)
  5880. {
  5881. // these menu items go in the new menu,
  5882. // only visible from scope pane
  5883. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  5884. {
  5885. strMenuText.LoadString(IDS_CREATE_NEW_EXCLUSION);
  5886. hr = LoadAndAddMenuItem( pContextMenuCallback,
  5887. strMenuText,
  5888. IDS_CREATE_NEW_EXCLUSION,
  5889. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  5890. fFlags );
  5891. ASSERT( SUCCEEDED(hr) );
  5892. }
  5893. }
  5894. return hr;
  5895. }
  5896. /*---------------------------------------------------------------------------
  5897. CDhcpAddressPool::OnCommand
  5898. Description
  5899. Author: EricDav
  5900. ---------------------------------------------------------------------------*/
  5901. STDMETHODIMP
  5902. CDhcpAddressPool::OnCommand
  5903. (
  5904. ITFSNode * pNode,
  5905. long nCommandId,
  5906. DATA_OBJECT_TYPES type,
  5907. LPDATAOBJECT pDataObject,
  5908. DWORD dwType
  5909. )
  5910. {
  5911. HRESULT hr = S_OK;
  5912. switch (nCommandId)
  5913. {
  5914. case IDS_CREATE_NEW_EXCLUSION:
  5915. OnCreateNewExclusion(pNode);
  5916. break;
  5917. case IDS_REFRESH:
  5918. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  5919. break;
  5920. default:
  5921. break;
  5922. }
  5923. return hr;
  5924. }
  5925. /*---------------------------------------------------------------------------
  5926. Message handlers
  5927. ---------------------------------------------------------------------------*/
  5928. /*---------------------------------------------------------------------------
  5929. CDhcpAddressPool::OnCreateNewExclusion
  5930. Description
  5931. Author: EricDav
  5932. ---------------------------------------------------------------------------*/
  5933. DWORD
  5934. CDhcpAddressPool::OnCreateNewExclusion
  5935. (
  5936. ITFSNode * pNode
  5937. )
  5938. {
  5939. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  5940. SPITFSNode spScopeNode;
  5941. pNode->GetParent(&spScopeNode);
  5942. CAddExclusion dlgAddExclusion(spScopeNode);
  5943. dlgAddExclusion.DoModal();
  5944. return 0;
  5945. }
  5946. /*---------------------------------------------------------------------------
  5947. CDhcpAddressPool::OnResultDelete
  5948. This function is called when we are supposed to delete result
  5949. pane items. We build a list of selected items and then delete them.
  5950. Author: EricDav
  5951. ---------------------------------------------------------------------------*/
  5952. HRESULT
  5953. CDhcpAddressPool::OnResultDelete
  5954. (
  5955. ITFSComponent * pComponent,
  5956. LPDATAOBJECT pDataObject,
  5957. MMC_COOKIE cookie,
  5958. LPARAM arg,
  5959. LPARAM param
  5960. )
  5961. {
  5962. HRESULT hr = NOERROR;
  5963. BOOL bIsRes, bIsActive, bBadAddress;
  5964. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  5965. // translate the cookie into a node pointer
  5966. SPITFSNode spAddressPool, spSelectedNode;
  5967. m_spNodeMgr->FindNode(cookie, &spAddressPool);
  5968. pComponent->GetSelectedNode(&spSelectedNode);
  5969. Assert(spSelectedNode == spAddressPool);
  5970. if (spSelectedNode != spAddressPool)
  5971. return hr;
  5972. // build the list of selected nodes
  5973. CTFSNodeList listNodesToDelete;
  5974. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  5975. //
  5976. // Confirm with the user
  5977. //
  5978. CString strMessage, strTemp;
  5979. int nNodes = (int)listNodesToDelete.GetCount();
  5980. if (nNodes > 1)
  5981. {
  5982. strTemp.Format(_T("%d"), nNodes);
  5983. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  5984. }
  5985. else
  5986. {
  5987. strMessage.LoadString(IDS_DELETE_ITEM);
  5988. }
  5989. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  5990. {
  5991. return NOERROR;
  5992. }
  5993. //
  5994. // Loop through all items deleting
  5995. //
  5996. BEGIN_WAIT_CURSOR;
  5997. while (listNodesToDelete.GetCount() > 0)
  5998. {
  5999. SPITFSNode spExclusionRangeNode;
  6000. spExclusionRangeNode = listNodesToDelete.RemoveHead();
  6001. CDhcpExclusionRange * pExclusion = GETHANDLER(CDhcpExclusionRange, spExclusionRangeNode);
  6002. if (spExclusionRangeNode->GetData(TFS_DATA_TYPE) == DHCPSNAP_ALLOCATION_RANGE)
  6003. {
  6004. //
  6005. // This is the allocation range, can't delete
  6006. //
  6007. AfxMessageBox(IDS_CANNOT_DELETE_ALLOCATION_RANGE);
  6008. spExclusionRangeNode.Release();
  6009. continue;
  6010. }
  6011. //
  6012. // Try to remove it from the server
  6013. //
  6014. CDhcpIpRange dhcpIpRange((DHCP_IP_RANGE) *pExclusion);
  6015. DWORD dwError = GetScopeObject(spAddressPool)->RemoveExclusion(dhcpIpRange);
  6016. if (dwError != 0)
  6017. {
  6018. ::DhcpMessageBox(dwError);
  6019. RESTORE_WAIT_CURSOR;
  6020. hr = E_FAIL;
  6021. continue;
  6022. }
  6023. //
  6024. // Remove from UI now
  6025. //
  6026. spAddressPool->RemoveChild(spExclusionRangeNode);
  6027. spExclusionRangeNode.Release();
  6028. }
  6029. // update stats
  6030. GetScopeObject(spAddressPool)->TriggerStatsRefresh();
  6031. END_WAIT_CURSOR;
  6032. return hr;
  6033. }
  6034. /*!--------------------------------------------------------------------------
  6035. CDhcpAddressPool::OnGetResultViewType
  6036. MMC calls this to get the result view information
  6037. Author: EricDav
  6038. ---------------------------------------------------------------------------*/
  6039. HRESULT
  6040. CDhcpAddressPool::OnGetResultViewType
  6041. (
  6042. ITFSComponent * pComponent,
  6043. MMC_COOKIE cookie,
  6044. LPOLESTR * ppViewType,
  6045. long * pViewOptions
  6046. )
  6047. {
  6048. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  6049. // we still want the default MMC result pane view, we just want
  6050. // multiselect, so return S_FALSE
  6051. return S_FALSE;
  6052. }
  6053. /*---------------------------------------------------------------------------
  6054. Background thread functionality
  6055. ---------------------------------------------------------------------------*/
  6056. /*---------------------------------------------------------------------------
  6057. CDhcpAddressPool::OnCreateQuery()
  6058. Description
  6059. Author: EricDav
  6060. ---------------------------------------------------------------------------*/
  6061. ITFSQueryObject*
  6062. CDhcpAddressPool::OnCreateQuery(ITFSNode * pNode)
  6063. {
  6064. CDhcpAddressPoolQueryObj* pQuery =
  6065. new CDhcpAddressPoolQueryObj(m_spTFSCompData, m_spNodeMgr);
  6066. pQuery->m_strServer = GetServerIpAddress(pNode);
  6067. CDhcpScope * pScope = GetScopeObject(pNode);
  6068. if (pScope)
  6069. {
  6070. pQuery->m_dhcpScopeAddress = pScope->GetAddress();
  6071. pQuery->m_fSupportsDynBootp = pScope->GetServerObject()->FSupportsDynBootp();
  6072. }
  6073. pQuery->m_dhcpExclResumeHandle = NULL;
  6074. pQuery->m_dwExclPreferredMax = 0xFFFFFFFF;
  6075. pQuery->m_dhcpIpResumeHandle = NULL;
  6076. pQuery->m_dwIpPreferredMax = 0xFFFFFFFF;
  6077. return pQuery;
  6078. }
  6079. /*---------------------------------------------------------------------------
  6080. CDhcpAddressPoolQueryObj::Execute()
  6081. Description
  6082. Author: EricDav
  6083. ---------------------------------------------------------------------------*/
  6084. STDMETHODIMP
  6085. CDhcpAddressPoolQueryObj::Execute()
  6086. {
  6087. HRESULT hr1 = EnumerateIpRanges();
  6088. HRESULT hr2 = EnumerateExcludedIpRanges();
  6089. if (hr1 == hrOK || hr2 == hrOK)
  6090. return hrOK;
  6091. else
  6092. return hrFalse;
  6093. }
  6094. /*---------------------------------------------------------------------------
  6095. Function Name Here
  6096. Description
  6097. Author: EricDav
  6098. ---------------------------------------------------------------------------*/
  6099. HRESULT
  6100. CDhcpAddressPoolQueryObj::EnumerateExcludedIpRanges()
  6101. {
  6102. DWORD dwError = ERROR_MORE_DATA;
  6103. DHCP_RESUME_HANDLE dhcpResumeHandle = 0;
  6104. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  6105. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6106. while (dwError == ERROR_MORE_DATA)
  6107. {
  6108. dwError = ::DhcpEnumSubnetElements((LPWSTR) ((LPCTSTR) m_strServer),
  6109. m_dhcpScopeAddress,
  6110. DhcpExcludedIpRanges,
  6111. &m_dhcpExclResumeHandle,
  6112. m_dwExclPreferredMax,
  6113. &pdhcpSubnetElementArray,
  6114. &dwElementsRead,
  6115. &dwElementsTotal);
  6116. Trace3("Scope %lx Excluded Ip Ranges read %d, total %d\n", m_dhcpScopeAddress, dwElementsRead, dwElementsTotal);
  6117. if (dwElementsRead && dwElementsTotal && pdhcpSubnetElementArray)
  6118. {
  6119. //
  6120. // loop through all of the elements that were returned
  6121. //
  6122. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6123. {
  6124. //
  6125. // Create the result pane item for this element
  6126. //
  6127. SPITFSNode spNode;
  6128. CDhcpExclusionRange * pDhcpExclusionRange =
  6129. new CDhcpExclusionRange(m_spTFSCompData,
  6130. pdhcpSubnetElementArray->Elements[i].Element.ExcludeIpRange);
  6131. CreateLeafTFSNode(&spNode,
  6132. &GUID_DhcpExclusionNodeType,
  6133. pDhcpExclusionRange,
  6134. pDhcpExclusionRange,
  6135. m_spNodeMgr);
  6136. // Tell the handler to initialize any specific data
  6137. pDhcpExclusionRange->InitializeNode(spNode);
  6138. AddToQueue(spNode);
  6139. pDhcpExclusionRange->Release();
  6140. }
  6141. // Free up the memory from the RPC call
  6142. //
  6143. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6144. }
  6145. // Check the abort flag on the thread
  6146. if (FCheckForAbort() == hrOK)
  6147. break;
  6148. // check to see if we have an error and post it to the main thread if we do..
  6149. if (dwError != ERROR_NO_MORE_ITEMS &&
  6150. dwError != ERROR_SUCCESS &&
  6151. dwError != ERROR_MORE_DATA)
  6152. {
  6153. Trace1("DHCP snapin: EnumerateExcludedIpRanges error: %d\n", dwError);
  6154. m_dwErr = dwError;
  6155. PostError(dwError);
  6156. }
  6157. }
  6158. return hrFalse;
  6159. }
  6160. /*---------------------------------------------------------------------------
  6161. Function Name Here
  6162. Description
  6163. Author: EricDav
  6164. ---------------------------------------------------------------------------*/
  6165. HRESULT
  6166. CDhcpAddressPoolQueryObj::EnumerateIpRanges()
  6167. {
  6168. DWORD dwError = ERROR_MORE_DATA;
  6169. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY pdhcpSubnetElementArray = NULL;
  6170. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6171. if (m_fSupportsDynBootp)
  6172. {
  6173. return EnumerateIpRangesV5();
  6174. }
  6175. while (dwError == ERROR_MORE_DATA)
  6176. {
  6177. dwError = ::DhcpEnumSubnetElements((LPWSTR) ((LPCTSTR) m_strServer),
  6178. m_dhcpScopeAddress,
  6179. DhcpIpRanges,
  6180. &m_dhcpIpResumeHandle,
  6181. m_dwIpPreferredMax,
  6182. &pdhcpSubnetElementArray,
  6183. &dwElementsRead,
  6184. &dwElementsTotal);
  6185. Trace4("Scope %lx allocation ranges read %d, total %d, dwError = %lx\n",
  6186. m_dhcpScopeAddress, dwElementsRead, dwElementsTotal, dwError);
  6187. if ((dwError == ERROR_MORE_DATA) ||
  6188. ( (dwElementsRead) && (dwError == ERROR_SUCCESS) ))
  6189. {
  6190. //
  6191. // Loop through the array that was returned
  6192. //
  6193. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6194. {
  6195. //
  6196. // Create the result pane item for this element
  6197. //
  6198. SPITFSNode spNode;
  6199. CDhcpAllocationRange * pDhcpAllocRange =
  6200. new CDhcpAllocationRange(m_spTFSCompData,
  6201. pdhcpSubnetElementArray->Elements[i].Element.IpRange);
  6202. CreateLeafTFSNode(&spNode,
  6203. &GUID_DhcpAllocationNodeType,
  6204. pDhcpAllocRange,
  6205. pDhcpAllocRange,
  6206. m_spNodeMgr);
  6207. // Tell the handler to initialize any specific data
  6208. pDhcpAllocRange->InitializeNode(spNode);
  6209. AddToQueue(spNode);
  6210. pDhcpAllocRange->Release();
  6211. }
  6212. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6213. }
  6214. else
  6215. if (dwError != ERROR_SUCCESS &&
  6216. dwError != ERROR_NO_MORE_ITEMS)
  6217. {
  6218. // set the error variable so that it can be looked at later
  6219. m_dwError = dwError;
  6220. }
  6221. // Check the abort flag on the thread
  6222. if (FCheckForAbort() == hrOK)
  6223. break;
  6224. // check to see if we have an error and post it to the main thread if we do..
  6225. if (dwError != ERROR_NO_MORE_ITEMS &&
  6226. dwError != ERROR_SUCCESS &&
  6227. dwError != ERROR_MORE_DATA)
  6228. {
  6229. Trace1("DHCP snapin: EnumerateAllocationRanges error: %d\n", dwError);
  6230. m_dwErr = dwError;
  6231. PostError(dwError);
  6232. }
  6233. }
  6234. return hrFalse;
  6235. }
  6236. HRESULT
  6237. CDhcpAddressPoolQueryObj::EnumerateIpRangesV5()
  6238. {
  6239. DWORD dwError = ERROR_MORE_DATA;
  6240. LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V5 pdhcpSubnetElementArray = NULL;
  6241. DWORD dwElementsRead = 0, dwElementsTotal = 0;
  6242. while (dwError == ERROR_MORE_DATA)
  6243. {
  6244. dwError = ::DhcpEnumSubnetElementsV5((LPWSTR) ((LPCTSTR) m_strServer),
  6245. m_dhcpScopeAddress,
  6246. DhcpIpRangesDhcpBootp,
  6247. &m_dhcpIpResumeHandle,
  6248. m_dwIpPreferredMax,
  6249. &pdhcpSubnetElementArray,
  6250. &dwElementsRead,
  6251. &dwElementsTotal);
  6252. Trace4("EnumerateIpRangesV5: Scope %lx allocation ranges read %d, total %d, dwError = %lx\n",
  6253. m_dhcpScopeAddress, dwElementsRead, dwElementsTotal, dwError);
  6254. if ((dwError == ERROR_MORE_DATA) ||
  6255. ( (dwElementsRead) && (dwError == ERROR_SUCCESS) ))
  6256. {
  6257. //
  6258. // Loop through the array that was returned
  6259. //
  6260. for (DWORD i = 0; i < pdhcpSubnetElementArray->NumElements; i++)
  6261. {
  6262. //
  6263. // Create the result pane item for this element
  6264. //
  6265. SPITFSNode spNode;
  6266. CDhcpAllocationRange * pDhcpAllocRange =
  6267. new CDhcpAllocationRange(m_spTFSCompData,
  6268. pdhcpSubnetElementArray->Elements[i].Element.IpRange);
  6269. pDhcpAllocRange->SetRangeType(pdhcpSubnetElementArray->Elements[i].ElementType);
  6270. CreateLeafTFSNode(&spNode,
  6271. &GUID_DhcpAllocationNodeType,
  6272. pDhcpAllocRange,
  6273. pDhcpAllocRange,
  6274. m_spNodeMgr);
  6275. // Tell the handler to initialize any specific data
  6276. pDhcpAllocRange->InitializeNode(spNode);
  6277. AddToQueue(spNode);
  6278. pDhcpAllocRange->Release();
  6279. }
  6280. ::DhcpRpcFreeMemory(pdhcpSubnetElementArray);
  6281. }
  6282. else
  6283. if (dwError != ERROR_SUCCESS &&
  6284. dwError != ERROR_NO_MORE_ITEMS)
  6285. {
  6286. // set the error variable so that it can be looked at later
  6287. m_dwError = dwError;
  6288. }
  6289. // Check the abort flag on the thread
  6290. if (FCheckForAbort() == hrOK)
  6291. break;
  6292. // check to see if we have an error and post it to the main thread if we do..
  6293. if (dwError != ERROR_NO_MORE_ITEMS &&
  6294. dwError != ERROR_SUCCESS &&
  6295. dwError != ERROR_MORE_DATA)
  6296. {
  6297. Trace1("DHCP snapin: EnumerateAllocationRanges error: %d\n", dwError);
  6298. m_dwErr = dwError;
  6299. PostError(dwError);
  6300. }
  6301. }
  6302. return hrFalse;
  6303. }
  6304. /*---------------------------------------------------------------------------
  6305. CDhcpAddressPool::CompareItems
  6306. Description
  6307. Author: EricDav
  6308. ---------------------------------------------------------------------------*/
  6309. STDMETHODIMP_(int)
  6310. CDhcpAddressPool::CompareItems
  6311. (
  6312. ITFSComponent * pComponent,
  6313. MMC_COOKIE cookieA,
  6314. MMC_COOKIE cookieB,
  6315. int nCol
  6316. )
  6317. {
  6318. SPITFSNode spNode1, spNode2;
  6319. m_spNodeMgr->FindNode(cookieA, &spNode1);
  6320. m_spNodeMgr->FindNode(cookieB, &spNode2);
  6321. int nCompare = 0;
  6322. CDhcpAllocationRange *pDhcpAR1 = GETHANDLER(CDhcpAllocationRange, spNode1);
  6323. CDhcpAllocationRange *pDhcpAR2 = GETHANDLER(CDhcpAllocationRange, spNode2);
  6324. switch (nCol)
  6325. {
  6326. case 0:
  6327. {
  6328. // Start IP address compare
  6329. //
  6330. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(TRUE);
  6331. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(TRUE);
  6332. if (dhcpIp1 < dhcpIp2)
  6333. nCompare = -1;
  6334. else
  6335. if (dhcpIp1 > dhcpIp2)
  6336. nCompare = 1;
  6337. // default is that they are equal
  6338. }
  6339. break;
  6340. case 1:
  6341. {
  6342. // End IP address compare
  6343. //
  6344. DHCP_IP_ADDRESS dhcpIp1 = pDhcpAR1->QueryAddr(FALSE);
  6345. DHCP_IP_ADDRESS dhcpIp2 = pDhcpAR2->QueryAddr(FALSE);
  6346. if (dhcpIp1 < dhcpIp2)
  6347. nCompare = -1;
  6348. else
  6349. if (dhcpIp1 > dhcpIp2)
  6350. nCompare = 1;
  6351. // default is that they are equal
  6352. }
  6353. break;
  6354. case 2:
  6355. {
  6356. // Description compare
  6357. //
  6358. CString strRange1 = pDhcpAR1->GetString(pComponent, cookieA, nCol);
  6359. CString strRange2 = pDhcpAR2->GetString(pComponent, cookieA, nCol);
  6360. // Compare should not be case sensitive
  6361. //
  6362. strRange1.MakeUpper();
  6363. strRange2.MakeUpper();
  6364. nCompare = strRange1.Compare(strRange2);
  6365. }
  6366. break;
  6367. }
  6368. return nCompare;
  6369. }
  6370. /*---------------------------------------------------------------------------
  6371. CDhcpScopeOptions Implementation
  6372. ---------------------------------------------------------------------------*/
  6373. /*---------------------------------------------------------------------------
  6374. CDhcpScopeOptions Constructor and destructor
  6375. Author: EricDav
  6376. ---------------------------------------------------------------------------*/
  6377. CDhcpScopeOptions::CDhcpScopeOptions
  6378. (
  6379. ITFSComponentData * pComponentData
  6380. ) : CMTDhcpHandler(pComponentData)
  6381. {
  6382. }
  6383. CDhcpScopeOptions::~CDhcpScopeOptions()
  6384. {
  6385. }
  6386. /*!--------------------------------------------------------------------------
  6387. CDhcpScopeOptions::InitializeNode
  6388. Initializes node specific data
  6389. Author: EricDav
  6390. ---------------------------------------------------------------------------*/
  6391. HRESULT
  6392. CDhcpScopeOptions::InitializeNode
  6393. (
  6394. ITFSNode * pNode
  6395. )
  6396. {
  6397. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6398. HRESULT hr = hrOK;
  6399. //
  6400. // Create the display name for this scope
  6401. //
  6402. CString strTemp;
  6403. strTemp.LoadString(IDS_SCOPE_OPTIONS_FOLDER);
  6404. SetDisplayName(strTemp);
  6405. // Make the node immediately visible
  6406. pNode->SetVisibilityState(TFS_VIS_SHOW);
  6407. pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE));
  6408. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE));
  6409. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  6410. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  6411. pNode->SetData(TFS_DATA_TYPE, DHCPSNAP_SCOPE_OPTIONS);
  6412. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  6413. SetColumnStringIDs(&aColumns[DHCPSNAP_SCOPE_OPTIONS][0]);
  6414. SetColumnWidths(&aColumnWidths[DHCPSNAP_SCOPE_OPTIONS][0]);
  6415. return hr;
  6416. }
  6417. /*---------------------------------------------------------------------------
  6418. CDhcpScopeOptions::OnCreateNodeId2
  6419. Returns a unique string for this node
  6420. Author: EricDav
  6421. ---------------------------------------------------------------------------*/
  6422. HRESULT CDhcpScopeOptions::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  6423. {
  6424. const GUID * pGuid = pNode->GetNodeType();
  6425. CString strIpAddress, strGuid;
  6426. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  6427. strGuid.ReleaseBuffer();
  6428. DHCP_IP_ADDRESS dhcpIpAddress = GetScopeObject(pNode)->GetAddress();
  6429. UtilCvtIpAddrToWstr (dhcpIpAddress, &strIpAddress);
  6430. strId = GetServerName(pNode) + strIpAddress + strGuid;
  6431. return hrOK;
  6432. }
  6433. /*---------------------------------------------------------------------------
  6434. CDhcpScopeOptions::GetImageIndex
  6435. Description
  6436. Author: EricDav
  6437. ---------------------------------------------------------------------------*/
  6438. int
  6439. CDhcpScopeOptions::GetImageIndex(BOOL bOpenImage)
  6440. {
  6441. int nIndex = -1;
  6442. switch (m_nState)
  6443. {
  6444. case notLoaded:
  6445. case loaded:
  6446. if (bOpenImage)
  6447. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN;
  6448. else
  6449. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED;
  6450. break;
  6451. case loading:
  6452. if (bOpenImage)
  6453. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN_BUSY;
  6454. else
  6455. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED_BUSY;
  6456. break;
  6457. case unableToLoad:
  6458. if (bOpenImage)
  6459. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_OPEN_LOST_CONNECTION;
  6460. else
  6461. nIndex = ICON_IDX_SCOPE_OPTION_FOLDER_CLOSED_LOST_CONNECTION;
  6462. break;
  6463. default:
  6464. ASSERT(FALSE);
  6465. }
  6466. return nIndex;
  6467. }
  6468. /*---------------------------------------------------------------------------
  6469. Overridden base handler functions
  6470. ---------------------------------------------------------------------------*/
  6471. /*---------------------------------------------------------------------------
  6472. CDhcpScopeOptions::OnAddMenuItems
  6473. Adds entries to the context sensitive menu
  6474. Author: EricDav
  6475. ---------------------------------------------------------------------------*/
  6476. STDMETHODIMP
  6477. CDhcpScopeOptions::OnAddMenuItems
  6478. (
  6479. ITFSNode * pNode,
  6480. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  6481. LPDATAOBJECT lpDataObject,
  6482. DATA_OBJECT_TYPES type,
  6483. DWORD dwType,
  6484. long * pInsertionAllowed
  6485. )
  6486. {
  6487. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6488. LONG fFlags = 0;
  6489. HRESULT hr = S_OK;
  6490. CString strMenuText;
  6491. if ( (m_nState != loaded) )
  6492. {
  6493. fFlags |= MF_GRAYED;
  6494. }
  6495. if (type == CCT_SCOPE)
  6496. {
  6497. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  6498. {
  6499. // these menu items go in the new menu,
  6500. // only visible from scope pane
  6501. strMenuText.LoadString(IDS_CREATE_OPTION_SCOPE);
  6502. hr = LoadAndAddMenuItem( pContextMenuCallback,
  6503. strMenuText,
  6504. IDS_CREATE_OPTION_SCOPE,
  6505. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  6506. fFlags );
  6507. ASSERT( SUCCEEDED(hr) );
  6508. }
  6509. }
  6510. return hr;
  6511. }
  6512. /*---------------------------------------------------------------------------
  6513. CDhcpScopeOptions::OnCommand
  6514. Description
  6515. Author: EricDav
  6516. ---------------------------------------------------------------------------*/
  6517. STDMETHODIMP
  6518. CDhcpScopeOptions::OnCommand
  6519. (
  6520. ITFSNode * pNode,
  6521. long nCommandId,
  6522. DATA_OBJECT_TYPES type,
  6523. LPDATAOBJECT pDataObject,
  6524. DWORD dwType
  6525. )
  6526. {
  6527. HRESULT hr = S_OK;
  6528. switch (nCommandId)
  6529. {
  6530. case IDS_CREATE_OPTION_SCOPE:
  6531. OnCreateNewOptions(pNode);
  6532. break;
  6533. case IDS_REFRESH:
  6534. OnRefresh(pNode, pDataObject, dwType, 0, 0);
  6535. break;
  6536. default:
  6537. break;
  6538. }
  6539. return hr;
  6540. }
  6541. /*!--------------------------------------------------------------------------
  6542. CDhcpScopeOptions::HasPropertyPages
  6543. Implementation of ITFSNodeHandler::HasPropertyPages
  6544. NOTE: the root node handler has to over-ride this function to
  6545. handle the snapin manager property page (wizard) case!!!
  6546. Author: KennT
  6547. ---------------------------------------------------------------------------*/
  6548. STDMETHODIMP
  6549. CDhcpScopeOptions::HasPropertyPages
  6550. (
  6551. ITFSNode * pNode,
  6552. LPDATAOBJECT pDataObject,
  6553. DATA_OBJECT_TYPES type,
  6554. DWORD dwType
  6555. )
  6556. {
  6557. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6558. HRESULT hr = hrOK;
  6559. // we have property pages in the normal case, but don't put the
  6560. // menu up if we are not loaded yet
  6561. if ( m_nState != loaded )
  6562. {
  6563. hr = hrFalse;
  6564. }
  6565. else
  6566. {
  6567. hr = hrOK;
  6568. }
  6569. return hr;
  6570. }
  6571. /*---------------------------------------------------------------------------
  6572. CDhcpScopeOptions::CreatePropertyPages
  6573. Description
  6574. Author: EricDav
  6575. ---------------------------------------------------------------------------*/
  6576. STDMETHODIMP
  6577. CDhcpScopeOptions::CreatePropertyPages
  6578. (
  6579. ITFSNode * pNode,
  6580. LPPROPERTYSHEETCALLBACK lpProvider,
  6581. LPDATAOBJECT pDataObject,
  6582. LONG_PTR handle,
  6583. DWORD dwType
  6584. )
  6585. {
  6586. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6587. DWORD dwError;
  6588. DWORD dwDynDnsFlags;
  6589. HRESULT hr = hrOK;
  6590. COptionsConfig * pOptCfg;
  6591. CString strOptCfgTitle, strOptType;
  6592. SPITFSNode spServerNode;
  6593. SPIComponentData spComponentData;
  6594. COptionValueEnum * pOptionValueEnum;
  6595. //
  6596. // Create the property page
  6597. //
  6598. COM_PROTECT_TRY
  6599. {
  6600. m_spNodeMgr->GetComponentData(&spComponentData);
  6601. BEGIN_WAIT_CURSOR;
  6602. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_SCOPE);
  6603. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  6604. GetScopeObject(pNode)->GetServerNode(&spServerNode);
  6605. pOptionValueEnum = GetScopeObject(pNode)->GetOptionValueEnum();
  6606. pOptCfg = new COptionsConfig(pNode,
  6607. spServerNode,
  6608. spComponentData,
  6609. m_spTFSCompData,
  6610. pOptionValueEnum,
  6611. strOptCfgTitle);
  6612. END_WAIT_CURSOR;
  6613. //
  6614. // Object gets deleted when the page is destroyed
  6615. //
  6616. Assert(lpProvider != NULL);
  6617. hr = pOptCfg->CreateModelessSheet(lpProvider, handle);
  6618. }
  6619. COM_PROTECT_CATCH
  6620. return hr;
  6621. }
  6622. /*---------------------------------------------------------------------------
  6623. CDhcpScopeOptions::OnPropertyChange
  6624. Description
  6625. Author: EricDav
  6626. ---------------------------------------------------------------------------*/
  6627. HRESULT
  6628. CDhcpScopeOptions::OnPropertyChange
  6629. (
  6630. ITFSNode * pNode,
  6631. LPDATAOBJECT pDataobject,
  6632. DWORD dwType,
  6633. LPARAM arg,
  6634. LPARAM lParam
  6635. )
  6636. {
  6637. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6638. COptionsConfig * pOptCfg = reinterpret_cast<COptionsConfig *>(lParam);
  6639. LPARAM changeMask = 0;
  6640. // tell the property page to do whatever now that we are back on the
  6641. // main thread
  6642. pOptCfg->OnPropertyChange(TRUE, &changeMask);
  6643. pOptCfg->AcknowledgeNotify();
  6644. if (changeMask)
  6645. pNode->ChangeNode(changeMask);
  6646. return hrOK;
  6647. }
  6648. /*---------------------------------------------------------------------------
  6649. CDhcpScopeOptions::OnPropertyChange
  6650. Description
  6651. Author: EricDav
  6652. ---------------------------------------------------------------------------*/
  6653. HRESULT
  6654. CDhcpScopeOptions::OnResultPropertyChange
  6655. (
  6656. ITFSComponent * pComponent,
  6657. LPDATAOBJECT pDataObject,
  6658. MMC_COOKIE cookie,
  6659. LPARAM arg,
  6660. LPARAM param
  6661. )
  6662. {
  6663. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  6664. SPITFSNode spNode;
  6665. m_spNodeMgr->FindNode(cookie, &spNode);
  6666. COptionsConfig * pOptCfg = reinterpret_cast<COptionsConfig *>(param);
  6667. LPARAM changeMask = 0;
  6668. // tell the property page to do whatever now that we are back on the
  6669. // main thread
  6670. pOptCfg->OnPropertyChange(TRUE, &changeMask);
  6671. pOptCfg->AcknowledgeNotify();
  6672. if (changeMask)
  6673. spNode->ChangeNode(changeMask);
  6674. return hrOK;
  6675. }
  6676. /*---------------------------------------------------------------------------
  6677. CDhcpScopeOptions::CompareItems
  6678. Description
  6679. Author: EricDav
  6680. ---------------------------------------------------------------------------*/
  6681. STDMETHODIMP_(int)
  6682. CDhcpScopeOptions::CompareItems
  6683. (
  6684. ITFSComponent * pComponent,
  6685. MMC_COOKIE cookieA,
  6686. MMC_COOKIE cookieB,
  6687. int nCol
  6688. )
  6689. {
  6690. SPITFSNode spNode1, spNode2;
  6691. m_spNodeMgr->FindNode(cookieA, &spNode1);
  6692. m_spNodeMgr->FindNode(cookieB, &spNode2);
  6693. int nCompare = 0;
  6694. CDhcpOptionItem *pOpt1 = GETHANDLER(CDhcpOptionItem, spNode1);
  6695. CDhcpOptionItem *pOpt2 = GETHANDLER(CDhcpOptionItem, spNode2);
  6696. switch (nCol)
  6697. {
  6698. case 0:
  6699. {
  6700. //
  6701. // Name compare - use the option #
  6702. //
  6703. LONG_PTR uImage1 = spNode1->GetData(TFS_DATA_IMAGEINDEX);
  6704. LONG_PTR uImage2 = spNode2->GetData(TFS_DATA_IMAGEINDEX);
  6705. nCompare = UtilGetOptionPriority((int) uImage1, (int) uImage2);
  6706. if (nCompare == 0)
  6707. {
  6708. DHCP_OPTION_ID id1 = pOpt1->GetOptionId();
  6709. DHCP_OPTION_ID id2 = pOpt2->GetOptionId();
  6710. if (id1 < id2)
  6711. nCompare = -1;
  6712. else
  6713. if (id1 > id2)
  6714. nCompare = 1;
  6715. }
  6716. }
  6717. break;
  6718. case 1:
  6719. {
  6720. // compare the vendor strings
  6721. CString str1, str2;
  6722. str1 = pOpt1->GetVendorDisplay();
  6723. str2 = pOpt2->GetVendorDisplay();
  6724. nCompare = str1.CompareNoCase(str2);
  6725. }
  6726. break;
  6727. case 2: {
  6728. // compare the printable values
  6729. CString str1, str2;
  6730. str1 = pOpt1->GetString( pComponent, cookieA, nCol );
  6731. str2 = pOpt2->GetString( pComponent, cookieB, nCol );
  6732. nCompare = str1.CompareNoCase( str2 );
  6733. break;
  6734. }
  6735. case 3:
  6736. {
  6737. CString str1, str2;
  6738. str1 = pOpt1->GetClassName();
  6739. str2 = pOpt2->GetClassName();
  6740. nCompare = str1.CompareNoCase(str2);
  6741. }
  6742. break;
  6743. }
  6744. return nCompare;
  6745. }
  6746. /*!--------------------------------------------------------------------------
  6747. CDhcpScopeOptions::OnResultSelect
  6748. Update the verbs and the result pane message
  6749. Author: EricDav
  6750. ---------------------------------------------------------------------------*/
  6751. HRESULT CDhcpScopeOptions::OnResultSelect(ITFSComponent *pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  6752. {
  6753. HRESULT hr = hrOK;
  6754. SPITFSNode spNode;
  6755. CORg(CMTDhcpHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam));
  6756. CORg (pComponent->GetSelectedNode(&spNode));
  6757. if ( spNode != 0 ) {
  6758. UpdateResultMessage(spNode);
  6759. }
  6760. Error:
  6761. return hr;
  6762. }
  6763. /*---------------------------------------------------------------------------
  6764. CDhcpScopeOptions::OnResultDelete
  6765. This function is called when we are supposed to delete result
  6766. pane items. We build a list of selected items and then delete them.
  6767. Author: EricDav
  6768. ---------------------------------------------------------------------------*/
  6769. HRESULT
  6770. CDhcpScopeOptions::OnResultDelete
  6771. (
  6772. ITFSComponent * pComponent,
  6773. LPDATAOBJECT pDataObject,
  6774. MMC_COOKIE cookie,
  6775. LPARAM arg,
  6776. LPARAM param
  6777. )
  6778. {
  6779. HRESULT hr = hrOK;
  6780. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  6781. // translate the cookie into a node pointer
  6782. SPITFSNode spScopeOpt, spSelectedNode;
  6783. m_spNodeMgr->FindNode(cookie, &spScopeOpt);
  6784. pComponent->GetSelectedNode(&spSelectedNode);
  6785. Assert(spSelectedNode == spScopeOpt);
  6786. if (spSelectedNode != spScopeOpt)
  6787. return hr;
  6788. // build the list of selected nodes
  6789. CTFSNodeList listNodesToDelete;
  6790. hr = BuildSelectedItemList(pComponent, &listNodesToDelete);
  6791. //
  6792. // Confirm with the user
  6793. //
  6794. CString strMessage, strTemp;
  6795. int nNodes = (int)listNodesToDelete.GetCount();
  6796. if (nNodes > 1)
  6797. {
  6798. strTemp.Format(_T("%d"), nNodes);
  6799. AfxFormatString1(strMessage, IDS_DELETE_ITEMS, (LPCTSTR) strTemp);
  6800. }
  6801. else
  6802. {
  6803. strMessage.LoadString(IDS_DELETE_ITEM);
  6804. }
  6805. if (AfxMessageBox(strMessage, MB_YESNO) == IDNO)
  6806. {
  6807. return NOERROR;
  6808. }
  6809. // check to make sure we are deleting just scope options
  6810. POSITION pos = listNodesToDelete.GetHeadPosition();
  6811. while (pos)
  6812. {
  6813. ITFSNode * pNode = listNodesToDelete.GetNext(pos);
  6814. if (pNode->GetData(TFS_DATA_IMAGEINDEX) != ICON_IDX_SCOPE_OPTION_LEAF)
  6815. {
  6816. // this option is not scope option. Put up a dialog telling the user what to do
  6817. AfxMessageBox(IDS_CANNOT_DELETE_OPTION_SCOPE);
  6818. return NOERROR;
  6819. }
  6820. }
  6821. CString strServer = GetServerIpAddress(spScopeOpt);
  6822. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  6823. dhcpOptionScopeInfo.ScopeType = DhcpSubnetOptions;
  6824. dhcpOptionScopeInfo.ScopeInfo.SubnetScopeInfo = GetScopeObject(spScopeOpt)->GetAddress();
  6825. //
  6826. // Loop through all items deleting
  6827. //
  6828. BEGIN_WAIT_CURSOR;
  6829. while (listNodesToDelete.GetCount() > 0)
  6830. {
  6831. SPITFSNode spOptionNode;
  6832. spOptionNode = listNodesToDelete.RemoveHead();
  6833. CDhcpOptionItem * pOptItem = GETHANDLER(CDhcpOptionItem, spOptionNode);
  6834. //
  6835. // Try to remove it from the server
  6836. //
  6837. DWORD dwError;
  6838. if (pOptItem->IsVendorOption() ||
  6839. pOptItem->IsClassOption())
  6840. {
  6841. LPCTSTR pClassName = pOptItem->GetClassName();
  6842. if (lstrlen(pClassName) == 0)
  6843. pClassName = NULL;
  6844. dwError = ::DhcpRemoveOptionValueV5((LPTSTR) ((LPCTSTR) strServer),
  6845. pOptItem->IsVendorOption() ? DHCP_FLAGS_OPTION_IS_VENDOR : 0,
  6846. pOptItem->GetOptionId(),
  6847. (LPTSTR) pClassName,
  6848. (LPTSTR) pOptItem->GetVendor(),
  6849. &dhcpOptionScopeInfo);
  6850. }
  6851. else
  6852. {
  6853. dwError = ::DhcpRemoveOptionValue(strServer,
  6854. pOptItem->GetOptionId(),
  6855. &dhcpOptionScopeInfo);
  6856. }
  6857. if (dwError != 0)
  6858. {
  6859. ::DhcpMessageBox(dwError);
  6860. RESTORE_WAIT_CURSOR;
  6861. hr = E_FAIL;
  6862. continue;
  6863. }
  6864. //
  6865. // remove from our internal list
  6866. //
  6867. GetScopeObject(spScopeOpt)->GetOptionValueEnum()->Remove(pOptItem->GetOptionId(), pOptItem->GetVendor(), pOptItem->GetClassName());
  6868. //
  6869. // Remove from UI now
  6870. //
  6871. spScopeOpt->RemoveChild(spOptionNode);
  6872. spOptionNode.Release();
  6873. }
  6874. END_WAIT_CURSOR;
  6875. UpdateResultMessage(spScopeOpt);
  6876. return hr;
  6877. }
  6878. /*!--------------------------------------------------------------------------
  6879. CDhcpScopeOptions::OnHaveData
  6880. Description
  6881. Author: EricDav
  6882. ---------------------------------------------------------------------------*/
  6883. void
  6884. CDhcpScopeOptions::OnHaveData
  6885. (
  6886. ITFSNode * pParentNode,
  6887. LPARAM Data,
  6888. LPARAM Type
  6889. )
  6890. {
  6891. // This is how we get non-node data back from the background thread.
  6892. switch (Type)
  6893. {
  6894. case DHCP_QDATA_OPTION_VALUES:
  6895. {
  6896. HRESULT hr = hrOK;
  6897. SPIComponentData spCompData;
  6898. SPIConsole spConsole;
  6899. SPIDataObject spDataObject;
  6900. IDataObject * pDataObject;
  6901. CDhcpScope * pScope = GetScopeObject(pParentNode);
  6902. COptionValueEnum * pOptionValueEnum = reinterpret_cast<COptionValueEnum *>(Data);
  6903. pScope->SetOptionValueEnum(pOptionValueEnum);
  6904. pOptionValueEnum->RemoveAll();
  6905. delete pOptionValueEnum;
  6906. // now tell the view to update themselves
  6907. m_spNodeMgr->GetComponentData(&spCompData);
  6908. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pParentNode, CCT_SCOPE, &pDataObject) );
  6909. spDataObject = pDataObject;
  6910. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  6911. CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM) pParentNode, DHCPSNAP_UPDATE_OPTIONS) );
  6912. break;
  6913. }
  6914. }
  6915. Error:
  6916. return;
  6917. }
  6918. /*!--------------------------------------------------------------------------
  6919. CDhcpScopeOptions::OnResultUpdateView
  6920. Implementation of ITFSResultHandler::OnResultUpdateView
  6921. Author: EricDav
  6922. ---------------------------------------------------------------------------*/
  6923. HRESULT CDhcpScopeOptions::OnResultUpdateView
  6924. (
  6925. ITFSComponent *pComponent,
  6926. LPDATAOBJECT pDataObject,
  6927. LPARAM data,
  6928. LPARAM hint
  6929. )
  6930. {
  6931. HRESULT hr = hrOK;
  6932. SPITFSNode spSelectedNode;
  6933. pComponent->GetSelectedNode(&spSelectedNode);
  6934. if (spSelectedNode == NULL)
  6935. return S_OK; // no selection for our IComponentData
  6936. if ( hint == DHCPSNAP_UPDATE_OPTIONS )
  6937. {
  6938. SPINTERNAL spInternal = ExtractInternalFormat(pDataObject);
  6939. ITFSNode * pNode = reinterpret_cast<ITFSNode *>(spInternal->m_cookie);
  6940. SPITFSNode spSelectedNode;
  6941. pComponent->GetSelectedNode(&spSelectedNode);
  6942. EnumerateResultPane(pComponent, (MMC_COOKIE) spSelectedNode.p, 0, 0);
  6943. }
  6944. else
  6945. {
  6946. // we don't handle this message, let the base class do it.
  6947. return CMTDhcpHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  6948. }
  6949. return hr;
  6950. }
  6951. /*!--------------------------------------------------------------------------
  6952. CDhcpScopeOptions::OnGetResultViewType
  6953. MMC calls this to get the result view information
  6954. Author: EricDav
  6955. ---------------------------------------------------------------------------*/
  6956. HRESULT
  6957. CDhcpScopeOptions::OnGetResultViewType
  6958. (
  6959. ITFSComponent * pComponent,
  6960. MMC_COOKIE cookie,
  6961. LPOLESTR * ppViewType,
  6962. long * pViewOptions
  6963. )
  6964. {
  6965. HRESULT hr = hrOK;
  6966. // call the base class to see if it is handling this
  6967. if (CMTDhcpHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK)
  6968. {
  6969. *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
  6970. hr = S_FALSE;
  6971. }
  6972. return hr;
  6973. }
  6974. /*!--------------------------------------------------------------------------
  6975. CDhcpScopeOptions::UpdateResultMessage
  6976. Figures out what message to put in the result pane, if any
  6977. Author: EricDav
  6978. ---------------------------------------------------------------------------*/
  6979. void CDhcpScopeOptions::UpdateResultMessage(ITFSNode * pNode)
  6980. {
  6981. HRESULT hr = hrOK;
  6982. int nMessage = -1; // default
  6983. int nVisible, nTotal;
  6984. int i;
  6985. CString strTitle, strBody, strTemp;
  6986. if (!m_dwErr)
  6987. {
  6988. pNode->GetChildCount(&nVisible, &nTotal);
  6989. // determine what message to display
  6990. if ( (m_nState == notLoaded) ||
  6991. (m_nState == loading) )
  6992. {
  6993. nMessage = -1;
  6994. }
  6995. else
  6996. if (nTotal == 0)
  6997. {
  6998. nMessage = SCOPE_OPTIONS_MESSAGE_NO_OPTIONS;
  6999. }
  7000. // build the strings
  7001. if (nMessage != -1)
  7002. {
  7003. // now build the text strings
  7004. // first entry is the title
  7005. strTitle.LoadString(g_uScopeOptionsMessages[nMessage][0]);
  7006. // second entry is the icon
  7007. // third ... n entries are the body strings
  7008. for (i = 2; g_uScopeOptionsMessages[nMessage][i] != 0; i++)
  7009. {
  7010. strTemp.LoadString(g_uScopeOptionsMessages[nMessage][i]);
  7011. strBody += strTemp;
  7012. }
  7013. }
  7014. }
  7015. // show the message
  7016. if (nMessage == -1)
  7017. {
  7018. ClearMessage(pNode);
  7019. }
  7020. else
  7021. {
  7022. ShowMessage(pNode, strTitle, strBody, (IconIdentifier) g_uScopeOptionsMessages[nMessage][1]);
  7023. }
  7024. }
  7025. /*!--------------------------------------------------------------------------
  7026. CDhcpScopeOptions::EnumerateResultPane
  7027. We override this function for the options nodes for one reason.
  7028. Whenever an option class is deleted, then all options defined for
  7029. that class will be removed as well. Since there are multiple places
  7030. that these options may show up, it's easier to just not show any
  7031. options that don't have a class defined for it.
  7032. Author: EricDav
  7033. ---------------------------------------------------------------------------*/
  7034. HRESULT
  7035. CDhcpScopeOptions::EnumerateResultPane
  7036. (
  7037. ITFSComponent * pComponent,
  7038. MMC_COOKIE cookie,
  7039. LPARAM arg,
  7040. LPARAM lParam
  7041. )
  7042. {
  7043. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  7044. CClassInfoArray ClassInfoArray;
  7045. SPITFSNode spContainer, spServerNode;
  7046. CDhcpServer * pServer;
  7047. COptionValueEnum * aEnum[2];
  7048. int aImages[2] = {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF};
  7049. m_spNodeMgr->FindNode(cookie, &spContainer);
  7050. spServerNode = GetServerNode(spContainer);
  7051. pServer = GETHANDLER(CDhcpServer, spServerNode);
  7052. pServer->GetClassInfoArray(ClassInfoArray);
  7053. aEnum[0] = GetScopeObject(spContainer)->GetOptionValueEnum();
  7054. aEnum[1] = pServer->GetOptionValueEnum();
  7055. aEnum[0]->Reset();
  7056. aEnum[1]->Reset();
  7057. return OnResultUpdateOptions(pComponent, spContainer, &ClassInfoArray, aEnum, aImages, 2);
  7058. }
  7059. /*---------------------------------------------------------------------------
  7060. Command handlers
  7061. ---------------------------------------------------------------------------*/
  7062. HRESULT
  7063. CDhcpScopeOptions::OnCreateNewOptions
  7064. (
  7065. ITFSNode * pNode
  7066. )
  7067. {
  7068. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  7069. CPropertyPageHolderBase * pPropSheet;
  7070. HRESULT hr = hrOK;
  7071. COM_PROTECT_TRY
  7072. {
  7073. if (HasPropSheetsOpen())
  7074. {
  7075. GetOpenPropSheet(0, &pPropSheet);
  7076. pPropSheet->SetActiveWindow();
  7077. }
  7078. else
  7079. {
  7080. CString strOptCfgTitle, strOptType;
  7081. SPIComponentData spComponentData;
  7082. strOptType.LoadString(IDS_CONFIGURE_OPTIONS_SCOPE);
  7083. AfxFormatString1(strOptCfgTitle, IDS_CONFIGURE_OPTIONS_TITLE, strOptType);
  7084. m_spNodeMgr->GetComponentData(&spComponentData);
  7085. hr = DoPropertiesOurselvesSinceMMCSucks(pNode, spComponentData, strOptCfgTitle);
  7086. }
  7087. }
  7088. COM_PROTECT_CATCH
  7089. return hr;
  7090. }
  7091. /*---------------------------------------------------------------------------
  7092. Background thread functionality
  7093. ---------------------------------------------------------------------------*/
  7094. /*---------------------------------------------------------------------------
  7095. CDhcpScopeOptions::OnCreateQuery()
  7096. Description
  7097. Author: EricDav
  7098. ---------------------------------------------------------------------------*/
  7099. ITFSQueryObject*
  7100. CDhcpScopeOptions::OnCreateQuery(ITFSNode * pNode)
  7101. {
  7102. CDhcpScopeOptionsQueryObj* pQuery =
  7103. new CDhcpScopeOptionsQueryObj(m_spTFSCompData, m_spNodeMgr);
  7104. pQuery->m_strServer = GetServerIpAddress(pNode);
  7105. pQuery->m_dhcpScopeAddress = GetScopeObject(pNode)->GetAddress();
  7106. pQuery->m_dhcpResumeHandle = NULL;
  7107. pQuery->m_dwPreferredMax = 0xFFFFFFFF;
  7108. GetScopeObject(pNode)->GetDynBootpClassName(pQuery->m_strDynBootpClassName);
  7109. GetScopeObject(pNode)->GetServerVersion(pQuery->m_liDhcpVersion);
  7110. return pQuery;
  7111. }
  7112. /*---------------------------------------------------------------------------
  7113. CDhcpScopeOptionsQueryObj::Execute()
  7114. Description
  7115. Author: EricDav
  7116. ---------------------------------------------------------------------------*/
  7117. STDMETHODIMP
  7118. CDhcpScopeOptionsQueryObj::Execute()
  7119. {
  7120. DWORD dwErr;
  7121. DHCP_OPTION_SCOPE_INFO dhcpOptionScopeInfo;
  7122. COptionValueEnum * pOptionValueEnum;
  7123. pOptionValueEnum = new COptionValueEnum();
  7124. pOptionValueEnum->m_strDynBootpClassName = m_strDynBootpClassName;
  7125. dhcpOptionScopeInfo.ScopeType = DhcpSubnetOptions;
  7126. dhcpOptionScopeInfo.ScopeInfo.SubnetScopeInfo = m_dhcpScopeAddress;
  7127. pOptionValueEnum->Init(m_strServer, m_liDhcpVersion, dhcpOptionScopeInfo);
  7128. dwErr = pOptionValueEnum->Enum();
  7129. if (dwErr != ERROR_SUCCESS)
  7130. {
  7131. Trace1("CDhcpScopeOptionsQueryObj::Execute - Enum Failed! %d\n", dwErr);
  7132. m_dwErr = dwErr;
  7133. PostError(dwErr);
  7134. delete pOptionValueEnum;
  7135. }
  7136. else
  7137. {
  7138. pOptionValueEnum->SortById();
  7139. AddToQueue((LPARAM) pOptionValueEnum, DHCP_QDATA_OPTION_VALUES);
  7140. }
  7141. return hrFalse;
  7142. }
  7143. /*!--------------------------------------------------------------------------
  7144. CDhcpScopeOptions::OnNotifyExiting
  7145. CMTDhcpHandler overridden functionality
  7146. allows us to know when the background thread is done
  7147. Author: EricDav
  7148. ---------------------------------------------------------------------------*/
  7149. STDMETHODIMP
  7150. CDhcpScopeOptions::OnNotifyExiting
  7151. (
  7152. LPARAM lParam
  7153. )
  7154. {
  7155. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  7156. SPITFSNode spNode;
  7157. spNode.Set(m_spNode); // save this off because OnNotifyExiting will release it
  7158. HRESULT hr = CMTDhcpHandler::OnNotifyExiting(lParam);
  7159. UpdateResultMessage(spNode);
  7160. return hr;
  7161. }
  7162. //
  7163. //
  7164. // qsort comparison routine to compare the ip addresses.
  7165. //
  7166. //
  7167. int __cdecl QCompare( const void *ip1, const void *ip2 )
  7168. {
  7169. DWORD *lip1, *lip2;
  7170. if ( ip1 && ip2 )
  7171. {
  7172. lip1 = (DWORD *)ip1;
  7173. lip2 = (DWORD *)ip2;
  7174. if ( *lip1 < *lip2 )
  7175. {
  7176. return -1;
  7177. }
  7178. else if ( *lip1 > *lip2 )
  7179. {
  7180. return 1;
  7181. }
  7182. else
  7183. {
  7184. return 0;
  7185. }
  7186. }
  7187. return 0;
  7188. }