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

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