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.

8461 lines
280 KiB

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